We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Incorrect invite token yields server exception
When using an incorrect invitation token, pretalx does not fail gracefully.
Incorrect invite token yields server exception
When using an incorrect invitation token, pretalx does not fail gracefully.

--- 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/cfp/views/user.py`
Content:
```
1 import urllib
2 
3 from csp.decorators import csp_update
4 from django.contrib import messages
5 from django.core.exceptions import ValidationError
6 from django.core.validators import validate_email
7 from django.http import Http404
8 from django.shortcuts import redirect
9 from django.utils.decorators import method_decorator
10 from django.utils.functional import cached_property
11 from django.views.generic import (
12     DetailView, FormView, ListView, TemplateView, UpdateView, View,
13 )
14 
15 from pretalx.cfp.forms.submissions import (
16     InfoForm, QuestionsForm, SubmissionInvitationForm,
17 )
18 from pretalx.cfp.views.event import LoggedInEventPageMixin
19 from pretalx.common.phrases import phrases
20 from pretalx.person.forms import LoginInfoForm, SpeakerProfileForm
21 from pretalx.submission.models import Submission, SubmissionStates
22 
23 
24 @method_decorator(csp_update(STYLE_SRC="'self' 'unsafe-inline'", IMG_SRC="https://www.gravatar.com"), name='dispatch')
25 class ProfileView(LoggedInEventPageMixin, TemplateView):
26     template_name = 'cfp/event/user_profile.html'
27 
28     @cached_property
29     def login_form(self):
30         return LoginInfoForm(user=self.request.user,
31                              data=(self.request.POST
32                                    if self.request.method == 'POST'
33                                    and self.request.POST.get('form') == 'login'
34                                    else None))
35 
36     @cached_property
37     def profile_form(self):
38         if self.request.method == 'POST' and self.request.POST.get('form') == 'profile':
39             return SpeakerProfileForm(
40                 user=self.request.user,
41                 event=self.request.event,
42                 read_only=False,
43                 data=self.request.POST,
44                 files=self.request.FILES,
45             )
46         return SpeakerProfileForm(
47             user=self.request.user,
48             event=self.request.event,
49             read_only=False,
50             data=None,
51         )
52 
53     @cached_property
54     def questions_form(self):
55         return QuestionsForm(
56             data=self.request.POST if self.request.method == 'POST' else None,
57             speaker=self.request.user,
58             event=self.request.event,
59             target='speaker',
60             request_user=self.request.user,
61         )
62 
63     def get_context_data(self, event):
64         ctx = super().get_context_data()
65         ctx['login_form'] = self.login_form
66         ctx['profile_form'] = self.profile_form
67         ctx['questions_form'] = self.questions_form
68         ctx['questions_exist'] = self.request.event.questions.filter(active=True, target='speaker').exists()
69         return ctx
70 
71     def post(self, request, *args, **kwargs):
72         if self.login_form.is_bound:
73             if self.login_form.is_valid():
74                 self.login_form.save()
75                 messages.success(self.request, phrases.base.saved)
76                 request.user.log_action('pretalx.user.password.update')
77                 return redirect('cfp:event.user.view', event=self.request.event.slug)
78         elif self.profile_form.is_bound:
79             if self.profile_form.is_valid():
80                 self.profile_form.save()
81                 messages.success(self.request, phrases.base.saved)
82                 profile = self.request.user.profiles.get_or_create(event=self.request.event)[0]
83                 profile.log_action('pretalx.user.profile.update', person=request.user)
84                 return redirect('cfp:event.user.view', event=self.request.event.slug)
85         elif self.questions_form.is_bound:
86             if self.questions_form.is_valid():
87                 self.questions_form.save()
88                 messages.success(self.request, phrases.base.saved)
89                 return redirect('cfp:event.user.view', event=self.request.event.slug)
90 
91         messages.error(self.request, phrases.base.error_saving_changes)
92         return super().get(request, *args, **kwargs)
93 
94 
95 class SubmissionViewMixin:
96     def get_object(self):
97         try:
98             return self.request.event.submissions.prefetch_related('answers', 'answers__options').get(
99                 speakers__in=[self.request.user],
100                 code__iexact=self.kwargs.get('code')
101             )
102         except Submission.DoesNotExist:
103             try:
104                 # Backwards compatibility
105                 return self.request.event.submissions.prefetch_related('answers', 'answers__options').get(
106                     speakers__in=[self.request.user],
107                     id=self.kwargs.get('code')
108                 )
109             except (Submission.DoesNotExist, ValueError):
110                 raise Http404()
111 
112 
113 class SubmissionsListView(LoggedInEventPageMixin, ListView):
114     template_name = 'cfp/event/user_submissions.html'
115     context_object_name = 'submissions'
116 
117     def get_queryset(self):
118         return self.request.event.submissions.filter(speakers__in=[self.request.user])
119 
120 
121 class SubmissionsWithdrawView(LoggedInEventPageMixin, SubmissionViewMixin, DetailView):
122     template_name = 'cfp/event/user_submission_withdraw.html'
123     model = Submission
124     context_object_name = 'submission'
125 
126     def dispatch(self, request, *args, **kwargs):
127         self.object = self.get_object()
128         if self.object.state == SubmissionStates.SUBMITTED:
129             self.object.state = SubmissionStates.WITHDRAWN
130             self.object.save(update_fields=['state'])
131             self.object.log_action('pretalx.submission.withdrawal', person=request.user)
132             messages.success(self.request, phrases.cfp.submission_withdrawn)
133         else:
134             messages.error(self.request, phrases.cfp.submission_not_withdrawn)
135         return redirect('cfp:event.user.submissions', event=self.request.event.slug)
136 
137 
138 class SubmissionConfirmView(LoggedInEventPageMixin, SubmissionViewMixin, View):
139 
140     def dispatch(self, request, *args, **kwargs):
141         if request.user.is_anonymous:
142             return redirect(request.event.urls.login)
143         submission = self.get_object()
144         if submission.state == SubmissionStates.ACCEPTED:
145             submission.confirm(person=request.user)
146             submission.log_action('pretalx.submission.confirm', person=request.user)
147             messages.success(self.request, phrases.cfp.submission_confirmed)
148         elif submission.state == SubmissionStates.CONFIRMED:
149             messages.success(self.request, phrases.cfp.submission_was_confirmed)
150         else:
151             messages.error(self.request, phrases.cfp.submission_not_confirmed)
152         return redirect('cfp:event.user.submissions', event=self.request.event.slug)
153 
154 
155 class SubmissionsEditView(LoggedInEventPageMixin, SubmissionViewMixin, UpdateView):
156     template_name = 'cfp/event/user_submission_edit.html'
157     model = Submission
158     form_class = InfoForm
159     context_object_name = 'submission'
160 
161     def get_context_data(self, **kwargs):
162         ctx = super().get_context_data(**kwargs)
163         ctx['qform'] = self.qform
164         ctx['can_edit'] = self.can_edit
165         return ctx
166 
167     @cached_property
168     def qform(self):
169         return QuestionsForm(
170             data=self.request.POST if self.request.method == 'POST' else None,
171             submission=self.object,
172             event=self.request.event,
173             readonly=not self.can_edit,
174         )
175 
176     def post(self, request, *args, **kwargs):
177         self.object = self.get_object()
178         form = self.get_form()
179         if form.is_valid() and self.qform.is_valid():
180             return self.form_valid(form)
181         else:
182             return self.form_invalid(form)
183 
184     @property
185     def can_edit(self):
186         return self.object.editable
187 
188     def get_form_kwargs(self):
189         kwargs = super().get_form_kwargs()
190         kwargs['event'] = self.request.event
191         kwargs['readonly'] = not self.can_edit
192         return kwargs
193 
194     def form_valid(self, form):
195         if self.can_edit:
196             form.save()
197             self.qform.save()
198             if form.has_changed():
199                 form.instance.log_action('pretalx.submission.update', person=self.request.user)
200             messages.success(self.request, phrases.base.saved)
201         else:
202             messages.error(self.request, phrases.cfp.submission_uneditable)
203         return redirect('cfp:event.user.submissions', event=self.request.event.slug)
204 
205 
206 class DeleteAccountView(LoggedInEventPageMixin, View):
207 
208     def post(self, request, event):
209 
210         if request.POST.get('really'):
211             from django.contrib.auth import logout
212             request.user.deactivate()
213             logout(request)
214             messages.success(request, phrases.cfp.account_deleted)
215             return redirect(request.event.urls.base)
216         else:
217             messages.error(request, phrases.cfp.account_delete_confirm)
218             return redirect(request.event.urls.user + '?really')
219 
220 
221 class SubmissionInviteView(LoggedInEventPageMixin, SubmissionViewMixin, FormView):
222     form_class = SubmissionInvitationForm
223     template_name = 'cfp/event/user_submission_invitation.html'
224 
225     def get_form_kwargs(self, *args, **kwargs):
226         kwargs = super().get_form_kwargs(*args, **kwargs)
227         kwargs['submission'] = self.get_object()
228         kwargs['speaker'] = self.request.user
229         if 'email' in self.request.GET and not self.request.method == 'POST':
230             initial = kwargs.get('initial', {})
231             initial['speaker'] = urllib.parse.unquote(self.request.GET['email'])
232             kwargs['initial'] = initial
233 
234             try:
235                 validate_email(initial['speaker'])
236             except ValidationError:
237                 messages.warning(self.request, phrases.cfp.invite_invalid_email)
238         return kwargs
239 
240     def get_context_data(self, *args, **kwargs):
241         ctx = super().get_context_data(*args, **kwargs)
242         ctx['submission'] = self.get_object()
243         ctx['invite_url'] = ctx['submission'].urls.accept_invitation.full(scheme='https')
244         return ctx
245 
246     def form_valid(self, form):
247         form.save()
248         messages.success(self.request, phrases.cfp.invite_sent)
249         self.get_object().log_action('pretalx.submission.speakers.invite', person=self.request.user)
250         return super().form_valid(form)
251 
252     def get_success_url(self):
253         return self.get_object().urls.user_base
254 
255 
256 class SubmissionInviteAcceptView(LoggedInEventPageMixin, DetailView):
257     template_name = 'cfp/event/invitation.html'
258     context_object_name = 'submission'
259 
260     def get_object(self, *args, **kwargs):
261         return Submission.objects.get(
262             code__iexact=self.kwargs['code'],
263             invitation_token__iexact=self.kwargs['invitation'],
264         )
265 
266     def post(self, *args, **kwargs):
267         submission = self.get_object()
268         submission.speakers.add(self.request.user)
269         submission.log_action('pretalx.submission.speakers.add', person=self.request.user)
270         submission.save()
271         messages.success(self.request, phrases.cfp.invite_accepted)
272         return redirect('cfp:event.user.view', event=self.request.event.slug)
273
```
--- 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/cfp/views/user.py b/src/pretalx/cfp/views/user.py
--- a/src/pretalx/cfp/views/user.py
+++ b/src/pretalx/cfp/views/user.py
@@ -5,7 +5,7 @@
 from django.core.exceptions import ValidationError
 from django.core.validators import validate_email
 from django.http import Http404
-from django.shortcuts import redirect
+from django.shortcuts import get_object_or_404, redirect
 from django.utils.decorators import method_decorator
 from django.utils.functional import cached_property
 from django.views.generic import (
@@ -258,7 +258,8 @@
     context_object_name = 'submission'
 
     def get_object(self, *args, **kwargs):
-        return Submission.objects.get(
+        return get_object_or_404(
+            Submission,
             code__iexact=self.kwargs['code'],
             invitation_token__iexact=self.kwargs['invitation'],
         )

{"golden_diff": "diff --git a/src/pretalx/cfp/views/user.py b/src/pretalx/cfp/views/user.py\n--- a/src/pretalx/cfp/views/user.py\n+++ b/src/pretalx/cfp/views/user.py\n@@ -5,7 +5,7 @@\n from django.core.exceptions import ValidationError\n from django.core.validators import validate_email\n from django.http import Http404\n-from django.shortcuts import redirect\n+from django.shortcuts import get_object_or_404, redirect\n from django.utils.decorators import method_decorator\n from django.utils.functional import cached_property\n from django.views.generic import (\n@@ -258,7 +258,8 @@\n     context_object_name = 'submission'\n \n     def get_object(self, *args, **kwargs):\n-        return Submission.objects.get(\n+        return get_object_or_404(\n+            Submission,\n             code__iexact=self.kwargs['code'],\n             invitation_token__iexact=self.kwargs['invitation'],\n         )\n", "issue": "Incorrect invite token yields server exception\nWhen using an incorrect invitation token, pretalx does not fail gracefully.\nIncorrect invite token yields server exception\nWhen using an incorrect invitation token, pretalx does not fail gracefully.\n", "before_files": [{"content": "import urllib\n\nfrom csp.decorators import csp_update\nfrom django.contrib import messages\nfrom django.core.exceptions import ValidationError\nfrom django.core.validators import validate_email\nfrom django.http import Http404\nfrom django.shortcuts import redirect\nfrom django.utils.decorators import method_decorator\nfrom django.utils.functional import cached_property\nfrom django.views.generic import (\n    DetailView, FormView, ListView, TemplateView, UpdateView, View,\n)\n\nfrom pretalx.cfp.forms.submissions import (\n    InfoForm, QuestionsForm, SubmissionInvitationForm,\n)\nfrom pretalx.cfp.views.event import LoggedInEventPageMixin\nfrom pretalx.common.phrases import phrases\nfrom pretalx.person.forms import LoginInfoForm, SpeakerProfileForm\nfrom pretalx.submission.models import Submission, SubmissionStates\n\n\n@method_decorator(csp_update(STYLE_SRC=\"'self' 'unsafe-inline'\", IMG_SRC=\"https://www.gravatar.com\"), name='dispatch')\nclass ProfileView(LoggedInEventPageMixin, TemplateView):\n    template_name = 'cfp/event/user_profile.html'\n\n    @cached_property\n    def login_form(self):\n        return LoginInfoForm(user=self.request.user,\n                             data=(self.request.POST\n                                   if self.request.method == 'POST'\n                                   and self.request.POST.get('form') == 'login'\n                                   else None))\n\n    @cached_property\n    def profile_form(self):\n        if self.request.method == 'POST' and self.request.POST.get('form') == 'profile':\n            return SpeakerProfileForm(\n                user=self.request.user,\n                event=self.request.event,\n                read_only=False,\n                data=self.request.POST,\n                files=self.request.FILES,\n            )\n        return SpeakerProfileForm(\n            user=self.request.user,\n            event=self.request.event,\n            read_only=False,\n            data=None,\n        )\n\n    @cached_property\n    def questions_form(self):\n        return QuestionsForm(\n            data=self.request.POST if self.request.method == 'POST' else None,\n            speaker=self.request.user,\n            event=self.request.event,\n            target='speaker',\n            request_user=self.request.user,\n        )\n\n    def get_context_data(self, event):\n        ctx = super().get_context_data()\n        ctx['login_form'] = self.login_form\n        ctx['profile_form'] = self.profile_form\n        ctx['questions_form'] = self.questions_form\n        ctx['questions_exist'] = self.request.event.questions.filter(active=True, target='speaker').exists()\n        return ctx\n\n    def post(self, request, *args, **kwargs):\n        if self.login_form.is_bound:\n            if self.login_form.is_valid():\n                self.login_form.save()\n                messages.success(self.request, phrases.base.saved)\n                request.user.log_action('pretalx.user.password.update')\n                return redirect('cfp:event.user.view', event=self.request.event.slug)\n        elif self.profile_form.is_bound:\n            if self.profile_form.is_valid():\n                self.profile_form.save()\n                messages.success(self.request, phrases.base.saved)\n                profile = self.request.user.profiles.get_or_create(event=self.request.event)[0]\n                profile.log_action('pretalx.user.profile.update', person=request.user)\n                return redirect('cfp:event.user.view', event=self.request.event.slug)\n        elif self.questions_form.is_bound:\n            if self.questions_form.is_valid():\n                self.questions_form.save()\n                messages.success(self.request, phrases.base.saved)\n                return redirect('cfp:event.user.view', event=self.request.event.slug)\n\n        messages.error(self.request, phrases.base.error_saving_changes)\n        return super().get(request, *args, **kwargs)\n\n\nclass SubmissionViewMixin:\n    def get_object(self):\n        try:\n            return self.request.event.submissions.prefetch_related('answers', 'answers__options').get(\n                speakers__in=[self.request.user],\n                code__iexact=self.kwargs.get('code')\n            )\n        except Submission.DoesNotExist:\n            try:\n                # Backwards compatibility\n                return self.request.event.submissions.prefetch_related('answers', 'answers__options').get(\n                    speakers__in=[self.request.user],\n                    id=self.kwargs.get('code')\n                )\n            except (Submission.DoesNotExist, ValueError):\n                raise Http404()\n\n\nclass SubmissionsListView(LoggedInEventPageMixin, ListView):\n    template_name = 'cfp/event/user_submissions.html'\n    context_object_name = 'submissions'\n\n    def get_queryset(self):\n        return self.request.event.submissions.filter(speakers__in=[self.request.user])\n\n\nclass SubmissionsWithdrawView(LoggedInEventPageMixin, SubmissionViewMixin, DetailView):\n    template_name = 'cfp/event/user_submission_withdraw.html'\n    model = Submission\n    context_object_name = 'submission'\n\n    def dispatch(self, request, *args, **kwargs):\n        self.object = self.get_object()\n        if self.object.state == SubmissionStates.SUBMITTED:\n            self.object.state = SubmissionStates.WITHDRAWN\n            self.object.save(update_fields=['state'])\n            self.object.log_action('pretalx.submission.withdrawal', person=request.user)\n            messages.success(self.request, phrases.cfp.submission_withdrawn)\n        else:\n            messages.error(self.request, phrases.cfp.submission_not_withdrawn)\n        return redirect('cfp:event.user.submissions', event=self.request.event.slug)\n\n\nclass SubmissionConfirmView(LoggedInEventPageMixin, SubmissionViewMixin, View):\n\n    def dispatch(self, request, *args, **kwargs):\n        if request.user.is_anonymous:\n            return redirect(request.event.urls.login)\n        submission = self.get_object()\n        if submission.state == SubmissionStates.ACCEPTED:\n            submission.confirm(person=request.user)\n            submission.log_action('pretalx.submission.confirm', person=request.user)\n            messages.success(self.request, phrases.cfp.submission_confirmed)\n        elif submission.state == SubmissionStates.CONFIRMED:\n            messages.success(self.request, phrases.cfp.submission_was_confirmed)\n        else:\n            messages.error(self.request, phrases.cfp.submission_not_confirmed)\n        return redirect('cfp:event.user.submissions', event=self.request.event.slug)\n\n\nclass SubmissionsEditView(LoggedInEventPageMixin, SubmissionViewMixin, UpdateView):\n    template_name = 'cfp/event/user_submission_edit.html'\n    model = Submission\n    form_class = InfoForm\n    context_object_name = 'submission'\n\n    def get_context_data(self, **kwargs):\n        ctx = super().get_context_data(**kwargs)\n        ctx['qform'] = self.qform\n        ctx['can_edit'] = self.can_edit\n        return ctx\n\n    @cached_property\n    def qform(self):\n        return QuestionsForm(\n            data=self.request.POST if self.request.method == 'POST' else None,\n            submission=self.object,\n            event=self.request.event,\n            readonly=not self.can_edit,\n        )\n\n    def post(self, request, *args, **kwargs):\n        self.object = self.get_object()\n        form = self.get_form()\n        if form.is_valid() and self.qform.is_valid():\n            return self.form_valid(form)\n        else:\n            return self.form_invalid(form)\n\n    @property\n    def can_edit(self):\n        return self.object.editable\n\n    def get_form_kwargs(self):\n        kwargs = super().get_form_kwargs()\n        kwargs['event'] = self.request.event\n        kwargs['readonly'] = not self.can_edit\n        return kwargs\n\n    def form_valid(self, form):\n        if self.can_edit:\n            form.save()\n            self.qform.save()\n            if form.has_changed():\n                form.instance.log_action('pretalx.submission.update', person=self.request.user)\n            messages.success(self.request, phrases.base.saved)\n        else:\n            messages.error(self.request, phrases.cfp.submission_uneditable)\n        return redirect('cfp:event.user.submissions', event=self.request.event.slug)\n\n\nclass DeleteAccountView(LoggedInEventPageMixin, View):\n\n    def post(self, request, event):\n\n        if request.POST.get('really'):\n            from django.contrib.auth import logout\n            request.user.deactivate()\n            logout(request)\n            messages.success(request, phrases.cfp.account_deleted)\n            return redirect(request.event.urls.base)\n        else:\n            messages.error(request, phrases.cfp.account_delete_confirm)\n            return redirect(request.event.urls.user + '?really')\n\n\nclass SubmissionInviteView(LoggedInEventPageMixin, SubmissionViewMixin, FormView):\n    form_class = SubmissionInvitationForm\n    template_name = 'cfp/event/user_submission_invitation.html'\n\n    def get_form_kwargs(self, *args, **kwargs):\n        kwargs = super().get_form_kwargs(*args, **kwargs)\n        kwargs['submission'] = self.get_object()\n        kwargs['speaker'] = self.request.user\n        if 'email' in self.request.GET and not self.request.method == 'POST':\n            initial = kwargs.get('initial', {})\n            initial['speaker'] = urllib.parse.unquote(self.request.GET['email'])\n            kwargs['initial'] = initial\n\n            try:\n                validate_email(initial['speaker'])\n            except ValidationError:\n                messages.warning(self.request, phrases.cfp.invite_invalid_email)\n        return kwargs\n\n    def get_context_data(self, *args, **kwargs):\n        ctx = super().get_context_data(*args, **kwargs)\n        ctx['submission'] = self.get_object()\n        ctx['invite_url'] = ctx['submission'].urls.accept_invitation.full(scheme='https')\n        return ctx\n\n    def form_valid(self, form):\n        form.save()\n        messages.success(self.request, phrases.cfp.invite_sent)\n        self.get_object().log_action('pretalx.submission.speakers.invite', person=self.request.user)\n        return super().form_valid(form)\n\n    def get_success_url(self):\n        return self.get_object().urls.user_base\n\n\nclass SubmissionInviteAcceptView(LoggedInEventPageMixin, DetailView):\n    template_name = 'cfp/event/invitation.html'\n    context_object_name = 'submission'\n\n    def get_object(self, *args, **kwargs):\n        return Submission.objects.get(\n            code__iexact=self.kwargs['code'],\n            invitation_token__iexact=self.kwargs['invitation'],\n        )\n\n    def post(self, *args, **kwargs):\n        submission = self.get_object()\n        submission.speakers.add(self.request.user)\n        submission.log_action('pretalx.submission.speakers.add', person=self.request.user)\n        submission.save()\n        messages.success(self.request, phrases.cfp.invite_accepted)\n        return redirect('cfp:event.user.view', event=self.request.event.slug)\n", "path": "src/pretalx/cfp/views/user.py"}], "after_files": [{"content": "import urllib\n\nfrom csp.decorators import csp_update\nfrom django.contrib import messages\nfrom django.core.exceptions import ValidationError\nfrom django.core.validators import validate_email\nfrom django.http import Http404\nfrom django.shortcuts import get_object_or_404, redirect\nfrom django.utils.decorators import method_decorator\nfrom django.utils.functional import cached_property\nfrom django.views.generic import (\n    DetailView, FormView, ListView, TemplateView, UpdateView, View,\n)\n\nfrom pretalx.cfp.forms.submissions import (\n    InfoForm, QuestionsForm, SubmissionInvitationForm,\n)\nfrom pretalx.cfp.views.event import LoggedInEventPageMixin\nfrom pretalx.common.phrases import phrases\nfrom pretalx.person.forms import LoginInfoForm, SpeakerProfileForm\nfrom pretalx.submission.models import Submission, SubmissionStates\n\n\n@method_decorator(csp_update(STYLE_SRC=\"'self' 'unsafe-inline'\", IMG_SRC=\"https://www.gravatar.com\"), name='dispatch')\nclass ProfileView(LoggedInEventPageMixin, TemplateView):\n    template_name = 'cfp/event/user_profile.html'\n\n    @cached_property\n    def login_form(self):\n        return LoginInfoForm(user=self.request.user,\n                             data=(self.request.POST\n                                   if self.request.method == 'POST'\n                                   and self.request.POST.get('form') == 'login'\n                                   else None))\n\n    @cached_property\n    def profile_form(self):\n        if self.request.method == 'POST' and self.request.POST.get('form') == 'profile':\n            return SpeakerProfileForm(\n                user=self.request.user,\n                event=self.request.event,\n                read_only=False,\n                data=self.request.POST,\n                files=self.request.FILES,\n            )\n        return SpeakerProfileForm(\n            user=self.request.user,\n            event=self.request.event,\n            read_only=False,\n            data=None,\n        )\n\n    @cached_property\n    def questions_form(self):\n        return QuestionsForm(\n            data=self.request.POST if self.request.method == 'POST' else None,\n            speaker=self.request.user,\n            event=self.request.event,\n            target='speaker',\n            request_user=self.request.user,\n        )\n\n    def get_context_data(self, event):\n        ctx = super().get_context_data()\n        ctx['login_form'] = self.login_form\n        ctx['profile_form'] = self.profile_form\n        ctx['questions_form'] = self.questions_form\n        ctx['questions_exist'] = self.request.event.questions.filter(active=True, target='speaker').exists()\n        return ctx\n\n    def post(self, request, *args, **kwargs):\n        if self.login_form.is_bound:\n            if self.login_form.is_valid():\n                self.login_form.save()\n                messages.success(self.request, phrases.base.saved)\n                request.user.log_action('pretalx.user.password.update')\n                return redirect('cfp:event.user.view', event=self.request.event.slug)\n        elif self.profile_form.is_bound:\n            if self.profile_form.is_valid():\n                self.profile_form.save()\n                messages.success(self.request, phrases.base.saved)\n                profile = self.request.user.profiles.get_or_create(event=self.request.event)[0]\n                profile.log_action('pretalx.user.profile.update', person=request.user)\n                return redirect('cfp:event.user.view', event=self.request.event.slug)\n        elif self.questions_form.is_bound:\n            if self.questions_form.is_valid():\n                self.questions_form.save()\n                messages.success(self.request, phrases.base.saved)\n                return redirect('cfp:event.user.view', event=self.request.event.slug)\n\n        messages.error(self.request, phrases.base.error_saving_changes)\n        return super().get(request, *args, **kwargs)\n\n\nclass SubmissionViewMixin:\n    def get_object(self):\n        try:\n            return self.request.event.submissions.prefetch_related('answers', 'answers__options').get(\n                speakers__in=[self.request.user],\n                code__iexact=self.kwargs.get('code')\n            )\n        except Submission.DoesNotExist:\n            try:\n                # Backwards compatibility\n                return self.request.event.submissions.prefetch_related('answers', 'answers__options').get(\n                    speakers__in=[self.request.user],\n                    id=self.kwargs.get('code')\n                )\n            except (Submission.DoesNotExist, ValueError):\n                raise Http404()\n\n\nclass SubmissionsListView(LoggedInEventPageMixin, ListView):\n    template_name = 'cfp/event/user_submissions.html'\n    context_object_name = 'submissions'\n\n    def get_queryset(self):\n        return self.request.event.submissions.filter(speakers__in=[self.request.user])\n\n\nclass SubmissionsWithdrawView(LoggedInEventPageMixin, SubmissionViewMixin, DetailView):\n    template_name = 'cfp/event/user_submission_withdraw.html'\n    model = Submission\n    context_object_name = 'submission'\n\n    def dispatch(self, request, *args, **kwargs):\n        self.object = self.get_object()\n        if self.object.state == SubmissionStates.SUBMITTED:\n            self.object.state = SubmissionStates.WITHDRAWN\n            self.object.save(update_fields=['state'])\n            self.object.log_action('pretalx.submission.withdrawal', person=request.user)\n            messages.success(self.request, phrases.cfp.submission_withdrawn)\n        else:\n            messages.error(self.request, phrases.cfp.submission_not_withdrawn)\n        return redirect('cfp:event.user.submissions', event=self.request.event.slug)\n\n\nclass SubmissionConfirmView(LoggedInEventPageMixin, SubmissionViewMixin, View):\n\n    def dispatch(self, request, *args, **kwargs):\n        if request.user.is_anonymous:\n            return redirect(request.event.urls.login)\n        submission = self.get_object()\n        if submission.state == SubmissionStates.ACCEPTED:\n            submission.confirm(person=request.user)\n            submission.log_action('pretalx.submission.confirm', person=request.user)\n            messages.success(self.request, phrases.cfp.submission_confirmed)\n        elif submission.state == SubmissionStates.CONFIRMED:\n            messages.success(self.request, phrases.cfp.submission_was_confirmed)\n        else:\n            messages.error(self.request, phrases.cfp.submission_not_confirmed)\n        return redirect('cfp:event.user.submissions', event=self.request.event.slug)\n\n\nclass SubmissionsEditView(LoggedInEventPageMixin, SubmissionViewMixin, UpdateView):\n    template_name = 'cfp/event/user_submission_edit.html'\n    model = Submission\n    form_class = InfoForm\n    context_object_name = 'submission'\n\n    def get_context_data(self, **kwargs):\n        ctx = super().get_context_data(**kwargs)\n        ctx['qform'] = self.qform\n        ctx['can_edit'] = self.can_edit\n        return ctx\n\n    @cached_property\n    def qform(self):\n        return QuestionsForm(\n            data=self.request.POST if self.request.method == 'POST' else None,\n            submission=self.object,\n            event=self.request.event,\n            readonly=not self.can_edit,\n        )\n\n    def post(self, request, *args, **kwargs):\n        self.object = self.get_object()\n        form = self.get_form()\n        if form.is_valid() and self.qform.is_valid():\n            return self.form_valid(form)\n        else:\n            return self.form_invalid(form)\n\n    @property\n    def can_edit(self):\n        return self.object.editable\n\n    def get_form_kwargs(self):\n        kwargs = super().get_form_kwargs()\n        kwargs['event'] = self.request.event\n        kwargs['readonly'] = not self.can_edit\n        return kwargs\n\n    def form_valid(self, form):\n        if self.can_edit:\n            form.save()\n            self.qform.save()\n            if form.has_changed():\n                form.instance.log_action('pretalx.submission.update', person=self.request.user)\n            messages.success(self.request, phrases.base.saved)\n        else:\n            messages.error(self.request, phrases.cfp.submission_uneditable)\n        return redirect('cfp:event.user.submissions', event=self.request.event.slug)\n\n\nclass DeleteAccountView(LoggedInEventPageMixin, View):\n\n    def post(self, request, event):\n\n        if request.POST.get('really'):\n            from django.contrib.auth import logout\n            request.user.deactivate()\n            logout(request)\n            messages.success(request, phrases.cfp.account_deleted)\n            return redirect(request.event.urls.base)\n        else:\n            messages.error(request, phrases.cfp.account_delete_confirm)\n            return redirect(request.event.urls.user + '?really')\n\n\nclass SubmissionInviteView(LoggedInEventPageMixin, SubmissionViewMixin, FormView):\n    form_class = SubmissionInvitationForm\n    template_name = 'cfp/event/user_submission_invitation.html'\n\n    def get_form_kwargs(self, *args, **kwargs):\n        kwargs = super().get_form_kwargs(*args, **kwargs)\n        kwargs['submission'] = self.get_object()\n        kwargs['speaker'] = self.request.user\n        if 'email' in self.request.GET and not self.request.method == 'POST':\n            initial = kwargs.get('initial', {})\n            initial['speaker'] = urllib.parse.unquote(self.request.GET['email'])\n            kwargs['initial'] = initial\n\n            try:\n                validate_email(initial['speaker'])\n            except ValidationError:\n                messages.warning(self.request, phrases.cfp.invite_invalid_email)\n        return kwargs\n\n    def get_context_data(self, *args, **kwargs):\n        ctx = super().get_context_data(*args, **kwargs)\n        ctx['submission'] = self.get_object()\n        ctx['invite_url'] = ctx['submission'].urls.accept_invitation.full(scheme='https')\n        return ctx\n\n    def form_valid(self, form):\n        form.save()\n        messages.success(self.request, phrases.cfp.invite_sent)\n        self.get_object().log_action('pretalx.submission.speakers.invite', person=self.request.user)\n        return super().form_valid(form)\n\n    def get_success_url(self):\n        return self.get_object().urls.user_base\n\n\nclass SubmissionInviteAcceptView(LoggedInEventPageMixin, DetailView):\n    template_name = 'cfp/event/invitation.html'\n    context_object_name = 'submission'\n\n    def get_object(self, *args, **kwargs):\n        return get_object_or_404(\n            Submission,\n            code__iexact=self.kwargs['code'],\n            invitation_token__iexact=self.kwargs['invitation'],\n        )\n\n    def post(self, *args, **kwargs):\n        submission = self.get_object()\n        submission.speakers.add(self.request.user)\n        submission.log_action('pretalx.submission.speakers.add', person=self.request.user)\n        submission.save()\n        messages.success(self.request, phrases.cfp.invite_accepted)\n        return redirect('cfp:event.user.view', event=self.request.event.slug)\n", "path": "src/pretalx/cfp/views/user.py"}]}