Add Country admin to views

This commit is contained in:
Виктор Гладких 2019-10-16 10:14:23 +03:00
parent 322cfcd89d
commit 86692019d1
11 changed files with 97 additions and 20 deletions

View File

@ -24,11 +24,13 @@ class Role(ProjectBaseMixin):
STANDARD_USER = 1 STANDARD_USER = 1
COMMENTS_MODERATOR = 2 COMMENTS_MODERATOR = 2
COUNTRY_ADMIN = 3 COUNTRY_ADMIN = 3
CONTENT_PAGE_MANAGER = 4
ROLE_CHOICES = ( ROLE_CHOICES = (
(STANDARD_USER, 'Standard user'), (STANDARD_USER, 'Standard user'),
(COMMENTS_MODERATOR, 'Comments moderator'), (COMMENTS_MODERATOR, 'Comments moderator'),
(COUNTRY_ADMIN, 'Country admin'), (COUNTRY_ADMIN, 'Country admin'),
(CONTENT_PAGE_MANAGER, 'Content page manager')
) )
role = models.PositiveIntegerField(verbose_name=_('Role'), choices=ROLE_CHOICES, role = models.PositiveIntegerField(verbose_name=_('Role'), choices=ROLE_CHOICES,
null=False, blank=False) null=False, blank=False)

View File

@ -1,7 +1,7 @@
from rest_framework import generics, permissions from rest_framework import generics, permissions
from comment.serializers import back as serializers from comment.serializers import back as serializers
from comment import models from comment import models
from utils.permissions import IsCommentModerator from utils.permissions import IsCommentModerator, IsCountryAdmin
class CommentLstView(generics.ListCreateAPIView): class CommentLstView(generics.ListCreateAPIView):
@ -15,5 +15,5 @@ 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 = [IsCommentModerator] permission_classes = [IsCountryAdmin|IsCommentModerator]
lookup_field = 'id' lookup_field = 'id'

View File

@ -382,6 +382,13 @@ class Establishment(ProjectBaseMixin, URLImageMixin, TranslatedFieldsMixin):
return Award.objects.filter(Q(establishment=self) | Q(employees__establishments=self)).latest( return Award.objects.filter(Q(establishment=self) | Q(employees__establishments=self)).latest(
field_name='vintage_year') field_name='vintage_year')
@property
def country_id(self):
"""
Return Country object of establishment location
"""
return self.address.city.country.id
class Position(BaseAttributes, TranslatedFieldsMixin): class Position(BaseAttributes, TranslatedFieldsMixin):
"""Position model.""" """Position model."""

View File

@ -4,6 +4,7 @@ from rest_framework import generics
from establishment import models from establishment import models
from establishment import serializers from establishment import serializers
from utils.permissions import IsCountryAdmin
class EstablishmentMixinViews: class EstablishmentMixinViews:
@ -18,11 +19,13 @@ class EstablishmentListCreateView(EstablishmentMixinViews, generics.ListCreateAP
"""Establishment list/create view.""" """Establishment list/create view."""
queryset = models.Establishment.objects.all() queryset = models.Establishment.objects.all()
serializer_class = serializers.EstablishmentListCreateSerializer serializer_class = serializers.EstablishmentListCreateSerializer
permission_classes = [IsCountryAdmin]
class EstablishmentRUDView(generics.RetrieveUpdateDestroyAPIView): class EstablishmentRUDView(generics.RetrieveUpdateDestroyAPIView):
queryset = models.Establishment.objects.all() queryset = models.Establishment.objects.all()
serializer_class = serializers.EstablishmentRUDSerializer serializer_class = serializers.EstablishmentRUDSerializer
permission_classes = [IsCountryAdmin]
class MenuListCreateView(generics.ListCreateAPIView): class MenuListCreateView(generics.ListCreateAPIView):

View File

@ -11,7 +11,7 @@ from main import methods
from main.models import MetaDataContent from main.models import MetaDataContent
from timetable.serialziers import ScheduleRUDSerializer, ScheduleCreateSerializer from timetable.serialziers import ScheduleRUDSerializer, ScheduleCreateSerializer
from utils.pagination import EstablishmentPortionPagination from utils.pagination import EstablishmentPortionPagination
from utils.permissions import IsCountryAdmin
class EstablishmentMixinView: class EstablishmentMixinView:
"""Establishment mixin.""" """Establishment mixin."""

View File

@ -112,6 +112,10 @@ class Address(models.Model):
return {'lat': self.latitude, return {'lat': self.latitude,
'lon': self.longitude} 'lon': self.longitude}
@property
def country_id(self):
return self.city.country_id
# todo: Make recalculate price levels # todo: Make recalculate price levels
@receiver(post_save, sender=Country) @receiver(post_save, sender=Country)

View File

@ -3,50 +3,54 @@ 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
# 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]
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]
# 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]
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]
# 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]
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]
# Country # Country
class CountryListCreateView(common.CountryViewMixin, generics.ListCreateAPIView): class CountryListCreateView(common.CountryViewMixin, generics.ListCreateAPIView):
"""List/Create view for model Country.""" """List/Create view for model Country."""
serializer_class = serializers.CountryBackSerializer serializer_class = serializers.CountryBackSerializer
pagination_class = None pagination_class = None
permission_classes = [IsCountryAdmin]
class CountryRUDView(common.CountryViewMixin, generics.RetrieveUpdateDestroyAPIView): class CountryRUDView(common.CountryViewMixin, generics.RetrieveUpdateDestroyAPIView):
"""RUD view for model Country.""" """RUD view for model Country."""
serializer_class = serializers.CountryBackSerializer serializer_class = serializers.CountryBackSerializer
permission_classes = [IsCountryAdmin]

