1use super::builder::{
3 constrained_rule, date, fact, pred, rule, string, var, Binary, BlockBuilder, Check, Expression,
4 Fact, Op, Policy, PolicyKind, Rule, Scope, Term,
5};
6use super::builder_ext::{AuthorizerExt, BuilderExt};
7use super::{Biscuit, Block};
8use crate::builder::{self, CheckKind, Convert};
9use crate::crypto::PublicKey;
10use crate::datalog::{self, Origin, RunLimits, SymbolTable, TrustedOrigins};
11use crate::error;
12use crate::time::Instant;
13use crate::token;
14use biscuit_parser::parser::parse_source;
15use prost::Message;
16use std::collections::{BTreeMap, HashSet};
17use std::time::Duration;
18use std::{
19 collections::HashMap,
20 convert::{TryFrom, TryInto},
21 default::Default,
22 fmt::Write,
23 time::SystemTime,
24};
25
26mod snapshot;
27
28#[derive(Clone)]
32pub struct Authorizer {
33 authorizer_block_builder: BlockBuilder,
34 world: datalog::World,
35 pub(crate) symbols: datalog::SymbolTable,
36 token_origins: TrustedOrigins,
37 policies: Vec<Policy>,
38 blocks: Option<Vec<Block>>,
39 public_key_to_block_id: HashMap<usize, Vec<usize>>,
40 limits: AuthorizerLimits,
41 execution_time: Duration,
42}
43
44impl Authorizer {
45 pub(crate) fn from_token(token: &Biscuit) -> Result<Self, error::Token> {
46 let mut v = Authorizer::new();
47 v.add_token(token)?;
48
49 Ok(v)
50 }
51
52 pub fn new() -> Self {
62 let world = datalog::World::new();
63 let symbols = super::default_symbol_table();
64 let authorizer_block_builder = BlockBuilder::new();
65
66 Authorizer {
67 authorizer_block_builder,
68 world,
69 symbols,
70 token_origins: TrustedOrigins::default(),
71 policies: vec![],
72 blocks: None,
73 public_key_to_block_id: HashMap::new(),
74 limits: AuthorizerLimits::default(),
75 execution_time: Duration::default(),
76 }
77 }
78
79 pub fn from(data: &[u8]) -> Result<Self, error::Token> {
81 AuthorizerPolicies::deserialize(data)?.try_into()
82 }
83
84 pub fn add_token(&mut self, token: &Biscuit) -> Result<(), error::Token> {
86 if self.blocks.is_some() {
87 return Err(error::Logic::AuthorizerNotEmpty.into());
88 }
89
90 for (i, block) in token.container.blocks.iter().enumerate() {
91 if let Some(sig) = block.external_signature.as_ref() {
92 let new_key_id = self.symbols.public_keys.insert(&sig.public_key);
93
94 self.public_key_to_block_id
95 .entry(new_key_id as usize)
96 .or_default()
97 .push(i + 1);
98 }
99 }
100
101 let mut blocks = Vec::new();
102
103 for i in 0..token.block_count() {
104 let mut block = token.block(i)?;
105
106 self.load_and_translate_block(&mut block, i, &token.symbols)?;
107
108 blocks.push(block);
109 }
110
111 self.blocks = Some(blocks);
112 self.token_origins = TrustedOrigins::from_scopes(
113 &[token::Scope::Previous],
114 &TrustedOrigins::default(),
115 token.block_count(),
116 &self.public_key_to_block_id,
117 );
118
119 Ok(())
120 }
121
122 fn load_and_translate_block(
124 &mut self,
125 block: &mut Block,
126 i: usize,
127 token_symbols: &SymbolTable,
128 ) -> Result<(), error::Token> {
129 let block_symbols = if i == 0 || block.external_key.is_none() {
131 token_symbols.clone()
132 } else {
133 block.symbols.clone()
134 };
135
136 let mut block_origin = Origin::default();
137 block_origin.insert(i);
138
139 for scope in block.scopes.iter_mut() {
140 *scope = builder::Scope::convert_from(scope, &block_symbols)
141 .map(|s| s.convert(&mut self.symbols))?;
142 }
143
144 let block_trusted_origins = TrustedOrigins::from_scopes(
145 &block.scopes,
146 &TrustedOrigins::default(),
147 i,
148 &self.public_key_to_block_id,
149 );
150
151 for fact in block.facts.iter_mut() {
152 *fact = Fact::convert_from(fact, &block_symbols)?.convert(&mut self.symbols);
153 self.world.facts.insert(&block_origin, fact.clone());
154 }
155
156 for rule in block.rules.iter_mut() {
157 if let Err(_message) = rule.validate_variables(&block_symbols) {
158 return Err(
159 error::Logic::InvalidBlockRule(0, block_symbols.print_rule(rule)).into(),
160 );
161 }
162 *rule = rule.translate(&block_symbols, &mut self.symbols)?;
163
164 let rule_trusted_origins = TrustedOrigins::from_scopes(
165 &rule.scopes,
166 &block_trusted_origins,
167 i,
168 &self.public_key_to_block_id,
169 );
170
171 self.world
172 .rules
173 .insert(i, &rule_trusted_origins, rule.clone());
174 }
175
176 for check in block.checks.iter_mut() {
177 let c = Check::convert_from(check, &block_symbols)?;
178 *check = c.convert(&mut self.symbols);
179 }
180
181 Ok(())
182 }
183
184 pub fn save(&self) -> Result<AuthorizerPolicies, error::Token> {
189 let facts = self.authorizer_block_builder.facts.to_vec();
190
191 let rules = self.authorizer_block_builder.rules.to_vec();
192
193 let checks = self.authorizer_block_builder.checks.to_vec();
194
195 Ok(AuthorizerPolicies {
196 version: crate::token::MAX_SCHEMA_VERSION,
197 facts,
198 rules,
199 checks,
200 policies: self.policies.clone(),
201 })
202 }
203
204 pub fn merge(&mut self, mut other: Authorizer) {
207 self.merge_block(other.authorizer_block_builder);
208 self.policies.append(&mut other.policies);
209 }
210
211 pub fn merge_block(&mut self, other: BlockBuilder) {
213 self.authorizer_block_builder.merge(other)
214 }
215
216 pub fn add_fact<F: TryInto<Fact>>(&mut self, fact: F) -> Result<(), error::Token>
217 where
218 error::Token: From<<F as TryInto<Fact>>::Error>,
219 {
220 self.authorizer_block_builder.add_fact(fact)
221 }
222
223 pub fn add_rule<Ru: TryInto<Rule>>(&mut self, rule: Ru) -> Result<(), error::Token>
224 where
225 error::Token: From<<Ru as TryInto<Rule>>::Error>,
226 {
227 self.authorizer_block_builder.add_rule(rule)
228 }
229
230 pub fn add_check<C: TryInto<Check>>(&mut self, check: C) -> Result<(), error::Token>
231 where
232 error::Token: From<<C as TryInto<Check>>::Error>,
233 {
234 self.authorizer_block_builder.add_check(check)
235 }
236
237 pub fn add_code<T: AsRef<str>>(&mut self, source: T) -> Result<(), error::Token> {
256 self.add_code_with_params(source, HashMap::new(), HashMap::new())
257 }
258
259 pub fn add_code_with_params<T: AsRef<str>>(
260 &mut self,
261 source: T,
262 params: HashMap<String, Term>,
263 scope_params: HashMap<String, PublicKey>,
264 ) -> Result<(), error::Token> {
265 let source = source.as_ref();
266
267 let source_result = parse_source(source).map_err(|e| {
268 let e2: biscuit_parser::error::LanguageError = e.into();
269 e2
270 })?;
271
272 for (_, fact) in source_result.facts.into_iter() {
273 let mut fact: Fact = fact.into();
274 for (name, value) in ¶ms {
275 let res = match fact.set(name, value) {
276 Ok(_) => Ok(()),
277 Err(error::Token::Language(
278 biscuit_parser::error::LanguageError::Parameters {
279 missing_parameters, ..
280 },
281 )) if missing_parameters.is_empty() => Ok(()),
282 Err(e) => Err(e),
283 };
284 res?;
285 }
286 fact.validate()?;
287 self.authorizer_block_builder.facts.push(fact);
288 }
289
290 for (_, rule) in source_result.rules.into_iter() {
291 let mut rule: Rule = rule.into();
292 for (name, value) in ¶ms {
293 let res = match rule.set(name, value) {
294 Ok(_) => Ok(()),
295 Err(error::Token::Language(
296 biscuit_parser::error::LanguageError::Parameters {
297 missing_parameters, ..
298 },
299 )) if missing_parameters.is_empty() => Ok(()),
300 Err(e) => Err(e),
301 };
302 res?;
303 }
304 for (name, value) in &scope_params {
305 let res = match rule.set_scope(name, *value) {
306 Ok(_) => Ok(()),
307 Err(error::Token::Language(
308 biscuit_parser::error::LanguageError::Parameters {
309 missing_parameters, ..
310 },
311 )) if missing_parameters.is_empty() => Ok(()),
312 Err(e) => Err(e),
313 };
314 res?;
315 }
316 rule.validate_parameters()?;
317 self.authorizer_block_builder.rules.push(rule);
318 }
319
320 for (_, check) in source_result.checks.into_iter() {
321 let mut check: Check = check.into();
322 for (name, value) in ¶ms {
323 let res = match check.set(name, value) {
324 Ok(_) => Ok(()),
325 Err(error::Token::Language(
326 biscuit_parser::error::LanguageError::Parameters {
327 missing_parameters, ..
328 },
329 )) if missing_parameters.is_empty() => Ok(()),
330 Err(e) => Err(e),
331 };
332 res?;
333 }
334 for (name, value) in &scope_params {
335 let res = match check.set_scope(name, *value) {
336 Ok(_) => Ok(()),
337 Err(error::Token::Language(
338 biscuit_parser::error::LanguageError::Parameters {
339 missing_parameters, ..
340 },
341 )) if missing_parameters.is_empty() => Ok(()),
342 Err(e) => Err(e),
343 };
344 res?;
345 }
346 check.validate_parameters()?;
347 self.authorizer_block_builder.checks.push(check);
348 }
349 for (_, policy) in source_result.policies.into_iter() {
350 let mut policy: Policy = policy.into();
351 for (name, value) in ¶ms {
352 let res = match policy.set(name, value) {
353 Ok(_) => Ok(()),
354 Err(error::Token::Language(
355 biscuit_parser::error::LanguageError::Parameters {
356 missing_parameters, ..
357 },
358 )) if missing_parameters.is_empty() => Ok(()),
359 Err(e) => Err(e),
360 };
361 res?;
362 }
363 for (name, value) in &scope_params {
364 let res = match policy.set_scope(name, *value) {
365 Ok(_) => Ok(()),
366 Err(error::Token::Language(
367 biscuit_parser::error::LanguageError::Parameters {
368 missing_parameters, ..
369 },
370 )) if missing_parameters.is_empty() => Ok(()),
371 Err(e) => Err(e),
372 };
373 res?;
374 }
375 policy.validate_parameters()?;
376 self.policies.push(policy);
377 }
378
379 Ok(())
380 }
381
382 pub fn add_scope(&mut self, scope: Scope) {
383 self.authorizer_block_builder.add_scope(scope);
384 }
385
386 pub fn limits(&self) -> &AuthorizerLimits {
390 &self.limits
391 }
392
393 pub fn set_limits(&mut self, limits: AuthorizerLimits) {
397 self.limits = limits;
398 }
399
400 pub fn query<R: TryInto<Rule>, T: TryFrom<Fact, Error = E>, E: Into<error::Token>>(
419 &mut self,
420 rule: R,
421 ) -> Result<Vec<T>, error::Token>
422 where
423 error::Token: From<<R as TryInto<Rule>>::Error>,
424 {
425 let mut limits = self.limits.clone();
426 limits.max_iterations -= self.world.iterations;
427 if self.execution_time >= limits.max_time {
428 return Err(error::Token::RunLimit(error::RunLimit::Timeout));
429 }
430 limits.max_time -= self.execution_time;
431
432 self.query_with_limits(rule, limits)
433 }
434
435 pub fn query_with_limits<R: TryInto<Rule>, T: TryFrom<Fact, Error = E>, E: Into<error::Token>>(
441 &mut self,
442 rule: R,
443 limits: AuthorizerLimits,
444 ) -> Result<Vec<T>, error::Token>
445 where
446 error::Token: From<<R as TryInto<Rule>>::Error>,
447 {
448 let rule = rule.try_into()?.convert(&mut self.symbols);
449
450 let start = Instant::now();
451 let result = self.query_inner(rule, limits);
452 self.execution_time += start.elapsed();
453
454 result
455 }
456
457 fn query_inner<T: TryFrom<Fact, Error = E>, E: Into<error::Token>>(
458 &mut self,
459 rule: datalog::Rule,
460 limits: AuthorizerLimits,
461 ) -> Result<Vec<T>, error::Token> {
462 let rule_trusted_origins = TrustedOrigins::from_scopes(
463 &rule.scopes,
464 &TrustedOrigins::default(), usize::MAX,
469 &self.public_key_to_block_id,
470 );
471
472 self.world.run_with_limits(&self.symbols, limits)?;
473 let res = self
474 .world
475 .query_rule(rule, usize::MAX, &rule_trusted_origins, &self.symbols)?;
476
477 res.inner
478 .into_iter()
479 .flat_map(|(_, set)| set.into_iter())
480 .map(|f| Fact::convert_from(&f, &self.symbols))
481 .map(|fact| {
482 fact.map_err(error::Token::Format)
483 .and_then(|f| f.try_into().map_err(Into::into))
484 })
485 .collect()
486 }
487
488 pub fn query_all<R: TryInto<Rule>, T: TryFrom<Fact, Error = E>, E: Into<error::Token>>(
508 &mut self,
509 rule: R,
510 ) -> Result<Vec<T>, error::Token>
511 where
512 error::Token: From<<R as TryInto<Rule>>::Error>,
513 {
514 let mut limits = self.limits.clone();
515 limits.max_iterations -= self.world.iterations;
516 if self.execution_time >= limits.max_time {
517 return Err(error::Token::RunLimit(error::RunLimit::Timeout));
518 }
519 limits.max_time -= self.execution_time;
520
521 self.query_all_with_limits(rule, limits)
522 }
523
524 pub fn query_all_with_limits<
530 R: TryInto<Rule>,
531 T: TryFrom<Fact, Error = E>,
532 E: Into<error::Token>,
533 >(
534 &mut self,
535 rule: R,
536 limits: AuthorizerLimits,
537 ) -> Result<Vec<T>, error::Token>
538 where
539 error::Token: From<<R as TryInto<Rule>>::Error>,
540 {
541 let rule = rule.try_into()?.convert(&mut self.symbols);
542
543 let start = Instant::now();
544 let result = self.query_all_inner(rule, limits);
545 self.execution_time += start.elapsed();
546
547 result
548 }
549
550 fn query_all_inner<T: TryFrom<Fact, Error = E>, E: Into<error::Token>>(
551 &mut self,
552 rule: datalog::Rule,
553 limits: AuthorizerLimits,
554 ) -> Result<Vec<T>, error::Token> {
555 self.world.run_with_limits(&self.symbols, limits)?;
556
557 let rule_trusted_origins = if rule.scopes.is_empty() {
558 self.token_origins.clone()
559 } else {
560 TrustedOrigins::from_scopes(
561 &rule.scopes,
562 &TrustedOrigins::default(), usize::MAX,
567 &self.public_key_to_block_id,
568 )
569 };
570
571 let res = self
572 .world
573 .query_rule(rule, 0, &rule_trusted_origins, &self.symbols)?;
574
575 let r: HashSet<_> = res.into_iter().map(|(_, fact)| fact).collect();
576
577 r.into_iter()
578 .map(|f| Fact::convert_from(&f, &self.symbols))
579 .map(|fact| {
580 fact.map_err(error::Token::Format)
581 .and_then(|f| f.try_into().map_err(Into::into))
582 })
583 .collect::<Result<Vec<T>, _>>()
584 }
585
586 pub fn set_time(&mut self) {
588 let fact = fact("time", &[date(&SystemTime::now())]);
589 self.authorizer_block_builder.add_fact(fact).unwrap();
590 }
591
592 pub fn add_policy<P: TryInto<Policy>>(&mut self, policy: P) -> Result<(), error::Token>
594 where
595 error::Token: From<<P as TryInto<Policy>>::Error>,
596 {
597 let policy = policy.try_into()?;
598 policy.validate_parameters()?;
599 self.policies.push(policy);
600 Ok(())
601 }
602
603 pub fn allow(&mut self) -> Result<(), error::Token> {
606 self.add_policy("allow if true")
607 }
608
609 pub fn deny(&mut self) -> Result<(), error::Token> {
611 self.add_policy("deny if true")
612 }
613
614 pub fn execution_time(&self) -> Duration {
616 self.execution_time
617 }
618
619 pub fn iterations(&self) -> u64 {
621 self.world.iterations
622 }
623
624 pub fn fact_count(&self) -> usize {
626 self.world.facts.len()
627 }
628
629 pub fn authorize(&mut self) -> Result<usize, error::Token> {
634 let mut limits = self.limits.clone();
635 limits.max_iterations -= self.world.iterations;
636 if self.execution_time >= limits.max_time {
637 return Err(error::Token::RunLimit(error::RunLimit::Timeout));
638 }
639 limits.max_time -= self.execution_time;
640
641 self.authorize_with_limits(limits)
642 }
643
644 pub fn authorize_with_limits(
651 &mut self,
652 limits: AuthorizerLimits,
653 ) -> Result<usize, error::Token> {
654 let start = Instant::now();
655 let result = self.authorize_inner(limits);
656 self.execution_time += start.elapsed();
657
658 result
659 }
660
661 fn authorize_inner(&mut self, mut limits: AuthorizerLimits) -> Result<usize, error::Token> {
662 let start = Instant::now();
663 let time_limit = start + limits.max_time;
664 let mut current_iterations = self.world.iterations;
665
666 let mut errors = vec![];
667 let mut policy_result: Option<Result<usize, usize>> = None;
668
669 let mut authorizer_origin = Origin::default();
670 authorizer_origin.insert(usize::MAX);
671
672 let authorizer_scopes: Vec<token::Scope> = self
673 .authorizer_block_builder
674 .scopes
675 .clone()
676 .iter()
677 .map(|s| s.convert(&mut self.symbols))
678 .collect();
679
680 let authorizer_trusted_origins = TrustedOrigins::from_scopes(
681 &authorizer_scopes,
682 &TrustedOrigins::default(),
683 usize::MAX,
684 &self.public_key_to_block_id,
685 );
686
687 for fact in &self.authorizer_block_builder.facts {
688 self.world
689 .facts
690 .insert(&authorizer_origin, fact.convert(&mut self.symbols));
691 }
692
693 for rule in &self.authorizer_block_builder.rules {
694 let rule = rule.convert(&mut self.symbols);
695
696 let rule_trusted_origins = TrustedOrigins::from_scopes(
697 &rule.scopes,
698 &authorizer_trusted_origins,
699 usize::MAX,
700 &self.public_key_to_block_id,
701 );
702
703 self.world
704 .rules
705 .insert(usize::MAX, &rule_trusted_origins, rule);
706 }
707
708 limits.max_time = time_limit - Instant::now();
709 self.world.run_with_limits(&self.symbols, limits.clone())?;
710
711 let authorizer_scopes: Vec<token::Scope> = self
712 .authorizer_block_builder
713 .scopes
714 .clone()
715 .iter()
716 .map(|s| s.convert(&mut self.symbols))
717 .collect();
718
719 let authorizer_trusted_origins = TrustedOrigins::from_scopes(
720 &authorizer_scopes,
721 &TrustedOrigins::default(),
722 usize::MAX,
723 &self.public_key_to_block_id,
724 );
725
726 for (i, check) in self.authorizer_block_builder.checks.iter().enumerate() {
727 let c = check.convert(&mut self.symbols);
728 let mut successful = false;
729
730 for query in check.queries.iter() {
731 let query = query.convert(&mut self.symbols);
732 let rule_trusted_origins = TrustedOrigins::from_scopes(
733 &query.scopes,
734 &authorizer_trusted_origins,
735 usize::MAX,
736 &self.public_key_to_block_id,
737 );
738 let res = match check.kind {
739 CheckKind::One => self.world.query_match(
740 query,
741 usize::MAX,
742 &rule_trusted_origins,
743 &self.symbols,
744 )?,
745 CheckKind::All => {
746 self.world
747 .query_match_all(query, &rule_trusted_origins, &self.symbols)?
748 }
749 };
750
751 let now = Instant::now();
752 if now >= time_limit {
753 return Err(error::Token::RunLimit(error::RunLimit::Timeout));
754 }
755
756 if res {
757 successful = true;
758 break;
759 }
760 }
761
762 if !successful {
763 errors.push(error::FailedCheck::Authorizer(
764 error::FailedAuthorizerCheck {
765 check_id: i as u32,
766 rule: self.symbols.print_check(&c),
767 },
768 ));
769 }
770 }
771
772 if let Some(blocks) = self.blocks.as_ref() {
773 for (j, check) in blocks[0].checks.iter().enumerate() {
774 let mut successful = false;
775
776 let authority_trusted_origins = TrustedOrigins::from_scopes(
777 &blocks[0].scopes,
778 &TrustedOrigins::default(),
779 0,
780 &self.public_key_to_block_id,
781 );
782
783 for query in check.queries.iter() {
784 let rule_trusted_origins = TrustedOrigins::from_scopes(
785 &query.scopes,
786 &authority_trusted_origins,
787 0,
788 &self.public_key_to_block_id,
789 );
790 let res = match check.kind {
791 CheckKind::One => self.world.query_match(
792 query.clone(),
793 0,
794 &rule_trusted_origins,
795 &self.symbols,
796 )?,
797 CheckKind::All => self.world.query_match_all(
798 query.clone(),
799 &rule_trusted_origins,
800 &self.symbols,
801 )?,
802 };
803
804 let now = Instant::now();
805 if now >= time_limit {
806 return Err(error::Token::RunLimit(error::RunLimit::Timeout));
807 }
808
809 if res {
810 successful = true;
811 break;
812 }
813 }
814
815 if !successful {
816 errors.push(error::FailedCheck::Block(error::FailedBlockCheck {
817 block_id: 0u32,
818 check_id: j as u32,
819 rule: self.symbols.print_check(check),
820 }));
821 }
822 }
823 }
824
825 'policies_test: for (i, policy) in self.policies.iter().enumerate() {
826 for query in policy.queries.iter() {
827 let query = query.convert(&mut self.symbols);
828 let rule_trusted_origins = TrustedOrigins::from_scopes(
829 &query.scopes,
830 &authorizer_trusted_origins,
831 usize::MAX,
832 &self.public_key_to_block_id,
833 );
834
835 let res = self.world.query_match(
836 query,
837 usize::MAX,
838 &rule_trusted_origins,
839 &self.symbols,
840 )?;
841
842 let now = Instant::now();
843 if now >= time_limit {
844 return Err(error::Token::RunLimit(error::RunLimit::Timeout));
845 }
846
847 if res {
848 match policy.kind {
849 PolicyKind::Allow => policy_result = Some(Ok(i)),
850 PolicyKind::Deny => policy_result = Some(Err(i)),
851 };
852 break 'policies_test;
853 }
854 }
855 }
856
857 if let Some(blocks) = self.blocks.as_ref() {
858 for (i, block) in (blocks[1..]).iter().enumerate() {
859 let block_trusted_origins = TrustedOrigins::from_scopes(
860 &block.scopes,
861 &TrustedOrigins::default(),
862 i + 1,
863 &self.public_key_to_block_id,
864 );
865
866 limits.max_time = time_limit - Instant::now();
867 limits.max_iterations -= self.world.iterations - current_iterations;
868 current_iterations = self.world.iterations;
869
870 self.world.run_with_limits(&self.symbols, limits.clone())?;
871
872 for (j, check) in block.checks.iter().enumerate() {
873 let mut successful = false;
874
875 for query in check.queries.iter() {
876 let rule_trusted_origins = TrustedOrigins::from_scopes(
877 &query.scopes,
878 &block_trusted_origins,
879 i + 1,
880 &self.public_key_to_block_id,
881 );
882
883 let res = match check.kind {
884 CheckKind::One => self.world.query_match(
885 query.clone(),
886 i + 1,
887 &rule_trusted_origins,
888 &self.symbols,
889 )?,
890 CheckKind::All => self.world.query_match_all(
891 query.clone(),
892 &rule_trusted_origins,
893 &self.symbols,
894 )?,
895 };
896
897 let now = Instant::now();
898 if now >= time_limit {
899 return Err(error::Token::RunLimit(error::RunLimit::Timeout));
900 }
901
902 if res {
903 successful = true;
904 break;
905 }
906 }
907
908 if !successful {
909 errors.push(error::FailedCheck::Block(error::FailedBlockCheck {
910 block_id: (i + 1) as u32,
911 check_id: j as u32,
912 rule: self.symbols.print_check(check),
913 }));
914 }
915 }
916 }
917 }
918
919 match (policy_result, errors.is_empty()) {
920 (Some(Ok(i)), true) => Ok(i),
921 (None, _) => Err(error::Token::FailedLogic(error::Logic::NoMatchingPolicy {
922 checks: errors,
923 })),
924 (Some(Ok(i)), _) => Err(error::Token::FailedLogic(error::Logic::Unauthorized {
925 policy: error::MatchedPolicy::Allow(i),
926 checks: errors,
927 })),
928 (Some(Err(i)), _) => Err(error::Token::FailedLogic(error::Logic::Unauthorized {
929 policy: error::MatchedPolicy::Deny(i),
930 checks: errors,
931 })),
932 }
933 }
934
935 pub fn print_world(&self) -> String {
937 self.to_string()
938 }
939
940 pub fn dump(&self) -> (Vec<Fact>, Vec<Rule>, Vec<Check>, Vec<Policy>) {
942 let mut checks = self.authorizer_block_builder.checks.clone();
943 if let Some(blocks) = &self.blocks {
944 for block in blocks {
945 checks.extend(
946 block
947 .checks
948 .iter()
949 .map(|c| Check::convert_from(c, &self.symbols).unwrap()),
950 );
951 }
952 }
953
954 let mut facts = self
955 .world
956 .facts
957 .iter_all()
958 .map(|f| Fact::convert_from(f.1, &self.symbols))
959 .collect::<Result<Vec<_>, error::Format>>()
960 .unwrap();
961 facts.extend(self.authorizer_block_builder.facts.clone());
962
963 let mut rules = self
964 .world
965 .rules
966 .iter_all()
967 .map(|r| Rule::convert_from(r.1, &self.symbols))
968 .collect::<Result<Vec<_>, error::Format>>()
969 .unwrap();
970 rules.extend(self.authorizer_block_builder.rules.clone());
971
972 (facts, rules, checks, self.policies.clone())
973 }
974
975 pub fn dump_code(&self) -> String {
976 let (facts, rules, checks, policies) = self.dump();
977 let mut f = String::new();
978 for fact in &facts {
979 let _ = writeln!(f, "{fact};");
980 }
981 if !facts.is_empty() {
982 let _ = writeln!(f);
983 }
984
985 for rule in &rules {
986 let _ = writeln!(f, "{rule};");
987 }
988 if !rules.is_empty() {
989 let _ = writeln!(f);
990 }
991
992 for check in &checks {
993 let _ = writeln!(f, "{check};");
994 }
995 if !checks.is_empty() {
996 let _ = writeln!(f);
997 }
998
999 for policy in &policies {
1000 let _ = writeln!(f, "{policy};");
1001 }
1002 f
1003 }
1004}
1005
1006impl std::fmt::Display for Authorizer {
1007 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1008 let mut has_facts = false;
1009 let mut all_facts = BTreeMap::new();
1010 for (origin, factset) in &self.world.facts.inner {
1011 let mut facts = HashSet::new();
1012 for fact in factset {
1013 facts.insert(self.symbols.print_fact(fact));
1014 }
1015
1016 has_facts = has_facts || !facts.is_empty();
1017 all_facts.insert(origin, facts);
1018 }
1019
1020 let builder_facts = self
1021 .authorizer_block_builder
1022 .facts
1023 .iter()
1024 .map(|f| f.to_string())
1025 .collect::<HashSet<_>>();
1026 has_facts = has_facts || !builder_facts.is_empty();
1027 let mut authorizer_origin = Origin::default();
1028 authorizer_origin.insert(usize::MAX);
1029 match all_facts.get_mut(&authorizer_origin) {
1030 Some(e) => {
1031 e.extend(builder_facts);
1032 }
1033 None => {
1034 all_facts.insert(&authorizer_origin, builder_facts);
1035 }
1036 }
1037
1038 if has_facts {
1039 writeln!(f, "// Facts:")?;
1040 }
1041
1042 for (origin, factset) in &all_facts {
1043 let mut facts = factset.iter().collect::<Vec<_>>();
1044 facts.sort();
1045
1046 if !facts.is_empty() {
1047 writeln!(f, "// origin: {origin}")?;
1048 }
1049
1050 for fact in facts {
1051 writeln!(f, "{};", fact)?;
1052 }
1053 }
1054
1055 if has_facts {
1056 writeln!(f)?;
1057 }
1058
1059 let mut has_rules = false;
1060 let mut rules_map: BTreeMap<usize, HashSet<String>> = BTreeMap::new();
1061 for ruleset in self.world.rules.inner.values() {
1062 has_rules = has_rules || !ruleset.is_empty();
1063 for (origin, rule) in ruleset {
1064 rules_map
1065 .entry(*origin)
1066 .or_default()
1067 .insert(self.symbols.print_rule(rule));
1068 }
1069 }
1070
1071 let builder_rules = self
1072 .authorizer_block_builder
1073 .rules
1074 .iter()
1075 .map(|rule| rule.to_string())
1076 .collect::<HashSet<_>>();
1077 has_rules = has_rules || !builder_rules.is_empty();
1078
1079 rules_map
1080 .entry(usize::MAX)
1081 .or_default()
1082 .extend(builder_rules);
1083
1084 if has_rules {
1085 writeln!(f, "// Rules:")?;
1086 }
1087
1088 for (origin, rule_list) in &rules_map {
1089 if !rule_list.is_empty() {
1090 if *origin == usize::MAX {
1091 writeln!(f, "// origin: authorizer")?;
1092 } else {
1093 writeln!(f, "// origin: {origin}")?;
1094 }
1095 }
1096
1097 let mut sorted_rule_list = rule_list.iter().collect::<Vec<_>>();
1098 sorted_rule_list.sort();
1099 for rule in sorted_rule_list {
1100 writeln!(f, "{};", rule)?;
1101 }
1102 }
1103
1104 if has_rules {
1105 writeln!(f)?;
1106 }
1107
1108 let mut has_checks = false;
1109 let mut checks_map: BTreeMap<usize, Vec<String>> = Default::default();
1110
1111 if let Some(blocks) = &self.blocks {
1112 for (i, block) in blocks.iter().enumerate() {
1113 let entry = checks_map.entry(i).or_default();
1114 has_checks = has_checks || !&block.checks.is_empty();
1115 for check in &block.checks {
1116 entry.push(self.symbols.print_check(check));
1117 }
1118 }
1119 }
1120
1121 let authorizer_entry = checks_map.entry(usize::MAX).or_default();
1122
1123 has_checks = has_checks || !&self.authorizer_block_builder.checks.is_empty();
1124 for check in &self.authorizer_block_builder.checks {
1125 authorizer_entry.push(check.to_string());
1126 }
1127
1128 if has_checks {
1129 writeln!(f, "// Checks:")?;
1130 }
1131
1132 for (origin, checks) in checks_map {
1133 if !checks.is_empty() {
1134 if origin == usize::MAX {
1135 writeln!(f, "// origin: authorizer")?;
1136 } else {
1137 writeln!(f, "// origin: {origin}")?;
1138 }
1139 }
1140
1141 for check in checks {
1142 writeln!(f, "{};", &check)?;
1143 }
1144 }
1145
1146 if has_checks {
1147 writeln!(f)?;
1148 }
1149
1150 if !self.policies.is_empty() {
1151 writeln!(f, "// Policies:")?;
1152 }
1153 for policy in self.policies.iter() {
1154 writeln!(f, "{policy};")?;
1155 }
1156
1157 Ok(())
1158 }
1159}
1160
1161impl TryFrom<AuthorizerPolicies> for Authorizer {
1162 type Error = error::Token;
1163
1164 fn try_from(authorizer_policies: AuthorizerPolicies) -> Result<Self, Self::Error> {
1165 let AuthorizerPolicies {
1166 version: _,
1167 facts,
1168 rules,
1169 checks,
1170 policies,
1171 } = authorizer_policies;
1172
1173 let mut authorizer = Self::new();
1174
1175 for fact in facts.into_iter() {
1176 authorizer.authorizer_block_builder.add_fact(fact)?;
1177 }
1178
1179 for rule in rules.into_iter() {
1180 authorizer.authorizer_block_builder.add_rule(rule)?;
1181 }
1182
1183 for check in checks.into_iter() {
1184 authorizer.authorizer_block_builder.add_check(check)?;
1185 }
1186
1187 for policy in policies {
1188 authorizer.policies.push(policy);
1189 }
1190
1191 Ok(authorizer)
1192 }
1193}
1194
1195#[derive(Debug, Clone)]
1196pub struct AuthorizerPolicies {
1197 pub version: u32,
1198 pub facts: Vec<Fact>,
1200 pub rules: Vec<Rule>,
1202 pub checks: Vec<Check>,
1204 pub policies: Vec<Policy>,
1205}
1206
1207impl AuthorizerPolicies {
1208 pub fn serialize(&self) -> Result<Vec<u8>, error::Token> {
1209 let proto = crate::format::convert::authorizer_to_proto_authorizer(self);
1210
1211 let mut v = Vec::new();
1212
1213 proto
1214 .encode(&mut v)
1215 .map(|_| v)
1216 .map_err(|e| error::Format::SerializationError(format!("serialization error: {:?}", e)))
1217 .map_err(error::Token::Format)
1218 }
1219
1220 pub fn deserialize(data: &[u8]) -> Result<Self, error::Token> {
1221 let data = crate::format::schema::AuthorizerPolicies::decode(data).map_err(|e| {
1222 error::Format::DeserializationError(format!("deserialization error: {:?}", e))
1223 })?;
1224
1225 Ok(crate::format::convert::proto_authorizer_to_authorizer(
1226 &data,
1227 )?)
1228 }
1229}
1230
1231pub type AuthorizerLimits = RunLimits;
1232
1233impl BuilderExt for Authorizer {
1234 fn add_resource(&mut self, name: &str) {
1235 let f = fact("resource", &[string(name)]);
1236 self.add_fact(f).unwrap();
1237 }
1238 fn check_resource(&mut self, name: &str) {
1239 self.add_check(Check {
1240 queries: vec![rule(
1241 "resource_check",
1242 &[string("resource_check")],
1243 &[pred("resource", &[string(name)])],
1244 )],
1245 kind: CheckKind::One,
1246 })
1247 .unwrap();
1248 }
1249 fn add_operation(&mut self, name: &str) {
1250 let f = fact("operation", &[string(name)]);
1251 self.add_fact(f).unwrap();
1252 }
1253 fn check_operation(&mut self, name: &str) {
1254 self.add_check(Check {
1255 queries: vec![rule(
1256 "operation_check",
1257 &[string("operation_check")],
1258 &[pred("operation", &[string(name)])],
1259 )],
1260 kind: CheckKind::One,
1261 })
1262 .unwrap();
1263 }
1264 fn check_resource_prefix(&mut self, prefix: &str) {
1265 let check = constrained_rule(
1266 "prefix",
1267 &[var("resource")],
1268 &[pred("resource", &[var("resource")])],
1269 &[Expression {
1270 ops: vec![
1271 Op::Value(var("resource")),
1272 Op::Value(string(prefix)),
1273 Op::Binary(Binary::Prefix),
1274 ],
1275 }],
1276 );
1277
1278 self.add_check(Check {
1279 queries: vec![check],
1280 kind: CheckKind::One,
1281 })
1282 .unwrap();
1283 }
1284
1285 fn check_resource_suffix(&mut self, suffix: &str) {
1286 let check = constrained_rule(
1287 "suffix",
1288 &[var("resource")],
1289 &[pred("resource", &[var("resource")])],
1290 &[Expression {
1291 ops: vec![
1292 Op::Value(var("resource")),
1293 Op::Value(string(suffix)),
1294 Op::Binary(Binary::Suffix),
1295 ],
1296 }],
1297 );
1298
1299 self.add_check(Check {
1300 queries: vec![check],
1301 kind: CheckKind::One,
1302 })
1303 .unwrap();
1304 }
1305
1306 fn check_expiration_date(&mut self, exp: SystemTime) {
1307 let check = constrained_rule(
1308 "expiration",
1309 &[var("time")],
1310 &[pred("time", &[var("time")])],
1311 &[Expression {
1312 ops: vec![
1313 Op::Value(var("time")),
1314 Op::Value(date(&exp)),
1315 Op::Binary(Binary::LessOrEqual),
1316 ],
1317 }],
1318 );
1319
1320 self.add_check(Check {
1321 queries: vec![check],
1322 kind: CheckKind::One,
1323 })
1324 .unwrap();
1325 }
1326}
1327
1328impl AuthorizerExt for Authorizer {
1329 fn add_allow_all(&mut self) {
1330 self.add_policy("allow if true").unwrap();
1331 }
1332 fn add_deny_all(&mut self) {
1333 self.add_policy("deny if true").unwrap();
1334 }
1335}
1336
1337#[cfg(test)]
1338mod tests {
1339 use std::time::Duration;
1340
1341 use crate::{
1342 builder::{BiscuitBuilder, BlockBuilder},
1343 KeyPair,
1344 };
1345
1346 use super::*;
1347
1348 #[test]
1349 fn empty_authorizer() {
1350 let mut authorizer = Authorizer::new();
1351 authorizer.add_policy("allow if true").unwrap();
1352 assert_eq!(
1353 authorizer.authorize_with_limits(AuthorizerLimits {
1354 max_time: Duration::from_secs(10),
1355 ..Default::default()
1356 }),
1357 Ok(0)
1358 );
1359 }
1360
1361 #[test]
1362 fn parameter_substitution() {
1363 let mut authorizer = Authorizer::new();
1364 let mut params = HashMap::new();
1365 params.insert("p1".to_string(), "value".into());
1366 params.insert("p2".to_string(), 0i64.into());
1367 params.insert("p3".to_string(), true.into());
1368 let mut scope_params = HashMap::new();
1369 scope_params.insert(
1370 "pk".to_string(),
1371 PublicKey::from_bytes(
1372 &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db")
1373 .unwrap(),
1374 )
1375 .unwrap(),
1376 );
1377 authorizer
1378 .add_code_with_params(
1379 r#"
1380 fact({p1}, "value");
1381 rule($var, {p2}) <- fact($var, {p2});
1382 check if {p3};
1383 allow if {p3} trusting {pk};
1384 "#,
1385 params,
1386 scope_params,
1387 )
1388 .unwrap();
1389 }
1390
1391 #[test]
1392 fn forbid_unbound_parameters() {
1393 let mut builder = Authorizer::new();
1394
1395 let mut fact = Fact::try_from("fact({p1}, {p4})").unwrap();
1396 fact.set("p1", "hello").unwrap();
1397 let res = builder.add_fact(fact);
1398 assert_eq!(
1399 res,
1400 Err(error::Token::Language(
1401 biscuit_parser::error::LanguageError::Parameters {
1402 missing_parameters: vec!["p4".to_string()],
1403 unused_parameters: vec![],
1404 }
1405 ))
1406 );
1407 let mut rule = Rule::try_from(
1408 "fact($var1, {p2}) <- f1($var1, $var3), f2({p2}, $var3, {p4}), $var3.starts_with({p2})",
1409 )
1410 .unwrap();
1411 rule.set("p2", "hello").unwrap();
1412 let res = builder.add_rule(rule);
1413 assert_eq!(
1414 res,
1415 Err(error::Token::Language(
1416 biscuit_parser::error::LanguageError::Parameters {
1417 missing_parameters: vec!["p4".to_string()],
1418 unused_parameters: vec![],
1419 }
1420 ))
1421 );
1422 let mut check = Check::try_from("check if {p4}, {p3}").unwrap();
1423 check.set("p3", true).unwrap();
1424 let res = builder.add_check(check);
1425 assert_eq!(
1426 res,
1427 Err(error::Token::Language(
1428 biscuit_parser::error::LanguageError::Parameters {
1429 missing_parameters: vec!["p4".to_string()],
1430 unused_parameters: vec![],
1431 }
1432 ))
1433 );
1434 let mut policy = Policy::try_from("allow if {p4}, {p3}").unwrap();
1435 policy.set("p3", true).unwrap();
1436
1437 let res = builder.add_policy(policy);
1438 assert_eq!(
1439 res,
1440 Err(error::Token::Language(
1441 biscuit_parser::error::LanguageError::Parameters {
1442 missing_parameters: vec!["p4".to_string()],
1443 unused_parameters: vec![],
1444 }
1445 ))
1446 );
1447 }
1448
1449 #[test]
1450 fn forbid_unbound_parameters_in_add_code() {
1451 let mut builder = Authorizer::new();
1452 let mut params = HashMap::new();
1453 params.insert("p1".to_string(), "hello".into());
1454 params.insert("p2".to_string(), 1i64.into());
1455 params.insert("p4".to_string(), "this will be ignored".into());
1456 let res = builder.add_code_with_params(
1457 r#"fact({p1}, "value");
1458 rule($head_var) <- f1($head_var), {p2} > 0;
1459 check if {p3};
1460 allow if {p3};
1461 "#,
1462 params,
1463 HashMap::new(),
1464 );
1465
1466 assert_eq!(
1467 res,
1468 Err(error::Token::Language(
1469 biscuit_parser::error::LanguageError::Parameters {
1470 missing_parameters: vec!["p3".to_string()],
1471 unused_parameters: vec![],
1472 }
1473 ))
1474 )
1475 }
1476
1477 #[test]
1478 fn query_authorizer_from_token_tuple() {
1479 use crate::Biscuit;
1480 use crate::KeyPair;
1481 let keypair = KeyPair::new();
1482 let mut builder = Biscuit::builder();
1483 builder.add_fact("user(\"John Doe\", 42)").unwrap();
1484
1485 let biscuit = builder.build(&keypair).unwrap();
1486
1487 let mut authorizer = biscuit.authorizer().unwrap();
1488 let res: Vec<(String, i64)> = authorizer
1489 .query("data($name, $id) <- user($name, $id)")
1490 .unwrap();
1491
1492 assert_eq!(res.len(), 1);
1493 assert_eq!(res[0].0, "John Doe");
1494 assert_eq!(res[0].1, 42);
1495 }
1496
1497 #[test]
1498 fn query_authorizer_from_token_string() {
1499 use crate::Biscuit;
1500 use crate::KeyPair;
1501 let keypair = KeyPair::new();
1502 let mut builder = Biscuit::builder();
1503 builder.add_fact("user(\"John Doe\")").unwrap();
1504
1505 let biscuit = builder.build(&keypair).unwrap();
1506
1507 let mut authorizer = biscuit.authorizer().unwrap();
1508 let res: Vec<(String,)> = authorizer.query("data($name) <- user($name)").unwrap();
1509
1510 assert_eq!(res.len(), 1);
1511 assert_eq!(res[0].0, "John Doe");
1512 }
1513
1514 #[test]
1515 fn authorizer_with_scopes() {
1516 let root = KeyPair::new();
1517 let external = KeyPair::new();
1518
1519 let mut builder = Biscuit::builder();
1520 let mut scope_params = HashMap::new();
1521 scope_params.insert("external_pub".to_string(), external.public());
1522 builder
1523 .add_code_with_params(
1524 r#"right("read");
1525 check if group("admin") trusting {external_pub};
1526 "#,
1527 HashMap::new(),
1528 scope_params,
1529 )
1530 .unwrap();
1531
1532 let biscuit1 = builder.build(&root).unwrap();
1533
1534 let req = biscuit1.third_party_request().unwrap();
1535
1536 let mut builder = BlockBuilder::new();
1537 builder
1538 .add_code(
1539 r#"group("admin");
1540 check if right("read");
1541 "#,
1542 )
1543 .unwrap();
1544 let res = req.create_block(&external.private(), builder).unwrap();
1545 let biscuit2 = biscuit1.append_third_party(external.public(), res).unwrap();
1546
1547 let mut authorizer = Authorizer::new();
1548 let external2 = KeyPair::new();
1549
1550 let mut scope_params = HashMap::new();
1551 scope_params.insert("external".to_string(), external.public());
1552 scope_params.insert("external2".to_string(), external2.public());
1553
1554 authorizer
1555 .add_code_with_params(
1556 r#"
1557 // this rule trusts both the third-party block and the authority, and can access facts
1558 // from both
1559 possible(true) <- right($right), group("admin") trusting authority, {external};
1560
1561 // this rule only trusts the third-party block and can't access authority facts
1562 // it should _not_ generate a fact
1563 impossible(true) <- right("read") trusting {external2};
1564
1565 authorizer(true);
1566
1567 check if possible(true) trusting authority, {external};
1568 deny if impossible(true) trusting {external2};
1569 allow if true;
1570 "#,
1571 HashMap::new(),
1572 scope_params,
1573 )
1574 .unwrap();
1575
1576 authorizer.add_token(&biscuit2).unwrap();
1577
1578 println!("token:\n{}", biscuit2);
1579 println!("world:\n{}", authorizer.print_world());
1580
1581 authorizer.set_limits(AuthorizerLimits {
1582 max_time: Duration::from_millis(10), ..Default::default()
1584 });
1585
1586 let res = authorizer.authorize_with_limits(AuthorizerLimits {
1587 max_time: Duration::from_secs(10),
1588 ..Default::default()
1589 });
1590 println!("world after:\n{}", authorizer.print_world());
1591
1592 res.unwrap();
1593
1594 let authorizer_facts: Vec<Fact> = authorizer
1596 .query_with_limits(
1597 "authorizer(true) <- authorizer(true)",
1598 AuthorizerLimits {
1599 max_time: Duration::from_secs(10),
1600 ..Default::default()
1601 },
1602 )
1603 .unwrap();
1604
1605 assert_eq!(authorizer_facts.len(), 1);
1606
1607 let authority_facts: Vec<Fact> = authorizer
1609 .query_with_limits(
1610 "right($right) <- right($right)",
1611 AuthorizerLimits {
1612 max_time: Duration::from_secs(10),
1613 ..Default::default()
1614 },
1615 )
1616 .unwrap();
1617 assert_eq!(authority_facts.len(), 1);
1618
1619 let authority_facts_untrusted: Vec<Fact> = authorizer
1623 .query_with_limits(
1624 {
1625 let mut r: Rule = "right($right) <- right($right) trusting {external}"
1626 .try_into()
1627 .unwrap();
1628 r.set_scope("external", external.public()).unwrap();
1629 r
1630 },
1631 AuthorizerLimits {
1632 max_time: Duration::from_secs(10),
1633 ..Default::default()
1634 },
1635 )
1636 .unwrap();
1637 assert_eq!(authority_facts_untrusted.len(), 0);
1638
1639 let block_facts_untrusted: Vec<Fact> = authorizer
1641 .query_with_limits(
1642 "group($group) <- group($group)",
1643 AuthorizerLimits {
1644 max_time: Duration::from_secs(10),
1645 ..Default::default()
1646 },
1647 )
1648 .unwrap();
1649 assert_eq!(block_facts_untrusted.len(), 0);
1650
1651 let block_facts_trusted: Vec<Fact> = authorizer
1653 .query_with_limits(
1654 {
1655 let mut r: Rule = "group($group) <- group($group) trusting {external}"
1656 .try_into()
1657 .unwrap();
1658 r.set_scope("external", external.public()).unwrap();
1659 r
1660 },
1661 AuthorizerLimits {
1662 max_time: Duration::from_secs(10),
1663 ..Default::default()
1664 },
1665 )
1666 .unwrap();
1667 assert_eq!(block_facts_trusted.len(), 1);
1668
1669 let block_facts_query_all: Vec<Fact> = authorizer
1671 .query_all_with_limits(
1672 "group($group) <- group($group)",
1673 AuthorizerLimits {
1674 max_time: Duration::from_secs(10),
1675 ..Default::default()
1676 },
1677 )
1678 .unwrap();
1679 assert_eq!(block_facts_query_all.len(), 1);
1680
1681 let block_facts_query_all_explicit: Vec<Fact> = authorizer
1684 .query_all_with_limits(
1685 "group($group) <- group($group) trusting authority",
1686 AuthorizerLimits {
1687 max_time: Duration::from_secs(10),
1688 ..Default::default()
1689 },
1690 )
1691 .unwrap();
1692 assert_eq!(block_facts_query_all_explicit.len(), 0);
1693 }
1694
1695 #[test]
1696 fn authorizer_display_before_and_after_authorization() {
1697 let root = KeyPair::new();
1698
1699 let mut token_builder = BiscuitBuilder::new();
1700 token_builder
1701 .add_code(
1702 r#"
1703 authority_fact(true);
1704 authority_rule($v) <- authority_fact($v);
1705 check if authority_fact(true), authority_rule(true);
1706 "#,
1707 )
1708 .unwrap();
1709 let token = token_builder.build(&root).unwrap();
1710
1711 let mut authorizer = token.authorizer().unwrap();
1712 authorizer
1713 .add_code(
1714 r#"
1715 authorizer_fact(true);
1716 authorizer_rule($v) <- authorizer_fact($v);
1717 check if authorizer_fact(true), authorizer_rule(true);
1718 allow if true;
1719 "#,
1720 )
1721 .unwrap();
1722 let output_before_authorization = authorizer.to_string();
1723
1724 assert!(
1725 output_before_authorization.contains("authorizer_fact(true)"),
1726 "Authorizer.to_string() displays authorizer facts even before running authorize()"
1727 );
1728
1729 authorizer
1730 .authorize_with_limits(AuthorizerLimits {
1731 max_time: Duration::from_secs(10),
1732 ..Default::default()
1733 })
1734 .unwrap();
1735
1736 let output_after_authorization = authorizer.to_string();
1737 assert!(
1738 output_after_authorization.contains("authorizer_rule(true)"),
1739 "Authorizer.to_string() displays generated facts after running authorize()"
1740 );
1741
1742 assert_eq!(
1743 r#"// Facts:
1744// origin: 0
1745authority_fact(true);
1746authority_rule(true);
1747// origin: authorizer
1748authorizer_fact(true);
1749authorizer_rule(true);
1750
1751// Rules:
1752// origin: 0
1753authority_rule($v) <- authority_fact($v);
1754// origin: authorizer
1755authorizer_rule($v) <- authorizer_fact($v);
1756
1757// Checks:
1758// origin: 0
1759check if authority_fact(true), authority_rule(true);
1760// origin: authorizer
1761check if authorizer_fact(true), authorizer_rule(true);
1762
1763// Policies:
1764allow if true;
1765"#,
1766 output_after_authorization
1767 );
1768 }
1769
1770 #[test]
1771 fn empty_authorizer_display() {
1772 let authorizer = Authorizer::new();
1773 assert_eq!("", authorizer.to_string())
1774 }
1775}