Files
movies-diary/crates/adapters/http-axum/src/api/import/profiles.rs

106 lines
3.4 KiB
Rust

use crate::{errors::ApiError, extractors::AuthenticatedUser, state::AppState};
use api_types::SaveProfileRequest;
use application::import::{
commands::{DeleteImportProfileCommand, SaveImportProfileCommand},
delete_profile as delete_import_profile, list_profiles as list_import_profiles,
save_profile as save_import_profile,
};
use axum::{
extract::{Path, State},
http::StatusCode,
response::IntoResponse,
};
use domain::errors::DomainError;
use domain::value_objects::ImportSessionId;
#[utoipa::path(
get, path = "/api/v1/import/profiles",
responses(
(status = 200, description = "List of saved import profiles", body = inline(Vec<serde_json::Value>)),
(status = 401, description = "Unauthorized"),
),
security(("bearer_auth" = []))
)]
pub async fn api_get_profiles(
State(state): State<AppState>,
AuthenticatedUser(user_id): AuthenticatedUser,
) -> Result<impl IntoResponse, ApiError> {
let profiles =
list_import_profiles::execute(&state.app_ctx.deps.import.list_profiles, &user_id).await?;
Ok(axum::Json(
profiles
.into_iter()
.map(|p| {
serde_json::json!({
"id": p.id.value().to_string(),
"name": p.name,
"created_at": p.created_at.to_string(),
})
})
.collect::<Vec<_>>(),
))
}
#[utoipa::path(
post, path = "/api/v1/import/profiles",
request_body = SaveProfileRequest,
responses(
(status = 200, description = "Profile saved", body = inline(serde_json::Value)),
(status = 401, description = "Unauthorized"),
(status = 422, description = "Session has no mapping yet"),
),
security(("bearer_auth" = []))
)]
pub async fn api_post_profile(
State(state): State<AppState>,
AuthenticatedUser(user_id): AuthenticatedUser,
axum::Json(body): axum::Json<SaveProfileRequest>,
) -> Result<impl IntoResponse, ApiError> {
let session_id = body
.session_id
.parse::<uuid::Uuid>()
.map(ImportSessionId::from_uuid)
.map_err(|_| DomainError::ValidationError("invalid session id".into()))?;
let id = save_import_profile::execute(
&state.app_ctx.deps.import.save_profile,
SaveImportProfileCommand {
user_id: user_id.value(),
session_id: session_id.value(),
name: body.name,
},
)
.await?;
Ok(axum::Json(
serde_json::json!({"id": id.value().to_string()}),
))
}
#[utoipa::path(
delete, path = "/api/v1/import/profiles/{id}",
params(("id" = String, Path, description = "Import profile UUID")),
responses(
(status = 204, description = "Deleted"),
(status = 401, description = "Unauthorized"),
(status = 404, description = "Profile not found"),
),
security(("bearer_auth" = []))
)]
pub async fn api_delete_profile(
State(state): State<AppState>,
AuthenticatedUser(user_id): AuthenticatedUser,
Path(profile_id_str): Path<String>,
) -> Result<impl IntoResponse, ApiError> {
let profile_id = profile_id_str
.parse::<uuid::Uuid>()
.map_err(|_| DomainError::ValidationError("invalid profile id".into()))?;
delete_import_profile::execute(
&state.app_ctx.deps.import.delete_profile,
DeleteImportProfileCommand {
user_id: user_id.value(),
profile_id,
},
)
.await?;
Ok(StatusCode::NO_CONTENT)
}