restrict fields according to user permissions in django - django

I'm building an API using Django rest framework. I have to restrict access to fields (both read or write access) according to the kind of user logged in. How do I go about it ? I'm considering writing separate serializers for different user roles (I will get an access token with every request using which I can authenticate the user, the next step will get me the user's roles, according to which I want to restrict what fields the user can see/edit).

In case you want to give certain users model level permissions to conduct certain actions you can do this with custom permissions like so:
class T21Turma(models.Model):
class Meta:
permissions = (("can_view_boletim", "Can view boletim"),
("can_view_mensalidades", "Can view mensalidades"),)
Then you can either make several serializers and swap them out in the views based on the permissions, or you can modify the fields of the serializer dynamically.

Related

Create custom permission classes

I have designed my own RBAC system for my Django app. Unlike the original Django's role-based that uses only permissions, content_types, groups, and users table, I designed mine so that it includes a model for defined operations (i.e. read, write, print), the objects (i.e. Post, Events, Documents), the roles (Writer Level 1, Events Manager) and the necessary relationships i.e. my own permissions table which takes in the object reference and a matching operation reference (i.e. Post | add).
My problem now is I am not quite sure how to implement this in DRF. When I use permission_class = (DjangoObjectPermissions,) and someone sends a 'POST' request to the Post model/table, we all know Django will check if the user has Can add post permission. I want to do this as well but I want Django to refer to my RBAC models/tables.
I want to write my own permission classes in my permissions.py but I might need a bit hint on how to implement this.
I've read you can create custom permissions, but I am not sure if that also means you can enforce your own RBAC tables with it.
Alright after checking rest_frameworks' permissions.py, I think I can enforce my own permission class behavior this way:
Create a custom permission class that subclasses rest_framework.permissions.BasePermission
override has_object_permission() method
Inside the method, write a logic that maps the requesting user into my custom RBAC models to check whether or not he has given the appropriate permission
Return the appropriate boolean
According to the DRF Permissions doc
As with DjangoModelPermissions, this permission must only be applied to views that have a .queryset property or .get_queryset() method. Authorization will only be granted if the user is authenticated and has the relevant per-object permissions and relevant model permissions assigned.
So, you should define either queryset attribute or get_queryset(...) method in your view class.
Example:
class MyViewClass(viewsets.ModelViewSet):
queryset = SomeModel.objects.all()
...
...
...
def get_queryset(self):
return SomeModel.objects.filter(some_field='foo')
...
...
...
The permissions to a User or groups can be controlled via Django's Admin site as well as Django shell

I need help in designing a database (and signup and login on base of their role )in which there are three user

I want make sign up and login on the base of their role there admin can add users and approved the request of other two user so that they can login.When user click on the sign up the user see sign up page accorading to their roll and same for login .
Django implements a pretty decent authentication framework inside it, so you already have things such as Users, Groups and Permissions to work on. All of those being managed easily by the admin page.
What you want to do is to assign a set of groups/permissions to a newly created user to determine its role and then build a frontend that manages the different kind of users in terms of templates. If you want an user to have itself validated before start using your page, refer to the is_active attribute of the User object.
Read for more information:
https://docs.djangoproject.com/en/2.2/topics/auth/default/#user-objects

Django DRF role level permission

I have developed API's using DRF. I am struggling to relate the authorization part from Django's default permission which we define in the admin section for each and every role to the API.
Let's say I have two API's Customer Management and Customer Sales and have two roles created from them at the Django admin portal. manager role will only manage customer (add, view, delete and update) whereas sales role will manage sales (add, view, delete and update) for every customer.
When I try testing them in the admin portal the permissions work fine. The corresponding role has corresponding access. If I use the same with REST API it fails to comply with permission which is defined in the backend. It is like both the roles are able to access both the API's.
How do I handle this? Should I implement my own permission system ignoring old one (auth_permission, auth_group_permissions, auth_user_user_permissions) used in Django or is there any workaround to use Django permissions to make this work?
You can make your permission class as below
class CustomPermission(BasePermission):
def has_permission(self, request, view):
if request.user.is_authenticated():
return True if request.has_perm('can_read') else False # or stuff similar to this
return False
And use this CustomPermission class to your APIView 's attribute.
For more information on DRF permissions visit https://www.django-rest-framework.org/api-guide/permissions/

Rolling out own permission app or modifying django permission

I am working on a project which needs a separate admin interface. The django admin interface is for the super super user, there will be companies who will sign up for our app and then they will have their own admin interface. Everything is set and done despite the permission. We want model level permission that's what Django provides.
What I did is:
class CompanyGroup(models.Model):
name = models.CharField(max_length=254)
permissions = models.ManyToManyField(Permissions)
Now this list all the permissions of the site itself. So, Should I start working on my own permission app or I can modify django Permissions to provide object level permissions for only some models.
Thanks
Try one of the several existing 'row level' / 'per object' permissions apps for Django:
http://django-guardian.readthedocs.org/en/v1.2/
http://django-object-permissions.readthedocs.org/en/latest/
...there are probably others, those are just the first two in Google
We are using django-guardian in current project at work, seems fine.
I am assuming that you need to control access to sub-sets of each model's objects, depending on which company the current user belongs to (i.e. you don't want people from Company A to see items from Company B). For this reason you need row level permissions.
You probably also need to limit the permissions of all 'company users' to only certain actions:
You do not need to create a CompanyGroup class.
Instead just enable the admin site, log in as super user and create a django.contrib.auth.models.Group which contains the global permissions applicable to company users.
then ensure when you create any new company user logins that they are added to that Group

In a django site I want to let users create other users that are tied to their accounts

I want to let a logged-in and registered user create extra user accounts that he will be the admin of. These accounts will be special "subordinate" accounts that are tied to the user creating them. He should be able to add/modify/delete these accounts kind of like the theory of how a Google apps administrator manages the accounts for his company (you are a regular user, but also create/destroy other users.)
The subordinate accounts cannot create/modify/delete accounts (except change their own password and normal user behavior.) I'm using the django auth model for all of these accounts. What is a good way to access the auth methods to add/modify/delete accounts from my own custom built webpages without using any admin code?
First, you'll need to extend your User model. Then: Add a field that represents the class of user - "subordinate" or "admin". Add a field that references the "admin" User via foreign key so you can group users by their "admin". Create views that check the class of user and allow creation, edit, deletion of "subordinate" user accounts if user class is "admin".