From 2f11d0407056477f29cd7dacd20442133cd34593 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Wed, 27 Nov 2024 11:01:58 +0100 Subject: [PATCH 01/28] create an AuthorizerBuilder --- biscuit-auth/src/token/authorizer.rs | 11 -- biscuit-auth/src/token/builder.rs | 2 + biscuit-auth/src/token/builder/authorizer.rs | 117 +++++++++++++++++++ 3 files changed, 119 insertions(+), 11 deletions(-) create mode 100644 biscuit-auth/src/token/builder/authorizer.rs diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index f43f1d01..a891555e 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -622,17 +622,6 @@ impl Authorizer { Ok(()) } - /// todo remove, it's covered in BuilderExt - /// adds a `allow if true` policy - pub fn allow(&mut self) -> Result<(), error::Token> { - self.add_policy("allow if true") - } - - /// adds a `deny if true` policy - pub fn deny(&mut self) -> Result<(), error::Token> { - self.add_policy("deny if true") - } - /// returns the elapsed execution time pub fn execution_time(&self) -> Duration { self.execution_time diff --git a/biscuit-auth/src/token/builder.rs b/biscuit-auth/src/token/builder.rs index 6af2a438..56a845ca 100644 --- a/biscuit-auth/src/token/builder.rs +++ b/biscuit-auth/src/token/builder.rs @@ -16,6 +16,7 @@ pub use crate::datalog::{ use crate::error; mod algorithm; +mod authorizer; mod biscuit; mod block; mod check; @@ -28,6 +29,7 @@ mod scope; mod term; pub use algorithm::*; +pub use authorizer::*; pub use biscuit::*; pub use block::*; pub use check::*; diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs new file mode 100644 index 00000000..7feab78a --- /dev/null +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -0,0 +1,117 @@ +use std::{collections::HashMap, convert::TryInto, time::SystemTime}; + +use crate::{ + builder_ext::{AuthorizerExt, BuilderExt}, + error, Authorizer, Biscuit, PublicKey, +}; + +use super::{BlockBuilder, Check, Fact, Policy, Rule, Scope, Term}; + +#[derive(Clone, Debug, Default)] +pub struct AuthorizerBuilder<'a> { + block: BlockBuilder, + policies: Vec, + token: Option<&'a Biscuit>, +} + +impl<'a> AuthorizerBuilder<'a> { + pub fn new() -> AuthorizerBuilder<'a> { + AuthorizerBuilder::default() + } + + pub fn add_fact>(&mut self, fact: F) -> Result<(), error::Token> + where + error::Token: From<>::Error>, + { + self.block.add_fact(fact) + } + + pub fn add_rule>(&mut self, rule: R) -> Result<(), error::Token> + where + error::Token: From<>::Error>, + { + self.block.add_rule(rule) + } + + pub fn add_check>(&mut self, check: C) -> Result<(), error::Token> + where + error::Token: From<>::Error>, + { + self.block.add_check(check) + } + + pub fn add_code>(&mut self, source: T) -> Result<(), error::Token> { + self.add_code_with_params(source, HashMap::new(), HashMap::new()) + } + + /// Add datalog code to the builder, performing parameter subsitution as required + /// Unknown parameters are ignored + pub fn add_code_with_params>( + &mut self, + source: T, + params: HashMap, + scope_params: HashMap, + ) -> Result<(), error::Token> { + self.block + .add_code_with_params(source, params, scope_params) + } + + pub fn add_scope(&mut self, scope: Scope) { + self.block.add_scope(scope); + } + + /// add a policy to the authorizer + pub fn add_policy>(&mut self, policy: P) -> Result<(), error::Token> + where + error::Token: From<

