[feature] Implemented view permissions by extending DjangoModelPermissions class #249#251
Conversation
DjangoModelPermissions class #249
openwisp_users/api/permissions.py
Outdated
| if request.method == 'GET': | ||
| if request.user.has_perms(perms) or request.user.has_perms(change_perm): | ||
| return True | ||
| else: | ||
| return False |
There was a problem hiding this comment.
Did not handled the case of super user becasue superuser by default has all the permissions.
There was a problem hiding this comment.
I think you can add a check at the top of the function stating:
if user.is_superuser:
return True
They are allowed to do anything regardless of any permission (this check is there in other has_permission functions too)!
P.S: Not sure if this would be required, please test! 😄
There was a problem hiding this comment.
@atb00ker I am trying to implement this in more generic way, cause am thinking of opening a similar PR in DRF repo once this gets merged here.
By default superuser has all permissions i.e., it can do anything it wants. suppose manually someone removes all the permissions for any specific model for superuser. Then in that case this would not work, since we will return True if it;s a super user, so that case will fail.
What do you think?
There was a problem hiding this comment.
To the best of my knowledge, removing permissions from superuser is an anti-pattern, but I understand your point.
- We should look at existing DRF functions and implement it in a similar way.
- I'll also wait for @nemesisdesign check this! 😄
atb00ker
left a comment
There was a problem hiding this comment.
This looks good to me, small comments:
openwisp_users/api/permissions.py
Outdated
| if request.method == 'GET': | ||
| if request.user.has_perms(perms) or request.user.has_perms(change_perm): | ||
| return True | ||
| else: | ||
| return False |
There was a problem hiding this comment.
I think you can add a check at the top of the function stating:
if user.is_superuser:
return True
They are allowed to do anything regardless of any permission (this check is there in other has_permission functions too)!
P.S: Not sure if this would be required, please test! 😄
|
Quoting from the issue #249
|
nemesifier
left a comment
There was a problem hiding this comment.
Looks on the right track! I'll need to test it.
But definitely please go ahead with the PR to Django REST Framework, hopefully we can get something similar or better merged there.
okraits
left a comment
There was a problem hiding this comment.
Looks fine. No objections from me.
atb00ker
left a comment
There was a problem hiding this comment.
I think this is looking good, small improvement in the tests.
| user = User.objects.create_user( | ||
| username='operator', password='tester', email='[email protected]' | ||
| ) | ||
| operator_group = Group.objects.filter(name='Operator') | ||
| user.groups.set(operator_group) |
There was a problem hiding this comment.
Just FYI, I think there are functions for common actions. Like _create_operator.
These should be inherited and used! 😄
There was a problem hiding this comment.
Hey, @atb00ker Yes, I tried to use it but with this function, the user gets all the permissions without being in the operator group, and here we only needed testapp.view_template permission.
| operator_group = Group.objects.filter(name='Operator') | ||
| user.groups.set(operator_group) | ||
| org1 = self._get_org() | ||
| OrganizationUser.objects.create(user=user, organization=org1, is_admin=True) |
There was a problem hiding this comment.
atb00ker
left a comment
There was a problem hiding this comment.
Functional Test:
- superuser has access
- non-su without view permission & org manager doesn't have access
- non-su with view permission & not org manager has access but sees nothing
- non-su with view permission & org manager can see temp for their obj. (not shared obj)
There was a problem hiding this comment.
Great work @ManishShah120 @atb00ker! 👍
Missing:
- Documentation (please add it near to the other sections related to DRF)
- Code simplification (see below)
openwisp_users/api/permissions.py
Outdated
| if user.has_perms(perms) or user.has_perms(change_perm): | ||
| return True | ||
| else: | ||
| return False |
There was a problem hiding this comment.
what about:
# user must have either view permission or change permission
return user.has_perms(perms) or user.has_perms(change_perm)| self.client.force_login(user) | ||
| token = self._obtain_auth_token() | ||
| auth = dict(HTTP_AUTHORIZATION=f'Bearer {token}') | ||
| t1 = self._create_template(organization=org1) |
There was a problem hiding this comment.
the first lines of each tests look really similar, please try to make a private helper method which prepares the data needed for the test, so we can make the actual test code shorter and easier to read.
There was a problem hiding this comment.
Done, Please have a look. 👍
openwisp_users/api/permissions.py
Outdated
| return org and (user.is_superuser or user.is_owner(org)) | ||
|
|
||
|
|
||
| class ViewDjangoModelPermissions(DjangoModelPermissions): |
There was a problem hiding this comment.
we could call this simply DjangoModelPermissions
openwisp_users/api/permissions.py
Outdated
| @@ -1,5 +1,5 @@ | |||
| from django.utils.translation import gettext_lazy as _ | |||
| from rest_framework.permissions import BasePermission | |||
| from rest_framework.permissions import BasePermission, DjangoModelPermissions | |||
There was a problem hiding this comment.
here you'd import it as BaseDjangoModelPermissions
| user = self._get_user() | ||
| operator_group = Group.objects.filter(name='Operator') | ||
| user.groups.set(operator_group) |
There was a problem hiding this comment.
Doesn't _get_operator() help here?
Closes #249