use serde::de::DeserializeOwned;
pub trait AuthClaims: DeserializeOwned + Clone {
fn role(&self) -> Option<&str> {
None
}
fn roles(&self) -> Option<&[String]> {
None
}
fn permissions(&self) -> Option<&[String]> {
None
}
}
#[macro_export]
macro_rules! claims {
(
$(#[$meta:meta])*
$vis:vis struct $name:ident {
$(
$(#[$field_meta:meta])*
$field:ident : $type:ty
),* $(,)?
}
) => {
$(#[$meta])*
$vis struct $name {
$(
$(#[$field_meta])*
pub $field: $type,
)*
}
impl $crate::auth::AuthClaims for $name {
$(
claims!(@gen_impl $field);
)*
}
};
(@gen_impl role) => {
fn role(&self) -> Option<&str> {
Some(&self.role)
}
};
(@gen_impl roles) => {
fn roles(&self) -> Option<&[String]> {
Some(&self.roles)
}
};
(@gen_impl permissions) => {
fn permissions(&self) -> Option<&[String]> {
Some(&self.permissions)
}
};
(@gen_impl $field:ident) => {};
}
#[cfg(test)]
mod tests {
use super::super::{Authorizer, permissions, predicate, role, roles};
use serde::{Deserialize, Serialize};
claims! {
#[derive(Clone, Debug, Serialize, Deserialize)]
struct MyClaims {
sub: String,
role: String,
permissions: Vec<String>,
}
}
claims! {
#[derive(Clone, Debug, Serialize, Deserialize)]
struct MyClaims2 {
sub: String,
roles: Vec<String>,
}
}
#[test]
fn it_creates_claims_and_test_role() {
let claims = MyClaims {
sub: "123".to_string(),
role: "admin".to_string(),
permissions: vec!["read".to_string(), "write".to_string()],
};
let validate: Authorizer<MyClaims> = role("admin");
assert!(validate.validate(&claims))
}
#[test]
fn it_creates_claims_and_test_roles() {
let claims = MyClaims2 {
sub: "123".to_string(),
roles: vec!["admin".to_string(), "user".to_string()],
};
let validate: Authorizer<MyClaims2> = roles(["admin", "user", "editor"]);
assert!(validate.validate(&claims))
}
#[test]
fn it_creates_claims_and_test_permissions() {
let claims = MyClaims {
sub: "123".to_string(),
role: "user".to_string(),
permissions: vec!["read".to_string(), "write".to_string()],
};
let validate: Authorizer<MyClaims> = permissions(["write"]);
assert!(validate.validate(&claims))
}
#[test]
fn it_creates_claims_and_test_predicate() {
let claims = MyClaims {
sub: "123".to_string(),
role: "user".to_string(),
permissions: vec!["read".to_string(), "write".to_string()],
};
let validate = predicate(|c: &MyClaims| c.sub == "123");
assert!(validate.validate(&claims))
}
}