Manage user roles and permissions

The rolepermissions app builds on django-role-permissions . It includes support for tenant-aware user roles and permissions, object-level permissions, and custom user permissions.

Changes to the core User model

The User model has been extended to include:

  • roles - list of user roles

  • user_tenant_permissions - list of permissions for that tenant

Defining roles

Roles are defined in config/ .

from enum import Enum
from apps.rolepermissions.roles import AbstractUserRole

class WorkspacePermissions(str, Enum):
    Workspace permissions
    create_workspace = "create_workspace"
    update_workspace = "update_workspace"
    delete_workspace = "delete_workspace"
    view_workspace = "view_workspace"
    manage_workspace_users = "manage_workspace_users"
    manage_workspace_invitations = "manage_workspace_invitations"
    manage_workspace_roles = "manage_workspace_roles"
    manage_billing = "manage_billing"

ws_perm = WorkspacePermissions

class WorkspaceAdmin(AbstractUserRole):
    available_permissions lists all the permissions that this role has.
    available_permissions = {
        WorkspacePermissions.update_workspace: True,
        WorkspacePermissions.delete_workspace: True,

Defining permissions

Object-level permissions can be defined in each app. Here is an example of how you can implement this for a CMS.

from apps.rolepermissions.permissions import register_object_checker
from apps.collection.models import Collection
from config.roles import CollectionAdmin, CollectionMember

def access_collection(role, user, team):
    """User Collections"""

    user_collections = Collection.objects.get_user_teams(user=user)
    if role in [CollectionAdmin, CollectionMember] and collection in user_collection:
        return True

    return False


In the next section, we will look at some utilities for assigning roles and permissions

Assign a role

from apps.rolepermissions.roles import assign_role

user = User.objects.get(id=1)
assign_role(user, 'workspace_member')

Check permissions

from rolepermissions.checkers import has_permission

# usage
has_permission(user, 'workspace_member')
# >> True

has_permission(user, 'edit_patient_file')
# >> False

Change permissions

from rolepermissions.permissions import grant_permission, revoke_permission

# usage
revoke_permission(user, 'create_medical_record')
grant_permission(user, 'edit_patient_file')

has_permission(user, 'create_medical_record')
# >> False

has_permission(user, 'edit_patient_file')
# >> True

Get a user’s roles

from apps.rolepermissions.roles import get_user_roles

role = get_user_roles(user)

Assigns a role to the user using strings

from apps.rolepermissions.roles import assign_role

assign_role(user, 'doctor')

Removes a role from a user using strings

from apps.rolepermissions.roles import remove_role

remove_role(user, 'doctor')

Any permissions that were explicitly granted to the user that are also defined to be granted by this role will be revoked when this role is revoked.

class TeamMember(AbstractUserRole):
     available_permissions = {
         "change_file": False,

class TeamManager(AbstractUserRole):
     available_permissions = {
         "change_file": True,

# usage
grant_permission(user, "change_file")
remove_role(user, TeamManager)

has_permission(user, "change_file")

In the example, the user no longer has the "change_file" permissions, even though it was set explicitly before the TeamManager role was removed.

Clear roles

from apps.rolepermissions.roles import clear_roles


A brief look at some functions

  1. function available_perm_status(user)

Returns a dictionary containing all permissions available across all the specified user's roles. Note that if a permission is granted in one role, it overrides any permissions set to False in other roles. Permissions are the keys of the dictionary, and values are True or False indicating if the permission is granted or not.

from apps.rolepermissions.permissions import available_perm_status

permissions = available_perm_status(user)

if permissions['create_medical_record']:
    print('user can create medical record')
  1. function grant_permission(user, permission_name)

Grants a permission to a user. Will raise a RolePermissionScopeException for a permission that is not listed in the user's roles' available_permissions .


from apps.rolepermissions.permissions import grant_permission

grant_permission(user, 'create_medical_record')
  1. function revoke_permission(user, permission_name)

Revokes a permission from a user. Will raise a RolePermissionScopeException for a permission that is not listed in the user's roles' available_permissions .

from apps.rolepermissions.permissions import revoke_permission

revoke_permission(user, 'create_medical_record')

Permission and role verification

The following functions will always return True for users with superuser status.

  1. function has_role(user, roles)

Receives a user and a role and returns True if user has the specified role. Roles can be passed as an object, snake cased string representation, or inside a list.


from apps.rolepermissions.checkers import has_role
from config.roles import Doctor

if has_role(user, [Doctor, 'nurse']):
    print 'User is a Doctor or a nurse'
  1. function has_permission(user, permission)

Receives a user and a permission and returns True is the user has ths specified permission.

from apps.rolepermissions.checkers import has_permission
from config.roles import Doctor
from records.models import MedicalRecord

if has_permission(user, 'create_medical_record'):
    medical_record = MedicalRecord(...)
  1. function has_object_permission(checker_name, user, obj)

Receives a string referencing the object permission checker, a user and the object to be verified.

from app.rolepermissions.checkers import has_object_permission
from clinics.models import Clinic

clinic = Clinic.objects.get(id=1)

if has_object_permission('access_clinic', user, clinic):
    print 'access granted'


The app is fully tested. All the tests from the original library have been ported over to pytest.