Implement cleanup route

This commit is contained in:
Ben Grant 2023-05-16 02:06:56 +10:00
parent 0304f5955d
commit 68cf43164d
4 changed files with 28 additions and 9 deletions

View file

@ -33,5 +33,5 @@ tower-http = { version = "0.4.0", features = ["cors", "trace"] }
tower_governor = "0.0.4" tower_governor = "0.0.4"
tower = "0.4.13" tower = "0.4.13"
utoipa = { version = "3.3.0", features = ["axum_extras", "preserve_order"] } utoipa = { version = "3.3.0", features = ["axum_extras", "preserve_order"] }
utoipa-swagger-ui = { version = "3.1.3", features = ["axum"] } utoipa-swagger-ui = { version = "3.1.3", features = ["axum", "debug-embed"] }
base64 = "0.21.0" base64 = "0.21.0"

View file

@ -1,6 +1,8 @@
use crate::payloads; use crate::payloads;
use crate::routes; use crate::routes;
use utoipa::openapi::security::ApiKey;
use utoipa::openapi::security::ApiKeyValue;
use utoipa::{ use utoipa::{
openapi::security::{HttpAuthScheme, HttpBuilder, SecurityScheme}, openapi::security::{HttpAuthScheme, HttpBuilder, SecurityScheme},
Modify, OpenApi, Modify, OpenApi,
@ -30,6 +32,7 @@ use utoipa::{
(name = "info"), (name = "info"),
(name = "event"), (name = "event"),
(name = "person"), (name = "person"),
(name = "tasks"),
), ),
modifiers(&SecurityAddon), modifiers(&SecurityAddon),
)] )]
@ -49,5 +52,9 @@ impl Modify for SecurityAddon {
.build(), .build(),
), ),
); );
openapi.components.as_mut().unwrap().add_security_scheme(
"cron-key",
SecurityScheme::ApiKey(ApiKey::Header(ApiKeyValue::new("X-Cron-Key"))),
);
} }
} }

View file

@ -12,6 +12,7 @@ use tokio::sync::Mutex;
use tower::ServiceBuilder; use tower::ServiceBuilder;
use tower_governor::{errors::display_error, governor::GovernorConfigBuilder, GovernorLayer}; use tower_governor::{errors::display_error, governor::GovernorConfigBuilder, GovernorLayer};
use tower_http::{cors::CorsLayer, trace::TraceLayer}; use tower_http::{cors::CorsLayer, trace::TraceLayer};
use tracing::Level;
use utoipa::OpenApi; use utoipa::OpenApi;
use utoipa_swagger_ui::SwaggerUi; use utoipa_swagger_ui::SwaggerUi;
@ -32,7 +33,7 @@ pub type State<A> = extract::State<Arc<Mutex<ApiState<A>>>>;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
tracing_subscriber::fmt::init(); tracing_subscriber::fmt().with_max_level(Level::INFO).init();
// Load env // Load env
dotenvy::dotenv().ok(); dotenvy::dotenv().ok();
@ -82,7 +83,7 @@ async fn main() {
"/event/:event_id/people/:person_name", "/event/:event_id/people/:person_name",
patch(person::update_person), patch(person::update_person),
) )
.route("/tasks/cleanup", patch(tasks::cleanup)) .route("/tasks/cleanup", get(tasks::cleanup))
.with_state(shared_state) .with_state(shared_state)
.layer(cors) .layer(cors)
.layer(rate_limit) .layer(rate_limit)

View file

@ -1,6 +1,7 @@
use std::env; use std::env;
use axum::{extract, http::HeaderMap}; use axum::{extract, http::HeaderMap};
use chrono::{Duration, Utc};
use common::Adaptor; use common::Adaptor;
use tracing::info; use tracing::info;
@ -14,6 +15,7 @@ use crate::{errors::ApiError, State};
(status = 401, description = "Missing or incorrect X-Cron-Key header"), (status = 401, description = "Missing or incorrect X-Cron-Key header"),
(status = 429, description = "Too many requests"), (status = 429, description = "Too many requests"),
), ),
security((), ("cron-key" = [])),
tag = "tasks", tag = "tasks",
)] )]
/// Delete events older than 3 months /// Delete events older than 3 months
@ -22,10 +24,12 @@ pub async fn cleanup<A: Adaptor>(
headers: HeaderMap, headers: HeaderMap,
) -> Result<(), ApiError<A>> { ) -> Result<(), ApiError<A>> {
// Check cron key // Check cron key
let cron_key = headers.get("X-Cron-Key").ok_or(ApiError::NotAuthorized)?; let cron_key_header = headers.get("X-Cron-Key");
if let Ok(key) = env::var("CRON_KEY") { if let Some(cron_key) = cron_key_header {
if !key.is_empty() && *cron_key != key { if let Ok(key) = env::var("CRON_KEY") {
return Err(ApiError::NotAuthorized); if !key.is_empty() && *cron_key != key {
return Err(ApiError::NotAuthorized);
}
} }
} }
@ -33,8 +37,15 @@ pub async fn cleanup<A: Adaptor>(
let adaptor = &state.lock().await.adaptor; let adaptor = &state.lock().await.adaptor;
// TODO: let result = adaptor
//let stats = adaptor.get_stats().await.map_err(ApiError::AdaptorError)?; .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(()) Ok(())
} }