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 Task<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 sub_tasks: Option<axum::Router<S>>,
26}
27
28impl<S> Default for Task<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 sub_tasks: Default::default(),
38 }
39 }
40}
41
42impl<S, P> Task<S, P>
43where
44 S: AsRef<dyn redfish_core::auth::AuthenticateRequest> + Clone + Send + Sync + 'static,
45 P: redfish_core::privilege::OperationPrivilegeMapping + 'static,
46 <P as redfish_core::privilege::OperationPrivilegeMapping>::Get: Send,
47 <P as redfish_core::privilege::OperationPrivilegeMapping>::Delete: Send,
48{
49 pub fn get<H, T>(mut self, handler: H) -> Self
50 where
51 H: axum::handler::Handler<T, S, axum::body::Body>,
52 T: 'static,
53 {
54 let operation = axum::routing::get(
55 |auth: redfish_core::extract::RedfishAuth<P::Get>,
56 axum::extract::State(state): axum::extract::State<S>,
57 mut request: axum::http::Request<axum::body::Body>| async {
58 request.extensions_mut().insert(auth.user);
59 handler.call(request, state).await
60 },
61 );
62 self.router = self.router.get(operation);
63 self.allowed_methods.push(axum::http::method::Method::GET);
64 self
65 }
66
67 pub fn delete<H, T>(mut self, handler: H) -> Self
68 where
69 H: axum::handler::Handler<T, S, axum::body::Body>,
70 T: 'static,
71 {
72 let operation = axum::routing::delete(
73 |auth: redfish_core::extract::RedfishAuth<P::Delete>,
74 axum::extract::State(state): axum::extract::State<S>,
75 mut request: axum::http::Request<axum::body::Body>| async {
76 request.extensions_mut().insert(auth.user);
77 handler.call(request, state).await
78 },
79 );
80 self.router = self.router.delete(operation);
81 self.allowed_methods.push(axum::http::method::Method::DELETE);
82 self
83 }
84
85 pub fn sub_tasks(mut self, sub_tasks: axum::Router<S>) -> Self {
87 self.sub_tasks = Some(sub_tasks);
88 self
89 }
90
91 pub fn into_router(self) -> axum::Router<S> {
92 let Self {
93 router,
94 mut allowed_methods,
95 sub_tasks,
96 ..
97 } = self;
98 let result = axum::Router::default();
99 let result = match sub_tasks {
100 Some(router) => result.nest("/SubTasks", router),
101 None => result,
102 };
103 allowed_methods.dedup();
104 let allow_header = allowed_methods
105 .into_iter()
106 .map(|method| method.to_string())
107 .reduce(|one, two| one + "," + &two)
108 .unwrap();
109 result.route(
110 "/",
111 router.fallback(|| async {
112 (
113 axum::http::StatusCode::METHOD_NOT_ALLOWED,
114 axum::Json(redfish_core::error::one_message(redfish_codegen::registries::base::v1_16_0::Base::OperationNotAllowed.into())),
115 )
116 })
117 .route_layer(axum::middleware::from_fn_with_state(
118 allow_header,
119 |axum::extract::State(allow_header): axum::extract::State<String>,
120 request: axum::http::Request<axum::body::Body>,
121 next: axum::middleware::Next<axum::body::Body>| async move {
122 let apply_allow = matches!(*request.method(), axum::http::Method::GET | axum::http::Method::HEAD);
123 let mut response = next.run(request).await;
124 if apply_allow && !response.headers().contains_key(axum::http::header::ALLOW) {
125 response.headers_mut().insert(
126 axum::http::header::ALLOW,
127 axum::http::HeaderValue::from_str(&allow_header).unwrap(),
128 );
129 }
130 response
131 },
132 )),
133 )
134 }
135}