Skip to content

Commit 3e9ad53

Browse files
committed
[tests] Updated tests for ViewDjangoModelPermissions class
1 parent 9665dbc commit 3e9ad53

5 files changed

Lines changed: 142 additions & 15 deletions

File tree

openwisp_users/api/permissions.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def validate_membership(self, user, org):
7070
return org and (user.is_superuser or user.is_owner(org))
7171

7272

73-
class CustomDjangoModelPermissions(DjangoModelPermissions):
73+
class ViewDjangoModelPermissions(DjangoModelPermissions):
7474
def __init__(self):
7575
self.perms_map = copy.deepcopy(self.perms_map)
7676
self.perms_map['GET'] = ['%(app_label)s.view_%(model_name)s']
@@ -81,19 +81,18 @@ def has_permission(self, request, view):
8181
if getattr(view, '_ignore_model_permissions', False):
8282
return True
8383

84-
if not request.user or (
85-
not request.user.is_authenticated and self.authenticated_users_only
86-
):
84+
user = request.user
85+
if not user or (not user.is_authenticated and self.authenticated_users_only):
8786
return False
8887

8988
queryset = self._queryset(view)
9089
perms = self.get_required_permissions(request.method, queryset.model)
9190
change_perm = self.get_required_permissions('PUT', queryset.model)
9291

9392
if request.method == 'GET':
94-
if request.user.has_perms(perms) or request.user.has_perms(change_perm):
93+
if user.has_perms(perms) or user.has_perms(change_perm):
9594
return True
9695
else:
9796
return False
9897

99-
return request.user.has_perms(perms)
98+
return user.has_perms(perms)

tests/testapp/__init__.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,11 @@ def _create_shelf(self, **kwargs):
1414
s.full_clean()
1515
s.save()
1616
return s
17+
18+
def _create_template(self, **kwargs):
19+
options = dict(name='test-template')
20+
options.update(kwargs)
21+
t = self.template_model(**options)
22+
t.full_clean()
23+
t.save()
24+
return t

tests/testapp/tests/test_permission_classes.py

Lines changed: 110 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,22 @@
22
from django.contrib.auth.models import Permission
33
from django.test import TestCase
44
from django.urls import reverse
5+
from swapper import load_model
56

67
from openwisp_users.api.throttling import AuthRateThrottle
78

9+
from ..models import Template
810
from .mixins import TestMultitenancyMixin
911

1012
User = get_user_model()
13+
Group = load_model('openwisp_users', 'Group')
14+
OrganizationUser = load_model('openwisp_users', 'OrganizationUser')
1115

1216

1317
class TestPermissionClasses(TestMultitenancyMixin, TestCase):
1418
def setUp(self):
1519
AuthRateThrottle.rate = 0
20+
self.template_model = Template
1621
self.member_url = reverse('test_api_member_view')
1722
self.manager_url = reverse('test_api_manager_view')
1823
self.owner_url = reverse('test_api_owner_view')
@@ -122,28 +127,127 @@ def test_organization_field_with_errored_parent(self):
122127
self.client.get(reverse('test_error_field_view'), **auth)
123128
self.assertIn('Organization not found', str(error.exception))
124129

