/* * Copyright (C) 2025 Jonni Liljamo * * This file is licensed under AGPL-3.0-or-later, see NOTICE and LICENSE for * more information. */ use std::{collections::HashMap, sync::Arc}; use axum::{Json, http::HeaderMap, response::IntoResponse}; use reqwest::StatusCode; use serde::Deserialize; use crate::{ routes::{extract_token, message::MessageForm}, state::State, }; const ALERTMANAGER_JSON_VERSION_4: &str = "4"; #[derive(Debug, Deserialize)] pub struct V4Alert { annotations: HashMap, } #[derive(Debug, Deserialize)] pub struct V4Form { version: String, alerts: Vec, } impl From for MessageForm { fn from(value: V4Alert) -> Self { MessageForm { title: value .annotations .get("summary") .cloned() .unwrap_or("Summary N/A".into()), message: value .annotations .get("description") .cloned() .unwrap_or("Description N/A".into()), format_commonmark: false, } } } pub async fn alertmanager_v4( state: Arc, headers: HeaderMap, Json(message): Json, ) -> impl IntoResponse { let token = extract_token!(headers).trim_start_matches("Bearer "); let notifier = match state.find_notifier(token) { Some(n) => n, None => return (StatusCode::UNAUTHORIZED, "unauthorized"), }; if message.version != ALERTMANAGER_JSON_VERSION_4 { return ( StatusCode::BAD_REQUEST, "wrong alertmanager json version, this API is for version 4", ); } for alert in message.alerts { if let Err(err) = state.send_message(notifier, &alert.into()).await { tracing::error!(?err, "message sending failed"); return (StatusCode::INTERNAL_SERVER_ERROR, "failed to send message"); }; } (StatusCode::OK, "") }