RBAC (Role-Based Access Control) Model Documentation
Overview​
The RBAC model implements role-based access control for the CODITECT platform, providing fine-grained permission management at the tenant level. It follows the principle of least privilege, allowing administrators to create custom roles with specific permission sets and assign them to users. The system supports both predefined system roles and custom tenant-specific roles.
Model Structure​
Permission Enum​
enum Permission {
// Project permissions
ProjectRead, // View projects and details
ProjectWrite, // Create and update projects
ProjectDelete, // Delete projects
ProjectManage, // Project settings and members
// Task permissions
TaskRead, // View tasks
TaskWrite, // Create and update tasks
TaskDelete, // Delete tasks
TaskAssign, // Assign tasks to members
// Member permissions
MemberRead, // View team members
MemberWrite, // Update member profiles
MemberInvite, // Invite new members
MemberRemove, // Remove members
// Admin permissions
AdminAccess, // Access admin panel
TenantManage, // Manage tenant settings
UserManage // Manage all users
}
Role Model​
| Field | Type | Description | Constraints |
|---|---|---|---|
role_id | UUID | Unique role identifier | Primary key, auto-generated |
tenant_id | UUID | Associated tenant | Foreign key to Tenant |
name | String | Role display name | Required, unique per tenant |
description | String | Role purpose | Optional |
permissions | HashSet | Granted permissions | Required, at least one |
is_system_role | bool | System-defined role | Cannot be modified if true |
UserRole Model​
| Field | Type | Description | Constraints |
|---|---|---|---|
user_id | UUID | User with role | Foreign key to User |
tenant_id | UUID | Tenant context | Foreign key to Tenant |
role_id | UUID | Assigned role | Foreign key to Role |
Predefined Roles​
System Roles​
{
"role_id": "550e8400-e29b-41d4-a716-446655440000",
"tenant_id": "123e4567-e89b-12d3-a456-426614174000",
"name": "Admin",
"description": "Full system access",
"permissions": [
"ProjectRead", "ProjectWrite", "ProjectDelete", "ProjectManage",
"TaskRead", "TaskWrite", "TaskDelete", "TaskAssign",
"MemberRead", "MemberWrite", "MemberInvite", "MemberRemove",
"AdminAccess", "TenantManage", "UserManage"
],
"is_system_role": true
}
Common Role Templates​
Developer Role​
{
"name": "Developer",
"description": "Standard developer access",
"permissions": [
"ProjectRead", "ProjectWrite",
"TaskRead", "TaskWrite", "TaskAssign",
"MemberRead"
],
"is_system_role": false
}
Manager Role​
{
"name": "Manager",
"description": "Project management access",
"permissions": [
"ProjectRead", "ProjectWrite", "ProjectManage",
"TaskRead", "TaskWrite", "TaskDelete", "TaskAssign",
"MemberRead", "MemberWrite", "MemberInvite"
],
"is_system_role": false
}
Viewer Role​
{
"name": "Viewer",
"description": "Read-only access",
"permissions": [
"ProjectRead",
"TaskRead",
"MemberRead"
],
"is_system_role": false
}
Database Schema​
Primary Storage Patterns​
# Roles
Key: /{tenant_id}/roles/{role_id}
Value: JSON serialized Role
# User role assignments
Key: /{tenant_id}/user_roles/{user_id}/{role_id}
Value: JSON serialized UserRole
# System roles (global)
Key: /system_roles/{role_name}
Value: JSON serialized Role template
Secondary Indexes​
# Roles by name
/{tenant_id}/roles_by_name/{name} -> role_id
# Users by role
/{tenant_id}/users_by_role/{role_id} -> [user_ids]
# Roles by permission
/{tenant_id}/roles_by_permission/{permission} -> [role_ids]
# User's roles
/{tenant_id}/user_roles/{user_id} -> [role_ids]
Permission Matrix​
Project Permissions​
| Permission | Capabilities |
|---|---|
| ProjectRead | View projects, see project details, list tasks |
| ProjectWrite | Create projects, update settings, modify details |
| ProjectDelete | Archive/delete projects, requires confirmation |
| ProjectManage | Add/remove members, configure integrations |
Task Permissions​
| Permission | Capabilities |
|---|---|
| TaskRead | View tasks, see assignments, read comments |
| TaskWrite | Create tasks, update status, add comments |
| TaskDelete | Delete tasks, bulk operations |
| TaskAssign | Assign to members, change assignees |
Member Permissions​
| Permission | Capabilities |
|---|---|
| MemberRead | View team directory, see profiles |
| MemberWrite | Update profiles, change availability |
| MemberInvite | Send invitations, create accounts |
| MemberRemove | Deactivate members, transfer ownership |
Administrative Permissions​
| Permission | Capabilities |
|---|---|
| AdminAccess | Access admin dashboard, view analytics |
| TenantManage | Configure tenant, billing, integrations |
| UserManage | Create/modify/delete all users |
Permission Inheritance​
Hierarchical Permissions​
Some permissions imply others:
ProjectManage→ProjectWrite→ProjectReadTaskAssign→TaskWrite→TaskReadMemberRemove→MemberInvite→MemberWrite→MemberReadTenantManage→AdminAccessUserManage→ All member permissions
Resource-Based Permissions​
Future enhancement for resource-specific access:
struct ResourcePermission {
permission: Permission,
resource_type: ResourceType,
resource_id: Option<Uuid>,
conditions: Option<Vec<Condition>>
}
enum ResourceType {
Project(Uuid),
Task(Uuid),
Team(Uuid)
}
Related Code​
Source Files​
- Models:
/src/models/rbac.rs - Repository:
/src/db/repositories/rbac_repository.rs - Service:
/src/services/authorization_service.rs - Middleware:
/src/api/middleware/auth.rs - API Handlers:
/src/api/handlers/roles.rs - Tests:
/src/models/tests/rbac_tests.rs
Key Methods​
impl Role {
fn new(tenant_id: Uuid, name: String, permissions: HashSet<Permission>) -> Self
fn admin_role(tenant_id: Uuid) -> Self
fn has_permission(&self, permission: &Permission) -> bool
fn add_permission(&mut self, permission: Permission)
fn remove_permission(&mut self, permission: Permission)
}
impl AuthorizationService {
async fn check_permission(&self, user_id: Uuid, permission: Permission) -> Result<bool>
async fn get_user_permissions(&self, user_id: Uuid) -> Result<HashSet<Permission>>
async fn assign_role(&self, user_id: Uuid, role_id: Uuid) -> Result<()>
async fn revoke_role(&self, user_id: Uuid, role_id: Uuid) -> Result<()>
}
API Endpoints​
Role Management​
- POST
/api/roles- Create custom role - GET
/api/roles- List all roles - GET
/api/roles/{role_id}- Get role details - PUT
/api/roles/{role_id}- Update role - DELETE
/api/roles/{role_id}- Delete role
User Role Assignment​
- POST
/api/users/{user_id}/roles- Assign role - GET
/api/users/{user_id}/roles- List user's roles - DELETE
/api/users/{user_id}/roles/{role_id}- Revoke role - GET
/api/users/{user_id}/permissions- Get effective permissions
Permission Checking​
- POST
/api/auth/check-permission- Check specific permission - GET
/api/auth/my-permissions- Get current user permissions
Authorization Patterns​
Request Authorization​
// Middleware pattern
async fn require_permission(permission: Permission) -> impl Filter {
warp::header::<String>("authorization")
.and_then(move |token: String| async move {
let user = verify_jwt(token)?;
let has_perm = auth_service
.check_permission(user.id, permission)
.await?;
if has_perm {
Ok(user)
} else {
Err(Forbidden)
}
})
}
// Usage
let route = warp::path!("projects" / Uuid)
.and(require_permission(Permission::ProjectRead))
.and_then(get_project);
Programmatic Checks​
// Service layer
impl ProjectService {
async fn update_project(&self, user_id: Uuid, project: Project) -> Result<()> {
// Check permission
if !self.auth.check_permission(user_id, Permission::ProjectWrite).await? {
return Err(Unauthorized);
}
// Additional project-specific check
if !self.is_project_member(user_id, project.id).await? {
return Err(Forbidden);
}
// Perform update
self.repo.update(project).await
}
}
Security Best Practices​
Role Design​
- Principle of Least Privilege: Grant minimum required permissions
- Separation of Duties: Divide responsibilities across roles
- No Default Admin: Require explicit admin assignment
- Regular Audits: Review role assignments periodically
Permission Guards​
// Ensure critical operations have multiple checks
async fn delete_tenant(user_id: Uuid, tenant_id: Uuid) -> Result<()> {
// Check permission
require_permission(user_id, Permission::TenantManage)?;
// Check ownership
require_tenant_owner(user_id, tenant_id)?;
// Require confirmation
require_confirmation_token()?;
// Audit log
audit_critical_action(user_id, "tenant_deletion", tenant_id)?;
// Perform deletion
tenant_service.delete(tenant_id).await
}
Audit Trail​
struct PermissionAudit {
audit_id: Uuid,
timestamp: DateTime<Utc>,
user_id: Uuid,
action: PermissionAction,
resource: String,
permission: Permission,
granted: bool,
reason: Option<String>
}
enum PermissionAction {
Check,
Grant,
Revoke,
Denied
}
Performance Optimization​
Caching Strategy​
// Cache user permissions for fast lookup
struct PermissionCache {
user_permissions: Arc<RwLock<HashMap<Uuid, (HashSet<Permission>, DateTime<Utc>)>>>,
ttl: Duration
}
impl PermissionCache {
async fn get_permissions(&self, user_id: Uuid) -> Option<HashSet<Permission>> {
let cache = self.user_permissions.read().await;
if let Some((perms, expires)) = cache.get(&user_id) {
if *expires > Utc::now() {
return Some(perms.clone());
}
}
None
}
}
Batch Operations​
- Load all user roles in single query
- Preload permissions for request context
- Use permission bitmasks for fast checks
- Index frequently checked permissions
Common Patterns​
Multi-Role Users​
// Users can have multiple roles
let developer_role = Role::new(tenant_id, "Developer", dev_perms);
let reviewer_role = Role::new(tenant_id, "Reviewer", review_perms);
user_service.assign_role(user_id, developer_role.id).await?;
user_service.assign_role(user_id, reviewer_role.id).await?;
// Effective permissions = union of all roles
let permissions = auth_service.get_user_permissions(user_id).await?;
Temporary Permissions​
struct TemporaryGrant {
user_id: Uuid,
permission: Permission,
expires_at: DateTime<Utc>,
reason: String
}
// Grant temporary elevated access
auth_service.grant_temporary(
user_id,
Permission::ProjectManage,
Duration::hours(24),
"Coverage for manager vacation"
).await?;
Delegation​
struct PermissionDelegation {
from_user_id: Uuid,
to_user_id: Uuid,
permissions: HashSet<Permission>,
valid_from: DateTime<Utc>,
valid_until: DateTime<Utc>
}
Future Enhancements​
Advanced RBAC Features​
- Attribute-Based Access Control (ABAC): Context-aware permissions
- Dynamic Roles: Roles based on attributes/conditions
- Permission Templates: Reusable permission sets
- Role Hierarchies: Parent-child role relationships
Resource-Level Permissions​
- Project-Specific Roles: Different roles per project
- Task-Level Permissions: Fine-grained task access
- Field-Level Security: Control access to specific fields
- Data Classification: Permission based on data sensitivity
Integration Features​
- SAML/OIDC Mapping: Map external roles to internal
- LDAP Sync: Import roles from directory services
- API Scopes: OAuth2 scope to permission mapping
- Webhook Permissions: External permission checks
Compliance Features​
- SOC2 Compliance: Audit trail requirements
- GDPR Rights: Data access permissions
- HIPAA Support: Healthcare data permissions
- Zero Trust: Continuous authorization
Last Updated: 2025-08-29 Version: 1.0