From 53c9160cd6825a84afbfc31181da90efdb4477e9 Mon Sep 17 00:00:00 2001 From: Paul Makles Date: Wed, 31 May 2023 19:04:20 +0100 Subject: [PATCH] feat: implement creating strikes feat: add moderator_id to strikes fix: use correct collection for strikes --- Cargo.lock | 6 +- clippy.toml | 7 ++- crates/bonfire/Cargo.toml | 2 +- .../admin_migrations/ops/mongodb/scripts.rs | 19 ++++++- .../src/models/safety_strikes/model.rs | 55 +++++++++++++------ .../src/models/safety_strikes/ops/mongodb.rs | 2 +- crates/core/models/src/v0/account_strikes.rs | 13 ++++- crates/delta/Cargo.toml | 2 +- crates/delta/src/routes/mod.rs | 7 ++- .../delta/src/routes/safety/create_strike.rs | 34 ++++++++++++ crates/delta/src/routes/safety/mod.rs | 2 + crates/quark/Cargo.toml | 2 +- 12 files changed, 120 insertions(+), 31 deletions(-) create mode 100644 crates/delta/src/routes/safety/create_strike.rs diff --git a/Cargo.lock b/Cargo.lock index 19c18261..8d55ada1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2837,7 +2837,7 @@ dependencies = [ [[package]] name = "revolt-bonfire" -version = "0.5.20" +version = "0.5.21" dependencies = [ "async-std", "async-tungstenite", @@ -2879,7 +2879,7 @@ dependencies = [ [[package]] name = "revolt-delta" -version = "0.5.20" +version = "0.5.21" dependencies = [ "async-channel", "async-std", @@ -2951,7 +2951,7 @@ dependencies = [ [[package]] name = "revolt-quark" -version = "0.5.20" +version = "0.5.21" dependencies = [ "async-lock", "async-recursion", diff --git a/clippy.toml b/clippy.toml index f2931377..a1c69535 100644 --- a/clippy.toml +++ b/clippy.toml @@ -2,11 +2,14 @@ disallowed-methods = [ # Shouldn't need to access these directly "revolt_database::models::bots::model::Bot::remove_field", - # Prefer to use Object::update() + # Prefer to use Object::create() + "revolt_database::models::safety_strikes::ops::AbstractAccountStrikes::insert_account_strike", + + # Prefer to use Object::update(&self) "revolt_database::models::bots::ops::AbstractBots::update_bot", "revolt_database::models::safety_strikes::ops::AbstractAccountStrikes::update_account_strike", - # Prefer to use Object::delete() + # Prefer to use Object::delete(&self) "revolt_database::models::bots::ops::AbstractBots::delete_bot", "revolt_database::models::safety_strikes::ops::AbstractAccountStrikes::delete_account_strike", ] diff --git a/crates/bonfire/Cargo.toml b/crates/bonfire/Cargo.toml index ad8cf9e2..9828f03d 100644 --- a/crates/bonfire/Cargo.toml +++ b/crates/bonfire/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "revolt-bonfire" -version = "0.5.20" +version = "0.5.21" license = "AGPL-3.0-or-later" edition = "2021" diff --git a/crates/core/database/src/models/admin_migrations/ops/mongodb/scripts.rs b/crates/core/database/src/models/admin_migrations/ops/mongodb/scripts.rs index 417749d9..7a9a8d38 100644 --- a/crates/core/database/src/models/admin_migrations/ops/mongodb/scripts.rs +++ b/crates/core/database/src/models/admin_migrations/ops/mongodb/scripts.rs @@ -16,7 +16,7 @@ struct MigrationInfo { revision: i32, } -pub const LATEST_REVISION: i32 = 22; +pub const LATEST_REVISION: i32 = 23; pub async fn migrate_database(db: &MongoDb) { let migrations = db.col::("migrations"); @@ -751,6 +751,23 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 { .unwrap(); } + if revision <= 22 { + info!("Running migration [revision 22 / 31-05-2023]: Add moderator_id to account strikes."); + + db.col::("safety_strikes") + .update_many( + doc! {}, + doc! { + "$set": { + "moderator_id": "01EX2NCWQ0CHS3QJF0FEQS1GR4" + } + }, + None, + ) + .await + .expect("Failed to update server members."); + } + // Need to migrate fields on attachments, change `user_id`, `object_id`, etc to `parent`. // Reminder to update LATEST_REVISION when adding new migrations. diff --git a/crates/core/database/src/models/safety_strikes/model.rs b/crates/core/database/src/models/safety_strikes/model.rs index ad0f86fe..28d699c9 100644 --- a/crates/core/database/src/models/safety_strikes/model.rs +++ b/crates/core/database/src/models/safety_strikes/model.rs @@ -8,8 +8,10 @@ auto_derived_partial!( /// Strike Id #[serde(rename = "_id")] pub id: String, - /// User Id of reported user + /// Id of reported user pub user_id: String, + /// Id of moderator + pub moderator_id: String, /// Attached reason pub reason: String, @@ -19,6 +21,23 @@ auto_derived_partial!( #[allow(clippy::disallowed_methods)] impl AccountStrike { + pub async fn create( + db: &Database, + user_id: String, + reason: String, + moderator_id: String, + ) -> Result { + let strike = AccountStrike { + id: ulid::Ulid::new().to_string(), + user_id, + moderator_id, + reason, + }; + + db.insert_account_strike(&strike).await?; + Ok(strike) + } + /// Update this strike pub async fn update(&mut self, db: &Database, partial: PartialAccountStrike) -> Result<()> { db.update_account_strike(&self.id, &partial).await?; @@ -42,16 +61,15 @@ mod tests { async fn crud() { database_test!(|db| async move { let user_id = "user"; - let strike_a = "a"; - let strike_b = "b"; - let strike = AccountStrike { - id: strike_a.to_string(), - user_id: user_id.to_string(), - reason: "reason 1".to_string(), - }; - - db.insert_account_strike(&strike).await.unwrap(); + let strike = AccountStrike::create( + &db, + user_id.to_string(), + "reason 1".to_string(), + "moderator_id".to_string(), + ) + .await + .unwrap(); let mut updated_strike = strike.clone(); updated_strike @@ -65,11 +83,12 @@ mod tests { .await .unwrap(); - db.insert_account_strike(&AccountStrike { - id: strike_b.to_string(), - user_id: user_id.to_string(), - reason: "reason 2".to_string(), - }) + let strike2 = AccountStrike::create( + &db, + user_id.to_string(), + "reason 2".to_string(), + "moderator_id".to_string(), + ) .await .unwrap(); @@ -81,12 +100,12 @@ mod tests { .map(|strike| strike.id) .collect::>(); - assert!(ids.contains(strike_a)); - assert!(ids.contains(strike_b)); + assert!(ids.contains(&strike.id)); + assert!(ids.contains(&strike2.id)); let fetched_strike = strikes .into_iter() - .find(|strike| strike.id == strike_a) + .find(|strike| strike.id == strike.id) .unwrap(); assert_eq!(fetched_strike, updated_strike); diff --git a/crates/core/database/src/models/safety_strikes/ops/mongodb.rs b/crates/core/database/src/models/safety_strikes/ops/mongodb.rs index 079bc997..e6903b3f 100644 --- a/crates/core/database/src/models/safety_strikes/ops/mongodb.rs +++ b/crates/core/database/src/models/safety_strikes/ops/mongodb.rs @@ -6,7 +6,7 @@ use crate::{AccountStrike, PartialAccountStrike}; use super::AbstractAccountStrikes; -static COL: &str = "bots"; +static COL: &str = "safety_strikes"; #[async_trait] impl AbstractAccountStrikes for MongoDb { diff --git a/crates/core/models/src/v0/account_strikes.rs b/crates/core/models/src/v0/account_strikes.rs index d958fe79..d402d2f1 100644 --- a/crates/core/models/src/v0/account_strikes.rs +++ b/crates/core/models/src/v0/account_strikes.rs @@ -4,14 +4,23 @@ auto_derived!( /// Strike Id #[serde(rename = "_id")] pub id: String, - /// User Id of reported user + /// Id of reported user pub user_id: String, /// Attached reason pub reason: String, } - /// # Strike Data + /// New strike information + pub struct DataCreateStrike { + /// Id of reported user + pub user_id: String, + + /// Attached reason + pub reason: String, + } + + /// New strike information pub struct DataEditAccountStrike { /// New attached reason pub reason: String, diff --git a/crates/delta/Cargo.toml b/crates/delta/Cargo.toml index 5810899a..1445cb60 100644 --- a/crates/delta/Cargo.toml +++ b/crates/delta/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "revolt-delta" -version = "0.5.20" +version = "0.5.21" license = "AGPL-3.0-or-later" authors = ["Paul Makles "] edition = "2018" diff --git a/crates/delta/src/routes/mod.rs b/crates/delta/src/routes/mod.rs index b26d2cd2..dae3e819 100644 --- a/crates/delta/src/routes/mod.rs +++ b/crates/delta/src/routes/mod.rs @@ -158,7 +158,12 @@ fn custom_openapi_spec() -> OpenApi { servers: vec![ Server { url: "https://api.revolt.chat".to_owned(), - description: Some("Revolt API".to_owned()), + description: Some("Revolt Production".to_owned()), + ..Default::default() + }, + Server { + url: "https://revolt.chat/api".to_owned(), + description: Some("Revolt Staging".to_owned()), ..Default::default() }, Server { diff --git a/crates/delta/src/routes/safety/create_strike.rs b/crates/delta/src/routes/safety/create_strike.rs new file mode 100644 index 00000000..43fc078c --- /dev/null +++ b/crates/delta/src/routes/safety/create_strike.rs @@ -0,0 +1,34 @@ +use revolt_database::{AccountStrike, Database}; +use revolt_models::v0::{AccountStrike as AccountStrikeModel, DataCreateStrike}; +use revolt_quark::models::User; +use revolt_quark::{Error, Result}; +use rocket::serde::json::Json; +use rocket::State; + +/// # Create Strike +/// +/// Create a new account strike +#[openapi(tag = "User Safety")] +#[post("/strikes", data = "")] +pub async fn create_strike( + db: &State, + user: User, + data: Json, +) -> Result> { + // Must be privileged for this route + if !user.privileged { + return Err(Error::NotPrivileged); + } + + let data = data.into_inner(); + let target = db + .fetch_user(&data.user_id) + .await + .map_err(Error::from_core)?; + + AccountStrike::create(db, target.id, data.reason, user.id) + .await + .map(|strike| strike.into()) + .map(Json) + .map_err(Error::from_core) +} diff --git a/crates/delta/src/routes/safety/mod.rs b/crates/delta/src/routes/safety/mod.rs index fac79499..f9027811 100644 --- a/crates/delta/src/routes/safety/mod.rs +++ b/crates/delta/src/routes/safety/mod.rs @@ -8,6 +8,7 @@ mod report_content; mod fetch_snapshots; +mod create_strike; mod delete_strike; mod edit_strike; mod fetch_strikes; @@ -22,6 +23,7 @@ pub fn routes() -> (Vec, OpenApi) { // Snapshots fetch_snapshots::fetch_snapshots, // Strikes + create_strike::create_strike, fetch_strikes::fetch_strikes, edit_strike::edit_strike, delete_strike::delete_strike diff --git a/crates/quark/Cargo.toml b/crates/quark/Cargo.toml index 87878c6f..36204037 100644 --- a/crates/quark/Cargo.toml +++ b/crates/quark/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "revolt-quark" -version = "0.5.20" +version = "0.5.21" edition = "2021" license = "AGPL-3.0-or-later"