redfish_axum/
metric_definition_collection.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::ConfigureManager;
9 type Put = redfish_core::privilege::ConfigureManager;
10 type Patch = redfish_core::privilege::ConfigureManager;
11 type Delete = redfish_core::privilege::ConfigureManager;
12}
13
14pub struct MetricDefinitionCollection<S, P>
19where
20 S: Clone,
21{
22 router: axum::routing::MethodRouter<S>,
23 privilege_marker: std::marker::PhantomData<fn() -> P>,
24 allowed_methods: Vec<axum::http::method::Method>,
25 members_router: axum::routing::MethodRouter<S>,
26 metric_definition: Option<axum::Router<S>>,
27}
28
29impl<S> Default for MetricDefinitionCollection<S, DefaultPrivileges>
30where
31 S: Clone,
32{
33 fn default() -> Self {
34 Self {
35 router: Default::default(),
36 privilege_marker: Default::default(),
37 allowed_methods: Vec::new(),
38 members_router: Default::default(),
39 metric_definition: Default::default(),
40 }
41 }
42}
43
44impl<S, P> MetricDefinitionCollection<S, P>
45where
46 S: AsRef<dyn redfish_core::auth::AuthenticateRequest> + Clone + Send + Sync + 'static,
47 P: redfish_core::privilege::OperationPrivilegeMapping + 'static,
48 <P as redfish_core::privilege::OperationPrivilegeMapping>::Get: Send,
49 <P as redfish_core::privilege::OperationPrivilegeMapping>::Post: Send,
50{
51 pub fn get<H, T>(mut self, handler: H) -> Self
52 where
53 H: axum::handler::Handler<T, S, axum::body::Body>,
54 T: 'static,
55 {
56 let operation = axum::routing::get(
57 |auth: redfish_core::extract::RedfishAuth<P::Get>,
58 axum::extract::State(state): axum::extract::State<S>,
59 mut request: axum::http::Request<axum::body::Body>| async {
60 request.extensions_mut().insert(auth.user);
61 handler.call(request, state).await
62 },
63 );
64 self.router = self.router.get(operation);
65 self.allowed_methods.push(axum::http::method::Method::GET);
66 self
67 }
68
69 pub fn post<H, T>(mut self, handler: H) -> Self
70 where
71 H: axum::handler::Handler<T, S, axum::body::Body>,
72 T: 'static,
73 {
74 let operation = axum::routing::post(
75 |auth: redfish_core::extract::RedfishAuth<P::Post>,
76 axum::extract::State(state): axum::extract::State<S>,
77 mut request: axum::http::Request<axum::body::Body>| async {
78 request.extensions_mut().insert(auth.user);
79 handler.call(request, state).await
80 },
81 );
82 self.members_router = self.members_router.post(operation.clone());
83 self.router = self.router.post(operation);
84 self.allowed_methods.push(axum::http::method::Method::POST);
85 self
86 }
87
88 pub fn metric_definition(mut self, metric_definition: axum::Router<S>) -> Self {
90 self.metric_definition = Some(metric_definition);
91 self
92 }
93
94 pub fn into_router(self) -> axum::Router<S> {
95 let Self {
96 router,
97 mut allowed_methods,
98 members_router,
99 metric_definition,
100 ..
101 } = self;
102 let result = axum::Router::default();
103 let result = match metric_definition {
104 Some(router) => result.nest("/:metric_definition_id", router),
105 None => result,
106 };
107 let result = result.route(
108 "/Members",
109 members_router.fallback(|| async {
110 (
111 axum::http::StatusCode::METHOD_NOT_ALLOWED,
112 axum::Json(redfish_core::error::one_message(redfish_codegen::registries::base::v1_16_0::Base::OperationNotAllowed.into())),
113 )
114 })
115 );
116 allowed_methods.dedup();
117 let allow_header = allowed_methods
118 .into_iter()
119 .map(|method| method.to_string())
120 .reduce(|one, two| one + "," + &two)
121 .unwrap();
122 result.route(
123 "/",
124 router.fallback(|| async {
125 (
126 axum::http::StatusCode::METHOD_NOT_ALLOWED,
127 axum::Json(redfish_core::error::one_message(redfish_codegen::registries::base::v1_16_0::Base::OperationNotAllowed.into())),
128 )
129 })
130 .route_layer(axum::middleware::from_fn_with_state(
131 allow_header,
132 |axum::extract::State(allow_header): axum::extract::State<String>,
133 request: axum::http::Request<axum::body::Body>,
134 next: axum::middleware::Next<axum::body::Body>| async move {
135 let apply_allow = matches!(*request.method(), axum::http::Method::GET | axum::http::Method::HEAD);
136 let mut response = next.run(request).await;
137 if apply_allow && !response.headers().contains_key(axum::http::header::ALLOW) {
138 response.headers_mut().insert(
139 axum::http::header::ALLOW,
140 axum::http::HeaderValue::from_str(&allow_header).unwrap(),
141 );
142 }
143 response
144 },
145 )),
146 )
147 }
148}