chore: strip legacy admin API
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@ target
|
|||||||
.env
|
.env
|
||||||
|
|
||||||
.vercel
|
.vercel
|
||||||
|
.DS_Store
|
||||||
|
|||||||
@@ -2,16 +2,12 @@ use std::{collections::HashMap, sync::Arc};
|
|||||||
|
|
||||||
use futures::lock::Mutex;
|
use futures::lock::Mutex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{Bot, Channel, File, Member, MemberCompositeKey, Server, User, UserSettings, Webhook};
|
||||||
AccountStrike, Bot, Channel, File, Member, MemberCompositeKey, Server, User, UserSettings,
|
|
||||||
Webhook,
|
|
||||||
};
|
|
||||||
|
|
||||||
database_derived!(
|
database_derived!(
|
||||||
/// Reference implementation
|
/// Reference implementation
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ReferenceDb {
|
pub struct ReferenceDb {
|
||||||
pub account_strikes: Arc<Mutex<HashMap<String, AccountStrike>>>,
|
|
||||||
pub bots: Arc<Mutex<HashMap<String, Bot>>>,
|
pub bots: Arc<Mutex<HashMap<String, Bot>>>,
|
||||||
pub channel_webhooks: Arc<Mutex<HashMap<String, Webhook>>>,
|
pub channel_webhooks: Arc<Mutex<HashMap<String, Webhook>>>,
|
||||||
pub user_settings: Arc<Mutex<HashMap<String, UserSettings>>>,
|
pub user_settings: Arc<Mutex<HashMap<String, UserSettings>>>,
|
||||||
|
|||||||
@@ -697,7 +697,9 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if revision <= 19 {
|
if revision <= 19 {
|
||||||
info!("Running migration [revision 19 / 27-02-2023]: Create report / snapshot collections, migrate to new model if applicable.");
|
info!(
|
||||||
|
"Running migration [revision 19 / 27-02-2023]: Create report / snapshot collections."
|
||||||
|
);
|
||||||
|
|
||||||
db.db()
|
db.db()
|
||||||
.create_collection("safety_reports", None)
|
.create_collection("safety_reports", None)
|
||||||
@@ -708,19 +710,6 @@ pub async fn run_migrations(db: &MongoDb, revision: i32) -> i32 {
|
|||||||
.create_collection("safety_snapshots", None)
|
.create_collection("safety_snapshots", None)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
db.col::<Document>("safety_reports")
|
|
||||||
.update_many(
|
|
||||||
doc! {},
|
|
||||||
doc! {
|
|
||||||
"$set": {
|
|
||||||
"status": "Created"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if revision <= 20 {
|
if revision <= 20 {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ mod channel_webhooks;
|
|||||||
mod channels;
|
mod channels;
|
||||||
mod files;
|
mod files;
|
||||||
mod ratelimit_events;
|
mod ratelimit_events;
|
||||||
mod safety_strikes;
|
|
||||||
mod server_members;
|
mod server_members;
|
||||||
mod servers;
|
mod servers;
|
||||||
mod user_settings;
|
mod user_settings;
|
||||||
@@ -16,7 +15,6 @@ pub use channel_webhooks::*;
|
|||||||
pub use channels::*;
|
pub use channels::*;
|
||||||
pub use files::*;
|
pub use files::*;
|
||||||
pub use ratelimit_events::*;
|
pub use ratelimit_events::*;
|
||||||
pub use safety_strikes::*;
|
|
||||||
pub use server_members::*;
|
pub use server_members::*;
|
||||||
pub use servers::*;
|
pub use servers::*;
|
||||||
pub use user_settings::*;
|
pub use user_settings::*;
|
||||||
@@ -33,7 +31,6 @@ pub trait AbstractDatabase:
|
|||||||
+ channel_webhooks::AbstractWebhooks
|
+ channel_webhooks::AbstractWebhooks
|
||||||
+ files::AbstractAttachments
|
+ files::AbstractAttachments
|
||||||
+ ratelimit_events::AbstractRatelimitEvents
|
+ ratelimit_events::AbstractRatelimitEvents
|
||||||
+ safety_strikes::AbstractAccountStrikes
|
|
||||||
+ server_members::AbstractServerMembers
|
+ server_members::AbstractServerMembers
|
||||||
+ servers::AbstractServers
|
+ servers::AbstractServers
|
||||||
+ user_settings::AbstractUserSettings
|
+ user_settings::AbstractUserSettings
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
mod model;
|
|
||||||
mod ops;
|
|
||||||
|
|
||||||
pub use model::*;
|
|
||||||
pub use ops::*;
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
use revolt_result::Result;
|
|
||||||
|
|
||||||
use crate::Database;
|
|
||||||
|
|
||||||
auto_derived_partial!(
|
|
||||||
/// Account Strike
|
|
||||||
pub struct AccountStrike {
|
|
||||||
/// Strike Id
|
|
||||||
#[serde(rename = "_id")]
|
|
||||||
pub id: String,
|
|
||||||
/// Id of reported user
|
|
||||||
pub user_id: String,
|
|
||||||
/// Id of moderator
|
|
||||||
pub moderator_id: String,
|
|
||||||
|
|
||||||
/// Attached reason
|
|
||||||
pub reason: String,
|
|
||||||
},
|
|
||||||
"PartialAccountStrike"
|
|
||||||
);
|
|
||||||
|
|
||||||
#[allow(clippy::disallowed_methods)]
|
|
||||||
impl AccountStrike {
|
|
||||||
pub async fn create(
|
|
||||||
db: &Database,
|
|
||||||
user_id: String,
|
|
||||||
reason: String,
|
|
||||||
moderator_id: String,
|
|
||||||
) -> Result<AccountStrike> {
|
|
||||||
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?;
|
|
||||||
self.apply_options(partial);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Delete this strike
|
|
||||||
pub async fn delete(&self, db: &Database) -> Result<()> {
|
|
||||||
db.delete_account_strike(&self.id).await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use std::collections::HashSet;
|
|
||||||
|
|
||||||
use crate::{AccountStrike, PartialAccountStrike};
|
|
||||||
|
|
||||||
#[async_std::test]
|
|
||||||
async fn crud() {
|
|
||||||
database_test!(|db| async move {
|
|
||||||
let user_id = "user";
|
|
||||||
|
|
||||||
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
|
|
||||||
.update(
|
|
||||||
&db,
|
|
||||||
PartialAccountStrike {
|
|
||||||
reason: Some("new reason".to_string()),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let strike2 = AccountStrike::create(
|
|
||||||
&db,
|
|
||||||
user_id.to_string(),
|
|
||||||
"reason 2".to_string(),
|
|
||||||
"moderator_id".to_string(),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let strikes = db.fetch_account_strikes_by_user(user_id).await.unwrap();
|
|
||||||
|
|
||||||
let ids = strikes
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.map(|strike| strike.id)
|
|
||||||
.collect::<HashSet<String>>();
|
|
||||||
|
|
||||||
assert!(ids.contains(&strike.id));
|
|
||||||
assert!(ids.contains(&strike2.id));
|
|
||||||
|
|
||||||
let fetched_strike = strikes
|
|
||||||
.into_iter()
|
|
||||||
.find(|entry| entry.id == strike.id)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(fetched_strike, updated_strike);
|
|
||||||
assert_ne!(fetched_strike, strike);
|
|
||||||
|
|
||||||
strike.delete(&db).await.unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
1,
|
|
||||||
db.fetch_account_strikes_by_user(user_id)
|
|
||||||
.await
|
|
||||||
.unwrap()
|
|
||||||
.len()
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
use revolt_result::Result;
|
|
||||||
|
|
||||||
use crate::{AccountStrike, PartialAccountStrike};
|
|
||||||
|
|
||||||
mod mongodb;
|
|
||||||
mod reference;
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
pub trait AbstractAccountStrikes: Sync + Send {
|
|
||||||
/// Insert new strike into the database
|
|
||||||
async fn insert_account_strike(&self, strike: &AccountStrike) -> Result<()>;
|
|
||||||
|
|
||||||
/// Fetch strike by id
|
|
||||||
async fn fetch_account_strike(&self, id: &str) -> Result<AccountStrike>;
|
|
||||||
|
|
||||||
/// Fetch strikes by user id
|
|
||||||
async fn fetch_account_strikes_by_user(&self, user_id: &str) -> Result<Vec<AccountStrike>>;
|
|
||||||
|
|
||||||
/// Update strike with new information
|
|
||||||
async fn update_account_strike(&self, id: &str, partial: &PartialAccountStrike) -> Result<()>;
|
|
||||||
|
|
||||||
/// Delete a strike from the database
|
|
||||||
async fn delete_account_strike(&self, id: &str) -> Result<()>;
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
use futures::StreamExt;
|
|
||||||
use revolt_result::Result;
|
|
||||||
|
|
||||||
use crate::MongoDb;
|
|
||||||
use crate::{AccountStrike, PartialAccountStrike};
|
|
||||||
|
|
||||||
use super::AbstractAccountStrikes;
|
|
||||||
|
|
||||||
static COL: &str = "safety_strikes";
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl AbstractAccountStrikes for MongoDb {
|
|
||||||
/// Insert new strike into the database
|
|
||||||
async fn insert_account_strike(&self, strike: &AccountStrike) -> Result<()> {
|
|
||||||
query!(self, insert_one, COL, &strike).map(|_| ())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fetch strike by id
|
|
||||||
async fn fetch_account_strike(&self, id: &str) -> Result<AccountStrike> {
|
|
||||||
query!(self, find_one_by_id, COL, id)?.ok_or_else(|| create_error!(NotFound))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fetch strikes by user id
|
|
||||||
async fn fetch_account_strikes_by_user(&self, user_id: &str) -> Result<Vec<AccountStrike>> {
|
|
||||||
Ok(self
|
|
||||||
.col::<AccountStrike>(COL)
|
|
||||||
.find(
|
|
||||||
doc! {
|
|
||||||
"user_id": user_id,
|
|
||||||
},
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.map_err(|_| create_database_error!("find", COL))?
|
|
||||||
.filter_map(|s| async {
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
Some(s.unwrap())
|
|
||||||
} else {
|
|
||||||
s.ok()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
.await)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update strike with new information
|
|
||||||
async fn update_account_strike(&self, id: &str, partial: &PartialAccountStrike) -> Result<()> {
|
|
||||||
query!(self, update_one_by_id, COL, id, partial, vec![], None).map(|_| ())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Delete a strike from the database
|
|
||||||
async fn delete_account_strike(&self, id: &str) -> Result<()> {
|
|
||||||
query!(self, delete_one_by_id, COL, id).map(|_| ())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
use revolt_result::Result;
|
|
||||||
|
|
||||||
use crate::ReferenceDb;
|
|
||||||
use crate::{AccountStrike, PartialAccountStrike};
|
|
||||||
|
|
||||||
use super::AbstractAccountStrikes;
|
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl AbstractAccountStrikes for ReferenceDb {
|
|
||||||
/// Insert new strike into the database
|
|
||||||
async fn insert_account_strike(&self, strike: &AccountStrike) -> Result<()> {
|
|
||||||
let mut strikes = self.account_strikes.lock().await;
|
|
||||||
if strikes.contains_key(&strike.id) {
|
|
||||||
Err(create_database_error!("insert", "strike"))
|
|
||||||
} else {
|
|
||||||
strikes.insert(strike.id.to_string(), strike.clone());
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fetch strike by id
|
|
||||||
async fn fetch_account_strike(&self, id: &str) -> Result<AccountStrike> {
|
|
||||||
let strikes = self.account_strikes.lock().await;
|
|
||||||
strikes
|
|
||||||
.get(id)
|
|
||||||
.cloned()
|
|
||||||
.ok_or_else(|| create_error!(NotFound))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fetch strikes by user id
|
|
||||||
async fn fetch_account_strikes_by_user(&self, user_id: &str) -> Result<Vec<AccountStrike>> {
|
|
||||||
let strikes = self.account_strikes.lock().await;
|
|
||||||
Ok(strikes
|
|
||||||
.values()
|
|
||||||
.filter(|strike| strike.user_id == user_id)
|
|
||||||
.cloned()
|
|
||||||
.collect())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Update strike with new information
|
|
||||||
async fn update_account_strike(&self, id: &str, partial: &PartialAccountStrike) -> Result<()> {
|
|
||||||
let mut strikes = self.account_strikes.lock().await;
|
|
||||||
if let Some(strike) = strikes.get_mut(id) {
|
|
||||||
strike.apply_options(partial.clone());
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(create_error!(NotFound))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Delete a strike from the database
|
|
||||||
async fn delete_account_strike(&self, id: &str) -> Result<()> {
|
|
||||||
let mut strikes = self.account_strikes.lock().await;
|
|
||||||
if strikes.remove(id).is_some() {
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(create_error!(NotFound))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +1,5 @@
|
|||||||
use revolt_models::v0::*;
|
use revolt_models::v0::*;
|
||||||
|
|
||||||
impl From<crate::AccountStrike> for AccountStrike {
|
|
||||||
fn from(value: crate::AccountStrike) -> Self {
|
|
||||||
AccountStrike {
|
|
||||||
id: value.id,
|
|
||||||
user_id: value.user_id,
|
|
||||||
reason: value.reason,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl crate::Bot {
|
impl crate::Bot {
|
||||||
pub fn into_public_bot(self, user: crate::User) -> PublicBot {
|
pub fn into_public_bot(self, user: crate::User) -> PublicBot {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
@@ -52,7 +42,7 @@ impl From<crate::Webhook> for Webhook {
|
|||||||
avatar: value.avatar.map(|file| file.into()),
|
avatar: value.avatar.map(|file| file.into()),
|
||||||
channel_id: value.channel_id,
|
channel_id: value.channel_id,
|
||||||
token: value.token,
|
token: value.token,
|
||||||
permissions: value.permissions
|
permissions: value.permissions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -65,7 +55,7 @@ impl From<crate::PartialWebhook> for PartialWebhook {
|
|||||||
avatar: value.avatar.map(|file| file.into()),
|
avatar: value.avatar.map(|file| file.into()),
|
||||||
channel_id: value.channel_id,
|
channel_id: value.channel_id,
|
||||||
token: value.token,
|
token: value.token,
|
||||||
permissions: value.permissions
|
permissions: value.permissions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
auto_derived!(
|
|
||||||
/// Account Strike
|
|
||||||
pub struct AccountStrike {
|
|
||||||
/// Strike Id
|
|
||||||
#[cfg_attr(feature = "serde", serde(rename = "_id"))]
|
|
||||||
pub id: String,
|
|
||||||
/// Id of reported user
|
|
||||||
pub user_id: String,
|
|
||||||
|
|
||||||
/// Attached reason
|
|
||||||
pub reason: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
mod account_strikes;
|
|
||||||
mod bots;
|
mod bots;
|
||||||
mod channel_webhooks;
|
mod channel_webhooks;
|
||||||
mod channels;
|
mod channels;
|
||||||
mod files;
|
mod files;
|
||||||
mod users;
|
mod users;
|
||||||
|
|
||||||
pub use account_strikes::*;
|
|
||||||
pub use bots::*;
|
pub use bots::*;
|
||||||
pub use channel_webhooks::*;
|
pub use channel_webhooks::*;
|
||||||
pub use channels::*;
|
pub use channels::*;
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
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 = "<data>")]
|
|
||||||
pub async fn create_strike(
|
|
||||||
db: &State<Database>,
|
|
||||||
user: User,
|
|
||||||
data: Json<DataCreateStrike>,
|
|
||||||
) -> Result<Json<AccountStrikeModel>> {
|
|
||||||
// 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)
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
use revolt_database::Database;
|
|
||||||
use revolt_quark::models::User;
|
|
||||||
use revolt_quark::{Error, Result};
|
|
||||||
use rocket::State;
|
|
||||||
|
|
||||||
/// # Delete Strike
|
|
||||||
///
|
|
||||||
/// Delete a strike by its ID
|
|
||||||
#[openapi(tag = "User Safety")]
|
|
||||||
#[delete("/strikes/<strike_id>")]
|
|
||||||
pub async fn delete_strike(db: &State<Database>, user: User, strike_id: String) -> Result<()> {
|
|
||||||
// Must be privileged for this route
|
|
||||||
if !user.privileged {
|
|
||||||
return Err(Error::NotPrivileged);
|
|
||||||
}
|
|
||||||
|
|
||||||
let strike = db
|
|
||||||
.fetch_account_strike(&strike_id)
|
|
||||||
.await
|
|
||||||
.map_err(Error::from_core)?;
|
|
||||||
|
|
||||||
strike.delete(db).await.map_err(Error::from_core)
|
|
||||||
}
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
use revolt_quark::{
|
|
||||||
models::{
|
|
||||||
report::{PartialReport, ReportStatus},
|
|
||||||
Report, User,
|
|
||||||
},
|
|
||||||
Db, Error, Ref, Result,
|
|
||||||
};
|
|
||||||
use rocket::serde::json::Json;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use validator::Validate;
|
|
||||||
|
|
||||||
/// # Report Data
|
|
||||||
#[derive(Validate, Deserialize, JsonSchema)]
|
|
||||||
pub struct DataEditReport {
|
|
||||||
/// New report status
|
|
||||||
status: Option<ReportStatus>,
|
|
||||||
/// Report notes
|
|
||||||
notes: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// # Edit Report
|
|
||||||
///
|
|
||||||
/// Edit a report.
|
|
||||||
#[openapi(tag = "User Safety")]
|
|
||||||
#[patch("/reports/<report>", data = "<edit>")]
|
|
||||||
pub async fn edit_report(
|
|
||||||
db: &Db,
|
|
||||||
user: User,
|
|
||||||
report: Ref,
|
|
||||||
edit: Json<DataEditReport>,
|
|
||||||
) -> Result<Json<Report>> {
|
|
||||||
// Must be privileged for this route
|
|
||||||
if !user.privileged {
|
|
||||||
return Err(Error::NotPrivileged);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate data
|
|
||||||
let edit = edit.into_inner();
|
|
||||||
edit.validate()
|
|
||||||
.map_err(|error| Error::FailedValidation { error })?;
|
|
||||||
|
|
||||||
// Create and apply update to report
|
|
||||||
let mut report = report.as_report(db).await?;
|
|
||||||
report
|
|
||||||
.update(
|
|
||||||
db,
|
|
||||||
PartialReport {
|
|
||||||
status: edit.status,
|
|
||||||
notes: edit.notes,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(Json(report))
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
use revolt_database::{Database, PartialAccountStrike};
|
|
||||||
use revolt_models::v0::DataEditAccountStrike;
|
|
||||||
use revolt_quark::models::User;
|
|
||||||
use revolt_quark::{Error, Result};
|
|
||||||
use rocket::serde::json::Json;
|
|
||||||
use rocket::State;
|
|
||||||
|
|
||||||
/// # Edit Strike
|
|
||||||
///
|
|
||||||
/// Edit a strike by its ID
|
|
||||||
#[openapi(tag = "User Safety")]
|
|
||||||
#[post("/strikes/<strike_id>", data = "<data>")]
|
|
||||||
pub async fn edit_strike(
|
|
||||||
db: &State<Database>,
|
|
||||||
user: User,
|
|
||||||
strike_id: String,
|
|
||||||
data: Json<DataEditAccountStrike>,
|
|
||||||
) -> Result<()> {
|
|
||||||
// Must be privileged for this route
|
|
||||||
if !user.privileged {
|
|
||||||
return Err(Error::NotPrivileged);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut strike = db
|
|
||||||
.fetch_account_strike(&strike_id)
|
|
||||||
.await
|
|
||||||
.map_err(Error::from_core)?;
|
|
||||||
|
|
||||||
strike
|
|
||||||
.update(
|
|
||||||
db,
|
|
||||||
PartialAccountStrike {
|
|
||||||
reason: Some(data.0.reason),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
.map_err(Error::from_core)
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
use revolt_quark::models::{Report, User};
|
|
||||||
use revolt_quark::{Db, Error, Result};
|
|
||||||
use rocket::serde::json::Json;
|
|
||||||
|
|
||||||
/// # Fetch Report
|
|
||||||
///
|
|
||||||
/// Fetch a report by its ID
|
|
||||||
#[openapi(tag = "User Safety")]
|
|
||||||
#[get("/report/<id>")]
|
|
||||||
pub async fn fetch_report(db: &Db, user: User, id: String) -> Result<Json<Report>> {
|
|
||||||
// Must be privileged for this route
|
|
||||||
if !user.privileged {
|
|
||||||
return Err(Error::NotPrivileged);
|
|
||||||
}
|
|
||||||
|
|
||||||
db.fetch_report(&id).await.map(Json)
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
use revolt_quark::models::report::{ReportStatus, ReportStatusString, ReportedContent};
|
|
||||||
use revolt_quark::models::{Report, User};
|
|
||||||
use revolt_quark::{Db, Error, Result};
|
|
||||||
use rocket::serde::json::Json;
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
/// # Query Parameters
|
|
||||||
#[derive(Deserialize, JsonSchema, FromForm)]
|
|
||||||
pub struct OptionsFetchReports {
|
|
||||||
/// Find reports against messages, servers, or users
|
|
||||||
content_id: Option<String>,
|
|
||||||
|
|
||||||
/// Find reports created by user
|
|
||||||
author_id: Option<String>,
|
|
||||||
|
|
||||||
/// Report status to include in search
|
|
||||||
status: Option<ReportStatusString>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// # Fetch Reports
|
|
||||||
///
|
|
||||||
/// Fetch all available reports
|
|
||||||
#[openapi(tag = "User Safety")]
|
|
||||||
#[get("/reports?<options..>")]
|
|
||||||
pub async fn fetch_reports(
|
|
||||||
db: &Db,
|
|
||||||
user: User,
|
|
||||||
options: OptionsFetchReports,
|
|
||||||
) -> Result<Json<Vec<Report>>> {
|
|
||||||
// Must be privileged for this route
|
|
||||||
if !user.privileged {
|
|
||||||
return Err(Error::NotPrivileged);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut reports = db.fetch_reports().await?;
|
|
||||||
|
|
||||||
if let Some(content_id) = options.content_id {
|
|
||||||
reports.retain(|report| match &report.content {
|
|
||||||
ReportedContent::Message { id, .. }
|
|
||||||
| ReportedContent::Server { id, .. }
|
|
||||||
| ReportedContent::User { id, .. } => id == &content_id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(author_id) = options.author_id {
|
|
||||||
reports.retain(|report| report.author_id == author_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(status) = options.status {
|
|
||||||
reports.retain(|report| {
|
|
||||||
matches!(
|
|
||||||
(&status, &report.status),
|
|
||||||
(ReportStatusString::Created, ReportStatus::Created { .. })
|
|
||||||
| (ReportStatusString::Rejected, ReportStatus::Rejected { .. })
|
|
||||||
| (ReportStatusString::Resolved, ReportStatus::Resolved { .. })
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Json(reports))
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
use std::collections::HashSet;
|
|
||||||
|
|
||||||
use revolt_quark::models::snapshot::{SnapshotContent, SnapshotWithContext};
|
|
||||||
use revolt_quark::models::{Channel, User};
|
|
||||||
use revolt_quark::{Db, Error, Result};
|
|
||||||
use rocket::serde::json::Json;
|
|
||||||
|
|
||||||
/// # Fetch Snapshots
|
|
||||||
///
|
|
||||||
/// Fetch a snapshots for a given report
|
|
||||||
#[openapi(tag = "User Safety")]
|
|
||||||
#[get("/snapshot/<report_id>")]
|
|
||||||
pub async fn fetch_snapshots(
|
|
||||||
db: &Db,
|
|
||||||
user: User,
|
|
||||||
report_id: String,
|
|
||||||
) -> Result<Json<Vec<SnapshotWithContext>>> {
|
|
||||||
// Must be privileged for this route
|
|
||||||
if !user.privileged {
|
|
||||||
return Err(Error::NotPrivileged);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch snapshots
|
|
||||||
let snapshots = db.fetch_snapshots(&report_id).await?;
|
|
||||||
let mut result = vec![];
|
|
||||||
|
|
||||||
for snapshot in snapshots {
|
|
||||||
// Resolve and fetch IDs of associated content
|
|
||||||
let mut user_ids: HashSet<&str> = HashSet::new();
|
|
||||||
let mut channel_ids: HashSet<&str> = HashSet::new();
|
|
||||||
|
|
||||||
match &snapshot.content {
|
|
||||||
SnapshotContent::Message {
|
|
||||||
prior_context,
|
|
||||||
leading_context,
|
|
||||||
message,
|
|
||||||
} => {
|
|
||||||
for msg in prior_context {
|
|
||||||
user_ids.insert(&msg.author);
|
|
||||||
}
|
|
||||||
|
|
||||||
for msg in leading_context {
|
|
||||||
user_ids.insert(&msg.author);
|
|
||||||
}
|
|
||||||
|
|
||||||
user_ids.insert(&message.author);
|
|
||||||
channel_ids.insert(&message.channel);
|
|
||||||
}
|
|
||||||
SnapshotContent::User(user) => {
|
|
||||||
user_ids.insert(&user.id);
|
|
||||||
}
|
|
||||||
SnapshotContent::Server(server) => {
|
|
||||||
for channel in &server.channels {
|
|
||||||
channel_ids.insert(channel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect user and channel IDs
|
|
||||||
let user_ids: Vec<String> = user_ids.into_iter().map(|s| s.to_owned()).collect();
|
|
||||||
let channel_ids: Vec<String> = channel_ids.into_iter().map(|s| s.to_owned()).collect();
|
|
||||||
|
|
||||||
// Fetch users and channels
|
|
||||||
let users = db.fetch_users(&user_ids).await?;
|
|
||||||
let channels = db.fetch_channels(&channel_ids).await?;
|
|
||||||
|
|
||||||
// Pull out first server from channels if possible
|
|
||||||
let server = if let Some(server_id) = channels.iter().find_map(|channel| match channel {
|
|
||||||
Channel::TextChannel { server, .. } => Some(server),
|
|
||||||
_ => None,
|
|
||||||
}) {
|
|
||||||
Some(db.fetch_server(server_id).await?)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
// Return snapshot with context
|
|
||||||
result.push(SnapshotWithContext {
|
|
||||||
snapshot,
|
|
||||||
users,
|
|
||||||
channels,
|
|
||||||
server,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Json(result))
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
use revolt_database::Database;
|
|
||||||
use revolt_models::v0::AccountStrike;
|
|
||||||
use revolt_quark::models::User;
|
|
||||||
use revolt_quark::{Error, Result};
|
|
||||||
use rocket::serde::json::Json;
|
|
||||||
use rocket::State;
|
|
||||||
|
|
||||||
/// # Fetch Strikes
|
|
||||||
///
|
|
||||||
/// Fetch strikes for a user by their ID
|
|
||||||
#[openapi(tag = "User Safety")]
|
|
||||||
#[get("/strikes/<user_id>")]
|
|
||||||
pub async fn fetch_strikes(
|
|
||||||
db: &State<Database>,
|
|
||||||
user: User,
|
|
||||||
user_id: String,
|
|
||||||
) -> Result<Json<Vec<AccountStrike>>> {
|
|
||||||
// Must be privileged for this route
|
|
||||||
if !user.privileged {
|
|
||||||
return Err(Error::NotPrivileged);
|
|
||||||
}
|
|
||||||
|
|
||||||
db.fetch_account_strikes_by_user(&user_id)
|
|
||||||
.await
|
|
||||||
.map(|v| v.into_iter().map(|e| e.into()).collect())
|
|
||||||
.map(Json)
|
|
||||||
.map_err(Error::from_core)
|
|
||||||
}
|
|
||||||
@@ -1,31 +1,11 @@
|
|||||||
use revolt_rocket_okapi::revolt_okapi::openapi3::OpenApi;
|
use revolt_rocket_okapi::revolt_okapi::openapi3::OpenApi;
|
||||||
use rocket::Route;
|
use rocket::Route;
|
||||||
|
|
||||||
mod edit_report;
|
|
||||||
mod fetch_report;
|
|
||||||
mod fetch_reports;
|
|
||||||
mod report_content;
|
mod report_content;
|
||||||
|
|
||||||
mod fetch_snapshots;
|
|
||||||
|
|
||||||
mod create_strike;
|
|
||||||
mod delete_strike;
|
|
||||||
mod edit_strike;
|
|
||||||
mod fetch_strikes;
|
|
||||||
|
|
||||||
pub fn routes() -> (Vec<Route>, OpenApi) {
|
pub fn routes() -> (Vec<Route>, OpenApi) {
|
||||||
openapi_get_routes_spec![
|
openapi_get_routes_spec![
|
||||||
// Reports
|
// Reports
|
||||||
edit_report::edit_report,
|
|
||||||
fetch_report::fetch_report,
|
|
||||||
fetch_reports::fetch_reports,
|
|
||||||
report_content::report_content,
|
report_content::report_content,
|
||||||
// Snapshots
|
|
||||||
fetch_snapshots::fetch_snapshots,
|
|
||||||
// Strikes
|
|
||||||
create_strike::create_strike,
|
|
||||||
fetch_strikes::fetch_strikes,
|
|
||||||
edit_strike::edit_strike,
|
|
||||||
delete_strike::delete_strike
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user