start implementing diesel and SQLite db

This commit is contained in:
MrDulfin 2025-05-24 10:01:58 -04:00
parent 5a8a19cb64
commit 21977fe74f
10 changed files with 79 additions and 24 deletions

3
.gitignore vendored
View file

@ -8,3 +8,6 @@ settings.toml
test/
Cargo.lock
.env
*.db

View file

@ -9,7 +9,7 @@ members = [
authors = ["G2-Games <ke0bhogsg@gmail.com>", "MrDulfin"]
[workspace.lints.rust]
unsafe_code = "forbid"
# unsafe_code = "forbid"
[profile.production]
inherits = "release"

View file

@ -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]

View file

@ -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<Hash, HashSet<Mmid>>,
/// All entries in the database
entries: HashMap<Mmid, MochiFile>,
/// connection to the db
db: Arc<Mutex<diesel::sqlite::SqliteConnection>>,
}
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<Utc>,
upload_datetime: chrono::NaiveDateTime,
/// The datetime when the file is set to expire
expiry_datetime: DateTime<Utc>,
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<Utc>,
expiry: DateTime<Utc>,
hash: String,
upload: NaiveDateTime,
expiry: NaiveDateTime,
) -> Self {
Self {
mmid,
@ -197,16 +197,16 @@ impl MochiFile {
&self.name
}
pub fn expiry(&self) -> DateTime<Utc> {
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<RwLock<Mochibase>>, file_path: &Path) {
@ -262,7 +264,8 @@ pub fn clean_database(db: &Arc<RwLock<Mochibase>>, 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 {

View file

@ -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,
}
}

9
diesel.toml Normal file
View file

@ -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/"

0
migrations/.keep Normal file
View file

View file

@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
DROP TABLE mochifiles

View file

@ -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
)

12
src/database/schema.rs Normal file
View file

@ -0,0 +1,12 @@
// @generated automatically by Diesel CLI.
diesel::table! {
mochifiles (mmid) {
mmid -> Nullable<Integer>,
name -> Text,
mime_type -> Text,
hash -> Text,
upload_datetime -> Nullable<Timestamp>,
expiry_datetime -> Timestamp,
}
}