1use crate::{
2 auth::{unauthorized, AuthenticateRequest, AuthenticatedUser},
3 privilege::SatisfiesPrivilege,
4};
5use axum::{async_trait, extract::FromRequestParts, http::request::Parts, response::Response};
6use std::marker::PhantomData;
7
8pub struct RedfishAuth<T: SatisfiesPrivilege> {
9 pub user: Option<AuthenticatedUser>,
10 privilege: PhantomData<T>,
11}
12
13#[async_trait]
14impl<S, T> FromRequestParts<S> for RedfishAuth<T>
15where
16 S: AsRef<dyn AuthenticateRequest> + Send + Sync + Clone + 'static,
17 T: SatisfiesPrivilege,
18{
19 type Rejection = Response;
20
21 async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
22 match state.as_ref().authenticate_request(parts) {
23 Ok(Some(user)) => {
24 if T::is_satisfied(&user.role.privileges()) {
25 Ok(RedfishAuth::<T> {
26 user: Some(user),
27 privilege: Default::default(),
28 })
29 } else {
30 Err(unauthorized(&state.as_ref().challenge()))
31 }
32 }
33 Ok(None) => Ok(RedfishAuth::<T> {
34 user: None,
35 privilege: Default::default(),
36 }),
37 Err(error) => Err(error),
38 }
39 }
40}