scopes_rs/policy/
policy.rs1use std::ops::{BitAnd, BitOr, Not};
2
3use crate::scope::{AsScopeRef, Scope};
4
5#[derive(Debug, PartialEq)]
23pub enum Policy<S: Scope> {
24
25 Scope(S),
27
28 OneOf(Vec<Policy<S>>),
30
31 AllOf(Vec<Policy<S>>),
33
34 Not(Box<Policy<S>>),
36
37 AllowAll,
39
40 DenyAll,
42}
43
44impl<S> Default for Policy<S> where S: Scope {
45 fn default() -> Self {
46 Policy::DenyAll
47 }
48}
49
50impl<S> Clone for Policy<S>
51where S: Scope + Clone {
52 fn clone(&self) -> Self {
53 match self {
54 Self::Scope(arg0) => Self::Scope(arg0.clone()),
55 Self::OneOf(arg0) => Self::OneOf(arg0.clone()),
56 Self::AllOf(arg0) => Self::AllOf(arg0.clone()),
57 Self::Not(arg0) => Self::Not(arg0.clone()),
58 Self::AllowAll => Self::AllowAll,
59 Self::DenyAll => Self::DenyAll,
60 }
61 }
62}
63
64impl<S> Policy<S> where S: Scope {
65
66 pub fn verify<Iterator>(&self, scopes: Iterator) -> bool
68 where
69 Iterator: IntoIterator + Clone,
70 Iterator::Item: AsScopeRef<S>,
71 {
72 match self {
73
74 #[cfg(not(feature = "hierarchy"))]
75 Policy::Scope(required) => scopes.into_iter().find(|s| s.as_scope_ref() == required).is_some(),
76
77 #[cfg(feature = "hierarchy")]
78 Policy::Scope(required) => scopes.into_iter().any(|s| s.as_scope_ref().includes(required)),
79
80 Policy::Not(policy) => !policy.verify(scopes),
81 Policy::OneOf(policies) => policies.iter().any(|p| p.verify(scopes.clone())),
82 Policy::AllOf(policies) => policies.iter().all(|p| p.verify(scopes.clone())),
83 Policy::AllowAll => true,
84 Policy::DenyAll => false,
85 }
86 }
87}
88
89impl<S, I> BitAnd<I> for Policy<S>
90where
91 S: Scope,
92 I: IntoPolicy<S>,
93{
94 type Output = Policy<S>;
95
96 fn bitand(self, rhs: I) -> Self::Output {
97 let rhs: Policy<S> = rhs.into_policy();
98 match (self, rhs) {
99 (Policy::AllOf(mut left), Policy::AllOf(mut right)) => {
101
102 left.append(&mut right);
103 Policy::AllOf(left)
104 },
105
106 (Policy::DenyAll, _) | (_, Policy::DenyAll) => Policy::DenyAll,
108
109 (Policy::AllOf(mut policies), other)
111 | (other, Policy::AllOf(mut policies)) => {
112
113 policies.push(other);
114 Policy::AllOf(policies)
115 }
116
117 (left, right) => Policy::AllOf(vec![left, right])
118 }
119 }
120}
121
122impl<S, I> BitOr<I> for Policy<S>
123where
124 S: Scope,
125 I: IntoPolicy<S>,
126{
127 type Output = Policy<S>;
128
129 fn bitor(self, rhs: I) -> Self::Output {
130 let rhs: Policy<S> = rhs.into_policy();
131 match (self, rhs) {
132 (Policy::OneOf(mut left), Policy::OneOf(mut right)) => {
134
135 left.append(&mut right);
136 Policy::OneOf(left)
137 },
138
139 (Policy::AllowAll, _) | (_, Policy::AllowAll) => Policy::AllowAll,
141
142 (Policy::OneOf(mut policies), other)
144 | (other, Policy::OneOf(mut policies)) => {
145
146 policies.push(other);
147 Policy::OneOf(policies)
148 }
149
150 (left, right) => Policy::OneOf(vec![left, right])
151 }
152 }
153}
154
155impl<S> Not for Policy<S>
156where
157 S: Scope,
158{
159 type Output = Policy<S>;
160
161 fn not(self) -> Self::Output {
162 match self {
163 Policy::AllowAll => Policy::DenyAll,
164 Policy::DenyAll => Policy::AllowAll,
165 Policy::Not(policy) => *policy,
166 p => Policy::Not(Box::new(p)),
167 }
168 }
169}
170
171impl<S> From<S> for Policy<S>
172where
173 S: Scope
174{
175 fn from(value: S) -> Self {
176 Policy::Scope(value)
177 }
178}
179
180impl<S> From<&S> for Policy<S>
181where
182 S: Scope + Clone
183{
184 fn from(value: &S) -> Self {
185 Policy::Scope(value.clone())
186 }
187}
188
189pub trait IntoPolicy<S> where S: Scope {
205
206 fn into_policy(self) -> Policy<S>;
208}
209
210impl<S, I> IntoPolicy<S> for I
211where
212 S: Scope,
213 I: Into<Policy<S>>,
214{
215 fn into_policy(self) -> Policy<S> {
216 self.into()
217 }
218}