use std::{env, fs}; use axum::{extract, http::HeaderMap}; use chrono::{Duration, Utc}; use common::Adaptor; use tracing::info; use crate::{errors::ApiError, State}; #[utoipa::path( get, path = "/tasks/cleanup", responses( (status = 200, description = "Cleanup complete"), (status = 401, description = "Missing or incorrect X-Cron-Key header"), (status = 429, description = "Too many requests"), ), security((), ("cron-key" = [])), tag = "tasks", )] /// Delete events older than 3 months pub async fn cleanup( extract::State(state): State, headers: HeaderMap, ) -> Result<(), ApiError> { // Check cron key let cron_key_header: String = headers .get("X-Cron-Key") .map(|k| k.to_str().unwrap_or_default().into()) .unwrap_or_default(); let env_key = if let Ok(key) = env::var("CRON_KEY") { key } else if let Some(path) = env::var_os("CRON_KEY_FILE") { let Ok(key) = fs::read(&path) else { println!("Error reading CRON_KEY_FILE at {path:?}"); return Err(ApiError::NotAuthorized); }; String::from_utf8_lossy(key.as_slice()).to_owned().trim_end().to_string() } else { Default::default() }; if !env_key.is_empty() && cron_key_header != env_key { return Err(ApiError::NotAuthorized); } info!("Running cleanup task"); let adaptor = &state.lock().await.adaptor; let result = adaptor .delete_events(Utc::now() - Duration::days(90)) .await .map_err(ApiError::AdaptorError)?; info!( "Cleanup successful: {} events and {} people removed", result.event_count, result.person_count ); Ok(()) }