View File

@ -1,3 +1,4 @@
from django.urls import reverse
from http.cookies import SimpleCookie from http.cookies import SimpleCookie
from rest_framework.test import APITestCase from rest_framework.test import APITestCase
@ -6,7 +7,8 @@ from datetime import datetime, timedelta
from news.models import NewsType, News from news.models import NewsType, News
from account.models import User from account.models import User
from translation.models import Language
from location.models import Country
# Create your tests here. # Create your tests here.
@ -27,7 +29,20 @@ class BaseTestCase(APITestCase):
playlist=1, start=datetime.now() + timedelta(hours=-2), playlist=1, start=datetime.now() + timedelta(hours=-2),
end=datetime.now() + timedelta(hours=2), end=datetime.now() + timedelta(hours=2),
state=News.PUBLISHED, slug='test-news-slug',) state=News.PUBLISHED, slug='test-news-slug',)
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()
class NewsTestCase(BaseTestCase): class NewsTestCase(BaseTestCase):
@ -50,3 +65,18 @@ class NewsTestCase(BaseTestCase):
def test_news_type_list(self): def test_news_type_list(self):
response = self.client.get("/api/web/news/types/") response = self.client.get("/api/web/news/types/")
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_news_back_detail_put(self):
# retrieve-update-destroy
url = reverse('back:news:retrieve-update-destroy', kwargs={'pk': self.test_news.id})
data = {
'id': self.test_news.id,
'description': {"en-GB": "Description test news!"},
'slug': self.test_news.slug,
'start': self.test_news.start,
'playlist': self.test_news.playlist,
'news_type_id':self.test_news.news_type_id,
'country_id': self.country_ru.id
}
response = self.client.put(url, data=data, format='json')
self.assertEqual(response.status_code, status.HTTP_200_OK)

View File

@ -2,6 +2,7 @@
from rest_framework import generics, permissions from rest_framework import generics, permissions
from news import filters, models, serializers from news import filters, models, serializers
from rating.tasks import add_rating from rating.tasks import add_rating
from utils.permissions import IsCountryAdmin
class NewsMixinView: class NewsMixinView:
"""News mixin.""" """News mixin."""
@ -57,6 +58,7 @@ class NewsBackOfficeLCView(NewsBackOfficeMixinView,
serializer_class = serializers.NewsBackOfficeBaseSerializer serializer_class = serializers.NewsBackOfficeBaseSerializer
create_serializers_class = serializers.NewsBackOfficeDetailSerializer create_serializers_class = serializers.NewsBackOfficeDetailSerializer
permission_classes = [IsCountryAdmin]
def get_serializer_class(self): def get_serializer_class(self):
"""Override serializer class.""" """Override serializer class."""

View File

@ -67,9 +67,34 @@ class IsStandardUser(IsGuest):
""" """
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
if super().has_object_permission(request, view, obj) or\ if obj.user == request.user and obj.user.email_confirmed:
(obj.user == request.user and obj.user.email_confirmed):
return True return True
if super().has_object_permission(request, view, obj):
return True
return False
class IsContentPageManager(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.
role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER,
country_id=obj.country_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
if super().has_object_permission(request, view, obj):
return True
return False return False
@ -80,17 +105,18 @@ class IsCountryAdmin(IsStandardUser):
""" """
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.
if super().has_object_permission(request, view, obj):
return True
# Must have role
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'
is_access = UserRole.objects.filter(user=request.user, role=role).exists() is_access = UserRole.objects.filter(user=request.user, role=role).exists()
if obj.user != request.user and is_access: if obj.user != request.user and is_access:
return True return True
if super().has_object_permission(request, view, obj):
return True
return False return False
@ -102,17 +128,16 @@ class IsCommentModerator(IsCountryAdmin):
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.
if super().has_object_permission(request, view, obj):
return True
# Must have role
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'
is_access = UserRole.objects.filter(user=request.user, role=role).exists() is_access = UserRole.objects.filter(user=request.user, role=role).exists()
if obj.user != request.user and is_access: if obj.user != request.user and is_access:
return True return True
if super().has_object_permission(request, view, obj):
return True
return False return False