From bca17b11a728cd9ce8f5c9f668e08fb39aeb1f00 Mon Sep 17 00:00:00 2001 From: Paul Makles Date: Wed, 31 May 2023 17:04:33 +0100 Subject: [PATCH] feat: filter reports on fetch --- .../delta/src/routes/safety/fetch_reports.rs | 50 +++++++++++++++++-- .../quark/src/impl/generic/safety/report.rs | 23 ++++++++- crates/quark/src/models/safety/report.rs | 14 ++++++ 3 files changed, 83 insertions(+), 4 deletions(-) diff --git a/crates/delta/src/routes/safety/fetch_reports.rs b/crates/delta/src/routes/safety/fetch_reports.rs index 5b418472..0832e157 100644 --- a/crates/delta/src/routes/safety/fetch_reports.rs +++ b/crates/delta/src/routes/safety/fetch_reports.rs @@ -1,17 +1,61 @@ +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, + + /// Find reports created by user + author_id: Option, + + /// Report status to include in search + status: Option, +} /// # Fetch Reports /// /// Fetch all available reports #[openapi(tag = "User Safety")] -#[get("/reports")] -pub async fn fetch_reports(db: &Db, user: User) -> Result>> { +#[get("/reports?")] +pub async fn fetch_reports( + db: &Db, + user: User, + options: OptionsFetchReports, +) -> Result>> { // Must be privileged for this route if !user.privileged { return Err(Error::NotPrivileged); } - db.fetch_reports().await.map(Json) + 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)) } diff --git a/crates/quark/src/impl/generic/safety/report.rs b/crates/quark/src/impl/generic/safety/report.rs index 259d7701..daac34d7 100644 --- a/crates/quark/src/impl/generic/safety/report.rs +++ b/crates/quark/src/impl/generic/safety/report.rs @@ -1,9 +1,30 @@ -use crate::{models::report::PartialReport, models::Report, Database, Result}; +use iso8601_timestamp::Timestamp; + +use crate::{ + models::report::PartialReport, + models::{report::ReportStatus, Report}, + Database, Result, +}; impl Report { /// Update report data pub async fn update(&mut self, db: &Database, partial: PartialReport) -> Result<()> { self.apply_options(partial.clone()); + + match &mut self.status { + ReportStatus::Created {} => {} + ReportStatus::Rejected { closed_at, .. } => { + if closed_at.is_none() { + closed_at.replace(Timestamp::now_utc()); + } + } + ReportStatus::Resolved { closed_at } => { + if closed_at.is_none() { + closed_at.replace(Timestamp::now_utc()); + } + } + } + db.update_report(&self.id, &partial).await } } diff --git a/crates/quark/src/models/safety/report.rs b/crates/quark/src/models/safety/report.rs index 654f6d2f..186fa77a 100644 --- a/crates/quark/src/models/safety/report.rs +++ b/crates/quark/src/models/safety/report.rs @@ -1,4 +1,5 @@ use iso8601_timestamp::Timestamp; +use rocket::FromFormField; use serde::{Deserialize, Serialize}; /// Reason for reporting content (message or server) @@ -119,6 +120,19 @@ pub enum ReportStatus { Resolved { closed_at: Option }, } +/// Just the status of the report +#[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, FromFormField)] +pub enum ReportStatusString { + /// Report is waiting for triage / action + Created, + + /// Report was rejected + Rejected, + + /// Report was actioned and resolved + Resolved, +} + /// User-generated platform moderation report. #[derive(Serialize, Deserialize, JsonSchema, Debug, OptionalStruct, Clone)] #[optional_derive(Serialize, Deserialize, JsonSchema, Debug, Default, Clone)]