>::Error>, + { + let policy = policy.try_into()?; + policy.validate_parameters()?; + self.policies.push(policy); + Ok(()) + } + + pub fn add_token(&mut self, token: &'a Biscuit) { + self.token = Some(token); + } + + pub fn build(self) -> Result { + let authorizer = Authorizer::new(); + Ok(authorizer) + } +} + +impl<'a> BuilderExt for AuthorizerBuilder<'a> { + fn add_resource(&mut self, name: &str) { + self.block.add_resource(name); + } + fn check_resource(&mut self, name: &str) { + self.block.check_resource(name); + } + fn add_operation(&mut self, name: &str) { + self.block.add_operation(name); + } + fn check_operation(&mut self, name: &str) { + self.block.check_operation(name); + } + fn check_resource_prefix(&mut self, prefix: &str) { + self.block.check_resource_prefix(prefix); + } + + fn check_resource_suffix(&mut self, suffix: &str) { + self.block.check_resource_suffix(suffix); + } + + fn check_expiration_date(&mut self, exp: SystemTime) { + self.block.check_expiration_date(exp); + } +} + +impl<'a> AuthorizerExt for AuthorizerBuilder<'a> { + fn add_allow_all(&mut self) { + self.add_policy("allow if true").unwrap(); + } + fn add_deny_all(&mut self) { + self.add_policy("deny if true").unwrap(); + } +} From 70c6ce9f189150f55f8f81b58fe683aa050d0d56 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Wed, 27 Nov 2024 15:11:00 +0100 Subject: [PATCH 02/28] build and Authorizer --- biscuit-auth/src/token/authorizer.rs | 16 +- biscuit-auth/src/token/builder/authorizer.rs | 223 +++++++++++++++++-- biscuit-auth/src/token/mod.rs | 52 ++++- 3 files changed, 254 insertions(+), 37 deletions(-) diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index a891555e..3908eed4 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -30,15 +30,15 @@ mod snapshot; /// can be created from [Biscuit::authorizer] or [Authorizer::new] #[derive(Clone)] pub struct Authorizer { - authorizer_block_builder: BlockBuilder, - world: datalog::World, + pub(crate) authorizer_block_builder: BlockBuilder, + pub(crate) world: datalog::World, pub(crate) symbols: datalog::SymbolTable, - token_origins: TrustedOrigins, - policies: Vec, - blocks: Option>, - public_key_to_block_id: HashMap>, - limits: AuthorizerLimits, - execution_time: Duration, + pub(crate) token_origins: TrustedOrigins, + pub(crate) policies: Vec, + pub(crate) blocks: Option>, + pub(crate) public_key_to_block_id: HashMap>, + pub(crate) limits: AuthorizerLimits, + pub(crate) execution_time: Duration, } impl Authorizer { diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs index 7feab78a..620aad20 100644 --- a/biscuit-auth/src/token/builder/authorizer.rs +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -1,16 +1,26 @@ -use std::{collections::HashMap, convert::TryInto, time::SystemTime}; +use std::{ + collections::HashMap, + convert::TryInto, + time::{Instant, SystemTime}, +}; use crate::{ + builder::Convert, builder_ext::{AuthorizerExt, BuilderExt}, - error, Authorizer, Biscuit, PublicKey, + datalog::{ExternFunc, Origin, SymbolTable, TrustedOrigins, World}, + error, + token::{self, Block}, + Authorizer, AuthorizerLimits, Biscuit, PublicKey, }; use super::{BlockBuilder, Check, Fact, Policy, Rule, Scope, Term}; #[derive(Clone, Debug, Default)] pub struct AuthorizerBuilder<'a> { - block: BlockBuilder, + authorizer_block_builder: BlockBuilder, policies: Vec, + extern_funcs: HashMap, + limits: AuthorizerLimits, token: Option<&'a Biscuit>, } @@ -23,21 +33,21 @@ impl<'a> AuthorizerBuilder<'a> { where error::Token: From<>::Error>, { - self.block.add_fact(fact) + self.authorizer_block_builder.add_fact(fact) } pub fn add_rule>(&mut self, rule: R) -> Result<(), error::Token> where error::Token: From<>::Error>, { - self.block.add_rule(rule) + self.authorizer_block_builder.add_rule(rule) } pub fn add_check>(&mut self, check: C) -> Result<(), error::Token> where error::Token: From<>::Error>, { - self.block.add_check(check) + self.authorizer_block_builder.add_check(check) } pub fn add_code>(&mut self, source: T) -> Result<(), error::Token> { @@ -52,12 +62,12 @@ impl<'a> AuthorizerBuilder<'a> { params: HashMap, scope_params: HashMap, ) -> Result<(), error::Token> { - self.block + self.authorizer_block_builder .add_code_with_params(source, params, scope_params) } pub fn add_scope(&mut self, scope: Scope) { - self.block.add_scope(scope); + self.authorizer_block_builder.add_scope(scope); } /// add a policy to the authorizer @@ -71,39 +81,218 @@ impl<'a> AuthorizerBuilder<'a> { Ok(()) } + /// Sets the runtime limits of the authorizer + /// + /// Those limits cover all the executions under the `authorize`, `query` and `query_all` methods + pub fn set_limits(&mut self, limits: AuthorizerLimits) { + self.limits = limits; + } + + /// Replaces the registered external functions + pub fn set_extern_funcs(&mut self, extern_funcs: HashMap) { + self.extern_funcs = extern_funcs; + } + + /// Registers the provided external functions (possibly replacing already registered functions) + pub fn register_extern_funcs(&mut self, extern_funcs: HashMap) { + self.extern_funcs.extend(extern_funcs); + } + + /// Registers the provided external function (possibly replacing an already registered function) + pub fn register_extern_func(&mut self, name: String, func: ExternFunc) { + self.extern_funcs.insert(name, func); + } + pub fn add_token(&mut self, token: &'a Biscuit) { self.token = Some(token); } pub fn build(self) -> Result { - let authorizer = Authorizer::new(); - Ok(authorizer) + let mut world = World::new(); + world.extern_funcs = self.extern_funcs; + + let mut symbols = SymbolTable::new(); + let mut public_key_to_block_id: HashMap> = HashMap::new(); + let mut token_origins = TrustedOrigins::default(); + let mut blocks: Option> = None; + + // load the token if present + if let Some(token) = self.token { + for (i, block) in token.container.blocks.iter().enumerate() { + if let Some(sig) = block.external_signature.as_ref() { + let new_key_id = symbols.public_keys.insert(&sig.public_key); + + public_key_to_block_id + .entry(new_key_id as usize) + .or_default() + .push(i + 1); + } + } + + blocks = Some( + token + .blocks() + .enumerate() + .map(|(i, block)| { + block.and_then(|mut b| { + load_and_translate_block( + &mut b, + i, + &token.symbols, + &mut symbols, + &mut public_key_to_block_id, + &mut world, + )?; + Ok(b) + }) + }) + .collect::, _>>()?, + ); + + token_origins = TrustedOrigins::from_scopes( + &[token::Scope::Previous], + &TrustedOrigins::default(), + token.block_count(), + &public_key_to_block_id, + ); + } + let mut authorizer_origin = Origin::default(); + authorizer_origin.insert(usize::MAX); + + let authorizer_scopes: Vec = self + .authorizer_block_builder + .scopes + .clone() + .iter() + .map(|s| s.convert(&mut symbols)) + .collect(); + + let authorizer_trusted_origins = TrustedOrigins::from_scopes( + &authorizer_scopes, + &TrustedOrigins::default(), + usize::MAX, + &public_key_to_block_id, + ); + for fact in &self.authorizer_block_builder.facts { + world + .facts + .insert(&authorizer_origin, fact.convert(&mut symbols)); + } + + for rule in &self.authorizer_block_builder.rules { + let rule = rule.convert(&mut symbols); + + let rule_trusted_origins = TrustedOrigins::from_scopes( + &rule.scopes, + &authorizer_trusted_origins, + usize::MAX, + &public_key_to_block_id, + ); + + world.rules.insert(usize::MAX, &rule_trusted_origins, rule); + } + + let start = Instant::now(); + world.run_with_limits(&symbols, self.limits.clone())?; + let execution_time = start.elapsed(); + + Ok(Authorizer { + authorizer_block_builder: self.authorizer_block_builder, + world, + symbols, + token_origins, + policies: self.policies, + blocks, + public_key_to_block_id, + limits: self.limits, + execution_time, + }) + } +} + +/// we need to modify the block loaded from the token, because the authorizer's and the token's symbol table can differ +fn load_and_translate_block( + block: &mut Block, + i: usize, + token_symbols: &SymbolTable, + authorizer_symbols: &mut SymbolTable, + public_key_to_block_id: &mut HashMap>, + world: &mut World, +) -> Result<(), error::Token> { + // if it is a 3rd party block, it should not affect the main symbol table + let block_symbols = if i == 0 || block.external_key.is_none() { + token_symbols.clone() + } else { + block.symbols.clone() + }; + + let mut block_origin = Origin::default(); + block_origin.insert(i); + + for scope in block.scopes.iter_mut() { + *scope = crate::token::builder::Scope::convert_from(scope, &block_symbols) + .map(|s| s.convert(authorizer_symbols))?; + } + + let block_trusted_origins = TrustedOrigins::from_scopes( + &block.scopes, + &TrustedOrigins::default(), + i, + &public_key_to_block_id, + ); + + for fact in block.facts.iter_mut() { + *fact = Fact::convert_from(fact, &block_symbols)?.convert(authorizer_symbols); + world.facts.insert(&block_origin, fact.clone()); } + + for rule in block.rules.iter_mut() { + if let Err(_message) = rule.validate_variables(&block_symbols) { + return Err(error::Logic::InvalidBlockRule(0, block_symbols.print_rule(rule)).into()); + } + *rule = rule.translate(&block_symbols, authorizer_symbols)?; + + let rule_trusted_origins = TrustedOrigins::from_scopes( + &rule.scopes, + &block_trusted_origins, + i, + &public_key_to_block_id, + ); + + world.rules.insert(i, &rule_trusted_origins, rule.clone()); + } + + for check in block.checks.iter_mut() { + let c = Check::convert_from(check, &block_symbols)?; + *check = c.convert(authorizer_symbols); + } + + Ok(()) } impl<'a> BuilderExt for AuthorizerBuilder<'a> { fn add_resource(&mut self, name: &str) { - self.block.add_resource(name); + self.authorizer_block_builder.add_resource(name); } fn check_resource(&mut self, name: &str) { - self.block.check_resource(name); + self.authorizer_block_builder.check_resource(name); } fn add_operation(&mut self, name: &str) { - self.block.add_operation(name); + self.authorizer_block_builder.add_operation(name); } fn check_operation(&mut self, name: &str) { - self.block.check_operation(name); + self.authorizer_block_builder.check_operation(name); } fn check_resource_prefix(&mut self, prefix: &str) { - self.block.check_resource_prefix(prefix); + self.authorizer_block_builder.check_resource_prefix(prefix); } fn check_resource_suffix(&mut self, suffix: &str) { - self.block.check_resource_suffix(suffix); + self.authorizer_block_builder.check_resource_suffix(suffix); } fn check_expiration_date(&mut self, exp: SystemTime) { - self.block.check_expiration_date(exp); + self.authorizer_block_builder.check_expiration_date(exp); } } diff --git a/biscuit-auth/src/token/mod.rs b/biscuit-auth/src/token/mod.rs index b0aa3d40..1ea3086a 100644 --- a/biscuit-auth/src/token/mod.rs +++ b/biscuit-auth/src/token/mod.rs @@ -1,5 +1,6 @@ //! main structures to interact with Biscuit tokens use std::fmt::Display; +use std::iter::once; use builder::{BiscuitBuilder, BlockBuilder}; use prost::Message; @@ -575,6 +576,32 @@ impl Biscuit { Ok(block) } + + pub(crate) fn blocks(&self) -> impl Iterator> + use<'_> { + once( + proto_block_to_token_block( + &self.authority, + self.container + .authority + .external_signature + .as_ref() + .map(|ex| ex.public_key), + ) + .map_err(error::Token::Format), + ) + .chain(self.blocks.iter().zip(self.container.blocks.iter()).map( + |(block, container)| { + proto_block_to_token_block( + block, + container + .external_signature + .as_ref() + .map(|ex| ex.public_key), + ) + .map_err(error::Token::Format) + }, + )) + } } impl Display for Biscuit { @@ -711,6 +738,7 @@ mod tests { use crate::builder::CheckKind; use crate::crypto::KeyPair; use crate::{error::*, AuthorizerLimits, UnverifiedBiscuit}; + use builder_ext::AuthorizerExt; use rand::prelude::*; use std::time::{Duration, SystemTime}; @@ -840,7 +868,7 @@ mod tests { } //println!("final token: {:#?}", final_token); - authorizer.allow().unwrap(); + authorizer.add_allow_all(); let res = authorizer.authorize(); println!("res1: {:?}", res); @@ -859,7 +887,7 @@ mod tests { authorizer.add_fact(fact).unwrap(); } - authorizer.allow().unwrap(); + authorizer.add_allow_all(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -908,7 +936,7 @@ mod tests { let mut authorizer = biscuit2.authorizer().unwrap(); authorizer.add_fact("resource(\"/folder1/file1\")").unwrap(); authorizer.add_fact("operation(\"read\")").unwrap(); - authorizer.allow().unwrap(); + authorizer.add_allow_all(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -923,7 +951,7 @@ mod tests { let mut authorizer = biscuit2.authorizer().unwrap(); authorizer.add_fact("resource(\"/folder2/file3\")").unwrap(); authorizer.add_fact("operation(\"read\")").unwrap(); - authorizer.allow().unwrap(); + authorizer.add_allow_all(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -990,7 +1018,7 @@ mod tests { authorizer.add_fact("resource(\"file1\")").unwrap(); authorizer.add_fact("operation(\"read\")").unwrap(); authorizer.set_time(); - authorizer.allow().unwrap(); + authorizer.add_allow_all(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -1006,7 +1034,7 @@ mod tests { authorizer.add_fact("resource(\"file1\")").unwrap(); authorizer.add_fact("operation(\"read\")").unwrap(); authorizer.set_time(); - authorizer.allow().unwrap(); + authorizer.add_allow_all(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -1052,7 +1080,7 @@ mod tests { let mut authorizer = biscuit2.authorizer().unwrap(); authorizer.add_fact("resource(\"/folder1/file1\")").unwrap(); authorizer.add_fact("operation(\"read\")").unwrap(); - authorizer.allow().unwrap(); + authorizer.add_allow_all(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -1074,7 +1102,7 @@ mod tests { let mut authorizer = biscuit3.authorizer().unwrap(); authorizer.add_fact("resource(\"/folder1/file1\")").unwrap(); authorizer.add_fact("operation(\"read\")").unwrap(); - authorizer.allow().unwrap(); + authorizer.add_allow_all(); let res = authorizer.authorize(); println!("res1: {:?}", res); @@ -1348,7 +1376,7 @@ mod tests { authorizer .add_check("check if bytes($0), { hex:00000000, hex:0102AB }.contains($0)") .unwrap(); - authorizer.allow().unwrap(); + authorizer.add_allow_all(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -1444,7 +1472,7 @@ mod tests { authorizer .add_policy("allow if resource($file), operation($op), right($file, $op)") .unwrap(); - authorizer.deny().unwrap(); + authorizer.add_deny_all(); let res = authorizer.authorize_with_limits(crate::token::authorizer::AuthorizerLimits { max_time: Duration::from_secs(1), @@ -1487,7 +1515,7 @@ mod tests { authorizer.add_fact("fact(1)").unwrap(); //println!("final token: {:#?}", final_token); - authorizer.allow().unwrap(); + authorizer.add_allow_all(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -1503,7 +1531,7 @@ mod tests { authorizer.add_fact("fact(1)").unwrap(); //println!("final token: {:#?}", final_token); - authorizer.allow().unwrap(); + authorizer.add_allow_all(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), From 7060df787437bf3565c31867a44a3f9fa950a160 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Wed, 27 Nov 2024 15:41:21 +0100 Subject: [PATCH 03/28] start using the new API --- biscuit-auth/benches/token.rs | 28 +-- biscuit-auth/examples/testcases.rs | 12 +- biscuit-auth/examples/third_party.rs | 9 +- biscuit-auth/examples/verifying_printer.rs | 4 +- biscuit-auth/src/token/authorizer.rs | 39 ++-- biscuit-auth/src/token/builder/authorizer.rs | 38 +++- biscuit-auth/src/token/mod.rs | 187 +++++++++++-------- biscuit-auth/tests/macros.rs | 5 +- 8 files changed, 201 insertions(+), 121 deletions(-) diff --git a/biscuit-auth/benches/token.rs b/biscuit-auth/benches/token.rs index 58239b1f..6b5b0624 100644 --- a/biscuit-auth/benches/token.rs +++ b/biscuit-auth/benches/token.rs @@ -3,8 +3,10 @@ extern crate biscuit_auth as biscuit; use std::time::Duration; use biscuit::{ - builder::*, builder_ext::BuilderExt, datalog::SymbolTable, AuthorizerLimits, Biscuit, KeyPair, - UnverifiedBiscuit, + builder::*, + builder_ext::{AuthorizerExt, BuilderExt}, + datalog::SymbolTable, + AuthorizerLimits, Biscuit, KeyPair, UnverifiedBiscuit, }; use codspeed_bencher_compat::{benchmark_group, benchmark_main, Bencher}; use rand::rngs::OsRng; @@ -244,7 +246,7 @@ fn verify_block_2(b: &mut Bencher) { let mut verifier = token.authorizer().unwrap(); verifier.add_fact("resource(\"file1\")"); verifier.add_fact("operation(\"read\")"); - verifier.allow(); + verifier.add_allow_all(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -257,7 +259,7 @@ fn verify_block_2(b: &mut Bencher) { let mut verifier = token.authorizer().unwrap(); verifier.add_fact("resource(\"file1\")"); verifier.add_fact("operation(\"read\")"); - verifier.allow(); + verifier.add_allow_all(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -322,7 +324,7 @@ fn verify_block_5(b: &mut Bencher) { let mut verifier = token.authorizer().unwrap(); verifier.add_fact("resource(\"file1\")"); verifier.add_fact("operation(\"read\")"); - verifier.allow(); + verifier.add_allow_all(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -336,7 +338,7 @@ fn verify_block_5(b: &mut Bencher) { let mut verifier = token.authorizer().unwrap(); verifier.add_fact("resource(\"file1\")"); verifier.add_fact("operation(\"read\")"); - verifier.allow(); + verifier.add_allow_all(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -374,7 +376,7 @@ fn check_signature_2(b: &mut Bencher) { let mut verifier = token.authorizer().unwrap(); verifier.add_fact("resource(\"file1\")"); verifier.add_fact("operation(\"read\")"); - verifier.allow(); + verifier.add_allow_all(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -442,7 +444,7 @@ fn check_signature_5(b: &mut Bencher) { let mut verifier = token.authorizer().unwrap(); verifier.add_fact("resource(\"file1\")"); verifier.add_fact("operation(\"read\")"); - verifier.allow(); + verifier.add_allow_all(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -484,7 +486,7 @@ fn checks_block_2(b: &mut Bencher) { let mut verifier = token.authorizer().unwrap(); verifier.add_fact("resource(\"file1\")"); verifier.add_fact("operation(\"read\")"); - verifier.allow(); + verifier.add_allow_all(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -498,7 +500,7 @@ fn checks_block_2(b: &mut Bencher) { let mut verifier = token.authorizer().unwrap(); verifier.add_fact("resource(\"file1\")"); verifier.add_fact("operation(\"read\")"); - verifier.allow(); + verifier.add_allow_all(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -536,7 +538,7 @@ fn checks_block_create_verifier2(b: &mut Bencher) { let mut verifier = token.authorizer().unwrap(); verifier.add_fact("resource(\"file1\")"); verifier.add_fact("operation(\"read\")"); - verifier.allow(); + verifier.add_allow_all(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -579,7 +581,7 @@ fn checks_block_verify_only2(b: &mut Bencher) { let mut verifier = token.authorizer().unwrap(); verifier.add_fact("resource(\"file1\")"); verifier.add_fact("operation(\"read\")"); - verifier.allow(); + verifier.add_allow_all(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -592,7 +594,7 @@ fn checks_block_verify_only2(b: &mut Bencher) { let mut verifier = token.authorizer().unwrap(); verifier.add_fact("resource(\"file1\")"); verifier.add_fact("operation(\"read\")"); - verifier.allow(); + verifier.add_allow_all(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), diff --git a/biscuit-auth/examples/testcases.rs b/biscuit-auth/examples/testcases.rs index d8a33d9f..2dda8499 100644 --- a/biscuit-auth/examples/testcases.rs +++ b/biscuit-auth/examples/testcases.rs @@ -7,7 +7,6 @@ use biscuit::datalog::SymbolTable; use biscuit::error; use biscuit::format::convert::v2 as convert; use biscuit::macros::*; -use biscuit::Authorizer; use biscuit::{builder::*, builder_ext::*, Biscuit}; use biscuit::{KeyPair, PrivateKey, PublicKey}; use biscuit_auth::builder; @@ -344,12 +343,13 @@ fn validate_token_with_limits_and_external_functions( revocation_ids.push(hex::encode(&bytes)); } - let mut authorizer = Authorizer::new(); - authorizer.set_extern_funcs(extern_funcs); - authorizer.add_code(authorizer_code).unwrap(); - let authorizer_code = authorizer.dump_code(); + let mut builder = AuthorizerBuilder::new(); + builder.set_extern_funcs(extern_funcs); + builder.add_code(authorizer_code).unwrap(); + let authorizer_code = builder.dump_code(); + builder.add_token(&token); - match authorizer.add_token(&token) { + let mut authorizer = match builder.build() { Ok(v) => v, Err(e) => { return Validation { diff --git a/biscuit-auth/examples/third_party.rs b/biscuit-auth/examples/third_party.rs index 67fd6d99..b22ab47e 100644 --- a/biscuit-auth/examples/third_party.rs +++ b/biscuit-auth/examples/third_party.rs @@ -1,5 +1,8 @@ use biscuit_auth::{ - builder::Algorithm, builder::BlockBuilder, datalog::SymbolTable, Biscuit, KeyPair, + builder::{Algorithm, BlockBuilder}, + builder_ext::AuthorizerExt, + datalog::SymbolTable, + Biscuit, KeyPair, }; use rand::{prelude::StdRng, SeedableRng}; @@ -36,12 +39,12 @@ fn main() { println!("biscuit2: {}", biscuit2); let mut authorizer = biscuit1.authorizer().unwrap(); - authorizer.allow().unwrap(); + authorizer.add_allow_all(); println!("authorize biscuit1:\n{:?}", authorizer.authorize()); println!("world:\n{}", authorizer.print_world()); let mut authorizer = biscuit2.authorizer().unwrap(); - authorizer.allow().unwrap(); + authorizer.add_allow_all(); println!("authorize biscuit2:\n{:?}", authorizer.authorize()); println!("world:\n{}", authorizer.print_world()); } diff --git a/biscuit-auth/examples/verifying_printer.rs b/biscuit-auth/examples/verifying_printer.rs index cb55df40..580681d3 100644 --- a/biscuit-auth/examples/verifying_printer.rs +++ b/biscuit-auth/examples/verifying_printer.rs @@ -1,4 +1,4 @@ -use biscuit_auth::PublicKey; +use biscuit_auth::{builder_ext::AuthorizerExt, PublicKey}; fn main() { let mut args = std::env::args(); @@ -26,7 +26,7 @@ fn main() { println!("token:\n{}", token); let mut authorizer = token.authorizer().unwrap(); - authorizer.allow().unwrap(); + authorizer.add_allow_all(); println!("authorizer result: {:?}", authorizer.authorize()); println!("authorizer world:\n{}", authorizer.print_world()); diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index 3908eed4..f98f57f3 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -1,7 +1,7 @@ //! Authorizer structure and associated functions use super::builder::{ - constrained_rule, date, fact, pred, rule, string, var, Binary, BlockBuilder, Check, Expression, - Fact, Op, Policy, PolicyKind, Rule, Scope, Term, + constrained_rule, date, fact, pred, rule, string, var, AuthorizerBuilder, Binary, BlockBuilder, + Check, Expression, Fact, Op, Policy, PolicyKind, Rule, Scope, Term, }; use super::builder_ext::{AuthorizerExt, BuilderExt}; use super::{Biscuit, Block}; @@ -43,10 +43,10 @@ pub struct Authorizer { impl Authorizer { pub(crate) fn from_token(token: &Biscuit) -> Result { - let mut v = Authorizer::new(); - v.add_token(token)?; + let mut b = AuthorizerBuilder::new(); + b.add_token(token); - Ok(v) + b.build() } /// creates a new empty authorizer @@ -58,7 +58,7 @@ impl Authorizer { /// In the latter case, we can create an empty authorizer, load it /// with the facts, rules and checks, and each time a token must be checked, /// clone the authorizer and load the token with [`Authorizer::add_token`] - pub fn new() -> Self { + fn new() -> Self { let world = datalog::World::new(); let symbols = super::default_symbol_table(); let authorizer_block_builder = BlockBuilder::new(); @@ -213,21 +213,21 @@ impl Authorizer { self.authorizer_block_builder.merge(other) } - pub fn add_fact>(&mut self, fact: F) -> Result<(), error::Token> + fn add_fact>(&mut self, fact: F) -> Result<(), error::Token> where error::Token: From<>::Error>, { self.authorizer_block_builder.add_fact(fact) } - pub fn add_rule>(&mut self, rule: Ru) -> Result<(), error::Token> + fn add_rule>(&mut self, rule: Ru) -> Result<(), error::Token> where error::Token: From<>::Error>, { self.authorizer_block_builder.add_rule(rule) } - pub fn add_check>(&mut self, check: C) -> Result<(), error::Token> + fn add_check>(&mut self, check: C) -> Result<(), error::Token> where error::Token: From<>::Error>, { @@ -252,11 +252,11 @@ impl Authorizer { /// allow if true; /// "#).expect("should parse correctly"); /// ``` - pub fn add_code>(&mut self, source: T) -> Result<(), error::Token> { + fn add_code>(&mut self, source: T) -> Result<(), error::Token> { self.add_code_with_params(source, HashMap::new(), HashMap::new()) } - pub fn add_code_with_params>( + fn add_code_with_params>( &mut self, source: T, params: HashMap, @@ -379,7 +379,7 @@ impl Authorizer { Ok(()) } - pub fn add_scope(&mut self, scope: Scope) { + fn add_scope(&mut self, scope: Scope) { self.authorizer_block_builder.add_scope(scope); } @@ -393,7 +393,7 @@ impl Authorizer { /// Sets the runtime limits of the authorizer /// /// Those limits cover all the executions under the `authorize`, `query` and `query_all` methods - pub fn set_limits(&mut self, limits: AuthorizerLimits) { + fn set_limits(&mut self, limits: AuthorizerLimits) { self.limits = limits; } @@ -403,17 +403,17 @@ impl Authorizer { } /// Replaces the registered external functions - pub fn set_extern_funcs(&mut self, extern_funcs: HashMap) { + fn set_extern_funcs(&mut self, extern_funcs: HashMap) { self.world.extern_funcs = extern_funcs; } /// Registers the provided external functions (possibly replacing already registered functions) - pub fn register_extern_funcs(&mut self, extern_funcs: HashMap) { + fn register_extern_funcs(&mut self, extern_funcs: HashMap) { self.world.extern_funcs.extend(extern_funcs); } /// Registers the provided external function (possibly replacing an already registered function) - pub fn register_extern_func(&mut self, name: String, func: ExternFunc) { + fn register_extern_func(&mut self, name: String, func: ExternFunc) { self.world.extern_funcs.insert(name, func); } @@ -1578,14 +1578,14 @@ mod tests { let serialized = biscuit2.to_vec().unwrap(); let biscuit2 = Biscuit::from(serialized, root.public()).unwrap(); - let mut authorizer = Authorizer::new(); + let mut builder = AuthorizerBuilder::new(); let external2 = KeyPair::new(Algorithm::Ed25519); let mut scope_params = HashMap::new(); scope_params.insert("external".to_string(), external.public()); scope_params.insert("external2".to_string(), external2.public()); - authorizer + builder .add_code_with_params( r#" // this rule trusts both the third-party block and the authority, and can access facts @@ -1607,7 +1607,8 @@ mod tests { ) .unwrap(); - authorizer.add_token(&biscuit2).unwrap(); + builder.add_token(&biscuit2); + let mut authorizer = builder.build().unwrap(); println!("token:\n{}", biscuit2); println!("world:\n{}", authorizer.print_world()); diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs index 620aad20..3ded161b 100644 --- a/biscuit-auth/src/token/builder/authorizer.rs +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -1,6 +1,7 @@ use std::{ collections::HashMap, convert::TryInto, + fmt::Write, time::{Instant, SystemTime}, }; @@ -13,7 +14,7 @@ use crate::{ Authorizer, AuthorizerLimits, Biscuit, PublicKey, }; -use super::{BlockBuilder, Check, Fact, Policy, Rule, Scope, Term}; +use super::{date, fact, BlockBuilder, Check, Fact, Policy, Rule, Scope, Term}; #[derive(Clone, Debug, Default)] pub struct AuthorizerBuilder<'a> { @@ -81,6 +82,12 @@ impl<'a> AuthorizerBuilder<'a> { Ok(()) } + /// adds a fact with the current time + pub fn set_time(&mut self) { + let fact = fact("time", &[date(&SystemTime::now())]); + self.authorizer_block_builder.add_fact(fact).unwrap(); + } + /// Sets the runtime limits of the authorizer /// /// Those limits cover all the executions under the `authorize`, `query` and `query_all` methods @@ -107,6 +114,35 @@ impl<'a> AuthorizerBuilder<'a> { self.token = Some(token); } + pub fn dump_code(&self) -> String { + let mut f = String::new(); + for fact in &self.authorizer_block_builder.facts { + let _ = writeln!(f, "{fact};"); + } + if !self.authorizer_block_builder.facts.is_empty() { + let _ = writeln!(f); + } + + for rule in &self.authorizer_block_builder.rules { + let _ = writeln!(f, "{rule};"); + } + if !self.authorizer_block_builder.rules.is_empty() { + let _ = writeln!(f); + } + + for check in &self.authorizer_block_builder.checks { + let _ = writeln!(f, "{check};"); + } + if !self.authorizer_block_builder.checks.is_empty() { + let _ = writeln!(f); + } + + for policy in &self.policies { + let _ = writeln!(f, "{policy};"); + } + f + } + pub fn build(self) -> Result { let mut world = World::new(); world.extern_funcs = self.extern_funcs; diff --git a/biscuit-auth/src/token/mod.rs b/biscuit-auth/src/token/mod.rs index 1ea3086a..b6cf9282 100644 --- a/biscuit-auth/src/token/mod.rs +++ b/biscuit-auth/src/token/mod.rs @@ -157,18 +157,11 @@ impl Biscuit { Ok(token) } - /// creates a authorizer from this token + /// creates an authorizer from this token pub fn authorizer(&self) -> Result { Authorizer::from_token(self) } - /// runs authorization with the provided authorizer - pub fn authorize(&self, authorizer: &Authorizer) -> Result { - let mut a = authorizer.clone(); - a.add_token(self)?; - a.authorize() - } - /// adds a new block to the token /// /// since the public key is integrated into the token, the keypair can be @@ -738,6 +731,7 @@ mod tests { use crate::builder::CheckKind; use crate::crypto::KeyPair; use crate::{error::*, AuthorizerLimits, UnverifiedBiscuit}; + use builder::AuthorizerBuilder; use builder_ext::AuthorizerExt; use rand::prelude::*; use std::time::{Duration, SystemTime}; @@ -856,7 +850,8 @@ mod tests { let final_token = Biscuit::from(&serialized3, root.public()).unwrap(); println!("final token:\n{}", final_token); { - let mut authorizer = final_token.authorizer().unwrap(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&final_token); let mut facts = vec![ fact("resource", &[string("file1")]), @@ -864,11 +859,13 @@ mod tests { ]; for fact in facts.drain(..) { - authorizer.add_fact(fact).unwrap(); + builder.add_fact(fact).unwrap(); } //println!("final token: {:#?}", final_token); - authorizer.add_allow_all(); + builder.add_allow_all(); + + let mut authorizer = builder.build().unwrap(); let res = authorizer.authorize(); println!("res1: {:?}", res); @@ -876,7 +873,8 @@ mod tests { } { - let mut authorizer = final_token.authorizer().unwrap(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&final_token); let mut facts = vec![ fact("resource", &[string("file2")]), @@ -884,9 +882,11 @@ mod tests { ]; for fact in facts.drain(..) { - authorizer.add_fact(fact).unwrap(); + builder.add_fact(fact).unwrap(); } + let mut authorizer = builder.build().unwrap(); + authorizer.add_allow_all(); let res = authorizer.authorize_with_limits(AuthorizerLimits { @@ -933,10 +933,13 @@ mod tests { let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); { - let mut authorizer = biscuit2.authorizer().unwrap(); - authorizer.add_fact("resource(\"/folder1/file1\")").unwrap(); - authorizer.add_fact("operation(\"read\")").unwrap(); - authorizer.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&biscuit2); + builder.add_fact("resource(\"/folder1/file1\")").unwrap(); + builder.add_fact("operation(\"read\")").unwrap(); + builder.add_allow_all(); + + let mut authorizer = builder.build().unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -948,10 +951,13 @@ mod tests { } { - let mut authorizer = biscuit2.authorizer().unwrap(); - authorizer.add_fact("resource(\"/folder2/file3\")").unwrap(); - authorizer.add_fact("operation(\"read\")").unwrap(); - authorizer.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&biscuit2); + builder.add_fact("resource(\"/folder2/file3\")").unwrap(); + builder.add_fact("operation(\"read\")").unwrap(); + builder.add_allow_all(); + + let mut authorizer = builder.build().unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -974,9 +980,12 @@ mod tests { } { - let mut authorizer = biscuit2.authorizer().unwrap(); - authorizer.add_fact("resource(\"/folder2/file1\")").unwrap(); - authorizer.add_fact("operation(\"write\")").unwrap(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&biscuit2); + builder.add_fact("resource(\"/folder2/file1\")").unwrap(); + builder.add_fact("operation(\"write\")").unwrap(); + + let mut authorizer = builder.build().unwrap(); let res = authorizer.authorize(); println!("res3: {:?}", res); @@ -1014,11 +1023,14 @@ mod tests { let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); { - let mut authorizer = biscuit2.authorizer().unwrap(); - authorizer.add_fact("resource(\"file1\")").unwrap(); - authorizer.add_fact("operation(\"read\")").unwrap(); - authorizer.set_time(); - authorizer.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&biscuit2); + builder.add_fact("resource(\"file1\")").unwrap(); + builder.add_fact("operation(\"read\")").unwrap(); + builder.set_time(); + builder.add_allow_all(); + + let mut authorizer = builder.build().unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -1030,11 +1042,14 @@ mod tests { { println!("biscuit2: {}", biscuit2); - let mut authorizer = biscuit2.authorizer().unwrap(); - authorizer.add_fact("resource(\"file1\")").unwrap(); - authorizer.add_fact("operation(\"read\")").unwrap(); - authorizer.set_time(); - authorizer.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&biscuit2); + builder.add_fact("resource(\"file1\")").unwrap(); + builder.add_fact("operation(\"read\")").unwrap(); + builder.set_time(); + builder.add_allow_all(); + + let mut authorizer = builder.build().unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -1077,10 +1092,13 @@ mod tests { //println!("biscuit2:\n{:#?}", biscuit2); //panic!(); { - let mut authorizer = biscuit2.authorizer().unwrap(); - authorizer.add_fact("resource(\"/folder1/file1\")").unwrap(); - authorizer.add_fact("operation(\"read\")").unwrap(); - authorizer.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&biscuit2); + builder.add_fact("resource(\"/folder1/file1\")").unwrap(); + builder.add_fact("operation(\"read\")").unwrap(); + builder.add_allow_all(); + + let mut authorizer = builder.build().unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -1099,10 +1117,13 @@ mod tests { let biscuit3 = Biscuit::from(sealed, root.public()).unwrap(); { - let mut authorizer = biscuit3.authorizer().unwrap(); - authorizer.add_fact("resource(\"/folder1/file1\")").unwrap(); - authorizer.add_fact("operation(\"read\")").unwrap(); - authorizer.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&biscuit3); + builder.add_fact("resource(\"/folder1/file1\")").unwrap(); + builder.add_fact("operation(\"read\")").unwrap(); + builder.add_allow_all(); + + let mut authorizer = builder.build().unwrap(); let res = authorizer.authorize(); println!("res1: {:?}", res); @@ -1134,17 +1155,20 @@ mod tests { .unwrap(); println!("{}", biscuit1); - let mut v = biscuit1.authorizer().expect("omg authorizer"); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&biscuit1); - v.add_check(rule( - "right", - &[string("right")], - &[pred("right", &[string("file2"), string("write")])], - )) - .unwrap(); + builder + .add_check(rule( + "right", + &[string("right")], + &[pred("right", &[string("file2"), string("write")])], + )) + .unwrap(); + let mut authorizer = builder.build().unwrap(); //assert!(v.verify().is_err()); - let res = v.authorize_with_limits(AuthorizerLimits { + let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), ..Default::default() }); @@ -1195,10 +1219,12 @@ mod tests { { println!("biscuit3: {}", biscuit3); - let mut authorizer = biscuit3.authorizer().unwrap(); - authorizer.add_fact("resource(\"file1\")").unwrap(); - authorizer.add_fact("operation(\"read\")").unwrap(); - authorizer.set_time(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&biscuit3); + builder.add_fact("resource(\"file1\")").unwrap(); + builder.add_fact("operation(\"read\")").unwrap(); + builder.set_time(); + let mut authorizer = builder.build().unwrap(); // test that cloning correctly embeds the first block's facts let mut other_authorizer = authorizer.clone(); @@ -1279,11 +1305,12 @@ mod tests { //println!("generated biscuit token 2: {} bytes\n{}", serialized2.len(), serialized2.to_hex(16)); { - let mut authorizer = biscuit2.authorizer().unwrap(); - authorizer.add_fact("resource(\"file1\")").unwrap(); - authorizer.add_fact("operation(\"read\")").unwrap(); - println!("symbols before time: {:?}", authorizer.symbols); - authorizer.set_time(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&biscuit2); + builder.add_fact("resource(\"file1\")").unwrap(); + builder.add_fact("operation(\"read\")").unwrap(); + builder.set_time(); + let mut authorizer = builder.build().unwrap(); println!("world:\n{}", authorizer.print_world()); println!("symbols: {:?}", authorizer.symbols); @@ -1372,11 +1399,13 @@ mod tests { let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); - let mut authorizer = biscuit2.authorizer().unwrap(); - authorizer + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&biscuit2); + builder .add_check("check if bytes($0), { hex:00000000, hex:0102AB }.contains($0)") .unwrap(); - authorizer.add_allow_all(); + builder.add_allow_all(); + let mut authorizer = builder.build().unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -1466,13 +1495,15 @@ mod tests { let final_token = Biscuit::from(&serialized2, root.public()).unwrap(); println!("final token:\n{}", final_token); - let mut authorizer = final_token.authorizer().unwrap(); - authorizer.add_fact("resource(\"/folder2/file1\")").unwrap(); - authorizer.add_fact("operation(\"write\")").unwrap(); - authorizer + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&final_token); + builder.add_fact("resource(\"/folder2/file1\")").unwrap(); + builder.add_fact("operation(\"write\")").unwrap(); + builder .add_policy("allow if resource($file), operation($op), right($file, $op)") .unwrap(); - authorizer.add_deny_all(); + builder.add_deny_all(); + let mut authorizer = builder.build().unwrap(); let res = authorizer.authorize_with_limits(crate::token::authorizer::AuthorizerLimits { max_time: Duration::from_secs(1), @@ -1510,12 +1541,15 @@ mod tests { println!("biscuit2 (authority): {}", biscuit2); { - let mut authorizer = biscuit1.authorizer().unwrap(); - authorizer.add_fact("fact(0)").unwrap(); - authorizer.add_fact("fact(1)").unwrap(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&biscuit1); + builder.add_fact("fact(0)").unwrap(); + builder.add_fact("fact(1)").unwrap(); //println!("final token: {:#?}", final_token); - authorizer.add_allow_all(); + builder.add_allow_all(); + + let mut authorizer = builder.build().unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -1526,12 +1560,15 @@ mod tests { } { - let mut authorizer = biscuit2.authorizer().unwrap(); - authorizer.add_fact("fact(0)").unwrap(); - authorizer.add_fact("fact(1)").unwrap(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&biscuit2); + builder.add_fact("fact(0)").unwrap(); + builder.add_fact("fact(1)").unwrap(); //println!("final token: {:#?}", final_token); - authorizer.add_allow_all(); + builder.add_allow_all(); + + let mut authorizer = builder.build().unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), diff --git a/biscuit-auth/tests/macros.rs b/biscuit-auth/tests/macros.rs index 0922b342..fed6e21a 100644 --- a/biscuit-auth/tests/macros.rs +++ b/biscuit-auth/tests/macros.rs @@ -249,7 +249,7 @@ fn json() { ); let json_value: biscuit_auth::builder::Term = value.try_into().unwrap(); - let mut authorizer = authorizer!( + let mut builder = authorizer!( r#" user_roles({json_value}); allow if @@ -259,7 +259,8 @@ fn json() { $value.get("roles").contains("admin");"# ); - authorizer.add_token(&biscuit).unwrap(); + builder.add_token(&biscuit); + let mut authorizer = builder.build().unwrap(); assert_eq!( authorizer .authorize_with_limits(RunLimits { From 49f74989770ffbcf615c17c872f133a9d5db40b6 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Wed, 27 Nov 2024 16:00:07 +0100 Subject: [PATCH 04/28] fix macros --- biscuit-auth/src/token/authorizer.rs | 4 +- biscuit-auth/src/token/builder/authorizer.rs | 119 ++++++++++++++++++- biscuit-auth/tests/macros.rs | 8 +- biscuit-auth/tests/rights.rs | 13 +- biscuit-quote/src/lib.rs | 4 +- 5 files changed, 134 insertions(+), 14 deletions(-) diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index f98f57f3..11ec6762 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -987,7 +987,7 @@ impl Authorizer { .map(|f| Fact::convert_from(f.1, &self.symbols)) .collect::, error::Format>>() .unwrap(); - facts.extend(self.authorizer_block_builder.facts.clone()); + //facts.extend(self.authorizer_block_builder.facts.clone()); let mut rules = self .world @@ -996,7 +996,7 @@ impl Authorizer { .map(|r| Rule::convert_from(r.1, &self.symbols)) .collect::, error::Format>>() .unwrap(); - rules.extend(self.authorizer_block_builder.rules.clone()); + //rules.extend(self.authorizer_block_builder.rules.clone()); (facts, rules, checks, self.policies.clone()) } diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs index 3ded161b..df1cbc39 100644 --- a/biscuit-auth/src/token/builder/authorizer.rs +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -5,6 +5,8 @@ use std::{ time::{Instant, SystemTime}, }; +use biscuit_parser::parser::parse_source; + use crate::{ builder::Convert, builder_ext::{AuthorizerExt, BuilderExt}, @@ -63,8 +65,121 @@ impl<'a> AuthorizerBuilder<'a> { params: HashMap, scope_params: HashMap, ) -> Result<(), error::Token> { - self.authorizer_block_builder - .add_code_with_params(source, params, scope_params) + let source = source.as_ref(); + + let source_result = parse_source(source).map_err(|e| { + let e2: biscuit_parser::error::LanguageError = e.into(); + e2 + })?; + + for (_, fact) in source_result.facts.into_iter() { + let mut fact: Fact = fact.into(); + for (name, value) in ¶ms { + let res = match fact.set(name, value) { + Ok(_) => Ok(()), + Err(error::Token::Language( + biscuit_parser::error::LanguageError::Parameters { + missing_parameters, .. + }, + )) if missing_parameters.is_empty() => Ok(()), + Err(e) => Err(e), + }; + res?; + } + fact.validate()?; + self.authorizer_block_builder.facts.push(fact); + } + + for (_, rule) in source_result.rules.into_iter() { + let mut rule: Rule = rule.into(); + for (name, value) in ¶ms { + let res = match rule.set(name, value) { + Ok(_) => Ok(()), + Err(error::Token::Language( + biscuit_parser::error::LanguageError::Parameters { + missing_parameters, .. + }, + )) if missing_parameters.is_empty() => Ok(()), + Err(e) => Err(e), + }; + res?; + } + for (name, value) in &scope_params { + let res = match rule.set_scope(name, *value) { + Ok(_) => Ok(()), + Err(error::Token::Language( + biscuit_parser::error::LanguageError::Parameters { + missing_parameters, .. + }, + )) if missing_parameters.is_empty() => Ok(()), + Err(e) => Err(e), + }; + res?; + } + rule.validate_parameters()?; + self.authorizer_block_builder.rules.push(rule); + } + + for (_, check) in source_result.checks.into_iter() { + let mut check: Check = check.into(); + for (name, value) in ¶ms { + let res = match check.set(name, value) { + Ok(_) => Ok(()), + Err(error::Token::Language( + biscuit_parser::error::LanguageError::Parameters { + missing_parameters, .. + }, + )) if missing_parameters.is_empty() => Ok(()), + Err(e) => Err(e), + }; + res?; + } + for (name, value) in &scope_params { + let res = match check.set_scope(name, *value) { + Ok(_) => Ok(()), + Err(error::Token::Language( + biscuit_parser::error::LanguageError::Parameters { + missing_parameters, .. + }, + )) if missing_parameters.is_empty() => Ok(()), + Err(e) => Err(e), + }; + res?; + } + check.validate_parameters()?; + self.authorizer_block_builder.checks.push(check); + } + for (_, policy) in source_result.policies.into_iter() { + let mut policy: Policy = policy.into(); + for (name, value) in ¶ms { + let res = match policy.set(name, value) { + Ok(_) => Ok(()), + Err(error::Token::Language( + biscuit_parser::error::LanguageError::Parameters { + missing_parameters, .. + }, + )) if missing_parameters.is_empty() => Ok(()), + Err(e) => Err(e), + }; + res?; + } + for (name, value) in &scope_params { + let res = match policy.set_scope(name, *value) { + Ok(_) => Ok(()), + Err(error::Token::Language( + biscuit_parser::error::LanguageError::Parameters { + missing_parameters, .. + }, + )) if missing_parameters.is_empty() => Ok(()), + Err(e) => Err(e), + }; + res?; + } + policy.validate_parameters()?; + self.policies.push(policy); + } + + Ok(()) } pub fn add_scope(&mut self, scope: Scope) { diff --git a/biscuit-auth/tests/macros.rs b/biscuit-auth/tests/macros.rs index fed6e21a..b9ba8b53 100644 --- a/biscuit-auth/tests/macros.rs +++ b/biscuit-auth/tests/macros.rs @@ -75,9 +75,11 @@ fn authorizer_macro() { "# ); + let authorizer = b.build().unwrap(); assert_eq!( - b.dump_code(), + authorizer.dump_code(), r#"fact("test", hex:aabbcc, [true], "my_value"); +rule("test", true); appended(true); rule($0, true) <- fact($0, $1, $2, "my_value"); @@ -92,7 +94,9 @@ allow if true; #[test] fn authorizer_macro_trailing_comma() { - let a = authorizer!(r#"fact("test", {my_key});"#, my_key = "my_value",); + let a = authorizer!(r#"fact("test", {my_key});"#, my_key = "my_value",) + .build() + .unwrap(); assert_eq!( a.dump_code(), r#"fact("test", "my_value"); diff --git a/biscuit-auth/tests/rights.rs b/biscuit-auth/tests/rights.rs index 3741abad..646df48e 100644 --- a/biscuit-auth/tests/rights.rs +++ b/biscuit-auth/tests/rights.rs @@ -31,12 +31,9 @@ fn main() { .unwrap(); println!("{}", biscuit1); - let mut v = biscuit1.authorizer().expect("omg verifier"); - //v.add_resource("file2"); - //v.add_operation("read"); - //v.add_operation("write"); - - v.add_check(rule( + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&biscuit1); + builder.add_check(rule( "right", &[string("right")], &[pred( @@ -44,6 +41,10 @@ fn main() { &[string("authority"), string("file2"), string("write")], )], )); + let mut v = builder.build().expect("omg verifier"); + //v.add_resource("file2"); + //v.add_operation("read"); + //v.add_operation("write"); let res = v.authorize(); println!("{:#?}", res); diff --git a/biscuit-quote/src/lib.rs b/biscuit-quote/src/lib.rs index 8b2380dc..9dd34c48 100644 --- a/biscuit-quote/src/lib.rs +++ b/biscuit-quote/src/lib.rs @@ -129,7 +129,7 @@ pub fn authorizer(input: proc_macro::TokenStream) -> proc_macro::TokenStream { parameters, } = syn::parse_macro_input!(input as ParsedCreateNew); - let ty = syn::parse_quote!(::biscuit_auth::Authorizer); + let ty = syn::parse_quote!(::biscuit_auth::builder::AuthorizerBuilder); let builder = Builder::source(ty, None, datalog, parameters) .unwrap_or_else(|e| abort_call_site!(e.to_string())); @@ -148,7 +148,7 @@ pub fn authorizer_merge(input: proc_macro::TokenStream) -> proc_macro::TokenStre parameters, } = syn::parse_macro_input!(input as ParsedMerge); - let ty = syn::parse_quote!(::biscuit_auth::Authorizer); + let ty = syn::parse_quote!(::biscuit_auth::builder::AuthorizerBuilder); let builder = Builder::source(ty, Some(target), datalog, parameters) .unwrap_or_else(|e| abort_call_site!(e.to_string())); From 3550e8e14f02886deca5d22c218ebb28e0203e7c Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Wed, 27 Nov 2024 17:09:45 +0100 Subject: [PATCH 05/28] cleanup --- biscuit-auth/src/token/authorizer.rs | 467 +------------------ biscuit-auth/src/token/builder/authorizer.rs | 18 + biscuit-auth/src/token/mod.rs | 3 +- 3 files changed, 42 insertions(+), 446 deletions(-) diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index 11ec6762..f14865db 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -81,106 +81,6 @@ impl Authorizer { AuthorizerPolicies::deserialize(data)?.try_into() } - /// add a token to an empty authorizer - pub fn add_token(&mut self, token: &Biscuit) -> Result<(), error::Token> { - if self.blocks.is_some() { - return Err(error::Logic::AuthorizerNotEmpty.into()); - } - - for (i, block) in token.container.blocks.iter().enumerate() { - if let Some(sig) = block.external_signature.as_ref() { - let new_key_id = self.symbols.public_keys.insert(&sig.public_key); - - self.public_key_to_block_id - .entry(new_key_id as usize) - .or_default() - .push(i + 1); - } - } - - let mut blocks = Vec::new(); - - for i in 0..token.block_count() { - let mut block = token.block(i)?; - - self.load_and_translate_block(&mut block, i, &token.symbols)?; - - blocks.push(block); - } - - self.blocks = Some(blocks); - self.token_origins = TrustedOrigins::from_scopes( - &[token::Scope::Previous], - &TrustedOrigins::default(), - token.block_count(), - &self.public_key_to_block_id, - ); - - Ok(()) - } - - /// we need to modify the block loaded from the token, because the authorizer's and the token's symbol table can differ - fn load_and_translate_block( - &mut self, - block: &mut Block, - i: usize, - token_symbols: &SymbolTable, - ) -> Result<(), error::Token> { - // if it is a 3rd party block, it should not affect the main symbol table - let block_symbols = if i == 0 || block.external_key.is_none() { - token_symbols.clone() - } else { - block.symbols.clone() - }; - - let mut block_origin = Origin::default(); - block_origin.insert(i); - - for scope in block.scopes.iter_mut() { - *scope = builder::Scope::convert_from(scope, &block_symbols) - .map(|s| s.convert(&mut self.symbols))?; - } - - let block_trusted_origins = TrustedOrigins::from_scopes( - &block.scopes, - &TrustedOrigins::default(), - i, - &self.public_key_to_block_id, - ); - - for fact in block.facts.iter_mut() { - *fact = Fact::convert_from(fact, &block_symbols)?.convert(&mut self.symbols); - self.world.facts.insert(&block_origin, fact.clone()); - } - - for rule in block.rules.iter_mut() { - if let Err(_message) = rule.validate_variables(&block_symbols) { - return Err( - error::Logic::InvalidBlockRule(0, block_symbols.print_rule(rule)).into(), - ); - } - *rule = rule.translate(&block_symbols, &mut self.symbols)?; - - let rule_trusted_origins = TrustedOrigins::from_scopes( - &rule.scopes, - &block_trusted_origins, - i, - &self.public_key_to_block_id, - ); - - self.world - .rules - .insert(i, &rule_trusted_origins, rule.clone()); - } - - for check in block.checks.iter_mut() { - let c = Check::convert_from(check, &block_symbols)?; - *check = c.convert(&mut self.symbols); - } - - Ok(()) - } - /// serializes a authorizer's content /// /// you can use this to save a set of policies and load them quickly before @@ -201,188 +101,6 @@ impl Authorizer { }) } - /// Add the rules, facts, checks, and policies of another `Authorizer`. - /// If a token has already been added to `other`, it is not merged into `self`. - pub fn merge(&mut self, mut other: Authorizer) { - self.merge_block(other.authorizer_block_builder); - self.policies.append(&mut other.policies); - } - - /// Add the rules, facts, and checks of another `BlockBuilder`. - pub fn merge_block(&mut self, other: BlockBuilder) { - self.authorizer_block_builder.merge(other) - } - - fn add_fact>(&mut self, fact: F) -> Result<(), error::Token> - where - error::Token: From<>::Error>, - { - self.authorizer_block_builder.add_fact(fact) - } - - fn add_rule>(&mut self, rule: Ru) -> Result<(), error::Token> - where - error::Token: From<>::Error>, - { - self.authorizer_block_builder.add_rule(rule) - } - - fn add_check>(&mut self, check: C) -> Result<(), error::Token> - where - error::Token: From<>::Error>, - { - self.authorizer_block_builder.add_check(check) - } - - /// adds some datalog code to the authorizer - /// - /// ```rust - /// extern crate biscuit_auth as biscuit; - /// - /// use biscuit::Authorizer; - /// - /// let mut authorizer = Authorizer::new(); - /// - /// authorizer.add_code(r#" - /// resource("/file1.txt"); - /// - /// check if user(1234); - /// - /// // default allow - /// allow if true; - /// "#).expect("should parse correctly"); - /// ``` - fn add_code>(&mut self, source: T) -> Result<(), error::Token> { - self.add_code_with_params(source, HashMap::new(), HashMap::new()) - } - - fn add_code_with_params>( - &mut self, - source: T, - params: HashMap, - scope_params: HashMap, - ) -> Result<(), error::Token> { - let source = source.as_ref(); - - let source_result = parse_source(source).map_err(|e| { - let e2: biscuit_parser::error::LanguageError = e.into(); - e2 - })?; - - for (_, fact) in source_result.facts.into_iter() { - let mut fact: Fact = fact.into(); - for (name, value) in ¶ms { - let res = match fact.set(name, value) { - Ok(_) => Ok(()), - Err(error::Token::Language( - biscuit_parser::error::LanguageError::Parameters { - missing_parameters, .. - }, - )) if missing_parameters.is_empty() => Ok(()), - Err(e) => Err(e), - }; - res?; - } - fact.validate()?; - self.authorizer_block_builder.facts.push(fact); - } - - for (_, rule) in source_result.rules.into_iter() { - let mut rule: Rule = rule.into(); - for (name, value) in ¶ms { - let res = match rule.set(name, value) { - Ok(_) => Ok(()), - Err(error::Token::Language( - biscuit_parser::error::LanguageError::Parameters { - missing_parameters, .. - }, - )) if missing_parameters.is_empty() => Ok(()), - Err(e) => Err(e), - }; - res?; - } - for (name, value) in &scope_params { - let res = match rule.set_scope(name, *value) { - Ok(_) => Ok(()), - Err(error::Token::Language( - biscuit_parser::error::LanguageError::Parameters { - missing_parameters, .. - }, - )) if missing_parameters.is_empty() => Ok(()), - Err(e) => Err(e), - }; - res?; - } - rule.validate_parameters()?; - self.authorizer_block_builder.rules.push(rule); - } - - for (_, check) in source_result.checks.into_iter() { - let mut check: Check = check.into(); - for (name, value) in ¶ms { - let res = match check.set(name, value) { - Ok(_) => Ok(()), - Err(error::Token::Language( - biscuit_parser::error::LanguageError::Parameters { - missing_parameters, .. - }, - )) if missing_parameters.is_empty() => Ok(()), - Err(e) => Err(e), - }; - res?; - } - for (name, value) in &scope_params { - let res = match check.set_scope(name, *value) { - Ok(_) => Ok(()), - Err(error::Token::Language( - biscuit_parser::error::LanguageError::Parameters { - missing_parameters, .. - }, - )) if missing_parameters.is_empty() => Ok(()), - Err(e) => Err(e), - }; - res?; - } - check.validate_parameters()?; - self.authorizer_block_builder.checks.push(check); - } - for (_, policy) in source_result.policies.into_iter() { - let mut policy: Policy = policy.into(); - for (name, value) in ¶ms { - let res = match policy.set(name, value) { - Ok(_) => Ok(()), - Err(error::Token::Language( - biscuit_parser::error::LanguageError::Parameters { - missing_parameters, .. - }, - )) if missing_parameters.is_empty() => Ok(()), - Err(e) => Err(e), - }; - res?; - } - for (name, value) in &scope_params { - let res = match policy.set_scope(name, *value) { - Ok(_) => Ok(()), - Err(error::Token::Language( - biscuit_parser::error::LanguageError::Parameters { - missing_parameters, .. - }, - )) if missing_parameters.is_empty() => Ok(()), - Err(e) => Err(e), - }; - res?; - } - policy.validate_parameters()?; - self.policies.push(policy); - } - - Ok(()) - } - - fn add_scope(&mut self, scope: Scope) { - self.authorizer_block_builder.add_scope(scope); - } - /// Returns the runtime limits of the authorizer /// /// Those limits cover all the executions under the `authorize`, `query` and `query_all` methods @@ -390,33 +108,11 @@ impl Authorizer { &self.limits } - /// Sets the runtime limits of the authorizer - /// - /// Those limits cover all the executions under the `authorize`, `query` and `query_all` methods - fn set_limits(&mut self, limits: AuthorizerLimits) { - self.limits = limits; - } - /// Returns the currently registered external functions pub fn external_funcs(&self) -> &HashMap { &self.world.extern_funcs } - /// Replaces the registered external functions - fn set_extern_funcs(&mut self, extern_funcs: HashMap) { - self.world.extern_funcs = extern_funcs; - } - - /// Registers the provided external functions (possibly replacing already registered functions) - fn register_extern_funcs(&mut self, extern_funcs: HashMap) { - self.world.extern_funcs.extend(extern_funcs); - } - - /// Registers the provided external function (possibly replacing an already registered function) - fn register_extern_func(&mut self, name: String, func: ExternFunc) { - self.world.extern_funcs.insert(name, func); - } - /// run a query over the authorizer's Datalog engine to gather data /// /// ```rust @@ -605,23 +301,6 @@ impl Authorizer { .collect::, _>>() } - /// adds a fact with the current time - pub fn set_time(&mut self) { - let fact = fact("time", &[date(&SystemTime::now())]); - self.authorizer_block_builder.add_fact(fact).unwrap(); - } - - /// add a policy to the authorizer - pub fn add_policy>(&mut self, policy: P) -> Result<(), error::Token> - where - error::Token: From<

>::Error>, - { - let policy = policy.try_into()?; - policy.validate_parameters()?; - self.policies.push(policy); - Ok(()) - } - /// returns the elapsed execution time pub fn execution_time(&self) -> Duration { self.execution_time @@ -980,23 +659,21 @@ impl Authorizer { } } - let mut facts = self + let facts = self .world .facts .iter_all() .map(|f| Fact::convert_from(f.1, &self.symbols)) .collect::, error::Format>>() .unwrap(); - //facts.extend(self.authorizer_block_builder.facts.clone()); - let mut rules = self + let rules = self .world .rules .iter_all() .map(|r| Rule::convert_from(r.1, &self.symbols)) .collect::, error::Format>>() .unwrap(); - //rules.extend(self.authorizer_block_builder.rules.clone()); (facts, rules, checks, self.policies.clone()) } @@ -1259,110 +936,6 @@ impl AuthorizerPolicies { pub type AuthorizerLimits = RunLimits; -impl BuilderExt for Authorizer { - fn add_resource(&mut self, name: &str) { - let f = fact("resource", &[string(name)]); - self.add_fact(f).unwrap(); - } - fn check_resource(&mut self, name: &str) { - self.add_check(Check { - queries: vec![rule( - "resource_check", - &[string("resource_check")], - &[pred("resource", &[string(name)])], - )], - kind: CheckKind::One, - }) - .unwrap(); - } - fn add_operation(&mut self, name: &str) { - let f = fact("operation", &[string(name)]); - self.add_fact(f).unwrap(); - } - fn check_operation(&mut self, name: &str) { - self.add_check(Check { - queries: vec![rule( - "operation_check", - &[string("operation_check")], - &[pred("operation", &[string(name)])], - )], - kind: CheckKind::One, - }) - .unwrap(); - } - fn check_resource_prefix(&mut self, prefix: &str) { - let check = constrained_rule( - "prefix", - &[var("resource")], - &[pred("resource", &[var("resource")])], - &[Expression { - ops: vec![ - Op::Value(var("resource")), - Op::Value(string(prefix)), - Op::Binary(Binary::Prefix), - ], - }], - ); - - self.add_check(Check { - queries: vec![check], - kind: CheckKind::One, - }) - .unwrap(); - } - - fn check_resource_suffix(&mut self, suffix: &str) { - let check = constrained_rule( - "suffix", - &[var("resource")], - &[pred("resource", &[var("resource")])], - &[Expression { - ops: vec![ - Op::Value(var("resource")), - Op::Value(string(suffix)), - Op::Binary(Binary::Suffix), - ], - }], - ); - - self.add_check(Check { - queries: vec![check], - kind: CheckKind::One, - }) - .unwrap(); - } - - fn check_expiration_date(&mut self, exp: SystemTime) { - let check = constrained_rule( - "expiration", - &[var("time")], - &[pred("time", &[var("time")])], - &[Expression { - ops: vec![ - Op::Value(var("time")), - Op::Value(date(&exp)), - Op::Binary(Binary::LessOrEqual), - ], - }], - ); - - self.add_check(Check { - queries: vec![check], - kind: CheckKind::One, - }) - .unwrap(); - } -} - -impl AuthorizerExt for Authorizer { - fn add_allow_all(&mut self) { - self.add_policy("allow if true").unwrap(); - } - fn add_deny_all(&mut self) { - self.add_policy("deny if true").unwrap(); - } -} - #[cfg(test)] mod tests { use std::time::Duration; @@ -1378,8 +951,9 @@ mod tests { #[test] fn empty_authorizer() { - let mut authorizer = Authorizer::new(); - authorizer.add_policy("allow if true").unwrap(); + let mut builder = AuthorizerBuilder::new(); + builder.add_policy("allow if true").unwrap(); + let mut authorizer = builder.build().unwrap(); assert_eq!( authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -1391,7 +965,7 @@ mod tests { #[test] fn parameter_substitution() { - let mut authorizer = Authorizer::new(); + let mut builder = AuthorizerBuilder::new(); let mut params = HashMap::new(); params.insert("p1".to_string(), "value".into()); params.insert("p2".to_string(), 0i64.into()); @@ -1406,7 +980,7 @@ mod tests { ) .unwrap(), ); - authorizer + builder .add_code_with_params( r#" fact({p1}, "value"); @@ -1418,11 +992,12 @@ mod tests { scope_params, ) .unwrap(); + let _authorizer = builder.build().unwrap(); } #[test] fn forbid_unbound_parameters() { - let mut builder = Authorizer::new(); + let mut builder = AuthorizerBuilder::new(); let mut fact = Fact::try_from("fact({p1}, {p4})").unwrap(); fact.set("p1", "hello").unwrap(); @@ -1480,7 +1055,7 @@ mod tests { #[test] fn forbid_unbound_parameters_in_add_code() { - let mut builder = Authorizer::new(); + let mut builder = AuthorizerBuilder::new(); let mut params = HashMap::new(); params.insert("p1".to_string(), "hello".into()); params.insert("p2".to_string(), 1i64.into()); @@ -1608,16 +1183,16 @@ mod tests { .unwrap(); builder.add_token(&biscuit2); + builder.set_limits(AuthorizerLimits { + max_time: Duration::from_millis(10), //Set 10 milliseconds as the maximum time allowed for the authorization due to "cheap" worker on GitHub Actions + ..Default::default() + }); + let mut authorizer = builder.build().unwrap(); println!("token:\n{}", biscuit2); println!("world:\n{}", authorizer.print_world()); - authorizer.set_limits(AuthorizerLimits { - max_time: Duration::from_millis(10), //Set 10 milliseconds as the maximum time allowed for the authorization due to "cheap" worker on GitHub Actions - ..Default::default() - }); - let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), ..Default::default() @@ -1743,8 +1318,10 @@ mod tests { .unwrap(); let token = token_builder.build(&root).unwrap(); - let mut authorizer = token.authorizer().unwrap(); - authorizer + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&token); + + builder .add_code( r#" authorizer_fact(true); @@ -1754,6 +1331,7 @@ mod tests { "#, ) .unwrap(); + let mut authorizer = builder.build().unwrap(); let output_before_authorization = authorizer.to_string(); assert!( @@ -1810,7 +1388,7 @@ allow if true; #[test] fn rule_validate_variables() { - let mut authorizer = Authorizer::new(); + let mut builder = AuthorizerBuilder::new(); let mut syms = SymbolTable::new(); let rule_name = syms.insert("test"); let pred_name = syms.insert("pred"); @@ -1842,13 +1420,14 @@ allow if true; ); // broken rules directly added to the authorizer currently don’t trigger any error, but silently fail to generate facts when they match - authorizer + builder .add_rule(builder::rule( "test", &[var("unbound")], &[builder::pred("pred", &[builder::var("any")])], )) .unwrap(); + let mut authorizer = builder.build().unwrap(); let res: Vec<(String,)> = authorizer .query(builder::rule( "output", diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs index df1cbc39..4f3298c6 100644 --- a/biscuit-auth/src/token/builder/authorizer.rs +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -53,6 +53,24 @@ impl<'a> AuthorizerBuilder<'a> { self.authorizer_block_builder.add_check(check) } + /// adds some datalog code to the authorizer + /// + /// ```rust + /// extern crate biscuit_auth as biscuit; + /// + /// use biscuit::Authorizer; + /// + /// let mut authorizer = Authorizer::new(); + /// + /// authorizer.add_code(r#" + /// resource("/file1.txt"); + /// + /// check if user(1234); + /// + /// // default allow + /// allow if true; + /// "#).expect("should parse correctly"); + /// ``` pub fn add_code>(&mut self, source: T) -> Result<(), error::Token> { self.add_code_with_params(source, HashMap::new(), HashMap::new()) } diff --git a/biscuit-auth/src/token/mod.rs b/biscuit-auth/src/token/mod.rs index b6cf9282..22c11884 100644 --- a/biscuit-auth/src/token/mod.rs +++ b/biscuit-auth/src/token/mod.rs @@ -884,11 +884,10 @@ mod tests { for fact in facts.drain(..) { builder.add_fact(fact).unwrap(); } + builder.add_allow_all(); let mut authorizer = builder.build().unwrap(); - authorizer.add_allow_all(); - let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), ..Default::default() From 23bf232efc6f902a194f41866fd3cdfb85fcbd2e Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Wed, 27 Nov 2024 17:23:27 +0100 Subject: [PATCH 06/28] fix --- biscuit-auth/benches/token.rs | 110 +++++++++++------- biscuit-auth/examples/third_party.rs | 16 ++- biscuit-auth/examples/verifying_printer.rs | 8 +- biscuit-auth/src/token/authorizer.rs | 17 ++- biscuit-auth/src/token/authorizer/snapshot.rs | 11 +- biscuit-auth/src/token/builder/authorizer.rs | 2 +- 6 files changed, 106 insertions(+), 58 deletions(-) diff --git a/biscuit-auth/benches/token.rs b/biscuit-auth/benches/token.rs index 6b5b0624..929a5a3b 100644 --- a/biscuit-auth/benches/token.rs +++ b/biscuit-auth/benches/token.rs @@ -243,10 +243,12 @@ fn verify_block_2(b: &mut Bencher) { }; let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut verifier = token.authorizer().unwrap(); - verifier.add_fact("resource(\"file1\")"); - verifier.add_fact("operation(\"read\")"); - verifier.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&token); + builder.add_fact("resource(\"file1\")"); + builder.add_fact("operation(\"read\")"); + builder.add_allow_all(); + let mut verifier = builder.build().unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -256,10 +258,12 @@ fn verify_block_2(b: &mut Bencher) { b.bytes = data.len() as u64; b.iter(|| { let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut verifier = token.authorizer().unwrap(); - verifier.add_fact("resource(\"file1\")"); - verifier.add_fact("operation(\"read\")"); - verifier.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&token); + builder.add_fact("resource(\"file1\")"); + builder.add_fact("operation(\"read\")"); + builder.add_allow_all(); + let mut verifier = builder.build().unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -321,10 +325,12 @@ fn verify_block_5(b: &mut Bencher) { }; let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut verifier = token.authorizer().unwrap(); - verifier.add_fact("resource(\"file1\")"); - verifier.add_fact("operation(\"read\")"); - verifier.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&token); + builder.add_fact("resource(\"file1\")"); + builder.add_fact("operation(\"read\")"); + builder.add_allow_all(); + let mut verifier = builder.build().unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -335,10 +341,12 @@ fn verify_block_5(b: &mut Bencher) { b.bytes = data.len() as u64; b.iter(|| { let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut verifier = token.authorizer().unwrap(); - verifier.add_fact("resource(\"file1\")"); - verifier.add_fact("operation(\"read\")"); - verifier.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&token); + builder.add_fact("resource(\"file1\")"); + builder.add_fact("operation(\"read\")"); + builder.add_allow_all(); + let mut verifier = builder.build().unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -373,10 +381,12 @@ fn check_signature_2(b: &mut Bencher) { }; let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut verifier = token.authorizer().unwrap(); - verifier.add_fact("resource(\"file1\")"); - verifier.add_fact("operation(\"read\")"); - verifier.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&token); + builder.add_fact("resource(\"file1\")"); + builder.add_fact("operation(\"read\")"); + builder.add_allow_all(); + let mut verifier = builder.build().unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -441,10 +451,12 @@ fn check_signature_5(b: &mut Bencher) { }; let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut verifier = token.authorizer().unwrap(); - verifier.add_fact("resource(\"file1\")"); - verifier.add_fact("operation(\"read\")"); - verifier.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&token); + builder.add_fact("resource(\"file1\")"); + builder.add_fact("operation(\"read\")"); + builder.add_allow_all(); + let mut verifier = builder.build().unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -483,10 +495,12 @@ fn checks_block_2(b: &mut Bencher) { }; let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut verifier = token.authorizer().unwrap(); - verifier.add_fact("resource(\"file1\")"); - verifier.add_fact("operation(\"read\")"); - verifier.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&token); + builder.add_fact("resource(\"file1\")"); + builder.add_fact("operation(\"read\")"); + builder.add_allow_all(); + let mut verifier = builder.build().unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -497,10 +511,12 @@ fn checks_block_2(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); b.bytes = data.len() as u64; b.iter(|| { - let mut verifier = token.authorizer().unwrap(); - verifier.add_fact("resource(\"file1\")"); - verifier.add_fact("operation(\"read\")"); - verifier.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&token); + builder.add_fact("resource(\"file1\")"); + builder.add_fact("operation(\"read\")"); + builder.add_allow_all(); + let mut verifier = builder.build().unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -535,10 +551,12 @@ fn checks_block_create_verifier2(b: &mut Bencher) { }; let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut verifier = token.authorizer().unwrap(); - verifier.add_fact("resource(\"file1\")"); - verifier.add_fact("operation(\"read\")"); - verifier.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&token); + builder.add_fact("resource(\"file1\")"); + builder.add_fact("operation(\"read\")"); + builder.add_allow_all(); + let mut verifier = builder.build().unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -578,10 +596,12 @@ fn checks_block_verify_only2(b: &mut Bencher) { }; let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut verifier = token.authorizer().unwrap(); - verifier.add_fact("resource(\"file1\")"); - verifier.add_fact("operation(\"read\")"); - verifier.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&token); + builder.add_fact("resource(\"file1\")"); + builder.add_fact("operation(\"read\")"); + builder.add_allow_all(); + let mut verifier = builder.build().unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -591,10 +611,12 @@ fn checks_block_verify_only2(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); b.iter(|| { - let mut verifier = token.authorizer().unwrap(); - verifier.add_fact("resource(\"file1\")"); - verifier.add_fact("operation(\"read\")"); - verifier.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&token); + builder.add_fact("resource(\"file1\")"); + builder.add_fact("operation(\"read\")"); + builder.add_allow_all(); + let mut verifier = builder.build().unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), diff --git a/biscuit-auth/examples/third_party.rs b/biscuit-auth/examples/third_party.rs index b22ab47e..eb3ab52f 100644 --- a/biscuit-auth/examples/third_party.rs +++ b/biscuit-auth/examples/third_party.rs @@ -1,5 +1,5 @@ use biscuit_auth::{ - builder::{Algorithm, BlockBuilder}, + builder::{Algorithm, AuthorizerBuilder, BlockBuilder}, builder_ext::AuthorizerExt, datalog::SymbolTable, Biscuit, KeyPair, @@ -38,13 +38,19 @@ fn main() { println!("biscuit2: {}", biscuit2); - let mut authorizer = biscuit1.authorizer().unwrap(); - authorizer.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&biscuit1); + builder.add_allow_all(); + let mut authorizer = builder.build().unwrap(); + println!("authorize biscuit1:\n{:?}", authorizer.authorize()); println!("world:\n{}", authorizer.print_world()); - let mut authorizer = biscuit2.authorizer().unwrap(); - authorizer.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&biscuit2); + builder.add_allow_all(); + let mut authorizer = builder.build().unwrap(); + println!("authorize biscuit2:\n{:?}", authorizer.authorize()); println!("world:\n{}", authorizer.print_world()); } diff --git a/biscuit-auth/examples/verifying_printer.rs b/biscuit-auth/examples/verifying_printer.rs index 580681d3..41febf25 100644 --- a/biscuit-auth/examples/verifying_printer.rs +++ b/biscuit-auth/examples/verifying_printer.rs @@ -1,4 +1,4 @@ -use biscuit_auth::{builder_ext::AuthorizerExt, PublicKey}; +use biscuit_auth::{builder::AuthorizerBuilder, builder_ext::AuthorizerExt, PublicKey}; fn main() { let mut args = std::env::args(); @@ -25,8 +25,10 @@ fn main() { } println!("token:\n{}", token); - let mut authorizer = token.authorizer().unwrap(); - authorizer.add_allow_all(); + let mut builder = AuthorizerBuilder::new(); + builder.add_token(&token); + builder.add_allow_all(); + let mut authorizer = builder.build().unwrap(); println!("authorizer result: {:?}", authorizer.authorize()); println!("authorizer world:\n{}", authorizer.print_world()); diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index f14865db..0d0eb5e0 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -940,6 +940,8 @@ pub type AuthorizerLimits = RunLimits; mod tests { use std::time::Duration; + use builder::load_and_translate_block; + use datalog::World; use token::{public_keys::PublicKeys, DATALOG_3_1}; use crate::{ @@ -1409,10 +1411,19 @@ allow if true; scopes: vec![], }; + // FIXME assert_eq!( - authorizer - .load_and_translate_block(&mut block, 0, &syms) - .unwrap_err(), + /*builder + .load_and_translate_block(&mut block, 0, &syms)*/ + load_and_translate_block( + &mut block, + 0, + &syms, + &mut SymbolTable::new(), + &mut HashMap::new(), + &mut World::new(), + ) + .unwrap_err(), error::Token::FailedLogic(error::Logic::InvalidBlockRule( 0, "test($unbound) <- pred($any)".to_string() diff --git a/biscuit-auth/src/token/authorizer/snapshot.rs b/biscuit-auth/src/token/authorizer/snapshot.rs index 373aff9f..02274120 100644 --- a/biscuit-auth/src/token/authorizer/snapshot.rs +++ b/biscuit-auth/src/token/authorizer/snapshot.rs @@ -2,7 +2,7 @@ use prost::Message; use std::{collections::HashMap, time::Duration}; use crate::{ - builder::{BlockBuilder, Convert, Policy}, + builder::{load_and_translate_block, BlockBuilder, Convert, Policy}, datalog::{Origin, RunLimits, TrustedOrigins}, error, format::{ @@ -91,7 +91,14 @@ impl super::Authorizer { .push(i); } - authorizer.load_and_translate_block(&mut block, i, &token_symbols)?; + load_and_translate_block( + &mut block, + i, + &token_symbols, + &mut authorizer.symbols, + &mut public_key_to_block_id, + &mut authorizer.world, + )?; blocks.push(block); } diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs index 4f3298c6..6f564a8b 100644 --- a/biscuit-auth/src/token/builder/authorizer.rs +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -380,7 +380,7 @@ impl<'a> AuthorizerBuilder<'a> { } /// we need to modify the block loaded from the token, because the authorizer's and the token's symbol table can differ -fn load_and_translate_block( +pub(crate) fn load_and_translate_block( block: &mut Block, i: usize, token_symbols: &SymbolTable, From a13e1433e8f4096cb569d6daafd6d9df9a124d9e Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Wed, 27 Nov 2024 17:25:02 +0100 Subject: [PATCH 07/28] clean up imports --- biscuit-auth/src/token/authorizer.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index 0d0eb5e0..fe8b45f8 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -1,17 +1,11 @@ //! Authorizer structure and associated functions -use super::builder::{ - constrained_rule, date, fact, pred, rule, string, var, AuthorizerBuilder, Binary, BlockBuilder, - Check, Expression, Fact, Op, Policy, PolicyKind, Rule, Scope, Term, -}; -use super::builder_ext::{AuthorizerExt, BuilderExt}; +use super::builder::{AuthorizerBuilder, BlockBuilder, Check, Fact, Policy, PolicyKind, Rule}; use super::{Biscuit, Block}; -use crate::builder::{self, CheckKind, Convert}; -use crate::crypto::PublicKey; -use crate::datalog::{self, ExternFunc, Origin, RunLimits, SymbolTable, TrustedOrigins}; +use crate::builder::{CheckKind, Convert}; +use crate::datalog::{self, ExternFunc, Origin, RunLimits, TrustedOrigins}; use crate::error; use crate::time::Instant; use crate::token; -use biscuit_parser::parser::parse_source; use prost::Message; use std::collections::{BTreeMap, HashSet}; use std::time::Duration; @@ -20,7 +14,6 @@ use std::{ convert::{TryFrom, TryInto}, default::Default, fmt::Write, - time::SystemTime, }; mod snapshot; @@ -940,10 +933,11 @@ pub type AuthorizerLimits = RunLimits; mod tests { use std::time::Duration; - use builder::load_and_translate_block; - use datalog::World; + use datalog::{SymbolTable, World}; + use token::builder::{self, load_and_translate_block, var}; use token::{public_keys::PublicKeys, DATALOG_3_1}; + use crate::PublicKey; use crate::{ builder::{Algorithm, BiscuitBuilder, BlockBuilder}, KeyPair, From c1d625d017f7afb4d18220909a82a7709ffcbd4a Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Wed, 27 Nov 2024 17:31:16 +0100 Subject: [PATCH 08/28] remove redundant runs --- biscuit-auth/src/token/authorizer.rs | 48 ---------------------------- 1 file changed, 48 deletions(-) diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index fe8b45f8..9b998b43 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -179,7 +179,6 @@ impl Authorizer { &self.public_key_to_block_id, ); - self.world.run_with_limits(&self.symbols, limits)?; let res = self .world .query_rule(rule, usize::MAX, &rule_trusted_origins, &self.symbols)?; @@ -263,8 +262,6 @@ impl Authorizer { rule: datalog::Rule, limits: AuthorizerLimits, ) -> Result, error::Token> { - self.world.run_with_limits(&self.symbols, limits)?; - let rule_trusted_origins = if rule.scopes.is_empty() { self.token_origins.clone() } else { @@ -367,45 +364,6 @@ impl Authorizer { &self.public_key_to_block_id, ); - for fact in &self.authorizer_block_builder.facts { - self.world - .facts - .insert(&authorizer_origin, fact.convert(&mut self.symbols)); - } - - for rule in &self.authorizer_block_builder.rules { - let rule = rule.convert(&mut self.symbols); - - let rule_trusted_origins = TrustedOrigins::from_scopes( - &rule.scopes, - &authorizer_trusted_origins, - usize::MAX, - &self.public_key_to_block_id, - ); - - self.world - .rules - .insert(usize::MAX, &rule_trusted_origins, rule); - } - - limits.max_time = time_limit - Instant::now(); - self.world.run_with_limits(&self.symbols, limits.clone())?; - - let authorizer_scopes: Vec = self - .authorizer_block_builder - .scopes - .clone() - .iter() - .map(|s| s.convert(&mut self.symbols)) - .collect(); - - let authorizer_trusted_origins = TrustedOrigins::from_scopes( - &authorizer_scopes, - &TrustedOrigins::default(), - usize::MAX, - &self.public_key_to_block_id, - ); - for (i, check) in self.authorizer_block_builder.checks.iter().enumerate() { let c = check.convert(&mut self.symbols); let mut successful = false; @@ -558,12 +516,6 @@ impl Authorizer { &self.public_key_to_block_id, ); - limits.max_time = time_limit - Instant::now(); - limits.max_iterations -= self.world.iterations - current_iterations; - current_iterations = self.world.iterations; - - self.world.run_with_limits(&self.symbols, limits.clone())?; - for (j, check) in block.checks.iter().enumerate() { let mut successful = false; From b1ee758a698bb84d6c9dc3e98580d32ecb397040 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Wed, 27 Nov 2024 17:37:20 +0100 Subject: [PATCH 09/28] wip --- biscuit-auth/src/token/builder/authorizer.rs | 48 ++++++++++++-------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs index 6f564a8b..28d6bae1 100644 --- a/biscuit-auth/src/token/builder/authorizer.rs +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -32,25 +32,28 @@ impl<'a> AuthorizerBuilder<'a> { AuthorizerBuilder::default() } - pub fn add_fact>(&mut self, fact: F) -> Result<(), error::Token> + pub fn add_fact>(mut self, fact: F) -> Result where error::Token: From<>::Error>, { - self.authorizer_block_builder.add_fact(fact) + self.authorizer_block_builder.add_fact(fact)?; + Ok(self) } - pub fn add_rule>(&mut self, rule: R) -> Result<(), error::Token> + pub fn add_rule>(mut self, rule: R) -> Result where error::Token: From<>::Error>, { - self.authorizer_block_builder.add_rule(rule) + self.authorizer_block_builder.add_rule(rule)?; + Ok(self) } - pub fn add_check>(&mut self, check: C) -> Result<(), error::Token> + pub fn add_check>(mut self, check: C) -> Result where error::Token: From<>::Error>, { - self.authorizer_block_builder.add_check(check) + self.authorizer_block_builder.add_check(check)?; + Ok(self) } /// adds some datalog code to the authorizer @@ -71,18 +74,18 @@ impl<'a> AuthorizerBuilder<'a> { /// allow if true; /// "#).expect("should parse correctly"); /// ``` - pub fn add_code>(&mut self, source: T) -> Result<(), error::Token> { + pub fn add_code>(mut self, source: T) -> Result { self.add_code_with_params(source, HashMap::new(), HashMap::new()) } /// Add datalog code to the builder, performing parameter subsitution as required /// Unknown parameters are ignored pub fn add_code_with_params>( - &mut self, + mut self, source: T, params: HashMap, scope_params: HashMap, - ) -> Result<(), error::Token> { + ) -> Result { let source = source.as_ref(); let source_result = parse_source(source).map_err(|e| { @@ -197,54 +200,61 @@ impl<'a> AuthorizerBuilder<'a> { self.policies.push(policy); } - Ok(()) + Ok(self) } - pub fn add_scope(&mut self, scope: Scope) { + pub fn add_scope(mut self, scope: Scope) -> Self { self.authorizer_block_builder.add_scope(scope); + self } /// add a policy to the authorizer - pub fn add_policy>(&mut self, policy: P) -> Result<(), error::Token> + pub fn add_policy>(mut self, policy: P) -> Result where error::Token: From<

>::Error>, { let policy = policy.try_into()?; policy.validate_parameters()?; self.policies.push(policy); - Ok(()) + Ok(self) } /// adds a fact with the current time - pub fn set_time(&mut self) { + pub fn set_time(mut self) -> Self { let fact = fact("time", &[date(&SystemTime::now())]); self.authorizer_block_builder.add_fact(fact).unwrap(); + self } /// Sets the runtime limits of the authorizer /// /// Those limits cover all the executions under the `authorize`, `query` and `query_all` methods - pub fn set_limits(&mut self, limits: AuthorizerLimits) { + pub fn set_limits(mut self, limits: AuthorizerLimits) -> Self { self.limits = limits; + self } /// Replaces the registered external functions - pub fn set_extern_funcs(&mut self, extern_funcs: HashMap) { + pub fn set_extern_funcs(mut self, extern_funcs: HashMap) -> Self { self.extern_funcs = extern_funcs; + self } /// Registers the provided external functions (possibly replacing already registered functions) - pub fn register_extern_funcs(&mut self, extern_funcs: HashMap) { + pub fn register_extern_funcs(mut self, extern_funcs: HashMap) -> Self { self.extern_funcs.extend(extern_funcs); + self } /// Registers the provided external function (possibly replacing an already registered function) - pub fn register_extern_func(&mut self, name: String, func: ExternFunc) { + pub fn register_extern_func(mut self, name: String, func: ExternFunc) -> Self { self.extern_funcs.insert(name, func); + self } - pub fn add_token(&mut self, token: &'a Biscuit) { + pub fn add_token(mut self, token: &'a Biscuit) -> Self { self.token = Some(token); + self } pub fn dump_code(&self) -> String { From f7fe86f9dee214a9fc0dcfb16a2cff9fb32ac2a4 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Wed, 27 Nov 2024 18:03:14 +0100 Subject: [PATCH 10/28] refactor the builder API --- biscuit-auth/src/token/authorizer.rs | 82 +++++++++++--------- biscuit-auth/src/token/builder.rs | 62 +++++++-------- biscuit-auth/src/token/builder/biscuit.rs | 91 ++++++++++++++--------- biscuit-auth/src/token/builder/block.rs | 56 ++++++++------ biscuit-auth/src/token/builder_ext.rs | 14 ++-- biscuit-auth/src/token/mod.rs | 23 +++--- 6 files changed, 180 insertions(+), 148 deletions(-) diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index f43f1d01..3fe78241 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -209,22 +209,25 @@ impl Authorizer { } /// Add the rules, facts, and checks of another `BlockBuilder`. - pub fn merge_block(&mut self, other: BlockBuilder) { - self.authorizer_block_builder.merge(other) + pub fn merge_block(&mut self, other: BlockBuilder) -> Result<(), error::Token> { + self.authorizer_block_builder = self.authorizer_block_builder.merge(other); + Ok(()) } pub fn add_fact>(&mut self, fact: F) -> Result<(), error::Token> where error::Token: From<>::Error>, { - self.authorizer_block_builder.add_fact(fact) + self.authorizer_block_builder = self.authorizer_block_builder.add_fact(fact)?; + Ok(()) } pub fn add_rule>(&mut self, rule: Ru) -> Result<(), error::Token> where error::Token: From<>::Error>, { - self.authorizer_block_builder.add_rule(rule) + self.authorizer_block_builder = self.authorizer_block_builder.add_rule(rule)?; + Ok(()) } pub fn add_check>(&mut self, check: C) -> Result<(), error::Token> @@ -608,7 +611,7 @@ impl Authorizer { /// adds a fact with the current time pub fn set_time(&mut self) { let fact = fact("time", &[date(&SystemTime::now())]); - self.authorizer_block_builder.add_fact(fact).unwrap(); + self.authorizer_block_builder = self.authorizer_block_builder.add_fact(fact).unwrap(); } /// add a policy to the authorizer @@ -1213,15 +1216,18 @@ impl TryFrom for Authorizer { let mut authorizer = Self::new(); for fact in facts.into_iter() { - authorizer.authorizer_block_builder.add_fact(fact)?; + authorizer.authorizer_block_builder = + authorizer.authorizer_block_builder.add_fact(fact)?; } for rule in rules.into_iter() { - authorizer.authorizer_block_builder.add_rule(rule)?; + authorizer.authorizer_block_builder = + authorizer.authorizer_block_builder.add_rule(rule)?; } for check in checks.into_iter() { - authorizer.authorizer_block_builder.add_check(check)?; + authorizer.authorizer_block_builder = + authorizer.authorizer_block_builder.add_check(check)?; } for policy in policies { @@ -1271,11 +1277,12 @@ impl AuthorizerPolicies { pub type AuthorizerLimits = RunLimits; impl BuilderExt for Authorizer { - fn add_resource(&mut self, name: &str) { + fn add_resource(mut self, name: &str) -> Self { let f = fact("resource", &[string(name)]); self.add_fact(f).unwrap(); + self } - fn check_resource(&mut self, name: &str) { + fn check_resource(mut self, name: &str) -> Self { self.add_check(Check { queries: vec![rule( "resource_check", @@ -1285,12 +1292,14 @@ impl BuilderExt for Authorizer { kind: CheckKind::One, }) .unwrap(); + self } - fn add_operation(&mut self, name: &str) { + fn add_operation(mut self, name: &str) -> Self { let f = fact("operation", &[string(name)]); self.add_fact(f).unwrap(); + self } - fn check_operation(&mut self, name: &str) { + fn check_operation(mut self, name: &str) -> Self { self.add_check(Check { queries: vec![rule( "operation_check", @@ -1300,8 +1309,9 @@ impl BuilderExt for Authorizer { kind: CheckKind::One, }) .unwrap(); + self } - fn check_resource_prefix(&mut self, prefix: &str) { + fn check_resource_prefix(mut self, prefix: &str) -> Self { let check = constrained_rule( "prefix", &[var("resource")], @@ -1320,9 +1330,10 @@ impl BuilderExt for Authorizer { kind: CheckKind::One, }) .unwrap(); + self } - fn check_resource_suffix(&mut self, suffix: &str) { + fn check_resource_suffix(mut self, suffix: &str) -> Self { let check = constrained_rule( "suffix", &[var("resource")], @@ -1341,9 +1352,10 @@ impl BuilderExt for Authorizer { kind: CheckKind::One, }) .unwrap(); + self } - fn check_expiration_date(&mut self, exp: SystemTime) { + fn check_expiration_date(mut self, exp: SystemTime) -> Self { let check = constrained_rule( "expiration", &[var("time")], @@ -1362,6 +1374,7 @@ impl BuilderExt for Authorizer { kind: CheckKind::One, }) .unwrap(); + self } } @@ -1522,10 +1535,11 @@ mod tests { use crate::Biscuit; use crate::KeyPair; let keypair = KeyPair::new(Algorithm::Ed25519); - let mut builder = Biscuit::builder(); - builder.add_fact("user(\"John Doe\", 42)").unwrap(); - - let biscuit = builder.build(&keypair).unwrap(); + let biscuit = Biscuit::builder() + .add_fact("user(\"John Doe\", 42)") + .unwrap() + .build(&keypair) + .unwrap(); let mut authorizer = biscuit.authorizer().unwrap(); let res: Vec<(String, i64)> = authorizer @@ -1542,10 +1556,11 @@ mod tests { use crate::Biscuit; use crate::KeyPair; let keypair = KeyPair::new(Algorithm::Ed25519); - let mut builder = Biscuit::builder(); - builder.add_fact("user(\"John Doe\")").unwrap(); - - let biscuit = builder.build(&keypair).unwrap(); + let biscuit = Biscuit::builder() + .add_fact("user(\"John Doe\")") + .unwrap() + .build(&keypair) + .unwrap(); let mut authorizer = biscuit.authorizer().unwrap(); let res: Vec<(String,)> = authorizer.query("data($name) <- user($name)").unwrap(); @@ -1559,25 +1574,24 @@ mod tests { let root = KeyPair::new(Algorithm::Ed25519); let external = KeyPair::new(Algorithm::Ed25519); - let mut builder = Biscuit::builder(); let mut scope_params = HashMap::new(); scope_params.insert("external_pub".to_string(), external.public()); - builder + + let biscuit1 = Biscuit::builder() .add_code_with_params( r#"right("read"); - check if group("admin") trusting {external_pub}; - "#, + check if group("admin") trusting {external_pub}; + "#, HashMap::new(), scope_params, ) + .unwrap() + .build(&root) .unwrap(); - let biscuit1 = builder.build(&root).unwrap(); - let req = biscuit1.third_party_request().unwrap(); - let mut builder = BlockBuilder::new(); - builder + let builder = BlockBuilder::new() .add_code( r#"group("admin"); check if right("read"); @@ -1741,8 +1755,7 @@ mod tests { fn authorizer_display_before_and_after_authorization() { let root = KeyPair::new(Algorithm::Ed25519); - let mut token_builder = BiscuitBuilder::new(); - token_builder + let token = BiscuitBuilder::new() .add_code( r#" authority_fact(true); @@ -1750,8 +1763,9 @@ mod tests { check if authority_fact(true), authority_rule(true); "#, ) + .unwrap() + .build(&root) .unwrap(); - let token = token_builder.build(&root).unwrap(); let mut authorizer = token.authorizer().unwrap(); authorizer diff --git a/biscuit-auth/src/token/builder.rs b/biscuit-auth/src/token/builder.rs index 6af2a438..98ed41fd 100644 --- a/biscuit-auth/src/token/builder.rs +++ b/biscuit-auth/src/token/builder.rs @@ -249,7 +249,7 @@ mod tests { .unwrap(); let mut scope_params = HashMap::new(); scope_params.insert("pk".to_string(), pubkey); - builder + builder = builder .add_code_with_params( r#"fact({p1}, "value"); rule($head_var) <- f1($head_var), {p2} > 0 trusting {pk}; @@ -270,52 +270,46 @@ check if true trusting ed25519/6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc #[test] fn forbid_unbound_parameters() { - let mut builder = BlockBuilder::new(); + let builder = BlockBuilder::new(); let mut fact = Fact::try_from("fact({p1}, {p4})").unwrap(); fact.set("p1", "hello").unwrap(); - let res = builder.add_fact(fact); + let res = builder.clone().add_fact(fact); assert_eq!( - res, - Err(error::Token::Language( - biscuit_parser::error::LanguageError::Parameters { - missing_parameters: vec!["p4".to_string()], - unused_parameters: vec![], - } - )) + res.unwrap_err(), + error::Token::Language(biscuit_parser::error::LanguageError::Parameters { + missing_parameters: vec!["p4".to_string()], + unused_parameters: vec![], + }) ); let mut rule = Rule::try_from( "fact($var1, {p2}) <- f1($var1, $var3), f2({p2}, $var3, {p4}), $var3.starts_with({p2})", ) .unwrap(); rule.set("p2", "hello").unwrap(); - let res = builder.add_rule(rule); + let res = builder.clone().add_rule(rule); assert_eq!( - res, - Err(error::Token::Language( - biscuit_parser::error::LanguageError::Parameters { - missing_parameters: vec!["p4".to_string()], - unused_parameters: vec![], - } - )) + res.unwrap_err(), + error::Token::Language(biscuit_parser::error::LanguageError::Parameters { + missing_parameters: vec!["p4".to_string()], + unused_parameters: vec![], + }) ); let mut check = Check::try_from("check if {p4}, {p3}").unwrap(); check.set("p3", true).unwrap(); - let res = builder.add_check(check); + let res = builder.clone().add_check(check); assert_eq!( - res, - Err(error::Token::Language( - biscuit_parser::error::LanguageError::Parameters { - missing_parameters: vec!["p4".to_string()], - unused_parameters: vec![], - } - )) + res.unwrap_err(), + error::Token::Language(biscuit_parser::error::LanguageError::Parameters { + missing_parameters: vec!["p4".to_string()], + unused_parameters: vec![], + }) ); } #[test] fn forbid_unbound_parameters_in_set_code() { - let mut builder = BlockBuilder::new(); + let builder = BlockBuilder::new(); let mut params = HashMap::new(); params.insert("p1".to_string(), "hello".into()); params.insert("p2".to_string(), 1i64.into()); @@ -330,13 +324,11 @@ check if true trusting ed25519/6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc ); assert_eq!( - res, - Err(error::Token::Language( - biscuit_parser::error::LanguageError::Parameters { - missing_parameters: vec!["p3".to_string()], - unused_parameters: vec![], - } - )) - ) + res.unwrap_err(), + error::Token::Language(biscuit_parser::error::LanguageError::Parameters { + missing_parameters: vec!["p3".to_string()], + unused_parameters: vec![], + }) + ); } } diff --git a/biscuit-auth/src/token/builder/biscuit.rs b/biscuit-auth/src/token/builder/biscuit.rs index 8d1fd82e..5bcdce3e 100644 --- a/biscuit-auth/src/token/builder/biscuit.rs +++ b/biscuit-auth/src/token/builder/biscuit.rs @@ -25,65 +25,77 @@ impl BiscuitBuilder { } } - pub fn merge(&mut self, other: BlockBuilder) { - self.inner.merge(other) + pub fn merge(mut self, other: BlockBuilder) -> Self { + self.inner = self.inner.merge(other); + self } - pub fn add_fact>(&mut self, fact: F) -> Result<(), error::Token> + pub fn add_fact>(mut self, fact: F) -> Result where error::Token: From<>::Error>, { - self.inner.add_fact(fact) + self.inner = self.inner.add_fact(fact)?; + Ok(self) } - pub fn add_rule>(&mut self, rule: Ru) -> Result<(), error::Token> + pub fn add_rule>(mut self, rule: Ru) -> Result where error::Token: From<>::Error>, { - self.inner.add_rule(rule) + self.inner = self.inner.add_rule(rule)?; + Ok(self) } - pub fn add_check>(&mut self, check: C) -> Result<(), error::Token> + pub fn add_check>(mut self, check: C) -> Result where error::Token: From<>::Error>, { - self.inner.add_check(check) + self.inner = self.inner.add_check(check)?; + Ok(self) } - pub fn add_code>(&mut self, source: T) -> Result<(), error::Token> { - self.inner - .add_code_with_params(source, HashMap::new(), HashMap::new()) + pub fn add_code>(mut self, source: T) -> Result { + self.inner = self + .inner + .add_code_with_params(source, HashMap::new(), HashMap::new())?; + Ok(self) } pub fn add_code_with_params>( - &mut self, + mut self, source: T, params: HashMap, scope_params: HashMap, - ) -> Result<(), error::Token> { - self.inner - .add_code_with_params(source, params, scope_params) + ) -> Result { + self.inner = self + .inner + .add_code_with_params(source, params, scope_params)?; + Ok(self) } - pub fn add_scope(&mut self, scope: Scope) { - self.inner.add_scope(scope); + pub fn add_scope(mut self, scope: Scope) -> Self { + self.inner = self.inner.add_scope(scope); + self } #[cfg(test)] - pub(crate) fn add_right(&mut self, resource: &str, right: &str) { + pub(crate) fn add_right(self, resource: &str, right: &str) -> Self { use crate::builder::fact; use super::string; - let _ = self.add_fact(fact("right", &[string(resource), string(right)])); + self.add_fact(fact("right", &[string(resource), string(right)])) + .unwrap() } - pub fn set_context(&mut self, context: String) { - self.inner.set_context(context); + pub fn set_context(mut self, context: String) -> Self { + self.inner = self.inner.set_context(context); + self } - pub fn set_root_key_id(&mut self, root_key_id: u32) { + pub fn set_root_key_id(mut self, root_key_id: u32) -> Self { self.root_key_id = Some(root_key_id); + self } /// returns all of the datalog loaded in the biscuit builder @@ -154,25 +166,32 @@ impl fmt::Display for BiscuitBuilder { } impl BuilderExt for BiscuitBuilder { - fn add_resource(&mut self, name: &str) { - self.inner.add_resource(name); + fn add_resource(mut self, name: &str) -> Self { + self.inner = self.inner.add_resource(name); + self } - fn check_resource(&mut self, name: &str) { - self.inner.check_resource(name); + fn check_resource(mut self, name: &str) -> Self { + self.inner = self.inner.check_resource(name); + self } - fn check_resource_prefix(&mut self, prefix: &str) { - self.inner.check_resource_prefix(prefix); + fn check_resource_prefix(mut self, prefix: &str) -> Self { + self.inner = self.inner.check_resource_prefix(prefix); + self } - fn check_resource_suffix(&mut self, suffix: &str) { - self.inner.check_resource_suffix(suffix); + fn check_resource_suffix(mut self, suffix: &str) -> Self { + self.inner = self.inner.check_resource_suffix(suffix); + self } - fn add_operation(&mut self, name: &str) { - self.inner.add_operation(name); + fn add_operation(mut self, name: &str) -> Self { + self.inner = self.inner.add_operation(name); + self } - fn check_operation(&mut self, name: &str) { - self.inner.check_operation(name); + fn check_operation(mut self, name: &str) -> Self { + self.inner = self.inner.check_operation(name); + self } - fn check_expiration_date(&mut self, date: SystemTime) { - self.inner.check_expiration_date(date); + fn check_expiration_date(mut self, date: SystemTime) -> Self { + self.inner = self.inner.check_expiration_date(date); + self } } diff --git a/biscuit-auth/src/token/builder/block.rs b/biscuit-auth/src/token/builder/block.rs index 4967d07e..677d11bf 100644 --- a/biscuit-auth/src/token/builder/block.rs +++ b/biscuit-auth/src/token/builder/block.rs @@ -26,17 +26,18 @@ impl BlockBuilder { BlockBuilder::default() } - pub fn merge(&mut self, mut other: BlockBuilder) { + pub fn merge(mut self, mut other: BlockBuilder) -> Self { self.facts.append(&mut other.facts); self.rules.append(&mut other.rules); self.checks.append(&mut other.checks); if let Some(c) = other.context { - self.set_context(c); + self.context = Some(c); } + self } - pub fn add_fact>(&mut self, fact: F) -> Result<(), error::Token> + pub fn add_fact>(mut self, fact: F) -> Result where error::Token: From<>::Error>, { @@ -44,41 +45,41 @@ impl BlockBuilder { fact.validate()?; self.facts.push(fact); - Ok(()) + Ok(self) } - pub fn add_rule>(&mut self, rule: R) -> Result<(), error::Token> + pub fn add_rule>(mut self, rule: R) -> Result where error::Token: From<>::Error>, { let rule = rule.try_into()?; rule.validate_parameters()?; self.rules.push(rule); - Ok(()) + Ok(self) } - pub fn add_check>(&mut self, check: C) -> Result<(), error::Token> + pub fn add_check>(mut self, check: C) -> Result where error::Token: From<>::Error>, { let check = check.try_into()?; check.validate_parameters()?; self.checks.push(check); - Ok(()) + Ok(self) } - pub fn add_code>(&mut self, source: T) -> Result<(), error::Token> { + pub fn add_code>(self, source: T) -> Result { self.add_code_with_params(source, HashMap::new(), HashMap::new()) } /// Add datalog code to the builder, performing parameter subsitution as required /// Unknown parameters are ignored pub fn add_code_with_params>( - &mut self, + mut self, source: T, params: HashMap, scope_params: HashMap, - ) -> Result<(), error::Token> { + ) -> Result { let input = source.as_ref(); let source_result = parse_block_source(input).map_err(|e| { @@ -164,15 +165,17 @@ impl BlockBuilder { self.checks.push(check); } - Ok(()) + Ok(self) } - pub fn add_scope(&mut self, scope: Scope) { + pub fn add_scope(mut self, scope: Scope) -> Self { self.scopes.push(scope); + self } - pub fn set_context(&mut self, context: String) { + pub fn set_context(mut self, context: String) -> Self { self.context = Some(context); + self } pub(crate) fn build(self, mut symbols: SymbolTable) -> Block { @@ -247,7 +250,7 @@ impl BlockBuilder { // still used in tests but does not make sense for the public API #[cfg(test)] - pub(crate) fn check_right(&mut self, right: &str) { + pub(crate) fn check_right(self, right: &str) -> Result { use crate::builder::{pred, string, var}; use super::rule; @@ -263,7 +266,7 @@ impl BlockBuilder { ], ); - let _ = self.add_check(check); + self.add_check(check) } } @@ -286,10 +289,11 @@ impl fmt::Display for BlockBuilder { } impl BuilderExt for BlockBuilder { - fn add_resource(&mut self, name: &str) { + fn add_resource(mut self, name: &str) -> Self { self.facts.push(fact("resource", &[string(name)])); + self } - fn check_resource(&mut self, name: &str) { + fn check_resource(mut self, name: &str) -> Self { self.checks.push(Check { queries: vec![rule( "resource_check", @@ -298,11 +302,13 @@ impl BuilderExt for BlockBuilder { )], kind: CheckKind::One, }); + self } - fn add_operation(&mut self, name: &str) { + fn add_operation(mut self, name: &str) -> Self { self.facts.push(fact("operation", &[string(name)])); + self } - fn check_operation(&mut self, name: &str) { + fn check_operation(mut self, name: &str) -> Self { self.checks.push(Check { queries: vec![rule( "operation_check", @@ -311,8 +317,9 @@ impl BuilderExt for BlockBuilder { )], kind: CheckKind::One, }); + self } - fn check_resource_prefix(&mut self, prefix: &str) { + fn check_resource_prefix(mut self, prefix: &str) -> Self { let check = constrained_rule( "prefix", &[var("resource")], @@ -330,9 +337,10 @@ impl BuilderExt for BlockBuilder { queries: vec![check], kind: CheckKind::One, }); + self } - fn check_resource_suffix(&mut self, suffix: &str) { + fn check_resource_suffix(mut self, suffix: &str) -> Self { let check = constrained_rule( "suffix", &[var("resource")], @@ -350,9 +358,10 @@ impl BuilderExt for BlockBuilder { queries: vec![check], kind: CheckKind::One, }); + self } - fn check_expiration_date(&mut self, exp: SystemTime) { + fn check_expiration_date(mut self, exp: SystemTime) -> Self { let empty: Vec = Vec::new(); let ops = vec![ Op::Value(var("time")), @@ -370,5 +379,6 @@ impl BuilderExt for BlockBuilder { queries: vec![check], kind: CheckKind::One, }); + self } } diff --git a/biscuit-auth/src/token/builder_ext.rs b/biscuit-auth/src/token/builder_ext.rs index 021cb44a..2983d6c3 100644 --- a/biscuit-auth/src/token/builder_ext.rs +++ b/biscuit-auth/src/token/builder_ext.rs @@ -1,13 +1,13 @@ use std::time::SystemTime; pub trait BuilderExt { - fn add_resource(&mut self, name: &str); - fn check_resource(&mut self, name: &str); - fn check_resource_prefix(&mut self, prefix: &str); - fn check_resource_suffix(&mut self, suffix: &str); - fn add_operation(&mut self, name: &str); - fn check_operation(&mut self, name: &str); - fn check_expiration_date(&mut self, date: SystemTime); + fn add_resource(self, name: &str) -> Self; + fn check_resource(self, name: &str) -> Self; + fn check_resource_prefix(self, prefix: &str) -> Self; + fn check_resource_suffix(self, suffix: &str) -> Self; + fn add_operation(self, name: &str) -> Self; + fn check_operation(self, name: &str) -> Self; + fn check_expiration_date(self, date: SystemTime) -> Self; } pub trait AuthorizerExt { diff --git a/biscuit-auth/src/token/mod.rs b/biscuit-auth/src/token/mod.rs index b0aa3d40..07498b69 100644 --- a/biscuit-auth/src/token/mod.rs +++ b/biscuit-auth/src/token/mod.rs @@ -882,24 +882,21 @@ mod tests { let mut rng: StdRng = SeedableRng::seed_from_u64(0); let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); - let mut builder = Biscuit::builder(); - - builder.add_right("/folder1/file1", "read"); - builder.add_right("/folder1/file1", "write"); - builder.add_right("/folder1/file2", "read"); - builder.add_right("/folder1/file2", "write"); - builder.add_right("/folder2/file3", "read"); - - let biscuit1 = builder + let biscuit1 = Biscuit::builder() + .add_right("/folder1/file1", "read") + .add_right("/folder1/file1", "write") + .add_right("/folder1/file2", "read") + .add_right("/folder1/file2", "write") + .add_right("/folder2/file3", "read") .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); println!("biscuit1 (authority): {}", biscuit1); - let mut block2 = BlockBuilder::new(); - - block2.check_resource_prefix("/folder1/"); - block2.check_right("read"); + let block2 = BlockBuilder::new() + .check_resource_prefix("/folder1/") + .check_right("read") + .unwrap(); let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); From e0948d5b5df7807a32ffc49bd8393c0ec4080b28 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Wed, 27 Nov 2024 18:15:02 +0100 Subject: [PATCH 11/28] use the new API in tests --- biscuit-auth/src/token/mod.rs | 183 +++++++++++--------------- biscuit-auth/src/token/third_party.rs | 14 +- 2 files changed, 82 insertions(+), 115 deletions(-) diff --git a/biscuit-auth/src/token/mod.rs b/biscuit-auth/src/token/mod.rs index 07498b69..78fd96c0 100644 --- a/biscuit-auth/src/token/mod.rs +++ b/biscuit-auth/src/token/mod.rs @@ -720,13 +720,13 @@ mod tests { let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let serialized1 = { - let mut builder = Biscuit::builder(); - - builder.add_fact("right(\"file1\", \"read\")").unwrap(); - builder.add_fact("right(\"file2\", \"read\")").unwrap(); - builder.add_fact("right(\"file1\", \"write\")").unwrap(); - - let biscuit1 = builder + let biscuit1 = Biscuit::builder() + .add_fact("right(\"file1\", \"read\")") + .unwrap() + .add_fact("right(\"file2\", \"read\")") + .unwrap() + .add_fact("right(\"file1\", \"write\")") + .unwrap() .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); @@ -772,9 +772,7 @@ mod tests { let biscuit1_deser = Biscuit::from(&serialized1, root.public()).unwrap(); // new check: can only have read access1 - let mut block2 = BlockBuilder::new(); - - block2 + let block2 = BlockBuilder::new() .add_check(rule( "check1", &[var("resource")], @@ -803,9 +801,7 @@ mod tests { let biscuit2_deser = Biscuit::from(&serialized2, root.public()).unwrap(); // new check: can only access file1 - let mut block3 = BlockBuilder::new(); - - block3 + let block3 = BlockBuilder::new() .add_check(rule( "check2", &[string("file1")], @@ -963,21 +959,18 @@ mod tests { let mut rng: StdRng = SeedableRng::seed_from_u64(0); let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); - let mut builder = Biscuit::builder(); - - builder.add_right("file1", "read"); - builder.add_right("file2", "read"); - - let biscuit1 = builder + let biscuit1 = Biscuit::builder() + .add_right("file1", "read") + .add_right("file2", "read") .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); println!("biscuit1 (authority): {}", biscuit1); - let mut block2 = BlockBuilder::new(); - - block2.check_expiration_date(SystemTime::now() + Duration::from_secs(30)); - block2.add_fact("key(1234)").unwrap(); + let block2 = BlockBuilder::new() + .check_expiration_date(SystemTime::now() + Duration::from_secs(30)) + .add_fact("key(1234)") + .unwrap(); let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); @@ -1021,24 +1014,21 @@ mod tests { fn sealed_token() { let mut rng: StdRng = SeedableRng::seed_from_u64(0); let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); - let mut builder = Biscuit::builder(); - - builder.add_right("/folder1/file1", "read"); - builder.add_right("/folder1/file1", "write"); - builder.add_right("/folder1/file2", "read"); - builder.add_right("/folder1/file2", "write"); - builder.add_right("/folder2/file3", "read"); - - let biscuit1 = builder + let biscuit1 = Biscuit::builder() + .add_right("/folder1/file1", "read") + .add_right("/folder1/file1", "write") + .add_right("/folder1/file2", "read") + .add_right("/folder1/file2", "write") + .add_right("/folder2/file3", "read") .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); println!("biscuit1 (authority): {}", biscuit1); - let mut block2 = BlockBuilder::new(); - - block2.check_resource_prefix("/folder1/"); - block2.check_right("read"); + let block2 = BlockBuilder::new() + .check_resource_prefix("/folder1/") + .check_right("read") + .unwrap(); let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); @@ -1086,19 +1076,13 @@ mod tests { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); - let mut builder = Biscuit::builder(); - - builder + let biscuit1 = Biscuit::builder() .add_fact(fact("right", &[string("file1"), string("read")])) - .unwrap(); - builder + .unwrap() .add_fact(fact("right", &[string("file2"), string("read")])) - .unwrap(); - builder + .unwrap() .add_fact(fact("right", &[string("file1"), string("write")])) - .unwrap(); - - let biscuit1 = builder + .unwrap() .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); println!("{}", biscuit1); @@ -1134,30 +1118,28 @@ mod tests { let mut rng: StdRng = SeedableRng::seed_from_u64(0); let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); - let mut builder = Biscuit::builder(); - - builder.add_right("file1", "read"); - builder.add_right("file2", "read"); - builder.add_fact("key(0000)").unwrap(); - - let biscuit1 = builder + let biscuit1 = Biscuit::builder() + .add_right("file1", "read") + .add_right("file2", "read") + .add_fact("key(0000)") + .unwrap() .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); println!("biscuit1 (authority): {}", biscuit1); - let mut block2 = BlockBuilder::new(); - - block2.check_expiration_date(SystemTime::now() + Duration::from_secs(30)); - block2.add_fact("key(1234)").unwrap(); + let block2 = BlockBuilder::new() + .check_expiration_date(SystemTime::now() + Duration::from_secs(30)) + .add_fact("key(1234)") + .unwrap(); let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); - let mut block3 = BlockBuilder::new(); - - block3.check_expiration_date(SystemTime::now() + Duration::from_secs(10)); - block3.add_fact("key(5678)").unwrap(); + let block3 = BlockBuilder::new() + .check_expiration_date(SystemTime::now() + Duration::from_secs(10)) + .add_fact("key(5678)") + .unwrap(); let keypair3 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit3 = biscuit2.append_with_keypair(&keypair3, block3).unwrap(); @@ -1222,24 +1204,21 @@ mod tests { let mut rng: StdRng = SeedableRng::seed_from_u64(0); let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); - let mut builder = Biscuit::builder(); - - builder + let biscuit1 = Biscuit::builder() .add_check(check( &[pred("resource", &[string("hello")])], CheckKind::One, )) - .unwrap(); - - let biscuit1 = builder + .unwrap() .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); println!("biscuit1 (authority): {}", biscuit1); // new check: can only have read access1 - let mut block2 = BlockBuilder::new(); - block2.add_fact(fact("check1", &[string("test")])).unwrap(); + let block2 = BlockBuilder::new() + .add_fact(fact("check1", &[string("test")])) + .unwrap(); let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); @@ -1326,16 +1305,15 @@ mod tests { let mut rng: StdRng = SeedableRng::seed_from_u64(0); let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); - let mut builder = Biscuit::builder(); - builder.add_fact("bytes(hex:0102AB)").unwrap(); - let biscuit1 = builder + let biscuit1 = Biscuit::builder() + .add_fact("bytes(hex:0102AB)") + .unwrap() .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); println!("biscuit1 (authority): {}", biscuit1); - let mut block2 = BlockBuilder::new(); - block2 + let block2 = BlockBuilder::new() .add_rule("has_bytes($0) <- bytes($0), { hex:00000000, hex:0102AB }.contains($0)") .unwrap(); let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); @@ -1373,20 +1351,15 @@ mod tests { let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let serialized1 = { - let mut builder = Biscuit::builder(); - - builder + let biscuit1 = Biscuit::builder() .add_fact("right(\"/folder1/file1\", \"read\")") - .unwrap(); - builder + .unwrap() .add_fact("right(\"/folder1/file1\", \"write\")") - .unwrap(); - builder + .unwrap() .add_fact("right(\"/folder2/file1\", \"read\")") - .unwrap(); - builder.add_check("check if operation(\"read\")").unwrap(); - - let biscuit1 = builder + .unwrap() + .add_check("check if operation(\"read\")") + .unwrap() .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); @@ -1403,20 +1376,18 @@ mod tests { let biscuit1_deser = Biscuit::from(&serialized1, |_| Ok(root.public())).unwrap(); // new check: can only have read access1 - let mut block2 = BlockBuilder::new(); + let block2 = BlockBuilder::new() // Bypass `check if operation("read")` from authority block - block2 .add_rule("operation(\"read\") <- operation($any)") - .unwrap(); + .unwrap() // Bypass `check if resource($file), $file.starts_with("/folder1/")` from block #1 - block2 .add_rule("resource(\"/folder1/\") <- resource($any)") - .unwrap(); + .unwrap() // Add missing rights - block2.add_rule("right($file, $right) <- right($any1, $any2), resource($file), operation($right)") + .add_rule("right($file, $right) <- right($any1, $any2), resource($file), operation($right)") .unwrap(); let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); @@ -1458,21 +1429,17 @@ mod tests { let mut rng: StdRng = SeedableRng::seed_from_u64(0); let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); - let mut builder = Biscuit::builder(); - - builder.add_check("check if fact($v), $v < 1").unwrap(); - - let biscuit1 = builder + let biscuit1 = Biscuit::builder() + .add_check("check if fact($v), $v < 1") + .unwrap() .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); println!("biscuit1 (authority): {}", biscuit1); - let mut builder = Biscuit::builder(); - - builder.add_check("check all fact($v), $v < 1").unwrap(); - - let biscuit2 = builder + let biscuit2 = Biscuit::builder() + .add_check("check all fact($v), $v < 1") + .unwrap() .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); @@ -1579,13 +1546,13 @@ mod tests { fn verified_unverified_consistency() { let mut rng: StdRng = SeedableRng::seed_from_u64(0); let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); - let mut builder = Biscuit::builder(); - - builder.add_fact("right(\"file1\", \"read\")").unwrap(); - builder.add_fact("right(\"file2\", \"read\")").unwrap(); - builder.add_fact("right(\"file1\", \"write\")").unwrap(); - - let biscuit1 = builder + let biscuit1 = Biscuit::builder() + .add_fact("right(\"file1\", \"read\")") + .unwrap() + .add_fact("right(\"file2\", \"read\")") + .unwrap() + .add_fact("right(\"file1\", \"write\")") + .unwrap() .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); diff --git a/biscuit-auth/src/token/third_party.rs b/biscuit-auth/src/token/third_party.rs index e5b7ea62..acd022a2 100644 --- a/biscuit-auth/src/token/third_party.rs +++ b/biscuit-auth/src/token/third_party.rs @@ -159,13 +159,13 @@ mod tests { fn third_party_request_roundtrip() { let mut rng: rand::rngs::StdRng = rand::SeedableRng::seed_from_u64(0); let root = KeyPair::new_with_rng(crate::builder::Algorithm::Ed25519, &mut rng); - let mut builder = crate::Biscuit::builder(); - - builder.add_fact("right(\"file1\", \"read\")").unwrap(); - builder.add_fact("right(\"file2\", \"read\")").unwrap(); - builder.add_fact("right(\"file1\", \"write\")").unwrap(); - - let biscuit1 = builder + let biscuit1 = crate::Biscuit::builder() + .add_fact("right(\"file1\", \"read\")") + .unwrap() + .add_fact("right(\"file2\", \"read\")") + .unwrap() + .add_fact("right(\"file1\", \"write\")") + .unwrap() .build_with_rng(&root, crate::token::default_symbol_table(), &mut rng) .unwrap(); let req = biscuit1.third_party_request().unwrap(); From cdf646d39c4d752ec4899fbe117975d57af32144 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Wed, 27 Nov 2024 18:44:30 +0100 Subject: [PATCH 12/28] update tests --- biscuit-auth/benches/token.rs | 373 ++++++++++++++------------- biscuit-auth/examples/testcases.rs | 27 +- biscuit-auth/examples/third_party.rs | 14 +- biscuit-auth/src/token/authorizer.rs | 22 +- biscuit-auth/tests/macros.rs | 6 +- biscuit-auth/tests/rights.rs | 32 +-- biscuit-capi/src/lib.rs | 2 +- biscuit-quote/src/lib.rs | 8 +- 8 files changed, 254 insertions(+), 230 deletions(-) diff --git a/biscuit-auth/benches/token.rs b/biscuit-auth/benches/token.rs index 58239b1f..86c0fe29 100644 --- a/biscuit-auth/benches/token.rs +++ b/biscuit-auth/benches/token.rs @@ -13,12 +13,13 @@ fn create_block_1(b: &mut Bencher) { let mut rng = OsRng; let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let mut builder = Biscuit::builder(); - builder.add_fact(fact("right", &[string("file1"), string("read")])); - builder.add_fact(fact("right", &[string("file2"), string("read")])); - builder.add_fact(fact("right", &[string("file1"), string("write")])); - - let token = builder + let token = Biscuit::builder() + .add_fact(fact("right", &[string("file1"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file2"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file1"), string("write")])) + .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); let data = token.to_vec().unwrap(); @@ -26,15 +27,16 @@ fn create_block_1(b: &mut Bencher) { b.bytes = data.len() as u64; assert_eq!(b.bytes, 206); b.iter(|| { - let mut builder = Biscuit::builder(); - builder.add_fact(fact("right", &[string("file1"), string("read")])); - builder.add_fact(fact("right", &[string("file2"), string("read")])); - builder.add_fact(fact("right", &[string("file1"), string("write")])); - - let token = builder + let token = Biscuit::builder() + .add_fact(fact("right", &[string("file1"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file2"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file1"), string("write")])) + .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); - let data = token.to_vec().unwrap(); + let _data = token.to_vec().unwrap(); }); } @@ -43,19 +45,20 @@ fn append_block_2(b: &mut Bencher) { let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let mut builder = Biscuit::builder(); - builder.add_fact(fact("right", &[string("file1"), string("read")])); - builder.add_fact(fact("right", &[string("file2"), string("read")])); - builder.add_fact(fact("right", &[string("file1"), string("write")])); - - let token = builder + let token = Biscuit::builder() + .add_fact(fact("right", &[string("file1"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file2"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file1"), string("write")])) + .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); let base_data = token.to_vec().unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); let data = token2.to_vec().unwrap(); @@ -64,12 +67,12 @@ fn append_block_2(b: &mut Bencher) { assert_eq!(b.bytes, 189); b.iter(|| { let token = Biscuit::from(&base_data, &root.public()).unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); - let data = token2.to_vec().unwrap(); + let _data = token2.to_vec().unwrap(); }); } @@ -81,19 +84,20 @@ fn append_block_5(b: &mut Bencher) { let keypair4 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let keypair5 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let mut builder = Biscuit::builder(); - builder.add_fact(fact("right", &[string("file1"), string("read")])); - builder.add_fact(fact("right", &[string("file2"), string("read")])); - builder.add_fact(fact("right", &[string("file1"), string("write")])); - - let token = builder + let token = Biscuit::builder() + .add_fact(fact("right", &[string("file1"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file2"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file1"), string("write")])) + .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); let base_data = token.to_vec().unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); let data = token2.to_vec().unwrap(); @@ -102,28 +106,34 @@ fn append_block_5(b: &mut Bencher) { assert_eq!(b.bytes, 189); b.iter(|| { let token2 = Biscuit::from(&data, &root.public()).unwrap(); - let mut b = BlockBuilder::new(); - b.check_resource("file1"); - b.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); - let token3 = token2.append_with_keypair(&keypair3, b).unwrap(); + let token3 = token2 + .append_with_keypair(&keypair3, block_builder) + .unwrap(); let data = token3.to_vec().unwrap(); let token3 = Biscuit::from(&data, &root.public()).unwrap(); - let mut b = BlockBuilder::new(); - b.check_resource("file1"); - b.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); - let token4 = token3.append_with_keypair(&keypair4, b).unwrap(); + let token4 = token3 + .append_with_keypair(&keypair4, block_builder) + .unwrap(); let data = token4.to_vec().unwrap(); let token4 = Biscuit::from(&data, &root.public()).unwrap(); - let mut b = BlockBuilder::new(); - b.check_resource("file1"); - b.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); - let token5 = token4.append_with_keypair(&keypair5, b).unwrap(); - let data = token5.to_vec().unwrap(); + let token5 = token4 + .append_with_keypair(&keypair5, block_builder) + .unwrap(); + let _data = token5.to_vec().unwrap(); }); } @@ -132,19 +142,20 @@ fn unverified_append_block_2(b: &mut Bencher) { let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let mut builder = Biscuit::builder(); - builder.add_fact(fact("right", &[string("file1"), string("read")])); - builder.add_fact(fact("right", &[string("file2"), string("read")])); - builder.add_fact(fact("right", &[string("file1"), string("write")])); - - let token = builder + let token = Biscuit::builder() + .add_fact(fact("right", &[string("file1"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file2"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file1"), string("write")])) + .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); let base_data = token.to_vec().unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); let data = token2.to_vec().unwrap(); @@ -153,12 +164,12 @@ fn unverified_append_block_2(b: &mut Bencher) { assert_eq!(b.bytes, 189); b.iter(|| { let token = UnverifiedBiscuit::from(&base_data).unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); - let data = token2.to_vec().unwrap(); + let _data = token2.to_vec().unwrap(); }); } @@ -170,19 +181,20 @@ fn unverified_append_block_5(b: &mut Bencher) { let keypair4 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let keypair5 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - let mut builder = Biscuit::builder(); - builder.add_fact(fact("right", &[string("file1"), string("read")])); - builder.add_fact(fact("right", &[string("file2"), string("read")])); - builder.add_fact(fact("right", &[string("file1"), string("write")])); - - let token = builder + let token = Biscuit::builder() + .add_fact(fact("right", &[string("file1"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file2"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file1"), string("write")])) + .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); let base_data = token.to_vec().unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); let data = token2.to_vec().unwrap(); @@ -191,28 +203,34 @@ fn unverified_append_block_5(b: &mut Bencher) { assert_eq!(b.bytes, 189); b.iter(|| { let token2 = UnverifiedBiscuit::from(&data).unwrap(); - let mut b = BlockBuilder::new(); - b.check_resource("file1"); - b.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); - let token3 = token2.append_with_keypair(&keypair3, b).unwrap(); + let token3 = token2 + .append_with_keypair(&keypair3, block_builder) + .unwrap(); let data = token3.to_vec().unwrap(); let token3 = UnverifiedBiscuit::from(&data).unwrap(); - let mut b = BlockBuilder::new(); - b.check_resource("file1"); - b.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); - let token4 = token3.append_with_keypair(&keypair4, b).unwrap(); + let token4 = token3 + .append_with_keypair(&keypair4, block_builder) + .unwrap(); let data = token4.to_vec().unwrap(); let token4 = UnverifiedBiscuit::from(&data).unwrap(); - let mut b = BlockBuilder::new(); - b.check_resource("file1"); - b.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); - let token5 = token4.append_with_keypair(&keypair5, b).unwrap(); - let data = token5.to_vec().unwrap(); + let token5 = token4 + .append_with_keypair(&keypair5, block_builder) + .unwrap(); + let _data = token5.to_vec().unwrap(); }); } @@ -222,19 +240,20 @@ fn verify_block_2(b: &mut Bencher) { let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let data = { - let mut builder = Biscuit::builder(); - builder.add_fact(fact("right", &[string("file1"), string("read")])); - builder.add_fact(fact("right", &[string("file2"), string("read")])); - builder.add_fact(fact("right", &[string("file1"), string("write")])); - - let token = builder + let token = Biscuit::builder() + .add_fact(fact("right", &[string("file1"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file2"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file1"), string("write")])) + .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); - let base_data = token.to_vec().unwrap(); + let _base_data = token.to_vec().unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); token2.to_vec().unwrap() @@ -276,41 +295,42 @@ fn verify_block_5(b: &mut Bencher) { let keypair5 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let data = { - let mut builder = Biscuit::builder(); - builder.add_fact(fact("right", &[string("file1"), string("read")])); - builder.add_fact(fact("right", &[string("file2"), string("read")])); - builder.add_fact(fact("right", &[string("file1"), string("write")])); - - let token = builder + let token = Biscuit::builder() + .add_fact(fact("right", &[string("file1"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file2"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file1"), string("write")])) + .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); - let base_data = token.to_vec().unwrap(); + let _base_data = token.to_vec().unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token3 = token2 .append_with_keypair(&keypair3, block_builder) .unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token4 = token3 .append_with_keypair(&keypair4, block_builder) .unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token5 = token4 .append_with_keypair(&keypair5, block_builder) @@ -352,19 +372,20 @@ fn check_signature_2(b: &mut Bencher) { let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let data = { - let mut builder = Biscuit::builder(); - builder.add_fact(fact("right", &[string("file1"), string("read")])); - builder.add_fact(fact("right", &[string("file2"), string("read")])); - builder.add_fact(fact("right", &[string("file1"), string("write")])); - - let token = builder + let token = Biscuit::builder() + .add_fact(fact("right", &[string("file1"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file2"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file1"), string("write")])) + .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); - let base_data = token.to_vec().unwrap(); + let _base_data = token.to_vec().unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); token2.to_vec().unwrap() @@ -384,7 +405,7 @@ fn check_signature_2(b: &mut Bencher) { b.bytes = data.len() as u64; b.iter(|| { - let token = Biscuit::from(&data, &root.public()).unwrap(); + let _token = Biscuit::from(&data, &root.public()).unwrap(); }); } @@ -397,40 +418,41 @@ fn check_signature_5(b: &mut Bencher) { let keypair5 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let data = { - let mut builder = Biscuit::builder(); - builder.add_fact(fact("right", &[string("file1"), string("read")])); - builder.add_fact(fact("right", &[string("file2"), string("read")])); - builder.add_fact(fact("right", &[string("file1"), string("write")])); - - let token = builder + let token = Biscuit::builder() + .add_fact(fact("right", &[string("file1"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file2"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file1"), string("write")])) + .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); - let base_data = token.to_vec().unwrap(); + let _base_data = token.to_vec().unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token3 = token2 .append_with_keypair(&keypair3, block_builder) .unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token4 = token3 .append_with_keypair(&keypair4, block_builder) .unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token5 = token4 .append_with_keypair(&keypair5, block_builder) @@ -452,7 +474,7 @@ fn check_signature_5(b: &mut Bencher) { b.bytes = data.len() as u64; b.iter(|| { - let token = Biscuit::from(&data, &root.public()).unwrap(); + let _token = Biscuit::from(&data, &root.public()).unwrap(); }); } @@ -462,19 +484,20 @@ fn checks_block_2(b: &mut Bencher) { let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let data = { - let mut builder = Biscuit::builder(); - builder.add_fact(fact("right", &[string("file1"), string("read")])); - builder.add_fact(fact("right", &[string("file2"), string("read")])); - builder.add_fact(fact("right", &[string("file1"), string("write")])); - - let token = builder + let token = Biscuit::builder() + .add_fact(fact("right", &[string("file1"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file2"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file1"), string("write")])) + .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); - let base_data = token.to_vec().unwrap(); + let _base_data = token.to_vec().unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); token2.to_vec().unwrap() @@ -514,19 +537,20 @@ fn checks_block_create_verifier2(b: &mut Bencher) { let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let data = { - let mut builder = Biscuit::builder(); - builder.add_fact(fact("right", &[string("file1"), string("read")])); - builder.add_fact(fact("right", &[string("file2"), string("read")])); - builder.add_fact(fact("right", &[string("file1"), string("write")])); - - let token = builder + let token = Biscuit::builder() + .add_fact(fact("right", &[string("file1"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file2"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file1"), string("write")])) + .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); - let base_data = token.to_vec().unwrap(); + let _base_data = token.to_vec().unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); token2.to_vec().unwrap() @@ -547,7 +571,7 @@ fn checks_block_create_verifier2(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); b.bytes = data.len() as u64; b.iter(|| { - let mut verifier = token.authorizer().unwrap(); + let _verifier = token.authorizer().unwrap(); }); } @@ -557,19 +581,20 @@ fn checks_block_verify_only2(b: &mut Bencher) { let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let data = { - let mut builder = Biscuit::builder(); - builder.add_fact(fact("right", &[string("file1"), string("read")])); - builder.add_fact(fact("right", &[string("file2"), string("read")])); - builder.add_fact(fact("right", &[string("file1"), string("write")])); - - let token = builder + let token = Biscuit::builder() + .add_fact(fact("right", &[string("file1"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file2"), string("read")])) + .unwrap() + .add_fact(fact("right", &[string("file1"), string("write")])) + .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); - let base_data = token.to_vec().unwrap(); + let _base_data = token.to_vec().unwrap(); - let mut block_builder = BlockBuilder::new(); - block_builder.check_resource("file1"); - block_builder.check_operation("read"); + let block_builder = BlockBuilder::new() + .check_resource("file1") + .check_operation("read"); let token2 = token.append_with_keypair(&keypair2, block_builder).unwrap(); token2.to_vec().unwrap() diff --git a/biscuit-auth/examples/testcases.rs b/biscuit-auth/examples/testcases.rs index d8a33d9f..faf6b021 100644 --- a/biscuit-auth/examples/testcases.rs +++ b/biscuit-auth/examples/testcases.rs @@ -878,9 +878,9 @@ fn scoped_rules(target: &str, root: &KeyPair, test: bool) -> TestResult { ) .unwrap(); - let mut block3 = BlockBuilder::new(); - - block3.add_fact(r#"owner("alice", "file2")"#).unwrap(); + let block3 = BlockBuilder::new() + .add_fact(r#"owner("alice", "file2")"#) + .unwrap(); let keypair3 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit3 = biscuit2.append_with_keypair(&keypair3, block3).unwrap(); @@ -973,14 +973,13 @@ fn expired_token(target: &str, root: &KeyPair, test: bool) -> TestResult { .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); - let mut block2 = block!(r#"check if resource("file1");"#); - - // January 1 2019 - block2.check_expiration_date( - UNIX_EPOCH - .checked_add(Duration::from_secs(49 * 365 * 24 * 3600)) - .unwrap(), - ); + let block2 = block!(r#"check if resource("file1");"#) + // January 1 2019 + .check_expiration_date( + UNIX_EPOCH + .checked_add(Duration::from_secs(49 * 365 * 24 * 3600)) + .unwrap(), + ); let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); @@ -1410,10 +1409,8 @@ fn unbound_variables_in_rule(target: &str, root: &KeyPair, test: bool) -> TestRe .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); - let mut block2 = BlockBuilder::new(); - - // this one does not go through the parser because it checks for unused variables - block2 + let block2 = BlockBuilder::new() + // this one does not go through the parser because it checks for unused variables .add_rule(rule( "operation", &[var("unbound"), string("read")], diff --git a/biscuit-auth/examples/third_party.rs b/biscuit-auth/examples/third_party.rs index 67fd6d99..1a206e08 100644 --- a/biscuit-auth/examples/third_party.rs +++ b/biscuit-auth/examples/third_party.rs @@ -7,18 +7,13 @@ fn main() { let mut rng: StdRng = SeedableRng::seed_from_u64(0); let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let external = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); - - let mut builder = Biscuit::builder(); - let external_pub = hex::encode(external.public().to_bytes()); - builder + let biscuit1 = Biscuit::builder() .add_check( format!("check if external_fact(\"hello\") trusting ed25519/{external_pub}").as_str(), ) - .unwrap(); - - let biscuit1 = builder + .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); @@ -27,8 +22,9 @@ fn main() { let serialized_req = biscuit1.third_party_request().unwrap().serialize().unwrap(); let req = biscuit_auth::ThirdPartyRequest::deserialize(&serialized_req).unwrap(); - let mut builder = BlockBuilder::new(); - builder.add_fact("external_fact(\"hello\")").unwrap(); + let builder = BlockBuilder::new() + .add_fact("external_fact(\"hello\")") + .unwrap(); let res = req.create_block(&external.private(), builder).unwrap(); let biscuit2 = biscuit1.append_third_party(external.public(), res).unwrap(); diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index 3fe78241..b348aed8 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -203,14 +203,15 @@ impl Authorizer { /// Add the rules, facts, checks, and policies of another `Authorizer`. /// If a token has already been added to `other`, it is not merged into `self`. - pub fn merge(&mut self, mut other: Authorizer) { - self.merge_block(other.authorizer_block_builder); + pub fn merge(&mut self, mut other: Authorizer) -> Result<(), error::Token> { + self.merge_block(other.authorizer_block_builder)?; self.policies.append(&mut other.policies); + Ok(()) } /// Add the rules, facts, and checks of another `BlockBuilder`. pub fn merge_block(&mut self, other: BlockBuilder) -> Result<(), error::Token> { - self.authorizer_block_builder = self.authorizer_block_builder.merge(other); + self.authorizer_block_builder = self.authorizer_block_builder.clone().merge(other); Ok(()) } @@ -218,7 +219,7 @@ impl Authorizer { where error::Token: From<>::Error>, { - self.authorizer_block_builder = self.authorizer_block_builder.add_fact(fact)?; + self.authorizer_block_builder = self.authorizer_block_builder.clone().add_fact(fact)?; Ok(()) } @@ -226,7 +227,7 @@ impl Authorizer { where error::Token: From<>::Error>, { - self.authorizer_block_builder = self.authorizer_block_builder.add_rule(rule)?; + self.authorizer_block_builder = self.authorizer_block_builder.clone().add_rule(rule)?; Ok(()) } @@ -234,7 +235,8 @@ impl Authorizer { where error::Token: From<>::Error>, { - self.authorizer_block_builder.add_check(check) + self.authorizer_block_builder = self.authorizer_block_builder.clone().add_check(check)?; + Ok(()) } /// adds some datalog code to the authorizer @@ -383,7 +385,7 @@ impl Authorizer { } pub fn add_scope(&mut self, scope: Scope) { - self.authorizer_block_builder.add_scope(scope); + self.authorizer_block_builder = self.authorizer_block_builder.clone().add_scope(scope); } /// Returns the runtime limits of the authorizer @@ -611,7 +613,11 @@ impl Authorizer { /// adds a fact with the current time pub fn set_time(&mut self) { let fact = fact("time", &[date(&SystemTime::now())]); - self.authorizer_block_builder = self.authorizer_block_builder.add_fact(fact).unwrap(); + self.authorizer_block_builder = self + .authorizer_block_builder + .clone() + .add_fact(fact) + .unwrap(); } /// add a policy to the authorizer diff --git a/biscuit-auth/tests/macros.rs b/biscuit-auth/tests/macros.rs index 0922b342..3df56965 100644 --- a/biscuit-auth/tests/macros.rs +++ b/biscuit-auth/tests/macros.rs @@ -23,7 +23,7 @@ fn block_macro() { ); let is_true = true; - block_merge!(&mut b, r#"appended({is_true});"#); + b = block_merge!(b, r#"appended({is_true});"#); assert_eq!( b.to_string(), @@ -123,8 +123,8 @@ fn biscuit_macro() { b.set_root_key_id(2); let is_true = true; - biscuit_merge!( - &mut b, + b = biscuit_merge!( + b, r#"appended({is_true}); check if true; "# diff --git a/biscuit-auth/tests/rights.rs b/biscuit-auth/tests/rights.rs index 3741abad..89a8019e 100644 --- a/biscuit-auth/tests/rights.rs +++ b/biscuit-auth/tests/rights.rs @@ -11,22 +11,22 @@ fn main() { let mut rng: StdRng = SeedableRng::seed_from_u64(1234); let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); - let mut builder = Biscuit::builder(); - - builder.add_fact(fact( - "right", - &[string("authority"), string("file1"), string("read")], - )); - builder.add_fact(fact( - "right", - &[string("authority"), string("file2"), string("read")], - )); - builder.add_fact(fact( - "right", - &[string("authority"), string("file1"), string("write")], - )); - - let biscuit1 = builder + let biscuit1 = Biscuit::builder() + .add_fact(fact( + "right", + &[string("authority"), string("file1"), string("read")], + )) + .unwrap() + .add_fact(fact( + "right", + &[string("authority"), string("file2"), string("read")], + )) + .unwrap() + .add_fact(fact( + "right", + &[string("authority"), string("file1"), string("write")], + )) + .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); println!("{}", biscuit1); diff --git a/biscuit-capi/src/lib.rs b/biscuit-capi/src/lib.rs index 2232c47f..235029cc 100644 --- a/biscuit-capi/src/lib.rs +++ b/biscuit-capi/src/lib.rs @@ -858,7 +858,7 @@ pub unsafe extern "C" fn block_builder_add_fact( return false; } - builder + builder.0 = builder .0 .add_fact(s.unwrap()) .map_err(|e| { diff --git a/biscuit-quote/src/lib.rs b/biscuit-quote/src/lib.rs index 8b2380dc..4a660668 100644 --- a/biscuit-quote/src/lib.rs +++ b/biscuit-quote/src/lib.rs @@ -349,7 +349,7 @@ impl Item { }, middle: TokenStream::new(), end: quote! { - __biscuit_auth_builder.add_fact(__biscuit_auth_item).unwrap(); + __biscuit_auth_builder = __biscuit_auth_builder.add_fact(__biscuit_auth_item).unwrap(); }, } } @@ -361,7 +361,7 @@ impl Item { }, middle: TokenStream::new(), end: quote! { - __biscuit_auth_builder.add_rule(__biscuit_auth_item).unwrap(); + __biscuit_auth_builder = __biscuit_auth_builder.add_rule(__biscuit_auth_item).unwrap(); }, } } @@ -374,7 +374,7 @@ impl Item { }, middle: TokenStream::new(), end: quote! { - __biscuit_auth_builder.add_check(__biscuit_auth_item).unwrap(); + __biscuit_auth_builder =__biscuit_auth_builder.add_check(__biscuit_auth_item).unwrap(); }, } } @@ -387,7 +387,7 @@ impl Item { }, middle: TokenStream::new(), end: quote! { - __biscuit_auth_builder.add_policy(__biscuit_auth_item).unwrap(); + __biscuit_auth_builder = __biscuit_auth_builder.add_policy(__biscuit_auth_item).unwrap(); }, } } From 15389afdcbf3b2cc47e061ca79e32bc402ba0930 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Wed, 27 Nov 2024 18:55:59 +0100 Subject: [PATCH 13/28] update the capi --- biscuit-capi/src/lib.rs | 92 ++++++++++++++++++++++++++++++++++------- 1 file changed, 77 insertions(+), 15 deletions(-) diff --git a/biscuit-capi/src/lib.rs b/biscuit-capi/src/lib.rs index 235029cc..d156306a 100644 --- a/biscuit-capi/src/lib.rs +++ b/biscuit-capi/src/lib.rs @@ -292,8 +292,8 @@ pub extern "C" fn error_check_is_authorizer(check_index: u64) -> bool { pub struct Biscuit(biscuit_auth::Biscuit); pub struct KeyPair(biscuit_auth::KeyPair); pub struct PublicKey(biscuit_auth::PublicKey); -pub struct BiscuitBuilder(biscuit_auth::builder::BiscuitBuilder); -pub struct BlockBuilder(biscuit_auth::builder::BlockBuilder); +pub struct BiscuitBuilder(Option); +pub struct BlockBuilder(Option); pub struct Authorizer(biscuit_auth::Authorizer); #[repr(C)] @@ -422,9 +422,45 @@ pub unsafe extern "C" fn public_key_deserialize( #[no_mangle] pub unsafe extern "C" fn public_key_free(_kp: Option>) {} +impl BiscuitBuilder { + fn set_context(&mut self, context: &str) { + let mut inner = self.0.take().unwrap(); + inner = inner.set_context(context.to_string()); + self.0 = Some(inner); + } + + fn set_root_key_id(&mut self, root_key_id: u32) { + let mut inner = self.0.take().unwrap(); + inner = inner.set_root_key_id(root_key_id); + self.0 = Some(inner); + } + + fn add_fact(&mut self, fact: &str) -> Result<(), biscuit_auth::error::Token> { + let mut inner = self.0.take().unwrap(); + inner = inner.add_fact(fact)?; + self.0 = Some(inner); + Ok(()) + } + + fn add_rule(&mut self, rule: &str) -> Result<(), biscuit_auth::error::Token> { + let mut inner = self.0.take().unwrap(); + inner = inner.add_rule(rule)?; + self.0 = Some(inner); + Ok(()) + } + + fn add_check(&mut self, check: &str) -> Result<(), biscuit_auth::error::Token> { + let mut inner = self.0.take().unwrap(); + inner = inner.add_check(check)?; + self.0 = Some(inner); + Ok(()) + } +} #[no_mangle] pub unsafe extern "C" fn biscuit_builder() -> Option> { - Some(Box::new(BiscuitBuilder(biscuit_auth::Biscuit::builder()))) + Some(Box::new(BiscuitBuilder(Some( + biscuit_auth::Biscuit::builder(), + )))) } #[no_mangle] @@ -446,7 +482,7 @@ pub unsafe extern "C" fn biscuit_builder_set_context( false } Ok(context) => { - builder.0.set_context(context.to_string()); + builder.set_context(context); true } } @@ -463,7 +499,7 @@ pub unsafe extern "C" fn biscuit_builder_set_root_key_id( } let builder = builder.unwrap(); - builder.0.set_root_key_id(root_key_id); + builder.set_root_key_id(root_key_id); true } @@ -486,7 +522,6 @@ pub unsafe extern "C" fn biscuit_builder_add_fact( } builder - .0 .add_fact(s.unwrap()) .map_err(|e| { update_last_error(Error::Biscuit(e)); @@ -513,7 +548,6 @@ pub unsafe extern "C" fn biscuit_builder_add_rule( } builder - .0 .add_rule(s.unwrap()) .map_err(|e| { update_last_error(Error::Biscuit(e)); @@ -540,7 +574,6 @@ pub unsafe extern "C" fn biscuit_builder_add_check( } builder - .0 .add_check(s.unwrap()) .map_err(|e| { update_last_error(Error::Biscuit(e)); @@ -577,6 +610,7 @@ pub unsafe extern "C" fn biscuit_builder_build( (*builder) .0 .clone() + .expect("builder is none") .build_with_rng(&key_pair.0, SymbolTable::default(), &mut rng) .map(Biscuit) .map(Box::new) @@ -762,9 +796,40 @@ pub unsafe extern "C" fn biscuit_block_context( } } +impl BlockBuilder { + fn set_context(&mut self, context: &str) { + let mut inner = self.0.take().unwrap(); + inner = inner.set_context(context.to_string()); + self.0 = Some(inner); + } + + fn add_fact(&mut self, fact: &str) -> Result<(), biscuit_auth::error::Token> { + let mut inner = self.0.take().unwrap(); + inner = inner.add_fact(fact)?; + self.0 = Some(inner); + Ok(()) + } + + fn add_rule(&mut self, rule: &str) -> Result<(), biscuit_auth::error::Token> { + let mut inner = self.0.take().unwrap(); + inner = inner.add_rule(rule)?; + self.0 = Some(inner); + Ok(()) + } + + fn add_check(&mut self, check: &str) -> Result<(), biscuit_auth::error::Token> { + let mut inner = self.0.take().unwrap(); + inner = inner.add_check(check)?; + self.0 = Some(inner); + Ok(()) + } +} + #[no_mangle] pub unsafe extern "C" fn create_block() -> Box { - Box::new(BlockBuilder(biscuit_auth::builder::BlockBuilder::new())) + Box::new(BlockBuilder(Some( + biscuit_auth::builder::BlockBuilder::new(), + ))) } #[no_mangle] @@ -790,7 +855,7 @@ pub unsafe extern "C" fn biscuit_append_block( match biscuit .0 - .append_with_keypair(&key_pair.0, builder.0.clone()) + .append_with_keypair(&key_pair.0, builder.0.clone().expect("builder is none")) { Ok(token) => Some(Box::new(Biscuit(token))), Err(e) => { @@ -834,7 +899,7 @@ pub unsafe extern "C" fn block_builder_set_context( false } Ok(context) => { - builder.0.set_context(context.to_string()); + builder.set_context(context); true } } @@ -858,8 +923,7 @@ pub unsafe extern "C" fn block_builder_add_fact( return false; } - builder.0 = builder - .0 + builder .add_fact(s.unwrap()) .map_err(|e| { update_last_error(Error::Biscuit(e)); @@ -886,7 +950,6 @@ pub unsafe extern "C" fn block_builder_add_rule( } builder - .0 .add_rule(s.unwrap()) .map_err(|e| { update_last_error(Error::Biscuit(e)); @@ -913,7 +976,6 @@ pub unsafe extern "C" fn block_builder_add_check( } builder - .0 .add_check(s.unwrap()) .map_err(|e| { update_last_error(Error::Biscuit(e)); From aff9748596f9194849a56a02b6c3e5e9c2e4f115 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Wed, 27 Nov 2024 19:00:21 +0100 Subject: [PATCH 14/28] update macros --- biscuit-quote/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biscuit-quote/src/lib.rs b/biscuit-quote/src/lib.rs index 4a660668..f917e736 100644 --- a/biscuit-quote/src/lib.rs +++ b/biscuit-quote/src/lib.rs @@ -476,7 +476,7 @@ impl ToTokens for Builder { let builder_type = &self.builder_type; let builder_quote = if let Some(target) = &self.target { quote! { - let __biscuit_auth_builder: &mut #builder_type = #target; + let mut __biscuit_auth_builder: #builder_type = #target; } } else { quote! { From 14adc83d0563097405f3df0511e6b95d66699f78 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Thu, 28 Nov 2024 10:07:52 +0100 Subject: [PATCH 15/28] update tests --- biscuit-auth/benches/token.rs | 165 +++++++------ biscuit-auth/examples/testcases.rs | 10 +- biscuit-auth/examples/third_party.rs | 18 +- biscuit-auth/examples/verifying_printer.rs | 9 +- biscuit-auth/src/token/authorizer.rs | 126 +++++----- biscuit-auth/src/token/builder/authorizer.rs | 55 +++-- biscuit-auth/src/token/builder_ext.rs | 4 +- biscuit-auth/src/token/mod.rs | 232 ++++++++++--------- biscuit-auth/tests/macros.rs | 17 +- biscuit-auth/tests/rights.rs | 22 +- 10 files changed, 355 insertions(+), 303 deletions(-) diff --git a/biscuit-auth/benches/token.rs b/biscuit-auth/benches/token.rs index 4158a613..034e4758 100644 --- a/biscuit-auth/benches/token.rs +++ b/biscuit-auth/benches/token.rs @@ -262,12 +262,15 @@ fn verify_block_2(b: &mut Bencher) { }; let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&token); - builder.add_fact("resource(\"file1\")"); - builder.add_fact("operation(\"read\")"); - builder.add_allow_all(); - let mut verifier = builder.build().unwrap(); + let mut verifier = AuthorizerBuilder::new() + .add_token(&token) + .add_fact("resource(\"file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .add_allow_all() + .build() + .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -277,12 +280,15 @@ fn verify_block_2(b: &mut Bencher) { b.bytes = data.len() as u64; b.iter(|| { let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&token); - builder.add_fact("resource(\"file1\")"); - builder.add_fact("operation(\"read\")"); - builder.add_allow_all(); - let mut verifier = builder.build().unwrap(); + let mut verifier = AuthorizerBuilder::new() + .add_token(&token) + .add_fact("resource(\"file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .add_allow_all() + .build() + .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -345,12 +351,15 @@ fn verify_block_5(b: &mut Bencher) { }; let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&token); - builder.add_fact("resource(\"file1\")"); - builder.add_fact("operation(\"read\")"); - builder.add_allow_all(); - let mut verifier = builder.build().unwrap(); + let mut verifier = AuthorizerBuilder::new() + .add_token(&token) + .add_fact("resource(\"file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .add_allow_all() + .build() + .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -361,12 +370,15 @@ fn verify_block_5(b: &mut Bencher) { b.bytes = data.len() as u64; b.iter(|| { let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&token); - builder.add_fact("resource(\"file1\")"); - builder.add_fact("operation(\"read\")"); - builder.add_allow_all(); - let mut verifier = builder.build().unwrap(); + let mut verifier = AuthorizerBuilder::new() + .add_token(&token) + .add_fact("resource(\"file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .add_allow_all() + .build() + .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -402,12 +414,15 @@ fn check_signature_2(b: &mut Bencher) { }; let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&token); - builder.add_fact("resource(\"file1\")"); - builder.add_fact("operation(\"read\")"); - builder.add_allow_all(); - let mut verifier = builder.build().unwrap(); + let mut verifier = AuthorizerBuilder::new() + .add_token(&token) + .add_fact("resource(\"file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .add_allow_all() + .build() + .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -473,12 +488,15 @@ fn check_signature_5(b: &mut Bencher) { }; let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&token); - builder.add_fact("resource(\"file1\")"); - builder.add_fact("operation(\"read\")"); - builder.add_allow_all(); - let mut verifier = builder.build().unwrap(); + let mut verifier = AuthorizerBuilder::new() + .add_token(&token) + .add_fact("resource(\"file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .add_allow_all() + .build() + .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -518,12 +536,15 @@ fn checks_block_2(b: &mut Bencher) { }; let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&token); - builder.add_fact("resource(\"file1\")"); - builder.add_fact("operation(\"read\")"); - builder.add_allow_all(); - let mut verifier = builder.build().unwrap(); + let mut verifier = AuthorizerBuilder::new() + .add_token(&token) + .add_fact("resource(\"file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .add_allow_all() + .build() + .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -534,12 +555,15 @@ fn checks_block_2(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); b.bytes = data.len() as u64; b.iter(|| { - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&token); - builder.add_fact("resource(\"file1\")"); - builder.add_fact("operation(\"read\")"); - builder.add_allow_all(); - let mut verifier = builder.build().unwrap(); + let mut verifier = AuthorizerBuilder::new() + .add_token(&token) + .add_fact("resource(\"file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .add_allow_all() + .build() + .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -575,12 +599,15 @@ fn checks_block_create_verifier2(b: &mut Bencher) { }; let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&token); - builder.add_fact("resource(\"file1\")"); - builder.add_fact("operation(\"read\")"); - builder.add_allow_all(); - let mut verifier = builder.build().unwrap(); + let mut verifier = AuthorizerBuilder::new() + .add_token(&token) + .add_fact("resource(\"file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .add_allow_all() + .build() + .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -621,12 +648,15 @@ fn checks_block_verify_only2(b: &mut Bencher) { }; let token = Biscuit::from(&data, &root.public()).unwrap(); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&token); - builder.add_fact("resource(\"file1\")"); - builder.add_fact("operation(\"read\")"); - builder.add_allow_all(); - let mut verifier = builder.build().unwrap(); + let mut verifier = AuthorizerBuilder::new() + .add_token(&token) + .add_fact("resource(\"file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .add_allow_all() + .build() + .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -636,12 +666,15 @@ fn checks_block_verify_only2(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); b.iter(|| { - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&token); - builder.add_fact("resource(\"file1\")"); - builder.add_fact("operation(\"read\")"); - builder.add_allow_all(); - let mut verifier = builder.build().unwrap(); + let mut verifier = AuthorizerBuilder::new() + .add_token(&token) + .add_fact("resource(\"file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .add_allow_all() + .build() + .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), diff --git a/biscuit-auth/examples/testcases.rs b/biscuit-auth/examples/testcases.rs index 2a205d24..69915631 100644 --- a/biscuit-auth/examples/testcases.rs +++ b/biscuit-auth/examples/testcases.rs @@ -343,13 +343,13 @@ fn validate_token_with_limits_and_external_functions( revocation_ids.push(hex::encode(&bytes)); } - let mut builder = AuthorizerBuilder::new(); - builder.set_extern_funcs(extern_funcs); - builder.add_code(authorizer_code).unwrap(); + let builder = AuthorizerBuilder::new() + .set_extern_funcs(extern_funcs) + .add_code(authorizer_code) + .unwrap(); let authorizer_code = builder.dump_code(); - builder.add_token(&token); - let mut authorizer = match builder.build() { + let mut authorizer = match builder.add_token(&token).build() { Ok(v) => v, Err(e) => { return Validation { diff --git a/biscuit-auth/examples/third_party.rs b/biscuit-auth/examples/third_party.rs index b35f60f4..6b11beb4 100644 --- a/biscuit-auth/examples/third_party.rs +++ b/biscuit-auth/examples/third_party.rs @@ -34,18 +34,20 @@ fn main() { println!("biscuit2: {}", biscuit2); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&biscuit1); - builder.add_allow_all(); - let mut authorizer = builder.build().unwrap(); + let mut authorizer = AuthorizerBuilder::new() + .add_token(&biscuit1) + .add_allow_all() + .build() + .unwrap(); println!("authorize biscuit1:\n{:?}", authorizer.authorize()); println!("world:\n{}", authorizer.print_world()); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&biscuit2); - builder.add_allow_all(); - let mut authorizer = builder.build().unwrap(); + let mut authorizer = AuthorizerBuilder::new() + .add_token(&biscuit2) + .add_allow_all() + .build() + .unwrap(); println!("authorize biscuit2:\n{:?}", authorizer.authorize()); println!("world:\n{}", authorizer.print_world()); diff --git a/biscuit-auth/examples/verifying_printer.rs b/biscuit-auth/examples/verifying_printer.rs index 41febf25..8dc6e210 100644 --- a/biscuit-auth/examples/verifying_printer.rs +++ b/biscuit-auth/examples/verifying_printer.rs @@ -25,10 +25,11 @@ fn main() { } println!("token:\n{}", token); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&token); - builder.add_allow_all(); - let mut authorizer = builder.build().unwrap(); + let mut authorizer = AuthorizerBuilder::new() + .add_token(&token) + .add_allow_all() + .build() + .unwrap(); println!("authorizer result: {:?}", authorizer.authorize()); println!("authorizer world:\n{}", authorizer.print_world()); diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index 9144d1d5..6f217cb0 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -36,10 +36,7 @@ pub struct Authorizer { impl Authorizer { pub(crate) fn from_token(token: &Biscuit) -> Result { - let mut b = AuthorizerBuilder::new(); - b.add_token(token); - - b.build() + AuthorizerBuilder::new().add_token(token).build() } /// creates a new empty authorizer @@ -902,9 +899,11 @@ mod tests { #[test] fn empty_authorizer() { - let mut builder = AuthorizerBuilder::new(); - builder.add_policy("allow if true").unwrap(); - let mut authorizer = builder.build().unwrap(); + let mut authorizer = AuthorizerBuilder::new() + .add_policy("allow if true") + .unwrap() + .build() + .unwrap(); assert_eq!( authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -916,7 +915,6 @@ mod tests { #[test] fn parameter_substitution() { - let mut builder = AuthorizerBuilder::new(); let mut params = HashMap::new(); params.insert("p1".to_string(), "value".into()); params.insert("p2".to_string(), 0i64.into()); @@ -931,7 +929,7 @@ mod tests { ) .unwrap(), ); - builder + let _authorizer = AuthorizerBuilder::new() .add_code_with_params( r#" fact({p1}, "value"); @@ -942,71 +940,64 @@ mod tests { params, scope_params, ) + .unwrap() + .build() .unwrap(); - let _authorizer = builder.build().unwrap(); } #[test] fn forbid_unbound_parameters() { - let mut builder = AuthorizerBuilder::new(); + let builder = AuthorizerBuilder::new(); let mut fact = Fact::try_from("fact({p1}, {p4})").unwrap(); fact.set("p1", "hello").unwrap(); - let res = builder.add_fact(fact); + let res = builder.clone().add_fact(fact); assert_eq!( - res, - Err(error::Token::Language( - biscuit_parser::error::LanguageError::Parameters { - missing_parameters: vec!["p4".to_string()], - unused_parameters: vec![], - } - )) + res.unwrap_err(), + error::Token::Language(biscuit_parser::error::LanguageError::Parameters { + missing_parameters: vec!["p4".to_string()], + unused_parameters: vec![], + }) ); let mut rule = Rule::try_from( "fact($var1, {p2}) <- f1($var1, $var3), f2({p2}, $var3, {p4}), $var3.starts_with({p2})", ) .unwrap(); rule.set("p2", "hello").unwrap(); - let res = builder.add_rule(rule); + let res = builder.clone().add_rule(rule); assert_eq!( - res, - Err(error::Token::Language( - biscuit_parser::error::LanguageError::Parameters { - missing_parameters: vec!["p4".to_string()], - unused_parameters: vec![], - } - )) + res.unwrap_err(), + error::Token::Language(biscuit_parser::error::LanguageError::Parameters { + missing_parameters: vec!["p4".to_string()], + unused_parameters: vec![], + }) ); let mut check = Check::try_from("check if {p4}, {p3}").unwrap(); check.set("p3", true).unwrap(); - let res = builder.add_check(check); + let res = builder.clone().add_check(check); assert_eq!( - res, - Err(error::Token::Language( - biscuit_parser::error::LanguageError::Parameters { - missing_parameters: vec!["p4".to_string()], - unused_parameters: vec![], - } - )) + res.unwrap_err(), + error::Token::Language(biscuit_parser::error::LanguageError::Parameters { + missing_parameters: vec!["p4".to_string()], + unused_parameters: vec![], + }) ); let mut policy = Policy::try_from("allow if {p4}, {p3}").unwrap(); policy.set("p3", true).unwrap(); - let res = builder.add_policy(policy); + let res = builder.clone().add_policy(policy); assert_eq!( - res, - Err(error::Token::Language( - biscuit_parser::error::LanguageError::Parameters { - missing_parameters: vec!["p4".to_string()], - unused_parameters: vec![], - } - )) + res.unwrap_err(), + error::Token::Language(biscuit_parser::error::LanguageError::Parameters { + missing_parameters: vec!["p4".to_string()], + unused_parameters: vec![], + }) ); } #[test] fn forbid_unbound_parameters_in_add_code() { - let mut builder = AuthorizerBuilder::new(); + let builder = AuthorizerBuilder::new(); let mut params = HashMap::new(); params.insert("p1".to_string(), "hello".into()); params.insert("p2".to_string(), 1i64.into()); @@ -1022,13 +1013,11 @@ mod tests { ); assert_eq!( - res, - Err(error::Token::Language( - biscuit_parser::error::LanguageError::Parameters { - missing_parameters: vec!["p3".to_string()], - unused_parameters: vec![], - } - )) + res.unwrap_err(), + error::Token::Language(biscuit_parser::error::LanguageError::Parameters { + missing_parameters: vec!["p3".to_string()], + unused_parameters: vec![], + }) ) } @@ -1105,14 +1094,14 @@ mod tests { let serialized = biscuit2.to_vec().unwrap(); let biscuit2 = Biscuit::from(serialized, root.public()).unwrap(); - let mut builder = AuthorizerBuilder::new(); + let builder = AuthorizerBuilder::new(); let external2 = KeyPair::new(Algorithm::Ed25519); let mut scope_params = HashMap::new(); scope_params.insert("external".to_string(), external.public()); scope_params.insert("external2".to_string(), external2.public()); - builder + let mut authorizer = builder .add_code_with_params( r#" // this rule trusts both the third-party block and the authority, and can access facts @@ -1132,16 +1121,15 @@ mod tests { HashMap::new(), scope_params, ) + .unwrap() + .add_token(&biscuit2) + .set_limits(AuthorizerLimits { + max_time: Duration::from_millis(10), //Set 10 milliseconds as the maximum time allowed for the authorization due to "cheap" worker on GitHub Actions + ..Default::default() + }) + .build() .unwrap(); - builder.add_token(&biscuit2); - builder.set_limits(AuthorizerLimits { - max_time: Duration::from_millis(10), //Set 10 milliseconds as the maximum time allowed for the authorization due to "cheap" worker on GitHub Actions - ..Default::default() - }); - - let mut authorizer = builder.build().unwrap(); - println!("token:\n{}", biscuit2); println!("world:\n{}", authorizer.print_world()); @@ -1270,10 +1258,8 @@ mod tests { .build(&root) .unwrap(); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&token); - - builder + let mut authorizer = AuthorizerBuilder::new() + .add_token(&token) .add_code( r#" authorizer_fact(true); @@ -1282,8 +1268,9 @@ mod tests { allow if true; "#, ) + .unwrap() + .build() .unwrap(); - let mut authorizer = builder.build().unwrap(); let output_before_authorization = authorizer.to_string(); assert!( @@ -1340,7 +1327,7 @@ allow if true; #[test] fn rule_validate_variables() { - let mut builder = AuthorizerBuilder::new(); + let builder = AuthorizerBuilder::new(); let mut syms = SymbolTable::new(); let rule_name = syms.insert("test"); let pred_name = syms.insert("pred"); @@ -1381,14 +1368,15 @@ allow if true; ); // broken rules directly added to the authorizer currently don’t trigger any error, but silently fail to generate facts when they match - builder + let mut authorizer = builder .add_rule(builder::rule( "test", &[var("unbound")], &[builder::pred("pred", &[builder::var("any")])], )) + .unwrap() + .build() .unwrap(); - let mut authorizer = builder.build().unwrap(); let res: Vec<(String,)> = authorizer .query(builder::rule( "output", diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs index 28d6bae1..c6f448a1 100644 --- a/biscuit-auth/src/token/builder/authorizer.rs +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -36,7 +36,7 @@ impl<'a> AuthorizerBuilder<'a> { where error::Token: From<>::Error>, { - self.authorizer_block_builder.add_fact(fact)?; + self.authorizer_block_builder = self.authorizer_block_builder.add_fact(fact)?; Ok(self) } @@ -44,7 +44,7 @@ impl<'a> AuthorizerBuilder<'a> { where error::Token: From<>::Error>, { - self.authorizer_block_builder.add_rule(rule)?; + self.authorizer_block_builder = self.authorizer_block_builder.add_rule(rule)?; Ok(self) } @@ -52,7 +52,7 @@ impl<'a> AuthorizerBuilder<'a> { where error::Token: From<>::Error>, { - self.authorizer_block_builder.add_check(check)?; + self.authorizer_block_builder = self.authorizer_block_builder.add_check(check)?; Ok(self) } @@ -74,7 +74,7 @@ impl<'a> AuthorizerBuilder<'a> { /// allow if true; /// "#).expect("should parse correctly"); /// ``` - pub fn add_code>(mut self, source: T) -> Result { + pub fn add_code>(self, source: T) -> Result { self.add_code_with_params(source, HashMap::new(), HashMap::new()) } @@ -204,7 +204,7 @@ impl<'a> AuthorizerBuilder<'a> { } pub fn add_scope(mut self, scope: Scope) -> Self { - self.authorizer_block_builder.add_scope(scope); + self.authorizer_block_builder = self.authorizer_block_builder.add_scope(scope); self } @@ -222,7 +222,7 @@ impl<'a> AuthorizerBuilder<'a> { /// adds a fact with the current time pub fn set_time(mut self) -> Self { let fact = fact("time", &[date(&SystemTime::now())]); - self.authorizer_block_builder.add_fact(fact).unwrap(); + self.authorizer_block_builder = self.authorizer_block_builder.add_fact(fact).unwrap(); self } @@ -450,36 +450,43 @@ pub(crate) fn load_and_translate_block( } impl<'a> BuilderExt for AuthorizerBuilder<'a> { - fn add_resource(&mut self, name: &str) { - self.authorizer_block_builder.add_resource(name); + fn add_resource(mut self, name: &str) -> Self { + self.authorizer_block_builder = self.authorizer_block_builder.add_resource(name); + self } - fn check_resource(&mut self, name: &str) { - self.authorizer_block_builder.check_resource(name); + fn check_resource(mut self, name: &str) -> Self { + self.authorizer_block_builder = self.authorizer_block_builder.check_resource(name); + self } - fn add_operation(&mut self, name: &str) { - self.authorizer_block_builder.add_operation(name); + fn add_operation(mut self, name: &str) -> Self { + self.authorizer_block_builder = self.authorizer_block_builder.add_operation(name); + self } - fn check_operation(&mut self, name: &str) { - self.authorizer_block_builder.check_operation(name); + fn check_operation(mut self, name: &str) -> Self { + self.authorizer_block_builder = self.authorizer_block_builder.check_operation(name); + self } - fn check_resource_prefix(&mut self, prefix: &str) { - self.authorizer_block_builder.check_resource_prefix(prefix); + fn check_resource_prefix(mut self, prefix: &str) -> Self { + self.authorizer_block_builder = self.authorizer_block_builder.check_resource_prefix(prefix); + self } - fn check_resource_suffix(&mut self, suffix: &str) { - self.authorizer_block_builder.check_resource_suffix(suffix); + fn check_resource_suffix(mut self, suffix: &str) -> Self { + self.authorizer_block_builder = self.authorizer_block_builder.check_resource_suffix(suffix); + self } - fn check_expiration_date(&mut self, exp: SystemTime) { - self.authorizer_block_builder.check_expiration_date(exp); + fn check_expiration_date(mut self, exp: SystemTime) -> Self { + self.authorizer_block_builder = self.authorizer_block_builder.check_expiration_date(exp); + self } } impl<'a> AuthorizerExt for AuthorizerBuilder<'a> { - fn add_allow_all(&mut self) { - self.add_policy("allow if true").unwrap(); + fn add_allow_all(self) -> Self { + self.add_policy("allow if true").unwrap() } - fn add_deny_all(&mut self) { - self.add_policy("deny if true").unwrap(); + fn add_deny_all(self) -> Self { + self.add_policy("deny if true").unwrap() } } diff --git a/biscuit-auth/src/token/builder_ext.rs b/biscuit-auth/src/token/builder_ext.rs index 2983d6c3..c23b4e88 100644 --- a/biscuit-auth/src/token/builder_ext.rs +++ b/biscuit-auth/src/token/builder_ext.rs @@ -11,6 +11,6 @@ pub trait BuilderExt { } pub trait AuthorizerExt { - fn add_allow_all(&mut self); - fn add_deny_all(&mut self); + fn add_allow_all(self) -> Self; + fn add_deny_all(self) -> Self; } diff --git a/biscuit-auth/src/token/mod.rs b/biscuit-auth/src/token/mod.rs index 41e49938..79d82975 100644 --- a/biscuit-auth/src/token/mod.rs +++ b/biscuit-auth/src/token/mod.rs @@ -846,8 +846,7 @@ mod tests { let final_token = Biscuit::from(&serialized3, root.public()).unwrap(); println!("final token:\n{}", final_token); { - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&final_token); + let mut builder = AuthorizerBuilder::new().add_token(&final_token); let mut facts = vec![ fact("resource", &[string("file1")]), @@ -855,13 +854,12 @@ mod tests { ]; for fact in facts.drain(..) { - builder.add_fact(fact).unwrap(); + builder = builder.add_fact(fact).unwrap(); } //println!("final token: {:#?}", final_token); - builder.add_allow_all(); - let mut authorizer = builder.build().unwrap(); + let mut authorizer = builder.add_allow_all().build().unwrap(); let res = authorizer.authorize(); println!("res1: {:?}", res); @@ -869,8 +867,7 @@ mod tests { } { - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&final_token); + let mut builder = AuthorizerBuilder::new().add_token(&final_token); let mut facts = vec![ fact("resource", &[string("file2")]), @@ -878,9 +875,9 @@ mod tests { ]; for fact in facts.drain(..) { - builder.add_fact(fact).unwrap(); + builder = builder.add_fact(fact).unwrap(); } - builder.add_allow_all(); + builder = builder.add_allow_all(); let mut authorizer = builder.build().unwrap(); @@ -925,13 +922,15 @@ mod tests { let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); { - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&biscuit2); - builder.add_fact("resource(\"/folder1/file1\")").unwrap(); - builder.add_fact("operation(\"read\")").unwrap(); - builder.add_allow_all(); - - let mut authorizer = builder.build().unwrap(); + let mut authorizer = AuthorizerBuilder::new() + .add_token(&biscuit2) + .add_fact("resource(\"/folder1/file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .add_allow_all() + .build() + .unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -943,13 +942,15 @@ mod tests { } { - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&biscuit2); - builder.add_fact("resource(\"/folder2/file3\")").unwrap(); - builder.add_fact("operation(\"read\")").unwrap(); - builder.add_allow_all(); - - let mut authorizer = builder.build().unwrap(); + let mut authorizer = AuthorizerBuilder::new() + .add_token(&biscuit2) + .add_fact("resource(\"/folder2/file3\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .add_allow_all() + .build() + .unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -972,12 +973,14 @@ mod tests { } { - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&biscuit2); - builder.add_fact("resource(\"/folder2/file1\")").unwrap(); - builder.add_fact("operation(\"write\")").unwrap(); - - let mut authorizer = builder.build().unwrap(); + let mut authorizer = AuthorizerBuilder::new() + .add_token(&biscuit2) + .add_fact("resource(\"/folder2/file1\")") + .unwrap() + .add_fact("operation(\"write\")") + .unwrap() + .build() + .unwrap(); let res = authorizer.authorize(); println!("res3: {:?}", res); @@ -1012,14 +1015,16 @@ mod tests { let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); { - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&biscuit2); - builder.add_fact("resource(\"file1\")").unwrap(); - builder.add_fact("operation(\"read\")").unwrap(); - builder.set_time(); - builder.add_allow_all(); - - let mut authorizer = builder.build().unwrap(); + let mut authorizer = AuthorizerBuilder::new() + .add_token(&biscuit2) + .add_fact("resource(\"file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .set_time() + .add_allow_all() + .build() + .unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -1031,14 +1036,16 @@ mod tests { { println!("biscuit2: {}", biscuit2); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&biscuit2); - builder.add_fact("resource(\"file1\")").unwrap(); - builder.add_fact("operation(\"read\")").unwrap(); - builder.set_time(); - builder.add_allow_all(); - - let mut authorizer = builder.build().unwrap(); + let mut authorizer = AuthorizerBuilder::new() + .add_token(&biscuit2) + .add_fact("resource(\"file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .set_time() + .add_allow_all() + .build() + .unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -1078,13 +1085,15 @@ mod tests { //println!("biscuit2:\n{:#?}", biscuit2); //panic!(); { - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&biscuit2); - builder.add_fact("resource(\"/folder1/file1\")").unwrap(); - builder.add_fact("operation(\"read\")").unwrap(); - builder.add_allow_all(); - - let mut authorizer = builder.build().unwrap(); + let mut authorizer = AuthorizerBuilder::new() + .add_token(&biscuit2) + .add_fact("resource(\"/folder1/file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .add_allow_all() + .build() + .unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -1103,13 +1112,15 @@ mod tests { let biscuit3 = Biscuit::from(sealed, root.public()).unwrap(); { - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&biscuit3); - builder.add_fact("resource(\"/folder1/file1\")").unwrap(); - builder.add_fact("operation(\"read\")").unwrap(); - builder.add_allow_all(); - - let mut authorizer = builder.build().unwrap(); + let mut authorizer = AuthorizerBuilder::new() + .add_token(&biscuit3) + .add_fact("resource(\"/folder1/file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .add_allow_all() + .build() + .unwrap(); let res = authorizer.authorize(); println!("res1: {:?}", res); @@ -1135,17 +1146,16 @@ mod tests { .unwrap(); println!("{}", biscuit1); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&biscuit1); - - builder + let mut authorizer = AuthorizerBuilder::new() + .add_token(&biscuit1) .add_check(rule( "right", &[string("right")], &[pred("right", &[string("file2"), string("write")])], )) + .unwrap() + .build() .unwrap(); - let mut authorizer = builder.build().unwrap(); //assert!(v.verify().is_err()); let res = authorizer.authorize_with_limits(AuthorizerLimits { @@ -1197,12 +1207,15 @@ mod tests { { println!("biscuit3: {}", biscuit3); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&biscuit3); - builder.add_fact("resource(\"file1\")").unwrap(); - builder.add_fact("operation(\"read\")").unwrap(); - builder.set_time(); - let mut authorizer = builder.build().unwrap(); + let mut authorizer = AuthorizerBuilder::new() + .add_token(&biscuit3) + .add_fact("resource(\"file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .set_time() + .build() + .unwrap(); // test that cloning correctly embeds the first block's facts let mut other_authorizer = authorizer.clone(); @@ -1280,12 +1293,15 @@ mod tests { //println!("generated biscuit token 2: {} bytes\n{}", serialized2.len(), serialized2.to_hex(16)); { - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&biscuit2); - builder.add_fact("resource(\"file1\")").unwrap(); - builder.add_fact("operation(\"read\")").unwrap(); - builder.set_time(); - let mut authorizer = builder.build().unwrap(); + let mut authorizer = AuthorizerBuilder::new() + .add_token(&biscuit2) + .add_fact("resource(\"file1\")") + .unwrap() + .add_fact("operation(\"read\")") + .unwrap() + .set_time() + .build() + .unwrap(); println!("world:\n{}", authorizer.print_world()); println!("symbols: {:?}", authorizer.symbols); @@ -1373,13 +1389,13 @@ mod tests { let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&biscuit2); - builder + let mut authorizer = AuthorizerBuilder::new() + .add_token(&biscuit2) .add_check("check if bytes($0), { hex:00000000, hex:0102AB }.contains($0)") + .unwrap() + .add_allow_all() + .build() .unwrap(); - builder.add_allow_all(); - let mut authorizer = builder.build().unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -1462,15 +1478,17 @@ mod tests { let final_token = Biscuit::from(&serialized2, root.public()).unwrap(); println!("final token:\n{}", final_token); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&final_token); - builder.add_fact("resource(\"/folder2/file1\")").unwrap(); - builder.add_fact("operation(\"write\")").unwrap(); - builder + let mut authorizer = AuthorizerBuilder::new() + .add_token(&final_token) + .add_fact("resource(\"/folder2/file1\")") + .unwrap() + .add_fact("operation(\"write\")") + .unwrap() .add_policy("allow if resource($file), operation($op), right($file, $op)") + .unwrap() + .add_deny_all() + .build() .unwrap(); - builder.add_deny_all(); - let mut authorizer = builder.build().unwrap(); let res = authorizer.authorize_with_limits(crate::token::authorizer::AuthorizerLimits { max_time: Duration::from_secs(1), @@ -1504,15 +1522,16 @@ mod tests { println!("biscuit2 (authority): {}", biscuit2); { - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&biscuit1); - builder.add_fact("fact(0)").unwrap(); - builder.add_fact("fact(1)").unwrap(); - - //println!("final token: {:#?}", final_token); - builder.add_allow_all(); - - let mut authorizer = builder.build().unwrap(); + let mut authorizer = AuthorizerBuilder::new() + .add_token(&biscuit1) + .add_fact("fact(0)") + .unwrap() + .add_fact("fact(1)") + .unwrap() + //println!("final token: {:#?}", final_token); + .add_allow_all() + .build() + .unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -1523,15 +1542,16 @@ mod tests { } { - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&biscuit2); - builder.add_fact("fact(0)").unwrap(); - builder.add_fact("fact(1)").unwrap(); - - //println!("final token: {:#?}", final_token); - builder.add_allow_all(); - - let mut authorizer = builder.build().unwrap(); + let mut authorizer = AuthorizerBuilder::new() + .add_token(&biscuit2) + .add_fact("fact(0)") + .unwrap() + .add_fact("fact(1)") + .unwrap() + //println!("final token: {:#?}", final_token); + .add_allow_all() + .build() + .unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), diff --git a/biscuit-auth/tests/macros.rs b/biscuit-auth/tests/macros.rs index 5295152d..9ec905ff 100644 --- a/biscuit-auth/tests/macros.rs +++ b/biscuit-auth/tests/macros.rs @@ -68,8 +68,8 @@ fn authorizer_macro() { ); let is_true = true; - authorizer_merge!( - &mut b, + b = authorizer_merge!( + b, r#"appended({is_true}); allow if true; "# @@ -123,8 +123,7 @@ fn biscuit_macro() { check if true trusting ed25519/6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db; "#, my_key_bytes = s.into_bytes(), - ); - b.set_root_key_id(2); + ).set_root_key_id(2); let is_true = true; b = biscuit_merge!( @@ -253,7 +252,7 @@ fn json() { ); let json_value: biscuit_auth::builder::Term = value.try_into().unwrap(); - let mut builder = authorizer!( + let mut authorizer = authorizer!( r#" user_roles({json_value}); allow if @@ -261,10 +260,10 @@ fn json() { user_roles($value), $value.get("id") == $id, $value.get("roles").contains("admin");"# - ); - - builder.add_token(&biscuit); - let mut authorizer = builder.build().unwrap(); + ) + .add_token(&biscuit) + .build() + .unwrap(); assert_eq!( authorizer .authorize_with_limits(RunLimits { diff --git a/biscuit-auth/tests/rights.rs b/biscuit-auth/tests/rights.rs index 12bd2f5a..e6918db3 100644 --- a/biscuit-auth/tests/rights.rs +++ b/biscuit-auth/tests/rights.rs @@ -31,17 +31,19 @@ fn main() { .unwrap(); println!("{}", biscuit1); - let mut builder = AuthorizerBuilder::new(); - builder.add_token(&biscuit1); - builder.add_check(rule( - "right", - &[string("right")], - &[pred( + let mut v = AuthorizerBuilder::new() + .add_token(&biscuit1) + .add_check(rule( "right", - &[string("authority"), string("file2"), string("write")], - )], - )); - let mut v = builder.build().expect("omg verifier"); + &[string("right")], + &[pred( + "right", + &[string("authority"), string("file2"), string("write")], + )], + )) + .unwrap() + .build() + .unwrap(); //v.add_resource("file2"); //v.add_operation("read"); //v.add_operation("write"); From e8792353dbef2fb1dead683ec6df5c94a9b3107a Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Thu, 28 Nov 2024 10:18:15 +0100 Subject: [PATCH 16/28] fix capi --- biscuit-capi/src/lib.rs | 96 ++++++++++++++++++++++++++++++----------- 1 file changed, 72 insertions(+), 24 deletions(-) diff --git a/biscuit-capi/src/lib.rs b/biscuit-capi/src/lib.rs index d156306a..3b269fb3 100644 --- a/biscuit-capi/src/lib.rs +++ b/biscuit-capi/src/lib.rs @@ -295,6 +295,7 @@ pub struct PublicKey(biscuit_auth::PublicKey); pub struct BiscuitBuilder(Option); pub struct BlockBuilder(Option); pub struct Authorizer(biscuit_auth::Authorizer); +pub struct AuthorizerBuilder<'a>(Option>); #[repr(C)] pub enum SignatureAlgorithm { @@ -986,16 +987,45 @@ pub unsafe extern "C" fn block_builder_add_check( #[no_mangle] pub unsafe extern "C" fn block_builder_free(_builder: Option>) {} +impl<'a> AuthorizerBuilder<'a> { + fn add_fact(&mut self, fact: &str) -> Result<(), biscuit_auth::error::Token> { + let mut inner = self.0.take().unwrap(); + inner = inner.add_fact(fact)?; + self.0 = Some(inner); + Ok(()) + } + + fn add_rule(&mut self, rule: &str) -> Result<(), biscuit_auth::error::Token> { + let mut inner = self.0.take().unwrap(); + inner = inner.add_rule(rule)?; + self.0 = Some(inner); + Ok(()) + } + + fn add_check(&mut self, check: &str) -> Result<(), biscuit_auth::error::Token> { + let mut inner = self.0.take().unwrap(); + inner = inner.add_check(check)?; + self.0 = Some(inner); + Ok(()) + } + + fn add_policy(&mut self, policy: &str) -> Result<(), biscuit_auth::error::Token> { + let mut inner = self.0.take().unwrap(); + inner = inner.add_policy(policy)?; + self.0 = Some(inner); + Ok(()) + } +} #[no_mangle] -pub unsafe extern "C" fn authorizer_add_fact( - authorizer: Option<&mut Authorizer>, +pub unsafe extern "C" fn authorizer_builder_add_fact( + builder: Option<&mut AuthorizerBuilder>, fact: *const c_char, ) -> bool { - if authorizer.is_none() { + if builder.is_none() { update_last_error(Error::InvalidArgument); return false; } - let authorizer = authorizer.unwrap(); + let builder = builder.unwrap(); let fact = CStr::from_ptr(fact); let s = fact.to_str(); @@ -1004,8 +1034,7 @@ pub unsafe extern "C" fn authorizer_add_fact( return false; } - authorizer - .0 + builder .add_fact(s.unwrap()) .map_err(|e| { update_last_error(Error::Biscuit(e)); @@ -1014,15 +1043,15 @@ pub unsafe extern "C" fn authorizer_add_fact( } #[no_mangle] -pub unsafe extern "C" fn authorizer_add_rule( - authorizer: Option<&mut Authorizer>, +pub unsafe extern "C" fn authorizer_builder_add_rule( + builder: Option<&mut AuthorizerBuilder>, rule: *const c_char, ) -> bool { - if authorizer.is_none() { + if builder.is_none() { update_last_error(Error::InvalidArgument); return false; } - let authorizer = authorizer.unwrap(); + let builder = builder.unwrap(); let rule = CStr::from_ptr(rule); let s = rule.to_str(); @@ -1031,8 +1060,7 @@ pub unsafe extern "C" fn authorizer_add_rule( return false; } - authorizer - .0 + builder .add_rule(s.unwrap()) .map_err(|e| { update_last_error(Error::Biscuit(e)); @@ -1041,15 +1069,15 @@ pub unsafe extern "C" fn authorizer_add_rule( } #[no_mangle] -pub unsafe extern "C" fn authorizer_add_check( - authorizer: Option<&mut Authorizer>, +pub unsafe extern "C" fn authorizer_builder_add_check( + builder: Option<&mut AuthorizerBuilder>, check: *const c_char, ) -> bool { - if authorizer.is_none() { + if builder.is_none() { update_last_error(Error::InvalidArgument); return false; } - let authorizer = authorizer.unwrap(); + let builder = builder.unwrap(); let check = CStr::from_ptr(check); let s = check.to_str(); @@ -1058,8 +1086,7 @@ pub unsafe extern "C" fn authorizer_add_check( return false; } - authorizer - .0 + builder .add_check(s.unwrap()) .map_err(|e| { update_last_error(Error::Biscuit(e)); @@ -1068,15 +1095,15 @@ pub unsafe extern "C" fn authorizer_add_check( } #[no_mangle] -pub unsafe extern "C" fn authorizer_add_policy( - authorizer: Option<&mut Authorizer>, +pub unsafe extern "C" fn authorizer_builder_add_policy( + builder: Option<&mut AuthorizerBuilder>, policy: *const c_char, ) -> bool { - if authorizer.is_none() { + if builder.is_none() { update_last_error(Error::InvalidArgument); return false; } - let authorizer = authorizer.unwrap(); + let builder = builder.unwrap(); let policy = CStr::from_ptr(policy); let s = policy.to_str(); @@ -1085,8 +1112,7 @@ pub unsafe extern "C" fn authorizer_add_policy( return false; } - authorizer - .0 + builder .add_policy(s.unwrap()) .map_err(|e| { update_last_error(Error::Biscuit(e)); @@ -1094,6 +1120,28 @@ pub unsafe extern "C" fn authorizer_add_policy( .is_ok() } +#[no_mangle] +pub unsafe extern "C" fn authorizer_builder_build( + builder: Option, +) -> Option> { + if builder.is_none() { + update_last_error(Error::InvalidArgument); + } + let builder = builder.unwrap(); + builder + .0 + .clone() + .take() + .unwrap() + .build() + .map(Authorizer) + .map(Box::new) + .ok() +} + +#[no_mangle] +pub unsafe extern "C" fn authorizer_builder_free(_builder: Option>) {} + #[no_mangle] pub unsafe extern "C" fn authorizer_authorize(authorizer: Option<&mut Authorizer>) -> bool { if authorizer.is_none() { From 0fc38694cf974f45f1450e77d281489574988846 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Thu, 28 Nov 2024 10:30:43 +0100 Subject: [PATCH 17/28] capi fixes --- biscuit-capi/src/lib.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/biscuit-capi/src/lib.rs b/biscuit-capi/src/lib.rs index 3b269fb3..19c3f5ff 100644 --- a/biscuit-capi/src/lib.rs +++ b/biscuit-capi/src/lib.rs @@ -581,7 +581,9 @@ pub unsafe extern "C" fn biscuit_builder_add_check( }) .is_ok() } - +/// Build a biscuit token from a builder +/// +/// The builder will be freed automatically when the biscuit is returned #[no_mangle] pub unsafe extern "C" fn biscuit_builder_build( builder: Option<&BiscuitBuilder>, @@ -1120,9 +1122,12 @@ pub unsafe extern "C" fn authorizer_builder_add_policy( .is_ok() } +/// Build an authorizer +/// +/// The builder will be freed automatically when the authorizer is returned #[no_mangle] pub unsafe extern "C" fn authorizer_builder_build( - builder: Option, + builder: Option>, ) -> Option> { if builder.is_none() { update_last_error(Error::InvalidArgument); From a5f9696f462c6b2a1d82815e35090d00f1f1a091 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Thu, 28 Nov 2024 10:40:43 +0100 Subject: [PATCH 18/28] sort facts in dump_code to get a consistent order --- biscuit-auth/src/token/authorizer.rs | 3 +++ biscuit-auth/tests/macros.rs | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index 6f217cb0..bf594a95 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -623,6 +623,9 @@ impl Authorizer { pub fn dump_code(&self) -> String { let (facts, rules, checks, policies) = self.dump(); let mut f = String::new(); + + let mut facts = facts.into_iter().map(|f| f.to_string()).collect::>(); + facts.sort(); for fact in &facts { let _ = writeln!(f, "{fact};"); } diff --git a/biscuit-auth/tests/macros.rs b/biscuit-auth/tests/macros.rs index 9ec905ff..adc2034e 100644 --- a/biscuit-auth/tests/macros.rs +++ b/biscuit-auth/tests/macros.rs @@ -78,9 +78,9 @@ fn authorizer_macro() { let authorizer = b.build().unwrap(); assert_eq!( authorizer.dump_code(), - r#"fact("test", hex:aabbcc, [true], "my_value"); + r#"appended(true); +fact("test", hex:aabbcc, [true], "my_value"); rule("test", true); -appended(true); rule($0, true) <- fact($0, $1, $2, "my_value"); From c55e6b2ce22be7ab5a0166735b3c4176506b162b Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Thu, 28 Nov 2024 11:02:15 +0100 Subject: [PATCH 19/28] doc --- biscuit-auth/src/lib.rs | 22 +++++++++++++------- biscuit-auth/src/macros.rs | 21 ++++++++++++------- biscuit-auth/src/token/authorizer.rs | 18 +++++++++------- biscuit-auth/src/token/builder/authorizer.rs | 19 +++++++++-------- biscuit-auth/src/token/mod.rs | 21 ++++++++++--------- 5 files changed, 58 insertions(+), 43 deletions(-) diff --git a/biscuit-auth/src/lib.rs b/biscuit-auth/src/lib.rs index f5719a3a..10df1b8b 100644 --- a/biscuit-auth/src/lib.rs +++ b/biscuit-auth/src/lib.rs @@ -88,7 +88,7 @@ //! // - one for /a/file1.txt and a write operation //! // - one for /a/file2.txt and a read operation //! -//! let v1 = authorizer!(r#" +//! let mut v1 = authorizer!(r#" //! resource("/a/file1.txt"); //! operation("read"); //! @@ -101,26 +101,32 @@ //! // explicit catch-all deny. here it is not necessary: if no policy //! // matches, a default deny applies //! deny if true; -//! "#); +//! "#) +//! .add_token(&biscuit2) +//! .build()?; //! //! let mut v2 = authorizer!(r#" //! resource("/a/file1.txt"); //! operation("write"); //! allow if right("/a/file1.txt", "write"); -//! "#); -//! +//! "#) +//! .add_token(&biscuit2) +//! .build()?; +//! //! let mut v3 = authorizer!(r#" //! resource("/a/file2.txt"); //! operation("read"); //! allow if right("/a/file2.txt", "read"); -//! "#); +//! "#) +//! .add_token(&biscuit2) +//! .build()?; //! //! // the token restricts to read operations: -//! assert!(biscuit2.authorize(&v1).is_ok()); +//! assert!(v1.authorize().is_ok()); //! // the second verifier requested a read operation -//! assert!(biscuit2.authorize(&v2).is_err()); +//! assert!(v2.authorize().is_err()); //! // the third verifier requests /a/file2.txt -//! assert!(biscuit2.authorize(&v3).is_err()); +//! assert!(v3.authorize().is_err()); //! //! Ok(()) //! } diff --git a/biscuit-auth/src/macros.rs b/biscuit-auth/src/macros.rs index cbd47669..a0075b72 100644 --- a/biscuit-auth/src/macros.rs +++ b/biscuit-auth/src/macros.rs @@ -26,7 +26,7 @@ //! expiration = SystemTime::now() + Duration::from_secs(86_400), //! )).expect("Failed to append block"); //! -//! new_biscuit.authorize(&authorizer!( +//! authorizer!( //! r#" //! time({now}); //! operation({operation}); @@ -42,7 +42,12 @@ //! operation = "read", //! resource = "file1", //! user_id = "1234", -//! )).expect("Failed to authorize biscuit"); +//! ) +//! .add_token(&new_biscuit) +//! .build() +//! .expect("failed to build the authorizer") +//! .authorize() +//! .expect("Failed to authorize biscuit"); //! ``` /// Create an `Authorizer` from a datalog string and optional parameters. @@ -78,8 +83,8 @@ pub use biscuit_quote::authorizer; /// now = SystemTime::now() /// ); /// -/// authorizer_merge!( -/// &mut b, +/// b = authorizer_merge!( +/// b, /// r#" /// allow if true; /// "# @@ -128,8 +133,8 @@ pub use biscuit_quote::biscuit; /// user_id = "1234" /// ); /// -/// biscuit_merge!( -/// &mut b, +/// b = biscuit_merge!( +/// b, /// r#" /// check if time($time), $time < {expiration} /// "#, @@ -173,8 +178,8 @@ pub use biscuit_quote::block; /// user_id = "1234" /// ); /// -/// block_merge!( -/// &mut b, +/// b = block_merge!( +/// b, /// r#" /// check if user($id); /// "# diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index bf594a95..a2e6e86b 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -110,10 +110,11 @@ impl Authorizer { /// # use biscuit_auth::Biscuit; /// # use biscuit_auth::builder::Algorithm; /// let keypair = KeyPair::new(Algorithm::Ed25519); - /// let mut builder = Biscuit::builder(); - /// builder.add_fact("user(\"John Doe\", 42)"); - /// - /// let biscuit = builder.build(&keypair).unwrap(); + /// let biscuit = Biscuit::builder() + /// .add_fact("user(\"John Doe\", 42)") + /// .expect("parse error") + /// .build(&keypair) + /// .unwrap(); /// /// let mut authorizer = biscuit.authorizer().unwrap(); /// let res: Vec<(String, i64)> = authorizer.query("data($name, $id) <- user($name, $id)").unwrap(); @@ -200,10 +201,11 @@ impl Authorizer { /// # use biscuit_auth::Biscuit; /// # use biscuit_auth::builder::Algorithm; /// let keypair = KeyPair::new(Algorithm::Ed25519,); - /// let mut builder = Biscuit::builder(); - /// builder.add_fact("user(\"John Doe\", 42)"); - /// - /// let biscuit = builder.build(&keypair).unwrap(); + /// let biscuit = Biscuit::builder() + /// .add_fact("user(\"John Doe\", 42)") + /// .expect("parse error") + /// .build(&keypair) + /// .unwrap(); /// /// let mut authorizer = biscuit.authorizer().unwrap(); /// let res: Vec<(String, i64)> = authorizer.query_all("data($name, $id) <- user($name, $id)").unwrap(); diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs index c6f448a1..87d0c5af 100644 --- a/biscuit-auth/src/token/builder/authorizer.rs +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -61,18 +61,19 @@ impl<'a> AuthorizerBuilder<'a> { /// ```rust /// extern crate biscuit_auth as biscuit; /// - /// use biscuit::Authorizer; + /// use biscuit::builder::AuthorizerBuilder; /// - /// let mut authorizer = Authorizer::new(); + /// let mut authorizer = AuthorizerBuilder::new() + /// .add_code(r#" + /// resource("/file1.txt"); /// - /// authorizer.add_code(r#" - /// resource("/file1.txt"); + /// check if user(1234); /// - /// check if user(1234); - /// - /// // default allow - /// allow if true; - /// "#).expect("should parse correctly"); + /// // default allow + /// allow if true; + /// "#) + /// .expect("should parse correctly") + /// .build(); /// ``` pub fn add_code>(self, source: T) -> Result { self.add_code_with_params(source, HashMap::new(), HashMap::new()) diff --git a/biscuit-auth/src/token/mod.rs b/biscuit-auth/src/token/mod.rs index 79d82975..fd9a5bb4 100644 --- a/biscuit-auth/src/token/mod.rs +++ b/biscuit-auth/src/token/mod.rs @@ -54,25 +54,26 @@ pub fn default_symbol_table() -> SymbolTable { /// /// use biscuit::{KeyPair, Biscuit, builder::*, builder_ext::*}; /// -/// fn main() { +/// fn main() -> Result<(), biscuit::error::Token> { /// let root = KeyPair::new(Algorithm::Ed25519); /// /// // first we define the authority block for global data, /// // like access rights /// // data from the authority block cannot be created in any other block -/// let mut builder = Biscuit::builder(); -/// builder.add_fact(fact("right", &[string("/a/file1.txt"), string("read")])); +/// let token1 = Biscuit::builder() +/// .add_fact(fact("right", &[string("/a/file1.txt"), string("read")]))? /// -/// // facts and rules can also be parsed from a string -/// builder.add_fact("right(\"/a/file1.txt\", \"read\")").expect("parse error"); -/// -/// let token1 = builder.build(&root).unwrap(); +/// // facts and rules can also be parsed from a string +/// .add_fact("right(\"/a/file1.txt\", \"read\")")? +/// .build(&root)?; /// /// // we can create a new block builder from that token -/// let mut builder2 = BlockBuilder::new(); -/// builder2.check_operation("read"); +/// let builder2 = BlockBuilder::new() +/// .check_operation("read"); +/// +/// let token2 = token1.append(builder2)?; /// -/// let token2 = token1.append(builder2).unwrap(); +/// Ok(()) /// } /// ``` #[derive(Clone, Debug)] From b5757454312f155476d464c01ce60390bda6c2a0 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Thu, 28 Nov 2024 11:18:19 +0100 Subject: [PATCH 20/28] cleanup --- biscuit-auth/src/token/authorizer.rs | 32 ---------------------------- 1 file changed, 32 deletions(-) diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index a2e6e86b..122310ef 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -320,7 +320,6 @@ impl Authorizer { self.authorize_with_limits(limits) } - /// TODO: consume the input to prevent further direct use /// verifies the checks and policies /// /// on error, this can return a list of all the failed checks or deny policy @@ -670,24 +669,6 @@ impl std::fmt::Display for Authorizer { all_facts.insert(origin, facts); } - let builder_facts = self - .authorizer_block_builder - .facts - .iter() - .map(|f| f.to_string()) - .collect::>(); - has_facts = has_facts || !builder_facts.is_empty(); - let mut authorizer_origin = Origin::default(); - authorizer_origin.insert(usize::MAX); - match all_facts.get_mut(&authorizer_origin) { - Some(e) => { - e.extend(builder_facts); - } - None => { - all_facts.insert(&authorizer_origin, builder_facts); - } - } - if has_facts { writeln!(f, "// Facts:")?; } @@ -721,19 +702,6 @@ impl std::fmt::Display for Authorizer { } } - let builder_rules = self - .authorizer_block_builder - .rules - .iter() - .map(|rule| rule.to_string()) - .collect::>(); - has_rules = has_rules || !builder_rules.is_empty(); - - rules_map - .entry(usize::MAX) - .or_default() - .extend(builder_rules); - if has_rules { writeln!(f, "// Rules:")?; } From 33026e5a19f54d9b161e9659711b25b1f9909e89 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Thu, 28 Nov 2024 11:43:25 +0100 Subject: [PATCH 21/28] rename --- biscuit-auth/benches/token.rs | 166 +++++++-------- biscuit-auth/examples/testcases.rs | 8 +- biscuit-auth/examples/third_party.rs | 12 +- biscuit-auth/examples/verifying_printer.rs | 4 +- biscuit-auth/src/lib.rs | 6 +- biscuit-auth/src/macros.rs | 2 +- biscuit-auth/src/token/authorizer.rs | 50 +++-- biscuit-auth/src/token/builder.rs | 10 +- biscuit-auth/src/token/builder/authorizer.rs | 50 ++--- biscuit-auth/src/token/builder/biscuit.rs | 44 ++-- biscuit-auth/src/token/builder/block.rs | 22 +- biscuit-auth/src/token/builder_ext.rs | 8 +- biscuit-auth/src/token/mod.rs | 210 +++++++++---------- biscuit-auth/src/token/third_party.rs | 6 +- biscuit-auth/tests/macros.rs | 4 +- biscuit-auth/tests/rights.rs | 10 +- biscuit-capi/src/lib.rs | 26 +-- biscuit-quote/src/lib.rs | 8 +- 18 files changed, 321 insertions(+), 325 deletions(-) diff --git a/biscuit-auth/benches/token.rs b/biscuit-auth/benches/token.rs index 034e4758..3d12bebb 100644 --- a/biscuit-auth/benches/token.rs +++ b/biscuit-auth/benches/token.rs @@ -16,11 +16,11 @@ fn create_block_1(b: &mut Bencher) { let root = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let token = Biscuit::builder() - .add_fact(fact("right", &[string("file1"), string("read")])) + .fact(fact("right", &[string("file1"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file2"), string("read")])) + .fact(fact("right", &[string("file2"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file1"), string("write")])) + .fact(fact("right", &[string("file1"), string("write")])) .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); @@ -30,11 +30,11 @@ fn create_block_1(b: &mut Bencher) { assert_eq!(b.bytes, 206); b.iter(|| { let token = Biscuit::builder() - .add_fact(fact("right", &[string("file1"), string("read")])) + .fact(fact("right", &[string("file1"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file2"), string("read")])) + .fact(fact("right", &[string("file2"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file1"), string("write")])) + .fact(fact("right", &[string("file1"), string("write")])) .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); @@ -48,11 +48,11 @@ fn append_block_2(b: &mut Bencher) { let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let token = Biscuit::builder() - .add_fact(fact("right", &[string("file1"), string("read")])) + .fact(fact("right", &[string("file1"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file2"), string("read")])) + .fact(fact("right", &[string("file2"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file1"), string("write")])) + .fact(fact("right", &[string("file1"), string("write")])) .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); @@ -87,11 +87,11 @@ fn append_block_5(b: &mut Bencher) { let keypair5 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let token = Biscuit::builder() - .add_fact(fact("right", &[string("file1"), string("read")])) + .fact(fact("right", &[string("file1"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file2"), string("read")])) + .fact(fact("right", &[string("file2"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file1"), string("write")])) + .fact(fact("right", &[string("file1"), string("write")])) .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); @@ -145,11 +145,11 @@ fn unverified_append_block_2(b: &mut Bencher) { let keypair2 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let token = Biscuit::builder() - .add_fact(fact("right", &[string("file1"), string("read")])) + .fact(fact("right", &[string("file1"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file2"), string("read")])) + .fact(fact("right", &[string("file2"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file1"), string("write")])) + .fact(fact("right", &[string("file1"), string("write")])) .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); @@ -184,11 +184,11 @@ fn unverified_append_block_5(b: &mut Bencher) { let keypair5 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); let token = Biscuit::builder() - .add_fact(fact("right", &[string("file1"), string("read")])) + .fact(fact("right", &[string("file1"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file2"), string("read")])) + .fact(fact("right", &[string("file2"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file1"), string("write")])) + .fact(fact("right", &[string("file1"), string("write")])) .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); @@ -243,11 +243,11 @@ fn verify_block_2(b: &mut Bencher) { let data = { let token = Biscuit::builder() - .add_fact(fact("right", &[string("file1"), string("read")])) + .fact(fact("right", &[string("file1"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file2"), string("read")])) + .fact(fact("right", &[string("file2"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file1"), string("write")])) + .fact(fact("right", &[string("file1"), string("write")])) .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); @@ -263,12 +263,12 @@ fn verify_block_2(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .add_token(&token) - .add_fact("resource(\"file1\")") + .token(&token) + .fact("resource(\"file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .add_allow_all() + .allow_all() .build() .unwrap(); verifier @@ -281,12 +281,12 @@ fn verify_block_2(b: &mut Bencher) { b.iter(|| { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .add_token(&token) - .add_fact("resource(\"file1\")") + .token(&token) + .fact("resource(\"file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .add_allow_all() + .allow_all() .build() .unwrap(); verifier @@ -308,11 +308,11 @@ fn verify_block_5(b: &mut Bencher) { let data = { let token = Biscuit::builder() - .add_fact(fact("right", &[string("file1"), string("read")])) + .fact(fact("right", &[string("file1"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file2"), string("read")])) + .fact(fact("right", &[string("file2"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file1"), string("write")])) + .fact(fact("right", &[string("file1"), string("write")])) .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); @@ -352,12 +352,12 @@ fn verify_block_5(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .add_token(&token) - .add_fact("resource(\"file1\")") + .token(&token) + .fact("resource(\"file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .add_allow_all() + .allow_all() .build() .unwrap(); verifier @@ -371,12 +371,12 @@ fn verify_block_5(b: &mut Bencher) { b.iter(|| { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .add_token(&token) - .add_fact("resource(\"file1\")") + .token(&token) + .fact("resource(\"file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .add_allow_all() + .allow_all() .build() .unwrap(); verifier @@ -395,11 +395,11 @@ fn check_signature_2(b: &mut Bencher) { let data = { let token = Biscuit::builder() - .add_fact(fact("right", &[string("file1"), string("read")])) + .fact(fact("right", &[string("file1"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file2"), string("read")])) + .fact(fact("right", &[string("file2"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file1"), string("write")])) + .fact(fact("right", &[string("file1"), string("write")])) .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); @@ -415,12 +415,12 @@ fn check_signature_2(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .add_token(&token) - .add_fact("resource(\"file1\")") + .token(&token) + .fact("resource(\"file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .add_allow_all() + .allow_all() .build() .unwrap(); verifier @@ -446,11 +446,11 @@ fn check_signature_5(b: &mut Bencher) { let data = { let token = Biscuit::builder() - .add_fact(fact("right", &[string("file1"), string("read")])) + .fact(fact("right", &[string("file1"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file2"), string("read")])) + .fact(fact("right", &[string("file2"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file1"), string("write")])) + .fact(fact("right", &[string("file1"), string("write")])) .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); @@ -489,12 +489,12 @@ fn check_signature_5(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .add_token(&token) - .add_fact("resource(\"file1\")") + .token(&token) + .fact("resource(\"file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .add_allow_all() + .allow_all() .build() .unwrap(); verifier @@ -517,11 +517,11 @@ fn checks_block_2(b: &mut Bencher) { let data = { let token = Biscuit::builder() - .add_fact(fact("right", &[string("file1"), string("read")])) + .fact(fact("right", &[string("file1"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file2"), string("read")])) + .fact(fact("right", &[string("file2"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file1"), string("write")])) + .fact(fact("right", &[string("file1"), string("write")])) .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); @@ -537,12 +537,12 @@ fn checks_block_2(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .add_token(&token) - .add_fact("resource(\"file1\")") + .token(&token) + .fact("resource(\"file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .add_allow_all() + .allow_all() .build() .unwrap(); verifier @@ -556,12 +556,12 @@ fn checks_block_2(b: &mut Bencher) { b.bytes = data.len() as u64; b.iter(|| { let mut verifier = AuthorizerBuilder::new() - .add_token(&token) - .add_fact("resource(\"file1\")") + .token(&token) + .fact("resource(\"file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .add_allow_all() + .allow_all() .build() .unwrap(); verifier @@ -580,11 +580,11 @@ fn checks_block_create_verifier2(b: &mut Bencher) { let data = { let token = Biscuit::builder() - .add_fact(fact("right", &[string("file1"), string("read")])) + .fact(fact("right", &[string("file1"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file2"), string("read")])) + .fact(fact("right", &[string("file2"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file1"), string("write")])) + .fact(fact("right", &[string("file1"), string("write")])) .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); @@ -600,12 +600,12 @@ fn checks_block_create_verifier2(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .add_token(&token) - .add_fact("resource(\"file1\")") + .token(&token) + .fact("resource(\"file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .add_allow_all() + .allow_all() .build() .unwrap(); verifier @@ -629,11 +629,11 @@ fn checks_block_verify_only2(b: &mut Bencher) { let data = { let token = Biscuit::builder() - .add_fact(fact("right", &[string("file1"), string("read")])) + .fact(fact("right", &[string("file1"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file2"), string("read")])) + .fact(fact("right", &[string("file2"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file1"), string("write")])) + .fact(fact("right", &[string("file1"), string("write")])) .unwrap() .build_with_rng(&root, SymbolTable::default(), &mut rng) .unwrap(); @@ -649,12 +649,12 @@ fn checks_block_verify_only2(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .add_token(&token) - .add_fact("resource(\"file1\")") + .token(&token) + .fact("resource(\"file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .add_allow_all() + .allow_all() .build() .unwrap(); verifier @@ -667,12 +667,12 @@ fn checks_block_verify_only2(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); b.iter(|| { let mut verifier = AuthorizerBuilder::new() - .add_token(&token) - .add_fact("resource(\"file1\")") + .token(&token) + .fact("resource(\"file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .add_allow_all() + .allow_all() .build() .unwrap(); verifier diff --git a/biscuit-auth/examples/testcases.rs b/biscuit-auth/examples/testcases.rs index 69915631..f107d007 100644 --- a/biscuit-auth/examples/testcases.rs +++ b/biscuit-auth/examples/testcases.rs @@ -345,11 +345,11 @@ fn validate_token_with_limits_and_external_functions( let builder = AuthorizerBuilder::new() .set_extern_funcs(extern_funcs) - .add_code(authorizer_code) + .code(authorizer_code) .unwrap(); let authorizer_code = builder.dump_code(); - let mut authorizer = match builder.add_token(&token).build() { + let mut authorizer = match builder.token(&token).build() { Ok(v) => v, Err(e) => { return Validation { @@ -879,7 +879,7 @@ fn scoped_rules(target: &str, root: &KeyPair, test: bool) -> TestResult { .unwrap(); let block3 = BlockBuilder::new() - .add_fact(r#"owner("alice", "file2")"#) + .fact(r#"owner("alice", "file2")"#) .unwrap(); let keypair3 = KeyPair::new_with_rng(Algorithm::Ed25519, &mut rng); @@ -1411,7 +1411,7 @@ fn unbound_variables_in_rule(target: &str, root: &KeyPair, test: bool) -> TestRe let block2 = BlockBuilder::new() // this one does not go through the parser because it checks for unused variables - .add_rule(rule( + .rule(rule( "operation", &[var("unbound"), string("read")], &[pred("operation", &[var("any1"), var("any2")])], diff --git a/biscuit-auth/examples/third_party.rs b/biscuit-auth/examples/third_party.rs index 6b11beb4..5f135e2e 100644 --- a/biscuit-auth/examples/third_party.rs +++ b/biscuit-auth/examples/third_party.rs @@ -13,7 +13,7 @@ fn main() { let external_pub = hex::encode(external.public().to_bytes()); let biscuit1 = Biscuit::builder() - .add_check( + .check( format!("check if external_fact(\"hello\") trusting ed25519/{external_pub}").as_str(), ) .unwrap() @@ -26,7 +26,7 @@ fn main() { let req = biscuit_auth::ThirdPartyRequest::deserialize(&serialized_req).unwrap(); let builder = BlockBuilder::new() - .add_fact("external_fact(\"hello\")") + .fact("external_fact(\"hello\")") .unwrap(); let res = req.create_block(&external.private(), builder).unwrap(); @@ -35,8 +35,8 @@ fn main() { println!("biscuit2: {}", biscuit2); let mut authorizer = AuthorizerBuilder::new() - .add_token(&biscuit1) - .add_allow_all() + .token(&biscuit1) + .allow_all() .build() .unwrap(); @@ -44,8 +44,8 @@ fn main() { println!("world:\n{}", authorizer.print_world()); let mut authorizer = AuthorizerBuilder::new() - .add_token(&biscuit2) - .add_allow_all() + .token(&biscuit2) + .allow_all() .build() .unwrap(); diff --git a/biscuit-auth/examples/verifying_printer.rs b/biscuit-auth/examples/verifying_printer.rs index 8dc6e210..177b560a 100644 --- a/biscuit-auth/examples/verifying_printer.rs +++ b/biscuit-auth/examples/verifying_printer.rs @@ -26,8 +26,8 @@ fn main() { println!("token:\n{}", token); let mut authorizer = AuthorizerBuilder::new() - .add_token(&token) - .add_allow_all() + .token(&token) + .allow_all() .build() .unwrap(); diff --git a/biscuit-auth/src/lib.rs b/biscuit-auth/src/lib.rs index 10df1b8b..e1d3b4bb 100644 --- a/biscuit-auth/src/lib.rs +++ b/biscuit-auth/src/lib.rs @@ -102,7 +102,7 @@ //! // matches, a default deny applies //! deny if true; //! "#) -//! .add_token(&biscuit2) +//! .token(&biscuit2) //! .build()?; //! //! let mut v2 = authorizer!(r#" @@ -110,7 +110,7 @@ //! operation("write"); //! allow if right("/a/file1.txt", "write"); //! "#) -//! .add_token(&biscuit2) +//! .token(&biscuit2) //! .build()?; //! //! let mut v3 = authorizer!(r#" @@ -118,7 +118,7 @@ //! operation("read"); //! allow if right("/a/file2.txt", "read"); //! "#) -//! .add_token(&biscuit2) +//! .token(&biscuit2) //! .build()?; //! //! // the token restricts to read operations: diff --git a/biscuit-auth/src/macros.rs b/biscuit-auth/src/macros.rs index a0075b72..9a24da99 100644 --- a/biscuit-auth/src/macros.rs +++ b/biscuit-auth/src/macros.rs @@ -43,7 +43,7 @@ //! resource = "file1", //! user_id = "1234", //! ) -//! .add_token(&new_biscuit) +//! .token(&new_biscuit) //! .build() //! .expect("failed to build the authorizer") //! .authorize() diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index 122310ef..f0843a73 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -36,7 +36,7 @@ pub struct Authorizer { impl Authorizer { pub(crate) fn from_token(token: &Biscuit) -> Result { - AuthorizerBuilder::new().add_token(token).build() + AuthorizerBuilder::new().token(token).build() } /// creates a new empty authorizer @@ -111,7 +111,7 @@ impl Authorizer { /// # use biscuit_auth::builder::Algorithm; /// let keypair = KeyPair::new(Algorithm::Ed25519); /// let biscuit = Biscuit::builder() - /// .add_fact("user(\"John Doe\", 42)") + /// .fact("user(\"John Doe\", 42)") /// .expect("parse error") /// .build(&keypair) /// .unwrap(); @@ -202,7 +202,7 @@ impl Authorizer { /// # use biscuit_auth::builder::Algorithm; /// let keypair = KeyPair::new(Algorithm::Ed25519,); /// let biscuit = Biscuit::builder() - /// .add_fact("user(\"John Doe\", 42)") + /// .fact("user(\"John Doe\", 42)") /// .expect("parse error") /// .build(&keypair) /// .unwrap(); @@ -794,18 +794,16 @@ impl TryFrom for Authorizer { let mut authorizer = Self::new(); for fact in facts.into_iter() { - authorizer.authorizer_block_builder = - authorizer.authorizer_block_builder.add_fact(fact)?; + authorizer.authorizer_block_builder = authorizer.authorizer_block_builder.fact(fact)?; } for rule in rules.into_iter() { - authorizer.authorizer_block_builder = - authorizer.authorizer_block_builder.add_rule(rule)?; + authorizer.authorizer_block_builder = authorizer.authorizer_block_builder.rule(rule)?; } for check in checks.into_iter() { authorizer.authorizer_block_builder = - authorizer.authorizer_block_builder.add_check(check)?; + authorizer.authorizer_block_builder.check(check)?; } for policy in policies { @@ -873,7 +871,7 @@ mod tests { #[test] fn empty_authorizer() { let mut authorizer = AuthorizerBuilder::new() - .add_policy("allow if true") + .policy("allow if true") .unwrap() .build() .unwrap(); @@ -903,7 +901,7 @@ mod tests { .unwrap(), ); let _authorizer = AuthorizerBuilder::new() - .add_code_with_params( + .code_with_params( r#" fact({p1}, "value"); rule($var, {p2}) <- fact($var, {p2}); @@ -924,7 +922,7 @@ mod tests { let mut fact = Fact::try_from("fact({p1}, {p4})").unwrap(); fact.set("p1", "hello").unwrap(); - let res = builder.clone().add_fact(fact); + let res = builder.clone().fact(fact); assert_eq!( res.unwrap_err(), error::Token::Language(biscuit_parser::error::LanguageError::Parameters { @@ -937,7 +935,7 @@ mod tests { ) .unwrap(); rule.set("p2", "hello").unwrap(); - let res = builder.clone().add_rule(rule); + let res = builder.clone().rule(rule); assert_eq!( res.unwrap_err(), error::Token::Language(biscuit_parser::error::LanguageError::Parameters { @@ -947,7 +945,7 @@ mod tests { ); let mut check = Check::try_from("check if {p4}, {p3}").unwrap(); check.set("p3", true).unwrap(); - let res = builder.clone().add_check(check); + let res = builder.clone().check(check); assert_eq!( res.unwrap_err(), error::Token::Language(biscuit_parser::error::LanguageError::Parameters { @@ -958,7 +956,7 @@ mod tests { let mut policy = Policy::try_from("allow if {p4}, {p3}").unwrap(); policy.set("p3", true).unwrap(); - let res = builder.clone().add_policy(policy); + let res = builder.clone().policy(policy); assert_eq!( res.unwrap_err(), error::Token::Language(biscuit_parser::error::LanguageError::Parameters { @@ -975,7 +973,7 @@ mod tests { params.insert("p1".to_string(), "hello".into()); params.insert("p2".to_string(), 1i64.into()); params.insert("p4".to_string(), "this will be ignored".into()); - let res = builder.add_code_with_params( + let res = builder.code_with_params( r#"fact({p1}, "value"); rule($head_var) <- f1($head_var), {p2} > 0; check if {p3}; @@ -1000,7 +998,7 @@ mod tests { use crate::KeyPair; let keypair = KeyPair::new(Algorithm::Ed25519); let biscuit = Biscuit::builder() - .add_fact("user(\"John Doe\", 42)") + .fact("user(\"John Doe\", 42)") .unwrap() .build(&keypair) .unwrap(); @@ -1021,7 +1019,7 @@ mod tests { use crate::KeyPair; let keypair = KeyPair::new(Algorithm::Ed25519); let biscuit = Biscuit::builder() - .add_fact("user(\"John Doe\")") + .fact("user(\"John Doe\")") .unwrap() .build(&keypair) .unwrap(); @@ -1042,7 +1040,7 @@ mod tests { scope_params.insert("external_pub".to_string(), external.public()); let biscuit1 = Biscuit::builder() - .add_code_with_params( + .code_with_params( r#"right("read"); check if group("admin") trusting {external_pub}; "#, @@ -1056,7 +1054,7 @@ mod tests { let req = biscuit1.third_party_request().unwrap(); let builder = BlockBuilder::new() - .add_code( + .code( r#"group("admin"); check if right("read"); "#, @@ -1075,7 +1073,7 @@ mod tests { scope_params.insert("external2".to_string(), external2.public()); let mut authorizer = builder - .add_code_with_params( + .code_with_params( r#" // this rule trusts both the third-party block and the authority, and can access facts // from both @@ -1095,8 +1093,8 @@ mod tests { scope_params, ) .unwrap() - .add_token(&biscuit2) - .set_limits(AuthorizerLimits { + .token(&biscuit2) + .limits(AuthorizerLimits { max_time: Duration::from_millis(10), //Set 10 milliseconds as the maximum time allowed for the authorization due to "cheap" worker on GitHub Actions ..Default::default() }) @@ -1220,7 +1218,7 @@ mod tests { let root = KeyPair::new(Algorithm::Ed25519); let token = BiscuitBuilder::new() - .add_code( + .code( r#" authority_fact(true); authority_rule($v) <- authority_fact($v); @@ -1232,8 +1230,8 @@ mod tests { .unwrap(); let mut authorizer = AuthorizerBuilder::new() - .add_token(&token) - .add_code( + .token(&token) + .code( r#" authorizer_fact(true); authorizer_rule($v) <- authorizer_fact($v); @@ -1342,7 +1340,7 @@ allow if true; // broken rules directly added to the authorizer currently don’t trigger any error, but silently fail to generate facts when they match let mut authorizer = builder - .add_rule(builder::rule( + .rule(builder::rule( "test", &[var("unbound")], &[builder::pred("pred", &[builder::var("any")])], diff --git a/biscuit-auth/src/token/builder.rs b/biscuit-auth/src/token/builder.rs index c03d98e9..aa80194a 100644 --- a/biscuit-auth/src/token/builder.rs +++ b/biscuit-auth/src/token/builder.rs @@ -252,7 +252,7 @@ mod tests { let mut scope_params = HashMap::new(); scope_params.insert("pk".to_string(), pubkey); builder = builder - .add_code_with_params( + .code_with_params( r#"fact({p1}, "value"); rule($head_var) <- f1($head_var), {p2} > 0 trusting {pk}; check if {p3} trusting {pk}; @@ -276,7 +276,7 @@ check if true trusting ed25519/6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc let mut fact = Fact::try_from("fact({p1}, {p4})").unwrap(); fact.set("p1", "hello").unwrap(); - let res = builder.clone().add_fact(fact); + let res = builder.clone().fact(fact); assert_eq!( res.unwrap_err(), error::Token::Language(biscuit_parser::error::LanguageError::Parameters { @@ -289,7 +289,7 @@ check if true trusting ed25519/6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc ) .unwrap(); rule.set("p2", "hello").unwrap(); - let res = builder.clone().add_rule(rule); + let res = builder.clone().rule(rule); assert_eq!( res.unwrap_err(), error::Token::Language(biscuit_parser::error::LanguageError::Parameters { @@ -299,7 +299,7 @@ check if true trusting ed25519/6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc ); let mut check = Check::try_from("check if {p4}, {p3}").unwrap(); check.set("p3", true).unwrap(); - let res = builder.clone().add_check(check); + let res = builder.clone().check(check); assert_eq!( res.unwrap_err(), error::Token::Language(biscuit_parser::error::LanguageError::Parameters { @@ -316,7 +316,7 @@ check if true trusting ed25519/6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc params.insert("p1".to_string(), "hello".into()); params.insert("p2".to_string(), 1i64.into()); params.insert("p4".to_string(), "this will be ignored".into()); - let res = builder.add_code_with_params( + let res = builder.code_with_params( r#"fact({p1}, "value"); rule($head_var) <- f1($head_var), {p2} > 0; check if {p3}; diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs index 87d0c5af..abfc2a6a 100644 --- a/biscuit-auth/src/token/builder/authorizer.rs +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -32,27 +32,27 @@ impl<'a> AuthorizerBuilder<'a> { AuthorizerBuilder::default() } - pub fn add_fact>(mut self, fact: F) -> Result + pub fn fact>(mut self, fact: F) -> Result where error::Token: From<>::Error>, { - self.authorizer_block_builder = self.authorizer_block_builder.add_fact(fact)?; + self.authorizer_block_builder = self.authorizer_block_builder.fact(fact)?; Ok(self) } - pub fn add_rule>(mut self, rule: R) -> Result + pub fn rule>(mut self, rule: R) -> Result where error::Token: From<>::Error>, { - self.authorizer_block_builder = self.authorizer_block_builder.add_rule(rule)?; + self.authorizer_block_builder = self.authorizer_block_builder.rule(rule)?; Ok(self) } - pub fn add_check>(mut self, check: C) -> Result + pub fn check>(mut self, check: C) -> Result where error::Token: From<>::Error>, { - self.authorizer_block_builder = self.authorizer_block_builder.add_check(check)?; + self.authorizer_block_builder = self.authorizer_block_builder.check(check)?; Ok(self) } @@ -64,7 +64,7 @@ impl<'a> AuthorizerBuilder<'a> { /// use biscuit::builder::AuthorizerBuilder; /// /// let mut authorizer = AuthorizerBuilder::new() - /// .add_code(r#" + /// .code(r#" /// resource("/file1.txt"); /// /// check if user(1234); @@ -75,13 +75,13 @@ impl<'a> AuthorizerBuilder<'a> { /// .expect("should parse correctly") /// .build(); /// ``` - pub fn add_code>(self, source: T) -> Result { - self.add_code_with_params(source, HashMap::new(), HashMap::new()) + pub fn code>(self, source: T) -> Result { + self.code_with_params(source, HashMap::new(), HashMap::new()) } /// Add datalog code to the builder, performing parameter subsitution as required /// Unknown parameters are ignored - pub fn add_code_with_params>( + pub fn code_with_params>( mut self, source: T, params: HashMap, @@ -204,13 +204,13 @@ impl<'a> AuthorizerBuilder<'a> { Ok(self) } - pub fn add_scope(mut self, scope: Scope) -> Self { - self.authorizer_block_builder = self.authorizer_block_builder.add_scope(scope); + pub fn scope(mut self, scope: Scope) -> Self { + self.authorizer_block_builder = self.authorizer_block_builder.scope(scope); self } /// add a policy to the authorizer - pub fn add_policy>(mut self, policy: P) -> Result + pub fn policy>(mut self, policy: P) -> Result where error::Token: From<

>::Error>, { @@ -221,16 +221,16 @@ impl<'a> AuthorizerBuilder<'a> { } /// adds a fact with the current time - pub fn set_time(mut self) -> Self { + pub fn time(mut self) -> Self { let fact = fact("time", &[date(&SystemTime::now())]); - self.authorizer_block_builder = self.authorizer_block_builder.add_fact(fact).unwrap(); + self.authorizer_block_builder = self.authorizer_block_builder.fact(fact).unwrap(); self } /// Sets the runtime limits of the authorizer /// /// Those limits cover all the executions under the `authorize`, `query` and `query_all` methods - pub fn set_limits(mut self, limits: AuthorizerLimits) -> Self { + pub fn limits(mut self, limits: AuthorizerLimits) -> Self { self.limits = limits; self } @@ -253,7 +253,7 @@ impl<'a> AuthorizerBuilder<'a> { self } - pub fn add_token(mut self, token: &'a Biscuit) -> Self { + pub fn token(mut self, token: &'a Biscuit) -> Self { self.token = Some(token); self } @@ -451,16 +451,16 @@ pub(crate) fn load_and_translate_block( } impl<'a> BuilderExt for AuthorizerBuilder<'a> { - fn add_resource(mut self, name: &str) -> Self { - self.authorizer_block_builder = self.authorizer_block_builder.add_resource(name); + fn resource(mut self, name: &str) -> Self { + self.authorizer_block_builder = self.authorizer_block_builder.resource(name); self } fn check_resource(mut self, name: &str) -> Self { self.authorizer_block_builder = self.authorizer_block_builder.check_resource(name); self } - fn add_operation(mut self, name: &str) -> Self { - self.authorizer_block_builder = self.authorizer_block_builder.add_operation(name); + fn operation(mut self, name: &str) -> Self { + self.authorizer_block_builder = self.authorizer_block_builder.operation(name); self } fn check_operation(mut self, name: &str) -> Self { @@ -484,10 +484,10 @@ impl<'a> BuilderExt for AuthorizerBuilder<'a> { } impl<'a> AuthorizerExt for AuthorizerBuilder<'a> { - fn add_allow_all(self) -> Self { - self.add_policy("allow if true").unwrap() + fn allow_all(self) -> Self { + self.policy("allow if true").unwrap() } - fn add_deny_all(self) -> Self { - self.add_policy("deny if true").unwrap() + fn deny_all(self) -> Self { + self.policy("deny if true").unwrap() } } diff --git a/biscuit-auth/src/token/builder/biscuit.rs b/biscuit-auth/src/token/builder/biscuit.rs index 5bcdce3e..4bd769f4 100644 --- a/biscuit-auth/src/token/builder/biscuit.rs +++ b/biscuit-auth/src/token/builder/biscuit.rs @@ -30,70 +30,68 @@ impl BiscuitBuilder { self } - pub fn add_fact>(mut self, fact: F) -> Result + pub fn fact>(mut self, fact: F) -> Result where error::Token: From<>::Error>, { - self.inner = self.inner.add_fact(fact)?; + self.inner = self.inner.fact(fact)?; Ok(self) } - pub fn add_rule>(mut self, rule: Ru) -> Result + pub fn rule>(mut self, rule: Ru) -> Result where error::Token: From<>::Error>, { - self.inner = self.inner.add_rule(rule)?; + self.inner = self.inner.rule(rule)?; Ok(self) } - pub fn add_check>(mut self, check: C) -> Result + pub fn check>(mut self, check: C) -> Result where error::Token: From<>::Error>, { - self.inner = self.inner.add_check(check)?; + self.inner = self.inner.check(check)?; Ok(self) } - pub fn add_code>(mut self, source: T) -> Result { + pub fn code>(mut self, source: T) -> Result { self.inner = self .inner - .add_code_with_params(source, HashMap::new(), HashMap::new())?; + .code_with_params(source, HashMap::new(), HashMap::new())?; Ok(self) } - pub fn add_code_with_params>( + pub fn code_with_params>( mut self, source: T, params: HashMap, scope_params: HashMap, ) -> Result { - self.inner = self - .inner - .add_code_with_params(source, params, scope_params)?; + self.inner = self.inner.code_with_params(source, params, scope_params)?; Ok(self) } - pub fn add_scope(mut self, scope: Scope) -> Self { - self.inner = self.inner.add_scope(scope); + pub fn scope(mut self, scope: Scope) -> Self { + self.inner = self.inner.scope(scope); self } #[cfg(test)] - pub(crate) fn add_right(self, resource: &str, right: &str) -> Self { + pub(crate) fn right(self, resource: &str, right: &str) -> Self { use crate::builder::fact; use super::string; - self.add_fact(fact("right", &[string(resource), string(right)])) + self.fact(fact("right", &[string(resource), string(right)])) .unwrap() } - pub fn set_context(mut self, context: String) -> Self { - self.inner = self.inner.set_context(context); + pub fn context(mut self, context: String) -> Self { + self.inner = self.inner.context(context); self } - pub fn set_root_key_id(mut self, root_key_id: u32) -> Self { + pub fn root_key_id(mut self, root_key_id: u32) -> Self { self.root_key_id = Some(root_key_id); self } @@ -166,8 +164,8 @@ impl fmt::Display for BiscuitBuilder { } impl BuilderExt for BiscuitBuilder { - fn add_resource(mut self, name: &str) -> Self { - self.inner = self.inner.add_resource(name); + fn resource(mut self, name: &str) -> Self { + self.inner = self.inner.resource(name); self } fn check_resource(mut self, name: &str) -> Self { @@ -182,8 +180,8 @@ impl BuilderExt for BiscuitBuilder { self.inner = self.inner.check_resource_suffix(suffix); self } - fn add_operation(mut self, name: &str) -> Self { - self.inner = self.inner.add_operation(name); + fn operation(mut self, name: &str) -> Self { + self.inner = self.inner.operation(name); self } fn check_operation(mut self, name: &str) -> Self { diff --git a/biscuit-auth/src/token/builder/block.rs b/biscuit-auth/src/token/builder/block.rs index 677d11bf..d0bf0459 100644 --- a/biscuit-auth/src/token/builder/block.rs +++ b/biscuit-auth/src/token/builder/block.rs @@ -37,7 +37,7 @@ impl BlockBuilder { self } - pub fn add_fact>(mut self, fact: F) -> Result + pub fn fact>(mut self, fact: F) -> Result where error::Token: From<>::Error>, { @@ -48,7 +48,7 @@ impl BlockBuilder { Ok(self) } - pub fn add_rule>(mut self, rule: R) -> Result + pub fn rule>(mut self, rule: R) -> Result where error::Token: From<>::Error>, { @@ -58,7 +58,7 @@ impl BlockBuilder { Ok(self) } - pub fn add_check>(mut self, check: C) -> Result + pub fn check>(mut self, check: C) -> Result where error::Token: From<>::Error>, { @@ -68,13 +68,13 @@ impl BlockBuilder { Ok(self) } - pub fn add_code>(self, source: T) -> Result { - self.add_code_with_params(source, HashMap::new(), HashMap::new()) + pub fn code>(self, source: T) -> Result { + self.code_with_params(source, HashMap::new(), HashMap::new()) } /// Add datalog code to the builder, performing parameter subsitution as required /// Unknown parameters are ignored - pub fn add_code_with_params>( + pub fn code_with_params>( mut self, source: T, params: HashMap, @@ -168,12 +168,12 @@ impl BlockBuilder { Ok(self) } - pub fn add_scope(mut self, scope: Scope) -> Self { + pub fn scope(mut self, scope: Scope) -> Self { self.scopes.push(scope); self } - pub fn set_context(mut self, context: String) -> Self { + pub fn context(mut self, context: String) -> Self { self.context = Some(context); self } @@ -266,7 +266,7 @@ impl BlockBuilder { ], ); - self.add_check(check) + self.check(check) } } @@ -289,7 +289,7 @@ impl fmt::Display for BlockBuilder { } impl BuilderExt for BlockBuilder { - fn add_resource(mut self, name: &str) -> Self { + fn resource(mut self, name: &str) -> Self { self.facts.push(fact("resource", &[string(name)])); self } @@ -304,7 +304,7 @@ impl BuilderExt for BlockBuilder { }); self } - fn add_operation(mut self, name: &str) -> Self { + fn operation(mut self, name: &str) -> Self { self.facts.push(fact("operation", &[string(name)])); self } diff --git a/biscuit-auth/src/token/builder_ext.rs b/biscuit-auth/src/token/builder_ext.rs index c23b4e88..93ca14d8 100644 --- a/biscuit-auth/src/token/builder_ext.rs +++ b/biscuit-auth/src/token/builder_ext.rs @@ -1,16 +1,16 @@ use std::time::SystemTime; pub trait BuilderExt { - fn add_resource(self, name: &str) -> Self; + fn resource(self, name: &str) -> Self; fn check_resource(self, name: &str) -> Self; fn check_resource_prefix(self, prefix: &str) -> Self; fn check_resource_suffix(self, suffix: &str) -> Self; - fn add_operation(self, name: &str) -> Self; + fn operation(self, name: &str) -> Self; fn check_operation(self, name: &str) -> Self; fn check_expiration_date(self, date: SystemTime) -> Self; } pub trait AuthorizerExt { - fn add_allow_all(self) -> Self; - fn add_deny_all(self) -> Self; + fn allow_all(self) -> Self; + fn deny_all(self) -> Self; } diff --git a/biscuit-auth/src/token/mod.rs b/biscuit-auth/src/token/mod.rs index fd9a5bb4..7a042b86 100644 --- a/biscuit-auth/src/token/mod.rs +++ b/biscuit-auth/src/token/mod.rs @@ -61,10 +61,10 @@ pub fn default_symbol_table() -> SymbolTable { /// // like access rights /// // data from the authority block cannot be created in any other block /// let token1 = Biscuit::builder() -/// .add_fact(fact("right", &[string("/a/file1.txt"), string("read")]))? +/// .fact(fact("right", &[string("/a/file1.txt"), string("read")]))? /// /// // facts and rules can also be parsed from a string -/// .add_fact("right(\"/a/file1.txt\", \"read\")")? +/// .fact("right(\"/a/file1.txt\", \"read\")")? /// .build(&root)?; /// /// // we can create a new block builder from that token @@ -744,11 +744,11 @@ mod tests { let serialized1 = { let biscuit1 = Biscuit::builder() - .add_fact("right(\"file1\", \"read\")") + .fact("right(\"file1\", \"read\")") .unwrap() - .add_fact("right(\"file2\", \"read\")") + .fact("right(\"file2\", \"read\")") .unwrap() - .add_fact("right(\"file1\", \"write\")") + .fact("right(\"file1\", \"write\")") .unwrap() .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); @@ -796,7 +796,7 @@ mod tests { // new check: can only have read access1 let block2 = BlockBuilder::new() - .add_check(rule( + .check(rule( "check1", &[var("resource")], &[ @@ -825,7 +825,7 @@ mod tests { // new check: can only access file1 let block3 = BlockBuilder::new() - .add_check(rule( + .check(rule( "check2", &[string("file1")], &[pred("resource", &[string("file1")])], @@ -847,7 +847,7 @@ mod tests { let final_token = Biscuit::from(&serialized3, root.public()).unwrap(); println!("final token:\n{}", final_token); { - let mut builder = AuthorizerBuilder::new().add_token(&final_token); + let mut builder = AuthorizerBuilder::new().token(&final_token); let mut facts = vec![ fact("resource", &[string("file1")]), @@ -855,12 +855,12 @@ mod tests { ]; for fact in facts.drain(..) { - builder = builder.add_fact(fact).unwrap(); + builder = builder.fact(fact).unwrap(); } //println!("final token: {:#?}", final_token); - let mut authorizer = builder.add_allow_all().build().unwrap(); + let mut authorizer = builder.allow_all().build().unwrap(); let res = authorizer.authorize(); println!("res1: {:?}", res); @@ -868,7 +868,7 @@ mod tests { } { - let mut builder = AuthorizerBuilder::new().add_token(&final_token); + let mut builder = AuthorizerBuilder::new().token(&final_token); let mut facts = vec![ fact("resource", &[string("file2")]), @@ -876,9 +876,9 @@ mod tests { ]; for fact in facts.drain(..) { - builder = builder.add_fact(fact).unwrap(); + builder = builder.fact(fact).unwrap(); } - builder = builder.add_allow_all(); + builder = builder.allow_all(); let mut authorizer = builder.build().unwrap(); @@ -904,11 +904,11 @@ mod tests { let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() - .add_right("/folder1/file1", "read") - .add_right("/folder1/file1", "write") - .add_right("/folder1/file2", "read") - .add_right("/folder1/file2", "write") - .add_right("/folder2/file3", "read") + .right("/folder1/file1", "read") + .right("/folder1/file1", "write") + .right("/folder1/file2", "read") + .right("/folder1/file2", "write") + .right("/folder2/file3", "read") .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); @@ -924,12 +924,12 @@ mod tests { { let mut authorizer = AuthorizerBuilder::new() - .add_token(&biscuit2) - .add_fact("resource(\"/folder1/file1\")") + .token(&biscuit2) + .fact("resource(\"/folder1/file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .add_allow_all() + .allow_all() .build() .unwrap(); @@ -944,12 +944,12 @@ mod tests { { let mut authorizer = AuthorizerBuilder::new() - .add_token(&biscuit2) - .add_fact("resource(\"/folder2/file3\")") + .token(&biscuit2) + .fact("resource(\"/folder2/file3\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .add_allow_all() + .allow_all() .build() .unwrap(); @@ -975,10 +975,10 @@ mod tests { { let mut authorizer = AuthorizerBuilder::new() - .add_token(&biscuit2) - .add_fact("resource(\"/folder2/file1\")") + .token(&biscuit2) + .fact("resource(\"/folder2/file1\")") .unwrap() - .add_fact("operation(\"write\")") + .fact("operation(\"write\")") .unwrap() .build() .unwrap(); @@ -1000,8 +1000,8 @@ mod tests { let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() - .add_right("file1", "read") - .add_right("file2", "read") + .right("file1", "read") + .right("file2", "read") .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); @@ -1009,7 +1009,7 @@ mod tests { let block2 = BlockBuilder::new() .check_expiration_date(SystemTime::now() + Duration::from_secs(30)) - .add_fact("key(1234)") + .fact("key(1234)") .unwrap(); let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); @@ -1017,13 +1017,13 @@ mod tests { { let mut authorizer = AuthorizerBuilder::new() - .add_token(&biscuit2) - .add_fact("resource(\"file1\")") + .token(&biscuit2) + .fact("resource(\"file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .set_time() - .add_allow_all() + .time() + .allow_all() .build() .unwrap(); @@ -1038,13 +1038,13 @@ mod tests { { println!("biscuit2: {}", biscuit2); let mut authorizer = AuthorizerBuilder::new() - .add_token(&biscuit2) - .add_fact("resource(\"file1\")") + .token(&biscuit2) + .fact("resource(\"file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .set_time() - .add_allow_all() + .time() + .allow_all() .build() .unwrap(); @@ -1065,11 +1065,11 @@ mod tests { let mut rng: StdRng = SeedableRng::seed_from_u64(0); let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() - .add_right("/folder1/file1", "read") - .add_right("/folder1/file1", "write") - .add_right("/folder1/file2", "read") - .add_right("/folder1/file2", "write") - .add_right("/folder2/file3", "read") + .right("/folder1/file1", "read") + .right("/folder1/file1", "write") + .right("/folder1/file2", "read") + .right("/folder1/file2", "write") + .right("/folder2/file3", "read") .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); @@ -1087,12 +1087,12 @@ mod tests { //panic!(); { let mut authorizer = AuthorizerBuilder::new() - .add_token(&biscuit2) - .add_fact("resource(\"/folder1/file1\")") + .token(&biscuit2) + .fact("resource(\"/folder1/file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .add_allow_all() + .allow_all() .build() .unwrap(); @@ -1114,12 +1114,12 @@ mod tests { { let mut authorizer = AuthorizerBuilder::new() - .add_token(&biscuit3) - .add_fact("resource(\"/folder1/file1\")") + .token(&biscuit3) + .fact("resource(\"/folder1/file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .add_allow_all() + .allow_all() .build() .unwrap(); @@ -1137,19 +1137,19 @@ mod tests { let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() - .add_fact(fact("right", &[string("file1"), string("read")])) + .fact(fact("right", &[string("file1"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file2"), string("read")])) + .fact(fact("right", &[string("file2"), string("read")])) .unwrap() - .add_fact(fact("right", &[string("file1"), string("write")])) + .fact(fact("right", &[string("file1"), string("write")])) .unwrap() .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); println!("{}", biscuit1); let mut authorizer = AuthorizerBuilder::new() - .add_token(&biscuit1) - .add_check(rule( + .token(&biscuit1) + .check(rule( "right", &[string("right")], &[pred("right", &[string("file2"), string("write")])], @@ -1181,9 +1181,9 @@ mod tests { let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() - .add_right("file1", "read") - .add_right("file2", "read") - .add_fact("key(0000)") + .right("file1", "read") + .right("file2", "read") + .fact("key(0000)") .unwrap() .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); @@ -1192,7 +1192,7 @@ mod tests { let block2 = BlockBuilder::new() .check_expiration_date(SystemTime::now() + Duration::from_secs(30)) - .add_fact("key(1234)") + .fact("key(1234)") .unwrap(); let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); @@ -1200,7 +1200,7 @@ mod tests { let block3 = BlockBuilder::new() .check_expiration_date(SystemTime::now() + Duration::from_secs(10)) - .add_fact("key(5678)") + .fact("key(5678)") .unwrap(); let keypair3 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); @@ -1209,12 +1209,12 @@ mod tests { println!("biscuit3: {}", biscuit3); let mut authorizer = AuthorizerBuilder::new() - .add_token(&biscuit3) - .add_fact("resource(\"file1\")") + .token(&biscuit3) + .fact("resource(\"file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .set_time() + .time() .build() .unwrap(); @@ -1272,7 +1272,7 @@ mod tests { let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() - .add_check(check( + .check(check( &[pred("resource", &[string("hello")])], CheckKind::One, )) @@ -1284,7 +1284,7 @@ mod tests { // new check: can only have read access1 let block2 = BlockBuilder::new() - .add_fact(fact("check1", &[string("test")])) + .fact(fact("check1", &[string("test")])) .unwrap(); let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); @@ -1295,12 +1295,12 @@ mod tests { //println!("generated biscuit token 2: {} bytes\n{}", serialized2.len(), serialized2.to_hex(16)); { let mut authorizer = AuthorizerBuilder::new() - .add_token(&biscuit2) - .add_fact("resource(\"file1\")") + .token(&biscuit2) + .fact("resource(\"file1\")") .unwrap() - .add_fact("operation(\"read\")") + .fact("operation(\"read\")") .unwrap() - .set_time() + .time() .build() .unwrap(); @@ -1377,7 +1377,7 @@ mod tests { let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() - .add_fact("bytes(hex:0102AB)") + .fact("bytes(hex:0102AB)") .unwrap() .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); @@ -1385,16 +1385,16 @@ mod tests { println!("biscuit1 (authority): {}", biscuit1); let block2 = BlockBuilder::new() - .add_rule("has_bytes($0) <- bytes($0), { hex:00000000, hex:0102AB }.contains($0)") + .rule("has_bytes($0) <- bytes($0), { hex:00000000, hex:0102AB }.contains($0)") .unwrap(); let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); let mut authorizer = AuthorizerBuilder::new() - .add_token(&biscuit2) - .add_check("check if bytes($0), { hex:00000000, hex:0102AB }.contains($0)") + .token(&biscuit2) + .check("check if bytes($0), { hex:00000000, hex:0102AB }.contains($0)") .unwrap() - .add_allow_all() + .allow_all() .build() .unwrap(); @@ -1425,13 +1425,13 @@ mod tests { let serialized1 = { let biscuit1 = Biscuit::builder() - .add_fact("right(\"/folder1/file1\", \"read\")") + .fact("right(\"/folder1/file1\", \"read\")") .unwrap() - .add_fact("right(\"/folder1/file1\", \"write\")") + .fact("right(\"/folder1/file1\", \"write\")") .unwrap() - .add_fact("right(\"/folder2/file1\", \"read\")") + .fact("right(\"/folder2/file1\", \"read\")") .unwrap() - .add_check("check if operation(\"read\")") + .check("check if operation(\"read\")") .unwrap() .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); @@ -1452,15 +1452,15 @@ mod tests { let block2 = BlockBuilder::new() // Bypass `check if operation("read")` from authority block - .add_rule("operation(\"read\") <- operation($any)") + .rule("operation(\"read\") <- operation($any)") .unwrap() // Bypass `check if resource($file), $file.starts_with("/folder1/")` from block #1 - .add_rule("resource(\"/folder1/\") <- resource($any)") + .rule("resource(\"/folder1/\") <- resource($any)") .unwrap() // Add missing rights - .add_rule("right($file, $right) <- right($any1, $any2), resource($file), operation($right)") + .rule("right($file, $right) <- right($any1, $any2), resource($file), operation($right)") .unwrap(); let keypair2 = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); @@ -1480,14 +1480,14 @@ mod tests { println!("final token:\n{}", final_token); let mut authorizer = AuthorizerBuilder::new() - .add_token(&final_token) - .add_fact("resource(\"/folder2/file1\")") + .token(&final_token) + .fact("resource(\"/folder2/file1\")") .unwrap() - .add_fact("operation(\"write\")") + .fact("operation(\"write\")") .unwrap() - .add_policy("allow if resource($file), operation($op), right($file, $op)") + .policy("allow if resource($file), operation($op), right($file, $op)") .unwrap() - .add_deny_all() + .deny_all() .build() .unwrap(); @@ -1507,7 +1507,7 @@ mod tests { let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() - .add_check("check if fact($v), $v < 1") + .check("check if fact($v), $v < 1") .unwrap() .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); @@ -1515,7 +1515,7 @@ mod tests { println!("biscuit1 (authority): {}", biscuit1); let biscuit2 = Biscuit::builder() - .add_check("check all fact($v), $v < 1") + .check("check all fact($v), $v < 1") .unwrap() .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); @@ -1524,13 +1524,13 @@ mod tests { { let mut authorizer = AuthorizerBuilder::new() - .add_token(&biscuit1) - .add_fact("fact(0)") + .token(&biscuit1) + .fact("fact(0)") .unwrap() - .add_fact("fact(1)") + .fact("fact(1)") .unwrap() //println!("final token: {:#?}", final_token); - .add_allow_all() + .allow_all() .build() .unwrap(); @@ -1544,13 +1544,13 @@ mod tests { { let mut authorizer = AuthorizerBuilder::new() - .add_token(&biscuit2) - .add_fact("fact(0)") + .token(&biscuit2) + .fact("fact(0)") .unwrap() - .add_fact("fact(1)") + .fact("fact(1)") .unwrap() //println!("final token: {:#?}", final_token); - .add_allow_all() + .allow_all() .build() .unwrap(); @@ -1632,11 +1632,11 @@ mod tests { let mut rng: StdRng = SeedableRng::seed_from_u64(0); let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() - .add_fact("right(\"file1\", \"read\")") + .fact("right(\"file1\", \"read\")") .unwrap() - .add_fact("right(\"file2\", \"read\")") + .fact("right(\"file2\", \"read\")") .unwrap() - .add_fact("right(\"file1\", \"write\")") + .fact("right(\"file1\", \"write\")") .unwrap() .build_with_rng(&root, default_symbol_table(), &mut rng) .unwrap(); diff --git a/biscuit-auth/src/token/third_party.rs b/biscuit-auth/src/token/third_party.rs index acd022a2..64b43d22 100644 --- a/biscuit-auth/src/token/third_party.rs +++ b/biscuit-auth/src/token/third_party.rs @@ -160,11 +160,11 @@ mod tests { let mut rng: rand::rngs::StdRng = rand::SeedableRng::seed_from_u64(0); let root = KeyPair::new_with_rng(crate::builder::Algorithm::Ed25519, &mut rng); let biscuit1 = crate::Biscuit::builder() - .add_fact("right(\"file1\", \"read\")") + .fact("right(\"file1\", \"read\")") .unwrap() - .add_fact("right(\"file2\", \"read\")") + .fact("right(\"file2\", \"read\")") .unwrap() - .add_fact("right(\"file1\", \"write\")") + .fact("right(\"file1\", \"write\")") .unwrap() .build_with_rng(&root, crate::token::default_symbol_table(), &mut rng) .unwrap(); diff --git a/biscuit-auth/tests/macros.rs b/biscuit-auth/tests/macros.rs index adc2034e..3bf92906 100644 --- a/biscuit-auth/tests/macros.rs +++ b/biscuit-auth/tests/macros.rs @@ -123,7 +123,7 @@ fn biscuit_macro() { check if true trusting ed25519/6e9e6d5a75cf0c0e87ec1256b4dfed0ca3ba452912d213fcc70f8516583db9db; "#, my_key_bytes = s.into_bytes(), - ).set_root_key_id(2); + ).root_key_id(2); let is_true = true; b = biscuit_merge!( @@ -261,7 +261,7 @@ fn json() { $value.get("id") == $id, $value.get("roles").contains("admin");"# ) - .add_token(&biscuit) + .token(&biscuit) .build() .unwrap(); assert_eq!( diff --git a/biscuit-auth/tests/rights.rs b/biscuit-auth/tests/rights.rs index e6918db3..84006470 100644 --- a/biscuit-auth/tests/rights.rs +++ b/biscuit-auth/tests/rights.rs @@ -12,17 +12,17 @@ fn main() { let root = KeyPair::new_with_rng(builder::Algorithm::Ed25519, &mut rng); let biscuit1 = Biscuit::builder() - .add_fact(fact( + .fact(fact( "right", &[string("authority"), string("file1"), string("read")], )) .unwrap() - .add_fact(fact( + .fact(fact( "right", &[string("authority"), string("file2"), string("read")], )) .unwrap() - .add_fact(fact( + .fact(fact( "right", &[string("authority"), string("file1"), string("write")], )) @@ -32,8 +32,8 @@ fn main() { println!("{}", biscuit1); let mut v = AuthorizerBuilder::new() - .add_token(&biscuit1) - .add_check(rule( + .token(&biscuit1) + .check(rule( "right", &[string("right")], &[pred( diff --git a/biscuit-capi/src/lib.rs b/biscuit-capi/src/lib.rs index 19c3f5ff..010fb360 100644 --- a/biscuit-capi/src/lib.rs +++ b/biscuit-capi/src/lib.rs @@ -426,33 +426,33 @@ pub unsafe extern "C" fn public_key_free(_kp: Option>) {} impl BiscuitBuilder { fn set_context(&mut self, context: &str) { let mut inner = self.0.take().unwrap(); - inner = inner.set_context(context.to_string()); + inner = inner.context(context.to_string()); self.0 = Some(inner); } fn set_root_key_id(&mut self, root_key_id: u32) { let mut inner = self.0.take().unwrap(); - inner = inner.set_root_key_id(root_key_id); + inner = inner.root_key_id(root_key_id); self.0 = Some(inner); } fn add_fact(&mut self, fact: &str) -> Result<(), biscuit_auth::error::Token> { let mut inner = self.0.take().unwrap(); - inner = inner.add_fact(fact)?; + inner = inner.fact(fact)?; self.0 = Some(inner); Ok(()) } fn add_rule(&mut self, rule: &str) -> Result<(), biscuit_auth::error::Token> { let mut inner = self.0.take().unwrap(); - inner = inner.add_rule(rule)?; + inner = inner.rule(rule)?; self.0 = Some(inner); Ok(()) } fn add_check(&mut self, check: &str) -> Result<(), biscuit_auth::error::Token> { let mut inner = self.0.take().unwrap(); - inner = inner.add_check(check)?; + inner = inner.check(check)?; self.0 = Some(inner); Ok(()) } @@ -802,27 +802,27 @@ pub unsafe extern "C" fn biscuit_block_context( impl BlockBuilder { fn set_context(&mut self, context: &str) { let mut inner = self.0.take().unwrap(); - inner = inner.set_context(context.to_string()); + inner = inner.context(context.to_string()); self.0 = Some(inner); } fn add_fact(&mut self, fact: &str) -> Result<(), biscuit_auth::error::Token> { let mut inner = self.0.take().unwrap(); - inner = inner.add_fact(fact)?; + inner = inner.fact(fact)?; self.0 = Some(inner); Ok(()) } fn add_rule(&mut self, rule: &str) -> Result<(), biscuit_auth::error::Token> { let mut inner = self.0.take().unwrap(); - inner = inner.add_rule(rule)?; + inner = inner.rule(rule)?; self.0 = Some(inner); Ok(()) } fn add_check(&mut self, check: &str) -> Result<(), biscuit_auth::error::Token> { let mut inner = self.0.take().unwrap(); - inner = inner.add_check(check)?; + inner = inner.check(check)?; self.0 = Some(inner); Ok(()) } @@ -992,28 +992,28 @@ pub unsafe extern "C" fn block_builder_free(_builder: Option>) impl<'a> AuthorizerBuilder<'a> { fn add_fact(&mut self, fact: &str) -> Result<(), biscuit_auth::error::Token> { let mut inner = self.0.take().unwrap(); - inner = inner.add_fact(fact)?; + inner = inner.fact(fact)?; self.0 = Some(inner); Ok(()) } fn add_rule(&mut self, rule: &str) -> Result<(), biscuit_auth::error::Token> { let mut inner = self.0.take().unwrap(); - inner = inner.add_rule(rule)?; + inner = inner.rule(rule)?; self.0 = Some(inner); Ok(()) } fn add_check(&mut self, check: &str) -> Result<(), biscuit_auth::error::Token> { let mut inner = self.0.take().unwrap(); - inner = inner.add_check(check)?; + inner = inner.check(check)?; self.0 = Some(inner); Ok(()) } fn add_policy(&mut self, policy: &str) -> Result<(), biscuit_auth::error::Token> { let mut inner = self.0.take().unwrap(); - inner = inner.add_policy(policy)?; + inner = inner.policy(policy)?; self.0 = Some(inner); Ok(()) } diff --git a/biscuit-quote/src/lib.rs b/biscuit-quote/src/lib.rs index 80867f71..5263b44d 100644 --- a/biscuit-quote/src/lib.rs +++ b/biscuit-quote/src/lib.rs @@ -349,7 +349,7 @@ impl Item { }, middle: TokenStream::new(), end: quote! { - __biscuit_auth_builder = __biscuit_auth_builder.add_fact(__biscuit_auth_item).unwrap(); + __biscuit_auth_builder = __biscuit_auth_builder.fact(__biscuit_auth_item).unwrap(); }, } } @@ -361,7 +361,7 @@ impl Item { }, middle: TokenStream::new(), end: quote! { - __biscuit_auth_builder = __biscuit_auth_builder.add_rule(__biscuit_auth_item).unwrap(); + __biscuit_auth_builder = __biscuit_auth_builder.rule(__biscuit_auth_item).unwrap(); }, } } @@ -374,7 +374,7 @@ impl Item { }, middle: TokenStream::new(), end: quote! { - __biscuit_auth_builder =__biscuit_auth_builder.add_check(__biscuit_auth_item).unwrap(); + __biscuit_auth_builder =__biscuit_auth_builder.check(__biscuit_auth_item).unwrap(); }, } } @@ -387,7 +387,7 @@ impl Item { }, middle: TokenStream::new(), end: quote! { - __biscuit_auth_builder = __biscuit_auth_builder.add_policy(__biscuit_auth_item).unwrap(); + __biscuit_auth_builder = __biscuit_auth_builder.policy(__biscuit_auth_item).unwrap(); }, } } From 48742856978efaac83ada362a41e6dd9c2c89acf Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Thu, 28 Nov 2024 11:46:05 +0100 Subject: [PATCH 22/28] remove warnings --- biscuit-auth/src/token/authorizer.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index f0843a73..278b6943 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -165,7 +165,7 @@ impl Authorizer { fn query_inner, E: Into>( &mut self, rule: datalog::Rule, - limits: AuthorizerLimits, + _limits: AuthorizerLimits, ) -> Result, error::Token> { let rule_trusted_origins = TrustedOrigins::from_scopes( &rule.scopes, @@ -259,7 +259,7 @@ impl Authorizer { fn query_all_inner, E: Into>( &mut self, rule: datalog::Rule, - limits: AuthorizerLimits, + _limits: AuthorizerLimits, ) -> Result, error::Token> { let rule_trusted_origins = if rule.scopes.is_empty() { self.token_origins.clone() @@ -336,10 +336,9 @@ impl Authorizer { result } - fn authorize_inner(&mut self, mut limits: AuthorizerLimits) -> Result { + fn authorize_inner(&mut self, limits: AuthorizerLimits) -> Result { let start = Instant::now(); let time_limit = start + limits.max_time; - let mut current_iterations = self.world.iterations; let mut errors = vec![]; let mut policy_result: Option> = None; From c1e647f0bca323cec3b983f31f3e297f230c202e Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Thu, 28 Nov 2024 12:02:27 +0100 Subject: [PATCH 23/28] support snapshots with AuthorizerBuilder --- biscuit-auth/src/token/authorizer/snapshot.rs | 6 +- biscuit-auth/src/token/builder/authorizer.rs | 168 +++++++++++++++++- 2 files changed, 169 insertions(+), 5 deletions(-) diff --git a/biscuit-auth/src/token/authorizer/snapshot.rs b/biscuit-auth/src/token/authorizer/snapshot.rs index 02274120..905da00d 100644 --- a/biscuit-auth/src/token/authorizer/snapshot.rs +++ b/biscuit-auth/src/token/authorizer/snapshot.rs @@ -231,7 +231,7 @@ impl super::Authorizer { } } -fn authorizer_origin_to_proto_origin(origin: &Origin) -> Vec { +pub(crate) fn authorizer_origin_to_proto_origin(origin: &Origin) -> Vec { origin .inner .iter() @@ -249,7 +249,9 @@ fn authorizer_origin_to_proto_origin(origin: &Origin) -> Vec { .collect() } -fn proto_origin_to_authorizer_origin(origins: &[schema::Origin]) -> Result { +pub(crate) fn proto_origin_to_authorizer_origin( + origins: &[schema::Origin], +) -> Result { let mut new_origin = Origin::default(); for origin in origins { diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs index abfc2a6a..aa8a4719 100644 --- a/biscuit-auth/src/token/builder/authorizer.rs +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -2,17 +2,25 @@ use std::{ collections::HashMap, convert::TryInto, fmt::Write, - time::{Instant, SystemTime}, + time::{Duration, Instant, SystemTime}, }; use biscuit_parser::parser::parse_source; +use prost::Message; use crate::{ builder::Convert, builder_ext::{AuthorizerExt, BuilderExt}, - datalog::{ExternFunc, Origin, SymbolTable, TrustedOrigins, World}, + datalog::{ExternFunc, Origin, RunLimits, SymbolTable, TrustedOrigins, World}, error, - token::{self, Block}, + format::{ + convert::{ + proto_snapshot_block_to_token_block, token_block_to_proto_snapshot_block, + v2::{policy_to_proto_policy, proto_policy_to_policy}, + }, + schema, + }, + token::{self, default_symbol_table, Block, MAX_SCHEMA_VERSION, MIN_SCHEMA_VERSION}, Authorizer, AuthorizerLimits, Biscuit, PublicKey, }; @@ -491,3 +499,157 @@ impl<'a> AuthorizerExt for AuthorizerBuilder<'a> { self.policy("deny if true").unwrap() } } + +impl<'a> AuthorizerBuilder<'a> { + pub fn from_snapshot(input: schema::AuthorizerSnapshot) -> Result { + let schema::AuthorizerSnapshot { + limits, + execution_time, + world, + } = input; + + let limits = RunLimits { + max_facts: limits.max_facts, + max_iterations: limits.max_iterations, + max_time: Duration::from_nanos(limits.max_time), + }; + + let version = world.version.unwrap_or(0); + if !(MIN_SCHEMA_VERSION..=MAX_SCHEMA_VERSION).contains(&version) { + return Err(error::Format::Version { + minimum: crate::token::MIN_SCHEMA_VERSION, + maximum: crate::token::MAX_SCHEMA_VERSION, + actual: version, + } + .into()); + } + + if !world.blocks.is_empty() { + return Err(error::Format::DeserializationError( + "cannot deserialize an AuthorizerBuilder fro a snapshot with blocks".to_string(), + ) + .into()); + } + + if !world.generated_facts.is_empty() { + return Err(error::Format::DeserializationError( + "cannot deserialize an AuthorizerBuilder from a snapshot with generated facts" + .to_string(), + ) + .into()); + } + + if world.iterations != 0 { + return Err(error::Format::DeserializationError( + "cannot deserialize an AuthorizerBuilder from a snapshot with non-zero iterations" + .to_string(), + ) + .into()); + } + + if execution_time != 0 { + return Err(error::Format::DeserializationError( + "cannot deserialize an AuthorizerBuilder from a snapshot with non-zero execution time".to_string(), + ) + .into()); + } + + let mut symbols = default_symbol_table(); + for symbol in world.symbols { + symbols.insert(&symbol); + } + for public_key in world.public_keys { + symbols + .public_keys + .insert(&PublicKey::from_proto(&public_key)?); + } + + let authorizer_block = proto_snapshot_block_to_token_block(&world.authorizer_block)?; + + let authorizer_block_builder = BlockBuilder::convert_from(&authorizer_block, &symbols)?; + let policies = world + .authorizer_policies + .iter() + .map(|policy| proto_policy_to_policy(policy, &symbols, version)) + .collect::, error::Format>>()?; + + let mut authorizer: AuthorizerBuilder<'_> = AuthorizerBuilder::new(); + authorizer.authorizer_block_builder = authorizer_block_builder; + authorizer.policies = policies; + authorizer.limits = limits; + + Ok(authorizer) + } + + pub fn from_raw_snapshot(input: &[u8]) -> Result { + let snapshot = schema::AuthorizerSnapshot::decode(input).map_err(|e| { + error::Format::DeserializationError(format!("deserialization error: {:?}", e)) + })?; + Self::from_snapshot(snapshot) + } + + pub fn from_base64_snapshot(input: &str) -> Result { + let bytes = base64::decode_config(input, base64::URL_SAFE)?; + Self::from_raw_snapshot(&bytes) + } + + pub fn snapshot(&self) -> Result { + let mut symbols = default_symbol_table(); + + let authorizer_policies = self + .policies + .iter() + .map(|policy| policy_to_proto_policy(policy, &mut symbols)) + .collect(); + + let authorizer_block = self.authorizer_block_builder.clone().build(symbols.clone()); + symbols.extend(&authorizer_block.symbols)?; + symbols.public_keys.extend(&authorizer_block.public_keys)?; + + let authorizer_block = token_block_to_proto_snapshot_block(&authorizer_block); + + let blocks = vec![]; + + let generated_facts = vec![]; + + let world = schema::AuthorizerWorld { + version: Some(MAX_SCHEMA_VERSION), + symbols: symbols.strings(), + public_keys: symbols + .public_keys + .into_inner() + .into_iter() + .map(|key| key.to_proto()) + .collect(), + blocks, + authorizer_block, + authorizer_policies, + generated_facts, + iterations: 0, + }; + + Ok(schema::AuthorizerSnapshot { + world, + execution_time: 0u64, + limits: schema::RunLimits { + max_facts: self.limits.max_facts, + max_iterations: self.limits.max_iterations, + max_time: self.limits.max_time.as_nanos() as u64, + }, + }) + } + + pub fn to_raw_snapshot(&self) -> Result, error::Format> { + let snapshot = self.snapshot()?; + let mut bytes = Vec::new(); + snapshot.encode(&mut bytes).map_err(|e| { + error::Format::SerializationError(format!("serialization error: {:?}", e)) + })?; + Ok(bytes) + } + + pub fn to_base64_snapshot(&self) -> Result { + let snapshot_bytes = self.to_raw_snapshot()?; + Ok(base64::encode_config(snapshot_bytes, base64::URL_SAFE)) + } +} From e6d70b257020413886c7729dd7147ff363e91ae0 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Thu, 28 Nov 2024 14:37:30 +0100 Subject: [PATCH 24/28] add the token as argument to build() --- biscuit-auth/benches/token.rs | 33 +++++-------- biscuit-auth/examples/testcases.rs | 2 +- biscuit-auth/examples/third_party.rs | 6 +-- biscuit-auth/examples/verifying_printer.rs | 6 +-- biscuit-auth/src/token/authorizer.rs | 14 +++--- biscuit-auth/src/token/builder/authorizer.rs | 34 +++++++------ biscuit-auth/src/token/mod.rs | 50 +++++++------------- biscuit-auth/tests/macros.rs | 7 ++- biscuit-auth/tests/rights.rs | 3 +- biscuit-capi/src/lib.rs | 37 +++++++++++++-- biscuit-capi/tests/capi.rs | 12 +++-- 11 files changed, 104 insertions(+), 100 deletions(-) diff --git a/biscuit-auth/benches/token.rs b/biscuit-auth/benches/token.rs index 3d12bebb..a4ca33fe 100644 --- a/biscuit-auth/benches/token.rs +++ b/biscuit-auth/benches/token.rs @@ -263,13 +263,12 @@ fn verify_block_2(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .token(&token) .fact("resource(\"file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .allow_all() - .build() + .build(&token) .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { @@ -281,13 +280,12 @@ fn verify_block_2(b: &mut Bencher) { b.iter(|| { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .token(&token) .fact("resource(\"file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .allow_all() - .build() + .build(&token) .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { @@ -352,13 +350,12 @@ fn verify_block_5(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .token(&token) .fact("resource(\"file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .allow_all() - .build() + .build(&token) .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { @@ -371,13 +368,12 @@ fn verify_block_5(b: &mut Bencher) { b.iter(|| { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .token(&token) .fact("resource(\"file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .allow_all() - .build() + .build(&token) .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { @@ -415,13 +411,12 @@ fn check_signature_2(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .token(&token) .fact("resource(\"file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .allow_all() - .build() + .build(&token) .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { @@ -489,13 +484,12 @@ fn check_signature_5(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .token(&token) .fact("resource(\"file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .allow_all() - .build() + .build(&token) .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { @@ -537,13 +531,12 @@ fn checks_block_2(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .token(&token) .fact("resource(\"file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .allow_all() - .build() + .build(&token) .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { @@ -556,13 +549,12 @@ fn checks_block_2(b: &mut Bencher) { b.bytes = data.len() as u64; b.iter(|| { let mut verifier = AuthorizerBuilder::new() - .token(&token) .fact("resource(\"file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .allow_all() - .build() + .build(&token) .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { @@ -600,13 +592,12 @@ fn checks_block_create_verifier2(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .token(&token) .fact("resource(\"file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .allow_all() - .build() + .build(&token) .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { @@ -649,13 +640,12 @@ fn checks_block_verify_only2(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); let mut verifier = AuthorizerBuilder::new() - .token(&token) .fact("resource(\"file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .allow_all() - .build() + .build(&token) .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { @@ -667,13 +657,12 @@ fn checks_block_verify_only2(b: &mut Bencher) { let token = Biscuit::from(&data, &root.public()).unwrap(); b.iter(|| { let mut verifier = AuthorizerBuilder::new() - .token(&token) .fact("resource(\"file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .allow_all() - .build() + .build(&token) .unwrap(); verifier .authorize_with_limits(AuthorizerLimits { diff --git a/biscuit-auth/examples/testcases.rs b/biscuit-auth/examples/testcases.rs index f107d007..482dbb2a 100644 --- a/biscuit-auth/examples/testcases.rs +++ b/biscuit-auth/examples/testcases.rs @@ -349,7 +349,7 @@ fn validate_token_with_limits_and_external_functions( .unwrap(); let authorizer_code = builder.dump_code(); - let mut authorizer = match builder.token(&token).build() { + let mut authorizer = match builder.build(&token) { Ok(v) => v, Err(e) => { return Validation { diff --git a/biscuit-auth/examples/third_party.rs b/biscuit-auth/examples/third_party.rs index 5f135e2e..f7fe6b72 100644 --- a/biscuit-auth/examples/third_party.rs +++ b/biscuit-auth/examples/third_party.rs @@ -35,18 +35,16 @@ fn main() { println!("biscuit2: {}", biscuit2); let mut authorizer = AuthorizerBuilder::new() - .token(&biscuit1) .allow_all() - .build() + .build(&biscuit1) .unwrap(); println!("authorize biscuit1:\n{:?}", authorizer.authorize()); println!("world:\n{}", authorizer.print_world()); let mut authorizer = AuthorizerBuilder::new() - .token(&biscuit2) .allow_all() - .build() + .build(&biscuit2) .unwrap(); println!("authorize biscuit2:\n{:?}", authorizer.authorize()); diff --git a/biscuit-auth/examples/verifying_printer.rs b/biscuit-auth/examples/verifying_printer.rs index 177b560a..033d0a8a 100644 --- a/biscuit-auth/examples/verifying_printer.rs +++ b/biscuit-auth/examples/verifying_printer.rs @@ -25,11 +25,7 @@ fn main() { } println!("token:\n{}", token); - let mut authorizer = AuthorizerBuilder::new() - .token(&token) - .allow_all() - .build() - .unwrap(); + let mut authorizer = AuthorizerBuilder::new().allow_all().build(&token).unwrap(); println!("authorizer result: {:?}", authorizer.authorize()); println!("authorizer world:\n{}", authorizer.print_world()); diff --git a/biscuit-auth/src/token/authorizer.rs b/biscuit-auth/src/token/authorizer.rs index 278b6943..077cfafd 100644 --- a/biscuit-auth/src/token/authorizer.rs +++ b/biscuit-auth/src/token/authorizer.rs @@ -36,7 +36,7 @@ pub struct Authorizer { impl Authorizer { pub(crate) fn from_token(token: &Biscuit) -> Result { - AuthorizerBuilder::new().token(token).build() + AuthorizerBuilder::new().build(token) } /// creates a new empty authorizer @@ -872,7 +872,7 @@ mod tests { let mut authorizer = AuthorizerBuilder::new() .policy("allow if true") .unwrap() - .build() + .build_unauthenticated() .unwrap(); assert_eq!( authorizer.authorize_with_limits(AuthorizerLimits { @@ -911,7 +911,7 @@ mod tests { scope_params, ) .unwrap() - .build() + .build_unauthenticated() .unwrap(); } @@ -1092,12 +1092,11 @@ mod tests { scope_params, ) .unwrap() - .token(&biscuit2) .limits(AuthorizerLimits { max_time: Duration::from_millis(10), //Set 10 milliseconds as the maximum time allowed for the authorization due to "cheap" worker on GitHub Actions ..Default::default() }) - .build() + .build(&biscuit2) .unwrap(); println!("token:\n{}", biscuit2); @@ -1229,7 +1228,6 @@ mod tests { .unwrap(); let mut authorizer = AuthorizerBuilder::new() - .token(&token) .code( r#" authorizer_fact(true); @@ -1239,7 +1237,7 @@ mod tests { "#, ) .unwrap() - .build() + .build(&token) .unwrap(); let output_before_authorization = authorizer.to_string(); @@ -1345,7 +1343,7 @@ allow if true; &[builder::pred("pred", &[builder::var("any")])], )) .unwrap() - .build() + .build_unauthenticated() .unwrap(); let res: Vec<(String,)> = authorizer .query(builder::rule( diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs index aa8a4719..3968907e 100644 --- a/biscuit-auth/src/token/builder/authorizer.rs +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -27,16 +27,15 @@ use crate::{ use super::{date, fact, BlockBuilder, Check, Fact, Policy, Rule, Scope, Term}; #[derive(Clone, Debug, Default)] -pub struct AuthorizerBuilder<'a> { +pub struct AuthorizerBuilder { authorizer_block_builder: BlockBuilder, policies: Vec, extern_funcs: HashMap, limits: AuthorizerLimits, - token: Option<&'a Biscuit>, } -impl<'a> AuthorizerBuilder<'a> { - pub fn new() -> AuthorizerBuilder<'a> { +impl AuthorizerBuilder { + pub fn new() -> AuthorizerBuilder { AuthorizerBuilder::default() } @@ -261,11 +260,6 @@ impl<'a> AuthorizerBuilder<'a> { self } - pub fn token(mut self, token: &'a Biscuit) -> Self { - self.token = Some(token); - self - } - pub fn dump_code(&self) -> String { let mut f = String::new(); for fact in &self.authorizer_block_builder.facts { @@ -295,7 +289,17 @@ impl<'a> AuthorizerBuilder<'a> { f } - pub fn build(self) -> Result { + /// builds the authorizer from a token + pub fn build(self, token: &Biscuit) -> Result { + self.build_inner(Some(token)) + } + + /// builds the authorizer without a token + pub fn build_unauthenticated(self) -> Result { + self.build_inner(None) + } + + fn build_inner(self, token: Option<&Biscuit>) -> Result { let mut world = World::new(); world.extern_funcs = self.extern_funcs; @@ -305,7 +309,7 @@ impl<'a> AuthorizerBuilder<'a> { let mut blocks: Option> = None; // load the token if present - if let Some(token) = self.token { + if let Some(token) = token { for (i, block) in token.container.blocks.iter().enumerate() { if let Some(sig) = block.external_signature.as_ref() { let new_key_id = symbols.public_keys.insert(&sig.public_key); @@ -458,7 +462,7 @@ pub(crate) fn load_and_translate_block( Ok(()) } -impl<'a> BuilderExt for AuthorizerBuilder<'a> { +impl BuilderExt for AuthorizerBuilder { fn resource(mut self, name: &str) -> Self { self.authorizer_block_builder = self.authorizer_block_builder.resource(name); self @@ -491,7 +495,7 @@ impl<'a> BuilderExt for AuthorizerBuilder<'a> { } } -impl<'a> AuthorizerExt for AuthorizerBuilder<'a> { +impl AuthorizerExt for AuthorizerBuilder { fn allow_all(self) -> Self { self.policy("allow if true").unwrap() } @@ -500,7 +504,7 @@ impl<'a> AuthorizerExt for AuthorizerBuilder<'a> { } } -impl<'a> AuthorizerBuilder<'a> { +impl AuthorizerBuilder { pub fn from_snapshot(input: schema::AuthorizerSnapshot) -> Result { let schema::AuthorizerSnapshot { limits, @@ -573,7 +577,7 @@ impl<'a> AuthorizerBuilder<'a> { .map(|policy| proto_policy_to_policy(policy, &symbols, version)) .collect::, error::Format>>()?; - let mut authorizer: AuthorizerBuilder<'_> = AuthorizerBuilder::new(); + let mut authorizer = AuthorizerBuilder::new(); authorizer.authorizer_block_builder = authorizer_block_builder; authorizer.policies = policies; authorizer.limits = limits; diff --git a/biscuit-auth/src/token/mod.rs b/biscuit-auth/src/token/mod.rs index 7a042b86..6a963200 100644 --- a/biscuit-auth/src/token/mod.rs +++ b/biscuit-auth/src/token/mod.rs @@ -847,7 +847,7 @@ mod tests { let final_token = Biscuit::from(&serialized3, root.public()).unwrap(); println!("final token:\n{}", final_token); { - let mut builder = AuthorizerBuilder::new().token(&final_token); + let mut builder = AuthorizerBuilder::new(); let mut facts = vec![ fact("resource", &[string("file1")]), @@ -860,7 +860,7 @@ mod tests { //println!("final token: {:#?}", final_token); - let mut authorizer = builder.allow_all().build().unwrap(); + let mut authorizer = builder.allow_all().build(&final_token).unwrap(); let res = authorizer.authorize(); println!("res1: {:?}", res); @@ -868,7 +868,7 @@ mod tests { } { - let mut builder = AuthorizerBuilder::new().token(&final_token); + let mut builder = AuthorizerBuilder::new(); let mut facts = vec![ fact("resource", &[string("file2")]), @@ -880,7 +880,7 @@ mod tests { } builder = builder.allow_all(); - let mut authorizer = builder.build().unwrap(); + let mut authorizer = builder.build(&final_token).unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { max_time: Duration::from_secs(10), @@ -924,13 +924,12 @@ mod tests { { let mut authorizer = AuthorizerBuilder::new() - .token(&biscuit2) .fact("resource(\"/folder1/file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .allow_all() - .build() + .build(&biscuit2) .unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { @@ -944,13 +943,12 @@ mod tests { { let mut authorizer = AuthorizerBuilder::new() - .token(&biscuit2) .fact("resource(\"/folder2/file3\")") .unwrap() .fact("operation(\"read\")") .unwrap() .allow_all() - .build() + .build(&biscuit2) .unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { @@ -975,12 +973,11 @@ mod tests { { let mut authorizer = AuthorizerBuilder::new() - .token(&biscuit2) .fact("resource(\"/folder2/file1\")") .unwrap() .fact("operation(\"write\")") .unwrap() - .build() + .build(&biscuit2) .unwrap(); let res = authorizer.authorize(); @@ -1017,14 +1014,13 @@ mod tests { { let mut authorizer = AuthorizerBuilder::new() - .token(&biscuit2) .fact("resource(\"file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .time() .allow_all() - .build() + .build(&biscuit2) .unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { @@ -1038,14 +1034,13 @@ mod tests { { println!("biscuit2: {}", biscuit2); let mut authorizer = AuthorizerBuilder::new() - .token(&biscuit2) .fact("resource(\"file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .time() .allow_all() - .build() + .build(&biscuit2) .unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { @@ -1087,13 +1082,12 @@ mod tests { //panic!(); { let mut authorizer = AuthorizerBuilder::new() - .token(&biscuit2) .fact("resource(\"/folder1/file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .allow_all() - .build() + .build(&biscuit2) .unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { @@ -1114,13 +1108,12 @@ mod tests { { let mut authorizer = AuthorizerBuilder::new() - .token(&biscuit3) .fact("resource(\"/folder1/file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .allow_all() - .build() + .build(&biscuit3) .unwrap(); let res = authorizer.authorize(); @@ -1148,14 +1141,13 @@ mod tests { println!("{}", biscuit1); let mut authorizer = AuthorizerBuilder::new() - .token(&biscuit1) .check(rule( "right", &[string("right")], &[pred("right", &[string("file2"), string("write")])], )) .unwrap() - .build() + .build(&biscuit1) .unwrap(); //assert!(v.verify().is_err()); @@ -1209,13 +1201,12 @@ mod tests { println!("biscuit3: {}", biscuit3); let mut authorizer = AuthorizerBuilder::new() - .token(&biscuit3) .fact("resource(\"file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .time() - .build() + .build(&biscuit3) .unwrap(); // test that cloning correctly embeds the first block's facts @@ -1295,13 +1286,12 @@ mod tests { //println!("generated biscuit token 2: {} bytes\n{}", serialized2.len(), serialized2.to_hex(16)); { let mut authorizer = AuthorizerBuilder::new() - .token(&biscuit2) .fact("resource(\"file1\")") .unwrap() .fact("operation(\"read\")") .unwrap() .time() - .build() + .build(&biscuit2) .unwrap(); println!("world:\n{}", authorizer.print_world()); @@ -1391,11 +1381,10 @@ mod tests { let biscuit2 = biscuit1.append_with_keypair(&keypair2, block2).unwrap(); let mut authorizer = AuthorizerBuilder::new() - .token(&biscuit2) .check("check if bytes($0), { hex:00000000, hex:0102AB }.contains($0)") .unwrap() .allow_all() - .build() + .build(&biscuit2) .unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { @@ -1480,7 +1469,6 @@ mod tests { println!("final token:\n{}", final_token); let mut authorizer = AuthorizerBuilder::new() - .token(&final_token) .fact("resource(\"/folder2/file1\")") .unwrap() .fact("operation(\"write\")") @@ -1488,7 +1476,7 @@ mod tests { .policy("allow if resource($file), operation($op), right($file, $op)") .unwrap() .deny_all() - .build() + .build(&final_token) .unwrap(); let res = authorizer.authorize_with_limits(crate::token::authorizer::AuthorizerLimits { @@ -1524,14 +1512,13 @@ mod tests { { let mut authorizer = AuthorizerBuilder::new() - .token(&biscuit1) .fact("fact(0)") .unwrap() .fact("fact(1)") .unwrap() //println!("final token: {:#?}", final_token); .allow_all() - .build() + .build(&biscuit1) .unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { @@ -1544,14 +1531,13 @@ mod tests { { let mut authorizer = AuthorizerBuilder::new() - .token(&biscuit2) .fact("fact(0)") .unwrap() .fact("fact(1)") .unwrap() //println!("final token: {:#?}", final_token); .allow_all() - .build() + .build(&biscuit2) .unwrap(); let res = authorizer.authorize_with_limits(AuthorizerLimits { diff --git a/biscuit-auth/tests/macros.rs b/biscuit-auth/tests/macros.rs index 3bf92906..1696724f 100644 --- a/biscuit-auth/tests/macros.rs +++ b/biscuit-auth/tests/macros.rs @@ -75,7 +75,7 @@ fn authorizer_macro() { "# ); - let authorizer = b.build().unwrap(); + let authorizer = b.build_unauthenticated().unwrap(); assert_eq!( authorizer.dump_code(), r#"appended(true); @@ -95,7 +95,7 @@ allow if true; #[test] fn authorizer_macro_trailing_comma() { let a = authorizer!(r#"fact("test", {my_key});"#, my_key = "my_value",) - .build() + .build_unauthenticated() .unwrap(); assert_eq!( a.dump_code(), @@ -261,8 +261,7 @@ fn json() { $value.get("id") == $id, $value.get("roles").contains("admin");"# ) - .token(&biscuit) - .build() + .build(&biscuit) .unwrap(); assert_eq!( authorizer diff --git a/biscuit-auth/tests/rights.rs b/biscuit-auth/tests/rights.rs index 84006470..a470ee64 100644 --- a/biscuit-auth/tests/rights.rs +++ b/biscuit-auth/tests/rights.rs @@ -32,7 +32,6 @@ fn main() { println!("{}", biscuit1); let mut v = AuthorizerBuilder::new() - .token(&biscuit1) .check(rule( "right", &[string("right")], @@ -42,7 +41,7 @@ fn main() { )], )) .unwrap() - .build() + .build(&biscuit1) .unwrap(); //v.add_resource("file2"); //v.add_operation("read"); diff --git a/biscuit-capi/src/lib.rs b/biscuit-capi/src/lib.rs index 010fb360..2900c26c 100644 --- a/biscuit-capi/src/lib.rs +++ b/biscuit-capi/src/lib.rs @@ -295,7 +295,7 @@ pub struct PublicKey(biscuit_auth::PublicKey); pub struct BiscuitBuilder(Option); pub struct BlockBuilder(Option); pub struct Authorizer(biscuit_auth::Authorizer); -pub struct AuthorizerBuilder<'a>(Option>); +pub struct AuthorizerBuilder(Option); #[repr(C)] pub enum SignatureAlgorithm { @@ -989,7 +989,7 @@ pub unsafe extern "C" fn block_builder_add_check( #[no_mangle] pub unsafe extern "C" fn block_builder_free(_builder: Option>) {} -impl<'a> AuthorizerBuilder<'a> { +impl AuthorizerBuilder { fn add_fact(&mut self, fact: &str) -> Result<(), biscuit_auth::error::Token> { let mut inner = self.0.take().unwrap(); inner = inner.fact(fact)?; @@ -1018,6 +1018,14 @@ impl<'a> AuthorizerBuilder<'a> { Ok(()) } } + +#[no_mangle] +pub unsafe extern "C" fn authorizer_builder() -> Option> { + Some(Box::new(AuthorizerBuilder(Some( + biscuit_auth::builder::AuthorizerBuilder::new(), + )))) +} + #[no_mangle] pub unsafe extern "C" fn authorizer_builder_add_fact( builder: Option<&mut AuthorizerBuilder>, @@ -1128,6 +1136,29 @@ pub unsafe extern "C" fn authorizer_builder_add_policy( #[no_mangle] pub unsafe extern "C" fn authorizer_builder_build( builder: Option>, + token: &Biscuit, +) -> Option> { + if builder.is_none() { + update_last_error(Error::InvalidArgument); + } + let builder = builder.unwrap(); + builder + .0 + .clone() + .take() + .unwrap() + .build(&token.0) + .map(Authorizer) + .map(Box::new) + .ok() +} + +/// Build an authorizer without a token +/// +/// The builder will be freed automatically when the authorizer is returned +#[no_mangle] +pub unsafe extern "C" fn authorizer_builder_build_unauthenticated( + builder: Option>, ) -> Option> { if builder.is_none() { update_last_error(Error::InvalidArgument); @@ -1138,7 +1169,7 @@ pub unsafe extern "C" fn authorizer_builder_build( .clone() .take() .unwrap() - .build() + .build_unauthenticated() .map(Authorizer) .map(Box::new) .ok() diff --git a/biscuit-capi/tests/capi.rs b/biscuit-capi/tests/capi.rs index a168f2e6..44a498ee 100644 --- a/biscuit-capi/tests/capi.rs +++ b/biscuit-capi/tests/capi.rs @@ -39,14 +39,18 @@ mod capi { Biscuit* b2 = biscuit_append_block(biscuit, bb, kp2); printf("biscuit append error? %s\n", error_message()); - Authorizer * authorizer = biscuit_authorizer(b2); - printf("authorizer creation error? %s\n", error_message()); - authorizer_add_check(authorizer, "check if right(\"efgh\")"); + AuthorizerBuilder * ab = authorizer_builder(); + printf("authorizer builder creation error? %s\n", error_message()); + + authorizer_builder_add_check(authorizer, "check if right(\"efgh\")"); printf("authorizer add check error? %s\n", error_message()); - authorizer_add_policy(authorizer, "allow if true"); + authorizer_builder_add_policy(authorizer, "allow if true"); printf("authorizer add policy error? %s\n", error_message()); + Authorizer * authorizer = authorizer_builder_build(b2); + printf("authorizer creation error? %s\n", error_message()); + if(!authorizer_authorize(authorizer)) { printf("authorizer error(code = %d): %s\n", error_kind(), error_message()); From bfaacb72b9ecf0ef6e2f1e9675a3920289f91cac Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Thu, 28 Nov 2024 16:27:56 +0100 Subject: [PATCH 25/28] fix doctests --- biscuit-auth/src/lib.rs | 9 +++------ biscuit-auth/src/macros.rs | 3 +-- biscuit-auth/src/token/builder/authorizer.rs | 2 +- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/biscuit-auth/src/lib.rs b/biscuit-auth/src/lib.rs index e1d3b4bb..e10c4703 100644 --- a/biscuit-auth/src/lib.rs +++ b/biscuit-auth/src/lib.rs @@ -102,24 +102,21 @@ //! // matches, a default deny applies //! deny if true; //! "#) -//! .token(&biscuit2) -//! .build()?; +//! .build(&biscuit2)?; //! //! let mut v2 = authorizer!(r#" //! resource("/a/file1.txt"); //! operation("write"); //! allow if right("/a/file1.txt", "write"); //! "#) -//! .token(&biscuit2) -//! .build()?; +//! .build(&biscuit2)?; //! //! let mut v3 = authorizer!(r#" //! resource("/a/file2.txt"); //! operation("read"); //! allow if right("/a/file2.txt", "read"); //! "#) -//! .token(&biscuit2) -//! .build()?; +//! .build(&biscuit2)?; //! //! // the token restricts to read operations: //! assert!(v1.authorize().is_ok()); diff --git a/biscuit-auth/src/macros.rs b/biscuit-auth/src/macros.rs index 9a24da99..b57ecc71 100644 --- a/biscuit-auth/src/macros.rs +++ b/biscuit-auth/src/macros.rs @@ -43,8 +43,7 @@ //! resource = "file1", //! user_id = "1234", //! ) -//! .token(&new_biscuit) -//! .build() +//! .build(&new_biscuit) //! .expect("failed to build the authorizer") //! .authorize() //! .expect("Failed to authorize biscuit"); diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs index 3968907e..dea63c11 100644 --- a/biscuit-auth/src/token/builder/authorizer.rs +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -80,7 +80,7 @@ impl AuthorizerBuilder { /// allow if true; /// "#) /// .expect("should parse correctly") - /// .build(); + /// .build_unauthenticated(); /// ``` pub fn code>(self, source: T) -> Result { self.code_with_params(source, HashMap::new(), HashMap::new()) From af8bb11b5fe95a6ee32934fc6b5ba97db266176a Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Thu, 28 Nov 2024 16:32:35 +0100 Subject: [PATCH 26/28] fix capi tests --- biscuit-capi/tests/capi.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/biscuit-capi/tests/capi.rs b/biscuit-capi/tests/capi.rs index 44a498ee..ec1a387e 100644 --- a/biscuit-capi/tests/capi.rs +++ b/biscuit-capi/tests/capi.rs @@ -42,13 +42,13 @@ mod capi { AuthorizerBuilder * ab = authorizer_builder(); printf("authorizer builder creation error? %s\n", error_message()); - authorizer_builder_add_check(authorizer, "check if right(\"efgh\")"); - printf("authorizer add check error? %s\n", error_message()); + authorizer_builder_add_check(ab, "check if right(\"efgh\")"); + printf("authorizer builder add check error? %s\n", error_message()); - authorizer_builder_add_policy(authorizer, "allow if true"); - printf("authorizer add policy error? %s\n", error_message()); + authorizer_builder_add_policy(ab, "allow if true"); + printf("authorizer builder add policy error? %s\n", error_message()); - Authorizer * authorizer = authorizer_builder_build(b2); + Authorizer * authorizer = authorizer_builder_build(ab, b2); printf("authorizer creation error? %s\n", error_message()); if(!authorizer_authorize(authorizer)) { @@ -115,9 +115,10 @@ builder add authority error? (null) biscuit creation error? (null) builder add check error? (null) biscuit append error? (null) +authorizer builder creation error? (null) +authorizer builder add check error? (null) +authorizer builder add policy error? (null) authorizer creation error? (null) -authorizer add check error? (null) -authorizer add policy error? (null) authorizer error(code = 21): authorization failed: an allow policy matched (policy index: 0), and the following checks failed: Check n°0 in authorizer: check if right("efgh"), Check n°0 in block n°1: check if operation("read") failed checks (2): Authorizer check 0: check if right("efgh") From 7b6b3e789b9786e9e7099488c68dac55eb29880d Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Thu, 28 Nov 2024 16:35:49 +0100 Subject: [PATCH 27/28] fix lifetime issue --- biscuit-auth/src/datalog/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/biscuit-auth/src/datalog/mod.rs b/biscuit-auth/src/datalog/mod.rs index d1fba3d0..eac57d95 100644 --- a/biscuit-auth/src/datalog/mod.rs +++ b/biscuit-auth/src/datalog/mod.rs @@ -783,7 +783,7 @@ impl FactSet { pub fn iterator<'a>( &'a self, block_ids: &'a TrustedOrigins, - ) -> impl Iterator + Clone { + ) -> impl Iterator + Clone { self.inner .iter() .filter_map(move |(ids, facts)| { From aaaa9fdee7402c2644229e70b9aff7b256a13f89 Mon Sep 17 00:00:00 2001 From: Geoffroy Couprie Date: Thu, 28 Nov 2024 16:37:36 +0100 Subject: [PATCH 28/28] cleanup --- biscuit-auth/src/token/builder/authorizer.rs | 4 ++-- biscuit-auth/src/token/builder/term.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/biscuit-auth/src/token/builder/authorizer.rs b/biscuit-auth/src/token/builder/authorizer.rs index dea63c11..40dea490 100644 --- a/biscuit-auth/src/token/builder/authorizer.rs +++ b/biscuit-auth/src/token/builder/authorizer.rs @@ -430,7 +430,7 @@ pub(crate) fn load_and_translate_block( &block.scopes, &TrustedOrigins::default(), i, - &public_key_to_block_id, + public_key_to_block_id, ); for fact in block.facts.iter_mut() { @@ -448,7 +448,7 @@ pub(crate) fn load_and_translate_block( &rule.scopes, &block_trusted_origins, i, - &public_key_to_block_id, + public_key_to_block_id, ); world.rules.insert(i, &rule_trusted_origins, rule.clone()); diff --git a/biscuit-auth/src/token/builder/term.rs b/biscuit-auth/src/token/builder/term.rs index 56836199..e1e6e4e7 100644 --- a/biscuit-auth/src/token/builder/term.rs +++ b/biscuit-auth/src/token/builder/term.rs @@ -374,9 +374,9 @@ impl fmt::Display for Term { let terms = m .iter() .map(|(key, term)| match key { - MapKey::Integer(i) => format!("{i}: {}", term.to_string()), - MapKey::Str(s) => format!("\"{s}\": {}", term.to_string()), - MapKey::Parameter(s) => format!("{{{s}}}: {}", term.to_string()), + MapKey::Integer(i) => format!("{i}: {}", term), + MapKey::Str(s) => format!("\"{s}\": {}", term), + MapKey::Parameter(s) => format!("{{{s}}}: {}", term), }) .collect::>(); write!(f, "{{{}}}", terms.join(", "))