(request, token=None)
| 110 | |
| 111 | @atomic_for_request_method |
| 112 | def confirm_email(request, token=None): |
| 113 | # clean up expired tokens; doing this on every request is just fine, it saves us from having to run a cron job-like |
| 114 | EmailVerification.objects.filter( |
| 115 | created_at__lt=timezone.now() - timedelta(get_settings().USER_REGISTRATION_VERIFY_EMAIL_EXPIRY)).delete() |
| 116 | |
| 117 | try: |
| 118 | verification = EmailVerification.objects.get(token=token) |
| 119 | except EmailVerification.DoesNotExist: |
| 120 | # good enough (though a special page might be prettier) |
| 121 | raise Http404("Invalid or expired token") |
| 122 | |
| 123 | if request.method == 'POST': |
| 124 | # We insist on POST requests to do the actual confirmation (at the cost of an extra click). See: |
| 125 | # https://softwareengineering.stackexchange.com/a/422579/168778 |
| 126 | # there's no Django form (fields), there's just a button to generate the post request |
| 127 | |
| 128 | verification.user.is_active = True |
| 129 | verification.user.save() |
| 130 | verification.delete() |
| 131 | |
| 132 | # this mirrors the approach of what we do in password-resetting; and rightfully so because the in both cases |
| 133 | # access to email is assumed to be sufficient proof of identity. |
| 134 | login(request, verification.user) |
| 135 | |
| 136 | return redirect('home') |
| 137 | |
| 138 | return render(request, "users/confirm_email.html") |
| 139 | |
| 140 | |
| 141 | @atomic_for_request_method |
nothing calls this directly
no test coverage detected