use axum::{ extract::{Json, State}, http::StatusCode, response::{IntoResponse, Response}, }; use crate::{ app::App, clock::RequestedAt, error::Internal, login::{Login, Password}, token::{ app, extract::{Identity, IdentityCookie}, }, }; pub async fn handler( State(app): State, RequestedAt(now): RequestedAt, identity: Identity, cookie: IdentityCookie, Json(request): Json, ) -> Result<(IdentityCookie, Json), Error> { let (login, secret) = app .tokens() .change_password(&identity.login, &request.password, &request.to, &now) .await .map_err(Error)?; let cookie = cookie.set(secret); Ok((cookie, Json(login))) } #[derive(serde::Deserialize)] pub struct Request { pub password: Password, pub to: Password, } #[derive(Debug, thiserror::Error)] #[error(transparent)] pub struct Error(#[from] pub app::LoginError); impl IntoResponse for Error { fn into_response(self) -> Response { let Self(error) = self; match error { app::LoginError::Rejected => { (StatusCode::BAD_REQUEST, "invalid name or password").into_response() } other => Internal::from(other).into_response(), } } }