feat: filter reports on fetch

This commit is contained in:
Paul Makles
2023-05-31 17:04:33 +01:00
parent 2a6d532852
commit bca17b11a7
3 changed files with 83 additions and 4 deletions

View File

@@ -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<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")]
pub async fn fetch_reports(db: &Db, user: User) -> Result<Json<Vec<Report>>> {
#[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);
}
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))
}

View File

@@ -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
}
}

View File

@@ -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<Timestamp> },
}
/// 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)]