manta_server/server/handlers/
configuration.rs1use axum::{Json, extract::Query, http::StatusCode, response::IntoResponse};
4
5use super::{
6 ErrorResponse, RequestCtx, SiteHeader, parse_iso_datetime, serialize_or_500,
7 to_handler_error,
8};
9use crate::service;
10use manta_shared::types::api::configuration_analysis::ConfigurationAnalysis;
11
12pub use manta_shared::types::api::queries::{
17 ConfigurationQuery, DeleteConfigurationsQuery,
18};
19
20#[utoipa::path(get, path = "/configurations", tag = "configurations",
26 params(ConfigurationQuery, SiteHeader),
27 security(("bearerAuth" = [])),
28 responses(
29 (status = 200, description = "Configurations with components-only safe_to_delete verdict",
30 body = Vec<ConfigurationAnalysis>),
31 (status = 401, description = "Unauthorized", body = ErrorResponse),
32 (status = 500, description = "Internal error", body = ErrorResponse),
33 )
34)]
35#[tracing::instrument(skip_all)]
36pub async fn get_configurations(
37 ctx: RequestCtx,
38 Query(q): Query<ConfigurationQuery>,
39) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
40 let infra = ctx.infra();
41
42 let params = service::configuration::GetConfigurationParams {
43 name: q.name,
44 pattern: q.pattern,
45 group_name: q.hsm_group,
46 settings_hsm_group_name: None,
47 since: None,
48 until: None,
49 limit: q.limit,
50 };
51
52 let rows = service::configuration::get_configurations_with_analysis(
53 &infra, &ctx.token, ¶ms,
54 )
55 .await
56 .map_err(to_handler_error)?;
57
58 Ok(Json(rows))
59}
60
61#[utoipa::path(delete, path = "/configurations", tag = "configurations",
67 params(DeleteConfigurationsQuery, SiteHeader),
68 security(("bearerAuth" = [])),
69 responses(
70 (status = 200, description = "Configurations deleted or preview", body = serde_json::Value),
72 (status = 400, description = "Bad request", body = ErrorResponse),
73 (status = 401, description = "Unauthorized", body = ErrorResponse),
74 (status = 500, description = "Internal error", body = ErrorResponse),
75 )
76)]
77#[tracing::instrument(skip_all)]
78pub async fn delete_configurations(
79 ctx: RequestCtx,
80 Query(q): Query<DeleteConfigurationsQuery>,
81) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
82 tracing::info!("delete_configurations dry_run={}", q.dry_run);
83 let infra = ctx.infra();
84
85 let since = q
86 .since
87 .as_deref()
88 .map(|s| parse_iso_datetime("since", s))
89 .transpose()?;
90 let until = q
91 .until
92 .as_deref()
93 .map(|s| parse_iso_datetime("until", s))
94 .transpose()?;
95
96 let candidates = service::configuration::get_deletion_candidates(
97 &infra,
98 &ctx.token,
99 None,
100 q.pattern.as_deref(),
101 since,
102 until,
103 )
104 .await
105 .map_err(to_handler_error)?;
106
107 if q.dry_run {
108 return Ok((StatusCode::OK, Json(serialize_or_500(&candidates)?)));
109 }
110
111 service::configuration::delete_configurations_and_derivatives(
112 &infra,
113 &ctx.token,
114 &candidates,
115 )
116 .await
117 .map_err(to_handler_error)?;
118
119 Ok((
120 StatusCode::OK,
121 Json(serde_json::json!({
122 "deleted_configurations": candidates.configuration_names,
123 "deleted_images": candidates.image_ids,
124 })),
125 ))
126}
127
128