66 lines
1.9 KiB
Rust
66 lines
1.9 KiB
Rust
use axum::{
|
|
extract::{Extension, State},
|
|
http::{HeaderMap, StatusCode},
|
|
response::IntoResponse,
|
|
};
|
|
use module_auth::LogoutCurrentSessionInput;
|
|
use platform_auth::hash_refresh_session_token;
|
|
use shared_contracts::auth::LogoutResponse;
|
|
use time::OffsetDateTime;
|
|
|
|
use crate::{
|
|
api_response::json_success_body,
|
|
auth::{AuthenticatedAccessToken, RefreshSessionToken},
|
|
auth_session::{
|
|
attach_set_cookie_header, build_clear_refresh_session_cookie_header, map_logout_error,
|
|
},
|
|
http_error::AppError,
|
|
request_context::RequestContext,
|
|
state::AppState,
|
|
};
|
|
|
|
pub async fn logout(
|
|
State(state): State<AppState>,
|
|
Extension(request_context): Extension<RequestContext>,
|
|
Extension(authenticated): Extension<AuthenticatedAccessToken>,
|
|
maybe_refresh_token: Option<Extension<RefreshSessionToken>>,
|
|
) -> Result<impl IntoResponse, AppError> {
|
|
let refresh_token_hash = maybe_refresh_token.and_then(|token| {
|
|
let token = token.0.token().trim().to_string();
|
|
if token.is_empty() {
|
|
return None;
|
|
}
|
|
|
|
Some(hash_refresh_session_token(&token))
|
|
});
|
|
|
|
state
|
|
.auth_user_service()
|
|
.logout_current_session(
|
|
LogoutCurrentSessionInput {
|
|
user_id: authenticated.claims().user_id().to_string(),
|
|
refresh_token_hash,
|
|
},
|
|
OffsetDateTime::now_utc(),
|
|
)
|
|
.map_err(map_logout_error)?;
|
|
state
|
|
.sync_auth_store_snapshot_to_spacetime()
|
|
.await
|
|
.map_err(|error| {
|
|
AppError::from_status(StatusCode::INTERNAL_SERVER_ERROR)
|
|
.with_message(format!("同步认证快照失败:{error}"))
|
|
})?;
|
|
|
|
let mut headers = HeaderMap::new();
|
|
attach_set_cookie_header(
|
|
&mut headers,
|
|
build_clear_refresh_session_cookie_header(&state)?,
|
|
);
|
|
|
|
Ok((
|
|
headers,
|
|
json_success_body(Some(&request_context), LogoutResponse { ok: true }),
|
|
))
|
|
}
|