Skip to content

Commit

Permalink
✨ Strongly type errors in orangutan-refresh-token
Browse files Browse the repository at this point in the history
  • Loading branch information
RemiBardon committed Jun 8, 2024
1 parent 7a1f598 commit 63c940b
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 15 deletions.
2 changes: 1 addition & 1 deletion src/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/orangutan-refresh-token/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "orangutan-refresh-token"
version = "0.2.1"
version = "0.3.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
39 changes: 28 additions & 11 deletions src/orangutan-refresh-token/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ extern crate biscuit_auth as biscuit;
use std::{process, time::SystemTime};

use biscuit::{
builder::{BlockBuilder, Fact},
macros::{block, fact},
Biscuit,
};
Expand Down Expand Up @@ -31,21 +32,21 @@ impl RefreshToken {
pub fn new(
duration: std::time::Duration,
profiles: impl Iterator<Item = String>,
) -> Result<Self, String> {
) -> Result<Self, Error> {
let mut builder = Biscuit::builder();

// Add profiles to Biscuit
for profile in profiles {
let fact = fact!("profile({profile});");
builder
.add_fact(fact.to_owned())
.map_err(|e| format!("Could not add fact '{fact:?}' to Biscuit: {e}"))?;
.map_err(|e| Error::CannotAddFact(fact, e))?;
}

// Create first Biscuit block
let mut biscuit = builder
.build(&ROOT_KEY)
.map_err(|e| format!("Error building Biscuit: {e}"))?;
.map_err(Error::CannotBuildBiscuit)?;

// Add expiry block to Biscuit
let expiry_block = block!(
Expand All @@ -54,7 +55,7 @@ impl RefreshToken {
);
biscuit = biscuit
.append(expiry_block.to_owned())
.map_err(|e| format!("Could not add block '{expiry_block}' to Biscuit: {e}"))?;
.map_err(|e| Error::CannotAddBlock(expiry_block, e))?;

Ok(Self(biscuit))
}
Expand All @@ -63,23 +64,22 @@ impl RefreshToken {
pub fn try_from(
duration: String,
profiles: impl Iterator<Item = String>,
) -> Result<Self, String> {
) -> Result<Self, Error> {
let duration = IsoDuration::parse(&duration)
.map_err(|e| format!("Duration malformatted ({e:?}). Check ISO 8601."))?
.map_err(|e| Error::MalformattedDuration(duration.clone(), e))?
.to_std()
.ok_or(
"Cannot convert `iso8601_duration::Duration` to `std::time::Duration`.".to_string(),
)?;
.ok_or(Error::UnsupportedDuration(duration.clone()))?;
Self::new(duration, profiles)
}

pub fn as_base64(&self) -> Result<String, String> {
pub fn as_base64(&self) -> Result<String, Error> {
// Encode Biscuit to Base64
let biscuit_base64 = self
.0
.to_base64()
// Remove Base64 padding (for easier URL query parameter parsing)
.map(|b| remove_padding(&b).to_owned())
.map_err(|e| format!("Error converting Biscuit to Base64: {e}"))?;
.map_err(Error::CannotConvertToBase64)?;

Ok(biscuit_base64)
}
Expand All @@ -95,3 +95,20 @@ fn remove_padding<'a>(base64_string: &'a str) -> &'a str {
// If no '=' character is found, return the original string
base64_string
}

#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Could not add fact '{0:?}' to Biscuit: {1}")]
CannotAddFact(Fact, biscuit::error::Token),
#[error("Error building Biscuit: {0}")]
CannotBuildBiscuit(biscuit::error::Token),
#[error("Could not add block '{0}' to Biscuit: {1}")]
CannotAddBlock(BlockBuilder, biscuit::error::Token),
#[error("Could convert Biscuit to Base64: {0}")]
CannotConvertToBase64(biscuit::error::Token),
#[error("Duration '{0}' malformatted ({1:?}). Check ISO 8601.")]
MalformattedDuration(String, iso8601_duration::ParseDurationError),
// FIXME: Support `year` and `month` durations
#[error("Could not convert `iso8601_duration::Duration` to `std::time::Duration`. '{0}' contains `year` or `month`, which isn't supported by `{}`.", stringify!(iso8601_duration::duration::Duration::to_std))]
UnsupportedDuration(String),
}
4 changes: 2 additions & 2 deletions src/orangutan-refresh-token/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ extern crate biscuit_auth as biscuit;

use std::{env, process};

use orangutan_refresh_token::RefreshToken;
use orangutan_refresh_token::{Error, RefreshToken};
use tracing::error;

fn main() {
Expand All @@ -12,7 +12,7 @@ fn main() {
}
}

fn main_() -> Result<(), String> {
fn main_() -> Result<(), Error> {
// Parse arguments
let duration = env::args()
.skip(1)
Expand Down

0 comments on commit 63c940b

Please sign in to comment.