From b3eac3666b6cfa59f6667f668560d2ec9c6a9f52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80=20=D0=93=D0=BB=D0=B0?= =?UTF-8?q?=D0=B4=D0=BA=D0=B8=D1=85?= Date: Mon, 14 Oct 2019 14:48:13 +0300 Subject: [PATCH] Standart user, guest. --- .../migrations/0011_merge_20191014_0839.py | 14 +++ apps/comment/permissions.py | 28 ----- apps/comment/tests.py | 103 +---------------- apps/comment/views/back.py | 2 +- apps/utils/permissions.py | 63 ++++++++++- apps/utils/tests/__init__.py | 0 apps/utils/tests/tests_json_field.py | 37 +++++++ apps/utils/tests/tests_permissions.py | 104 ++++++++++++++++++ .../{tests.py => tests/tests_translated.py} | 38 ------- 9 files changed, 220 insertions(+), 169 deletions(-) create mode 100644 apps/account/migrations/0011_merge_20191014_0839.py delete mode 100644 apps/comment/permissions.py create mode 100644 apps/utils/tests/__init__.py create mode 100644 apps/utils/tests/tests_json_field.py create mode 100644 apps/utils/tests/tests_permissions.py rename apps/utils/{tests.py => tests/tests_translated.py} (80%) diff --git a/apps/account/migrations/0011_merge_20191014_0839.py b/apps/account/migrations/0011_merge_20191014_0839.py new file mode 100644 index 00000000..653f39b7 --- /dev/null +++ b/apps/account/migrations/0011_merge_20191014_0839.py @@ -0,0 +1,14 @@ +# Generated by Django 2.2.4 on 2019-10-14 08:39 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('account', '0009_auto_20191011_1123'), + ('account', '0010_user_password_confirmed'), + ] + + operations = [ + ] diff --git a/apps/comment/permissions.py b/apps/comment/permissions.py deleted file mode 100644 index 6d691c07..00000000 --- a/apps/comment/permissions.py +++ /dev/null @@ -1,28 +0,0 @@ -from rest_framework import permissions -from account.models import UserRole, Role, User - - -class IsCommentModerator(permissions.IsAuthenticatedOrReadOnly): - """ - Object-level permission to only allow owners of an object to edit it. - Assumes the model instance has an `owner` attribute. - """ - - def has_object_permission(self, request, view, obj): - # Read permissions are allowed to any request, - # so we'll always allow GET, HEAD or OPTIONS requests. - if request.method in permissions.SAFE_METHODS or \ - obj.user == request.user or request.user.is_superuser: - return True - - # Must have role - role = Role.objects.filter(role=Role.COMMENTS_MODERATOR, - country__languages__id=obj.language_id)\ - .first() # 'Comments moderator' - - is_access = UserRole.objects.filter(user=request.user, role=role).exists() - if obj.user != request.user and is_access: - return True - - return False - diff --git a/apps/comment/tests.py b/apps/comment/tests.py index 949ba597..6c6c3d6a 100644 --- a/apps/comment/tests.py +++ b/apps/comment/tests.py @@ -1,64 +1,12 @@ -from rest_framework.test import APITestCase from rest_framework import status -from authorization.tests.tests_authorization import get_tokens_for_user -from django.urls import reverse -from django.contrib.contenttypes.models import ContentType from http.cookies import SimpleCookie -from location.models import Country -from account.models import Role, User, UserRole -from comment.models import Comment -from translation.models import Language +from account.models import User +from utils.tests.tests_permissions import BasePermissionTests -class CommentModeratorPermissionTests(APITestCase): +class CommentModeratorPermissionTests(BasePermissionTests): def setUp(self): - - self.lang = Language.objects.create( - title='Russia', - locale='ru-RU' - ) - self.lang.save() - - self.country_ru = Country.objects.create( - name='{"ru-RU":"Russia"}', - code='23', - low_price=15, - high_price=150000, - ) - self.country_ru.languages.add(self.lang) - self.country_ru.save() - - self.role = Role.objects.create( - role=2, - country=self.country_ru - ) - self.role.save() - - self.moderator = User.objects.create_user(username='moderator', - email='moderator@mail.com', - password='passwordmoderator') - - self.userRole = UserRole.objects.create( - user=self.moderator, - role=self.role - ) - self.userRole.save() - - content_type = ContentType.objects.get(app_label='location', model='country') - - self.user_test = get_tokens_for_user() - self.comment = Comment.objects.create(text='Test comment', mark=1, - user=self.user_test["user"], - object_id= self.country_ru.pk, - content_type_id=content_type.id, - language=self.lang - ) - self.comment.save() - self.url = reverse('back:comment:comment-crud', kwargs={"id": self.comment.id}) - - def test_get(self): - response = self.client.get(self.url, format='json') - self.assertEqual(response.status_code, status.HTTP_200_OK) + super().setUp() def test_put_moderator(self): tokens = User.create_jwt_tokens(self.moderator) @@ -76,48 +24,5 @@ class CommentModeratorPermissionTests(APITestCase): response = self.client.put(self.url, data=data, format='json') self.assertEqual(response.status_code, status.HTTP_200_OK) - def test_put_other_user(self): - other_user = User.objects.create_user(username='test', - email='test@mail.com', - password='passwordtest') - - tokens = User.create_jwt_tokens(other_user) - - self.client.cookies = SimpleCookie( - {'access_token': tokens.get('access_token'), - 'refresh_token': tokens.get('access_token')}) - - data = { - "id": self.comment.id, - "text": "test text moderator", - "mark": 1, - "user": other_user.id - } - - response = self.client.put(self.url, data=data, format='json') - self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - - def test_put_super_user(self): - super_user = User.objects.create_user(username='super', - email='super@mail.com', - password='passwordtestsuper', - is_superuser=True) - - tokens = User.create_jwt_tokens(super_user) - - self.client.cookies = SimpleCookie( - {'access_token': tokens.get('access_token'), - 'refresh_token': tokens.get('access_token')}) - - data = { - "id": self.comment.id, - "text": "test text moderator", - "mark": 1, - "user": super_user.id - } - - response = self.client.put(self.url, data=data, format='json') - self.assertEqual(response.status_code, status.HTTP_200_OK) - diff --git a/apps/comment/views/back.py b/apps/comment/views/back.py index 77edfa97..7f066f30 100644 --- a/apps/comment/views/back.py +++ b/apps/comment/views/back.py @@ -1,7 +1,7 @@ from rest_framework import generics, permissions from comment.serializers import back as serializers from comment import models -from comment.permissions import IsCommentModerator +from utils.permissions import IsCommentModerator class CommentLstView(generics.ListCreateAPIView): diff --git a/apps/utils/permissions.py b/apps/utils/permissions.py index 09b24ecd..2d406850 100644 --- a/apps/utils/permissions.py +++ b/apps/utils/permissions.py @@ -1,12 +1,13 @@ """Project custom permissions""" -from rest_framework.permissions import BasePermission +from rest_framework import permissions from rest_framework_simplejwt.tokens import AccessToken +from account.models import UserRole, Role from authorization.models import JWTRefreshToken from utils.tokens import GMRefreshToken -class IsAuthenticatedAndTokenIsValid(BasePermission): +class IsAuthenticatedAndTokenIsValid(permissions.BasePermission): """ Check if user has a valid token and authenticated """ @@ -24,7 +25,7 @@ class IsAuthenticatedAndTokenIsValid(BasePermission): return False -class IsRefreshTokenValid(BasePermission): +class IsRefreshTokenValid(permissions.BasePermission): """ Check if user has a valid refresh token and authenticated """ @@ -38,3 +39,59 @@ class IsRefreshTokenValid(BasePermission): return refresh_token_qs.exists() else: return False + + def has_object_permission(self, request, view, obj): + # Read permissions are allowed to any request, + # so we'll always allow GET, HEAD or OPTIONS requests. + if request.method in permissions.SAFE_METHODS or \ + obj.user == request.user or request.user.is_superuser: + return True + return False + + +class IsGuest(permissions.IsAuthenticatedOrReadOnly): + """ + Object-level permission to only allow owners of an object to edit it. + """ + def has_object_permission(self, request, view, obj): + if request.method in permissions.SAFE_METHODS: + return True + + return False + + +class IsStandardUser(IsGuest): + """ + Object-level permission to only allow owners of an object to edit it. + Assumes the model instance has an `owner` attribute. + """ + def has_object_permission(self, request, view, obj): + # Read permissions are allowed to any request + if super().has_object_permission(request, view, obj) or\ + obj.user == request.user or request.user.is_superuser: + return True + return False + + +class IsCommentModerator(IsStandardUser): + """ + Object-level permission to only allow owners of an object to edit it. + Assumes the model instance has an `owner` attribute. + """ + + def has_object_permission(self, request, view, obj): + # Read permissions are allowed to any request. + + if super().has_object_permission(request, view, obj): + return True + + # Must have role + role = Role.objects.filter(role=Role.COMMENTS_MODERATOR, + country__languages__id=obj.language_id)\ + .first() # 'Comments moderator' + + is_access = UserRole.objects.filter(user=request.user, role=role).exists() + if obj.user != request.user and is_access: + return True + + return False diff --git a/apps/utils/tests/__init__.py b/apps/utils/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/utils/tests/tests_json_field.py b/apps/utils/tests/tests_json_field.py new file mode 100644 index 00000000..c0207def --- /dev/null +++ b/apps/utils/tests/tests_json_field.py @@ -0,0 +1,37 @@ +from django.test import TestCase +from translation.models import Language +from django.core import exceptions +from utils.serializers import validate_tjson + + +class ValidJSONTest(TestCase): + + def test_valid_json(self): + lang = Language.objects.create(title='English', locale='en-GB') + lang.save() + + data = 'str' + + with self.assertRaises(exceptions.ValidationError) as err: + validate_tjson(data) + + self.assertEqual(err.exception.code, 'invalid_json') + + data = { + "string": "value" + } + + with self.assertRaises(exceptions.ValidationError) as err: + validate_tjson(data) + + self.assertEqual(err.exception.code, 'invalid_translated_keys') + + data = { + "en-GB": "English" + } + + try: + validate_tjson(data) + self.assertTrue(True) + except exceptions.ValidationError: + self.assert_(False, "Test json translated FAILED") \ No newline at end of file diff --git a/apps/utils/tests/tests_permissions.py b/apps/utils/tests/tests_permissions.py new file mode 100644 index 00000000..1e1e0e81 --- /dev/null +++ b/apps/utils/tests/tests_permissions.py @@ -0,0 +1,104 @@ +from rest_framework.test import APITestCase +from rest_framework import status +from authorization.tests.tests_authorization import get_tokens_for_user +from django.urls import reverse +from django.contrib.contenttypes.models import ContentType +from http.cookies import SimpleCookie +from location.models import Country +from account.models import Role, User, UserRole +from comment.models import Comment +from translation.models import Language + + +class BasePermissionTests(APITestCase): + def setUp(self): + + self.lang = Language.objects.create( + title='Russia', + locale='ru-RU' + ) + self.lang.save() + + self.country_ru = Country.objects.create( + name='{"ru-RU":"Russia"}', + code='23', + low_price=15, + high_price=150000, + ) + self.country_ru.languages.add(self.lang) + self.country_ru.save() + + self.role = Role.objects.create( + role=2, + country=self.country_ru + ) + self.role.save() + + self.moderator = User.objects.create_user(username='moderator', + email='moderator@mail.com', + password='passwordmoderator') + + self.userRole = UserRole.objects.create( + user=self.moderator, + role=self.role + ) + self.userRole.save() + + content_type = ContentType.objects.get(app_label='location', model='country') + + self.user_test = get_tokens_for_user() + self.comment = Comment.objects.create(text='Test comment', mark=1, + user=self.user_test["user"], + object_id= self.country_ru.pk, + content_type_id=content_type.id, + language=self.lang + ) + self.comment.save() + self.url = reverse('back:comment:comment-crud', kwargs={"id": self.comment.id}) + + def test_get(self): + response = self.client.get(self.url, format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + + def test_put_other_user(self): + other_user = User.objects.create_user(username='test', + email='test@mail.com', + password='passwordtest') + + tokens = User.create_jwt_tokens(other_user) + + self.client.cookies = SimpleCookie( + {'access_token': tokens.get('access_token'), + 'refresh_token': tokens.get('access_token')}) + + data = { + "id": self.comment.id, + "text": "test text moderator", + "mark": 1, + "user": other_user.id + } + + response = self.client.put(self.url, data=data, format='json') + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + + def test_put_super_user(self): + super_user = User.objects.create_user(username='super', + email='super@mail.com', + password='passwordtestsuper', + is_superuser=True) + + tokens = User.create_jwt_tokens(super_user) + + self.client.cookies = SimpleCookie( + {'access_token': tokens.get('access_token'), + 'refresh_token': tokens.get('access_token')}) + + data = { + "id": self.comment.id, + "text": "test text moderator", + "mark": 1, + "user": super_user.id + } + + response = self.client.put(self.url, data=data, format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) diff --git a/apps/utils/tests.py b/apps/utils/tests/tests_translated.py similarity index 80% rename from apps/utils/tests.py rename to apps/utils/tests/tests_translated.py index 0eaf343d..8f5caaaf 100644 --- a/apps/utils/tests.py +++ b/apps/utils/tests/tests_translated.py @@ -8,11 +8,6 @@ from http.cookies import SimpleCookie from account.models import User from news.models import News, NewsType -from django.test import TestCase -from translation.models import Language -from django.core import exceptions -from .serializers import validate_tjson - from establishment.models import Establishment, EstablishmentType, Employee @@ -125,36 +120,3 @@ class BaseAttributeTests(BaseTestCase): employee.refresh_from_db() self.assertEqual(modify_user, employee.modified_by) self.assertEqual(self.user, employee.created_by) - - -class ValidJSONTest(TestCase): - - def test_valid_json(self): - lang = Language.objects.create(title='English', locale='en-GB') - lang.save() - - data = 'str' - - with self.assertRaises(exceptions.ValidationError) as err: - validate_tjson(data) - - self.assertEqual(err.exception.code, 'invalid_json') - - data = { - "string": "value" - } - - with self.assertRaises(exceptions.ValidationError) as err: - validate_tjson(data) - - self.assertEqual(err.exception.code, 'invalid_translated_keys') - - data = { - "en-GB": "English" - } - - try: - validate_tjson(data) - self.assertTrue(True) - except exceptions.ValidationError: - self.assert_(False, "Test json translated FAILED") \ No newline at end of file