diff --git a/Cargo.lock b/Cargo.lock index 19e0577f..575a3ac8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -105,7 +105,7 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" dependencies = [ - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -199,13 +199,13 @@ dependencies = [ [[package]] name = "async-recursion" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cda8f4bcc10624c4e85bc66b3f452cca98cfa5ca002dc83a16aad2367641bea" +checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" dependencies = [ "proc-macro2", - "quote 1.0.18", - "syn 1.0.107", + "quote 1.0.26", + "syn 2.0.15", ] [[package]] @@ -269,7 +269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -286,7 +286,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96cf8829f67d2eab0b2dfa42c5d0ef737e0724e4a82b01b3e292456202b19716" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -715,7 +715,7 @@ version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" dependencies = [ - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -747,7 +747,7 @@ dependencies = [ "fnv", "ident_case", "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "strsim", "syn 1.0.107", ] @@ -759,7 +759,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" dependencies = [ "darling_core", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -808,7 +808,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -829,7 +829,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "123c73e7a6e51b05c75fe1a1b2f4e241399ea5740ed810b0e3e6cacd9db5e7b2" dependencies = [ "devise_core", - "quote 1.0.18", + "quote 1.0.26", ] [[package]] @@ -841,7 +841,7 @@ dependencies = [ "bitflags", "proc-macro2", "proc-macro2-diagnostics", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -909,7 +909,7 @@ checksum = "21cdad81446a7f7dc43f6a77409efeb9733d2fa65553efef6018ef257c959b73" dependencies = [ "heck", "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -929,7 +929,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "828de45d0ca18782232dfb8f3ea9cc428e8ced380eb26a520baaacfc70de39ce" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -1113,7 +1113,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -1204,7 +1204,7 @@ checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" dependencies = [ "proc-macro-error", "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -1842,7 +1842,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49e30813093f757be5cf21e50389a24dc7dbb22c49f23b7e8f51d69b508a5ffa" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -2110,7 +2110,7 @@ checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce" dependencies = [ "proc-macro-crate", "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -2163,7 +2163,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -2268,7 +2268,7 @@ checksum = "82a5ca643c2303ecb740d506539deba189e16f2754040a42901cd8105d0282d0" dependencies = [ "proc-macro2", "proc-macro2-diagnostics", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -2306,7 +2306,7 @@ dependencies = [ "pest", "pest_meta", "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -2337,7 +2337,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -2424,7 +2424,7 @@ checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", "version_check", ] @@ -2436,15 +2436,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "version_check", ] [[package]] name = "proc-macro2" -version = "1.0.50" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ "unicode-ident", ] @@ -2456,7 +2456,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bf29726d67464d49fa6224a1d07936a8c08bb3fba727c7493f6cf1616fdaada" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", "version_check", "yansi", @@ -2482,9 +2482,9 @@ checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" [[package]] name = "quote" -version = "1.0.18" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] @@ -2722,7 +2722,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a043824e29c94169374ac5183ac0ed43f5724dc4556b19568007486bd840fa1f" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -2823,6 +2823,17 @@ dependencies = [ "serde_json", ] +[[package]] +name = "revolt-database" +version = "0.1.0" +dependencies = [ + "async-recursion", + "futures", + "mongodb", + "serde", + "serde_json", +] + [[package]] name = "revolt-delta" version = "0.5.19" @@ -2845,6 +2856,8 @@ dependencies = [ "once_cell", "regex", "reqwest", + "revolt-database", + "revolt-models", "revolt-quark", "revolt_rocket_okapi", "rocket", @@ -2859,6 +2872,19 @@ dependencies = [ "vergen", ] +[[package]] +name = "revolt-models" +version = "0.1.0" +dependencies = [ + "async-std", + "async-trait", + "authifier", + "futures", + "log", + "revolt-database", + "serde", +] + [[package]] name = "revolt-quark" version = "0.5.19" @@ -2943,7 +2969,7 @@ checksum = "cc6620569d8ac8f0a1690fcca13f488503807a60e96ebf729749b59aca1dbef9" dependencies = [ "darling", "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "rocket_http", "syn 1.0.107", ] @@ -3050,7 +3076,7 @@ dependencies = [ "glob", "indexmap", "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "rocket_http", "syn 1.0.107", "unicode-xid 0.2.3", @@ -3225,7 +3251,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af4d7e1b012cb3d9129567661a63755ea4b8a7386d339dc945ae187e403c6743" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "serde_derive_internals", "syn 1.0.107", ] @@ -3401,7 +3427,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -3412,15 +3438,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ "indexmap", "itoa 1.0.2", @@ -3458,7 +3484,7 @@ checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" dependencies = [ "darling", "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -3633,7 +3659,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +dependencies = [ + "proc-macro2", + "quote 1.0.26", "unicode-ident", ] @@ -3705,7 +3742,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -3814,7 +3851,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -3950,7 +3987,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -4080,7 +4117,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89851716b67b937e393b3daa8423e67ddfc4bbbf1654bcf05488e95e0828db0c" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", ] @@ -4290,7 +4327,7 @@ dependencies = [ "lazy_static", "proc-macro-error", "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "regex", "syn 1.0.107", "validator_types", @@ -4400,7 +4437,7 @@ dependencies = [ "lazy_static", "log", "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", "wasm-bindgen-shared", ] @@ -4423,7 +4460,7 @@ version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" dependencies = [ - "quote 1.0.18", + "quote 1.0.26", "wasm-bindgen-macro-support", ] @@ -4434,7 +4471,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" dependencies = [ "proc-macro2", - "quote 1.0.18", + "quote 1.0.26", "syn 1.0.107", "wasm-bindgen-backend", "wasm-bindgen-shared", diff --git a/Cargo.toml b/Cargo.toml index 68903beb..89be2f2a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] -members = ["crates/*"] +members = ["crates/delta", "crates/bonfire", "crates/quark", "crates/core/*"] [patch.crates-io] # mobc-redis = { git = "https://github.com/insertish/mobc", rev = "8b880bb59f2ba80b4c7bc40c649c113d8857a186" } diff --git a/crates/core/database/Cargo.toml b/crates/core/database/Cargo.toml new file mode 100644 index 00000000..57b92202 --- /dev/null +++ b/crates/core/database/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "revolt-database" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[features] +mongodb = [ "dep:mongodb" ] +default = [ "mongodb" ] + +[dependencies] +# Serialisation +serde_json = "1" +serde = { version = "1", features = ["derive"] } + +# Database +mongodb = { optional = true, version = "2.1.0", default-features = false } + +# Async Language Features +futures = "0.3.19" +async-recursion = "1.0.4" diff --git a/crates/core/database/src/drivers/dummy.rs b/crates/core/database/src/drivers/dummy.rs new file mode 100644 index 00000000..198bf59c --- /dev/null +++ b/crates/core/database/src/drivers/dummy.rs @@ -0,0 +1,4 @@ +database_derived!( + /// Dummy implementation + pub struct DummyDb {} +); diff --git a/crates/core/database/src/drivers/mod.rs b/crates/core/database/src/drivers/mod.rs new file mode 100644 index 00000000..19bd06c6 --- /dev/null +++ b/crates/core/database/src/drivers/mod.rs @@ -0,0 +1,5 @@ +mod dummy; +mod mongodb; + +pub use self::dummy::*; +pub use self::mongodb::*; diff --git a/crates/core/database/src/drivers/mongodb.rs b/crates/core/database/src/drivers/mongodb.rs new file mode 100644 index 00000000..6fb99135 --- /dev/null +++ b/crates/core/database/src/drivers/mongodb.rs @@ -0,0 +1,228 @@ +use std::collections::HashMap; +use std::ops::Deref; + +use futures::StreamExt; +use mongodb::bson::{doc, to_document, Document}; +use mongodb::error::Result; +use mongodb::options::{FindOneOptions, FindOptions}; +use mongodb::results::{DeleteResult, InsertOneResult, UpdateResult}; +use serde::de::DeserializeOwned; +use serde::Serialize; + +database_derived!( + #[cfg(feature = "mongodb")] + /// MongoDB implementation + pub struct MongoDb(pub ::mongodb::Client); +); + +impl Deref for MongoDb { + type Target = mongodb::Client; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +#[allow(dead_code)] +impl MongoDb { + /// Get the Revolt database + pub fn db(&self) -> mongodb::Database { + self.database("revolt") + } + + /// Get a collection by its name + pub fn col(&self, collection: &str) -> mongodb::Collection { + self.db().collection(collection) + } + + /// Insert one document into a collection + async fn insert_one( + &self, + collection: &'static str, + document: T, + ) -> Result { + self.col::(collection).insert_one(document, None).await + } + + /// Find multiple documents in a collection with options + async fn find_with_options( + &self, + collection: &'static str, + projection: Document, + options: O, + ) -> Result> + where + O: Into>, + { + Ok(self + .col::(collection) + .find(projection, options) + .await? + .filter_map(|s| async { + if cfg!(debug_assertions) { + // Hard fail on invalid documents + Some(s.unwrap()) + } else { + s.ok() + } + }) + .collect::>() + .await) + } + + /// Find multiple documents in a collection + async fn find( + &self, + collection: &'static str, + projection: Document, + ) -> Result> { + self.find_with_options(collection, projection, None).await + } + + /// Find one document with options + async fn find_one_with_options( + &self, + collection: &'static str, + projection: Document, + options: O, + ) -> Result> + where + O: Into>, + { + self.col::(collection) + .find_one(projection, options) + .await + } + + /// Find one document + async fn find_one( + &self, + collection: &'static str, + projection: Document, + ) -> Result> { + self.find_one_with_options(collection, projection, None) + .await + } + + /// Find one document by its ID + async fn find_one_by_id( + &self, + collection: &'static str, + id: &str, + ) -> Result> { + self.find_one( + collection, + doc! { + "_id": id + }, + ) + .await + } + + /// Update one document given a projection, partial document, and list of paths to unset + async fn update_one( + &self, + collection: &'static str, + projection: Document, + partial: T, + remove: Vec<&dyn IntoDocumentPath>, + prefix: P, + ) -> Result + where + P: Into>, + { + let prefix = prefix.into(); + + let mut unset = doc! {}; + for field in remove { + if let Some(path) = field.as_path() { + if let Some(prefix) = &prefix { + unset.insert(prefix.to_owned() + path, 1_i32); + } else { + unset.insert(path, 1_i32); + } + } + } + + let query = doc! { + "$unset": unset, + "$set": if let Some(prefix) = &prefix { + to_document(&prefix_keys(&partial, prefix)) + } else { + to_document(&partial) + }? + }; + + self.col::(collection) + .update_one(projection, query, None) + .await + } + + /// Update one document given an ID, partial document, and list of paths to unset + async fn update_one_by_id( + &self, + collection: &'static str, + id: &str, + partial: T, + remove: Vec<&dyn IntoDocumentPath>, + prefix: P, + ) -> Result + where + P: Into>, + { + self.update_one( + collection, + doc! { + "_id": id + }, + partial, + remove, + prefix, + ) + .await + } + + /// Delete one document by the given projection + async fn delete_one( + &self, + collection: &'static str, + projection: Document, + ) -> Result { + self.col::(collection) + .delete_one(projection, None) + .await + } + + /// Delete one document by the given ID + async fn delete_one_by_id(&self, collection: &'static str, id: &str) -> Result { + self.delete_one( + collection, + doc! { + "_id": id + }, + ) + .await + } +} + +/// Just a string ID struct +#[derive(Deserialize)] +pub struct DocumentId { + #[serde(rename = "_id")] + pub id: String, +} + +pub trait IntoDocumentPath: Send + Sync { + /// Create JSON key path + fn as_path(&self) -> Option<&'static str>; +} + +/// Prefix keys on an arbitrary object +pub fn prefix_keys(t: &T, prefix: &str) -> HashMap { + let v: String = serde_json::to_string(t).unwrap(); + let v: HashMap = serde_json::from_str(&v).unwrap(); + v.into_iter() + .filter(|(_k, v)| !v.is_null()) + .map(|(k, v)| (prefix.to_owned() + &k, v)) + .collect() +} diff --git a/crates/core/database/src/lib.rs b/crates/core/database/src/lib.rs new file mode 100644 index 00000000..3b926353 --- /dev/null +++ b/crates/core/database/src/lib.rs @@ -0,0 +1,66 @@ +#[macro_use] +extern crate serde; + +#[macro_use] +extern crate async_recursion; + +macro_rules! database_derived { + ( $( $item:item )+ ) => { + $( + #[derive(Clone)] + $item + )+ + }; +} + +#[cfg(feature = "mongodb")] +pub use mongodb; + +mod drivers; +pub use drivers::*; + +/// Database information to use to create a client +pub enum DatabaseInfo { + /// Auto-detect the database in use + Auto, + /// Use the mock database + Dummy, + /// Connect to MongoDB + MongoDb(String), + /// Use existing MongoDB connection + MongoDbFromClient(::mongodb::Client), +} + +/// Database +#[derive(Clone)] +pub enum Database { + /// Mock database + Dummy(DummyDb), + /// MongoDB database + MongoDb(MongoDb), +} + +impl DatabaseInfo { + /// Create a database client from the given database information + #[async_recursion] + pub async fn connect(self) -> Result { + Ok(match self { + DatabaseInfo::Auto => { + if let Ok(uri) = std::env::var("MONGODB") { + return DatabaseInfo::MongoDb(uri).connect().await; + } + + DatabaseInfo::Dummy.connect().await? + } + DatabaseInfo::Dummy => Database::Dummy(DummyDb {}), + DatabaseInfo::MongoDb(uri) => { + let client = mongodb::Client::with_uri_str(uri) + .await + .map_err(|_| "Failed to init db connection.".to_string())?; + + Database::MongoDb(MongoDb(client)) + } + DatabaseInfo::MongoDbFromClient(client) => Database::MongoDb(MongoDb(client)), + }) + } +} diff --git a/crates/core/models/Cargo.toml b/crates/core/models/Cargo.toml new file mode 100644 index 00000000..13cf041a --- /dev/null +++ b/crates/core/models/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "revolt-models" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[features] +serde = [ "dep:serde" ] +async-std-runtime = [ "async-std" ] +database = [ "revolt-database", "revolt-database/default", "authifier/database-mongodb" ] + +default = [ "serde", "async-std-runtime", "database" ] + +[dependencies] +# Utility +log = "*" + +# Serialisation +serde = { version = "1", features = ["derive"], optional = true } + +# Async Language Features +futures = "0.3.19" +async-trait = "0.1.51" + +# Async +async-std = { version = "1.8.0", features = ["attributes"], optional = true } + +# Peer dependencies +revolt-database = { path = "../database", optional = true, default-features = false } + +# Authifier +authifier = { version = "1.0", default-features = false } diff --git a/crates/core/models/examples/migrate.rs b/crates/core/models/examples/migrate.rs new file mode 100644 index 00000000..96f975b5 --- /dev/null +++ b/crates/core/models/examples/migrate.rs @@ -0,0 +1,8 @@ +use revolt_database::DatabaseInfo; +use revolt_models::*; + +#[async_std::main] +async fn main() { + let db = Database(DatabaseInfo::Auto.connect().await.unwrap()); + db.migrate_database().await.unwrap(); +} diff --git a/crates/core/models/src/admin_migrations/mod.rs b/crates/core/models/src/admin_migrations/mod.rs new file mode 100644 index 00000000..233a1d96 --- /dev/null +++ b/crates/core/models/src/admin_migrations/mod.rs @@ -0,0 +1,9 @@ +mod model; + +pub use model::*; + +#[cfg(feature = "database")] +mod ops; + +#[cfg(feature = "database")] +pub use ops::*; diff --git a/crates/core/models/src/admin_migrations/model.rs b/crates/core/models/src/admin_migrations/model.rs new file mode 100644 index 00000000..8f6dcbbc --- /dev/null +++ b/crates/core/models/src/admin_migrations/model.rs @@ -0,0 +1,10 @@ +auto_derived!( + /// Document representing migration information + pub struct MigrationInfo { + /// Unique Id + #[serde(rename = "_id")] + pub id: i32, + /// Current database revision + pub revision: i32, + } +); diff --git a/crates/core/models/src/admin_migrations/ops/dummy.rs b/crates/core/models/src/admin_migrations/ops/dummy.rs new file mode 100644 index 00000000..0db084c3 --- /dev/null +++ b/crates/core/models/src/admin_migrations/ops/dummy.rs @@ -0,0 +1,11 @@ +use revolt_database::DummyDb; + +use super::AbstractMigrations; + +#[async_trait] +impl AbstractMigrations for DummyDb { + /// Migrate the database + async fn migrate_database(&self) -> Result<(), ()> { + Ok(()) + } +} diff --git a/crates/core/models/src/admin_migrations/ops/mod.rs b/crates/core/models/src/admin_migrations/ops/mod.rs new file mode 100644 index 00000000..386434d8 --- /dev/null +++ b/crates/core/models/src/admin_migrations/ops/mod.rs @@ -0,0 +1,8 @@ +mod dummy; +mod mongodb; + +#[async_trait] +pub trait AbstractMigrations: Sync + Send { + /// Migrate the database + async fn migrate_database(&self) -> Result<(), ()>; +} diff --git a/crates/quark/src/impl/mongo/admin/migrations.rs b/crates/core/models/src/admin_migrations/ops/mongodb.rs similarity index 75% rename from crates/quark/src/impl/mongo/admin/migrations.rs rename to crates/core/models/src/admin_migrations/ops/mongodb.rs index 943ca78f..85086830 100644 --- a/crates/quark/src/impl/mongo/admin/migrations.rs +++ b/crates/core/models/src/admin_migrations/ops/mongodb.rs @@ -1,13 +1,14 @@ -use crate::{AbstractMigrations, Result}; +use revolt_database::MongoDb; -use super::super::MongoDb; +use super::AbstractMigrations; mod init; mod scripts; #[async_trait] impl AbstractMigrations for MongoDb { - async fn migrate_database(&self) -> Result<()> { + /// Migrate the database + async fn migrate_database(&self) -> Result<(), ()> { info!("Migrating the database."); let list = self diff --git a/crates/quark/src/impl/mongo/admin/migrations/init.rs b/crates/core/models/src/admin_migrations/ops/mongodb/init.rs similarity index 97% rename from crates/quark/src/impl/mongo/admin/migrations/init.rs rename to crates/core/models/src/admin_migrations/ops/mongodb/init.rs index 4501381c..37864805 100644 --- a/crates/quark/src/impl/mongo/admin/migrations/init.rs +++ b/crates/core/models/src/admin_migrations/ops/mongodb/init.rs @@ -1,9 +1,8 @@ -use crate::r#impl::mongo::MongoDb; - use super::scripts::LATEST_REVISION; -use mongodb::bson::doc; -use mongodb::options::CreateCollectionOptions; +use revolt_database::mongodb::bson::doc; +use revolt_database::mongodb::options::CreateCollectionOptions; +use revolt_database::MongoDb; pub async fn create_database(db: &MongoDb) { info!("Creating database."); diff --git a/crates/quark/src/impl/mongo/admin/migrations/scripts.rs b/crates/core/models/src/admin_migrations/ops/mongodb/scripts.rs similarity index 98% rename from crates/quark/src/impl/mongo/admin/migrations/scripts.rs rename to crates/core/models/src/admin_migrations/ops/mongodb/scripts.rs index 168029e6..1aa1c7c3 100644 --- a/crates/quark/src/impl/mongo/admin/migrations/scripts.rs +++ b/crates/core/models/src/admin_migrations/ops/mongodb/scripts.rs @@ -1,15 +1,15 @@ -use std::{time::Duration, ops::BitXor}; +use std::{ops::BitXor, time::Duration}; -use bson::{Bson, DateTime}; use futures::StreamExt; -use mongodb::{ - bson::{doc, from_bson, from_document, to_document, Document}, - options::FindOptions, +use revolt_database::{ + mongodb::{ + bson::{doc, from_bson, from_document, to_document, Bson, DateTime, Document}, + options::FindOptions, + }, + MongoDb, }; use serde::{Deserialize, Serialize}; -use crate::{r#impl::mongo::MongoDb, Permission, DEFAULT_PERMISSION_SERVER}; - #[derive(Serialize, Deserialize)] struct MigrationInfo { _id: i32, @@ -504,7 +504,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { update.insert( "default_permissions", // Remove Send Message permission if it wasn't originally granted - DEFAULT_PERMISSION_SERVER.bitxor(if has_send { 0 } else { Permission::SendMessage as u64}) as i64, + (4000323584).bitxor(if has_send { 0 } else { (1 << 22) as u64 }) as i64, ); if let Some(Bson::Document(mut roles)) = document.remove("roles") { @@ -563,7 +563,7 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { doc! { "default_permissions": { "a": 0_i64, - "d": Permission::SendMessage as i64 + "d": (1 << 22) as i64 } }, ); diff --git a/crates/core/models/src/lib.rs b/crates/core/models/src/lib.rs new file mode 100644 index 00000000..bffcadf4 --- /dev/null +++ b/crates/core/models/src/lib.rs @@ -0,0 +1,40 @@ +#[cfg(feature = "serde")] +#[macro_use] +extern crate serde; + +#[macro_use] +extern crate async_trait; + +#[macro_use] +extern crate log; + +macro_rules! auto_derived { + ( $( $item:item )+ ) => { + $( + #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] + #[derive(Debug, Clone)] + $item + )+ + }; +} + +mod admin_migrations; + +pub use admin_migrations::*; + +pub struct Database(pub revolt_database::Database); + +pub trait AbstractDatabase: Sync + Send + admin_migrations::AbstractMigrations {} +impl AbstractDatabase for revolt_database::DummyDb {} +impl AbstractDatabase for revolt_database::MongoDb {} + +impl std::ops::Deref for Database { + type Target = dyn AbstractDatabase; + + fn deref(&self) -> &Self::Target { + match &self.0 { + revolt_database::Database::Dummy(dummy) => dummy, + revolt_database::Database::MongoDb(mongo) => mongo, + } + } +} diff --git a/crates/delta/Cargo.toml b/crates/delta/Cargo.toml index 84d4ffdd..556f301d 100644 --- a/crates/delta/Cargo.toml +++ b/crates/delta/Cargo.toml @@ -55,5 +55,9 @@ revolt_rocket_okapi = { version = "0.9.1", features = [ "swagger" ] } # quark revolt-quark = { path = "../quark" } +# core +revolt-database = { path = "../core/database" } +revolt-models = { path = "../core/models" } + [build-dependencies] vergen = "7.5.0" diff --git a/crates/delta/src/main.rs b/crates/delta/src/main.rs index 4dc3ba38..3c2b516a 100644 --- a/crates/delta/src/main.rs +++ b/crates/delta/src/main.rs @@ -22,15 +22,19 @@ async fn rocket() -> _ { revolt_quark::variables::delta::preflight_checks(); // Setup database - let db = DatabaseInfo::Auto.connect().await.unwrap(); + let db = revolt_database::DatabaseInfo::Auto.connect().await.unwrap(); + let db = revolt_models::Database(db); db.migrate_database().await.unwrap(); + // Legacy database setup from quark + let legacy_db = DatabaseInfo::Auto.connect().await.unwrap(); + // Setup Authifier event channel let (sender, receiver) = unbounded(); // Setup Authifier let authifier = Authifier { - database: db.clone().into(), + database: legacy_db.clone().into(), config: revolt_quark::util::authifier::config(), event_channel: Some(sender), }; @@ -52,7 +56,7 @@ async fn rocket() -> _ { }); // Launch background task workers - async_std::task::spawn(revolt_quark::tasks::start_workers(db.clone())); + async_std::task::spawn(revolt_quark::tasks::start_workers(legacy_db.clone())); // Configure CORS let cors = revolt_quark::web::cors::new(); @@ -65,6 +69,7 @@ async fn rocket() -> _ { .mount("/swagger/", revolt_quark::web::swagger::routes()) .manage(authifier) .manage(db) + .manage(legacy_db) .manage(cors.clone()) .attach(revolt_quark::web::ratelimiter::RatelimitFairing) .attach(cors) diff --git a/crates/quark/src/impl/dummy/admin/migrations.rs b/crates/quark/src/impl/dummy/admin/migrations.rs deleted file mode 100644 index d8694453..00000000 --- a/crates/quark/src/impl/dummy/admin/migrations.rs +++ /dev/null @@ -1,11 +0,0 @@ -use crate::{AbstractMigrations, Result}; - -use super::super::DummyDb; - -#[async_trait] -impl AbstractMigrations for DummyDb { - async fn migrate_database(&self) -> Result<()> { - info!("Migrating the database."); - Ok(()) - } -} diff --git a/crates/quark/src/impl/dummy/mod.rs b/crates/quark/src/impl/dummy/mod.rs index fe26641b..194f2edb 100644 --- a/crates/quark/src/impl/dummy/mod.rs +++ b/crates/quark/src/impl/dummy/mod.rs @@ -1,7 +1,6 @@ use crate::AbstractDatabase; pub mod admin { - pub mod migrations; pub mod stats; } diff --git a/crates/quark/src/impl/generic/admin/migrations.rs b/crates/quark/src/impl/generic/admin/migrations.rs deleted file mode 100644 index 8b137891..00000000 --- a/crates/quark/src/impl/generic/admin/migrations.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/crates/quark/src/impl/generic/mod.rs b/crates/quark/src/impl/generic/mod.rs index 5dd5dff6..015bc9dd 100644 --- a/crates/quark/src/impl/generic/mod.rs +++ b/crates/quark/src/impl/generic/mod.rs @@ -1,9 +1,5 @@ //! Database agnostic implementations. -pub mod admin { - pub mod migrations; -} - pub mod media { pub mod attachment; pub mod emoji; diff --git a/crates/quark/src/impl/mongo/mod.rs b/crates/quark/src/impl/mongo/mod.rs index 582d3d6e..7711ab0f 100644 --- a/crates/quark/src/impl/mongo/mod.rs +++ b/crates/quark/src/impl/mongo/mod.rs @@ -12,7 +12,6 @@ use serde::{Deserialize, Serialize}; use crate::{util::manipulation::prefix_keys, AbstractDatabase, Error, Result}; pub mod admin { - pub mod migrations; pub mod stats; } diff --git a/crates/quark/src/models/admin/migrations.rs b/crates/quark/src/models/admin/migrations.rs deleted file mode 100644 index 0a3e620f..00000000 --- a/crates/quark/src/models/admin/migrations.rs +++ /dev/null @@ -1,11 +0,0 @@ -use serde::{Deserialize, Serialize}; - -/// Document representing migration information -#[derive(Serialize, Deserialize)] -pub struct MigrationInfo { - /// Unique Id - #[serde(rename = "_id")] - id: i32, - /// Current database revision - revision: i32, -} diff --git a/crates/quark/src/models/mod.rs b/crates/quark/src/models/mod.rs index c0fdcf28..370c72a1 100644 --- a/crates/quark/src/models/mod.rs +++ b/crates/quark/src/models/mod.rs @@ -1,5 +1,4 @@ mod admin { - pub mod migrations; pub mod simple; pub mod stats; } @@ -47,7 +46,6 @@ pub use channel_invite::Invite; pub use channel_unread::ChannelUnread; pub use emoji::Emoji; pub use message::Message; -pub use migrations::MigrationInfo; pub use report::Report; pub use server::Server; pub use server_ban::ServerBan; diff --git a/crates/quark/src/traits/admin/migrations.rs b/crates/quark/src/traits/admin/migrations.rs deleted file mode 100644 index bb46db7a..00000000 --- a/crates/quark/src/traits/admin/migrations.rs +++ /dev/null @@ -1,6 +0,0 @@ -use crate::Result; - -#[async_trait] -pub trait AbstractMigrations: Sync + Send { - async fn migrate_database(&self) -> Result<()>; -} diff --git a/crates/quark/src/traits/mod.rs b/crates/quark/src/traits/mod.rs index b7c2f6c9..341565a1 100644 --- a/crates/quark/src/traits/mod.rs +++ b/crates/quark/src/traits/mod.rs @@ -1,5 +1,4 @@ mod admin { - pub mod migrations; pub mod stats; } @@ -32,7 +31,6 @@ mod safety { pub mod snapshot; } -pub use admin::migrations::AbstractMigrations; pub use admin::stats::AbstractStats; pub use media::attachment::AbstractAttachment; @@ -57,7 +55,6 @@ pub use safety::snapshot::AbstractSnapshot; pub trait AbstractDatabase: Sync + Send - + AbstractMigrations + AbstractStats + AbstractAttachment + AbstractEmoji