Merge branch 'feature/permission' into 'develop'

Feature/permission

See merge request gm/gm-backend!156
This commit is contained in:
d.kuzmenko 2019-11-25 14:07:00 +00:00
commit 357b3fdaa5
20 changed files with 278 additions and 108 deletions

View File

@ -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'),
),
]

View File

@ -46,10 +46,8 @@ class Role(ProjectBaseMixin):
null=False, blank=False) null=False, blank=False)
country = models.ForeignKey(Country, verbose_name=_('Country'), country = models.ForeignKey(Country, verbose_name=_('Country'),
null=True, blank=True, on_delete=models.SET_NULL) null=True, blank=True, on_delete=models.SET_NULL)
# is_list = models.BooleanField(verbose_name=_('list'), default=True, null=False) site = models.ForeignKey(SiteSettings, verbose_name=_('Site settings'),
# is_create = models.BooleanField(verbose_name=_('create'), default=False, null=False) null=True, blank=True, on_delete=models.SET_NULL)
# is_update = models.BooleanField(verbose_name=_('update'), default=False, null=False)
# is_delete = models.BooleanField(verbose_name=_('delete'), default=False, null=False)
class UserManager(BaseUserManager): class UserManager(BaseUserManager):

View File

@ -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'),
),
]

View File

@ -35,7 +35,8 @@ class Comment(ProjectBaseMixin):
user = models.ForeignKey('account.User', related_name='comments', on_delete=models.CASCADE, verbose_name=_('User')) 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) old_id = models.IntegerField(null=True, blank=True, default=None)
is_publish = models.BooleanField(default=False, verbose_name=_('Publish status')) 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) content_type = models.ForeignKey(generic.ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField() object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id') content_object = generic.GenericForeignKey('content_type', 'object_id')

View File

@ -8,15 +8,20 @@ from account.models import Role, User, UserRole
from authorization.tests.tests_authorization import get_tokens_for_user from authorization.tests.tests_authorization import get_tokens_for_user
from comment.models import Comment from comment.models import Comment
from utils.tests.tests_permissions import BasePermissionTests from utils.tests.tests_permissions import BasePermissionTests
from main.models import SiteSettings
class CommentModeratorPermissionTests(BasePermissionTests): class CommentModeratorPermissionTests(BasePermissionTests):
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.site_ru, created = SiteSettings.objects.get_or_create(
subdomain='ru'
)
self.role = Role.objects.create( self.role = Role.objects.create(
role=2, role=2,
country=self.country_ru site=self.site_ru
) )
self.role.save() self.role.save()
@ -33,11 +38,12 @@ class CommentModeratorPermissionTests(BasePermissionTests):
self.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=self.content_type.id, content_type_id=self.content_type.id,
country=self.country_ru site=self.site_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})
@ -50,7 +56,7 @@ class CommentModeratorPermissionTests(BasePermissionTests):
"user": self.user_test["user"].id, "user": self.user_test["user"].id,
"object_id": self.country_ru.pk, "object_id": self.country_ru.pk,
"content_type": self.content_type.id, "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) response = self.client.post(self.url, format='json', data=comment)
@ -61,7 +67,7 @@ class CommentModeratorPermissionTests(BasePermissionTests):
"user": self.moderator.id, "user": self.moderator.id,
"object_id": self.country_ru.id, "object_id": self.country_ru.id,
"content_type": self.content_type.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) tokens = User.create_jwt_tokens(self.moderator)
@ -83,8 +89,9 @@ class CommentModeratorPermissionTests(BasePermissionTests):
"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, "object_id": self.country_ru.id,
"content_type": self.content_type.id "content_type": self.content_type.id,
'site_id': self.site_ru.id
} }
response = self.client.put(self.url, data=data, format='json') response = self.client.put(self.url, data=data, format='json')

View File

@ -8,13 +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| IsCommentModerator|IsCountryAdmin] # 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 = [IsCommentModerator]
permission_classes = [IsCountryAdmin | IsCommentModerator] # permission_classes = [IsCountryAdmin | IsCommentModerator]
lookup_field = 'id' lookup_field = 'id'

View File

