mark_deleted: atomic last-admin guard; review minors
This commit is contained in:
@@ -8,13 +8,13 @@ use axum::{
|
||||
};
|
||||
use domain::{errors::DomainError, value_objects::UserId};
|
||||
|
||||
use crate::{errors::ApiError, state::AppState};
|
||||
|
||||
async fn ensure_active(state: &AppState, user_id: &UserId) -> Result<(), DomainError> {
|
||||
application::users::ensure_active::execute(&state.app_ctx.deps.users.ensure_active, user_id)
|
||||
.await
|
||||
}
|
||||
|
||||
use crate::{errors::ApiError, state::AppState};
|
||||
|
||||
pub struct AuthenticatedUser(pub UserId);
|
||||
|
||||
impl<S> FromRequestParts<S> for AuthenticatedUser
|
||||
@@ -82,8 +82,16 @@ where
|
||||
.await
|
||||
.ok();
|
||||
let user_id = match user_id {
|
||||
Some(id) if ensure_active(&app_state, &id).await.is_ok() => Some(id),
|
||||
_ => None,
|
||||
Some(id) => match ensure_active(&app_state, &id).await {
|
||||
Ok(()) => Some(id),
|
||||
Err(e) => {
|
||||
if e.is_transient() {
|
||||
tracing::warn!("ensure_active failed, treating as anonymous: {e:?}");
|
||||
}
|
||||
None
|
||||
}
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
Ok(OptionalCookieUser(user_id))
|
||||
}
|
||||
@@ -138,6 +146,7 @@ where
|
||||
)
|
||||
.await
|
||||
.map_err(ApiError)?
|
||||
// `None` only if the account vanished between `ensure_active` and here.
|
||||
.ok_or_else(|| ApiError(DomainError::NotFound("user not found".into())))?;
|
||||
if is_admin {
|
||||
Ok(AdminApiUser(user_id))
|
||||
@@ -166,6 +175,7 @@ where
|
||||
)
|
||||
.await
|
||||
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR.into_response())?
|
||||
// `None` only if the account vanished between `ensure_active` and here.
|
||||
.ok_or_else(|| StatusCode::UNAUTHORIZED.into_response())?;
|
||||
if is_admin {
|
||||
Ok(AdminUser(user_id))
|
||||
|
||||
Reference in New Issue
Block a user