From 3ccf32ed483cc40da153ee5756e2540965eea166 Mon Sep 17 00:00:00 2001 From: Bai Date: Tue, 29 Sep 2020 15:31:45 +0800 Subject: [PATCH] =?UTF-8?q?feat(authentication):=20=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E9=87=8D=E7=BD=AE=E5=AF=86=E7=A0=81=E6=88=90=E5=8A=9F=E5=90=8E?= =?UTF-8?q?=EF=BC=8C=E5=8F=91=E9=80=81=E7=94=A8=E6=88=B7=E9=87=8D=E7=BD=AE?= =?UTF-8?q?=E5=AF=86=E7=A0=81=E6=88=90=E5=8A=9F=E9=82=AE=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/utils/common.py | 5 ++++ apps/users/models/user.py | 12 ++++++--- apps/users/utils.py | 41 ++++++++++++++++++++++++++++++- apps/users/views/profile/reset.py | 4 ++- 4 files changed, 56 insertions(+), 6 deletions(-) diff --git a/apps/common/utils/common.py b/apps/common/utils/common.py index fc9137814..63a5afff9 100644 --- a/apps/common/utils/common.py +++ b/apps/common/utils/common.py @@ -164,6 +164,11 @@ def get_request_ip_or_data(request): return ip +def get_request_user_agent(request): + user_agent = request.META.get('HTTP_USER_AGENT', '') + return user_agent + + def validate_ip(ip): try: ipaddress.ip_address(ip) diff --git a/apps/users/models/user.py b/apps/users/models/user.py index f0f2ec896..22adab238 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -393,16 +393,20 @@ class TokenMixin: @classmethod def validate_reset_password_token(cls, token): + if not token: + return None + key = cls.CACHE_KEY_USER_RESET_PASSWORD_PREFIX.format(token) + value = cache.get(key) + if not value: + return None try: - key = cls.CACHE_KEY_USER_RESET_PASSWORD_PREFIX.format(token) - value = cache.get(key) user_id = value.get('id', '') email = value.get('email', '') user = cls.objects.get(id=user_id, email=email) + return user except (AttributeError, cls.DoesNotExist) as e: logger.error(e, exc_info=True) - user = None - return user + return None def set_cache(self, token): key = self.CACHE_KEY_USER_RESET_PASSWORD_PREFIX.format(token) diff --git a/apps/users/utils.py b/apps/users/utils.py index cf6be4c67..99bdb5902 100644 --- a/apps/users/utils.py +++ b/apps/users/utils.py @@ -13,7 +13,7 @@ from django.core.cache import cache from datetime import datetime from common.tasks import send_mail_async -from common.utils import reverse, get_object_or_none +from common.utils import reverse, get_object_or_none, get_request_ip_or_data, get_request_user_agent from .models import User @@ -112,6 +112,45 @@ def send_reset_password_mail(user): send_mail_async.delay(subject, message, recipient_list, html_message=message) +def send_reset_password_success_mail(request, user): + subject = _('Reset password success') + recipient_list = [user.email] + message = _(""" + + Hi %(name)s: +
+ + +
+ Your JumpServer password has just been successfully updated. +
+ +
+ If the password update was not initiated by you, your account may have security issues. + It is recommended that you log on to the JumpServer immediately and change your password. +
+ +
+ If you have any questions, you can contact the administrator. +
+
+ --- +
+
+ IP Address: %(ip_address)s +
+
+ Browser: %(browser)s +
+ + """) % { + 'name': user.name, + 'ip_address': get_request_ip_or_data(request), + 'browser': get_request_user_agent(request), + } + send_mail_async.delay(subject, message, recipient_list, html_message=message) + + def send_password_expiration_reminder_mail(user): subject = _('Security notice') recipient_list = [user.email] diff --git a/apps/users/views/profile/reset.py b/apps/users/views/profile/reset.py index 32b44f861..c25726561 100644 --- a/apps/users/views/profile/reset.py +++ b/apps/users/views/profile/reset.py @@ -16,7 +16,8 @@ from common.utils import get_object_or_none from common.permissions import PermissionsMixin, IsValidUser from ...models import User from ...utils import ( - send_reset_password_mail, get_password_check_rules, check_password_rules + send_reset_password_mail, get_password_check_rules, check_password_rules, + send_reset_password_success_mail ) from ... import forms @@ -126,6 +127,7 @@ class UserResetPasswordView(FormView): user.reset_password(password) User.expired_reset_password_token(token) + send_reset_password_success_mail(self.request, user) return redirect('authentication:reset-password-success')