1use super::{default_symbol_table, Biscuit, Block};
3use crate::crypto::{KeyPair, PublicKey};
4use crate::datalog::{self, get_schema_version, SymbolTable};
5use crate::error;
6use crate::token::builder_ext::BuilderExt;
7use biscuit_parser::parser::parse_block_source;
8use nom::Finish;
9use rand_core::{CryptoRng, RngCore};
10use std::str::FromStr;
11use std::{
12 collections::{BTreeSet, HashMap},
13 convert::{TryFrom, TryInto},
14 fmt::{self, Write},
15 time::{Duration, SystemTime, UNIX_EPOCH},
16};
17
18pub use crate::datalog::{Binary, Expression as DatalogExpression, Op as DatalogOp, Unary};
20
21#[derive(Clone, Debug, Default)]
23pub struct BlockBuilder {
24 pub facts: Vec<Fact>,
25 pub rules: Vec<Rule>,
26 pub checks: Vec<Check>,
27 pub scopes: Vec<Scope>,
28 pub context: Option<String>,
29}
30
31impl BlockBuilder {
32 pub fn new() -> BlockBuilder {
33 BlockBuilder::default()
34 }
35
36 pub fn merge(&mut self, mut other: BlockBuilder) {
37 self.facts.append(&mut other.facts);
38 self.rules.append(&mut other.rules);
39 self.checks.append(&mut other.checks);
40
41 if let Some(c) = other.context {
42 self.set_context(c);
43 }
44 }
45
46 pub fn add_fact<F: TryInto<Fact>>(&mut self, fact: F) -> Result<(), error::Token>
47 where
48 error::Token: From<<F as TryInto<Fact>>::Error>,
49 {
50 let fact = fact.try_into()?;
51 fact.validate()?;
52
53 self.facts.push(fact);
54 Ok(())
55 }
56
57 pub fn add_rule<R: TryInto<Rule>>(&mut self, rule: R) -> Result<(), error::Token>
58 where
59 error::Token: From<<R as TryInto<Rule>>::Error>,
60 {
61 let rule = rule.try_into()?;
62 rule.validate_parameters()?;
63 self.rules.push(rule);
64 Ok(())
65 }
66
67 pub fn add_check<C: TryInto<Check>>(&mut self, check: C) -> Result<(), error::Token>
68 where
69 error::Token: From<<C as TryInto<Check>>::Error>,
70 {
71 let check = check.try_into()?;
72 check.validate_parameters()?;
73 self.checks.push(check);
74 Ok(())
75 }
76
77 pub fn add_code<T: AsRef<str>>(&mut self, source: T) -> Result<(), error::Token> {
78 self.add_code_with_params(source, HashMap::new(), HashMap::new())
79 }
80
81 pub fn add_code_with_params<T: AsRef<str>>(
84 &mut self,
85 source: T,
86 params: HashMap<String, Term>,
87 scope_params: HashMap<String, PublicKey>,
88 ) -> Result<(), error::Token> {
89 let input = source.as_ref();
90
91 let source_result = parse_block_source(input).map_err(|e| {
92 let e2: biscuit_parser::error::LanguageError = e.into();
93 e2
94 })?;
95
96 for (_, fact) in source_result.facts.into_iter() {
97 let mut fact: Fact = fact.into();
98 for (name, value) in ¶ms {
99 let res = match fact.set(name, value) {
100 Ok(_) => Ok(()),
101 Err(error::Token::Language(
102 biscuit_parser::error::LanguageError::Parameters {
103 missing_parameters, ..
104 },
105 )) if missing_parameters.is_empty() => Ok(()),
106 Err(e) => Err(e),
107 };
108 res?;
109 }
110 fact.validate()?;
111 self.facts.push(fact);
112 }
113
114 for (_, rule) in source_result.rules.into_iter() {
115 let mut rule: Rule = rule.into();
116 for (name, value) in ¶ms {
117 let res = match rule.set(name, value) {
118 Ok(_) => Ok(()),
119 Err(error::Token::Language(
120 biscuit_parser::error::LanguageError::Parameters {
121 missing_parameters, ..
122 },
123 )) if missing_parameters.is_empty() => Ok(()),
124 Err(e) => Err(e),
125 };
126 res?;
127 }
128 for (name, value) in &scope_params {
129 let res = match rule.set_scope(name, *value) {
130 Ok(_) => Ok(()),
131 Err(error::Token::Language(
132 biscuit_parser::error::LanguageError::Parameters {
133 missing_parameters, ..
134 },
135 )) if missing_parameters.is_empty() => Ok(()),
136 Err(e) => Err(e),
137 };
138 res?;
139 }
140 rule.validate_parameters()?;
141 self.rules.push(rule);
142 }
143
144 for (_, check) in source_result.checks.into_iter() {
145 let mut check: Check = check.into();
146 for (name, value) in ¶ms {
147 let res = match check.set(name, value) {
148 Ok(_) => Ok(()),
149 Err(error::Token::Language(
150 biscuit_parser::error::LanguageError::Parameters {
151 missing_parameters, ..
152 },
153 )) if missing_parameters.is_empty() => Ok(()),
154 Err(e) => Err(e),
155 };
156 res?;
157 }
158 for (name, value) in &scope_params {
159 let res = match check.set_scope(name, *value) {
160 Ok(_) => Ok(()),
161 Err(error::Token::Language(
162 biscuit_parser::error::LanguageError::Parameters {
163 missing_parameters, ..
164 },
165 )) if missing_parameters.is_empty() => Ok(()),
166 Err(e) => Err(e),
167 };
168 res?;
169 }
170 check.validate_parameters()?;
171 self.checks.push(check);
172 }
173
174 Ok(())
175 }
176
177 pub fn add_scope(&mut self, scope: Scope) {
178 self.scopes.push(scope);
179 }
180
181 pub fn set_context(&mut self, context: String) {
182 self.context = Some(context);
183 }
184
185 pub(crate) fn build(self, mut symbols: SymbolTable) -> Block {
186 let symbols_start = symbols.current_offset();
187 let public_keys_start = symbols.public_keys.current_offset();
188
189 let mut facts = Vec::new();
190 for fact in self.facts {
191 facts.push(fact.convert(&mut symbols));
192 }
193
194 let mut rules = Vec::new();
195 for rule in &self.rules {
196 rules.push(rule.convert(&mut symbols));
197 }
198
199 let mut checks = Vec::new();
200 for check in &self.checks {
201 checks.push(check.convert(&mut symbols));
202 }
203
204 let mut scopes = Vec::new();
205 for scope in &self.scopes {
206 scopes.push(scope.convert(&mut symbols));
207 }
208
209 let new_syms = symbols.split_at(symbols_start);
210 let public_keys = symbols.public_keys.split_at(public_keys_start);
211 let schema_version = get_schema_version(&facts, &rules, &checks, &scopes);
212
213 Block {
214 symbols: new_syms,
215 facts,
216 rules,
217 checks,
218 context: self.context,
219 version: schema_version.version(),
220 external_key: None,
221 public_keys,
222 scopes,
223 }
224 }
225
226 pub(crate) fn convert_from(
227 block: &Block,
228 symbols: &SymbolTable,
229 ) -> Result<Self, error::Format> {
230 Ok(BlockBuilder {
231 facts: block
232 .facts
233 .iter()
234 .map(|f| Fact::convert_from(f, symbols))
235 .collect::<Result<Vec<Fact>, error::Format>>()?,
236 rules: block
237 .rules
238 .iter()
239 .map(|r| Rule::convert_from(r, symbols))
240 .collect::<Result<Vec<Rule>, error::Format>>()?,
241 checks: block
242 .checks
243 .iter()
244 .map(|c| Check::convert_from(c, symbols))
245 .collect::<Result<Vec<Check>, error::Format>>()?,
246 scopes: block
247 .scopes
248 .iter()
249 .map(|s| Scope::convert_from(s, symbols))
250 .collect::<Result<Vec<Scope>, error::Format>>()?,
251 context: block.context.clone(),
252 })
253 }
254
255 #[cfg(test)]
257 pub(crate) fn check_right(&mut self, right: &str) {
258 let check = rule(
259 "check_right",
260 &[string(right)],
261 &[
262 pred("resource", &[var("resource_name")]),
263 pred("operation", &[string(right)]),
264 pred("right", &[var("resource_name"), string(right)]),
265 ],
266 );
267
268 let _ = self.add_check(check);
269 }
270}
271
272impl fmt::Display for BlockBuilder {
273 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
274 for mut fact in self.facts.clone().into_iter() {
275 fact.apply_parameters();
276 writeln!(f, "{};", &fact)?;
277 }
278 for mut rule in self.rules.clone().into_iter() {
279 rule.apply_parameters();
280 writeln!(f, "{};", &rule)?;
281 }
282 for mut check in self.checks.clone().into_iter() {
283 check.apply_parameters();
284 writeln!(f, "{};", &check)?;
285 }
286 Ok(())
287 }
288}
289
290#[derive(Clone, Default)]
292pub struct BiscuitBuilder {
293 inner: BlockBuilder,
294 root_key_id: Option<u32>,
295}
296
297impl BiscuitBuilder {
298 pub fn new() -> BiscuitBuilder {
299 BiscuitBuilder {
300 inner: BlockBuilder::new(),
301 root_key_id: None,
302 }
303 }
304
305 pub fn merge(&mut self, other: BlockBuilder) {
306 self.inner.merge(other)
307 }
308
309 pub fn add_fact<F: TryInto<Fact>>(&mut self, fact: F) -> Result<(), error::Token>
310 where
311 error::Token: From<<F as TryInto<Fact>>::Error>,
312 {
313 self.inner.add_fact(fact)
314 }
315
316 pub fn add_rule<Ru: TryInto<Rule>>(&mut self, rule: Ru) -> Result<(), error::Token>
317 where
318 error::Token: From<<Ru as TryInto<Rule>>::Error>,
319 {
320 self.inner.add_rule(rule)
321 }
322
323 pub fn add_check<C: TryInto<Check>>(&mut self, check: C) -> Result<(), error::Token>
324 where
325 error::Token: From<<C as TryInto<Check>>::Error>,
326 {
327 self.inner.add_check(check)
328 }
329
330 pub fn add_code<T: AsRef<str>>(&mut self, source: T) -> Result<(), error::Token> {
331 self.inner
332 .add_code_with_params(source, HashMap::new(), HashMap::new())
333 }
334
335 pub fn add_code_with_params<T: AsRef<str>>(
336 &mut self,
337 source: T,
338 params: HashMap<String, Term>,
339 scope_params: HashMap<String, PublicKey>,
340 ) -> Result<(), error::Token> {
341 self.inner
342 .add_code_with_params(source, params, scope_params)
343 }
344
345 pub fn add_scope(&mut self, scope: Scope) {
346 self.inner.add_scope(scope);
347 }
348
349 #[cfg(test)]
350 pub(crate) fn add_right(&mut self, resource: &str, right: &str) {
351 let _ = self.add_fact(fact("right", &[string(resource), string(right)]));
352 }
353
354 pub fn set_context(&mut self, context: String) {
355 self.inner.set_context(context);
356 }
357
358 pub fn set_root_key_id(&mut self, root_key_id: u32) {
359 self.root_key_id = Some(root_key_id);
360 }
361
362 pub fn dump(&self) -> (Vec<Fact>, Vec<Rule>, Vec<Check>) {
364 (
365 self.inner.facts.clone(),
366 self.inner.rules.clone(),
367 self.inner.checks.clone(),
368 )
369 }
370
371 pub fn dump_code(&self) -> String {
372 let (facts, rules, checks) = self.dump();
373 let mut f = String::new();
374 for fact in facts {
375 let _ = writeln!(f, "{};", fact);
376 }
377 for rule in rules {
378 let _ = writeln!(f, "{};", rule);
379 }
380 for check in checks {
381 let _ = writeln!(f, "{};", check);
382 }
383 f
384 }
385
386 pub fn build(self, root_key: &KeyPair) -> Result<Biscuit, error::Token> {
387 self.build_with_symbols(root_key, default_symbol_table())
388 }
389
390 pub fn build_with_symbols(
391 self,
392 root_key: &KeyPair,
393 symbols: SymbolTable,
394 ) -> Result<Biscuit, error::Token> {
395 self.build_with_rng(root_key, symbols, &mut rand::rngs::OsRng)
396 }
397
398 pub fn build_with_rng<R: RngCore + CryptoRng>(
399 self,
400 root: &KeyPair,
401 symbols: SymbolTable,
402 rng: &mut R,
403 ) -> Result<Biscuit, error::Token> {
404 let authority_block = self.inner.build(symbols.clone());
405 Biscuit::new_with_rng(rng, self.root_key_id, root, symbols, authority_block)
406 }
407}
408
409pub trait Convert<T>: Sized {
410 fn convert(&self, symbols: &mut SymbolTable) -> T;
411 fn convert_from(f: &T, symbols: &SymbolTable) -> Result<Self, error::Format>;
412 fn translate(
413 f: &T,
414 from_symbols: &SymbolTable,
415 to_symbols: &mut SymbolTable,
416 ) -> Result<T, error::Format> {
417 Ok(Self::convert_from(f, from_symbols)?.convert(to_symbols))
418 }
419}
420
421#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
423pub enum Term {
424 Variable(String),
425 Integer(i64),
426 Str(String),
427 Date(u64),
428 Bytes(Vec<u8>),
429 Bool(bool),
430 Set(BTreeSet<Term>),
431 Parameter(String),
432}
433
434impl Convert<datalog::Term> for Term {
435 fn convert(&self, symbols: &mut SymbolTable) -> datalog::Term {
436 match self {
437 Term::Variable(s) => datalog::Term::Variable(symbols.insert(s) as u32),
438 Term::Integer(i) => datalog::Term::Integer(*i),
439 Term::Str(s) => datalog::Term::Str(symbols.insert(s)),
440 Term::Date(d) => datalog::Term::Date(*d),
441 Term::Bytes(s) => datalog::Term::Bytes(s.clone()),
442 Term::Bool(b) => datalog::Term::Bool(*b),
443 Term::Set(s) => datalog::Term::Set(s.iter().map(|i| i.convert(symbols)).collect()),
444 Term::Parameter(s) => panic!("Remaining parameter {}", &s),
447 }
448 }
449
450 fn convert_from(f: &datalog::Term, symbols: &SymbolTable) -> Result<Self, error::Format> {
451 Ok(match f {
452 datalog::Term::Variable(s) => Term::Variable(symbols.print_symbol(*s as u64)?),
453 datalog::Term::Integer(i) => Term::Integer(*i),
454 datalog::Term::Str(s) => Term::Str(symbols.print_symbol(*s)?),
455 datalog::Term::Date(d) => Term::Date(*d),
456 datalog::Term::Bytes(s) => Term::Bytes(s.clone()),
457 datalog::Term::Bool(b) => Term::Bool(*b),
458 datalog::Term::Set(s) => Term::Set(
459 s.iter()
460 .map(|i| Term::convert_from(i, symbols))
461 .collect::<Result<BTreeSet<_>, error::Format>>()?,
462 ),
463 })
464 }
465}
466
467impl From<&Term> for Term {
468 fn from(i: &Term) -> Self {
469 match i {
470 Term::Variable(ref v) => Term::Variable(v.clone()),
471 Term::Integer(ref i) => Term::Integer(*i),
472 Term::Str(ref s) => Term::Str(s.clone()),
473 Term::Date(ref d) => Term::Date(*d),
474 Term::Bytes(ref s) => Term::Bytes(s.clone()),
475 Term::Bool(b) => Term::Bool(*b),
476 Term::Set(ref s) => Term::Set(s.clone()),
477 Term::Parameter(ref p) => Term::Parameter(p.clone()),
478 }
479 }
480}
481
482impl From<biscuit_parser::builder::Term> for Term {
483 fn from(t: biscuit_parser::builder::Term) -> Self {
484 match t {
485 biscuit_parser::builder::Term::Variable(v) => Term::Variable(v),
486 biscuit_parser::builder::Term::Integer(i) => Term::Integer(i),
487 biscuit_parser::builder::Term::Str(s) => Term::Str(s),
488 biscuit_parser::builder::Term::Date(d) => Term::Date(d),
489 biscuit_parser::builder::Term::Bytes(s) => Term::Bytes(s),
490 biscuit_parser::builder::Term::Bool(b) => Term::Bool(b),
491 biscuit_parser::builder::Term::Set(s) => {
492 Term::Set(s.into_iter().map(|t| t.into()).collect())
493 }
494 biscuit_parser::builder::Term::Parameter(ref p) => Term::Parameter(p.clone()),
495 }
496 }
497}
498
499impl AsRef<Term> for Term {
500 fn as_ref(&self) -> &Term {
501 self
502 }
503}
504
505impl fmt::Display for Term {
506 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
507 match self {
508 Term::Variable(i) => write!(f, "${}", i),
509 Term::Integer(i) => write!(f, "{}", i),
510 Term::Str(s) => write!(f, "\"{}\"", s),
511 Term::Date(d) => {
512 let date = time::OffsetDateTime::from_unix_timestamp(*d as i64)
513 .ok()
514 .and_then(|t| {
515 t.format(&time::format_description::well_known::Rfc3339)
516 .ok()
517 })
518 .unwrap_or_else(|| "<invalid date>".to_string());
519
520 write!(f, "{}", date)
521 }
522 Term::Bytes(s) => write!(f, "hex:{}", hex::encode(s)),
523 Term::Bool(b) => {
524 if *b {
525 write!(f, "true")
526 } else {
527 write!(f, "false")
528 }
529 }
530 Term::Set(s) => {
531 let terms = s.iter().map(|term| term.to_string()).collect::<Vec<_>>();
532 write!(f, "[{}]", terms.join(", "))
533 }
534 Term::Parameter(s) => {
535 write!(f, "{{{}}}", s)
536 }
537 }
538 }
539}
540
541#[derive(Clone, Debug, Hash, PartialEq, Eq)]
543pub enum Scope {
544 Authority,
546 Previous,
548 PublicKey(PublicKey),
550 Parameter(String),
552}
553
554impl Convert<super::Scope> for Scope {
555 fn convert(&self, symbols: &mut SymbolTable) -> super::Scope {
556 match self {
557 Scope::Authority => crate::token::Scope::Authority,
558 Scope::Previous => crate::token::Scope::Previous,
559 Scope::PublicKey(key) => {
560 crate::token::Scope::PublicKey(symbols.public_keys.insert(key))
561 }
562 Scope::Parameter(s) => panic!("Remaining parameter {}", &s),
565 }
566 }
567
568 fn convert_from(scope: &super::Scope, symbols: &SymbolTable) -> Result<Self, error::Format> {
569 Ok(match scope {
570 super::Scope::Authority => Scope::Authority,
571 super::Scope::Previous => Scope::Previous,
572 super::Scope::PublicKey(key_id) => Scope::PublicKey(
573 *symbols
574 .public_keys
575 .get_key(*key_id)
576 .ok_or(error::Format::UnknownExternalKey)?,
577 ),
578 })
579 }
580}
581
582impl fmt::Display for Scope {
583 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
584 match self {
585 Scope::Authority => write!(f, "authority"),
586 Scope::Previous => write!(f, "previous"),
587 Scope::PublicKey(pk) => write!(f, "ed25519/{}", hex::encode(pk.to_bytes())),
588 Scope::Parameter(s) => {
589 write!(f, "{{{}}}", s)
590 }
591 }
592 }
593}
594
595impl From<biscuit_parser::builder::Scope> for Scope {
596 fn from(scope: biscuit_parser::builder::Scope) -> Self {
597 match scope {
598 biscuit_parser::builder::Scope::Authority => Scope::Authority,
599 biscuit_parser::builder::Scope::Previous => Scope::Previous,
600 biscuit_parser::builder::Scope::PublicKey(pk) => {
601 Scope::PublicKey(PublicKey::from_bytes(&pk).expect("invalid public key"))
602 }
603 biscuit_parser::builder::Scope::Parameter(s) => Scope::Parameter(s),
604 }
605 }
606}
607
608#[derive(Debug, Clone, PartialEq, Hash, Eq)]
610pub struct Predicate {
611 pub name: String,
612 pub terms: Vec<Term>,
613}
614
615impl Predicate {
616 pub fn new<T: Into<Vec<Term>>>(name: String, terms: T) -> Predicate {
617 Predicate {
618 name,
619 terms: terms.into(),
620 }
621 }
622}
623
624impl Convert<datalog::Predicate> for Predicate {
625 fn convert(&self, symbols: &mut SymbolTable) -> datalog::Predicate {
626 let name = symbols.insert(&self.name);
627 let mut terms = vec![];
628
629 for term in self.terms.iter() {
630 terms.push(term.convert(symbols));
631 }
632
633 datalog::Predicate { name, terms }
634 }
635
636 fn convert_from(p: &datalog::Predicate, symbols: &SymbolTable) -> Result<Self, error::Format> {
637 Ok(Predicate {
638 name: symbols.print_symbol(p.name)?,
639 terms: p
640 .terms
641 .iter()
642 .map(|term| Term::convert_from(term, symbols))
643 .collect::<Result<Vec<_>, error::Format>>()?,
644 })
645 }
646}
647
648impl AsRef<Predicate> for Predicate {
649 fn as_ref(&self) -> &Predicate {
650 self
651 }
652}
653
654impl fmt::Display for Predicate {
655 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
656 write!(f, "{}(", self.name)?;
657
658 if !self.terms.is_empty() {
659 write!(f, "{}", self.terms[0])?;
660
661 if self.terms.len() > 1 {
662 for i in 1..self.terms.len() {
663 write!(f, ", {}", self.terms[i])?;
664 }
665 }
666 }
667 write!(f, ")")
668 }
669}
670
671impl From<biscuit_parser::builder::Predicate> for Predicate {
672 fn from(p: biscuit_parser::builder::Predicate) -> Self {
673 Predicate {
674 name: p.name,
675 terms: p.terms.into_iter().map(|t| t.into()).collect(),
676 }
677 }
678}
679
680#[derive(Debug, Clone, PartialEq, Eq)]
682pub struct Fact {
683 pub predicate: Predicate,
684 pub parameters: Option<HashMap<String, Option<Term>>>,
685}
686
687impl Fact {
688 pub fn new<T: Into<Vec<Term>>>(name: String, terms: T) -> Fact {
689 let mut parameters = HashMap::new();
690 let terms: Vec<Term> = terms.into();
691
692 for term in &terms {
693 if let Term::Parameter(name) = &term {
694 parameters.insert(name.to_string(), None);
695 }
696 }
697 Fact {
698 predicate: Predicate::new(name, terms),
699 parameters: Some(parameters),
700 }
701 }
702
703 pub fn validate(&self) -> Result<(), error::Token> {
704 match &self.parameters {
705 None => Ok(()),
706 Some(parameters) => {
707 let invalid_parameters = parameters
708 .iter()
709 .filter_map(
710 |(name, opt_term)| {
711 if opt_term.is_none() {
712 Some(name)
713 } else {
714 None
715 }
716 },
717 )
718 .map(|name| name.to_string())
719 .collect::<Vec<_>>();
720
721 if invalid_parameters.is_empty() {
722 Ok(())
723 } else {
724 Err(error::Token::Language(
725 biscuit_parser::error::LanguageError::Parameters {
726 missing_parameters: invalid_parameters,
727 unused_parameters: vec![],
728 },
729 ))
730 }
731 }
732 }
733 }
734
735 pub fn set<T: Into<Term>>(&mut self, name: &str, term: T) -> Result<(), error::Token> {
737 if let Some(parameters) = self.parameters.as_mut() {
738 match parameters.get_mut(name) {
739 None => Err(error::Token::Language(
740 biscuit_parser::error::LanguageError::Parameters {
741 missing_parameters: vec![],
742 unused_parameters: vec![name.to_string()],
743 },
744 )),
745 Some(v) => {
746 *v = Some(term.into());
747 Ok(())
748 }
749 }
750 } else {
751 Err(error::Token::Language(
752 biscuit_parser::error::LanguageError::Parameters {
753 missing_parameters: vec![],
754 unused_parameters: vec![name.to_string()],
755 },
756 ))
757 }
758 }
759
760 pub fn set_lenient<T: Into<Term>>(&mut self, name: &str, term: T) -> Result<(), error::Token> {
763 if let Some(parameters) = self.parameters.as_mut() {
764 match parameters.get_mut(name) {
765 None => Ok(()),
766 Some(v) => {
767 *v = Some(term.into());
768 Ok(())
769 }
770 }
771 } else {
772 Err(error::Token::Language(
773 biscuit_parser::error::LanguageError::Parameters {
774 missing_parameters: vec![],
775 unused_parameters: vec![name.to_string()],
776 },
777 ))
778 }
779 }
780
781 #[cfg(feature = "datalog-macro")]
782 pub fn set_macro_param<T: ToAnyParam>(
783 &mut self,
784 name: &str,
785 param: T,
786 ) -> Result<(), error::Token> {
787 match param.to_any_param() {
788 AnyParam::Term(t) => self.set_lenient(name, t),
789 AnyParam::PublicKey(_) => Ok(()),
790 }
791 }
792
793 fn apply_parameters(&mut self) {
794 if let Some(parameters) = self.parameters.clone() {
795 self.predicate.terms = self
796 .predicate
797 .terms
798 .drain(..)
799 .map(|t| {
800 if let Term::Parameter(name) = &t {
801 if let Some(Some(term)) = parameters.get(name) {
802 return term.clone();
803 }
804 }
805 t
806 })
807 .collect();
808 }
809 }
810}
811
812impl Convert<datalog::Fact> for Fact {
813 fn convert(&self, symbols: &mut SymbolTable) -> datalog::Fact {
814 let mut fact = self.clone();
815 fact.apply_parameters();
816
817 datalog::Fact {
818 predicate: fact.predicate.convert(symbols),
819 }
820 }
821
822 fn convert_from(f: &datalog::Fact, symbols: &SymbolTable) -> Result<Self, error::Format> {
823 Ok(Fact {
824 predicate: Predicate::convert_from(&f.predicate, symbols)?,
825 parameters: None,
826 })
827 }
828}
829
830impl fmt::Display for Fact {
831 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
832 let mut fact = self.clone();
833 fact.apply_parameters();
834
835 fact.predicate.fmt(f)
836 }
837}
838
839impl From<biscuit_parser::builder::Fact> for Fact {
840 fn from(f: biscuit_parser::builder::Fact) -> Self {
841 Fact {
842 predicate: f.predicate.into(),
843 parameters: f.parameters.map(|h| {
845 h.into_iter()
846 .map(|(k, v)| (k, v.map(|term| term.into())))
847 .collect()
848 }),
849 }
850 }
851}
852
853#[derive(Debug, Clone, PartialEq, Eq)]
855pub struct Expression {
856 pub ops: Vec<Op>,
857}
858impl Convert<datalog::Expression> for Expression {
861 fn convert(&self, symbols: &mut SymbolTable) -> datalog::Expression {
862 datalog::Expression {
863 ops: self.ops.iter().map(|op| op.convert(symbols)).collect(),
864 }
865 }
866
867 fn convert_from(e: &datalog::Expression, symbols: &SymbolTable) -> Result<Self, error::Format> {
868 Ok(Expression {
869 ops: e
870 .ops
871 .iter()
872 .map(|op| Op::convert_from(op, symbols))
873 .collect::<Result<Vec<_>, error::Format>>()?,
874 })
875 }
876}
877
878impl AsRef<Expression> for Expression {
879 fn as_ref(&self) -> &Expression {
880 self
881 }
882}
883
884impl fmt::Display for Expression {
885 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
886 let mut syms = super::default_symbol_table();
887 let expr = self.convert(&mut syms);
888 let s = expr.print(&syms).unwrap();
889 write!(f, "{}", s)
890 }
891}
892
893impl From<biscuit_parser::builder::Expression> for Expression {
894 fn from(e: biscuit_parser::builder::Expression) -> Self {
895 Expression {
896 ops: e.ops.into_iter().map(|op| op.into()).collect(),
897 }
898 }
899}
900
901#[derive(Debug, Clone, PartialEq, Eq)]
903pub enum Op {
904 Value(Term),
905 Unary(Unary),
906 Binary(Binary),
907}
908
909impl Convert<datalog::Op> for Op {
910 fn convert(&self, symbols: &mut SymbolTable) -> datalog::Op {
911 match self {
912 Op::Value(t) => datalog::Op::Value(t.convert(symbols)),
913 Op::Unary(u) => datalog::Op::Unary(u.clone()),
914 Op::Binary(b) => datalog::Op::Binary(b.clone()),
915 }
916 }
917
918 fn convert_from(op: &datalog::Op, symbols: &SymbolTable) -> Result<Self, error::Format> {
919 Ok(match op {
920 datalog::Op::Value(t) => Op::Value(Term::convert_from(t, symbols)?),
921 datalog::Op::Unary(u) => Op::Unary(u.clone()),
922 datalog::Op::Binary(b) => Op::Binary(b.clone()),
923 })
924 }
925}
926
927impl From<biscuit_parser::builder::Op> for Op {
928 fn from(op: biscuit_parser::builder::Op) -> Self {
929 match op {
930 biscuit_parser::builder::Op::Value(t) => Op::Value(t.into()),
931 biscuit_parser::builder::Op::Unary(u) => Op::Unary(u.into()),
932 biscuit_parser::builder::Op::Binary(b) => Op::Binary(b.into()),
933 }
934 }
935}
936
937impl From<biscuit_parser::builder::Unary> for Unary {
938 fn from(unary: biscuit_parser::builder::Unary) -> Self {
939 match unary {
940 biscuit_parser::builder::Unary::Negate => Unary::Negate,
941 biscuit_parser::builder::Unary::Parens => Unary::Parens,
942 biscuit_parser::builder::Unary::Length => Unary::Length,
943 }
944 }
945}
946
947impl From<biscuit_parser::builder::Binary> for Binary {
948 fn from(binary: biscuit_parser::builder::Binary) -> Self {
949 match binary {
950 biscuit_parser::builder::Binary::LessThan => Binary::LessThan,
951 biscuit_parser::builder::Binary::GreaterThan => Binary::GreaterThan,
952 biscuit_parser::builder::Binary::LessOrEqual => Binary::LessOrEqual,
953 biscuit_parser::builder::Binary::GreaterOrEqual => Binary::GreaterOrEqual,
954 biscuit_parser::builder::Binary::Equal => Binary::Equal,
955 biscuit_parser::builder::Binary::Contains => Binary::Contains,
956 biscuit_parser::builder::Binary::Prefix => Binary::Prefix,
957 biscuit_parser::builder::Binary::Suffix => Binary::Suffix,
958 biscuit_parser::builder::Binary::Regex => Binary::Regex,
959 biscuit_parser::builder::Binary::Add => Binary::Add,
960 biscuit_parser::builder::Binary::Sub => Binary::Sub,
961 biscuit_parser::builder::Binary::Mul => Binary::Mul,
962 biscuit_parser::builder::Binary::Div => Binary::Div,
963 biscuit_parser::builder::Binary::And => Binary::And,
964 biscuit_parser::builder::Binary::Or => Binary::Or,
965 biscuit_parser::builder::Binary::Intersection => Binary::Intersection,
966 biscuit_parser::builder::Binary::Union => Binary::Union,
967 biscuit_parser::builder::Binary::BitwiseAnd => Binary::BitwiseAnd,
968 biscuit_parser::builder::Binary::BitwiseOr => Binary::BitwiseOr,
969 biscuit_parser::builder::Binary::BitwiseXor => Binary::BitwiseXor,
970 biscuit_parser::builder::Binary::NotEqual => Binary::NotEqual,
971 }
972 }
973}
974
975#[derive(Debug, Clone, PartialEq, Eq)]
977pub struct Rule {
978 pub head: Predicate,
979 pub body: Vec<Predicate>,
980 pub expressions: Vec<Expression>,
981 pub parameters: Option<HashMap<String, Option<Term>>>,
982 pub scopes: Vec<Scope>,
983 pub scope_parameters: Option<HashMap<String, Option<PublicKey>>>,
984}
985
986impl Rule {
987 pub fn new(
988 head: Predicate,
989 body: Vec<Predicate>,
990 expressions: Vec<Expression>,
991 scopes: Vec<Scope>,
992 ) -> Rule {
993 let mut parameters = HashMap::new();
994 let mut scope_parameters = HashMap::new();
995 for term in &head.terms {
996 if let Term::Parameter(name) = &term {
997 parameters.insert(name.to_string(), None);
998 }
999 }
1000
1001 for predicate in &body {
1002 for term in &predicate.terms {
1003 if let Term::Parameter(name) = &term {
1004 parameters.insert(name.to_string(), None);
1005 }
1006 }
1007 }
1008
1009 for expression in &expressions {
1010 for op in &expression.ops {
1011 if let Op::Value(Term::Parameter(name)) = &op {
1012 parameters.insert(name.to_string(), None);
1013 }
1014 }
1015 }
1016
1017 for scope in &scopes {
1018 if let Scope::Parameter(name) = &scope {
1019 scope_parameters.insert(name.to_string(), None);
1020 }
1021 }
1022
1023 Rule {
1024 head,
1025 body,
1026 expressions,
1027 parameters: Some(parameters),
1028 scopes,
1029 scope_parameters: Some(scope_parameters),
1030 }
1031 }
1032
1033 pub fn validate_parameters(&self) -> Result<(), error::Token> {
1034 let mut invalid_parameters = match &self.parameters {
1035 None => vec![],
1036 Some(parameters) => parameters
1037 .iter()
1038 .filter_map(
1039 |(name, opt_term)| {
1040 if opt_term.is_none() {
1041 Some(name)
1042 } else {
1043 None
1044 }
1045 },
1046 )
1047 .map(|name| name.to_string())
1048 .collect::<Vec<_>>(),
1049 };
1050 let mut invalid_scope_parameters = match &self.scope_parameters {
1051 None => vec![],
1052 Some(parameters) => parameters
1053 .iter()
1054 .filter_map(
1055 |(name, opt_key)| {
1056 if opt_key.is_none() {
1057 Some(name)
1058 } else {
1059 None
1060 }
1061 },
1062 )
1063 .map(|name| name.to_string())
1064 .collect::<Vec<_>>(),
1065 };
1066 let mut all_invalid_parameters = vec![];
1067 all_invalid_parameters.append(&mut invalid_parameters);
1068 all_invalid_parameters.append(&mut invalid_scope_parameters);
1069
1070 if all_invalid_parameters.is_empty() {
1071 Ok(())
1072 } else {
1073 Err(error::Token::Language(
1074 biscuit_parser::error::LanguageError::Parameters {
1075 missing_parameters: all_invalid_parameters,
1076 unused_parameters: vec![],
1077 },
1078 ))
1079 }
1080 }
1081
1082 pub fn validate_variables(&self) -> Result<(), String> {
1083 let mut head_variables: std::collections::HashSet<String> = self
1084 .head
1085 .terms
1086 .iter()
1087 .filter_map(|term| match term {
1088 Term::Variable(s) => Some(s.to_string()),
1089 _ => None,
1090 })
1091 .collect();
1092
1093 for predicate in self.body.iter() {
1094 for term in predicate.terms.iter() {
1095 if let Term::Variable(v) = term {
1096 head_variables.remove(v);
1097 if head_variables.is_empty() {
1098 return Ok(());
1099 }
1100 }
1101 }
1102 }
1103
1104 if head_variables.is_empty() {
1105 Ok(())
1106 } else {
1107 Err(format!(
1108 "rule head contains variables that are not used in predicates of the rule's body: {}",
1109 head_variables
1110 .iter()
1111 .map(|s| format!("${}", s))
1112 .collect::<Vec<_>>()
1113 .join(", ")
1114 ))
1115 }
1116 }
1117
1118 pub fn set<T: Into<Term>>(&mut self, name: &str, term: T) -> Result<(), error::Token> {
1120 if let Some(parameters) = self.parameters.as_mut() {
1121 match parameters.get_mut(name) {
1122 None => Err(error::Token::Language(
1123 biscuit_parser::error::LanguageError::Parameters {
1124 missing_parameters: vec![],
1125 unused_parameters: vec![name.to_string()],
1126 },
1127 )),
1128 Some(v) => {
1129 *v = Some(term.into());
1130 Ok(())
1131 }
1132 }
1133 } else {
1134 Err(error::Token::Language(
1135 biscuit_parser::error::LanguageError::Parameters {
1136 missing_parameters: vec![],
1137 unused_parameters: vec![name.to_string()],
1138 },
1139 ))
1140 }
1141 }
1142
1143 pub fn set_lenient<T: Into<Term>>(&mut self, name: &str, term: T) -> Result<(), error::Token> {
1146 if let Some(parameters) = self.parameters.as_mut() {
1147 match parameters.get_mut(name) {
1148 None => Ok(()),
1149 Some(v) => {
1150 *v = Some(term.into());
1151 Ok(())
1152 }
1153 }
1154 } else {
1155 Err(error::Token::Language(
1156 biscuit_parser::error::LanguageError::Parameters {
1157 missing_parameters: vec![],
1158 unused_parameters: vec![name.to_string()],
1159 },
1160 ))
1161 }
1162 }
1163
1164 pub fn set_scope(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> {
1166 if let Some(parameters) = self.scope_parameters.as_mut() {
1167 match parameters.get_mut(name) {
1168 None => Err(error::Token::Language(
1169 biscuit_parser::error::LanguageError::Parameters {
1170 missing_parameters: vec![],
1171 unused_parameters: vec![name.to_string()],
1172 },
1173 )),
1174 Some(v) => {
1175 *v = Some(pubkey);
1176 Ok(())
1177 }
1178 }
1179 } else {
1180 Err(error::Token::Language(
1181 biscuit_parser::error::LanguageError::Parameters {
1182 missing_parameters: vec![],
1183 unused_parameters: vec![name.to_string()],
1184 },
1185 ))
1186 }
1187 }
1188
1189 pub fn set_scope_lenient(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> {
1192 if let Some(parameters) = self.scope_parameters.as_mut() {
1193 match parameters.get_mut(name) {
1194 None => Ok(()),
1195 Some(v) => {
1196 *v = Some(pubkey);
1197 Ok(())
1198 }
1199 }
1200 } else {
1201 Err(error::Token::Language(
1202 biscuit_parser::error::LanguageError::Parameters {
1203 missing_parameters: vec![],
1204 unused_parameters: vec![name.to_string()],
1205 },
1206 ))
1207 }
1208 }
1209
1210 #[cfg(feature = "datalog-macro")]
1211 pub fn set_macro_param<T: ToAnyParam>(
1212 &mut self,
1213 name: &str,
1214 param: T,
1215 ) -> Result<(), error::Token> {
1216 match param.to_any_param() {
1217 AnyParam::Term(t) => self.set_lenient(name, t),
1218 AnyParam::PublicKey(pubkey) => self.set_scope_lenient(name, pubkey),
1219 }
1220 }
1221
1222 fn apply_parameters(&mut self) {
1223 if let Some(parameters) = self.parameters.clone() {
1224 self.head.terms = self
1225 .head
1226 .terms
1227 .drain(..)
1228 .map(|t| {
1229 if let Term::Parameter(name) = &t {
1230 if let Some(Some(term)) = parameters.get(name) {
1231 return term.clone();
1232 }
1233 }
1234 t
1235 })
1236 .collect();
1237
1238 for predicate in &mut self.body {
1239 predicate.terms = predicate
1240 .terms
1241 .drain(..)
1242 .map(|t| {
1243 if let Term::Parameter(name) = &t {
1244 if let Some(Some(term)) = parameters.get(name) {
1245 return term.clone();
1246 }
1247 }
1248 t
1249 })
1250 .collect();
1251 }
1252
1253 for expression in &mut self.expressions {
1254 expression.ops = expression
1255 .ops
1256 .drain(..)
1257 .map(|op| {
1258 if let Op::Value(Term::Parameter(name)) = &op {
1259 if let Some(Some(term)) = parameters.get(name) {
1260 return Op::Value(term.clone());
1261 }
1262 }
1263 op
1264 })
1265 .collect();
1266 }
1267 }
1268
1269 if let Some(parameters) = self.scope_parameters.clone() {
1270 self.scopes = self
1271 .scopes
1272 .drain(..)
1273 .map(|scope| {
1274 if let Scope::Parameter(name) = &scope {
1275 if let Some(Some(pubkey)) = parameters.get(name) {
1276 return Scope::PublicKey(*pubkey);
1277 }
1278 }
1279 scope
1280 })
1281 .collect();
1282 }
1283 }
1284}
1285
1286impl Convert<datalog::Rule> for Rule {
1287 fn convert(&self, symbols: &mut SymbolTable) -> datalog::Rule {
1288 let mut r = self.clone();
1289 r.apply_parameters();
1290
1291 let head = r.head.convert(symbols);
1292 let mut body = vec![];
1293 let mut expressions = vec![];
1294 let mut scopes = vec![];
1295
1296 for p in r.body.iter() {
1297 body.push(p.convert(symbols));
1298 }
1299
1300 for c in r.expressions.iter() {
1301 expressions.push(c.convert(symbols));
1302 }
1303
1304 for scope in r.scopes.iter() {
1305 scopes.push(match scope {
1306 Scope::Authority => crate::token::Scope::Authority,
1307 Scope::Previous => crate::token::Scope::Previous,
1308 Scope::PublicKey(key) => {
1309 crate::token::Scope::PublicKey(symbols.public_keys.insert(key))
1310 }
1311 Scope::Parameter(s) => panic!("Remaining parameter {}", &s),
1314 })
1315 }
1316 datalog::Rule {
1317 head,
1318 body,
1319 expressions,
1320 scopes,
1321 }
1322 }
1323
1324 fn convert_from(r: &datalog::Rule, symbols: &SymbolTable) -> Result<Self, error::Format> {
1325 Ok(Rule {
1326 head: Predicate::convert_from(&r.head, symbols)?,
1327 body: r
1328 .body
1329 .iter()
1330 .map(|p| Predicate::convert_from(p, symbols))
1331 .collect::<Result<Vec<Predicate>, error::Format>>()?,
1332 expressions: r
1333 .expressions
1334 .iter()
1335 .map(|c| Expression::convert_from(c, symbols))
1336 .collect::<Result<Vec<_>, error::Format>>()?,
1337 parameters: None,
1338 scopes: r
1339 .scopes
1340 .iter()
1341 .map(|scope| Scope::convert_from(scope, symbols))
1342 .collect::<Result<Vec<Scope>, error::Format>>()?,
1343 scope_parameters: None,
1344 })
1345 }
1346}
1347
1348fn display_rule_body(r: &Rule, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1349 let mut rule = r.clone();
1350 rule.apply_parameters();
1351 if !rule.body.is_empty() {
1352 write!(f, "{}", rule.body[0])?;
1353
1354 if rule.body.len() > 1 {
1355 for i in 1..rule.body.len() {
1356 write!(f, ", {}", rule.body[i])?;
1357 }
1358 }
1359 }
1360
1361 if !rule.expressions.is_empty() {
1362 if !rule.body.is_empty() {
1363 write!(f, ", ")?;
1364 }
1365
1366 write!(f, "{}", rule.expressions[0])?;
1367
1368 if rule.expressions.len() > 1 {
1369 for i in 1..rule.expressions.len() {
1370 write!(f, ", {}", rule.expressions[i])?;
1371 }
1372 }
1373 }
1374
1375 if !rule.scopes.is_empty() {
1376 write!(f, " trusting {}", rule.scopes[0])?;
1377 if rule.scopes.len() > 1 {
1378 for i in 1..rule.scopes.len() {
1379 write!(f, ", {}", rule.scopes[i])?;
1380 }
1381 }
1382 }
1383
1384 Ok(())
1385}
1386
1387impl fmt::Display for Rule {
1388 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1389 let mut r = self.clone();
1390 r.apply_parameters();
1391
1392 write!(f, "{} <- ", r.head)?;
1393
1394 display_rule_body(&r, f)
1395 }
1396}
1397
1398impl From<biscuit_parser::builder::Rule> for Rule {
1399 fn from(r: biscuit_parser::builder::Rule) -> Self {
1400 Rule {
1401 head: r.head.into(),
1402 body: r.body.into_iter().map(|p| p.into()).collect(),
1403 expressions: r.expressions.into_iter().map(|e| e.into()).collect(),
1404 parameters: r.parameters.map(|h| {
1405 h.into_iter()
1406 .map(|(k, v)| (k, v.map(|term| term.into())))
1407 .collect()
1408 }),
1409 scopes: r.scopes.into_iter().map(|s| s.into()).collect(),
1410 scope_parameters: r.scope_parameters.map(|h| {
1411 h.into_iter()
1412 .map(|(k, v)| {
1413 (
1414 k,
1415 v.map(|bytes| {
1416 PublicKey::from_bytes(&bytes).expect("invalid public key")
1417 }),
1418 )
1419 })
1420 .collect()
1421 }),
1422 }
1423 }
1424}
1425
1426#[derive(Debug, Clone, PartialEq, Eq)]
1428pub struct Check {
1429 pub queries: Vec<Rule>,
1430 pub kind: CheckKind,
1431}
1432
1433#[derive(Debug, Clone, PartialEq, Eq)]
1435pub enum CheckKind {
1436 One,
1437 All,
1438}
1439
1440impl Check {
1441 pub fn set<T: Into<Term>>(&mut self, name: &str, term: T) -> Result<(), error::Token> {
1443 let term = term.into();
1444 self.set_inner(name, term)
1445 }
1446
1447 fn set_inner(&mut self, name: &str, term: Term) -> Result<(), error::Token> {
1448 let mut found = false;
1449 for query in &mut self.queries {
1450 if query.set(name, term.clone()).is_ok() {
1451 found = true;
1452 }
1453 }
1454
1455 if found {
1456 Ok(())
1457 } else {
1458 Err(error::Token::Language(
1459 biscuit_parser::error::LanguageError::Parameters {
1460 missing_parameters: vec![],
1461 unused_parameters: vec![name.to_string()],
1462 },
1463 ))
1464 }
1465 }
1466
1467 pub fn set_scope(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> {
1469 let mut found = false;
1470 for query in &mut self.queries {
1471 if query.set_scope(name, pubkey).is_ok() {
1472 found = true;
1473 }
1474 }
1475
1476 if found {
1477 Ok(())
1478 } else {
1479 Err(error::Token::Language(
1480 biscuit_parser::error::LanguageError::Parameters {
1481 missing_parameters: vec![],
1482 unused_parameters: vec![name.to_string()],
1483 },
1484 ))
1485 }
1486 }
1487
1488 pub fn set_lenient<T: Into<Term>>(&mut self, name: &str, term: T) -> Result<(), error::Token> {
1491 let term = term.into();
1492 for query in &mut self.queries {
1493 query.set_lenient(name, term.clone())?;
1494 }
1495 Ok(())
1496 }
1497
1498 pub fn set_scope_lenient(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> {
1501 for query in &mut self.queries {
1502 query.set_scope_lenient(name, pubkey)?;
1503 }
1504 Ok(())
1505 }
1506
1507 #[cfg(feature = "datalog-macro")]
1508 pub fn set_macro_param<T: ToAnyParam>(
1509 &mut self,
1510 name: &str,
1511 param: T,
1512 ) -> Result<(), error::Token> {
1513 match param.to_any_param() {
1514 AnyParam::Term(t) => self.set_lenient(name, t),
1515 AnyParam::PublicKey(p) => self.set_scope_lenient(name, p),
1516 }
1517 }
1518
1519 pub fn validate_parameters(&self) -> Result<(), error::Token> {
1520 for rule in &self.queries {
1521 rule.validate_parameters()?;
1522 }
1523
1524 Ok(())
1525 }
1526
1527 fn apply_parameters(&mut self) {
1528 for rule in self.queries.iter_mut() {
1529 rule.apply_parameters();
1530 }
1531 }
1532}
1533
1534impl Convert<datalog::Check> for Check {
1535 fn convert(&self, symbols: &mut SymbolTable) -> datalog::Check {
1536 let mut queries = vec![];
1537 for q in self.queries.iter() {
1538 queries.push(q.convert(symbols));
1539 }
1540
1541 datalog::Check {
1542 queries,
1543 kind: self.kind.clone(),
1544 }
1545 }
1546
1547 fn convert_from(r: &datalog::Check, symbols: &SymbolTable) -> Result<Self, error::Format> {
1548 let mut queries = vec![];
1549 for q in r.queries.iter() {
1550 queries.push(Rule::convert_from(q, symbols)?);
1551 }
1552
1553 Ok(Check {
1554 queries,
1555 kind: r.kind.clone(),
1556 })
1557 }
1558}
1559
1560impl TryFrom<Rule> for Check {
1561 type Error = error::Token;
1562
1563 fn try_from(value: Rule) -> Result<Self, Self::Error> {
1564 Ok(Check {
1565 queries: vec![value],
1566 kind: CheckKind::One,
1567 })
1568 }
1569}
1570
1571impl TryFrom<&[Rule]> for Check {
1572 type Error = error::Token;
1573
1574 fn try_from(values: &[Rule]) -> Result<Self, Self::Error> {
1575 Ok(Check {
1576 queries: values.to_vec(),
1577 kind: CheckKind::One,
1578 })
1579 }
1580}
1581
1582impl fmt::Display for Check {
1583 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1584 match self.kind {
1585 CheckKind::One => write!(f, "check if ")?,
1586 CheckKind::All => write!(f, "check all ")?,
1587 };
1588
1589 if !self.queries.is_empty() {
1590 let mut q0 = self.queries[0].clone();
1591 q0.apply_parameters();
1592 display_rule_body(&q0, f)?;
1593
1594 if self.queries.len() > 1 {
1595 for i in 1..self.queries.len() {
1596 write!(f, " or ")?;
1597 let mut qn = self.queries[i].clone();
1598 qn.apply_parameters();
1599 display_rule_body(&qn, f)?;
1600 }
1601 }
1602 }
1603
1604 Ok(())
1605 }
1606}
1607
1608impl From<biscuit_parser::builder::Check> for Check {
1609 fn from(c: biscuit_parser::builder::Check) -> Self {
1610 Check {
1611 queries: c.queries.into_iter().map(|q| q.into()).collect(),
1612 kind: match c.kind {
1613 biscuit_parser::builder::CheckKind::One => CheckKind::One,
1614 biscuit_parser::builder::CheckKind::All => CheckKind::All,
1615 },
1616 }
1617 }
1618}
1619
1620#[derive(Debug, Clone, PartialEq, Eq)]
1621pub enum PolicyKind {
1622 Allow,
1623 Deny,
1624}
1625
1626#[derive(Debug, Clone, PartialEq, Eq)]
1628pub struct Policy {
1629 pub queries: Vec<Rule>,
1630 pub kind: PolicyKind,
1631}
1632
1633impl Policy {
1634 pub fn set<T: Into<Term>>(&mut self, name: &str, term: T) -> Result<(), error::Token> {
1636 let term = term.into();
1637 self.set_inner(name, term)
1638 }
1639
1640 pub fn set_inner(&mut self, name: &str, term: Term) -> Result<(), error::Token> {
1641 let mut found = false;
1642 for query in &mut self.queries {
1643 if query.set(name, term.clone()).is_ok() {
1644 found = true;
1645 }
1646 }
1647
1648 if found {
1649 Ok(())
1650 } else {
1651 Err(error::Token::Language(
1652 biscuit_parser::error::LanguageError::Parameters {
1653 missing_parameters: vec![],
1654 unused_parameters: vec![name.to_string()],
1655 },
1656 ))
1657 }
1658 }
1659
1660 pub fn set_scope(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> {
1662 let mut found = false;
1663 for query in &mut self.queries {
1664 if query.set_scope(name, pubkey).is_ok() {
1665 found = true;
1666 }
1667 }
1668
1669 if found {
1670 Ok(())
1671 } else {
1672 Err(error::Token::Language(
1673 biscuit_parser::error::LanguageError::Parameters {
1674 missing_parameters: vec![],
1675 unused_parameters: vec![name.to_string()],
1676 },
1677 ))
1678 }
1679 }
1680
1681 pub fn set_lenient<T: Into<Term>>(&mut self, name: &str, term: T) -> Result<(), error::Token> {
1683 let term = term.into();
1684 for query in &mut self.queries {
1685 query.set_lenient(name, term.clone())?;
1686 }
1687 Ok(())
1688 }
1689
1690 pub fn set_scope_lenient(&mut self, name: &str, pubkey: PublicKey) -> Result<(), error::Token> {
1692 for query in &mut self.queries {
1693 query.set_scope_lenient(name, pubkey)?;
1694 }
1695 Ok(())
1696 }
1697
1698 #[cfg(feature = "datalog-macro")]
1699 pub fn set_macro_param<T: ToAnyParam>(
1700 &mut self,
1701 name: &str,
1702 param: T,
1703 ) -> Result<(), error::Token> {
1704 match param.to_any_param() {
1705 AnyParam::Term(t) => self.set_lenient(name, t),
1706 AnyParam::PublicKey(p) => self.set_scope_lenient(name, p),
1707 }
1708 }
1709
1710 pub fn validate_parameters(&self) -> Result<(), error::Token> {
1711 for query in &self.queries {
1712 query.validate_parameters()?;
1713 }
1714
1715 Ok(())
1716 }
1717}
1718
1719impl fmt::Display for Policy {
1720 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1721 if !self.queries.is_empty() {
1722 match self.kind {
1723 PolicyKind::Allow => write!(f, "allow if ")?,
1724 PolicyKind::Deny => write!(f, "deny if ")?,
1725 }
1726
1727 if !self.queries.is_empty() {
1728 display_rule_body(&self.queries[0], f)?;
1729
1730 if self.queries.len() > 1 {
1731 for i in 1..self.queries.len() {
1732 write!(f, " or ")?;
1733 display_rule_body(&self.queries[i], f)?;
1734 }
1735 }
1736 }
1737 } else {
1738 match self.kind {
1739 PolicyKind::Allow => write!(f, "allow")?,
1740 PolicyKind::Deny => write!(f, "deny")?,
1741 }
1742 }
1743
1744 Ok(())
1745 }
1746}
1747
1748impl From<biscuit_parser::builder::Policy> for Policy {
1749 fn from(p: biscuit_parser::builder::Policy) -> Self {
1750 Policy {
1751 queries: p.queries.into_iter().map(|q| q.into()).collect(),
1752 kind: match p.kind {
1753 biscuit_parser::builder::PolicyKind::Allow => PolicyKind::Allow,
1754 biscuit_parser::builder::PolicyKind::Deny => PolicyKind::Deny,
1755 },
1756 }
1757 }
1758}
1759
1760pub fn fact<I: AsRef<Term>>(name: &str, terms: &[I]) -> Fact {
1762 let pred = pred(name, terms);
1763 Fact::new(pred.name, pred.terms)
1764}
1765
1766pub fn pred<I: AsRef<Term>>(name: &str, terms: &[I]) -> Predicate {
1768 Predicate {
1769 name: name.to_string(),
1770 terms: terms.iter().map(|term| term.as_ref().clone()).collect(),
1771 }
1772}
1773
1774pub fn rule<T: AsRef<Term>, P: AsRef<Predicate>>(
1776 head_name: &str,
1777 head_terms: &[T],
1778 predicates: &[P],
1779) -> Rule {
1780 Rule::new(
1781 pred(head_name, head_terms),
1782 predicates.iter().map(|p| p.as_ref().clone()).collect(),
1783 Vec::new(),
1784 vec![],
1785 )
1786}
1787
1788pub fn constrained_rule<T: AsRef<Term>, P: AsRef<Predicate>, E: AsRef<Expression>>(
1790 head_name: &str,
1791 head_terms: &[T],
1792 predicates: &[P],
1793 expressions: &[E],
1794) -> Rule {
1795 Rule::new(
1796 pred(head_name, head_terms),
1797 predicates.iter().map(|p| p.as_ref().clone()).collect(),
1798 expressions.iter().map(|c| c.as_ref().clone()).collect(),
1799 vec![],
1800 )
1801}
1802
1803pub fn check<P: AsRef<Predicate>>(predicates: &[P], kind: CheckKind) -> Check {
1805 let empty_terms: &[Term] = &[];
1806 Check {
1807 queries: vec![Rule::new(
1808 pred("query", empty_terms),
1809 predicates.iter().map(|p| p.as_ref().clone()).collect(),
1810 vec![],
1811 vec![],
1812 )],
1813 kind,
1814 }
1815}
1816
1817pub fn int(i: i64) -> Term {
1819 Term::Integer(i)
1820}
1821
1822pub fn string(s: &str) -> Term {
1824 Term::Str(s.to_string())
1825}
1826
1827pub fn date(t: &SystemTime) -> Term {
1831 let dur = t.duration_since(UNIX_EPOCH).unwrap();
1832 Term::Date(dur.as_secs())
1833}
1834
1835pub fn var(s: &str) -> Term {
1837 Term::Variable(s.to_string())
1838}
1839
1840pub fn variable(s: &str) -> Term {
1842 Term::Variable(s.to_string())
1843}
1844
1845pub fn bytes(s: &[u8]) -> Term {
1847 Term::Bytes(s.to_vec())
1848}
1849
1850pub fn boolean(b: bool) -> Term {
1852 Term::Bool(b)
1853}
1854
1855pub fn set(s: BTreeSet<Term>) -> Term {
1857 Term::Set(s)
1858}
1859
1860pub fn parameter(p: &str) -> Term {
1862 Term::Parameter(p.to_string())
1863}
1864
1865#[cfg(feature = "datalog-macro")]
1866pub enum AnyParam {
1867 Term(Term),
1868 PublicKey(PublicKey),
1869}
1870
1871#[cfg(feature = "datalog-macro")]
1872pub trait ToAnyParam {
1873 fn to_any_param(&self) -> AnyParam;
1874}
1875
1876impl From<i64> for Term {
1877 fn from(i: i64) -> Self {
1878 Term::Integer(i)
1879 }
1880}
1881
1882#[cfg(feature = "datalog-macro")]
1883impl ToAnyParam for i64 {
1884 fn to_any_param(&self) -> AnyParam {
1885 AnyParam::Term((*self).into())
1886 }
1887}
1888
1889impl TryFrom<Term> for i64 {
1890 type Error = error::Token;
1891 fn try_from(value: Term) -> Result<Self, Self::Error> {
1892 match value {
1893 Term::Integer(i) => Ok(i),
1894 _ => Err(error::Token::ConversionError(format!(
1895 "expected integer, got {:?}",
1896 value
1897 ))),
1898 }
1899 }
1900}
1901
1902impl From<bool> for Term {
1903 fn from(b: bool) -> Self {
1904 Term::Bool(b)
1905 }
1906}
1907
1908#[cfg(feature = "datalog-macro")]
1909impl ToAnyParam for bool {
1910 fn to_any_param(&self) -> AnyParam {
1911 AnyParam::Term((*self).into())
1912 }
1913}
1914
1915impl TryFrom<Term> for bool {
1916 type Error = error::Token;
1917 fn try_from(value: Term) -> Result<Self, Self::Error> {
1918 match value {
1919 Term::Bool(b) => Ok(b),
1920 _ => Err(error::Token::ConversionError(format!(
1921 "expected boolean, got {:?}",
1922 value
1923 ))),
1924 }
1925 }
1926}
1927
1928impl From<String> for Term {
1929 fn from(s: String) -> Self {
1930 Term::Str(s)
1931 }
1932}
1933
1934#[cfg(feature = "datalog-macro")]
1935impl ToAnyParam for String {
1936 fn to_any_param(&self) -> AnyParam {
1937 AnyParam::Term((self.clone()).into())
1938 }
1939}
1940
1941impl From<&str> for Term {
1942 fn from(s: &str) -> Self {
1943 Term::Str(s.into())
1944 }
1945}
1946
1947#[cfg(feature = "datalog-macro")]
1948impl ToAnyParam for &str {
1949 fn to_any_param(&self) -> AnyParam {
1950 AnyParam::Term(self.to_string().into())
1951 }
1952}
1953
1954impl TryFrom<Term> for String {
1955 type Error = error::Token;
1956 fn try_from(value: Term) -> Result<Self, Self::Error> {
1957 match value {
1958 Term::Str(s) => Ok(s),
1959 _ => Err(error::Token::ConversionError(format!(
1960 "expected string or symbol, got {:?}",
1961 value
1962 ))),
1963 }
1964 }
1965}
1966
1967impl From<Vec<u8>> for Term {
1968 fn from(v: Vec<u8>) -> Self {
1969 Term::Bytes(v)
1970 }
1971}
1972
1973#[cfg(feature = "datalog-macro")]
1974impl ToAnyParam for Vec<u8> {
1975 fn to_any_param(&self) -> AnyParam {
1976 AnyParam::Term((self.clone()).into())
1977 }
1978}
1979
1980impl TryFrom<Term> for Vec<u8> {
1981 type Error = error::Token;
1982 fn try_from(value: Term) -> Result<Self, Self::Error> {
1983 match value {
1984 Term::Bytes(b) => Ok(b),
1985 _ => Err(error::Token::ConversionError(format!(
1986 "expected byte array, got {:?}",
1987 value
1988 ))),
1989 }
1990 }
1991}
1992
1993impl From<&[u8]> for Term {
1994 fn from(v: &[u8]) -> Self {
1995 Term::Bytes(v.into())
1996 }
1997}
1998
1999#[cfg(feature = "datalog-macro")]
2000impl ToAnyParam for [u8] {
2001 fn to_any_param(&self) -> AnyParam {
2002 AnyParam::Term(self.into())
2003 }
2004}
2005
2006#[cfg(feature = "uuid")]
2007impl ToAnyParam for uuid::Uuid {
2008 fn to_any_param(&self) -> AnyParam {
2009 AnyParam::Term(Term::Bytes(self.as_bytes().to_vec()))
2010 }
2011}
2012
2013impl From<SystemTime> for Term {
2014 fn from(t: SystemTime) -> Self {
2015 let dur = t.duration_since(UNIX_EPOCH).unwrap();
2016 Term::Date(dur.as_secs())
2017 }
2018}
2019
2020#[cfg(feature = "datalog-macro")]
2021impl ToAnyParam for SystemTime {
2022 fn to_any_param(&self) -> AnyParam {
2023 AnyParam::Term((*self).into())
2024 }
2025}
2026
2027impl TryFrom<Term> for SystemTime {
2028 type Error = error::Token;
2029 fn try_from(value: Term) -> Result<Self, Self::Error> {
2030 match value {
2031 Term::Date(d) => Ok(UNIX_EPOCH + Duration::from_secs(d)),
2032 _ => Err(error::Token::ConversionError(format!(
2033 "expected date, got {:?}",
2034 value
2035 ))),
2036 }
2037 }
2038}
2039
2040impl From<BTreeSet<Term>> for Term {
2041 fn from(value: BTreeSet<Term>) -> Term {
2042 set(value)
2043 }
2044}
2045
2046#[cfg(feature = "datalog-macro")]
2047impl ToAnyParam for BTreeSet<Term> {
2048 fn to_any_param(&self) -> AnyParam {
2049 AnyParam::Term((self.clone()).into())
2050 }
2051}
2052
2053impl<T: Ord + TryFrom<Term, Error = error::Token>> TryFrom<Term> for BTreeSet<T> {
2054 type Error = error::Token;
2055 fn try_from(value: Term) -> Result<Self, Self::Error> {
2056 match value {
2057 Term::Set(d) => d.iter().cloned().map(TryFrom::try_from).collect(),
2058 _ => Err(error::Token::ConversionError(format!(
2059 "expected set, got {:?}",
2060 value
2061 ))),
2062 }
2063 }
2064}
2065
2066macro_rules! tuple_try_from(
2067 ($ty1:ident, $ty2:ident, $($ty:ident),*) => (
2068 tuple_try_from!(__impl $ty1, $ty2; $($ty),*);
2069 );
2070 (__impl $($ty: ident),+; $ty1:ident, $($ty2:ident),*) => (
2071 tuple_try_from_impl!($($ty),+);
2072 tuple_try_from!(__impl $($ty),+ , $ty1; $($ty2),*);
2073 );
2074 (__impl $($ty: ident),+; $ty1:ident) => (
2075 tuple_try_from_impl!($($ty),+);
2076 tuple_try_from_impl!($($ty),+, $ty1);
2077 );
2078 );
2079
2080impl<A: TryFrom<Term, Error = error::Token>> TryFrom<Fact> for (A,) {
2081 type Error = error::Token;
2082 fn try_from(fact: Fact) -> Result<Self, Self::Error> {
2083 let mut terms = fact.predicate.terms;
2084 let mut it = terms.drain(..);
2085
2086 Ok((it
2087 .next()
2088 .ok_or_else(|| error::Token::ConversionError("not enough terms in fact".to_string()))
2089 .and_then(A::try_from)?,))
2090 }
2091}
2092
2093macro_rules! tuple_try_from_impl(
2094 ($($ty: ident),+) => (
2095 impl<$($ty: TryFrom<Term, Error = error::Token>),+> TryFrom<Fact> for ($($ty),+) {
2096 type Error = error::Token;
2097 fn try_from(fact: Fact) -> Result<Self, Self::Error> {
2098 let mut terms = fact.predicate.terms;
2099 let mut it = terms.drain(..);
2100
2101 Ok((
2102 $(
2103 it.next().ok_or(error::Token::ConversionError("not enough terms in fact".to_string())).and_then($ty::try_from)?
2104 ),+
2105 ))
2106
2107 }
2108 }
2109 );
2110 );
2111
2112tuple_try_from!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U);
2113
2114#[cfg(feature = "datalog-macro")]
2115impl ToAnyParam for PublicKey {
2116 fn to_any_param(&self) -> AnyParam {
2117 AnyParam::PublicKey(*self)
2118 }
2119}
2120
2121impl TryFrom<&str> for Fact {
2122 type Error = error::Token;
2123
2124 fn try_from(value: &str) -> Result<Self, Self::Error> {
2125 Ok(biscuit_parser::parser::fact(value)
2126 .finish()
2127 .map(|(_, o)| o.into())
2128 .map_err(biscuit_parser::error::LanguageError::from)?)
2129 }
2130}
2131
2132impl TryFrom<&str> for Rule {
2133 type Error = error::Token;
2134
2135 fn try_from(value: &str) -> Result<Self, Self::Error> {
2136 Ok(biscuit_parser::parser::rule(value)
2137 .finish()
2138 .map(|(_, o)| o.into())
2139 .map_err(biscuit_parser::error::LanguageError::from)?)
2140 }
2141}
2142
2143impl FromStr for Fact {
2144 type Err = error::Token;
2145
2146 fn from_str(s: &str) -> Result<Self, Self::Err> {
2147 Ok(biscuit_parser::parser::fact(s)
2148 .finish()
2149 .map(|(_, o)| o.into())
2150 .map_err(biscuit_parser::error::LanguageError::from)?)
2151 }
2152}
2153
2154impl FromStr for Rule {
2155 type Err = error::Token;
2156
2157 fn from_str(s: &str) -> Result<Self, Self::Err> {
2158 Ok(biscuit_parser::parser::rule(s)
2159 .finish()
2160 .map(|(_, o)| o.into())
2161 .map_err(biscuit_parser::error::LanguageError::from)?)
2162 }
2163}
2164
2165impl TryFrom<&str> for Check {
2166 type Error = error::Token;
2167
2168 fn try_from(value: &str) -> Result<Self, Self::Error> {
2169 Ok(biscuit_parser::parser::check(value)
2170 .finish()
2171 .map(|(_, o)| o.into())
2172 .map_err(biscuit_parser::error::LanguageError::from)?)
2173 }
2174}
2175
2176impl FromStr for Check {
2177 type Err = error::Token;
2178
2179 fn from_str(s: &str) -> Result<Self, Self::Err> {
2180 Ok(biscuit_parser::parser::check(s)
2181 .finish()
2182 .map(|(_, o)| o.into())
2183 .map_err(biscuit_parser::error::LanguageError::from)?)
2184 }
2185}
2186
2187impl TryFrom<&str> for Policy {
2188 type Error = error::Token;
2189
2190 fn try_from(value: &str) -> Result<Self, Self::Error> {
2191 Ok(biscuit_parser::parser::policy(value)
2192 .finish()
2193 .map(|(_, o)| o.into())
2194 .map_err(biscuit_parser::error::LanguageError::from)?)
2195 }
2196}
2197
2198impl FromStr for Policy {
2199 type Err = error::Token;
2200
2201 fn from_str(s: &str) -> Result<Self, Self::Err> {
2202 Ok(biscuit_parser::parser::policy(s)
2203 .finish()
2204 .map(|(_, o)| o.into())
2205 .map_err(biscuit_parser::error::LanguageError::from)?)
2206 }
2207}
2208
2209impl BuilderExt for BlockBuilder {
2210 fn add_resource(&mut self, name: &str) {
2211 self.facts.push(fact("resource", &[string(name)]));
2212 }
2213 fn check_resource(&mut self, name: &str) {
2214 self.checks.push(Check {
2215 queries: vec![rule(
2216 "resource_check",
2217 &[string("resource_check")],
2218 &[pred("resource", &[string(name)])],
2219 )],
2220 kind: CheckKind::One,
2221 });
2222 }
2223 fn add_operation(&mut self, name: &str) {
2224 self.facts.push(fact("operation", &[string(name)]));
2225 }
2226 fn check_operation(&mut self, name: &str) {
2227 self.checks.push(Check {
2228 queries: vec![rule(
2229 "operation_check",
2230 &[string("operation_check")],
2231 &[pred("operation", &[string(name)])],
2232 )],
2233 kind: CheckKind::One,
2234 });
2235 }
2236 fn check_resource_prefix(&mut self, prefix: &str) {
2237 let check = constrained_rule(
2238 "prefix",
2239 &[var("resource")],
2240 &[pred("resource", &[var("resource")])],
2241 &[Expression {
2242 ops: vec![
2243 Op::Value(var("resource")),
2244 Op::Value(string(prefix)),
2245 Op::Binary(Binary::Prefix),
2246 ],
2247 }],
2248 );
2249
2250 self.checks.push(Check {
2251 queries: vec![check],
2252 kind: CheckKind::One,
2253 });
2254 }
2255
2256 fn check_resource_suffix(&mut self, suffix: &str) {
2257 let check = constrained_rule(
2258 "suffix",
2259 &[var("resource")],
2260 &[pred("resource", &[var("resource")])],
2261 &[Expression {
2262 ops: vec![
2263 Op::Value(var("resource")),
2264 Op::Value(string(suffix)),
2265 Op::Binary(Binary::Suffix),
2266 ],
2267 }],
2268 );
2269
2270 self.checks.push(Check {
2271 queries: vec![check],
2272 kind: CheckKind::One,
2273 });
2274 }
2275
2276 fn check_expiration_date(&mut self, exp: SystemTime) {
2277 let empty: Vec<Term> = Vec::new();
2278 let check = constrained_rule(
2279 "query",
2280 &empty,
2281 &[pred("time", &[var("time")])],
2282 &[Expression {
2283 ops: vec![
2284 Op::Value(var("time")),
2285 Op::Value(date(&exp)),
2286 Op::Binary(Binary::LessOrEqual),
2287 ],
2288 }],
2289 );
2290
2291 self.checks.push(Check {
2292 queries: vec![check],
2293 kind: CheckKind::One,
2294 });
2295 }
2296}
2297
2298impl fmt::Display for BiscuitBuilder {
2299 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2300 match self.root_key_id {
2301 None => writeln!(f, "// no root key id set")?,
2302 Some(id) => writeln!(f, "// root key id: {}", id)?,
2303 }
2304 self.inner.fmt(f)
2305 }
2306}
2307
2308impl BuilderExt for BiscuitBuilder {
2309 fn add_resource(&mut self, name: &str) {
2310 self.inner.add_resource(name);
2311 }
2312 fn check_resource(&mut self, name: &str) {
2313 self.inner.check_resource(name);
2314 }
2315 fn check_resource_prefix(&mut self, prefix: &str) {
2316 self.inner.check_resource_prefix(prefix);
2317 }
2318 fn check_resource_suffix(&mut self, suffix: &str) {
2319 self.inner.check_resource_suffix(suffix);
2320 }
2321 fn add_operation(&mut self, name: &str) {
2322 self.inner.add_operation(name);
2323 }
2324 fn check_operation(&mut self, name: &str) {
2325 self.inner.check_operation(name);
2326 }
2327 fn check_expiration_date(&mut self, date: SystemTime) {
2328 self.inner.check_expiration_date(date);
2329 }
2330}
2331
2332#[cfg(test)]
2333mod tests {
2334 use super::*;
2335
2336 #[test]
2337 fn set_rule_parameters() {
2338 let mut rule = Rule::try_from(
2339 "fact($var1, {p2}, {p5}) <- f1($var1, $var3), f2({p2}, $var3, {p4}), $var3.starts_with({p2})",
2340 )
2341 .unwrap();
2342 rule.set("p2", "hello").unwrap();
2343 rule.set("p4", 0i64).unwrap();
2344 rule.set("p4", 1i64).unwrap();
2345
2346 let mut term_set = BTreeSet::new();
2347 term_set.insert(int(0i64));
2348 rule.set("p5", term_set).unwrap();
2349
2350 let s = rule.to_string();
2351 assert_eq!(s, "fact($var1, \"hello\", [0]) <- f1($var1, $var3), f2(\"hello\", $var3, 1), $var3.starts_with(\"hello\")");
2352 }
2353
2354 #[test]
2355 fn set_rule_scope_parameters() {
2356 let pubkey = PublicKey::from_bytes(
2357 &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db")
2358 .unwrap(),
2359 )
2360 .unwrap();
2361 let mut rule = Rule::try_from(
2362 "fact($var1, {p2}) <- f1($var1, $var3), f2({p2}, $var3, {p4}), $var3.starts_with({p2}) trusting {pk}",
2363 )
2364 .unwrap();
2365 rule.set("p2", "hello").unwrap();
2366 rule.set("p4", 0i64).unwrap();
2367 rule.set("p4", 1i64).unwrap();
2368 rule.set_scope("pk", pubkey).unwrap();
2369
2370 let s = rule.to_string();
2371 assert_eq!(s, "fact($var1, \"hello\") <- f1($var1, $var3), f2(\"hello\", $var3, 1), $var3.starts_with(\"hello\") trusting ed25519/6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db");
2372 }
2373
2374 #[test]
2375 fn set_code_parameters() {
2376 let mut builder = BlockBuilder::new();
2377 let mut params = HashMap::new();
2378 params.insert("p1".to_string(), "hello".into());
2379 params.insert("p2".to_string(), 1i64.into());
2380 params.insert("p3".to_string(), true.into());
2381 params.insert("p4".to_string(), "this will be ignored".into());
2382 let pubkey = PublicKey::from_bytes(
2383 &hex::decode("6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db")
2384 .unwrap(),
2385 )
2386 .unwrap();
2387 let mut scope_params = HashMap::new();
2388 scope_params.insert("pk".to_string(), pubkey);
2389 builder
2390 .add_code_with_params(
2391 r#"fact({p1}, "value");
2392 rule($head_var) <- f1($head_var), {p2} > 0 trusting {pk};
2393 check if {p3} trusting {pk};
2394 "#,
2395 params,
2396 scope_params,
2397 )
2398 .unwrap();
2399 assert_eq!(
2400 format!("{}", &builder),
2401 r#"fact("hello", "value");
2402rule($head_var) <- f1($head_var), 1 > 0 trusting ed25519/6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db;
2403check if true trusting ed25519/6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db;
2404"#
2405 );
2406 }
2407
2408 #[test]
2409 fn forbid_unbound_parameters() {
2410 let mut builder = BlockBuilder::new();
2411
2412 let mut fact = Fact::try_from("fact({p1}, {p4})").unwrap();
2413 fact.set("p1", "hello").unwrap();
2414 let res = builder.add_fact(fact);
2415 assert_eq!(
2416 res,
2417 Err(error::Token::Language(
2418 biscuit_parser::error::LanguageError::Parameters {
2419 missing_parameters: vec!["p4".to_string()],
2420 unused_parameters: vec![],
2421 }
2422 ))
2423 );
2424 let mut rule = Rule::try_from(
2425 "fact($var1, {p2}) <- f1($var1, $var3), f2({p2}, $var3, {p4}), $var3.starts_with({p2})",
2426 )
2427 .unwrap();
2428 rule.set("p2", "hello").unwrap();
2429 let res = builder.add_rule(rule);
2430 assert_eq!(
2431 res,
2432 Err(error::Token::Language(
2433 biscuit_parser::error::LanguageError::Parameters {
2434 missing_parameters: vec!["p4".to_string()],
2435 unused_parameters: vec![],
2436 }
2437 ))
2438 );
2439 let mut check = Check::try_from("check if {p4}, {p3}").unwrap();
2440 check.set("p3", true).unwrap();
2441 let res = builder.add_check(check);
2442 assert_eq!(
2443 res,
2444 Err(error::Token::Language(
2445 biscuit_parser::error::LanguageError::Parameters {
2446 missing_parameters: vec!["p4".to_string()],
2447 unused_parameters: vec![],
2448 }
2449 ))
2450 );
2451 }
2452
2453 #[test]
2454 fn forbid_unbound_parameters_in_set_code() {
2455 let mut builder = BlockBuilder::new();
2456 let mut params = HashMap::new();
2457 params.insert("p1".to_string(), "hello".into());
2458 params.insert("p2".to_string(), 1i64.into());
2459 params.insert("p4".to_string(), "this will be ignored".into());
2460 let res = builder.add_code_with_params(
2461 r#"fact({p1}, "value");
2462 rule($head_var) <- f1($head_var), {p2} > 0;
2463 check if {p3};
2464 "#,
2465 params,
2466 HashMap::new(),
2467 );
2468
2469 assert_eq!(
2470 res,
2471 Err(error::Token::Language(
2472 biscuit_parser::error::LanguageError::Parameters {
2473 missing_parameters: vec!["p3".to_string()],
2474 unused_parameters: vec![],
2475 }
2476 ))
2477 )
2478 }
2479}