From 21977fe74fb91e7c00942695988ccb7f31a6de2d Mon Sep 17 00:00:00 2001 From: MrDulfin Date: Sat, 24 May 2025 10:01:58 -0400 Subject: [PATCH] start implementing diesel and SQLite db --- .gitignore | 3 ++ Cargo.toml | 2 +- confetti-box/Cargo.toml | 4 ++ .../src/{database.rs => database/mod.rs} | 49 ++++++++++--------- confetti-box/src/database/schema.rs | 12 +++++ diesel.toml | 9 ++++ migrations/.keep | 0 .../2025-05-22-234448_create_files/down.sql | 2 + .../2025-05-22-234448_create_files/up.sql | 10 ++++ src/database/schema.rs | 12 +++++ 10 files changed, 79 insertions(+), 24 deletions(-) rename confetti-box/src/{database.rs => database/mod.rs} (92%) create mode 100644 confetti-box/src/database/schema.rs create mode 100644 diesel.toml create mode 100644 migrations/.keep create mode 100644 migrations/2025-05-22-234448_create_files/down.sql create mode 100644 migrations/2025-05-22-234448_create_files/up.sql create mode 100644 src/database/schema.rs diff --git a/.gitignore b/.gitignore index bf23712..9c97094 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ settings.toml test/ Cargo.lock + +.env +*.db \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index fefb8d8..5ecc63e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ members = [ authors = ["G2-Games ", "MrDulfin"] [workspace.lints.rust] -unsafe_code = "forbid" +# unsafe_code = "forbid" [profile.production] inherits = "release" diff --git a/confetti-box/Cargo.toml b/confetti-box/Cargo.toml index d97b754..7b1cc1e 100644 --- a/confetti-box/Cargo.toml +++ b/confetti-box/Cargo.toml @@ -29,6 +29,10 @@ toml = "0.8" unidecode = "0.3" urlencoding = "2.1" uuid = { version = "1.11", features = ["serde", "v4"] } +diesel = { version = "2.2.0", features = ["sqlite", "returning_clauses_for_sqlite_3_35", "chrono"] } +libsqlite3-sys = { version = "0.30", features = ["bundled"] } +dotenvy = "0.15" +diesel-derive-newtype = "2.1.2" [build-dependencies] diff --git a/confetti-box/src/database.rs b/confetti-box/src/database/mod.rs similarity index 92% rename from confetti-box/src/database.rs rename to confetti-box/src/database/mod.rs index f986997..f70a5c5 100644 --- a/confetti-box/src/database.rs +++ b/confetti-box/src/database/mod.rs @@ -1,33 +1,31 @@ +mod schema; + use std::{ collections::{hash_map::Values, HashMap, HashSet}, ffi::OsStr, fs::{self, File}, io::{self, Write}, path::{Path, PathBuf}, - sync::{Arc, RwLock}, + sync::{Arc, Mutex, RwLock}, }; use blake3::Hash; -use chrono::{DateTime, TimeDelta, Utc}; +use chrono::{DateTime, NaiveDateTime, TimeDelta, Utc}; use ciborium::{from_reader, into_writer}; +use diesel::{prelude::Queryable, Selectable}; use log::{error, info, warn}; use rand::distributions::{Alphanumeric, DistString}; use rocket::{ form::{self, FromFormField, ValueField}, serde::{Deserialize, Serialize}, }; -use serde_with::{serde_as, DisplayFromStr}; +use serde_with::serde_as; use uuid::Uuid; -#[derive(Debug, Clone, Deserialize, Serialize)] pub struct Mochibase { path: PathBuf, - - /// Every hash in the database along with the [`Mmid`]s associated with them - hashes: HashMap>, - - /// All entries in the database - entries: HashMap, + /// connection to the db + db: Arc>, } impl Mochibase { @@ -150,8 +148,10 @@ impl Mochibase { } /// An entry in the database storing metadata about a file -#[serde_as] -#[derive(Debug, Clone, Deserialize, Serialize)] +#[derive(Queryable, Selectable)] +#[diesel(table_name = crate::database::schema::mochifiles)] +#[diesel(check_for_backend(diesel::sqlite::Sqlite))] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct MochiFile { /// A unique identifier describing this file mmid: Mmid, @@ -163,25 +163,25 @@ pub struct MochiFile { mime_type: String, /// The Blake3 hash of the file - #[serde_as(as = "DisplayFromStr")] - hash: Hash, + hash: String, /// The datetime when the file was uploaded - upload_datetime: DateTime, + upload_datetime: chrono::NaiveDateTime, /// The datetime when the file is set to expire - expiry_datetime: DateTime, + expiry_datetime: chrono::NaiveDateTime, } + impl MochiFile { /// Create a new file that expires in `expiry`. pub fn new( mmid: Mmid, name: String, mime_type: String, - hash: Hash, - upload: DateTime, - expiry: DateTime, + hash: String, + upload: NaiveDateTime, + expiry: NaiveDateTime, ) -> Self { Self { mmid, @@ -197,16 +197,16 @@ impl MochiFile { &self.name } - pub fn expiry(&self) -> DateTime { + pub fn expiry(&self) -> NaiveDateTime { self.expiry_datetime } pub fn is_expired(&self) -> bool { let datetime = Utc::now(); - datetime > self.expiry_datetime + datetime > self.expiry_datetime.and_utc() } - pub fn hash(&self) -> &Hash { + pub fn hash(&self) -> &String { &self.hash } @@ -219,6 +219,8 @@ impl MochiFile { } } + + /// Clean the database. Removes files which are past their expiry /// [`chrono::DateTime`]. Also removes files which no longer exist on the disk. pub fn clean_database(db: &Arc>, file_path: &Path) { @@ -262,7 +264,8 @@ pub fn clean_database(db: &Arc>, file_path: &Path) { /// A unique identifier for an entry in the database, 8 characters long, /// consists of ASCII alphanumeric characters (`a-z`, `A-Z`, and `0-9`). -#[derive(Debug, PartialEq, Eq, Clone, Hash, Deserialize, Serialize)] +#[derive(diesel_derive_newtype::DieselNewType)] +#[derive(Debug, PartialEq, Eq, Clone, Hash, Serialize, Deserialize)] pub struct Mmid(String); impl Mmid { diff --git a/confetti-box/src/database/schema.rs b/confetti-box/src/database/schema.rs new file mode 100644 index 0000000..2c441f6 --- /dev/null +++ b/confetti-box/src/database/schema.rs @@ -0,0 +1,12 @@ +// @generated automatically by Diesel CLI. + +diesel::table! { + mochifiles (mmid) { + mmid -> Text, + name -> Text, + mime_type -> Text, + hash -> Text, + upload_datetime -> Timestamp, + expiry_datetime -> Timestamp, + } +} diff --git a/diesel.toml b/diesel.toml new file mode 100644 index 0000000..c3c2d53 --- /dev/null +++ b/diesel.toml @@ -0,0 +1,9 @@ +# For documentation on how to configure this file, +# see https://diesel.rs/guides/configuring-diesel-cli + +[print_schema] +file = "confetti-box/src/database/schema.rs" +custom_type_derives = ["diesel::query_builder::QueryId", "Clone"] + +[migrations_directory] +dir = "migrations/" diff --git a/migrations/.keep b/migrations/.keep new file mode 100644 index 0000000..e69de29 diff --git a/migrations/2025-05-22-234448_create_files/down.sql b/migrations/2025-05-22-234448_create_files/down.sql new file mode 100644 index 0000000..be65f7a --- /dev/null +++ b/migrations/2025-05-22-234448_create_files/down.sql @@ -0,0 +1,2 @@ +-- This file should undo anything in `up.sql` +DROP TABLE mochifiles \ No newline at end of file diff --git a/migrations/2025-05-22-234448_create_files/up.sql b/migrations/2025-05-22-234448_create_files/up.sql new file mode 100644 index 0000000..ca843b7 --- /dev/null +++ b/migrations/2025-05-22-234448_create_files/up.sql @@ -0,0 +1,10 @@ +-- Your SQL goes here + +CREATE TABLE mochifiles ( + mmid TEXT PRIMARY KEY NOT NULL, + name TEXT NOT NULL, + mime_type TEXT NOT NULL, + hash TEXT NOT NULL UNIQUE, + upload_datetime DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + expiry_datetime DATETIME NOT NULL +) diff --git a/src/database/schema.rs b/src/database/schema.rs new file mode 100644 index 0000000..a4c6dec --- /dev/null +++ b/src/database/schema.rs @@ -0,0 +1,12 @@ +// @generated automatically by Diesel CLI. + +diesel::table! { + mochifiles (mmid) { + mmid -> Nullable, + name -> Text, + mime_type -> Text, + hash -> Text, + upload_datetime -> Nullable, + expiry_datetime -> Timestamp, + } +}