refactored roles

This commit is contained in:
Anatoly 2020-01-30 12:50:14 +03:00
parent 25c63b8097
commit ca5440d431
9 changed files with 66 additions and 79 deletions

View File

@ -1,6 +1,7 @@
"""Account models""" """Account models"""
from collections import Counter from collections import Counter
from datetime import datetime from datetime import datetime
from typing import List
from django.conf import settings from django.conf import settings
from django.contrib.auth.models import AbstractUser, UserManager as BaseUserManager from django.contrib.auth.models import AbstractUser, UserManager as BaseUserManager
@ -15,8 +16,6 @@ from django.utils.http import urlsafe_base64_encode
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from phonenumber_field.modelfields import PhoneNumberField from phonenumber_field.modelfields import PhoneNumberField
from rest_framework.authtoken.models import Token from rest_framework.authtoken.models import Token
from collections import Counter
from typing import List
from authorization.models import Application from authorization.models import Application
from establishment.models import Establishment, EstablishmentSubType from establishment.models import Establishment, EstablishmentSubType
@ -74,16 +73,6 @@ class Role(ProjectBaseMixin):
(ARTISAN_INSPECTOR, _('Artisan inspector')), (ARTISAN_INSPECTOR, _('Artisan inspector')),
) )
ESTABLISHMENT_EDITORS = [
COUNTRY_ADMIN,
ESTABLISHMENT_MANAGER,
ESTABLISHMENT_ADMINISTRATOR,
]
PRODUCT_EDITORS = ESTABLISHMENT_EDITORS + [
DISTILLERY_LIQUOR_INSPECTOR
]
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)
country = models.ForeignKey(Country, verbose_name=_('Country'), country = models.ForeignKey(Country, verbose_name=_('Country'),

View File

@ -14,7 +14,7 @@ from django.contrib.postgres.fields import ArrayField
from django.contrib.postgres.indexes import GinIndex from django.contrib.postgres.indexes import GinIndex
from django.contrib.postgres.search import TrigramSimilarity from django.contrib.postgres.search import TrigramSimilarity
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import MinValueValidator, MaxValueValidator, FileExtensionValidator from django.core.validators import MinValueValidator, MaxValueValidator
from django.db import models from django.db import models
from django.db.models import When, Case, F, ExpressionWrapper, Subquery, Q, Prefetch from django.db.models import When, Case, F, ExpressionWrapper, Subquery, Q, Prefetch
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
@ -519,27 +519,22 @@ class EstablishmentQuerySet(models.QuerySet):
to_attr='main_image') to_attr='main_image')
) )
def available_establishments(self, user): def available_establishments(self, user, country_code: str):
"""Return QuerySet with establishment that user has an access.""" """Return QuerySet with establishments that user has an access."""
from account.models import UserRole from account.models import UserRole
administrator_establishment_ids = []
filters = {}
# put in array administrated establishment ids
if user.is_establishment_administrator:
administrator_establishment_ids.extend(
UserRole.objects.filter(user=user)
.distinct('user', 'establishment')
.values_list('establishment', flat=True)
)
# check if user is_staff
if not user.is_staff: if not user.is_staff:
filters.update({'address__city__country__code__in': user.administrated_country_codes}) filters = {'address__city__country__code': country_code}
if user.is_establishment_administrator and not user.is_establishment_manager:
return self.filter(**filters).union( filters.update({
self.filter(id__in=administrator_establishment_ids) 'id__in': models.Subquery(
) UserRole.objects.filter(user=user, role__site__country__code=country_code)
.distinct('user', 'establishment')
.values_list('establishment', flat=True)
)
})
return self.filter(**filters)
return self
def with_contacts(self): def with_contacts(self):
return self.prefetch_related('emails', 'phones') return self.prefetch_related('emails', 'phones')

View File

