diff --git a/back_latienda/permissions.py b/back_latienda/permissions.py index 9bb10d0..1d1cf51 100644 --- a/back_latienda/permissions.py +++ b/back_latienda/permissions.py @@ -43,10 +43,14 @@ class IsSiteAdmin(permissions.BasePermission): admin_role = 'SITE_ADMIN' def has_object_permission(self, request, view, obj): - return request.user.role == self.admin_role + if request.user.is_authenticated: + return request.user.role == self.admin_role + return False def has_permission(self, request, view): - return request.user.role == self.admin_role + if request.user.is_authenticated: + return request.user.role == self.admin_role + return False class ReadOnly(permissions.BasePermission): diff --git a/back_latienda/routers.py b/back_latienda/routers.py index b734217..ef0d46c 100644 --- a/back_latienda/routers.py +++ b/back_latienda/routers.py @@ -2,7 +2,7 @@ from rest_framework import routers from core.views import CustomUserViewSet from companies.views import CompanyViewSet, MyCompanyViewSet -from products.views import ProductViewSet, MyProductsViewSet +from products.views import ProductViewSet, MyProductsViewSet, AdminProductsViewSet from history.views import HistorySyncViewSet from stats.views import StatsLogViewSet @@ -16,6 +16,7 @@ router.register('companies', CompanyViewSet, basename='company') router.register('my_company', MyCompanyViewSet, basename='my-company') router.register('products', ProductViewSet, basename='product') router.register('my_products', MyProductsViewSet, basename='my-products') +router.register('admin_products', AdminProductsViewSet, basename='admin-product') router.register('history', HistorySyncViewSet, basename='history') router.register('stats', StatsLogViewSet, basename='stats') diff --git a/products/tests.py b/products/tests.py index 7aa43de..d15e5c6 100644 --- a/products/tests.py +++ b/products/tests.py @@ -979,6 +979,171 @@ class MyProductsViewTest(APITestCase): self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) +class AdminProductViewSet(APITestCase): + + def setUp(self): + """Tests setup + """ + self.endpoint = '/api/v1/admin_products/' + self.factory = ProductFactory + self.model = Product + # create user + self.email = f"user@mail.com" + self.password = ''.join(random.choices(string.ascii_uppercase, k = 10)) + self.user = CustomUserFactory(email=self.email, is_active=True) + self.user.set_password(self.password) + # self.user.role = 'SITE_ADMIN' + self.user.save() + + def test_anon_user_cannot_access(self): + instance = self.factory() + url = f"{self.endpoint}{instance.id}/" + # GET + response = self.client.get(self.endpoint) + # check response + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + # POST + response = self.client.post(self.endpoint, data={}) + # check response + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + # PUT + response = self.client.get(url, data={}) + # check response + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + # delete + response = self.client.get(url) + # check response + self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) + + def test_auth_user_cannot_access(self): + # Authenticate + token = get_tokens_for_user(self.user) + self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {token['access']}") + + instance = self.factory() + url = f"{self.endpoint}{instance.id}/" + # GET + response = self.client.get(self.endpoint) + # check response + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + # POST + response = self.client.post(self.endpoint, data={}) + # check response + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + # PUT + response = self.client.get(url, data={}) + # check response + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + # delete + response = self.client.get(url) + # check response + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + + def test_admin_user_can_list(self): + # make user site amdin + self.user.role = 'SITE_ADMIN' + self.user.save() + + # Authenticate + token = get_tokens_for_user(self.user) + self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {token['access']}") + + # create instances + instance = [self.factory() for i in range(random.randint(1,5))] + # query endpoint + response = self.client.get(self.endpoint) + + # assertions + self.assertEquals(response.status_code, 200) + payload = response.json() + self.assertEquals(len(instance), len(payload)) + + def test_admin_user_can_get_details(self): + # make user site amdin + self.user.role = 'SITE_ADMIN' + self.user.save() + + # Authenticate + token = get_tokens_for_user(self.user) + self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {token['access']}") + + # create instances + instance = self.factory() + url = f"{self.endpoint}{instance.id}/" + # query endpoint + response = self.client.get(url) + + # assertions + self.assertEquals(response.status_code, 200) + payload = response.json() + self.assertEquals(instance.id, payload['id']) + + def test_admin_can_create_instance(self): + # make user site amdin + self.user.role = 'SITE_ADMIN' + self.user.save() + + # Authenticate + token = get_tokens_for_user(self.user) + self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {token['access']}") + + # create instances + data = { + 'name': 'test_product_name', + } + # query endpoint + response = self.client.post(self.endpoint, data=data) + + # assertions + self.assertEquals(response.status_code, 201) + payload = response.json() + self.assertEquals(data['name'], payload['name']) + + def test_admin_can_update_instance(self): + # make user site amdin + self.user.role = 'SITE_ADMIN' + self.user.save() + + # Authenticate + token = get_tokens_for_user(self.user) + self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {token['access']}") + + # create instance + instance = self.factory() + url = f"{self.endpoint}{instance.id}/" + + # data + data = { + 'name': 'test_product_name', + } + # query endpoint + response = self.client.put(url, data=data) + + # assertions + self.assertEquals(response.status_code, 200) + payload = response.json() + self.assertEquals(data['name'], payload['name']) + + def test_admin_can_delete_instance(self): + # make user site amdin + self.user.role = 'SITE_ADMIN' + self.user.save() + + # Authenticate + token = get_tokens_for_user(self.user) + self.client.credentials(HTTP_AUTHORIZATION=f"Bearer {token['access']}") + + # create instance + instance = self.factory() + url = f"{self.endpoint}{instance.id}/" + + # query endpoint + response = self.client.delete(url) + + # assertions + self.assertEquals(response.status_code, 204) + + class FindRelatedProductsTest(APITestCase): def setUp(self): diff --git a/products/views.py b/products/views.py index 84c2340..537cce9 100644 --- a/products/views.py +++ b/products/views.py @@ -16,13 +16,13 @@ from rest_framework.filters import OrderingFilter from django_filters.rest_framework import DjangoFilterBackend import requests -from products.models import Product, CategoryTag -from products.serializers import ProductSerializer, TagFilterSerializer, SearchResultSerializer -from companies.models import Company from history.models import HistorySync from dal import autocomplete -from back_latienda.permissions import IsCreator +from products.models import Product, CategoryTag +from products.serializers import ProductSerializer, TagFilterSerializer, SearchResultSerializer +from companies.models import Company +from back_latienda.permissions import IsCreator, IsSiteAdmin from .utils import extract_search_filters, find_related_products_v3, find_related_products_v6, product_loader from utils.tag_serializers import TaggitSerializer from utils.tag_filters import ProductTagFilter, ProductOrderFilter @@ -53,6 +53,8 @@ class ProductViewSet(viewsets.ModelViewSet): class MyProductsViewSet(viewsets.ModelViewSet): + """ Allows user to get all products where user is product creator + """ model = Product serializer_class = ProductSerializer permission_classes = [IsAuthenticated] @@ -64,6 +66,17 @@ class MyProductsViewSet(viewsets.ModelViewSet): serializer.save(creator=self.request.user) +class AdminProductsViewSet(viewsets.ModelViewSet): + """ Allows user with role 'SITE_ADMIN' to access all product instances + """ + queryset = Product.objects.all() + serializer_class = ProductSerializer + permission_classes = [IsSiteAdmin] + + def perform_create(self, serializer): + serializer.save(creator=self.request.user) + + @api_view(['POST',]) @permission_classes([IsAuthenticated,]) def load_coop_products(request):