Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@ $ source .env/bin/activate
$ pip install -r requirements-dev.txt
```

With that, you should be able to run `maturin develop` to build and install the extension. You can then `import biscuit_auth` in a Python shell to play around, or run `pytest` to run the Python tests.
With that, you should be able to run `maturin develop` to build and install the extension. You can then `import biscuit_auth` in a Python shell to play around, or run `pytest` to run the Python tests.
11 changes: 11 additions & 0 deletions biscuit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,3 +463,14 @@ def test(left, right):
policy = authorizer.build_unauthenticated().authorize()
assert policy == 0

def test_append_third_party_block():
root_kp = KeyPair()
external_kp = KeyPair()

builder = BiscuitBuilder("user({user});", {'user': "123"})
biscuit = builder.build(root_kp.private_key)

third_party_block = BlockBuilder("external_fact({fact});", {'fact': "456"})
new_biscuit = biscuit.append_third_party_block(external_kp, third_party_block)

assert str(new_biscuit.block_external_key(1)) == str(external_kp.public_key)
52 changes: 52 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ impl From<PyAlgorithm> for builder::Algorithm {
}
}

impl BiscuitBuildError {
/// Helper function to build `BiscuitBuildError` from other errors.
pub fn from_err(error: impl ToString) -> PyErr {
Self::new_err(error.to_string())
}
}

struct PyKeyProvider {
py_value: PyObject,
}
Expand Down Expand Up @@ -397,6 +404,36 @@ impl PyBiscuit {
.map(PyBiscuit)
}

/// Create a new `Biscuit` by appending a third party attenuation block
///
/// :param kp: keypair used to sign the block
/// :type kp: KeyPair
/// :param block: a builder for the new block
/// :type block: BlockBuilder
/// :return: the attenuated biscuit
/// :rtype: Biscuit
pub fn append_third_party_block(
&self,
kp: &PyKeyPair,
block: &PyBlockBuilder,
) -> PyResult<PyBiscuit> {
let third_party_block = self
.0
.third_party_request()
.and_then(|req| {
req.create_block(
&kp.private_key().0,
block.0.clone().expect("builder already consumed"),
)
})
.map_err(BiscuitBuildError::from_err)?;

self.0
.append_third_party(kp.public_key().0, third_party_block)
.map_err(BiscuitBuildError::from_err)
.map(PyBiscuit)
}

/// The revocation ids of the token, encoded as hexadecimal strings
#[getter]
pub fn revocation_ids(&self) -> Vec<String> {
Expand All @@ -407,6 +444,21 @@ impl PyBiscuit {
.collect()
}

/// Get the external key of a block if it exists
///
/// :param index: the block index
/// :type index: int
/// :return: the public key if it exists
/// :rtype: str | None
pub fn block_external_key(&self, index: usize) -> PyResult<Option<PyPublicKey>> {
let opt_key = self
.0
.block_external_key(index)
.map_err(|e| BiscuitBlockError::new_err(e.to_string()))?;

Ok(opt_key.map(PyPublicKey))
}

fn __repr__(&self) -> String {
self.0.print()
}
Expand Down