Skip to content
Clone
563bb99
56 lines 1.8 KB Rust
use axum::extract::{Request, State};
use axum::middleware::Next;
use axum::response::{IntoResponse, Response};
use models::admin::admin_user;
use sea_orm::EntityTrait;
use session::Session;
use crate::errors::AdminApiError;
use crate::errors::password_change_required_response;
use crate::services::service::AdminService;
use crate::share::roles::AdminActor;
use crate::share::session::{admin_uid, clear_admin, pwd_version_matches};
pub async fn admin_guard(
State(service): State<AdminService>,
session: Session,
mut request: Request,
next: Next,
) -> Response {
let Some(uid) = admin_uid(&session) else {
return AdminApiError::unauthorized().into_response();
};
let row = match admin_user::Entity::find_by_id(uid)
.one(service.db().read())
.await
{
Ok(row) => row,
Err(error) => return AdminApiError::internal(error).into_response(),
};
let Some(row) = row else {
clear_admin(&session);
return AdminApiError::unauthorized().into_response();
};
if !row.is_active || !pwd_version_matches(&session, row.passwd_version) {
clear_admin(&session);
return AdminApiError::unauthorized().into_response();
}
if row.must_change_password && !password_change_path_allowed(request.uri().path()) {
return password_change_required_response();
}
request.extensions_mut().insert(AdminActor {
id: row.id,
username: row.username,
display_name: row.display_name,
role: row.role,
must_change_password: row.must_change_password,
});
next.run(request).await
}
fn password_change_path_allowed(path: &str) -> bool {
let path = path.trim_end_matches('/');
path.ends_with("/admin/me")
|| path.ends_with("/admin/me/password")
|| path.ends_with("/admin/auth/logout")
}