Merge branch 'feature/fix_role' into 'develop'

Feature/fix role

See merge request gm/gm-backend!76
This commit is contained in:
d.kuzmenko 2019-10-25 13:06:38 +00:00
commit e9683ed668
9 changed files with 236 additions and 36 deletions

View File

@ -6,4 +6,4 @@ from rest_framework import serializers
class CommentBaseSerializer(serializers.ModelSerializer): class CommentBaseSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = models.Comment model = models.Comment
fields = ('id', 'text', 'mark', 'user') fields = ('id', 'text', 'mark', 'user', 'object_id', 'content_type')

View File

@ -30,18 +30,48 @@ class CommentModeratorPermissionTests(BasePermissionTests):
) )
self.userRole.save() self.userRole.save()
content_type = ContentType.objects.get(app_label='location', model='country') self.content_type = ContentType.objects.get(app_label='location', model='country')
self.user_test = get_tokens_for_user() self.user_test = get_tokens_for_user()
self.comment = Comment.objects.create(text='Test comment', mark=1, self.comment = Comment.objects.create(text='Test comment', mark=1,
user=self.user_test["user"], user=self.user_test["user"],
object_id= self.country_ru.pk, object_id=self.country_ru.pk,
content_type_id=content_type.id, content_type_id=self.content_type.id,
country=self.country_ru country=self.country_ru
) )
self.comment.save() self.comment.save()
self.url = reverse('back:comment:comment-crud', kwargs={"id": self.comment.id}) self.url = reverse('back:comment:comment-crud', kwargs={"id": self.comment.id})
def test_post(self):
self.url = reverse('back:comment:comment-list-create')
comment = {
"text": "Test comment POST",
"user": self.user_test["user"].id,
"object_id": self.country_ru.pk,
"content_type": self.content_type.id,
"country_id": self.country_ru.id
}
response = self.client.post(self.url, format='json', data=comment)
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
comment = {
"text": "Test comment POST moder",
"user": self.moderator.id,
"object_id": self.country_ru.id,
"content_type": self.content_type.id,
"country_id": self.country_ru.id
}
tokens = User.create_jwt_tokens(self.moderator)
self.client.cookies = SimpleCookie(
{'access_token': tokens.get('access_token'),
'refresh_token': tokens.get('access_token')})
response = self.client.post(self.url, format='json', data=comment)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
def test_put_moderator(self): def test_put_moderator(self):
tokens = User.create_jwt_tokens(self.moderator) tokens = User.create_jwt_tokens(self.moderator)
self.client.cookies = SimpleCookie( self.client.cookies = SimpleCookie(
@ -52,7 +82,9 @@ class CommentModeratorPermissionTests(BasePermissionTests):
"id": self.comment.id, "id": self.comment.id,
"text": "test text moderator", "text": "test text moderator",
"mark": 1, "mark": 1,
"user": self.moderator.id "user": self.moderator.id,
"object_id": self.comment.country_id,
"content_type": self.content_type.id
} }
response = self.client.put(self.url, data=data, format='json') response = self.client.put(self.url, data=data, format='json')
@ -60,7 +92,7 @@ class CommentModeratorPermissionTests(BasePermissionTests):
def test_get(self): def test_get(self):
response = self.client.get(self.url, format='json') response = self.client.get(self.url, format='json')
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_put_other_user(self): def test_put_other_user(self):
other_user = User.objects.create_user(username='test', other_user = User.objects.create_user(username='test',
@ -99,9 +131,10 @@ class CommentModeratorPermissionTests(BasePermissionTests):
"id": self.comment.id, "id": self.comment.id,
"text": "test text moderator", "text": "test text moderator",
"mark": 1, "mark": 1,
"user": super_user.id "user": super_user.id,
"object_id": self.country_ru.id,
"content_type": self.content_type.id,
} }
response = self.client.put(self.url, data=data, format='json') response = self.client.put(self.url, data=data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)

View File

