1use super::{
11 FieldNameMatching,
12 InputOutputLimit,
13 MaskPolicy,
14 MaskingPolicy,
15 PolicyError,
16 PolicyLocation,
17 RedactionFloor,
18 RedactionLimits,
19 RedactionPolicy,
20 RedactionRules,
21 RedactionRulesBuilder,
22 SensitiveFieldPreset,
23 Sensitivity,
24 UnknownFieldPolicy,
25};
26#[cfg(feature = "json")]
27use super::{
28 JsonDepthBudget,
29 UnkeyedJsonValuePolicy,
30};
31
32#[must_use]
34#[derive(Debug, Clone)]
35pub struct RedactionPolicyBuilder {
36 rules: RedactionRulesBuilder,
37 masking: MaskingPolicy,
38 floor: Option<RedactionFloor>,
39 limits: RedactionLimits,
40 #[cfg(feature = "http")]
41 http: crate::http::HttpPolicyBuilder,
42 #[cfg(feature = "uri")]
43 uri: crate::uri::UriPolicyBuilder,
44 #[cfg(feature = "json")]
45 unkeyed_json_value_policy: UnkeyedJsonValuePolicy,
46}
47
48impl RedactionPolicyBuilder {
49 pub fn new() -> Self {
51 Self {
52 rules: RedactionRulesBuilder::empty(PolicyLocation::Rules),
53 masking: MaskingPolicy::default(),
54 floor: Some(RedactionFloor::standard()),
55 limits: RedactionLimits::default(),
56 #[cfg(feature = "http")]
57 http: crate::http::HttpPolicyBuilder::new(),
58 #[cfg(feature = "uri")]
59 uri: crate::uri::UriPolicyBuilder::new(),
60 #[cfg(feature = "json")]
61 unkeyed_json_value_policy: UnkeyedJsonValuePolicy::PassThrough,
62 }
63 }
64 pub(super) fn from_policy(policy: &RedactionPolicy) -> Self {
65 Self {
66 rules: RedactionRulesBuilder::from_inner(
67 &policy.rules().clone_application(),
68 PolicyLocation::Rules,
69 ),
70 masking: policy.masking().clone(),
71 floor: policy.rules().floor().cloned(),
72 limits: *policy.limits(),
73 #[cfg(feature = "http")]
74 http: crate::http::HttpPolicyBuilder::from_policy(policy.http()),
75 #[cfg(feature = "uri")]
76 uri: crate::uri::UriPolicyBuilder::from_policy(policy.uri()),
77 #[cfg(feature = "json")]
78 unkeyed_json_value_policy: policy.unkeyed_json_value_policy(),
79 }
80 }
81
82 pub fn fields(&mut self) -> FieldsBuilder<'_> {
84 FieldsBuilder { builder: self }
85 }
86
87 #[cfg(feature = "http")]
89 pub fn http(&mut self) -> HttpPolicyBuilderView<'_> {
90 HttpPolicyBuilderView { builder: self }
91 }
92
93 #[cfg(feature = "uri")]
95 pub fn uri(&mut self) -> UriPolicyBuilderView<'_> {
96 UriPolicyBuilderView {
97 builder: &mut self.uri,
98 }
99 }
100
101 pub fn limits(&mut self) -> LimitsBuilder<'_> {
103 LimitsBuilder { builder: self }
104 }
105
106 pub fn validate_field_name(field: &str) -> Result<(), PolicyError> {
113 RedactionRulesBuilder::validate_field_name(field, PolicyLocation::Rules)
114 }
115
116 pub fn floor(mut self, floor: RedactionFloor) -> Self {
120 self.floor = Some(floor);
121 self
122 }
123 pub fn disable_floor(mut self) -> Self {
130 self.floor = None;
131 self
132 }
133
134 pub fn matching(mut self, matching: FieldNameMatching) -> Self {
136 self.rules.matching(matching);
137 self
138 }
139
140 pub fn unknown_field_policy(mut self, policy: UnknownFieldPolicy) -> Self {
142 self.rules.unknown_field_policy(policy);
143 self
144 }
145
146 pub fn include_preset(mut self, preset: SensitiveFieldPreset) -> Self {
148 self.rules.include_preset(preset);
149 self
150 }
151
152 pub fn raise(
164 mut self,
165 field: &str,
166 level: Sensitivity,
167 ) -> Result<Self, PolicyError> {
168 self.rules.raise(field, level)?;
169 Ok(self)
170 }
171
172 pub fn override_level(
182 mut self,
183 field: &str,
184 level: Sensitivity,
185 ) -> Result<Self, PolicyError> {
186 self.rules.override_level(field, level)?;
187 Ok(self)
188 }
189
190 pub fn allow_canonical_exact(
199 mut self,
200 field: &str,
201 ) -> Result<Self, PolicyError> {
202 self.rules.allow_canonical_exact(field)?;
203 Ok(self)
204 }
205
206 pub fn allow_suffix(mut self, field: &str) -> Result<Self, PolicyError> {
215 self.rules.allow_suffix(field)?;
216 Ok(self)
217 }
218
219 pub fn remove_allow_canonical_exact(
226 mut self,
227 field: &str,
228 ) -> Result<Self, PolicyError> {
229 self.rules.remove_allow_canonical_exact(field)?;
230 Ok(self)
231 }
232
233 pub fn remove_allow_suffix(
240 mut self,
241 field: &str,
242 ) -> Result<Self, PolicyError> {
243 self.rules.remove_allow_suffix(field)?;
244 Ok(self)
245 }
246
247 pub fn clear_allow_rules(mut self) -> Self {
249 self.rules.clear_allow_rules();
250 self
251 }
252
253 pub fn mask(
260 mut self,
261 level: Sensitivity,
262 policy: MaskPolicy,
263 ) -> Result<Self, PolicyError> {
264 let masking = self.masking.with_policy(level, policy);
265 masking.validate(PolicyLocation::Rules)?;
266 self.masking = masking;
267 Ok(self)
268 }
269
270 pub const fn diagnostic_event(mut self, budget: InputOutputLimit) -> Self {
272 self.limits = self.limits.with_diagnostic_event(budget);
273 self
274 }
275
276 pub const fn ordinary_operation(
278 mut self,
279 budget: InputOutputLimit,
280 ) -> Self {
281 self.limits = self.limits.with_ordinary_operation(budget);
282 self
283 }
284
285 #[cfg(feature = "http")]
287 pub fn url_path_policy(
288 mut self,
289 policy: crate::http::UrlPathPolicy,
290 ) -> Self {
291 self.http.url_path_mut(policy);
292 self
293 }
294
295 #[cfg(feature = "http")]
297 pub fn text_body_policy(
298 mut self,
299 policy: crate::http::TextBodyPolicy,
300 ) -> Self {
301 self.http.text_body_mut(policy);
302 self
303 }
304
305 #[cfg(feature = "http")]
307 pub fn body_budget(mut self, budget: crate::http::BodyBudget) -> Self {
308 self.limits = self.limits.with_http_body(budget);
309 self
310 }
311
312 #[cfg(feature = "uri")]
314 pub fn path_policy(mut self, policy: crate::uri::UriPathPolicy) -> Self {
315 self.uri = self.uri.path_policy(policy);
316 self
317 }
318
319 #[cfg(feature = "uri")]
321 pub fn fragment_policy(
322 mut self,
323 policy: crate::uri::UriFragmentPolicy,
324 ) -> Self {
325 self.uri = self.uri.fragment_policy(policy);
326 self
327 }
328
329 #[cfg(feature = "json")]
331 pub const fn json_depth_budget(mut self, budget: JsonDepthBudget) -> Self {
332 self.limits = self.limits.with_json_depth_budget(budget);
333 self
334 }
335
336 #[cfg(feature = "json")]
338 pub const fn unkeyed_json_value_policy(
339 mut self,
340 policy: UnkeyedJsonValuePolicy,
341 ) -> Self {
342 self.unkeyed_json_value_policy = policy;
343 self
344 }
345
346 pub fn build(self) -> Result<RedactionPolicy, PolicyError> {
352 let rules = RedactionRules::new(self.rules.build_inner()?, self.floor);
353 self.masking.validate(PolicyLocation::Rules)?;
354 #[cfg(feature = "http")]
355 let http = self.http.build()?;
356 #[cfg(feature = "uri")]
357 let uri = self.uri.build()?;
358 Ok(RedactionPolicy::from_rules(
359 rules,
360 self.masking,
361 self.limits,
362 #[cfg(feature = "http")]
363 http,
364 #[cfg(feature = "uri")]
365 uri,
366 #[cfg(feature = "json")]
367 self.unkeyed_json_value_policy,
368 ))
369 }
370}
371
372mod views {
373 #[cfg(feature = "json")]
374 use super::JsonDepthBudget;
375 #[cfg(feature = "http")]
376 use super::RedactionRules;
377 use super::{
378 FieldNameMatching,
379 InputOutputLimit,
380 MaskPolicy,
381 PolicyError,
382 PolicyLocation,
383 RedactionFloor,
384 RedactionPolicyBuilder,
385 SensitiveFieldPreset,
386 Sensitivity,
387 UnknownFieldPolicy,
388 };
389
390 #[must_use]
392 pub struct FieldsBuilder<'a> {
393 pub(super) builder: &'a mut RedactionPolicyBuilder,
394 }
395
396 impl FieldsBuilder<'_> {
397 pub fn matching(&mut self, matching: FieldNameMatching) -> &mut Self {
399 self.builder.rules.matching(matching);
400 self
401 }
402
403 pub fn unknown_field_policy(
405 &mut self,
406 policy: UnknownFieldPolicy,
407 ) -> &mut Self {
408 self.builder.rules.unknown_field_policy(policy);
409 self
410 }
411
412 pub fn include_preset(
414 &mut self,
415 preset: SensitiveFieldPreset,
416 ) -> &mut Self {
417 self.builder.rules.include_preset(preset);
418 self
419 }
420
421 pub fn raise(
423 &mut self,
424 field: &str,
425 level: Sensitivity,
426 ) -> Result<&mut Self, PolicyError> {
427 self.builder.rules.raise(field, level)?;
428 Ok(self)
429 }
430
431 pub fn override_level(
433 &mut self,
434 field: &str,
435 level: Sensitivity,
436 ) -> Result<&mut Self, PolicyError> {
437 self.builder.rules.override_level(field, level)?;
438 Ok(self)
439 }
440
441 pub fn allow_exact(
443 &mut self,
444 field: &str,
445 ) -> Result<&mut Self, PolicyError> {
446 self.builder.rules.allow_canonical_exact(field)?;
447 Ok(self)
448 }
449
450 pub fn allow_suffix(
452 &mut self,
453 field: &str,
454 ) -> Result<&mut Self, PolicyError> {
455 self.builder.rules.allow_suffix(field)?;
456 Ok(self)
457 }
458
459 pub fn remove_allow_exact(
461 &mut self,
462 field: &str,
463 ) -> Result<&mut Self, PolicyError> {
464 self.builder.rules.remove_allow_canonical_exact(field)?;
465 Ok(self)
466 }
467
468 pub fn remove_allow_suffix(
470 &mut self,
471 field: &str,
472 ) -> Result<&mut Self, PolicyError> {
473 self.builder.rules.remove_allow_suffix(field)?;
474 Ok(self)
475 }
476
477 pub fn clear_allow_rules(&mut self) -> &mut Self {
479 self.builder.rules.clear_allow_rules();
480 self
481 }
482
483 pub fn floor(&mut self, floor: RedactionFloor) -> &mut Self {
485 self.builder.floor = Some(floor);
486 self
487 }
488
489 pub fn disable_floor(&mut self) -> &mut Self {
491 self.builder.floor = None;
492 self
493 }
494
495 pub fn mask(
497 &mut self,
498 level: Sensitivity,
499 policy: MaskPolicy,
500 ) -> Result<&mut Self, PolicyError> {
501 let masking =
502 self.builder.masking.clone().with_policy(level, policy);
503 masking.validate(PolicyLocation::Rules)?;
504 self.builder.masking = masking;
505 Ok(self)
506 }
507 }
508
509 #[cfg(feature = "http")]
511 #[must_use]
512 pub struct HttpPolicyBuilderView<'a> {
513 pub(super) builder: &'a mut RedactionPolicyBuilder,
514 }
515
516 #[cfg(feature = "uri")]
518 #[must_use]
519 pub struct UriPolicyBuilderView<'a> {
520 pub(super) builder: &'a mut crate::uri::UriPolicyBuilder,
521 }
522
523 #[cfg(feature = "uri")]
524 impl UriPolicyBuilderView<'_> {
525 pub fn path(&mut self, policy: crate::uri::UriPathPolicy) -> &mut Self {
527 self.builder.path_policy_mut(policy);
528 self
529 }
530
531 pub fn fragment(
533 &mut self,
534 policy: crate::uri::UriFragmentPolicy,
535 ) -> &mut Self {
536 self.builder.fragment_policy_mut(policy);
537 self
538 }
539 }
540
541 #[cfg(feature = "http")]
542 impl HttpPolicyBuilderView<'_> {
543 pub fn header(&mut self) -> HttpContextBuilderView<'_> {
545 HttpContextBuilderView {
546 builder: &mut self.builder.http,
547 context: crate::http::HttpFieldContext::Header,
548 }
549 }
550
551 pub fn query(&mut self) -> HttpContextBuilderView<'_> {
553 HttpContextBuilderView {
554 builder: &mut self.builder.http,
555 context: crate::http::HttpFieldContext::Query,
556 }
557 }
558
559 pub fn body(&mut self) -> HttpContextBuilderView<'_> {
561 HttpContextBuilderView {
562 builder: &mut self.builder.http,
563 context: crate::http::HttpFieldContext::Body,
564 }
565 }
566
567 pub fn url_path(
569 &mut self,
570 policy: crate::http::UrlPathPolicy,
571 ) -> &mut Self {
572 self.builder.http.url_path_mut(policy);
573 self
574 }
575
576 pub fn text_body(
578 &mut self,
579 policy: crate::http::TextBodyPolicy,
580 ) -> &mut Self {
581 self.builder.http.text_body_mut(policy);
582 self
583 }
584
585 pub fn floor_all(&mut self, floor: RedactionFloor) -> &mut Self {
587 self.builder.http.floor_all_mut(floor);
588 self
589 }
590
591 pub fn disable_all_floors(&mut self) -> &mut Self {
593 self.builder.http.disable_all_floors_mut();
594 self
595 }
596
597 pub fn unkeyed_json(
600 &mut self,
601 policy: crate::http::UnkeyedJsonValuePolicy,
602 ) -> &mut Self {
603 self.builder.unkeyed_json_value_policy = policy;
604 self
605 }
606 }
607
608 #[cfg(feature = "http")]
610 #[must_use]
611 pub struct HttpContextBuilderView<'a> {
612 builder: &'a mut crate::http::HttpPolicyBuilder,
613 context: crate::http::HttpFieldContext,
614 }
615
616 #[cfg(feature = "http")]
617 impl HttpContextBuilderView<'_> {
618 pub fn replace_rules(&mut self, rules: RedactionRules) -> &mut Self {
620 self.builder.rules_mut(self.context, rules);
621 self
622 }
623
624 pub fn raise(
626 &mut self,
627 field: &str,
628 level: Sensitivity,
629 ) -> Result<&mut Self, PolicyError> {
630 self.builder.raise_mut(self.context, field, level)?;
631 Ok(self)
632 }
633
634 pub fn override_level(
636 &mut self,
637 field: &str,
638 level: Sensitivity,
639 ) -> Result<&mut Self, PolicyError> {
640 self.builder
641 .override_level_mut(self.context, field, level)?;
642 Ok(self)
643 }
644
645 pub fn allow_exact(
647 &mut self,
648 field: &str,
649 ) -> Result<&mut Self, PolicyError> {
650 self.builder.allow_exact_mut(self.context, field)?;
651 Ok(self)
652 }
653
654 pub fn allow_suffix(
656 &mut self,
657 field: &str,
658 ) -> Result<&mut Self, PolicyError> {
659 self.builder.allow_suffix_mut(self.context, field)?;
660 Ok(self)
661 }
662
663 pub fn remove_allow_exact(
665 &mut self,
666 field: &str,
667 ) -> Result<&mut Self, PolicyError> {
668 self.builder.remove_allow_exact_mut(self.context, field)?;
669 Ok(self)
670 }
671
672 pub fn remove_allow_suffix(
674 &mut self,
675 field: &str,
676 ) -> Result<&mut Self, PolicyError> {
677 self.builder.remove_allow_suffix_mut(self.context, field)?;
678 Ok(self)
679 }
680
681 pub fn clear_allow_rules(&mut self) -> &mut Self {
683 self.builder.clear_allow_rules_mut(self.context);
684 self
685 }
686
687 pub fn floor(&mut self, floor: RedactionFloor) -> &mut Self {
690 self.builder.floor_mut(self.context, floor);
691 self
692 }
693
694 pub fn disable_floor(&mut self) -> &mut Self {
696 self.builder.disable_floor_mut(self.context);
697 self
698 }
699 }
700
701 #[must_use]
703 pub struct LimitsBuilder<'a> {
704 pub(super) builder: &'a mut RedactionPolicyBuilder,
705 }
706
707 impl LimitsBuilder<'_> {
708 pub fn diagnostic_event(
710 &mut self,
711 limit: InputOutputLimit,
712 ) -> &mut Self {
713 self.builder.limits =
714 self.builder.limits.with_diagnostic_event(limit);
715 self
716 }
717
718 pub fn ordinary_operation(
720 &mut self,
721 limit: InputOutputLimit,
722 ) -> &mut Self {
723 self.builder.limits =
724 self.builder.limits.with_ordinary_operation(limit);
725 self
726 }
727
728 #[cfg(feature = "http")]
730 pub fn http_body(
731 &mut self,
732 limit: crate::http::BodyBudget,
733 ) -> &mut Self {
734 self.builder.limits = self.builder.limits.with_http_body(limit);
735 self
736 }
737
738 #[cfg(feature = "json")]
740 pub fn json_depth(&mut self, limit: JsonDepthBudget) -> &mut Self {
741 self.builder.limits =
742 self.builder.limits.with_json_depth_budget(limit);
743 self
744 }
745 }
746}
747
748#[cfg(feature = "uri")]
749pub use views::UriPolicyBuilderView;
750pub use views::{
751 FieldsBuilder,
752 LimitsBuilder,
753};
754#[cfg(feature = "http")]
755pub use views::{
756 HttpContextBuilderView,
757 HttpPolicyBuilderView,
758};
759
760impl Default for RedactionPolicyBuilder {
761 fn default() -> Self {
762 Self::new()
763 }
764}