use crate::api::api_error;
use crate::api::authorize_request;
use crate::api::ok_json_with_trace;
use crate::api::parse_json_payload;
use crate::api::BearerToken;
use crate::db::crud;
use crate::db::models::SecurityAlert;
use crate::AppState;
use actix_web::http::StatusCode;
use actix_web::{post, web, HttpRequest, Responder};
use serde::Deserialize;
use serde_json::json;
use uuid::Uuid;
#[derive(Deserialize)]
pub struct AlertTriggerRequest {
pub entity_id: Uuid, pub entity_type: String, pub alert_type: String, pub severity: String, pub details: serde_json::Value, }
#[post("/alerts/trigger")]
pub async fn trigger_alert(
app_data: web::Data<AppState>,
req: HttpRequest,
bearer: BearerToken,
payload_bytes: web::Bytes,
) -> impl Responder {
if let Err(resp) = authorize_request(&app_data, &req, &bearer, &payload_bytes).await {
return resp;
}
let payload: AlertTriggerRequest = match parse_json_payload(&payload_bytes) {
Ok(v) => v,
Err(resp) => return resp,
};
let alert = SecurityAlert {
id: Uuid::new_v4(),
user_id: payload.entity_id, alert_type: payload.alert_type.clone(), alert_data: json!({
"entity_type": payload.entity_type,
"severity": payload.severity,
"details": payload.details,
}), created_at: chrono::Utc::now().naive_utc(), };
app_data.alert_memory.push(alert.alert_type.clone()).await;
if let Some(pool) = &app_data.db_pool {
if crud::create_security_alert(pool, &alert).await.is_err() {
return api_error(
StatusCode::INTERNAL_SERVER_ERROR,
"ALERT_PERSISTENCE_FAILED",
"Failed to persist alert",
);
}
}
ok_json_with_trace(
&req,
json!({
"status": "alert_triggered",
"alert": alert
}),
)
}