diff --git a/src/pretix/base/migrations/0002_auto_20150524_1148.py b/src/pretix/base/migrations/0002_auto_20150524_1148.py new file mode 100644 index 0000000000..1654d8cec4 --- /dev/null +++ b/src/pretix/base/migrations/0002_auto_20150524_1148.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import models, migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('pretixbase', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='organizer', + name='slug', + field=models.SlugField(verbose_name='Slug'), + ), + ] diff --git a/src/pretix/base/models.py b/src/pretix/base/models.py index ed6100e5fe..32cef5eecf 100644 --- a/src/pretix/base/models.py +++ b/src/pretix/base/models.py @@ -298,7 +298,7 @@ class Organizer(Versionable): name = models.CharField(max_length=200, verbose_name=_("Name")) slug = models.SlugField(max_length=50, - unique=True, db_index=True, + db_index=True, verbose_name=_("Slug")) permitted = models.ManyToManyField(User, through='OrganizerPermission', related_name="organizers") diff --git a/src/pretix/control/middleware.py b/src/pretix/control/middleware.py index e5aea9e817..2509466b1a 100644 --- a/src/pretix/control/middleware.py +++ b/src/pretix/control/middleware.py @@ -7,7 +7,7 @@ from django.contrib.auth import REDIRECT_FIELD_NAME from django.http import HttpResponseNotFound from django.utils.translation import ugettext as _ -from pretix.base.models import Event +from pretix.base.models import Event, Organizer class PermissionMiddleware: @@ -53,6 +53,16 @@ class PermissionMiddleware: permitted__id__exact=request.user.id, organizer__slug=url.kwargs['organizer'], ).select_related('organizer')[0] + request.organizer = request.event.organizer except IndexError: return HttpResponseNotFound(_("The selected event was not found or you " "have no permission to administrate it.")) + elif 'organizer' in url.kwargs: + try: + request.organizer = Organizer.objects.current.filter( + slug=url.kwargs['organizer'], + permitted__id__exact=request.user.id, + )[0] + except IndexError: + return HttpResponseNotFound(_("The selected organizer was not found or you " + "have no permission to administrate it.")) diff --git a/src/pretix/control/permissions.py b/src/pretix/control/permissions.py index f9df2cd0f9..8a77970011 100644 --- a/src/pretix/control/permissions.py +++ b/src/pretix/control/permissions.py @@ -1,7 +1,7 @@ from django.http import HttpResponseForbidden from django.utils.translation import ugettext as _ -from pretix.base.models import EventPermission +from pretix.base.models import EventPermission, OrganizerPermission def event_permission_required(permission): @@ -14,17 +14,22 @@ def event_permission_required(permission): if not request.user.is_authenticated(): # NOQA # just a double check, should not ever happen return HttpResponseForbidden() - perm = EventPermission.objects.get( - event=request.event, - user=request.user - ) - allowed = False try: - allowed = getattr(perm, permission) - except AttributeError: + perm = EventPermission.objects.get( + event=request.event, + user=request.user + ) + except: pass - if allowed: - return function(request, *args, **kw) + else: + allowed = not permission + try: + if permission: + allowed = getattr(perm, permission) + except AttributeError: + pass + if allowed: + return function(request, *args, **kw) return HttpResponseForbidden(_('You do not have permission to view this content.')) return wrapper return decorator @@ -41,3 +46,47 @@ class EventPermissionRequiredMixin: def as_view(cls, **initkwargs): view = super(EventPermissionRequiredMixin, cls).as_view(**initkwargs) return event_permission_required(cls.permission)(view) + + +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. + """ + def decorator(function): + def wrapper(request, *args, **kw): + if not request.user.is_authenticated(): # NOQA + # just a double check, should not ever happen + return HttpResponseForbidden() + try: + perm = OrganizerPermission.objects.get( + organizer=request.organizer, + user=request.user + ) + except: + pass + else: + allowed = not permission + try: + if permission: + allowed = getattr(perm, permission) + except AttributeError: + pass + if allowed or request.user.is_superuser: + return function(request, *args, **kw) + return HttpResponseForbidden(_('You do not have permission to view this content.')) + return wrapper + return decorator + + +class OrganizerPermissionRequiredMixin: + """ + This mixin is equivalent to the event_permission_required view decorator but + is in a form suitable for class-based views. + """ + permission = '' + + @classmethod + def as_view(cls, **initkwargs): + view = super(OrganizerPermissionRequiredMixin, cls).as_view(**initkwargs) + return organizer_permission_required(cls.permission)(view) diff --git a/src/pretix/control/templates/pretixcontrol/base.html b/src/pretix/control/templates/pretixcontrol/base.html index 062d0598d7..58b6e0d0b0 100644 --- a/src/pretix/control/templates/pretixcontrol/base.html +++ b/src/pretix/control/templates/pretixcontrol/base.html @@ -76,6 +76,12 @@ {% trans "Events" %} +