use axum::{ extract::{Json, State}, http::StatusCode, response::{IntoResponse, Response}, }; use crate::{ clock::RequestedAt, empty::Empty, error::Internal, login::{app, app::Logins}, password::Password, token::extract::{Identity, IdentityCookie}, }; #[cfg(test)] mod test; pub async fn handler( State(logins): State, RequestedAt(now): RequestedAt, identity: Identity, cookie: IdentityCookie, Json(request): Json, ) -> Result<(IdentityCookie, Empty), Error> { let secret = logins .change_password(&identity.login, &request.password, &request.to, &now) .await .map_err(Error)?; let cookie = cookie.set(secret); Ok((cookie, Empty)) } #[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(), } } }