cat_gateway/service/common/auth/
none_or_rbac.rs

1//! Either has No Authorization, or RBAC Token.
2
3use poem::{
4    web::headers::{authorization::Bearer, Authorization, HeaderMapExt},
5    Request, RequestBody,
6};
7use poem_openapi::{registry::Registry, ApiExtractor, ApiExtractorType, ExtractParamOptions};
8
9use super::{
10    none::NoAuthorization,
11    rbac::{scheme::CatalystRBACSecurityScheme, token::CatalystRBACTokenV1},
12};
13
14#[allow(dead_code, clippy::upper_case_acronyms, clippy::large_enum_variant)]
15/// Endpoint allows Authorization with or without RBAC Token.
16pub(crate) enum NoneOrRBAC {
17    /// Has RBAC Token.
18    RBAC(CatalystRBACSecurityScheme),
19    /// Has No Authorization.
20    None(NoAuthorization),
21}
22
23impl<'a> ApiExtractor<'a> for NoneOrRBAC {
24    type ParamRawType = ();
25    type ParamType = ();
26
27    const TYPES: &'static [ApiExtractorType] = &[ApiExtractorType::SecurityScheme];
28
29    fn register(registry: &mut Registry) {
30        CatalystRBACSecurityScheme::register(registry);
31        NoAuthorization::register(registry);
32    }
33
34    fn security_schemes() -> Vec<&'static str> {
35        let mut schemas = Vec::new();
36        schemas.extend(CatalystRBACSecurityScheme::security_schemes());
37        schemas.extend(NoAuthorization::security_schemes());
38        schemas
39    }
40
41    async fn from_request(
42        req: &'a Request, body: &mut RequestBody, param_opts: ExtractParamOptions<Self::ParamType>,
43    ) -> poem::Result<Self> {
44        if req.headers().typed_get::<Authorization<Bearer>>().is_some() {
45            let auth = CatalystRBACSecurityScheme::from_request(req, body, param_opts).await?;
46            Ok(NoneOrRBAC::RBAC(auth))
47        } else {
48            Ok(NoneOrRBAC::None(NoAuthorization))
49        }
50    }
51}
52
53impl From<NoneOrRBAC> for Option<CatalystRBACTokenV1> {
54    fn from(value: NoneOrRBAC) -> Self {
55        match value {
56            NoneOrRBAC::RBAC(auth) => Some(auth.into()),
57            NoneOrRBAC::None(_) => None,
58        }
59    }
60}