How to Implement a Role-Based Access Control (RBAC) System in Django
Introduction
In many web applications, user access to specific parts of the application needs to be controlled based on their role. For example, a basic HR system might have Admins, Managers, and Employees, each with different levels of access. This is where Role-Based Access Control (RBAC) helps. RBAC allows developers to assign roles to users and control what they can and cannot access within the application.
In this blog, we’ll walk through creating a simple RBAC system in Django, where users are assigned roles and permissions.
Step 1: Define Your User Roles
For this example, let’s assume our system has three main roles:
- Admin – Can access everything.
- Manager – Can manage employees but has restricted access to certain admin features.
- Employee – Has limited access, mainly to view and update personal information.
We’ll represent these roles as choices in our database and set up access control accordingly.
Step 2: Extend the Django User Model
First, create a custom user model to store the role information. Django’s default User model doesn’t have a role field, so let’s add it.
Create a custom user model:
In models.py, define the roles using choices.
from django.contrib.auth.models import AbstractUser
from django.db import models
class CustomUser(AbstractUser):
ROLE_CHOICES = [
('admin', 'Admin'),
('manager', 'Manager'),
('employee', 'Employee'),
]
role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='employee')
def __str__(self):
return f"{self.username} ({self.role})"
Update settings.py:
Use this custom model instead of the default User model.
AUTH_USER_MODEL = 'your_app_name.CustomUser'
Step 3: Define Permissions for Each Role
Now, let’s define the permissions for each role. One way to do this is by creating decorators that check the user’s role before allowing access to certain views.
Create a decorator for role-based access:
In the decorators.py, define the decorators for checking that if a user has a specific role.
from django.http import HttpResponseForbidden
from functools import wraps
def role_required(role):
def decorator(view_func):
@wraps(view_func)
def _wrapped_view(request, *args, **kwargs):
if request.user.is_authenticated and request.user.role == role:
return view_func(request, *args, **kwargs)
return HttpResponseForbidden("You don't have permission.")
return _wrapped_view
return decorator
Example usage of the decorator:
So we can use this decorator to protect specific views.
from django.shortcuts import render
from .decorators import role_required
@role_required('admin')
def admin_dashboard(request):
return render(request, 'admin_dashboard.html')
@role_required('manager')
def manager_dashboard(request):
return render(request, 'manager_dashboard.html')
Step 4: Assigning Permissions from the Django’s Admin Panel
To allow flexible role assignments, make sure the role field in your CustomUser model is available in Django’s admin panel.
Update the admin configuration:
In admin.py, customize the user admin to include the role field.
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser
class CustomUserAdmin(UserAdmin):
fieldsets = UserAdmin.fieldsets + (
(None, {'fields': ('role',)}),
)
admin.site.register(CustomUser, CustomUserAdmin)
Step 5: Protecting Template Content
Sometimes, you may want to show or hide certain parts of a template based on the user’s role. You can get this by using Django’s template tags and filters.Example of conditional rendering in templates:
In your HTML template, use {% if %} statements to check the user’s role and conditionally display elements.
{% if user.role == 'admin' %}
<a href="{% url 'admin_dashboard' %}">Admin Dashboard</a>
{% elif user.role == 'manager' %}
<a href="{% url 'manager_dashboard' %}">Manager Dashboard</a>
{% endif %}
Step 6: Testing the RBAC System
Make sure to test the RBAC system thoroughly by logging in with users assigned different roles.
- Create test users in the Django admin panel, each with different roles.
- Verify access to views using different roles to ensure each user can only access the appropriate pages.
Conclusion
Role-Based Access Control (RBAC) is a crucial component for many applications, enabling you to assign different levels of access to users based on their roles. In this guide, we created a simple RBAC system in Django, demonstrating how to extend the User model, create decorators for role-based permissions, and customize templates based on user roles.You can expand this system further by integrating Django’s permissions framework to assign more granular permissions or using a third-party package like django-guardian for object-level permissions. With a solid RBAC setup in place, your application will be better equipped to manage and secure user access!