this repo has no description
1use crate::api::ApiError; 2use crate::state::AppState; 3use axum::{ 4 Json, 5 extract::State, 6 http::StatusCode, 7 response::{IntoResponse, Response}, 8}; 9use serde::{Deserialize, Serialize}; 10use serde_json::{Value, json}; 11use tracing::error; 12 13#[derive(Deserialize)] 14#[serde(rename_all = "camelCase")] 15pub struct CreateReportInput { 16 pub reason_type: String, 17 pub reason: Option<String>, 18 pub subject: Value, 19} 20 21#[derive(Serialize)] 22#[serde(rename_all = "camelCase")] 23pub struct CreateReportOutput { 24 pub id: i64, 25 pub reason_type: String, 26 pub reason: Option<String>, 27 pub subject: Value, 28 pub reported_by: String, 29 pub created_at: String, 30} 31 32pub async fn create_report( 33 State(state): State<AppState>, 34 headers: axum::http::HeaderMap, 35 Json(input): Json<CreateReportInput>, 36) -> Response { 37 let token = match crate::auth::extract_bearer_token_from_header( 38 headers.get("Authorization").and_then(|h| h.to_str().ok()) 39 ) { 40 Some(t) => t, 41 None => return ApiError::AuthenticationRequired.into_response(), 42 }; 43 44 let did = match crate::auth::validate_bearer_token(&state.db, &token).await { 45 Ok(user) => user.did, 46 Err(e) => return ApiError::from(e).into_response(), 47 }; 48 49 let valid_reason_types = [ 50 "com.atproto.moderation.defs#reasonSpam", 51 "com.atproto.moderation.defs#reasonViolation", 52 "com.atproto.moderation.defs#reasonMisleading", 53 "com.atproto.moderation.defs#reasonSexual", 54 "com.atproto.moderation.defs#reasonRude", 55 "com.atproto.moderation.defs#reasonOther", 56 "com.atproto.moderation.defs#reasonAppeal", 57 ]; 58 59 if !valid_reason_types.contains(&input.reason_type.as_str()) { 60 return ( 61 StatusCode::BAD_REQUEST, 62 Json(json!({"error": "InvalidRequest", "message": "Invalid reasonType"})), 63 ) 64 .into_response(); 65 } 66 67 let created_at = chrono::Utc::now(); 68 let report_id = created_at.timestamp_millis(); 69 70 let subject_json = json!(input.subject); 71 let insert = sqlx::query!( 72 "INSERT INTO reports (id, reason_type, reason, subject_json, reported_by_did, created_at) VALUES ($1, $2, $3, $4, $5, $6)", 73 report_id, 74 input.reason_type, 75 input.reason, 76 subject_json, 77 did, 78 created_at 79 ) 80 .execute(&state.db) 81 .await; 82 83 if let Err(e) = insert { 84 error!("Failed to insert report: {:?}", e); 85 return ( 86 StatusCode::INTERNAL_SERVER_ERROR, 87 Json(json!({"error": "InternalError"})), 88 ) 89 .into_response(); 90 } 91 92 ( 93 StatusCode::OK, 94 Json(CreateReportOutput { 95 id: report_id, 96 reason_type: input.reason_type, 97 reason: input.reason, 98 subject: input.subject, 99 reported_by: did, 100 created_at: created_at.to_rfc3339(), 101 }), 102 ) 103 .into_response() 104}