biscuit_auth/token/builder/
biscuit.rs1use super::{BlockBuilder, Check, Fact, Rule, Scope, Term};
6use crate::builder_ext::BuilderExt;
7use crate::crypto::PublicKey;
8use crate::datalog::SymbolTable;
9use crate::token::default_symbol_table;
10use crate::{error, Biscuit, KeyPair};
11use rand::{CryptoRng, RngCore};
12
13use std::fmt;
14use std::time::SystemTime;
15use std::{collections::HashMap, convert::TryInto, fmt::Write};
16
17#[derive(Clone, Default)]
19pub struct BiscuitBuilder {
20 inner: BlockBuilder,
21 root_key_id: Option<u32>,
22}
23
24impl BiscuitBuilder {
25 pub fn new() -> BiscuitBuilder {
26 BiscuitBuilder {
27 inner: BlockBuilder::new(),
28 root_key_id: None,
29 }
30 }
31
32 pub fn merge(mut self, other: BlockBuilder) -> Self {
33 self.inner = self.inner.merge(other);
34 self
35 }
36
37 pub fn fact<F: TryInto<Fact>>(mut self, fact: F) -> Result<Self, error::Token>
38 where
39 error::Token: From<<F as TryInto<Fact>>::Error>,
40 {
41 self.inner = self.inner.fact(fact)?;
42 Ok(self)
43 }
44
45 pub fn rule<Ru: TryInto<Rule>>(mut self, rule: Ru) -> Result<Self, error::Token>
46 where
47 error::Token: From<<Ru as TryInto<Rule>>::Error>,
48 {
49 self.inner = self.inner.rule(rule)?;
50 Ok(self)
51 }
52
53 pub fn check<C: TryInto<Check>>(mut self, check: C) -> Result<Self, error::Token>
54 where
55 error::Token: From<<C as TryInto<Check>>::Error>,
56 {
57 self.inner = self.inner.check(check)?;
58 Ok(self)
59 }
60
61 pub fn code<T: AsRef<str>>(mut self, source: T) -> Result<Self, error::Token> {
62 self.inner = self
63 .inner
64 .code_with_params(source, HashMap::new(), HashMap::new())?;
65 Ok(self)
66 }
67
68 pub fn code_with_params<T: AsRef<str>>(
69 mut self,
70 source: T,
71 params: HashMap<String, Term>,
72 scope_params: HashMap<String, PublicKey>,
73 ) -> Result<Self, error::Token> {
74 self.inner = self.inner.code_with_params(source, params, scope_params)?;
75 Ok(self)
76 }
77
78 pub fn scope(mut self, scope: Scope) -> Self {
79 self.inner = self.inner.scope(scope);
80 self
81 }
82
83 #[cfg(test)]
84 pub(crate) fn right(self, resource: &str, right: &str) -> Self {
85 use crate::builder::fact;
86
87 use super::string;
88
89 self.fact(fact("right", &[string(resource), string(right)]))
90 .unwrap()
91 }
92
93 pub fn context(mut self, context: String) -> Self {
94 self.inner = self.inner.context(context);
95 self
96 }
97
98 pub fn root_key_id(mut self, root_key_id: u32) -> Self {
99 self.root_key_id = Some(root_key_id);
100 self
101 }
102
103 pub fn dump(&self) -> (Vec<Fact>, Vec<Rule>, Vec<Check>) {
105 (
106 self.inner.facts.clone(),
107 self.inner.rules.clone(),
108 self.inner.checks.clone(),
109 )
110 }
111
112 pub fn dump_code(&self) -> String {
113 let (facts, rules, checks) = self.dump();
114 let mut f = String::new();
115 for fact in facts {
116 let _ = writeln!(f, "{};", fact);
117 }
118 for rule in rules {
119 let _ = writeln!(f, "{};", rule);
120 }
121 for check in checks {
122 let _ = writeln!(f, "{};", check);
123 }
124 f
125 }
126
127 pub fn build(self, root_key: &KeyPair) -> Result<Biscuit, error::Token> {
128 self.build_with_symbols(root_key, default_symbol_table())
129 }
130
131 pub fn build_with_symbols(
132 self,
133 root_key: &KeyPair,
134 symbols: SymbolTable,
135 ) -> Result<Biscuit, error::Token> {
136 self.build_with_rng(root_key, symbols, &mut rand::rngs::OsRng)
137 }
138
139 pub fn build_with_rng<R: RngCore + CryptoRng>(
140 self,
141 root: &KeyPair,
142 symbols: SymbolTable,
143 rng: &mut R,
144 ) -> Result<Biscuit, error::Token> {
145 let authority_block = self.inner.build(symbols.clone());
146 Biscuit::new_with_rng(rng, self.root_key_id, root, symbols, authority_block)
147 }
148
149 pub fn build_with_key_pair(
150 self,
151 root: &KeyPair,
152 symbols: SymbolTable,
153 next: &KeyPair,
154 ) -> Result<Biscuit, error::Token> {
155 let authority_block = self.inner.build(symbols.clone());
156 Biscuit::new_with_key_pair(self.root_key_id, root, next, symbols, authority_block)
157 }
158}
159
160impl fmt::Display for BiscuitBuilder {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 match self.root_key_id {
163 None => writeln!(f, "// no root key id set")?,
164 Some(id) => writeln!(f, "// root key id: {}", id)?,
165 }
166 self.inner.fmt(f)
167 }
168}
169
170impl BuilderExt for BiscuitBuilder {
171 fn resource(mut self, name: &str) -> Self {
172 self.inner = self.inner.resource(name);
173 self
174 }
175 fn check_resource(mut self, name: &str) -> Self {
176 self.inner = self.inner.check_resource(name);
177 self
178 }
179 fn check_resource_prefix(mut self, prefix: &str) -> Self {
180 self.inner = self.inner.check_resource_prefix(prefix);
181 self
182 }
183 fn check_resource_suffix(mut self, suffix: &str) -> Self {
184 self.inner = self.inner.check_resource_suffix(suffix);
185 self
186 }
187 fn operation(mut self, name: &str) -> Self {
188 self.inner = self.inner.operation(name);
189 self
190 }
191 fn check_operation(mut self, name: &str) -> Self {
192 self.inner = self.inner.check_operation(name);
193 self
194 }
195 fn check_expiration_date(mut self, date: SystemTime) -> Self {
196 self.inner = self.inner.check_expiration_date(date);
197 self
198 }
199}