manta_server/server/handlers/
image.rs1use axum::{Json, extract::Query, http::StatusCode, response::IntoResponse};
12
13use super::{
14 ErrorResponse, RequestCtx, SiteHeader, parse_iso_datetime, to_handler_error,
15};
16use crate::service;
17
18pub use manta_shared::types::api::queries::{DeleteImagesQuery, ImageQuery};
23
24#[utoipa::path(get, path = "/images", tag = "images",
26 params(ImageQuery, SiteHeader),
27 security(("bearerAuth" = [])),
28 responses(
29 (status = 200, description = "List of images", body = Vec<serde_json::Value>),
30 (status = 400, description = "Malformed since/until, or since after until", body = ErrorResponse),
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_images(
37 ctx: RequestCtx,
38 Query(q): Query<ImageQuery>,
39) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
40 let infra = ctx.infra();
41
42 let since = q
43 .since
44 .as_deref()
45 .map(|s| parse_iso_datetime("since", s))
46 .transpose()?;
47 let until = q
48 .until
49 .as_deref()
50 .map(|s| parse_iso_datetime("until", s))
51 .transpose()?;
52
53 let params = service::image::GetImagesParams {
54 id: q.id,
55 pattern: q.pattern,
56 since,
57 until,
58 limit: q.limit,
59 };
60
61 let images = service::image::get_images(&infra, &ctx.token, ¶ms)
62 .await
63 .map_err(to_handler_error)?;
64
65 Ok(Json(images))
66}
67
68#[utoipa::path(delete, path = "/images", tag = "images",
74 params(DeleteImagesQuery, SiteHeader),
75 security(("bearerAuth" = [])),
76 responses(
77 (status = 200, description = "Images deleted or validation result", body = serde_json::Value),
79 (status = 400, description = "Bad request", body = ErrorResponse),
80 (status = 401, description = "Unauthorized", body = ErrorResponse),
81 (status = 500, description = "Internal error", body = ErrorResponse),
82 )
83)]
84#[tracing::instrument(skip_all)]
85pub async fn delete_images(
86 ctx: RequestCtx,
87 Query(q): Query<DeleteImagesQuery>,
88) -> Result<impl IntoResponse, (StatusCode, Json<ErrorResponse>)> {
89 tracing::info!("delete_images ids={} dry_run={}", q.ids, q.dry_run);
90 let infra = ctx.infra();
91
92 let id_strings: Vec<String> =
93 q.ids.split(',').map(|s| s.trim().to_string()).collect();
94 let id_refs: Vec<&str> =
95 id_strings.iter().map(std::string::String::as_str).collect();
96
97 if q.dry_run {
98 service::image::validate_image_deletion(&infra, &ctx.token, &id_refs, None)
99 .await
100 .map_err(to_handler_error)?;
101 return Ok((
102 StatusCode::OK,
103 Json(serde_json::json!({ "validated_ids": id_strings })),
104 ));
105 }
106
107 let deleted =
108 service::image::delete_images(&infra, &ctx.token, &id_refs, None)
109 .await
110 .map_err(to_handler_error)?;
111
112 Ok((
113 StatusCode::OK,
114 Json(serde_json::json!({ "deleted": deleted })),
115 ))
116}