diff --git a/src/core/models/assemblies.py b/src/core/models/assemblies.py index 8990771ec281287afde06b9e82804aa0fa103c52..d5c6244df38e965d590a3977e98b727ebbfb4950 100644 --- a/src/core/models/assemblies.py +++ b/src/core/models/assemblies.py @@ -85,7 +85,7 @@ class Assembly(TaggedItemMixin, ActivityLogMixin, RulesModel): verbose_name = _('Assembly') verbose_name_plural = _('Assemblies') rules_permissions = { - 'view': is_assembly_member, + 'view': is_assembly_member | has_perms('core.view_assembly', require_staff=True), 'add': is_authenticated, 'change': is_assembly_manager | has_perms('core.change_assembly', require_staff=True), 'delete': is_assembly_manager | has_perms('core.delete_assembly', require_staff=True), diff --git a/src/plainui/views/badges.py b/src/plainui/views/badges.py index dbc254e8b0596f854d073341b9a48adda9ae2fac..83e9bb3ade7ae8cd343c31237e1ac2626e04d095 100644 --- a/src/plainui/views/badges.py +++ b/src/plainui/views/badges.py @@ -24,7 +24,7 @@ from django.views.generic.base import TemplateView from django.views.generic.detail import DetailView from django.views.generic.edit import FormView, UpdateView -from core.models import Assembly, Badge, BadgeToken, UserBadge +from core.models import Badge, BadgeToken, UserBadge from core.models.badges import TokenInvalid from core.models.conference import ConferenceMember from core.views.list_views import FilteredListView @@ -108,6 +108,15 @@ class RedeemTokenDetailView(ConferenceRequiredMixin, DetailView): model = BadgeToken template_name = 'plainui/badges/token_detail.html.j2' context_object_name = 'token' + require_user = True + + def get(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse: + if not BadgeToken.type_is(token := self.get_object()): # pragma: no cover + raise ValueError('Token is not a badge token') + if self.request.user.has_perm('core.view_assembly', token.badge.issuing_assembly): + return super().get(request, *args, **kwargs) + else: + return HttpResponseRedirect(f"{reverse('plainui:manage_badges')}?redeem_token={token.token}") def get_context_data(self, **kwargs: Any) -> dict[str, Any]: # Regenerate the qr code if needed @@ -119,12 +128,6 @@ class RedeemTokenDetailView(ConferenceRequiredMixin, DetailView): 'conf': self.conf, } - def get_queryset(self) -> QuerySet[BadgeToken]: - manageable = Assembly.objects.manageable_by_user(user=self.request.user, conference=self.conf, staff_can_manage=False) - qs = super().get_queryset() - qs = qs.filter(badge__issuing_assembly__in=manageable) - return qs - @method_decorator(ratelimit(group='redeem_badge', key='user', rate=settings.BADGE_RATE_LIMIT), name='dispatch') class RedeemBadgeView(ConferenceRequiredMixin, FormView):