@ -3,7 +3,7 @@ from django.db.models.query_utils import Q
from django.http import Http404 from django.http import Http404
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django_filters.rest_framework import DjangoFilterBackend from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import generics, status, permissions from rest_framework import generics, status
from rest_framework.response import Response from rest_framework.response import Response
from account.models import User from account.models import User
@ -13,8 +13,7 @@ from timetable.models import Timetable
from timetable.serialziers import ScheduleCreateSerializer, ScheduleRUDSerializer from timetable.serialziers import ScheduleCreateSerializer, ScheduleRUDSerializer
from utils.methods import get_permission_classes from utils.methods import get_permission_classes
from utils.permissions import ( from utils.permissions import (
IsEstablishmentManager, IsEstablishmentAdministrator, IsReviewManager, IsEstablishmentManager, IsEstablishmentAdministrator, )
)
from utils.views import CreateDestroyGalleryViewMixin from utils.views import CreateDestroyGalleryViewMixin
@ -40,7 +39,7 @@ class EstablishmentMixinViews:
queryset = models.Establishment.objects.with_base_related queryset = models.Establishment.objects.with_base_related
if hasattr(self, 'request') and \ if hasattr(self, 'request') and \
(hasattr(self.request, 'user') and hasattr(self.request, 'country_code')): (hasattr(self.request, 'user') and hasattr(self.request, 'country_code')):
return queryset().available_establishments(self.request.user) return queryset().available_establishments(self.request.user, self.request.country_code)
return queryset().none() return queryset().none()

View File

@ -1,15 +1,16 @@
"""News app models.""" """News app models."""
import uuid import uuid
from datetime import datetime
import elasticsearch_dsl import elasticsearch_dsl
from django.conf import settings from django.conf import settings
from django.contrib.contenttypes import fields as generic from django.contrib.contenttypes import fields as generic
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.postgres.fields import HStoreField from django.contrib.postgres.fields import HStoreField
from django.contrib.postgres.search import TrigramSimilarity
from django.db import models from django.db import models
from django.db.models import Case, When, Q, F from django.db.models import Case, When, Q, F
from django.db.models.functions import Cast from django.db.models.functions import Cast
from django.contrib.postgres.search import TrigramSimilarity
from django.urls.exceptions import NoReverseMatch from django.urls.exceptions import NoReverseMatch
from django.utils import timezone from django.utils import timezone
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -21,7 +22,6 @@ from utils.models import (BaseAttributes, TJSONField, TranslatedFieldsMixin, Has
ProjectBaseMixin, GalleryMixin, IntermediateGalleryModelMixin, ProjectBaseMixin, GalleryMixin, IntermediateGalleryModelMixin,
FavoritesMixin, TypeDefaultImageMixin) FavoritesMixin, TypeDefaultImageMixin)
from utils.querysets import TranslationQuerysetMixin from utils.querysets import TranslationQuerysetMixin
from datetime import datetime
class Agenda(ProjectBaseMixin, TranslatedFieldsMixin): class Agenda(ProjectBaseMixin, TranslatedFieldsMixin):
@ -244,6 +244,10 @@ class NewsQuerySet(TranslationQuerysetMixin):
'subtitle_similarity')) 'subtitle_similarity'))
).filter(relevance__gte=0.3).order_by('-relevance') ).filter(relevance__gte=0.3).order_by('-relevance')
def available_news(self, user, country_code: str):
"""Return QuerySet with news that user has an access."""
return self.filter(site__country__code=country_code) if not user.is_staff else self
class News(GalleryMixin, BaseAttributes, TranslatedFieldsMixin, HasTagsMixin, class News(GalleryMixin, BaseAttributes, TranslatedFieldsMixin, HasTagsMixin,
FavoritesMixin): FavoritesMixin):

View File

