improve permission handling

This commit is contained in:
Mira Weller
2024-07-29 11:08:43 +02:00
parent 1be702a59e
commit f32b532cc6
3 changed files with 38 additions and 17 deletions

View File

@@ -44,7 +44,24 @@ from pretix.helpers.security import (
)
class RequireAll:
def __init__(self, *permissions):
self.permissions = permissions
class EventPermission(BasePermission):
@staticmethod
def _check_required_permission(request, required_permission):
if isinstance(required_permission, RequireAll):
if any(p not in request.eventpermset for p in required_permission.permissions):
return False
elif isinstance(required_permission, (list, tuple)):
if not any(p in request.eventpermset for p in required_permission):
return False
else:
if required_permission and required_permission not in request.eventpermset:
return False
return True
def has_permission(self, request, view):
if not request.user.is_authenticated and not isinstance(request.auth, (Device, TeamAPIToken)):
@@ -87,12 +104,8 @@ class EventPermission(BasePermission):
else:
request.eventpermset = perm_holder.get_event_permission_set(request.organizer, request.event)
if isinstance(required_permission, (list, tuple)):
if not any(p in request.eventpermset for p in required_permission):
return False
else:
if required_permission and required_permission not in request.eventpermset:
return False
if not self._check_required_permission(request, required_permission):
return False
elif 'organizer' in request.resolver_match.kwargs:
if not request.organizer or not perm_holder.has_organizer_permission(request.organizer, request=request):
@@ -102,12 +115,8 @@ class EventPermission(BasePermission):
else:
request.orgapermset = perm_holder.get_organizer_permission_set(request.organizer)
if isinstance(required_permission, (list, tuple)):
if not any(p in request.eventpermset for p in required_permission):
return False
else:
if required_permission and required_permission not in request.orgapermset:
return False
if not self._check_required_permission(request, required_permission):
return False
if isinstance(request.auth, OAuthAccessToken):
if not request.auth.allow_scopes(['write']) and request.method not in SAFE_METHODS:

View File

@@ -42,9 +42,10 @@ from django_scopes import scopes_disabled
from rest_framework import serializers, views, viewsets
from rest_framework.exceptions import PermissionDenied, ValidationError, NotFound
from rest_framework.generics import get_object_or_404
from rest_framework.permissions import SAFE_METHODS
from rest_framework.response import Response
from pretix.api.auth.permission import EventCRUDPermission
from pretix.api.auth.permission import EventCRUDPermission, RequireAll
from pretix.api.pagination import TotalOrderingFilter
from pretix.api.serializers.event import (
CloneEventSerializer, DeviceEventSettingsSerializer, EventSerializer,
@@ -672,11 +673,17 @@ class EventSettingsView(views.APIView):
class SeatViewSet(ConditionalListView, viewsets.ModelViewSet):
serializer_class = SeatSerializer
queryset = Seat.objects.none()
permission = 'can_view_orders'
write_permission = 'can_change_event_settings'
filter_backends = (DjangoFilterBackend,)
filterset_fields = ('zone_name', 'row_name', 'row_label', 'seat_number', 'seat_label', 'seat_guid', 'blocked',)
def _get_permission_name(self, request):
perms = []
if 'orderposition' in request.query_params.getlist('expand'):
perms.append('can_view_orders')
if request.method not in SAFE_METHODS:
perms.append('can_change_event_settings')
return RequireAll(*perms)
def get_queryset(self):
if self.request.event.has_subevents and 'subevent' in self.request.resolver_match.kwargs:
try:

View File

@@ -34,6 +34,7 @@ from rest_framework.exceptions import MethodNotAllowed
from rest_framework.filters import OrderingFilter
from rest_framework.response import Response
from pretix.api.auth.permission import RequireAll
from pretix.api.serializers.media import (
MediaLookupInputSerializer, ReusableMediaSerializer,
)
@@ -61,13 +62,17 @@ with scopes_disabled():
class ReusableMediaViewSet(viewsets.ModelViewSet):
serializer_class = ReusableMediaSerializer
queryset = ReusableMedium.objects.none()
permission = 'can_manage_reusable_media'
write_permission = 'can_manage_reusable_media'
filter_backends = (DjangoFilterBackend, OrderingFilter)
ordering = ('-updated', '-id')
ordering_fields = ('created', 'updated', 'identifier', 'type', 'id')
filterset_class = ReusableMediumFilter
def _get_permission_name(self, request):
if 'linked_orderposition' in request.query_params.getlist('expand'):
return RequireAll(['can_manage_reusable_media', 'can_view_orders'])
else:
return 'can_manage_reusable_media'
def get_queryset(self):
s = GiftCardTransaction.objects.filter(
card=OuterRef('pk')