| Crates.io | decide-core |
| lib.rs | decide-core |
| version | 0.1.1 |
| created_at | 2025-06-25 20:48:59.315857+00 |
| updated_at | 2025-06-30 06:45:22.733946+00 |
| description | A fast, lightweight permission engine for Rust and TypeScript with condition support. |
| homepage | https://github.com/aether-flux/decide |
| repository | https://github.com/aether-flux/decide |
| max_upload_size | |
| id | 1726386 |
| size | 18,943 |
A tiny and fast permission engine for Rust.
Define roles and permissions with simple logic like user_id == resource_owner. Done.
Add to your Cargo.toml:
[dependencies]
decide-core = "0.1.1"
use decide_core::types::{User, Resource, RoleMap};
use decide_core::evaluator::Decide;
fn main() {
let roles_json = r#"
{
"editor": {
"name": "editor",
"permissions": [
{ "action": "edit_post", "condition": "user_id == resource_owner" },
{ "action": "like_post", "condition": null }
]
}
}
"#;
let user_json = r#"
{
"id": "123",
"roles": ["editor"]
}
"#;
let resource_json = r#"
{
"owner_id": "123",
"resource_name": "hello-world",
"resource_type": "post"
}
"#;
let role_map: RoleMap = serde_json::from_str(roles_json).unwrap();
let user: User = serde_json::from_str(user_json).unwrap();
let resource: Resource = serde_json::from_str(resource_json).unwrap();
let decide = Decide::new(role_map);
let allowed = decide.can(&user, "edit_post", &resource).unwrap();
println!("Can edit? {}", allowed); // true
}
let decide = Decide::from_file("config_file.json").unwrap();
// or use default "decide.config.json" from root:
let decide = Decide::default().unwrap();
Conditions are written in a simple expression format using Rhai, a safe and embeddable scripting language.
Available fields:
user_id => user.iduser_roles => user.rolesresource_owner => resource.owner_idresource_name => resource.resource_nameresource_type => resource.resource_typeYou can write things like:
condition: 'user_id == resource_owner'
condition: 'user_roles.contains("admin")'
condition: 'user_roles.contains("moderator") || user_id == resource_owner'
Decide::can() returns a Result<bool, DecideError>. So you can check and handle errors as follows:
match decide.can(&user, "edit_post", &resource) {
Ok(true) => println!("Access granted"),
Ok(false) => println!("Access denied"),
Err(e) => eprintln!("Error: {}", e),
}
pub struct User {
pub id: String,
pub roles: Vec<String>,
}
pub struct Resource {
pub owner_id: String,
pub resource_name: String,
pub resource_type: String,
}
pub struct Permission {
pub action: String,
pub condition: Option<String>,
}
pub struct Role {
pub name: String,
pub permissions: Vec<Permission>,
}
pub type RoleMap = HashMap<String, Role>;
MIT