@ -10,6 +10,8 @@ from translation.models import Language
from account.models import Role, UserRole from account.models import Role, UserRole
from location.models import Country, Address, City, Region from location.models import Country, Address, City, Region
from pytz import timezone as py_tz from pytz import timezone as py_tz
from main.models import SiteSettings
from timetable.models import Timetable
class BaseTestCase(APITestCase): class BaseTestCase(APITestCase):
@ -278,13 +280,13 @@ class PlateTests(ChildTestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
menu = Menu.objects.create( menu = Menu.objects.create(
category=json.dumps({"en-GB": "Test category"}), category=json.dumps({"ru-RU": "Test category"}),
establishment=self.establishment establishment=self.establishment
) )
currency = Currency.objects.create(name="Test currency") currency = Currency.objects.create(name="Test currency")
data = { data = {
'name': json.dumps({"en-GB": "Test plate"}), 'name': json.dumps({"ru-RU": "Test plate"}),
'establishment': self.establishment.id, 'establishment': self.establishment.id,
'price': 10, 'price': 10,
'menu': menu.id, 'menu': menu.id,
@ -298,7 +300,7 @@ class PlateTests(ChildTestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
update_data = { 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) response = self.client.patch('/api/back/establishments/plates/1/', data=update_data)
@ -314,7 +316,7 @@ class MenuTests(ChildTestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
data = { data = {
'category': json.dumps({"en-GB": "Test category"}), 'category': json.dumps({"ru-RU": "Test category"}),
'establishment': self.establishment.id 'establishment': self.establishment.id
} }
@ -325,7 +327,7 @@ class MenuTests(ChildTestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
update_data = { 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) response = self.client.patch('/api/back/establishments/menus/1/', data=update_data)
@ -336,24 +338,56 @@ class MenuTests(ChildTestCase):
class EstablishmentShedulerTests(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 = { data = {
'weekday': 1 'weekday': 1
} }
response = self.client.post(f'/api/back/establishments/{self.establishment.id}/schedule/', data=data) response = self.client.post(f'/api/back/establishments/{self.establishment.id}/schedule/', data=data)
self.assertEqual(response.status_code, status.HTTP_201_CREATED) 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) self.assertEqual(response.status_code, status.HTTP_200_OK)
update_data = { update_data = {
'weekday': 2 '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) 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) self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)

View File

@ -25,12 +25,12 @@ class BaseTestCase(APITestCase):
{'access_token': tokens.get('access_token'), {'access_token': tokens.get('access_token'),
'refresh_token': tokens.get('refresh_token')}) 'refresh_token': tokens.get('refresh_token')})
self.lang = Language.objects.get( self.lang, created = Language.objects.get_or_create(
title='Russia', title='Russia',
locale='ru-RU' locale='ru-RU'
) )
self.country_ru = Country.objects.get( self.country_ru, created = Country.objects.get_or_create(
name={"en-GB": "Russian"} name={"en-GB": "Russian"}
) )
@ -72,7 +72,7 @@ class CountryTests(BaseTestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
update_data = { 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) response = self.client.patch(f'/api/back/location/countries/{response_data["id"]}/', data=update_data)

View File

@ -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'),
),
]

View File

@ -204,7 +204,8 @@ class News(GalleryModelMixin, BaseAttributes, TranslatedFieldsMixin, HasTagsMixi
banner = models.ForeignKey('news.NewsBanner', blank=True, null=True, banner = models.ForeignKey('news.NewsBanner', blank=True, null=True,
on_delete=models.SET_NULL, on_delete=models.SET_NULL,
verbose_name=_('banner')) 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() objects = NewsQuerySet.as_manager()
class Meta: class Meta:

View File

@ -5,6 +5,7 @@ from rest_framework.fields import SerializerMethodField
from account.serializers.common import UserBaseSerializer from account.serializers.common import UserBaseSerializer
from gallery.models import Image from gallery.models import Image
from main.models import SiteSettings
from location import models as location_models from location import models as location_models
from location.serializers import CountrySimpleSerializer, AddressBaseSerializer from location.serializers import CountrySimpleSerializer, AddressBaseSerializer
from news import models from news import models
@ -80,7 +81,6 @@ class NewsBaseSerializer(ProjectModelSerializer):
'news_type', 'news_type',
'tags', 'tags',
'slug', 'slug',
'in_favorites',
'view_counter', 'view_counter',
) )
@ -184,6 +184,9 @@ class NewsBackOfficeDetailSerializer(NewsBackOfficeBaseSerializer,
country_id = serializers.PrimaryKeyRelatedField( country_id = serializers.PrimaryKeyRelatedField(
source='country', write_only=True, source='country', write_only=True,
queryset=location_models.Country.objects.all()) 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', template_display = serializers.CharField(source='get_template_display',
read_only=True) read_only=True)
@ -195,6 +198,7 @@ class NewsBackOfficeDetailSerializer(NewsBackOfficeBaseSerializer,
'description', 'description',
'news_type_id', 'news_type_id',
'country_id', 'country_id',
'site_id',
'template', 'template',
'template_display', 'template_display',
) )

View File

@ -5,6 +5,7 @@ from rest_framework.test import APITestCase
from rest_framework import status from rest_framework import status
from datetime import datetime, timedelta from datetime import datetime, timedelta
from main.models import SiteSettings
from news.models import NewsType, News from news.models import NewsType, News
from account.models import User, Role, UserRole from account.models import User, Role, UserRole
from translation.models import Language from translation.models import Language
@ -30,18 +31,23 @@ class BaseTestCase(APITestCase):
'refresh_token': tokens.get('refresh_token')}) 'refresh_token': tokens.get('refresh_token')})
self.test_news_type = NewsType.objects.create(name="Test news type") self.test_news_type = NewsType.objects.create(name="Test news type")
self.lang = Language.objects.create(
self.lang, created = Language.objects.get_or_create(
title='Russia', title='Russia',
locale='ru-RU' locale='ru-RU'
) )
self.country_ru = Country.objects.create( self.country_ru, created = Country.objects.get_or_create(
name={"en-GB": "Russian"} name={"en-GB": "Russian"}
) )
self.site_ru, created = SiteSettings.objects.get_or_create(
subdomain='ru'
)
role = Role.objects.create( role = Role.objects.create(
role=Role.CONTENT_PAGE_MANAGER, role=Role.CONTENT_PAGE_MANAGER,
country=self.country_ru site_id=self.site_ru.id
) )
role.save() role.save()
@ -51,16 +57,18 @@ class BaseTestCase(APITestCase):
) )
user_role.save() user_role.save()
self.test_news = News.objects.create( self.test_news = News.objects.create(
created_by=self.user, modified_by=self.user, created_by=self.user, modified_by=self.user,
title={"en-GB": "Test news"}, title={"ru-RU": "Test news"},
news_type=self.test_news_type, news_type=self.test_news_type,
description={"en-GB": "Description test news"}, description={"ru-RU": "Description test news"},
start=datetime.now() + timedelta(hours=-2), start=datetime.now() + timedelta(hours=-2),
end=datetime.now() + timedelta(hours=2), end=datetime.now() + timedelta(hours=2),
state=News.PUBLISHED, state=News.PUBLISHED,
slug='test-news-slug', slug='test-news-slug',
country=self.country_ru, country=self.country_ru,
site=self.site_ru
) )
@ -70,14 +78,15 @@ class NewsTestCase(BaseTestCase):
def test_news_post(self): def test_news_post(self):
test_news = { test_news = {
"title": {"en-GB": "Test news POST"}, "title": {"ru-RU": "Test news POST"},
"news_type_id": self.test_news_type.id, "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), "start": datetime.now() + timedelta(hours=-2),
"end": datetime.now() + timedelta(hours=2), "end": datetime.now() + timedelta(hours=2),
"state": News.PUBLISHED, "state": News.PUBLISHED,
"slug": 'test-news-slug_post', "slug": 'test-news-slug_post',
"country_id": self.country_ru.id, "country_id": self.country_ru.id,
"site_id": self.site_ru.id
} }
url = reverse("back:news:list-create") url = reverse("back:news:list-create")
@ -107,11 +116,12 @@ class NewsTestCase(BaseTestCase):
url = reverse('back:news:retrieve-update-destroy', kwargs={'pk': self.test_news.id}) url = reverse('back:news:retrieve-update-destroy', kwargs={'pk': self.test_news.id})
data = { data = {
'id': self.test_news.id, 'id': self.test_news.id,
'description': {"en-GB": "Description test news!"}, 'description': {"ru-RU": "Description test news!"},
'slug': self.test_news.slug, 'slug': self.test_news.slug,
'start': self.test_news.start, 'start': self.test_news.start,
'news_type_id': self.test_news.news_type_id, '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') response = self.client.put(url, data=data, format='json')

View File

@ -84,6 +84,7 @@ class NewsBackOfficeLCView(NewsBackOfficeMixinView,
serializer_class = serializers.NewsBackOfficeBaseSerializer serializer_class = serializers.NewsBackOfficeBaseSerializer
filter_class = filters.NewsListFilterSet filter_class = filters.NewsListFilterSet
create_serializers_class = serializers.NewsBackOfficeDetailSerializer create_serializers_class = serializers.NewsBackOfficeDetailSerializer
permission_classes = [IsCountryAdmin | IsContentPageManager] permission_classes = [IsCountryAdmin | IsContentPageManager]
def get_serializer_class(self): def get_serializer_class(self):

View File

@ -13,6 +13,7 @@ class BackPartnerSerializer(serializers.ModelSerializer):
'url', 'url',
'image', 'image',
'establishment', 'establishment',
'establishment_id',
'type', 'type',
'starting_date', 'starting_date',
'expiry_date', 'expiry_date',

View File

@ -20,6 +20,8 @@ class ScheduleRUDSerializer(serializers.ModelSerializer):
dinner_end = serializers.TimeField(required=False) dinner_end = serializers.TimeField(required=False)
opening_at = serializers.TimeField(required=False) opening_at = serializers.TimeField(required=False)
closed_at = serializers.TimeField(required=False) closed_at = serializers.TimeField(required=False)
# For permission!!
establishment_id = serializers.ReadOnlyField(source='establishment.id')
class Meta: class Meta:
"""Meta class.""" """Meta class."""
@ -34,6 +36,7 @@ class ScheduleRUDSerializer(serializers.ModelSerializer):
'dinner_end', 'dinner_end',
'opening_at', 'opening_at',
'closed_at', 'closed_at',
'establishment_id'
] ]
def validate(self, attrs): def validate(self, attrs):

