diff --git a/biscuit_test.py b/biscuit_test.py index 5181735..4c5302b 100644 --- a/biscuit_test.py +++ b/biscuit_test.py @@ -1,6 +1,6 @@ import json import os -from datetime import datetime, timezone +from datetime import datetime, timedelta, timezone import pytest @@ -205,6 +205,16 @@ def test_authorizer_builder(): allow if fact($var, true) trusting ed25519/acdd6d5b53bfee478bf689f8e012fe7988bf755e3d7c5152947abc149bc20189; """ + +def test_authorizer_limits(): + auth = Authorizer("") + limits = auth.limits() + limits.max_time = timedelta(microseconds=2000) + auth.set_limits(limits) + limits = auth.limits() + assert limits.max_time.microseconds == 2000 + + def test_key_selection(): private_key = PrivateKey.from_hex("473b5189232f3f597b5c2f3f9b0d5e28b1ee4e7cce67ec6b7fbf5984157a6b97") root = KeyPair.from_private_key(private_key) @@ -431,4 +441,4 @@ def test_keypair_from_private_key_pem(): private_key_pem = "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEIASZaU0NoF3KxABSZj5x1QwVOUZfiSbf6SAzz3qq1T1l\n-----END PRIVATE KEY-----" private_key_hex = "0499694d0da05dcac40052663e71d50c1539465f8926dfe92033cf7aaad53d65" kp = KeyPair.from_private_key_pem(pem=private_key_pem) - assert kp.private_key.to_hex() == private_key_hex \ No newline at end of file + assert kp.private_key.to_hex() == private_key_hex diff --git a/src/lib.rs b/src/lib.rs index b57df23..72effac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,12 +3,15 @@ use ::biscuit_auth::RootKeyProvider; use ::biscuit_auth::UnverifiedBiscuit; use chrono::DateTime; +use chrono::Duration; use chrono::TimeZone; use chrono::Utc; use std::collections::BTreeSet; use std::collections::HashMap; -use ::biscuit_auth::{builder, error, Authorizer, Biscuit, KeyPair, PrivateKey, PublicKey}; +use ::biscuit_auth::{ + builder, error, Authorizer, AuthorizerLimits, Biscuit, KeyPair, PrivateKey, PublicKey, +}; use pyo3::exceptions::PyValueError; use pyo3::prelude::*; @@ -341,6 +344,17 @@ impl PyBiscuit { #[pyclass(name = "Authorizer")] pub struct PyAuthorizer(Authorizer); +#[pyclass(name = "AuthorizerLimits")] +#[derive(Clone)] +pub struct PyAuthorizerLimits { + #[pyo3(get, set)] + pub max_facts: u64, + #[pyo3(get, set)] + pub max_iterations: u64, + #[pyo3(get, set)] + pub max_time: Duration, +} + #[pymethods] impl PyAuthorizer { /// Create a new authorizer from a datalog snippet and optional parameter values @@ -446,6 +460,29 @@ impl PyAuthorizer { .map_err(|e| DataLogError::new_err(e.to_string())) } + /// Returns the runtime limits of the authorizer + /// + /// Those limits cover all the executions under the `authorize`, `query` and `query_all` methods + pub fn limits(&self) -> PyAuthorizerLimits { + let limits = self.0.limits(); + PyAuthorizerLimits { + max_facts: limits.max_facts, + max_iterations: limits.max_iterations, + max_time: Duration::from_std(limits.max_time).expect("Duration out of range"), + } + } + + /// 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: &PyAuthorizerLimits) { + self.0.set_limits(AuthorizerLimits { + max_facts: limits.max_facts, + max_iterations: limits.max_iterations, + max_time: Duration::to_std(&limits.max_time).expect("Duration out of range"), + }) + } + /// Merge another `Authorizer` in this `Authorizer`. The `Authorizer` argument will not be modified /// /// :param builder: an Authorizer