Permissions & Roles
The Permissions & Roles module provides a flexible and powerful access control system for the UBU Digital Finance Solution.
Overview
This module implements a role-based access control (RBAC) system with the following components:
- Permissions: Granular access rights to specific system functions
- Roles: Collections of permissions that can be assigned to users
- Role Assignments: Mapping of roles to users
Features
Permission Management
Permissions represent the ability to perform specific actions within the system:
- Each permission has a unique key, name, and description
- Permissions are atomic and represent specific capabilities
- Permissions can be created, updated, and deleted by administrators
- Permissions cannot be directly assigned to users; they must be assigned to roles
Role Management
Roles are collections of permissions that can be assigned to users:
- Each role has a name, description, and active status
- Roles can be created, updated, and deleted by administrators
- Roles can be assigned to multiple users
- A user can have multiple roles
Dynamic Role-Based Access Control
The system implements a dynamic RBAC system:
- Access to endpoints is controlled by permission checks
- When a user attempts to access a protected resource, their permissions are checked
- Permissions are determined by the roles assigned to the user
- Role assignments can be activated or deactivated without removing the assignment
Hierarchical Roles
The system supports a hierarchical role structure:
- Roles can be organized in a hierarchy (e.g., super-admin -> branch manager -> teller)
- This allows for more efficient permission management
- Higher-level roles typically include all permissions of lower-level roles
API Endpoints
Permission Endpoints
| Endpoint | Method | Description |
|---|---|---|
/permission/ |
POST | Create a new permission |
/permission/ |
GET | Get all permissions |
/permission/{permission_id} |
GET | Get a specific permission |
/permission/{permission_id} |
PUT | Update a permission |
/permission/{permission_id} |
DELETE | Delete a permission |
Role Endpoints
| Endpoint | Method | Description |
|---|---|---|
/role/ |
POST | Create a new role |
/role/ |
GET | Get all roles |
/role/{role_id} |
GET | Get a specific role |
/role/{role_id} |
PUT | Update a role |
/role/{role_id} |
DELETE | Delete a role |
/role/{role_id}/permissions |
POST | Assign permissions to a role |
/role/{role_id}/permissions |
GET | Get permissions for a role |
/role/user/{user_id} |
GET | Get roles for a user |
/role/{role_id}/users |
GET | Get users with a specific role |
Data Model
The Permissions & Roles module uses the following database tables:
Permission: Stores permission definitionsRoleModel: Stores role definitionsRolePermissionModel: Maps roles to permissions (many-to-many)UserRole: Maps users to roles (many-to-many)
For detailed schema information, see the Database Schema documentation.
Implementation Details
Permission Checking
Permission checks are implemented using a dependency injection pattern:
def permission(permission_key: str):
def dependency(
db: AsyncSession = db_dependency,
current_user: TokenData = Depends(get_current_user)
):
# Check if user is active
if not current_user.is_active:
raise HTTPException(
status_code=403,
detail="Activate your account to access this resource"
)
# Get user's active roles
stmt = select(UserRole.role_id).where(
UserRole.user_id == current_user.id,
UserRole.role_is_active == True
)
result = await db.execute(stmt)
user_role_ids = [row[0] for row in result.all()]
if not user_role_ids:
raise HTTPException(
status_code=403, detail="User has no active roles")
# Get permissions for those roles
stmt = (
select(Permission.permision_key)
.join(RolePermissionModel, RolePermissionModel.permission_id == Permission.permission_id)
.where(RolePermissionModel.role_id.in_(user_role_ids))
)
result = await db.execute(stmt)
user_permission_keys = [row[0] for row in result.all()]
# Check for required permission
if permission_key not in user_permission_keys:
raise HTTPException(status_code=403, detail="Permission denied")
return True
return dependency
This function is used as a dependency in FastAPI route definitions:
@router.post("/", status_code=status.HTTP_201_CREATED, dependencies=[Depends(permission("create_user"))])
async def create_user(...):
# Function implementation
Default Permissions
The system includes a set of default permissions for common operations:
| Permission Key | Description |
|---|---|
create_user |
Create new user accounts |
view_users |
View the list of all users |
view_user_profile |
View a specific user's profile |
update_user |
Update user information |
activate_deactivate_user |
Activate or deactivate user accounts |
reset_password |
Reset a user's password |
change_password |
Change own password |
create_permission |
Create new permissions |
view_permissions |
View all permissions |
update_permission |
Update permissions |
delete_permission |
Delete permissions |
create_role |
Create new roles |
view_roles |
View all roles |
update_role |
Update roles |
delete_role |
Delete roles |
assign_permissions |
Assign permissions to roles |
view_role_permissions |
View permissions assigned to a role |
create_organizational_unit |
Create new organizational units |
view_organizational_units |
View all organizational units |
update_organizational_unit |
Update organizational units |
delete_organizational_unit |
Delete organizational units |
Default Roles
The system includes a set of default roles:
| Role Name | Description |
|---|---|
Super Admin |
Has all permissions |
Branch Manager |
Can manage users and view all data |
Teller |
Can perform basic operations |
Customer |
Limited access to own data |
Best Practices
When implementing role-based access control:
- Principle of Least Privilege: Assign only the permissions necessary for a user to perform their job
- Role Separation: Create distinct roles for different job functions
- Regular Audits: Periodically review role assignments and permissions
- Role Hierarchy: Use role hierarchies to simplify permission management
- Permission Granularity: Define permissions at an appropriate level of granularity