redfish_axum/
simple_storage.rs1pub struct DefaultPrivileges;
5impl redfish_core::privilege::OperationPrivilegeMapping for DefaultPrivileges {
6 type Get = redfish_core::privilege::Login;
7 type Head = redfish_core::privilege::Login;
8 type Post = redfish_core::privilege::ConfigureComponents;
9 type Put = redfish_core::privilege::ConfigureComponents;
10 type Patch = redfish_core::privilege::ConfigureComponents;
11 type Delete = redfish_core::privilege::ConfigureComponents;
12}
13
14pub struct SimpleStorage<S, P>
20where
21 S: Clone,
22{
23 router: axum::routing::MethodRouter<S>,
24 privilege_marker: std::marker::PhantomData<fn() -> P>,
25 allowed_methods: Vec<axum::http::method::Method>,
26}
27
28impl<S> Default for SimpleStorage<S, DefaultPrivileges>
29where
30 S: Clone,
31{
32 fn default() -> Self {
33 Self {
34 router: Default::default(),
35 privilege_marker: Default::default(),
36 allowed_methods: Vec::new(),
37 }
38 }
39}
40
41impl<S, P> SimpleStorage<S, P>
42where
43 S: AsRef<dyn redfish_core::auth::AuthenticateRequest> + Clone + Send + Sync + 'static,
44 P: redfish_core::privilege::OperationPrivilegeMapping + 'static,
45 <P as redfish_core::privilege::OperationPrivilegeMapping>::Get: Send,
46{
47 pub fn get<H, T>(mut self, handler: H) -> Self
48 where
49 H: axum::handler::Handler<T, S, axum::body::Body>,
50 T: 'static,
51 {
52 let operation = axum::routing::get(
53 |auth: redfish_core::extract::RedfishAuth<P::Get>,
54 axum::extract::State(state): axum::extract::State<S>,
55 mut request: axum::http::Request<axum::body::Body>| async {
56 request.extensions_mut().insert(auth.user);
57 handler.call(request, state).await
58 },
59 );
60 self.router = self.router.get(operation);
61 self.allowed_methods.push(axum::http::method::Method::GET);
62 self
63 }
64
65 pub fn into_router(self) -> axum::Router<S> {
66 let Self {
67 router,
68 mut allowed_methods,
69 ..
70 } = self;
71 let result = axum::Router::default();
72 allowed_methods.dedup();
73 let allow_header = allowed_methods
74 .into_iter()
75 .map(|method| method.to_string())
76 .reduce(|one, two| one + "," + &two)
77 .unwrap();
78 result.route(
79 "/",
80 router.fallback(|| async {
81 (
82 axum::http::StatusCode::METHOD_NOT_ALLOWED,
83 axum::Json(redfish_core::error::one_message(redfish_codegen::registries::base::v1_16_0::Base::OperationNotAllowed.into())),
84 )
85 })
86 .route_layer(axum::middleware::from_fn_with_state(
87 allow_header,
88 |axum::extract::State(allow_header): axum::extract::State<String>,
89 request: axum::http::Request<axum::body::Body>,
90 next: axum::middleware::Next<axum::body::Body>| async move {
91 let apply_allow = matches!(*request.method(), axum::http::Method::GET | axum::http::Method::HEAD);
92 let mut response = next.run(request).await;
93 if apply_allow && !response.headers().contains_key(axum::http::header::ALLOW) {
94 response.headers_mut().insert(
95 axum::http::header::ALLOW,
96 axum::http::HeaderValue::from_str(&allow_header).unwrap(),
97 );
98 }
99 response
100 },
101 )),
102 )
103 }
104}