-
-
Notifications
You must be signed in to change notification settings - Fork 74
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[feature] Implemented view permissions by extending DjangoModelPermissions
class #249
#251
[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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did not handled the case of super user becasue superuser by default has all the permissions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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! 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks fine. No objections from me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here. Find function here: https://github.com/openwisp/openwisp-users/blob/master/openwisp_users/tests/utils.py#L128
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, Please have a look. 👍
openwisp_users/api/permissions.py
Outdated
@@ -66,3 +66,37 @@ class IsOrganizationOwner(BaseOrganizationPermission): | |||
|
|||
def validate_membership(self, user, org): | |||
return org and (user.is_superuser or user.is_owner(org)) | |||
|
|||
|
|||
class ViewDjangoModelPermissions(DjangoModelPermissions): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here you'd import it as BaseDjangoModelPermissions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! 👍
user = self._get_user() | ||
operator_group = Group.objects.filter(name='Operator') | ||
user.groups.set(operator_group) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't _get_operator()
help here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No @atb00ker.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
Closes #249