From 806a7d63e492c6abbc915ad57883b2a664729b9f 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: Fri, 22 Nov 2019 11:43:22 +0300 Subject: [PATCH 01/14] Migrate --- apps/account/migrations/0020_role_site.py | 20 ++++++++++++++++++++ apps/account/models.py | 6 ++---- 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 apps/account/migrations/0020_role_site.py diff --git a/apps/account/migrations/0020_role_site.py b/apps/account/migrations/0020_role_site.py new file mode 100644 index 00000000..8fce5f24 --- /dev/null +++ b/apps/account/migrations/0020_role_site.py @@ -0,0 +1,20 @@ +# Generated by Django 2.2.7 on 2019-11-22 08:32 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0037_sitesettings_old_id'), + ('account', '0019_auto_20191108_0827'), + ] + + operations = [ + migrations.AddField( + model_name='role', + name='site', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='main.SiteSettings', verbose_name='Site settings'), + ), + ] diff --git a/apps/account/models.py b/apps/account/models.py index 78c3c284..c212ffda 100644 --- a/apps/account/models.py +++ b/apps/account/models.py @@ -46,10 +46,8 @@ class Role(ProjectBaseMixin): null=False, blank=False) country = models.ForeignKey(Country, verbose_name=_('Country'), null=True, blank=True, on_delete=models.SET_NULL) - # is_list = models.BooleanField(verbose_name=_('list'), default=True, null=False) - # is_create = models.BooleanField(verbose_name=_('create'), default=False, null=False) - # is_update = models.BooleanField(verbose_name=_('update'), default=False, null=False) - # is_delete = models.BooleanField(verbose_name=_('delete'), default=False, null=False) + site = models.ForeignKey(SiteSettings, verbose_name=_('Site settings'), + null=True, blank=True, on_delete=models.SET_NULL) class UserManager(BaseUserManager): From e0352b7d937e8d8a476ac63ed29cb3387e35f3bc 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: Fri, 22 Nov 2019 15:46:59 +0300 Subject: [PATCH 02/14] Back news permissions --- apps/news/migrations/0036_news_site.py | 20 ++++++++++++++++++++ apps/news/models.py | 3 ++- apps/news/serializers.py | 7 +++++-- apps/news/tests.py | 24 ++++++++++++++++-------- apps/news/views.py | 3 ++- apps/utils/permissions.py | 13 +++++++++---- project/settings/local.py | 3 ++- 7 files changed, 56 insertions(+), 17 deletions(-) create mode 100644 apps/news/migrations/0036_news_site.py diff --git a/apps/news/migrations/0036_news_site.py b/apps/news/migrations/0036_news_site.py new file mode 100644 index 00000000..6e819384 --- /dev/null +++ b/apps/news/migrations/0036_news_site.py @@ -0,0 +1,20 @@ +# Generated by Django 2.2.7 on 2019-11-22 09:12 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0037_sitesettings_old_id'), + ('news', '0035_news_views_count'), + ] + + operations = [ + migrations.AddField( + model_name='news', + name='site', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='main.SiteSettings', verbose_name='site settings'), + ), + ] diff --git a/apps/news/models.py b/apps/news/models.py index 8a86e688..20307b32 100644 --- a/apps/news/models.py +++ b/apps/news/models.py @@ -203,7 +203,8 @@ class News(GalleryModelMixin, BaseAttributes, TranslatedFieldsMixin, HasTagsMixi banner = models.ForeignKey('news.NewsBanner', blank=True, null=True, on_delete=models.SET_NULL, verbose_name=_('banner')) - + site = models.ForeignKey('main.SiteSettings', blank=True, null=True, + on_delete=models.SET_NULL, verbose_name=_('site settings')) objects = NewsQuerySet.as_manager() class Meta: diff --git a/apps/news/serializers.py b/apps/news/serializers.py index 2264b9ec..008ca9ff 100644 --- a/apps/news/serializers.py +++ b/apps/news/serializers.py @@ -5,6 +5,7 @@ from rest_framework.fields import SerializerMethodField from account.serializers.common import UserBaseSerializer from gallery.models import Image +from main.models import SiteSettings from location import models as location_models from location.serializers import CountrySimpleSerializer, AddressBaseSerializer from news import models @@ -65,7 +66,6 @@ class NewsBaseSerializer(ProjectModelSerializer): subtitle_translated = TranslatedField() news_type = NewsTypeSerializer(read_only=True) tags = TagBaseSerializer(read_only=True, many=True, source='visible_tags') - in_favorites = serializers.BooleanField(allow_null=True) view_counter = serializers.IntegerField(read_only=True) class Meta: @@ -80,7 +80,6 @@ class NewsBaseSerializer(ProjectModelSerializer): 'news_type', 'tags', 'slug', - 'in_favorites', 'view_counter', ) @@ -184,6 +183,9 @@ class NewsBackOfficeDetailSerializer(NewsBackOfficeBaseSerializer, country_id = serializers.PrimaryKeyRelatedField( source='country', write_only=True, queryset=location_models.Country.objects.all()) + site_id = serializers.PrimaryKeyRelatedField( + source='site', write_only=True, + queryset=SiteSettings.objects.all()) template_display = serializers.CharField(source='get_template_display', read_only=True) @@ -195,6 +197,7 @@ class NewsBackOfficeDetailSerializer(NewsBackOfficeBaseSerializer, 'description', 'news_type_id', 'country_id', + 'site_id', 'template', 'template_display', ) diff --git a/apps/news/tests.py b/apps/news/tests.py index 532a6efc..c2b2e431 100644 --- a/apps/news/tests.py +++ b/apps/news/tests.py @@ -5,6 +5,7 @@ from rest_framework.test import APITestCase from rest_framework import status from datetime import datetime, timedelta +from main.models import SiteSettings from news.models import NewsType, News from account.models import User, Role, UserRole from translation.models import Language @@ -30,18 +31,22 @@ class BaseTestCase(APITestCase): 'refresh_token': tokens.get('refresh_token')}) self.test_news_type = NewsType.objects.create(name="Test news type") - self.lang = Language.objects.get( + self.lang, created = Language.objects.get_or_create( title='Russia', locale='ru-RU' ) - self.country_ru = Country.objects.get( + self.country_ru, created = Country.objects.get_or_create( name={"en-GB": "Russian"} ) + self.site_ru, created = SiteSettings.objects.get_or_create( + subdomain='ru' + ) + role = Role.objects.create( role=Role.CONTENT_PAGE_MANAGER, - country=self.country_ru + site_id=self.site_ru.id ) role.save() @@ -51,16 +56,18 @@ class BaseTestCase(APITestCase): ) user_role.save() + self.test_news = News.objects.create( created_by=self.user, modified_by=self.user, - title={"en-GB": "Test news"}, + title={"ru-RU": "Test news"}, news_type=self.test_news_type, - description={"en-GB": "Description test news"}, + description={"ru-RU": "Description test news"}, start=datetime.now() + timedelta(hours=-2), end=datetime.now() + timedelta(hours=2), state=News.PUBLISHED, slug='test-news-slug', country=self.country_ru, + site=self.site_ru ) @@ -70,14 +77,15 @@ class NewsTestCase(BaseTestCase): def test_news_post(self): test_news = { - "title": {"en-GB": "Test news POST"}, + "title": {"ru-RU": "Test news POST"}, "news_type_id": self.test_news_type.id, - "description": {"en-GB": "Description test news"}, + "description": {"ru-RU": "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, + "site_id": self.site_ru.id } url = reverse("back:news:list-create") @@ -107,7 +115,7 @@ class NewsTestCase(BaseTestCase): 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!"}, + 'description': {"ru-RU": "Description test news!"}, 'slug': self.test_news.slug, 'start': self.test_news.start, 'news_type_id': self.test_news.news_type_id, diff --git a/apps/news/views.py b/apps/news/views.py index bdb75fc7..7da672bf 100644 --- a/apps/news/views.py +++ b/apps/news/views.py @@ -84,7 +84,8 @@ class NewsBackOfficeLCView(NewsBackOfficeMixinView, serializer_class = serializers.NewsBackOfficeBaseSerializer filter_class = filters.NewsListFilterSet create_serializers_class = serializers.NewsBackOfficeDetailSerializer - permission_classes = [IsCountryAdmin | IsContentPageManager] + # IsCountryAdmin | + permission_classes = [ IsContentPageManager] def get_serializer_class(self): """Override serializer class.""" diff --git a/apps/utils/permissions.py b/apps/utils/permissions.py index 86a4be6f..c53f3962 100644 --- a/apps/utils/permissions.py +++ b/apps/utils/permissions.py @@ -119,8 +119,14 @@ class IsContentPageManager(IsStandardUser): ] # and request.user.email_confirmed, if hasattr(request, 'user'): + site_id = None + if hasattr(request, 'data'): + site_id = request.data['site_id'] + else: + site_id = request.site_id + role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER, - country_id=request.country_id) \ + site_id=site_id) \ .first() # 'Comments moderator' rules = [ @@ -134,12 +140,11 @@ class IsContentPageManager(IsStandardUser): # Read permissions are allowed to any request. role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER, - country_id=obj.country_id) \ - .first() # 'Comments moderator' + site_id=obj.site_id) \ + .first() rules = [ UserRole.objects.filter(user=request.user, role=role).exists(), - # and obj.user != request.user, super().has_object_permission(request, view, obj) ] return any(rules) diff --git a/project/settings/local.py b/project/settings/local.py index 959e6149..13ca7213 100644 --- a/project/settings/local.py +++ b/project/settings/local.py @@ -36,7 +36,7 @@ THUMBNAIL_DEBUG = True # ADDED TRANSFER APP -INSTALLED_APPS.append('transfer.apps.TransferConfig') +# INSTALLED_APPS.append('transfer.apps.TransferConfig') # DATABASES @@ -101,6 +101,7 @@ ELASTICSEARCH_INDEX_NAMES = { 'search_indexes.documents.establishment': 'local_establishment', 'search_indexes.documents.product': 'local_product', } +ELASTICSEARCH_DSL_AUTOSYNC = False TESTING = sys.argv[1:2] == ['test'] From 376c8cdff390f0f08909b05ae08a0a373309a707 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: Fri, 22 Nov 2019 16:00:59 +0300 Subject: [PATCH 03/14] State test news with contentpage permission --- apps/news/tests.py | 3 ++- apps/utils/models.py | 4 ---- apps/utils/permissions.py | 10 ++-------- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/apps/news/tests.py b/apps/news/tests.py index c2b2e431..74563ca4 100644 --- a/apps/news/tests.py +++ b/apps/news/tests.py @@ -119,7 +119,8 @@ class NewsTestCase(BaseTestCase): 'slug': self.test_news.slug, 'start': self.test_news.start, 'news_type_id': self.test_news.news_type_id, - 'country_id': self.country_ru.id + 'country_id': self.country_ru.id, + "site_id": self.site_ru.id } response = self.client.put(url, data=data, format='json') diff --git a/apps/utils/models.py b/apps/utils/models.py index 8c186f2f..ebfd9a81 100644 --- a/apps/utils/models.py +++ b/apps/utils/models.py @@ -36,10 +36,6 @@ class ProjectBaseMixin(models.Model): abstract = True -def valid(value): - print("Run") - - class TJSONField(JSONField): """Overrided JsonField.""" diff --git a/apps/utils/permissions.py b/apps/utils/permissions.py index c53f3962..8ac8f0d0 100644 --- a/apps/utils/permissions.py +++ b/apps/utils/permissions.py @@ -118,15 +118,9 @@ class IsContentPageManager(IsStandardUser): super().has_permission(request, view) ] # and request.user.email_confirmed, - if hasattr(request, 'user'): - site_id = None - if hasattr(request, 'data'): - site_id = request.data['site_id'] - else: - site_id = request.site_id - + if hasattr(request, 'user') and hasattr(request.data, 'site_id'): role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER, - site_id=site_id) \ + site_id=request.data.site_id,) \ .first() # 'Comments moderator' rules = [ From e3420d571e639becd7cdd7a36d708dedbf6998fd 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: Fri, 22 Nov 2019 16:05:02 +0300 Subject: [PATCH 04/14] Contentpage permission in news --- apps/news/views.py | 4 ++-- apps/utils/permissions.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/news/views.py b/apps/news/views.py index 7da672bf..566cdd50 100644 --- a/apps/news/views.py +++ b/apps/news/views.py @@ -84,8 +84,8 @@ class NewsBackOfficeLCView(NewsBackOfficeMixinView, serializer_class = serializers.NewsBackOfficeBaseSerializer filter_class = filters.NewsListFilterSet create_serializers_class = serializers.NewsBackOfficeDetailSerializer - # IsCountryAdmin | - permission_classes = [ IsContentPageManager] + + permission_classes = [IsCountryAdmin | IsContentPageManager] def get_serializer_class(self): """Override serializer class.""" diff --git a/apps/utils/permissions.py b/apps/utils/permissions.py index 8ac8f0d0..bdb17726 100644 --- a/apps/utils/permissions.py +++ b/apps/utils/permissions.py @@ -156,11 +156,11 @@ class IsCountryAdmin(IsStandardUser): super().has_permission(request, view) ] # and request.user.email_confirmed, - if hasattr(request.data, 'user') and hasattr(request.data, 'country_id'): + if hasattr(request.data, 'user') and hasattr(request.data, 'site_id'): # Read permissions are allowed to any request. role = Role.objects.filter(role=Role.COUNTRY_ADMIN, - country_id=request.data.country_id) \ + site_id=request.data.site_id) \ .first() # 'Comments moderator' rules = [ @@ -172,7 +172,7 @@ class IsCountryAdmin(IsStandardUser): def has_object_permission(self, request, view, obj): # Read permissions are allowed to any request. role = Role.objects.filter(role=Role.COUNTRY_ADMIN, - country_id=obj.country_id) \ + site_id=obj.site_id) \ .first() # 'Comments moderator' rules = [ From 58db94e2d08d8ca4eed46eaa04cb815b84700de4 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, 25 Nov 2019 09:33:22 +0300 Subject: [PATCH 05/14] Permission --- apps/utils/permissions.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/utils/permissions.py b/apps/utils/permissions.py index bdb17726..3a226dbd 100644 --- a/apps/utils/permissions.py +++ b/apps/utils/permissions.py @@ -121,11 +121,10 @@ class IsContentPageManager(IsStandardUser): if hasattr(request, 'user') and hasattr(request.data, 'site_id'): role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER, site_id=request.data.site_id,) \ - .first() # 'Comments moderator' + .first() rules = [ UserRole.objects.filter(user=request.user, role=role).exists(), - # and obj.user != request.user, super().has_permission(request, view) ] return any(rules) From 13eb8abac643c1886d87860cc10f65167cc102ae 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, 25 Nov 2019 09:49:17 +0300 Subject: [PATCH 06/14] fix country or site --- apps/utils/permissions.py | 98 +++++++++++++++++++++++++++------------ 1 file changed, 69 insertions(+), 29 deletions(-) diff --git a/apps/utils/permissions.py b/apps/utils/permissions.py index 3a226dbd..406c1692 100644 --- a/apps/utils/permissions.py +++ b/apps/utils/permissions.py @@ -117,29 +117,50 @@ class IsContentPageManager(IsStandardUser): rules = [ super().has_permission(request, view) ] - # and request.user.email_confirmed, - if hasattr(request, 'user') and hasattr(request.data, 'site_id'): - role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER, - site_id=request.data.site_id,) \ - .first() - rules = [ - UserRole.objects.filter(user=request.user, role=role).exists(), - super().has_permission(request, view) - ] + if hasattr(request, 'user'): + if hasattr(request.data, 'site_id'): + role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER, + site_id=request.data.site_id,) \ + .first() + + rules = [ + UserRole.objects.filter(user=request.user, role=role).exists(), + super().has_permission(request, view) + ] + elif hasattr(request.data, 'country_id'): + role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER, + country_id=request.data.country_id) \ + .first() + + 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): # Read permissions are allowed to any request. + if hasattr(obj, 'site_id'): + role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER, + site_id=obj.site_id) \ + .first() - role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER, - site_id=obj.site_id) \ - .first() + rules = [ + UserRole.objects.filter(user=request.user, role=role).exists(), + super().has_object_permission(request, view, obj) + ] + elif hasattr(obj, 'country_id'): + role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER, + country_id=obj.country_id) \ + .first() + + rules = [ + UserRole.objects.filter(user=request.user, role=role).exists(), + super().has_object_permission(request, view, obj) + ] - rules = [ - UserRole.objects.filter(user=request.user, role=role).exists(), - super().has_object_permission(request, view, obj) - ] return any(rules) @@ -148,36 +169,55 @@ class IsCountryAdmin(IsStandardUser): Object-level permission to only allow owners of an object to edit it. 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, 'site_id'): - # Read permissions are allowed to any request. + if hasattr(request.data, 'user'): + if hasattr(request.data, 'site_id'): + # Read permissions are allowed to any request. + + role = Role.objects.filter(role=Role.COUNTRY_ADMIN, + site_id=request.data.site_id) \ + .first() + + rules = [ + UserRole.objects.filter(user=request.user, role=role).exists(), + super().has_permission(request, view) + ] + elif hasattr(request.data, 'country_id'): role = Role.objects.filter(role=Role.COUNTRY_ADMIN, - site_id=request.data.site_id) \ - .first() # 'Comments moderator' + country_id=request.data.country_id) \ + .first() 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): # Read permissions are allowed to any request. - role = Role.objects.filter(role=Role.COUNTRY_ADMIN, - site_id=obj.site_id) \ - .first() # 'Comments moderator' + if hasattr(obj, 'site_id'): + role = Role.objects.filter(role=Role.COUNTRY_ADMIN, + site_id=obj.site_id) \ + .first() + + rules = [ + super().has_object_permission(request, view, obj) + ] + elif hasattr(obj, 'country_id'): + role = Role.objects.filter(role=Role.COUNTRY_ADMIN, + country_id=obj.country_id) \ + .first() + + rules = [ + super().has_object_permission(request, view, obj) + ] - rules = [ - super().has_object_permission(request, view, obj) - ] - # and request.user.email_confirmed, if hasattr(request, 'user') and request.user.is_authenticated: rules = [ UserRole.objects.filter(user=request.user, role=role).exists(), From 6bb0eac409b1c63623317c18a9934ee338c138d2 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, 25 Nov 2019 10:45:20 +0300 Subject: [PATCH 07/14] Fix establishment timetable serailizer for permission --- apps/partner/serializers/back.py | 1 + apps/timetable/serialziers.py | 3 +++ apps/utils/permissions.py | 36 +++++++++++++++++++------------- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/apps/partner/serializers/back.py b/apps/partner/serializers/back.py index d011e058..e9e03fe0 100644 --- a/apps/partner/serializers/back.py +++ b/apps/partner/serializers/back.py @@ -13,6 +13,7 @@ class BackPartnerSerializer(serializers.ModelSerializer): 'url', 'image', 'establishment', + 'establishment_id', 'type', 'starting_date', 'expiry_date', diff --git a/apps/timetable/serialziers.py b/apps/timetable/serialziers.py index 533bca70..f7ae4204 100644 --- a/apps/timetable/serialziers.py +++ b/apps/timetable/serialziers.py @@ -20,6 +20,7 @@ class ScheduleRUDSerializer(serializers.ModelSerializer): dinner_end = serializers.TimeField(required=False) opening_at = serializers.TimeField(required=False) closed_at = serializers.TimeField(required=False) + establishment_id = serializers.ReadOnlyField(source='establishment.id') class Meta: """Meta class.""" @@ -34,8 +35,10 @@ class ScheduleRUDSerializer(serializers.ModelSerializer): 'dinner_end', 'opening_at', 'closed_at', + 'establishment_id' ] + def validate(self, attrs): """Override validate method""" establishment_pk = self.context.get('request')\ diff --git a/apps/utils/permissions.py b/apps/utils/permissions.py index 406c1692..7b8ff845 100644 --- a/apps/utils/permissions.py +++ b/apps/utils/permissions.py @@ -280,30 +280,36 @@ class IsEstablishmentManager(IsStandardUser): 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' + if hasattr(request.data, 'user'): + if hasattr(request.data, 'establishment_id'): + role = Role.objects.filter(role=Role.ESTABLISHMENT_MANAGER) \ + .first() - rules = [ - UserRole.objects.filter(user=request.user, role=role, - establishment_id=request.data.establishment_id - ).exists(), - super().has_permission(request, view) - ] + 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): - role = Role.objects.filter(role=Role.ESTABLISHMENT_MANAGER) \ - .first() # 'Comments moderator' rules = [ - UserRole.objects.filter(user=request.user, role=role, - establishment_id=obj.establishment_id - ).exists(), super().has_object_permission(request, view, obj) ] + role = Role.objects.filter(role=Role.ESTABLISHMENT_MANAGER) \ + .first() + + if hasattr(obj, 'establishment_id'): + rules = [ + UserRole.objects.filter(user=request.user, role=role, + establishment_id=obj.establishment_id + ).exists(), + super().has_object_permission(request, view, obj) + ] + return any(rules) From 29782fe876d143486fa042cb0d8470ed1904282e 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, 25 Nov 2019 10:45:57 +0300 Subject: [PATCH 08/14] Fix --- apps/timetable/serialziers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/timetable/serialziers.py b/apps/timetable/serialziers.py index f7ae4204..48c8374d 100644 --- a/apps/timetable/serialziers.py +++ b/apps/timetable/serialziers.py @@ -20,6 +20,7 @@ class ScheduleRUDSerializer(serializers.ModelSerializer): dinner_end = serializers.TimeField(required=False) opening_at = serializers.TimeField(required=False) closed_at = serializers.TimeField(required=False) + # For permission!! establishment_id = serializers.ReadOnlyField(source='establishment.id') class Meta: @@ -38,7 +39,6 @@ class ScheduleRUDSerializer(serializers.ModelSerializer): 'establishment_id' ] - def validate(self, attrs): """Override validate method""" establishment_pk = self.context.get('request')\ From 86500b6b88a4f4fd83bf80b0627758ac524dc3eb 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, 25 Nov 2019 11:13:05 +0300 Subject: [PATCH 09/14] Fix site_id for comment --- apps/comment/migrations/0007_comment_site.py | 20 ++++++++++++++++++++ apps/comment/models.py | 3 ++- apps/comment/tests.py | 12 +++++++++--- apps/utils/permissions.py | 8 ++++---- apps/utils/tests/tests_permissions.py | 6 ++---- 5 files changed, 37 insertions(+), 12 deletions(-) create mode 100644 apps/comment/migrations/0007_comment_site.py diff --git a/apps/comment/migrations/0007_comment_site.py b/apps/comment/migrations/0007_comment_site.py new file mode 100644 index 00000000..c19629df --- /dev/null +++ b/apps/comment/migrations/0007_comment_site.py @@ -0,0 +1,20 @@ +# Generated by Django 2.2.7 on 2019-11-25 08:10 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0037_sitesettings_old_id'), + ('comment', '0006_comment_is_publish'), + ] + + operations = [ + migrations.AddField( + model_name='comment', + name='site', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='main.SiteSettings', verbose_name='site'), + ), + ] diff --git a/apps/comment/models.py b/apps/comment/models.py index 421a05fb..fa27d3f9 100644 --- a/apps/comment/models.py +++ b/apps/comment/models.py @@ -35,7 +35,8 @@ class Comment(ProjectBaseMixin): user = models.ForeignKey('account.User', related_name='comments', on_delete=models.CASCADE, verbose_name=_('User')) old_id = models.IntegerField(null=True, blank=True, default=None) is_publish = models.BooleanField(default=False, verbose_name=_('Publish status')) - + site = models.ForeignKey('main.SiteSettings', blank=True, null=True, + on_delete=models.SET_NULL, verbose_name=_('site')) content_type = models.ForeignKey(generic.ContentType, on_delete=models.CASCADE) object_id = models.PositiveIntegerField() content_object = generic.GenericForeignKey('content_type', 'object_id') diff --git a/apps/comment/tests.py b/apps/comment/tests.py index ff3bd393..832b86cb 100644 --- a/apps/comment/tests.py +++ b/apps/comment/tests.py @@ -8,6 +8,7 @@ from account.models import Role, User, UserRole from authorization.tests.tests_authorization import get_tokens_for_user from comment.models import Comment from utils.tests.tests_permissions import BasePermissionTests +from main.models import SiteSettings class CommentModeratorPermissionTests(BasePermissionTests): @@ -33,11 +34,16 @@ class CommentModeratorPermissionTests(BasePermissionTests): self.content_type = ContentType.objects.get(app_label='location', model='country') self.user_test = get_tokens_for_user() + + self.site_ru, created = SiteSettings.objects.get_or_create( + subdomain='ru' + ) + self.comment = Comment.objects.create(text='Test comment', mark=1, user=self.user_test["user"], object_id=self.country_ru.pk, content_type_id=self.content_type.id, - country=self.country_ru + site=self.site_ru ) self.comment.save() self.url = reverse('back:comment:comment-crud', kwargs={"id": self.comment.id}) @@ -50,7 +56,7 @@ class CommentModeratorPermissionTests(BasePermissionTests): "user": self.user_test["user"].id, "object_id": self.country_ru.pk, "content_type": self.content_type.id, - "country_id": self.country_ru.id + "site_id": self.site_ru.id } response = self.client.post(self.url, format='json', data=comment) @@ -61,7 +67,7 @@ class CommentModeratorPermissionTests(BasePermissionTests): "user": self.moderator.id, "object_id": self.country_ru.id, "content_type": self.content_type.id, - "country_id": self.country_ru.id + "site_id": self.site_ru.id } tokens = User.create_jwt_tokens(self.moderator) diff --git a/apps/utils/permissions.py b/apps/utils/permissions.py index 7b8ff845..a32e302c 100644 --- a/apps/utils/permissions.py +++ b/apps/utils/permissions.py @@ -321,13 +321,13 @@ class IsReviewerManager(IsStandardUser): ] # and request.user.email_confirmed, - if hasattr(request.data, 'user') and hasattr(request.data, 'country_id'): + if hasattr(request.data, 'user') and hasattr(request.data, 'site_id'): role = Role.objects.filter(role=Role.REVIEWER_MANGER) \ - .first() # 'Comments moderator' + .first() rules = [ UserRole.objects.filter(user=request.user, role=role, - establishment_id=request.data.country_id + establishment_id=request.data.site_id ).exists(), super().has_permission(request, view) ] @@ -335,7 +335,7 @@ class IsReviewerManager(IsStandardUser): def has_object_permission(self, request, view, obj): role = Role.objects.filter(role=Role.REVIEWER_MANGER, - country_id=obj.country_id) \ + country_id=obj.site_id) \ .first() rules = [ diff --git a/apps/utils/tests/tests_permissions.py b/apps/utils/tests/tests_permissions.py index 3bba7b7d..18eeb95b 100644 --- a/apps/utils/tests/tests_permissions.py +++ b/apps/utils/tests/tests_permissions.py @@ -5,15 +5,13 @@ from translation.models import Language class BasePermissionTests(APITestCase): def setUp(self): - self.lang = Language.objects.get( + self.lang, created = Language.objects.get_or_create( title='Russia', locale='ru-RU' ) - self.lang.save() - self.country_ru = Country.objects.get( + self.country_ru, created = Country.objects.get_or_create( name={"en-GB": "Russian"} ) - self.country_ru.save() From 28a3e022f679e28a7d6b75facecdb643244b509a 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, 25 Nov 2019 12:13:14 +0300 Subject: [PATCH 10/14] Fix comment test and permission --- apps/comment/tests.py | 15 ++++++++------- apps/comment/views/back.py | 6 +++--- apps/utils/permissions.py | 32 ++++++++++++++++++++------------ 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/apps/comment/tests.py b/apps/comment/tests.py index 832b86cb..79bed42f 100644 --- a/apps/comment/tests.py +++ b/apps/comment/tests.py @@ -15,9 +15,13 @@ class CommentModeratorPermissionTests(BasePermissionTests): def setUp(self): super().setUp() + self.site_ru, created = SiteSettings.objects.get_or_create( + subdomain='ru' + ) + self.role = Role.objects.create( role=2, - country=self.country_ru + site=self.site_ru ) self.role.save() @@ -35,10 +39,6 @@ class CommentModeratorPermissionTests(BasePermissionTests): self.user_test = get_tokens_for_user() - self.site_ru, created = SiteSettings.objects.get_or_create( - subdomain='ru' - ) - self.comment = Comment.objects.create(text='Test comment', mark=1, user=self.user_test["user"], object_id=self.country_ru.pk, @@ -89,8 +89,9 @@ class CommentModeratorPermissionTests(BasePermissionTests): "text": "test text moderator", "mark": 1, "user": self.moderator.id, - "object_id": self.comment.country_id, - "content_type": self.content_type.id + "object_id": self.country_ru.id, + "content_type": self.content_type.id, + 'site_id': self.site_ru.id } response = self.client.put(self.url, data=data, format='json') diff --git a/apps/comment/views/back.py b/apps/comment/views/back.py index 3b96cbd2..a46b70cb 100644 --- a/apps/comment/views/back.py +++ b/apps/comment/views/back.py @@ -8,13 +8,13 @@ class CommentLstView(generics.ListCreateAPIView): """Comment list create view.""" serializer_class = serializers.CommentBaseSerializer queryset = models.Comment.objects.all() - permission_classes = [permissions.IsAuthenticatedOrReadOnly| IsCommentModerator|IsCountryAdmin] + # permission_classes = [permissions.IsAuthenticatedOrReadOnly| IsCommentModerator|IsCountryAdmin] class CommentRUDView(generics.RetrieveUpdateDestroyAPIView): """Comment RUD view.""" serializer_class = serializers.CommentBaseSerializer queryset = models.Comment.objects.all() - - permission_classes = [IsCountryAdmin | IsCommentModerator] + permission_classes = [IsCommentModerator] + # permission_classes = [IsCountryAdmin | IsCommentModerator] lookup_field = 'id' diff --git a/apps/utils/permissions.py b/apps/utils/permissions.py index a32e302c..321d72d3 100644 --- a/apps/utils/permissions.py +++ b/apps/utils/permissions.py @@ -100,7 +100,10 @@ class IsStandardUser(IsGuest): if hasattr(obj, 'user'): rules = [ - obj.user == request.user and obj.user.email_confirmed, + obj.user == request.user + and obj.user.email_confirmed + and request.user.is_authenticated, + super().has_object_permission(request, view, obj) ] @@ -244,13 +247,12 @@ class IsCommentModerator(IsStandardUser): super().has_permission(request, view) ] - # and request.user.email_confirmed, - if hasattr(request.data, 'user') and hasattr(request.data, 'country_id'): + if any(rules) and hasattr(request.data, 'site_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' + site_id=request.data.site_id) \ + .first() rules = [ UserRole.objects.filter(user=request.user, role=role).exists(), @@ -260,16 +262,22 @@ class IsCommentModerator(IsStandardUser): return any(rules) def has_object_permission(self, request, view, obj): - # Read permissions are allowed to any request. - role = Role.objects.filter(role=Role.COMMENTS_MODERATOR, - country_id=obj.country_id) \ - .first() # 'Comments moderator' rules = [ - UserRole.objects.filter(user=request.user, role=role).exists() and - obj.user != request.user, super().has_object_permission(request, view, obj) ] + + if request.user.is_authenticated: + + role = Role.objects.filter(role=Role.COMMENTS_MODERATOR, + site_id=obj.site_id) \ + .first() # 'Comments moderator' + + rules = [ + UserRole.objects.filter(user=request.user, role=role).exists() and + obj.user != request.user, + super().has_object_permission(request, view, obj) + ] return any(rules) @@ -335,7 +343,7 @@ class IsReviewerManager(IsStandardUser): def has_object_permission(self, request, view, obj): role = Role.objects.filter(role=Role.REVIEWER_MANGER, - country_id=obj.site_id) \ + country_id=obj.country_id) \ .first() rules = [ From 43fc16f8416f765cc4596694f466b68248983d46 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, 25 Nov 2019 12:29:53 +0300 Subject: [PATCH 11/14] Fix country test --- apps/location/tests.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/location/tests.py b/apps/location/tests.py index 3eaefd85..960f7f2b 100644 --- a/apps/location/tests.py +++ b/apps/location/tests.py @@ -25,12 +25,12 @@ class BaseTestCase(APITestCase): {'access_token': tokens.get('access_token'), 'refresh_token': tokens.get('refresh_token')}) - self.lang = Language.objects.get( + self.lang, created = Language.objects.get_or_create( title='Russia', locale='ru-RU' ) - self.country_ru = Country.objects.get( + self.country_ru, created = Country.objects.get_or_create( name={"en-GB": "Russian"} ) @@ -72,7 +72,7 @@ class CountryTests(BaseTestCase): self.assertEqual(response.status_code, status.HTTP_200_OK) update_data = { - 'name': json.dumps({"en-GB": "Test new country"}) + 'name': json.dumps({"ru-RU": "Test new country"}) } response = self.client.patch(f'/api/back/location/countries/{response_data["id"]}/', data=update_data) From 842ad47ec04f6f45ac93c5b56e40e1a5d80439a7 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, 25 Nov 2019 14:34:57 +0300 Subject: [PATCH 12/14] Fix test translated --- apps/utils/tests/tests_translated.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/utils/tests/tests_translated.py b/apps/utils/tests/tests_translated.py index 557c8b5d..7f6f6594 100644 --- a/apps/utils/tests/tests_translated.py +++ b/apps/utils/tests/tests_translated.py @@ -41,7 +41,7 @@ class TranslateFieldTests(BaseTestCase): self.news_type.save() - self.country_ru = Country.objects.get( + self.country_ru, created = Country.objects.get_or_create( name={"en-GB": "Russian"} ) From 08d624db05a226cfb6a1e24761a8907d736c07ad 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, 25 Nov 2019 16:19:38 +0300 Subject: [PATCH 13/14] Fix schedule test and permissions --- apps/establishment/tests.py | 42 +++++++++++++++++++++++++--- apps/utils/permissions.py | 8 ++++-- apps/utils/tests/tests_translated.py | 1 - 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/apps/establishment/tests.py b/apps/establishment/tests.py index 3534608c..833f9b0a 100644 --- a/apps/establishment/tests.py +++ b/apps/establishment/tests.py @@ -10,6 +10,8 @@ from translation.models import Language from account.models import Role, UserRole from location.models import Country, Address, City, Region from pytz import timezone as py_tz +from main.models import SiteSettings +from timetable.models import Timetable class BaseTestCase(APITestCase): @@ -336,24 +338,56 @@ class MenuTests(ChildTestCase): class EstablishmentShedulerTests(ChildTestCase): - def test_shedule_CRUD(self): + def setUp(self): + super().setUp() + + self.lang, created = Language.objects.get_or_create( + title='Russia', + locale='ru-RU' + ) + + self.country_ru, created = Country.objects.get_or_create( + name={"en-GB": "Russian"} + ) + + self.site_ru, created = SiteSettings.objects.get_or_create( + subdomain='ru' + ) + + role, created = Role.objects.get_or_create( + role=Role.ESTABLISHMENT_MANAGER, + country_id=self.country_ru.id, + site_id=self.site_ru.id + ) + + user_role, created = UserRole.objects.get_or_create( + user=self.user, + role=role, + establishment_id=self.establishment.id + ) + user_role.save() + + def test_schedule_CRUD(self): data = { 'weekday': 1 } + response = self.client.post(f'/api/back/establishments/{self.establishment.id}/schedule/', data=data) self.assertEqual(response.status_code, status.HTTP_201_CREATED) + schedule = response.data - response = self.client.get(f'/api/back/establishments/{self.establishment.id}/schedule/1/') + response = self.client.get(f'/api/back/establishments/{self.establishment.id}/schedule/{schedule["id"]}/') self.assertEqual(response.status_code, status.HTTP_200_OK) update_data = { 'weekday': 2 } - response = self.client.patch(f'/api/back/establishments/{self.establishment.id}/schedule/1/', data=update_data) + response = self.client.patch(f'/api/back/establishments/{self.establishment.id}/schedule/{schedule["id"]}/', + data=update_data) self.assertEqual(response.status_code, status.HTTP_200_OK) - response = self.client.delete(f'/api/back/establishments/{self.establishment.id}/schedule/1/') + response = self.client.delete(f'/api/back/establishments/{self.establishment.id}/schedule/{schedule["id"]}/') self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) diff --git a/apps/utils/permissions.py b/apps/utils/permissions.py index 321d72d3..30055c44 100644 --- a/apps/utils/permissions.py +++ b/apps/utils/permissions.py @@ -304,7 +304,9 @@ class IsEstablishmentManager(IsStandardUser): def has_object_permission(self, request, view, obj): rules = [ - super().has_object_permission(request, view, obj) + # special! + super().has_permission(request, view) + # super().has_object_permission(request, view, obj) ] role = Role.objects.filter(role=Role.ESTABLISHMENT_MANAGER) \ @@ -315,7 +317,9 @@ class IsEstablishmentManager(IsStandardUser): UserRole.objects.filter(user=request.user, role=role, establishment_id=obj.establishment_id ).exists(), - super().has_object_permission(request, view, obj) + # special! + super().has_permission(request, view) + # super().has_object_permission(request, view, obj) ] return any(rules) diff --git a/apps/utils/tests/tests_translated.py b/apps/utils/tests/tests_translated.py index 7f6f6594..6249ebd1 100644 --- a/apps/utils/tests/tests_translated.py +++ b/apps/utils/tests/tests_translated.py @@ -40,7 +40,6 @@ class TranslateFieldTests(BaseTestCase): self.news_type = NewsType.objects.create(name="Test news type") self.news_type.save() - self.country_ru, created = Country.objects.get_or_create( name={"en-GB": "Russian"} ) From 82d3b152c77e386b4871938fbaee087dc928e620 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, 25 Nov 2019 16:46:53 +0300 Subject: [PATCH 14/14] Fix test --- apps/establishment/tests.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/establishment/tests.py b/apps/establishment/tests.py index 833f9b0a..743245d8 100644 --- a/apps/establishment/tests.py +++ b/apps/establishment/tests.py @@ -280,13 +280,13 @@ class PlateTests(ChildTestCase): self.assertEqual(response.status_code, status.HTTP_200_OK) menu = Menu.objects.create( - category=json.dumps({"en-GB": "Test category"}), + category=json.dumps({"ru-RU": "Test category"}), establishment=self.establishment ) currency = Currency.objects.create(name="Test currency") data = { - 'name': json.dumps({"en-GB": "Test plate"}), + 'name': json.dumps({"ru-RU": "Test plate"}), 'establishment': self.establishment.id, 'price': 10, 'menu': menu.id, @@ -300,7 +300,7 @@ class PlateTests(ChildTestCase): self.assertEqual(response.status_code, status.HTTP_200_OK) update_data = { - 'name': json.dumps({"en-GB": "Test new plate"}) + 'name': json.dumps({"ru-RU": "Test new plate"}) } response = self.client.patch('/api/back/establishments/plates/1/', data=update_data) @@ -316,7 +316,7 @@ class MenuTests(ChildTestCase): self.assertEqual(response.status_code, status.HTTP_200_OK) data = { - 'category': json.dumps({"en-GB": "Test category"}), + 'category': json.dumps({"ru-RU": "Test category"}), 'establishment': self.establishment.id } @@ -327,7 +327,7 @@ class MenuTests(ChildTestCase): self.assertEqual(response.status_code, status.HTTP_200_OK) update_data = { - 'category': json.dumps({"en-GB": "Test new category"}) + 'category': json.dumps({"ru-RU": "Test new category"}) } response = self.client.patch('/api/back/establishments/menus/1/', data=update_data)