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::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 LogEntryPrivileges;
17impl redfish_core::privilege::OperationPrivilegeMapping for LogEntryPrivileges {
18 type Get = redfish_core::privilege::Login;
19 type Head = redfish_core::privilege::Login;
20 type Post = redfish_core::privilege::ConfigureComponents;
21 type Put = redfish_core::privilege::ConfigureComponents;
22 type Patch = redfish_core::privilege::ConfigureComponents;
23 type Delete = redfish_core::privilege::ConfigureComponents;
24}
25
26pub struct LogEntryCollectionPrivileges;
29impl redfish_core::privilege::OperationPrivilegeMapping for LogEntryCollectionPrivileges {
30 type Get = redfish_core::privilege::Login;
31 type Head = redfish_core::privilege::Login;
32 type Post = redfish_core::privilege::ConfigureComponents;
33 type Put = redfish_core::privilege::ConfigureComponents;
34 type Patch = redfish_core::privilege::ConfigureComponents;
35 type Delete = redfish_core::privilege::ConfigureComponents;
36}
37
38pub struct LogServicePrivileges;
41impl redfish_core::privilege::OperationPrivilegeMapping for LogServicePrivileges {
42 type Get = redfish_core::privilege::Login;
43 type Head = redfish_core::privilege::Login;
44 type Post = redfish_core::privilege::ConfigureComponents;
45 type Put = redfish_core::privilege::ConfigureComponents;
46 type Patch = redfish_core::privilege::ConfigureComponents;
47 type Delete = redfish_core::privilege::ConfigureComponents;
48}
49
50pub struct LogServiceCollectionPrivileges;
53impl redfish_core::privilege::OperationPrivilegeMapping for LogServiceCollectionPrivileges {
54 type Get = redfish_core::privilege::Login;
55 type Head = redfish_core::privilege::Login;
56 type Post = redfish_core::privilege::ConfigureComponents;
57 type Put = redfish_core::privilege::ConfigureComponents;
58 type Patch = redfish_core::privilege::ConfigureComponents;
59 type Delete = redfish_core::privilege::ConfigureComponents;
60}
61
62pub struct Chassis<S, P>
67where
68 S: Clone,
69{
70 router: axum::routing::MethodRouter<S>,
71 privilege_marker: std::marker::PhantomData<fn() -> P>,
72 allowed_methods: Vec<axum::http::method::Method>,
73 log_services: Option<axum::Router<S>>,
74 controls: Option<axum::Router<S>>,
75 pcie_devices: Option<axum::Router<S>>,
76 pcie_slots: Option<axum::Router<S>>,
77 processors: Option<axum::Router<S>>,
78 certificates: Option<axum::Router<S>>,
79 memory_domains: Option<axum::Router<S>>,
80 environment_metrics: Option<axum::Router<S>>,
81 media_controllers: Option<axum::Router<S>>,
82 trusted_components: Option<axum::Router<S>>,
83 network_adapters: Option<axum::Router<S>>,
84 thermal_subsystem: Option<axum::Router<S>>,
85 sensors: Option<axum::Router<S>>,
86 thermal: Option<axum::Router<S>>,
87 power: Option<axum::Router<S>>,
88 power_subsystem: Option<axum::Router<S>>,
89 assembly: Option<axum::Router<S>>,
90 fabric_adapters: Option<axum::Router<S>>,
91 memory: Option<axum::Router<S>>,
92 drives: Option<axum::Router<S>>,
93 reset: Option<axum::routing::MethodRouter<S>>,
94}
95
96impl<S> Default for Chassis<S, DefaultPrivileges>
97where
98 S: Clone,
99{
100 fn default() -> Self {
101 Self {
102 router: Default::default(),
103 privilege_marker: Default::default(),
104 allowed_methods: Vec::new(),
105 log_services: Default::default(),
106 controls: Default::default(),
107 pcie_devices: Default::default(),
108 pcie_slots: Default::default(),
109 processors: Default::default(),
110 certificates: Default::default(),
111 memory_domains: Default::default(),
112 environment_metrics: Default::default(),
113 media_controllers: Default::default(),
114 trusted_components: Default::default(),
115 network_adapters: Default::default(),
116 thermal_subsystem: Default::default(),
117 sensors: Default::default(),
118 thermal: Default::default(),
119 power: Default::default(),
120 power_subsystem: Default::default(),
121 assembly: Default::default(),
122 fabric_adapters: Default::default(),
123 memory: Default::default(),
124 drives: Default::default(),
125 reset: Default::default(),
126 }
127 }
128}
129
130impl<S, P> Chassis<S, P>
131where
132 S: AsRef<dyn redfish_core::auth::AuthenticateRequest> + Clone + Send + Sync + 'static,
133 P: redfish_core::privilege::OperationPrivilegeMapping + 'static,
134 <P as redfish_core::privilege::OperationPrivilegeMapping>::Get: Send,
135 <P as redfish_core::privilege::OperationPrivilegeMapping>::Put: Send,
136 <P as redfish_core::privilege::OperationPrivilegeMapping>::Patch: Send,
137 <P as redfish_core::privilege::OperationPrivilegeMapping>::Delete: Send,
138 <P as redfish_core::privilege::OperationPrivilegeMapping>::Post: Send,
139{
140 pub fn get<H, T>(mut self, handler: H) -> Self
141 where
142 H: axum::handler::Handler<T, S, axum::body::Body>,
143 T: 'static,
144 {
145 let operation = axum::routing::get(
146 |auth: redfish_core::extract::RedfishAuth<P::Get>,
147 axum::extract::State(state): axum::extract::State<S>,
148 mut request: axum::http::Request<axum::body::Body>| async {
149 request.extensions_mut().insert(auth.user);
150 handler.call(request, state).await
151 },
152 );
153 self.router = self.router.get(operation);
154 self.allowed_methods.push(axum::http::method::Method::GET);
155 self
156 }
157
158 pub fn put<H, T>(mut self, handler: H) -> Self
159 where
160 H: axum::handler::Handler<T, S, axum::body::Body>,
161 T: 'static,
162 {
163 let operation = axum::routing::put(
164 |auth: redfish_core::extract::RedfishAuth<P::Put>,
165 axum::extract::State(state): axum::extract::State<S>,
166 mut request: axum::http::Request<axum::body::Body>| async {
167 request.extensions_mut().insert(auth.user);
168 handler.call(request, state).await
169 },
170 );
171 self.router = self.router.put(operation);
172 self.allowed_methods.push(axum::http::method::Method::PUT);
173 self
174 }
175
176 pub fn patch<H, T>(mut self, handler: H) -> Self
177 where
178 H: axum::handler::Handler<T, S, axum::body::Body>,
179 T: 'static,
180 {
181 let operation = axum::routing::patch(
182 |auth: redfish_core::extract::RedfishAuth<P::Patch>,
183 axum::extract::State(state): axum::extract::State<S>,
184 mut request: axum::http::Request<axum::body::Body>| async {
185 request.extensions_mut().insert(auth.user);
186 handler.call(request, state).await
187 },
188 );
189 self.router = self.router.patch(operation);
190 self.allowed_methods.push(axum::http::method::Method::PATCH);
191 self
192 }
193
194 pub fn delete<H, T>(mut self, handler: H) -> Self
195 where
196 H: axum::handler::Handler<T, S, axum::body::Body>,
197 T: 'static,
198 {
199 let operation = axum::routing::delete(
200 |auth: redfish_core::extract::RedfishAuth<P::Delete>,
201 axum::extract::State(state): axum::extract::State<S>,
202 mut request: axum::http::Request<axum::body::Body>| async {
203 request.extensions_mut().insert(auth.user);
204 handler.call(request, state).await
205 },
206 );
207 self.router = self.router.delete(operation);
208 self.allowed_methods.push(axum::http::method::Method::DELETE);
209 self
210 }
211
212 pub fn log_services(mut self, log_services: axum::Router<S>) -> Self {
214 self.log_services = Some(log_services);
215 self
216 }
217
218 pub fn controls(mut self, controls: axum::Router<S>) -> Self {
220 self.controls = Some(controls);
221 self
222 }
223
224 pub fn pcie_devices(mut self, pcie_devices: axum::Router<S>) -> Self {
226 self.pcie_devices = Some(pcie_devices);
227 self
228 }
229
230 pub fn pcie_slots(mut self, pcie_slots: axum::Router<S>) -> Self {
232 self.pcie_slots = Some(pcie_slots);
233 self
234 }
235
236 pub fn processors(mut self, processors: axum::Router<S>) -> Self {
238 self.processors = Some(processors);
239 self
240 }
241
242 pub fn certificates(mut self, certificates: axum::Router<S>) -> Self {
244 self.certificates = Some(certificates);
245 self
246 }
247
248 pub fn memory_domains(mut self, memory_domains: axum::Router<S>) -> Self {
250 self.memory_domains = Some(memory_domains);
251 self
252 }
253
254 pub fn environment_metrics(mut self, environment_metrics: axum::Router<S>) -> Self {
256 self.environment_metrics = Some(environment_metrics);
257 self
258 }
259
260 pub fn media_controllers(mut self, media_controllers: axum::Router<S>) -> Self {
262 self.media_controllers = Some(media_controllers);
263 self
264 }
265
266 pub fn trusted_components(mut self, trusted_components: axum::Router<S>) -> Self {
268 self.trusted_components = Some(trusted_components);
269 self
270 }
271
272 pub fn network_adapters(mut self, network_adapters: axum::Router<S>) -> Self {
274 self.network_adapters = Some(network_adapters);
275 self
276 }
277
278 pub fn thermal_subsystem(mut self, thermal_subsystem: axum::Router<S>) -> Self {
280 self.thermal_subsystem = Some(thermal_subsystem);
281 self
282 }
283
284 pub fn sensors(mut self, sensors: axum::Router<S>) -> Self {
286 self.sensors = Some(sensors);
287 self
288 }
289
290 pub fn thermal(mut self, thermal: axum::Router<S>) -> Self {
292 self.thermal = Some(thermal);
293 self
294 }
295
296 pub fn power(mut self, power: axum::Router<S>) -> Self {
298 self.power = Some(power);
299 self
300 }
301
302 pub fn power_subsystem(mut self, power_subsystem: axum::Router<S>) -> Self {
304 self.power_subsystem = Some(power_subsystem);
305 self
306 }
307
308 pub fn assembly(mut self, assembly: axum::Router<S>) -> Self {
310 self.assembly = Some(assembly);
311 self
312 }
313
314 pub fn fabric_adapters(mut self, fabric_adapters: axum::Router<S>) -> Self {
316 self.fabric_adapters = Some(fabric_adapters);
317 self
318 }
319
320 pub fn memory(mut self, memory: axum::Router<S>) -> Self {
322 self.memory = Some(memory);
323 self
324 }
325
326 pub fn drives(mut self, drives: axum::Router<S>) -> Self {
328 self.drives = Some(drives);
329 self
330 }
331
332 pub fn reset<H, T>(mut self, handler: H) -> Self
334 where
335 H: axum::handler::Handler<T, S, axum::body::Body>,
336 T: 'static,
337 {
338 self.reset = Some(axum::routing::post(
339 |auth: redfish_core::extract::RedfishAuth<P::Post>,
340 axum::extract::State(state): axum::extract::State<S>,
341 mut request: axum::http::Request<axum::body::Body>| async {
342 request.extensions_mut().insert(auth.user);
343 handler.call(request, state).await
344 },
345 ));
346 self
347 }
348
349 pub fn into_router(self) -> axum::Router<S> {
350 let Self {
351 router,
352 mut allowed_methods,
353 log_services,
354 controls,
355 pcie_devices,
356 pcie_slots,
357 processors,
358 certificates,
359 memory_domains,
360 environment_metrics,
361 media_controllers,
362 trusted_components,
363 network_adapters,
364 thermal_subsystem,
365 sensors,
366 thermal,
367 power,
368 power_subsystem,
369 assembly,
370 fabric_adapters,
371 memory,
372 drives,
373 reset,
374 ..
375 } = self;
376 let result = axum::Router::default();
377 let result = match log_services {
378 Some(router) => result.nest("/LogServices", router),
379 None => result,
380 };
381 let result = match controls {
382 Some(router) => result.nest("/Controls", router),
383 None => result,
384 };
385 let result = match pcie_devices {
386 Some(router) => result.nest("/PCIeDevices", router),
387 None => result,
388 };
389 let result = match pcie_slots {
390 Some(router) => result.nest("/PCIeSlots", router),
391 None => result,
392 };
393 let result = match processors {
394 Some(router) => result.nest("/Processors", router),
395 None => result,
396 };
397 let result = match certificates {
398 Some(router) => result.nest("/Certificates", router),
399 None => result,
400 };
401 let result = match memory_domains {
402 Some(router) => result.nest("/MemoryDomains", router),
403 None => result,
404 };
405 let result = match environment_metrics {
406 Some(router) => result.nest("/EnvironmentMetrics", router),
407 None => result,
408 };
409 let result = match media_controllers {
410 Some(router) => result.nest("/MediaControllers", router),
411 None => result,
412 };
413 let result = match trusted_components {
414 Some(router) => result.nest("/TrustedComponents", router),
415 None => result,
416 };
417 let result = match network_adapters {
418 Some(router) => result.nest("/NetworkAdapters", router),
419 None => result,
420 };
421 let result = match thermal_subsystem {
422 Some(router) => result.nest("/ThermalSubsystem", router),
423 None => result,
424 };
425 let result = match sensors {
426 Some(router) => result.nest("/Sensors", router),
427 None => result,
428 };
429 let result = match thermal {
430 Some(router) => result.nest("/Thermal", router),
431 None => result,
432 };
433 let result = match power {
434 Some(router) => result.nest("/Power", router),
435 None => result,
436 };
437 let result = match power_subsystem {
438 Some(router) => result.nest("/PowerSubsystem", router),
439 None => result,
440 };
441 let result = match assembly {
442 Some(router) => result.nest("/Assembly", router),
443 None => result,
444 };
445 let result = match fabric_adapters {
446 Some(router) => result.nest("/FabricAdapters", router),
447 None => result,
448 };
449 let result = match memory {
450 Some(router) => result.nest("/Memory", router),
451 None => result,
452 };
453 let result = match drives {
454 Some(router) => result.nest("/Drives", router),
455 None => result,
456 };
457 let result = match reset {
458 Some(router) => result.route("/Actions/Chassis.Reset", router),
459 None => result,
460 };
461 allowed_methods.dedup();
462 let allow_header = allowed_methods
463 .into_iter()
464 .map(|method| method.to_string())
465 .reduce(|one, two| one + "," + &two)
466 .unwrap();
467 result.route(
468 "/",
469 router.fallback(|| async {
470 (
471 axum::http::StatusCode::METHOD_NOT_ALLOWED,
472 axum::Json(redfish_core::error::one_message(redfish_codegen::registries::base::v1_16_0::Base::OperationNotAllowed.into())),
473 )
474 })
475 .route_layer(axum::middleware::from_fn_with_state(
476 allow_header,
477 |axum::extract::State(allow_header): axum::extract::State<String>,
478 request: axum::http::Request<axum::body::Body>,
479 next: axum::middleware::Next<axum::body::Body>| async move {
480 let apply_allow = matches!(*request.method(), axum::http::Method::GET | axum::http::Method::HEAD);
481 let mut response = next.run(request).await;
482 if apply_allow && !response.headers().contains_key(axum::http::header::ALLOW) {
483 response.headers_mut().insert(
484 axum::http::header::ALLOW,
485 axum::http::HeaderValue::from_str(&allow_header).unwrap(),
486 );
487 }
488 response
489 },
490 )),
491 )
492 }
493}