@ -8,12 +8,13 @@ class CommentLstView(generics.ListCreateAPIView):
"""Comment list create view.""" """Comment list create view."""
serializer_class = serializers.CommentBaseSerializer serializer_class = serializers.CommentBaseSerializer
queryset = models.Comment.objects.all() queryset = models.Comment.objects.all()
permission_classes = [permissions.IsAuthenticatedOrReadOnly,] permission_classes = [permissions.IsAuthenticatedOrReadOnly| IsCommentModerator|IsCountryAdmin]
class CommentRUDView(generics.RetrieveUpdateDestroyAPIView): class CommentRUDView(generics.RetrieveUpdateDestroyAPIView):
"""Comment RUD view.""" """Comment RUD view."""
serializer_class = serializers.CommentBaseSerializer serializer_class = serializers.CommentBaseSerializer
queryset = models.Comment.objects.all() queryset = models.Comment.objects.all()
permission_classes = [IsCountryAdmin|IsCommentModerator]
permission_classes = [IsCountryAdmin | IsCommentModerator]
lookup_field = 'id' lookup_field = 'id'

View File

@ -16,4 +16,5 @@ class CountryBackSerializer(common.CountrySerializer):
'code', 'code',
'svg_image', 'svg_image',
'name', 'name',
'country_id'
] ]

View File

@ -20,6 +20,7 @@ class BaseTestCase(APITestCase):
username=self.username, email=self.email, password=self.password) username=self.username, email=self.email, password=self.password)
tokens = User.create_jwt_tokens(self.user) tokens = User.create_jwt_tokens(self.user)
self.client.cookies = SimpleCookie( self.client.cookies = SimpleCookie(
{'access_token': tokens.get('access_token'), {'access_token': tokens.get('access_token'),
'refresh_token': tokens.get('refresh_token')}) 'refresh_token': tokens.get('refresh_token')})

View File

@ -4,44 +4,48 @@ from rest_framework import generics
from location import models, serializers from location import models, serializers
from location.views import common from location.views import common
from utils.permissions import IsCountryAdmin from utils.permissions import IsCountryAdmin
from rest_framework.permissions import IsAuthenticatedOrReadOnly
# Address # Address
class AddressListCreateView(common.AddressViewMixin, generics.ListCreateAPIView): class AddressListCreateView(common.AddressViewMixin, generics.ListCreateAPIView):
"""Create view for model Address.""" """Create view for model Address."""
serializer_class = serializers.AddressDetailSerializer serializer_class = serializers.AddressDetailSerializer
queryset = models.Address.objects.all() queryset = models.Address.objects.all()
permission_classes = [IsCountryAdmin] permission_classes = [IsAuthenticatedOrReadOnly|IsCountryAdmin]
class AddressRUDView(common.AddressViewMixin, generics.RetrieveUpdateDestroyAPIView): class AddressRUDView(common.AddressViewMixin, generics.RetrieveUpdateDestroyAPIView):
"""RUD view for model Address.""" """RUD view for model Address."""
serializer_class = serializers.AddressDetailSerializer serializer_class = serializers.AddressDetailSerializer
queryset = models.Address.objects.all() queryset = models.Address.objects.all()
permission_classes = [IsCountryAdmin] permission_classes = [IsAuthenticatedOrReadOnly|IsCountryAdmin]
# City # City
class CityListCreateView(common.CityViewMixin, generics.ListCreateAPIView): class CityListCreateView(common.CityViewMixin, generics.ListCreateAPIView):
"""Create view for model City.""" """Create view for model City."""
serializer_class = serializers.CitySerializer serializer_class = serializers.CitySerializer
permission_classes = [IsCountryAdmin] permission_classes = [IsAuthenticatedOrReadOnly|IsCountryAdmin]
class CityRUDView(common.CityViewMixin, generics.RetrieveUpdateDestroyAPIView): class CityRUDView(common.CityViewMixin, generics.RetrieveUpdateDestroyAPIView):
"""RUD view for model City.""" """RUD view for model City."""
serializer_class = serializers.CitySerializer serializer_class = serializers.CitySerializer
permission_classes = [IsCountryAdmin] permission_classes = [IsAuthenticatedOrReadOnly|IsCountryAdmin]
# Region # Region
class RegionListCreateView(common.RegionViewMixin, generics.ListCreateAPIView): class RegionListCreateView(common.RegionViewMixin, generics.ListCreateAPIView):
"""Create view for model Region""" """Create view for model Region"""
serializer_class = serializers.RegionSerializer serializer_class = serializers.RegionSerializer
permission_classes = [IsCountryAdmin] permission_classes = [IsAuthenticatedOrReadOnly|IsCountryAdmin]
class RegionRUDView(common.RegionViewMixin, generics.RetrieveUpdateDestroyAPIView): class RegionRUDView(common.RegionViewMixin, generics.RetrieveUpdateDestroyAPIView):
"""Retrieve view for model Region""" """Retrieve view for model Region"""
serializer_class = serializers.RegionSerializer serializer_class = serializers.RegionSerializer
permission_classes = [IsCountryAdmin] permission_classes = [IsAuthenticatedOrReadOnly|IsCountryAdmin]
# Country # Country
@ -50,10 +54,11 @@ class CountryListCreateView(generics.ListCreateAPIView):
queryset = models.Country.objects.all() queryset = models.Country.objects.all()
serializer_class = serializers.CountryBackSerializer serializer_class = serializers.CountryBackSerializer
pagination_class = None pagination_class = None
permission_classes = [IsCountryAdmin] permission_classes = [IsAuthenticatedOrReadOnly|IsCountryAdmin]
class CountryRUDView(generics.RetrieveUpdateDestroyAPIView): class CountryRUDView(generics.RetrieveUpdateDestroyAPIView):
"""RUD view for model Country.""" """RUD view for model Country."""
serializer_class = serializers.CountryBackSerializer serializer_class = serializers.CountryBackSerializer
permission_classes = [IsCountryAdmin] permission_classes = [IsAuthenticatedOrReadOnly|IsCountryAdmin]
queryset = models.Country.objects.all() queryset = models.Country.objects.all()

