From 513fcb458589efeef81451922fd54c363b056d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E6=B0=B8=E5=BC=BA?= <11704063+s-yongqiang@user.noreply.gitee.com> Date: Fri, 14 Jun 2024 17:53:37 +0800 Subject: [PATCH 1/9] send emails to new device login user --- seahub/api2/utils.py | 13 +++++++++++ seahub/auth/views.py | 17 +++++++++++++- .../registration/new_device_login_email.html | 22 +++++++++++++++++++ .../registration/password_change_email.html | 20 +++++++++++++++++ 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 seahub/templates/registration/new_device_login_email.html create mode 100644 seahub/templates/registration/password_change_email.html diff --git a/seahub/api2/utils.py b/seahub/api2/utils.py index 6c5f35218ab..0b758337e33 100644 --- a/seahub/api2/utils.py +++ b/seahub/api2/utils.py @@ -34,6 +34,8 @@ from seahub.utils.mail import send_html_email_with_dj_template from django.utils.translation import gettext as _ from seahub.settings import SECRET_KEY +from seahub.utils import send_html_email +from seahub.utils import get_site_name logger = logging.getLogger(__name__) @@ -207,6 +209,17 @@ def get_token_v2(request, username, platform, device_id, device_name, raise serializers.ValidationError('invalid device id') else: raise serializers.ValidationError('invalid platform') + + try: + TokenV2.objects.get(user=username, device_id=device_id) + except TokenV2.DoesNotExist: + email_template_name='registration/new_device_login_email.html' + send_to = email2contact_email(username) + site_name = get_site_name() + c = {'email': send_to} + send_html_email(_("New Device Login on %s") % site_name, + email_template_name, c, None, + [send_to]) return TokenV2.objects.get_or_create_token( username, platform, device_id, device_name, diff --git a/seahub/auth/views.py b/seahub/auth/views.py index ef95a11ce7d..cbd71253013 100644 --- a/seahub/auth/views.py +++ b/seahub/auth/views.py @@ -50,6 +50,10 @@ from seahub.onlyoffice.settings import ONLYOFFICE_DESKTOP_EDITOR_HTTP_USER_AGENT +from seahub.utils import send_html_email +from django.utils.translation import gettext_lazy as _ +from seahub.base.templatetags.seahub_tags import email2contact_email + # Get an instance of a logger logger = logging.getLogger(__name__) @@ -107,7 +111,8 @@ def login(request, template_name='registration/login.html', return HttpResponseRedirect(reverse(redirect_if_logged_in)) ip = get_remote_ip(request) - + print('ip',ip) + print(request.headers.get('User-Agent',None)) if request.method == "POST": login = request.POST.get('login', '').strip() failed_attempt = get_login_failed_attempts(username=login, ip=ip) @@ -482,6 +487,16 @@ def password_change(request, template_name='registration/password_change_form.ht if form.is_valid(): form.save() + email_template_name = 'registration/password_change_email.html' + send_to = email2contact_email(request.user.username) + site_name = get_site_name() + c = { + 'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S') + } + send_html_email(_("Successfully Changed Password on %s") % site_name, + email_template_name, c, None, + [send_to]) + if request.session.get('force_passwd_change', False): del request.session['force_passwd_change'] UserOptions.objects.unset_force_passwd_change( diff --git a/seahub/templates/registration/new_device_login_email.html b/seahub/templates/registration/new_device_login_email.html new file mode 100644 index 00000000000..fa1e9a9e4e8 --- /dev/null +++ b/seahub/templates/registration/new_device_login_email.html @@ -0,0 +1,22 @@ +{% extends 'email_base.html' %} + +{% load i18n %} + +{% block email_con %} + +{% autoescape off %} + +

{% trans "Hi," %}

+ +

+{% blocktrans with account=email %}You are attempting to log in to your account {{ account }} on {{ site_name }} using a new device{% endblocktrans %} +

+ + +

+{% trans "If you have not attempted to login with a new device, please change your password as soon as possible." %} +

+ +{% endautoescape %} + +{% endblock %} diff --git a/seahub/templates/registration/password_change_email.html b/seahub/templates/registration/password_change_email.html new file mode 100644 index 00000000000..6c035893a72 --- /dev/null +++ b/seahub/templates/registration/password_change_email.html @@ -0,0 +1,20 @@ +{% extends 'email_base.html' %} + +{% load i18n %} + +{% block email_con %} + +{% autoescape off %} + +

{% trans "Hi," %}

+ +

+{% blocktrans with account=email %}You submitted a password change request on {{ time }}. {% endblocktrans %} +

+

+{% trans "You have successfully changed your password!" %} +

+ +{% endautoescape %} + +{% endblock %} From 96b59b7e3d9683b235ded8589249b7a5e1fd4528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E6=B0=B8=E5=BC=BA?= <11704063+s-yongqiang@user.noreply.gitee.com> Date: Thu, 8 Aug 2024 15:24:21 +0800 Subject: [PATCH 2/9] update --- seahub/api2/endpoints/user.py | 13 +++++++++++-- seahub/auth/views.py | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/seahub/api2/endpoints/user.py b/seahub/api2/endpoints/user.py index be913aee466..89bd39f373d 100644 --- a/seahub/api2/endpoints/user.py +++ b/seahub/api2/endpoints/user.py @@ -1,5 +1,6 @@ # Copyright (c) 2012-2016 Seafile Ltd. import logging +from datetime import datetime from rest_framework import status from rest_framework.authentication import SessionAuthentication @@ -16,7 +17,7 @@ from seahub.organizations.settings import ORG_AUTO_URL_PREFIX from seahub.organizations.views import gen_org_url_prefix from seahub.password_session import update_session_auth_hash -from seahub.utils import is_valid_email +from seahub.utils import is_valid_email, send_html_email, get_site_name from seahub.api2.authentication import TokenAuthentication from seahub.api2.throttling import UserRateThrottle from seahub.api2.utils import api_error @@ -245,7 +246,15 @@ def post(self, request): user.set_password(new_password) user.save() - + email_template_name = 'registration/password_change_email.html' + send_to = email2contact_email(request.user.username) + site_name = get_site_name() + c = { + 'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S') + } + send_html_email(_("Successfully Changed Password on %s") % site_name, + email_template_name, c, None, + [send_to]) if not request.session.is_empty(): # update session auth hash update_session_auth_hash(request, request.user) diff --git a/seahub/auth/views.py b/seahub/auth/views.py index cbd71253013..bfd9afeb1d5 100644 --- a/seahub/auth/views.py +++ b/seahub/auth/views.py @@ -486,7 +486,7 @@ def password_change(request, template_name='registration/password_change_form.ht form = password_change_form(user=request.user, data=request.POST) if form.is_valid(): form.save() - + print('进入') email_template_name = 'registration/password_change_email.html' send_to = email2contact_email(request.user.username) site_name = get_site_name() From b85dd6b829f5843712013e971425a19f0d323dee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E6=B0=B8=E5=BC=BA?= <11704063+s-yongqiang@user.noreply.gitee.com> Date: Tue, 13 Aug 2024 17:11:47 +0800 Subject: [PATCH 3/9] update --- seahub/auth/views.py | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/seahub/auth/views.py b/seahub/auth/views.py index bfd9afeb1d5..b163bdd7332 100644 --- a/seahub/auth/views.py +++ b/seahub/auth/views.py @@ -43,6 +43,7 @@ from seahub.utils.user_permissions import get_user_role from seahub.utils.auth import get_login_bg_image_path from seahub.organizations.models import OrgSAMLConfig +from seahub.sysadmin_extra.models import UserLoginLog from constance import config @@ -77,7 +78,16 @@ def log_user_in(request, user, redirect_to): # Okay, security checks complete. Log the user in. auth_login(request, user) - + # if UserLoginLog.objects.filter(username=user.username).count() == 1: + # email_template_name = 'registration/password_change_email.html' + # send_to = email2contact_email(request.user.username) + # site_name = get_site_name() + # c = { + # 'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S') + # } + # send_html_email(_("Successfully Changed Password on %s") % site_name, + # email_template_name, c, None, + # [send_to]) return HttpResponseRedirect(redirect_to) def _handle_login_form_valid(request, user, redirect_to, remember_me): @@ -111,15 +121,12 @@ def login(request, template_name='registration/login.html', return HttpResponseRedirect(reverse(redirect_if_logged_in)) ip = get_remote_ip(request) - print('ip',ip) - print(request.headers.get('User-Agent',None)) if request.method == "POST": login = request.POST.get('login', '').strip() failed_attempt = get_login_failed_attempts(username=login, ip=ip) remember_me = True if request.POST.get('remember_me', '') == 'on' else False redirect_to = request.POST.get(redirect_field_name, '') or redirect_to - # check the form used_captcha_already = False if bool(config.FREEZE_USER_ON_LOGIN_FAILED) is True: @@ -130,7 +137,6 @@ def login(request, template_name='registration/login.html', used_captcha_already = True else: form = authentication_form(data=request.POST) - if form.is_valid(): return _handle_login_form_valid(request, form.get_user(), redirect_to, remember_me) @@ -486,16 +492,6 @@ def password_change(request, template_name='registration/password_change_form.ht form = password_change_form(user=request.user, data=request.POST) if form.is_valid(): form.save() - print('进入') - email_template_name = 'registration/password_change_email.html' - send_to = email2contact_email(request.user.username) - site_name = get_site_name() - c = { - 'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S') - } - send_html_email(_("Successfully Changed Password on %s") % site_name, - email_template_name, c, None, - [send_to]) if request.session.get('force_passwd_change', False): del request.session['force_passwd_change'] From 062f7e929d53b12867fa375c9392f4574d848403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E6=B0=B8=E5=BC=BA?= <11704063+s-yongqiang@user.noreply.gitee.com> Date: Wed, 14 Aug 2024 13:59:27 +0800 Subject: [PATCH 4/9] Update notification content --- seahub/api2/endpoints/user.py | 11 ++++++--- seahub/api2/utils.py | 18 +++++++------- seahub/auth/views.py | 24 +++++++++++-------- .../registration/browse_login_email.html | 20 ++++++++++++++++ .../registration/new_device_login_email.html | 5 ++-- .../registration/password_change_email.html | 7 ++---- 6 files changed, 55 insertions(+), 30 deletions(-) create mode 100644 seahub/templates/registration/browse_login_email.html diff --git a/seahub/api2/endpoints/user.py b/seahub/api2/endpoints/user.py index 89bd39f373d..419302ee75a 100644 --- a/seahub/api2/endpoints/user.py +++ b/seahub/api2/endpoints/user.py @@ -250,11 +250,16 @@ def post(self, request): send_to = email2contact_email(request.user.username) site_name = get_site_name() c = { + 'email': send_to, 'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S') } - send_html_email(_("Successfully Changed Password on %s") % site_name, - email_template_name, c, None, - [send_to]) + try: + send_html_email(_("Successfully Changed Password on %s") % site_name, + email_template_name, c, None, + [send_to]) + except Exception as e: + logger.error('Failed to send notification to %s' % send_to) + if not request.session.is_empty(): # update session auth hash update_session_auth_hash(request, request.user) diff --git a/seahub/api2/utils.py b/seahub/api2/utils.py index 0b758337e33..8678477d15a 100644 --- a/seahub/api2/utils.py +++ b/seahub/api2/utils.py @@ -34,8 +34,7 @@ from seahub.utils.mail import send_html_email_with_dj_template from django.utils.translation import gettext as _ from seahub.settings import SECRET_KEY -from seahub.utils import send_html_email -from seahub.utils import get_site_name +from seahub.utils import send_html_email, get_site_name logger = logging.getLogger(__name__) @@ -209,17 +208,18 @@ def get_token_v2(request, username, platform, device_id, device_name, raise serializers.ValidationError('invalid device id') else: raise serializers.ValidationError('invalid platform') - - try: - TokenV2.objects.get(user=username, device_id=device_id) - except TokenV2.DoesNotExist: + + if not TokenV2.objects.filter(user=username, device_id=device_id).first(): email_template_name='registration/new_device_login_email.html' send_to = email2contact_email(username) site_name = get_site_name() c = {'email': send_to} - send_html_email(_("New Device Login on %s") % site_name, - email_template_name, c, None, - [send_to]) + try: + send_html_email(_("New Device Login on %s") % site_name, + email_template_name, c, None, + [send_to]) + except Exception as e: + logger.error('Failed to send notification to %s' % send_to) return TokenV2.objects.get_or_create_token( username, platform, device_id, device_name, diff --git a/seahub/auth/views.py b/seahub/auth/views.py index b163bdd7332..27084d44c25 100644 --- a/seahub/auth/views.py +++ b/seahub/auth/views.py @@ -78,16 +78,20 @@ def log_user_in(request, user, redirect_to): # Okay, security checks complete. Log the user in. auth_login(request, user) - # if UserLoginLog.objects.filter(username=user.username).count() == 1: - # email_template_name = 'registration/password_change_email.html' - # send_to = email2contact_email(request.user.username) - # site_name = get_site_name() - # c = { - # 'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S') - # } - # send_html_email(_("Successfully Changed Password on %s") % site_name, - # email_template_name, c, None, - # [send_to]) + if UserLoginLog.objects.filter(username=user.username, login_success=1).count() == 1: + email_template_name = 'registration/browse_login_email.html' + send_to = email2contact_email(request.user.username) + site_name = get_site_name() + c = { + 'email': send_to + } + try: + send_html_email(_("%s account login reminder") % site_name, + email_template_name, c, None, + [send_to]) + except Exception as e: + logger.error(e) + return HttpResponseRedirect(redirect_to) def _handle_login_form_valid(request, user, redirect_to, remember_me): diff --git a/seahub/templates/registration/browse_login_email.html b/seahub/templates/registration/browse_login_email.html new file mode 100644 index 00000000000..9b90f9f436c --- /dev/null +++ b/seahub/templates/registration/browse_login_email.html @@ -0,0 +1,20 @@ +{% extends 'email_base.html' %} + +{% load i18n %} + +{% block email_con %} + +{% autoescape off %} + +

{% trans "Hi," %}

+ +

+{% blocktrans with account=email %}You are currently logging into this site using a browser{% endblocktrans %} +

+

+{{ email }} +

+ +{% endautoescape %} + +{% endblock %} diff --git a/seahub/templates/registration/new_device_login_email.html b/seahub/templates/registration/new_device_login_email.html index fa1e9a9e4e8..343e5c1e473 100644 --- a/seahub/templates/registration/new_device_login_email.html +++ b/seahub/templates/registration/new_device_login_email.html @@ -9,12 +9,11 @@

{% trans "Hi," %}

-{% blocktrans with account=email %}You are attempting to log in to your account {{ account }} on {{ site_name }} using a new device{% endblocktrans %} +{% blocktrans with account=email %}You are trying to log in to your account with a new device {{ account }}{% endblocktrans %}

-

-{% trans "If you have not attempted to login with a new device, please change your password as soon as possible." %} +{% trans "If you do not have this operation, please change your password as soon as possible." %}

{% endautoescape %} diff --git a/seahub/templates/registration/password_change_email.html b/seahub/templates/registration/password_change_email.html index 6c035893a72..00f17daa075 100644 --- a/seahub/templates/registration/password_change_email.html +++ b/seahub/templates/registration/password_change_email.html @@ -4,17 +4,14 @@ {% block email_con %} -{% autoescape off %} -

{% trans "Hi," %}

-{% blocktrans with account=email %}You submitted a password change request on {{ time }}. {% endblocktrans %} +{% blocktrans with account=email %}Your password was changed. {% endblocktrans %}

-{% trans "You have successfully changed your password!" %} +{{ email }}

-{% endautoescape %} {% endblock %} From 9f662cb190632421be97064d721326055746bdd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E6=B0=B8=E5=BC=BA?= <11704063+s-yongqiang@user.noreply.gitee.com> Date: Fri, 16 Aug 2024 09:48:19 +0800 Subject: [PATCH 5/9] add user config --- .../components/user-settings/email-notice.js | 64 +++++++++++++++++-- frontend/src/pages/dashboard/activity-item.js | 4 +- frontend/src/utils/user-api.js | 12 ++++ seahub/api2/endpoints/user.py | 30 +++++---- seahub/api2/utils.py | 5 +- seahub/api2/views.py | 23 +++++++ seahub/auth/__init__.py | 4 ++ seahub/auth/views.py | 5 +- seahub/options/models.py | 32 +++++++++- .../templates/profile/set_profile_react.html | 2 + seahub/profile/views.py | 5 ++ 11 files changed, 160 insertions(+), 26 deletions(-) diff --git a/frontend/src/components/user-settings/email-notice.js b/frontend/src/components/user-settings/email-notice.js index 286b603ed52..1d3d96a7bcd 100644 --- a/frontend/src/components/user-settings/email-notice.js +++ b/frontend/src/components/user-settings/email-notice.js @@ -1,12 +1,15 @@ import React from 'react'; import { gettext } from '../../utils/constants'; -import { seafileAPI } from '../../utils/seafile-api'; +import { userAPI } from '../../utils/user-api'; import { Utils } from '../../utils/utils'; import toaster from '../toast'; const { fileUpdatesEmailInterval, - collaborateEmailInterval + collaborateEmailInterval, + enableLoginEmail, + enablePasswordUpdateEmail, + } = window.app.pageOptions; class EmailNotice extends React.Component { @@ -28,9 +31,21 @@ class EmailNotice extends React.Component { { interval: 3600, text: gettext('Per hour') + ' (' + gettext('If notifications have not been read within one hour, they will be sent to your mailbox.') + ')' } ]; + this.passwordOption = [ + { enabled: 0, text: gettext('Don\'t send emails') }, + { enabled: 1, text: gettext('Send email after changing password') } + ]; + + this.loginOption = [ + { enabled: 0, text: gettext('Don\'t send emails') }, + { enabled: 1, text: gettext('Send an email when a new device or browser logs in for the first time') } + ]; + this.state = { fileUpdatesEmailInterval: fileUpdatesEmailInterval, - collaborateEmailInterval: collaborateEmailInterval + collaborateEmailInterval: collaborateEmailInterval, + enableLoginEmail: enableLoginEmail, + enablePasswordUpdateEmail: enablePasswordUpdateEmail }; } @@ -50,10 +65,26 @@ class EmailNotice extends React.Component { } }; + inputPasswordEmailEnabledChange = (e) => { + if (e.target.checked) { + this.setState({ + enablePasswordUpdateEmail: parseInt(e.target.value) + }); + } + }; + + inputLoginEmailEnabledChange = (e) => { + if (e.target.checked) { + this.setState({ + enableLoginEmail: parseInt(e.target.value) + }); + } + }; + formSubmit = (e) => { e.preventDefault(); - let { fileUpdatesEmailInterval, collaborateEmailInterval } = this.state; - seafileAPI.updateEmailNotificationInterval(fileUpdatesEmailInterval, collaborateEmailInterval).then((res) => { + let { fileUpdatesEmailInterval, collaborateEmailInterval, enablePasswordUpdateEmail, enableLoginEmail } = this.state; + userAPI.updateEmailNotificationInterval(fileUpdatesEmailInterval, collaborateEmailInterval, enablePasswordUpdateEmail, enableLoginEmail).then((res) => { toaster.success(gettext('Success')); }).catch((error) => { let errorMsg = Utils.getErrorMsg(error); @@ -62,7 +93,7 @@ class EmailNotice extends React.Component { }; render() { - const { fileUpdatesEmailInterval, collaborateEmailInterval } = this.state; + const { fileUpdatesEmailInterval, collaborateEmailInterval, enableLoginEmail, enablePasswordUpdateEmail } = this.state; return (

{gettext('Email Notification')}

@@ -88,6 +119,27 @@ class EmailNotice extends React.Component {
); })} + +

{gettext('Notifications of change password')}

+ {this.passwordOption.map((item, index) => { + return ( +
+ + +
+ ); + })} + +

{gettext('Notifications of login')}

+

{gettext('Send a mail as soon as a new device or browser has signed into the account (like google and many other services do).')}

+ {this.loginOption.map((item, index) => { + return ( +
+ + +
+ ); + })} diff --git a/frontend/src/pages/dashboard/activity-item.js b/frontend/src/pages/dashboard/activity-item.js index 1266f3bbebd..5dc4c633f90 100644 --- a/frontend/src/pages/dashboard/activity-item.js +++ b/frontend/src/pages/dashboard/activity-item.js @@ -37,13 +37,13 @@ class ActivityItem extends Component { this.setState({ isHighlighted: true }); - } + }; onMouseLeave = () => { this.setState({ isHighlighted: false }); - } + }; render() { const { isHighlighted } = this.state; diff --git a/frontend/src/utils/user-api.js b/frontend/src/utils/user-api.js index 7acf52c8046..15207419ae2 100644 --- a/frontend/src/utils/user-api.js +++ b/frontend/src/utils/user-api.js @@ -42,6 +42,18 @@ class UserAPI { }; return this.req.post(url, data); } + + updateEmailNotificationInterval(fileUpdatesEmailInterval, collaborateEmailInterval, enablePasswordUpdateEmail, enableLoginEmail) { + let url = this.server + '/api2/account/info/'; + let data = { + 'file_updates_email_interval': fileUpdatesEmailInterval, + 'collaborate_email_interval': collaborateEmailInterval, + 'enable_password_update_email': enablePasswordUpdateEmail, + 'enable_login_email': enableLoginEmail + }; + return this.req.put(url, data); + } + } let userAPI = new UserAPI(); diff --git a/seahub/api2/endpoints/user.py b/seahub/api2/endpoints/user.py index 419302ee75a..65023ffcace 100644 --- a/seahub/api2/endpoints/user.py +++ b/seahub/api2/endpoints/user.py @@ -25,6 +25,8 @@ email2contact_email from seahub.profile.models import Profile, DetailedProfile from seahub.settings import ENABLE_UPDATE_USER_INFO, ENABLE_USER_SET_CONTACT_EMAIL, ENABLE_CONVERT_TO_TEAM_ACCOUNT +from seahub.options.models import UserOptions + import seaserv from seaserv import ccnet_api, seafile_api @@ -246,19 +248,21 @@ def post(self, request): user.set_password(new_password) user.save() - email_template_name = 'registration/password_change_email.html' - send_to = email2contact_email(request.user.username) - site_name = get_site_name() - c = { - 'email': send_to, - 'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S') - } - try: - send_html_email(_("Successfully Changed Password on %s") % site_name, - email_template_name, c, None, - [send_to]) - except Exception as e: - logger.error('Failed to send notification to %s' % send_to) + enable_pwd_email = bool(UserOptions.objects.get_password_update_email_enable_status(user.username)) + if enable_pwd_email: + email_template_name = 'registration/password_change_email.html' + send_to = email2contact_email(request.user.username) + site_name = get_site_name() + c = { + 'email': send_to, + 'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S') + } + try: + send_html_email(_("Successfully Changed Password on %s") % site_name, + email_template_name, c, None, + [send_to]) + except Exception as e: + logger.error('Failed to send notification to %s' % send_to) if not request.session.is_empty(): # update session auth hash diff --git a/seahub/api2/utils.py b/seahub/api2/utils.py index 8678477d15a..4d6b47d44cc 100644 --- a/seahub/api2/utils.py +++ b/seahub/api2/utils.py @@ -35,6 +35,7 @@ from django.utils.translation import gettext as _ from seahub.settings import SECRET_KEY from seahub.utils import send_html_email, get_site_name +from seahub.options.models import UserOptions logger = logging.getLogger(__name__) @@ -208,8 +209,8 @@ def get_token_v2(request, username, platform, device_id, device_name, raise serializers.ValidationError('invalid device id') else: raise serializers.ValidationError('invalid platform') - - if not TokenV2.objects.filter(user=username, device_id=device_id).first(): + enable_new_device_email = bool(UserOptions.objects.get_login_email_enable_status(username)) + if not TokenV2.objects.filter(user=username, device_id=device_id).first() and enable_new_device_email: email_template_name='registration/new_device_login_email.html' send_to = email2contact_email(username) site_name = get_site_name() diff --git a/seahub/api2/views.py b/seahub/api2/views.py index c566349723a..96961f39540 100644 --- a/seahub/api2/views.py +++ b/seahub/api2/views.py @@ -383,6 +383,21 @@ def put(self, request, format=None): return api_error(status.HTTP_400_BAD_REQUEST, 'collaborate_email_interval invalid') + enable_login_email = request.data.get("enable_login_email", None) + if enable_login_email is not None: + try: + enable_login_email = int(enable_login_email) + except ValueError: + return api_error(status.HTTP_400_BAD_REQUEST, + 'enable_login_email invalid') + + enable_password_update_email = request.data.get("enable_password_update_email", None) + if enable_password_update_email is not None: + try: + enable_password_update_email = int(enable_password_update_email) + except ValueError: + return api_error(status.HTTP_400_BAD_REQUEST, + 'enable_password_update_email invalid') # update user info if name is not None: @@ -403,6 +418,14 @@ def put(self, request, format=None): UserOptions.objects.set_collaborate_email_interval( username, collaborate_email_interval) + if enable_password_update_email is not None: + UserOptions.objects.set_password_update_email_enable_status( + username, enable_password_update_email) + + if enable_login_email is not None: + UserOptions.objects.set_login_email_enable_status( + username, enable_login_email) + return Response(self._get_account_info(request)) diff --git a/seahub/auth/__init__.py b/seahub/auth/__init__.py index 1e5e4a918e5..12034f4dd60 100644 --- a/seahub/auth/__init__.py +++ b/seahub/auth/__init__.py @@ -106,7 +106,11 @@ def logout(request): session data. Also remove all passwords used to decrypt repos. """ + already_logged_list = request.session.get('_already_logged', []) request.session.flush() + if request.user.username not in already_logged_list: + already_logged_list.append(request.user.username) + request.session['_already_logged'] = already_logged_list if hasattr(request, 'user'): from seahub.base.accounts import User if isinstance(request.user, User): diff --git a/seahub/auth/views.py b/seahub/auth/views.py index 27084d44c25..5a885b7e037 100644 --- a/seahub/auth/views.py +++ b/seahub/auth/views.py @@ -43,7 +43,6 @@ from seahub.utils.user_permissions import get_user_role from seahub.utils.auth import get_login_bg_image_path from seahub.organizations.models import OrgSAMLConfig -from seahub.sysadmin_extra.models import UserLoginLog from constance import config @@ -78,7 +77,9 @@ def log_user_in(request, user, redirect_to): # Okay, security checks complete. Log the user in. auth_login(request, user) - if UserLoginLog.objects.filter(username=user.username, login_success=1).count() == 1: + enable_login_email = bool(UserOptions.objects.get_login_email_enable_status(user.username)) + already_logs = request.session.get('_already_logged', []) + if user.username not in already_logs and enable_login_email: email_template_name = 'registration/browse_login_email.html' send_to = email2contact_email(request.user.username) site_name = get_site_name() diff --git a/seahub/options/models.py b/seahub/options/models.py index 3166b552799..5a38c5f8328 100644 --- a/seahub/options/models.py +++ b/seahub/options/models.py @@ -38,9 +38,11 @@ KEY_FILE_UPDATES_LAST_EMAILED_TIME = "file_updates_last_emailed_time" KEY_COLLABORATE_EMAIL_INTERVAL = 'collaborate_email_interval' KEY_COLLABORATE_LAST_EMAILED_TIME = 'collaborate_last_emailed_time' +KEY_LOGIN_EMAIL_INTERVAL = 'enable_login_email' +KEY_PASSWD_UPDATE_EMAIL_INTERVAL = 'enable_password_update_email' DEFAULT_COLLABORATE_EMAIL_INTERVAL = 3600 - +DEFAULT_PWD_UPDATE_EMAIL_ENABLED = 1 class CryptoOptionNotSetError(Exception): pass @@ -346,6 +348,34 @@ def get_collaborate_last_emailed_time(self, username): def unset_collaborate_last_emailed_time(self, username): return self.unset_user_option(username, KEY_COLLABORATE_LAST_EMAILED_TIME) + def get_login_email_enable_status(self, username): + val = self.get_user_option(username, KEY_LOGIN_EMAIL_INTERVAL) + if not val: + return None + try: + return int(val) + except ValueError: + logger.error('Failed to convert string %s to int' % val) + return None + + def set_login_email_enable_status(self, username, enable): + return self.set_user_option(username, KEY_LOGIN_EMAIL_INTERVAL, + str(enable)) + + def get_password_update_email_enable_status(self, username): + val = self.get_user_option(username, KEY_PASSWD_UPDATE_EMAIL_INTERVAL) + if not val: + return DEFAULT_PWD_UPDATE_EMAIL_ENABLED + try: + return int(val) + except ValueError: + logger.error('Failed to convert string %s to int' % val) + return None + + def set_password_update_email_enable_status(self, username, enable): + return self.set_user_option(username, KEY_PASSWD_UPDATE_EMAIL_INTERVAL, + str(enable)) + class UserOptions(models.Model): email = LowerCaseCharField(max_length=255, db_index=True) diff --git a/seahub/profile/templates/profile/set_profile_react.html b/seahub/profile/templates/profile/set_profile_react.html index 7eb2baa2505..4689e4e4586 100644 --- a/seahub/profile/templates/profile/set_profile_react.html +++ b/seahub/profile/templates/profile/set_profile_react.html @@ -56,6 +56,8 @@ fileUpdatesEmailInterval: {{ file_updates_email_interval }}, collaborateEmailInterval: {{ collaborate_email_interval }}, + enablePasswordUpdateEmail: {{ enable_password_update_email }}, + enableLoginEmail: {{ enable_login_email }}, twoFactorAuthEnabled: {% if two_factor_auth_enabled %} true {% else %} false {% endif %}, {% if two_factor_auth_enabled %} diff --git a/seahub/profile/views.py b/seahub/profile/views.py index 4dfd51f8b11..96ec5a108e8 100644 --- a/seahub/profile/views.py +++ b/seahub/profile/views.py @@ -89,6 +89,9 @@ def edit_profile(request): file_updates_email_interval = file_updates_email_interval if file_updates_email_interval is not None else 0 collaborate_email_interval = UserOptions.objects.get_collaborate_email_interval(username) collaborate_email_interval = collaborate_email_interval if collaborate_email_interval is not None else DEFAULT_COLLABORATE_EMAIL_INTERVAL + enable_login_email = UserOptions.objects.get_login_email_enable_status(username) + enable_login_email = enable_login_email if enable_login_email is not None else 0 + enable_password_update_email = UserOptions.objects.get_password_update_email_enable_status(username) if work_weixin_oauth_check(): enable_wechat_work = True @@ -159,6 +162,8 @@ def edit_profile(request): 'ENABLE_UPDATE_USER_INFO': ENABLE_UPDATE_USER_INFO, 'file_updates_email_interval': file_updates_email_interval, 'collaborate_email_interval': collaborate_email_interval, + 'enable_password_update_email': enable_password_update_email, + 'enable_login_email': enable_login_email, 'social_next_page': reverse('edit_profile'), 'enable_wechat_work': enable_wechat_work, 'social_connected': social_connected, From faf2cae1c784efd0aac711ae85ae6fa3730e9aad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E6=B0=B8=E5=BC=BA?= <11704063+s-yongqiang@user.noreply.gitee.com> Date: Fri, 16 Aug 2024 10:02:08 +0800 Subject: [PATCH 6/9] optimize code --- seahub/api2/endpoints/user.py | 4 +--- seahub/auth/views.py | 3 +++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/seahub/api2/endpoints/user.py b/seahub/api2/endpoints/user.py index 65023ffcace..8c5a13c893d 100644 --- a/seahub/api2/endpoints/user.py +++ b/seahub/api2/endpoints/user.py @@ -1,6 +1,5 @@ # Copyright (c) 2012-2016 Seafile Ltd. import logging -from datetime import datetime from rest_framework import status from rest_framework.authentication import SessionAuthentication @@ -254,8 +253,7 @@ def post(self, request): send_to = email2contact_email(request.user.username) site_name = get_site_name() c = { - 'email': send_to, - 'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S') + 'email': send_to } try: send_html_email(_("Successfully Changed Password on %s") % site_name, diff --git a/seahub/auth/views.py b/seahub/auth/views.py index 5a885b7e037..3124f6457ed 100644 --- a/seahub/auth/views.py +++ b/seahub/auth/views.py @@ -108,6 +108,7 @@ def _handle_login_form_valid(request, user, redirect_to, remember_me): # password is valid, log user in request.session['remember_me'] = remember_me + return log_user_in(request, user, redirect_to) @csrf_protect @@ -132,6 +133,7 @@ def login(request, template_name='registration/login.html', remember_me = True if request.POST.get('remember_me', '') == 'on' else False redirect_to = request.POST.get(redirect_field_name, '') or redirect_to + # check the form used_captcha_already = False if bool(config.FREEZE_USER_ON_LOGIN_FAILED) is True: @@ -142,6 +144,7 @@ def login(request, template_name='registration/login.html', used_captcha_already = True else: form = authentication_form(data=request.POST) + if form.is_valid(): return _handle_login_form_valid(request, form.get_user(), redirect_to, remember_me) From 6cf1da61f903a86a42df8aa1f4f7493d97b7a7ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E6=B0=B8=E5=BC=BA?= <11704063+s-yongqiang@user.noreply.gitee.com> Date: Fri, 16 Aug 2024 15:39:09 +0800 Subject: [PATCH 7/9] update email content --- .../components/user-settings/email-notice.js | 3 +-- seahub/api2/utils.py | 8 ++++--- seahub/auth/__init__.py | 10 +++++---- seahub/auth/views.py | 14 ++++++------- .../registration/browse_login_email.html | 20 ------------------ .../templates/registration/login_email.html | 21 +++++++++++++++++++ .../registration/new_device_login_email.html | 21 ------------------- 7 files changed, 40 insertions(+), 57 deletions(-) delete mode 100644 seahub/templates/registration/browse_login_email.html create mode 100644 seahub/templates/registration/login_email.html delete mode 100644 seahub/templates/registration/new_device_login_email.html diff --git a/frontend/src/components/user-settings/email-notice.js b/frontend/src/components/user-settings/email-notice.js index 1d3d96a7bcd..fd4972cb17d 100644 --- a/frontend/src/components/user-settings/email-notice.js +++ b/frontend/src/components/user-settings/email-notice.js @@ -130,8 +130,7 @@ class EmailNotice extends React.Component { ); })} -

