mirror of https://github.com/jumpserver/jumpserver
pref: 修改使用的消息内容 (#7061)
* perf: 再次优化通知 * pref: 修改使用的消息内容 * perf: 修复url地址 Co-authored-by: ibuler <ibuler@qq.com>pull/7063/head
parent
a0db2f6ef8
commit
c244cf5f43
|
@ -12,7 +12,5 @@
|
|||
</p>
|
||||
|
||||
<p>
|
||||
<small>
|
||||
{% trans 'If you suspect that the login behavior is abnormal, please modify the account password in time.' %}
|
||||
</small>
|
||||
{% trans 'If you suspect that the login behavior is abnormal, please modify the account password in time.' %}
|
||||
</p>
|
|
@ -1,15 +1,17 @@
|
|||
{% load i18n %}
|
||||
{% trans 'Hello' %} {{ user.name }},
|
||||
<br>
|
||||
{% trans 'Please click the link below to reset your password, if not your request, concern your account security' %}
|
||||
<br>
|
||||
<br>
|
||||
<a href="{{ rest_password_url }}?token={{ rest_password_token}}" class='showLink'>{% trans 'Click here reset password' %}</a>
|
||||
<br>
|
||||
<br>
|
||||
{% trans 'This link is valid for 1 hour. After it expires,' %} <a href="{{ forget_password_url }}?email={{ user.email }}">{% trans 'request new one' %}</a>
|
||||
<br>
|
||||
---
|
||||
<br>
|
||||
<a href="{{ login_url }}">{% trans 'Login direct' %}</a>
|
||||
<br>
|
||||
<p>
|
||||
{% trans 'Hello' %} {{ user.name }},
|
||||
</p>
|
||||
<p>
|
||||
{% trans 'Please click the link below to reset your password, if not your request, concern your account security' %}
|
||||
<br>
|
||||
<br>
|
||||
<a href="{{ rest_password_url }}?token={{ rest_password_token}}" class='showLink'>{% trans 'Click here reset password' %}</a>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
{% trans 'This link is valid for 1 hour. After it expires' %}
|
||||
<a href="{{ forget_password_url }}?email={{ user.email }}">
|
||||
{% trans 'request new one' %}
|
||||
</a>
|
||||
</p>
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
{% load i18n %}
|
||||
|
||||
<p>{% trans 'Hello' %}: {{ name }},</p>
|
||||
<p>{% trans 'Hello' %} {{ name }},</p>
|
||||
|
||||
<p>
|
||||
{% trans 'Your password has just been successfully updated.' %}
|
||||
{% trans 'Your password has just been successfully updated' %}
|
||||
</p>
|
||||
<p>
|
||||
{% trans 'IP' %}: {{ ip_address }} <br />
|
||||
{% trans 'Browser' %}: {{ browser }}
|
||||
<b>{% trans 'IP' %}:</b> {{ ip_address }} <br />
|
||||
<b>{% trans 'Browser' %}:</b> {{ browser }}
|
||||
</p>
|
||||
<p>---</p>
|
||||
<p>
|
||||
<small>
|
||||
{% trans 'If the password update was not initiated by you, your account may have security issues.' %} <br />
|
||||
{% trans 'If you have any questions, you can contact the administrator.' %}
|
||||
</small>
|
||||
{% trans 'If the password update was not initiated by you, your account may have security issues' %} <br />
|
||||
{% trans 'If you have any questions, you can contact the administrator' %}
|
||||
</p>
|
||||
|
|
|
@ -28,6 +28,10 @@ def local_now():
|
|||
return as_current_tz(utc_now())
|
||||
|
||||
|
||||
def local_now_display(fmt='%Y-%m-%d %H:%M:%S'):
|
||||
return local_now().strftime(fmt)
|
||||
|
||||
|
||||
_rest_dt_field = DateTimeField()
|
||||
dt_parser = _rest_dt_field.to_internal_value
|
||||
dt_formatter = _rest_dt_field.to_representation
|
||||
|
|
|
@ -8,7 +8,6 @@ from django.http.response import JsonResponse, HttpResponse
|
|||
from rest_framework.views import APIView
|
||||
from rest_framework.permissions import AllowAny
|
||||
from collections import Counter
|
||||
from django.conf import settings
|
||||
from rest_framework.response import Response
|
||||
|
||||
from users.models import User
|
||||
|
|
|
@ -4,27 +4,39 @@ from django.templatetags.static import static
|
|||
from django.conf import settings
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
default_context = {
|
||||
'DEFAULT_PK': '00000000-0000-0000-0000-000000000000',
|
||||
'LOGO_URL': static('img/logo.png'),
|
||||
'LOGO_TEXT_URL': static('img/logo_text.png'),
|
||||
'LOGIN_IMAGE_URL': static('img/login_image.jpg'),
|
||||
'FAVICON_URL': static('img/facio.ico'),
|
||||
'LOGIN_CAS_LOGO_URL': static('img/login_cas_logo.png'),
|
||||
'LOGIN_WECOM_LOGO_URL': static('img/login_wecom_logo.png'),
|
||||
'LOGIN_DINGTALK_LOGO_URL': static('img/login_dingtalk_logo.png'),
|
||||
'LOGIN_FEISHU_LOGO_URL': static('img/login_feishu_logo.png'),
|
||||
'JMS_TITLE': _('JumpServer Open Source Bastion Host'),
|
||||
}
|
||||
|
||||
default_interface = {
|
||||
'login_title': default_context['JMS_TITLE'],
|
||||
'logo_logout': default_context['LOGO_URL'],
|
||||
'logo_index': default_context['LOGO_TEXT_URL'],
|
||||
'login_image': default_context['LOGIN_IMAGE_URL'],
|
||||
'favicon': default_context['FAVICON_URL'],
|
||||
}
|
||||
|
||||
|
||||
def jumpserver_processor(request):
|
||||
# Setting default pk
|
||||
context = {
|
||||
'DEFAULT_PK': '00000000-0000-0000-0000-000000000000',
|
||||
'LOGO_URL': static('img/logo.png'),
|
||||
'LOGO_TEXT_URL': static('img/logo_text.png'),
|
||||
'LOGIN_IMAGE_URL': static('img/login_image.jpg'),
|
||||
'FAVICON_URL': static('img/facio.ico'),
|
||||
'LOGIN_CAS_LOGO_URL': static('img/login_cas_logo.png'),
|
||||
'LOGIN_WECOM_LOGO_URL': static('img/login_wecom_logo.png'),
|
||||
'LOGIN_DINGTALK_LOGO_URL': static('img/login_dingtalk_logo.png'),
|
||||
'LOGIN_FEISHU_LOGO_URL': static('img/login_feishu_logo.png'),
|
||||
'JMS_TITLE': _('JumpServer Open Source Bastion Host'),
|
||||
context = default_context
|
||||
context.update({
|
||||
'VERSION': settings.VERSION,
|
||||
'COPYRIGHT': 'FIT2CLOUD 飞致云' + ' © 2014-2021',
|
||||
'SECURITY_COMMAND_EXECUTION': settings.SECURITY_COMMAND_EXECUTION,
|
||||
'SECURITY_MFA_VERIFY_TTL': settings.SECURITY_MFA_VERIFY_TTL,
|
||||
'FORCE_SCRIPT_NAME': settings.FORCE_SCRIPT_NAME,
|
||||
'SECURITY_VIEW_AUTH_NEED_MFA': settings.SECURITY_VIEW_AUTH_NEED_MFA,
|
||||
}
|
||||
})
|
||||
return context
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b5a90a96a51ef2f38d4530f3e5b79cd59b07dbca39f60bc35cde5ee0e364b210
|
||||
size 91089
|
||||
oid sha256:b2663d90ceadd419c40abd472a3b5030b007b1e1db1fcaeda9893ff90cd7cdd6
|
||||
size 89955
|
||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: JumpServer 0.3.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-10-21 18:50+0800\n"
|
||||
"POT-Creation-Date: 2021-10-22 19:15+0800\n"
|
||||
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
|
||||
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
||||
"Language-Team: JumpServer team<ibuler@qq.com>\n"
|
||||
|
@ -85,8 +85,7 @@ msgstr "登录复核"
|
|||
#: orgs/models.py:19 orgs/models.py:433 perms/models/base.py:45
|
||||
#: templates/index.html:78 terminal/backends/command/models.py:18
|
||||
#: terminal/backends/command/serializers.py:12 terminal/models/session.py:38
|
||||
#: terminal/templates/terminal/_msg_command_alert.html:10
|
||||
#: terminal/templates/terminal/_msg_command_execute_alert.html:4
|
||||
#: terminal/notifications.py:91 terminal/notifications.py:136
|
||||
#: tickets/models/comment.py:17 users/const.py:14 users/models/user.py:173
|
||||
#: users/models/user.py:801 users/models/user.py:827
|
||||
#: users/serializers/group.py:19
|
||||
|
@ -128,7 +127,7 @@ msgstr "系统用户"
|
|||
#: audits/models.py:38 perms/models/asset_permission.py:99
|
||||
#: templates/index.html:82 terminal/backends/command/models.py:19
|
||||
#: terminal/backends/command/serializers.py:13 terminal/models/session.py:40
|
||||
#: terminal/templates/terminal/_msg_command_alert.html:7
|
||||
#: terminal/notifications.py:90
|
||||
#: users/templates/users/user_asset_permission.html:40
|
||||
#: users/templates/users/user_asset_permission.html:70
|
||||
#: xpack/plugins/change_auth_plan/models/asset.py:195
|
||||
|
@ -154,6 +153,7 @@ msgstr "格式为逗号分隔的字符串, * 表示匹配所有. "
|
|||
#: audits/models.py:105 authentication/forms.py:15 authentication/forms.py:17
|
||||
#: authentication/templates/authentication/_msg_different_city.html:9
|
||||
#: ops/models/adhoc.py:148 users/forms/profile.py:31 users/models/user.py:595
|
||||
#: users/templates/users/_msg_user_created.html:10
|
||||
#: users/templates/users/_select_user_modal.html:14
|
||||
#: xpack/plugins/change_auth_plan/models/asset.py:35
|
||||
#: xpack/plugins/change_auth_plan/models/asset.py:191
|
||||
|
@ -174,7 +174,7 @@ msgstr ""
|
|||
#: applications/serializers/attrs/application_type/mysql_workbench.py:18
|
||||
#: assets/models/asset.py:180 assets/models/domain.py:61
|
||||
#: assets/serializers/account.py:12
|
||||
#: authentication/templates/authentication/_msg_rest_password_success.html:9
|
||||
#: authentication/templates/authentication/_msg_rest_password_success.html:8
|
||||
#: settings/serializers/terminal.py:8
|
||||
#: users/templates/users/_granted_assets.html:26
|
||||
#: users/templates/users/user_asset_permission.html:156
|
||||
|
@ -384,6 +384,7 @@ msgstr "目标URL"
|
|||
#: authentication/forms.py:22
|
||||
#: authentication/templates/authentication/login.html:151
|
||||
#: settings/serializers/auth/ldap.py:44 users/forms/profile.py:21
|
||||
#: users/templates/users/_msg_user_created.html:11
|
||||
#: users/templates/users/user_otp_check_password.html:13
|
||||
#: users/templates/users/user_password_update.html:43
|
||||
#: users/templates/users/user_password_verify.html:18
|
||||
|
@ -647,7 +648,7 @@ msgstr "正则表达式"
|
|||
|
||||
#: assets/models/cmd_filter.py:41 ops/models/command.py:25
|
||||
#: terminal/backends/command/serializers.py:15 terminal/models/session.py:49
|
||||
#: terminal/templates/terminal/_msg_command_alert.html:4
|
||||
#: terminal/templates/terminal/_msg_command_alert.html:12
|
||||
#: terminal/templates/terminal/_msg_command_execute_alert.html:10
|
||||
msgid "Command"
|
||||
msgstr "命令"
|
||||
|
@ -1445,7 +1446,7 @@ msgstr "{ApplicationPermission} 添加 {SystemUser}"
|
|||
msgid "{ApplicationPermission} REMOVE {SystemUser}"
|
||||
msgstr "{ApplicationPermission} 移除 {SystemUser}"
|
||||
|
||||
#: authentication/api/connection_token.py:235
|
||||
#: authentication/api/connection_token.py:239
|
||||
msgid "Invalid token"
|
||||
msgstr "无效的令牌"
|
||||
|
||||
|
@ -1731,6 +1732,7 @@ msgid "Secret"
|
|||
msgstr "密钥"
|
||||
|
||||
#: authentication/templates/authentication/_access_key_modal.html:33
|
||||
#: terminal/notifications.py:93 terminal/notifications.py:138
|
||||
msgid "Date"
|
||||
msgstr "日期"
|
||||
|
||||
|
@ -1788,8 +1790,8 @@ msgid "Code error"
|
|||
msgstr "代码错误"
|
||||
|
||||
#: authentication/templates/authentication/_msg_different_city.html:3
|
||||
#: authentication/templates/authentication/_msg_reset_password.html:2
|
||||
#: authentication/templates/authentication/_msg_rest_password_success.html:3
|
||||
#: authentication/templates/authentication/_msg_reset_password.html:3
|
||||
#: authentication/templates/authentication/_msg_rest_password_success.html:2
|
||||
#: perms/templates/perms/_msg_item_permissions_expire.html:3
|
||||
#: perms/templates/perms/_msg_permed_items_expire.html:3
|
||||
#: users/templates/users/_msg_account_expire_reminder.html:4
|
||||
|
@ -1807,53 +1809,48 @@ msgstr "你的账号存在异地登录行为,请关注。"
|
|||
msgid "Login time"
|
||||
msgstr "登录日期"
|
||||
|
||||
#: authentication/templates/authentication/_msg_different_city.html:16
|
||||
#: authentication/templates/authentication/_msg_different_city.html:15
|
||||
msgid ""
|
||||
"If you suspect that the login behavior is abnormal, please modify the "
|
||||
"account password in time."
|
||||
msgstr "若怀疑此次登录行为异常,请及时修改账号密码"
|
||||
|
||||
#: authentication/templates/authentication/_msg_reset_password.html:4
|
||||
#: authentication/templates/authentication/_msg_reset_password.html:6
|
||||
msgid ""
|
||||
"Please click the link below to reset your password, if not your request, "
|
||||
"concern your account security"
|
||||
msgstr "请点击下面链接重置密码, 如果不是您申请的,请关注账号安全"
|
||||
|
||||
#: authentication/templates/authentication/_msg_reset_password.html:7
|
||||
#: authentication/templates/authentication/_msg_reset_password.html:9
|
||||
msgid "Click here reset password"
|
||||
msgstr "点击这里重置密码"
|
||||
|
||||
#: authentication/templates/authentication/_msg_reset_password.html:10
|
||||
msgid "This link is valid for 1 hour. After it expires,"
|
||||
#: authentication/templates/authentication/_msg_reset_password.html:13
|
||||
#: users/templates/users/_msg_user_created.html:17
|
||||
msgid "This link is valid for 1 hour. After it expires"
|
||||
msgstr "这个链接有效期1小时, 超过时间您可以"
|
||||
|
||||
#: authentication/templates/authentication/_msg_reset_password.html:10
|
||||
#: authentication/templates/authentication/_msg_reset_password.html:15
|
||||
#: users/templates/users/_msg_user_created.html:18
|
||||
msgid "request new one"
|
||||
msgstr "重新申请"
|
||||
|
||||
#: authentication/templates/authentication/_msg_reset_password.html:14
|
||||
#: users/templates/users/_msg_password_expire_reminder.html:22
|
||||
#: users/templates/users/_msg_reset_mfa.html:11
|
||||
#: users/templates/users/_msg_reset_ssh_key.html:11
|
||||
msgid "Login direct"
|
||||
msgstr "直接登录"
|
||||
#: authentication/templates/authentication/_msg_rest_password_success.html:5
|
||||
msgid "Your password has just been successfully updated"
|
||||
msgstr "你的密码刚刚成功更新"
|
||||
|
||||
#: authentication/templates/authentication/_msg_rest_password_success.html:6
|
||||
msgid "Your password has just been successfully updated."
|
||||
msgstr "你的密码刚刚已经成功更新。"
|
||||
|
||||
#: authentication/templates/authentication/_msg_rest_password_success.html:10
|
||||
#: authentication/templates/authentication/_msg_rest_password_success.html:9
|
||||
msgid "Browser"
|
||||
msgstr "浏览器"
|
||||
|
||||
#: authentication/templates/authentication/_msg_rest_password_success.html:15
|
||||
#: authentication/templates/authentication/_msg_rest_password_success.html:12
|
||||
msgid ""
|
||||
"If the password update was not initiated by you, your account may have "
|
||||
"security issues."
|
||||
msgstr "如果这次密码更新不是由你发起的,那么你的账号可能存在安全问题。"
|
||||
"security issues"
|
||||
msgstr "如果这次密码更新不是由你发起的,那么你的账号可能存在安全问题"
|
||||
|
||||
#: authentication/templates/authentication/_msg_rest_password_success.html:16
|
||||
msgid "If you have any questions, you can contact the administrator."
|
||||
#: authentication/templates/authentication/_msg_rest_password_success.html:13
|
||||
msgid "If you have any questions, you can contact the administrator"
|
||||
msgstr "如果有疑问或需求,请联系系统管理员"
|
||||
|
||||
#: authentication/templates/authentication/login.html:143
|
||||
|
@ -2206,7 +2203,7 @@ msgstr "不能包含特殊字符"
|
|||
msgid "The mobile phone number format is incorrect"
|
||||
msgstr "手机号格式不正确"
|
||||
|
||||
#: jumpserver/context_processor.py:20
|
||||
#: jumpserver/context_processor.py:17
|
||||
msgid "JumpServer Open Source Bastion Host"
|
||||
msgstr "JumpServer 开源堡垒机"
|
||||
|
||||
|
@ -2246,7 +2243,7 @@ msgstr "邮件"
|
|||
msgid "Site message"
|
||||
msgstr "站内信"
|
||||
|
||||
#: notifications/notifications.py:148 ops/models/adhoc.py:246
|
||||
#: notifications/notifications.py:167 ops/models/adhoc.py:246
|
||||
#: xpack/plugins/change_auth_plan/models/base.py:108
|
||||
#: xpack/plugins/change_auth_plan/models/base.py:190
|
||||
#: xpack/plugins/gathered_user/models.py:79
|
||||
|
@ -2261,7 +2258,7 @@ msgstr "等待任务开始"
|
|||
msgid "Not has host {} permission"
|
||||
msgstr "没有该主机 {} 权限"
|
||||
|
||||
#: ops/apps.py:9 ops/notifications.py:14
|
||||
#: ops/apps.py:9 ops/notifications.py:15
|
||||
msgid "Operations"
|
||||
msgstr "运维"
|
||||
|
||||
|
@ -2383,29 +2380,33 @@ msgstr "命令 `{}` 不允许被执行 ......."
|
|||
msgid "Task end"
|
||||
msgstr "任务结束"
|
||||
|
||||
#: ops/notifications.py:15
|
||||
#: ops/notifications.py:16
|
||||
msgid "Server performance"
|
||||
msgstr "监控告警"
|
||||
|
||||
#: ops/notifications.py:54
|
||||
#: ops/notifications.py:22
|
||||
msgid "Terminal health check warning"
|
||||
msgstr ""
|
||||
|
||||
#: ops/notifications.py:63
|
||||
#, python-brace-format
|
||||
msgid "The terminal is offline: {name}"
|
||||
msgstr "终端已离线: {name}"
|
||||
|
||||
#: ops/notifications.py:60
|
||||
#: ops/notifications.py:68
|
||||
#, python-brace-format
|
||||
msgid "Disk used more than {max_threshold}%: => {value} ({name})"
|
||||
msgstr "硬盘使用率超过 {max_threshold}%: => {value} ({name})"
|
||||
msgid "Disk used more than {max_threshold}%: => {value}"
|
||||
msgstr "硬盘使用率超过 {max_threshold}%: => {value}"
|
||||
|
||||
#: ops/notifications.py:67
|
||||
#: ops/notifications.py:73
|
||||
#, python-brace-format
|
||||
msgid "Memory used more than {max_threshold}%: => {value} ({name})"
|
||||
msgstr "内存使用率超过 {max_threshold}%: => {value} ({name})"
|
||||
msgid "Memory used more than {max_threshold}%: => {value}"
|
||||
msgstr "内存使用率超过 {max_threshold}%: => {value}"
|
||||
|
||||
#: ops/notifications.py:74
|
||||
#: ops/notifications.py:78
|
||||
#, python-brace-format
|
||||
msgid "CPU load more than {max_threshold}: => {value} ({name})"
|
||||
msgstr "CPU 使用率超过 {max_threshold}: => {value} ({name})"
|
||||
msgid "CPU load more than {max_threshold}: => {value}"
|
||||
msgstr "CPU 使用率超过 {max_threshold}: => {value}"
|
||||
|
||||
#: ops/tasks.py:71
|
||||
msgid "Clean task history period"
|
||||
|
@ -2533,35 +2534,35 @@ msgstr "失效日期"
|
|||
msgid "From ticket"
|
||||
msgstr "来自工单"
|
||||
|
||||
#: perms/notifications.py:19
|
||||
#: perms/notifications.py:15
|
||||
msgid "You permed assets is about to expire"
|
||||
msgstr "你授权的资产即将到期"
|
||||
|
||||
#: perms/notifications.py:23
|
||||
#: perms/notifications.py:19
|
||||
msgid "permed assets"
|
||||
msgstr "授权的资产"
|
||||
|
||||
#: perms/notifications.py:61
|
||||
#: perms/notifications.py:57
|
||||
msgid "Asset permissions is about to expire"
|
||||
msgstr "资产授权规则将要过期"
|
||||
|
||||
#: perms/notifications.py:65
|
||||
#: perms/notifications.py:61
|
||||
msgid "asset permissions of organization {}"
|
||||
msgstr "组织 ({}) 的资产授权"
|
||||
|
||||
#: perms/notifications.py:91
|
||||
#: perms/notifications.py:87
|
||||
msgid "Your permed applications is about to expire"
|
||||
msgstr "你授权的应用即将过期"
|
||||
|
||||
#: perms/notifications.py:94
|
||||
#: perms/notifications.py:90
|
||||
msgid "permed applications"
|
||||
msgstr "授权的应用"
|
||||
|
||||
#: perms/notifications.py:132
|
||||
#: perms/notifications.py:128
|
||||
msgid "Application permissions is about to expire"
|
||||
msgstr "应用授权规则即将过期"
|
||||
|
||||
#: perms/notifications.py:135
|
||||
#: perms/notifications.py:131
|
||||
msgid "application permissions of organization {}"
|
||||
msgstr "组织 ({}) 的应用授权"
|
||||
|
||||
|
@ -2633,7 +2634,7 @@ msgstr ""
|
|||
" 以下 %(item_type)s 即将在 3 天后过期\n"
|
||||
" "
|
||||
|
||||
#: perms/templates/perms/_msg_permed_items_expire.html:22
|
||||
#: perms/templates/perms/_msg_permed_items_expire.html:20
|
||||
msgid "If you have any question, please contact the administrator"
|
||||
msgstr "如果有疑问或需求,请联系系统管理员"
|
||||
|
||||
|
@ -2671,11 +2672,6 @@ msgstr "获取 LDAP 用户为 None"
|
|||
msgid "Imported {} users successfully (Organization: {})"
|
||||
msgstr "成功导入 {} 个用户 ( 组织: {} )"
|
||||
|
||||
#: settings/api/public.py:41 xpack/plugins/interface/api.py:18
|
||||
#: xpack/plugins/interface/models.py:36
|
||||
msgid "Welcome to the JumpServer open source Bastion Host"
|
||||
msgstr "欢迎使用JumpServer开源堡垒机"
|
||||
|
||||
#: settings/models.py:191 users/templates/users/reset_password.html:29
|
||||
msgid "Setting"
|
||||
msgstr "设置"
|
||||
|
@ -3725,7 +3721,7 @@ msgstr "数据库应用"
|
|||
msgid "Perms"
|
||||
msgstr "权限管理"
|
||||
|
||||
#: templates/_nav.html:97 terminal/notifications.py:22
|
||||
#: templates/_nav.html:97 terminal/notifications.py:24
|
||||
msgid "Sessions"
|
||||
msgstr "会话管理"
|
||||
|
||||
|
@ -4068,7 +4064,7 @@ msgstr "输出"
|
|||
|
||||
#: terminal/backends/command/models.py:23 terminal/models/sharing.py:15
|
||||
#: terminal/models/sharing.py:58
|
||||
#: terminal/templates/terminal/_msg_command_alert.html:16
|
||||
#: terminal/templates/terminal/_msg_command_alert.html:10
|
||||
msgid "Session"
|
||||
msgstr "会话"
|
||||
|
||||
|
@ -4235,11 +4231,15 @@ msgstr "命令存储"
|
|||
msgid "Replay storage"
|
||||
msgstr "录像存储"
|
||||
|
||||
#: terminal/notifications.py:68
|
||||
#: terminal/notifications.py:70
|
||||
msgid "Danger command alert"
|
||||
msgstr "危险命令告警"
|
||||
|
||||
#: terminal/notifications.py:106
|
||||
#: terminal/notifications.py:92 terminal/notifications.py:137
|
||||
msgid "Level"
|
||||
msgstr "级别"
|
||||
|
||||
#: terminal/notifications.py:110
|
||||
msgid "Batch danger command alert"
|
||||
msgstr "批量危险命令告警"
|
||||
|
||||
|
@ -4348,12 +4348,7 @@ msgstr ""
|
|||
msgid "Not found"
|
||||
msgstr "没有发现"
|
||||
|
||||
#: terminal/templates/terminal/_msg_command_alert.html:13
|
||||
#: terminal/templates/terminal/_msg_command_execute_alert.html:7
|
||||
msgid "Level"
|
||||
msgstr "级别"
|
||||
|
||||
#: terminal/templates/terminal/_msg_command_alert.html:16
|
||||
#: terminal/templates/terminal/_msg_command_alert.html:10
|
||||
msgid "view"
|
||||
msgstr "查看"
|
||||
|
||||
|
@ -4445,7 +4440,7 @@ msgstr "申请的开始日期"
|
|||
msgid "Applied date expired"
|
||||
msgstr "申请的失效日期"
|
||||
|
||||
#: tickets/handler/apply_application.py:79 tickets/handler/apply_asset.py:72
|
||||
#: tickets/handler/apply_application.py:79
|
||||
msgid ""
|
||||
"Created by the ticket, ticket title: {}, ticket applicant: {}, ticket "
|
||||
"processor: {}, ticket ID: {}"
|
||||
|
@ -4460,87 +4455,94 @@ msgstr "申请的主机名组"
|
|||
msgid "Applied actions"
|
||||
msgstr "申请的动作"
|
||||
|
||||
#: tickets/handler/apply_asset.py:72
|
||||
msgid ""
|
||||
"Created by the ticket ticket title: {} ticket applicant: {} ticket "
|
||||
"processor: {} ticket ID: {}"
|
||||
msgstr ""
|
||||
"通过工单创建, 工单标题: {}, 工单申请人: {}, 工单处理人: {}, 工单 ID: {}"
|
||||
|
||||
#: tickets/handler/base.py:86
|
||||
msgid "{} {} the ticket"
|
||||
msgstr "{} {}工单"
|
||||
msgstr "{} {} 工单"
|
||||
|
||||
#: tickets/handler/base.py:113
|
||||
#: tickets/handler/base.py:114
|
||||
msgid "Ticket title"
|
||||
msgstr "工单标题"
|
||||
|
||||
#: tickets/handler/base.py:114
|
||||
#: tickets/handler/base.py:115
|
||||
msgid "Ticket type"
|
||||
msgstr "工单类型"
|
||||
|
||||
#: tickets/handler/base.py:115
|
||||
#: tickets/handler/base.py:116
|
||||
msgid "Ticket status"
|
||||
msgstr "工单状态"
|
||||
|
||||
#: tickets/handler/base.py:116
|
||||
#: tickets/handler/base.py:117
|
||||
msgid "Ticket applicant"
|
||||
msgstr "工单申请人"
|
||||
|
||||
#: tickets/handler/base.py:118
|
||||
#: tickets/handler/base.py:119
|
||||
msgid "Ticket basic info"
|
||||
msgstr "工单基本信息"
|
||||
|
||||
#: tickets/handler/base.py:129
|
||||
#: tickets/handler/base.py:130
|
||||
msgid "No content"
|
||||
msgstr "无内容"
|
||||
|
||||
#: tickets/handler/base.py:131
|
||||
#: tickets/handler/base.py:132
|
||||
msgid "Ticket applied info"
|
||||
msgstr "工单申请信息"
|
||||
|
||||
#: tickets/handler/command_confirm.py:24
|
||||
#: tickets/handler/command_confirm.py:25
|
||||
msgid "Applied run user"
|
||||
msgstr "申请运行的用户"
|
||||
|
||||
#: tickets/handler/command_confirm.py:25
|
||||
#: tickets/handler/command_confirm.py:26
|
||||
msgid "Applied run asset"
|
||||
msgstr "申请运行的资产"
|
||||
|
||||
#: tickets/handler/command_confirm.py:26
|
||||
#: tickets/handler/command_confirm.py:27
|
||||
msgid "Applied run system user"
|
||||
msgstr "申请运行的系统用户"
|
||||
|
||||
#: tickets/handler/command_confirm.py:27
|
||||
#: tickets/handler/command_confirm.py:28
|
||||
msgid "Applied run command"
|
||||
msgstr "申请运行的命令"
|
||||
|
||||
#: tickets/handler/command_confirm.py:28
|
||||
#: tickets/handler/command_confirm.py:29
|
||||
msgid "Applied from session"
|
||||
msgstr "申请来自会话"
|
||||
|
||||
#: tickets/handler/command_confirm.py:29
|
||||
#: tickets/handler/command_confirm.py:30
|
||||
msgid "Applied from command filter rules"
|
||||
msgstr "申请来自命令过滤规则"
|
||||
|
||||
#: tickets/handler/command_confirm.py:30
|
||||
#: tickets/handler/command_confirm.py:31
|
||||
msgid "Applied from command filter"
|
||||
msgstr "申请来自命令过滤规则"
|
||||
|
||||
#: tickets/handler/login_asset_confirm.py:16
|
||||
#: tickets/handler/login_asset_confirm.py:17
|
||||
msgid "Applied login user"
|
||||
msgstr "申请登录的用户"
|
||||
|
||||
#: tickets/handler/login_asset_confirm.py:17
|
||||
#: tickets/handler/login_asset_confirm.py:18
|
||||
msgid "Applied login asset"
|
||||
msgstr "申请登录的资产"
|
||||
|
||||
#: tickets/handler/login_asset_confirm.py:18
|
||||
#: tickets/handler/login_asset_confirm.py:19
|
||||
msgid "Applied login system user"
|
||||
msgstr "申请登录的系统用户"
|
||||
|
||||
#: tickets/handler/login_confirm.py:16
|
||||
#: tickets/handler/login_confirm.py:17
|
||||
msgid "Applied login IP"
|
||||
msgstr "申请登录的IP"
|
||||
|
||||
#: tickets/handler/login_confirm.py:17
|
||||
#: tickets/handler/login_confirm.py:18
|
||||
msgid "Applied login city"
|
||||
msgstr "申请登录的城市"
|
||||
|
||||
#: tickets/handler/login_confirm.py:18
|
||||
#: tickets/handler/login_confirm.py:19
|
||||
msgid "Applied login datetime"
|
||||
msgstr "申请登录的日期"
|
||||
|
||||
|
@ -4741,7 +4743,8 @@ msgstr "请选择受理人"
|
|||
msgid "The current organization type already exists"
|
||||
msgstr "当前组织已存在该类型"
|
||||
|
||||
#: tickets/templates/tickets/_msg_ticket.html:11
|
||||
#: tickets/templates/tickets/_base_ticket_body.html:17
|
||||
#: tickets/templates/tickets/_msg_ticket.html:12
|
||||
msgid "Click here to review"
|
||||
msgstr "点击查看"
|
||||
|
||||
|
@ -4901,30 +4904,38 @@ msgstr "管理员"
|
|||
msgid "Administrator is the super user of system"
|
||||
msgstr "Administrator是初始的超级管理员"
|
||||
|
||||
#: users/notifications.py:20
|
||||
#: users/notifications.py:15
|
||||
msgid "Create account successfully"
|
||||
msgstr "创建账户成功"
|
||||
|
||||
#: users/notifications.py:19
|
||||
msgid "Hello {}"
|
||||
msgstr "你好"
|
||||
|
||||
#: users/notifications.py:51
|
||||
#: users/templates/users/_msg_password_expire_reminder.html:17
|
||||
#: users/templates/users/reset_password.html:5
|
||||
#: users/templates/users/reset_password.html:6
|
||||
msgid "Reset password"
|
||||
msgstr "重置密码"
|
||||
|
||||
#: users/notifications.py:50 users/views/profile/reset.py:127
|
||||
#: users/notifications.py:81 users/views/profile/reset.py:127
|
||||
msgid "Reset password success"
|
||||
msgstr "重置密码成功"
|
||||
|
||||
#: users/notifications.py:78
|
||||
#: users/notifications.py:110
|
||||
msgid "Password is about expire"
|
||||
msgstr "密码即将过期"
|
||||
|
||||
#: users/notifications.py:105
|
||||
#: users/notifications.py:137
|
||||
msgid "Account is about expire"
|
||||
msgstr "账号即将过期"
|
||||
|
||||
#: users/notifications.py:127
|
||||
#: users/notifications.py:161
|
||||
msgid "Reset SSH Key"
|
||||
msgstr "重置 SSH 密钥"
|
||||
|
||||
#: users/notifications.py:147
|
||||
#: users/notifications.py:181
|
||||
msgid "Reset MFA"
|
||||
msgstr "重置 MFA"
|
||||
|
||||
|
@ -5073,28 +5084,34 @@ msgid "Click here update password"
|
|||
msgstr "点击这里更新密码"
|
||||
|
||||
#: users/templates/users/_msg_password_expire_reminder.html:16
|
||||
msgid "If your password has expired, please click"
|
||||
msgstr "如果你的密码已过期,先点击"
|
||||
|
||||
#: users/templates/users/_msg_password_expire_reminder.html:18
|
||||
msgid "to apply for a password reset email."
|
||||
msgstr "申请重置"
|
||||
msgid "If your password has expired, please click the link below to"
|
||||
msgstr "如果你的密码已过期,请点击"
|
||||
|
||||
#: users/templates/users/_msg_reset_mfa.html:7
|
||||
msgid "Your MFA has been reset by site administrator."
|
||||
msgstr "你的 MFA 已经被管理员重置。"
|
||||
msgid "Your MFA has been reset by site administrator"
|
||||
msgstr "你的 MFA 已经被管理员重置"
|
||||
|
||||
#: users/templates/users/_msg_reset_mfa.html:8
|
||||
msgid "Please login and reset your MFA."
|
||||
msgstr "请登录并重新设置你的 MFA"
|
||||
#: users/templates/users/_msg_reset_ssh_key.html:8
|
||||
msgid "Please click the link below to set"
|
||||
msgstr "请点击下面链接设置"
|
||||
|
||||
#: users/templates/users/_msg_reset_mfa.html:11
|
||||
#: users/templates/users/_msg_reset_ssh_key.html:11
|
||||
msgid "Click here set"
|
||||
msgstr "点击这里设置"
|
||||
|
||||
#: users/templates/users/_msg_reset_ssh_key.html:7
|
||||
msgid "Your ssh public key has been reset by site administrator."
|
||||
msgstr "你的 SSH 密钥已经被管理员重置。"
|
||||
msgid "Your ssh public key has been reset by site administrator"
|
||||
msgstr "你的 SSH 密钥已经被管理员重置"
|
||||
|
||||
#: users/templates/users/_msg_reset_ssh_key.html:8
|
||||
msgid "Please login and reset your ssh public key."
|
||||
msgstr "请登录并重新设置你的密钥"
|
||||
#: users/templates/users/_msg_user_created.html:8
|
||||
msgid "Your account has been created successfully"
|
||||
msgstr "您的账户已创建成功"
|
||||
|
||||
#: users/templates/users/_msg_user_created.html:13
|
||||
msgid "click here to set your password"
|
||||
msgstr "点击这里设置密码"
|
||||
|
||||
#: users/templates/users/_select_user_modal.html:5
|
||||
msgid "Please Select User"
|
||||
|
@ -5279,56 +5296,6 @@ msgstr "账号保护已开启,请根据提示完成以下操作"
|
|||
msgid "Open MFA Authenticator and enter the 6-bit dynamic code"
|
||||
msgstr "请打开MFA验证器,输入6位动态码"
|
||||
|
||||
# msgid "Update user"
|
||||
# msgstr "更新用户"
|
||||
#: users/utils.py:23
|
||||
#, python-format
|
||||
msgid ""
|
||||
"\n"
|
||||
" <div>\n"
|
||||
" <p>Your account has been created successfully</p>\n"
|
||||
" <div>\n"
|
||||
" Username: %(username)s\n"
|
||||
" <br/>\n"
|
||||
" Password: <a href=\"%(rest_password_url)s?token="
|
||||
"%(rest_password_token)s\">\n"
|
||||
" click here to set your password</a> \n"
|
||||
" (This link is valid for 1 hour. After it expires, <a href="
|
||||
"\"%(forget_password_url)s?email=%(email)s\">request new one</a>)\n"
|
||||
" </div>\n"
|
||||
" <div>\n"
|
||||
" <p>---</p>\n"
|
||||
" <a href=\"%(login_url)s\">Login direct</a>\n"
|
||||
" </div>\n"
|
||||
" </div>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
" <div>\n"
|
||||
" <p>您的账户已创建成功</p>\n"
|
||||
" <div>\n"
|
||||
" 用户名: %(username)s\n"
|
||||
" <br/>\n"
|
||||
" 密码: <a href=\"%(rest_password_url)s?token="
|
||||
"%(rest_password_token)s\">请点击这里设置密码</a> (这个链接有效期1小时, 超过时"
|
||||
"间您可以 <a href=\"%(forget_password_url)s?email=%(email)s\">重新申请</a>)\n"
|
||||
" </div>\n"
|
||||
" <div>\n"
|
||||
" <p>---</p>\n"
|
||||
" <a href=\"%(login_url)s\">直接登录</a>\n"
|
||||
" </div>\n"
|
||||
" </div>\n"
|
||||
" "
|
||||
|
||||
#: users/utils.py:57
|
||||
msgid "Create account successfully"
|
||||
msgstr "创建账户成功"
|
||||
|
||||
#: users/utils.py:61
|
||||
#, python-format
|
||||
msgid "Hello %(name)s"
|
||||
msgstr "你好 %(name)s"
|
||||
|
||||
#: users/views/profile/otp.py:122 users/views/profile/otp.py:161
|
||||
#: users/views/profile/otp.py:181
|
||||
msgid "MFA code invalid, or ntp sync server time"
|
||||
|
@ -5923,11 +5890,11 @@ msgstr "资产为空,请更改节点"
|
|||
msgid "Executed times"
|
||||
msgstr "执行次数"
|
||||
|
||||
#: xpack/plugins/interface/api.py:68
|
||||
#: xpack/plugins/interface/api.py:43
|
||||
msgid "It is already in the default setting state!"
|
||||
msgstr "当前已经是初始化状态!"
|
||||
|
||||
#: xpack/plugins/interface/api.py:72
|
||||
#: xpack/plugins/interface/api.py:46
|
||||
msgid "Restore default successfully."
|
||||
msgstr "恢复默认成功!"
|
||||
|
||||
|
@ -5935,23 +5902,23 @@ msgstr "恢复默认成功!"
|
|||
msgid "Interface settings"
|
||||
msgstr "界面设置"
|
||||
|
||||
#: xpack/plugins/interface/models.py:15
|
||||
#: xpack/plugins/interface/models.py:16
|
||||
msgid "Title of login page"
|
||||
msgstr "登录页面标题"
|
||||
|
||||
#: xpack/plugins/interface/models.py:19
|
||||
#: xpack/plugins/interface/models.py:20
|
||||
msgid "Image of login page"
|
||||
msgstr "登录页面图片"
|
||||
|
||||
#: xpack/plugins/interface/models.py:23
|
||||
#: xpack/plugins/interface/models.py:24
|
||||
msgid "Website icon"
|
||||
msgstr "网站图标"
|
||||
|
||||
#: xpack/plugins/interface/models.py:27
|
||||
#: xpack/plugins/interface/models.py:28
|
||||
msgid "Logo of management page"
|
||||
msgstr "管理页面logo"
|
||||
|
||||
#: xpack/plugins/interface/models.py:31
|
||||
#: xpack/plugins/interface/models.py:32
|
||||
msgid "Logo of logout page"
|
||||
msgstr "退出页面logo"
|
||||
|
||||
|
@ -5983,6 +5950,69 @@ msgstr "旗舰版"
|
|||
msgid "Community edition"
|
||||
msgstr "社区版"
|
||||
|
||||
#~ msgid "Login direct"
|
||||
#~ msgstr "直接登录"
|
||||
|
||||
#~ msgid "to apply for a password reset email."
|
||||
#~ msgstr "申请重置"
|
||||
|
||||
#~ msgid "Please login and reset your MFA."
|
||||
#~ msgstr "请登录并重新设置你的 MFA"
|
||||
|
||||
#~ msgid "Please login and reset your ssh public key."
|
||||
#~ msgstr "请登录并重新设置你的密钥"
|
||||
|
||||
# msgid "Update user"
|
||||
# msgstr "更新用户"
|
||||
#, python-format
|
||||
#~ msgid ""
|
||||
#~ "\n"
|
||||
#~ " <div>\n"
|
||||
#~ " <p>Your account has been created successfully</p>\n"
|
||||
#~ " <div>\n"
|
||||
#~ " Username: %(username)s\n"
|
||||
#~ " <br/>\n"
|
||||
#~ " Password: <a href=\"%(rest_password_url)s?token="
|
||||
#~ "%(rest_password_token)s\">\n"
|
||||
#~ " click here to set your password</a> \n"
|
||||
#~ " (This link is valid for 1 hour. After it expires, <a href="
|
||||
#~ "\"%(forget_password_url)s?email=%(email)s\">request new one</a>)\n"
|
||||
#~ " </div>\n"
|
||||
#~ " <div>\n"
|
||||
#~ " <p>---</p>\n"
|
||||
#~ " <a href=\"%(login_url)s\">Login direct</a>\n"
|
||||
#~ " </div>\n"
|
||||
#~ " </div>\n"
|
||||
#~ " "
|
||||
#~ msgstr ""
|
||||
#~ "\n"
|
||||
#~ " <div>\n"
|
||||
#~ " <p>您的账户已创建成功</p>\n"
|
||||
#~ " <div>\n"
|
||||
#~ " 用户名: %(username)s\n"
|
||||
#~ " <br/>\n"
|
||||
#~ " 密码: <a href=\"%(rest_password_url)s?token="
|
||||
#~ "%(rest_password_token)s\">请点击这里设置密码</a> (这个链接有效期1小时, 超"
|
||||
#~ "过时间您可以 <a href=\"%(forget_password_url)s?email=%(email)s\">重新申请"
|
||||
#~ "</a>)\n"
|
||||
#~ " </div>\n"
|
||||
#~ " <div>\n"
|
||||
#~ " <p>---</p>\n"
|
||||
#~ " <a href=\"%(login_url)s\">直接登录</a>\n"
|
||||
#~ " </div>\n"
|
||||
#~ " </div>\n"
|
||||
#~ " "
|
||||
|
||||
#, python-format
|
||||
#~ msgid "Hello %(name)s"
|
||||
#~ msgstr "你好 %(name)s"
|
||||
|
||||
#~ msgid "This link is valid for 1 hour. After it expires,"
|
||||
#~ msgstr "这个链接有效期1小时, 超过时间您可以"
|
||||
|
||||
#~ msgid "Welcome to the JumpServer open source Bastion Host"
|
||||
#~ msgstr "欢迎使用JumpServer开源堡垒机"
|
||||
|
||||
#~ msgid "Login IP"
|
||||
#~ msgstr "登录IP"
|
||||
|
||||
|
|
|
@ -12,7 +12,10 @@ from notifications.serializers import (
|
|||
UserMsgSubscriptionSerializer,
|
||||
)
|
||||
|
||||
__all__ = ('BackendListView', 'SystemMsgSubscriptionViewSet', 'UserMsgSubscriptionViewSet')
|
||||
__all__ = (
|
||||
'BackendListView', 'SystemMsgSubscriptionViewSet',
|
||||
'UserMsgSubscriptionViewSet', 'get_all_test_messages'
|
||||
)
|
||||
|
||||
|
||||
class BackendListView(APIView):
|
||||
|
@ -80,3 +83,43 @@ class UserMsgSubscriptionViewSet(ListModelMixin,
|
|||
queryset = UserMsgSubscription.objects.all()
|
||||
serializer_class = UserMsgSubscriptionSerializer
|
||||
permission_classes = (IsObjectOwner | IsSuperUser, OnlySuperUserCanList)
|
||||
|
||||
|
||||
def get_all_test_messages(request):
|
||||
import textwrap
|
||||
from ..notifications import Message
|
||||
from django.shortcuts import HttpResponse
|
||||
|
||||
msgs_cls = Message.get_all_sub_messages()
|
||||
html_data = '<h3>HTML 格式 </h3>'
|
||||
text_data = '<h3>Text 格式</h3>'
|
||||
|
||||
for msg_cls in msgs_cls:
|
||||
try:
|
||||
msg = msg_cls.gen_test_msg()
|
||||
if not msg:
|
||||
continue
|
||||
msg_html = msg.html_msg_with_sign['message']
|
||||
msg_text = msg.text_msg_with_sign['message']
|
||||
except NotImplementedError:
|
||||
msg_html = msg_text = '没有实现方法'
|
||||
except Exception as e:
|
||||
msg_html = msg_text = 'Error: ' + str(e)
|
||||
|
||||
html_data += """
|
||||
<h3>{}</h3>
|
||||
{}
|
||||
<hr />
|
||||
""".format(msg_cls.__name__, msg_html)
|
||||
|
||||
text_data += textwrap.dedent("""
|
||||
<h3>{}</h3>
|
||||
<pre>
|
||||
{}
|
||||
</pre>
|
||||
<br/>
|
||||
<hr />
|
||||
""").format(msg_cls.__name__, msg_text)
|
||||
return HttpResponse(html_data + text_data)
|
||||
|
||||
|
||||
|
|
|
@ -2,22 +2,23 @@ import traceback
|
|||
from html2text import HTML2Text
|
||||
from typing import Iterable
|
||||
from itertools import chain
|
||||
import textwrap
|
||||
|
||||
from celery import shared_task
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from common.utils.timezone import local_now
|
||||
from common.utils import lazyproperty
|
||||
from settings.utils import get_login_title
|
||||
from users.models import User
|
||||
from notifications.backends import BACKEND
|
||||
from .models import SystemMsgSubscription, UserMsgSubscription
|
||||
|
||||
__all__ = ('SystemMessage', 'UserMessage', 'system_msgs')
|
||||
__all__ = ('SystemMessage', 'UserMessage', 'system_msgs', 'Message')
|
||||
|
||||
|
||||
system_msgs = []
|
||||
user_msgs = []
|
||||
all_msgs = []
|
||||
|
||||
|
||||
class MessageType(type):
|
||||
|
@ -55,7 +56,6 @@ class Message(metaclass=MessageType):
|
|||
- publish 该方法的实现与消息订阅的表结构有关
|
||||
- send_msg
|
||||
"""
|
||||
|
||||
message_type_label: str
|
||||
category: str
|
||||
category_label: str
|
||||
|
@ -84,16 +84,13 @@ class Message(metaclass=MessageType):
|
|||
backend = BACKEND(backend)
|
||||
if not backend.is_enable:
|
||||
continue
|
||||
|
||||
get_msg_method = getattr(self, f'get_{backend}_msg', self.get_common_msg)
|
||||
try:
|
||||
msg = get_msg_method()
|
||||
except NotImplementedError:
|
||||
continue
|
||||
|
||||
msg = get_msg_method()
|
||||
client = backend.client()
|
||||
client.send_msg(users, **msg)
|
||||
except Exception:
|
||||
except NotImplementedError:
|
||||
continue
|
||||
except:
|
||||
traceback.print_exc()
|
||||
|
||||
@classmethod
|
||||
|
@ -111,10 +108,7 @@ class Message(metaclass=MessageType):
|
|||
|
||||
@staticmethod
|
||||
def get_common_msg() -> dict:
|
||||
return {
|
||||
'subject': '',
|
||||
'message': ''
|
||||
}
|
||||
return {'subject': '', 'message': ''}
|
||||
|
||||
def get_html_msg(self) -> dict:
|
||||
return self.get_common_msg()
|
||||
|
@ -133,11 +127,39 @@ class Message(metaclass=MessageType):
|
|||
|
||||
@lazyproperty
|
||||
def text_msg(self) -> dict:
|
||||
return self.get_text_msg()
|
||||
msg = self.get_text_msg()
|
||||
return msg
|
||||
|
||||
@lazyproperty
|
||||
def html_msg(self) -> dict:
|
||||
return self.get_html_msg()
|
||||
msg = self.get_html_msg()
|
||||
return msg
|
||||
|
||||
@lazyproperty
|
||||
def html_msg_with_sign(self):
|
||||
msg = self.get_html_msg()
|
||||
msg['message'] = textwrap.dedent("""
|
||||
{}
|
||||
<br />
|
||||
—
|
||||
<br />
|
||||
<small>{}</small>
|
||||
""").format(msg['message'], self.signature)
|
||||
return msg
|
||||
|
||||
@lazyproperty
|
||||
def text_msg_with_sign(self):
|
||||
msg = self.get_text_msg()
|
||||
msg['message'] = textwrap.dedent("""
|
||||
{}
|
||||
—
|
||||
{}
|
||||
""").format(msg['message'], self.signature)
|
||||
return msg
|
||||
|
||||
@lazyproperty
|
||||
def signature(self):
|
||||
return get_login_title()
|
||||
|
||||
# --------------------------------------------------------------
|
||||
# 支持不同发送消息的方式定义自己的消息内容,比如有些支持 html 标签
|
||||
|
@ -159,16 +181,16 @@ class Message(metaclass=MessageType):
|
|||
return self.text_msg
|
||||
|
||||
def get_email_msg(self) -> dict:
|
||||
return self.html_msg
|
||||
return self.html_msg_with_sign
|
||||
|
||||
def get_site_msg_msg(self) -> dict:
|
||||
return self.html_msg
|
||||
|
||||
def get_sms_msg(self) -> dict:
|
||||
return self.text_msg
|
||||
return self.text_msg_with_sign
|
||||
|
||||
@classmethod
|
||||
def test_all_messages(cls):
|
||||
def get_all_sub_messages(cls):
|
||||
def get_subclasses(cls):
|
||||
"""returns all subclasses of argument, cls"""
|
||||
if issubclass(cls, type):
|
||||
|
@ -180,6 +202,12 @@ class Message(metaclass=MessageType):
|
|||
return subclasses
|
||||
|
||||
messages_cls = get_subclasses(cls)
|
||||
return messages_cls
|
||||
|
||||
@classmethod
|
||||
def test_all_messages(cls):
|
||||
messages_cls = cls.get_all_sub_messages()
|
||||
|
||||
for _cls in messages_cls:
|
||||
try:
|
||||
msg = _cls.send_test_msg()
|
||||
|
@ -225,6 +253,11 @@ class UserMessage(Message):
|
|||
sub = UserMsgSubscription.objects.get(user=self.user)
|
||||
self.send_msg([self.user], sub.receive_backends)
|
||||
|
||||
@classmethod
|
||||
def get_test_user(cls):
|
||||
from users.models import User
|
||||
return User.objects.all().first()
|
||||
|
||||
@classmethod
|
||||
def gen_test_msg(cls):
|
||||
raise NotImplementedError
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
from rest_framework_bulk.routes import BulkRouter
|
||||
from django.urls import path
|
||||
from django.conf import settings
|
||||
|
||||
from notifications import api
|
||||
|
||||
|
@ -14,3 +15,8 @@ router.register('site-message', api.SiteMessageViewSet, 'site-message')
|
|||
urlpatterns = [
|
||||
path('backends/', api.BackendListView.as_view(), name='backends')
|
||||
] + router.urls
|
||||
|
||||
if settings.DEBUG:
|
||||
urlpatterns += [
|
||||
path('debug-msgs/', api.get_all_test_messages, name='debug-all-msgs')
|
||||
]
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
from notifications.notifications import SystemMessage
|
||||
from notifications.models import SystemMsgSubscription
|
||||
|
@ -14,14 +15,18 @@ class ServerPerformanceMessage(SystemMessage):
|
|||
category_label = _('Operations')
|
||||
message_type_label = _('Server performance')
|
||||
|
||||
def __init__(self, msg):
|
||||
self._msg = msg
|
||||
def __init__(self, terms_with_errors):
|
||||
self.terms_with_errors = terms_with_errors
|
||||
|
||||
def get_html_msg(self) -> dict:
|
||||
subject = self._msg[:80]
|
||||
subject = _("Terminal health check warning")
|
||||
context = {
|
||||
'terms_with_errors': self.terms_with_errors
|
||||
}
|
||||
message = render_to_string('ops/_msg_terminal_performance.html', context)
|
||||
return {
|
||||
'subject': subject.replace('<br>', '; '),
|
||||
'message': self._msg
|
||||
'subject': subject,
|
||||
'message': message
|
||||
}
|
||||
|
||||
@classmethod
|
||||
|
@ -33,17 +38,21 @@ class ServerPerformanceMessage(SystemMessage):
|
|||
|
||||
@classmethod
|
||||
def gen_test_msg(cls):
|
||||
alarm_messages = []
|
||||
from terminal.models import Terminal
|
||||
items_mapper = ServerPerformanceCheckUtil.items_mapper
|
||||
for item, data in items_mapper.items():
|
||||
msg = data['alarm_msg_format']
|
||||
max_threshold = data['max_threshold']
|
||||
value = 123
|
||||
msg = msg.format(max_threshold=max_threshold, value=value, name='Fake terminal')
|
||||
alarm_messages.append(msg)
|
||||
terms_with_errors = []
|
||||
terms = Terminal.objects.all()[:5]
|
||||
|
||||
msg = '<br>'.join(alarm_messages)
|
||||
return cls(msg)
|
||||
for i, term in enumerate(terms, 1):
|
||||
errors = []
|
||||
for item, data in items_mapper.items():
|
||||
msg = data['alarm_msg_format']
|
||||
max_threshold = data['max_threshold']
|
||||
value = 123 // i+1
|
||||
msg = msg.format(max_threshold=max_threshold, value=value, name=term.name)
|
||||
errors.append(msg)
|
||||
terms_with_errors.append([term, errors])
|
||||
return cls(terms_with_errors)
|
||||
|
||||
|
||||
class ServerPerformanceCheckUtil(object):
|
||||
|
@ -56,59 +65,65 @@ class ServerPerformanceCheckUtil(object):
|
|||
'disk_used': {
|
||||
'default': 0,
|
||||
'max_threshold': 80,
|
||||
'alarm_msg_format': _(
|
||||
'Disk used more than {max_threshold}%: => {value} ({name})'
|
||||
)
|
||||
'alarm_msg_format': _('Disk used more than {max_threshold}%: => {value}')
|
||||
},
|
||||
'memory_used': {
|
||||
'default': 0,
|
||||
'max_threshold': 85,
|
||||
'alarm_msg_format': _(
|
||||
'Memory used more than {max_threshold}%: => {value} ({name})'
|
||||
),
|
||||
'alarm_msg_format': _('Memory used more than {max_threshold}%: => {value}'),
|
||||
},
|
||||
'cpu_load': {
|
||||
'default': 0,
|
||||
'max_threshold': 5,
|
||||
'alarm_msg_format': _(
|
||||
'CPU load more than {max_threshold}: => {value} ({name})'
|
||||
),
|
||||
'alarm_msg_format': _('CPU load more than {max_threshold}: => {value}'),
|
||||
},
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.alarm_messages = []
|
||||
self.terms_with_errors = []
|
||||
self._terminals = []
|
||||
self._terminal = None
|
||||
|
||||
def check_and_publish(self):
|
||||
self.check()
|
||||
self.publish()
|
||||
|
||||
def check(self):
|
||||
self.alarm_messages = []
|
||||
self.terms_with_errors = []
|
||||
self.initial_terminals()
|
||||
for item, data in self.items_mapper.items():
|
||||
for self._terminal in self._terminals:
|
||||
self.check_item(item, data)
|
||||
|
||||
def check_item(self, item, data):
|
||||
for term in self._terminals:
|
||||
errors = self.check_terminal(term)
|
||||
if not errors:
|
||||
continue
|
||||
self.terms_with_errors.append((term, errors))
|
||||
|
||||
def check_terminal(self, term):
|
||||
errors = []
|
||||
for item, data in self.items_mapper.items():
|
||||
error = self.check_item(term, item, data)
|
||||
if not error:
|
||||
continue
|
||||
errors.append(error)
|
||||
return errors
|
||||
|
||||
@staticmethod
|
||||
def check_item(term, item, data):
|
||||
default = data['default']
|
||||
max_threshold = data['max_threshold']
|
||||
value = getattr(self._terminal.stat, item, default)
|
||||
value = getattr(term.stat, item, default)
|
||||
|
||||
if isinstance(value, bool) and value != max_threshold:
|
||||
return
|
||||
elif isinstance(value, (int, float)) and value < max_threshold:
|
||||
return
|
||||
msg = data['alarm_msg_format']
|
||||
msg = msg.format(max_threshold=max_threshold, value=value, name=self._terminal.name)
|
||||
self.alarm_messages.append(msg)
|
||||
error = msg.format(max_threshold=max_threshold, value=value, name=term.name)
|
||||
return error
|
||||
|
||||
def publish(self):
|
||||
if not self.alarm_messages:
|
||||
if not self.terms_with_errors:
|
||||
return
|
||||
msg = '<br>'.join(self.alarm_messages)
|
||||
ServerPerformanceMessage(msg).publish()
|
||||
ServerPerformanceMessage(self.terms_with_errors).publish()
|
||||
|
||||
def initial_terminals(self):
|
||||
terminals = []
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<div>
|
||||
{% for term, errors in terms_with_errors %}
|
||||
<h4>{{ term.name }}</h4>
|
||||
<ul>
|
||||
{% for error in errors %}
|
||||
<li>{{ error }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endfor %}
|
||||
</div>
|
|
@ -1,4 +1,6 @@
|
|||
from urllib.parse import urljoin
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
|
@ -6,7 +8,7 @@ from common.utils import reverse as js_reverse
|
|||
from notifications.notifications import UserMessage
|
||||
|
||||
|
||||
class PermedWillExpireUserMsg(UserMessage):
|
||||
class PermedAssetsWillExpireUserMsg(UserMessage):
|
||||
def __init__(self, user, assets):
|
||||
super().__init__(user)
|
||||
self.assets = assets
|
||||
|
@ -114,12 +116,9 @@ class AppPermsWillExpireForOrgAdminMsg(UserMessage):
|
|||
|
||||
def get_items_with_url(self):
|
||||
items_with_url = []
|
||||
perm_detail_url = urljoin(settings.SITE_URL, '/ui/#/perms/app-permissions/{}')
|
||||
for perm in self.perms:
|
||||
url = js_reverse(
|
||||
'perms:application-permission-detail',
|
||||
kwargs={'pk': perm.id}, external=True,
|
||||
api_to_ui=True
|
||||
) + f'?oid={perm.org_id}'
|
||||
url = perm_detail_url.format(perm.id) + f'?oid={perm.org_id}'
|
||||
items_with_url.append([perm.name, url])
|
||||
return items_with_url
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ from common.utils import get_logger
|
|||
from common.utils.timezone import local_now, dt_formatter, dt_parser
|
||||
from ops.celery.decorator import register_as_period_task
|
||||
from perms.notifications import (
|
||||
PermedWillExpireUserMsg, AssetPermsWillExpireForOrgAdminMsg,
|
||||
PermedAssetsWillExpireUserMsg, AssetPermsWillExpireForOrgAdminMsg,
|
||||
PermedAppsWillExpireUserMsg, AppPermsWillExpireForOrgAdminMsg
|
||||
)
|
||||
from perms.models import AssetPermission, ApplicationPermission
|
||||
|
@ -83,7 +83,7 @@ def check_asset_permission_will_expired():
|
|||
user_asset_mapper[u].update(assets)
|
||||
|
||||
for user, assets in user_asset_mapper.items():
|
||||
PermedWillExpireUserMsg(user, assets).publish_async()
|
||||
PermedAssetsWillExpireUserMsg(user, assets).publish_async()
|
||||
|
||||
for org, perms in org_perm_mapper.items():
|
||||
org_admins = org.admins.all()
|
||||
|
|
|
@ -17,8 +17,5 @@
|
|||
|
||||
<br />
|
||||
<p>
|
||||
---<br />
|
||||
<small>
|
||||
{% trans 'If you have any question, please contact the administrator' %}
|
||||
</small>
|
||||
{% trans 'If you have any question, please contact the administrator' %}
|
||||
</p>
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
from rest_framework import generics
|
||||
from rest_framework.permissions import AllowAny
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.templatetags.static import static
|
||||
|
||||
from jumpserver.utils import has_valid_xpack_license
|
||||
from common.utils import get_logger
|
||||
from .. import serializers
|
||||
from ..utils import get_interface_setting
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
@ -19,30 +18,14 @@ class PublicSettingApi(generics.RetrieveAPIView):
|
|||
|
||||
@staticmethod
|
||||
def get_logo_urls():
|
||||
logo_urls = {
|
||||
'logo_logout': static('img/logo.png'),
|
||||
'logo_index': static('img/logo_text.png'),
|
||||
'login_image': static('img/login_image.jpg'),
|
||||
'favicon': static('img/facio.ico')
|
||||
}
|
||||
if not settings.XPACK_ENABLED:
|
||||
return logo_urls
|
||||
from xpack.plugins.interface.models import Interface
|
||||
obj = Interface.interface()
|
||||
if not obj:
|
||||
return logo_urls
|
||||
for attr in ['logo_logout', 'logo_index', 'login_image', 'favicon']:
|
||||
if getattr(obj, attr, '') and getattr(obj, attr).url:
|
||||
logo_urls.update({attr: getattr(obj, attr).url})
|
||||
return logo_urls
|
||||
interface = get_interface_setting()
|
||||
keys = ['logo_logout', 'logo_index', 'login_image', 'favicon']
|
||||
return {k: interface[k] for k in keys}
|
||||
|
||||
@staticmethod
|
||||
def get_login_title():
|
||||
default_title = _('Welcome to the JumpServer open source Bastion Host')
|
||||
if not settings.XPACK_ENABLED:
|
||||
return default_title
|
||||
from xpack.plugins.interface.models import Interface
|
||||
return Interface.get_login_title()
|
||||
interface = get_interface_setting()
|
||||
return interface['login_title']
|
||||
|
||||
def get_object(self):
|
||||
instance = {
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
# coding: utf-8
|
||||
from jumpserver.context_processor import default_interface
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
class ObjectDict(dict):
|
||||
|
@ -16,3 +18,14 @@ class ObjectDict(dict):
|
|||
del self[name]
|
||||
else:
|
||||
raise AttributeError("No such attribute: " + name)
|
||||
|
||||
|
||||
def get_interface_setting():
|
||||
if not settings.XPACK_ENABLED:
|
||||
return default_interface
|
||||
from xpack.plugins.interface.models import Interface
|
||||
return Interface.get_interface_setting()
|
||||
|
||||
|
||||
def get_login_title():
|
||||
return get_interface_setting()['login_title']
|
||||
|
|
|
@ -134,11 +134,8 @@ class Terminal(StorageMixin, TerminalStatusMixin, models.Model):
|
|||
|
||||
@staticmethod
|
||||
def get_login_title_setting():
|
||||
login_title = None
|
||||
if settings.XPACK_ENABLED:
|
||||
from xpack.plugins.interface.models import Interface
|
||||
login_title = Interface.get_login_title()
|
||||
return {'TERMINAL_HEADER_TITLE': login_title}
|
||||
from settings.utils import get_login_title
|
||||
return {'TERMINAL_HEADER_TITLE': get_login_title()}
|
||||
|
||||
@property
|
||||
def config(self):
|
||||
|
|
|
@ -13,6 +13,8 @@ from notifications.models import SystemMsgSubscription
|
|||
from notifications.backends import BACKEND
|
||||
from orgs.utils import tmp_to_root_org
|
||||
from common.utils import lazyproperty
|
||||
from common.utils.timezone import local_now_display
|
||||
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
@ -73,25 +75,26 @@ class CommandAlertMessage(CommandAlertMixin, SystemMessage):
|
|||
@classmethod
|
||||
def gen_test_msg(cls):
|
||||
command = Command.objects.first().to_dict()
|
||||
command['session'] = Session.objects.first().id
|
||||
return cls(command)
|
||||
|
||||
def get_html_msg(self) -> dict:
|
||||
command = self.command
|
||||
|
||||
with tmp_to_root_org():
|
||||
session = Session.objects.get(id=command['session'])
|
||||
session_detail_url = reverse(
|
||||
'api-terminal:session-detail', kwargs={'pk': command['session']},
|
||||
external=True, api_to_ui=True
|
||||
)
|
||||
) + '?oid={}'.format(self.command['org_id'])
|
||||
level = Command.get_risk_level_str(command['risk_level'])
|
||||
items = {
|
||||
_("Asset"): command['asset'],
|
||||
_("User"): command['user'],
|
||||
_("Level"): level,
|
||||
_("Date"): local_now_display(),
|
||||
}
|
||||
context = {
|
||||
'command': command['input'],
|
||||
'hostname': command['asset'],
|
||||
'host_ip': session.asset_obj.ip,
|
||||
'user': command['user'],
|
||||
'risk_level': Command.get_risk_level_str(command['risk_level']),
|
||||
'session_detail_url': session_detail_url,
|
||||
'oid': session.org_id
|
||||
'items': items,
|
||||
'session_url': session_detail_url,
|
||||
"command": command['input'],
|
||||
}
|
||||
message = render_to_string('terminal/_msg_command_alert.html', context)
|
||||
return {
|
||||
|
@ -122,19 +125,25 @@ class CommandExecutionAlert(CommandAlertMixin, SystemMessage):
|
|||
|
||||
def get_html_msg(self) -> dict:
|
||||
command = self.command
|
||||
_input = command['input']
|
||||
_input = _input.replace('\n', '<br>')
|
||||
|
||||
assets_with_url = []
|
||||
for asset in command['assets']:
|
||||
url = reverse('assets:asset-detail', kwargs={'pk': asset.id}, api_to_ui=True, external=True)
|
||||
url = reverse(
|
||||
'assets:asset-detail', kwargs={'pk': asset.id},
|
||||
api_to_ui=True, external=True
|
||||
) + '?oid={}'.format(asset.org_id)
|
||||
assets_with_url.append([asset, url])
|
||||
|
||||
level = Command.get_risk_level_str(command['risk_level'])
|
||||
items = {
|
||||
_("User"): command['user'],
|
||||
_("Level"): level,
|
||||
_("Date"): local_now_display(),
|
||||
}
|
||||
|
||||
context = {
|
||||
'command': _input,
|
||||
'items': items,
|
||||
'assets_with_url': assets_with_url,
|
||||
'user': command['user'],
|
||||
'risk_level': Command.get_risk_level_str(command['risk_level'])
|
||||
'command': command['input'],
|
||||
}
|
||||
message = render_to_string('terminal/_msg_command_execute_alert.html', context)
|
||||
return {
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
{% load i18n %}
|
||||
|
||||
<p>
|
||||
<b>{% trans 'Command' %}:</b> {{ command }}
|
||||
</p>
|
||||
<p>
|
||||
<b>{% trans 'Asset' %}:</b> {{ hostname }}({{ host_ip }})
|
||||
</p>
|
||||
<p>
|
||||
<b>{% trans 'User' %}:</b> {{ user }}
|
||||
</p>
|
||||
<p>
|
||||
<b>{% trans 'Level' %}:</b> {{ risk_level }}
|
||||
</p>
|
||||
<p>
|
||||
<b>{% trans 'Session' %}:</b> <a href="{{ session_detail_url}}?oid={{ oid }}">{% trans 'view' %}</a>
|
||||
</p>
|
||||
<div>
|
||||
{% for item, value in items.items %}
|
||||
<span class="cmd-item">
|
||||
<b>{{ item }}:</b> {{ value }}
|
||||
</span>
|
||||
<br />
|
||||
{% endfor %}
|
||||
<b>{% trans 'Session' %}:</b> <a href="{{ session_url }}">{% trans 'view' %}</a>
|
||||
<br />
|
||||
<b>{% trans 'Command' %}: </b><br />
|
||||
<pre>
|
||||
{{ command }}
|
||||
</pre>
|
||||
</div>
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
{% load i18n %}
|
||||
|
||||
<p>
|
||||
<b>{% trans 'User' %}:</b> {{ user }}
|
||||
</p>
|
||||
<p>
|
||||
<b>{% trans 'Level' %}:</b> {{ risk_level }}
|
||||
</p>
|
||||
<div>
|
||||
<b>{% trans 'Command' %}: </b><br>
|
||||
<pre>
|
||||
{% for item, value in items.items %}
|
||||
<span class="cmd-item">
|
||||
<b>{{ item }}:</b> {{ value }}
|
||||
</span>
|
||||
<br />
|
||||
{% endfor %}
|
||||
<b>{% trans 'Command' %}: </b><br />
|
||||
<pre>
|
||||
{{ command }}
|
||||
</pre>
|
||||
</pre>
|
||||
</div>
|
||||
<div>
|
||||
<b>{% trans 'Assets' %}:</b><br>
|
||||
|
|
|
@ -19,6 +19,7 @@ class BaseTicketMessage(UserMessage):
|
|||
|
||||
@property
|
||||
def ticket_detail_url(self):
|
||||
tp = self.ticket.type
|
||||
return urljoin(settings.SITE_URL, const.TICKET_DETAIL_URL.format(id=str(self.ticket.id)))
|
||||
|
||||
@property
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from datetime import datetime
|
||||
from urllib.parse import urljoin
|
||||
|
||||
from django.utils import timezone
|
||||
|
@ -10,6 +9,38 @@ from common.utils import reverse, get_request_ip_or_data, get_request_user_agent
|
|||
from notifications.notifications import UserMessage
|
||||
|
||||
|
||||
class UserCreatedMsg(UserMessage):
|
||||
def get_html_msg(self) -> dict:
|
||||
user = self.user
|
||||
subject = _('Create account successfully')
|
||||
if settings.EMAIL_CUSTOM_USER_CREATED_SUBJECT:
|
||||
subject = settings.EMAIL_CUSTOM_USER_CREATED_SUBJECT
|
||||
|
||||
honorific = settings.EMAIL_CUSTOM_USER_CREATED_HONORIFIC or _('Hello {}').format(user.name)
|
||||
signature = settings.EMAIL_CUSTOM_USER_CREATED_SIGNATURE or 'JumpServer'
|
||||
|
||||
context = {
|
||||
'honorific': honorific,
|
||||
'signature': signature,
|
||||
'username': user.username,
|
||||
'rest_password_url': reverse('authentication:reset-password', external=True),
|
||||
'rest_password_token': user.generate_reset_token(),
|
||||
'forget_password_url': reverse('authentication:forgot-password', external=True),
|
||||
'email': user.email,
|
||||
'login_url': reverse('authentication:login', external=True),
|
||||
}
|
||||
message = render_to_string('users/_msg_user_created.html', context)
|
||||
return {
|
||||
'subject': subject,
|
||||
'message': message
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def gen_test_msg(cls):
|
||||
user = cls.get_test_user()
|
||||
return cls(user)
|
||||
|
||||
|
||||
class ResetPasswordMsg(UserMessage):
|
||||
def __init__(self, user):
|
||||
super().__init__(user)
|
||||
|
@ -71,18 +102,17 @@ class ResetPasswordSuccessMsg(UserMessage):
|
|||
|
||||
|
||||
class PasswordExpirationReminderMsg(UserMessage):
|
||||
update_password_url = urljoin(settings.SITE_URL, '/ui/#/users/profile/?activeTab=PasswordUpdate')
|
||||
|
||||
def get_html_msg(self) -> dict:
|
||||
user = self.user
|
||||
subject = _('Password is about expire')
|
||||
|
||||
date_password_expired_local = timezone.localtime(user.date_password_expired)
|
||||
update_password_url = urljoin(settings.SITE_URL, '/ui/#/users/profile/?activeTab=PasswordUpdate')
|
||||
date_password_expired = date_password_expired_local.strftime('%Y-%m-%d %H:%M:%S')
|
||||
context = {
|
||||
'name': user.name,
|
||||
'date_password_expired': date_password_expired,
|
||||
'update_password_url': self.update_password_url,
|
||||
'update_password_url': update_password_url,
|
||||
'forget_password_url': reverse('authentication:forgot-password', external=True),
|
||||
'email': user.email,
|
||||
'login_url': reverse('authentication:login', external=True),
|
||||
|
@ -125,9 +155,10 @@ class UserExpirationReminderMsg(UserMessage):
|
|||
class ResetSSHKeyMsg(UserMessage):
|
||||
def get_html_msg(self) -> dict:
|
||||
subject = _('Reset SSH Key')
|
||||
update_url = urljoin(settings.SITE_URL, '/ui/#/users/profile/?activeTab=SSHUpdate')
|
||||
context = {
|
||||
'name': self.user.name,
|
||||
'login_url': reverse('authentication:login', external=True),
|
||||
'url': update_url,
|
||||
}
|
||||
message = render_to_string('users/_msg_reset_ssh_key.html', context)
|
||||
return {
|
||||
|
@ -147,7 +178,7 @@ class ResetMFAMsg(UserMessage):
|
|||
subject = _('Reset MFA')
|
||||
context = {
|
||||
'name': self.user.name,
|
||||
'login_url': reverse('authentication:login', external=True),
|
||||
'url': reverse('authentication:user-otp-enable-start', external=True),
|
||||
}
|
||||
message = render_to_string('users/_msg_reset_mfa.html', context)
|
||||
return {
|
||||
|
|
|
@ -13,10 +13,6 @@
|
|||
</p>
|
||||
|
||||
<p>
|
||||
{% trans 'If your password has expired, please click' %}
|
||||
{% trans 'If your password has expired, please click the link below to' %}
|
||||
<a href="{{ forget_password_url }}?email={{ email }}">{% trans 'Reset password' %}</a>
|
||||
{% trans 'to apply for a password reset email.' %}
|
||||
</p>
|
||||
---
|
||||
<br>
|
||||
<a href="{{ login_url }}">{% trans 'Login direct' %}</a>
|
|
@ -4,9 +4,9 @@
|
|||
{% trans 'Hello' %} {{ name }},
|
||||
</p>
|
||||
<p>
|
||||
{% trans 'Your MFA has been reset by site administrator.' %} <br />
|
||||
{% trans 'Please login and reset your MFA.' %}
|
||||
{% trans 'Your MFA has been reset by site administrator' %} <br />
|
||||
{% trans 'Please click the link below to set' %}
|
||||
<br>
|
||||
<br>
|
||||
<a href="{{ url }}" class='showLink'>{% trans 'Click here set' %}</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="{{ login_url }}">{% trans 'Login direct' %}</a>
|
||||
</p>
|
|
@ -4,9 +4,9 @@
|
|||
{% trans 'Hello' %} {{ name }},
|
||||
</p>
|
||||
<p>
|
||||
{% trans 'Your ssh public key has been reset by site administrator.' %} <br />
|
||||
{% trans 'Please login and reset your ssh public key.' %}
|
||||
{% trans 'Your ssh public key has been reset by site administrator' %} <br />
|
||||
{% trans 'Please click the link below to set' %}
|
||||
<br>
|
||||
<br>
|
||||
<a href="{{ url }}" class='showLink'>{% trans 'Click here set' %}</a>
|
||||
</p>
|
||||
<p>
|
||||
<a href="{{ login_url }}">{% trans 'Login direct' %}</a>
|
||||
</p>
|
|
@ -0,0 +1,20 @@
|
|||
{% load i18n %}
|
||||
|
||||
<p>
|
||||
{{ honorific }}:
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<p>{% trans 'Your account has been created successfully' %}</p>
|
||||
<p>
|
||||
{% trans 'Username' %}: {{ username }} <br />
|
||||
{% trans 'Password' %}:
|
||||
<a href="{{ rest_password_url}}?token={{ rest_password_token }}">
|
||||
{% trans 'click here to set your password' %}
|
||||
</a>
|
||||
</p>
|
||||
<p>
|
||||
{% trans 'This link is valid for 1 hour. After it expires' %}
|
||||
<a href="{{ forget_password_url }}?email={{ email }}">{% trans 'request new one' %}</a>
|
||||
</p>
|
||||
</div>
|
|
@ -8,67 +8,24 @@ import logging
|
|||
import time
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.core.cache import cache
|
||||
|
||||
from common.tasks import send_mail_async
|
||||
from common.utils import reverse, get_object_or_none, get_request_ip_or_data, get_request_user_agent
|
||||
from common.utils import reverse, get_object_or_none
|
||||
from .models import User
|
||||
|
||||
|
||||
logger = logging.getLogger('jumpserver')
|
||||
|
||||
|
||||
def construct_user_created_email_body(user):
|
||||
default_body = _("""
|
||||
<div>
|
||||
<p>Your account has been created successfully</p>
|
||||
<div>
|
||||
Username: %(username)s
|
||||
<br/>
|
||||
Password: <a href="%(rest_password_url)s?token=%(rest_password_token)s">
|
||||
click here to set your password</a>
|
||||
(This link is valid for 1 hour. After it expires, <a href="%(forget_password_url)s?email=%(email)s">request new one</a>)
|
||||
</div>
|
||||
<div>
|
||||
<p>---</p>
|
||||
<a href="%(login_url)s">Login direct</a>
|
||||
</div>
|
||||
</div>
|
||||
""") % {
|
||||
'username': user.username,
|
||||
'rest_password_url': reverse('authentication:reset-password', external=True),
|
||||
'rest_password_token': user.generate_reset_token(),
|
||||
'forget_password_url': reverse('authentication:forgot-password', external=True),
|
||||
'email': user.email,
|
||||
'login_url': reverse('authentication:login', external=True),
|
||||
}
|
||||
|
||||
if settings.EMAIL_CUSTOM_USER_CREATED_BODY:
|
||||
custom_body = '<p style="text-indent:2em">' + settings.EMAIL_CUSTOM_USER_CREATED_BODY + '</p>'
|
||||
else:
|
||||
custom_body = ''
|
||||
body = custom_body + default_body
|
||||
return body
|
||||
|
||||
|
||||
def send_user_created_mail(user):
|
||||
from .notifications import UserCreatedMsg
|
||||
|
||||
recipient_list = [user.email]
|
||||
subject = _('Create account successfully')
|
||||
if settings.EMAIL_CUSTOM_USER_CREATED_SUBJECT:
|
||||
subject = settings.EMAIL_CUSTOM_USER_CREATED_SUBJECT
|
||||
msg = UserCreatedMsg.html_msg
|
||||
subject = msg['subject']
|
||||
message = msg['message']
|
||||
|
||||
honorific = '<p>' + _('Hello %(name)s') % {'name': user.name} + ':</p>'
|
||||
if settings.EMAIL_CUSTOM_USER_CREATED_HONORIFIC:
|
||||
honorific = '<p>' + settings.EMAIL_CUSTOM_USER_CREATED_HONORIFIC + ':</p>'
|
||||
|
||||
body = construct_user_created_email_body(user)
|
||||
|
||||
signature = '<p style="float:right">jumpserver</p>'
|
||||
if settings.EMAIL_CUSTOM_USER_CREATED_SIGNATURE:
|
||||
signature = '<p style="float:right">' + settings.EMAIL_CUSTOM_USER_CREATED_SIGNATURE + '</p>'
|
||||
|
||||
message = honorific + body + signature
|
||||
if settings.DEBUG:
|
||||
try:
|
||||
print(message)
|
||||
|
|
Loading…
Reference in New Issue