View File

@ -66,6 +66,22 @@ class NewsTestCase(BaseTestCase):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
def test_news_post(self):
test_news ={
"title": {"en-GB": "Test news POST"},
"news_type_id": self.test_news_type.id,
"description": {"en-GB": "Description test news"},
"start": datetime.now() + timedelta(hours=-2),
"end": datetime.now() + timedelta(hours=2),
"state": News.PUBLISHED,
"slug": 'test-news-slug_post',
"country_id": self.country_ru.id,
}
url = reverse("back:news:list-create")
response = self.client.post(url, data=test_news, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
def test_web_news(self): def test_web_news(self):
response = self.client.get(reverse('web:news:list')) response = self.client.get(reverse('web:news:list'))
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)

View File

@ -20,7 +20,7 @@ class IsAuthenticatedAndTokenIsValid(permissions.BasePermission):
access_token = request.COOKIES.get('access_token') access_token = request.COOKIES.get('access_token')
if user.is_authenticated and access_token: if user.is_authenticated and access_token:
access_token = AccessToken(access_token) access_token = AccessToken(access_token)
valid_tokens = user.access_tokens.valid()\ valid_tokens = user.access_tokens.valid() \
.by_jti(jti=access_token.payload.get('jti')) .by_jti(jti=access_token.payload.get('jti'))
return valid_tokens.exists() return valid_tokens.exists()
else: else:
@ -31,12 +31,13 @@ class IsRefreshTokenValid(permissions.BasePermission):
""" """
Check if user has a valid refresh token and authenticated Check if user has a valid refresh token and authenticated
""" """
def has_permission(self, request, view): def has_permission(self, request, view):
"""Check permissions by refresh token and default REST permission IsAuthenticated""" """Check permissions by refresh token and default REST permission IsAuthenticated"""
refresh_token = request.COOKIES.get('refresh_token') refresh_token = request.COOKIES.get('refresh_token')
if refresh_token: if refresh_token:
refresh_token = GMRefreshToken(refresh_token) refresh_token = GMRefreshToken(refresh_token)
refresh_token_qs = JWTRefreshToken.objects.valid()\ refresh_token_qs = JWTRefreshToken.objects.valid() \
.by_jti(jti=refresh_token.payload.get('jti')) .by_jti(jti=refresh_token.payload.get('jti'))
return refresh_token_qs.exists() return refresh_token_qs.exists()
else: else:
@ -55,11 +56,15 @@ class IsGuest(permissions.IsAuthenticatedOrReadOnly):
""" """
Object-level permission to only allow owners of an object to edit it. Object-level permission to only allow owners of an object to edit it.
""" """
def has_permission(self, request, view): def has_permission(self, request, view):
return request.user.is_authenticated rules = [
request.user.is_superuser,
request.method in permissions.SAFE_METHODS
]
return any(rules)
def has_object_permission(self, request, view, obj): def has_object_permission(self, request, view, obj):
rules = [ rules = [
request.user.is_superuser, request.user.is_superuser,
request.method in permissions.SAFE_METHODS request.method in permissions.SAFE_METHODS
@ -72,6 +77,21 @@ class IsStandardUser(IsGuest):
Object-level permission to only allow owners of an object to edit it. Object-level permission to only allow owners of an object to edit it.
Assumes the model instance has an `owner` attribute. Assumes the model instance has an `owner` attribute.
""" """
def has_permission(self, request, view):
rules = [
super().has_permission(request, view)
]
# and request.user.email_confirmed,
if hasattr(request, 'user'):
rules = [
request.user.is_authenticated,
super().has_permission(request, view)
]
return any(rules)
def has_object_permission(self, request, view, obj): def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request # Read permissions are allowed to any request
rules = [ rules = [
@ -92,11 +112,29 @@ class IsContentPageManager(IsStandardUser):
Object-level permission to only allow owners of an object to edit it. Object-level permission to only allow owners of an object to edit it.
Assumes the model instance has an `owner` attribute. Assumes the model instance has an `owner` attribute.
""" """
def has_permission(self, request, view):
rules = [
super().has_permission(request, view)
]
# and request.user.email_confirmed,
if hasattr(request, 'user'):
role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER,
country_id=request.country_id) \
.first() # 'Comments moderator'
rules = [
UserRole.objects.filter(user=request.user, role=role).exists(),
# and obj.user != request.user,
super().has_permission(request, view)
]
return any(rules)
def has_object_permission(self, request, view, obj): def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request. # Read permissions are allowed to any request.
role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER, role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER,
country_id=obj.country_id)\ country_id=obj.country_id) \
.first() # 'Comments moderator' .first() # 'Comments moderator'
rules = [ rules = [
@ -112,17 +150,48 @@ class IsCountryAdmin(IsStandardUser):
Object-level permission to only allow owners of an object to edit it. Object-level permission to only allow owners of an object to edit it.
Assumes the model instance has an `owner` attribute. Assumes the model instance has an `owner` attribute.
""" """
def has_permission(self, request, view):
rules = [
super().has_permission(request, view)
]
# and request.user.email_confirmed,
if hasattr(request.data, 'user') and hasattr(request.data, 'country_id'):
# Read permissions are allowed to any request.
role = Role.objects.filter(role=Role.COUNTRY_ADMIN,
country_id=request.data.country_id) \
.first() # 'Comments moderator'
rules = [
UserRole.objects.filter(user=request.user, role=role).exists(),
super().has_permission(request, view)
]
return any(rules)
def has_object_permission(self, request, view, obj): def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request. # Read permissions are allowed to any request.
role = Role.objects.filter(role=Role.COUNTRY_ADMIN, role = Role.objects.filter(role=Role.COUNTRY_ADMIN,
country_id=obj.country_id) \ country_id=obj.country_id) \
.first() # 'Comments moderator' .first() # 'Comments moderator'
rules = [
super().has_object_permission(request, view, obj)
]
# and request.user.email_confirmed,
if hasattr(request, 'user') and request.user.is_authenticated:
rules = [ rules = [
UserRole.objects.filter(user=request.user, role=role).exists(), UserRole.objects.filter(user=request.user, role=role).exists(),
super().has_object_permission(request, view, obj), super().has_object_permission(request, view, obj),
] ]
if hasattr(request.data, 'user'):
rules = [
UserRole.objects.filter(user=request.data.user, role=role).exists(),
super().has_object_permission(request, view, obj),
]
return any(rules) return any(rules)
@ -131,10 +200,31 @@ class IsCommentModerator(IsStandardUser):
Object-level permission to only allow owners of an object to edit it. Object-level permission to only allow owners of an object to edit it.
Assumes the model instance has an `owner` attribute. Assumes the model instance has an `owner` attribute.
""" """
def has_permission(self, request, view):
rules = [
super().has_permission(request, view)
]
# and request.user.email_confirmed,
if hasattr(request.data, 'user') and hasattr(request.data, 'country_id'):
# Read permissions are allowed to any request.
role = Role.objects.filter(role=Role.COMMENTS_MODERATOR,
country_id=request.data.country_id) \
.first() # 'Comments moderator'
rules = [
UserRole.objects.filter(user=request.user, role=role).exists(),
super().has_permission(request, view)
]
return any(rules)
def has_object_permission(self, request, view, obj): def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request. # Read permissions are allowed to any request.
role = Role.objects.filter(role=Role.COMMENTS_MODERATOR, role = Role.objects.filter(role=Role.COMMENTS_MODERATOR,
country_id=obj.country_id)\ country_id=obj.country_id) \
.first() # 'Comments moderator' .first() # 'Comments moderator'
rules = [ rules = [
@ -147,8 +237,26 @@ class IsCommentModerator(IsStandardUser):
class IsEstablishmentManager(IsStandardUser): class IsEstablishmentManager(IsStandardUser):
def has_permission(self, request, view):
rules = [
super().has_permission(request, view)
]
# and request.user.email_confirmed,
if hasattr(request.data, 'user') and hasattr(request.data, 'establishment_id'):
role = Role.objects.filter(role=Role.ESTABLISHMENT_MANAGER) \
.first() # 'Comments moderator'
rules = [
UserRole.objects.filter(user=request.user, role=role,
establishment_id=request.data.establishment_id
).exists(),
super().has_permission(request, view)
]
return any(rules)
def has_object_permission(self, request, view, obj): def has_object_permission(self, request, view, obj):
role = Role.objects.filter(role=Role.ESTABLISHMENT_MANAGER)\ role = Role.objects.filter(role=Role.ESTABLISHMENT_MANAGER) \
.first() # 'Comments moderator' .first() # 'Comments moderator'
rules = [ rules = [
@ -163,10 +271,27 @@ class IsEstablishmentManager(IsStandardUser):
class IsReviewerManager(IsStandardUser): class IsReviewerManager(IsStandardUser):
def has_object_permission(self, request, view, obj): def has_permission(self, request, view):
rules = [
super().has_permission(request, view)
]
# and request.user.email_confirmed,
if hasattr(request.data, 'user') and hasattr(request.data, 'country_id'):
role = Role.objects.filter(role=Role.REVIEWER_MANGER) \
.first() # 'Comments moderator'
rules = [
UserRole.objects.filter(user=request.user, role=role,
establishment_id=request.data.country_id
).exists(),
super().has_permission(request, view)
]
return any(rules)
def has_object_permission(self, request, view, obj):
role = Role.objects.filter(role=Role.REVIEWER_MANGER, role = Role.objects.filter(role=Role.REVIEWER_MANGER,
country_id=obj.country_id)\ country_id=obj.country_id) \
.first() .first()
rules = [ rules = [
@ -179,8 +304,25 @@ class IsReviewerManager(IsStandardUser):
class IsRestaurantReviewer(IsStandardUser): class IsRestaurantReviewer(IsStandardUser):
def has_object_permission(self, request, view, obj): def has_permission(self, request, view):
rules = [
super().has_permission(request, view)
]
# and request.user.email_confirmed,
if hasattr(request.data, 'user') and hasattr(request.data, 'object_id'):
role = Role.objects.filter(role=Role.RESTAURANT_REVIEWER) \
.first() # 'Comments moderator'
rules = [
UserRole.objects.filter(user=request.user, role=role,
establishment_id=request.data.object_id
).exists(),
super().has_permission(request, view)
]
return any(rules)
def has_object_permission(self, request, view, obj):
content_type = ContentType.objects.get(app_lable='establishment', content_type = ContentType.objects.get(app_lable='establishment',
model='establishment') model='establishment')

View File

@ -9,10 +9,11 @@ class BasePermissionTests(APITestCase):
title='Russia', title='Russia',
locale='ru-RU' locale='ru-RU'
) )
self.lang.save()
self.country_ru = Country.objects.get( self.country_ru = Country.objects.get(
name={"en-GB": "Russian"} name={"en-GB": "Russian"}
) )
self.country_ru.save()