We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Prevent removing the last organiser of an event
… because this is a really bad idea.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/pretalx/orga/views/event.py`
Content:
```
1 from csp.decorators import csp_update
2 from django import forms
3 from django.contrib import messages
4 from django.contrib.auth import login
5 from django.core.exceptions import PermissionDenied
6 from django.db import transaction
7 from django.shortcuts import get_object_or_404, redirect
8 from django.urls import reverse
9 from django.utils.decorators import method_decorator
10 from django.utils.functional import cached_property
11 from django.utils.translation import ugettext_lazy as _
12 from django.views.generic import FormView, TemplateView
13 from rest_framework.authtoken.models import Token
14 
15 from pretalx.common.mixins.views import ActionFromUrl, PermissionRequired
16 from pretalx.common.phrases import phrases
17 from pretalx.common.tasks import regenerate_css
18 from pretalx.common.views import CreateOrUpdateView
19 from pretalx.event.models import Event
20 from pretalx.orga.forms import EventForm, EventSettingsForm
21 from pretalx.orga.forms.event import MailSettingsForm
22 from pretalx.person.forms import LoginInfoForm, OrgaProfileForm, UserForm
23 from pretalx.person.models import EventPermission, User
24 
25 
26 class EventSettingsPermission(PermissionRequired):
27     permission_required = 'orga.change_settings'
28 
29     def get_permission_object(self):
30         return self.request.event
31 
32 
33 class EventDetail(ActionFromUrl, CreateOrUpdateView):
34     model = Event
35     form_class = EventForm
36     write_permission_required = 'orga.change_settings'
37 
38     @cached_property
39     def _action(self):
40         if 'event' not in self.kwargs:
41             return 'create'
42         if self.request.user.has_perm(self.write_permission_required, self.object):
43             return 'edit'
44         return 'view'
45 
46     def get_template_names(self):
47         if self._action == 'create':
48             return 'orga/settings/create_event.html'
49         return 'orga/settings/form.html'
50 
51     def dispatch(self, request, *args, **kwargs):
52         if self._action == 'create':
53             if not request.user.is_anonymous and not request.user.is_administrator:
54                 raise PermissionDenied()
55         else:
56             if not request.user.has_perm('orga.change_settings', self.object):
57                 raise PermissionDenied()
58         return super().dispatch(request, *args, **kwargs)
59 
60     def get_object(self):
61         return self.object
62 
63     @cached_property
64     def object(self):
65         try:
66             return self.request.event
67         except AttributeError:
68             return
69 
70     @cached_property
71     def sform(self):
72         if not hasattr(self.request, 'event') or not self.request.event:
73             return
74         return EventSettingsForm(
75             read_only=(self._action == 'view'),
76             locales=self.request.event.locales,
77             obj=self.request.event,
78             attribute_name='settings',
79             data=self.request.POST if self.request.method == "POST" else None,
80             prefix='settings'
81         )
82 
83     def get_context_data(self, *args, **kwargs):
84         context = super().get_context_data(*args, **kwargs)
85         context['sform'] = self.sform
86         context['url_placeholder'] = f'https://{self.request.host}/'
87         return context
88 
89     def get_success_url(self) -> str:
90         return self.object.orga_urls.settings
91 
92     def form_valid(self, form):
93         new_event = not bool(form.instance.pk)
94         if not new_event:
95             if not self.sform.is_valid():
96                 return self.form_invalid(form)
97 
98         ret = super().form_valid(form)
99 
100         if new_event:
101             url = form.instance.cfp.urls.base
102             messages.success(self.request, _('Yay, a new event! Check these settings and <a href="{url}">configure a CfP</a> and you\'re good to go!').format(url=url))
103             form.instance.log_action('pretalx.event.create', person=self.request.user, orga=True)
104             EventPermission.objects.create(
105                 event=form.instance,
106                 user=self.request.user,
107                 is_orga=True,
108             )
109         else:
110             self.sform.save()
111             form.instance.log_action('pretalx.event.update', person=self.request.user, orga=True)
112             messages.success(self.request, _('The event settings have been saved.'))
113         regenerate_css.apply_async(args=(form.instance.pk,))
114         return ret
115 
116 
117 class EventMailSettings(EventSettingsPermission, ActionFromUrl, FormView):
118     form_class = MailSettingsForm
119     template_name = 'orga/settings/mail.html'
120     write_permission_required = 'orga.change_settings'
121 
122     def get_success_url(self) -> str:
123         return self.request.event.orga_urls.mail_settings
124 
125     def get_form_kwargs(self):
126         kwargs = super().get_form_kwargs()
127         kwargs['obj'] = self.request.event
128         kwargs['attribute_name'] = 'settings'
129         kwargs['locales'] = self.request.event.locales
130         return kwargs
131 
132     def form_valid(self, form):
133         form.save()
134 
135         if self.request.POST.get('test', '0').strip() == '1':
136             backend = self.request.event.get_mail_backend(force_custom=True)
137             try:
138                 backend.test(self.request.event.settings.mail_from)
139             except Exception as e:
140                 messages.warning(self.request, _('An error occured while contacting the SMTP server: %s') % str(e))
141                 return redirect(self.request.event.orga_urls.mail_settings)
142             else:
143                 if form.cleaned_data.get('smtp_use_custom'):
144                     messages.success(self.request, _('Yay, your changes have been saved and the connection attempt to '
145                                                      'your SMTP server was successful.'))
146                 else:
147                     messages.success(self.request, _('We\'ve been able to contact the SMTP server you configured. '
148                                                      'Remember to check the "use custom SMTP server" checkbox, '
149                                                      'otherwise your SMTP server will not be used.'))
150         else:
151             messages.success(self.request, _('Yay! We saved your changes.'))
152 
153         ret = super().form_valid(form)
154         return ret
155 
156 
157 @method_decorator(csp_update(SCRIPT_SRC="'self' 'unsafe-inline'"), name='get')
158 class EventTeam(EventSettingsPermission, TemplateView):
159     template_name = 'orga/settings/team.html'
160 
161     @cached_property
162     def formset(self):
163         formset_class = forms.inlineformset_factory(
164             Event, EventPermission, can_delete=True, extra=0,
165             fields=[
166                 'is_orga',
167                 'is_reviewer',
168                 'review_override_count',
169                 'invitation_email',
170             ],
171         )
172         return formset_class(
173             self.request.POST if self.request.method == 'POST' else None,
174             queryset=EventPermission.objects.filter(event=self.request.event),
175             instance=self.request.event,
176         )
177 
178     def get_context_data(self, *args, **kwargs):
179         ctx = super().get_context_data(*args, **kwargs)
180         ctx['formset'] = self.formset
181         return ctx
182 
183     @classmethod
184     def _find_user(cls, email):
185         from pretalx.person.models import User
186         return User.objects.filter(nick=email).first() or User.objects.filter(email=email).first()
187 
188     @transaction.atomic
189     def post(self, request, *args, **kwargs):
190         if not self.formset.is_valid():
191             messages.error(request, phrases.base.error_saving_changes)
192             return redirect(self.request.event.orga_urls.team_settings)
193         permissions = self.formset.save(commit=False)
194         mails = []
195 
196         for permission in self.formset.deleted_objects:
197             permission.delete()
198 
199         for permission in permissions:
200             if permission.invitation_email:
201                 user = self._find_user(permission.invitation_email)
202 
203                 if user:
204                     permission.user = user
205                     permission.invitation_email = None
206                     permission.invitation_token = None
207                 mails.append(permission.send_invite_email())
208                 request.event.log_action('pretalx.invite.orga.send', person=request.user, orga=True)
209                 messages.success(
210                     request,
211                     _('<{email}> has been invited to your team - more team members help distribute the workload, so … yay!').format(email=permission.invitation_email)
212                 )
213 
214             permission.save()
215 
216         for permission in permissions:
217             if permission.user:
218                 EventPermission.objects \
219                     .filter(event=permission.event, user=permission.user) \
220                     .exclude(id=permission.id) \
221                     .delete()
222 
223         for mail in mails:
224             mail.send()
225 
226         return redirect(self.request.event.orga_urls.team_settings)
227 
228 
229 @method_decorator(csp_update(SCRIPT_SRC="'self' 'unsafe-inline'"), name='dispatch')
230 class InvitationView(FormView):
231     template_name = 'orga/invitation.html'
232     form_class = UserForm
233 
234     @cached_property
235     def object(self):
236         return get_object_or_404(
237             EventPermission,
238             invitation_token__iexact=self.kwargs.get('code'),
239             user__isnull=True,
240         )
241 
242     def get_context_data(self, *args, **kwargs):
243         ctx = super().get_context_data(*args, **kwargs)
244         ctx['invitation'] = self.object
245         return ctx
246 
247     def form_valid(self, form):
248         form.save()
249         permission = self.object
250         user = User.objects.filter(pk=form.cleaned_data.get('user_id')).first()
251         if not user:
252             messages.error(self.request, _('There was a problem with your authentication. Please contact the organiser for further help.'))
253             return redirect(self.request.event.urls.base)
254 
255         perm = EventPermission.objects.filter(user=user, event=permission.event).exclude(pk=permission.pk).first()
256         event = permission.event
257 
258         if perm:
259             if permission.is_orga:
260                 perm.is_orga = True
261             if permission.is_reviewer:
262                 perm.is_reviewer = True
263             perm.save()
264             permission.delete()
265             permission = perm
266 
267         permission.user = user
268         permission.save()
269         permission.event.log_action('pretalx.invite.orga.accept', person=user, orga=True)
270         messages.info(self.request, _('You are now part of the event team!'))
271 
272         login(self.request, user, backend='django.contrib.auth.backends.ModelBackend')
273         return redirect(event.orga_urls.base)
274 
275 
276 @method_decorator(csp_update(SCRIPT_SRC="'self' 'unsafe-inline'"), name='dispatch')
277 class UserSettings(TemplateView):
278     form_class = LoginInfoForm
279     template_name = 'orga/user.html'
280 
281     def get_success_url(self) -> str:
282         return reverse('orga:user.view')
283 
284     @cached_property
285     def login_form(self):
286         bind = self.request.method == 'POST' and self.request.POST.get('action') == 'login'
287         return LoginInfoForm(
288             user=self.request.user,
289             data=self.request.POST if bind else None
290         )
291 
292     @cached_property
293     def profile_form(self):
294         bind = self.request.method == 'POST' and self.request.POST.get('action') == 'profile'
295         return OrgaProfileForm(
296             instance=self.request.user,
297             data=self.request.POST if bind else None
298         )
299 
300     def get_context_data(self, **kwargs):
301         ctx = super().get_context_data(**kwargs)
302         ctx['token'] = Token.objects.filter(user=self.request.user).first() or Token.objects.create(user=self.request.user)
303         ctx['login_form'] = self.login_form
304         ctx['profile_form'] = self.profile_form
305         return ctx
306 
307     def post(self, request, *args, **kwargs):
308         if self.login_form.is_bound and self.login_form.is_valid():
309             self.login_form.save()
310             messages.success(request, _('Your changes have been saved.'))
311             request.user.log_action('pretalx.user.password.update')
312         elif self.profile_form.is_bound and self.profile_form.is_valid():
313             self.profile_form.save()
314             messages.success(request, _('Your changes have been saved.'))
315             request.user.log_action('pretalx.user.profile.update')
316         elif request.POST.get('form') == 'token':
317             request.user.regenerate_token()
318             messages.success(request, _('Your API token has been regenerated. The previous token will not be usable any longer.'))
319         else:
320             messages.error(self.request, _('Oh :( We had trouble saving your input. See below for details.'))
321         return redirect(self.get_success_url())
322
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/pretalx/orga/views/event.py b/src/pretalx/orga/views/event.py
--- a/src/pretalx/orga/views/event.py
+++ b/src/pretalx/orga/views/event.py
@@ -185,6 +185,16 @@
         from pretalx.person.models import User
         return User.objects.filter(nick=email).first() or User.objects.filter(email=email).first()
 
