From 02a2965e0421841053ef24ba724d89ae70341431 Mon Sep 17 00:00:00 2001 From: Andrey Zhavoronkov Date: Thu, 4 Aug 2022 13:22:58 +0300 Subject: [PATCH] Fixed reset password after switching to dj-rest-auth (#52) --- CHANGELOG.md | 1 + cvat/apps/iam/forms.py | 48 +++++++++++++++++++ cvat/apps/iam/serializers.py | 7 ++- .../password_reset_key_message.html | 24 ++++++++++ ...il.html => password_reset_key_message.txt} | 0 .../password_reset_key_subject.txt | 4 ++ 6 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 cvat/apps/iam/forms.py create mode 100644 cvat/apps/iam/templates/authentication/password_reset_key_message.html rename cvat/apps/iam/templates/authentication/{password_reset_email.html => password_reset_key_message.txt} (100%) create mode 100644 cvat/apps/iam/templates/authentication/password_reset_key_subject.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 5132de4e..b13c11dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Generated OpenAPI schema for several endpoints - Annotation window might have top offset if try to move a locked object - Image search in cloud storage () +- Reset password functionality () ### Security - TDB diff --git a/cvat/apps/iam/forms.py b/cvat/apps/iam/forms.py new file mode 100644 index 00000000..c1668b92 --- /dev/null +++ b/cvat/apps/iam/forms.py @@ -0,0 +1,48 @@ +# Copyright (C) 2022 CVAT.ai Corporation +# +# SPDX-License-Identifier: MIT + +from django.contrib.sites.shortcuts import get_current_site +from django.contrib.auth import get_user_model + +from allauth.account.forms import default_token_generator +from allauth.account.utils import user_pk_to_url_str +from allauth.account.adapter import get_adapter +from dj_rest_auth.forms import AllAuthPasswordResetForm + +UserModel = get_user_model() + +class ResetPasswordFormEx(AllAuthPasswordResetForm): + def save(self, request=None, domain_override=None, + email_template_prefix='authentication/password_reset_key', + use_https=False, token_generator=default_token_generator, + extra_email_context=None, **kwargs): + + """ + Generate a one-use only link for resetting password and send it to the + user. + """ + email = self.cleaned_data["email"] + if not domain_override: + current_site = get_current_site(request) + site_name = current_site.name + domain = current_site.domain + else: + site_name = domain = domain_override + email_field_name = UserModel.get_email_field_name() + for user in self.users: + user_email = getattr(user, email_field_name) + context = { + 'email': user_email, + 'domain': domain, + 'site_name': site_name, + 'uid': user_pk_to_url_str(user), + 'user': user, + 'token': token_generator.make_token(user), + 'protocol': 'https' if use_https else 'http', + **(extra_email_context or {}), + } + + get_adapter(request).send_mail(email_template_prefix, email, context) + + return self.cleaned_data['email'] diff --git a/cvat/apps/iam/serializers.py b/cvat/apps/iam/serializers.py index 79cf7e23..c1ec0e4e 100644 --- a/cvat/apps/iam/serializers.py +++ b/cvat/apps/iam/serializers.py @@ -9,6 +9,8 @@ from rest_framework import serializers from django.conf import settings +from cvat.apps.iam.forms import ResetPasswordFormEx + class RegisterSerializerEx(RegisterSerializer): first_name = serializers.CharField(required=False) last_name = serializers.CharField(required=False) @@ -23,6 +25,10 @@ class RegisterSerializerEx(RegisterSerializer): return data class PasswordResetSerializerEx(PasswordResetSerializer): + @property + def password_reset_form_class(self): + return ResetPasswordFormEx + def get_email_options(self): domain = None if hasattr(settings, 'UI_HOST') and settings.UI_HOST: @@ -30,6 +36,5 @@ class PasswordResetSerializerEx(PasswordResetSerializer): if hasattr(settings, 'UI_PORT') and settings.UI_PORT: domain += ':{}'.format(settings.UI_PORT) return { - 'email_template_name': 'authentication/password_reset_email.html', 'domain_override': domain } diff --git a/cvat/apps/iam/templates/authentication/password_reset_key_message.html b/cvat/apps/iam/templates/authentication/password_reset_key_message.html new file mode 100644 index 00000000..bc12e459 --- /dev/null +++ b/cvat/apps/iam/templates/authentication/password_reset_key_message.html @@ -0,0 +1,24 @@ +{% load i18n %}{% autoescape off %} +{% blocktrans %} +

+ You're receiving this email because you requested a password reset for your user account at {{ site_name }}. +

+{% endblocktrans %} + +{% trans "Please go to the following page and choose a new password:" %} +{% block reset_link %} +

+{{ protocol }}://{{ domain }}/auth/password/reset/confirm?uid={{ uid }}&token={{ token }} +

+{% endblock %} +

+{% trans "Your username, in case you've forgotten:" %} {{ user.get_username }} +

+ +{% trans "Thanks for using our site!" %} + +

+{% blocktrans %}The {{ site_name }} team{% endblocktrans %} +

+ +{% endautoescape %} diff --git a/cvat/apps/iam/templates/authentication/password_reset_email.html b/cvat/apps/iam/templates/authentication/password_reset_key_message.txt similarity index 100% rename from cvat/apps/iam/templates/authentication/password_reset_email.html rename to cvat/apps/iam/templates/authentication/password_reset_key_message.txt diff --git a/cvat/apps/iam/templates/authentication/password_reset_key_subject.txt b/cvat/apps/iam/templates/authentication/password_reset_key_subject.txt new file mode 100644 index 00000000..6840c40b --- /dev/null +++ b/cvat/apps/iam/templates/authentication/password_reset_key_subject.txt @@ -0,0 +1,4 @@ +{% load i18n %} +{% autoescape off %} +{% blocktrans %}Password Reset E-mail{% endblocktrans %} +{% endautoescape %}