View File

@ -36,10 +36,6 @@ class ProjectBaseMixin(models.Model):
abstract = True abstract = True
def valid(value):
print("Run")
class TJSONField(JSONField): class TJSONField(JSONField):
"""Overrided JsonField.""" """Overrided JsonField."""

View File

@ -100,7 +100,10 @@ class IsStandardUser(IsGuest):
if hasattr(obj, 'user'): if hasattr(obj, 'user'):
rules = [ 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) super().has_object_permission(request, view, obj)
] ]
@ -117,31 +120,50 @@ class IsContentPageManager(IsStandardUser):
rules = [ rules = [
super().has_permission(request, view) super().has_permission(request, view)
] ]
# and request.user.email_confirmed,
if hasattr(request, 'user'): if hasattr(request, 'user'):
if hasattr(request.data, 'site_id'):
role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER, role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER,
country_id=request.country_id) \ site_id=request.data.site_id,) \
.first() # 'Comments moderator' .first()
rules = [ rules = [
UserRole.objects.filter(user=request.user, role=role).exists(), UserRole.objects.filter(user=request.user, role=role).exists(),
# and obj.user != request.user,
super().has_permission(request, view) 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) 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.
if hasattr(obj, 'site_id'):
role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER, role = Role.objects.filter(role=Role.CONTENT_PAGE_MANAGER,
country_id=obj.country_id) \ site_id=obj.site_id) \
.first() # 'Comments moderator' .first()
rules = [ rules = [
UserRole.objects.filter(user=request.user, role=role).exists(), UserRole.objects.filter(user=request.user, role=role).exists(),
# and obj.user != request.user,
super().has_object_permission(request, view, obj) 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)
]
return any(rules) return any(rules)
@ -150,19 +172,29 @@ 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): def has_permission(self, request, view):
rules = [ rules = [
super().has_permission(request, view) super().has_permission(request, view)
] ]
# and request.user.email_confirmed, # and request.user.email_confirmed,
if hasattr(request.data, 'user') and hasattr(request.data, 'country_id'): if hasattr(request.data, 'user'):
if hasattr(request.data, 'site_id'):
# Read permissions are allowed to any request. # 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, role = Role.objects.filter(role=Role.COUNTRY_ADMIN,
country_id=request.data.country_id) \ country_id=request.data.country_id) \
.first() # 'Comments moderator' .first()
rules = [ rules = [
UserRole.objects.filter(user=request.user, role=role).exists(), UserRole.objects.filter(user=request.user, role=role).exists(),
@ -172,14 +204,23 @@ 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 hasattr(obj, 'site_id'):
role = Role.objects.filter(role=Role.COUNTRY_ADMIN, role = Role.objects.filter(role=Role.COUNTRY_ADMIN,
country_id=obj.country_id) \ site_id=obj.site_id) \
.first() # 'Comments moderator' .first()
rules = [ rules = [
super().has_object_permission(request, view, obj) super().has_object_permission(request, view, obj)
] ]
# and request.user.email_confirmed, 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)
]
if hasattr(request, 'user') and request.user.is_authenticated: 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(),
@ -206,13 +247,12 @@ class IsCommentModerator(IsStandardUser):
super().has_permission(request, view) super().has_permission(request, view)
] ]
# and request.user.email_confirmed, if any(rules) and hasattr(request.data, 'site_id'):
if hasattr(request.data, 'user') and hasattr(request.data, 'country_id'):
# 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=request.data.country_id) \ site_id=request.data.site_id) \
.first() # 'Comments moderator' .first()
rules = [ rules = [
UserRole.objects.filter(user=request.user, role=role).exists(), UserRole.objects.filter(user=request.user, role=role).exists(),
@ -222,9 +262,15 @@ class IsCommentModerator(IsStandardUser):
return any(rules) 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.
rules = [
super().has_object_permission(request, view, obj)
]
if request.user.is_authenticated:
role = Role.objects.filter(role=Role.COMMENTS_MODERATOR, role = Role.objects.filter(role=Role.COMMENTS_MODERATOR,
country_id=obj.country_id) \ site_id=obj.site_id) \
.first() # 'Comments moderator' .first() # 'Comments moderator'
rules = [ rules = [
@ -242,10 +288,10 @@ class IsEstablishmentManager(IsStandardUser):
super().has_permission(request, view) super().has_permission(request, view)
] ]
# and request.user.email_confirmed, if hasattr(request.data, 'user'):
if hasattr(request.data, 'user') and hasattr(request.data, 'establishment_id'): if hasattr(request.data, 'establishment_id'):
role = Role.objects.filter(role=Role.ESTABLISHMENT_MANAGER) \ role = Role.objects.filter(role=Role.ESTABLISHMENT_MANAGER) \
.first() # 'Comments moderator' .first()
rules = [ rules = [
UserRole.objects.filter(user=request.user, role=role, UserRole.objects.filter(user=request.user, role=role,
@ -256,14 +302,24 @@ class IsEstablishmentManager(IsStandardUser):
return any(rules) 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) \
.first() # 'Comments moderator'
rules = [
# special!
super().has_permission(request, view)
# super().has_object_permission(request, view, obj)
]
role = Role.objects.filter(role=Role.ESTABLISHMENT_MANAGER) \
.first()
if hasattr(obj, 'establishment_id'):
rules = [ rules = [
UserRole.objects.filter(user=request.user, role=role, UserRole.objects.filter(user=request.user, role=role,
establishment_id=obj.establishment_id establishment_id=obj.establishment_id
).exists(), ).exists(),
super().has_object_permission(request, view, obj) # special!
super().has_permission(request, view)
# super().has_object_permission(request, view, obj)
] ]
return any(rules) return any(rules)
@ -277,13 +333,13 @@ class IsReviewerManager(IsStandardUser):
] ]
# and request.user.email_confirmed, # 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) \ role = Role.objects.filter(role=Role.REVIEWER_MANGER) \
.first() # 'Comments moderator' .first()
rules = [ rules = [
UserRole.objects.filter(user=request.user, role=role, UserRole.objects.filter(user=request.user, role=role,
establishment_id=request.data.country_id establishment_id=request.data.site_id
).exists(), ).exists(),
super().has_permission(request, view) super().has_permission(request, view)
] ]

View File

@ -5,15 +5,13 @@ from translation.models import Language
class BasePermissionTests(APITestCase): class BasePermissionTests(APITestCase):
def setUp(self): def setUp(self):
self.lang = Language.objects.get( self.lang, created = Language.objects.get_or_create(
title='Russia', title='Russia',
locale='ru-RU' 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"} name={"en-GB": "Russian"}
) )
self.country_ru.save()

View File

@ -40,8 +40,7 @@ class TranslateFieldTests(BaseTestCase):
self.news_type = NewsType.objects.create(name="Test news type") self.news_type = NewsType.objects.create(name="Test news type")
self.news_type.save() self.news_type.save()
self.country_ru, created = Country.objects.get_or_create(
self.country_ru = Country.objects.get(
name={"en-GB": "Russian"} name={"en-GB": "Russian"}
) )

View File

@ -30,7 +30,7 @@ MEDIA_ROOT = os.path.join(PUBLIC_ROOT, MEDIA_LOCATION)
THUMBNAIL_DEBUG = True THUMBNAIL_DEBUG = True
# ADDED TRANSFER APP # ADDED TRANSFER APP
INSTALLED_APPS.append('transfer.apps.TransferConfig') # INSTALLED_APPS.append('transfer.apps.TransferConfig')
# DATABASES # DATABASES
DATABASES.update({ DATABASES.update({
@ -93,6 +93,7 @@ ELASTICSEARCH_INDEX_NAMES = {
'search_indexes.documents.establishment': 'local_establishment', 'search_indexes.documents.establishment': 'local_establishment',
'search_indexes.documents.product': 'local_product', 'search_indexes.documents.product': 'local_product',
} }
ELASTICSEARCH_DSL_AUTOSYNC = False
TESTING = sys.argv[1:2] == ['test'] TESTING = sys.argv[1:2] == ['test']
if TESTING: if TESTING: