Skip to content

Commit 84bf3dc

Browse files
committed
wip: demo structured data in exceptions
1 parent 309dd82 commit 84bf3dc

File tree

2 files changed

+64
-4
lines changed

2 files changed

+64
-4
lines changed

biscuit_test.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import pytest
66

7-
from biscuit_auth import Algorithm, KeyPair, Authorizer, AuthorizerBuilder, Biscuit, BiscuitBuilder, BlockBuilder, Check, Fact, KeyPair, Policy, PrivateKey, PublicKey, Rule, UnverifiedBiscuit
7+
from biscuit_auth import Algorithm, KeyPair, Authorizer, AuthorizerBuilder, Biscuit, BiscuitBuilder, BlockBuilder, Check, Fact, KeyPair, Policy, PrivateKey, PublicKey, Rule, UnverifiedBiscuit, AuthorizationError
88

99
def test_fact():
1010
fact = Fact('fact(1, true, "", "Test", hex:aabbcc, 2023-04-29T01:00:00Z)')
@@ -237,6 +237,16 @@ def choose_key(kid):
237237
except:
238238
pass
239239

240+
def test_authorizer_exception():
241+
authorizer = AuthorizerBuilder("check if true; reject if true; allow if false; deny if true;").build_unauthenticated()
242+
try:
243+
authorizer.authorize()
244+
assert false
245+
except AuthorizationError as e:
246+
(args,) = e.args
247+
assert args['policy_id'] == {'code': 'deny if true', 'policy_id': 1}
248+
assert args['checks'] == [{'authorizer_check': True, 'block_id': None, 'check_id': 1, 'code': 'reject if true'}]
249+
240250
def test_complete_lifecycle():
241251
private_key = PrivateKey("ed25519-private/473b5189232f3f597b5c2f3f9b0d5e28b1ee4e7cce67ec6b7fbf5984157a6b97")
242252
root = KeyPair.from_private_key(private_key)

src/lib.rs

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#![allow(clippy::useless_conversion)]
1010
use ::biscuit_auth::builder::MapKey;
1111
use ::biscuit_auth::datalog::ExternFunc;
12+
use ::biscuit_auth::error::MatchedPolicy;
1213
use ::biscuit_auth::AuthorizerBuilder;
1314
use ::biscuit_auth::RootKeyProvider;
1415
use ::biscuit_auth::UnverifiedBiscuit;
@@ -38,6 +39,27 @@ create_exception!(
3839
AuthorizationError,
3940
pyo3::exceptions::PyException
4041
);
42+
43+
#[derive(IntoPyObject)]
44+
struct AuthorizationErrorData {
45+
policy_id: Option<MatchedPolicyData>,
46+
checks: Vec<FailedCheckData>,
47+
}
48+
49+
#[derive(IntoPyObject)]
50+
struct MatchedPolicyData {
51+
policy_id: usize,
52+
code: String,
53+
}
54+
55+
#[derive(IntoPyObject)]
56+
struct FailedCheckData {
57+
authorizer_check: bool,
58+
block_id: Option<u32>,
59+
check_id: u32,
60+
code: String,
61+
}
62+
4163
create_exception!(
4264
biscuit_auth,
4365
BiscuitBuildError,
@@ -786,9 +808,37 @@ impl PyAuthorizer {
786808
/// :return: the index of the matched allow rule
787809
/// :rtype: int
788810
pub fn authorize(&mut self) -> PyResult<usize> {
789-
self.0
790-
.authorize()
791-
.map_err(|error| AuthorizationError::new_err(error.to_string()))
811+
self.0.authorize().map_err(|error| match error {
812+
error::Token::FailedLogic(error::Logic::Unauthorized {
813+
policy: MatchedPolicy::Deny(pid),
814+
checks,
815+
}) => AuthorizationError::new_err(AuthorizationErrorData {
816+
policy_id: Some(MatchedPolicyData {
817+
policy_id: pid,
818+
code: self.0.dump().3.get(pid).unwrap().to_string(),
819+
}),
820+
checks: checks
821+
.into_iter()
822+
.map(|c| match c {
823+
error::FailedCheck::Block(failed_block_check) => FailedCheckData {
824+
authorizer_check: false,
825+
block_id: Some(failed_block_check.block_id),
826+
check_id: failed_block_check.check_id,
827+
code: failed_block_check.rule,
828+
},
829+
error::FailedCheck::Authorizer(failed_authorizer_check) => {
830+
FailedCheckData {
831+
authorizer_check: true,
832+
block_id: None,
833+
check_id: failed_authorizer_check.check_id,
834+
code: failed_authorizer_check.rule,
835+
}
836+
}
837+
})
838+
.collect(),
839+
}),
840+
_ => AuthorizationError::new_err(error.to_string()),
841+
})
792842
}
793843

794844
/// Query the authorizer by returning all the `Fact`s generated by the provided `Rule`. The generated facts won't be

0 commit comments

Comments
 (0)