+    def _count_orga_permissions(self, permissions):
+        return len([p for p in permissions if p.is_orga])
+
+    def has_remaining_team(self):
+        return (
+            self._count_orga_permissions(self.formset.new_objects)
+            + self._count_orga_permissions(self.formset.changed_objects)
+            - self._count_orga_permissions(self.formset.deleted_objects)
+        ) > 0
+
     @transaction.atomic
     def post(self, request, *args, **kwargs):
         if not self.formset.is_valid():
@@ -193,6 +203,10 @@
         permissions = self.formset.save(commit=False)
         mails = []
 
+        if not self.has_remaining_team():
+            messages.error(request, _("That would be a pretty lonely event. You can't remove the last remaining team member."))
+            return redirect(self.request.event.orga_urls.team_settings)
+
         for permission in self.formset.deleted_objects:
             permission.delete()

{"golden_diff": "diff --git a/src/pretalx/orga/views/event.py b/src/pretalx/orga/views/event.py\n--- a/src/pretalx/orga/views/event.py\n+++ b/src/pretalx/orga/views/event.py\n@@ -185,6 +185,16 @@\n         from pretalx.person.models import User\n         return User.objects.filter(nick=email).first() or User.objects.filter(email=email).first()\n \n+    def _count_orga_permissions(self, permissions):\n+        return len([p for p in permissions if p.is_orga])\n+\n+    def has_remaining_team(self):\n+        return (\n+            self._count_orga_permissions(self.formset.new_objects)\n+            + self._count_orga_permissions(self.formset.changed_objects)\n+            - self._count_orga_permissions(self.formset.deleted_objects)\n+        ) > 0\n+\n     @transaction.atomic\n     def post(self, request, *args, **kwargs):\n         if not self.formset.is_valid():\n@@ -193,6 +203,10 @@\n         permissions = self.formset.save(commit=False)\n         mails = []\n \n+        if not self.has_remaining_team():\n+            messages.error(request, _(\"That would be a pretty lonely event. You can't remove the last remaining team member.\"))\n+            return redirect(self.request.event.orga_urls.team_settings)\n+\n         for permission in self.formset.deleted_objects:\n             permission.delete()\n", "issue": "Prevent removing the last organiser of an event\n\u2026 because this is a really bad idea.\n", "before_files": [{"content": "from csp.decorators import csp_update\nfrom django import forms\nfrom django.contrib import messages\nfrom django.contrib.auth import login\nfrom django.core.exceptions import PermissionDenied\nfrom django.db import transaction\nfrom django.shortcuts import get_object_or_404, redirect\nfrom django.urls import reverse\nfrom django.utils.decorators import method_decorator\nfrom django.utils.functional import cached_property\nfrom django.utils.translation import ugettext_lazy as _\nfrom django.views.generic import FormView, TemplateView\nfrom rest_framework.authtoken.models import Token\n\nfrom pretalx.common.mixins.views import ActionFromUrl, PermissionRequired\nfrom pretalx.common.phrases import phrases\nfrom pretalx.common.tasks import regenerate_css\nfrom pretalx.common.views import CreateOrUpdateView\nfrom pretalx.event.models import Event\nfrom pretalx.orga.forms import EventForm, EventSettingsForm\nfrom pretalx.orga.forms.event import MailSettingsForm\nfrom pretalx.person.forms import LoginInfoForm, OrgaProfileForm, UserForm\nfrom pretalx.person.models import EventPermission, User\n\n\nclass EventSettingsPermission(PermissionRequired):\n    permission_required = 'orga.change_settings'\n\n    def get_permission_object(self):\n        return self.request.event\n\n\nclass EventDetail(ActionFromUrl, CreateOrUpdateView):\n    model = Event\n    form_class = EventForm\n    write_permission_required = 'orga.change_settings'\n\n    @cached_property\n    def _action(self):\n        if 'event' not in self.kwargs:\n            return 'create'\n        if self.request.user.has_perm(self.write_permission_required, self.object):\n            return 'edit'\n        return 'view'\n\n    def get_template_names(self):\n        if self._action == 'create':\n            return 'orga/settings/create_event.html'\n        return 'orga/settings/form.html'\n\n    def dispatch(self, request, *args, **kwargs):\n        if self._action == 'create':\n            if not request.user.is_anonymous and not request.user.is_administrator:\n                raise PermissionDenied()\n        else:\n            if not request.user.has_perm('orga.change_settings', self.object):\n                raise PermissionDenied()\n        return super().dispatch(request, *args, **kwargs)\n\n    def get_object(self):\n        return self.object\n\n    @cached_property\n    def object(self):\n        try:\n            return self.request.event\n        except AttributeError:\n            return\n\n    @cached_property\n    def sform(self):\n        if not hasattr(self.request, 'event') or not self.request.event:\n            return\n        return EventSettingsForm(\n            read_only=(self._action == 'view'),\n            locales=self.request.event.locales,\n            obj=self.request.event,\n            attribute_name='settings',\n            data=self.request.POST if self.request.method == \"POST\" else None,\n            prefix='settings'\n        )\n\n    def get_context_data(self, *args, **kwargs):\n        context = super().get_context_data(*args, **kwargs)\n        context['sform'] = self.sform\n        context['url_placeholder'] = f'https://{self.request.host}/'\n        return context\n\n    def get_success_url(self) -> str:\n        return self.object.orga_urls.settings\n\n    def form_valid(self, form):\n        new_event = not bool(form.instance.pk)\n        if not new_event:\n            if not self.sform.is_valid():\n                return self.form_invalid(form)\n\n        ret = super().form_valid(form)\n\n        if new_event:\n            url = form.instance.cfp.urls.base\n            messages.success(self.request, _('Yay, a new event! Check these settings and <a href=\"{url}\">configure a CfP</a> and you\\'re good to go!').format(url=url))\n            form.instance.log_action('pretalx.event.create', person=self.request.user, orga=True)\n            EventPermission.objects.create(\n                event=form.instance,\n                user=self.request.user,\n                is_orga=True,\n            )\n        else:\n            self.sform.save()\n            form.instance.log_action('pretalx.event.update', person=self.request.user, orga=True)\n            messages.success(self.request, _('The event settings have been saved.'))\n        regenerate_css.apply_async(args=(form.instance.pk,))\n        return ret\n\n\nclass EventMailSettings(EventSettingsPermission, ActionFromUrl, FormView):\n    form_class = MailSettingsForm\n    template_name = 'orga/settings/mail.html'\n    write_permission_required = 'orga.change_settings'\n\n    def get_success_url(self) -> str:\n        return self.request.event.orga_urls.mail_settings\n\n    def get_form_kwargs(self):\n        kwargs = super().get_form_kwargs()\n        kwargs['obj'] = self.request.event\n        kwargs['attribute_name'] = 'settings'\n        kwargs['locales'] = self.request.event.locales\n        return kwargs\n\n    def form_valid(self, form):\n        form.save()\n\n        if self.request.POST.get('test', '0').strip() == '1':\n            backend = self.request.event.get_mail_backend(force_custom=True)\n            try:\n                backend.test(self.request.event.settings.mail_from)\n            except Exception as e:\n                messages.warning(self.request, _('An error occured while contacting the SMTP server: %s') % str(e))\n                return redirect(self.request.event.orga_urls.mail_settings)\n            else:\n                if form.cleaned_data.get('smtp_use_custom'):\n                    messages.success(self.request, _('Yay, your changes have been saved and the connection attempt to '\n                                                     'your SMTP server was successful.'))\n                else:\n                    messages.success(self.request, _('We\\'ve been able to contact the SMTP server you configured. '\n                                                     'Remember to check the \"use custom SMTP server\" checkbox, '\n                                                     'otherwise your SMTP server will not be used.'))\n        else:\n            messages.success(self.request, _('Yay! We saved your changes.'))\n\n        ret = super().form_valid(form)\n        return ret\n\n\n@method_decorator(csp_update(SCRIPT_SRC=\"'self' 'unsafe-inline'\"), name='get')\nclass EventTeam(EventSettingsPermission, TemplateView):\n    template_name = 'orga/settings/team.html'\n\n    @cached_property\n    def formset(self):\n        formset_class = forms.inlineformset_factory(\n            Event, EventPermission, can_delete=True, extra=0,\n            fields=[\n                'is_orga',\n                'is_reviewer',\n                'review_override_count',\n                'invitation_email',\n            ],\n        )\n        return formset_class(\n            self.request.POST if self.request.method == 'POST' else None,\n            queryset=EventPermission.objects.filter(event=self.request.event),\n            instance=self.request.event,\n        )\n\n    def get_context_data(self, *args, **kwargs):\n        ctx = super().get_context_data(*args, **kwargs)\n        ctx['formset'] = self.formset\n        return ctx\n\n    @classmethod\n    def _find_user(cls, email):\n        from pretalx.person.models import User\n        return User.objects.filter(nick=email).first() or User.objects.filter(email=email).first()\n\n    @transaction.atomic\n    def post(self, request, *args, **kwargs):\n        if not self.formset.is_valid():\n            messages.error(request, phrases.base.error_saving_changes)\n            return redirect(self.request.event.orga_urls.team_settings)\n        permissions = self.formset.save(commit=False)\n        mails = []\n\n        for permission in self.formset.deleted_objects:\n            permission.delete()\n\n        for permission in permissions:\n            if permission.invitation_email:\n                user = self._find_user(permission.invitation_email)\n\n                if user:\n                    permission.user = user\n                    permission.invitation_email = None\n                    permission.invitation_token = None\n                mails.append(permission.send_invite_email())\n                request.event.log_action('pretalx.invite.orga.send', person=request.user, orga=True)\n                messages.success(\n                    request,\n                    _('<{email}> has been invited to your team - more team members help distribute the workload, so \u2026 yay!').format(email=permission.invitation_email)\n                )\n\n            permission.save()\n\n        for permission in permissions:\n            if permission.user:\n                EventPermission.objects \\\n                    .filter(event=permission.event, user=permission.user) \\\n                    .exclude(id=permission.id) \\\n                    .delete()\n\n        for mail in mails:\n            mail.send()\n\n        return redirect(self.request.event.orga_urls.team_settings)\n\n\n@method_decorator(csp_update(SCRIPT_SRC=\"'self' 'unsafe-inline'\"), name='dispatch')\nclass InvitationView(FormView):\n    template_name = 'orga/invitation.html'\n    form_class = UserForm\n\n    @cached_property\n    def object(self):\n        return get_object_or_404(\n            EventPermission,\n            invitation_token__iexact=self.kwargs.get('code'),\n            user__isnull=True,\n        )\n\n    def get_context_data(self, *args, **kwargs):\n        ctx = super().get_context_data(*args, **kwargs)\n        ctx['invitation'] = self.object\n        return ctx\n\n    def form_valid(self, form):\n        form.save()\n        permission = self.object\n        user = User.objects.filter(pk=form.cleaned_data.get('user_id')).first()\n        if not user:\n            messages.error(self.request, _('There was a problem with your authentication. Please contact the organiser for further help.'))\n            return redirect(self.request.event.urls.base)\n\n        perm = EventPermission.objects.filter(user=user, event=permission.event).exclude(pk=permission.pk).first()\n        event = permission.event\n\n        if perm:\n            if permission.is_orga:\n                perm.is_orga = True\n            if permission.is_reviewer:\n                perm.is_reviewer = True\n            perm.save()\n            permission.delete()\n            permission = perm\n\n        permission.user = user\n        permission.save()\n        permission.event.log_action('pretalx.invite.orga.accept', person=user, orga=True)\n        messages.info(self.request, _('You are now part of the event team!'))\n\n        login(self.request, user, backend='django.contrib.auth.backends.ModelBackend')\n        return redirect(event.orga_urls.base)\n\n\n@method_decorator(csp_update(SCRIPT_SRC=\"'self' 'unsafe-inline'\"), name='dispatch')\nclass UserSettings(TemplateView):\n    form_class = LoginInfoForm\n    template_name = 'orga/user.html'\n\n    def get_success_url(self) -> str:\n        return reverse('orga:user.view')\n\n    @cached_property\n    def login_form(self):\n        bind = self.request.method == 'POST' and self.request.POST.get('action') == 'login'\n        return LoginInfoForm(\n            user=self.request.user,\n            data=self.request.POST if bind else None\n        )\n\n    @cached_property\n    def profile_form(self):\n        bind = self.request.method == 'POST' and self.request.POST.get('action') == 'profile'\n        return OrgaProfileForm(\n            instance=self.request.user,\n            data=self.request.POST if bind else None\n        )\n\n    def get_context_data(self, **kwargs):\n        ctx = super().get_context_data(**kwargs)\n        ctx['token'] = Token.objects.filter(user=self.request.user).first() or Token.objects.create(user=self.request.user)\n        ctx['login_form'] = self.login_form\n        ctx['profile_form'] = self.profile_form\n        return ctx\n\n    def post(self, request, *args, **kwargs):\n        if self.login_form.is_bound and self.login_form.is_valid():\n            self.login_form.save()\n            messages.success(request, _('Your changes have been saved.'))\n            request.user.log_action('pretalx.user.password.update')\n        elif self.profile_form.is_bound and self.profile_form.is_valid():\n            self.profile_form.save()\n            messages.success(request, _('Your changes have been saved.'))\n            request.user.log_action('pretalx.user.profile.update')\n        elif request.POST.get('form') == 'token':\n            request.user.regenerate_token()\n            messages.success(request, _('Your API token has been regenerated. The previous token will not be usable any longer.'))\n        else:\n            messages.error(self.request, _('Oh :( We had trouble saving your input. See below for details.'))\n        return redirect(self.get_success_url())\n", "path": "src/pretalx/orga/views/event.py"}], "after_files": [{"content": "from csp.decorators import csp_update\nfrom django import forms\nfrom django.contrib import messages\nfrom django.contrib.auth import login\nfrom django.core.exceptions import PermissionDenied\nfrom django.db import transaction\nfrom django.shortcuts import get_object_or_404, redirect\nfrom django.urls import reverse\nfrom django.utils.decorators import method_decorator\nfrom django.utils.functional import cached_property\nfrom django.utils.translation import ugettext_lazy as _\nfrom django.views.generic import FormView, TemplateView\nfrom rest_framework.authtoken.models import Token\n\nfrom pretalx.common.mixins.views import ActionFromUrl, PermissionRequired\nfrom pretalx.common.phrases import phrases\nfrom pretalx.common.tasks import regenerate_css\nfrom pretalx.common.views import CreateOrUpdateView\nfrom pretalx.event.models import Event\nfrom pretalx.orga.forms import EventForm, EventSettingsForm\nfrom pretalx.orga.forms.event import MailSettingsForm\nfrom pretalx.person.forms import LoginInfoForm, OrgaProfileForm, UserForm\nfrom pretalx.person.models import EventPermission, User\n\n\nclass EventSettingsPermission(PermissionRequired):\n    permission_required = 'orga.change_settings'\n\n    def get_permission_object(self):\n        return self.request.event\n\n\nclass EventDetail(ActionFromUrl, CreateOrUpdateView):\n    model = Event\n    form_class = EventForm\n    write_permission_required = 'orga.change_settings'\n\n    @cached_property\n    def _action(self):\n        if 'event' not in self.kwargs:\n            return 'create'\n        if self.request.user.has_perm(self.write_permission_required, self.object):\n            return 'edit'\n        return 'view'\n\n    def get_template_names(self):\n        if self._action == 'create':\n            return 'orga/settings/create_event.html'\n        return 'orga/settings/form.html'\n\n    def dispatch(self, request, *args, **kwargs):\n        if self._action == 'create':\n            if not request.user.is_anonymous and not request.user.is_administrator:\n                raise PermissionDenied()\n        else:\n            if not request.user.has_perm('orga.change_settings', self.object):\n                raise PermissionDenied()\n        return super().dispatch(request, *args, **kwargs)\n\n    def get_object(self):\n        return self.object\n\n    @cached_property\n    def object(self):\n        try:\n            return self.request.event\n        except AttributeError:\n            return\n\n    @cached_property\n    def sform(self):\n        if not hasattr(self.request, 'event') or not self.request.event:\n            return\n        return EventSettingsForm(\n            read_only=(self._action == 'view'),\n            locales=self.request.event.locales,\n            obj=self.request.event,\n            attribute_name='settings',\n            data=self.request.POST if self.request.method == \"POST\" else None,\n            prefix='settings'\n        )\n\n    def get_context_data(self, *args, **kwargs):\n        context = super().get_context_data(*args, **kwargs)\n        context['sform'] = self.sform\n        context['url_placeholder'] = f'https://{self.request.host}/'\n        return context\n\n    def get_success_url(self) -> str:\n        return self.object.orga_urls.settings\n\n    def form_valid(self, form):\n        new_event = not bool(form.instance.pk)\n        if not new_event:\n            if not self.sform.is_valid():\n                return self.form_invalid(form)\n\n        ret = super().form_valid(form)\n\n        if new_event:\n            url = form.instance.cfp.urls.base\n            messages.success(self.request, _('Yay, a new event! Check these settings and <a href=\"{url}\">configure a CfP</a> and you\\'re good to go!').format(url=url))\n            form.instance.log_action('pretalx.event.create', person=self.request.user, orga=True)\n            EventPermission.objects.create(\n                event=form.instance,\n                user=self.request.user,\n                is_orga=True,\n            )\n        else:\n            self.sform.save()\n            form.instance.log_action('pretalx.event.update', person=self.request.user, orga=True)\n            messages.success(self.request, _('The event settings have been saved.'))\n        regenerate_css.apply_async(args=(form.instance.pk,))\n        return ret\n\n\nclass EventMailSettings(EventSettingsPermission, ActionFromUrl, FormView):\n    form_class = MailSettingsForm\n    template_name = 'orga/settings/mail.html'\n    write_permission_required = 'orga.change_settings'\n\n    def get_success_url(self) -> str:\n        return self.request.event.orga_urls.mail_settings\n\n    def get_form_kwargs(self):\n        kwargs = super().get_form_kwargs()\n        kwargs['obj'] = self.request.event\n        kwargs['attribute_name'] = 'settings'\n        kwargs['locales'] = self.request.event.locales\n        return kwargs\n\n    def form_valid(self, form):\n        form.save()\n\n        if self.request.POST.get('test', '0').strip() == '1':\n            backend = self.request.event.get_mail_backend(force_custom=True)\n            try:\n                backend.test(self.request.event.settings.mail_from)\n            except Exception as e:\n                messages.warning(self.request, _('An error occured while contacting the SMTP server: %s') % str(e))\n                return redirect(self.request.event.orga_urls.mail_settings)\n            else:\n                if form.cleaned_data.get('smtp_use_custom'):\n                    messages.success(self.request, _('Yay, your changes have been saved and the connection attempt to '\n                                                     'your SMTP server was successful.'))\n                else:\n                    messages.success(self.request, _('We\\'ve been able to contact the SMTP server you configured. '\n                                                     'Remember to check the \"use custom SMTP server\" checkbox, '\n                                                     'otherwise your SMTP server will not be used.'))\n        else:\n            messages.success(self.request, _('Yay! We saved your changes.'))\n\n        ret = super().form_valid(form)\n        return ret\n\n\n@method_decorator(csp_update(SCRIPT_SRC=\"'self' 'unsafe-inline'\"), name='get')\nclass EventTeam(EventSettingsPermission, TemplateView):\n    template_name = 'orga/settings/team.html'\n\n    @cached_property\n    def formset(self):\n        formset_class = forms.inlineformset_factory(\n            Event, EventPermission, can_delete=True, extra=0,\n            fields=[\n                'is_orga',\n                'is_reviewer',\n                'review_override_count',\n                'invitation_email',\n            ],\n        )\n        return formset_class(\n            self.request.POST if self.request.method == 'POST' else None,\n            queryset=EventPermission.objects.filter(event=self.request.event),\n            instance=self.request.event,\n        )\n\n    def get_context_data(self, *args, **kwargs):\n        ctx = super().get_context_data(*args, **kwargs)\n        ctx['formset'] = self.formset\n        return ctx\n\n    @classmethod\n    def _find_user(cls, email):\n        from pretalx.person.models import User\n        return User.objects.filter(nick=email).first() or User.objects.filter(email=email).first()\n\n    def _count_orga_permissions(self, permissions):\n        return len([p for p in permissions if p.is_orga])\n\n    def has_remaining_team(self):\n        return (\n            self._count_orga_permissions(self.formset.new_objects)\n            + self._count_orga_permissions(self.formset.changed_objects)\n            - self._count_orga_permissions(self.formset.deleted_objects)\n        ) > 0\n\n    @transaction.atomic\n    def post(self, request, *args, **kwargs):\n        if not self.formset.is_valid():\n            messages.error(request, phrases.base.error_saving_changes)\n            return redirect(self.request.event.orga_urls.team_settings)\n        permissions = self.formset.save(commit=False)\n        mails = []\n\n        if not self.has_remaining_team():\n            messages.error(request, _(\"That would be a pretty lonely event. You can't remove the last remaining team member.\"))\n            return redirect(self.request.event.orga_urls.team_settings)\n\n        for permission in self.formset.deleted_objects:\n            permission.delete()\n\n        for permission in permissions:\n            if permission.invitation_email:\n                user = self._find_user(permission.invitation_email)\n\n                if user:\n                    permission.user = user\n                    permission.invitation_email = None\n                    permission.invitation_token = None\n                mails.append(permission.send_invite_email())\n                request.event.log_action('pretalx.invite.orga.send', person=request.user, orga=True)\n                messages.success(\n                    request,\n                    _('<{email}> has been invited to your team - more team members help distribute the workload, so \u2026 yay!').format(email=permission.invitation_email)\n                )\n\n            permission.save()\n\n        for permission in permissions:\n            if permission.user:\n                EventPermission.objects \\\n                    .filter(event=permission.event, user=permission.user) \\\n                    .exclude(id=permission.id) \\\n                    .delete()\n\n        for mail in mails:\n            mail.send()\n\n        return redirect(self.request.event.orga_urls.team_settings)\n\n\n@method_decorator(csp_update(SCRIPT_SRC=\"'self' 'unsafe-inline'\"), name='dispatch')\nclass InvitationView(FormView):\n    template_name = 'orga/invitation.html'\n    form_class = UserForm\n\n    @cached_property\n    def object(self):\n        return get_object_or_404(\n            EventPermission,\n            invitation_token__iexact=self.kwargs.get('code'),\n            user__isnull=True,\n        )\n\n    def get_context_data(self, *args, **kwargs):\n        ctx = super().get_context_data(*args, **kwargs)\n        ctx['invitation'] = self.object\n        return ctx\n\n    def form_valid(self, form):\n        form.save()\n        permission = self.object\n        user = User.objects.filter(pk=form.cleaned_data.get('user_id')).first()\n        if not user:\n            messages.error(self.request, _('There was a problem with your authentication. Please contact the organiser for further help.'))\n            return redirect(self.request.event.urls.base)\n\n        perm = EventPermission.objects.filter(user=user, event=permission.event).exclude(pk=permission.pk).first()\n        event = permission.event\n\n        if perm:\n            if permission.is_orga:\n                perm.is_orga = True\n            if permission.is_reviewer:\n                perm.is_reviewer = True\n            perm.save()\n            permission.delete()\n            permission = perm\n\n        permission.user = user\n        permission.save()\n        permission.event.log_action('pretalx.invite.orga.accept', person=user, orga=True)\n        messages.info(self.request, _('You are now part of the event team!'))\n\n        login(self.request, user, backend='django.contrib.auth.backends.ModelBackend')\n        return redirect(event.orga_urls.base)\n\n\n@method_decorator(csp_update(SCRIPT_SRC=\"'self' 'unsafe-inline'\"), name='dispatch')\nclass UserSettings(TemplateView):\n    form_class = LoginInfoForm\n    template_name = 'orga/user.html'\n\n    def get_success_url(self) -> str:\n        return reverse('orga:user.view')\n\n    @cached_property\n    def login_form(self):\n        bind = self.request.method == 'POST' and self.request.POST.get('action') == 'login'\n        return LoginInfoForm(\n            user=self.request.user,\n            data=self.request.POST if bind else None\n        )\n\n    @cached_property\n    def profile_form(self):\n        bind = self.request.method == 'POST' and self.request.POST.get('action') == 'profile'\n        return OrgaProfileForm(\n            instance=self.request.user,\n            data=self.request.POST if bind else None\n        )\n\n    def get_context_data(self, **kwargs):\n        ctx = super().get_context_data(**kwargs)\n        ctx['token'] = Token.objects.filter(user=self.request.user).first() or Token.objects.create(user=self.request.user)\n        ctx['login_form'] = self.login_form\n        ctx['profile_form'] = self.profile_form\n        return ctx\n\n    def post(self, request, *args, **kwargs):\n        if self.login_form.is_bound and self.login_form.is_valid():\n            self.login_form.save()\n            messages.success(request, _('Your changes have been saved.'))\n            request.user.log_action('pretalx.user.password.update')\n        elif self.profile_form.is_bound and self.profile_form.is_valid():\n            self.profile_form.save()\n            messages.success(request, _('Your changes have been saved.'))\n            request.user.log_action('pretalx.user.profile.update')\n        elif request.POST.get('form') == 'token':\n            request.user.regenerate_token()\n            messages.success(request, _('Your API token has been regenerated. The previous token will not be usable any longer.'))\n        else:\n            messages.error(self.request, _('Oh :( We had trouble saving your input. See below for details.'))\n        return redirect(self.get_success_url())\n", "path": "src/pretalx/orga/views/event.py"}]}