Role Based Access Control is an approach to provide restrictive access to users in a system based on their role in the organization. It is a major feature which can make your application access refined and obviously more secure. Django provides authentication and authorization features out of the box that youcan leverage to build a role based access control. Django user authentication has built-in models like User, Group and Permission that can help us get granular access control needed by your application.
This model here stores the actual users in the system. It has basic fields like username, password, email etc. You can extend this class to add more attributes as needed by your application. Django user authentication handles the authentication through session and middlewares . With every request django hooks a request object that gives details of the the logged in user through request.user. To achieve role based access control you can use the request.user to authorize the user request to access information.
These are logical groups of user as needed by the system. These groups can be assigned permissions and the users can be assigned to these groups. Django provides a basic view in the admin to create these groups and manage the permissions. The group can be coined as the “role” the user has in the system. Like, a user can be an “admin” and belong to a group called “admin” or a he/she could be “support” staff and can belong to a group called “support”.
The defined groups control access based on the permissions assigned to each group. Django provides add, edit and change permissions for each model by default. These permissions can be used at the admin view and even in your application. For eg, if you have a model say ‘Blog’.
Each of these models are registered as ContentType in django and all of the permissions that django creates under class Permission has a reference to this ContentType. For the model taken as example these are the permissions that would be created by default:
add_blog : Any User or group that has this permission can add a new blog. change_blog: Any user or group that has this permission can edit the blog. delete_blog: Any user or group that has this permission can delete a blog.
Django default permissions are very basic and they may not always suffice to your application’s requirement. Django allows you to add custom permissions and use them like you need. You can use a model meta attribute to add new permissions:
These extra permissions are created along with default permissions when you run manage.py migrate.
These permission can be assigned to a user directly or to a group which can be assigned to a user. For eg; the group “admin” can be assigned all of these permissions, wherein the “support” group may only have “change_blog” permission. That would mean only an admin user can add or delete a blog. Role based access control would come into play when you check for these permission in your views, templates or APIs.
Permissions can be checked in a view using has_perm method or a decorator. The User object provides the method has_perm(perm, obj=None), where perm is “
You can also use a decorator ‘permission_required(perm, login_url=None, raise_exception=False)’ to check the permission. This decorator also takes permission in the form “
from django.contrib.auth.decorators import permission_required
@permission_required(‘blog.can_publish_blog’, login_url=’/signin/’) def publish_blog(request): …
If you have a class based view then you can use “PermissionRequiredMixin”. You can pass one or multiple permission to permission_required parameter.
from django.contrib.auth.mixins import PermissionRequiredMixin
class PublishBlog(PermissionRequiredMixin, View): permission_required =blog.can_publish_blog’
The permissions of the logged in user are stored in template variable , You can check for a particular permission within an app.
This is the question that most of us ask, “where do I put my permission check, decorator or middleware?”. The answer can be kept straight forward by answering if your access control rule is global or specific to few views. For eg; if you have two access control rules, first that all the users accessing the application must have “view_blog” permission and second that only a user having a permission “can_publish_blog” can publish a blog. In case of latter you can add the check as a decorator to the”publish_blog” view.
However in case of former you will put that check in your middleware as it applies to all your urls, a user who does not have this permission cannot enter your application. Now there is nothing wrong to add it as a decorator, that would still keep the views safe. But adding the decorator to each and every view of your application would be cumbersome and if a new developer forgets to add the decorator to a view he wrote then the the rule would be violated. Thus any permission that has to be honored globally should be checked in the middleware.
Django user authentication can be used to achieve complete role based access control for your application. So leverage as much of these features as you can and deliver delight real quick