use axum::{ extract::{Json, State}, http::StatusCode, response::{IntoResponse, Response}, routing::post, Router, }; use super::app; use crate::{ app::App, clock::RequestedAt, error::Internal, login::Password, token::extract::IdentityToken, }; pub fn router() -> Router { Router::new().route("/api/setup", post(on_setup)) } #[derive(serde::Deserialize)] struct SetupRequest { name: String, password: Password, } async fn on_setup( State(app): State, RequestedAt(setup_at): RequestedAt, identity: IdentityToken, Json(request): Json, ) -> Result<(IdentityToken, StatusCode), SetupError> { let secret = app .setup() .initial(&request.name, &request.password, &setup_at) .await .map_err(SetupError)?; let identity = identity.set(secret); Ok((identity, StatusCode::NO_CONTENT)) } #[derive(Debug)] struct SetupError(app::Error); impl IntoResponse for SetupError { fn into_response(self) -> Response { let Self(error) = self; match error { app::Error::SetupCompleted => (StatusCode::CONFLICT, error.to_string()).into_response(), other => Internal::from(other).into_response(), } } }