Skip to content

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 definitions
  • RoleModel: Stores role definitions
  • RolePermissionModel: 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:

  1. Principle of Least Privilege: Assign only the permissions necessary for a user to perform their job
  2. Role Separation: Create distinct roles for different job functions
  3. Regular Audits: Periodically review role assignments and permissions
  4. Role Hierarchy: Use role hierarchies to simplify permission management
  5. Permission Granularity: Define permissions at an appropriate level of granularity