diff --git a/apps/authentication/templates/authentication/_msg_rest_public_key_success.html b/apps/authentication/templates/authentication/_msg_rest_public_key_success.html
new file mode 100644
index 000000000..a95bfdd9b
--- /dev/null
+++ b/apps/authentication/templates/authentication/_msg_rest_public_key_success.html
@@ -0,0 +1,14 @@
+{% load i18n %}
+
{% trans 'Hello' %} {{ name }},
+
+
+ {% trans 'Your public key has just been successfully updated' %}
+
+
+ {% trans 'IP' %}: {{ ip_address }}
+ {% trans 'Browser' %}: {{ browser }}
+
+
+ {% trans 'If the public key update was not initiated by you, your account may have security issues' %}
+ {% trans 'If you have any questions, you can contact the administrator' %}
+
diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po
index 2b057ff8f..0b4d4b4be 100644
--- a/apps/locale/zh/LC_MESSAGES/django.po
+++ b/apps/locale/zh/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: JumpServer 0.3.3\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-11-10 17:18+0800\n"
+"POT-Creation-Date: 2021-11-12 15:28+0800\n"
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
"Last-Translator: ibuler \n"
"Language-Team: JumpServer team\n"
@@ -52,7 +52,7 @@ msgid "Active"
msgstr "激活中"
#: acls/models/base.py:32 applications/models/application.py:179
-#: assets/models/asset.py:144 assets/models/asset.py:220
+#: assets/models/asset.py:144 assets/models/asset.py:232
#: assets/models/base.py:180 assets/models/cluster.py:29
#: assets/models/cmd_filter.py:23 assets/models/cmd_filter.py:64
#: assets/models/domain.py:25 assets/models/domain.py:65
@@ -128,7 +128,7 @@ msgstr "系统用户"
#: acls/models/login_asset_acl.py:22
#: applications/serializers/attrs/application_category/remote_app.py:37
-#: assets/models/asset.py:357 assets/models/authbook.py:18
+#: assets/models/asset.py:350 assets/models/authbook.py:18
#: assets/models/gathered_user.py:14 assets/serializers/system_user.py:258
#: audits/models.py:38 perms/models/asset_permission.py:99
#: templates/index.html:82 terminal/backends/command/models.py:19
@@ -192,16 +192,17 @@ msgstr ""
#: acls/serializers/login_asset_acl.py:31 acls/serializers/rules/rules.py:32
#: applications/serializers/attrs/application_type/mysql_workbench.py:18
-#: assets/models/asset.py:180 assets/models/domain.py:61
+#: assets/models/asset.py:211 assets/models/domain.py:61
#: assets/serializers/account.py:12
#: authentication/templates/authentication/_msg_rest_password_success.html:8
+#: authentication/templates/authentication/_msg_rest_public_key_success.html:8
#: settings/serializers/terminal.py:8
#: users/templates/users/_granted_assets.html:26
#: users/templates/users/user_asset_permission.html:156
msgid "IP"
msgstr "IP"
-#: acls/serializers/login_asset_acl.py:35 assets/models/asset.py:181
+#: acls/serializers/login_asset_acl.py:35 assets/models/asset.py:212
#: assets/serializers/account.py:13 assets/serializers/gathered_user.py:23
#: settings/serializers/terminal.py:7
#: users/templates/users/_granted_assets.html:25
@@ -215,7 +216,7 @@ msgid ""
"options: {}"
msgstr "格式为逗号分隔的字符串, * 表示匹配所有. 可选的协议有: {}"
-#: acls/serializers/login_asset_acl.py:55 assets/models/asset.py:184
+#: acls/serializers/login_asset_acl.py:55 assets/models/asset.py:214
#: assets/models/domain.py:63 assets/models/user.py:200
#: terminal/serializers/session.py:30 terminal/serializers/storage.py:69
msgid "Protocol"
@@ -323,7 +324,7 @@ msgstr "类别"
msgid "Type"
msgstr "类型"
-#: applications/models/application.py:175 assets/models/asset.py:188
+#: applications/models/application.py:175 assets/models/asset.py:218
#: assets/models/domain.py:30 assets/models/domain.py:64
msgid "Domain"
msgstr "网域"
@@ -375,7 +376,7 @@ msgstr "主机"
#: applications/serializers/attrs/application_type/mysql_workbench.py:22
#: applications/serializers/attrs/application_type/oracle.py:11
#: applications/serializers/attrs/application_type/pgsql.py:11
-#: assets/models/asset.py:185 assets/models/domain.py:62
+#: assets/models/asset.py:215 assets/models/domain.py:62
#: settings/serializers/auth/radius.py:15
#: xpack/plugins/cloud/serializers/account_attrs.py:61
msgid "Port"
@@ -463,103 +464,103 @@ msgstr "元数据"
msgid "Internal"
msgstr "内部的"
-#: assets/models/asset.py:163 assets/models/asset.py:187
+#: assets/models/asset.py:163 assets/models/asset.py:217
#: assets/serializers/asset.py:65 perms/serializers/asset/user_permission.py:43
msgid "Platform"
msgstr "系统平台"
-#: assets/models/asset.py:186 assets/serializers/asset.py:67
+#: assets/models/asset.py:169
+msgid "Vendor"
+msgstr "制造商"
+
+#: assets/models/asset.py:170
+msgid "Model"
+msgstr "型号"
+
+#: assets/models/asset.py:171
+msgid "Serial number"
+msgstr "序列号"
+
+#: assets/models/asset.py:173
+msgid "CPU model"
+msgstr "CPU型号"
+
+#: assets/models/asset.py:174
+msgid "CPU count"
+msgstr "CPU数量"
+
+#: assets/models/asset.py:175
+msgid "CPU cores"
+msgstr "CPU核数"
+
+#: assets/models/asset.py:176
+msgid "CPU vcpus"
+msgstr "CPU总数"
+
+#: assets/models/asset.py:177
+msgid "Memory"
+msgstr "内存"
+
+#: assets/models/asset.py:178
+msgid "Disk total"
+msgstr "硬盘大小"
+
+#: assets/models/asset.py:179
+msgid "Disk info"
+msgstr "硬盘信息"
+
+#: assets/models/asset.py:181
+msgid "OS"
+msgstr "操作系统"
+
+#: assets/models/asset.py:182
+msgid "OS version"
+msgstr "系统版本"
+
+#: assets/models/asset.py:183
+msgid "OS arch"
+msgstr "系统架构"
+
+#: assets/models/asset.py:184
+msgid "Hostname raw"
+msgstr "主机名原始"
+
+#: assets/models/asset.py:216 assets/serializers/asset.py:67
#: perms/serializers/asset/user_permission.py:41
#: xpack/plugins/cloud/models.py:104 xpack/plugins/cloud/serializers/task.py:42
msgid "Protocols"
msgstr "协议组"
-#: assets/models/asset.py:189 assets/models/user.py:190
+#: assets/models/asset.py:219 assets/models/user.py:190
#: perms/models/asset_permission.py:100
#: xpack/plugins/change_auth_plan/models/asset.py:44
#: xpack/plugins/gathered_user/models.py:24
msgid "Nodes"
msgstr "节点"
-#: assets/models/asset.py:190 assets/models/cmd_filter.py:22
+#: assets/models/asset.py:220 assets/models/cmd_filter.py:22
#: assets/models/domain.py:66 assets/models/label.py:22
msgid "Is active"
msgstr "激活"
-#: assets/models/asset.py:193 assets/models/cluster.py:19
+#: assets/models/asset.py:223 assets/models/cluster.py:19
#: assets/models/user.py:187 assets/models/user.py:340 templates/_nav.html:44
msgid "Admin user"
msgstr "特权用户"
-#: assets/models/asset.py:196
+#: assets/models/asset.py:226
msgid "Public IP"
msgstr "公网IP"
-#: assets/models/asset.py:197
+#: assets/models/asset.py:227
msgid "Asset number"
msgstr "资产编号"
-#: assets/models/asset.py:200
-msgid "Vendor"
-msgstr "制造商"
-
-#: assets/models/asset.py:201
-msgid "Model"
-msgstr "型号"
-
-#: assets/models/asset.py:202
-msgid "Serial number"
-msgstr "序列号"
-
-#: assets/models/asset.py:204
-msgid "CPU model"
-msgstr "CPU型号"
-
-#: assets/models/asset.py:205
-msgid "CPU count"
-msgstr "CPU数量"
-
-#: assets/models/asset.py:206
-msgid "CPU cores"
-msgstr "CPU核数"
-
-#: assets/models/asset.py:207
-msgid "CPU vcpus"
-msgstr "CPU总数"
-
-#: assets/models/asset.py:208
-msgid "Memory"
-msgstr "内存"
-
-#: assets/models/asset.py:209
-msgid "Disk total"
-msgstr "硬盘大小"
-
-#: assets/models/asset.py:210
-msgid "Disk info"
-msgstr "硬盘信息"
-
-#: assets/models/asset.py:212
-msgid "OS"
-msgstr "操作系统"
-
-#: assets/models/asset.py:213
-msgid "OS version"
-msgstr "系统版本"
-
-#: assets/models/asset.py:214
-msgid "OS arch"
-msgstr "系统架构"
-
-#: assets/models/asset.py:215
-msgid "Hostname raw"
-msgstr "主机名原始"
-
-#: assets/models/asset.py:217 templates/_nav.html:46
+#: assets/models/asset.py:229 templates/_nav.html:46
msgid "Labels"
msgstr "标签管理"
-#: assets/models/asset.py:218 assets/models/base.py:183
+#: assets/models/asset.py:230 assets/models/base.py:183
#: assets/models/cluster.py:28 assets/models/cmd_filter.py:26
#: assets/models/cmd_filter.py:67 assets/models/group.py:21
#: common/db/models.py:70 common/mixins/models.py:49 orgs/models.py:25
@@ -570,7 +571,7 @@ msgstr "标签管理"
msgid "Created by"
msgstr "创建者"
-#: assets/models/asset.py:219 assets/models/base.py:181
+#: assets/models/asset.py:231 assets/models/base.py:181
#: assets/models/cluster.py:26 assets/models/domain.py:27
#: assets/models/gathered_user.py:19 assets/models/group.py:22
#: assets/models/label.py:25 common/db/models.py:72 common/mixins/models.py:50
@@ -875,19 +876,14 @@ msgstr "协议重复: {}"
msgid "Domain name"
msgstr "网域名称"
-#: assets/serializers/asset.py:69
+#: assets/serializers/asset.py:70
msgid "Nodes name"
msgstr "节点名称"
-#: assets/serializers/asset.py:103
+#: assets/serializers/asset.py:104
msgid "Hardware info"
msgstr "硬件信息"
-#: assets/serializers/asset.py:104 assets/serializers/system_user.py:276
-#: orgs/mixins/serializers.py:26
-msgid "Org name"
-msgstr "组织名称"
-
#: assets/serializers/asset.py:105
msgid "Admin user display"
msgstr "特权用户名称"
@@ -988,6 +984,10 @@ msgstr "仅允许自动登录的系统用户"
msgid "System user name"
msgstr "系统用户名称"
+#: assets/serializers/system_user.py:276 orgs/mixins/serializers.py:26
+msgid "Org name"
+msgstr "组织名称"
+
#: assets/serializers/system_user.py:285
msgid "Asset hostname"
msgstr "资产主机名"
@@ -1501,7 +1501,7 @@ msgstr "{ApplicationPermission} 添加 {SystemUser}"
msgid "{ApplicationPermission} REMOVE {SystemUser}"
msgstr "{ApplicationPermission} 移除 {SystemUser}"
-#: authentication/api/connection_token.py:239
+#: authentication/api/connection_token.py:248
msgid "Invalid token"
msgstr "无效的令牌"
@@ -1880,6 +1880,7 @@ msgstr "代码错误"
#: authentication/templates/authentication/_msg_different_city.html:3
#: authentication/templates/authentication/_msg_reset_password.html:3
#: authentication/templates/authentication/_msg_rest_password_success.html:2
+#: authentication/templates/authentication/_msg_rest_public_key_success.html:2
#: jumpserver/conf.py:269
#: perms/templates/perms/_msg_item_permissions_expire.html:3
#: perms/templates/perms/_msg_permed_items_expire.html:3
@@ -1929,6 +1930,7 @@ msgid "Your password has just been successfully updated"
msgstr "你的密码刚刚成功更新"
#: authentication/templates/authentication/_msg_rest_password_success.html:9
+#: authentication/templates/authentication/_msg_rest_public_key_success.html:9
msgid "Browser"
msgstr "浏览器"
@@ -1939,9 +1941,20 @@ msgid ""
msgstr "如果这次密码更新不是由你发起的,那么你的账号可能存在安全问题"
#: authentication/templates/authentication/_msg_rest_password_success.html:13
+#: authentication/templates/authentication/_msg_rest_public_key_success.html:13
msgid "If you have any questions, you can contact the administrator"
msgstr "如果有疑问或需求,请联系系统管理员"
+#: authentication/templates/authentication/_msg_rest_public_key_success.html:5
+msgid "Your public key has just been successfully updated"
+msgstr "你的公钥刚刚成功更新"
+
+#: authentication/templates/authentication/_msg_rest_public_key_success.html:12
+msgid ""
+"If the public key update was not initiated by you, your account may have "
+"security issues"
+msgstr "如果这次公钥更新不是由你发起的,那么你的账号可能存在安全问题"
+
#: authentication/templates/authentication/login.html:143
msgid "Welcome back, please enter username and password to login"
msgstr "欢迎回来,请输入用户名和密码登录"
@@ -3262,7 +3275,9 @@ msgstr "显示未分组节点"
#: settings/serializers/other.py:30
msgid "Perm single to ungroup node"
-msgstr "放置单独授权的资产到未分组节点, 避免能看到资产所在节点,但该节点未被授权的问题"
+msgstr ""
+"放置单独授权的资产到未分组节点, 避免能看到资产所在节点,但该节点未被授权的问"
+"题"
#: settings/serializers/other.py:34
msgid "Help Docs URL"
@@ -3280,14 +3295,6 @@ msgstr "支持链接"
msgid "default: http://www.jumpserver.org/support/"
msgstr "默认: http://www.jumpserver.org/support/"
-#: settings/serializers/other.py:44
-msgid "Help Website URL"
-msgstr "官网链接"
-
-#: settings/serializers/other.py:45
-msgid "default: http://www.jumpserver.org"
-msgstr "如: http://dev.jumpserver.org:8080"
-
#: settings/serializers/security.py:8
msgid "Password minimum length"
msgstr "密码最小长度"
@@ -5064,19 +5071,23 @@ msgstr "重置密码"
msgid "Reset password success"
msgstr "重置密码成功"
-#: users/notifications.py:111
+#: users/notifications.py:117
+msgid "Reset public key success"
+msgstr "重置公钥成功"
+
+#: users/notifications.py:143
msgid "Password is about expire"
msgstr "密码即将过期"
-#: users/notifications.py:139
+#: users/notifications.py:171
msgid "Account is about expire"
msgstr "账号即将过期"
-#: users/notifications.py:161
+#: users/notifications.py:193
msgid "Reset SSH Key"
msgstr "重置 SSH 密钥"
-#: users/notifications.py:182
+#: users/notifications.py:214
msgid "Reset MFA"
msgstr "重置 MFA"
@@ -5523,8 +5534,8 @@ msgstr "* 新密码不能是最近 {} 次的密码"
msgid "Reset password success, return to login page"
msgstr "重置密码成功,返回到登录页面"
-#: xpack/plugins/change_auth_plan/api/app.py:113
-#: xpack/plugins/change_auth_plan/api/asset.py:100
+#: xpack/plugins/change_auth_plan/api/app.py:114
+#: xpack/plugins/change_auth_plan/api/asset.py:101
msgid "The parameter 'action' must be [{}]"
msgstr "参数 'action' 必须是 [{}]"
@@ -5655,15 +5666,15 @@ msgstr "* 请输入正确的密码长度"
msgid "* Password length range 6-30 bits"
msgstr "* 密码长度范围 6-30 位"
-#: xpack/plugins/change_auth_plan/task_handlers/base/handler.py:248
+#: xpack/plugins/change_auth_plan/task_handlers/base/handler.py:249
msgid "Invalid/incorrect password"
msgstr "无效/错误 密码"
-#: xpack/plugins/change_auth_plan/task_handlers/base/handler.py:250
+#: xpack/plugins/change_auth_plan/task_handlers/base/handler.py:251
msgid "Failed to connect to the host"
msgstr "连接主机失败"
-#: xpack/plugins/change_auth_plan/task_handlers/base/handler.py:252
+#: xpack/plugins/change_auth_plan/task_handlers/base/handler.py:253
msgid "Data could not be sent to remote"
msgstr "无法将数据发送到远程"
@@ -6021,7 +6032,7 @@ msgstr "执行次数"
msgid "Instance count"
msgstr "实例个数"
-#: xpack/plugins/cloud/utils.py:65
+#: xpack/plugins/cloud/utils.py:68
msgid "Account unavailable"
msgstr "账户无效"
@@ -6109,6 +6120,12 @@ msgstr "旗舰版"
msgid "Community edition"
msgstr "社区版"
+#~ msgid "Help Website URL"
+#~ msgstr "官网链接"
+
+#~ msgid "default: http://www.jumpserver.org"
+#~ msgstr "如: http://dev.jumpserver.org:8080"
+
#~ msgid "One-time password invalid, or ntp sync server time"
#~ msgstr "MFA 验证码不正确,或者服务器端时间不对"
diff --git a/apps/users/api/profile.py b/apps/users/api/profile.py
index 372ed5809..14aa1d8f6 100644
--- a/apps/users/api/profile.py
+++ b/apps/users/api/profile.py
@@ -5,7 +5,10 @@ from rest_framework import generics
from common.permissions import IsOrgAdmin
from rest_framework.permissions import IsAuthenticated
-from users.notifications import ResetPasswordMsg, ResetPasswordSuccessMsg, ResetSSHKeyMsg
+from users.notifications import (
+ ResetPasswordMsg, ResetPasswordSuccessMsg, ResetSSHKeyMsg,
+ ResetPublicKeySuccessMsg,
+)
from common.permissions import (
IsCurrentUserOrReadOnly
)
@@ -87,4 +90,4 @@ class UserPublicKeyApi(generics.RetrieveUpdateAPIView):
def perform_update(self, serializer):
super().perform_update(serializer)
- ResetPasswordSuccessMsg(self.get_object(), self.request).publish_async()
+ ResetPublicKeySuccessMsg(self.get_object(), self.request).publish_async()
diff --git a/apps/users/notifications.py b/apps/users/notifications.py
index d1fbad546..c9e5a0521 100644
--- a/apps/users/notifications.py
+++ b/apps/users/notifications.py
@@ -105,6 +105,38 @@ class ResetPasswordSuccessMsg(UserMessage):
return cls(user, request)
+class ResetPublicKeySuccessMsg(UserMessage):
+ def __init__(self, user, request):
+ super().__init__(user)
+ self.ip_address = get_request_ip_or_data(request)
+ self.browser = get_request_user_agent(request)
+
+ def get_html_msg(self) -> dict:
+ user = self.user
+
+ subject = _('Reset public key success')
+ context = {
+ 'name': user.name,
+ 'ip_address': self.ip_address,
+ 'browser': self.browser,
+ }
+ message = render_to_string('authentication/_msg_rest_public_key_success.html', context)
+ return {
+ 'subject': subject,
+ 'message': message
+ }
+
+ @classmethod
+ def gen_test_msg(cls):
+ from users.models import User
+ from rest_framework.test import APIRequestFactory
+ from rest_framework.request import Request
+ factory = APIRequestFactory()
+ request = Request(factory.get('/notes/'))
+ user = User.objects.first()
+ return cls(user, request)
+
+
class PasswordExpirationReminderMsg(UserMessage):
def get_html_msg(self) -> dict:
user = self.user