This one is rather tricky. We do a major overhaul of URLs and general flow of confirmations, relying heavily on the messages framework to avoid the need to have separate pages. Previously, configuring opt-in or opt-out of email involved the following:
GET /mail/ POST /mail/ [some validation] POST /mail/optout/ # or optin If the last step threw an error, we'd stay on '/mail/optout/' or '/mail/optin/' with a displayed error and tell the user to correct the mistake. Now, we simply do this: GET /mail/ POST /mail/ [some validation] GET /mail/<email>/ POST /mail/<email>/ Error messages are propagated via the messages framework with all non-field validation errors resulting in a redirect to the homepage. Signed-off-by: Stephen Finucane <step...@that.guru> --- .../templates/patchwork/confirm-error.html | 23 --- .../templates/patchwork/mail-configure.html | 70 ++++++++ .../templates/patchwork/mail-settings.html | 106 +++++++---- patchwork/templates/patchwork/mail.html | 37 ---- .../templates/patchwork/optin-request.html | 53 ------ patchwork/templates/patchwork/optin.html | 21 --- .../templates/patchwork/optout-request.html | 56 ------ patchwork/templates/patchwork/optout.html | 25 --- .../patchwork/registration-confirm.html | 14 -- patchwork/urls.py | 3 +- patchwork/views/mail.py | 168 +++++++++++------- patchwork/views/notification.py | 35 ++-- patchwork/views/user.py | 56 +++--- 13 files changed, 304 insertions(+), 363 deletions(-) delete mode 100644 patchwork/templates/patchwork/confirm-error.html create mode 100644 patchwork/templates/patchwork/mail-configure.html delete mode 100644 patchwork/templates/patchwork/mail.html delete mode 100644 patchwork/templates/patchwork/optin-request.html delete mode 100644 patchwork/templates/patchwork/optin.html delete mode 100644 patchwork/templates/patchwork/optout-request.html delete mode 100644 patchwork/templates/patchwork/optout.html delete mode 100644 patchwork/templates/patchwork/registration-confirm.html diff --git patchwork/templates/patchwork/confirm-error.html patchwork/templates/patchwork/confirm-error.html deleted file mode 100644 index b1ce42ee..00000000 --- patchwork/templates/patchwork/confirm-error.html +++ /dev/null @@ -1,23 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Confirmation{% endblock %} -{% block heading %}Confirmation{% endblock %} - - -{% block body %} - -{% if error == 'inactive' %} -<p> - This confirmation has already been processed; you've probably visited this - page before. -</p> -{% endif %} - -{% if error == 'expired' %} -<p> - The confirmation has expired. If you'd still like to perform the - {{ conf.get_type_display }} process, you'll need to resubmit the request. -</p> -{% endif %} - -{% endblock %} diff --git patchwork/templates/patchwork/mail-configure.html patchwork/templates/patchwork/mail-configure.html new file mode 100644 index 00000000..c0e07154 --- /dev/null +++ patchwork/templates/patchwork/mail-configure.html @@ -0,0 +1,70 @@ +{% extends "base2.html" %} + +{% block title %}Mail settings{% endblock %} + +{% block body %} +{% for message in messages %} +{% if message.tags == 'success' %} +<div class="notification is-success"> +{% elif message.tags == 'warning' %} +<div class="notification is-warning"> +{% elif message.tags == 'error' %} +<div class="notification is-danger"> +{% else %} +<div class="notification"> +{% endif %} + {{ message }} + <button class="delete" onclick="dismiss(this);"></button> +</div> +{% endfor %} + +<div class="container" style="margin-top: 1rem;"> + <section class="block"> + <h1 class="title"> + Mail settings for {{ email }} + </h1> + </section> + + <div class="content"> + <p> + You can configure your notification settings for Patchwork. + Use this if you wish to opt out of all email from Patchwork, + or if have previously opted out of Patchwork mail but now wish to + receive notifications from Patchwork. + </p> + <p> + If you opt out of email, Patchwork may still email you if you do certain + actions yourself (such as create a new Patchwork account) but will not + send you unsolicited email. + </p> + <p> + When you submit a request, an email will be sent to your address with + a link to click to finalise the request. + Patchwork does this to prevent someone modifying your mail settings + without your consent. + </p> + +{% if is_optout %} + <p> + Patchwork <strong>may not</strong> send automated notifications to this address. + </p> +{% else %} + <p> + Patchwork <strong>may</strong> send automated notifications to this address. + </p> +{% endif %} + + <form class="form" method="post"> + {% csrf_token %} + <div class="field is-grouped"> + <div class="control"> + <input class="button" type="submit" name="optin" value="Opt-in"{% if not is_optout %} disabled{% endif %}/> + </div> + <div class="control"> + <input class="button" type="submit" name="optout" value="Opt-out"{% if is_optout %} disabled{% endif %}/> + </div> + </div> + </form> + </div> +</div> +{% endblock %} diff --git patchwork/templates/patchwork/mail-settings.html patchwork/templates/patchwork/mail-settings.html index 58f567ac..858140ae 100644 --- patchwork/templates/patchwork/mail-settings.html +++ patchwork/templates/patchwork/mail-settings.html @@ -1,37 +1,83 @@ -{% extends "base.html" %} +{% extends "base2.html" %} {% block title %}Mail settings{% endblock %} -{% block heading %}Mail settings{% endblock %} {% block body %} -<p>Settings for <strong>{{ email }}</strong>:</p> - -<table class="horizontal"> - <tr> - <th>Opt-out list</th> -{% if is_optout %} - <td> - Patchwork <strong>may not</strong> send automated notifications to this address. - </td> - <td> - <form method="post" action="{% url 'mail-optin' %}"> - {% csrf_token %} - <input type="hidden" name="email" value="{{ email }}"/> - <input type="submit" value="Opt-in"/> - </form> - </td> +{% for message in messages %} +{% if message.tags == 'success' %} +<div class="notification is-success"> +{% elif message.tags == 'warning' %} +<div class="notification is-warning"> +{% elif message.tags == 'error' %} +<div class="notification is-danger"> {% else %} - <td> - Patchwork <strong>may</strong> send automated notifications to this address. - </td> - <td> - <form method="post" action="{% url 'mail-optout' %}"> - {% csrf_token %} - <input type="hidden" name="email" value="{{ email }}"/> - <input type="submit" value="Opt-out"/> - </form> - </td> +<div class="notification"> {% endif %} - </tr> -</table> + {{ message }} + <button class="delete" onclick="dismiss(this);"></button> +</div> +{% endfor %} + +<div class="container" style="margin-top: 1rem;"> + <section class="block"> + <h1 class="title"> + Mail settings + </h1> + </section> + + <p> + You can configure Patchwork to send you mail on certain events, + or block automated mail altogether. Enter your email address to + view or change your email settings. + </p> + + <div class="block"></div> + +{% if form.non_field_errors %} + <div class="notification is-danger is-light"> + <button class="delete" onclick="dismiss(this);"></button> + {{ form.non_field_errors }} + </div> +{% endif %} + + <form class="form" method="post"> + {% csrf_token %} + + <div class="field is-horizontal"> + <div class="field-label is-normal"> + <label for="email" class="label"> + Email address + </label> + </div> + <div class="field-body"> + <div class="field"> + <div class="control"> + <input id="id_email" type="email" name="email" class="input" placeholder="e.g. bobsm...@example.com"> + </div> + <p class="help"> + Your email address + </p> +{% for error in form.email.errors %} + <p class="help is-danger">{{ error }}</p> +{% endfor %} + </div> + </div> + </div> + + <div class="field is-horizontal"> + <div class="field-label"> + <!-- Left empty for spacing --> + </div> + <div class="field-body"> + <div class="field"> + <div class="control"> + <button class="button is-primary"> + Submit + </button> + </div> + </div> + </div> + </div> + </form> +</div> {% endblock %} diff --git patchwork/templates/patchwork/mail.html patchwork/templates/patchwork/mail.html deleted file mode 100644 index a2ad23d1..00000000 --- patchwork/templates/patchwork/mail.html +++ /dev/null @@ -1,37 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Mail settings{% endblock %} -{% block heading %}Mail settings{% endblock %} - -{% block body %} -<p> - You can configure Patchwork to send you mail on certain events, - or block automated mail altogether. Enter your email address to - view or change your email settings. -</p> - -<form method="post"> -{% csrf_token %} -<table class="form registerform"> -{% if form.errors %} - <tr> - <td colspan="2" class="error"> - There was an error accessing your mail settings: - </td> - </tr> -{% endif %} - <tr> - <th>{{ form.email.label_tag }}</th> - <td> - {{ form.email }} - {{ form.email.errors }} - </td> - </tr> - <tr> - <td colspan="2" class="submitrow"> - <input type="submit" value="Access mail settings"/> - </td> - </tr> -</table> -</form> -{% endblock %} diff --git patchwork/templates/patchwork/optin-request.html patchwork/templates/patchwork/optin-request.html deleted file mode 100644 index 36744c26..00000000 --- patchwork/templates/patchwork/optin-request.html +++ /dev/null @@ -1,53 +0,0 @@ -{% extends "base.html" %} - -{% load admins %} - -{% block title %}Opt-in{% endblock %} -{% block heading %}Opt-in{% endblock %} - -{% block body %} -{% if confirmation %} -<p><strong>Opt-in confirmation email sent</strong></p> -<p> - An opt-in confirmation mail has been sent to - <strong>{{ confirmation.email }}</strong>, containing a link. Please click on - that link to confirm your opt-in. -</p> -{% else %} -{% if error %} -<p class="error">{{ error }}</p> -{% endif %} - -{% if form %} -<p> - This form allows you to opt-in to automated email from Patchwork. Use - this if you have previously opted-out of Patchwork mail, but now want to - received notifications from Patchwork. -</p> -<p> - When you submit it, an email will be sent to your address with a link to - click to finalise the opt-in. Patchwork does this to prevent someone opting - you in without your consent. -</p> - -<form method="post" action=""> - {% csrf_token %} - {{ form.email.errors }} - <div style="padding: 0.5em 1em 2em;"> - {{ form.email.label_tag }}: {{ form.email }} - </div> - <input type="submit" value="Send me an opt-in link"> -</form> -{% endif %} - -{% if error and admins %} -<p> - If you are having trouble opting in, please email {% site_admins %}. -</p> -{% endif %} -{% endif %} - -{% if user.is_authenticated %} -<p>Return to your <a href="{% url 'user-profile' %}">user profile</a>.</p> -{% endif %} -{% endblock %} diff --git patchwork/templates/patchwork/optin.html patchwork/templates/patchwork/optin.html deleted file mode 100644 index 659bfccb..00000000 --- patchwork/templates/patchwork/optin.html +++ /dev/null @@ -1,21 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Opt-in{% endblock %} -{% block heading %}Opt-in{% endblock %} - -{% block body %} -<p> - <strong>Opt-in complete</strong>. You have successfully opted back in to - automated email from this Patchwork system, using the address - <strong>{{ email }}</strong>. -</p> -<p> - If you later decide that you no longer want to receive automated mail from - Patchwork, just visit - <a href="{% url 'mail-settings' %}">http://{{ site.domain }}{% url 'mail-settings' %}</a>, - or visit the main Patchwork page and navigate from there. -</p> -{% if user.is_authenticated %} -<p>Return to your <a href="{% url 'user-profile' %}">user profile</a>.</p> -{% endif %} -{% endblock %} diff --git patchwork/templates/patchwork/optout-request.html patchwork/templates/patchwork/optout-request.html deleted file mode 100644 index a89f72bb..00000000 --- patchwork/templates/patchwork/optout-request.html +++ /dev/null @@ -1,56 +0,0 @@ -{% extends "base.html" %} - -{% load admins %} - -{% block title %}Opt-out{% endblock %} -{% block heading %}Opt-out{% endblock %} - -{% block body %} -{% if confirmation %} -<p><strong>Opt-out confirmation email sent</strong></p> -<p> - An opt-out confirmation mail has been sent to - <strong>{{ confirmation.email }}</strong>, containing a link. Please click on - that link to confirm your opt-out. -</p> -{% else %} -{% if error %} -<p class="error">{{ error }}</p> -{% endif %} - -{% if form %} -<p> - This form allows you to opt-out of automated email from Patchwork. -</p> -<p> - If you opt-out of email, Patchwork may still email you if you do certain - actions yourself (such as create a new Patchwork account), but will not - send you unsolicited email. -</p> -<p> - When you submit it, one email will be sent to your address with a link to - click to finalise the opt-out. Patchwork does this to prevent someone - opting you out without your consent. -</p> -<form method="post" action=""> - {% csrf_token %} - {{ form.email.errors }} - <div style="padding: 0.5em 1em 2em;"> - {{ form.email.label_tag }}: {{ form.email }} - </div> - <input type="submit" value="Send me an opt-out link"> -</form> -{% endif %} - -{% if error and admins %} -<p> - If you are having trouble opting out, please email {% site_admins %}. -</p> -{% endif %} -{% endif %} - -{% if user.is_authenticated %} -<p>Return to your <a href="{% url 'user-profile' %}">user profile</a>.</p> -{% endif %} - -{% endblock %} diff --git patchwork/templates/patchwork/optout.html patchwork/templates/patchwork/optout.html deleted file mode 100644 index 2d7e67e5..00000000 --- patchwork/templates/patchwork/optout.html +++ /dev/null @@ -1,25 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Opt-out{% endblock %} -{% block heading %}Opt-out{% endblock %} - -{% block body %} -<p> - <strong>Opt-out complete</strong>. You have successfully opted-out of - automated notifications from this Patchwork system, from the address - <strong>{{ email }}</strong> -</p> -<p> - Please note that you may still receive email from other Patchwork setups at - different sites, as they are run independently. You may need to opt-out of - those separately. -</p> -<p> - If you later decide to receive mail from Patchwork, just visit - <a href="{% url 'mail-settings' %}">http://{{ site.domain }}{% url 'mail-settings' %}</a>, - or visit the main Patchwork page and navigate from there. -</p> -{% if user.is_authenticated %} -<p>Return to your <a href="{% url 'user-profile' %}">user profile</a>.</p> -{% endif %} -{% endblock %} diff --git patchwork/templates/patchwork/registration-confirm.html patchwork/templates/patchwork/registration-confirm.html deleted file mode 100644 index e9219a5a..00000000 --- patchwork/templates/patchwork/registration-confirm.html +++ /dev/null @@ -1,14 +0,0 @@ -{% extends "base.html" %} - -{% block title %}Registration{% endblock %} -{% block heading %}Registration{% endblock %} - -{% block body %} -<p>Registration confirmed!</p> - -<p> - Your Patchwork registration is complete. Head over to your - <a href="{% url 'user-profile' %}">profile</a> to start using - Patchwork's extra features. -</p> -{% endblock %} diff --git patchwork/urls.py patchwork/urls.py index 30c070a9..e8ddba10 100644 --- patchwork/urls.py +++ patchwork/urls.py @@ -185,8 +185,7 @@ urlpatterns = [ path('delegate/', api_views.delegates, name='api-delegates'), # email setup path('mail/', mail_views.settings, name='mail-settings'), - path('mail/optout/', mail_views.optout, name='mail-optout'), - path('mail/optin/', mail_views.optin, name='mail-optin'), + path('mail/<path:email>/', mail_views.configure, name='mail-configure'), # about path('about/', about_views.about, name='about'), # legacy redirects diff --git patchwork/views/mail.py patchwork/views/mail.py index 1a2019eb..d20f9d2f 100644 --- patchwork/views/mail.py +++ patchwork/views/mail.py @@ -7,6 +7,7 @@ import smtplib from django.conf import settings as conf_settings from django.core.mail import send_mail +from django.contrib import messages from django.http import HttpResponseRedirect from django.shortcuts import render from django.template.loader import render_to_string @@ -22,12 +23,9 @@ def settings(request): form = EmailForm(data=request.POST) if form.is_valid(): email = form.cleaned_data['email'] - is_optout = EmailOptout.objects.filter(email=email).count() > 0 - context = { - 'email': email, - 'is_optout': is_optout, - } - return render(request, 'patchwork/mail-settings.html', context) + return HttpResponseRedirect( + reverse('mail-configure', kwargs={'email': email}), + ) else: form = EmailForm() @@ -35,91 +33,125 @@ def settings(request): 'form': form, } - return render(request, 'patchwork/mail.html', context) + return render(request, 'patchwork/mail-settings.html', context) -def optout_confirm(request, conf): - email = conf.email.strip().lower() - # silently ignore duplicated optouts - if EmailOptout.objects.filter(email=email).count() == 0: - optout = EmailOptout(email=email) - optout.save() +def _opt_in(request, email): + EmailConfirmation.objects.filter(type='optin', email=email).delete() - conf.deactivate() + confirmation = EmailConfirmation(type='optin', email=email) + confirmation.save() - context = { - 'email': conf.email, - } + context = {'confirmation': confirmation} + subject = render_to_string('patchwork/mails/optin-request-subject.txt') + message = render_to_string( + 'patchwork/mails/optin-request.txt', context, request=request) - return render(request, 'patchwork/optout.html', context) + try: + send_mail(subject, message, conf_settings.DEFAULT_FROM_EMAIL, [email]) + except smtplib.SMTPException: + messages.error( + request, + 'An error occurred while submitting this request. ' + 'Please contact an administrator.' + ) + return False + messages.success( + request, + 'Requested opt-in to email from Patchwork. ' + 'Check your email for confirmation.', + ) -def optin_confirm(request, conf): - email = conf.email.strip().lower() - EmailOptout.objects.filter(email=email).delete() + return True - conf.deactivate() - context = { - 'email': conf.email, - } +def _opt_out(request, email): + EmailConfirmation.objects.filter(type='optout', email=email).delete() - return render(request, 'patchwork/optin.html', context) + confirmation = EmailConfirmation(type='optout', email=email) + confirmation.save() + context = {'confirmation': confirmation} + subject = render_to_string('patchwork/mails/optout-request-subject.txt') + message = render_to_string( + 'patchwork/mails/optout-request.txt', context, request=request) -def _optinout(request, action): - context = {} - mail_template = 'patchwork/mails/%s-request.txt' % action - mail_subject_template = 'patchwork/mails/%s-request-subject.txt' % action - html_template = 'patchwork/%s-request.html' % action + try: + send_mail(subject, message, conf_settings.DEFAULT_FROM_EMAIL, [email]) + except smtplib.SMTPException: + messages.error( + request, + 'An error occurred while submitting this request. ' + 'Please contact an administrator.' + ) + return False - if request.method != 'POST': - return HttpResponseRedirect(reverse(settings)) + messages.success( + request, + 'Requested opt-out of email from Patchwork. ' + 'Check your email for confirmation.', + ) + + return True - form = EmailForm(data=request.POST) + +def configure(request, email): + # Yes, we're kind of abusing forms here, but this is easier than doing our + # own view-based validation + form = EmailForm(data={'email': email}) if not form.is_valid(): - context['error'] = ( - 'There was an error in the form. Please review ' 'and re-submit.' - ) - context['form'] = form - return render(request, html_template, context) + # don't worry - Django escapes these by default + messages.error(request, f'{email} is not a valid email address.') + return HttpResponseRedirect(reverse(settings)) email = form.cleaned_data['email'] - if ( - action == 'optin' and - EmailOptout.objects.filter(email=email).count() == 0 - ): - context['error'] = ( - "The email address %s is not on the patchwork " - "opt-out list, so you don't need to opt back in" % email - ) - context['form'] = form - return render(request, html_template, context) - conf = EmailConfirmation(type=action, email=email) - conf.save() + if request.method == 'POST': + if 'optin' in request.POST: + if _opt_in(request, email): + return HttpResponseRedirect(reverse('project-list')) + elif 'optout' in request.POST: + if _opt_out(request, email): + return HttpResponseRedirect(reverse('project-list')) + else: + messages.error(request, 'Invalid request.') + + is_optout = EmailOptout.objects.filter(email=email).count() > 0 + context = { + 'email': email, + 'is_optout': is_optout, + } - context['confirmation'] = conf + return render(request, 'patchwork/mail-configure.html', context) - subject = render_to_string(mail_subject_template) - message = render_to_string(mail_template, context, request=request) - try: - send_mail(subject, message, conf_settings.DEFAULT_FROM_EMAIL, [email]) - except smtplib.SMTPException: - context['confirmation'] = None - context['error'] = ( - 'An error occurred during confirmation. ' - 'Please try again later.' - ) - context['admins'] = conf_settings.ADMINS +def optout_confirm(request, confirmation): + email = confirmation.email.strip().lower() + # silently ignore duplicated optouts + if EmailOptout.objects.filter(email=email).count() == 0: + optout = EmailOptout(email=email) + optout.save() - return render(request, html_template, context) + confirmation.deactivate() + messages.success( + request, + 'Successfully opted out of email from Patchwork.' + ) + + return HttpResponseRedirect(reverse('project-list')) + + +def optin_confirm(request, confirmation): + email = confirmation.email.strip().lower() + EmailOptout.objects.filter(email=email).delete() -def optout(request): - return _optinout(request, 'optout') + confirmation.deactivate() + messages.success( + request, + 'Successfully opted into email from Patchwork.' + ) -def optin(request): - return _optinout(request, 'optin') + return HttpResponseRedirect(reverse('project-list')) diff --git patchwork/views/notification.py patchwork/views/notification.py index 4e023867..7c773ba7 100644 --- patchwork/views/notification.py +++ patchwork/views/notification.py @@ -4,9 +4,9 @@ # # SPDX-License-Identifier: GPL-2.0-or-later -from django.http import Http404 -from django.shortcuts import get_object_or_404 -from django.shortcuts import render +from django.contrib import messages +from django.http import HttpResponseRedirect +from django.urls import reverse from patchwork.models import EmailConfirmation from patchwork.views import mail @@ -22,18 +22,27 @@ def confirm(request, key): 'optin': mail.optin_confirm, } - conf = get_object_or_404(EmailConfirmation, key=key) + try: + conf = EmailConfirmation.objects.get(key=key) + except EmailConfirmation.DoesNotExist: + messages.error( + request, + 'That request is invalid or expired. Please try again.' + ) + return HttpResponseRedirect(reverse('project-list')) + if conf.type not in views: - raise Http404 + messages.error( + request, + 'That request is invalid or expired. Please try again.' + ) + return HttpResponseRedirect(reverse('project-list')) if conf.active and conf.is_valid(): return views[conf.type](request, conf) - context = {} - context['conf'] = conf - if not conf.active: - context['error'] = 'inactive' - elif not conf.is_valid(): - context['error'] = 'expired' - - return render(request, 'patchwork/confirm-error.html', context) + messages.error( + request, + 'That request is invalid or expired. Please try again.' + ) + return HttpResponseRedirect(reverse('project-list')) diff --git patchwork/views/user.py patchwork/views/user.py index 440aa38a..973061b7 100644 --- patchwork/views/user.py +++ patchwork/views/user.py @@ -54,12 +54,12 @@ def register(request): user.save() # create confirmation - conf = EmailConfirmation( + confirmation = EmailConfirmation( type='registration', user=user, email=user.email ) - conf.save() + confirmation.save() - context['confirmation'] = conf + context['confirmation'] = confirmation # send email subject = render_to_string( @@ -67,12 +67,18 @@ def register(request): ) message = render_to_string( 'patchwork/mails/activation.txt', - {'site': Site.objects.get_current(), 'confirmation': conf}, + { + 'site': Site.objects.get_current(), + 'confirmation': confirmation, + }, ) try: send_mail( - subject, message, settings.DEFAULT_FROM_EMAIL, [conf.email] + subject, + message, + settings.DEFAULT_FROM_EMAIL, + [confirmation.email] ) except smtplib.SMTPException: context['confirmation'] = None @@ -88,26 +94,34 @@ def register(request): return render(request, 'patchwork/registration.html', context) -def register_confirm(request, conf): - conf.user.is_active = True - conf.user.save() - conf.deactivate() +def register_confirm(request, confirmation): + confirmation.user.is_active = True + confirmation.user.save() + confirmation.deactivate() try: - person = Person.objects.get(email__iexact=conf.user.email) + person = Person.objects.get(email__iexact=confirmation.user.email) except Person.DoesNotExist: - person = Person(email=conf.user.email, name=conf.user.profile.name) - person.user = conf.user + person = Person( + email=confirmation.user.email, name=confirmation.user.profile.name, + ) + person.user = confirmation.user person.save() - return render(request, 'patchwork/registration-confirm.html') + messages.success(request, 'Successfully confirmed account.') + + return HttpResponseRedirect(reverse('project-list')) def _send_confirmation_email(request, email): - conf = EmailConfirmation(type='userperson', user=request.user, email=email) - conf.save() + confirmation = EmailConfirmation( + type='userperson', + user=request.user, + email=email, + ) + confirmation.save() - context = {'confirmation': conf} + context = {'confirmation': confirmation} subject = render_to_string('patchwork/mails/user-link-subject.txt') message = render_to_string( 'patchwork/mails/user-link.txt', @@ -273,15 +287,15 @@ def profile(request): @login_required -def link_confirm(request, conf): +def link_confirm(request, confirmation): try: - person = Person.objects.get(email__iexact=conf.email) + person = Person.objects.get(email__iexact=confirmation.email) except Person.DoesNotExist: - person = Person(email=conf.email) + person = Person(email=confirmation.email) - person.link_to_user(conf.user) + person.link_to_user(confirmation.user) person.save() - conf.deactivate() + confirmation.deactivate() messages.success(request, 'Successfully linked email to account.') -- 2.31.1 _______________________________________________ Patchwork mailing list Patchwork@lists.ozlabs.org https://lists.ozlabs.org/listinfo/patchwork