Skip to content

Commit

Permalink
[tests] Added django-filters multi-tenancy tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Aryamanz29 committed Mar 25, 2023
1 parent e9e8e6d commit 7c64a08
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 1 deletion.
4 changes: 3 additions & 1 deletion openwisp_users/api/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,9 @@ def filter_for_field(cls, field, name, lookup_expr='exact'):
field_name=field.name,
user_attr=cls._user_attr,
)
if isinstance(field, ManyToManyField) and field.name != 'user':
if (
isinstance(field, ManyToManyField) and field.name != 'user'
): # pragma: no cover
return DjangoOrganizationM2MFilter(
queryset=field.remote_field.model.objects.all(),
label=field.verbose_name.capitalize(),
Expand Down
1 change: 1 addition & 0 deletions tests/openwisp2/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
'drf_yasg',
'testapp',
'reversion',
'django_filters',
]

AUTH_USER_MODEL = 'openwisp_users.User'
Expand Down
52 changes: 52 additions & 0 deletions tests/testapp/tests/test_filter_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

OrganizationUser = load_model('openwisp_users', 'OrganizationUser')
OrganizationOwner = load_model('openwisp_users', 'OrganizationOwner')
Organization = load_model('openwisp_users', 'Organization')
User = get_user_model()


Expand All @@ -35,6 +36,19 @@ def setUp(self):
name='book2', organization=self._get_org('org_a'), shelf=self.shelf_b
)

def _assert_django_filters_options(self, response, shelf_a, shelf_b):
self.assertEqual(response.data[0]['id'], str(shelf_a.id))
self.assertNotContains(response, str(shelf_b.id))
# make sure only correct organization is
# visible in the django filters select options
self.assertContains(response, 'org_a</option>')
self.assertNotContains(response, 'org_b</option>')
self.assertNotContains(response, 'org_b</option>')
self.assertNotContains(response, 'default</option>')
self.assertNotContains(response, 'test org</option>')
self.assertNotContains(response, 'test-shelf-a</option>')
self.assertNotContains(response, 'test-shelf-b</option>')

def test_browsable_api_filter_manager(self):
operator = self._get_operator()
# First user is automatically owner, so created dummy
Expand Down Expand Up @@ -282,3 +296,41 @@ def test_shelf_with_read_only_org_field(self):
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data[0]['organization'], org1.pk)
self.assertNotContains(response, 'org1</option>')

def test_django_filter_by_org_membership(self):
operator = self._get_operator()
self._create_org_user(user=operator, organization=self._get_org('org_a'))
token = self._obtain_auth_token(operator)
url = reverse('test_shelf_list_member_view')
response = self.client.get(
url, {'format': 'api'}, HTTP_AUTHORIZATION=f'Bearer {token}'
)

self._assert_django_filters_options(response, self.shelf_a, self.shelf_b)

def test_django_filter_by_org_managed(self):
operator = self._get_operator()
self._create_org_user(
user=self._get_user(), is_admin=True, organization=self._get_org('org_a')
)
self._create_org_user(
user=operator, is_admin=True, organization=self._get_org('org_a')
)
token = self._obtain_auth_token(operator)
url = reverse('test_shelf_list_manager_view')
response = self.client.get(
url, {'format': 'api'}, HTTP_AUTHORIZATION=f'Bearer {token}'
)
self._assert_django_filters_options(response, self.shelf_a, self.shelf_b)

def test_django_filter_by_org_owned(self):
operator = self._get_operator()
self._create_org_user(
user=operator, is_admin=True, organization=self._get_org('org_a')
)
token = self._obtain_auth_token()
url = reverse('test_shelf_list_owner_view')
response = self.client.get(
url, {'format': 'api'}, HTTP_AUTHORIZATION=f'Bearer {token}'
)
self._assert_django_filters_options(response, self.shelf_a, self.shelf_b)
28 changes: 28 additions & 0 deletions tests/testapp/views.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import swapper
from django_filters import rest_framework as filters
from rest_framework.generics import (
ListAPIView,
ListCreateAPIView,
Expand All @@ -15,6 +16,9 @@
FilterByParentManaged,
FilterByParentMembership,
FilterByParentOwned,
FilterDjangoByOrgManaged,
FilterDjangoByOrgMembership,
FilterDjangoByOrgOwned,
)
from openwisp_users.api.permissions import (
BaseOrganizationPermission,
Expand Down Expand Up @@ -59,6 +63,12 @@ def get(self, request, *args, **kwargs):
return Response({})


class BaseShelfListFilter:
class Meta:
model = Shelf
fields = ('organization',)


class ApiMemberView(BaseGetApiView):
authentication_classes = (BearerAuthentication,)
permission_classes = (IsOrganizationMember,)
Expand Down Expand Up @@ -99,25 +109,43 @@ class ErrorOrganizationFieldView(BaseGetApiView):
organization_field = 'error__organization'


class ShelfListMemberFilter(BaseShelfListFilter, FilterDjangoByOrgMembership):
pass


class ShelfListMemberView(FilterByOrganizationMembership, ListAPIView):
authentication_classes = (BearerAuthentication,)
permission_classes = (IsOrganizationMember,)
serializer_class = ShelfSerializer
queryset = Shelf.objects.all()
filter_backends = (filters.DjangoFilterBackend,)
filterset_class = ShelfListMemberFilter


class ShelfListManagerFilter(BaseShelfListFilter, FilterDjangoByOrgManaged):
pass


class ShelfListManagerView(FilterByOrganizationManaged, ListAPIView):
authentication_classes = (BearerAuthentication,)
permission_classes = (IsOrganizationManager,)
serializer_class = ShelfSerializer
queryset = Shelf.objects.all()
filter_backends = (filters.DjangoFilterBackend,)
filterset_class = ShelfListManagerFilter


class ShelfListOwnerFilter(BaseShelfListFilter, FilterDjangoByOrgOwned):
pass


class ShelfListOwnerView(FilterByOrganizationOwned, ListAPIView):
authentication_classes = (BearerAuthentication,)
permission_classes = (IsOrganizationOwner,)
serializer_class = ShelfSerializer
queryset = Shelf.objects.all()
filter_backends = (filters.DjangoFilterBackend,)
filterset_class = ShelfListOwnerFilter


class BooksListMemberView(BookOrgMixin, FilterByParentMembership, ListCreateAPIView):
Expand Down

0 comments on commit 7c64a08

Please sign in to comment.