diff --git a/.gitignore b/.gitignore index 861c79d..43e427c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /target .DS_Store +.env diff --git a/Cargo.lock b/Cargo.lock index 0120986..954dad5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,6 +49,12 @@ dependencies = [ "syn", ] +[[package]] +name = "atomic" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" + [[package]] name = "autocfg" version = "1.1.0" @@ -248,6 +254,12 @@ dependencies = [ "syn", ] +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + [[package]] name = "fediblog" version = "0.1.0" @@ -255,9 +267,11 @@ dependencies = [ "axum", "chrono", "diesel", + "dotenvy", "serde", "serde_json", "tokio", + "uuid", ] [[package]] @@ -308,6 +322,17 @@ dependencies = [ "pin-utils", ] +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "gimli" version = "0.28.0" @@ -913,6 +938,11 @@ name = "uuid" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +dependencies = [ + "atomic", + "getrandom", + "serde", +] [[package]] name = "vcpkg" diff --git a/Cargo.toml b/Cargo.toml index b827dd6..49f1654 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,9 @@ name = "fediblog" [dependencies] axum = "0.6.20" chrono = "0.4.31" -diesel = { version = "2.1.3", features = ["postgres", "extras"] } +diesel = { version = "2.1.3", features = ["postgres", "extras", "uuid"] } +dotenvy = "0.15.7" serde = { version = "1.0.189", features = ["derive"] } serde_json = "1.0.107" tokio = { version = "1.33.0", features = ["full"] } +uuid = { version = "1.0.0", features = ["serde", "v4", "v7"] } diff --git a/README.md b/README.md index a270cfe..484fb33 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,5 @@ SPDX-FileCopyrightText: 2023 Louis Hollingworth SPDX-License-Identifier: AGPL-3.0-or-later --> +# Fediblog +[![REUSE status](https://api.reuse.software/badge/git.ludoviko.ch/lucxjo/fediblog)](https://api.reuse.software/info/git.ludoviko.ch/lucxjo/fediblog) diff --git a/diesel.toml b/diesel.toml new file mode 100644 index 0000000..a2acdb8 --- /dev/null +++ b/diesel.toml @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2023 Louis Hollingworth +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +# For documentation on how to configure this file, +# see https://diesel.rs/guides/configuring-diesel-cli + +[print_schema] +file = "src/schema.rs" +custom_type_derives = ["diesel::query_builder::QueryId"] + +[migrations_directory] +dir = "migrations" diff --git a/migrations/.keep b/migrations/.keep new file mode 100644 index 0000000..e69de29 diff --git a/migrations/00000000000000_diesel_initial_setup/down.sql b/migrations/00000000000000_diesel_initial_setup/down.sql new file mode 100644 index 0000000..3d373d4 --- /dev/null +++ b/migrations/00000000000000_diesel_initial_setup/down.sql @@ -0,0 +1,10 @@ +-- SPDX-FileCopyrightText: 2023 Louis Hollingworth +-- +-- SPDX-License-Identifier: AGPL-3.0-or-later + +-- This file was automatically created by Diesel to setup helper functions +-- and other internal bookkeeping. This file is safe to edit, any future +-- changes will be added to existing projects as new migrations. + +DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass); +DROP FUNCTION IF EXISTS diesel_set_updated_at(); diff --git a/migrations/00000000000000_diesel_initial_setup/up.sql b/migrations/00000000000000_diesel_initial_setup/up.sql new file mode 100644 index 0000000..a547da4 --- /dev/null +++ b/migrations/00000000000000_diesel_initial_setup/up.sql @@ -0,0 +1,42 @@ +-- SPDX-FileCopyrightText: 2023 Louis Hollingworth +-- +-- SPDX-License-Identifier: AGPL-3.0-or-later + +-- This file was automatically created by Diesel to setup helper functions +-- and other internal bookkeeping. This file is safe to edit, any future +-- changes will be added to existing projects as new migrations. + + + + +-- Sets up a trigger for the given table to automatically set a column called +-- `updated_at` whenever the row is modified (unless `updated_at` was included +-- in the modified columns) +-- +-- # Example +-- +-- ```sql +-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW()); +-- +-- SELECT diesel_manage_updated_at('users'); +-- ``` +CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$ +BEGIN + EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s + FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl); +END; +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$ +BEGIN + IF ( + NEW IS DISTINCT FROM OLD AND + NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at + ) THEN + NEW.updated_at := current_timestamp; + END IF; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + + diff --git a/migrations/2023-10-15-172140_create_users/down.sql b/migrations/2023-10-15-172140_create_users/down.sql new file mode 100644 index 0000000..dad4a62 --- /dev/null +++ b/migrations/2023-10-15-172140_create_users/down.sql @@ -0,0 +1,6 @@ +-- SPDX-FileCopyrightText: 2023 Louis Hollingworth +-- +-- SPDX-License-Identifier: AGPL-3.0-or-later + +-- This file should undo anything in `up.sql` +DROP TABLE users; diff --git a/migrations/2023-10-15-172140_create_users/up.sql b/migrations/2023-10-15-172140_create_users/up.sql new file mode 100644 index 0000000..e8aee9d --- /dev/null +++ b/migrations/2023-10-15-172140_create_users/up.sql @@ -0,0 +1,16 @@ +-- SPDX-FileCopyrightText: 2023 Louis Hollingworth +-- +-- SPDX-License-Identifier: AGPL-3.0-or-later + +-- Your SQL goes here +CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; + +CREATE TABLE users ( + id SERIAL PRIMARY KEY, + username VARCHAR NOT NULL, + epost VARCHAR NOT NULL, + pass VARCHAR NOT NULL, + created_at TIMESTAMP NOT NULL DEFAULT NOW(), + updated_at TIMESTAMP NOT NULL DEFAULT NOW() +); +SELECT diesel_manage_updated_at('users'); diff --git a/migrations/2023-10-15-172149_create_posts/down.sql b/migrations/2023-10-15-172149_create_posts/down.sql new file mode 100644 index 0000000..1ea0b58 --- /dev/null +++ b/migrations/2023-10-15-172149_create_posts/down.sql @@ -0,0 +1,6 @@ +-- SPDX-FileCopyrightText: 2023 Louis Hollingworth +-- +-- SPDX-License-Identifier: AGPL-3.0-or-later + +-- This file should undo anything in `up.sql` +DROP TABLE posts; diff --git a/migrations/2023-10-15-172149_create_posts/up.sql b/migrations/2023-10-15-172149_create_posts/up.sql new file mode 100644 index 0000000..7e02e5f --- /dev/null +++ b/migrations/2023-10-15-172149_create_posts/up.sql @@ -0,0 +1,17 @@ +-- SPDX-FileCopyrightText: 2023 Louis Hollingworth +-- +-- SPDX-License-Identifier: AGPL-3.0-or-later + +-- Your SQL goes here + +CREATE TABLE posts ( + id SERIAL PRIMARY KEY, + slug VARCHAR NOT NULL, + title VARCHAR NOT NULL, + body TEXT NOT NULL, + published BOOLEAN NOT NULL DEFAULT FALSE, + author INTEGER NOT NULL REFERENCES users(id), + created_at TIMESTAMP NOT NULL DEFAULT NOW(), + updated_at TIMESTAMP NOT NULL DEFAULT NOW() +); +SELECT diesel_manage_updated_at('posts'); diff --git a/migrations/2023-10-15-172156_create_blogs/down.sql b/migrations/2023-10-15-172156_create_blogs/down.sql new file mode 100644 index 0000000..af245cd --- /dev/null +++ b/migrations/2023-10-15-172156_create_blogs/down.sql @@ -0,0 +1,6 @@ +-- SPDX-FileCopyrightText: 2023 Louis Hollingworth +-- +-- SPDX-License-Identifier: AGPL-3.0-or-later + +-- This file should undo anything in `up.sql` +DROP TABLE blogs; diff --git a/migrations/2023-10-15-172156_create_blogs/up.sql b/migrations/2023-10-15-172156_create_blogs/up.sql new file mode 100644 index 0000000..07a0a32 --- /dev/null +++ b/migrations/2023-10-15-172156_create_blogs/up.sql @@ -0,0 +1,18 @@ +-- SPDX-FileCopyrightText: 2023 Louis Hollingworth +-- +-- SPDX-License-Identifier: AGPL-3.0-or-later + +-- Your SQL goes here +CREATE TABLE blogs ( + id SERIAL PRIMARY KEY, + slug VARCHAR NOT NULL, + name VARCHAR NOT NULL, + description TEXT NOT NULL, + url TEXT NOT NULL, + owner INTEGER NOT NULL REFERENCES users(id), + created_at TIMESTAMP NOT NULL DEFAULT NOW(), + updated_at TIMESTAMP NOT NULL DEFAULT NOW() +); + +SELECT diesel_manage_updated_at('blogs'); + diff --git a/src/lib.rs b/src/lib.rs index e69de29..bbd4e6c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -0,0 +1,16 @@ +// SPDX-FileCopyrightText: 2023 Louis Hollingworth +// +// SPDX-License-Identifier: AGPL-3.0-or-later +pub mod schema; +pub mod uuid; +pub mod models; +use diesel::prelude::*; + +pub fn establish_connection() -> diesel::pg::PgConnection { + dotenvy::dotenv().ok(); + + let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set"); + diesel::pg::PgConnection::establish(&database_url) + .unwrap_or_else(|_| panic!("Error connecting to {}", database_url)) +} + diff --git a/src/main.rs b/src/main.rs index 627f17e..ef49f15 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: AGPL-3.0-or-later */ +#![feature(trivial_bounds)] fn main() { } diff --git a/src/models.rs b/src/models.rs new file mode 100644 index 0000000..ad4277d --- /dev/null +++ b/src/models.rs @@ -0,0 +1,12 @@ +// SPDX-FileCopyrightText: 2023 Louis Hollingworth +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use diesel::prelude::*; + +#[derive(Queryable, Selectable)] +#[diesel(table_name = crate::schema::posts)] +#[diesel(check_for_backend(diesel::pg::Pg))] +pub struct User { + pub id: i32, +} diff --git a/src/schema.rs b/src/schema.rs new file mode 100644 index 0000000..b4b0cc5 --- /dev/null +++ b/src/schema.rs @@ -0,0 +1,51 @@ +// SPDX-FileCopyrightText: 2023 Louis Hollingworth +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +// @generated automatically by Diesel CLI. + +diesel::table! { + blogs (id) { + id -> Int4, + slug -> Varchar, + name -> Varchar, + description -> Text, + url -> Text, + owner -> Int4, + created_at -> Timestamp, + updated_at -> Timestamp, + } +} + +diesel::table! { + posts (id) { + id -> Int4, + slug -> Varchar, + title -> Varchar, + body -> Text, + published -> Bool, + author -> Int4, + created_at -> Timestamp, + updated_at -> Timestamp, + } +} + +diesel::table! { + users (id) { + id -> Int4, + username -> Varchar, + epost -> Varchar, + pass -> Varchar, + created_at -> Timestamp, + updated_at -> Timestamp, + } +} + +diesel::joinable!(blogs -> users (owner)); +diesel::joinable!(posts -> users (author)); + +diesel::allow_tables_to_appear_in_same_query!( + blogs, + posts, + users, +);