From 0614a9ebc3bd95b85d371c748bfee5d18946e397 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Thu, 2 Apr 2026 15:31:41 +0200 Subject: [PATCH] Use a protocol --- src/pretix/base/exporter.py | 7 +++---- src/pretix/base/models/auth.py | 9 +++++++++ src/pretix/base/models/devices.py | 3 ++- src/pretix/base/models/organizer.py | 3 ++- src/pretix/base/services/export.py | 12 +++--------- 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/pretix/base/exporter.py b/src/pretix/base/exporter.py index 121ee5d51..a89140e0b 100644 --- a/src/pretix/base/exporter.py +++ b/src/pretix/base/exporter.py @@ -47,6 +47,7 @@ from django.utils.formats import localize from django.utils.translation import gettext, gettext_lazy as _ from pretix.base.models import Event +from pretix.base.models.auth import PermissionHolder from pretix.helpers.safe_openpyxl import ( # NOQA: backwards compatibility for plugins using excel_safe SafeWorkbook, remove_invalid_excel_chars as excel_safe, ) @@ -59,7 +60,7 @@ class BaseExporter: This is the base class for all data exporters """ - def __init__(self, event, organizer, user=None, token=None, device=None, progress_callback=lambda v: None): + def __init__(self, event, organizer, permission_holder: PermissionHolder=None, progress_callback=lambda v: None): """ :param event: Event context, can also be a queryset of events for multi-event exports :param organizer: Organizer context @@ -72,9 +73,7 @@ class BaseExporter: self.organizer = organizer self.progress_callback = progress_callback self.is_multievent = isinstance(event, QuerySet) - self.user = user - self.token = token - self.device = device + self.permission_holder = permission_holder if isinstance(event, QuerySet): self.events = event self.event = None diff --git a/src/pretix/base/models/auth.py b/src/pretix/base/models/auth.py index a14f2e4b7..afd7b0435 100644 --- a/src/pretix/base/models/auth.py +++ b/src/pretix/base/models/auth.py @@ -38,6 +38,7 @@ import operator import secrets from datetime import timedelta from functools import reduce +from typing import Protocol from django.conf import settings from django.contrib.auth.models import ( @@ -67,6 +68,14 @@ class EmailAddressTakenError(IntegrityError): pass +class PermissionHolder(Protocol): + def has_event_permission(self, organizer, event, perm_name=None, request=None, session_key=None) -> bool: + ... + + def has_organizer_permission(self, organizer, perm_name=None, request=None): + ... + + class UserManager(BaseUserManager): """ This is the user manager for our custom user model. See the User diff --git a/src/pretix/base/models/devices.py b/src/pretix/base/models/devices.py index a19f8e840..726586e8e 100644 --- a/src/pretix/base/models/devices.py +++ b/src/pretix/base/models/devices.py @@ -229,7 +229,7 @@ class Device(LoggedModel): """ return self._organizer_permission_set() if self.organizer == organizer else set() - def has_event_permission(self, organizer, event, perm_name=None, request=None) -> bool: + def has_event_permission(self, organizer, event, perm_name=None, request=None, session_key=None) -> bool: """ Checks if this token is part of a team that grants access of type ``perm_name`` to the event ``event``. @@ -238,6 +238,7 @@ class Device(LoggedModel): :param event: The event to check :param perm_name: The permission, e.g. ``event.orders:read`` :param request: This parameter is ignored and only defined for compatibility reasons. + :param session_key: This parameter is ignored and only defined for compatibility reasons. :return: bool """ has_event_access = (self.all_events and organizer == self.organizer) or ( diff --git a/src/pretix/base/models/organizer.py b/src/pretix/base/models/organizer.py index 6afc25117..65cff5edf 100644 --- a/src/pretix/base/models/organizer.py +++ b/src/pretix/base/models/organizer.py @@ -556,7 +556,7 @@ class TeamAPIToken(models.Model): """ return self.team.organizer_permission_set() if self.team.organizer == organizer else set() - def has_event_permission(self, organizer, event, perm_name=None, request=None) -> bool: + def has_event_permission(self, organizer, event, perm_name=None, request=None, session_key=None) -> bool: """ Checks if this token is part of a team that grants access of type ``perm_name`` to the event ``event``. @@ -565,6 +565,7 @@ class TeamAPIToken(models.Model): :param event: The event to check :param perm_name: The permission, e.g. ``event.orders:read`` :param request: This parameter is ignored and only defined for compatibility reasons. + :param session_key: This parameter is ignored and only defined for compatibility reasons. :return: bool """ has_event_access = (self.team.all_events and organizer == self.team.organizer) or ( diff --git a/src/pretix/base/services/export.py b/src/pretix/base/services/export.py index 8cb660b58..31ad1b267 100644 --- a/src/pretix/base/services/export.py +++ b/src/pretix/base/services/export.py @@ -214,9 +214,7 @@ def init_event_exporters(event, user=None, token=None, device=None, request=None exporter: BaseExporter = response( event=event, organizer=event.organizer, - user=user, - token=token, - device=device, + permission_holder=token or device or user, **kwargs ) @@ -253,9 +251,7 @@ def init_organizer_exporters( exporter: BaseExporter = response( event=Event.objects.none(), organizer=organizer, - user=user, - token=token, - device=device, + permission_holder=token or device or user, **kwargs, ) @@ -312,9 +308,7 @@ def init_organizer_exporters( exporter: BaseExporter = response( event=_event_list_cache[permission_name], organizer=organizer, - user=user, - token=token, - device=device, + permission_holder=token or device or user, **kwargs, )