diff --git a/src/pretix/api/auth/permission.py b/src/pretix/api/auth/permission.py index 802781d00..093fc0978 100644 --- a/src/pretix/api/auth/permission.py +++ b/src/pretix/api/auth/permission.py @@ -124,12 +124,12 @@ class EventCRUDPermission(EventPermission): def has_permission(self, request, view): if not super(EventCRUDPermission, self).has_permission(request, view): return False - elif view.action == 'create' and 'can_create_events' not in request.orgapermset: + elif view.action == 'create' and 'organizer.events:create' not in request.orgapermset: return False - elif view.action == 'destroy' and 'can_change_event_settings' not in request.eventpermset: + elif view.action == 'destroy' and 'event.settings.general:write' not in request.eventpermset: return False elif view.action in ['update', 'partial_update'] \ - and 'can_change_event_settings' not in request.eventpermset: + and 'event.settings.general:write' not in request.eventpermset: return False return True diff --git a/src/pretix/api/serializers/event.py b/src/pretix/api/serializers/event.py index 325e24c7c..4d99e7425 100644 --- a/src/pretix/api/serializers/event.py +++ b/src/pretix/api/serializers/event.py @@ -300,7 +300,7 @@ class EventSerializer(SalesChannelMigrationMixin, I18nAwareModelSerializer): def ignored_meta_properties(self): perm_holder = (self.context['request'].auth if isinstance(self.context['request'].auth, (Device, TeamAPIToken)) else self.context['request'].user) - if perm_holder.has_organizer_permission(self.context['request'].organizer, 'can_change_organizer_settings', request=self.context['request']): + if perm_holder.has_organizer_permission(self.context['request'].organizer, 'organizer.settings.general:write', request=self.context['request']): return [] return [k for k, p in self.meta_properties.items() if p.protected] @@ -561,7 +561,7 @@ class SubEventSerializer(I18nAwareModelSerializer): def ignored_meta_properties(self): perm_holder = (self.context['request'].auth if isinstance(self.context['request'].auth, (Device, TeamAPIToken)) else self.context['request'].user) - if perm_holder.has_organizer_permission(self.context['request'].organizer, 'can_change_organizer_settings', request=self.context['request']): + if perm_holder.has_organizer_permission(self.context['request'].organizer, 'organizer.settings.general:write', request=self.context['request']): return [] return [k for k, p in self.meta_properties.items() if p.protected] @@ -1079,16 +1079,16 @@ class SeatSerializer(I18nAwareModelSerializer): def prefetch_expanded_data(self, items, request, expand_fields): if 'orderposition' in expand_fields: - if 'can_view_orders' not in request.eventpermset: - raise PermissionDenied('can_view_orders permission required for expand=orderposition') + if 'event.orders:read' not in request.eventpermset: + raise PermissionDenied('event.orders:read permission required for expand=orderposition') prefetch_by_id(items, OrderPosition.objects.prefetch_related('order'), 'orderposition_id', 'orderposition') if 'cartposition' in expand_fields: - if 'can_view_orders' not in request.eventpermset: - raise PermissionDenied('can_view_orders permission required for expand=cartposition') + if 'event.orders:read' not in request.eventpermset: + raise PermissionDenied('event.orders:read permission required for expand=cartposition') prefetch_by_id(items, CartPosition.objects, 'cartposition_id', 'cartposition') if 'voucher' in expand_fields: - if 'can_view_vouchers' not in request.eventpermset: - raise PermissionDenied('can_view_vouchers permission required for expand=voucher') + if 'event.vouchers:read' not in request.eventpermset: + raise PermissionDenied('event.vouchers:read permission required for expand=voucher') prefetch_by_id(items, Voucher.objects, 'voucher_id', 'voucher') def __init__(self, instance, *args, **kwargs): diff --git a/src/pretix/api/serializers/order.py b/src/pretix/api/serializers/order.py index 1459e1c26..5cee7d08e 100644 --- a/src/pretix/api/serializers/order.py +++ b/src/pretix/api/serializers/order.py @@ -613,7 +613,7 @@ class OrderPositionSerializer(I18nAwareModelSerializer): # /events/…/checkinlists/…/positions/ # We're unable to check this on this level if we're on /checkinrpc/, in which case we rely on the view # layer to not set pdf_data=true in the first place. - request and hasattr(request, 'eventpermset') and 'can_view_orders' not in request.eventpermset + request and hasattr(request, 'eventpermset') and 'event.orders:read' not in request.eventpermset ) if ('pdf_data' in self.context and not self.context['pdf_data']) or pdf_data_forbidden: self.fields.pop('pdf_data', None) diff --git a/src/pretix/api/views/cart.py b/src/pretix/api/views/cart.py index 9a02a86db..3f858affc 100644 --- a/src/pretix/api/views/cart.py +++ b/src/pretix/api/views/cart.py @@ -52,8 +52,8 @@ class CartPositionViewSet(CreateModelMixin, DestroyModelMixin, viewsets.ReadOnly ordering = ('datetime',) ordering_fields = ('datetime', 'cart_id') lookup_field = 'id' - permission = 'can_view_orders' - write_permission = 'can_change_orders' + permission = 'event.orders:read' + write_permission = 'event.orders:write' def get_queryset(self): return CartPosition.objects.filter( diff --git a/src/pretix/api/views/checkin.py b/src/pretix/api/views/checkin.py index 26c0bbcae..4a102f542 100644 --- a/src/pretix/api/views/checkin.py +++ b/src/pretix/api/views/checkin.py @@ -118,11 +118,11 @@ class CheckinListViewSet(viewsets.ModelViewSet): def _get_permission_name(self, request): if request.path.endswith('/failed_checkins/'): - return 'can_checkin_orders', 'can_change_orders' + return 'event.orders:checkin', 'event.orders:write' elif request.method in SAFE_METHODS: - return 'can_view_orders', 'can_checkin_orders', + return 'event.orders:read', 'event.orders:checkin', else: - return 'can_change_event_settings' + return 'event.settings.general:write' def get_queryset(self): qs = self.request.event.checkin_lists.prefetch_related( @@ -457,7 +457,7 @@ def _redeem_process(*, checkinlists, raw_barcode, answers_data, datetime, force, 'event': op.order.event, 'pdf_data': pdf_data and ( user if user and user.is_authenticated else auth - ).has_event_permission(request.organizer, event, 'can_view_orders', request), + ).has_event_permission(request.organizer, event, 'event.orders:read', request), } common_checkin_args = dict( @@ -822,8 +822,8 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet): } filterset_class = CheckinOrderPositionFilter - permission = ('can_view_orders', 'can_checkin_orders') - write_permission = ('can_change_orders', 'can_checkin_orders') + permission = ('event.orders:read', 'event.orders:checkin') + write_permission = ('event.orders:write', 'event.orders:checkin') def get_serializer_context(self): ctx = super().get_serializer_context() @@ -854,7 +854,7 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet): expand=self.request.query_params.getlist('expand'), ) - if 'pk' not in self.request.resolver_match.kwargs and 'can_view_orders' not in self.request.eventpermset \ + if 'pk' not in self.request.resolver_match.kwargs and 'event.orders:read' not in self.request.eventpermset \ and len(self.request.query_params.get('search', '')) < 3: qs = qs.none() @@ -903,9 +903,9 @@ class CheckinListPositionViewSet(viewsets.ReadOnlyModelViewSet): class CheckinRPCRedeemView(views.APIView): def post(self, request, *args, **kwargs): if isinstance(self.request.auth, (TeamAPIToken, Device)): - events = self.request.auth.get_events_with_permission(('can_change_orders', 'can_checkin_orders')) + events = self.request.auth.get_events_with_permission(('event.orders:write', 'event.orders:checkin')) elif self.request.user.is_authenticated: - events = self.request.user.get_events_with_permission(('can_change_orders', 'can_checkin_orders'), self.request).filter( + events = self.request.user.get_events_with_permission(('event.orders:write', 'event.orders:checkin'), self.request).filter( organizer=self.request.organizer ) else: @@ -972,9 +972,9 @@ class CheckinRPCSearchView(ListAPIView): @cached_property def lists(self): if isinstance(self.request.auth, (TeamAPIToken, Device)): - events = self.request.auth.get_events_with_permission(('can_view_orders', 'can_checkin_orders')) + events = self.request.auth.get_events_with_permission(('event.orders:read', 'event.orders:checkin')) elif self.request.user.is_authenticated: - events = self.request.user.get_events_with_permission(('can_view_orders', 'can_checkin_orders'), self.request).filter( + events = self.request.user.get_events_with_permission(('event.orders:read', 'event.orders:checkin'), self.request).filter( organizer=self.request.organizer ) else: @@ -991,9 +991,9 @@ class CheckinRPCSearchView(ListAPIView): @cached_property def has_full_access_permission(self): if isinstance(self.request.auth, (TeamAPIToken, Device)): - events = self.request.auth.get_events_with_permission('can_view_orders') + events = self.request.auth.get_events_with_permission('event.orders:read') elif self.request.user.is_authenticated: - events = self.request.user.get_events_with_permission('can_view_orders', self.request).filter( + events = self.request.user.get_events_with_permission('event.orders:read', self.request).filter( organizer=self.request.organizer ) else: @@ -1020,9 +1020,9 @@ class CheckinRPCSearchView(ListAPIView): class CheckinRPCAnnulView(views.APIView): def post(self, request, *args, **kwargs): if isinstance(self.request.auth, (TeamAPIToken, Device)): - events = self.request.auth.get_events_with_permission(('can_change_orders', 'can_checkin_orders')) + events = self.request.auth.get_events_with_permission(('event.orders:write', 'event.orders:checkin')) elif self.request.user.is_authenticated: - events = self.request.user.get_events_with_permission(('can_change_orders', 'can_checkin_orders'), self.request).filter( + events = self.request.user.get_events_with_permission(('event.orders:write', 'event.orders:checkin'), self.request).filter( organizer=self.request.organizer ) else: @@ -1100,7 +1100,7 @@ class CheckinViewSet(viewsets.ReadOnlyModelViewSet): filterset_class = CheckinFilter ordering = ('created', 'id') ordering_fields = ('created', 'datetime', 'id',) - permission = 'can_view_orders' + permission = 'event.orders:read' def get_queryset(self): qs = Checkin.all.filter().select_related( diff --git a/src/pretix/api/views/discount.py b/src/pretix/api/views/discount.py index 4504d0381..53386d3d0 100644 --- a/src/pretix/api/views/discount.py +++ b/src/pretix/api/views/discount.py @@ -57,7 +57,7 @@ class DiscountViewSet(ConditionalListView, viewsets.ModelViewSet): ordering_fields = ('id', 'position') ordering = ('position', 'id') permission = None - write_permission = 'can_change_items' + write_permission = 'event.items:write' def get_queryset(self): return self.request.event.discounts.prefetch_related( diff --git a/src/pretix/api/views/event.py b/src/pretix/api/views/event.py index b61771bdb..77b566173 100644 --- a/src/pretix/api/views/event.py +++ b/src/pretix/api/views/event.py @@ -341,7 +341,7 @@ class CloneEventViewSet(viewsets.ModelViewSet): lookup_field = 'slug' lookup_url_kwarg = 'event' http_method_names = ['post'] - write_permission = 'can_create_events' + write_permission = 'organizer.events:create' def get_serializer_context(self): ctx = super().get_serializer_context() @@ -426,7 +426,7 @@ with scopes_disabled(): class SubEventViewSet(ConditionalListView, viewsets.ModelViewSet): serializer_class = SubEventSerializer queryset = SubEvent.objects.none() - write_permission = 'can_change_event_settings' + write_permission = 'event.settings.general:write' filter_backends = (DjangoFilterBackend, TotalOrderingFilter) ordering = ('date_from',) ordering_fields = ('id', 'date_from', 'last_modified') @@ -546,7 +546,7 @@ class SubEventViewSet(ConditionalListView, viewsets.ModelViewSet): class TaxRuleViewSet(ConditionalListView, viewsets.ModelViewSet): serializer_class = TaxRuleSerializer queryset = TaxRule.objects.none() - write_permission = 'can_change_event_settings' + write_permission = 'event.settings.general:write' def get_queryset(self): return self.request.event.tax_rules.all() @@ -589,7 +589,7 @@ class TaxRuleViewSet(ConditionalListView, viewsets.ModelViewSet): class ItemMetaPropertiesViewSet(viewsets.ModelViewSet): serializer_class = ItemMetaPropertiesSerializer queryset = ItemMetaProperty.objects.none() - write_permission = 'can_change_event_settings' + write_permission = 'event.settings.general:write' def get_queryset(self): qs = self.request.event.item_meta_properties.all() @@ -636,14 +636,14 @@ class ItemMetaPropertiesViewSet(viewsets.ModelViewSet): class EventSettingsView(views.APIView): permission = None - write_permission = 'can_change_event_settings' + write_permission = 'event.settings.general:write' def get(self, request, *args, **kwargs): if isinstance(request.auth, Device): s = DeviceEventSettingsSerializer(instance=request.event.settings, event=request.event, context={ 'request': request }) - elif 'can_change_event_settings' in request.eventpermset: + elif 'event.settings.general:write' in request.eventpermset: s = EventSettingsSerializer(instance=request.event.settings, event=request.event, context={ 'request': request }) @@ -701,7 +701,7 @@ class SeatFilter(FilterSet): class SeatViewSet(ConditionalListView, viewsets.ModelViewSet): serializer_class = SeatSerializer queryset = Seat.objects.none() - write_permission = 'can_change_event_settings' + write_permission = 'event.settings.general:write' filter_backends = (DjangoFilterBackend, ) filterset_class = SeatFilter diff --git a/src/pretix/api/views/exporters.py b/src/pretix/api/views/exporters.py index 63344b21e..1bd9c4073 100644 --- a/src/pretix/api/views/exporters.py +++ b/src/pretix/api/views/exporters.py @@ -130,7 +130,7 @@ class ExportersMixin: class EventExportersViewSet(ExportersMixin, viewsets.ViewSet): - permission = 'can_view_orders' + permission = 'event.orders:read' def get_serializer_kwargs(self): return {} @@ -163,7 +163,7 @@ class OrganizerExportersViewSet(ExportersMixin, viewsets.ViewSet): perm_holder = self.request.auth else: perm_holder = self.request.user - events = perm_holder.get_events_with_permission('can_view_orders', request=self.request).filter( + events = perm_holder.get_events_with_permission('event.orders:read', request=self.request).filter( organizer=self.request.organizer ) responses = register_multievent_data_exporters.send(self.request.organizer) @@ -190,7 +190,7 @@ class OrganizerExportersViewSet(ExportersMixin, viewsets.ViewSet): else: perm_holder = self.request.user return { - 'events': perm_holder.get_events_with_permission('can_view_orders', request=self.request).filter( + 'events': perm_holder.get_events_with_permission('event.orders:read', request=self.request).filter( organizer=self.request.organizer ) } @@ -216,11 +216,11 @@ class ScheduledExportersViewSet(viewsets.ModelViewSet): class ScheduledEventExportViewSet(ScheduledExportersViewSet): serializer_class = ScheduledEventExportSerializer queryset = ScheduledEventExport.objects.none() - permission = 'can_view_orders' + permission = 'event.orders:read' def get_queryset(self): perm_holder = self.request.auth if isinstance(self.request.auth, (TeamAPIToken, Device)) else self.request.user - if not perm_holder.has_event_permission(self.request.organizer, self.request.event, 'can_change_event_settings', + if not perm_holder.has_event_permission(self.request.organizer, self.request.event, 'event.settings.general:write', request=self.request): if self.request.user.is_authenticated: qs = self.request.event.scheduled_exports.filter(owner=self.request.user) @@ -285,7 +285,7 @@ class ScheduledOrganizerExportViewSet(ScheduledExportersViewSet): def get_queryset(self): perm_holder = self.request.auth if isinstance(self.request.auth, (TeamAPIToken, Device)) else self.request.user - if not perm_holder.has_organizer_permission(self.request.organizer, 'can_change_organizer_settings', + if not perm_holder.has_organizer_permission(self.request.organizer, 'organizer.settings.general:write', request=self.request): if self.request.user.is_authenticated: qs = self.request.organizer.scheduled_exports.filter(owner=self.request.user) @@ -318,9 +318,9 @@ class ScheduledOrganizerExportViewSet(ScheduledExportersViewSet): @cached_property def events(self): if isinstance(self.request.auth, (TeamAPIToken, Device)): - return self.request.auth.get_events_with_permission('can_view_orders') + return self.request.auth.get_events_with_permission('event.orders:read') elif self.request.user.is_authenticated: - return self.request.user.get_events_with_permission('can_view_orders', self.request).filter( + return self.request.user.get_events_with_permission('event.orders:read', self.request).filter( organizer=self.request.organizer ) diff --git a/src/pretix/api/views/item.py b/src/pretix/api/views/item.py index a84fa589a..e5e1b2b4d 100644 --- a/src/pretix/api/views/item.py +++ b/src/pretix/api/views/item.py @@ -99,7 +99,7 @@ class ItemViewSet(ConditionalListView, viewsets.ModelViewSet): ordering = ('position', 'id') filterset_class = ItemFilter permission = None - write_permission = 'can_change_items' + write_permission = 'event.items:write' def get_queryset(self): return self.request.event.items.select_related('tax_rule').prefetch_related( @@ -163,7 +163,7 @@ class ItemVariationViewSet(viewsets.ModelViewSet): ordering_fields = ('id', 'position') ordering = ('id',) permission = None - write_permission = 'can_change_items' + write_permission = 'event.items:write' @cached_property def item(self): @@ -234,7 +234,7 @@ class ItemBundleViewSet(viewsets.ModelViewSet): ordering_fields = ('id',) ordering = ('id',) permission = None - write_permission = 'can_change_items' + write_permission = 'event.items:write' @cached_property def item(self): @@ -286,7 +286,7 @@ class ItemProgramTimeViewSet(viewsets.ModelViewSet): ordering_fields = ('id',) ordering = ('id',) permission = None - write_permission = 'can_change_items' + write_permission = 'event.items:write' @cached_property def item(self): @@ -339,7 +339,7 @@ class ItemAddOnViewSet(viewsets.ModelViewSet): ordering_fields = ('id', 'position') ordering = ('id',) permission = None - write_permission = 'can_change_items' + write_permission = 'event.items:write' @cached_property def item(self): @@ -398,7 +398,7 @@ class ItemCategoryViewSet(ConditionalListView, viewsets.ModelViewSet): ordering_fields = ('id', 'position') ordering = ('position', 'id') permission = None - write_permission = 'can_change_items' + write_permission = 'event.items:write' def get_queryset(self): return self.request.event.categories.all() @@ -453,7 +453,7 @@ class QuestionViewSet(ConditionalListView, viewsets.ModelViewSet): ordering_fields = ('id', 'position') ordering = ('position', 'id') permission = None - write_permission = 'can_change_items' + write_permission = 'event.items:write' def get_queryset(self): return self.request.event.questions.prefetch_related('options').all() @@ -497,7 +497,7 @@ class QuestionOptionViewSet(viewsets.ModelViewSet): ordering_fields = ('id', 'position') ordering = ('position',) permission = None - write_permission = 'can_change_items' + write_permission = 'event.items:write' def get_queryset(self): q = get_object_or_404(Question, pk=self.kwargs['question'], event=self.request.event) @@ -564,7 +564,7 @@ class QuotaViewSet(ConditionalListView, viewsets.ModelViewSet): ordering_fields = ('id', 'size') ordering = ('id',) permission = None - write_permission = 'can_change_items' + write_permission = 'event.items:write' def get_queryset(self): return self.request.event.quotas.select_related('subevent').prefetch_related('items', 'variations').all() diff --git a/src/pretix/api/views/media.py b/src/pretix/api/views/media.py index 1569ee289..d16bb6a56 100644 --- a/src/pretix/api/views/media.py +++ b/src/pretix/api/views/media.py @@ -62,8 +62,8 @@ 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' + permission = 'organizer.reusablemedia:read' + write_permission = 'organizer.reusablemedia:write' filter_backends = (DjangoFilterBackend, OrderingFilter) ordering = ('-updated', '-id') ordering_fields = ('created', 'updated', 'identifier', 'type', 'id') diff --git a/src/pretix/api/views/order.py b/src/pretix/api/views/order.py index 51d463047..5dc758552 100644 --- a/src/pretix/api/views/order.py +++ b/src/pretix/api/views/order.py @@ -317,7 +317,7 @@ class OrderViewSetMixin: class OrganizerOrderViewSet(OrderViewSetMixin, viewsets.ReadOnlyModelViewSet): def get_base_queryset(self): - perm = "can_view_orders" if self.request.method in SAFE_METHODS else "can_change_orders" + perm = "event.orders:read" if self.request.method in SAFE_METHODS else "event.orders:write" if isinstance(self.request.auth, (TeamAPIToken, Device)): return Order.objects.filter( event__organizer=self.request.organizer, @@ -338,8 +338,8 @@ class OrganizerOrderViewSet(OrderViewSetMixin, viewsets.ReadOnlyModelViewSet): class EventOrderViewSet(OrderViewSetMixin, viewsets.ModelViewSet): - permission = 'can_view_orders' - write_permission = 'can_change_orders' + permission = 'event.orders:read' + write_permission = 'event.orders:write' def get_serializer_context(self): ctx = super().get_serializer_context() @@ -1078,8 +1078,8 @@ class OrderPositionViewSet(viewsets.ModelViewSet): ordering = ('order__datetime', 'positionid') ordering_fields = ('order__code', 'order__datetime', 'positionid', 'attendee_name', 'order__status',) filterset_class = OrderPositionFilter - permission = 'can_view_orders' - write_permission = 'can_change_orders' + permission = 'event.orders:read' + write_permission = 'event.orders:write' ordering_custom = { 'attendee_name': { '_order': F('display_name').asc(nulls_first=True), @@ -1580,8 +1580,8 @@ class OrderPositionViewSet(viewsets.ModelViewSet): class PaymentViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet): serializer_class = OrderPaymentSerializer queryset = OrderPayment.objects.none() - permission = 'can_view_orders' - write_permission = 'can_change_orders' + permission = 'event.orders:read' + write_permission = 'event.orders:write' lookup_field = 'local_id' def get_serializer_context(self): @@ -1757,8 +1757,8 @@ class PaymentViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet): class RefundViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet): serializer_class = OrderRefundSerializer queryset = OrderRefund.objects.none() - permission = 'can_view_orders' - write_permission = 'can_change_orders' + permission = 'event.orders:read' + write_permission = 'event.orders:write' lookup_field = 'local_id' def get_queryset(self): @@ -1915,13 +1915,13 @@ class InvoiceViewSet(viewsets.ReadOnlyModelViewSet): ordering = ('nr',) ordering_fields = ('nr', 'date') filterset_class = InvoiceFilter - permission = 'can_view_orders' + permission = 'event.orders:read' lookup_url_kwarg = 'number' lookup_field = 'nr' - write_permission = 'can_change_orders' + write_permission = 'event.orders:write' def get_queryset(self): - perm = "can_view_orders" if self.request.method in SAFE_METHODS else "can_change_orders" + perm = "event.orders:read" if self.request.method in SAFE_METHODS else "event.orders:write" if getattr(self.request, 'event', None): qs = self.request.event.invoices elif isinstance(self.request.auth, (TeamAPIToken, Device)): @@ -2062,8 +2062,8 @@ class RevokedSecretViewSet(viewsets.ReadOnlyModelViewSet): ordering = ('-created',) ordering_fields = ('created', 'secret') filterset_class = RevokedSecretFilter - permission = 'can_view_orders' - write_permission = 'can_change_orders' + permission = 'event.orders:read' + write_permission = 'event.orders:write' def get_queryset(self): return RevokedTicketSecret.objects.filter(event=self.request.event) @@ -2084,8 +2084,8 @@ class BlockedSecretViewSet(viewsets.ReadOnlyModelViewSet): filter_backends = (DjangoFilterBackend, TotalOrderingFilter) ordering = ('-updated', '-pk') filterset_class = BlockedSecretFilter - permission = 'can_view_orders' - write_permission = 'can_change_orders' + permission = 'event.orders:read' + write_permission = 'event.orders:write' def get_queryset(self): return BlockedTicketSecret.objects.filter(event=self.request.event) @@ -2120,7 +2120,7 @@ class TransactionViewSet(viewsets.ReadOnlyModelViewSet): ordering = ('datetime', 'pk') ordering_fields = ('datetime', 'created', 'id',) filterset_class = TransactionFilter - permission = 'can_view_orders' + permission = 'event.orders:read' def get_queryset(self): return Transaction.objects.filter(order__event=self.request.event).select_related("order") @@ -2137,11 +2137,11 @@ class OrganizerTransactionViewSet(TransactionViewSet): if isinstance(self.request.auth, (TeamAPIToken, Device)): qs = qs.filter( - order__event__in=self.request.auth.get_events_with_permission("can_view_orders"), + order__event__in=self.request.auth.get_events_with_permission("event.orders:read"), ) elif self.request.user.is_authenticated: qs = qs.filter( - order__event__in=self.request.user.get_events_with_permission("can_view_orders", request=self.request) + order__event__in=self.request.user.get_events_with_permission("event.orders:read", request=self.request) ) else: raise PermissionDenied("Unknown authentication scheme") diff --git a/src/pretix/api/views/organizer.py b/src/pretix/api/views/organizer.py index f084a1679..9a79b3ec1 100644 --- a/src/pretix/api/views/organizer.py +++ b/src/pretix/api/views/organizer.py @@ -70,7 +70,7 @@ class OrganizerViewSet(mixins.UpdateModelMixin, viewsets.ReadOnlyModelViewSet): filter_backends = (TotalOrderingFilter,) ordering = ('slug',) ordering_fields = ('name', 'slug') - write_permission = "can_change_organizer_settings" + write_permission = "organizer.settings.general:write" def get_queryset(self): if self.request.user.is_authenticated: @@ -154,8 +154,8 @@ class OrganizerViewSet(mixins.UpdateModelMixin, viewsets.ReadOnlyModelViewSet): class SeatingPlanViewSet(viewsets.ModelViewSet): serializer_class = SeatingPlanSerializer queryset = SeatingPlan.objects.none() - permission = 'can_change_organizer_settings' - write_permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' + write_permission = 'organizer.settings.general:write' def get_queryset(self): return self.request.organizer.seating_plans.order_by('name') @@ -221,8 +221,8 @@ with scopes_disabled(): class GiftCardViewSet(viewsets.ModelViewSet): serializer_class = GiftCardSerializer queryset = GiftCard.objects.none() - permission = 'can_manage_gift_cards' - write_permission = 'can_manage_gift_cards' + permission = 'organizer.giftcards:write' + write_permission = 'organizer.giftcards:write' filter_backends = (DjangoFilterBackend,) filterset_class = GiftCardFilter @@ -323,8 +323,8 @@ class GiftCardViewSet(viewsets.ModelViewSet): class GiftCardTransactionViewSet(viewsets.ReadOnlyModelViewSet): serializer_class = GiftCardTransactionSerializer queryset = GiftCardTransaction.objects.none() - permission = 'can_manage_gift_cards' - write_permission = 'can_manage_gift_cards' + permission = 'organizer.giftcards:write' + write_permission = 'organizer.giftcards:write' @cached_property def giftcard(self): @@ -341,8 +341,8 @@ class GiftCardTransactionViewSet(viewsets.ReadOnlyModelViewSet): class TeamViewSet(viewsets.ModelViewSet): serializer_class = TeamSerializer queryset = Team.objects.none() - permission = 'can_change_teams' - write_permission = 'can_change_teams' + permission = 'organizer.teams:write' + write_permission = 'organizer.teams:write' def get_queryset(self): return self.request.organizer.teams.order_by('pk') @@ -381,8 +381,8 @@ class TeamViewSet(viewsets.ModelViewSet): class TeamMemberViewSet(DestroyModelMixin, viewsets.ReadOnlyModelViewSet): serializer_class = TeamMemberSerializer queryset = User.objects.none() - permission = 'can_change_teams' - write_permission = 'can_change_teams' + permission = 'organizer.teams:write' + write_permission = 'organizer.teams:write' @cached_property def team(self): @@ -410,8 +410,8 @@ class TeamMemberViewSet(DestroyModelMixin, viewsets.ReadOnlyModelViewSet): class TeamInviteViewSet(CreateModelMixin, DestroyModelMixin, viewsets.ReadOnlyModelViewSet): serializer_class = TeamInviteSerializer queryset = TeamInvite.objects.none() - permission = 'can_change_teams' - write_permission = 'can_change_teams' + permission = 'organizer.teams:write' + write_permission = 'organizer.teams:write' @cached_property def team(self): @@ -447,8 +447,8 @@ class TeamInviteViewSet(CreateModelMixin, DestroyModelMixin, viewsets.ReadOnlyMo class TeamAPITokenViewSet(CreateModelMixin, DestroyModelMixin, viewsets.ReadOnlyModelViewSet): serializer_class = TeamAPITokenSerializer queryset = TeamAPIToken.objects.none() - permission = 'can_change_teams' - write_permission = 'can_change_teams' + permission = 'organizer.teams:write' + write_permission = 'organizer.teams:write' @cached_property def team(self): @@ -511,8 +511,8 @@ class DeviceViewSet(mixins.CreateModelMixin, GenericViewSet): serializer_class = DeviceSerializer queryset = Device.objects.none() - permission = 'can_change_organizer_settings' - write_permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' + write_permission = 'organizer.settings.general:write' lookup_field = 'device_id' def get_queryset(self): @@ -547,7 +547,7 @@ class DeviceViewSet(mixins.CreateModelMixin, class OrganizerSettingsView(views.APIView): permission = None - write_permission = 'can_change_organizer_settings' + write_permission = 'organizer.settings.general:write' def get(self, request, *args, **kwargs): s = OrganizerSettingsSerializer(instance=request.organizer.settings, organizer=request.organizer, context={ @@ -597,7 +597,7 @@ with scopes_disabled(): class CustomerViewSet(viewsets.ModelViewSet): serializer_class = CustomerSerializer queryset = Customer.objects.none() - permission = 'can_manage_customers' + permission = 'organizer.customers:write' lookup_field = 'identifier' filter_backends = (DjangoFilterBackend,) filterset_class = CustomerFilter @@ -657,7 +657,7 @@ class CustomerViewSet(viewsets.ModelViewSet): class MembershipTypeViewSet(viewsets.ModelViewSet): serializer_class = MembershipTypeSerializer queryset = MembershipType.objects.none() - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' def get_queryset(self): qs = self.request.organizer.membership_types.all() @@ -714,7 +714,7 @@ with scopes_disabled(): class MembershipViewSet(viewsets.ModelViewSet): serializer_class = MembershipSerializer queryset = Membership.objects.none() - permission = 'can_manage_customers' + permission = 'organizer.customers:write' filter_backends = (DjangoFilterBackend,) filterset_class = MembershipFilter @@ -764,8 +764,8 @@ with scopes_disabled(): class SalesChannelViewSet(viewsets.ModelViewSet): serializer_class = SalesChannelSerializer queryset = SalesChannel.objects.none() - permission = 'can_change_organizer_settings' - write_permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' + write_permission = 'organizer.settings.general:write' filter_backends = (DjangoFilterBackend,) filterset_class = SalesChannelFilter lookup_field = 'identifier' diff --git a/src/pretix/api/views/shredders.py b/src/pretix/api/views/shredders.py index acb34fa83..26925d9a9 100644 --- a/src/pretix/api/views/shredders.py +++ b/src/pretix/api/views/shredders.py @@ -204,7 +204,7 @@ class ShreddersMixin: class EventShreddersViewSet(ShreddersMixin, viewsets.ViewSet): - permission = 'can_change_orders' + permission = 'event.orders:write' def get_serializer_kwargs(self): return {} diff --git a/src/pretix/api/views/voucher.py b/src/pretix/api/views/voucher.py index 2d6243b24..5527a11e5 100644 --- a/src/pretix/api/views/voucher.py +++ b/src/pretix/api/views/voucher.py @@ -62,8 +62,8 @@ class VoucherViewSet(viewsets.ModelViewSet): ordering = ('id',) ordering_fields = ('id', 'code', 'max_usages', 'valid_until', 'value') filterset_class = VoucherFilter - permission = 'can_view_vouchers' - write_permission = 'can_change_vouchers' + permission = 'event.vouchers:read' + write_permission = 'event.vouchers:write' @scopes_disabled() # we have an event check here, and we can save some performance on subqueries def get_queryset(self): diff --git a/src/pretix/api/views/waitinglist.py b/src/pretix/api/views/waitinglist.py index f645a5e56..569c64b56 100644 --- a/src/pretix/api/views/waitinglist.py +++ b/src/pretix/api/views/waitinglist.py @@ -51,8 +51,8 @@ class WaitingListViewSet(viewsets.ModelViewSet): ordering = ('created', 'pk',) ordering_fields = ('id', 'created', 'email', 'item') filterset_class = WaitingListFilter - permission = 'can_view_orders' - write_permission = 'can_change_orders' + permission = 'event.orders:read' + write_permission = 'event.orders:write' def get_queryset(self): return self.request.event.waitinglistentries.all() diff --git a/src/pretix/api/views/webhooks.py b/src/pretix/api/views/webhooks.py index f0c781523..b7b883906 100644 --- a/src/pretix/api/views/webhooks.py +++ b/src/pretix/api/views/webhooks.py @@ -35,8 +35,8 @@ class WebhookFilter(FilterSet): class WebHookViewSet(viewsets.ModelViewSet): serializer_class = WebHookSerializer queryset = WebHook.objects.none() - permission = 'can_change_organizer_settings' - write_permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' + write_permission = 'organizer.settings.general:write' filter_backends = (DjangoFilterBackend,) filterset_class = WebhookFilter diff --git a/src/pretix/base/auth.py b/src/pretix/base/auth.py index f504729ee..dd7e8201d 100644 --- a/src/pretix/base/auth.py +++ b/src/pretix/base/auth.py @@ -224,7 +224,7 @@ class HistoryPasswordValidator: ).delete() -def has_event_access_permission(request, permission='can_change_event_settings'): +def has_event_access_permission(request, permission='event.settings.general:write'): return ( request.user.is_authenticated and request.user.has_event_permission(request.organizer, request.event, permission, request=request) diff --git a/src/pretix/base/exporter.py b/src/pretix/base/exporter.py index 2a40dabc9..f23e5bf11 100644 --- a/src/pretix/base/exporter.py +++ b/src/pretix/base/exporter.py @@ -184,7 +184,7 @@ class OrganizerLevelExportMixin: The permission level required to use this exporter. Only useful for organizer-level exports, not for event-level exports. """ - return 'can_view_orders' + return 'event.orders:read' class ListExporter(BaseExporter): diff --git a/src/pretix/base/exporters/customers.py b/src/pretix/base/exporters/customers.py index 7aa748093..0675c2d5e 100644 --- a/src/pretix/base/exporters/customers.py +++ b/src/pretix/base/exporters/customers.py @@ -47,7 +47,7 @@ from ..signals import register_multievent_data_exporters class CustomerListExporter(OrganizerLevelExportMixin, ListExporter): identifier = 'customerlist' verbose_name = gettext_lazy('Customer accounts') - organizer_required_permission = 'can_manage_customers' + organizer_required_permission = 'organizer.customers:write' category = pgettext_lazy('export_category', 'Customer accounts') description = gettext_lazy('Download a spreadsheet of all currently registered customer accounts.') diff --git a/src/pretix/base/exporters/orderlist.py b/src/pretix/base/exporters/orderlist.py index 945737d35..d4ac2cc2f 100644 --- a/src/pretix/base/exporters/orderlist.py +++ b/src/pretix/base/exporters/orderlist.py @@ -1200,7 +1200,7 @@ class QuotaListExporter(ListExporter): class GiftcardTransactionListExporter(OrganizerLevelExportMixin, ListExporter): identifier = 'giftcardtransactionlist' verbose_name = gettext_lazy('Gift card transactions') - organizer_required_permission = 'can_manage_gift_cards' + organizer_required_permission = 'organizer.giftcards:write' category = pgettext_lazy('export_category', 'Gift cards') description = gettext_lazy('Download a spreadsheet of all gift card transactions.') repeatable_read = False @@ -1307,7 +1307,7 @@ class GiftcardRedemptionListExporter(ListExporter): class GiftcardListExporter(OrganizerLevelExportMixin, ListExporter): identifier = 'giftcardlist' verbose_name = gettext_lazy('Gift cards') - organizer_required_permission = 'can_manage_gift_cards' + organizer_required_permission = 'organizer.giftcards:write' category = pgettext_lazy('export_category', 'Gift cards') description = gettext_lazy('Download a spreadsheet of all gift cards including their current value.') diff --git a/src/pretix/base/models/devices.py b/src/pretix/base/models/devices.py index c94cf6827..52f4a2045 100644 --- a/src/pretix/base/models/devices.py +++ b/src/pretix/base/models/devices.py @@ -191,11 +191,13 @@ class Device(LoggedModel): def permission_set(self) -> set: return { - 'can_view_orders', - 'can_change_orders', - 'can_view_vouchers', - 'can_manage_gift_cards', - 'can_manage_reusable_media', + 'event.orders:read', + 'event.orders:write', + 'event.vouchers:read', + 'organizer.giftcards:read', + 'organizer.giftcards:write', + 'organizer.reusablemedia:read', + 'organizer.reusablemedia:write', } def get_event_permission_set(self, organizer, event) -> set: @@ -271,7 +273,7 @@ class Device(LoggedModel): :return: Iterable of Events """ if ( - isinstance(permission, (list, tuple)) and any(p in self.permission_set() for p in permission) + isinstance(permission, (list, tuple)) and any(p in self.permission_set() for p in permission) ) or (isinstance(permission, str) and permission in self.permission_set()): return self.get_events_with_any_permission() else: diff --git a/src/pretix/base/models/organizer.py b/src/pretix/base/models/organizer.py index 20ddb9062..ae5921fbf 100644 --- a/src/pretix/base/models/organizer.py +++ b/src/pretix/base/models/organizer.py @@ -578,8 +578,8 @@ class TeamAPIToken(models.Model): :return: Iterable of Events """ if ( - isinstance(permission, (list, tuple)) and any(getattr(self.team, p, False) for p in permission) - ) or (isinstance(permission, str) and getattr(self.team, permission, False)): + isinstance(permission, (list, tuple)) and any(self.team.has_event_permission(p) for p in permission) + ) or (isinstance(permission, str) and self.team.has_event_permission(permission)): return self.get_events_with_any_permission() else: return self.team.organizer.events.none() diff --git a/src/pretix/base/notifications.py b/src/pretix/base/notifications.py index b95d48406..e29b94723 100644 --- a/src/pretix/base/notifications.py +++ b/src/pretix/base/notifications.py @@ -151,7 +151,7 @@ def get_all_notification_types(event=None): class ParametrizedOrderNotificationType(NotificationType): - required_permission = "can_view_orders" + required_permission = "event.orders:read" def __init__(self, event, action_type, verbose_name, title): self._action_type = action_type diff --git a/src/pretix/base/services/export.py b/src/pretix/base/services/export.py index c1fbe0664..7684d8b51 100644 --- a/src/pretix/base/services/export.py +++ b/src/pretix/base/services/export.py @@ -106,7 +106,7 @@ def multiexport(self, organizer: Organizer, user: User, device: int, token: int, device = Device.objects.get(pk=device) if token: device = TeamAPIToken.objects.get(pk=token) - allowed_events = (device or token or user).get_events_with_permission('can_view_orders') + allowed_events = (device or token or user).get_events_with_permission('event.orders:read') if user and staff_session: allowed_events = organizer.events.all() @@ -291,7 +291,7 @@ def _run_scheduled_export(schedule, context: Union[Event, Organizer], exporter, def scheduled_organizer_export(self, organizer: Organizer, schedule: int) -> None: schedule = organizer.scheduled_exports.get(pk=schedule) - allowed_events = schedule.owner.get_events_with_permission('can_view_orders') + allowed_events = schedule.owner.get_events_with_permission('event.orders:read') if schedule.export_form_data.get('events') is not None and not schedule.export_form_data.get('all_events'): if isinstance(schedule.export_form_data['events'][0], str): events = allowed_events.filter(slug__in=schedule.export_form_data.get('events'), organizer=organizer) @@ -346,7 +346,7 @@ def scheduled_event_export(self, event: Event, schedule: int) -> None: exporter = ex break - has_permission = schedule.owner.is_active and schedule.owner.has_event_permission(event.organizer, event, 'can_view_orders') + has_permission = schedule.owner.is_active and schedule.owner.has_event_permission(event.organizer, event, 'event.orders:read') _run_scheduled_export( schedule, diff --git a/src/pretix/control/context.py b/src/pretix/control/context.py index 4480a1148..f622560ae 100644 --- a/src/pretix/control/context.py +++ b/src/pretix/control/context.py @@ -102,7 +102,7 @@ def _default_context(request): complain_testmode_orders = request.event.orders.filter(testmode=True).exists() request.event.cache.set('complain_testmode_orders', complain_testmode_orders, 30) ctx['complain_testmode_orders'] = complain_testmode_orders and request.user.has_event_permission( - request.organizer, request.event, 'can_view_orders', request=request + request.organizer, request.event, 'event.orders:read', request=request ) else: ctx['complain_testmode_orders'] = False diff --git a/src/pretix/control/forms/filter.py b/src/pretix/control/forms/filter.py index 0f3b2a1e4..f43745249 100644 --- a/src/pretix/control/forms/filter.py +++ b/src/pretix/control/forms/filter.py @@ -1110,7 +1110,7 @@ class OrderPaymentSearchFilterForm(forms.Form): self.fields['organizer'].queryset = Organizer.objects.filter( pk__in=self.request.user.teams.values_list('organizer', flat=True) ) - self.fields['event'].queryset = self.request.user.get_events_with_permission('can_view_orders') + self.fields['event'].queryset = self.request.user.get_events_with_permission('event.orders:read') self.fields['provider'].choices += get_all_payment_providers() diff --git a/src/pretix/control/navigation.py b/src/pretix/control/navigation.py index c3a0cbb8f..2fdb28ba9 100644 --- a/src/pretix/control/navigation.py +++ b/src/pretix/control/navigation.py @@ -43,7 +43,7 @@ def get_event_navigation(request: HttpRequest): 'icon': 'dashboard', } ] - if 'can_change_event_settings' in request.eventpermset: + if 'event.settings.general:write' in request.eventpermset: event_settings = [ { 'label': _('General'), @@ -133,7 +133,7 @@ def get_event_navigation(request: HttpRequest): 'children': event_settings }) - if 'can_change_items' in request.eventpermset: + if 'event.items:write' in request.eventpermset: nav.append({ 'label': _('Products'), 'url': reverse('control:event.items', kwargs={ @@ -187,7 +187,7 @@ def get_event_navigation(request: HttpRequest): ] }) - if 'can_change_event_settings' in request.eventpermset: + if 'event.settings.general:write' in request.eventpermset: if request.event.has_subevents: nav.append({ 'label': pgettext_lazy('subevent', 'Dates'), @@ -199,7 +199,7 @@ def get_event_navigation(request: HttpRequest): 'icon': 'calendar', }) - if 'can_view_orders' in request.eventpermset: + if 'event.orders:read' in request.eventpermset: children = [ { 'label': _('All orders'), @@ -242,7 +242,7 @@ def get_event_navigation(request: HttpRequest): 'active': 'event.orders.waitinglist' in url.url_name, }, ] - if 'can_change_orders' in request.eventpermset: + if 'event.orders:write' in request.eventpermset: children.append({ 'label': _('Import'), 'url': reverse('control:event.orders.import', kwargs={ @@ -262,7 +262,7 @@ def get_event_navigation(request: HttpRequest): 'children': children }) - if 'can_view_vouchers' in request.eventpermset: + if 'event.vouchers:read' in request.eventpermset: nav.append({ 'label': _('Vouchers'), 'url': reverse('control:event.vouchers', kwargs={ @@ -291,7 +291,7 @@ def get_event_navigation(request: HttpRequest): ] }) - if 'can_view_orders' in request.eventpermset: + if 'event.orders:read' in request.eventpermset: nav.append({ 'label': pgettext_lazy('navigation', 'Check-in'), 'url': reverse('control:event.orders.checkinlists', kwargs={ @@ -480,7 +480,7 @@ def get_organizer_navigation(request): 'icon': 'calendar', }, ] - if 'can_change_organizer_settings' in request.orgapermset: + if 'organizer.settings.general:write' in request.orgapermset: nav.append({ 'label': _('Settings'), 'url': reverse('control:organizer.edit', kwargs={ @@ -534,7 +534,7 @@ def get_organizer_navigation(request): ] }) - if 'can_change_teams' in request.orgapermset: + if 'organizer.teams:write' in request.orgapermset: nav.append({ 'label': _('Teams'), 'url': reverse('control:organizer.teams', kwargs={ @@ -544,7 +544,7 @@ def get_organizer_navigation(request): 'icon': 'group', }) - if 'can_manage_gift_cards' in request.orgapermset: + if 'organizer.giftcards:write' in request.orgapermset: children = [] children.append({ 'label': _('Gift cards'), @@ -554,7 +554,7 @@ def get_organizer_navigation(request): 'active': 'organizer.giftcard' in url.url_name and 'acceptance' not in url.url_name, 'children': children, }) - if 'can_change_organizer_settings' in request.orgapermset: + if 'organizer.settings.general:write' in request.orgapermset: children.append( { 'label': _('Acceptance'), @@ -575,7 +575,7 @@ def get_organizer_navigation(request): if request.organizer.settings.customer_accounts: children = [] - if 'can_manage_customers' in request.orgapermset: + if 'organizer.customers:write' in request.orgapermset: children.append( { 'label': _('Customers'), @@ -585,7 +585,7 @@ def get_organizer_navigation(request): 'active': 'organizer.customer' in url.url_name, } ) - if 'can_change_organizer_settings' in request.orgapermset: + if 'organizer.settings.general:write' in request.orgapermset: children.append( { 'label': _('Membership types'), @@ -633,7 +633,7 @@ def get_organizer_navigation(request): 'active': 'organizer.reusable_medi' in url.url_name, }) - if 'can_change_organizer_settings' in request.orgapermset: + if 'organizer.settings.general:write' in request.orgapermset: nav.append({ 'label': _('Devices'), 'url': reverse('control:organizer.devices', kwargs={ @@ -667,7 +667,7 @@ def get_organizer_navigation(request): 'icon': 'download', }) - if 'can_change_organizer_settings' in request.orgapermset: + if 'organizer.settings.general:write' in request.orgapermset: merge_in(nav, [{ 'parent': reverse('control:organizer.export', kwargs={ 'organizer': request.organizer.slug, diff --git a/src/pretix/control/permissions.py b/src/pretix/control/permissions.py index 059e2c9d3..9a25dfc38 100644 --- a/src/pretix/control/permissions.py +++ b/src/pretix/control/permissions.py @@ -53,9 +53,9 @@ def event_permission_required(permission): This view decorator rejects all requests with a 403 response which are not from users having the given permission for the event the request is associated with. """ - if permission == 'can_change_settings': + if permission == 'event.settings.general:write': # Legacy support - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' def decorator(function): def wrapper(request, *args, **kw): @@ -92,9 +92,9 @@ def organizer_permission_required(permission): This view decorator rejects all requests with a 403 response which are not from users having the given permission for the event the request is associated with. """ - if permission == 'can_change_settings': + if permission == 'event.settings.general:write': # Legacy support - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' def decorator(function): def wrapper(request, *args, **kw): diff --git a/src/pretix/control/views/checkin.py b/src/pretix/control/views/checkin.py index cd5ce59e1..56fa543b4 100644 --- a/src/pretix/control/views/checkin.py +++ b/src/pretix/control/views/checkin.py @@ -150,7 +150,7 @@ class CheckInListShow(EventPermissionRequiredMixin, PaginationMixin, CheckInList model = Checkin context_object_name = 'entries' template_name = 'pretixcontrol/checkin/index.html' - permission = 'can_view_orders' + permission = 'event.orders:read' def dispatch(self, request, *args, **kwargs): self.list = get_object_or_404(self.request.event.checkin_lists.all(), pk=kwargs.get("list")) @@ -211,7 +211,7 @@ class CheckInListBulkRevertConfirmView(CheckInListQueryMixin, EventPermissionReq class CheckInListBulkActionView(CheckInListQueryMixin, EventPermissionRequiredMixin, AsyncPostView): - permission = ('can_change_orders', 'can_checkin_orders') + permission = ('event.orders:write', 'event.orders:checkin') def dispatch(self, request, *args, **kwargs): self.list = get_object_or_404(self.request.event.checkin_lists.all(), pk=kwargs.get("list")) @@ -228,7 +228,7 @@ class CheckInListBulkActionView(CheckInListQueryMixin, EventPermissionRequiredMi self.list = get_object_or_404(request.event.checkin_lists.all(), pk=kwargs.get("list")) positions = self.get_queryset() if request.POST.get('revert') == 'true': - if not request.user.has_event_permission(request.organizer, request.event, 'can_change_orders', request=request): + if not request.user.has_event_permission(request.organizer, request.event, 'event.orders:write', request=request): raise PermissionDenied() for op in positions: if op.order.status == Order.STATUS_PAID or ( @@ -295,7 +295,7 @@ class CheckInListBulkActionView(CheckInListQueryMixin, EventPermissionRequiredMi class CheckinListList(EventPermissionRequiredMixin, PaginationMixin, ListView): model = CheckinList context_object_name = 'checkinlists' - permission = 'can_view_orders' + permission = 'event.orders:read' template_name = 'pretixcontrol/checkin/lists.html' ordering = ('subevent__date_from', 'name', 'pk') @@ -317,9 +317,9 @@ class CheckinListList(EventPermissionRequiredMixin, PaginationMixin, ListView): cl.subevent.event = self.request.event # re-use same event object to make sure settings are cached ctx['checkinlists'] = clists - ctx['can_change_organizer_settings'] = self.request.user.has_organizer_permission( + ctx['organizer.settings.general:write'] = self.request.user.has_organizer_permission( self.request.organizer, - 'can_change_organizer_settings', + 'organizer.settings.general:write', self.request ) ctx['filter_form'] = self.filter_form @@ -335,7 +335,7 @@ class CheckinListCreate(EventPermissionRequiredMixin, CreateView): model = CheckinList form_class = CheckinListForm template_name = 'pretixcontrol/checkin/list_edit.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' context_object_name = 'checkinlist' def dispatch(self, request, *args, **kwargs): @@ -386,7 +386,7 @@ class CheckinListUpdate(EventPermissionRequiredMixin, UpdateView): model = CheckinList form_class = CheckinListForm template_name = 'pretixcontrol/checkin/list_edit.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' context_object_name = 'checkinlist' def dispatch(self, request, *args, **kwargs): @@ -445,7 +445,7 @@ class CheckinListUpdate(EventPermissionRequiredMixin, UpdateView): class CheckinListDelete(EventPermissionRequiredMixin, CompatDeleteView): model = CheckinList template_name = 'pretixcontrol/checkin/list_delete.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' context_object_name = 'checkinlist' def get_object(self, queryset=None) -> CheckinList: @@ -476,7 +476,7 @@ class CheckinListDelete(EventPermissionRequiredMixin, CompatDeleteView): class CheckinListView(EventPermissionRequiredMixin, PaginationMixin, ListView): model = Checkin context_object_name = 'checkins' - permission = 'can_view_orders' + permission = 'event.orders:read' template_name = 'pretixcontrol/checkin/checkins.html' ordering = ('-datetime', '-pk') @@ -505,7 +505,7 @@ class CheckinListView(EventPermissionRequiredMixin, PaginationMixin, ListView): class CheckInListSimulator(EventPermissionRequiredMixin, FormView): template_name = 'pretixcontrol/checkin/simulator.html' - permission = 'can_view_orders' + permission = 'event.orders:read' form_class = CheckinListSimulatorForm def dispatch(self, request, *args, **kwargs): @@ -575,7 +575,7 @@ class CheckInListSimulator(EventPermissionRequiredMixin, FormView): class CheckInResetView(CheckInListQueryMixin, EventPermissionRequiredMixin, AsyncFormView): form_class = CheckinResetForm - permission = "can_change_orders" + permission = "event.orders:write" template_name = "pretixcontrol/checkin/reset.html" def get_error_url(self, *args): diff --git a/src/pretix/control/views/dashboards.py b/src/pretix/control/views/dashboards.py index 6903091d3..569d941f0 100644 --- a/src/pretix/control/views/dashboards.py +++ b/src/pretix/control/views/dashboards.py @@ -351,10 +351,10 @@ def event_index(request, organizer, event): except SubEvent.DoesNotExist: pass - can_view_orders = request.user.has_event_permission(request.organizer, request.event, 'can_view_orders', + can_view_orders = request.user.has_event_permission(request.organizer, request.event, 'event.orders:read', request=request) can_change_event_settings = request.user.has_event_permission(request.organizer, request.event, - 'can_change_event_settings', request=request) + 'event.settings.general:write', request=request) widgets = [] if can_view_orders: @@ -426,11 +426,11 @@ def event_index_log_lazy(request, organizer, event): 'device').order_by('-datetime') qs = qs.exclude(action_type__in=OVERVIEW_BANLIST) - can_view_orders = request.user.has_event_permission(request.organizer, request.event, 'can_view_orders', + can_view_orders = request.user.has_event_permission(request.organizer, request.event, 'event.orders:read', request=request) can_change_event_settings = request.user.has_event_permission(request.organizer, request.event, - 'can_change_event_settings', request=request) - can_view_vouchers = request.user.has_event_permission(request.organizer, request.event, 'can_view_vouchers', + 'event.settings.general:write', request=request) + can_view_vouchers = request.user.has_event_permission(request.organizer, request.event, 'event.vouchers:read', request=request) if not can_view_orders: @@ -442,7 +442,7 @@ def event_index_log_lazy(request, organizer, event): ContentType.objects.get_for_model(Voucher), ContentType.objects.get_for_model(Order) ] - if request.user.has_event_permission(request.organizer, request.event, 'can_change_items', request=request): + if request.user.has_event_permission(request.organizer, request.event, 'event.items:write', request=request): allowed_types += [ ContentType.objects.get_for_model(Item), ContentType.objects.get_for_model(ItemCategory), diff --git a/src/pretix/control/views/datasync.py b/src/pretix/control/views/datasync.py index ebffd8da1..8f17e4441 100644 --- a/src/pretix/control/views/datasync.py +++ b/src/pretix/control/views/datasync.py @@ -72,7 +72,7 @@ def on_control_order_info(sender: Event, request, order: Order, **kwargs): class ControlSyncJob(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' def post(self, request, provider, *args, **kwargs): prov, meta = datasync_providers.get(active_in=self.request.event, identifier=provider) @@ -154,7 +154,7 @@ class GlobalFailedSyncJobsView(AdministratorPermissionRequiredMixin, FailedSyncJ class OrganizerFailedSyncJobsView(OrganizerPermissionRequiredMixin, FailedSyncJobsView): - permission = "can_change_organizer_settings" + permission = "organizer.settings.general:write" def get_queryset(self): return super().get_queryset().filter( @@ -163,7 +163,7 @@ class OrganizerFailedSyncJobsView(OrganizerPermissionRequiredMixin, FailedSyncJo class EventFailedSyncJobsView(EventPermissionRequiredMixin, FailedSyncJobsView): - permission = "can_change_event_settings" + permission = "event.settings.general:write" def get_queryset(self): return super().get_queryset().filter( diff --git a/src/pretix/control/views/discounts.py b/src/pretix/control/views/discounts.py index 28b5addbe..3b9055a6d 100644 --- a/src/pretix/control/views/discounts.py +++ b/src/pretix/control/views/discounts.py @@ -50,7 +50,7 @@ from . import CreateView, PaginationMixin, UpdateView class DiscountDelete(EventPermissionRequiredMixin, CompatDeleteView): model = Discount template_name = 'pretixcontrol/items/discount_delete.html' - permission = 'can_change_items' + permission = 'event.items:write' context_object_name = 'discount' def get_context_data(self, *args, **kwargs) -> dict: @@ -96,7 +96,7 @@ class DiscountUpdate(EventPermissionRequiredMixin, UpdateView): model = Discount form_class = DiscountForm template_name = 'pretixcontrol/items/discount.html' - permission = 'can_change_items' + permission = 'event.items:write' context_object_name = 'discount' def get_object(self, queryset=None) -> Discount: @@ -139,7 +139,7 @@ class DiscountCreate(EventPermissionRequiredMixin, CreateView): model = Discount form_class = DiscountForm template_name = 'pretixcontrol/items/discount.html' - permission = 'can_change_items' + permission = 'event.items:write' context_object_name = 'discount' def get_success_url(self) -> str: @@ -227,7 +227,7 @@ def discount_move(request, discount, up=True): messages.success(request, _('The order of discounts has been updated.')) -@event_permission_required("can_change_items") +@event_permission_required("event.items:write") @require_http_methods(["POST"]) def discount_move_up(request, organizer, event, discount): discount_move(request, discount, up=True) @@ -236,7 +236,7 @@ def discount_move_up(request, organizer, event, discount): event=request.event.slug) -@event_permission_required("can_change_items") +@event_permission_required("event.items:write") @require_http_methods(["POST"]) def discount_move_down(request, organizer, event, discount): discount_move(request, discount, up=False) @@ -246,7 +246,7 @@ def discount_move_down(request, organizer, event, discount): @transaction.atomic -@event_permission_required("can_change_items") +@event_permission_required("event.items:write") @require_http_methods(["POST"]) def reorder_discounts(request, organizer, event): try: diff --git a/src/pretix/control/views/event.py b/src/pretix/control/views/event.py index bb768d1e6..7aae6fe36 100644 --- a/src/pretix/control/views/event.py +++ b/src/pretix/control/views/event.py @@ -155,7 +155,7 @@ class MetaDataEditorMixin: property=p, disabled=( p.protected and - not self.request.user.has_organizer_permission(self.request.organizer, 'can_change_organizer_settings', request=self.request) + not self.request.user.has_organizer_permission(self.request.organizer, 'organizer.settings.general:write', request=self.request) ), instance=val_instances.get(p.pk, self.meta_model(property=p, event=self.object)), data=(self.request.POST if self.request.method == "POST" else None) @@ -187,7 +187,7 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired model = Event form_class = EventUpdateForm template_name = 'pretixcontrol/event/settings.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' @cached_property def object(self) -> Event: @@ -346,7 +346,7 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired class EventPlugins(EventSettingsViewMixin, EventPermissionRequiredMixin, TemplateView, SingleObjectMixin): model = Event context_object_name = 'event' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' template_name = 'pretixcontrol/event/plugins.html' def get_object(self, queryset=None) -> Event: @@ -447,7 +447,7 @@ class EventPlugins(EventSettingsViewMixin, EventPermissionRequiredMixin, Templat continue if getattr(pluginmeta, 'level', PLUGIN_LEVEL_EVENT) == PLUGIN_LEVEL_EVENT_ORGANIZER_HYBRID: - if not request.user.has_organizer_permission(request.organizer, "can_change_organizer_settings", request): + if not request.user.has_organizer_permission(request.organizer, "organizer.settings.general:write", request): messages.error( request, _("You do not have sufficient permission to enable plugins that need to be enabled " @@ -502,7 +502,7 @@ class EventPlugins(EventSettingsViewMixin, EventPermissionRequiredMixin, Templat class PaymentProviderSettings(EventSettingsViewMixin, EventPermissionRequiredMixin, TemplateView, SingleObjectMixin): model = Event context_object_name = 'event' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' template_name = 'pretixcontrol/event/payment_provider.html' def get_success_url(self) -> str: @@ -581,7 +581,7 @@ class PaymentProviderSettings(EventSettingsViewMixin, EventPermissionRequiredMix class EventSettingsFormView(EventPermissionRequiredMixin, DecoupleMixin, FormView): model = Event - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' def get_context_data(self, *args, **kwargs) -> dict: context = super().get_context_data(*args, **kwargs) @@ -621,7 +621,7 @@ class EventSettingsFormView(EventPermissionRequiredMixin, DecoupleMixin, FormVie class PaymentSettings(EventSettingsViewMixin, EventSettingsFormView): template_name = 'pretixcontrol/event/payment.html' form_class = PaymentSettingsForm - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' def get_success_url(self) -> str: return reverse('control:event.settings.payment', kwargs={ @@ -650,7 +650,7 @@ class PaymentSettings(EventSettingsViewMixin, EventSettingsFormView): class TaxSettings(EventSettingsViewMixin, EventSettingsFormView): template_name = 'pretixcontrol/event/tax.html' form_class = TaxSettingsForm - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' def get_success_url(self) -> str: return reverse('control:event.settings.tax', kwargs={ @@ -670,7 +670,7 @@ class InvoiceSettings(EventSettingsViewMixin, EventSettingsFormView): model = Event form_class = InvoiceSettingsForm template_name = 'pretixcontrol/event/invoicing.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' def get_context_data(self, **kwargs): types = get_transmission_types() @@ -704,7 +704,7 @@ class CancelSettings(EventSettingsViewMixin, EventSettingsFormView): model = Event form_class = CancelSettingsForm template_name = 'pretixcontrol/event/cancel.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' def get_success_url(self) -> str: return reverse('control:event.settings.cancel', kwargs={ @@ -738,7 +738,7 @@ class CancelSettings(EventSettingsViewMixin, EventSettingsFormView): class InvoicePreview(EventPermissionRequiredMixin, View): - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' def get(self, request, *args, **kwargs): fname, ftype, fcontent = build_preview_invoice_pdf(request.event) @@ -753,7 +753,7 @@ class InvoicePreview(EventPermissionRequiredMixin, View): class DangerZone(EventPermissionRequiredMixin, TemplateView): - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' template_name = 'pretixcontrol/event/dangerzone.html' @@ -769,7 +769,7 @@ class MailSettings(EventSettingsViewMixin, EventSettingsFormView): model = Event form_class = MailSettingsForm template_name = 'pretixcontrol/event/mail.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' def get_success_url(self) -> str: return reverse('control:event.settings.mail', kwargs={ @@ -801,7 +801,7 @@ class MailSettings(EventSettingsViewMixin, EventSettingsFormView): class MailSettingsSetup(EventPermissionRequiredMixin, MailSettingsSetupView): - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' basetpl = 'pretixcontrol/event/base.html' def get_success_url(self) -> str: @@ -817,7 +817,7 @@ class MailSettingsSetup(EventPermissionRequiredMixin, MailSettingsSetupView): class MailSettingsPreview(EventPermissionRequiredMixin, View): - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' # create index-language mapping @cached_property @@ -875,7 +875,7 @@ class MailSettingsPreview(EventPermissionRequiredMixin, View): class MailSettingsRendererPreview(MailSettingsPreview): - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' def post(self, request, *args, **kwargs): return HttpResponse(status=405) @@ -923,7 +923,7 @@ class MailSettingsRendererPreview(MailSettingsPreview): class TicketSettingsPreview(EventPermissionRequiredMixin, View): - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' @cached_property def output(self): @@ -955,7 +955,7 @@ class TicketSettings(EventSettingsViewMixin, EventPermissionRequiredMixin, FormV model = Event form_class = TicketSettingsForm template_name = 'pretixcontrol/event/tickets.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' def get_context_data(self, *args, **kwargs) -> dict: context = super().get_context_data(*args, **kwargs) @@ -1066,7 +1066,7 @@ class EventPermissions(EventSettingsViewMixin, EventPermissionRequiredMixin, Tem class EventLive(EventPermissionRequiredMixin, TemplateView): - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' template_name = 'pretixcontrol/event/live.html' def get_context_data(self, **kwargs): @@ -1133,12 +1133,12 @@ class EventLive(EventPermissionRequiredMixin, TemplateView): class EventTransferSession(EventPermissionRequiredMixin, TemplateView): - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' template_name = 'pretixcontrol/event/transfer_session.html' class EventDelete(RecentAuthenticationRequiredMixin, EventPermissionRequiredMixin, FormView): - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' template_name = 'pretixcontrol/event/delete.html' form_class = EventDeleteForm @@ -1206,20 +1206,20 @@ class EventLog(EventPermissionRequiredMixin, PaginationMixin, ListView): 'user', 'content_type', 'api_token', 'oauth_application', 'device' ).order_by('-datetime', '-pk') qs = qs.exclude(action_type__in=OVERVIEW_BANLIST) - if not self.request.user.has_event_permission(self.request.organizer, self.request.event, 'can_view_orders', + if not self.request.user.has_event_permission(self.request.organizer, self.request.event, 'event.orders:read', request=self.request): qs = qs.exclude(content_type=ContentType.objects.get_for_model(Order)) - if not self.request.user.has_event_permission(self.request.organizer, self.request.event, 'can_view_vouchers', + if not self.request.user.has_event_permission(self.request.organizer, self.request.event, 'event.vouchers:read', request=self.request): qs = qs.exclude(content_type=ContentType.objects.get_for_model(Voucher)) if not self.request.user.has_event_permission(self.request.organizer, self.request.event, - 'can_change_event_settings', request=self.request): + 'event.settings.general:write', request=self.request): allowed_types = [ ContentType.objects.get_for_model(Voucher), ContentType.objects.get_for_model(Order) ] if self.request.user.has_event_permission(self.request.organizer, self.request.event, - 'can_change_items', request=self.request): + 'event.items:write', request=self.request): allowed_types += [ ContentType.objects.get_for_model(Item), ContentType.objects.get_for_model(ItemCategory), @@ -1256,7 +1256,7 @@ class EventLog(EventPermissionRequiredMixin, PaginationMixin, ListView): class EventComment(EventPermissionRequiredMixin, View): - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' def post(self, *args, **kwargs): form = CommentForm(self.request.POST) @@ -1285,7 +1285,7 @@ class TaxCreate(EventSettingsViewMixin, EventPermissionRequiredMixin, CreateView model = TaxRule form_class = TaxRuleForm template_name = 'pretixcontrol/event/tax_edit.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' context_object_name = 'taxrule' def get_success_url(self) -> str: @@ -1346,7 +1346,7 @@ class TaxUpdate(EventSettingsViewMixin, EventPermissionRequiredMixin, UpdateView model = TaxRule form_class = TaxRuleForm template_name = 'pretixcontrol/event/tax_edit.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' context_object_name = 'rule' def get_object(self, queryset=None) -> TaxRule: @@ -1410,7 +1410,7 @@ class TaxUpdate(EventSettingsViewMixin, EventPermissionRequiredMixin, UpdateView class TaxDefault(EventSettingsViewMixin, EventPermissionRequiredMixin, DetailView): model = TaxRule - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' def get_object(self, queryset=None) -> TaxRule: try: @@ -1455,7 +1455,7 @@ class TaxDefault(EventSettingsViewMixin, EventPermissionRequiredMixin, DetailVie class TaxDelete(EventSettingsViewMixin, EventPermissionRequiredMixin, CompatDeleteView): model = TaxRule template_name = 'pretixcontrol/event/tax_delete.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' context_object_name = 'taxrule' def get_object(self, queryset=None) -> TaxRule: @@ -1492,7 +1492,7 @@ class TaxDelete(EventSettingsViewMixin, EventPermissionRequiredMixin, CompatDele class WidgetSettings(EventSettingsViewMixin, EventPermissionRequiredMixin, FormView): template_name = 'pretixcontrol/event/widget.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' form_class = WidgetCodeForm def get_form_kwargs(self): @@ -1521,7 +1521,7 @@ class WidgetSettings(EventSettingsViewMixin, EventPermissionRequiredMixin, FormV class QuickSetupView(FormView): template_name = 'pretixcontrol/event/quick_setup.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' form_class = QuickSetupForm def dispatch(self, request, *args, **kwargs): diff --git a/src/pretix/control/views/item.py b/src/pretix/control/views/item.py index d75677b12..a74dc7da7 100644 --- a/src/pretix/control/views/item.py +++ b/src/pretix/control/views/item.py @@ -159,7 +159,7 @@ def item_move(request, item, up=True): messages.success(request, _('The order of items has been updated.')) -@event_permission_required("can_change_items") +@event_permission_required("event.items:write") @require_http_methods(["POST"]) def item_move_up(request, organizer, event, item): item_move(request, item, up=True) @@ -168,7 +168,7 @@ def item_move_up(request, organizer, event, item): event=request.event.slug) -@event_permission_required("can_change_items") +@event_permission_required("event.items:write") @require_http_methods(["POST"]) def item_move_down(request, organizer, event, item): item_move(request, item, up=False) @@ -178,7 +178,7 @@ def item_move_down(request, organizer, event, item): @transaction.atomic -@event_permission_required("can_change_items") +@event_permission_required("event.items:write") @require_http_methods(["POST"]) def reorder_items(request, organizer, event, category): try: @@ -215,7 +215,7 @@ def reorder_items(request, organizer, event, category): class CategoryDelete(EventPermissionRequiredMixin, CompatDeleteView): model = ItemCategory template_name = 'pretixcontrol/items/category_delete.html' - permission = 'can_change_items' + permission = 'event.items:write' context_object_name = 'category' def get_object(self, queryset=None) -> ItemCategory: @@ -249,7 +249,7 @@ class CategoryUpdate(EventPermissionRequiredMixin, UpdateView): model = ItemCategory form_class = CategoryForm template_name = 'pretixcontrol/items/category.html' - permission = 'can_change_items' + permission = 'event.items:write' context_object_name = 'category' def get_object(self, queryset=None) -> ItemCategory: @@ -287,7 +287,7 @@ class CategoryCreate(EventPermissionRequiredMixin, CreateView): model = ItemCategory form_class = CategoryForm template_name = 'pretixcontrol/items/category.html' - permission = 'can_change_items' + permission = 'event.items:write' context_object_name = 'category' def get_success_url(self) -> str: @@ -371,7 +371,7 @@ def category_move(request, category, up=True): messages.success(request, _('The order of categories has been updated.')) -@event_permission_required("can_change_items") +@event_permission_required("event.items:write") @require_http_methods(["POST"]) def category_move_up(request, organizer, event, category): category_move(request, category, up=True) @@ -380,7 +380,7 @@ def category_move_up(request, organizer, event, category): event=request.event.slug) -@event_permission_required("can_change_items") +@event_permission_required("event.items:write") @require_http_methods(["POST"]) def category_move_down(request, organizer, event, category): category_move(request, category, up=False) @@ -390,7 +390,7 @@ def category_move_down(request, organizer, event, category): @transaction.atomic -@event_permission_required("can_change_items") +@event_permission_required("event.items:write") @require_http_methods(["POST"]) def reorder_categories(request, organizer, event): try: @@ -522,7 +522,7 @@ class QuestionList(ListView): @transaction.atomic -@event_permission_required("can_change_items") +@event_permission_required("event.items:write") @require_http_methods(["POST"]) def reorder_questions(request, organizer, event): try: @@ -570,7 +570,7 @@ def reorder_questions(request, organizer, event): class QuestionDelete(EventPermissionRequiredMixin, CompatDeleteView): model = Question template_name = 'pretixcontrol/items/question_delete.html' - permission = 'can_change_items' + permission = 'event.items:write' context_object_name = 'question' def get_object(self, queryset=None) -> Question: @@ -664,7 +664,7 @@ class QuestionMixin: class QuestionView(EventPermissionRequiredMixin, ChartContainingView, DetailView): model = Question template_name = 'pretixcontrol/items/question.html' - permission = 'can_change_items' + permission = 'event.items:write' template_name_field = 'question' @cached_property @@ -753,7 +753,7 @@ class QuestionUpdate(EventPermissionRequiredMixin, QuestionMixin, UpdateView): model = Question form_class = QuestionForm template_name = 'pretixcontrol/items/question_edit.html' - permission = 'can_change_items' + permission = 'event.items:write' context_object_name = 'question' def get_object(self, queryset=None) -> Question: @@ -794,7 +794,7 @@ class QuestionCreate(EventPermissionRequiredMixin, QuestionMixin, CreateView): model = Question form_class = QuestionForm template_name = 'pretixcontrol/items/question_edit.html' - permission = 'can_change_items' + permission = 'event.items:write' context_object_name = 'question' def get_form_kwargs(self): @@ -888,7 +888,7 @@ class QuotaCreate(EventPermissionRequiredMixin, CreateView): model = Quota form_class = QuotaForm template_name = 'pretixcontrol/items/quota_edit.html' - permission = 'can_change_items' + permission = 'event.items:write' context_object_name = 'quota' def get_success_url(self) -> str: @@ -1055,7 +1055,7 @@ class QuotaView(ChartContainingView, DetailView): raise Http404(_("The requested quota does not exist.")) def post(self, request, *args, **kwargs): - if not request.user.has_event_permission(request.organizer, request.event, 'can_change_items', request): + if not request.user.has_event_permission(request.organizer, request.event, 'event.items:write', request): raise PermissionDenied() quota = self.get_object() if 'reopen' in request.POST: @@ -1085,7 +1085,7 @@ class QuotaUpdate(EventPermissionRequiredMixin, UpdateView): model = Quota form_class = QuotaForm template_name = 'pretixcontrol/items/quota_edit.html' - permission = 'can_change_items' + permission = 'event.items:write' context_object_name = 'quota' def get_context_data(self, *args, **kwargs): @@ -1143,7 +1143,7 @@ class QuotaUpdate(EventPermissionRequiredMixin, UpdateView): class QuotaDelete(EventPermissionRequiredMixin, CompatDeleteView): model = Quota template_name = 'pretixcontrol/items/quota_delete.html' - permission = 'can_change_items' + permission = 'event.items:write' context_object_name = 'quota' def get_object(self, queryset=None) -> Quota: @@ -1246,7 +1246,7 @@ class MetaDataEditorMixin: class ItemCreate(EventPermissionRequiredMixin, MetaDataEditorMixin, CreateView): form_class = ItemCreateForm template_name = 'pretixcontrol/item/create.html' - permission = 'can_change_items' + permission = 'event.items:write' def get_success_url(self) -> str: return reverse('control:event.item', kwargs={ @@ -1322,7 +1322,7 @@ class ItemCreate(EventPermissionRequiredMixin, MetaDataEditorMixin, CreateView): class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, MetaDataEditorMixin, UpdateView): form_class = ItemUpdateForm template_name = 'pretixcontrol/item/index.html' - permission = 'can_change_items' + permission = 'event.items:write' @cached_property def plugin_forms(self): @@ -1584,7 +1584,7 @@ class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, MetaDataE class ItemDelete(EventPermissionRequiredMixin, CompatDeleteView): model = Item template_name = 'pretixcontrol/item/delete.html' - permission = 'can_change_items' + permission = 'event.items:write' context_object_name = 'item' def get_context_data(self, *args, **kwargs) -> dict: diff --git a/src/pretix/control/views/main.py b/src/pretix/control/views/main.py index c21ceccf0..18bbc6a46 100644 --- a/src/pretix/control/views/main.py +++ b/src/pretix/control/views/main.py @@ -213,9 +213,9 @@ class EventWizard(SafeSessionWizardView): else: allow = ( request.user.has_event_permission(clone_from.organizer, clone_from, - 'can_change_event_settings', request) + 'event.settings.general:write', request) and request.user.has_event_permission(clone_from.organizer, clone_from, - 'can_change_items', request) + 'event.items:write', request) ) if not allow: messages.error(self.request, _('You do not have permission to clone this event.')) diff --git a/src/pretix/control/views/modelimport.py b/src/pretix/control/views/modelimport.py index 9d3ed5795..1358853ff 100644 --- a/src/pretix/control/views/modelimport.py +++ b/src/pretix/control/views/modelimport.py @@ -209,7 +209,7 @@ class BaseProcessView(AsyncAction, FormView): class OrderImportView(EventPermissionRequiredMixin, BaseImportView): template_name = 'pretixcontrol/orders/import_start.html' - permission = 'can_change_orders' + permission = 'event.orders:write' def get_process_url(self, request, cf, charset): return reverse('control:event.orders.import.process', kwargs={ @@ -220,7 +220,7 @@ class OrderImportView(EventPermissionRequiredMixin, BaseImportView): class OrderProcessView(EventPermissionRequiredMixin, BaseProcessView): - permission = 'can_change_orders' + permission = 'event.orders:write' template_name = 'pretixcontrol/orders/import_process.html' form_class = OrdersProcessForm task = import_orders @@ -252,7 +252,7 @@ class OrderProcessView(EventPermissionRequiredMixin, BaseProcessView): class VoucherImportView(EventPermissionRequiredMixin, BaseImportView): template_name = 'pretixcontrol/vouchers/import_start.html' - permission = 'can_change_vouchers' + permission = 'event.vouchers:write' def get_process_url(self, request, cf, charset): return reverse('control:event.vouchers.import.process', kwargs={ @@ -263,7 +263,7 @@ class VoucherImportView(EventPermissionRequiredMixin, BaseImportView): class VoucherProcessView(EventPermissionRequiredMixin, BaseProcessView): - permission = 'can_change_vouchers' + permission = 'event.vouchers:write' template_name = 'pretixcontrol/vouchers/import_process.html' form_class = VouchersProcessForm task = import_vouchers diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py index e6b498645..4a501304d 100644 --- a/src/pretix/control/views/orders.py +++ b/src/pretix/control/views/orders.py @@ -170,7 +170,7 @@ class OrderSearchMixin: class OrderSearch(OrderSearchMixin, EventPermissionRequiredMixin, TemplateView): template_name = 'pretixcontrol/orders/search.html' - permission = 'can_view_orders' + permission = 'event.orders:read' def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) @@ -200,7 +200,7 @@ class OrderSearch(OrderSearchMixin, EventPermissionRequiredMixin, TemplateView): class BaseOrderBulkActionView(OrderSearchMixin, EventPermissionRequiredMixin, AsyncFormView): template_name = 'pretixcontrol/orders/bulk_action.html' - permission = 'can_change_orders' + permission = 'event.orders:write' form_class = forms.Form def get_queryset(self): @@ -403,7 +403,7 @@ class OrderList(OrderSearchMixin, EventPermissionRequiredMixin, PaginationMixin, model = Order context_object_name = 'orders' template_name = 'pretixcontrol/orders/index.html' - permission = 'can_view_orders' + permission = 'event.orders:read' def get_queryset(self): qs = Order.objects.filter( @@ -526,7 +526,7 @@ class OrderView(EventPermissionRequiredMixin, DetailView): class OrderDetail(OrderView): template_name = 'pretixcontrol/order/index.html' - permission = 'can_view_orders' + permission = 'event.orders:read' def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) @@ -626,7 +626,7 @@ class OrderDetail(OrderView): class OrderTransactions(OrderView): template_name = 'pretixcontrol/order/transactions.html' - permission = 'can_view_orders' + permission = 'event.orders:read' def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) @@ -645,7 +645,7 @@ class OrderTransactions(OrderView): class OrderDownload(AsyncAction, OrderView): task = generate - permission = 'can_view_orders' + permission = 'event.orders:read' def get_success_url(self, value): return self.get_self_url() @@ -744,7 +744,7 @@ class OrderDownload(AsyncAction, OrderView): class OrderComment(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' def post(self, *args, **kwargs): form = CommentForm(self.request.POST) @@ -784,7 +784,7 @@ class OrderComment(OrderView): class OrderApprove(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' def post(self, *args, **kwargs): if self.order.require_approval: @@ -803,7 +803,7 @@ class OrderApprove(OrderView): class OrderDelete(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' def post(self, *args, **kwargs): if self.order.testmode: @@ -833,7 +833,7 @@ class OrderDelete(OrderView): class OrderDeny(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' def post(self, request, *args, **kwargs): if self.order.require_approval: @@ -859,7 +859,7 @@ class OrderDeny(OrderView): class OrderPaymentCancel(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' @cached_property def payment(self): @@ -898,7 +898,7 @@ class OrderPaymentCancel(OrderView): class OrderRefundCancel(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' @cached_property def refund(self): @@ -928,7 +928,7 @@ class OrderRefundCancel(OrderView): class OrderRefundProcess(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' @cached_property def refund(self): @@ -967,7 +967,7 @@ class OrderRefundProcess(OrderView): class OrderRefundDone(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' @cached_property def refund(self): @@ -990,7 +990,7 @@ class OrderRefundDone(OrderView): class OrderCancellationRequestDelete(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' @cached_property def req(self): @@ -1024,7 +1024,7 @@ class OrderCancellationRequestDelete(OrderView): class OrderPaymentConfirm(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' @cached_property def payment(self): @@ -1082,7 +1082,7 @@ class OrderPaymentConfirm(OrderView): class OrderRefundView(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' @cached_property def start_form(self): @@ -1427,7 +1427,7 @@ class OrderRefundView(OrderView): class OrderTransition(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' @cached_property def req(self): @@ -1595,7 +1595,7 @@ class OrderTransition(OrderView): class OrderInvoiceCreate(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' def post(self, *args, **kwargs): with transaction.atomic(): @@ -1621,7 +1621,7 @@ class OrderInvoiceCreate(OrderView): class OrderCheckVATID(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' def post(self, *args, **kwargs): try: @@ -1661,7 +1661,7 @@ class OrderCheckVATID(OrderView): class OrderInvoiceRegenerate(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' def post(self, *args, **kwargs): try: @@ -1694,7 +1694,7 @@ class OrderInvoiceRegenerate(OrderView): class OrderInvoiceRetransmit(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' def post(self, *args, **kwargs): with transaction.atomic(durable=True): @@ -1725,7 +1725,7 @@ class OrderInvoiceRetransmit(OrderView): class OrderInvoiceReissue(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' def post(self, *args, **kwargs): with transaction.atomic(): @@ -1775,7 +1775,7 @@ class OrderInvoiceInspect(AdministratorPermissionRequiredMixin, OrderView): class OrderResendLink(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' def post(self, *args, **kwargs): try: @@ -1796,7 +1796,7 @@ class OrderResendLink(OrderView): class InvoiceDownload(EventPermissionRequiredMixin, View): - permission = 'can_view_orders' + permission = 'event.orders:read' def get_order_url(self): return reverse('control:event.order', kwargs={ @@ -1840,7 +1840,7 @@ class InvoiceDownload(EventPermissionRequiredMixin, View): class OrderExtend(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' def post(self, *args, **kwargs): if self.form.is_valid(): @@ -1888,7 +1888,7 @@ class OrderExtend(OrderView): class OrderReactivate(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' @cached_property def reactivate_form(self): @@ -1938,7 +1938,7 @@ class OrderReactivate(OrderView): class OrderChange(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' template_name = 'pretixcontrol/order/change.html' @cached_property @@ -2195,7 +2195,7 @@ class OrderChange(OrderView): class OrderModifyInformation(OrderQuestionsViewMixin, OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' template_name = 'pretixcontrol/order/change_questions.html' only_user_visible = False all_optional = True @@ -2248,7 +2248,7 @@ class OrderModifyInformation(OrderQuestionsViewMixin, OrderView): class OrderContactChange(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' template_name = 'pretixcontrol/order/change_contact.html' def get_context_data(self, **kwargs): @@ -2263,7 +2263,7 @@ class OrderContactChange(OrderView): data=self.request.POST if self.request.method == "POST" else None, customers=self.request.organizer.settings.customer_accounts and ( self.request.user.has_organizer_permission( - self.request.organizer, 'can_manage_customers', request=self.request + self.request.organizer, 'organizer.customers:write', request=self.request ) ) ) @@ -2332,7 +2332,7 @@ class OrderContactChange(OrderView): class OrderLocaleChange(OrderView): - permission = 'can_change_orders' + permission = 'event.orders:write' template_name = 'pretixcontrol/order/change_locale.html' def get_context_data(self, **kwargs): @@ -2388,7 +2388,7 @@ class OrderViewMixin: class OrderSendMail(EventPermissionRequiredMixin, OrderViewMixin, FormView): template_name = 'pretixcontrol/order/sendmail.html' - permission = 'can_change_orders' + permission = 'event.orders:write' form_class = OrderMailForm def get_form_kwargs(self): @@ -2522,7 +2522,7 @@ class OrderPositionSendMail(OrderSendMail): class OrderEmailHistory(EventPermissionRequiredMixin, OrderViewMixin, ListView): template_name = 'pretixcontrol/order/mail_history.html' - permission = 'can_view_orders' + permission = 'event.orders:read' model = LogEntry context_object_name = 'logs' paginate_by = 10 @@ -2559,7 +2559,7 @@ class OrderEmailHistory(EventPermissionRequiredMixin, OrderViewMixin, ListView): class AnswerDownload(EventPermissionRequiredMixin, OrderViewMixin, ListView): - permission = 'can_view_orders' + permission = 'event.orders:read' def get(self, request, *args, **kwargs): answid = kwargs.get('answer') @@ -2583,7 +2583,7 @@ class AnswerDownload(EventPermissionRequiredMixin, OrderViewMixin, ListView): class OverView(EventPermissionRequiredMixin, TemplateView): template_name = 'pretixcontrol/orders/overview.html' - permission = 'can_view_orders' + permission = 'event.orders:read' @cached_property def filter_form(self): @@ -2622,7 +2622,7 @@ class OverView(EventPermissionRequiredMixin, TemplateView): class OrderGo(EventPermissionRequiredMixin, View): - permission = 'can_view_orders' + permission = 'event.orders:read' def get_order(self, code): try: @@ -2707,7 +2707,7 @@ class ExportMixin: return ex def get_scheduled_queryset(self): - if not self.request.user.has_event_permission(self.request.organizer, self.request.event, 'can_change_event_settings', + if not self.request.user.has_event_permission(self.request.organizer, self.request.event, 'event.settings.general:write', request=self.request): qs = self.request.event.scheduled_exports.filter(owner=self.request.user) else: @@ -2729,7 +2729,7 @@ class ExportMixin: class ExportDoView(EventPermissionRequiredMixin, ExportMixin, AsyncAction, TemplateView): - permission = 'can_view_orders' + permission = 'event.orders:read' known_errortypes = ['ExportError', 'ExportEmptyError'] task = export template_name = 'pretixcontrol/orders/export_form.html' @@ -2778,7 +2778,7 @@ class ExportDoView(EventPermissionRequiredMixin, ExportMixin, AsyncAction, Templ class ExportView(EventPermissionRequiredMixin, ExportMixin, ListView): - permission = 'can_view_orders' + permission = 'event.orders:read' paginate_by = 25 context_object_name = 'scheduled' @@ -2864,7 +2864,7 @@ class ExportView(EventPermissionRequiredMixin, ExportMixin, ListView): return self.get_scheduled_queryset() def has_permission(self): - return self.request.user.has_event_permission(self.request.organizer, self.request.event, "can_view_orders") + return self.request.user.has_event_permission(self.request.organizer, self.request.event, "event.orders:read") def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) @@ -2890,7 +2890,7 @@ class ExportView(EventPermissionRequiredMixin, ExportMixin, ListView): class DeleteScheduledExportView(EventPermissionRequiredMixin, ExportMixin, CompatDeleteView): - permission = 'can_view_orders' + permission = 'event.orders:read' template_name = 'pretixcontrol/orders/export_delete.html' context_object_name = 'export' @@ -2939,7 +2939,7 @@ class RefundList(EventPermissionRequiredMixin, PaginationMixin, ListView): model = OrderRefund context_object_name = 'refunds' template_name = 'pretixcontrol/orders/refunds.html' - permission = 'can_view_orders' + permission = 'event.orders:read' def get_queryset(self): qs = OrderRefund.objects.filter( @@ -2964,7 +2964,7 @@ class RefundList(EventPermissionRequiredMixin, PaginationMixin, ListView): class EventCancel(EventPermissionRequiredMixin, AsyncAction, FormView): template_name = 'pretixcontrol/orders/cancel.html' - permission = 'can_change_orders' + permission = 'event.orders:write' form_class = EventCancelForm task = cancel_event known_errortypes = ['OrderError'] @@ -3049,7 +3049,7 @@ class EventCancel(EventPermissionRequiredMixin, AsyncAction, FormView): class EventCancelConfirm(EventPermissionRequiredMixin, AsyncAction, FormView): template_name = 'pretixcontrol/orders/cancel_confirm.html' - permission = 'can_change_orders' + permission = 'event.orders:write' form_class = EventCancelConfirmForm task = cancel_event known_errortypes = ['OrderError'] diff --git a/src/pretix/control/views/organizer.py b/src/pretix/control/views/organizer.py index 051366f26..33755ea93 100644 --- a/src/pretix/control/views/organizer.py +++ b/src/pretix/control/views/organizer.py @@ -244,13 +244,13 @@ class OrganizerDetail(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin class OrganizerTeamView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DetailView): model = Organizer template_name = 'pretixcontrol/organizers/teams.html' - permission = 'can_change_permissions' + permission = 'organizer.teams:read' context_object_name = 'organizer' class OrganizerSettingsFormView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, FormView): model = Organizer - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' def get_form_kwargs(self): kwargs = super().get_form_kwargs() @@ -281,7 +281,7 @@ class OrganizerSettingsFormView(OrganizerDetailViewMixin, OrganizerPermissionReq class OrganizerMailSettings(OrganizerSettingsFormView): form_class = MailSettingsForm template_name = 'pretixcontrol/organizers/mail.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' def get_success_url(self): return reverse('control:organizer.settings.mail', kwargs={ @@ -307,7 +307,7 @@ class OrganizerMailSettings(OrganizerSettingsFormView): class MailSettingsSetup(OrganizerPermissionRequiredMixin, MailSettingsSetupView): - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' basetpl = 'pretixcontrol/base.html' def get_success_url(self): @@ -322,7 +322,7 @@ class MailSettingsSetup(OrganizerPermissionRequiredMixin, MailSettingsSetupView) class MailSettingsPreview(OrganizerPermissionRequiredMixin, View): - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' # return the origin text if key is missing in dict class SafeDict(dict): @@ -454,7 +454,7 @@ class OrganizerUpdate(OrganizerPermissionRequiredMixin, UpdateView): model = Organizer form_class = OrganizerUpdateForm template_name = 'pretixcontrol/organizers/edit.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'organizer' @cached_property @@ -596,7 +596,7 @@ class OrganizerCreate(CreateView): class OrganizerPlugins(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, TemplateView, SingleObjectMixin): model = Organizer context_object_name = 'organizer' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' template_name = 'pretixcontrol/organizers/plugins.html' def get_object(self, queryset=None) -> Organizer: @@ -768,14 +768,14 @@ class OrganizerPlugins(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixi class OrganizerPluginEvents(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, FormView): model = Organizer context_object_name = 'organizer' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' template_name = 'pretixcontrol/organizers/plugin_events.html' form_class = OrganizerPluginEventsForm def get_form_kwargs(self): kwargs = super().get_form_kwargs() kwargs["events"] = self.request.user.get_events_with_permission( - "can_change_event_settings", request=self.request + "event.settings.general:write", request=self.request ).filter(organizer=self.request.organizer) kwargs["initial"] = { "events": self.request.organizer.events.filter(plugins__regex='(^|,)' + self.plugin.module + '(,|$)') @@ -853,7 +853,7 @@ class OrganizerPluginEvents(OrganizerDetailViewMixin, OrganizerPermissionRequire class TeamListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, PaginationMixin, ListView): model = Team template_name = 'pretixcontrol/organizers/teams.html' - permission = 'can_change_teams' + permission = 'organizer.teams:write' context_object_name = 'teams' def get_queryset(self): @@ -879,7 +879,7 @@ class TeamListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, P class TeamCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView): model = Team template_name = 'pretixcontrol/organizers/team_edit.html' - permission = 'can_change_teams' + permission = 'organizer.teams:write' form_class = TeamForm def get_form_kwargs(self): @@ -916,7 +916,7 @@ class TeamCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, class TeamUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, UpdateView): model = Team template_name = 'pretixcontrol/organizers/team_edit.html' - permission = 'can_change_teams' + permission = 'organizer.teams:write' context_object_name = 'team' form_class = TeamForm @@ -952,7 +952,7 @@ class TeamUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, class TeamDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CompatDeleteView): model = Team template_name = 'pretixcontrol/organizers/team_delete.html' - permission = 'can_change_teams' + permission = 'organizer.teams:write' context_object_name = 'team' def get_object(self, queryset=None): @@ -1012,7 +1012,7 @@ class TeamDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, class TeamMemberView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DetailView): template_name = 'pretixcontrol/organizers/team_members.html' context_object_name = 'team' - permission = 'can_change_teams' + permission = 'organizer.teams:write' model = Team def get_object(self, queryset=None): @@ -1233,7 +1233,7 @@ class DeviceQueryMixin: class DeviceListView(DeviceQueryMixin, OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView): model = Device template_name = 'pretixcontrol/organizers/devices.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'devices' paginate_by = 100 @@ -1246,7 +1246,7 @@ class DeviceListView(DeviceQueryMixin, OrganizerDetailViewMixin, OrganizerPermis class DeviceCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView): model = Device template_name = 'pretixcontrol/organizers/device_edit.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' form_class = DeviceForm def get_form_kwargs(self): @@ -1277,7 +1277,7 @@ class DeviceCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixi class DeviceLogView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView): template_name = 'pretixcontrol/organizers/device_logs.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' model = LogEntry context_object_name = 'logs' paginate_by = 20 @@ -1305,7 +1305,7 @@ class DeviceLogView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, class DeviceUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, UpdateView): model = Device template_name = 'pretixcontrol/organizers/device_edit.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'device' form_class = DeviceForm @@ -1348,7 +1348,7 @@ class DeviceUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixi class DeviceBulkUpdateView(DeviceQueryMixin, OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, FormView): template_name = 'pretixcontrol/organizers/device_bulk_edit.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'device' form_class = DeviceBulkEditForm @@ -1462,7 +1462,7 @@ class DeviceBulkUpdateView(DeviceQueryMixin, OrganizerDetailViewMixin, Organizer class DeviceConnectView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DetailView): model = Device template_name = 'pretixcontrol/organizers/device_connect.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'device' def get_object(self, queryset=None): @@ -1494,7 +1494,7 @@ class DeviceConnectView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMix class DeviceRevokeView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DetailView): model = Device template_name = 'pretixcontrol/organizers/device_revoke.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'device' def get_object(self, queryset=None): @@ -1524,7 +1524,7 @@ class DeviceRevokeView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixi class WebHookListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView): model = WebHook template_name = 'pretixcontrol/organizers/webhooks.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'webhooks' def get_queryset(self): @@ -1534,7 +1534,7 @@ class WebHookListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin class WebHookCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView): model = WebHook template_name = 'pretixcontrol/organizers/webhook_edit.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' form_class = WebHookForm def get_form_kwargs(self): @@ -1568,7 +1568,7 @@ class WebHookCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMix class WebHookUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, UpdateView): model = WebHook template_name = 'pretixcontrol/organizers/webhook_edit.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'webhook' form_class = WebHookForm @@ -1611,7 +1611,7 @@ class WebHookUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMix class WebHookLogsView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView): model = WebHook template_name = 'pretixcontrol/organizers/webhook_logs.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'calls' paginate_by = 50 @@ -1653,7 +1653,7 @@ class WebHookLogsView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin class GiftCardAcceptanceInviteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, FormView): model = GiftCardAcceptance template_name = 'pretixcontrol/organizers/giftcard_acceptance_invite.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' form_class = GiftCardAcceptanceInviteForm def get_form_kwargs(self): @@ -1683,7 +1683,7 @@ class GiftCardAcceptanceInviteView(OrganizerDetailViewMixin, OrganizerPermission class GiftCardAcceptanceListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView): model = GiftCardAcceptance template_name = 'pretixcontrol/organizers/giftcard_acceptance_list.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'acceptor_acceptance' paginate_by = 50 @@ -1743,7 +1743,7 @@ class GiftCardAcceptanceListView(OrganizerDetailViewMixin, OrganizerPermissionRe class GiftCardListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView): model = GiftCard template_name = 'pretixcontrol/organizers/giftcards.html' - permission = 'can_manage_gift_cards' + permission = 'organizer.giftcards:write' context_object_name = 'giftcards' paginate_by = 50 @@ -1766,7 +1766,7 @@ class GiftCardListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixi ctx = super().get_context_data(**kwargs) ctx['filter_form'] = self.filter_form ctx['other_organizers'] = self.request.user.get_organizers_with_permission( - 'can_manage_gift_cards', self.request + 'organizer.giftcards:write', self.request ).exclude(pk=self.request.organizer.pk) return ctx @@ -1777,7 +1777,7 @@ class GiftCardListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixi class GiftCardDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DetailView): template_name = 'pretixcontrol/organizers/giftcard.html' - permission = 'can_manage_gift_cards' + permission = 'organizer.giftcards:write' context_object_name = 'card' def get_object(self, queryset=None) -> Organizer: @@ -1867,7 +1867,7 @@ class GiftCardDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMi class GiftCardCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView): template_name = 'pretixcontrol/organizers/giftcard_create.html' - permission = 'can_manage_gift_cards' + permission = 'organizer.giftcards:write' form_class = GiftCardCreateForm success_url = 'invalid' @@ -1909,7 +1909,7 @@ class GiftCardCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMi class GiftCardUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, UpdateView): template_name = 'pretixcontrol/organizers/giftcard_edit.html' - permission = 'can_manage_gift_cards' + permission = 'organizer.giftcards:write' form_class = GiftCardUpdateForm success_url = 'invalid' context_object_name = 'card' @@ -2000,7 +2000,7 @@ class ExportMixin: @cached_property def events(self): - return self.request.user.get_events_with_permission('can_view_orders', request=self.request).filter( + return self.request.user.get_events_with_permission('event.orders:read', request=self.request).filter( organizer=self.request.organizer ) @@ -2034,7 +2034,7 @@ class ExportMixin: return ctx def get_scheduled_queryset(self): - if not self.request.user.has_organizer_permission(self.request.organizer, 'can_change_organizer_settings', + if not self.request.user.has_organizer_permission(self.request.organizer, 'organizer.settings.general:write', request=self.request): qs = self.request.organizer.scheduled_exports.filter(owner=self.request.user) else: @@ -2268,7 +2268,7 @@ class RunScheduledExportView(OrganizerPermissionRequiredMixin, ExportMixin, View class GateListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView): model = Gate template_name = 'pretixcontrol/organizers/gates.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'gates' def get_queryset(self): @@ -2278,7 +2278,7 @@ class GateListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, L class GateCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView): model = Gate template_name = 'pretixcontrol/organizers/gate_edit.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' form_class = GateForm def get_form_kwargs(self): @@ -2312,7 +2312,7 @@ class GateCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, class GateUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, UpdateView): model = Gate template_name = 'pretixcontrol/organizers/gate_edit.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'gate' form_class = GateForm @@ -2347,7 +2347,7 @@ class GateUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, class GateDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CompatDeleteView): model = Gate template_name = 'pretixcontrol/organizers/gate_delete.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'gate' def get_object(self, queryset=None): @@ -2371,7 +2371,7 @@ class GateDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, class EventMetaPropertyListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView): model = EventMetaProperty template_name = 'pretixcontrol/organizers/properties.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'properties' def get_queryset(self): @@ -2422,7 +2422,7 @@ class EventMetaPropertyEditorMixin: class EventMetaPropertyCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, EventMetaPropertyEditorMixin, CreateView): model = EventMetaProperty - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' def get_object(self, queryset=None): return EventMetaProperty() @@ -2452,7 +2452,7 @@ class EventMetaPropertyCreateView(OrganizerDetailViewMixin, OrganizerPermissionR class EventMetaPropertyUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, EventMetaPropertyEditorMixin, UpdateView): model = EventMetaProperty - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'property' def get_object(self, queryset=None): @@ -2484,7 +2484,7 @@ class EventMetaPropertyUpdateView(OrganizerDetailViewMixin, OrganizerPermissionR class EventMetaPropertyDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CompatDeleteView): model = EventMetaProperty template_name = 'pretixcontrol/organizers/property_delete.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'property' def get_object(self, queryset=None): @@ -2528,7 +2528,7 @@ def meta_property_move(request, property, up=True): messages.success(request, _('The order of properties has been updated.')) -@organizer_permission_required("can_change_organizer_settings") +@organizer_permission_required("organizer.settings.general:write") @require_http_methods(["POST"]) def meta_property_move_up(request, organizer, property): meta_property_move(request, property, up=True) @@ -2536,7 +2536,7 @@ def meta_property_move_up(request, organizer, property): organizer=request.organizer.slug) -@organizer_permission_required("can_change_organizer_settings") +@organizer_permission_required("organizer.settings.general:write") @require_http_methods(["POST"]) def meta_property_move_down(request, organizer, property): meta_property_move(request, property, up=False) @@ -2545,7 +2545,7 @@ def meta_property_move_down(request, organizer, property): @transaction.atomic -@organizer_permission_required("can_change_organizer_settings") +@organizer_permission_required("organizer.settings.general:write") @require_http_methods(["POST"]) def reorder_meta_properties(request, organizer): try: @@ -2577,7 +2577,7 @@ def reorder_meta_properties(request, organizer): class LogView(OrganizerPermissionRequiredMixin, PaginationMixin, ListView): template_name = 'pretixcontrol/organizers/logs.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' model = LogEntry context_object_name = 'logs' @@ -2602,7 +2602,7 @@ class LogView(OrganizerPermissionRequiredMixin, PaginationMixin, ListView): class MembershipTypeListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView): model = MembershipType template_name = 'pretixcontrol/organizers/membershiptypes.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'types' def get_queryset(self): @@ -2612,7 +2612,7 @@ class MembershipTypeListView(OrganizerDetailViewMixin, OrganizerPermissionRequir class MembershipTypeCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView): model = MembershipType template_name = 'pretixcontrol/organizers/membershiptype_edit.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' form_class = MembershipTypeForm def get_object(self, queryset=None): @@ -2646,7 +2646,7 @@ class MembershipTypeCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequ class MembershipTypeUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, UpdateView): model = MembershipType template_name = 'pretixcontrol/organizers/membershiptype_edit.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'type' form_class = MembershipTypeForm @@ -2681,7 +2681,7 @@ class MembershipTypeUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequ class MembershipTypeDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CompatDeleteView): model = MembershipType template_name = 'pretixcontrol/organizers/membershiptype_delete.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'type' def get_object(self, queryset=None): @@ -2711,7 +2711,7 @@ class MembershipTypeDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequ class SSOProviderListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView): model = CustomerSSOProvider template_name = 'pretixcontrol/organizers/ssoproviders.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'providers' def get_queryset(self): @@ -2721,7 +2721,7 @@ class SSOProviderListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredM class SSOProviderCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView): model = CustomerSSOProvider template_name = 'pretixcontrol/organizers/ssoprovider_edit.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' form_class = SSOProviderForm def get_object(self, queryset=None): @@ -2755,7 +2755,7 @@ class SSOProviderCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequire class SSOProviderUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, UpdateView): model = CustomerSSOProvider template_name = 'pretixcontrol/organizers/ssoprovider_edit.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'provider' form_class = SSOProviderForm @@ -2797,7 +2797,7 @@ class SSOProviderUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequire class SSOProviderDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CompatDeleteView): model = CustomerSSOProvider template_name = 'pretixcontrol/organizers/ssoprovider_delete.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'provider' def get_object(self, queryset=None): @@ -2827,7 +2827,7 @@ class SSOProviderDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequire class SSOClientListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView): model = CustomerSSOClient template_name = 'pretixcontrol/organizers/ssoclients.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'clients' def get_queryset(self): @@ -2837,7 +2837,7 @@ class SSOClientListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMix class SSOClientCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView): model = CustomerSSOClient template_name = 'pretixcontrol/organizers/ssoclient_edit.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' form_class = SSOClientForm def get_object(self, queryset=None): @@ -2877,7 +2877,7 @@ class SSOClientCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredM class SSOClientUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, UpdateView): model = CustomerSSOClient template_name = 'pretixcontrol/organizers/ssoclient_edit.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'client' form_class = SSOClientForm @@ -2927,7 +2927,7 @@ class SSOClientUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredM class SSOClientDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CompatDeleteView): model = CustomerSSOClient template_name = 'pretixcontrol/organizers/ssoclient_delete.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'client' def get_object(self, queryset=None): @@ -2957,7 +2957,7 @@ class SSOClientDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredM class CustomerListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, PaginationMixin, ListView): model = Customer template_name = 'pretixcontrol/organizers/customers.html' - permission = 'can_manage_customers' + permission = 'organizer.customers:write' context_object_name = 'customers' def get_queryset(self): @@ -2978,7 +2978,7 @@ class CustomerListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixi class CustomerDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, PaginationMixin, ListView): template_name = 'pretixcontrol/organizers/customer.html' - permission = 'can_manage_customers' + permission = 'organizer.customers:write' context_object_name = 'orders' def get_queryset(self): @@ -3093,7 +3093,7 @@ class CustomerDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMi class CustomerCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView): template_name = 'pretixcontrol/organizers/customer_edit.html' - permission = 'can_manage_customers' + permission = 'organizer.customers:write' context_object_name = 'customer' form_class = CustomerCreateForm @@ -3123,7 +3123,7 @@ class CustomerCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMi class CustomerUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, UpdateView): template_name = 'pretixcontrol/organizers/customer_edit.html' - permission = 'can_manage_customers' + permission = 'organizer.customers:write' context_object_name = 'customer' form_class = CustomerUpdateForm @@ -3152,7 +3152,7 @@ class CustomerUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMi class MembershipUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, UpdateView): template_name = 'pretixcontrol/organizers/customer_membership.html' - permission = 'can_manage_customers' + permission = 'organizer.customers:write' context_object_name = 'membership' form_class = MembershipUpdateForm @@ -3192,7 +3192,7 @@ class MembershipUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequired class MembershipDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CompatDeleteView): template_name = 'pretixcontrol/organizers/customer_membership_delete.html' - permission = 'can_manage_customers' + permission = 'organizer.customers:write' context_object_name = 'membership' def get_object(self, queryset=None): @@ -3230,7 +3230,7 @@ class MembershipDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequired class MembershipCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView): template_name = 'pretixcontrol/organizers/customer_membership.html' - permission = 'can_manage_customers' + permission = 'organizer.customers:write' context_object_name = 'membership' form_class = MembershipUpdateForm @@ -3269,7 +3269,7 @@ class MembershipCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequired class CustomerAnonymizeView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DetailView): template_name = 'pretixcontrol/organizers/customer_anonymize.html' - permission = 'can_manage_customers' + permission = 'organizer.customers:write' context_object_name = 'customer' def get_object(self, queryset=None): @@ -3296,7 +3296,7 @@ class CustomerAnonymizeView(OrganizerDetailViewMixin, OrganizerPermissionRequire class ReusableMediaListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, PaginationMixin, ListView): model = ReusableMedium template_name = 'pretixcontrol/organizers/reusable_media.html' - permission = 'can_manage_reusable_media' + permission = 'organizer.reusablemedia:read' context_object_name = 'media' def get_queryset(self): @@ -3320,7 +3320,7 @@ class ReusableMediaListView(OrganizerDetailViewMixin, OrganizerPermissionRequire class ReusableMediumDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, TemplateView): template_name = 'pretixcontrol/organizers/reusable_medium.html' - permission = 'can_manage_reusable_media' + permission = 'organizer.reusablemedia:read' @cached_property def medium(self): @@ -3337,7 +3337,7 @@ class ReusableMediumDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequ class ReusableMediumCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CreateView): template_name = 'pretixcontrol/organizers/reusable_medium_edit.html' - permission = 'can_manage_reusable_media' + permission = 'organizer.reusablemedia:write' context_object_name = 'medium' form_class = ReusableMediumCreateForm @@ -3366,7 +3366,7 @@ class ReusableMediumCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequ class ReusableMediumUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, UpdateView): template_name = 'pretixcontrol/organizers/reusable_medium_edit.html' - permission = 'can_manage_reusable_media' + permission = 'organizer.reusablemedia:write' context_object_name = 'medium' form_class = ReusableMediumUpdateForm @@ -3396,7 +3396,7 @@ class ReusableMediumUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequ class ChannelListView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView): model = SalesChannel template_name = 'pretixcontrol/organizers/channels.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'channels' def get_queryset(self): @@ -3415,7 +3415,7 @@ class ChannelEditorMixin: class ChannelCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ChannelEditorMixin, CreateView): model = SalesChannel - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' template_name = 'pretixcontrol/organizers/channel_add.html' def get_object(self, queryset=None): @@ -3487,7 +3487,7 @@ class ChannelCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMix class ChannelUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ChannelEditorMixin, UpdateView): model = SalesChannel - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'channel' template_name = 'pretixcontrol/organizers/channel_edit.html' @@ -3532,7 +3532,7 @@ class ChannelUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMix class ChannelDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CompatDeleteView): model = SalesChannel template_name = 'pretixcontrol/organizers/channel_delete.html' - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' context_object_name = 'channel' def get_object(self, queryset=None): @@ -3588,7 +3588,7 @@ def channel_move(request, channel, up=True): messages.success(request, _('The order of sales channels has been updated.')) -@organizer_permission_required("can_change_organizer_settings") +@organizer_permission_required("organizer.settings.general:write") @require_http_methods(["POST"]) def channel_move_up(request, organizer, channel): channel_move(request, channel, up=True) @@ -3596,7 +3596,7 @@ def channel_move_up(request, organizer, channel): organizer=request.organizer.slug) -@organizer_permission_required("can_change_organizer_settings") +@organizer_permission_required("organizer.settings.general:write") @require_http_methods(["POST"]) def channel_move_down(request, organizer, channel): channel_move(request, channel, up=False) @@ -3605,7 +3605,7 @@ def channel_move_down(request, organizer, channel): @transaction.atomic -@organizer_permission_required("can_change_organizer_settings") +@organizer_permission_required("organizer.settings.general:write") @require_http_methods(["POST"]) def reorder_channels(request, organizer): try: diff --git a/src/pretix/control/views/pdf.py b/src/pretix/control/views/pdf.py index 719fa4cd9..90fe79308 100644 --- a/src/pretix/control/views/pdf.py +++ b/src/pretix/control/views/pdf.py @@ -58,7 +58,7 @@ logger = logging.getLogger(__name__) class BaseEditorView(EventPermissionRequiredMixin, TemplateView): template_name = 'pretixcontrol/pdf/index.html' - permission = 'can_change_settings' + permission = 'event.settings.general:write' accepted_formats = ( 'application/pdf', ) diff --git a/src/pretix/control/views/search.py b/src/pretix/control/views/search.py index 0501d9c4c..ec60b12ff 100644 --- a/src/pretix/control/views/search.py +++ b/src/pretix/control/views/search.py @@ -85,7 +85,7 @@ class OrderSearch(PaginationMixin, ListView): if not self.request.user.has_active_staff_session(self.request.session.session_key): qs = qs.filter( - Q(event_id__in=self.request.user.get_events_with_permission('can_view_orders').values_list('id', flat=True)) + Q(event_id__in=self.request.user.get_events_with_permission('event.orders:read').values_list('id', flat=True)) ) if self.filter_form.is_valid(): @@ -159,7 +159,7 @@ class PaymentSearch(PaginationMixin, ListView): if not self.request.user.has_active_staff_session(self.request.session.session_key): qs = qs.filter( - Q(order__event_id__in=self.request.user.get_events_with_permission('can_view_orders').values_list('id', flat=True)) + Q(order__event_id__in=self.request.user.get_events_with_permission('event.orders:read').values_list('id', flat=True)) ) if self.filter_form.is_valid(): diff --git a/src/pretix/control/views/shredder.py b/src/pretix/control/views/shredder.py index aed2c07ab..9a28b0423 100644 --- a/src/pretix/control/views/shredder.py +++ b/src/pretix/control/views/shredder.py @@ -75,7 +75,7 @@ class ShredderMixin: class StartShredView(RecentAuthenticationRequiredMixin, EventPermissionRequiredMixin, ShredderMixin, TemplateView): - permission = 'can_change_orders' + permission = 'event.orders:write' template_name = 'pretixcontrol/shredder/index.html' def get_context_data(self, **kwargs): @@ -86,7 +86,7 @@ class StartShredView(RecentAuthenticationRequiredMixin, EventPermissionRequiredM class ShredDownloadView(RecentAuthenticationRequiredMixin, EventPermissionRequiredMixin, ShredderMixin, TemplateView): - permission = 'can_change_orders' + permission = 'event.orders:write' template_name = 'pretixcontrol/shredder/download.html' def get_context_data(self, **kwargs): @@ -116,7 +116,7 @@ class ShredDownloadView(RecentAuthenticationRequiredMixin, EventPermissionRequir class ShredExportView(RecentAuthenticationRequiredMixin, EventPermissionRequiredMixin, ShredderMixin, AsyncAction, View): - permission = 'can_change_orders' + permission = 'event.orders:write' task = export known_errortypes = ['ShredError'] @@ -145,7 +145,7 @@ class ShredExportView(RecentAuthenticationRequiredMixin, EventPermissionRequired class ShredDoView(RecentAuthenticationRequiredMixin, EventPermissionRequiredMixin, ShredderMixin, AsyncAction, View): - permission = 'can_change_orders' + permission = 'event.orders:write' task = shred known_errortypes = ['ShredError'] diff --git a/src/pretix/control/views/subevents.py b/src/pretix/control/views/subevents.py index 9712efc80..f1a08cd12 100644 --- a/src/pretix/control/views/subevents.py +++ b/src/pretix/control/views/subevents.py @@ -117,7 +117,7 @@ class SubEventList(EventPermissionRequiredMixin, PaginationMixin, SubEventQueryM model = SubEvent context_object_name = 'subevents' template_name = 'pretixcontrol/subevents/index.html' - permission = 'can_change_settings' + permission = 'event.settings.general:write' def get_queryset(self): return super().get_queryset(True).prefetch_related( @@ -156,7 +156,7 @@ class SubEventList(EventPermissionRequiredMixin, PaginationMixin, SubEventQueryM class SubEventDelete(EventPermissionRequiredMixin, CompatDeleteView): model = SubEvent template_name = 'pretixcontrol/subevents/delete.html' - permission = 'can_change_settings' + permission = 'event.settings.general:write' context_object_name = 'subevents' def get_object(self, queryset=None) -> SubEvent: @@ -241,7 +241,7 @@ class SubEventEditorMixin(MetaDataEditorMixin): property=p, disabled=( p.protected and - not self.request.user.has_organizer_permission(self.request.organizer, 'can_change_organizer_settings', request=self.request) + not self.request.user.has_organizer_permission(self.request.organizer, 'organizer.settings.general:write', request=self.request) ), default=self._default_meta.get(p.name, ''), instance=val_instances.get(p.pk, self.meta_model(property=p, subevent=self.object)), @@ -508,7 +508,7 @@ class SubEventEditorMixin(MetaDataEditorMixin): class SubEventUpdate(EventPermissionRequiredMixin, SubEventEditorMixin, UpdateView): model = SubEvent template_name = 'pretixcontrol/subevents/detail.html' - permission = 'can_change_settings' + permission = 'event.settings.general:write' context_object_name = 'subevent' form_class = SubEventForm @@ -575,7 +575,7 @@ class SubEventUpdate(EventPermissionRequiredMixin, SubEventEditorMixin, UpdateVi class SubEventCreate(SubEventEditorMixin, EventPermissionRequiredMixin, CreateView): model = SubEvent template_name = 'pretixcontrol/subevents/detail.html' - permission = 'can_change_settings' + permission = 'event.settings.general:write' context_object_name = 'subevent' form_class = SubEventForm @@ -669,7 +669,7 @@ class SubEventCreate(SubEventEditorMixin, EventPermissionRequiredMixin, CreateVi class SubEventBulkAction(SubEventQueryMixin, EventPermissionRequiredMixin, View): - permission = 'can_change_settings' + permission = 'event.settings.general:write' @transaction.atomic def post(self, request, *args, **kwargs): @@ -740,7 +740,7 @@ class SubEventBulkAction(SubEventQueryMixin, EventPermissionRequiredMixin, View) class SubEventBulkCreate(SubEventEditorMixin, EventPermissionRequiredMixin, AsyncFormView): model = SubEvent template_name = 'pretixcontrol/subevents/bulk.html' - permission = 'can_change_settings' + permission = 'event.settings.general:write' context_object_name = 'subevent' form_class = SubEventBulkForm itemformclass = BulkSubEventItemForm @@ -1065,7 +1065,7 @@ class SubEventBulkCreate(SubEventEditorMixin, EventPermissionRequiredMixin, Asyn class SubEventBulkEdit(SubEventQueryMixin, EventPermissionRequiredMixin, FormView): - permission = 'can_change_settings' + permission = 'event.settings.general:write' form_class = SubEventBulkEditForm template_name = 'pretixcontrol/subevents/bulk_edit.html' context_object_name = 'subevent' diff --git a/src/pretix/control/views/typeahead.py b/src/pretix/control/views/typeahead.py index 77eed5c11..ab58348a5 100644 --- a/src/pretix/control/views/typeahead.py +++ b/src/pretix/control/views/typeahead.py @@ -173,7 +173,7 @@ def event_list(request): return JsonResponse(doc) -@organizer_permission_required(("can_manage_gift_cards", "can_manage_reusable_media")) +@organizer_permission_required(("organizer.giftcards:read", "organizer.reusablemedia:write")) def giftcard_select2(request, **kwargs): query = request.GET.get('query', '') try: @@ -181,7 +181,7 @@ def giftcard_select2(request, **kwargs): except ValueError: page = 1 - if request.user.has_organizer_permission(request.organizer, 'can_manage_gift_cards', request): + if request.user.has_organizer_permission(request.organizer, 'organizer.giftcards:write', request): qs = request.organizer.issued_gift_cards.filter( Q(secret__icontains=query) ).order_by('secret') @@ -211,7 +211,7 @@ def giftcard_select2(request, **kwargs): return JsonResponse(doc) -@organizer_permission_required(("can_manage_reusable_media", "can_manage_gift_cards")) +@organizer_permission_required(("organizer.reusablemedia:write", "organizer.giftcards:write")) def ticket_select2(request, **kwargs): query = request.GET.get('query', '') try: @@ -276,7 +276,7 @@ def ticket_select2(request, **kwargs): return JsonResponse(doc) -@organizer_permission_required("can_manage_customers") +@organizer_permission_required("organizer.customers:write") def customer_select2(request, **kwargs): query = request.GET.get('query', '') try: @@ -1013,7 +1013,7 @@ def item_meta_values(request, organizer, event): }) -@organizer_permission_required(("can_view_orders", "can_change_organizer_settings")) +@organizer_permission_required(("event.orders:read", "organizer.settings.general:write")) # This decorator is a bit of a hack since this is not technically an organizer permission, but it does the job here -- # anyone who can see orders for any event can see the check-in log view where this is used as a filter def devices_select2(request, **kwargs): @@ -1051,7 +1051,7 @@ def devices_select2(request, **kwargs): return JsonResponse(doc) -@organizer_permission_required(("can_view_orders", "can_change_event_settings", "can_change_organizer_settings")) +@organizer_permission_required(("event.orders:read", "event.settings.general:write", "organizer.settings.general:write")) # This decorator is a bit of a hack since this is not technically an organizer permission, but it does the job here -- # anyone who can see orders for any event can see the check-in log view where this is used as a filter def gate_select2(request, **kwargs): diff --git a/src/pretix/control/views/vouchers.py b/src/pretix/control/views/vouchers.py index 5bdabb277..64df0843e 100644 --- a/src/pretix/control/views/vouchers.py +++ b/src/pretix/control/views/vouchers.py @@ -83,7 +83,7 @@ class VoucherList(PaginationMixin, EventPermissionRequiredMixin, ListView): model = Voucher context_object_name = 'vouchers' template_name = 'pretixcontrol/vouchers/index.html' - permission = 'can_view_vouchers' + permission = 'event.vouchers:read' @scopes_disabled() # we have an event check here, and we can save some performance on subqueries def get_queryset(self): @@ -155,7 +155,7 @@ class VoucherList(PaginationMixin, EventPermissionRequiredMixin, ListView): class VoucherTags(EventPermissionRequiredMixin, TemplateView): template_name = 'pretixcontrol/vouchers/tags.html' - permission = 'can_view_vouchers' + permission = 'event.vouchers:read' def get_queryset(self): qs = self.request.event.vouchers.order_by('tag').filter( @@ -196,7 +196,7 @@ class VoucherTags(EventPermissionRequiredMixin, TemplateView): class VoucherDeleteCarts(EventPermissionRequiredMixin, CompatDeleteView): model = Voucher template_name = 'pretixcontrol/vouchers/delete_carts.html' - permission = 'can_change_vouchers' + permission = 'event.vouchers:write' context_object_name = 'voucher' def get_object(self, queryset=None) -> Voucher: @@ -228,7 +228,7 @@ class VoucherDeleteCarts(EventPermissionRequiredMixin, CompatDeleteView): class VoucherDelete(EventPermissionRequiredMixin, CompatDeleteView): model = Voucher template_name = 'pretixcontrol/vouchers/delete.html' - permission = 'can_change_vouchers' + permission = 'event.vouchers:write' context_object_name = 'voucher' def get_object(self, queryset=None) -> Voucher: @@ -270,7 +270,7 @@ class VoucherDelete(EventPermissionRequiredMixin, CompatDeleteView): class VoucherUpdate(EventPermissionRequiredMixin, UpdateView): model = Voucher template_name = 'pretixcontrol/vouchers/detail.html' - permission = ('can_change_vouchers', 'can_view_vouchers') + permission = ('event.vouchers:write', 'event.vouchers:read') context_object_name = 'voucher' def form_invalid(self, form): @@ -286,7 +286,7 @@ class VoucherUpdate(EventPermissionRequiredMixin, UpdateView): def get_form(self, form_class=None): form = super().get_form(form_class) - if not self.request.user.has_event_permission(self.request.organizer, self.request.event, 'can_change_vouchers', + if not self.request.user.has_event_permission(self.request.organizer, self.request.event, 'event.vouchers:write', request=self.request): for f in form.fields.values(): f.disabled = True @@ -313,7 +313,7 @@ class VoucherUpdate(EventPermissionRequiredMixin, UpdateView): @transaction.atomic def post(self, request, *args, **kwargs): - if not request.user.has_event_permission(request.organizer, request.event, 'can_change_vouchers', + if not request.user.has_event_permission(request.organizer, request.event, 'event.vouchers:write', request=request): raise PermissionDenied() return super().post(request, *args, **kwargs) @@ -344,7 +344,7 @@ class VoucherUpdate(EventPermissionRequiredMixin, UpdateView): class VoucherCreate(EventPermissionRequiredMixin, CreateView): model = Voucher template_name = 'pretixcontrol/vouchers/detail.html' - permission = 'can_change_vouchers' + permission = 'event.vouchers:write' context_object_name = 'voucher' def form_invalid(self, form): @@ -389,7 +389,7 @@ class VoucherCreate(EventPermissionRequiredMixin, CreateView): class VoucherGo(EventPermissionRequiredMixin, View): - permission = 'can_view_vouchers' + permission = 'event.vouchers:read' def get_voucher(self, code): return Voucher.objects.get(code__iexact=code, event=self.request.event) @@ -408,7 +408,7 @@ class VoucherGo(EventPermissionRequiredMixin, View): class VoucherBulkCreate(EventPermissionRequiredMixin, AsyncFormView): model = Voucher template_name = 'pretixcontrol/vouchers/bulk.html' - permission = 'can_change_vouchers' + permission = 'event.vouchers:write' context_object_name = 'voucher' atomic_execute = True @@ -540,7 +540,7 @@ class VoucherBulkCreate(EventPermissionRequiredMixin, AsyncFormView): class VoucherBulkMailPreview(EventPermissionRequiredMixin, View): - permission = 'can_change_vouchers' + permission = 'event.vouchers:write' # return the origin text if key is missing in dict class SafeDict(dict): @@ -579,7 +579,7 @@ class VoucherBulkMailPreview(EventPermissionRequiredMixin, View): class VoucherRNG(EventPermissionRequiredMixin, View): - permission = 'can_change_vouchers' + permission = 'event.vouchers:write' def get(self, request, *args, **kwargs): try: @@ -603,7 +603,7 @@ class VoucherRNG(EventPermissionRequiredMixin, View): class VoucherBulkAction(EventPermissionRequiredMixin, View): - permission = 'can_change_vouchers' + permission = 'event.vouchers:write' @cached_property def objects(self): diff --git a/src/pretix/control/views/waitinglist.py b/src/pretix/control/views/waitinglist.py index 1cacbb3c6..1949b3825 100644 --- a/src/pretix/control/views/waitinglist.py +++ b/src/pretix/control/views/waitinglist.py @@ -64,7 +64,7 @@ from . import UpdateView class AutoAssign(EventPermissionRequiredMixin, AsyncAction, View): task = assign_automatically known_errortypes = ['WaitingListError'] - permission = 'can_change_orders' + permission = 'event.orders:write' def get_success_message(self, value): return _('{num} vouchers have been created and sent out via email.').format(num=value) @@ -143,7 +143,7 @@ class WaitingListQuerySetMixin: class WaitingListActionView(EventPermissionRequiredMixin, WaitingListQuerySetMixin, View): model = WaitingListEntry - permission = 'can_change_orders' + permission = 'event.orders:write' def _redirect_back(self): if "next" in self.request.GET and url_has_allowed_host_and_scheme(self.request.GET.get("next"), allowed_hosts=None): @@ -233,7 +233,7 @@ class WaitingListView(EventPermissionRequiredMixin, WaitingListQuerySetMixin, Pa model = WaitingListEntry context_object_name = 'entries' template_name = 'pretixcontrol/waitinglist/index.html' - permission = 'can_view_orders' + permission = 'event.orders:read' def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) @@ -360,7 +360,7 @@ class WaitingListView(EventPermissionRequiredMixin, WaitingListQuerySetMixin, Pa class EntryDelete(EventPermissionRequiredMixin, CompatDeleteView): model = WaitingListEntry template_name = 'pretixcontrol/waitinglist/delete.html' - permission = 'can_change_orders' + permission = 'event.orders:write' context_object_name = 'entry' def get_object(self, queryset=None) -> WaitingListEntry: @@ -393,7 +393,7 @@ class EntryDelete(EventPermissionRequiredMixin, CompatDeleteView): class EntryTransfer(EventPermissionRequiredMixin, UpdateView): model = WaitingListEntry template_name = 'pretixcontrol/waitinglist/transfer.html' - permission = 'can_change_orders' + permission = 'event.orders:write' form_class = WaitingListEntryTransferForm context_object_name = 'entry' diff --git a/src/pretix/plugins/autocheckin/api.py b/src/pretix/plugins/autocheckin/api.py index 7f855892c..7ceea1022 100644 --- a/src/pretix/plugins/autocheckin/api.py +++ b/src/pretix/plugins/autocheckin/api.py @@ -108,7 +108,7 @@ class RuleViewSet(viewsets.ModelViewSet): filter_backends = (DjangoFilterBackend, TotalOrderingFilter) ordering = ("id",) ordering_fields = ("id",) - permission = "can_change_event_settings" + permission = "event.settings.general:write" def get_queryset(self): return AutoCheckinRule.objects.filter(event=self.request.event) diff --git a/src/pretix/plugins/autocheckin/signals.py b/src/pretix/plugins/autocheckin/signals.py index bf634d659..bb55be141 100644 --- a/src/pretix/plugins/autocheckin/signals.py +++ b/src/pretix/plugins/autocheckin/signals.py @@ -39,7 +39,7 @@ from pretix.plugins.autocheckin.models import AutoCheckinRule def nav_event_receiver(sender, request, **kwargs): url = request.resolver_match if not request.user.has_event_permission( - request.organizer, request.event, "can_change_event_settings", request=request + request.organizer, request.event, "event.settings.general:write", request=request ): return [] return [ diff --git a/src/pretix/plugins/autocheckin/views.py b/src/pretix/plugins/autocheckin/views.py index 9539450a4..0766a871b 100644 --- a/src/pretix/plugins/autocheckin/views.py +++ b/src/pretix/plugins/autocheckin/views.py @@ -35,7 +35,7 @@ from pretix.plugins.autocheckin.models import AutoCheckinRule class IndexView(EventPermissionRequiredMixin, ListView): - permission = "can_change_event_settings" + permission = "event.settings.general:write" template_name = "pretixplugins/autocheckin/index.html" paginate_by = 50 context_object_name = "rules" @@ -70,7 +70,7 @@ class IndexView(EventPermissionRequiredMixin, ListView): class RuleAddView(EventPermissionRequiredMixin, CreateView): template_name = "pretixplugins/autocheckin/add.html" - permission = "can_change_event_settings" + permission = "event.settings.general:write" form_class = AutoCheckinRuleForm model = AutoCheckinRule @@ -140,7 +140,7 @@ class RuleEditView(EventPermissionRequiredMixin, UpdateView): model = AutoCheckinRule form_class = AutoCheckinRuleForm template_name = "pretixplugins/autocheckin/edit.html" - permission = "can_change_event_settings" + permission = "event.settings.general:write" def get_object(self, queryset=None) -> AutoCheckinRule: return get_object_or_404( @@ -178,7 +178,7 @@ class RuleEditView(EventPermissionRequiredMixin, UpdateView): class RuleDeleteView(EventPermissionRequiredMixin, DeleteView): model = AutoCheckinRule - permission = "can_change_event_settings" + permission = "event.settings.general:write" template_name = "pretixplugins/autocheckin/delete.html" context_object_name = "rule" diff --git a/src/pretix/plugins/badges/signals.py b/src/pretix/plugins/badges/signals.py index f740938cd..00da12e3a 100644 --- a/src/pretix/plugins/badges/signals.py +++ b/src/pretix/plugins/badges/signals.py @@ -44,8 +44,8 @@ from pretix.plugins.badges.models import BadgeItem, BadgeLayout def control_nav_import(sender, request=None, **kwargs): url = resolve(request.path_info) p = ( - request.user.has_event_permission(request.organizer, request.event, 'can_change_settings', request) - or request.user.has_event_permission(request.organizer, request.event, 'can_view_orders', request) + request.user.has_event_permission(request.organizer, request.event, 'event.settings.general:write', request) + or request.user.has_event_permission(request.organizer, request.event, 'event.orders:read', request) ) if not p: return [] diff --git a/src/pretix/plugins/badges/views.py b/src/pretix/plugins/badges/views.py index 0ae02c430..9caeb7bed 100644 --- a/src/pretix/plugins/badges/views.py +++ b/src/pretix/plugins/badges/views.py @@ -59,7 +59,7 @@ from .templates import TEMPLATES class LayoutListView(EventPermissionRequiredMixin, ListView): model = BadgeLayout - permission = ('can_change_event_settings', 'can_view_orders') + permission = ('event.settings.general:write', 'event.orders:read') template_name = 'pretixplugins/badges/index.html' context_object_name = 'layouts' @@ -71,7 +71,7 @@ class LayoutCreate(EventPermissionRequiredMixin, CreateView): model = BadgeLayout form_class = BadgeLayoutForm template_name = 'pretixplugins/badges/edit.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' context_object_name = 'layout' success_url = '/ignored' @@ -139,7 +139,7 @@ class LayoutCreate(EventPermissionRequiredMixin, CreateView): class LayoutSetDefault(EventPermissionRequiredMixin, DetailView): model = BadgeLayout - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' def get_object(self, queryset=None) -> BadgeLayout: try: @@ -171,7 +171,7 @@ class LayoutSetDefault(EventPermissionRequiredMixin, DetailView): class LayoutDelete(EventPermissionRequiredMixin, CompatDeleteView): model = BadgeLayout template_name = 'pretixplugins/badges/delete.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' context_object_name = 'layout' def get_object(self, queryset=None) -> BadgeLayout: @@ -269,7 +269,7 @@ class LayoutEditorView(BaseEditorView): class OrderPrintDo(EventPermissionRequiredMixin, AsyncAction, View): task = badges_create_pdf - permission = 'can_view_orders' + permission = 'event.orders:read' known_errortypes = ['OrderError', 'ExportError'] def get_success_message(self, value): diff --git a/src/pretix/plugins/banktransfer/api.py b/src/pretix/plugins/banktransfer/api.py index f611f405b..3e3575dc1 100644 --- a/src/pretix/plugins/banktransfer/api.py +++ b/src/pretix/plugins/banktransfer/api.py @@ -97,7 +97,7 @@ class BankImportJobViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet): queryset = BankImportJob.objects.none() filter_backends = (DjangoFilterBackend,) filterset_class = JobFilter - permission = 'can_view_orders' + permission = 'event.orders:read' def get_queryset(self): return BankImportJob.objects.filter(organizer=self.request.organizer) @@ -107,7 +107,7 @@ class BankImportJobViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet): def create(self, request, *args, **kwargs): perm_holder = (request.auth if isinstance(request.auth, (Device, TeamAPIToken)) else request.user) - if not perm_holder.has_organizer_permission(request.organizer, 'can_change_orders'): + if not perm_holder.has_organizer_permission(request.organizer, 'event.orders:write'): raise PermissionDenied('Invalid set of permissions') if BankImportJob.objects.filter(Q(organizer=request.organizer)).filter( diff --git a/src/pretix/plugins/banktransfer/signals.py b/src/pretix/plugins/banktransfer/signals.py index 6302cfcbe..d681ed912 100644 --- a/src/pretix/plugins/banktransfer/signals.py +++ b/src/pretix/plugins/banktransfer/signals.py @@ -41,7 +41,7 @@ def register_payment_provider(sender, **kwargs): @receiver(nav_event, dispatch_uid="payment_banktransfer_nav") def control_nav_import(sender, request=None, **kwargs): url = resolve(request.path_info) - if not request.user.has_event_permission(request.organizer, request.event, 'can_change_orders', request=request): + if not request.user.has_event_permission(request.organizer, request.event, 'event.orders:write', request=request): return [] return [ { @@ -76,7 +76,7 @@ def control_nav_import(sender, request=None, **kwargs): @receiver(nav_organizer, dispatch_uid="payment_banktransfer_organav") def control_nav_orga_import(sender, request=None, **kwargs): url = resolve(request.path_info) - if not request.user.has_organizer_permission(request.organizer, 'can_change_orders', request=request): + if not request.user.has_organizer_permission(request.organizer, 'event.orders:write', request=request): return [] return [ { diff --git a/src/pretix/plugins/banktransfer/views.py b/src/pretix/plugins/banktransfer/views.py index 2aef7fd55..b04cf46a1 100644 --- a/src/pretix/plugins/banktransfer/views.py +++ b/src/pretix/plugins/banktransfer/views.py @@ -81,7 +81,7 @@ logger = logging.getLogger('pretix.plugins.banktransfer') class ActionView(View): - permission = 'can_change_orders' + permission = 'event.orders:write' def _discard(self, trans): trans.state = BankTransaction.STATE_DISCARDED @@ -286,7 +286,7 @@ class ActionView(View): class JobDetailView(DetailView): template_name = 'pretixplugins/banktransfer/job_detail.html' - permission = 'can_change_orders' + permission = 'event.orders:write' context_objectname = 'job' def redirect_form(self): @@ -375,7 +375,7 @@ class BankTransactionFilterForm(forms.Form): class ImportView(ListView): template_name = 'pretixplugins/banktransfer/import_form.html' - permission = 'can_change_orders' + permission = 'event.orders:write' context_object_name = 'transactions_unhandled' paginate_by = 30 @@ -636,30 +636,30 @@ class OrganizerBanktransferView: class EventImportView(EventPermissionRequiredMixin, ImportView): - permission = 'can_change_orders' + permission = 'event.orders:write' class OrganizerImportView(OrganizerBanktransferView, OrganizerPermissionRequiredMixin, OrganizerDetailViewMixin, ImportView): - permission = 'can_change_orders' + permission = 'event.orders:write' class EventJobDetailView(EventPermissionRequiredMixin, JobDetailView): - permission = 'can_change_orders' + permission = 'event.orders:write' class OrganizerJobDetailView(OrganizerBanktransferView, OrganizerPermissionRequiredMixin, OrganizerDetailViewMixin, JobDetailView): - permission = 'can_change_orders' + permission = 'event.orders:write' class EventActionView(EventPermissionRequiredMixin, ActionView): - permission = 'can_change_orders' + permission = 'event.orders:write' class OrganizerActionView(OrganizerBanktransferView, OrganizerPermissionRequiredMixin, OrganizerDetailViewMixin, ActionView): - permission = 'can_change_orders' + permission = 'event.orders:write' def order_qs(self): all = self.request.user.teams.filter( @@ -768,7 +768,7 @@ class RefundExportListView(ListView): class EventRefundExportListView(EventPermissionRequiredMixin, RefundExportListView): - permission = 'can_change_orders' + permission = 'event.orders:write' def get_success_url(self): return reverse('plugins:banktransfer:refunds.list', kwargs={ @@ -791,7 +791,7 @@ class EventRefundExportListView(EventPermissionRequiredMixin, RefundExportListVi class OrganizerRefundExportListView(OrganizerPermissionRequiredMixin, RefundExportListView): - permission = 'can_change_orders' + permission = 'event.orders:write' def get_success_url(self): return reverse('plugins:banktransfer:refunds.list', kwargs={ @@ -824,7 +824,7 @@ class DownloadRefundExportView(DetailView): class EventDownloadRefundExportView(EventPermissionRequiredMixin, DownloadRefundExportView): - permission = 'can_change_orders' + permission = 'event.orders:write' def get_object(self, *args, **kwargs): return get_object_or_404( @@ -835,7 +835,7 @@ class EventDownloadRefundExportView(EventPermissionRequiredMixin, DownloadRefund class OrganizerDownloadRefundExportView(OrganizerPermissionRequiredMixin, OrganizerDetailViewMixin, DownloadRefundExportView): - permission = 'can_change_orders' + permission = 'event.orders:write' def get_object(self, *args, **kwargs): return get_object_or_404( @@ -882,7 +882,7 @@ class SepaXMLExportView(SingleObjectMixin, FormView): class EventSepaXMLExportView(EventPermissionRequiredMixin, SepaXMLExportView): - permission = 'can_change_orders' + permission = 'event.orders:write' def get_object(self, *args, **kwargs): return get_object_or_404( @@ -898,7 +898,7 @@ class EventSepaXMLExportView(EventPermissionRequiredMixin, SepaXMLExportView): class OrganizerSepaXMLExportView(OrganizerPermissionRequiredMixin, OrganizerDetailViewMixin, SepaXMLExportView): - permission = 'can_change_orders' + permission = 'event.orders:write' def get_object(self, *args, **kwargs): return get_object_or_404( diff --git a/src/pretix/plugins/paypal/views.py b/src/pretix/plugins/paypal/views.py index 01a37b814..1436bdd5f 100644 --- a/src/pretix/plugins/paypal/views.py +++ b/src/pretix/plugins/paypal/views.py @@ -246,7 +246,7 @@ def webhook(request, *args, **kwargs): return HttpResponse(status=200) -@event_permission_required('can_change_event_settings') +@event_permission_required('event.settings.general:write') @require_POST def oauth_disconnect(request, **kwargs): del request.event.settings.payment_paypal_connect_refresh_token diff --git a/src/pretix/plugins/paypal2/views.py b/src/pretix/plugins/paypal2/views.py index 336239a18..7edf796bf 100644 --- a/src/pretix/plugins/paypal2/views.py +++ b/src/pretix/plugins/paypal2/views.py @@ -216,7 +216,7 @@ class PayView(PaypalOrderView, TemplateView): @scopes_disabled() -@event_permission_required('can_change_event_settings') +@event_permission_required('event.settings.general:write') def isu_return(request, *args, **kwargs): getparams = ['merchantId', 'merchantIdInPayPal', 'permissionsGranted', 'accountStatus', 'consentStatus', 'productIntentID', 'isEmailConfirmed'] sessionparams = ['payment_paypal_isu_event', 'payment_paypal_isu_tracking_id'] @@ -526,7 +526,7 @@ def webhook(request, *args, **kwargs): return HttpResponse(status=200) -@event_permission_required('can_change_event_settings') +@event_permission_required('event.settings.general:write') @require_POST def isu_disconnect(request, **kwargs): del request.event.settings.payment_paypal_connect_refresh_token diff --git a/src/pretix/plugins/returnurl/signals.py b/src/pretix/plugins/returnurl/signals.py index 60583003f..3cf7e6262 100644 --- a/src/pretix/plugins/returnurl/signals.py +++ b/src/pretix/plugins/returnurl/signals.py @@ -83,7 +83,7 @@ def check_against_prefix_list(u, allowlist): @receiver(nav_event_settings, dispatch_uid='returnurl_nav') def navbar_info(sender, request, **kwargs): url = resolve(request.path_info) - if not request.user.has_event_permission(request.organizer, request.event, 'can_change_event_settings', + if not request.user.has_event_permission(request.organizer, request.event, 'event.settings.general:write', request=request): return [] return [{ diff --git a/src/pretix/plugins/returnurl/views.py b/src/pretix/plugins/returnurl/views.py index f3fab2490..43f53f368 100644 --- a/src/pretix/plugins/returnurl/views.py +++ b/src/pretix/plugins/returnurl/views.py @@ -48,7 +48,7 @@ class ReturnSettings(EventSettingsViewMixin, EventSettingsFormView): model = Event form_class = ReturnSettingsForm template_name = 'returnurl/settings.html' - permission = 'can_change_settings' + permission = 'event.settings.general:write' def get_success_url(self) -> str: return reverse('plugins:returnurl:settings', kwargs={ diff --git a/src/pretix/plugins/sendmail/api.py b/src/pretix/plugins/sendmail/api.py index 1bcc80593..7d5e1548a 100644 --- a/src/pretix/plugins/sendmail/api.py +++ b/src/pretix/plugins/sendmail/api.py @@ -113,7 +113,7 @@ class RuleViewSet(viewsets.ModelViewSet): filterset_class = RuleFilter ordering = ('id',) ordering_fields = ('id',) - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' def get_queryset(self): return Rule.objects.filter(event=self.request.event) diff --git a/src/pretix/plugins/sendmail/signals.py b/src/pretix/plugins/sendmail/signals.py index 1186f11f4..e573ce71d 100644 --- a/src/pretix/plugins/sendmail/signals.py +++ b/src/pretix/plugins/sendmail/signals.py @@ -79,7 +79,7 @@ def scheduled_mail_create(sender, **kwargs): @receiver(nav_event, dispatch_uid="sendmail_nav") def control_nav_import(sender, request=None, **kwargs): url = resolve(request.path_info) - if not request.user.has_event_permission(request.organizer, request.event, 'can_change_orders', request=request): + if not request.user.has_event_permission(request.organizer, request.event, 'event.orders:write', request=request): return [] return [ { diff --git a/src/pretix/plugins/sendmail/views.py b/src/pretix/plugins/sendmail/views.py index 189761ab4..a78edbb9c 100644 --- a/src/pretix/plugins/sendmail/views.py +++ b/src/pretix/plugins/sendmail/views.py @@ -72,7 +72,7 @@ logger = logging.getLogger('pretix.plugins.sendmail') class IndexView(EventPermissionRequiredMixin, TemplateView): template_name = 'pretixplugins/sendmail/index.html' - permission = 'can_change_orders' + permission = 'event.orders:write' def get_context_data(self, **kwargs): from .signals import sendmail_view_classes @@ -94,7 +94,7 @@ class IndexView(EventPermissionRequiredMixin, TemplateView): class BaseSenderView(EventPermissionRequiredMixin, FormView): # These parameters usually SHOULD NOT be overridden template_name = 'pretixplugins/sendmail/send_form.html' - permission = 'can_change_orders' + permission = 'event.orders:write' # These parameters MUST be overridden by subclasses form_fragment_name = None @@ -523,7 +523,7 @@ class WaitinglistSendView(BaseSenderView): class EmailHistoryView(EventPermissionRequiredMixin, ListView): template_name = 'pretixplugins/sendmail/history.html' - permission = 'can_change_orders' + permission = 'event.orders:write' model = LogEntry context_object_name = 'logs' paginate_by = 5 @@ -571,7 +571,7 @@ class EmailHistoryView(EventPermissionRequiredMixin, ListView): class CreateRule(EventPermissionRequiredMixin, CreateView): template_name = 'pretixplugins/sendmail/rule_create.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' form_class = forms.RuleForm model = Rule @@ -621,7 +621,7 @@ class UpdateRule(EventPermissionRequiredMixin, UpdateView): model = Rule form_class = forms.RuleForm template_name = 'pretixplugins/sendmail/rule_update.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' def get_object(self, queryset=None) -> Rule: return get_object_or_404( @@ -701,7 +701,7 @@ class ListRules(EventPermissionRequiredMixin, PaginationMixin, ListView): class DeleteRule(EventPermissionRequiredMixin, DeleteView): model = Rule - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' template_name = 'pretixplugins/sendmail/rule_delete.html' context_object_name = 'rule' diff --git a/src/pretix/plugins/statistics/signals.py b/src/pretix/plugins/statistics/signals.py index 224a916b0..8c77d9ff6 100644 --- a/src/pretix/plugins/statistics/signals.py +++ b/src/pretix/plugins/statistics/signals.py @@ -30,7 +30,7 @@ from pretix.control.signals import nav_event @receiver(nav_event, dispatch_uid="statistics_nav") def control_nav_import(sender, request=None, **kwargs): url = resolve(request.path_info) - if not request.user.has_event_permission(request.organizer, request.event, 'can_view_orders', request=request): + if not request.user.has_event_permission(request.organizer, request.event, 'event.orders:read', request=request): return [] return [ { diff --git a/src/pretix/plugins/statistics/views.py b/src/pretix/plugins/statistics/views.py index 518120854..ecc87b1d5 100644 --- a/src/pretix/plugins/statistics/views.py +++ b/src/pretix/plugins/statistics/views.py @@ -52,7 +52,7 @@ from pretix.plugins.statistics.signals import clear_cache class IndexView(EventPermissionRequiredMixin, ChartContainingView, TemplateView): template_name = 'pretixplugins/statistics/index.html' - permission = 'can_view_orders' + permission = 'event.orders:read' def get_context_data(self, **kwargs): ctx = super().get_context_data(**kwargs) diff --git a/src/pretix/plugins/stripe/views.py b/src/pretix/plugins/stripe/views.py index f997a67b1..a9590f49a 100644 --- a/src/pretix/plugins/stripe/views.py +++ b/src/pretix/plugins/stripe/views.py @@ -473,7 +473,7 @@ def paymentintent_webhook(event, event_json, paymentintent_id, rso): return HttpResponse(status=200) -@event_permission_required('can_change_event_settings') +@event_permission_required('event.settings.general:write') def oauth_disconnect(request, **kwargs): if request.method != "POST": return render(request, 'pretixplugins/stripe/oauth_disconnect.html', {}) @@ -671,7 +671,7 @@ class ScaReturnView(StripeOrderView, View): class OrganizerSettingsFormView(DecoupleMixin, OrganizerDetailViewMixin, AdministratorPermissionRequiredMixin, FormView): model = Organizer - permission = 'can_change_organizer_settings' + permission = 'organizer.settings.general:write' form_class = OrganizerStripeSettingsForm template_name = 'pretixplugins/stripe/organizer_stripe.html' diff --git a/src/pretix/plugins/ticketoutputpdf/api.py b/src/pretix/plugins/ticketoutputpdf/api.py index 7232c4bcf..231c48b0f 100644 --- a/src/pretix/plugins/ticketoutputpdf/api.py +++ b/src/pretix/plugins/ticketoutputpdf/api.py @@ -206,7 +206,7 @@ class RenderJobSerializer(serializers.Serializer): class TicketRendererViewSet(viewsets.ViewSet): - permission = 'can_view_orders' + permission = 'event.orders:read' def get_serializer_kwargs(self): return {} diff --git a/src/pretix/plugins/ticketoutputpdf/views.py b/src/pretix/plugins/ticketoutputpdf/views.py index 5d47cad30..4194291d9 100644 --- a/src/pretix/plugins/ticketoutputpdf/views.py +++ b/src/pretix/plugins/ticketoutputpdf/views.py @@ -95,7 +95,7 @@ class EditorView(BaseEditorView): class LayoutListView(EventPermissionRequiredMixin, ListView): model = TicketLayout - permission = ('can_change_event_settings') + permission = ('event.settings.general:write') template_name = 'pretixplugins/ticketoutputpdf/index.html' context_object_name = 'layouts' @@ -107,7 +107,7 @@ class LayoutCreate(EventPermissionRequiredMixin, CreateView): model = TicketLayout form_class = TicketLayoutForm template_name = 'pretixplugins/ticketoutputpdf/edit.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' context_object_name = 'layout' success_url = '/ignored' @@ -157,7 +157,7 @@ class LayoutCreate(EventPermissionRequiredMixin, CreateView): class LayoutSetDefault(EventPermissionRequiredMixin, DetailView): model = TicketLayout - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' def get_object(self, queryset=None) -> TicketLayout: try: @@ -186,7 +186,7 @@ class LayoutSetDefault(EventPermissionRequiredMixin, DetailView): class LayoutDelete(EventPermissionRequiredMixin, CompatDeleteView): model = TicketLayout template_name = 'pretixplugins/ticketoutputpdf/delete.html' - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' context_object_name = 'layout' def get_object(self, queryset=None) -> TicketLayout: @@ -218,7 +218,7 @@ class LayoutDelete(EventPermissionRequiredMixin, CompatDeleteView): class LayoutGetDefault(EventPermissionRequiredMixin, View): - permission = 'can_change_event_settings' + permission = 'event.settings.general:write' def get(self, request, *args, **kwargs): layout = self.request.event.ticket_layouts.get_or_create( @@ -304,7 +304,7 @@ class LayoutEditorView(BaseEditorView): class OrderPrintDo(EventPermissionRequiredMixin, AsyncAction, View): task = tickets_create_pdf - permission = 'can_view_orders' + permission = 'event.orders:read' known_errortypes = ['OrderError', 'ExportError'] def get_success_message(self, value): diff --git a/src/pretix/plugins/webcheckin/signals.py b/src/pretix/plugins/webcheckin/signals.py index b88ad5fad..848862458 100644 --- a/src/pretix/plugins/webcheckin/signals.py +++ b/src/pretix/plugins/webcheckin/signals.py @@ -30,7 +30,7 @@ from pretix.control.signals import nav_event @receiver(nav_event, dispatch_uid='webcheckin_nav_event') def navbar_entry(sender, request, **kwargs): url = request.resolver_match - if not request.user.has_event_permission(request.organizer, request.event, ('can_change_orders', 'can_checkin_orders'), request=request): + if not request.user.has_event_permission(request.organizer, request.event, ('event.orders:write', 'event.orders:checkin'), request=request): return [] return [{ 'label': mark_safe(_('Web Check-in') + ' beta'), diff --git a/src/pretix/plugins/webcheckin/views.py b/src/pretix/plugins/webcheckin/views.py index c4b42a795..c72b21062 100644 --- a/src/pretix/plugins/webcheckin/views.py +++ b/src/pretix/plugins/webcheckin/views.py @@ -26,7 +26,7 @@ from pretix.helpers.countries import CachedCountries class IndexView(EventPermissionRequiredMixin, TemplateView): - permission = ('can_change_orders', 'can_checkin_orders') + permission = ('event.orders:write', 'event.orders:checkin') template_name = 'pretixplugins/webcheckin/index.html' def get_context_data(self, **kwargs): diff --git a/src/pretix/presale/views/order.py b/src/pretix/presale/views/order.py index dc8182dd6..948875291 100644 --- a/src/pretix/presale/views/order.py +++ b/src/pretix/presale/views/order.py @@ -208,7 +208,7 @@ class TicketPageMixin: ctx['download_buttons'] = self.download_buttons - ctx['backend_user'] = has_event_access_permission(self.request, 'can_view_orders') + ctx['backend_user'] = has_event_access_permission(self.request, 'event.orders:read') return ctx diff --git a/src/tests/api/test_exporters.py b/src/tests/api/test_exporters.py index 33ef8f4c2..fc4d47325 100644 --- a/src/tests/api/test_exporters.py +++ b/src/tests/api/test_exporters.py @@ -334,9 +334,10 @@ def test_event_scheduled_export_list_token(token_client, organizer, event, user, team.limit_organizer_permissions = {"organizer.events:create": True} team.all_organizer_permissions = False + team.all_event_permissions = False team.save() - # Token can no longer sees it an gets error message + # Token can no longer sees it and gets error message resp = token_client.get('/api/v1/organizers/{}/events/{}/scheduled_exports/'.format(organizer.slug, event.slug)) assert resp.status_code == 403 @@ -355,7 +356,9 @@ def test_event_scheduled_export_list_user(user_client, organizer, event, user, t resp = user_client.get('/api/v1/organizers/{}/events/{}/scheduled_exports/'.format(organizer.slug, event.slug)) assert [res] == resp.data['results'] - team.limit_event_permissions["event.settings.general:write"] = False + team.limit_organizer_permissions = {"organizer.events:create": True} + team.all_organizer_permissions = False + team.all_event_permissions = False team.save() # Owner still can diff --git a/src/tests/api/test_permissions.py b/src/tests/api/test_permissions.py index d6b560381..dcf3a1945 100644 --- a/src/tests/api/test_permissions.py +++ b/src/tests/api/test_permissions.py @@ -43,239 +43,238 @@ from pretix.base.models import Organizer event_urls = [ (None, ''), (None, 'categories/'), - ('can_view_orders', 'invoices/'), + ('event.orders:read', 'invoices/'), (None, 'items/'), - ('can_view_orders', 'orders/'), - ('can_view_orders', 'orderpositions/'), + ('event.orders:read', 'orders/'), + ('event.orders:read', 'orderpositions/'), (None, 'questions/'), (None, 'quotas/'), - ('can_view_vouchers', 'vouchers/'), + ('event.vouchers:read', 'vouchers/'), (None, 'subevents/'), (None, 'taxrules/'), - ('can_view_orders', 'waitinglistentries/'), - ('can_view_orders', 'checkinlists/'), - ('can_view_orders', 'checkins/'), + ('event.orders:read', 'waitinglistentries/'), + ('event.orders:read', 'checkinlists/'), + ('event.orders:read', 'checkins/'), (None, 'seats/'), ] event_permission_sub_urls = [ - ('get', 'can_change_event_settings', 'settings/', 200), - ('patch', 'can_change_event_settings', 'settings/', 200), - ('get', 'can_view_orders', 'revokedsecrets/', 200), - ('get', 'can_view_orders', 'revokedsecrets/1/', 404), - ('get', 'can_view_orders', 'blockedsecrets/', 200), - ('get', 'can_view_orders', 'blockedsecrets/1/', 404), - ('get', 'can_view_orders', 'transactions/', 200), - ('get', 'can_view_orders', 'transactions/1/', 404), - ('get', 'can_view_orders', 'orders/', 200), - ('get', 'can_view_orders', 'orderpositions/', 200), - ('delete', 'can_change_orders', 'orderpositions/1/', 404), - ('post', 'can_change_orders', 'orderpositions/1/price_calc/', 404), - ('get', 'can_view_vouchers', 'vouchers/', 200), - ('get', 'can_view_orders', 'invoices/', 200), - ('get', 'can_view_orders', 'invoices/1/', 404), - ('post', 'can_change_orders', 'invoices/1/regenerate/', 404), - ('post', 'can_change_orders', 'invoices/1/reissue/', 404), - ('post', 'can_change_orders', 'invoices/1/retransmit/', 404), - ('get', 'can_view_orders', 'waitinglistentries/', 200), - ('get', 'can_view_orders', 'waitinglistentries/1/', 404), - ('post', 'can_change_orders', 'waitinglistentries/', 400), - ('delete', 'can_change_orders', 'waitinglistentries/1/', 404), - ('patch', 'can_change_orders', 'waitinglistentries/1/', 404), - ('put', 'can_change_orders', 'waitinglistentries/1/', 404), - ('post', 'can_change_orders', 'waitinglistentries/1/send_voucher/', 404), + ('get', 'event.settings.general:write', 'settings/', 200), + ('patch', 'event.settings.general:write', 'settings/', 200), + ('get', 'event.orders:read', 'revokedsecrets/', 200), + ('get', 'event.orders:read', 'revokedsecrets/1/', 404), + ('get', 'event.orders:read', 'blockedsecrets/', 200), + ('get', 'event.orders:read', 'blockedsecrets/1/', 404), + ('get', 'event.orders:read', 'transactions/', 200), + ('get', 'event.orders:read', 'transactions/1/', 404), + ('get', 'event.orders:read', 'orders/', 200), + ('get', 'event.orders:read', 'orderpositions/', 200), + ('delete', 'event.orders:write', 'orderpositions/1/', 404), + ('post', 'event.orders:write', 'orderpositions/1/price_calc/', 404), + ('get', 'event.vouchers:read', 'vouchers/', 200), + ('get', 'event.orders:read', 'invoices/', 200), + ('get', 'event.orders:read', 'invoices/1/', 404), + ('post', 'event.orders:write', 'invoices/1/regenerate/', 404), + ('post', 'event.orders:write', 'invoices/1/reissue/', 404), + ('post', 'event.orders:write', 'invoices/1/retransmit/', 404), + ('get', 'event.orders:read', 'waitinglistentries/', 200), + ('get', 'event.orders:read', 'waitinglistentries/1/', 404), + ('post', 'event.orders:write', 'waitinglistentries/', 400), + ('delete', 'event.orders:write', 'waitinglistentries/1/', 404), + ('patch', 'event.orders:write', 'waitinglistentries/1/', 404), + ('put', 'event.orders:write', 'waitinglistentries/1/', 404), + ('post', 'event.orders:write', 'waitinglistentries/1/send_voucher/', 404), ('get', None, 'categories/', 200), ('get', None, 'items/', 200), ('get', None, 'questions/', 200), ('get', None, 'quotas/', 200), ('get', None, 'discounts/', 200), - ('post', 'can_change_items', 'items/', 400), + ('post', 'event.items:write', 'items/', 400), ('get', None, 'items/1/', 404), - ('put', 'can_change_items', 'items/1/', 404), - ('patch', 'can_change_items', 'items/1/', 404), - ('delete', 'can_change_items', 'items/1/', 404), - ('post', 'can_change_items', 'categories/', 400), + ('put', 'event.items:write', 'items/1/', 404), + ('patch', 'event.items:write', 'items/1/', 404), + ('delete', 'event.items:write', 'items/1/', 404), + ('post', 'event.items:write', 'categories/', 400), ('get', None, 'categories/1/', 404), - ('put', 'can_change_items', 'categories/1/', 404), - ('patch', 'can_change_items', 'categories/1/', 404), - ('delete', 'can_change_items', 'categories/1/', 404), - ('post', 'can_change_items', 'discounts/', 400), + ('put', 'event.items:write', 'categories/1/', 404), + ('patch', 'event.items:write', 'categories/1/', 404), + ('delete', 'event.items:write', 'categories/1/', 404), + ('post', 'event.items:write', 'discounts/', 400), ('get', None, 'discounts/1/', 404), - ('put', 'can_change_items', 'discounts/1/', 404), - ('patch', 'can_change_items', 'discounts/1/', 404), - ('delete', 'can_change_items', 'discounts/1/', 404), - ('post', 'can_change_items', 'items/1/variations/', 404), + ('put', 'event.items:write', 'discounts/1/', 404), + ('patch', 'event.items:write', 'discounts/1/', 404), + ('delete', 'event.items:write', 'discounts/1/', 404), + ('post', 'event.items:write', 'items/1/variations/', 404), ('get', None, 'items/1/variations/', 404), ('get', None, 'items/1/variations/1/', 404), - ('put', 'can_change_items', 'items/1/variations/1/', 404), - ('patch', 'can_change_items', 'items/1/variations/1/', 404), - ('delete', 'can_change_items', 'items/1/variations/1/', 404), + ('put', 'event.items:write', 'items/1/variations/1/', 404), + ('patch', 'event.items:write', 'items/1/variations/1/', 404), + ('delete', 'event.items:write', 'items/1/variations/1/', 404), ('get', None, 'items/1/addons/', 404), ('get', None, 'items/1/addons/1/', 404), - ('post', 'can_change_items', 'items/1/addons/', 404), - ('put', 'can_change_items', 'items/1/addons/1/', 404), - ('patch', 'can_change_items', 'items/1/addons/1/', 404), - ('delete', 'can_change_items', 'items/1/addons/1/', 404), + ('post', 'event.items:write', 'items/1/addons/', 404), + ('put', 'event.items:write', 'items/1/addons/1/', 404), + ('patch', 'event.items:write', 'items/1/addons/1/', 404), + ('delete', 'event.items:write', 'items/1/addons/1/', 404), ('get', None, 'subevents/', 200), ('get', None, 'subevents/1/', 404), ('get', None, 'taxrules/', 200), ('get', None, 'taxrules/1/', 404), - ('post', 'can_change_event_settings', 'taxrules/', 400), - ('put', 'can_change_event_settings', 'taxrules/1/', 404), - ('patch', 'can_change_event_settings', 'taxrules/1/', 404), - ('delete', 'can_change_event_settings', 'taxrules/1/', 404), - ('get', 'can_change_event_settings', 'sendmail_rules/', 200), - ('get', 'can_change_event_settings', 'sendmail_rules/1/', 404), - ('post', 'can_change_event_settings', 'sendmail_rules/', 400), - ('put', 'can_change_event_settings', 'sendmail_rules/1/', 404), - ('patch', 'can_change_event_settings', 'sendmail_rules/1/', 404), - ('delete', 'can_change_event_settings', 'sendmail_rules/1/', 404), - ('get', 'can_view_vouchers', 'vouchers/', 200), - ('get', 'can_view_vouchers', 'vouchers/1/', 404), - ('post', 'can_change_vouchers', 'vouchers/', 201), - ('put', 'can_change_vouchers', 'vouchers/1/', 404), - ('patch', 'can_change_vouchers', 'vouchers/1/', 404), - ('delete', 'can_change_vouchers', 'vouchers/1/', 404), + ('post', 'event.settings.general:write', 'taxrules/', 400), + ('put', 'event.settings.general:write', 'taxrules/1/', 404), + ('patch', 'event.settings.general:write', 'taxrules/1/', 404), + ('delete', 'event.settings.general:write', 'taxrules/1/', 404), + ('get', 'event.settings.general:write', 'sendmail_rules/', 200), + ('get', 'event.settings.general:write', 'sendmail_rules/1/', 404), + ('post', 'event.settings.general:write', 'sendmail_rules/', 400), + ('put', 'event.settings.general:write', 'sendmail_rules/1/', 404), + ('patch', 'event.settings.general:write', 'sendmail_rules/1/', 404), + ('delete', 'event.settings.general:write', 'sendmail_rules/1/', 404), + ('get', 'event.vouchers:read', 'vouchers/', 200), + ('get', 'event.vouchers:read', 'vouchers/1/', 404), + ('post', 'event.vouchers:write', 'vouchers/', 201), + ('put', 'event.vouchers:write', 'vouchers/1/', 404), + ('patch', 'event.vouchers:write', 'vouchers/1/', 404), + ('delete', 'event.vouchers:write', 'vouchers/1/', 404), ('get', None, 'quotas/', 200), ('get', None, 'quotas/1/', 404), - ('post', 'can_change_items', 'quotas/', 400), - ('put', 'can_change_items', 'quotas/1/', 404), - ('patch', 'can_change_items', 'quotas/1/', 404), - ('delete', 'can_change_items', 'quotas/1/', 404), + ('post', 'event.items:write', 'quotas/', 400), + ('put', 'event.items:write', 'quotas/1/', 404), + ('patch', 'event.items:write', 'quotas/1/', 404), + ('delete', 'event.items:write', 'quotas/1/', 404), ('get', None, 'questions/', 200), ('get', None, 'questions/1/', 404), - ('post', 'can_change_items', 'questions/', 400), - ('put', 'can_change_items', 'questions/1/', 404), - ('patch', 'can_change_items', 'questions/1/', 404), - ('delete', 'can_change_items', 'questions/1/', 404), + ('post', 'event.items:write', 'questions/', 400), + ('put', 'event.items:write', 'questions/1/', 404), + ('patch', 'event.items:write', 'questions/1/', 404), + ('delete', 'event.items:write', 'questions/1/', 404), ('get', None, 'questions/1/options/', 404), ('get', None, 'questions/1/options/1/', 404), - ('put', 'can_change_items', 'questions/1/options/1/', 404), - ('patch', 'can_change_items', 'questions/1/options/1/', 404), - ('delete', 'can_change_items', 'questions/1/options/1/', 404), - ('post', 'can_change_orders', 'orders/', 400), - ('patch', 'can_change_orders', 'orders/ABC12/', 404), - ('post', 'can_change_orders', 'orders/ABC12/mark_paid/', 404), - ('post', 'can_change_orders', 'orders/ABC12/mark_pending/', 404), - ('post', 'can_change_orders', 'orders/ABC12/mark_expired/', 404), - ('post', 'can_change_orders', 'orders/ABC12/mark_canceled/', 404), - ('post', 'can_change_orders', 'orders/ABC12/approve/', 404), - ('post', 'can_change_orders', 'orders/ABC12/deny/', 404), - ('post', 'can_change_orders', 'orders/ABC12/extend/', 400), - ('post', 'can_change_orders', 'orders/ABC12/create_invoice/', 404), - ('post', 'can_change_orders', 'orders/ABC12/resend_link/', 404), - ('post', 'can_change_orders', 'orders/ABC12/regenerate_secrets/', 404), - ('get', 'can_view_orders', 'orders/ABC12/payments/', 404), - ('get', 'can_view_orders', 'orders/ABC12/payments/1/', 404), - ('get', 'can_view_orders', 'orders/ABC12/refunds/', 404), - ('get', 'can_view_orders', 'orders/ABC12/refunds/1/', 404), - ('post', 'can_change_orders', 'orders/ABC12/payments/1/confirm/', 404), - ('post', 'can_change_orders', 'orders/ABC12/payments/1/refund/', 404), - ('post', 'can_change_orders', 'orders/ABC12/payments/1/cancel/', 404), - ('post', 'can_change_orders', 'orders/ABC12/refunds/1/cancel/', 404), - ('post', 'can_change_orders', 'orders/ABC12/refunds/1/process/', 404), - ('post', 'can_change_orders', 'orders/ABC12/refunds/1/done/', 404), - ('get', 'can_view_orders', 'checkinlists/', 200), - ('post', 'can_change_orders', 'checkinlists/1/failed_checkins/', 400), - ('get', 'can_view_orders', 'checkins/', 200), - ('get', 'can_view_orders', 'checkins/1/', 404), - ('post', 'can_change_event_settings', 'checkinlists/', 400), - ('put', 'can_change_event_settings', 'checkinlists/1/', 404), - ('patch', 'can_change_event_settings', 'checkinlists/1/', 404), - ('delete', 'can_change_event_settings', 'checkinlists/1/', 404), - ('get', 'can_view_orders', 'checkinlists/1/positions/', 404), - ('post', 'can_change_orders', 'checkinlists/1/positions/3/redeem/', 404), - ('post', 'can_create_events', 'clone/', 400), - ('get', 'can_view_orders', 'cartpositions/', 200), - ('get', 'can_view_orders', 'cartpositions/1/', 404), - ('post', 'can_change_orders', 'cartpositions/', 400), - ('delete', 'can_change_orders', 'cartpositions/1/', 404), - ('post', 'can_view_orders', 'exporters/invoicedata/run/', 400), - ('get', 'can_view_orders', 'exporters/invoicedata/download/bc3f9884-26ee-425b-8636-80613f84b6fa/3cb49ae6-eda3' - '-4605-814e-099e23777b36/', 404), + ('put', 'event.items:write', 'questions/1/options/1/', 404), + ('patch', 'event.items:write', 'questions/1/options/1/', 404), + ('delete', 'event.items:write', 'questions/1/options/1/', 404), + ('post', 'event.orders:write', 'orders/', 400), + ('patch', 'event.orders:write', 'orders/ABC12/', 404), + ('post', 'event.orders:write', 'orders/ABC12/mark_paid/', 404), + ('post', 'event.orders:write', 'orders/ABC12/mark_pending/', 404), + ('post', 'event.orders:write', 'orders/ABC12/mark_expired/', 404), + ('post', 'event.orders:write', 'orders/ABC12/mark_canceled/', 404), + ('post', 'event.orders:write', 'orders/ABC12/approve/', 404), + ('post', 'event.orders:write', 'orders/ABC12/deny/', 404), + ('post', 'event.orders:write', 'orders/ABC12/extend/', 400), + ('post', 'event.orders:write', 'orders/ABC12/create_invoice/', 404), + ('post', 'event.orders:write', 'orders/ABC12/resend_link/', 404), + ('post', 'event.orders:write', 'orders/ABC12/regenerate_secrets/', 404), + ('get', 'event.orders:read', 'orders/ABC12/payments/', 404), + ('get', 'event.orders:read', 'orders/ABC12/payments/1/', 404), + ('get', 'event.orders:read', 'orders/ABC12/refunds/', 404), + ('get', 'event.orders:read', 'orders/ABC12/refunds/1/', 404), + ('post', 'event.orders:write', 'orders/ABC12/payments/1/confirm/', 404), + ('post', 'event.orders:write', 'orders/ABC12/payments/1/refund/', 404), + ('post', 'event.orders:write', 'orders/ABC12/payments/1/cancel/', 404), + ('post', 'event.orders:write', 'orders/ABC12/refunds/1/cancel/', 404), + ('post', 'event.orders:write', 'orders/ABC12/refunds/1/process/', 404), + ('post', 'event.orders:write', 'orders/ABC12/refunds/1/done/', 404), + ('get', 'event.orders:read', 'checkinlists/', 200), + ('post', 'event.orders:write', 'checkinlists/1/failed_checkins/', 400), + ('get', 'event.orders:read', 'checkins/', 200), + ('get', 'event.orders:read', 'checkins/1/', 404), + ('post', 'event.settings.general:write', 'checkinlists/', 400), + ('put', 'event.settings.general:write', 'checkinlists/1/', 404), + ('patch', 'event.settings.general:write', 'checkinlists/1/', 404), + ('delete', 'event.settings.general:write', 'checkinlists/1/', 404), + ('get', 'event.orders:read', 'checkinlists/1/positions/', 404), + ('post', 'event.orders:write', 'checkinlists/1/positions/3/redeem/', 404), + ('post', 'organizer.events:create', 'clone/', 400), + ('get', 'event.orders:read', 'cartpositions/', 200), + ('get', 'event.orders:read', 'cartpositions/1/', 404), + ('post', 'event.orders:write', 'cartpositions/', 400), + ('delete', 'event.orders:write', 'cartpositions/1/', 404), + ('post', 'event.orders:read', 'exporters/invoicedata/run/', 400), + ('get', 'event.orders:read', 'exporters/invoicedata/download/bc3f9884-26ee-425b-8636-80613f84b6fa/3cb49ae6-eda3-4605-814e-099e23777b36/', 404), ('get', None, 'item_meta_properties/', 200), ('get', None, 'item_meta_properties/0/', 404), - ('post', 'can_change_event_settings', 'item_meta_properties/', 400), - ('patch', 'can_change_event_settings', 'item_meta_properties/0/', 404), - ('delete', 'can_change_event_settings', 'item_meta_properties/0/', 404), + ('post', 'event.settings.general:write', 'item_meta_properties/', 400), + ('patch', 'event.settings.general:write', 'item_meta_properties/0/', 404), + ('delete', 'event.settings.general:write', 'item_meta_properties/0/', 404), ('get', None, 'seats/', 200), - ('get', 'can_view_orders', 'seats/?expand=orderposition', 200), - ('get', 'can_view_orders', 'seats/?expand=cartposition', 200), - ('get', 'can_view_vouchers', 'seats/?expand=voucher', 200), + ('get', 'event.orders:read', 'seats/?expand=orderposition', 200), + ('get', 'event.orders:read', 'seats/?expand=cartposition', 200), + ('get', 'event.vouchers:read', 'seats/?expand=voucher', 200), ('get', None, 'seats/1/', 404), - ('patch', 'can_change_event_settings', 'seats/1/', 404), + ('patch', 'event.settings.general:write', 'seats/1/', 404), ] org_permission_sub_urls = [ - ('patch', 'can_change_organizer_settings', '', 200), - ('patch', 'can_change_organizer_settings', 'settings/', 200), - ('get', 'can_change_organizer_settings', 'webhooks/', 200), - ('post', 'can_change_organizer_settings', 'webhooks/', 400), - ('get', 'can_change_organizer_settings', 'webhooks/1/', 404), - ('put', 'can_change_organizer_settings', 'webhooks/1/', 404), - ('patch', 'can_change_organizer_settings', 'webhooks/1/', 404), - ('delete', 'can_change_organizer_settings', 'webhooks/1/', 404), - ('get', 'can_manage_customers', 'customers/', 200), - ('post', 'can_manage_customers', 'customers/', 201), - ('get', 'can_manage_customers', 'customers/1/', 404), - ('patch', 'can_manage_customers', 'customers/1/', 404), - ('post', 'can_manage_customers', 'customers/1/anonymize/', 404), - ('put', 'can_manage_customers', 'customers/1/', 404), - ('delete', 'can_manage_customers', 'customers/1/', 404), - ('get', 'can_manage_customers', 'memberships/', 200), - ('post', 'can_manage_customers', 'memberships/', 400), - ('get', 'can_manage_customers', 'memberships/1/', 404), - ('patch', 'can_manage_customers', 'memberships/1/', 404), - ('put', 'can_manage_customers', 'memberships/1/', 404), - ('delete', 'can_manage_customers', 'memberships/1/', 404), - ('get', 'can_change_organizer_settings', 'saleschannels/', 200), - ('post', 'can_change_organizer_settings', 'saleschannels/', 400), - ('get', 'can_change_organizer_settings', 'saleschannels/web/', 200), - ('patch', 'can_change_organizer_settings', 'saleschannels/web/', 200), - ('put', 'can_change_organizer_settings', 'saleschannels/api.1/', 404), - ('delete', 'can_change_organizer_settings', 'saleschannels/api.1/', 404), - ('get', 'can_change_organizer_settings', 'membershiptypes/', 200), - ('post', 'can_change_organizer_settings', 'membershiptypes/', 400), - ('get', 'can_change_organizer_settings', 'membershiptypes/1/', 404), - ('patch', 'can_change_organizer_settings', 'membershiptypes/1/', 404), - ('put', 'can_change_organizer_settings', 'membershiptypes/1/', 404), - ('delete', 'can_change_organizer_settings', 'membershiptypes/1/', 404), - ('get', 'can_manage_gift_cards', 'giftcards/', 200), - ('post', 'can_manage_gift_cards', 'giftcards/', 400), - ('get', 'can_manage_gift_cards', 'giftcards/1/', 404), - ('put', 'can_manage_gift_cards', 'giftcards/1/', 404), - ('patch', 'can_manage_gift_cards', 'giftcards/1/', 404), - ('get', 'can_manage_gift_cards', 'giftcards/1/transactions/', 404), - ('get', 'can_manage_gift_cards', 'giftcards/1/transactions/1/', 404), - ('get', 'can_change_organizer_settings', 'devices/', 200), - ('post', 'can_change_organizer_settings', 'devices/', 400), - ('get', 'can_change_organizer_settings', 'devices/1/', 404), - ('put', 'can_change_organizer_settings', 'devices/1/', 404), - ('patch', 'can_change_organizer_settings', 'devices/1/', 404), - ('get', 'can_change_teams', 'teams/', 200), - ('post', 'can_change_teams', 'teams/', 400), - ('get', 'can_change_teams', 'teams/{team_id}/', 200), - ('put', 'can_change_teams', 'teams/{team_id}/', 400), - ('patch', 'can_change_teams', 'teams/{team_id}/', 200), - ('get', 'can_change_teams', 'teams/{team_id}/members/', 200), - ('delete', 'can_change_teams', 'teams/{team_id}/members/2/', 404), - ('get', 'can_change_teams', 'teams/{team_id}/invites/', 200), - ('get', 'can_change_teams', 'teams/{team_id}/invites/2/', 404), - ('delete', 'can_change_teams', 'teams/{team_id}/invites/2/', 404), - ('post', 'can_change_teams', 'teams/{team_id}/invites/', 400), - ('get', 'can_change_teams', 'teams/{team_id}/tokens/', 200), - ('get', 'can_change_teams', 'teams/{team_id}/tokens/0/', 404), - ('delete', 'can_change_teams', 'teams/{team_id}/tokens/0/', 404), - ('post', 'can_change_teams', 'teams/{team_id}/tokens/', 400), - ('get', 'can_manage_reusable_media', 'reusablemedia/1/', 404), + ('patch', 'organizer.settings.general:write', '', 200), + ('patch', 'organizer.settings.general:write', 'settings/', 200), + ('get', 'organizer.settings.general:write', 'webhooks/', 200), + ('post', 'organizer.settings.general:write', 'webhooks/', 400), + ('get', 'organizer.settings.general:write', 'webhooks/1/', 404), + ('put', 'organizer.settings.general:write', 'webhooks/1/', 404), + ('patch', 'organizer.settings.general:write', 'webhooks/1/', 404), + ('delete', 'organizer.settings.general:write', 'webhooks/1/', 404), + ('get', 'organizer.customers:write', 'customers/', 200), + ('post', 'organizer.customers:write', 'customers/', 201), + ('get', 'organizer.customers:write', 'customers/1/', 404), + ('patch', 'organizer.customers:write', 'customers/1/', 404), + ('post', 'organizer.customers:write', 'customers/1/anonymize/', 404), + ('put', 'organizer.customers:write', 'customers/1/', 404), + ('delete', 'organizer.customers:write', 'customers/1/', 404), + ('get', 'organizer.customers:write', 'memberships/', 200), + ('post', 'organizer.customers:write', 'memberships/', 400), + ('get', 'organizer.customers:write', 'memberships/1/', 404), + ('patch', 'organizer.customers:write', 'memberships/1/', 404), + ('put', 'organizer.customers:write', 'memberships/1/', 404), + ('delete', 'organizer.customers:write', 'memberships/1/', 404), + ('get', 'organizer.settings.general:write', 'saleschannels/', 200), + ('post', 'organizer.settings.general:write', 'saleschannels/', 400), + ('get', 'organizer.settings.general:write', 'saleschannels/web/', 200), + ('patch', 'organizer.settings.general:write', 'saleschannels/web/', 200), + ('put', 'organizer.settings.general:write', 'saleschannels/api.1/', 404), + ('delete', 'organizer.settings.general:write', 'saleschannels/api.1/', 404), + ('get', 'organizer.settings.general:write', 'membershiptypes/', 200), + ('post', 'organizer.settings.general:write', 'membershiptypes/', 400), + ('get', 'organizer.settings.general:write', 'membershiptypes/1/', 404), + ('patch', 'organizer.settings.general:write', 'membershiptypes/1/', 404), + ('put', 'organizer.settings.general:write', 'membershiptypes/1/', 404), + ('delete', 'organizer.settings.general:write', 'membershiptypes/1/', 404), + ('get', 'organizer.giftcards:write', 'giftcards/', 200), + ('post', 'organizer.giftcards:write', 'giftcards/', 400), + ('get', 'organizer.giftcards:write', 'giftcards/1/', 404), + ('put', 'organizer.giftcards:write', 'giftcards/1/', 404), + ('patch', 'organizer.giftcards:write', 'giftcards/1/', 404), + ('get', 'organizer.giftcards:write', 'giftcards/1/transactions/', 404), + ('get', 'organizer.giftcards:write', 'giftcards/1/transactions/1/', 404), + ('get', 'organizer.settings.general:write', 'devices/', 200), + ('post', 'organizer.settings.general:write', 'devices/', 400), + ('get', 'organizer.settings.general:write', 'devices/1/', 404), + ('put', 'organizer.settings.general:write', 'devices/1/', 404), + ('patch', 'organizer.settings.general:write', 'devices/1/', 404), + ('get', 'organizer.teams:write', 'teams/', 200), + ('post', 'organizer.teams:write', 'teams/', 400), + ('get', 'organizer.teams:write', 'teams/{team_id}/', 200), + ('put', 'organizer.teams:write', 'teams/{team_id}/', 400), + ('patch', 'organizer.teams:write', 'teams/{team_id}/', 200), + ('get', 'organizer.teams:write', 'teams/{team_id}/members/', 200), + ('delete', 'organizer.teams:write', 'teams/{team_id}/members/2/', 404), + ('get', 'organizer.teams:write', 'teams/{team_id}/invites/', 200), + ('get', 'organizer.teams:write', 'teams/{team_id}/invites/2/', 404), + ('delete', 'organizer.teams:write', 'teams/{team_id}/invites/2/', 404), + ('post', 'organizer.teams:write', 'teams/{team_id}/invites/', 400), + ('get', 'organizer.teams:write', 'teams/{team_id}/tokens/', 200), + ('get', 'organizer.teams:write', 'teams/{team_id}/tokens/0/', 404), + ('delete', 'organizer.teams:write', 'teams/{team_id}/tokens/0/', 404), + ('post', 'organizer.teams:write', 'teams/{team_id}/tokens/', 400), + ('get', 'organizer.reusablemedia:read', 'reusablemedia/1/', 404), ] event_permission_root_urls = [ - ('post', 'can_create_events', 400), - ('put', 'can_change_event_settings', 400), - ('patch', 'can_change_event_settings', 200), - ('delete', 'can_change_event_settings', 204), + ('post', 'organizer.events:create', 400), + ('put', 'event.settings.general:write', 400), + ('patch', 'event.settings.general:write', 200), + ('delete', 'event.settings.general:write', 204), ] @@ -537,7 +536,7 @@ def test_update_session_activity(user_client, team, organizer, event): @pytest.mark.django_db @pytest.mark.parametrize("urlset", event_permission_sub_urls) def test_device_subresource_permission_check(device_client, device, organizer, event, urlset): - if urlset == ('get', 'can_change_event_settings', 'settings/', 200): + if urlset == ('get', 'event.settings.general:write', 'settings/', 200): return resp = getattr(device_client, urlset[0])('/api/v1/organizers/{}/events/{}/{}'.format( organizer.slug, event.slug, urlset[2])) diff --git a/src/tests/base/test_permissions.py b/src/tests/base/test_permissions.py index cf74044e6..604d4efa1 100644 --- a/src/tests/base/test_permissions.py +++ b/src/tests/base/test_permissions.py @@ -117,52 +117,52 @@ def test_any_event_permission_all(event, user): @pytest.mark.django_db def test_specific_event_permission_limited(event, user): user._teamcache = {} - assert not user.has_event_permission(event.organizer, event, 'can_change_orders') + assert not user.has_event_permission(event.organizer, event, 'event.orders:write') team = Team.objects.create(organizer=event.organizer, limit_event_permissions={"event.orders:write": True}) user._teamcache = {} - assert not user.has_event_permission(event.organizer, event, 'can_change_orders') + assert not user.has_event_permission(event.organizer, event, 'event.orders:write') team.members.add(user) user._teamcache = {} - assert not user.has_event_permission(event.organizer, event, 'can_change_orders') + assert not user.has_event_permission(event.organizer, event, 'event.orders:write') team.limit_events.add(event) user._teamcache = {} - assert user.has_event_permission(event.organizer, event, 'can_change_orders') - assert not user.has_event_permission(event.organizer, event, 'can_change_event_settings') + assert user.has_event_permission(event.organizer, event, 'event.orders:write') + assert not user.has_event_permission(event.organizer, event, 'event.settings.general:write') - assert user.has_event_permission(event.organizer, event, ('can_change_orders', 'can_change_event_settings')) - assert not user.has_event_permission(event.organizer, event, ('can_change_teams', 'can_change_event_settings')) + assert user.has_event_permission(event.organizer, event, ('event.orders:write', 'event.settings.general:write')) + assert not user.has_event_permission(event.organizer, event, ('organizer.teams:write', 'event.settings.general:write')) team.limit_event_permissions = {} team.save() user._teamcache = {} - assert not user.has_event_permission(event.organizer, event, 'can_change_orders') + assert not user.has_event_permission(event.organizer, event, 'event.orders:write') @pytest.mark.django_db def test_specific_event_permission_all(event, user): user._teamcache = {} - assert not user.has_event_permission(event.organizer, event, 'can_change_orders') + assert not user.has_event_permission(event.organizer, event, 'event.orders:write') team = Team.objects.create(organizer=event.organizer, limit_event_permissions={"event.orders:write": True}) user._teamcache = {} - assert not user.has_event_permission(event.organizer, event, 'can_change_orders') + assert not user.has_event_permission(event.organizer, event, 'event.orders:write') team.members.add(user) user._teamcache = {} - assert not user.has_event_permission(event.organizer, event, 'can_change_orders') + assert not user.has_event_permission(event.organizer, event, 'event.orders:write') team.all_events = True team.save() user._teamcache = {} - assert user.has_event_permission(event.organizer, event, 'can_change_orders') + assert user.has_event_permission(event.organizer, event, 'event.orders:write') team.limit_event_permissions = {} team.save() user._teamcache = {} - assert not user.has_event_permission(event.organizer, event, 'can_change_orders') + assert not user.has_event_permission(event.organizer, event, 'event.orders:write') @pytest.mark.django_db @@ -180,12 +180,12 @@ def test_event_permissions_multiple_teams(event, user): team2.limit_events.add(event) team3.limit_events.add(event2) - assert user.has_event_permission(event.organizer, event, 'can_change_orders') - assert user.has_event_permission(event.organizer, event, 'can_change_vouchers') - assert not user.has_event_permission(event.organizer, event, 'can_change_event_settings') - assert user.get_event_permission_set(event.organizer, event) == {'can_change_orders', 'can_change_vouchers'} - assert user.get_event_permission_set(event.organizer, event2) == {'can_change_orders', 'can_change_event_settings', - 'can_change_settings'} + assert user.has_event_permission(event.organizer, event, 'event.orders:write') + assert user.has_event_permission(event.organizer, event, 'event.vouchers:write') + assert not user.has_event_permission(event.organizer, event, 'event.settings.general:write') + assert user.get_event_permission_set(event.organizer, event) == {'event.orders:write', 'event.vouchers:write'} + assert user.get_event_permission_set(event.organizer, event2) == {'event.orders:write', 'event.settings.general:write', + 'event.settings.general:write'} @pytest.mark.django_db @@ -205,16 +205,16 @@ def test_any_organizer_permission(event, user): @pytest.mark.django_db def test_specific_organizer_permission(event, user): user._teamcache = {} - assert not user.has_organizer_permission(event.organizer, 'can_create_events') + assert not user.has_organizer_permission(event.organizer, 'organizer.events:create') team = Team.objects.create(organizer=event.organizer, limit_organizer_permissions={"organizer.events:create": True}) user._teamcache = {} - assert not user.has_organizer_permission(event.organizer, 'can_create_events') + assert not user.has_organizer_permission(event.organizer, 'organizer.events:create') team.members.add(user) user._teamcache = {} - assert user.has_organizer_permission(event.organizer, 'can_create_events') - assert user.has_organizer_permission(event.organizer, ('can_create_events', 'can_change_organizer_settings')) + assert user.has_organizer_permission(event.organizer, 'organizer.events:create') + assert user.has_organizer_permission(event.organizer, ('organizer.events:create', 'organizer.settings.general:write')) @pytest.mark.django_db @@ -227,19 +227,19 @@ def test_organizer_permissions_multiple_teams(event, user): team3 = Team.objects.create(organizer=orga2, limit_organizer_permissions={"organizer.teams:write": True}) team3.members.add(user) - assert user.has_organizer_permission(event.organizer, 'can_create_events') - assert user.has_organizer_permission(event.organizer, 'can_change_organizer_settings') - assert not user.has_organizer_permission(event.organizer, 'can_change_teams') - assert user.get_organizer_permission_set(event.organizer) == {'can_create_events', 'can_change_organizer_settings'} - assert user.get_organizer_permission_set(orga2) == {'can_change_teams'} + assert user.has_organizer_permission(event.organizer, 'organizer.events:create') + assert user.has_organizer_permission(event.organizer, 'organizer.settings.general:write') + assert not user.has_organizer_permission(event.organizer, 'organizer.teams:write') + assert user.get_organizer_permission_set(event.organizer) == {'organizer.events:create', 'organizer.settings.general:write'} + assert user.get_organizer_permission_set(orga2) == {'organizer.teams:write'} @pytest.mark.django_db def test_superuser(event, admin, admin_request): assert admin.has_organizer_permission(event.organizer, request=admin_request) - assert admin.has_organizer_permission(event.organizer, 'can_create_events', request=admin_request) + assert admin.has_organizer_permission(event.organizer, 'organizer.events:create', request=admin_request) assert admin.has_event_permission(event.organizer, event, request=admin_request) - assert admin.has_event_permission(event.organizer, event, 'can_change_event_settings', request=admin_request) + assert admin.has_event_permission(event.organizer, event, 'event.settings.general:write', request=admin_request) assert 'arbitrary' not in admin.get_event_permission_set(event.organizer, event) assert 'arbitrary' not in admin.get_organizer_permission_set(event.organizer) @@ -282,7 +282,7 @@ def test_list_of_events(event, user, admin, admin_request): assert event3 in events assert event4 not in events - events = list(user.get_events_with_permission('can_change_event_settings', request=admin_request)) + events = list(user.get_events_with_permission('event.settings.general:write', request=admin_request)) assert event not in events assert event2 not in events assert event3 in events @@ -293,8 +293,8 @@ def test_list_of_events(event, user, admin, admin_request): assert set(event3.get_users_with_any_permission()) == {user} assert set(event4.get_users_with_any_permission()) == set() - assert set(event.get_users_with_permission('can_change_event_settings')) == set() - assert set(event2.get_users_with_permission('can_change_event_settings')) == set() - assert set(event3.get_users_with_permission('can_change_event_settings')) == {user} - assert set(event4.get_users_with_permission('can_change_event_settings')) == set() - assert set(event.get_users_with_permission('can_change_orders')) == {user} + assert set(event.get_users_with_permission('event.settings.general:write')) == set() + assert set(event2.get_users_with_permission('event.settings.general:write')) == set() + assert set(event3.get_users_with_permission('event.settings.general:write')) == {user} + assert set(event4.get_users_with_permission('event.settings.general:write')) == set() + assert set(event.get_users_with_permission('event.orders:write')) == {user} diff --git a/src/tests/control/test_permissions.py b/src/tests/control/test_permissions.py index 3b3c11fc0..7d2fbd5ac 100644 --- a/src/tests/control/test_permissions.py +++ b/src/tests/control/test_permissions.py @@ -304,115 +304,115 @@ HTTP_POST = "post" HTTP_GET = "get" event_permission_urls = [ - ("can_change_event_settings", "live/", 200, HTTP_GET), - ("can_change_event_settings", "delete/", 200, HTTP_GET), - ("can_change_event_settings", "dangerzone/", 200, HTTP_GET), - ("can_change_event_settings", "settings/", 200, HTTP_GET), - ("can_change_event_settings", "settings/plugins", 200, HTTP_GET), - ("can_change_event_settings", "settings/payment", 200, HTTP_GET), - ("can_change_event_settings", "settings/tickets", 200, HTTP_GET), - ("can_change_event_settings", "settings/email", 200, HTTP_GET), - ("can_change_event_settings", "settings/email/setup", 200, HTTP_GET), - ("can_change_event_settings", "settings/cancel", 200, HTTP_GET), - ("can_change_event_settings", "settings/invoice", 200, HTTP_GET), - ("can_change_event_settings", "settings/widget", 200, HTTP_GET), - ("can_change_event_settings", "settings/invoice/preview", 200, HTTP_GET), - ("can_change_event_settings", "settings/tax/", 200, HTTP_GET), - ("can_change_event_settings", "settings/tax/1/", 404, HTTP_GET), - ("can_change_event_settings", "settings/tax/add", 200, HTTP_GET), - ("can_change_event_settings", "settings/tax/1/delete", 404, HTTP_GET), - ("can_change_event_settings", "settings/tax/1/default", 404, HTTP_POST), - ("can_change_event_settings", "comment/", 405, HTTP_GET), + ("event.settings.general:write", "live/", 200, HTTP_GET), + ("event.settings.general:write", "delete/", 200, HTTP_GET), + ("event.settings.general:write", "dangerzone/", 200, HTTP_GET), + ("event.settings.general:write", "settings/", 200, HTTP_GET), + ("event.settings.general:write", "settings/plugins", 200, HTTP_GET), + ("event.settings.general:write", "settings/payment", 200, HTTP_GET), + ("event.settings.general:write", "settings/tickets", 200, HTTP_GET), + ("event.settings.general:write", "settings/email", 200, HTTP_GET), + ("event.settings.general:write", "settings/email/setup", 200, HTTP_GET), + ("event.settings.general:write", "settings/cancel", 200, HTTP_GET), + ("event.settings.general:write", "settings/invoice", 200, HTTP_GET), + ("event.settings.general:write", "settings/widget", 200, HTTP_GET), + ("event.settings.general:write", "settings/invoice/preview", 200, HTTP_GET), + ("event.settings.general:write", "settings/tax/", 200, HTTP_GET), + ("event.settings.general:write", "settings/tax/1/", 404, HTTP_GET), + ("event.settings.general:write", "settings/tax/add", 200, HTTP_GET), + ("event.settings.general:write", "settings/tax/1/delete", 404, HTTP_GET), + ("event.settings.general:write", "settings/tax/1/default", 404, HTTP_POST), + ("event.settings.general:write", "comment/", 405, HTTP_GET), # Lists are currently not access-controlled - # ("can_change_items", "items/", 200), - ("can_change_items", "items/add", 200, HTTP_GET), - ("can_change_items", "items/1/up", 404, HTTP_POST), - ("can_change_items", "items/1/down", 404, HTTP_POST), - ("can_change_items", "items/reorder/2/", 400, HTTP_POST), - ("can_change_items", "items/1/delete", 404, HTTP_GET), - # ("can_change_items", "categories/", 200), + # ("event.items:write", "items/", 200), + ("event.items:write", "items/add", 200, HTTP_GET), + ("event.items:write", "items/1/up", 404, HTTP_POST), + ("event.items:write", "items/1/down", 404, HTTP_POST), + ("event.items:write", "items/reorder/2/", 400, HTTP_POST), + ("event.items:write", "items/1/delete", 404, HTTP_GET), + # ("event.items:write", "categories/", 200), # We don't have to create categories and similar objects # for testing this, it is enough to test that a 404 error # is returned instead of a 403 one. - ("can_change_items", "categories/2/", 404, HTTP_GET), - ("can_change_items", "categories/2/delete", 404, HTTP_GET), - ("can_change_items", "categories/2/up", 404, HTTP_POST), - ("can_change_items", "categories/2/down", 404, HTTP_POST), - ("can_change_items", "categories/reorder", 400, HTTP_POST), - ("can_change_items", "categories/add", 200, HTTP_GET), - # ("can_change_items", "questions/", 200, HTTP_GET), - ("can_change_items", "questions/2/", 404, HTTP_GET), - ("can_change_items", "questions/2/delete", 404, HTTP_GET), - ("can_change_items", "questions/reorder", 400, HTTP_POST), - ("can_change_items", "questions/add", 200, HTTP_GET), - # ("can_change_items", "quotas/", 200, HTTP_GET), - ("can_change_items", "quotas/2/change", 404, HTTP_GET), - ("can_change_items", "quotas/2/delete", 404, HTTP_GET), - ("can_change_items", "quotas/add", 200, HTTP_GET), - # ("can_change_items", "discounts/", 200), + ("event.items:write", "categories/2/", 404, HTTP_GET), + ("event.items:write", "categories/2/delete", 404, HTTP_GET), + ("event.items:write", "categories/2/up", 404, HTTP_POST), + ("event.items:write", "categories/2/down", 404, HTTP_POST), + ("event.items:write", "categories/reorder", 400, HTTP_POST), + ("event.items:write", "categories/add", 200, HTTP_GET), + # ("event.items:write", "questions/", 200, HTTP_GET), + ("event.items:write", "questions/2/", 404, HTTP_GET), + ("event.items:write", "questions/2/delete", 404, HTTP_GET), + ("event.items:write", "questions/reorder", 400, HTTP_POST), + ("event.items:write", "questions/add", 200, HTTP_GET), + # ("event.items:write", "quotas/", 200, HTTP_GET), + ("event.items:write", "quotas/2/change", 404, HTTP_GET), + ("event.items:write", "quotas/2/delete", 404, HTTP_GET), + ("event.items:write", "quotas/add", 200, HTTP_GET), + # ("event.items:write", "discounts/", 200), # We don't have to create categories and similar objects # for testing this, it is enough to test that a 404 error # is returned instead of a 403 one. - ("can_change_items", "discounts/2/", 404, HTTP_GET), - ("can_change_items", "discounts/2/delete", 404, HTTP_GET), - ("can_change_items", "discounts/2/up", 404, HTTP_POST), - ("can_change_items", "discounts/2/down", 404, HTTP_POST), - ("can_change_items", "discounts/reorder", 400, HTTP_POST), - ("can_change_items", "discounts/add", 200, HTTP_GET), - ("can_change_event_settings", "subevents/", 200, HTTP_GET), - ("can_change_event_settings", "subevents/2/", 404, HTTP_GET), - ("can_change_event_settings", "subevents/2/delete", 404, HTTP_GET), - ("can_change_event_settings", "subevents/add", 200, HTTP_GET), - ("can_view_orders", "orders/overview/", 200, HTTP_GET), - ("can_view_orders", "orders/export/", 200, HTTP_GET), - ("can_view_orders", "orders/export/do", 302, HTTP_POST), - ("can_view_orders", "orders/", 200, HTTP_GET), - ("can_view_orders", "orders/FOO/", 200, HTTP_GET), - ("can_change_orders", "orders/FOO/extend", 200, HTTP_GET), - ("can_change_orders", "orders/FOO/reactivate", 302, HTTP_GET), - ("can_change_orders", "orders/FOO/contact", 200, HTTP_GET), - ("can_change_orders", "orders/FOO/transition", 405, HTTP_GET), - ("can_change_orders", "orders/FOO/checkvatid", 405, HTTP_GET), - ("can_change_orders", "orders/FOO/resend", 405, HTTP_GET), - ("can_change_orders", "orders/FOO/invoice", 405, HTTP_GET), - ("can_change_orders", "orders/FOO/change", 200, HTTP_GET), - ("can_change_orders", "orders/FOO/approve", 200, HTTP_GET), - ("can_change_orders", "orders/FOO/deny", 200, HTTP_GET), - ("can_change_orders", "orders/FOO/delete", 302, HTTP_GET), - ("can_change_orders", "orders/FOO/comment", 405, HTTP_GET), - ("can_change_orders", "orders/FOO/locale", 200, HTTP_GET), - ("can_change_orders", "orders/FOO/sendmail", 200, HTTP_GET), - ("can_change_orders", "orders/FOO/1/sendmail", 404, HTTP_GET), - ("can_change_orders", "orders/import/", 200, HTTP_GET), - ("can_change_orders", "orders/import/0ab7b081-92d3-4480-82de-2f8b056fd32f/", 404, HTTP_GET), - ("can_view_orders", "orders/FOO/answer/5/", 404, HTTP_GET), - ("can_change_orders", "cancel/", 200, HTTP_GET), - ("can_change_vouchers", "vouchers/add", 200, HTTP_GET), - ("can_change_vouchers", "vouchers/bulk_add", 200, HTTP_GET), - ("can_view_vouchers", "vouchers/", 200, HTTP_GET), - ("can_view_vouchers", "vouchers/tags/", 200, HTTP_GET), - ("can_view_vouchers", "vouchers/1234/", 404, HTTP_GET), - ("can_change_vouchers", "vouchers/1234/", 404, HTTP_POST), - ("can_change_vouchers", "vouchers/1234/delete", 404, HTTP_GET), - ("can_view_orders", "waitinglist/", 200, HTTP_GET), - ("can_change_orders", "waitinglist/auto_assign", 405, HTTP_GET), - ("can_change_orders", "waitinglist/action", 405, HTTP_GET), - ("can_view_orders", "checkins/", 200, HTTP_GET), - ("can_view_orders", "checkinlists/", 200, HTTP_GET), - ("can_view_orders", "checkinlists/1/", 404, HTTP_GET), - ("can_change_orders", "checkinlists/1/bulk_action", 404, HTTP_POST), - ("can_checkin_orders", "checkinlists/1/bulk_action", 404, HTTP_POST), - ("can_change_event_settings", "checkinlists/add", 200, HTTP_GET), - ("can_change_event_settings", "checkinlists/1/change", 404, HTTP_GET), - ("can_change_event_settings", "checkinlists/1/delete", 404, HTTP_GET), + ("event.items:write", "discounts/2/", 404, HTTP_GET), + ("event.items:write", "discounts/2/delete", 404, HTTP_GET), + ("event.items:write", "discounts/2/up", 404, HTTP_POST), + ("event.items:write", "discounts/2/down", 404, HTTP_POST), + ("event.items:write", "discounts/reorder", 400, HTTP_POST), + ("event.items:write", "discounts/add", 200, HTTP_GET), + ("event.settings.general:write", "subevents/", 200, HTTP_GET), + ("event.settings.general:write", "subevents/2/", 404, HTTP_GET), + ("event.settings.general:write", "subevents/2/delete", 404, HTTP_GET), + ("event.settings.general:write", "subevents/add", 200, HTTP_GET), + ("event.orders:read", "orders/overview/", 200, HTTP_GET), + ("event.orders:read", "orders/export/", 200, HTTP_GET), + ("event.orders:read", "orders/export/do", 302, HTTP_POST), + ("event.orders:read", "orders/", 200, HTTP_GET), + ("event.orders:read", "orders/FOO/", 200, HTTP_GET), + ("event.orders:write", "orders/FOO/extend", 200, HTTP_GET), + ("event.orders:write", "orders/FOO/reactivate", 302, HTTP_GET), + ("event.orders:write", "orders/FOO/contact", 200, HTTP_GET), + ("event.orders:write", "orders/FOO/transition", 405, HTTP_GET), + ("event.orders:write", "orders/FOO/checkvatid", 405, HTTP_GET), + ("event.orders:write", "orders/FOO/resend", 405, HTTP_GET), + ("event.orders:write", "orders/FOO/invoice", 405, HTTP_GET), + ("event.orders:write", "orders/FOO/change", 200, HTTP_GET), + ("event.orders:write", "orders/FOO/approve", 200, HTTP_GET), + ("event.orders:write", "orders/FOO/deny", 200, HTTP_GET), + ("event.orders:write", "orders/FOO/delete", 302, HTTP_GET), + ("event.orders:write", "orders/FOO/comment", 405, HTTP_GET), + ("event.orders:write", "orders/FOO/locale", 200, HTTP_GET), + ("event.orders:write", "orders/FOO/sendmail", 200, HTTP_GET), + ("event.orders:write", "orders/FOO/1/sendmail", 404, HTTP_GET), + ("event.orders:write", "orders/import/", 200, HTTP_GET), + ("event.orders:write", "orders/import/0ab7b081-92d3-4480-82de-2f8b056fd32f/", 404, HTTP_GET), + ("event.orders:read", "orders/FOO/answer/5/", 404, HTTP_GET), + ("event.orders:write", "cancel/", 200, HTTP_GET), + ("event.vouchers:write", "vouchers/add", 200, HTTP_GET), + ("event.vouchers:write", "vouchers/bulk_add", 200, HTTP_GET), + ("event.vouchers:read", "vouchers/", 200, HTTP_GET), + ("event.vouchers:read", "vouchers/tags/", 200, HTTP_GET), + ("event.vouchers:read", "vouchers/1234/", 404, HTTP_GET), + ("event.vouchers:write", "vouchers/1234/", 404, HTTP_POST), + ("event.vouchers:write", "vouchers/1234/delete", 404, HTTP_GET), + ("event.orders:read", "waitinglist/", 200, HTTP_GET), + ("event.orders:write", "waitinglist/auto_assign", 405, HTTP_GET), + ("event.orders:write", "waitinglist/action", 405, HTTP_GET), + ("event.orders:read", "checkins/", 200, HTTP_GET), + ("event.orders:read", "checkinlists/", 200, HTTP_GET), + ("event.orders:read", "checkinlists/1/", 404, HTTP_GET), + ("event.orders:write", "checkinlists/1/bulk_action", 404, HTTP_POST), + ("event.orders:checkin", "checkinlists/1/bulk_action", 404, HTTP_POST), + ("event.settings.general:write", "checkinlists/add", 200, HTTP_GET), + ("event.settings.general:write", "checkinlists/1/change", 404, HTTP_GET), + ("event.settings.general:write", "checkinlists/1/delete", 404, HTTP_GET), # bank transfer - ("can_change_orders", "banktransfer/import/", 200, HTTP_GET), - ("can_change_orders", "banktransfer/job/1/", 404, HTTP_GET), - ("can_change_orders", "banktransfer/action/", 200, HTTP_GET), - ("can_change_orders", "banktransfer/refunds/", 200, HTTP_GET), - ("can_change_orders", "banktransfer/export/1/", 404, HTTP_GET), - ("can_change_orders", "banktransfer/sepa-export/1/", 404, HTTP_GET), + ("event.orders:write", "banktransfer/import/", 200, HTTP_GET), + ("event.orders:write", "banktransfer/job/1/", 404, HTTP_GET), + ("event.orders:write", "banktransfer/action/", 200, HTTP_GET), + ("event.orders:write", "banktransfer/refunds/", 200, HTTP_GET), + ("event.orders:write", "banktransfer/export/1/", 404, HTTP_GET), + ("event.orders:write", "banktransfer/sepa-export/1/", 404, HTTP_GET), ] @@ -457,14 +457,14 @@ def test_current_permission(client, env): t = Team( pk=2, organizer=env[2], all_events=True ) - setattr(t, 'can_change_event_settings', True) + setattr(t, 'event.settings.general:write', True) t.save() t.members.add(env[1]) client.login(email='dummy@dummy.dummy', password='dummy') response = client.get('/control/event/dummy/dummy/settings/') assert response.status_code == 200 - setattr(t, 'can_change_event_settings', False) + setattr(t, 'event.settings.general:write', False) t.save() response = client.get('/control/event/dummy/dummy/settings/') assert response.status_code == 403 @@ -518,66 +518,66 @@ def test_wrong_organizer(perf_patch, client, env, url): organizer_permission_urls = [ - ("can_change_teams", "organizer/dummy/teams", 200), - ("can_change_teams", "organizer/dummy/team/add", 200), - ("can_change_teams", "organizer/dummy/team/1/", 200), - ("can_change_teams", "organizer/dummy/team/1/edit", 200), - ("can_change_teams", "organizer/dummy/team/1/delete", 200), - ("can_change_organizer_settings", "organizer/dummy/edit", 200), - ("can_change_organizer_settings", "organizer/dummy/settings/plugins", 200), - ("can_change_organizer_settings", "organizer/dummy/settings/plugins/pretix.plugins.sendmail/events", 200), - ("can_change_organizer_settings", "organizer/dummy/settings/email", 200), - ("can_change_organizer_settings", "organizer/dummy/settings/email/setup", 200), - ("can_change_organizer_settings", "organizer/dummy/devices", 200), - ("can_change_organizer_settings", "organizer/dummy/devices/select2", 200), - ("can_change_organizer_settings", "organizer/dummy/device/add", 200), - ("can_change_organizer_settings", "organizer/dummy/device/1/edit", 404), - ("can_change_organizer_settings", "organizer/dummy/device/1/connect", 404), - ("can_change_organizer_settings", "organizer/dummy/device/1/revoke", 404), - ("can_change_organizer_settings", "organizer/dummy/gates", 200), - ("can_change_organizer_settings", "organizer/dummy/gates/select2", 200), - ("can_change_organizer_settings", "organizer/dummy/gate/add", 200), - ("can_change_organizer_settings", "organizer/dummy/gate/1/edit", 404), - ("can_change_organizer_settings", "organizer/dummy/gate/1/delete", 404), - ("can_change_organizer_settings", "organizer/dummy/properties", 200), - ("can_change_organizer_settings", "organizer/dummy/property/add", 200), - ("can_change_organizer_settings", "organizer/dummy/property/1/edit", 404), - ("can_change_organizer_settings", "organizer/dummy/property/1/delete", 404), - ("can_change_organizer_settings", "organizer/dummy/channels", 200), - ("can_change_organizer_settings", "organizer/dummy/channel/add", 200), - ("can_change_organizer_settings", "organizer/dummy/channel/web/edit", 200), - ("can_change_organizer_settings", "organizer/dummy/channel/web/delete", 200), - ("can_change_organizer_settings", "organizer/dummy/membershiptypes", 200), - ("can_change_organizer_settings", "organizer/dummy/membershiptype/add", 200), - ("can_change_organizer_settings", "organizer/dummy/membershiptype/1/edit", 404), - ("can_change_organizer_settings", "organizer/dummy/membershiptype/1/delete", 404), - ("can_change_organizer_settings", "organizer/dummy/ssoproviders", 200), - ("can_change_organizer_settings", "organizer/dummy/ssoprovider/add", 200), - ("can_change_organizer_settings", "organizer/dummy/ssoprovider/1/edit", 404), - ("can_change_organizer_settings", "organizer/dummy/ssoprovider/1/delete", 404), - ("can_manage_customers", "organizer/dummy/customers", 200), - ("can_manage_customers", "organizer/dummy/customer/ABC/edit", 404), - ("can_manage_customers", "organizer/dummy/customer/ABC/anonymize", 404), - ("can_manage_customers", "organizer/dummy/customer/ABC/membership/add", 404), - ("can_manage_customers", "organizer/dummy/customer/ABC/membership/1/edit", 404), - ("can_manage_customers", "organizer/dummy/customer/ABC/", 404), - ("can_manage_reusable_media", "organizer/dummy/reusable_media", 200), - ("can_manage_reusable_media", "organizer/dummy/reusable_media/1/edit", 404), - ("can_manage_reusable_media", "organizer/dummy/reusable_media/1/", 404), - ("can_manage_gift_cards", "organizer/dummy/giftcards", 200), - ("can_manage_gift_cards", "organizer/dummy/giftcard/add", 200), - ("can_manage_gift_cards", "organizer/dummy/giftcard/1/", 404), - ("can_manage_gift_cards", "organizer/dummy/giftcard/1/edit", 404), - ("can_change_organizer_settings", "organizer/dummy/giftcards/acceptance", 200), - ("can_change_organizer_settings", "organizer/dummy/giftcards/acceptance/invite", 200), + ("organizer.teams:write", "organizer/dummy/teams", 200), + ("organizer.teams:write", "organizer/dummy/team/add", 200), + ("organizer.teams:write", "organizer/dummy/team/1/", 200), + ("organizer.teams:write", "organizer/dummy/team/1/edit", 200), + ("organizer.teams:write", "organizer/dummy/team/1/delete", 200), + ("organizer.settings.general:write", "organizer/dummy/edit", 200), + ("organizer.settings.general:write", "organizer/dummy/settings/plugins", 200), + ("organizer.settings.general:write", "organizer/dummy/settings/plugins/pretix.plugins.sendmail/events", 200), + ("organizer.settings.general:write", "organizer/dummy/settings/email", 200), + ("organizer.settings.general:write", "organizer/dummy/settings/email/setup", 200), + ("organizer.settings.general:write", "organizer/dummy/devices", 200), + ("organizer.settings.general:write", "organizer/dummy/devices/select2", 200), + ("organizer.settings.general:write", "organizer/dummy/device/add", 200), + ("organizer.settings.general:write", "organizer/dummy/device/1/edit", 404), + ("organizer.settings.general:write", "organizer/dummy/device/1/connect", 404), + ("organizer.settings.general:write", "organizer/dummy/device/1/revoke", 404), + ("organizer.settings.general:write", "organizer/dummy/gates", 200), + ("organizer.settings.general:write", "organizer/dummy/gates/select2", 200), + ("organizer.settings.general:write", "organizer/dummy/gate/add", 200), + ("organizer.settings.general:write", "organizer/dummy/gate/1/edit", 404), + ("organizer.settings.general:write", "organizer/dummy/gate/1/delete", 404), + ("organizer.settings.general:write", "organizer/dummy/properties", 200), + ("organizer.settings.general:write", "organizer/dummy/property/add", 200), + ("organizer.settings.general:write", "organizer/dummy/property/1/edit", 404), + ("organizer.settings.general:write", "organizer/dummy/property/1/delete", 404), + ("organizer.settings.general:write", "organizer/dummy/channels", 200), + ("organizer.settings.general:write", "organizer/dummy/channel/add", 200), + ("organizer.settings.general:write", "organizer/dummy/channel/web/edit", 200), + ("organizer.settings.general:write", "organizer/dummy/channel/web/delete", 200), + ("organizer.settings.general:write", "organizer/dummy/membershiptypes", 200), + ("organizer.settings.general:write", "organizer/dummy/membershiptype/add", 200), + ("organizer.settings.general:write", "organizer/dummy/membershiptype/1/edit", 404), + ("organizer.settings.general:write", "organizer/dummy/membershiptype/1/delete", 404), + ("organizer.settings.general:write", "organizer/dummy/ssoproviders", 200), + ("organizer.settings.general:write", "organizer/dummy/ssoprovider/add", 200), + ("organizer.settings.general:write", "organizer/dummy/ssoprovider/1/edit", 404), + ("organizer.settings.general:write", "organizer/dummy/ssoprovider/1/delete", 404), + ("organizer.customers:write", "organizer/dummy/customers", 200), + ("organizer.customers:write", "organizer/dummy/customer/ABC/edit", 404), + ("organizer.customers:write", "organizer/dummy/customer/ABC/anonymize", 404), + ("organizer.customers:write", "organizer/dummy/customer/ABC/membership/add", 404), + ("organizer.customers:write", "organizer/dummy/customer/ABC/membership/1/edit", 404), + ("organizer.customers:write", "organizer/dummy/customer/ABC/", 404), + ("organizer.reusablemedia:read", "organizer/dummy/reusable_media", 200), + ("organizer.reusablemedia:write", "organizer/dummy/reusable_media/1/edit", 404), + ("organizer.reusablemedia:read", "organizer/dummy/reusable_media/1/", 404), + ("organizer.giftcards:read", "organizer/dummy/giftcards", 200), + ("organizer.giftcards:write", "organizer/dummy/giftcard/add", 200), + ("organizer.giftcards:read", "organizer/dummy/giftcard/1/", 404), + ("organizer.giftcards:write", "organizer/dummy/giftcard/1/edit", 404), + ("organizer.settings.general:write", "organizer/dummy/giftcards/acceptance", 200), + ("organizer.settings.general:write", "organizer/dummy/giftcards/acceptance/invite", 200), # bank transfer - ("can_change_orders", "organizer/dummy/banktransfer/import/", 200), - ("can_change_orders", "organizer/dummy/banktransfer/job/1/", 404), - ("can_change_orders", "organizer/dummy/banktransfer/action/", 200), - ("can_change_orders", "organizer/dummy/banktransfer/refunds/", 200), - ("can_change_orders", "organizer/dummy/banktransfer/export/1/", 404), - ("can_change_orders", "organizer/dummy/banktransfer/sepa-export/1/", 404), + ("event.orders:write", "organizer/dummy/banktransfer/import/", 200), + ("event.orders:write", "organizer/dummy/banktransfer/job/1/", 404), + ("event.orders:write", "organizer/dummy/banktransfer/action/", 200), + ("event.orders:write", "organizer/dummy/banktransfer/refunds/", 200), + ("event.orders:write", "organizer/dummy/banktransfer/export/1/", 404), + ("event.orders:write", "organizer/dummy/banktransfer/sepa-export/1/", 404), ] diff --git a/src/tests/control/test_teams.py b/src/tests/control/test_teams.py index df5a648f9..1e1da50d2 100644 --- a/src/tests/control/test_teams.py +++ b/src/tests/control/test_teams.py @@ -231,9 +231,9 @@ def test_create_team(event, admin_user, admin_team, client): client.login(email='dummy@dummy.dummy', password='dummy') client.post('/control/organizer/dummy/team/add', { 'name': 'Foo', - 'can_create_events': 'on', + 'organizer.events:create': 'on', 'limit_events': str(event.pk), - 'can_change_event_settings': 'on' + 'event.settings.general:write': 'on' }, follow=True) with scopes_disabled(): t = Team.objects.last() @@ -249,9 +249,9 @@ def test_update_team(event, admin_user, admin_team, client): client.login(email='dummy@dummy.dummy', password='dummy') client.post('/control/organizer/dummy/team/{}/edit'.format(admin_team.pk), { 'name': 'Admin', - 'can_change_teams': 'on', + 'organizer.teams:write': 'on', 'limit_events': str(event.pk), - 'can_change_event_settings': 'on' + 'event.settings.general:write': 'on' }, follow=True) admin_team.refresh_from_db() assert admin_team.can_change_event_settings @@ -265,7 +265,7 @@ def test_update_last_team_to_be_no_admin(event, admin_user, admin_team, client): client.login(email='dummy@dummy.dummy', password='dummy') resp = client.post('/control/organizer/dummy/team/{}/edit'.format(admin_team.pk), { 'name': 'Admin', - 'can_change_event_settings': 'on' + 'event.settings.general:write': 'on' }, follow=True) assert 'alert-danger' in resp.content.decode()