diff --git a/src/pretix/base/migrations/0055_organizerpermission_can_change_permissions.py b/src/pretix/base/migrations/0055_organizerpermission_can_change_permissions.py new file mode 100644 index 000000000..3a674b10a --- /dev/null +++ b/src/pretix/base/migrations/0055_organizerpermission_can_change_permissions.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.4 on 2017-01-07 12:37 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('pretixbase', '0054_auto_20170107_1058'), + ] + + operations = [ + migrations.AddField( + model_name='organizerpermission', + name='can_change_permissions', + field=models.BooleanField(default=True, verbose_name='Can change permissions'), + ), + ] diff --git a/src/pretix/base/migrations/0056_auto_20170107_1251.py b/src/pretix/base/migrations/0056_auto_20170107_1251.py new file mode 100644 index 000000000..a36fd87e6 --- /dev/null +++ b/src/pretix/base/migrations/0056_auto_20170107_1251.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.4 on 2017-01-07 12:51 +from __future__ import unicode_literals + +import django.db.models.deletion +from django.conf import settings +from django.db import migrations, models + +import pretix.base.models.organizer + + +class Migration(migrations.Migration): + + dependencies = [ + ('pretixbase', '0055_organizerpermission_can_change_permissions'), + ] + + operations = [ + migrations.AddField( + model_name='organizerpermission', + name='invite_email', + field=models.EmailField(blank=True, max_length=254, null=True), + ), + migrations.AddField( + model_name='organizerpermission', + name='invite_token', + field=models.CharField(blank=True, default=pretix.base.models.organizer.generate_invite_token, max_length=64, null=True), + ), + migrations.AlterField( + model_name='organizerpermission', + name='user', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='organizer_perms', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/src/pretix/base/models/organizer.py b/src/pretix/base/models/organizer.py index baf6fb915..ce7e51995 100644 --- a/src/pretix/base/models/organizer.py +++ b/src/pretix/base/models/organizer.py @@ -1,5 +1,8 @@ +import string + from django.core.validators import RegexValidator from django.db import models +from django.utils.crypto import get_random_string from django.utils.functional import cached_property from django.utils.translation import ugettext_lazy as _ @@ -76,6 +79,10 @@ class Organizer(LoggedModel): return ObjectRelatedCache(self) +def generate_invite_token(): + return get_random_string(length=32, allowed_chars=string.ascii_lowercase + string.digits) + + class OrganizerPermission(models.Model): """ The relation between an Organizer and a User who has permissions to @@ -91,11 +98,17 @@ class OrganizerPermission(models.Model): """ organizer = models.ForeignKey(Organizer, related_name="user_perms", on_delete=models.CASCADE) - user = models.ForeignKey(User, related_name="organizer_perms") + user = models.ForeignKey(User, related_name="organizer_perms", on_delete=models.CASCADE, null=True, blank=True) + invite_email = models.EmailField(null=True, blank=True) + invite_token = models.CharField(default=generate_invite_token, max_length=64, null=True, blank=True) can_create_events = models.BooleanField( default=True, verbose_name=_("Can create events"), ) + can_change_permissions = models.BooleanField( + default=True, + verbose_name=_("Can change permissions"), + ) class Meta: verbose_name = _("Organizer permission") diff --git a/src/pretix/control/middleware.py b/src/pretix/control/middleware.py index fb76dc9ce..adc0e253b 100644 --- a/src/pretix/control/middleware.py +++ b/src/pretix/control/middleware.py @@ -9,7 +9,9 @@ from django.utils.deprecation import MiddlewareMixin from django.utils.encoding import force_str from django.utils.translation import ugettext as _ -from pretix.base.models import Event, EventPermission, Organizer +from pretix.base.models import ( + Event, EventPermission, Organizer, OrganizerPermission, +) class PermissionMiddleware(MiddlewareMixin): @@ -82,6 +84,10 @@ class PermissionMiddleware(MiddlewareMixin): slug=url.kwargs['organizer'], permitted__id__exact=request.user.id, )[0] + request.orgaperm = OrganizerPermission.objects.get( + organizer=request.organizer, + user=request.user + ) except IndexError: raise Http404(_("The selected organizer was not found or you " "have no permission to administrate it.")) diff --git a/src/pretix/control/templates/pretixcontrol/email/invitation_organizer.txt b/src/pretix/control/templates/pretixcontrol/email/invitation_organizer.txt new file mode 100644 index 000000000..77f284740 --- /dev/null +++ b/src/pretix/control/templates/pretixcontrol/email/invitation_organizer.txt @@ -0,0 +1,16 @@ +{% load i18n %}{% blocktrans with url=url|safe %}Hello, + +you have been invited to the team of an event organizer that uses pretix +for their ticket sales. + +Organizer: {{ organizer }} + +If you want to join that team, just click on the following link: +{{ url }} + +If you do not want to join, you can safely ignore or delete this email. + +Best regards, + +Your pretix team +{% endblocktrans %} diff --git a/src/pretix/control/templates/pretixcontrol/organizers/detail.html b/src/pretix/control/templates/pretixcontrol/organizers/detail.html index b2fbf12d3..9b8a7a524 100644 --- a/src/pretix/control/templates/pretixcontrol/organizers/detail.html +++ b/src/pretix/control/templates/pretixcontrol/organizers/detail.html @@ -3,19 +3,131 @@ {% load bootstrap3 %} {% block title %}{% trans "Organizer" %}{% endblock %} {% block content %} -