From e4178849ba08982506e8988ca6696756a2bf1b5f Mon Sep 17 00:00:00 2001
From: feng626 <1304903146@qq.com>
Date: Wed, 15 Dec 2021 14:23:07 +0800
Subject: [PATCH 1/8] perf: ticket filter
---
apps/tickets/filters.py | 2 +-
apps/tickets/handler/base.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/apps/tickets/filters.py b/apps/tickets/filters.py
index 676efbea2..3c795f0df 100644
--- a/apps/tickets/filters.py
+++ b/apps/tickets/filters.py
@@ -10,7 +10,7 @@ class TicketFilter(BaseFilterSet):
class Meta:
model = Ticket
fields = (
- 'id', 'title', 'type', 'status', 'applicant', 'assignees__id',
+ 'id', 'title', 'type', 'status', 'state', 'applicant', 'assignees__id',
'applicant_display',
)
diff --git a/apps/tickets/handler/base.py b/apps/tickets/handler/base.py
index 5e13b7a60..4b09531fa 100644
--- a/apps/tickets/handler/base.py
+++ b/apps/tickets/handler/base.py
@@ -29,9 +29,9 @@ class BaseHandler(object):
self._send_applied_mail_to_assignees()
is_finished = False
else:
- self._send_processed_mail_to_applicant(self.ticket.processor)
self.ticket.set_state_approve()
self.ticket.set_status_closed()
+ self._send_processed_mail_to_applicant(self.ticket.processor)
is_finished = True
self.ticket.save()
From ac1479096099f9212701047c8f84f3c3994fad40 Mon Sep 17 00:00:00 2001
From: Michael Bai
Date: Wed, 15 Dec 2021 14:43:03 +0800
Subject: [PATCH 2/8] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E5=91=BD=E4=BB=A4?=
=?UTF-8?q?=E8=BF=87=E6=BB=A4=E8=A7=84=E5=88=99=E5=8A=A8=E4=BD=9C=E5=85=81?=
=?UTF-8?q?=E8=AE=B8=E5=80=BC1->9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../migrations/0083_auto_20211215_1436.py | 27 +++++++++++++++++++
apps/assets/models/cmd_filter.py | 2 +-
2 files changed, 28 insertions(+), 1 deletion(-)
create mode 100644 apps/assets/migrations/0083_auto_20211215_1436.py
diff --git a/apps/assets/migrations/0083_auto_20211215_1436.py b/apps/assets/migrations/0083_auto_20211215_1436.py
new file mode 100644
index 000000000..f3bde1ec9
--- /dev/null
+++ b/apps/assets/migrations/0083_auto_20211215_1436.py
@@ -0,0 +1,27 @@
+# Generated by Django 3.1.13 on 2021-12-15 06:36
+
+from django.db import migrations, models
+
+OLD_ACTION_ALLOW = 1
+NEW_ACTION_ALLOW = 9
+
+
+def migrate_action(apps, schema_editor):
+ model = apps.get_model("assets", "CommandFilterRule")
+ model.objects.filter(action=OLD_ACTION_ALLOW).update(action=NEW_ACTION_ALLOW)
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('assets', '0082_auto_20211209_1440'),
+ ]
+
+ operations = [
+ migrations.RunPython(migrate_action),
+ migrations.AlterField(
+ model_name='commandfilterrule',
+ name='action',
+ field=models.IntegerField(choices=[(0, 'Deny'), (9, 'Allow'), (2, 'Reconfirm')], default=0, verbose_name='Action'),
+ ),
+ ]
diff --git a/apps/assets/models/cmd_filter.py b/apps/assets/models/cmd_filter.py
index bff1002f8..9de4859b5 100644
--- a/apps/assets/models/cmd_filter.py
+++ b/apps/assets/models/cmd_filter.py
@@ -68,7 +68,7 @@ class CommandFilterRule(OrgModelMixin):
class ActionChoices(models.IntegerChoices):
deny = 0, _('Deny')
- allow = 1, _('Allow')
+ allow = 9, _('Allow')
confirm = 2, _('Reconfirm')
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
From 022e93d7a246dd5421b205637521b3ab0bfa7e77 Mon Sep 17 00:00:00 2001
From: feng626 <1304903146@qq.com>
Date: Wed, 15 Dec 2021 16:15:21 +0800
Subject: [PATCH 3/8] feat: translate
---
apps/locale/zh/LC_MESSAGES/django.mo | 4 +-
apps/locale/zh/LC_MESSAGES/django.po | 94 +++++++++++++++-------------
2 files changed, 51 insertions(+), 47 deletions(-)
diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo
index e9a002a25..3b62528ee 100644
--- a/apps/locale/zh/LC_MESSAGES/django.mo
+++ b/apps/locale/zh/LC_MESSAGES/django.mo
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:9a8f5840c041b5f3188621ec731fa1b4a5da20730ea6394cf5e2b5c9c241a00e
-size 94712
+oid sha256:2bf3340b7ca0dc3e698160fe8df980df07ebdecfd9312c5aca230d18a05fea18
+size 94929
diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po
index 7a2257f19..fcc84607b 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-12-14 17:54+0800\n"
+"POT-Creation-Date: 2021-12-15 15:41+0800\n"
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
"Last-Translator: ibuler \n"
"Language-Team: JumpServer team\n"
@@ -35,12 +35,12 @@ msgid "Name"
msgstr "名称"
#: acls/models/base.py:27 assets/models/cmd_filter.py:77
-#: assets/models/user.py:200
+#: assets/models/user.py:209
msgid "Priority"
msgstr "优先级"
#: acls/models/base.py:28 assets/models/cmd_filter.py:77
-#: assets/models/user.py:200
+#: assets/models/user.py:209
msgid "1-100, the lower the value will be match first"
msgstr "优先级可选范围为 1-100 (数值越小越优先)"
@@ -209,7 +209,7 @@ msgid ""
msgstr "格式为逗号分隔的字符串, * 表示匹配所有. 可选的协议有: {}"
#: acls/serializers/login_asset_acl.py:55 assets/models/asset.py:214
-#: assets/models/domain.py:63 assets/models/user.py:201
+#: assets/models/domain.py:63 assets/models/user.py:210
#: terminal/serializers/session.py:30 terminal/serializers/storage.py:69
msgid "Protocol"
msgstr "协议"
@@ -265,7 +265,7 @@ msgid "Custom"
msgstr "自定义"
#: applications/models/account.py:11 assets/models/authbook.py:19
-#: assets/models/cmd_filter.py:38 assets/models/user.py:291 audits/models.py:39
+#: assets/models/cmd_filter.py:38 assets/models/user.py:300 audits/models.py:39
#: perms/models/application_permission.py:32
#: perms/models/asset_permission.py:101 templates/_nav.html:45
#: terminal/backends/command/models.py:20
@@ -306,7 +306,7 @@ msgstr "类别"
#: applications/models/application.py:171
#: applications/serializers/application.py:90 assets/models/cmd_filter.py:76
-#: assets/models/user.py:199 perms/models/application_permission.py:23
+#: assets/models/user.py:208 perms/models/application_permission.py:23
#: perms/serializers/application/user_permission.py:34
#: terminal/models/storage.py:55 terminal/models/storage.py:116
#: tickets/models/flow.py:51 tickets/models/ticket.py:48
@@ -523,7 +523,7 @@ msgstr "主机名原始"
msgid "Protocols"
msgstr "协议组"
-#: assets/models/asset.py:219 assets/models/user.py:191
+#: assets/models/asset.py:219 assets/models/user.py:200
#: perms/models/asset_permission.py:100
#: xpack/plugins/change_auth_plan/models/asset.py:44
#: xpack/plugins/gathered_user/models.py:24
@@ -536,7 +536,7 @@ msgid "Is active"
msgstr "激活"
#: assets/models/asset.py:223 assets/models/cluster.py:19
-#: assets/models/user.py:188 assets/models/user.py:340 templates/_nav.html:44
+#: assets/models/user.py:197 assets/models/user.py:349 templates/_nav.html:44
msgid "Admin user"
msgstr "特权用户"
@@ -790,75 +790,75 @@ msgstr "ssh私钥"
msgid "Node"
msgstr "节点"
-#: assets/models/user.py:182
+#: assets/models/user.py:191
msgid "Automatic managed"
msgstr "托管密码"
-#: assets/models/user.py:183
+#: assets/models/user.py:192
msgid "Manually input"
msgstr "手动输入"
-#: assets/models/user.py:187
+#: assets/models/user.py:196
msgid "Common user"
msgstr "普通用户"
-#: assets/models/user.py:190
+#: assets/models/user.py:199
msgid "Username same with user"
msgstr "用户名与用户相同"
-#: assets/models/user.py:193 assets/serializers/domain.py:29
+#: assets/models/user.py:202 assets/serializers/domain.py:29
#: templates/_nav.html:39
#: terminal/templates/terminal/_msg_command_execute_alert.html:16
#: xpack/plugins/change_auth_plan/models/asset.py:40
msgid "Assets"
msgstr "资产"
-#: assets/models/user.py:197 templates/_nav.html:17
+#: assets/models/user.py:206 templates/_nav.html:17
#: users/views/profile/pubkey.py:37
msgid "Users"
msgstr "用户管理"
-#: assets/models/user.py:198
+#: assets/models/user.py:207
msgid "User groups"
msgstr "用户组"
-#: assets/models/user.py:202
+#: assets/models/user.py:211
msgid "Auto push"
msgstr "自动推送"
-#: assets/models/user.py:203
+#: assets/models/user.py:212
msgid "Sudo"
msgstr "Sudo"
-#: assets/models/user.py:204
+#: assets/models/user.py:213
msgid "Shell"
msgstr "Shell"
-#: assets/models/user.py:205
+#: assets/models/user.py:214
msgid "Login mode"
msgstr "认证方式"
-#: assets/models/user.py:206
+#: assets/models/user.py:215
msgid "SFTP Root"
msgstr "SFTP根路径"
-#: assets/models/user.py:207 authentication/models.py:45
+#: assets/models/user.py:216 authentication/models.py:45
msgid "Token"
msgstr ""
-#: assets/models/user.py:208
+#: assets/models/user.py:217
msgid "Home"
msgstr "家目录"
-#: assets/models/user.py:209
+#: assets/models/user.py:218
msgid "System groups"
msgstr "用户组"
-#: assets/models/user.py:212
+#: assets/models/user.py:221
msgid "User switch"
msgstr "用户切换"
-#: assets/models/user.py:213
+#: assets/models/user.py:222
msgid "Switch from"
msgstr "切换自"
@@ -1068,24 +1068,24 @@ msgid ""
"The task of self-checking is already running and cannot be started repeatedly"
msgstr "自检程序已经在运行,不能重复启动"
-#: assets/tasks/push_system_user.py:194
+#: assets/tasks/push_system_user.py:199
msgid "System user is dynamic: {}"
msgstr "系统用户是动态的: {}"
-#: assets/tasks/push_system_user.py:234
+#: assets/tasks/push_system_user.py:239
msgid "Start push system user for platform: [{}]"
msgstr "推送系统用户到平台: [{}]"
-#: assets/tasks/push_system_user.py:235
+#: assets/tasks/push_system_user.py:240
#: assets/tasks/system_user_connectivity.py:106
msgid "Hosts count: {}"
msgstr "主机数量: {}"
-#: assets/tasks/push_system_user.py:277 assets/tasks/push_system_user.py:310
+#: assets/tasks/push_system_user.py:282 assets/tasks/push_system_user.py:315
msgid "Push system users to assets: {}"
msgstr "推送系统用户到入资产: {}"
-#: assets/tasks/push_system_user.py:289
+#: assets/tasks/push_system_user.py:294
msgid "Push system users to asset: {}({}) => {}"
msgstr "推送系统用户到入资产: {}({}) => {}"
@@ -2785,23 +2785,23 @@ msgstr "测试成功"
msgid "Test mail sent to {}, please check"
msgstr "邮件已经发送{}, 请检查"
-#: settings/api/ldap.py:152
+#: settings/api/ldap.py:157
msgid "Synchronization start, please wait."
msgstr "同步开始,请稍等"
-#: settings/api/ldap.py:156
+#: settings/api/ldap.py:161
msgid "Synchronization is running, please wait."
msgstr "同步正在运行,请稍等"
-#: settings/api/ldap.py:161
+#: settings/api/ldap.py:166
msgid "Synchronization error: {}"
msgstr "同步错误: {}"
-#: settings/api/ldap.py:194
+#: settings/api/ldap.py:199
msgid "Get ldap users is None"
msgstr "获取 LDAP 用户为 None"
-#: settings/api/ldap.py:203
+#: settings/api/ldap.py:208
msgid "Imported {} users successfully (Organization: {})"
msgstr "成功导入 {} 个用户 ( 组织: {} )"
@@ -5516,31 +5516,31 @@ msgstr "账号保护已开启,请根据提示完成以下操作"
msgid "Open MFA Authenticator and enter the 6-bit dynamic code"
msgstr "请打开 MFA 验证器,输入 6 位动态码"
-#: users/views/profile/otp.py:86
+#: users/views/profile/otp.py:87
msgid "Already bound"
msgstr "已经绑定"
-#: users/views/profile/otp.py:87
+#: users/views/profile/otp.py:88
msgid "MFA already bound, disable first, then bound"
msgstr "MFA(OTP) 已经绑定,请先禁用,再绑定"
-#: users/views/profile/otp.py:114
+#: users/views/profile/otp.py:115
msgid "OTP enable success"
msgstr "MFA(OTP) 启用成功"
-#: users/views/profile/otp.py:115
+#: users/views/profile/otp.py:116
msgid "OTP enable success, return login page"
msgstr "MFA(OTP) 启用成功,返回到登录页面"
-#: users/views/profile/otp.py:157
+#: users/views/profile/otp.py:158
msgid "Disable OTP"
msgstr "禁用虚拟 MFA(OTP)"
-#: users/views/profile/otp.py:163
+#: users/views/profile/otp.py:164
msgid "OTP disable success"
msgstr "MFA(OTP) 禁用成功"
-#: users/views/profile/otp.py:164
+#: users/views/profile/otp.py:165
msgid "OTP disable success, return login page"
msgstr "MFA(OTP) 禁用成功,返回登录页面"
@@ -5752,15 +5752,19 @@ msgstr "* 请输入正确的密码长度"
msgid "* Password length range 6-30 bits"
msgstr "* 密码长度范围 6-30 位"
-#: xpack/plugins/change_auth_plan/task_handlers/base/handler.py:249
+#: xpack/plugins/change_auth_plan/task_handlers/base/handler.py:236
+msgid "After many attempts to change the secret, it still failed"
+msgstr "多次尝试改密后, 依然失败"
+
+#: xpack/plugins/change_auth_plan/task_handlers/base/handler.py:255
msgid "Invalid/incorrect password"
msgstr "无效/错误 密码"
-#: xpack/plugins/change_auth_plan/task_handlers/base/handler.py:251
+#: xpack/plugins/change_auth_plan/task_handlers/base/handler.py:257
msgid "Failed to connect to the host"
msgstr "连接主机失败"
-#: xpack/plugins/change_auth_plan/task_handlers/base/handler.py:253
+#: xpack/plugins/change_auth_plan/task_handlers/base/handler.py:259
msgid "Data could not be sent to remote"
msgstr "无法将数据发送到远程"
From ae1d419f707244201e6ccbcb6611c5fdaa35315d Mon Sep 17 00:00:00 2001
From: Michael Bai
Date: Wed, 15 Dec 2021 16:33:06 +0800
Subject: [PATCH 4/8] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=94=A8=E6=88=B7?=
=?UTF-8?q?=E7=BB=84=E5=91=BD=E4=BB=A4=E8=BF=87=E6=BB=A4=E8=A7=84=E5=88=99?=
=?UTF-8?q?=E8=8E=B7=E5=8F=96=E4=B8=8D=E5=88=B0=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
apps/assets/api/system_user.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/assets/api/system_user.py b/apps/assets/api/system_user.py
index 912630b79..cf61be658 100644
--- a/apps/assets/api/system_user.py
+++ b/apps/assets/api/system_user.py
@@ -217,7 +217,7 @@ class SystemUserCommandFilterRuleListApi(generics.ListAPIView):
q = Q()
if user:
q |= Q(users=user)
- if user_group:
+ if user_groups:
q |= Q(user_groups__in=set(user_groups))
if system_user:
q |= Q(system_users=system_user)
From 93d77b23128ef6183e11ff27e4e3ded519ba2415 Mon Sep 17 00:00:00 2001
From: xinwen
Date: Wed, 15 Dec 2021 17:58:14 +0800
Subject: [PATCH 5/8] =?UTF-8?q?fix:=20=E6=89=A7=E8=A1=8C=20ansible=20?=
=?UTF-8?q?=E4=BB=BB=E5=8A=A1=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95=E9=94=99?=
=?UTF-8?q?=E8=AF=AF?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
apps/ops/ansible/display.py | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/apps/ops/ansible/display.py b/apps/ops/ansible/display.py
index 0c4d57788..ab93892b2 100644
--- a/apps/ops/ansible/display.py
+++ b/apps/ops/ansible/display.py
@@ -54,6 +54,9 @@ class AdHocDisplay(Display, metaclass=UnSingleton):
self.log_file.write(msg)
def display(self, msg, color=None, stderr=False, screen_only=False, log_only=False, newline=True):
+ if log_only:
+ return
+
if color:
msg = stringc(msg, color)
@@ -62,7 +65,5 @@ class AdHocDisplay(Display, metaclass=UnSingleton):
else:
msg2 = msg
- if log_only:
- self._write_to_log_file(msg2)
- else:
- self._write_to_screen(msg2, stderr)
+ self._write_to_log_file(msg2)
+ self._write_to_screen(msg2, stderr)
From eb3165f8e75decab42b6362502e46941d2107d23 Mon Sep 17 00:00:00 2001
From: ibuler
Date: Wed, 15 Dec 2021 19:53:30 +0800
Subject: [PATCH 6/8] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=20saml?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
apps/authentication/backends/saml2/views.py | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/apps/authentication/backends/saml2/views.py b/apps/authentication/backends/saml2/views.py
index f1affb8af..4ce812fe8 100644
--- a/apps/authentication/backends/saml2/views.py
+++ b/apps/authentication/backends/saml2/views.py
@@ -270,7 +270,7 @@ class Saml2AuthCallbackView(View, PrepareRequestMixin):
class Saml2AuthMetadataView(View, PrepareRequestMixin):
- def get(self, _):
+ def get(self, request):
saml_settings = self.get_sp_settings()
saml_settings = JmsSaml2Settings(
settings=saml_settings, sp_validation_only=True,
@@ -279,8 +279,17 @@ class Saml2AuthMetadataView(View, PrepareRequestMixin):
metadata = saml_settings.get_sp_metadata()
errors = saml_settings.validate_metadata(metadata)
+ key = saml_settings.get_sp_key()
+ cert = saml_settings.get_sp_cert()
+ if not key:
+ errors.append('Not found SP private key')
+ if not cert:
+ errors.append('Not found SP cert')
+
if len(errors) == 0:
resp = HttpResponse(content=metadata, content_type='text/xml')
else:
- resp = HttpResponseServerError(content=', '.join(errors))
+ content = "Error occur:
"
+ content += '
'.join(errors)
+ resp = HttpResponseServerError(content=content)
return resp
From b113eeb1d695e81d868b3106d26303573ba31014 Mon Sep 17 00:00:00 2001
From: ibuler
Date: Wed, 15 Dec 2021 18:44:51 +0800
Subject: [PATCH 7/8] =?UTF-8?q?perf:=20=E4=BF=AE=E5=A4=8D=E5=9F=BA?=
=?UTF-8?q?=E6=9C=AC=E8=AE=BE=E7=BD=AE=E4=B8=AD=E7=9A=84=20base=5Fsite=20?=
=?UTF-8?q?=E5=8F=AF=E8=83=BD=E5=B8=A6=20/=20=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
apps/settings/serializers/basic.py | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/apps/settings/serializers/basic.py b/apps/settings/serializers/basic.py
index 4f38e2fd5..97ef96cbe 100644
--- a/apps/settings/serializers/basic.py
+++ b/apps/settings/serializers/basic.py
@@ -44,3 +44,10 @@ class BasicSettingSerializer(serializers.Serializer):
TICKETS_ENABLED = serializers.BooleanField(required=False, default=True, label=_("Enable tickets"))
ANNOUNCEMENT_ENABLED = serializers.BooleanField(label=_('Enable announcement'), default=True)
ANNOUNCEMENT = AnnouncementSerializer(label=_("Announcement"))
+
+ @staticmethod
+ def validate_SITE_URL(s):
+ if not s:
+ return 'http://127.0.0.1'
+ return s.strip('/')
+
From b92530f0b943141735753b124de38647fb86937c Mon Sep 17 00:00:00 2001
From: ibuler
Date: Wed, 15 Dec 2021 15:01:46 +0800
Subject: [PATCH 8/8] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E9=80=9A?=
=?UTF-8?q?=E7=9F=A5=EF=BC=8C=E5=AF=B9=E6=94=AF=E6=8C=81=20markdown=20?=
=?UTF-8?q?=E7=9A=84=E5=8F=91=20markdown?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../authentication/_msg_different_city.html | 1 +
.../authentication/_msg_reset_password.html | 5 ++--
.../_msg_rest_password_success.html | 1 +
.../_msg_rest_public_key_success.html | 1 +
apps/common/sdk/im/dingtalk/__init__.py | 21 +++++++++++++--
apps/common/sdk/im/wecom/__init__.py | 12 ++++++++-
apps/notifications/backends/dingtalk.py | 2 +-
apps/notifications/backends/wecom.py | 2 +-
apps/notifications/notifications.py | 27 ++++++++++++++-----
.../perms/_msg_permed_items_expire.html | 1 +
.../users/_msg_password_expire_reminder.html | 2 +-
.../templates/users/_msg_user_created.html | 3 +++
12 files changed, 63 insertions(+), 15 deletions(-)
diff --git a/apps/authentication/templates/authentication/_msg_different_city.html b/apps/authentication/templates/authentication/_msg_different_city.html
index b12e9aab6..02dbf4271 100644
--- a/apps/authentication/templates/authentication/_msg_different_city.html
+++ b/apps/authentication/templates/authentication/_msg_different_city.html
@@ -11,6 +11,7 @@
{% trans 'Login city' %}: {{ city }}({{ ip }})
+-
{% trans 'If you suspect that the login behavior is abnormal, please modify the account password in time.' %}
\ No newline at end of file
diff --git a/apps/authentication/templates/authentication/_msg_reset_password.html b/apps/authentication/templates/authentication/_msg_reset_password.html
index 7bb80a17d..f53bda209 100644
--- a/apps/authentication/templates/authentication/_msg_reset_password.html
+++ b/apps/authentication/templates/authentication/_msg_reset_password.html
@@ -11,9 +11,8 @@
+-
{% trans 'This link is valid for 1 hour. After it expires' %}
-
- {% trans 'request new one' %}
-
+ {% trans 'request new one' %}
diff --git a/apps/authentication/templates/authentication/_msg_rest_password_success.html b/apps/authentication/templates/authentication/_msg_rest_password_success.html
index a12d611f7..dce3ee13c 100644
--- a/apps/authentication/templates/authentication/_msg_rest_password_success.html
+++ b/apps/authentication/templates/authentication/_msg_rest_password_success.html
@@ -8,6 +8,7 @@
{% trans 'IP' %}: {{ ip_address }}
{% trans 'Browser' %}: {{ browser }}
+-
{% trans 'If the password 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/authentication/templates/authentication/_msg_rest_public_key_success.html b/apps/authentication/templates/authentication/_msg_rest_public_key_success.html
index a95bfdd9b..c8e8fabb6 100644
--- a/apps/authentication/templates/authentication/_msg_rest_public_key_success.html
+++ b/apps/authentication/templates/authentication/_msg_rest_public_key_success.html
@@ -8,6 +8,7 @@
{% 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/common/sdk/im/dingtalk/__init__.py b/apps/common/sdk/im/dingtalk/__init__.py
index af57f2cf5..f18cd4b35 100644
--- a/apps/common/sdk/im/dingtalk/__init__.py
+++ b/apps/common/sdk/im/dingtalk/__init__.py
@@ -151,12 +151,29 @@ class DingTalk:
'data': data
}
data = self._request.post(URL.SEND_MESSAGE_BY_TEMPLATE, json=body, with_token=True)
+ return data
+
+ def send_markdown(self, user_ids, title, msg):
+ body = {
+ 'agent_id': self._agentid,
+ 'userid_list': ','.join(user_ids),
+ 'to_all_user': False,
+ 'msg': {
+ 'msgtype': 'markdown',
+ 'markdown': {
+ 'title': title,
+ 'text': msg
+ }
+ }
+ }
+ logger.info(f'Dingtalk send markdown to user {user_ids}: {msg}')
+ data = self._request.post(URL.SEND_MESSAGE, json=body, with_token=True)
+ return data
def send_text(self, user_ids, msg):
body = {
'agent_id': self._agentid,
'userid_list': ','.join(user_ids),
- # 'dept_id_list': '',
'to_all_user': False,
'msg': {
'msgtype': 'text',
@@ -165,7 +182,7 @@ class DingTalk:
}
}
}
- logger.info(f'Dingtalk send text: user_ids={user_ids} msg={msg}')
+ logger.info(f'Dingtalk send msg to user {user_ids}: {msg}')
data = self._request.post(URL.SEND_MESSAGE, json=body, with_token=True)
return data
diff --git a/apps/common/sdk/im/wecom/__init__.py b/apps/common/sdk/im/wecom/__init__.py
index 6d7c2bf66..ceda292c7 100644
--- a/apps/common/sdk/im/wecom/__init__.py
+++ b/apps/common/sdk/im/wecom/__init__.py
@@ -90,7 +90,10 @@ class WeCom(RequestMixin):
timeout=timeout
)
- def send_text(self, users: Iterable, msg: AnyStr, **kwargs):
+ def send_markdown(self, users: Iterable, msg: AnyStr, **kwargs):
+ pass
+
+ def send_text(self, users: Iterable, msg: AnyStr, markdown=False, **kwargs):
"""
https://open.work.weixin.qq.com/api/doc/90000/90135/90236
@@ -115,6 +118,13 @@ class WeCom(RequestMixin):
},
**extra_params
}
+ if markdown:
+ body['msgtype'] = 'markdown'
+ body["markdown"] = {
+ "content": msg
+ }
+ body.pop('text', '')
+
logger.info(f'Wecom send text: users={users} msg={msg}')
data = self._requests.post(URL.SEND_MESSAGE, json=body, check_errcode_is_0=False)
diff --git a/apps/notifications/backends/dingtalk.py b/apps/notifications/backends/dingtalk.py
index 426a05fc0..52d11d041 100644
--- a/apps/notifications/backends/dingtalk.py
+++ b/apps/notifications/backends/dingtalk.py
@@ -16,7 +16,7 @@ class DingTalk(BackendBase):
def send_msg(self, users, message, subject=None):
accounts, __, __ = self.get_accounts(users)
- return self.dingtalk.send_text(accounts, message)
+ return self.dingtalk.send_markdown(accounts, subject, message)
backend = DingTalk
diff --git a/apps/notifications/backends/wecom.py b/apps/notifications/backends/wecom.py
index c2aadd4a9..fa615b7e7 100644
--- a/apps/notifications/backends/wecom.py
+++ b/apps/notifications/backends/wecom.py
@@ -17,7 +17,7 @@ class WeCom(BackendBase):
def send_msg(self, users, message, subject=None):
accounts, __, __ = self.get_accounts(users)
- return self.wecom.send_text(accounts, message)
+ return self.wecom.send_text(accounts, message, markdown=True)
backend = WeCom
diff --git a/apps/notifications/notifications.py b/apps/notifications/notifications.py
index 11e8f7011..481a4bc08 100644
--- a/apps/notifications/notifications.py
+++ b/apps/notifications/notifications.py
@@ -94,7 +94,7 @@ class Message(metaclass=MessageType):
traceback.print_exc()
@classmethod
- def send_test_msg(cls, ding=True):
+ def send_test_msg(cls, ding=True, wecom=False):
msg = cls.gen_test_msg()
if not msg:
return
@@ -104,6 +104,8 @@ class Message(metaclass=MessageType):
backends = []
if ding:
backends.append(BACKEND.DINGTALK)
+ if wecom:
+ backends.append(BACKEND.WECOM)
msg.send_msg(users, backends)
@staticmethod
@@ -113,8 +115,17 @@ class Message(metaclass=MessageType):
def get_html_msg(self) -> dict:
return self.get_common_msg()
+ def get_markdown_msg(self) -> dict:
+ h = HTML2Text()
+ h.body_width = 300
+ msg = self.get_html_msg()
+ content = msg['message']
+ msg['message'] = h.handle(content)
+ return msg
+
def get_text_msg(self) -> dict:
h = HTML2Text()
+ h.body_width = 90
msg = self.get_html_msg()
content = msg['message']
h.ignore_links = self.text_msg_ignore_links
@@ -130,6 +141,10 @@ class Message(metaclass=MessageType):
msg = self.get_text_msg()
return msg
+ @lazyproperty
+ def markdown_msg(self):
+ return self.get_markdown_msg()
+
@lazyproperty
def html_msg(self) -> dict:
msg = self.get_html_msg()
@@ -167,17 +182,17 @@ class Message(metaclass=MessageType):
# 支持不同发送消息的方式定义自己的消息内容,比如有些支持 html 标签
def get_dingtalk_msg(self) -> dict:
# 钉钉相同的消息一天只能发一次,所以给所有消息添加基于时间的序号,使他们不相同
- message = self.text_msg['message']
+ message = self.markdown_msg['message']
time = local_now().strftime('%Y-%m-%d %H:%M:%S')
suffix = '\n{}: {}'.format(_('Time'), time)
return {
- 'subject': self.text_msg['subject'],
+ 'subject': self.markdown_msg['subject'],
'message': message + suffix
}
def get_wecom_msg(self) -> dict:
- return self.text_msg
+ return self.markdown_msg
def get_feishu_msg(self) -> dict:
return self.text_msg
@@ -207,12 +222,12 @@ class Message(metaclass=MessageType):
return messages_cls
@classmethod
- def test_all_messages(cls):
+ def test_all_messages(cls, ding=True, wecom=False):
messages_cls = cls.get_all_sub_messages()
for _cls in messages_cls:
try:
- msg = _cls.send_test_msg()
+ _cls.send_test_msg(ding=ding, wecom=wecom)
except NotImplementedError:
continue
diff --git a/apps/perms/templates/perms/_msg_permed_items_expire.html b/apps/perms/templates/perms/_msg_permed_items_expire.html
index 74df4556d..f50c59933 100644
--- a/apps/perms/templates/perms/_msg_permed_items_expire.html
+++ b/apps/perms/templates/perms/_msg_permed_items_expire.html
@@ -16,6 +16,7 @@
+-
{% trans 'If you have any question, please contact the administrator' %}
diff --git a/apps/users/templates/users/_msg_password_expire_reminder.html b/apps/users/templates/users/_msg_password_expire_reminder.html
index 0c8175c23..bfd290156 100644
--- a/apps/users/templates/users/_msg_password_expire_reminder.html
+++ b/apps/users/templates/users/_msg_password_expire_reminder.html
@@ -11,7 +11,7 @@
{% trans 'Click here update password' %}
-
+-
{% trans 'If your password has expired, please click the link below to' %}
{% trans 'Reset password' %}
diff --git a/apps/users/templates/users/_msg_user_created.html b/apps/users/templates/users/_msg_user_created.html
index 678ca237f..3b1c36ed5 100644
--- a/apps/users/templates/users/_msg_user_created.html
+++ b/apps/users/templates/users/_msg_user_created.html
@@ -15,6 +15,9 @@
{% trans 'click here to set your password' %}
+
+
+ -
{% trans 'This link is valid for 1 hour. After it expires' %}
{% trans 'request new one' %}