biscuit_auth/token/
builder.rs

1//! helper functions and structure to create tokens and blocks
2use 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
18// reexport those because the builder uses the same definitions
19pub use crate::datalog::{Binary, Expression as DatalogExpression, Op as DatalogOp, Unary};
20
21/// creates a Block content to append to an existing token
22#[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    /// Add datalog code to the builder, performing parameter subsitution as required
82    /// Unknown parameters are ignored
83    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 &params {
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 &params {
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 &params {
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    // still used in tests but does not make sense for the public API
256    #[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/// creates a Biscuit
291#[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    /// returns all of the datalog loaded in the biscuit builder
363    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/// Builder for a Datalog value
422#[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            // The error is caught in the `add_xxx` functions, so this should
445            // not happenâ„¢
446            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/// Builder for a block or rule scope
542#[derive(Clone, Debug, Hash, PartialEq, Eq)]
543pub enum Scope {
544    /// Trusts the first block, current block and the authorizer
545    Authority,
546    /// Trusts the current block and all previous ones
547    Previous,
548    /// Trusts the current block and any block signed by the public key
549    PublicKey(PublicKey),
550    /// Used for parameter substitution
551    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            // The error is caught in the `add_xxx` functions, so this should
563            // not happenâ„¢
564            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/// Builder for a Datalog dicate, used in facts and rules
609#[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/// Builder for a Datalog fact
681#[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    /// replace a parameter with the term argument
736    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    /// replace a parameter with the term argument, without raising an error
761    /// if the parameter is not present in the fact description
762    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            //    pub parameters: Option<HashMap<String, Option<Term>>>,
844            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/// Builder for a Datalog expression
854#[derive(Debug, Clone, PartialEq, Eq)]
855pub struct Expression {
856    pub ops: Vec<Op>,
857}
858// todo track parameters
859
860impl 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/// Builder for an expression operation
902#[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/// Builder for a Datalog rule
976#[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    /// replace a parameter with the term argument
1119    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    /// replace a parameter with the term argument, without raising an error if the
1144    /// parameter is not present in the rule
1145    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    /// replace a scope parameter with the pubkey argument
1165    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    /// replace a scope parameter with the public key argument, without raising an error if the
1190    /// parameter is not present in the rule scope
1191    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                // The error is caught in the `add_xxx` functions, so this should
1312                // not happenâ„¢
1313                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/// Builder for a Biscuit check
1427#[derive(Debug, Clone, PartialEq, Eq)]
1428pub struct Check {
1429    pub queries: Vec<Rule>,
1430    pub kind: CheckKind,
1431}
1432
1433/// Builder for a Biscuit check
1434#[derive(Debug, Clone, PartialEq, Eq)]
1435pub enum CheckKind {
1436    One,
1437    All,
1438}
1439
1440impl Check {
1441    /// replace a parameter with the term argument
1442    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    /// replace a scope parameter with the pubkey argument
1468    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    /// replace a parameter with the term argument, without raising an error if the
1489    /// parameter is not present in the check
1490    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    /// replace a scope parameter with the term argument, without raising an error if the
1499    /// parameter is not present in the check
1500    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/// Builder for a Biscuit policy
1627#[derive(Debug, Clone, PartialEq, Eq)]
1628pub struct Policy {
1629    pub queries: Vec<Rule>,
1630    pub kind: PolicyKind,
1631}
1632
1633impl Policy {
1634    /// replace a parameter with the term argument
1635    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    /// replace a scope parameter with the pubkey argument
1661    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    /// replace a parameter with the term argument, ignoring unknown parameters
1682    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    /// replace a scope parameter with the pubkey argument, ignoring unknown parameters
1691    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
1760/// creates a new fact
1761pub 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
1766/// creates a predicate
1767pub 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
1774/// creates a rule
1775pub 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
1788/// creates a rule with constraints
1789pub 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
1803/// creates a check
1804pub 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
1817/// creates an integer value
1818pub fn int(i: i64) -> Term {
1819    Term::Integer(i)
1820}
1821
1822/// creates a string
1823pub fn string(s: &str) -> Term {
1824    Term::Str(s.to_string())
1825}
1826
1827/// creates a date
1828///
1829/// internally the date will be stored as seconds since UNIX_EPOCH
1830pub fn date(t: &SystemTime) -> Term {
1831    let dur = t.duration_since(UNIX_EPOCH).unwrap();
1832    Term::Date(dur.as_secs())
1833}
1834
1835/// creates a variable for a rule
1836pub fn var(s: &str) -> Term {
1837    Term::Variable(s.to_string())
1838}
1839
1840/// creates a variable for a rule
1841pub fn variable(s: &str) -> Term {
1842    Term::Variable(s.to_string())
1843}
1844
1845/// creates a byte array
1846pub fn bytes(s: &[u8]) -> Term {
1847    Term::Bytes(s.to_vec())
1848}
1849
1850/// creates a boolean
1851pub fn boolean(b: bool) -> Term {
1852    Term::Bool(b)
1853}
1854
1855/// creates a set
1856pub fn set(s: BTreeSet<Term>) -> Term {
1857    Term::Set(s)
1858}
1859
1860/// creates a parameter
1861pub 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}