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
123 fn info(&self) -> ServiceInfo {
124 self.inner.info()
125 }
126
127 fn capability(&self) -> Capability {
128 (self.apply)(self.inner.capability())
129 }
130
131 async fn create_dir(
132 &self,
133 ctx: &OperationContext,
134 path: &str,
135 args: OpCreateDir,
136 ) -> Result<RpCreateDir> {
137 self.inner.create_dir(ctx, path, args).await
138 }
139
140 async fn stat(&self, ctx: &OperationContext, path: &str, args: OpStat) -> Result<RpStat> {
141 self.inner.stat(ctx, path, args).await
142 }
143
144 fn read(&self, ctx: &OperationContext, path: &str, args: OpRead) -> Result<Self::Reader> {
145 self.inner.read(ctx, path, args)
146 }
147
148 fn write(&self, ctx: &OperationContext, path: &str, args: OpWrite) -> Result<Self::Writer> {
149 self.inner.write(ctx, path, args)
150 }
151
152 fn delete(&self, ctx: &OperationContext) -> Result<Self::Deleter> {
153 self.inner.delete(ctx)
154 }
155
156 fn list(&self, ctx: &OperationContext, path: &str, args: OpList) -> Result<Self::Lister> {
157 self.inner.list(ctx, path, args)
158 }
159
160 fn copy(
161 &self,
162 ctx: &OperationContext,
163 from: &str,
164 to: &str,
165 args: OpCopy,
166 opts: OpCopier,
167 ) -> Result<Self::Copier> {
168 self.inner.copy(ctx, from, to, args, opts)
169 }
170
171 async fn rename(
172 &self,
173 ctx: &OperationContext,
174 from: &str,
175 to: &str,
176 args: OpRename,
177 ) -> Result<RpRename> {
178 self.inner.rename(ctx, from, to, args).await
179 }
180
181 async fn presign(
182 &self,
183 ctx: &OperationContext,
184 path: &str,
185 args: OpPresign,
186 ) -> Result<RpPresign> {
187 self.inner.presign(ctx, path, args).await
188 }
189}
190
191#[derive(Clone, Debug, Default)]
192struct CapabilityOverrides {
193 values: Map<String, Value>,
194}
195
196impl CapabilityOverrides {
197 fn parse(input: &str) -> Result<Self> {
198 let mut overrides = Self::default();
199
200 for token in input.split(',').map(str::trim).filter(|v| !v.is_empty()) {
201 let (name, value) = parse_capability_override(token)?;
202 overrides.values.insert(name.to_string(), value);
203 overrides.try_apply(Capability::default()).map_err(|err| {
204 invalid_capability_override(token, &format!("failed to apply override: {err}"))
205 })?;
206 }
207
208 Ok(overrides)
209 }
210
211 fn apply(&self, cap: Capability) -> Capability {
212 self.try_apply(cap)
213 .expect("capability overrides must be validated before applying")
214 }
215
216 fn try_apply(&self, cap: Capability) -> Result<Capability> {
217 let mut value = serde_json::to_value(cap).map_err(|err| {
218 Error::new(
219 ErrorKind::Unexpected,
220 format!("failed to serialize capability: {err}"),
221 )
222 })?;
223 let object = value.as_object_mut().ok_or_else(|| {
224 Error::new(
225 ErrorKind::Unexpected,
226 "serialized capability must be a JSON object",
227 )
228 })?;
229 object.extend(self.values.clone());
230
231 serde_json::from_value(value).map_err(|err| {
232 Error::new(
233 ErrorKind::ConfigInvalid,
234 format!("failed to deserialize capability overrides: {err}"),
235 )
236 })
237 }
238}
239
240fn parse_capability_override(token: &str) -> Result<(&str, Value)> {
241 let Some((name, value)) = token.split_once('=') else {
242 return Err(invalid_capability_override(
243 token,
244 "expected `capability=value`",
245 ));
246 };
247
248 Ok((
249 name.trim(),
250 parse_capability_value(value.trim())
251 .map_err(|err| invalid_capability_override(token, &err.to_string()))?,
252 ))
253}
254
255fn invalid_capability_override(token: &str, reason: &str) -> Error {
256 Error::new(
257 ErrorKind::ConfigInvalid,
258 format!("invalid capability override entry `{token}`: {reason}"),
259 )
260}
261
262fn parse_capability_value(value: &str) -> Result<Value> {
263 match value {
264 "true" | "on" | "yes" => Ok(Value::Bool(true)),
265 "false" | "off" | "no" => Ok(Value::Bool(false)),
266 "none" | "null" | "unset" => Ok(Value::Null),
267 _ => value
268 .parse::<usize>()
269 .map(|v| Value::Number(Number::from(v)))
270 .map_err(|_| {
271 Error::new(
272 ErrorKind::ConfigInvalid,
273 "expected a boolean, non-negative integer, or `none`",
274 )
275 }),
276 }
277}
278
279#[cfg(test)]
280mod tests {
281 use super::*;
282 use crate::Operator;
283 use crate::services;
284
285 #[test]
286 fn capability_override_updates_capability() -> Result<()> {
287 let op = Operator::new(services::Memory::default())?.layer(CapabilityOverrideLayer::new(
288 |mut cap| {
289 cap.read = false;
290 cap.delete_max_size = Some(7);
291 cap
292 },
293 ));
294
295 assert!(!op.info().capability().read);
296 assert_eq!(op.info().capability().delete_max_size, Some(7));
297
298 Ok(())
299 }
300
301 #[test]
302 fn parse_capability_overrides() -> Result<()> {
303 let layer = CapabilityOverrideLayer::from_overrides(
304 "read=false,write_can_append=true,delete_max_size=7",
305 )?;
306 let op = Operator::new(services::Memory::default())?.layer(layer);
307
308 assert!(!op.info().capability().read);
309 assert!(op.info().capability().write_can_append);
310 assert_eq!(op.info().capability().delete_max_size, Some(7));
311
312 Ok(())
313 }
314
315 #[test]
316 fn parse_bool_assignments_and_unset_sizes() -> Result<()> {
317 let layer =
318 CapabilityOverrideLayer::from_overrides("read=false,write=true,delete_max_size=none")?;
319 let op = Operator::new(services::Memory::default())?.layer(layer);
320
321 assert!(!op.info().capability().read);
322 assert!(op.info().capability().write);
323 assert_eq!(op.info().capability().delete_max_size, None);
324
325 Ok(())
326 }
327
328 #[test]
329 fn reject_unknown_capability() {
330 let err = CapabilityOverrideLayer::from_overrides("not_a_capability=false").unwrap_err();
331 assert_eq!(err.kind(), ErrorKind::ConfigInvalid);
332 }
333
334 #[test]
335 fn reject_capability_shorthand() {
336 let err = CapabilityOverrideLayer::from_overrides("-read").unwrap_err();
337 assert_eq!(err.kind(), ErrorKind::ConfigInvalid);
338 }
339
340 #[test]
341 fn reject_invalid_capability_type() {
342 let err = CapabilityOverrideLayer::from_overrides("read=1").unwrap_err();
343 assert_eq!(err.kind(), ErrorKind::ConfigInvalid);
344 }
345}