1pub 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 EnvironmentMetrics<S, P>
30where
31 S: Clone,
32{
33 router: axum::routing::MethodRouter<S>,
34 privilege_marker: std::marker::PhantomData<fn() -> P>,
35 allowed_methods: Vec<axum::http::method::Method>,
36 reset_metrics: Option<axum::routing::MethodRouter<S>>,
37 reset_to_defaults: Option<axum::routing::MethodRouter<S>>,
38}
39
40impl<S> Default for EnvironmentMetrics<S, DefaultPrivileges>
41where
42 S: Clone,
43{
44 fn default() -> Self {
45 Self {
46 router: Default::default(),
47 privilege_marker: Default::default(),
48 allowed_methods: Vec::new(),
49 reset_metrics: Default::default(),
50 reset_to_defaults: Default::default(),
51 }
52 }
53}
54
55impl<S, P> EnvironmentMetrics<S, P>
56where
57 S: AsRef<dyn redfish_core::auth::AuthenticateRequest> + Clone + Send + Sync + 'static,
58 P: redfish_core::privilege::OperationPrivilegeMapping + 'static,
59 <P as redfish_core::privilege::OperationPrivilegeMapping>::Get: Send,
60 <P as redfish_core::privilege::OperationPrivilegeMapping>::Put: Send,
61 <P as redfish_core::privilege::OperationPrivilegeMapping>::Patch: Send,
62 <P as redfish_core::privilege::OperationPrivilegeMapping>::Post: Send,
63{
64 pub fn get<H, T>(mut self, handler: H) -> Self
65 where
66 H: axum::handler::Handler<T, S, axum::body::Body>,
67 T: 'static,
68 {
69 let operation = axum::routing::get(
70 |auth: redfish_core::extract::RedfishAuth<P::Get>,
71 axum::extract::State(state): axum::extract::State<S>,
72 mut request: axum::http::Request<axum::body::Body>| async {
73 request.extensions_mut().insert(auth.user);
74 handler.call(request, state).await
75 },
76 );
77 self.router = self.router.get(operation);
78 self.allowed_methods.push(axum::http::method::Method::GET);
79 self
80 }
81
82 pub fn put<H, T>(mut self, handler: H) -> Self
83 where
84 H: axum::handler::Handler<T, S, axum::body::Body>,
85 T: 'static,
86 {
87 let operation = axum::routing::put(
88 |auth: redfish_core::extract::RedfishAuth<P::Put>,
89 axum::extract::State(state): axum::extract::State<S>,
90 mut request: axum::http::Request<axum::body::Body>| async {
91 request.extensions_mut().insert(auth.user);
92 handler.call(request, state).await
93 },
94 );
95 self.router = self.router.put(operation);
96 self.allowed_methods.push(axum::http::method::Method::PUT);
97 self
98 }
99
100 pub fn patch<H, T>(mut self, handler: H) -> Self
101 where
102 H: axum::handler::Handler<T, S, axum::body::Body>,
103 T: 'static,
104 {
105 let operation = axum::routing::patch(
106 |auth: redfish_core::extract::RedfishAuth<P::Patch>,
107 axum::extract::State(state): axum::extract::State<S>,
108 mut request: axum::http::Request<axum::body::Body>| async {
109 request.extensions_mut().insert(auth.user);
110 handler.call(request, state).await
111 },
112 );
113 self.router = self.router.patch(operation);
114 self.allowed_methods.push(axum::http::method::Method::PATCH);
115 self
116 }
117
118 pub fn reset_metrics<H, T>(mut self, handler: H) -> Self
120 where
121 H: axum::handler::Handler<T, S, axum::body::Body>,
122 T: 'static,
123 {
124 self.reset_metrics = Some(axum::routing::post(
125 |auth: redfish_core::extract::RedfishAuth<P::Post>,
126 axum::extract::State(state): axum::extract::State<S>,
127 mut request: axum::http::Request<axum::body::Body>| async {
128 request.extensions_mut().insert(auth.user);
129 handler.call(request, state).await
130 },
131 ));
132 self
133 }
134
135 pub fn reset_to_defaults<H, T>(mut self, handler: H) -> Self
137 where
138 H: axum::handler::Handler<T, S, axum::body::Body>,
139 T: 'static,
140 {
141 self.reset_to_defaults = Some(axum::routing::post(
142 |auth: redfish_core::extract::RedfishAuth<P::Post>,
143 axum::extract::State(state): axum::extract::State<S>,
144 mut request: axum::http::Request<axum::body::Body>| async {
145 request.extensions_mut().insert(auth.user);
146 handler.call(request, state).await
147 },
148 ));
149 self
150 }
151
152 pub fn into_router(self) -> axum::Router<S> {
153 let Self {
154 router,
155 mut allowed_methods,
156 reset_metrics,
157 reset_to_defaults,
158 ..
159 } = self;
160 let result = axum::Router::default();
161 let result = match reset_metrics {
162 Some(router) => result.route("/Actions/EnvironmentMetrics.ResetMetrics", router),
163 None => result,
164 };
165 let result = match reset_to_defaults {
166 Some(router) => result.route("/Actions/EnvironmentMetrics.ResetToDefaults", router),
167 None => result,
168 };
169 allowed_methods.dedup();
170 let allow_header = allowed_methods
171 .into_iter()
172 .map(|method| method.to_string())
173 .reduce(|one, two| one + "," + &two)
174 .unwrap();
175 result.route(
176 "/",
177 router.fallback(|| async {
178 (
179 axum::http::StatusCode::METHOD_NOT_ALLOWED,
180 axum::Json(redfish_core::error::one_message(redfish_codegen::registries::base::v1_16_0::Base::OperationNotAllowed.into())),
181 )
182 })
183 .route_layer(axum::middleware::from_fn_with_state(
184 allow_header,
185 |axum::extract::State(allow_header): axum::extract::State<String>,
186 request: axum::http::Request<axum::body::Body>,
187 next: axum::middleware::Next<axum::body::Body>| async move {
188 let apply_allow = matches!(*request.method(), axum::http::Method::GET | axum::http::Method::HEAD);
189 let mut response = next.run(request).await;
190 if apply_allow && !response.headers().contains_key(axum::http::header::ALLOW) {
191 response.headers_mut().insert(
192 axum::http::header::ALLOW,
193 axum::http::HeaderValue::from_str(&allow_header).unwrap(),
194 );
195 }
196 response
197 },
198 )),
199 )
200 }
201}