Skip to content

Commit

Permalink
runes: Add Pay rule and disjunctive set rule
Browse files Browse the repository at this point in the history
- Adds a rule that only allows to call the `pay` method.
- Adds the special rule `Add` that combines the provided rules in a
  disjunctive set (all alternatives are OR combined).

Signed-off-by: Peter Neuroth <[email protected]>
  • Loading branch information
nepet committed Sep 10, 2023
1 parent 8da2bea commit 42ca93a
Showing 1 changed file with 52 additions and 2 deletions.
54 changes: 52 additions & 2 deletions libs/gl-client/src/runes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,21 @@ impl RuneFactory {
}

/// Predefined rule sets to generate `Restriction`s from.
pub enum DefRules {
#[derive(Clone, Copy)]
pub enum DefRules<'a> {
/// Represents a rule set where only read operations are allowed. This
/// translates to a `Restriction` that is "method^Get|method^List".
ReadOnly,
/// Represents a rule set where only the `pay` method is allowed. This
/// translates to a `Restriction` that is "method=pay".
Pay,
/// A special rule that adds the alternatives of the given `DefRules`
/// in a disjunctive set. Example: Add(vec![ReadOnly, Pay]) translates
/// to a `Restriction` that is "method^Get|method^List|method=pay".
Add(&'a [DefRules<'a>]),
}

impl Restricter for DefRules {
impl<'a> Restricter for DefRules<'a> {
/// Generate the actual `Restriction` entities based on the predefined rule
/// sets.
///
Expand All @@ -73,6 +81,30 @@ impl Restricter for DefRules {
.unwrap()];
Ok(a)
}
DefRules::Pay => {
let a =
vec![Restriction::new(vec![
alternative("method", Condition::Equal, "pay").unwrap()
])
.unwrap()];
Ok(a)
}
DefRules::Add(rules) => {
let alt_set =
rules
.into_iter()
.try_fold(Vec::new(), |mut acc: Vec<Alternative>, rule| {
let mut alts = rule
.generate()?
.into_iter()
.flat_map(|r| r.alternatives)
.collect();
acc.append(&mut alts);
Ok(acc)
})?;
let a = vec![Restriction::new(alt_set)?];
Ok(a)
}
}
}
}
Expand Down Expand Up @@ -116,4 +148,22 @@ mod tests {
let carved_rune = Rune::from_base64(&carved).unwrap();
assert!(mr.is_authorized(&carved_rune));
}

#[test]
fn test_carve_disjunction_rune() {
let seed = [0; 32];
let mr = Rune::new_master_rune(&seed, vec![], None, None).unwrap();

// Carve a new rune from the master rune with given restrictions.
let carved =
RuneFactory::carve(&mr, &[DefRules::Add(&[DefRules::ReadOnly, DefRules::Pay])])
.unwrap();

let carved_byt = general_purpose::URL_SAFE.decode(&carved).unwrap();
let carved_restr = String::from_utf8(carved_byt[32..].to_vec()).unwrap(); // Strip off the authcode to inspect the restrictions.
assert_eq!(carved_restr, *"method^Get|method^List|method=pay");

let carved_rune = Rune::from_base64(&carved).unwrap();
assert!(mr.is_authorized(&carved_rune));
}
}

0 comments on commit 42ca93a

Please sign in to comment.