fixes and functions
This commit is contained in:
+60
-12
@@ -2218,23 +2218,67 @@ pub async fn logout(
|
||||
State(state): State<SharedState>,
|
||||
headers: HeaderMap,
|
||||
) -> Result<Response, AuthError> {
|
||||
if let Some(token) = crate::security::session_token(&headers) {
|
||||
let result = sqlx::query(queries::get(
|
||||
state.db.kind(),
|
||||
queries::AUTH_DELETE_SESSION_BY_TOKEN,
|
||||
))
|
||||
.bind(token)
|
||||
.execute(state.db.pool())
|
||||
.await
|
||||
.map_err(AuthError::database)?;
|
||||
info!(rows_affected = result.rows_affected(), "logout processed");
|
||||
let session_token = crate::security::session_token(&headers).map(str::to_owned);
|
||||
let access_cookies = crate::security::resource_access_cookies(&headers);
|
||||
let has_access_tokens = access_cookies.iter().any(|(_, token)| token.is_some());
|
||||
let mut revoked_access_tokens = 0_u64;
|
||||
|
||||
if session_token.is_some() || has_access_tokens {
|
||||
let mut tx = state
|
||||
.db
|
||||
.pool()
|
||||
.begin()
|
||||
.await
|
||||
.map_err(AuthError::database)?;
|
||||
|
||||
if let Some(token) = session_token.as_deref() {
|
||||
let result = sqlx::query(queries::get(
|
||||
state.db.kind(),
|
||||
queries::AUTH_DELETE_SESSION_BY_TOKEN,
|
||||
))
|
||||
.bind(token)
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(AuthError::database)?;
|
||||
info!(rows_affected = result.rows_affected(), "logout processed");
|
||||
} else {
|
||||
debug!("logout requested without an active session");
|
||||
}
|
||||
|
||||
for (_, token) in &access_cookies {
|
||||
let Some(token) = token.as_deref() else {
|
||||
continue;
|
||||
};
|
||||
let result = sqlx::query(queries::get(
|
||||
state.db.kind(),
|
||||
queries::RESOURCE_ACCESS_TOKENS_DELETE_BY_TOKEN_HASH,
|
||||
))
|
||||
.bind(hash_token(token))
|
||||
.execute(&mut *tx)
|
||||
.await
|
||||
.map_err(AuthError::database)?;
|
||||
revoked_access_tokens += result.rows_affected();
|
||||
}
|
||||
|
||||
tx.commit().await.map_err(AuthError::database)?;
|
||||
} else {
|
||||
debug!("logout requested without an active session");
|
||||
debug!("logout requested without an active session or resource access cookies");
|
||||
}
|
||||
|
||||
debug!(
|
||||
revoked_access_tokens,
|
||||
cleared_access_cookies = access_cookies.len(),
|
||||
"password-derived resource access cleared during logout"
|
||||
);
|
||||
let mut response = Json(serde_json::json!({"ok": true})).into_response();
|
||||
response
|
||||
.headers_mut()
|
||||
.insert(header::SET_COOKIE, crate::security::clear_session_cookie());
|
||||
.append(header::SET_COOKIE, crate::security::clear_session_cookie());
|
||||
for (name, _) in access_cookies {
|
||||
if let Some(cookie) = crate::security::clear_resource_access_cookie(&name) {
|
||||
response.headers_mut().append(header::SET_COOKIE, cookie);
|
||||
}
|
||||
}
|
||||
Ok(response)
|
||||
}
|
||||
|
||||
@@ -3009,3 +3053,7 @@ impl axum::response::IntoResponse for AuthError {
|
||||
.into_response()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[path = "../tests/auth.rs"]
|
||||
mod logout_tests;
|
||||
|
||||
Reference in New Issue
Block a user