125-
def test_custom_django_model_permission_with_view_permission(self):
130+
def test_view_permission_with_operator(self):
131+
user = User.objects.create_user(
132+
username='operator', password='tester', email='operator@test.com'
133+
)
134+
operator_group = Group.objects.filter(name='Operator')
135+
user.groups.set(operator_group)
136+
org1 = self._get_org()
137+
OrganizationUser.objects.create(user=user, organization=org1, is_admin=True)
138+
self.client.force_login(user)
139+
token = self._obtain_auth_token()
140+
auth = dict(HTTP_AUTHORIZATION=f'Bearer {token}')
141+
t1 = self._create_template(organization=org1)
142+
with self.subTest('Get Template List'):
143+
response = self.client.get(reverse('test_template_list'), **auth)
144+
self.assertEqual(response.status_code, 403)
145+
with self.subTest('Get Template Detail'):
146+
response = self.client.get(
147+
reverse('test_template_detail', args=[t1.pk]), **auth
148+
)
149+
self.assertEqual(response.status_code, 403)
150+
151+
def test_view_permission_with_administrator(self):
152+
user = User.objects.create_user(
153+
username='operator', password='tester', email='operator@test.com'
154+
)
155+
administrator_group = Group.objects.get(name='Administrator')
156+
change_perm = Permission.objects.get(codename='change_template')
157+
administrator_group.permissions.add(change_perm)
158+
user.groups.add(administrator_group)
159+
org1 = self._get_org()
160+
OrganizationUser.objects.create(user=user, organization=org1, is_admin=True)
161+
self.client.force_login(user)
162+
token = self._obtain_auth_token()
163+
auth = dict(HTTP_AUTHORIZATION=f'Bearer {token}')
164+
t1 = self._create_template(organization=org1)
165+
with self.subTest('Get Template List'):
166+
response = self.client.get(reverse('test_template_list'), **auth)
167+
self.assertEqual(response.status_code, 200)
168+
with self.subTest('Get Template Detail'):
169+
response = self.client.get(
170+
reverse('test_template_detail', args=[t1.pk]), **auth
171+
)
172+
self.assertEqual(response.status_code, 200)
173+
permissions = administrator_group.permissions.values_list('codename', flat=True)
174+
self.assertFalse('view_template' in permissions)
175+
self.assertTrue('change_template' in permissions)
176+
177+
def test_view_permission_with_operator_having_view_perm(self):
178+
user = User.objects.create_user(
179+
username='operator', password='tester', email='operator@test.com'
180+
)
181+
operator_group = Group.objects.get(name='Operator')
182+
view_perm = Permission.objects.get(codename='view_template')
183+
operator_group.permissions.add(view_perm)
184+
user.groups.add(operator_group)
185+
org1 = self._get_org()
186+
OrganizationUser.objects.create(user=user, organization=org1, is_admin=True)
187+
self.client.force_login(user)
188+
token = self._obtain_auth_token()
189+
auth = dict(HTTP_AUTHORIZATION=f'Bearer {token}')
190+
t1 = self._create_template(organization=org1)
191+
with self.subTest('Get Template List'):
192+
response = self.client.get(reverse('test_template_list'), **auth)
193+
self.assertEqual(response.status_code, 200)
194+
with self.subTest('Get Template Detail'):
195+
response = self.client.get(
196+
reverse('test_template_detail', args=[t1.pk]), **auth
197+
)
198+
self.assertEqual(response.status_code, 200)
199+
with self.subTest('Change Template Detail'):
200+
data = {'name': 'change-template'}
201+
response = self.client.patch(
202+
reverse('test_template_detail', args=[t1.pk]), data, **auth
203+
)
204+
self.assertEqual(response.status_code, 403)
205+
with self.subTest('Delete Template'):
206+
response = self.client.delete(
207+
reverse('test_template_detail', args=[t1.pk]), **auth
208+
)
209+
self.assertEqual(response.status_code, 403)
210+
211+
def test_view_django_model_permission_with_view_perm(self):
126212
user = User.objects.create_user(
127213
username='operator', password='tester', email='operator@test.com'
128214
)
129215
user_permissions = Permission.objects.filter(codename='view_template')
130216
user.user_permissions.add(*user_permissions)
131217
user.organizations_dict # force caching
218+
org1 = self._get_org()
219+
OrganizationUser.objects.create(user=user, organization=org1, is_admin=True)
132220
self.client.force_login(user)
133221
token = self._obtain_auth_token()
134222
auth = dict(HTTP_AUTHORIZATION=f'Bearer {token}')
135-
response = self.client.get(reverse('test_template_list'), **auth)
136-
self.assertEqual(response.status_code, 200)
223+
t1 = self._create_template(organization=org1)
224+
with self.subTest('Get Template List'):
225+
response = self.client.get(reverse('test_template_list'), **auth)
226+
self.assertEqual(response.status_code, 200)
227+
with self.subTest('Get Template Detail'):
228+
response = self.client.get(
229+
reverse('test_template_detail', args=[t1.pk]), **auth
230+
)
231+
self.assertEqual(response.status_code, 200)
137232