{gettext('Notifications of login')}

-

{gettext('Send a mail as soon as a new device or browser has signed into the account (like google and many other services do).')}

+

{gettext(' Send a mail as soon as a new device or browser has signed into the account')}

{this.loginOption.map((item, index) => { return (
diff --git a/seahub/api2/utils.py b/seahub/api2/utils.py index 4d6b47d44cc..6edd77cd350 100644 --- a/seahub/api2/utils.py +++ b/seahub/api2/utils.py @@ -211,12 +211,14 @@ def get_token_v2(request, username, platform, device_id, device_name, raise serializers.ValidationError('invalid platform') enable_new_device_email = bool(UserOptions.objects.get_login_email_enable_status(username)) if not TokenV2.objects.filter(user=username, device_id=device_id).first() and enable_new_device_email: - email_template_name='registration/new_device_login_email.html' + email_template_name='registration/login_email.html' send_to = email2contact_email(username) site_name = get_site_name() - c = {'email': send_to} + c = { + 'name': email2nickname(username) + } try: - send_html_email(_("New Device Login on %s") % site_name, + send_html_email(_("Welcome to %s") % site_name, email_template_name, c, None, [send_to]) except Exception as e: diff --git a/seahub/auth/__init__.py b/seahub/auth/__init__.py index 12034f4dd60..fa77022997e 100644 --- a/seahub/auth/__init__.py +++ b/seahub/auth/__init__.py @@ -11,6 +11,7 @@ from constance import config SESSION_KEY = '_auth_user_name' +SESSION_USERS_LOGIN = '_already_loging_users' BACKEND_SESSION_KEY = '_auth_user_backend_2' REDIRECT_FIELD_NAME = 'next' @@ -106,12 +107,13 @@ def logout(request): session data. Also remove all passwords used to decrypt repos. """ - already_logged_list = request.session.get('_already_logged', []) + already_logged_list = request.session.get(SESSION_USERS_LOGIN, []) request.session.flush() - if request.user.username not in already_logged_list: - already_logged_list.append(request.user.username) - request.session['_already_logged'] = already_logged_list if hasattr(request, 'user'): + username = request.user.username + if username not in already_logged_list: + already_logged_list.append(username) + request.session[SESSION_USERS_LOGIN] = already_logged_list from seahub.base.accounts import User if isinstance(request.user, User): # Do not directly/indirectly import models in package root level. diff --git a/seahub/auth/views.py b/seahub/auth/views.py index 3124f6457ed..a892eecfdd5 100644 --- a/seahub/auth/views.py +++ b/seahub/auth/views.py @@ -19,7 +19,7 @@ from seaserv import seafile_api, ccnet_api from seahub.auth import REDIRECT_FIELD_NAME, get_backends -from seahub.auth import login as auth_login +from seahub.auth import login as auth_login, SESSION_USERS_LOGIN from seahub.auth.models import SocialAuthUser from seahub.auth.decorators import login_required from seahub.auth.forms import AuthenticationForm, CaptchaAuthenticationForm, \ @@ -52,7 +52,7 @@ from seahub.utils import send_html_email from django.utils.translation import gettext_lazy as _ -from seahub.base.templatetags.seahub_tags import email2contact_email +from seahub.base.templatetags.seahub_tags import email2contact_email, email2nickname # Get an instance of a logger logger = logging.getLogger(__name__) @@ -78,16 +78,16 @@ def log_user_in(request, user, redirect_to): # Okay, security checks complete. Log the user in. auth_login(request, user) enable_login_email = bool(UserOptions.objects.get_login_email_enable_status(user.username)) - already_logs = request.session.get('_already_logged', []) - if user.username not in already_logs and enable_login_email: - email_template_name = 'registration/browse_login_email.html' + already_login_users = request.session.get(SESSION_USERS_LOGIN, []) + if user.username not in already_login_users and enable_login_email: + email_template_name = 'registration/login_email.html' send_to = email2contact_email(request.user.username) site_name = get_site_name() c = { - 'email': send_to + 'name': email2nickname(user.username) } try: - send_html_email(_("%s account login reminder") % site_name, + send_html_email(_("Welcome to %s") % site_name, email_template_name, c, None, [send_to]) except Exception as e: diff --git a/seahub/templates/registration/browse_login_email.html b/seahub/templates/registration/browse_login_email.html deleted file mode 100644 index 9b90f9f436c..00000000000 --- a/seahub/templates/registration/browse_login_email.html +++ /dev/null @@ -1,20 +0,0 @@ -{% extends 'email_base.html' %} - -{% load i18n %} - -{% block email_con %} - -{% autoescape off %} - -

{% trans "Hi," %}

- -

-{% blocktrans with account=email %}You are currently logging into this site using a browser{% endblocktrans %} -

-

-{{ email }} -

- -{% endautoescape %} - -{% endblock %} diff --git a/seahub/templates/registration/login_email.html b/seahub/templates/registration/login_email.html new file mode 100644 index 00000000000..b0dcbb6443e --- /dev/null +++ b/seahub/templates/registration/login_email.html @@ -0,0 +1,21 @@ +{% extends 'email_base.html' %} + +{% load i18n %} + +{% block email_con %} + +{% autoescape off %} + +

+{% blocktrans with account=name %}Dear, {{ account }}{% endblocktrans %} +

+

+Greetings! +

+

+{% trans " We are thrilled to inform you that you have successfully joined Seafile - a cloud-based platform dedicated to file management and team collaboration. Here, you'll find seamless and secure digital workspaces for document sharing, version control, and teamwork." %} +

+ +{% endautoescape %} + +{% endblock %} diff --git a/seahub/templates/registration/new_device_login_email.html b/seahub/templates/registration/new_device_login_email.html deleted file mode 100644 index 343e5c1e473..00000000000 --- a/seahub/templates/registration/new_device_login_email.html +++ /dev/null @@ -1,21 +0,0 @@ -{% extends 'email_base.html' %} - -{% load i18n %} - -{% block email_con %} - -{% autoescape off %} - -

{% trans "Hi," %}

- -

-{% blocktrans with account=email %}You are trying to log in to your account with a new device {{ account }}{% endblocktrans %} -

- -

-{% trans "If you do not have this operation, please change your password as soon as possible." %} -

- -{% endautoescape %} - -{% endblock %} From 36b52bc049afed1a16dd7c3b3040a7c286f4c87d Mon Sep 17 00:00:00 2001 From: r350178982 <32759763+r350178982@users.noreply.github.com> Date: Tue, 20 Aug 2024 15:31:12 +0800 Subject: [PATCH 8/9] update --- seahub/api2/endpoints/user.py | 10 ++++--- seahub/api2/utils.py | 27 ++++++++----------- seahub/auth/utils.py | 22 +++++++++++++-- seahub/auth/views.py | 20 ++++---------- .../templates/registration/login_email.html | 6 ++++- .../registration/password_change_email.html | 14 +++++++--- 6 files changed, 58 insertions(+), 41 deletions(-) diff --git a/seahub/api2/endpoints/user.py b/seahub/api2/endpoints/user.py index 8c5a13c893d..c9f7a37141d 100644 --- a/seahub/api2/endpoints/user.py +++ b/seahub/api2/endpoints/user.py @@ -16,7 +16,7 @@ from seahub.organizations.settings import ORG_AUTO_URL_PREFIX from seahub.organizations.views import gen_org_url_prefix from seahub.password_session import update_session_auth_hash -from seahub.utils import is_valid_email, send_html_email, get_site_name +from seahub.utils import is_valid_email, send_html_email, get_site_name, IS_EMAIL_CONFIGURED from seahub.api2.authentication import TokenAuthentication from seahub.api2.throttling import UserRateThrottle from seahub.api2.utils import api_error @@ -248,15 +248,17 @@ def post(self, request): user.set_password(new_password) user.save() enable_pwd_email = bool(UserOptions.objects.get_password_update_email_enable_status(user.username)) - if enable_pwd_email: + + if IS_EMAIL_CONFIGURED and enable_pwd_email: email_template_name = 'registration/password_change_email.html' send_to = email2contact_email(request.user.username) site_name = get_site_name() c = { - 'email': send_to + 'email': send_to, + 'name': email2nickname(user.username) } try: - send_html_email(_("Successfully Changed Password on %s") % site_name, + send_html_email(_("[%s]Your Password Has Been Successfully Updated") % site_name, email_template_name, c, None, [send_to]) except Exception as e: diff --git a/seahub/api2/utils.py b/seahub/api2/utils.py index 6edd77cd350..63223a4df6e 100644 --- a/seahub/api2/utils.py +++ b/seahub/api2/utils.py @@ -22,6 +22,7 @@ get_group, seafserv_threaded_rpc from pysearpc import SearpcError +from seahub.auth.utils import send_login_email from seahub.base.templatetags.seahub_tags import email2nickname, \ translate_seahub_time, file_icon_filter, email2contact_email from seahub.constants import REPO_TYPE_WIKI @@ -30,7 +31,7 @@ from seahub.api2.models import Token, TokenV2, DESKTOP_PLATFORMS from seahub.avatar.settings import AVATAR_DEFAULT_SIZE from seahub.avatar.templatetags.avatar_tags import api_avatar_url -from seahub.utils import get_user_repos +from seahub.utils import get_user_repos, IS_EMAIL_CONFIGURED from seahub.utils.mail import send_html_email_with_dj_template from django.utils.translation import gettext as _ from seahub.settings import SECRET_KEY @@ -190,6 +191,7 @@ def get_token_v1(username): return token _ANDROID_DEVICE_ID_PATTERN = re.compile('^[a-f0-9]{1,16}$') + def get_token_v2(request, username, platform, device_id, device_name, client_version, platform_version): @@ -210,23 +212,16 @@ def get_token_v2(request, username, platform, device_id, device_name, else: raise serializers.ValidationError('invalid platform') enable_new_device_email = bool(UserOptions.objects.get_login_email_enable_status(username)) - if not TokenV2.objects.filter(user=username, device_id=device_id).first() and enable_new_device_email: - email_template_name='registration/login_email.html' - send_to = email2contact_email(username) - site_name = get_site_name() - c = { - 'name': email2nickname(username) - } - try: - send_html_email(_("Welcome to %s") % site_name, - email_template_name, c, None, - [send_to]) - except Exception as e: - logger.error('Failed to send notification to %s' % send_to) - - return TokenV2.objects.get_or_create_token( + + has_device = TokenV2.objects.filter(user=username, device_id=device_id, platform=platform).first() + token = TokenV2.objects.get_or_create_token( username, platform, device_id, device_name, client_version, platform_version, get_client_ip(request)) + + if IS_EMAIL_CONFIGURED and enable_new_device_email and (not has_device): + send_login_email(username) + + return token def get_api_token(request, keys=None, key_prefix='shib_'): diff --git a/seahub/auth/utils.py b/seahub/auth/utils.py index 893e8ed4257..6bd101fb7f2 100644 --- a/seahub/auth/utils.py +++ b/seahub/auth/utils.py @@ -1,13 +1,15 @@ # Copyright (c) 2012-2016 Seafile Ltd. +import logging from django.core.cache import cache from django.conf import settings +from django.utils.translation import gettext as _ from seahub.profile.models import Profile -from seahub.utils import normalize_cache_key +from seahub.utils import normalize_cache_key, get_site_name, send_html_email from seahub.utils.ip import get_remote_ip LOGIN_ATTEMPT_PREFIX = 'UserLoginAttempt_' - +logger = logging.getLogger(__name__) def get_login_failed_attempts(username=None, ip=None): """Get login failed attempts base on username and ip. @@ -84,3 +86,19 @@ def get_virtual_id_by_email(email): return email else: return p.user + + +def send_login_email(username): + from seahub.base.templatetags.seahub_tags import email2contact_email, email2nickname + email_template_name = 'registration/login_email.html' + send_to = email2contact_email(username) + site_name = get_site_name() + c = { + 'name': email2nickname(username) + } + try: + send_html_email(_("Welcome to %s") % site_name, + email_template_name, c, None, + [send_to]) + except Exception as e: + logger.error('Failed to send notification to %s, %s' % (send_to, e)) diff --git a/seahub/auth/views.py b/seahub/auth/views.py index a892eecfdd5..ea6ab92e6eb 100644 --- a/seahub/auth/views.py +++ b/seahub/auth/views.py @@ -29,12 +29,12 @@ from seahub.auth.tokens import default_token_generator from seahub.auth.utils import ( get_login_failed_attempts, incr_login_failed_attempts, - clear_login_failed_attempts) + clear_login_failed_attempts, send_login_email) from seahub.base.accounts import User, UNUSABLE_PASSWORD from seahub.options.models import UserOptions from seahub.profile.models import Profile from seahub.two_factor.views.login import is_device_remembered -from seahub.utils import render_error, get_site_name, is_valid_email, get_service_url +from seahub.utils import render_error, get_site_name, is_valid_email, get_service_url, IS_EMAIL_CONFIGURED from seahub.utils.http import rate_limit from seahub.utils.ip import get_remote_ip from seahub.utils.file_size import get_quota_from_string @@ -79,19 +79,9 @@ def log_user_in(request, user, redirect_to): auth_login(request, user) enable_login_email = bool(UserOptions.objects.get_login_email_enable_status(user.username)) already_login_users = request.session.get(SESSION_USERS_LOGIN, []) - if user.username not in already_login_users and enable_login_email: - email_template_name = 'registration/login_email.html' - send_to = email2contact_email(request.user.username) - site_name = get_site_name() - c = { - 'name': email2nickname(user.username) - } - try: - send_html_email(_("Welcome to %s") % site_name, - email_template_name, c, None, - [send_to]) - except Exception as e: - logger.error(e) + + if IS_EMAIL_CONFIGURED and (user.username not in already_login_users) and enable_login_email: + send_login_email(user.username) return HttpResponseRedirect(redirect_to) diff --git a/seahub/templates/registration/login_email.html b/seahub/templates/registration/login_email.html index b0dcbb6443e..6117cda9890 100644 --- a/seahub/templates/registration/login_email.html +++ b/seahub/templates/registration/login_email.html @@ -10,10 +10,14 @@ {% blocktrans with account=name %}Dear, {{ account }}{% endblocktrans %}

+{% blocktrans %} Greetings! +{% endblocktrans %}

-{% trans " We are thrilled to inform you that you have successfully joined Seafile - a cloud-based platform dedicated to file management and team collaboration. Here, you'll find seamless and secure digital workspaces for document sharing, version control, and teamwork." %} +{% blocktrans %} + We are thrilled to inform you that you have successfully joined {{ site_name }} - a cloud-based platform dedicated to file management and team collaboration. Here, you'll find seamless and secure digital workspaces for document sharing, version control, and teamwork. +{% endblocktrans %}

{% endautoescape %} diff --git a/seahub/templates/registration/password_change_email.html b/seahub/templates/registration/password_change_email.html index 00f17daa075..85986770902 100644 --- a/seahub/templates/registration/password_change_email.html +++ b/seahub/templates/registration/password_change_email.html @@ -4,14 +4,22 @@ {% block email_con %} -

{% trans "Hi," %}

+{% autoescape off %}

-{% blocktrans with account=email %}Your password was changed. {% endblocktrans %} +{% blocktrans with account=name %}Dear, {{ account }}{% endblocktrans %}

-{{ email }} +{% blocktrans %} +Greetings! +{% endblocktrans %} +

+

+{% blocktrans %} + We are pleased to inform you that your password for {{ site_name }} has been successfully updated. To ensure the security of your account, we recommend regularly changing your password and avoiding simple or personally identifiable combinations. +{% endblocktrans %}

+{% endautoescape %} {% endblock %} From 87dda2e31b849f2f8b98ef4646fee6006da2ee46 Mon Sep 17 00:00:00 2001 From: r350178982 <32759763+r350178982@users.noreply.github.com> Date: Tue, 20 Aug 2024 15:46:34 +0800 Subject: [PATCH 9/9] code-optimize --- frontend/src/components/user-settings/email-notice.js | 2 +- frontend/src/utils/user-api.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/components/user-settings/email-notice.js b/frontend/src/components/user-settings/email-notice.js index fd4972cb17d..7d08be191ed 100644 --- a/frontend/src/components/user-settings/email-notice.js +++ b/frontend/src/components/user-settings/email-notice.js @@ -84,7 +84,7 @@ class EmailNotice extends React.Component { formSubmit = (e) => { e.preventDefault(); let { fileUpdatesEmailInterval, collaborateEmailInterval, enablePasswordUpdateEmail, enableLoginEmail } = this.state; - userAPI.updateEmailNotificationInterval(fileUpdatesEmailInterval, collaborateEmailInterval, enablePasswordUpdateEmail, enableLoginEmail).then((res) => { + userAPI.updateEmailNotificationConfig(fileUpdatesEmailInterval, collaborateEmailInterval, enablePasswordUpdateEmail, enableLoginEmail).then((res) => { toaster.success(gettext('Success')); }).catch((error) => { let errorMsg = Utils.getErrorMsg(error); diff --git a/frontend/src/utils/user-api.js b/frontend/src/utils/user-api.js index 15207419ae2..a2477304acf 100644 --- a/frontend/src/utils/user-api.js +++ b/frontend/src/utils/user-api.js @@ -43,7 +43,7 @@ class UserAPI { return this.req.post(url, data); } - updateEmailNotificationInterval(fileUpdatesEmailInterval, collaborateEmailInterval, enablePasswordUpdateEmail, enableLoginEmail) { + updateEmailNotificationConfig(fileUpdatesEmailInterval, collaborateEmailInterval, enablePasswordUpdateEmail, enableLoginEmail) { let url = this.server + '/api2/account/info/'; let data = { 'file_updates_email_interval': fileUpdatesEmailInterval,