first pass db schema & deps
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
1744
Cargo.lock
generated
Normal file
1744
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
21
Cargo.toml
Normal file
21
Cargo.toml
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
[package]
|
||||||
|
name = "mnemosyne"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
argon2 = "0.5.3"
|
||||||
|
axum = "0.8.8"
|
||||||
|
chrono = "0.4.43"
|
||||||
|
chrono-tz = "0.10.4"
|
||||||
|
dotenvy = "0.15.7"
|
||||||
|
maud = { version = "0.27.0", features = ["axum"] }
|
||||||
|
rand = "0.10.0"
|
||||||
|
rusqlite = { version = "0.38.0", features = ["bundled", "chrono", "uuid"] }
|
||||||
|
serde = "1.0.228"
|
||||||
|
serde_json = "1.0.149"
|
||||||
|
thiserror = "2.0.18"
|
||||||
|
tokio = { version = "1.49.0", features = ["full"] }
|
||||||
|
tower = { version = "0.5.3", features = ["full"] }
|
||||||
|
tower-http = { version = "0.6.8", features = ["full"] }
|
||||||
|
uuid = { version = "1.21.0", features = ["serde", "v7"] }
|
||||||
88
src/database/migrations/2026-02-20--01.sql
Normal file
88
src/database/migrations/2026-02-20--01.sql
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
CREATE TABLE users (
|
||||||
|
id BLOB NOT NULL UNIQUE PRIMARY KEY, -- UUIDv7 as bytes
|
||||||
|
handle TEXT NOT NULL UNIQUE,
|
||||||
|
password TEXT, -- hashed, nullable in case of OAuth2-only login
|
||||||
|
prof_pic TEXT -- link probably
|
||||||
|
);
|
||||||
|
CREATE TABLE sessions (
|
||||||
|
id BLOB NOT NULL UNIQUE PRIMARY KEY, -- UUIDv7 as bytes
|
||||||
|
token TEXT NOT NULL UNIQUE,
|
||||||
|
user_id BLOB NOT NULL REFERENCES users(id), -- UUIDv7 bytes (userID)
|
||||||
|
issued TEXT NOT NULL, -- RFC3339 into DateTime<Utc>
|
||||||
|
expiry TEXT NOT NULL, -- RFC3339 into DateTime<Utc>
|
||||||
|
revoked INTEGER NOT NULL DEFAULT 0, -- bool (int 0 or int 1)
|
||||||
|
revoked_at TEXT DEFAULT NULL, -- RFC3339 into DateTime<Utc>
|
||||||
|
revoked_by BLOB DEFAULT NULL REFERENCES users(id) -- UUIDv7 bytes (userID)
|
||||||
|
);
|
||||||
|
CREATE INDEX sessions_by_userid ON sessions(user_id);
|
||||||
|
|
||||||
|
-- CREATE TABLE logs (
|
||||||
|
-- id BLOB NOT NULL UNIQUE PRIMARY KEY, -- UUIDv7 as bytes
|
||||||
|
-- actor BLOB NOT NULL REFERENCES users(id), -- UUIDv7 as bytes
|
||||||
|
-- -- (userID with special cases: UUID::nil if system, UUID::max if infradmin)
|
||||||
|
-- -- ((infradmin & system shall both be users))
|
||||||
|
-- target BLOB, -- Option<UUIDv7 as bytes (userID)>
|
||||||
|
-- change TEXT NOT NULL
|
||||||
|
-- );
|
||||||
|
|
||||||
|
CREATE TABLE quotes (
|
||||||
|
id BLOB NOT NULL UNIQUE PRIMARY KEY, -- UUIDv7 as bytes
|
||||||
|
timestamp TEXT NOT NULL, -- RFC3339 into DateTime<Utc>
|
||||||
|
location TEXT,
|
||||||
|
context TEXT,
|
||||||
|
created_by BLOB NOT NULL REFERENCES users(id), -- UUIDv7 as bytes
|
||||||
|
public INTEGER NOT NULL DEFAULT 0 -- bool (int 0 or int 1)
|
||||||
|
-- this is to be followed by a bigger role-based viewership scoping mechanism
|
||||||
|
);
|
||||||
|
CREATE INDEX quotes_by_creation_user ON quotes(created_by);
|
||||||
|
CREATE TABLE persons (
|
||||||
|
id BLOB NOT NULL UNIQUE PRIMARY KEY, -- UUIDv7 as bytes
|
||||||
|
created_by BLOB NOT NULL REFERENCES users(id), -- UUIDv7 as bytes
|
||||||
|
bio TEXT,
|
||||||
|
prof_pic TEXT -- link probably
|
||||||
|
);
|
||||||
|
CREATE TABLE names (
|
||||||
|
id BLOB NOT NULL UNIQUE PRIMARY KEY, -- UUIDv7 as bytes
|
||||||
|
is_primary INTEGER NOT NULL DEFAULT 0,
|
||||||
|
person_id BLOB NOT NULL REFERENCES persons(id),
|
||||||
|
created_by BLOB NOT NULL REFERENCES users(id),
|
||||||
|
name TEXT NOT NULL
|
||||||
|
);
|
||||||
|
CREATE INDEX names_by_personid ON names(person_id);
|
||||||
|
CREATE UNIQUE INDEX no_name_duplicate_for_same_person ON names(person_id, name);
|
||||||
|
CREATE UNIQUE INDEX primary_name_uniqueness ON names(person_id) WHERE is_primary = 1;
|
||||||
|
CREATE TABLE lines (
|
||||||
|
id BLOB NOT NULL UNIQUE PRIMARY KEY, -- UUIDv7 as bytes
|
||||||
|
quote_id BLOB NOT NULL REFERENCES quotes(id), -- UUIDv7 as bytes
|
||||||
|
name_id BLOB NOT NULL REFERENCES names(id), -- UUIDv7 as bytes
|
||||||
|
ordering INTEGER NOT NULL,
|
||||||
|
content TEXT NOT NULL
|
||||||
|
);
|
||||||
|
CREATE INDEX lines_by_quoteid ON lines(quote_id);
|
||||||
|
CREATE INDEX lines_by_nameid ON lines(name_id);
|
||||||
|
CREATE UNIQUE INDEX lines_unique_ordering ON lines(quote_id, ordering);
|
||||||
|
|
||||||
|
CREATE TABLE tags (
|
||||||
|
id BLOB NOT NULL UNIQUE PRIMARY KEY, -- UUIDv7 as bytes
|
||||||
|
tagname TEXT NOT NULL UNIQUE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE user_quote_likes (
|
||||||
|
quote_id BLOB NOT NULL REFERENCES quotes(id), -- UUIDv7 as bytes
|
||||||
|
user_id BLOB NOT NULL REFERENCES users(id), -- UUIDv7 as bytes
|
||||||
|
PRIMARY KEY (quote_id, user_id)
|
||||||
|
) WITHOUT ROWID;
|
||||||
|
CREATE INDEX likes_by_reverse_index ON user_quote_likes(user_id, quote_id);
|
||||||
|
|
||||||
|
CREATE TABLE quote_tags (
|
||||||
|
quote_id BLOB NOT NULL REFERENCES quotes(id), -- UUIDv7 as bytes
|
||||||
|
tag_id BLOB NOT NULL REFERENCES tags(id), -- UUIDv7 as bytes
|
||||||
|
PRIMARY KEY (quote_id, tag_id)
|
||||||
|
) WITHOUT ROWID;
|
||||||
|
CREATE INDEX quote_tags_reverse_index ON quote_tags(tag_id, quote_id);
|
||||||
|
|
||||||
|
-- all this to be followed by:
|
||||||
|
-- - a better access scoping mechanism (role-based like discord)
|
||||||
|
-- - photos just like quotes
|
||||||
|
-- - OAuth2 login via Steam/GitHub/Discord/Google/Potato/Whatever
|
||||||
|
-- - comments
|
||||||
1
src/database/mod.rs
Normal file
1
src/database/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
5
src/main.rs
Normal file
5
src/main.rs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
mod database;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user