use models::users::user_reports; use models::users::user_reports::ReportStatus; use sea_orm::{ActiveModelTrait, EntityTrait, Set}; use serde::{Deserialize, Serialize}; use time::OffsetDateTime; use uuid::Uuid; use super::AuthService; use crate::errors::AuthError; #[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)] pub struct CreateReportCmd { pub reported_id: i64, pub reason: String, pub evidence: Option, } #[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)] pub struct ReportDto { pub id: Uuid, pub reported_id: i64, pub reason: String, pub evidence: Option, pub status: ReportStatus, pub created_at: OffsetDateTime, } impl AuthService { pub async fn create_report( &self, reporter_uid: i64, cmd: CreateReportCmd, ) -> Result { if reporter_uid == cmd.reported_id { return Err(AuthError::BadRequest("cannot report yourself".to_string())); } let reason = cmd.reason.trim().to_string(); if reason.is_empty() || reason.len() > 500 { return Err(AuthError::BadRequest( "reason must be between 1 and 500 characters".to_string(), )); } let db = self.db(); let reported = models::users::user::Entity::find_by_id(cmd.reported_id) .one(db.read()) .await?; if reported.is_none() { return Err(AuthError::NotFound); } let now = OffsetDateTime::now_utc(); let row = user_reports::ActiveModel { id: Set(Uuid::now_v7()), reporter_uid: Set(Some(reporter_uid)), reported_uid: Set(cmd.reported_id), reason: Set(reason), evidence: Set(cmd.evidence), status: Set(ReportStatus::Open), resolver_uid: Set(None), resolution_note: Set(None), created_at: Set(now), updated_at: Set(now), }; let inserted = row.insert(db.write()).await?; Ok(ReportDto { id: inserted.id, reported_id: inserted.reported_uid, reason: inserted.reason, evidence: inserted.evidence, status: inserted.status, created_at: inserted.created_at, }) } }