@ -129,11 +129,18 @@ class NewsBackOfficeMixinView:
permission_classes = get_permission_classes(IsContentPageManager, IsContentPageManager) permission_classes = get_permission_classes(IsContentPageManager, IsContentPageManager)
def get_queryset(self): def get_queryset(self):
"""Override get_queryset method.""" """Overridden get_queryset method."""
qs = models.News.objects.with_base_related() \ queryset = models.News.objects
.annotate_in_favorites(self.request.user) \ if hasattr(self, 'request') and \
.order_by('-is_highlighted', '-created') (hasattr(self.request, 'user') and hasattr(self.request, 'country_code')):
return qs user = self.request.user
return (
queryset.with_base_related()
.annotate_in_favorites(user)
.available_news(user, self.request.country_code)
.order_by('-is_highlighted', '-created')
)
return queryset.none()
class NewsBackOfficeLCView(NewsBackOfficeMixinView, class NewsBackOfficeLCView(NewsBackOfficeMixinView,
@ -165,8 +172,6 @@ class NewsBackOfficeLCView(NewsBackOfficeMixinView,
self.request.query_params['ordering'] = self.request.query_params['ordering']\ self.request.query_params['ordering'] = self.request.query_params['ordering']\
.replace('publication_datetime', 'publication_date,publication_time') .replace('publication_datetime', 'publication_date,publication_time')
self.request.GET._mutable = False self.request.GET._mutable = False
if self.request.country_code:
qs = qs.by_country_code(self.request.country_code)
return qs return qs

View File

@ -17,24 +17,24 @@ class PartnerLstView(generics.ListCreateAPIView):
queryset = Partner.objects.with_base_related() queryset = Partner.objects.with_base_related()
serializer_class = serializers.BackPartnerSerializer serializer_class = serializers.BackPartnerSerializer
pagination_class = None pagination_class = None
filter_class = filters.PartnerFilterSet
permission_classes = get_permission_classes( permission_classes = get_permission_classes(
IsEstablishmentManager, IsEstablishmentManager,
IsEstablishmentAdministrator IsEstablishmentAdministrator
) )
filter_class = filters.PartnerFilterSet
class EstablishmentPartners(generics.ListAPIView): class EstablishmentPartners(generics.ListAPIView):
queryset = PartnerToEstablishment.objects.prefetch_related('partner', 'partner__country') queryset = PartnerToEstablishment.objects.prefetch_related('partner', 'partner__country')
serializer_class = serializers.PartnersForEstablishmentSerializer serializer_class = serializers.PartnersForEstablishmentSerializer
pagination_class = None pagination_class = None
filter_backends = (OrderingFilter, DjangoFilterBackend)
ordering_fields = '__all__'
ordering = '-partner_bind_date'
permission_classes = get_permission_classes( permission_classes = get_permission_classes(
IsEstablishmentManager, IsEstablishmentManager,
IsEstablishmentAdministrator IsEstablishmentAdministrator
) )
filter_backends = (OrderingFilter, DjangoFilterBackend)
ordering_fields = '__all__'
ordering = '-partner_bind_date'
def get_queryset(self): def get_queryset(self):
return super().get_queryset().filter(establishment=self.kwargs['establishment_id']) return super().get_queryset().filter(establishment=self.kwargs['establishment_id'])

View File

@ -227,27 +227,22 @@ class ProductQuerySet(models.QuerySet):
.distinct(*similarity_rules['distinction'], .distinct(*similarity_rules['distinction'],
'id') 'id')
def available_products(self, user): def available_products(self, user, country_code: str):
"""Return QuerySet with establishment that user has an access.""" """Return QuerySet with products that user has an access."""
from account.models import UserRole from account.models import UserRole
administrator_establishment_ids = []
filters = {}
# put in array administrated establishment ids
if user.is_establishment_administrator:
administrator_establishment_ids.extend(
UserRole.objects.filter(user=user)
.distinct('user', 'establishment')
.values_list('establishment', flat=True)
)
# check if user is_staff
if not user.is_staff: if not user.is_staff:
filters.update({'establishment__address__city__country__code__in': user.administrated_country_codes}) filters = {'establishment__address__city__country__code': country_code}
if user.is_establishment_administrator and not user.is_establishment_manager:
return self.filter(**filters).union( filters.update({
self.filter(establishment__id__in=administrator_establishment_ids) 'establishment__id__in': models.Subquery(
) UserRole.objects.filter(user=user, role__site__country__code=country_code)
.distinct('user', 'establishment')
.values_list('establishment', flat=True)
)
})
return self.filter(**filters)
return self
class Product(GalleryMixin, TranslatedFieldsMixin, BaseAttributes, class Product(GalleryMixin, TranslatedFieldsMixin, BaseAttributes,

View File

@ -28,7 +28,7 @@ class ProductBackOfficeMixinView(ProductBaseView):
) )
if hasattr(self, 'request') and \ if hasattr(self, 'request') and \
(hasattr(self.request, 'user') and hasattr(self.request, 'country_code')): (hasattr(self.request, 'user') and hasattr(self.request, 'country_code')):
return queryset.available_products(self.request.user) return queryset.available_products(self.request.user, self.request.country_code)
return queryset.none() return queryset.none()

View File

@ -100,7 +100,7 @@ class IsContentPageManager(IsApprovedUser):
role=Role.CONTENT_PAGE_MANAGER, site__country__code=request.country_code, role=Role.CONTENT_PAGE_MANAGER, site__country__code=request.country_code,
).only('id') ).only('id')
if role.exists(): if role.exists():
user_role = UserRole.objects.filter( user_role = UserRole.objects.validated().filter(
user=request.user, role__id__in=role.values_list('id', flat=True), user=request.user, role__id__in=role.values_list('id', flat=True),
).only('id') ).only('id')
has_permission = True if user_role.exists() else has_permission has_permission = True if user_role.exists() else has_permission
@ -125,7 +125,7 @@ class IsCountryAdmin(IsApprovedUser):
role=Role.COUNTRY_ADMIN, site__country__code=request.country_code, role=Role.COUNTRY_ADMIN, site__country__code=request.country_code,
).only('id') ).only('id')
if role.exists(): if role.exists():
user_role = UserRole.objects.filter( user_role = UserRole.objects.validated().filter(
user=request.user, role__id__in=role.values_list('id', flat=True) user=request.user, role__id__in=role.values_list('id', flat=True)
).only('id') ).only('id')
has_permission = True if user_role.exists() else has_permission has_permission = True if user_role.exists() else has_permission
@ -150,7 +150,7 @@ class IsModerator(IsApprovedUser):
role=Role.MODERATOR, site__country__code=request.country_code, role=Role.MODERATOR, site__country__code=request.country_code,
).only('id') ).only('id')
if role.exists(): if role.exists():
user_role = UserRole.objects.filter( user_role = UserRole.objects.validated().filter(
user=request.user, role__id__in=role.values_list('id', flat=True), user=request.user, role__id__in=role.values_list('id', flat=True),
).only('id') ).only('id')
has_permission = True if user_role.exists() else has_permission has_permission = True if user_role.exists() else has_permission
@ -173,7 +173,7 @@ class IsEstablishmentManager(IsApprovedUser):
role=Role.ESTABLISHMENT_MANAGER, site__country__code=request.country_code, role=Role.ESTABLISHMENT_MANAGER, site__country__code=request.country_code,
).only('id') ).only('id')
if role.exists(): if role.exists():
user_role = UserRole.objects.filter( user_role = UserRole.objects.validated().filter(
user=user, role__id__in=role.values_list('id', flat=True), user=user, role__id__in=role.values_list('id', flat=True),
).only('id') ).only('id')
has_permission = True if user_role.exists() else has_permission has_permission = True if user_role.exists() else has_permission
@ -195,7 +195,7 @@ class IsEstablishmentAdministrator(IsApprovedUser):
role=Role.ESTABLISHMENT_ADMINISTRATOR, site__country__code=request.country_code, role=Role.ESTABLISHMENT_ADMINISTRATOR, site__country__code=request.country_code,
).only('id') ).only('id')
if role.exists(): if role.exists():
user_role = UserRole.objects.filter( user_role = UserRole.objects.validated().filter(
user=request.user, role__id__in=role.values_list('id', flat=True), user=request.user, role__id__in=role.values_list('id', flat=True),
).only('id') ).only('id')
has_permission = True if user_role.exists() else has_permission has_permission = True if user_role.exists() else has_permission
@ -218,7 +218,7 @@ class IsEstablishmentAdministrator(IsApprovedUser):
if isinstance(obj, Product): if isinstance(obj, Product):
filters.update({'establishment__products__id': obj.id}) filters.update({'establishment__products__id': obj.id})
user_role = UserRole.objects.filter(**filters) user_role = UserRole.objects.validated().filter(**filters)
has_object_permission = True if user_role.exists() else has_object_permission has_object_permission = True if user_role.exists() else has_object_permission
rules.append(has_object_permission) rules.append(has_object_permission)
return all(rules) return all(rules)
@ -243,7 +243,7 @@ class IsReviewManager(IsApprovedUser):
role=Role.REVIEW_MANAGER, site__country__code=request.country_code, role=Role.REVIEW_MANAGER, site__country__code=request.country_code,
).only('id') ).only('id')
if role.exists(): if role.exists():
user_role = UserRole.objects.filter( user_role = UserRole.objects.validated().filter(
user=request.user, role__id__in=role.values_list('id', flat=True), user=request.user, role__id__in=role.values_list('id', flat=True),
).only('id') ).only('id')
if user_role.exists(): if user_role.exists():
@ -276,7 +276,7 @@ class IsRestaurantInspector(IsApprovedUser):
role=Role.RESTAURANT_INSPECTOR, site__country__code=request.country_code, role=Role.RESTAURANT_INSPECTOR, site__country__code=request.country_code,
).only('id') ).only('id')
if role.exists(): if role.exists():
user_role = UserRole.objects.filter( user_role = UserRole.objects.validated().filter(
user=request.user, role__id__in=role.values_list('id', flat=True), user=request.user, role__id__in=role.values_list('id', flat=True),
).only('id') ).only('id')
if user_role.exists(): if user_role.exists():
@ -309,7 +309,7 @@ class IsArtisanInspector(IsApprovedUser):
role=Role.ARTISAN_INSPECTOR, site__country__code=request.country_code, role=Role.ARTISAN_INSPECTOR, site__country__code=request.country_code,
).only('id') ).only('id')
if role.exists(): if role.exists():
user_role = UserRole.objects.filter( user_role = UserRole.objects.validated().filter(
user=request.user, role__id__in=role.values_list('id', flat=True), user=request.user, role__id__in=role.values_list('id', flat=True),
).only('id') ).only('id')
if user_role.exists(): if user_role.exists():
@ -342,7 +342,7 @@ class IsWineryWineInspector(IsApprovedUser):
role=Role.WINERY_WINE_INSPECTOR, site__country__code=request.country_code, role=Role.WINERY_WINE_INSPECTOR, site__country__code=request.country_code,
).only('id') ).only('id')
if role.exists(): if role.exists():
user_role = UserRole.objects.filter( user_role = UserRole.objects.validated().filter(
user=request.user, role__id__in=role.values_list('id', flat=True), user=request.user, role__id__in=role.values_list('id', flat=True),
).only('id') ).only('id')
if user_role.exists(): if user_role.exists():
@ -375,7 +375,7 @@ class IsProducerFoodInspector(IsApprovedUser):
role=Role.PRODUCER_FOOD_INSPECTOR, site__country__code=request.country_code, role=Role.PRODUCER_FOOD_INSPECTOR, site__country__code=request.country_code,
).only('id') ).only('id')
if role.exists(): if role.exists():
user_role = UserRole.objects.filter( user_role = UserRole.objects.validated().filter(
user=request.user, role__id__in=role.values_list('id', flat=True), user=request.user, role__id__in=role.values_list('id', flat=True),
).only('id') ).only('id')
if user_role.exists(): if user_role.exists():
@ -408,7 +408,7 @@ class IsDistilleryLiquorInspector(IsApprovedUser):
role=Role.DISTILLERY_LIQUOR_INSPECTOR, site__country__code=request.country_code, role=Role.DISTILLERY_LIQUOR_INSPECTOR, site__country__code=request.country_code,
).only('id') ).only('id')
if role.exists(): if role.exists():
user_role = UserRole.objects.filter( user_role = UserRole.objects.validated().filter(
user=request.user, role__id__in=role.values_list('id', flat=True), user=request.user, role__id__in=role.values_list('id', flat=True),
).only('id') ).only('id')
if user_role.exists(): if user_role.exists():