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