138-
def test_custom_django_model_permission_with_change_permission(self):
233+
def test_view_django_model_permission_with_change_perm(self):
139234
user = User.objects.create_user(
140235
username='operator', password='tester', email='operator@test.com'
141236
)
142237
user_permissions = Permission.objects.filter(codename='change_template')
143238
user.user_permissions.add(*user_permissions)
144239
user.organizations_dict # force caching
240+
org1 = self._get_org()
241+
OrganizationUser.objects.create(user=user, organization=org1, is_admin=True)
145242
self.client.force_login(user)
146243
token = self._obtain_auth_token()
147244
auth = dict(HTTP_AUTHORIZATION=f'Bearer {token}')
148-
response = self.client.get(reverse('test_template_list'), **auth)
149-
self.assertEqual(response.status_code, 200)
245+
t1 = self._create_template(organization=org1)
246+
with self.subTest('Get Template List'):
247+
response = self.client.get(reverse('test_template_list'), **auth)
248+
self.assertEqual(response.status_code, 200)
249+
with self.subTest('Get Template Detail'):
250+
response = self.client.get(
251+
reverse('test_template_detail', args=[t1.pk]), **auth
252+
)
253+
self.assertEqual(response.status_code, 200)

tests/testapp/urls.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,5 @@
4848
name='test_shelf_list_unauthorized_view',
4949
),
5050
path('template/', views.template_list, name='test_template_list',),
51+
path('template/<int:pk>/', views.template_detail, name='test_template_detail',),
5152
]

tests/testapp/views.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
import swapper
2-
from rest_framework.generics import ListAPIView, ListCreateAPIView
2+
from rest_framework.generics import (
3+
ListAPIView,
4+
ListCreateAPIView,
5+
RetrieveUpdateDestroyAPIView,
6+
)
37
from rest_framework.response import Response
48
from rest_framework.views import APIView
59

@@ -14,10 +18,10 @@
1418
)
1519
from openwisp_users.api.permissions import (
1620
BaseOrganizationPermission,
17-
CustomDjangoModelPermissions,
1821
IsOrganizationManager,
1922
IsOrganizationMember,
2023
IsOrganizationOwner,
24+
ViewDjangoModelPermissions,
2125
)
2226

2327
from .models import Book, Config, Shelf, Template
@@ -172,7 +176,17 @@ class TemplateListCreateView(ListCreateAPIView):
172176
authentication_classes = (BearerAuthentication,)
173177
permission_classes = (
174178
IsOrganizationMember,
175-
CustomDjangoModelPermissions,
179+
ViewDjangoModelPermissions,
180+
)
181+
queryset = Template.objects.all()
182+
183+
184+
class TemplateDetailView(FilterByOrganizationManaged, RetrieveUpdateDestroyAPIView):
185+
serializer_class = TemplateSerializer
186+
authentication_classes = (BearerAuthentication,)
187+
permission_classes = (
188+
IsOrganizationMember,
189+
ViewDjangoModelPermissions,
176190
)
177191
queryset = Template.objects.all()
178192

@@ -192,3 +206,4 @@ class TemplateListCreateView(ListCreateAPIView):
192206
shelf_list_manager_view = ShelfListManagerView.as_view()
193207
shelf_list_owner_view = ShelfListOwnerView.as_view()
194208
template_list = TemplateListCreateView.as_view()
209+
template_detail = TemplateDetailView.as_view()

0 commit comments

Comments
 (0)