RBAC
authx implements RBAC through Organizations, Roles, and Memberships. Every user can belong to multiple organizations, each with a different role.
Data model
Section titled “Data model”Organization └─ Role (name, permissions: Vec<String>) └─ Membership (user_id, org_id, role_id)Checking a role in a handler
Section titled “Checking a role in a handler”use authx_axum::RequireRole;
// Handler only reachable by users with "admin" role in the active orgasync fn admin_panel( RequireRole(identity, _): RequireRole<"admin">,) -> impl IntoResponse { // identity.active_membership.unwrap().role is verified}Programmatic check
Section titled “Programmatic check”use authx_core::policy::{AuthzEngine, AuthzRequest};
let engine = AuthzEngine::new(); // add policies as needed
engine.enforce( "reports.delete", &identity, Some("org:acme-uuid:reports"),).await?;// Returns Err(AuthError::Forbidden) if deniedManaging roles with OrgService
Section titled “Managing roles with OrgService”use authx_plugins::OrgService;
let svc = OrgService::new(store.clone(), events.clone());
// Create organization — owner gets a built-in "owner" role automaticallylet (org, membership) = svc.create(owner_id, "Acme Corp", "acme", None).await?;
// Create a custom rolelet role = svc.create_role(org.id, "billing", vec!["invoices.read", "invoices.write"]).await?;
// Assign role to a membersvc.set_member_role(org.id, user_id, role.id).await?;
// Invite someone (returns raw token — send it via email yourself)let details = svc.invite_member(org.id, "bob@example.com", role.id, actor_id).await?;
// Accept invite (user clicks link with token)let membership = svc.accept_invite(&details.raw_token, new_user_id).await?;