| Crates.io | permission_check |
| lib.rs | permission_check |
| version | 0.1.1 |
| created_at | 2025-09-07 17:44:22.843337+00 |
| updated_at | 2025-09-07 20:48:45.59912+00 |
| description | A relatively flexible permission checking library written in rust which checks for permission is scope (like: org.1028.user.*.write), with macro for compile time type checking and code generation |
| homepage | |
| repository | https://github.com/i-am-unknown-81514525/permission_check |
| max_upload_size | |
| id | 1828373 |
| size | 60,099 |
A relatively flexible permission checking library written in rust which checks for permission is scope (like: org.1028.user.*.write), with macro for compile time type checking and code generation
The permission system is scoped, and seperated with . with a few rules
readwriteassignenactaddremoveread_onelist_all* - a single scope level with any name or id (exclude specifier)** - a single scope level with any name, id or specifier*** - any scope level of any name, id or specifier0 unless it is just 0)2x - not allowed since it start with numberx2 - allowedorg.1.read - allowed since the only specifier read is at the endorg.1 - allowed since a specifier is not required, just most be at the end if includedorg.1.read.2 - NOT ALLOWEDorg.1.2*** glob level between 0 or 1 time
*** isn't used, it would imply *** at the endFor the permission to match the requirement, the permission must perfectly encapsulate all specified requirement (which therefore, if globbing is used in the requirement, it would only be true IF the corresponding globbing is qualified in the permission)
You can use check_expr to check a more complex permission required, where you can use |, &, ^, ! and () to define what is required (check usage in src/tests/test_expr.rs), and you can use permission_macro to build-time permission checking (as seen from below) and variable encapsulation
Example:
use permission_macro::{perm_parser, perm_expr};
#[test]
fn test_1() {
let checker = perm_expr!(
((org.1047.role.admin.enact | org.1047.role.owner.enact) | (org.1047.user.write && (org.1047.user.read | org.1047.user.read_one)) | (org.1047.user.243.read && org.1047.user.243.write)) &
!(user.blacklist.enact & !user.blacklist.*)
);
assert_eq!(checker.with_perm(perm_parser!(org.1047.user.243)), true);
assert_eq!(checker.with_perm(perm_parser!(org.1048.user.243)), false);
assert_eq!(checker.with_perm(perm_parser!(org.1047.user.244)), false);
assert_eq!(checker.with_perm(perm_parser!(org.1047.role.owner)), true);
assert_eq!(checker.with_perm(perm_parser!(org.1048.role.owner)), false);
assert_eq!(checker.with_perm(perm_parser!(org)), true);
assert_eq!(checker.with_perm(perm_parser!(*)), true);
assert_eq!(checker.with_perm(perm_parser!(org.1047)), true);
assert_eq!(checker.with_perm(perm_parser!(org.1048)), false);
assert_eq!(
checker.with_perm(vec![perm_parser!(org.1047.user.243.read)]),
false
);
assert_eq!(
checker.with_perm(vec![
perm_parser!(org.1047.user.243.read),
perm_parser!(org.1047.user.243.write)
]),
true
);
assert_eq!(
checker.with_perm(vec![
perm_parser!(org.1047.user.write),
perm_parser!(org.1047.user.read)
]),
true
);
assert_eq!(
checker.with_perm(vec![
perm_parser!(org.1047.user.write),
perm_parser!(org.1047.user.read_one)
]),
true
);
assert_eq!(
checker.with_perm(vec![
perm_parser!(org.1047.user.write),
perm_parser!(org.1047.user.assign)
]),
false
);
assert_eq!(
checker.with_perm(vec![
perm_parser!(org.1047.role.owner),
perm_parser!(user.blacklist.enact)
]),
false
);
assert_eq!(
checker.with_perm(vec![
perm_parser!(org.1047.role.owner),
perm_parser!(user.blacklist.***)
]),
true
);
let org_id = 1047;
let user_id = 243;
assert_eq!(
checker.with_perm(vec![
perm_parser!(org.{org_id}.user.{user_id}.read),
perm_parser!(org.{org_id}.user.{user_id}.write)
]),
true
);
let org_id = 1047;
let user_id = 244;
assert_eq!(
checker.with_perm(vec![
perm_parser!(org.{org_id}.user.{user_id}.read),
perm_parser!(org.{org_id}.user.{user_id}.write)
]),
false
);
}
https://github.com/user-attachments/assets/ef21806e-9803-47a6-8e62-3a334087049a