1use std::fmt;
19use std::sync::Arc;
20
21use serde_json::Map;
22use serde_json::Number;
23use serde_json::Value;
24
25use crate::raw::*;
26use crate::*;
27
28#[derive(Clone)]
55pub struct CapabilityOverrideLayer {
56 apply: Arc<dyn Fn(Capability) -> Capability + Send + Sync>,
57}
58
59impl fmt::Debug for CapabilityOverrideLayer {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 f.debug_struct("CapabilityOverrideLayer")
62 .finish_non_exhaustive()
63 }
64}
65
66impl CapabilityOverrideLayer {
67 pub fn new(apply: impl Fn(Capability) -> Capability + Send + Sync + 'static) -> Self {
69 Self {
70 apply: Arc::new(apply),
71 }
72 }
73
74 pub fn from_overrides(input: &str) -> Result<Self> {
83 let overrides = CapabilityOverrides::parse(input)?;
84 Ok(Self::new(move |cap| overrides.apply(cap)))
85 }
86}
87
88impl Layer for CapabilityOverrideLayer {
89 fn apply_service(&self, inner: Servicer) -> Servicer {
90 Arc::new(self.layer(inner))
91 }
92}
93
94impl CapabilityOverrideLayer {
95 fn layer(&self, inner: Servicer) -> CapabilityOverrideService {
96 CapabilityOverrideService {
97 inner,
98 apply: self.apply.clone(),
99 }
100 }
101}
102
103pub struct CapabilityOverrideService {
104 inner: Servicer,
105 apply: Arc<dyn Fn(Capability) -> Capability + Send + Sync>,
106}
107
108impl fmt::Debug for CapabilityOverrideService {
109 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110 f.debug_struct("CapabilityOverrideService")
111 .field("inner", &self.inner)
112 .finish_non_exhaustive()
113 }
114}
115
116impl Service for CapabilityOverrideService {
117 type Reader = oio::Reader;
118 type Writer = oio::Writer;
119 type Lister = oio::Lister;
120 type Deleter = oio::Deleter;
121 type Copier = oio::Copier;
122 type Composer = oio::Composer;
123
124 fn info(&self) -> ServiceInfo {
125 self.inner.info()
126 }
127
128 fn capability(&self) -> Capability {
129 (self.apply)(self.inner.capability())
130 }
131
132 async fn create_dir(
133 &self,
134 ctx: &OperationContext,
135 path: &str,
136 args: OpCreateDir,
137 ) -> Result<RpCreateDir> {
138 self.inner.create_dir(ctx, path, args).await
139 }
140
141 async fn stat(&self, ctx: &OperationContext, path: &str, args: OpStat) -> Result<RpStat> {
142 self.inner.stat(ctx, path, args).await
143 }
144
145 fn read(&self, ctx: &OperationContext, path: &str, args: OpRead) -> Result<Self::Reader> {
146 self.inner.read(ctx, path, args)
147 }
148
149 fn write(&self, ctx: &OperationContext, path: &str, args: OpWrite) -> Result<Self::Writer> {
150 self.inner.write(ctx, path, args)
151 }
152
153 fn delete(&self, ctx: &OperationContext) -> Result<Self::Deleter> {
154 self.inner.delete(ctx)
155 }
156
157 fn list(&self, ctx: &OperationContext, path: &str, args: OpList) -> Result<Self::Lister> {
158 self.inner.list(ctx, path, args)
159 }
160
161 fn copy(
162 &self,
163 ctx: &OperationContext,
164 from: &str,
165 to: &str,
166 args: OpCopy,
167 ) -> Result<Self::Copier> {
168 self.inner.copy(ctx, from, to, args)
169 }
170
171 fn compose(&self, ctx: &OperationContext, to: &str, args: OpCompose) -> Result<Self::Composer> {
172 self.inner.compose(ctx, to, args)
173 }
174
175 async fn rename(
176 &self,
177 ctx: &OperationContext,
178 from: &str,
179 to: &str,
180 args: OpRename,
181 ) -> Result<RpRename> {
182 self.inner.rename(ctx, from, to, args).await
183 }
184
185 async fn restore(
186 &self,
187 ctx: &OperationContext,
188 path: &str,
189 args: OpRestore,
190 ) -> Result<RpRestore> {
191 self.inner.restore(ctx, path, args).await
192 }
193
194 async fn presign(
195 &self,
196 ctx: &OperationContext,
197 path: &str,
198 args: OpPresign,
199 ) -> Result<RpPresign> {
200 self.inner.presign(ctx, path, args).await
201 }
202}
203
204#[derive(Clone, Debug, Default)]
205struct CapabilityOverrides {
206 values: Map<String, Value>,
207}
208
209impl CapabilityOverrides {
210 fn parse(input: &str) -> Result<Self> {
211 let mut overrides = Self::default();
212
213 for token in input.split(',').map(str::trim).filter(|v| !v.is_empty()) {
214 let (name, value) = parse_capability_override(token)?;
215 overrides.values.insert(name.to_string(), value);
216 overrides.try_apply(Capability::default()).map_err(|err| {
217 invalid_capability_override(token, &format!("failed to apply override: {err}"))
218 })?;
219 }
220
221 Ok(overrides)
222 }
223
224 fn apply(&self, cap: Capability) -> Capability {
225 self.try_apply(cap)
226 .expect("capability overrides must be validated before applying")
227 }
228
229 fn try_apply(&self, cap: Capability) -> Result<Capability> {
230 let mut value = serde_json::to_value(cap).map_err(|err| {
231 Error::new(
232 ErrorKind::Unexpected,
233 format!("failed to serialize capability: {err}"),
234 )
235 })?;
236 let object = value.as_object_mut().ok_or_else(|| {
237 Error::new(
238 ErrorKind::Unexpected,
239 "serialized capability must be a JSON object",
240 )
241 })?;
242 object.extend(self.values.clone());
243
244 serde_json::from_value(value).map_err(|err| {
245 Error::new(
246 ErrorKind::ConfigInvalid,
247 format!("failed to deserialize capability overrides: {err}"),
248 )
249 })
250 }
251}
252
253fn parse_capability_override(token: &str) -> Result<(&str, Value)> {
254 let Some((name, value)) = token.split_once('=') else {
255 return Err(invalid_capability_override(
256 token,
257 "expected `capability=value`",
258 ));
259 };
260
261 Ok((
262 name.trim(),
263 parse_capability_value(value.trim())
264 .map_err(|err| invalid_capability_override(token, &err.to_string()))?,
265 ))
266}
267
268fn invalid_capability_override(token: &str, reason: &str) -> Error {
269 Error::new(
270 ErrorKind::ConfigInvalid,
271 format!("invalid capability override entry `{token}`: {reason}"),
272 )
273}
274
275fn parse_capability_value(value: &str) -> Result<Value> {
276 match value {
277 "true" | "on" | "yes" => Ok(Value::Bool(true)),
278 "false" | "off" | "no" => Ok(Value::Bool(false)),
279 "none" | "null" | "unset" => Ok(Value::Null),
280 _ => value
281 .parse::<usize>()
282 .map(|v| Value::Number(Number::from(v)))
283 .map_err(|_| {
284 Error::new(
285 ErrorKind::ConfigInvalid,
286 "expected a boolean, non-negative integer, or `none`",
287 )
288 }),
289 }
290}
291
292#[cfg(test)]
293mod tests {
294 use super::*;
295 use crate::Operator;
296 use crate::services;
297
298 #[test]
299 fn capability_override_updates_capability() -> Result<()> {
300 let op = Operator::new(services::Memory::default())?.layer(CapabilityOverrideLayer::new(
301 |mut cap| {
302 cap.read = false;
303 cap.delete_max_size = Some(7);
304 cap
305 },
306 ));
307
308 assert!(!op.info().capability().read);
309 assert_eq!(op.info().capability().delete_max_size, Some(7));
310
311 Ok(())
312 }
313
314 #[test]
315 fn parse_capability_overrides() -> Result<()> {
316 let layer = CapabilityOverrideLayer::from_overrides(
317 "read=false,write_can_append=true,delete_max_size=7",
318 )?;
319 let op = Operator::new(services::Memory::default())?.layer(layer);
320
321 assert!(!op.info().capability().read);
322 assert!(op.info().capability().write_can_append);
323 assert_eq!(op.info().capability().delete_max_size, Some(7));
324
325 Ok(())
326 }
327
328 #[test]
329 fn parse_bool_assignments_and_unset_sizes() -> Result<()> {
330 let layer =
331 CapabilityOverrideLayer::from_overrides("read=false,write=true,delete_max_size=none")?;
332 let op = Operator::new(services::Memory::default())?.layer(layer);
333
334 assert!(!op.info().capability().read);
335 assert!(op.info().capability().write);
336 assert_eq!(op.info().capability().delete_max_size, None);
337
338 Ok(())
339 }
340
341 #[test]
342 fn reject_unknown_capability() {
343 let err = CapabilityOverrideLayer::from_overrides("not_a_capability=false").unwrap_err();
344 assert_eq!(err.kind(), ErrorKind::ConfigInvalid);
345 }
346
347 #[test]
348 fn reject_capability_shorthand() {
349 let err = CapabilityOverrideLayer::from_overrides("-read").unwrap_err();
350 assert_eq!(err.kind(), ErrorKind::ConfigInvalid);
351 }
352
353 #[test]
354 fn reject_invalid_capability_type() {
355 let err = CapabilityOverrideLayer::from_overrides("read=1").unwrap_err();
356 assert_eq!(err.kind(), ErrorKind::ConfigInvalid);
357 }
358}