use axum::{ extract::{Json, State}, response::{IntoResponse, Response}, }; use crate::{ app::App, clock::RequestedAt, empty::Empty, error::{Internal, Unauthorized}, token::{app, extract::IdentityCookie}, }; #[cfg(test)] mod test; pub async fn handler( State(app): State, RequestedAt(now): RequestedAt, identity: IdentityCookie, Json(_): Json, ) -> Result<(IdentityCookie, Empty), Error> { if let Some(secret) = identity.secret() { let (token, _) = app.tokens().validate(&secret, &now).await?; app.tokens().logout(&token).await?; } let identity = identity.clear(); Ok((identity, Empty)) } // This forces the only valid request to be `{}`, and not the infinite // variation allowed when there's no body extractor. #[derive(Default, serde::Deserialize)] pub struct Request {} #[derive(Debug, thiserror::Error)] #[error(transparent)] pub struct Error(#[from] pub app::ValidateError); impl IntoResponse for Error { fn into_response(self) -> Response { let Self(error) = self; match error { app::ValidateError::InvalidToken | app::ValidateError::LoginDeleted => { Unauthorized.into_response() } app::ValidateError::Name(_) | app::ValidateError::Database(_) => { Internal::from(error).into_response() } } } }