diff --git a/apps/account/models.py b/apps/account/models.py index 853d126c..2e22d24d 100644 --- a/apps/account/models.py +++ b/apps/account/models.py @@ -40,33 +40,35 @@ class RoleQuerySet(models.QuerySet): class Role(ProjectBaseMixin): """Base Role model.""" STANDARD_USER = 1 - COMMENTS_MODERATOR = 2 + MODERATOR = 2 COUNTRY_ADMIN = 3 CONTENT_PAGE_MANAGER = 4 ESTABLISHMENT_MANAGER = 5 - REVIEWER_MANGER = 6 - RESTAURANT_REVIEWER = 7 + REVIEW_MANAGER = 6 + RESTAURANT_INSPECTOR = 7 SALES_MAN = 8 - WINERY_REVIEWER = 9 # Establishments subtype "winery" + WINERY_WINE_INSPECTOR = 9 SELLER = 10 DISTILLERY_LIQUOR_INSPECTOR = 11 - PRODUCT_REVIEWER = 12 + PRODUCER_FOOD_INSPECTOR = 12 ESTABLISHMENT_ADMINISTRATOR = 13 + ARTISAN_INSPECTOR = 14 ROLE_CHOICES = ( (STANDARD_USER, _('Standard user')), - (COMMENTS_MODERATOR, _('Comments moderator')), + (MODERATOR, _('Moderator')), (COUNTRY_ADMIN, _('Country admin')), (CONTENT_PAGE_MANAGER, _('Content page manager')), (ESTABLISHMENT_MANAGER, _('Establishment manager')), - (REVIEWER_MANGER, _('Reviewer manager')), - (RESTAURANT_REVIEWER, _('Restaurant reviewer')), + (REVIEW_MANAGER, _('Review manager')), + (RESTAURANT_INSPECTOR, _('Restaurant inspector')), (SALES_MAN, _('Sales man')), - (WINERY_REVIEWER, _('Winery reviewer')), + (WINERY_WINE_INSPECTOR, _('Winery and wine inspector')), (SELLER, _('Seller')), (DISTILLERY_LIQUOR_INSPECTOR, _('Distillery & Liquor inspector')), - (PRODUCT_REVIEWER, _('Product reviewer')), + (PRODUCER_FOOD_INSPECTOR, _('Producer food inspector')), (ESTABLISHMENT_ADMINISTRATOR, _('Establishment administrator')), + (ARTISAN_INSPECTOR, _('Artisan inspector')), ) ESTABLISHMENT_EDITORS = [ @@ -496,13 +498,17 @@ class UserRoleQueryset(models.QuerySet): """Filter QuerySet by state.""" return self.filter(state=self.model.VALIDATED) - def establishment_editors(self): + def has_access_to_establishments(self): """Return QuerySet filtered by role and state.""" - return self.validated().filter(role__role__in=Role.ESTABLISHMENT_EDITORS) + return self.filter(role__role__in=Role.ESTABLISHMENT_EDITORS).validated() - def product_editors(self): + def has_access_to_products(self): """Return QuerySet filtered by role and state.""" - return self.validated().filter(role__role__in=Role.PRODUCT_EDITORS) + return self.filter(role__role__in=Role.PRODUCT_EDITORS).validated() + + def has_access_to_content_pages(self): + """Return QuerySet filtered by role and state.""" + return self.filter(role__role__in=Role.CONTENT_PAGE_MANAGER).validated() class UserRole(ProjectBaseMixin): diff --git a/apps/account/views/back.py b/apps/account/views/back.py index 0fd9bdde..5433245c 100644 --- a/apps/account/views/back.py +++ b/apps/account/views/back.py @@ -10,16 +10,23 @@ from account import models, filters from account.models import User from account.serializers import back as serializers from account.serializers.common import RoleBaseSerializer +from utils.permissions import * class RoleListView(generics.ListCreateAPIView): serializer_class = RoleBaseSerializer queryset = models.Role.objects.all() filter_class = filters.RoleListFilter + permission_classes = [ + IsCountryAdmin + ] class RoleTypeRetrieveView(generics.GenericAPIView): - permission_classes = [permissions.IsAdminUser] + permission_classes = [ + permissions.IsAdminUser | + IsCountryAdmin + ] def get(self, request, *args, **kwargs): """Implement GET-method""" @@ -36,12 +43,19 @@ class RoleTypeRetrieveView(generics.GenericAPIView): class UserRoleListView(generics.ListCreateAPIView): serializer_class = serializers.UserRoleSerializer queryset = models.UserRole.objects.all() + permission_classes = [ + IsCountryAdmin + ] class UserListView(generics.ListCreateAPIView): """User list create view.""" serializer_class = serializers.BackUserSerializer - permission_classes = (permissions.IsAdminUser,) + permission_classes = [ + permissions.IsAdminUser | + IsReviewManager | + IsCountryAdmin + ] filter_class = filters.AccountBackOfficeFilter filter_backends = (OrderingFilter, DjangoFilterBackend) diff --git a/apps/comment/views/back.py b/apps/comment/views/back.py index a3c05543..b998e4ed 100644 --- a/apps/comment/views/back.py +++ b/apps/comment/views/back.py @@ -2,21 +2,22 @@ from rest_framework import generics from comment import models from comment.serializers import CommentBaseSerializer -from utils.permissions import IsCommentModerator +from utils.permissions import IsModerator, IsCountryAdmin class CommentLstView(generics.ListCreateAPIView): """Comment list create view.""" serializer_class = CommentBaseSerializer queryset = models.Comment.objects.all() - - # permission_classes = [permissions.IsAuthenticatedOrReadOnly| IsCommentModerator|IsCountryAdmin] + permission_classes = [ + IsModerator | + IsCountryAdmin + ] class CommentRUDView(generics.RetrieveUpdateDestroyAPIView): """Comment RUD view.""" serializer_class = CommentBaseSerializer queryset = models.Comment.objects.all() - permission_classes = [IsCommentModerator] - # permission_classes = [IsCountryAdmin | IsCommentModerator] + permission_classes = [IsModerator] lookup_field = 'id' diff --git a/apps/establishment/models.py b/apps/establishment/models.py index b6521255..93fd9760 100644 --- a/apps/establishment/models.py +++ b/apps/establishment/models.py @@ -112,6 +112,10 @@ class EstablishmentSubType(TypeDefaultImageMixin, TranslatedFieldsMixin, Project verbose_name = _('Establishment subtype') verbose_name_plural = _('Establishment subtypes') + def __str__(self): + """Overridden str dunder.""" + return self.index_name + def clean_fields(self, exclude=None): if not self.establishment_type.use_subtypes: raise ValidationError(_('Establishment type is not use subtypes.')) @@ -514,7 +518,7 @@ class EstablishmentQuerySet(models.QuerySet): to_attr='main_image') ) - def available_establishments(self, user, country_code: str = None): + def user_role_establishments(self, user, country_code: str = None): """Return QuerySet with establishment that is available for editing.""" from account.models import UserRole @@ -532,9 +536,12 @@ class EstablishmentQuerySet(models.QuerySet): return self.filter(**filters) def available_objects(self, user, country_code: str = None): - access_roles = user.userrole_set.establishment_editors() + # role without establishment + + # role that has establishment + access_roles = user.userrole_set.has_access_to_establishments() if access_roles.exists(): - return self.available_establishments(user, country_code) + return self.user_role_establishments(user, country_code) return self.none() diff --git a/apps/establishment/views/back.py b/apps/establishment/views/back.py index 394e89f4..80f0b0ce 100644 --- a/apps/establishment/views/back.py +++ b/apps/establishment/views/back.py @@ -11,7 +11,9 @@ from timetable.models import Timetable from timetable.serialziers import ScheduleCreateSerializer, ScheduleRUDSerializer from utils.permissions import ( IsCountryAdmin, IsEstablishmentManager, - IsWineryReviewer, IsEstablishmentAdministrator) + IsWineryWineInspector, IsEstablishmentAdministrator, + IsReviewManager, IsRestaurantInspector +) from utils.views import CreateDestroyGalleryViewMixin @@ -29,7 +31,8 @@ class EstablishmentListCreateView(EstablishmentMixinViews, generics.ListCreateAP filter_class = filters.EstablishmentFilter permission_classes = [ - IsWineryReviewer | + IsReviewManager | + IsWineryWineInspector | IsCountryAdmin | IsEstablishmentManager | IsEstablishmentAdministrator @@ -46,7 +49,11 @@ class EstablishmentListCreateView(EstablishmentMixinViews, generics.ListCreateAP class EmployeeEstablishmentsListView(generics.ListAPIView): """Establishment by employee list view.""" - permission_classes = [IsWineryReviewer | IsCountryAdmin | IsEstablishmentManager] + permission_classes = [ + IsWineryWineInspector | + IsCountryAdmin | + IsEstablishmentManager + ] queryset = models.Establishment.objects.all() serializer_class = serializers.EstablishmentListCreateSerializer @@ -64,10 +71,11 @@ class EstablishmentRUDView(generics.RetrieveUpdateDestroyAPIView): ) serializer_class = serializers.EstablishmentRUDSerializer permission_classes = [ - IsWineryReviewer | - IsCountryAdmin | - IsEstablishmentManager | + # IsWineryWineInspector | + # IsCountryAdmin | + # IsEstablishmentManager | IsEstablishmentAdministrator + # IsRestaurantInspector ] @@ -75,7 +83,10 @@ class EstablishmentScheduleRUDView(generics.RetrieveUpdateDestroyAPIView): """Establishment schedule RUD view""" lookup_field = 'slug' serializer_class = ScheduleRUDSerializer - permission_classes = [IsWineryReviewer | IsEstablishmentManager] + permission_classes = [ + IsWineryWineInspector | + IsEstablishmentManager + ] def get_object(self): """ @@ -101,14 +112,20 @@ class EstablishmentScheduleCreateView(generics.CreateAPIView): lookup_field = 'slug' serializer_class = ScheduleCreateSerializer queryset = Timetable.objects.all() - permission_classes = [IsWineryReviewer | IsEstablishmentManager] + permission_classes = [ + IsWineryWineInspector | + IsEstablishmentManager + ] class MenuListCreateView(generics.ListCreateAPIView): """Menu list create view.""" serializer_class = serializers.MenuSerializers queryset = models.Menu.objects.all() - permission_classes = [IsWineryReviewer | IsEstablishmentManager] + permission_classes = [ + IsWineryWineInspector | + IsEstablishmentManager + ] filter_backends = (DjangoFilterBackend,) filterset_fields = ( 'establishment', @@ -120,7 +137,10 @@ class MenuRUDView(generics.RetrieveUpdateDestroyAPIView): """Menu RUD view.""" serializer_class = serializers.MenuRUDSerializers queryset = models.Menu.objects.all() - permission_classes = [IsWineryReviewer | IsEstablishmentManager] + permission_classes = [ + IsWineryWineInspector | + IsEstablishmentManager + ] class SocialChoiceListCreateView(generics.ListCreateAPIView): @@ -158,14 +178,14 @@ class PlateListCreateView(generics.ListCreateAPIView): serializer_class = serializers.PlatesSerializers queryset = models.Plate.objects.all() pagination_class = None - permission_classes = [IsWineryReviewer | IsEstablishmentManager] + permission_classes = [IsWineryWineInspector | IsEstablishmentManager] class PlateRUDView(generics.RetrieveUpdateDestroyAPIView): """Plate RUD view.""" serializer_class = serializers.PlatesSerializers queryset = models.Plate.objects.all() - permission_classes = [IsWineryReviewer | IsEstablishmentManager] + permission_classes = [IsWineryWineInspector | IsEstablishmentManager] class PhonesListCreateView(generics.ListCreateAPIView): @@ -173,14 +193,14 @@ class PhonesListCreateView(generics.ListCreateAPIView): serializer_class = serializers.ContactPhoneBackSerializers queryset = models.ContactPhone.objects.all() pagination_class = None - permission_classes = [IsWineryReviewer | IsEstablishmentManager] + permission_classes = [IsWineryWineInspector | IsEstablishmentManager] class PhonesRUDView(generics.RetrieveUpdateDestroyAPIView): """Phones RUD view.""" serializer_class = serializers.ContactPhoneBackSerializers queryset = models.ContactPhone.objects.all() - permission_classes = [IsWineryReviewer | IsEstablishmentManager] + permission_classes = [IsWineryWineInspector | IsEstablishmentManager] class EmailListCreateView(generics.ListCreateAPIView): @@ -188,18 +208,18 @@ class EmailListCreateView(generics.ListCreateAPIView): serializer_class = serializers.ContactEmailBackSerializers queryset = models.ContactEmail.objects.all() pagination_class = None - permission_classes = [IsWineryReviewer | IsEstablishmentManager] + permission_classes = [IsWineryWineInspector | IsEstablishmentManager] class EmailRUDView(generics.RetrieveUpdateDestroyAPIView): """Email RUD view.""" serializer_class = serializers.ContactEmailBackSerializers queryset = models.ContactEmail.objects.all() - permission_classes = [IsWineryReviewer | IsEstablishmentManager] + permission_classes = [IsWineryWineInspector | IsEstablishmentManager] class EmployeeListCreateView(generics.ListCreateAPIView): - """Emplyoee list create view.""" + """Employee list create view.""" permission_classes = (permissions.AllowAny,) filter_class = filters.EmployeeBackFilter serializer_class = serializers.EmployeeBackSerializers @@ -443,7 +463,7 @@ class MenuDishesListCreateView(generics.ListCreateAPIView): """Menu (dessert, main_course, starter) list create view.""" serializer_class = serializers.MenuDishesSerializer queryset = models.Menu.objects.with_schedule_plates_establishment().dishes().distinct() - permission_classes = [IsWineryReviewer | IsEstablishmentManager] + permission_classes = [IsWineryWineInspector | IsEstablishmentManager] filter_class = filters.MenuDishesBackFilter @@ -451,4 +471,4 @@ class MenuDishesRUDView(generics.RetrieveUpdateDestroyAPIView): """Menu (dessert, main_course, starter) RUD view.""" serializer_class = serializers.MenuDishesRUDSerializers queryset = models.Menu.objects.dishes().distinct() - permission_classes = [IsWineryReviewer | IsEstablishmentManager] + permission_classes = [IsWineryWineInspector | IsEstablishmentManager] diff --git a/apps/news/views.py b/apps/news/views.py index 4f0adc1e..b0454deb 100644 --- a/apps/news/views.py +++ b/apps/news/views.py @@ -9,7 +9,7 @@ from django_filters.rest_framework import DjangoFilterBackend from news import filters, models, serializers from rating.tasks import add_rating -from utils.permissions import IsCountryAdmin, IsContentPageManager +from utils.permissions import IsCountryAdmin, IsContentPageManager, IsReviewManager from utils.views import CreateDestroyGalleryViewMixin, FavoritesCreateDestroyMixinView, CarouselCreateDestroyMixinView from utils.serializers import ImageBaseSerializer, EmptySerializer @@ -124,7 +124,11 @@ class NewsBackOfficeLCView(NewsBackOfficeMixinView, filter_class = filters.NewsListFilterSet create_serializers_class = serializers.NewsBackOfficeDetailSerializer filter_backends = (OrderingFilter, DjangoFilterBackend) - permission_classes = [IsCountryAdmin | IsContentPageManager] + permission_classes = [ + IsCountryAdmin | + IsContentPageManager | + IsReviewManager + ] ordering_fields = '__all__' diff --git a/apps/product/models.py b/apps/product/models.py index 272fbd0b..e2584be0 100644 --- a/apps/product/models.py +++ b/apps/product/models.py @@ -240,7 +240,7 @@ class ProductQuerySet(models.QuerySet): return self.filter(id__in=available_ids) def available_objects(self, user): - access_roles = user.userrole_set.product_editors() + access_roles = user.userrole_set.has_access_to_products() if access_roles.exists(): return self.available_products(user) return self.none() diff --git a/apps/product/views/back.py b/apps/product/views/back.py index 7d4f5eb1..fb0d3f82 100644 --- a/apps/product/views/back.py +++ b/apps/product/views/back.py @@ -2,16 +2,14 @@ from django.shortcuts import get_object_or_404 from rest_framework import generics, status, permissions, views from rest_framework.response import Response -from django.db.models import Prefetch from product import serializers, models -from location.models import Address, City, Country from product.views import ProductBaseView +from utils.permissions import ( + IsDistilleryLiquorInspector, IsProducerFoodInspector, + IsEstablishmentManager, IsEstablishmentAdministrator) from utils.serializers import ImageBaseSerializer from utils.views import CreateDestroyGalleryViewMixin -from utils.permissions import ( - IsDistilleryLiquorInspector, IsProductReviewer, - IsEstablishmentManager, IsEstablishmentAdministrator) class ProductBackOfficeMixinView(ProductBaseView): @@ -110,7 +108,7 @@ class ProductListCreateBackOfficeView(ProductBackOfficeMixinView, serializer_class = serializers.ProductBackOfficeDetailSerializer permission_classes = [ IsDistilleryLiquorInspector | - IsProductReviewer | + IsProducerFoodInspector | IsEstablishmentAdministrator | IsEstablishmentManager ] diff --git a/apps/review/urls/back.py b/apps/review/urls/back.py index a59aafa8..d3f03ed3 100644 --- a/apps/review/urls/back.py +++ b/apps/review/urls/back.py @@ -6,12 +6,12 @@ from review.views import back as views app_name = 'review' urlpatterns = [ - path('', views.ReviewLstView.as_view(), name='review-list-create'), + path('', views.ReviewListView.as_view(), name='review-list-create'), path('/', views.ReviewRUDView.as_view(), name='review-crud'), - path('/inquiries/', views.InquiriesLstView.as_view(), name='inquiries-list'), - path('inquiries/', views.InquiriesLstView.as_view(), name='inquiries-list-create'), + path('/inquiries/', views.InquiriesListView.as_view(), name='inquiries-list'), + path('inquiries/', views.InquiriesListView.as_view(), name='inquiries-list-create'), path('inquiries//', views.InquiriesRUDView.as_view(), name='inquiries-crud'), - path('inquiries//grid/', views.GridItemsLstView.as_view(), name='grid-list-create'), - path('inquiries/grid/', views.GridItemsLstView.as_view(), name='grid-list-create'), + path('inquiries//grid/', views.GridItemsListView.as_view(), name='grid-list-create'), + path('inquiries/grid/', views.GridItemsListView.as_view(), name='grid-list-create'), path('inquiries/grid//', views.GridItemsRUDView.as_view(), name='grid-crud'), ] diff --git a/apps/review/views/back.py b/apps/review/views/back.py index caf12b62..d1e470db 100644 --- a/apps/review/views/back.py +++ b/apps/review/views/back.py @@ -3,11 +3,19 @@ from rest_framework import generics, permissions from review import filters from review import models from review import serializers -from utils.permissions import IsReviewerManager, IsRestaurantReviewer +from utils.permissions import IsReviewManager, IsRestaurantInspector from review.serializers.back import ReviewBackSerializer -class ReviewLstView(generics.ListCreateAPIView): +class ReviewMixinView: + """Review mixin.""" + + def get_queryset(self): + """Overridden method 'get_queryset'.""" + return models.Review.objects.all() + + +class ReviewListView(ReviewMixinView, generics.ListCreateAPIView): """Review list create view. status values: @@ -21,6 +29,10 @@ class ReviewLstView(generics.ListCreateAPIView): permission_classes = [permissions.IsAuthenticatedOrReadOnly, ] filterset_class = filters.ReviewFilter + def get_queryset(self): + """Overridden get_queryset method.""" + return super(ReviewListView, self).get_queryset() + class ReviewRUDView(generics.RetrieveUpdateDestroyAPIView): """Review RUD view. @@ -33,11 +45,11 @@ class ReviewRUDView(generics.RetrieveUpdateDestroyAPIView): """ serializer_class = ReviewBackSerializer queryset = models.Review.objects.all() - permission_classes = [permissions.IsAdminUser | IsReviewerManager | IsRestaurantReviewer] + permission_classes = [permissions.IsAdminUser | IsReviewManager | IsRestaurantInspector] lookup_field = 'id' -class InquiriesLstView(generics.ListCreateAPIView): +class InquiriesListView(generics.ListCreateAPIView): """Inquiries list create view.""" serializer_class = serializers.InquiriesBaseSerializer @@ -59,7 +71,7 @@ class InquiriesRUDView(generics.RetrieveUpdateDestroyAPIView): lookup_field = 'id' -class GridItemsLstView(generics.ListCreateAPIView): +class GridItemsListView(generics.ListCreateAPIView): """GridItems list create view.""" serializer_class = serializers.GridItemsBaseSerializer queryset = models.GridItems.objects.all() diff --git a/apps/tag/models.py b/apps/tag/models.py index 2a57a1c4..0f8b1d1b 100644 --- a/apps/tag/models.py +++ b/apps/tag/models.py @@ -11,6 +11,10 @@ from utils.models import IndexJSON class TagQuerySet(models.QuerySet): + def with_base_related(self): + """Return QuerySet with base related.""" + return self.select_related('category', 'translation') + def for_news(self): """Select chosen tags for news.""" return self.filter(category__news_types__isnull=False) diff --git a/apps/tag/views.py b/apps/tag/views.py index de49875f..41fbd77b 100644 --- a/apps/tag/views.py +++ b/apps/tag/views.py @@ -334,8 +334,8 @@ class TagBackOfficeViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, """List/create tag view.""" pagination_class = None - permission_classes = (permissions.IsAuthenticated,) - queryset = models.Tag.objects.all() + permission_classes = (permissions.IsAdminUser,) + queryset = models.Tag.objects.with_base_related() serializer_class = serializers.TagBackOfficeSerializer bind_object_serializer_class = serializers.TagBindObjectSerializer chosen_serializer_class = serializers.ChosenTagBindObjectSerializer @@ -388,7 +388,7 @@ class TagCategoryBackOfficeViewSet(mixins.CreateModelMixin, TagCategoryViewSet): """ViewSet for TagCategory model for BackOffice users.""" - permission_classes = (permissions.IsAuthenticated,) + permission_classes = (permissions.IsAdminUser,) queryset = TagCategoryViewSet.queryset.with_extended_related() serializer_class = serializers.TagCategoryBackOfficeDetailSerializer bind_object_serializer_class = serializers.TagCategoryBindObjectSerializer diff --git a/apps/utils/permissions.py b/apps/utils/permissions.py index bf06190e..2ea32b18 100644 --- a/apps/utils/permissions.py +++ b/apps/utils/permissions.py @@ -1,15 +1,13 @@ """Project custom permissions""" -from django.contrib.contenttypes.models import ContentType - from rest_framework import permissions +from rest_framework.permissions import SAFE_METHODS as SAFE_HTTP_METHODS from rest_framework_simplejwt.tokens import AccessToken from account.models import UserRole, Role from authorization.models import JWTRefreshToken +from establishment.models import Establishment +from product.models import Product from utils.tokens import GMRefreshToken -from establishment.models import EstablishmentSubType, Establishment -from location.models import Address -from product.models import Product, ProductType class IsAuthenticatedAndTokenIsValid(permissions.BasePermission): @@ -49,7 +47,7 @@ class IsRefreshTokenValid(permissions.BasePermission): def has_object_permission(self, request, view, obj): # Read permissions are allowed to all request, # so we'll always allow GET, HEAD or OPTIONS requests. - if request.method in permissions.SAFE_METHODS or \ + if request.method in SAFE_HTTP_METHODS or \ obj.user == request.user or request.user.is_superuser: return True return False @@ -63,43 +61,15 @@ class IsGuest(permissions.IsAuthenticatedOrReadOnly): rules = [ request.user.is_anonymous, - request.method in permissions.SAFE_METHODS + request.method in SAFE_HTTP_METHODS ] return all(rules) def has_object_permission(self, request, view, obj): - rules = [ - request.user.is_anonymous, - request.method in permissions.SAFE_METHODS - ] - return all(rules) + return self.has_permission(request, view) -class IsStandardUser(permissions.IsAuthenticated): - """ - 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), - request.user.email_confirmed, - ] - - return any(rules) - - def has_object_permission(self, request, view, obj): - # Read permissions are allowed to any request - - rules = [super().has_object_permission(request, view, obj), - request.user.email_confirmed, - ] - - return any(rules) - - -class IsContentPageManager(IsStandardUser): +class IsApprovedUser(permissions.IsAuthenticated): """ Object-level permission to only allow owners of an object to edit it. Assumes the model instance has an `owner` attribute. @@ -109,177 +79,98 @@ class IsContentPageManager(IsStandardUser): rules = [ 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 all(rules) - - def has_object_permission(self, request, view, obj): - # Read permissions are allowed to all request. - if hasattr(obj, 'site_id'): - 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) - ] - - return all(rules) - - -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) - ] - - rule = False - # and request.user.email_confirmed, - if hasattr(request.data, 'user'): - if hasattr(request.data, 'site_id'): - # Read permissions are allowed to all 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, - country_id=request.data.country_id - ).first() - rules = [ - UserRole.objects.filter(user=request.user, role=role).exists(), - super().has_permission(request, view) - ] - rules.append(rule) - return all(rules) - - def has_object_permission(self, request, view, obj): - # Read permissions are allowed to all request. - 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) - ] - - if hasattr(request, 'user') and request.user.is_authenticated: - rules = [ - UserRole.objects.filter(user=request.user, role=role).exists(), - super().has_object_permission(request, view, obj), - ] - - if hasattr(request.data, 'user'): - rules = [ - UserRole.objects.filter(user=request.data.user, role=role).exists(), - super().has_object_permission(request, view, obj), - ] - - return all(rules) - - -class IsCommentModerator(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) - ] - - if all(rules) and hasattr(request.data, 'site_id'): - # Read permissions are allowed to all request. - - role = Role.objects.filter(role=Role.COMMENTS_MODERATOR, - site_id=request.data.site_id) \ - .first() - - rules = [ - UserRole.objects.filter(user=request.user, role=role).exists(), - super().has_permission(request, view) - ] - - return all(rules) - - def has_object_permission(self, request, view, obj): - - rules = [ - super().has_object_permission(request, view, obj) - ] - + has_permission = False 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) - ] + has_permission = request.user.email_confirmed + rules.append(has_permission) return all(rules) -class IsEstablishmentManager(IsStandardUser): +class IsContentPageManager(IsApprovedUser): + """ + 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) ] - rule = False + has_permission = False + if (request.user.is_authenticated and hasattr(request, 'country_code') and + request.country_code): + role = Role.objects.filter( + role=Role.CONTENT_PAGE_MANAGER, site__country__code=request.country_code, + ).only('id') + if role.exists(): + user_role = UserRole.objects.filter( + user=request.user, role__id__in=role.values_list('id', flat=True), + ).only('id') + has_permission = True if user_role.exists() else has_permission + rules.append(has_permission) + return all(rules) + + +class IsCountryAdmin(IsApprovedUser): + """ + 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) + ] + has_permission = False + # check role + if (request.user.is_authenticated and hasattr(request, 'country_code') and + request.country_code): + role = Role.objects.filter( + role=Role.COUNTRY_ADMIN, site__country__code=request.country_code, + ).only('id') + if role.exists(): + user_role = UserRole.objects.filter( + user=request.user, role__id__in=role.values_list('id', flat=True) + ).only('id') + has_permission = True if user_role.exists() else has_permission + rules.append(has_permission) + return all(rules) + + +class IsModerator(IsApprovedUser): + """ + 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) + ] + has_permission = False + # check role + if (request.user.is_authenticated and hasattr(request, 'country_code') and + request.country_code): + role = Role.objects.filter( + role=Role.MODERATOR, site__country__code=request.country_code, + ).only('id') + if role.exists(): + user_role = UserRole.objects.filter( + user=request.user, role__id__in=role.values_list('id', flat=True), + ).only('id') + has_permission = True if user_role.exists() else has_permission + rules.append(has_permission) + return all(rules) + + +class IsEstablishmentManager(IsApprovedUser): + + def has_permission(self, request, view): + rules = [ + super().has_permission(request, view) + ] + has_permission = False + # check role if (request.user.is_authenticated and hasattr(request, 'country_code') and request.country_code): @@ -290,48 +181,43 @@ class IsEstablishmentManager(IsStandardUser): if role.exists(): user_role = UserRole.objects.filter( user=user, role__id__in=role.values_list('id', flat=True), - ) - rule = True if user_role.exists() else rule - rules.append(rule) + ).only('id') + has_permission = True if user_role.exists() else has_permission + rules.append(has_permission) return all(rules) - def has_object_permission(self, request, view, obj): - return self.has_permission(request, view) - -class IsEstablishmentAdministrator(IsStandardUser): +class IsEstablishmentAdministrator(IsApprovedUser): def has_permission(self, request, view): rules = [ super().has_permission(request, view) ] - rule = False + has_permission = False + # check role if (request.user.is_authenticated and hasattr(request, 'country_code') and request.country_code): - user = request.user role = Role.objects.filter( role=Role.ESTABLISHMENT_ADMINISTRATOR, site__country__code=request.country_code, ).only('id') if role.exists(): user_role = UserRole.objects.filter( - user=user, role__id__in=role.values_list('id', flat=True), - ) - rule = True if user_role.exists() else rule - rules.append(rule) + user=request.user, role__id__in=role.values_list('id', flat=True), + ).only('id') + has_permission = True if user_role.exists() else has_permission + rules.append(has_permission) return all(rules) def has_object_permission(self, request, view, obj): - rules = [ - super().has_permission(request, view) + super().has_object_permission(request, view, obj) ] - rule = False + has_object_permission = False role = Role.objects.filter(role=Role.ESTABLISHMENT_ADMINISTRATOR).only('id') if request.user.is_authenticated and role.exists() and hasattr(obj, 'id'): - user = request.user filters = { - 'user': user, + 'user': request.user, 'role__id__in': role.values_list('id', flat=True), } if isinstance(obj, Establishment): @@ -339,259 +225,211 @@ class IsEstablishmentAdministrator(IsStandardUser): if isinstance(obj, Product): filters.update({'establishment__products__id': obj.id}) - rule = True if UserRole.objects.filter(**filters).exists() else rule - rules.append(rule) + user_role = UserRole.objects.filter(**filters) + has_object_permission = True if user_role.exists() else has_object_permission + rules.append(has_object_permission) return all(rules) -class IsReviewerManager(IsStandardUser): +class IsReviewManager(IsApprovedUser): + + MODEL_PERMISSIONS = { + 'READ': ['establishment', 'product_type', 'news', 'recipe', 'user', ], + 'WRITE': ['inquiries', 'userrole', 'review', 'establishment', 'product', 'news', 'recipe', ] + } 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'): - role = Role.objects.filter(role=Role.REVIEWER_MANGER - ).first() - - rules = [ - UserRole.objects.filter(user=request.user, role=role, - establishment_id=request.data.site_id - ).exists(), - super().has_permission(request, view) - ] - return all(rules) - - def has_object_permission(self, request, view, obj): - role = Role.objects.filter(role=Role.REVIEWER_MANGER, - country_id=obj.country_id) \ - .first() - - rules = [ - UserRole.objects.filter(user=request.user, role=role).exists(), - super().has_object_permission(request, view, obj) - ] - - return all(rules) - - -class IsRestaurantReviewer(IsStandardUser): - - def has_permission(self, request, view): - rules = [ - super().has_permission(request, view) - ] - - # and request.user.email_confirmed, - if hasattr(request.data, 'user') and hasattr(request.data, 'object_id'): - role = Role.objects.filter(role=Role.RESTAURANT_REVIEWER) \ - .first() - - rules = [ - UserRole.objects.filter(user=request.user, role=role, - establishment_id=request.data.object_id - ).exists(), - super().has_permission(request, view) - ] - return all(rules) - - def has_object_permission(self, request, view, obj): - content_type = ContentType.objects.get(app_lable='establishment', - model='establishment') - - role = Role.objects.filter(role=Role.RESTAURANT_REVIEWER, - country=obj.country_id).first() - - rules = [ - obj.content_type_id == content_type.id and - UserRole.objects.filter(user=request.user, role=role, - establishment_id=obj.object_id - ).exists(), - super().has_object_permission(request, view, obj) - ] - - return all(rules) - - -class IsWineryReviewer(IsStandardUser): - - def has_permission(self, request, view): - rules = [ - super().has_permission(request, view) - ] - - rule = False - if request.user.is_authenticated: - if hasattr(request, 'data'): - type_id = request.data.get('type_id') - address_id = request.data.get('address_id') - - if type_id and address_id: - address_qs = Address.objects.filter(id=address_id) \ - .only('city__country') - - if address_qs.exists(): - country_id = address_qs.values_list('city__country', flat=True) - - est_subtype_qs = EstablishmentSubType.objects.filter(establishment_type_id=type_id).only('id') - if est_subtype_qs.exists(): - role = Role.objects.filter( - establishment_subtype_id=est_subtype_qs.values_list('id', flat=True)[0], - role=Role.WINERY_REVIEWER, - country_id=country_id - ) - rule = True if role.exists() else rule - rules.append(rule) - return all(rules) - - def has_object_permission(self, request, view, obj): - rules = [ - super().has_object_permission(request, view, obj) - ] - - rule = False - if request.user.is_authenticated: - type_id = None - object_id = None - country_id = None - - if hasattr(obj, 'type_id'): - type_id = obj.type_id - - if hasattr(obj, 'establishment_type_id'): - type_id = obj.establishment_type_id - - if hasattr(obj, 'object_id'): - object_id = obj.object_id - - if hasattr(obj, 'establishment_id'): - object_id = obj.establishment_id - - if hasattr(obj, 'country_id'): - country_id = obj.country_id - - if type_id and object_id and country_id: - est_subtype_qs = EstablishmentSubType.objects.filter( - establishment_type_id=type_id + has_permission = False + # check role + if (request.user.is_authenticated and + hasattr(request, 'country_code') and + request.country_code): + role = Role.objects.filter( + role=Role.REVIEW_MANAGER, site__country__code=request.country_code, + ).only('id') + if role.exists(): + user_role = UserRole.objects.filter( + user=request.user, role__id__in=role.values_list('id', flat=True), ).only('id') - - if est_subtype_qs.exists(): - est_subtype_id = est_subtype_qs.values_list('id', flat=True)[0] - - role = Role.objects.filter( - role=Role.WINERY_REVIEWER, - establishment_subtype_id=est_subtype_id, - country_id=country_id - ).first() - - user_role = UserRole.objects.filter( - user=request.user, - role=role, - establishment_id=object_id, - ) - rule = True if user_role.exists() else rule - rules.append(rule) + if user_role.exists(): + # check model for read + model_name = view.get_queryset().model._meta.model_name + if ((model_name in self.MODEL_PERMISSIONS.get('READ', []) and + request.method in SAFE_HTTP_METHODS) or + (model_name in self.MODEL_PERMISSIONS.get('WRITE', []))): + has_permission = True + rules.append(has_permission) return all(rules) -class IsProductReviewer(IsStandardUser): +class IsRestaurantInspector(IsApprovedUser): + + MODEL_PERMISSIONS = { + 'READ': ['establishment', ], + 'WRITE': ['inquiries', ] + } def has_permission(self, request, view): rules = [ super().has_permission(request, view) ] - - pk_object = None - roles = None - permission = False - - if 'site_id' in request.data: - if request.data['site_id'] is not None: - roles = Role.objects.filter(role=Role.PRODUCT_REVIEWER, - site_id=request.data['site_id']) - - if 'pk' in view.kwargs: - pk_object = view.kwargs['pk'] - - if pk_object is not None: - product = Product.objects.get(pk=pk_object) - if product.site_id is not None: - roles = Role.objects.filter(role=Role.PRODUCT_REVIEWER, - site_id=product.site_id) - - if roles is not None: - permission = UserRole.objects.filter(user=request.user, role__in=[role for role in roles])\ - .exists() - - rules.append(permission) + has_permission = False + # check role + if (request.user.is_authenticated and + hasattr(request, 'country_code') and + request.country_code): + role = Role.objects.filter( + role=Role.RESTAURANT_INSPECTOR, site__country__code=request.country_code, + ).only('id') + if role.exists(): + user_role = UserRole.objects.filter( + user=request.user, role__id__in=role.values_list('id', flat=True), + ).only('id') + if user_role.exists(): + # check model for read + model_name = view.get_queryset().model._meta.model_name + if ((model_name in self.MODEL_PERMISSIONS.get('READ', []) and + request.method in SAFE_HTTP_METHODS) or + (model_name in self.MODEL_PERMISSIONS.get('WRITE', []))): + has_permission = True + rules.append(has_permission) return all(rules) -class IsDistilleryLiquorInspector(IsStandardUser): +class IsArtisanInspector(IsApprovedUser): + + MODEL_PERMISSIONS = { + 'READ': ['establishment', ], + 'WRITE': ['inquiries', ] + } + def has_permission(self, request, view): rules = [ super().has_permission(request, view) ] - - pk_object = None - roles = None - permission = False - - if 'site_id' in request.data and 'product_type_id' in request.data: - if request.data['site_id'] is not None \ - and request.data['product_type_id'] is not None: - - product_types = ProductType.objects. \ - filter(index_name=ProductType.LIQUOR, - id=request.data['product_type_id']) - - if product_types.exists(): - roles = Role.objects.filter(role=Role.DISTILLERY_LIQUOR_INSPECTOR, - site_id=request.data['site_id']) - - if 'pk' in view.kwargs: - pk_object = view.kwargs['pk'] - - if pk_object is not None: - product = Product.objects.get(pk=pk_object) - if product.site_id is not None \ - and product.product_type_id is not None: - - product_types = ProductType.objects. \ - filter(index_name=ProductType.LIQUOR, - id=product.product_type_id) - - if product_types.exists(): - roles = Role.objects.filter(role=Role.DISTILLERY_LIQUOR_INSPECTOR, - site_id=product.site_id) - - if roles is not None: - permission = UserRole.objects.filter(user=request.user, role__in=[role for role in roles])\ - .exists() - - rules.append(permission) + has_permission = False + # check role + if (request.user.is_authenticated and + hasattr(request, 'country_code') and + request.country_code): + role = Role.objects.filter( + role=Role.ARTISAN_INSPECTOR, site__country__code=request.country_code, + ).only('id') + if role.exists(): + user_role = UserRole.objects.filter( + user=request.user, role__id__in=role.values_list('id', flat=True), + ).only('id') + if user_role.exists(): + # check model for read + model_name = view.get_queryset().model._meta.model_name + if ((model_name in self.MODEL_PERMISSIONS.get('READ', []) and + request.method in SAFE_HTTP_METHODS) or + (model_name in self.MODEL_PERMISSIONS.get('WRITE', []))): + has_permission = True + rules.append(has_permission) return all(rules) - # - # def has_object_permission(self, request, view, obj): - # rules = [ - # super().has_object_permission(request, view, obj) - # ] - # # pk_object = None - # # product = None - # # permission = False - # # - # # if 'pk' in view.kwargs: - # # pk_object = view.kwargs['pk'] - # # - # # if pk_object is not None: - # # product = Product.objects.get(pk=pk_object) - # # - # # if product.sites.exists(): - # # role = Role.objects.filter(role=Role.DISTILLERY_LIQUOR_INSPECTOR, site__in=[site for site in product.sites]) - # # permission = UserRole.objects.filter(user=request.user, role=role).exists() - # # - # # rules.append(permission) - # return all(rules) \ No newline at end of file + +class IsWineryWineInspector(IsApprovedUser): + + MODEL_PERMISSIONS = { + 'READ': ['establishment', 'product', ], + 'WRITE': ['inquiries', ] + } + + def has_permission(self, request, view): + rules = [ + super().has_permission(request, view) + ] + has_permission = False + # check role + if (request.user.is_authenticated and + hasattr(request, 'country_code') and + request.country_code): + role = Role.objects.filter( + role=Role.WINERY_WINE_INSPECTOR, site__country__code=request.country_code, + ).only('id') + if role.exists(): + user_role = UserRole.objects.filter( + user=request.user, role__id__in=role.values_list('id', flat=True), + ).only('id') + if user_role.exists(): + # check model for read + model_name = view.get_queryset().model._meta.model_name + if ((model_name in self.MODEL_PERMISSIONS.get('READ', []) and + request.method in SAFE_HTTP_METHODS) or + (model_name in self.MODEL_PERMISSIONS.get('WRITE', []))): + has_permission = True + rules.append(has_permission) + return all(rules) + + +class IsProducerFoodInspector(IsApprovedUser): + + MODEL_PERMISSIONS = { + 'READ': ['establishment', 'product', ], + 'WRITE': ['inquiries', ] + } + + def has_permission(self, request, view): + rules = [ + super().has_permission(request, view) + ] + has_permission = False + # check role + if (request.user.is_authenticated and + hasattr(request, 'country_code') and + request.country_code): + role = Role.objects.filter( + role=Role.PRODUCER_FOOD_INSPECTOR, site__country__code=request.country_code, + ).only('id') + if role.exists(): + user_role = UserRole.objects.filter( + user=request.user, role__id__in=role.values_list('id', flat=True), + ).only('id') + if user_role.exists(): + # check model for read + model_name = view.get_queryset().model._meta.model_name + if ((model_name in self.MODEL_PERMISSIONS.get('READ', []) and + request.method in SAFE_HTTP_METHODS) or + (model_name in self.MODEL_PERMISSIONS.get('WRITE', []))): + has_permission = True + rules.append(has_permission) + return all(rules) + + +class IsDistilleryLiquorInspector(IsApprovedUser): + + MODEL_PERMISSIONS = { + 'READ': ['establishment', 'product', ], + 'WRITE': ['inquiries', ] + } + + def has_permission(self, request, view): + rules = [ + super().has_permission(request, view) + ] + has_permission = False + # check role + if (request.user.is_authenticated and + hasattr(request, 'country_code') and + request.country_code): + role = Role.objects.filter( + role=Role.DISTILLERY_LIQUOR_INSPECTOR, site__country__code=request.country_code, + ).only('id') + if role.exists(): + user_role = UserRole.objects.filter( + user=request.user, role__id__in=role.values_list('id', flat=True), + ).only('id') + if user_role.exists(): + # check model for read + model_name = view.get_queryset().model._meta.model_name + if ((model_name in self.MODEL_PERMISSIONS.get('READ', []) and + request.method in SAFE_HTTP_METHODS) or + (model_name in self.MODEL_PERMISSIONS.get('WRITE', []))): + has_permission = True + rules.append(has_permission) + return all(rules)