From 7047e445a30713ebd789bdbc1c908e6fa82e2407 Mon Sep 17 00:00:00 2001 From: feng626 <1304903146@qq.com> Date: Fri, 8 Jul 2022 13:35:32 +0800 Subject: [PATCH 01/13] =?UTF-8?q?feat:=20=E4=B8=8B=E8=BD=BD=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E6=B7=BB=E5=8A=A0=E7=A6=BB=E7=BA=BF=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/ja/LC_MESSAGES/django.mo | 4 ++-- apps/locale/ja/LC_MESSAGES/django.po | 4 ++++ apps/locale/zh/LC_MESSAGES/django.mo | 4 ++-- apps/locale/zh/LC_MESSAGES/django.po | 4 ++++ apps/templates/resource_download.html | 9 +++++++++ 5 files changed, 21 insertions(+), 4 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index b1be6955d..d7bf5fff9 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba75ec2955d452a16930dbd845c8091de4d3cbe0c5b5ccb18f8deb28d7bf3809 -size 126865 +oid sha256:404cc258252754b1fbbb67b04b326369c7ca0797d5245fdd98939c2206e1d8a3 +size 126727 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 8668dd892..750b14423 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -4598,6 +4598,10 @@ msgstr "マイクロソフト" msgid "Official" msgstr "公式" +#: templates/resource_download.html:51 +msgid "Offline video player" +msgstr "オフラインビデオプレーヤー" + #: templates/resource_download.html:33 msgid "" "macOS needs to download the client to connect RDP asset, which comes with " diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 92b8e52cb..bb56392af 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:bfbd815ff09d4b7c5f64af1eb745b81937a267d469ffbcba93c849feada2a8a8 -size 104695 +oid sha256:603bfc1d89caaec72caf5cfba85fdc2a1ae7ac9556b4c3641353153d777ece1b +size 104603 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index cf215a3fb..ceae873f1 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -4530,6 +4530,10 @@ msgstr "微软" msgid "Official" msgstr "官方" +#: templates/resource_download.html:51 +msgid "Offline video player" +msgstr "离线录像播放器" + #: templates/resource_download.html:33 msgid "" "macOS needs to download the client to connect RDP asset, which comes with " diff --git a/apps/templates/resource_download.html b/apps/templates/resource_download.html index dddb1143c..4b60e1e09 100644 --- a/apps/templates/resource_download.html +++ b/apps/templates/resource_download.html @@ -46,6 +46,15 @@ p { {% endif %} + +
+

JumpServer {% trans 'Offline video player' %} v0.1.5

+ +
+ From b64727e04c867c3365b16679413e60ec12ebe32a Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Tue, 12 Jul 2022 14:09:08 +0800 Subject: [PATCH 05/13] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E8=87=AA=E6=9B=B4=E6=96=B0=E5=A4=B1=E8=B4=A5=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/users/serializers/user.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/users/serializers/user.py b/apps/users/serializers/user.py index b08b09144..eb03a0e6f 100644 --- a/apps/users/serializers/user.py +++ b/apps/users/serializers/user.py @@ -6,7 +6,7 @@ from rest_framework import serializers from common.mixins import CommonBulkSerializerMixin from common.validators import PhoneValidator -from common.utils import pretty_string +from common.utils import pretty_string, get_logger from common.drf.fields import EncryptedField from rbac.builtin import BuiltinRole from rbac.permissions import RBACPermission @@ -19,6 +19,8 @@ __all__ = [ 'InviteSerializer', 'ServiceAccountSerializer', ] +logger = get_logger(__file__) + class RolesSerializerMixin(serializers.Serializer): system_roles = serializers.ManyRelatedField( @@ -199,8 +201,10 @@ class UserSerializer(RolesSerializerMixin, CommonBulkSerializerMixin, serializer if not disallow_fields: return attrs # 用户自己不能更新自己的一些字段 - error = _('User cannot self-update fields: {}').format(disallow_fields) - raise serializers.ValidationError(error) + logger.debug('Disallow update self fields: %s', disallow_fields) + for field in disallow_fields: + attrs.pop(field, None) + return attrs def validate(self, attrs): attrs = self.check_disallow_self_update_fields(attrs) From b5cfc6831b3efc6a255815af6ab5483f02c809e0 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 12 Jul 2022 15:28:42 +0800 Subject: [PATCH 06/13] =?UTF-8?q?feat:=20=E5=B7=A5=E5=8D=95=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=AE=A1=E6=89=B9=E6=97=B6=E4=BF=AE=E6=94=B9=E8=B5=84?= =?UTF-8?q?=E4=BA=A7=20(#8549)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> Co-authored-by: feng626 <57284900+feng626@users.noreply.github.com> --- apps/common/db/encoder.py | 2 + apps/locale/ja/LC_MESSAGES/django.po | 90 +++++++++++-------- apps/locale/zh/LC_MESSAGES/django.po | 90 +++++++++++-------- apps/perms/serializers/base.py | 6 +- apps/tickets/api/ticket.py | 23 ++--- apps/tickets/handlers/base.py | 27 +++++- .../migrations/0017_auto_20220623_1027.py | 4 +- .../models/ticket/apply_application.py | 2 +- apps/tickets/models/ticket/apply_asset.py | 5 +- apps/tickets/models/ticket/general.py | 56 +++++++++--- apps/tickets/notifications.py | 11 +-- .../serializers/ticket/apply_application.py | 13 ++- .../tickets/serializers/ticket/apply_asset.py | 20 +++-- apps/tickets/serializers/ticket/common.py | 20 ++++- apps/tickets/serializers/ticket/ticket.py | 3 + .../tickets/ticket_approve_diff.html | 24 +++++ 16 files changed, 274 insertions(+), 122 deletions(-) create mode 100644 apps/tickets/templates/tickets/ticket_approve_diff.html diff --git a/apps/common/db/encoder.py b/apps/common/db/encoder.py index 673b8aeca..e09ffd60e 100644 --- a/apps/common/db/encoder.py +++ b/apps/common/db/encoder.py @@ -4,6 +4,7 @@ import logging from datetime import datetime from django.utils.translation import ugettext_lazy as _ +from django.utils import timezone as dj_timezone from django.db import models from django.conf import settings @@ -18,6 +19,7 @@ class ModelJSONFieldEncoder(json.JSONEncoder): if isinstance(obj, str_cls): return str(obj) elif isinstance(obj, datetime): + obj = dj_timezone.localtime(obj) return obj.strftime(settings.DATETIME_DISPLAY_FORMAT) elif isinstance(obj, (list, tuple)) and len(obj) > 0 \ and isinstance(obj[0], models.Model): diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 0f9e3d288..88cb86c95 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -63,7 +63,7 @@ msgstr "アクティブ" #: perms/models/base.py:93 rbac/models/role.py:37 settings/models.py:34 #: terminal/models/endpoint.py:21 terminal/models/endpoint.py:92 #: terminal/models/storage.py:29 terminal/models/terminal.py:114 -#: tickets/models/comment.py:32 tickets/models/ticket/general.py:278 +#: tickets/models/comment.py:32 tickets/models/ticket/general.py:288 #: users/models/group.py:16 users/models/user.py:698 #: xpack/plugins/change_auth_plan/models/base.py:44 #: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:116 @@ -309,10 +309,10 @@ msgstr "カテゴリ" #: assets/models/cmd_filter.py:82 assets/models/user.py:250 #: authentication/models.py:69 perms/models/application_permission.py:24 #: perms/serializers/application/user_permission.py:34 -#: terminal/models/storage.py:58 terminal/models/storage.py:142 +#: terminal/models/storage.py:58 terminal/models/storage.py:143 #: tickets/models/comment.py:26 tickets/models/flow.py:57 #: tickets/models/ticket/apply_application.py:17 -#: tickets/models/ticket/general.py:263 +#: tickets/models/ticket/general.py:273 #: xpack/plugins/change_auth_plan/models/app.py:28 #: xpack/plugins/change_auth_plan/models/app.py:153 msgid "Type" @@ -416,6 +416,8 @@ msgstr "アプリケーションパス" #: applications/serializers/attrs/application_category/remote_app.py:44 #: assets/serializers/system_user.py:167 +#: tickets/serializers/ticket/apply_application.py:35 +#: tickets/serializers/ticket/common.py:59 #: xpack/plugins/change_auth_plan/serializers/asset.py:67 #: xpack/plugins/change_auth_plan/serializers/asset.py:70 #: xpack/plugins/change_auth_plan/serializers/asset.py:73 @@ -503,7 +505,7 @@ msgid "Charset" msgstr "シャーセット" #: assets/models/asset.py:141 assets/serializers/asset.py:176 -#: tickets/models/ticket/general.py:288 +#: tickets/models/ticket/general.py:298 msgid "Meta" msgstr "メタ" @@ -525,7 +527,7 @@ msgstr "ベンダー" msgid "Model" msgstr "モデル" -#: assets/models/asset.py:170 tickets/models/ticket/general.py:286 +#: assets/models/asset.py:170 tickets/models/ticket/general.py:296 msgid "Serial number" msgstr "シリアル番号" @@ -1525,7 +1527,7 @@ msgid "MFA" msgstr "MFA" #: audits/models.py:128 terminal/models/status.py:33 -#: tickets/models/ticket/general.py:271 xpack/plugins/cloud/models.py:175 +#: tickets/models/ticket/general.py:281 xpack/plugins/cloud/models.py:175 #: xpack/plugins/cloud/models.py:227 msgid "Status" msgstr "ステータス" @@ -2581,7 +2583,7 @@ msgstr "%(name)s が正常に作成されました" msgid "%(name)s was updated successfully" msgstr "%(name)s は正常に更新されました" -#: common/db/encoder.py:10 +#: common/db/encoder.py:11 msgid "ugettext_lazy" msgstr "ugettext_lazy" @@ -3009,7 +3011,7 @@ msgstr "アプリ組織" #: orgs/mixins/models.py:46 orgs/mixins/serializers.py:25 orgs/models.py:80 #: orgs/models.py:211 rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 -#: tickets/models/ticket/general.py:290 tickets/serializers/ticket/ticket.py:64 +#: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:64 msgid "Organization" msgstr "組織" @@ -3417,7 +3419,7 @@ msgstr "マイアプリ" msgid "Ticket comment" msgstr "チケットコメント" -#: rbac/tree.py:115 tickets/models/ticket/general.py:295 +#: rbac/tree.py:115 tickets/models/ticket/general.py:305 msgid "Ticket" msgstr "チケット" @@ -4939,7 +4941,7 @@ msgstr "リンク期限切れ" msgid "User not allowed to join" msgstr "IPは許可されていません" -#: terminal/models/sharing.py:85 terminal/serializers/sharing.py:58 +#: terminal/models/sharing.py:85 terminal/serializers/sharing.py:59 msgid "Joiner" msgstr "ジョイナー" @@ -4996,11 +4998,11 @@ msgstr "ブート時間" msgid "Default storage" msgstr "デフォルトのストレージ" -#: terminal/models/storage.py:136 terminal/models/terminal.py:108 +#: terminal/models/storage.py:137 terminal/models/terminal.py:108 msgid "Command storage" msgstr "コマンドストレージ" -#: terminal/models/storage.py:196 terminal/models/terminal.py:109 +#: terminal/models/storage.py:197 terminal/models/terminal.py:109 msgid "Replay storage" msgstr "再生ストレージ" @@ -5253,7 +5255,19 @@ msgstr "" "チケットのタイトル: {} チケット申請者: {} チケットプロセッサ: {} チケットID: " "{}" -#: tickets/handlers/base.py:72 +#: tickets/handlers/base.py:79 +msgid "Change field" +msgstr "フィールドを変更" + +#: tickets/handlers/base.py:79 +msgid "Before change" +msgstr "変更前" + +#: tickets/handlers/base.py:79 +msgid "After change" +msgstr "変更後" + +#: tickets/handlers/base.py:91 msgid "{} {} the ticket" msgstr "{} {} チケット" @@ -5269,8 +5283,8 @@ msgstr "応用ログイン都市" msgid "Applied login datetime" msgstr "適用されたログインの日付時間" -#: tickets/models/comment.py:13 tickets/models/ticket/general.py:39 -#: tickets/models/ticket/general.py:267 +#: tickets/models/comment.py:13 tickets/models/ticket/general.py:41 +#: tickets/models/ticket/general.py:277 msgid "State" msgstr "状態" @@ -5287,7 +5301,7 @@ msgid "Body" msgstr "ボディ" #: tickets/models/flow.py:20 tickets/models/flow.py:62 -#: tickets/models/ticket/general.py:35 +#: tickets/models/ticket/general.py:37 msgid "Approve level" msgstr "レベルを承認する" @@ -5313,8 +5327,8 @@ msgstr "チケットセッションの関係" #: tickets/models/ticket/apply_application.py:11 #: tickets/models/ticket/apply_asset.py:13 -msgid "Apply name" -msgstr "名前を適用" +msgid "Permission name" +msgstr "認可ルール名" #: tickets/models/ticket/apply_application.py:20 msgid "Apply applications" @@ -5362,39 +5376,39 @@ msgstr "コマンドフィルタ規則から" msgid "From cmd filter rule" msgstr "コマンドフィルタ規則から" -#: tickets/models/ticket/general.py:70 +#: tickets/models/ticket/general.py:72 msgid "Ticket step" msgstr "チケットステップ" -#: tickets/models/ticket/general.py:88 +#: tickets/models/ticket/general.py:90 msgid "Ticket assignee" msgstr "割り当てられたチケット" -#: tickets/models/ticket/general.py:260 +#: tickets/models/ticket/general.py:270 msgid "Title" msgstr "タイトル" -#: tickets/models/ticket/general.py:276 +#: tickets/models/ticket/general.py:286 msgid "Applicant" msgstr "応募者" -#: tickets/models/ticket/general.py:281 +#: tickets/models/ticket/general.py:291 msgid "TicketFlow" msgstr "作業指示プロセス" -#: tickets/models/ticket/general.py:284 +#: tickets/models/ticket/general.py:294 msgid "Approval step" msgstr "承認ステップ" -#: tickets/models/ticket/general.py:287 +#: tickets/models/ticket/general.py:297 msgid "Relation snapshot" msgstr "製造オーダスナップショット" -#: tickets/models/ticket/general.py:380 +#: tickets/models/ticket/general.py:390 msgid "Please try again" msgstr "もう一度お試しください" -#: tickets/models/ticket/general.py:387 +#: tickets/models/ticket/general.py:421 msgid "Super ticket" msgstr "スーパーチケット" @@ -5414,27 +5428,27 @@ msgstr "ログインシステムユーザー" msgid "Login datetime" msgstr "ログイン日時" -#: tickets/notifications.py:64 +#: tickets/notifications.py:63 msgid "Ticket basic info" msgstr "チケット基本情報" -#: tickets/notifications.py:65 +#: tickets/notifications.py:64 msgid "Ticket applied info" msgstr "チケット適用情報" -#: tickets/notifications.py:116 -msgid "Your has a new ticket" +#: tickets/notifications.py:109 +msgid "Your has a new ticket, applicant - {}" msgstr "新しいチケットがあります- {}" -#: tickets/notifications.py:120 +#: tickets/notifications.py:113 msgid "{}: New Ticket - {} ({})" msgstr "新しいチケット- {} ({})" -#: tickets/notifications.py:164 +#: tickets/notifications.py:157 msgid "Your ticket has been processed, processor - {}" msgstr "チケットが処理されました。プロセッサー- {}" -#: tickets/notifications.py:168 +#: tickets/notifications.py:161 msgid "Ticket has processed - {} ({})" msgstr "チケットが処理済み- {} ({})" @@ -5455,19 +5469,19 @@ msgid "Processor" msgstr "プロセッサ" #: tickets/serializers/ticket/common.py:16 -#: tickets/serializers/ticket/common.py:68 +#: tickets/serializers/ticket/common.py:79 msgid "Created by ticket ({}-{})" msgstr "チケットで作成 ({}-{})" -#: tickets/serializers/ticket/common.py:58 +#: tickets/serializers/ticket/common.py:69 msgid "The expiration date should be greater than the start date" msgstr "有効期限は開始日より大きくする必要があります" -#: tickets/serializers/ticket/common.py:74 +#: tickets/serializers/ticket/common.py:85 msgid "Permission named `{}` already exists" msgstr "'{}'という名前の権限は既に存在します" -#: tickets/serializers/ticket/ticket.py:89 +#: tickets/serializers/ticket/ticket.py:92 msgid "The ticket flow `{}` does not exist" msgstr "チケットフロー '{}'が存在しない" diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 89123d879..ab6fe167e 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -62,7 +62,7 @@ msgstr "激活中" #: perms/models/base.py:93 rbac/models/role.py:37 settings/models.py:34 #: terminal/models/endpoint.py:21 terminal/models/endpoint.py:92 #: terminal/models/storage.py:29 terminal/models/terminal.py:114 -#: tickets/models/comment.py:32 tickets/models/ticket/general.py:278 +#: tickets/models/comment.py:32 tickets/models/ticket/general.py:288 #: users/models/group.py:16 users/models/user.py:698 #: xpack/plugins/change_auth_plan/models/base.py:44 #: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:116 @@ -304,10 +304,10 @@ msgstr "类别" #: assets/models/cmd_filter.py:82 assets/models/user.py:250 #: authentication/models.py:69 perms/models/application_permission.py:24 #: perms/serializers/application/user_permission.py:34 -#: terminal/models/storage.py:58 terminal/models/storage.py:142 +#: terminal/models/storage.py:58 terminal/models/storage.py:143 #: tickets/models/comment.py:26 tickets/models/flow.py:57 #: tickets/models/ticket/apply_application.py:17 -#: tickets/models/ticket/general.py:263 +#: tickets/models/ticket/general.py:273 #: xpack/plugins/change_auth_plan/models/app.py:28 #: xpack/plugins/change_auth_plan/models/app.py:153 msgid "Type" @@ -411,6 +411,8 @@ msgstr "应用路径" #: applications/serializers/attrs/application_category/remote_app.py:44 #: assets/serializers/system_user.py:167 +#: tickets/serializers/ticket/apply_application.py:35 +#: tickets/serializers/ticket/common.py:59 #: xpack/plugins/change_auth_plan/serializers/asset.py:67 #: xpack/plugins/change_auth_plan/serializers/asset.py:70 #: xpack/plugins/change_auth_plan/serializers/asset.py:73 @@ -498,7 +500,7 @@ msgid "Charset" msgstr "编码" #: assets/models/asset.py:141 assets/serializers/asset.py:176 -#: tickets/models/ticket/general.py:288 +#: tickets/models/ticket/general.py:298 msgid "Meta" msgstr "元数据" @@ -520,7 +522,7 @@ msgstr "制造商" msgid "Model" msgstr "型号" -#: assets/models/asset.py:170 tickets/models/ticket/general.py:286 +#: assets/models/asset.py:170 tickets/models/ticket/general.py:296 msgid "Serial number" msgstr "序列号" @@ -1513,7 +1515,7 @@ msgid "MFA" msgstr "MFA" #: audits/models.py:128 terminal/models/status.py:33 -#: tickets/models/ticket/general.py:271 xpack/plugins/cloud/models.py:175 +#: tickets/models/ticket/general.py:281 xpack/plugins/cloud/models.py:175 #: xpack/plugins/cloud/models.py:227 msgid "Status" msgstr "状态" @@ -2547,7 +2549,7 @@ msgstr "%(name)s 创建成功" msgid "%(name)s was updated successfully" msgstr "%(name)s 更新成功" -#: common/db/encoder.py:10 +#: common/db/encoder.py:11 msgid "ugettext_lazy" msgstr "ugettext_lazy" @@ -2969,7 +2971,7 @@ msgstr "组织管理" #: orgs/mixins/models.py:46 orgs/mixins/serializers.py:25 orgs/models.py:80 #: orgs/models.py:211 rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 -#: tickets/models/ticket/general.py:290 tickets/serializers/ticket/ticket.py:64 +#: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:64 msgid "Organization" msgstr "组织" @@ -3374,7 +3376,7 @@ msgstr "我的应用" msgid "Ticket comment" msgstr "工单评论" -#: rbac/tree.py:115 tickets/models/ticket/general.py:295 +#: rbac/tree.py:115 tickets/models/ticket/general.py:305 msgid "Ticket" msgstr "工单管理" @@ -4863,7 +4865,7 @@ msgstr "链接过期" msgid "User not allowed to join" msgstr "来源 IP 不被允许登录" -#: terminal/models/sharing.py:85 terminal/serializers/sharing.py:58 +#: terminal/models/sharing.py:85 terminal/serializers/sharing.py:59 msgid "Joiner" msgstr "加入者" @@ -4920,11 +4922,11 @@ msgstr "运行时间" msgid "Default storage" msgstr "默认存储" -#: terminal/models/storage.py:136 terminal/models/terminal.py:108 +#: terminal/models/storage.py:137 terminal/models/terminal.py:108 msgid "Command storage" msgstr "命令存储" -#: terminal/models/storage.py:196 terminal/models/terminal.py:109 +#: terminal/models/storage.py:197 terminal/models/terminal.py:109 msgid "Replay storage" msgstr "录像存储" @@ -5173,7 +5175,19 @@ msgid "" msgstr "" "通过工单创建, 工单标题: {}, 工单申请人: {}, 工单处理人: {}, 工单 ID: {}" -#: tickets/handlers/base.py:72 +#: tickets/handlers/base.py:79 +msgid "Change field" +msgstr "变更字段" + +#: tickets/handlers/base.py:79 +msgid "Before change" +msgstr "变更前" + +#: tickets/handlers/base.py:79 +msgid "After change" +msgstr "变更后" + +#: tickets/handlers/base.py:91 msgid "{} {} the ticket" msgstr "{} {} 工单" @@ -5189,8 +5203,8 @@ msgstr "申请登录的城市" msgid "Applied login datetime" msgstr "申请登录的日期" -#: tickets/models/comment.py:13 tickets/models/ticket/general.py:39 -#: tickets/models/ticket/general.py:267 +#: tickets/models/comment.py:13 tickets/models/ticket/general.py:41 +#: tickets/models/ticket/general.py:277 msgid "State" msgstr "状态" @@ -5207,7 +5221,7 @@ msgid "Body" msgstr "内容" #: tickets/models/flow.py:20 tickets/models/flow.py:62 -#: tickets/models/ticket/general.py:35 +#: tickets/models/ticket/general.py:37 msgid "Approve level" msgstr "审批级别" @@ -5233,8 +5247,8 @@ msgstr "工单会话" #: tickets/models/ticket/apply_application.py:11 #: tickets/models/ticket/apply_asset.py:13 -msgid "Apply name" -msgstr "应用名称" +msgid "Permission name" +msgstr "授权规则名称" #: tickets/models/ticket/apply_application.py:20 msgid "Apply applications" @@ -5282,39 +5296,39 @@ msgstr "来自命令过滤规则" msgid "From cmd filter rule" msgstr "来自命令过滤规则" -#: tickets/models/ticket/general.py:70 +#: tickets/models/ticket/general.py:72 msgid "Ticket step" msgstr "工单步骤" -#: tickets/models/ticket/general.py:88 +#: tickets/models/ticket/general.py:90 msgid "Ticket assignee" msgstr "工单受理人" -#: tickets/models/ticket/general.py:260 +#: tickets/models/ticket/general.py:270 msgid "Title" msgstr "标题" -#: tickets/models/ticket/general.py:276 +#: tickets/models/ticket/general.py:286 msgid "Applicant" msgstr "申请人" -#: tickets/models/ticket/general.py:281 +#: tickets/models/ticket/general.py:291 msgid "TicketFlow" msgstr "工单流程" -#: tickets/models/ticket/general.py:284 +#: tickets/models/ticket/general.py:294 msgid "Approval step" msgstr "审批步骤" -#: tickets/models/ticket/general.py:287 +#: tickets/models/ticket/general.py:297 msgid "Relation snapshot" msgstr "工单快照" -#: tickets/models/ticket/general.py:380 +#: tickets/models/ticket/general.py:390 msgid "Please try again" msgstr "请再次尝试" -#: tickets/models/ticket/general.py:387 +#: tickets/models/ticket/general.py:421 msgid "Super ticket" msgstr "超级工单" @@ -5334,27 +5348,27 @@ msgstr "登录系统用户" msgid "Login datetime" msgstr "登录日期" -#: tickets/notifications.py:64 +#: tickets/notifications.py:63 msgid "Ticket basic info" msgstr "工单基本信息" -#: tickets/notifications.py:65 +#: tickets/notifications.py:64 msgid "Ticket applied info" msgstr "工单申请信息" -#: tickets/notifications.py:116 -msgid "Your has a new ticket" +#: tickets/notifications.py:109 +msgid "Your has a new ticket, applicant - {}" msgstr "你有一个新的工单, 申请人 - {}" -#: tickets/notifications.py:120 +#: tickets/notifications.py:113 msgid "{}: New Ticket - {} ({})" msgstr "新工单 - {} ({})" -#: tickets/notifications.py:164 +#: tickets/notifications.py:157 msgid "Your ticket has been processed, processor - {}" msgstr "你的工单已被处理, 处理人 - {}" -#: tickets/notifications.py:168 +#: tickets/notifications.py:161 msgid "Ticket has processed - {} ({})" msgstr "你的工单已被处理, 处理人 - {} ({})" @@ -5375,19 +5389,19 @@ msgid "Processor" msgstr "处理人" #: tickets/serializers/ticket/common.py:16 -#: tickets/serializers/ticket/common.py:68 +#: tickets/serializers/ticket/common.py:79 msgid "Created by ticket ({}-{})" msgstr "通过工单创建 ({}-{})" -#: tickets/serializers/ticket/common.py:58 +#: tickets/serializers/ticket/common.py:69 msgid "The expiration date should be greater than the start date" msgstr "过期时间要大于开始时间" -#: tickets/serializers/ticket/common.py:74 +#: tickets/serializers/ticket/common.py:85 msgid "Permission named `{}` already exists" msgstr "授权名称 `{}` 已存在" -#: tickets/serializers/ticket/ticket.py:89 +#: tickets/serializers/ticket/ticket.py:92 msgid "The ticket flow `{}` does not exist" msgstr "工单流程 `{}` 不存在" diff --git a/apps/perms/serializers/base.py b/apps/perms/serializers/base.py index 3d48447fb..cbed4a2f8 100644 --- a/apps/perms/serializers/base.py +++ b/apps/perms/serializers/base.py @@ -21,8 +21,12 @@ class ActionsField(serializers.MultipleChoiceField): return Action.value_to_choices(value) def to_internal_value(self, data): - if data is None: + if not self.allow_empty and not data: + self.fail('empty') + + if not data: return data + return Action.choices_to_value(data) diff --git a/apps/tickets/api/ticket.py b/apps/tickets/api/ticket.py index 0cf9652a6..ee6b76534 100644 --- a/apps/tickets/api/ticket.py +++ b/apps/tickets/api/ticket.py @@ -5,7 +5,7 @@ from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.exceptions import MethodNotAllowed -from common.const.http import POST, PUT +from common.const.http import POST, PUT, PATCH from common.mixins.api import CommonApiMixin from orgs.utils import tmp_to_root_org @@ -71,32 +71,34 @@ class TicketViewSet(CommonApiMixin, viewsets.ModelViewSet): with tmp_to_root_org(): return super().create(request, *args, **kwargs) - @action(detail=True, methods=[PUT], permission_classes=[IsAssignee, ]) + @action(detail=True, methods=[PUT, PATCH], permission_classes=[IsAssignee, ]) def approve(self, request, *args, **kwargs): + partial = kwargs.pop('partial', False) instance = self.get_object() - serializer = self.get_serializer(instance) + serializer = self.get_serializer(instance, data=request.data, partial=partial) + serializer.is_valid(raise_exception=True) + instance = serializer.save() instance.approve(processor=request.user) - return Response(serializer.data) + return Response('ok') @action(detail=True, methods=[PUT], permission_classes=[IsAssignee, ]) def reject(self, request, *args, **kwargs): instance = self.get_object() - serializer = self.get_serializer(instance) instance.reject(processor=request.user) - return Response(serializer.data) + return Response('ok') @action(detail=True, methods=[PUT], permission_classes=[IsApplicant, ]) def close(self, request, *args, **kwargs): instance = self.get_object() - serializer = self.get_serializer(instance) instance.close() - return Response(serializer.data) + return Response('ok') class ApplyAssetTicketViewSet(TicketViewSet): serializer_class = serializers.ApplyAssetDisplaySerializer serializer_classes = { - 'open': serializers.ApplyAssetSerializer + 'open': serializers.ApplyAssetSerializer, + 'approve': serializers.ApproveAssetSerializer } model = ApplyAssetTicket filterset_class = filters.ApplyAssetTicketFilter @@ -105,7 +107,8 @@ class ApplyAssetTicketViewSet(TicketViewSet): class ApplyApplicationTicketViewSet(TicketViewSet): serializer_class = serializers.ApplyApplicationDisplaySerializer serializer_classes = { - 'open': serializers.ApplyApplicationSerializer + 'open': serializers.ApplyApplicationSerializer, + 'approve': serializers.ApproveApplicationSerializer } model = ApplyApplicationTicket filterset_class = filters.ApplyApplicationTicketFilter diff --git a/apps/tickets/handlers/base.py b/apps/tickets/handlers/base.py index 6165d035b..c48ce350b 100644 --- a/apps/tickets/handlers/base.py +++ b/apps/tickets/handlers/base.py @@ -1,11 +1,12 @@ from django.utils.translation import ugettext as _ +from django.template.loader import render_to_string from common.utils import get_logger from tickets.utils import ( send_ticket_processed_mail_to_applicant, send_ticket_applied_mail_to_assignees ) -from tickets.const import TicketState, TicketStatus +from tickets.const import TicketState, TicketType logger = get_logger(__name__) @@ -59,6 +60,25 @@ class BaseHandler: logger.debug('Send processed mail to applicant: {}'.format(applicant)) send_ticket_processed_mail_to_applicant(self.ticket, processor) + def _diff_prev_approve_context(self, state): + diff_context = {} + if state != TicketState.approved: + return diff_context + if self.ticket.type not in [TicketType.apply_asset, TicketType.apply_application]: + return diff_context + + old_rel_snapshot = self.ticket.old_rel_snapshot + current_rel_snapshot = self.ticket.get_local_snapshot() + diff = set(current_rel_snapshot.items()) - set(old_rel_snapshot.items()) + if not diff: + return diff_context + + content = [] + for k, v in sorted(list(diff), reverse=True): + content.append([k, old_rel_snapshot[k], v]) + headers = [_('Change field'), _('Before change'), _('After change')] + return {'headers': headers, 'content': content} + def _create_state_change_comment(self, state): # 打开或关闭工单,备注显示是自己,其他是受理人 if state in [TicketState.reopen, TicketState.pending, TicketState.closed]: @@ -68,8 +88,11 @@ class BaseHandler: user_display = str(user) state_display = getattr(TicketState, state).label + approve_info = _('{} {} the ticket').format(user_display, state_display) + context = self._diff_prev_approve_context(state) + context.update({'approve_info': approve_info}) data = { - 'body': _('{} {} the ticket').format(user_display, state_display), + 'body': render_to_string('tickets/ticket_approve_diff.html', context), 'user': user, 'user_display': str(user), 'type': 'state', diff --git a/apps/tickets/migrations/0017_auto_20220623_1027.py b/apps/tickets/migrations/0017_auto_20220623_1027.py index 3f241d54f..746d267c8 100644 --- a/apps/tickets/migrations/0017_auto_20220623_1027.py +++ b/apps/tickets/migrations/0017_auto_20220623_1027.py @@ -102,7 +102,7 @@ def apply_asset_migrate(apps, *args): 'applicant': instance.applicant_display, 'apply_nodes': meta.get('apply_nodes_display', []), 'apply_assets': meta.get('apply_assets_display', []), - 'apply_system_users': meta.get('apply_system_users', []), + 'apply_system_users': meta.get('apply_system_users_display', []), } instance.rel_snapshot = rel_snapshot instance.save(update_fields=['rel_snapshot']) @@ -140,7 +140,7 @@ def apply_application_migrate(apps, *args): rel_snapshot = { 'applicant': instance.applicant_display, 'apply_applications': meta.get('apply_applications_display', []), - 'apply_system_users': meta.get('apply_system_users', []), + 'apply_system_users': meta.get('apply_system_users_display', []), } instance.rel_snapshot = rel_snapshot instance.save(update_fields=['rel_snapshot']) diff --git a/apps/tickets/models/ticket/apply_application.py b/apps/tickets/models/ticket/apply_application.py index de041c8da..6bd721677 100644 --- a/apps/tickets/models/ticket/apply_application.py +++ b/apps/tickets/models/ticket/apply_application.py @@ -8,7 +8,7 @@ __all__ = ['ApplyApplicationTicket'] class ApplyApplicationTicket(Ticket): - apply_permission_name = models.CharField(max_length=128, verbose_name=_('Apply name')) + apply_permission_name = models.CharField(max_length=128, verbose_name=_('Permission name')) # 申请信息 apply_category = models.CharField( max_length=16, choices=AppCategory.choices, verbose_name=_('Category') diff --git a/apps/tickets/models/ticket/apply_asset.py b/apps/tickets/models/ticket/apply_asset.py index 45cad4dca..c3759dc9a 100644 --- a/apps/tickets/models/ticket/apply_asset.py +++ b/apps/tickets/models/ticket/apply_asset.py @@ -10,7 +10,7 @@ asset_or_node_help_text = _("Select at least one asset or node") class ApplyAssetTicket(Ticket): - apply_permission_name = models.CharField(max_length=128, verbose_name=_('Apply name')) + apply_permission_name = models.CharField(max_length=128, verbose_name=_('Permission name')) apply_nodes = models.ManyToManyField('assets.Node', verbose_name=_('Apply nodes')) # 申请信息 apply_assets = models.ManyToManyField('assets.Asset', verbose_name=_('Apply assets')) @@ -26,3 +26,6 @@ class ApplyAssetTicket(Ticket): @property def apply_actions_display(self): return Action.value_to_choices_display(self.apply_actions) + + def get_apply_actions_display(self): + return ', '.join(self.apply_actions_display) diff --git a/apps/tickets/models/ticket/general.py b/apps/tickets/models/ticket/general.py index c87b3aa7f..e58ffa04a 100644 --- a/apps/tickets/models/ticket/general.py +++ b/apps/tickets/models/ticket/general.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # +import json from typing import Callable from django.db import models @@ -7,6 +8,7 @@ from django.db.models import Q from django.utils.translation import ugettext_lazy as _ from django.db.utils import IntegrityError from django.db.models.fields import related +from django.forms import model_to_dict from common.exceptions import JMSException from common.utils.timezone import as_current_tz @@ -97,6 +99,7 @@ class StatusMixin: state: str status: str + applicant_id: str applicant: models.ForeignKey current_step: TicketStep save: Callable @@ -130,6 +133,7 @@ class StatusMixin: self._open() def approve(self, processor): + self.set_rel_snapshot() self._change_state(StepState.approved, processor) def reject(self, processor): @@ -178,28 +182,34 @@ class StatusMixin: @property def process_map(self): process_map = [] - steps = self.ticket_steps.all() - for step in steps: + for step in self.ticket_steps.all(): + processor_id = '' assignee_ids = [] + processor_display = '' assignees_display = [] - ticket_assignees = step.ticket_assignees.all() - processor = None state = step.state - for i in ticket_assignees: - assignee_ids.append(i.assignee_id) - assignees_display.append(str(i.assignee)) + for i in step.ticket_assignees.all().prefetch_related('assignee'): + assignee_id = i.assignee_id + assignee_display = str(i.assignee) + if state != StepState.pending and state == i.state: - processor = i.assignee + processor_id = assignee_id + processor_display = assignee_display if state == StepState.closed: - processor = self.applicant + processor_id = self.applicant_id + processor_display = str(self.applicant) + + assignee_ids.append(assignee_id) + assignees_display.append(assignee_display) + step_info = { 'state': state, 'approval_level': step.level, 'assignees': assignee_ids, 'assignees_display': assignees_display, 'approval_date': str(step.date_updated), - 'processor': processor.id if processor else '', - 'processor_display': str(processor) if processor else '' + 'processor': processor_id, + 'processor_display': processor_display } process_map.append(step_info) return process_map @@ -380,6 +390,30 @@ class Ticket(StatusMixin, CommonModelMixin): raise JMSException(detail=_('Please try again'), code='please_try_again') raise e + def get_field_display(self, name, field, data: dict): + value = data.get(name) + if hasattr(self, f'get_{name}_display'): + value = getattr(self, f'get_{name}_display')() + elif isinstance(field, related.ForeignKey): + value = self.rel_snapshot[name] + elif isinstance(field, related.ManyToManyField): + value = ', '.join(self.rel_snapshot[name]) + return value + + def get_local_snapshot(self): + fields = self._meta._forward_fields_map + json_data = json.dumps(model_to_dict(self), cls=ModelJSONFieldEncoder) + data = json.loads(json_data) + snapshot = {} + local_fields = self._meta.local_fields + self._meta.local_many_to_many + excludes = ['ticket_ptr'] + item_names = [field.name for field in local_fields if field.name not in excludes] + for name in item_names: + field = fields[name] + value = self.get_field_display(name, field, data) + snapshot[field.verbose_name] = value + return snapshot + class SuperTicket(Ticket): class Meta: diff --git a/apps/tickets/notifications.py b/apps/tickets/notifications.py index 728510280..3fa0e5a82 100644 --- a/apps/tickets/notifications.py +++ b/apps/tickets/notifications.py @@ -4,7 +4,6 @@ import json from django.conf import settings from django.core.cache import cache from django.shortcuts import reverse -from django.db.models.fields import related from django.template.loader import render_to_string from django.forms import model_to_dict from django.utils.translation import ugettext_lazy as _ @@ -75,13 +74,7 @@ class BaseTicketMessage(UserMessage): for name in item_names: field = fields[name] item = {'name': name, 'title': field.verbose_name} - value = data.get(name) - if hasattr(self.ticket, f'get_{name}_display'): - value = getattr(self.ticket, f'get_{name}_display')() - elif isinstance(field, related.ForeignKey): - value = self.ticket.rel_snapshot[name] - elif isinstance(field, related.ManyToManyField): - value = ', '.join(self.ticket.rel_snapshot[name]) + value = self.ticket.get_field_display(name, field, data) item['value'] = value items.append(item) return items @@ -113,7 +106,7 @@ class TicketAppliedToAssigneeMessage(BaseTicketMessage): @property def content_title(self): - return _('Your has a new ticket') + return _('Your has a new ticket, applicant - {}').format(self.ticket.applicant) @property def subject(self): diff --git a/apps/tickets/serializers/ticket/apply_application.py b/apps/tickets/serializers/ticket/apply_application.py index 700f7b45e..c713f21d6 100644 --- a/apps/tickets/serializers/ticket/apply_application.py +++ b/apps/tickets/serializers/ticket/apply_application.py @@ -1,3 +1,4 @@ +from django.utils.translation import ugettext as _ from rest_framework import serializers from perms.models import ApplicationPermission @@ -7,7 +8,7 @@ from tickets.models import ApplyApplicationTicket from .ticket import TicketApplySerializer from .common import BaseApplyAssetApplicationSerializer -__all__ = ['ApplyApplicationSerializer', 'ApplyApplicationDisplaySerializer'] +__all__ = ['ApplyApplicationSerializer', 'ApplyApplicationDisplaySerializer', 'ApproveApplicationSerializer'] class ApplyApplicationSerializer(BaseApplyAssetApplicationSerializer, TicketApplySerializer): @@ -24,15 +25,23 @@ class ApplyApplicationSerializer(BaseApplyAssetApplicationSerializer, TicketAppl read_only_fields = list(set(fields) - set(writeable_fields)) ticket_extra_kwargs = TicketApplySerializer.Meta.extra_kwargs extra_kwargs = { - 'apply_system_users': {'required': True}, + 'apply_applications': {'required': False, 'allow_empty': True}, + 'apply_system_users': {'required': False, 'allow_empty': True}, } extra_kwargs.update(ticket_extra_kwargs) def validate_apply_applications(self, applications): + if self.is_final_approval and not applications: + raise serializers.ValidationError(_('This field is required.')) tp = self.initial_data.get('apply_type') return self.filter_many_to_many_field(Application, applications, type=tp) +class ApproveApplicationSerializer(ApplyApplicationSerializer): + class Meta(ApplyApplicationSerializer.Meta): + read_only_fields = ApplyApplicationSerializer.Meta.read_only_fields + ['title', 'type'] + + class ApplyApplicationDisplaySerializer(ApplyApplicationSerializer): apply_applications = serializers.SerializerMethodField() apply_system_users = serializers.SerializerMethodField() diff --git a/apps/tickets/serializers/ticket/apply_asset.py b/apps/tickets/serializers/ticket/apply_asset.py index c32de52c1..b8a007e8d 100644 --- a/apps/tickets/serializers/ticket/apply_asset.py +++ b/apps/tickets/serializers/ticket/apply_asset.py @@ -10,13 +10,13 @@ from tickets.models import ApplyAssetTicket from .ticket import TicketApplySerializer from .common import BaseApplyAssetApplicationSerializer -__all__ = ['ApplyAssetSerializer', 'ApplyAssetDisplaySerializer'] +__all__ = ['ApplyAssetSerializer', 'ApplyAssetDisplaySerializer', 'ApproveAssetSerializer'] asset_or_node_help_text = _("Select at least one asset or node") class ApplyAssetSerializer(BaseApplyAssetApplicationSerializer, TicketApplySerializer): - apply_actions = ActionsField(required=True, allow_null=True) + apply_actions = ActionsField(required=True, allow_empty=False) permission_model = AssetPermission class Meta: @@ -30,9 +30,9 @@ class ApplyAssetSerializer(BaseApplyAssetApplicationSerializer, TicketApplySeria read_only_fields = list(set(fields) - set(writeable_fields)) ticket_extra_kwargs = TicketApplySerializer.Meta.extra_kwargs extra_kwargs = { - 'apply_nodes': {'required': False, 'help_text': asset_or_node_help_text}, - 'apply_assets': {'required': False, 'help_text': asset_or_node_help_text}, - 'apply_system_users': {'required': True}, + 'apply_nodes': {'required': False, 'allow_empty': True}, + 'apply_assets': {'required': False, 'allow_empty': True}, + 'apply_system_users': {'required': False, 'allow_empty': True}, } extra_kwargs.update(ticket_extra_kwargs) @@ -44,14 +44,22 @@ class ApplyAssetSerializer(BaseApplyAssetApplicationSerializer, TicketApplySeria def validate(self, attrs): attrs = super().validate(attrs) - if not attrs.get('apply_nodes') and not attrs.get('apply_assets'): + if self.is_final_approval and ( + not attrs.get('apply_nodes') and not attrs.get('apply_assets') + ): raise serializers.ValidationError({ 'apply_nodes': asset_or_node_help_text, 'apply_assets': asset_or_node_help_text, }) + return attrs +class ApproveAssetSerializer(ApplyAssetSerializer): + class Meta(ApplyAssetSerializer.Meta): + read_only_fields = ApplyAssetSerializer.Meta.read_only_fields + ['title', 'type'] + + class ApplyAssetDisplaySerializer(ApplyAssetSerializer): apply_nodes = serializers.SerializerMethodField() apply_assets = serializers.SerializerMethodField() diff --git a/apps/tickets/serializers/ticket/common.py b/apps/tickets/serializers/ticket/common.py index 4a375465e..6957da3b0 100644 --- a/apps/tickets/serializers/ticket/common.py +++ b/apps/tickets/serializers/ticket/common.py @@ -38,14 +38,25 @@ class DefaultPermissionName(object): class BaseApplyAssetApplicationSerializer(serializers.Serializer): permission_model: Model + @property + def is_final_approval(self): + instance = self.instance + if not instance: + return False + if instance.approval_step == instance.ticket_steps.count(): + return True + return False + def filter_many_to_many_field(self, model, values: list, **kwargs): - org_id = self.initial_data.get('org_id') + org_id = self.instance.org_id if self.instance else self.initial_data.get('org_id') ids = [instance.id for instance in values] with tmp_to_org(org_id): qs = model.objects.filter(id__in=ids, **kwargs).values_list('id', flat=True) return list(qs) def validate_apply_system_users(self, system_users): + if self.is_final_approval and not system_users: + raise serializers.ValidationError(_('This field is required.')) return self.filter_many_to_many_field(SystemUser, system_users) def validate(self, attrs): @@ -72,3 +83,10 @@ class BaseApplyAssetApplicationSerializer(serializers.Serializer): instance.save() return instance raise serializers.ValidationError(_('Permission named `{}` already exists'.format(name))) + + @atomic + def update(self, instance, validated_data): + old_rel_snapshot = instance.get_local_snapshot() + instance = super().update(instance, validated_data) + instance.old_rel_snapshot = old_rel_snapshot + return instance diff --git a/apps/tickets/serializers/ticket/ticket.py b/apps/tickets/serializers/ticket/ticket.py index 2af3811ca..facf3fcec 100644 --- a/apps/tickets/serializers/ticket/ticket.py +++ b/apps/tickets/serializers/ticket/ticket.py @@ -80,6 +80,9 @@ class TicketApplySerializer(TicketSerializer): return org_id def validate(self, attrs): + if self.instance: + return attrs + ticket_type = attrs.get('type') org_id = attrs.get('org_id') flow = TicketFlow.get_org_related_flows(org_id=org_id).filter(type=ticket_type).first() diff --git a/apps/tickets/templates/tickets/ticket_approve_diff.html b/apps/tickets/templates/tickets/ticket_approve_diff.html new file mode 100644 index 000000000..9fe6b80e0 --- /dev/null +++ b/apps/tickets/templates/tickets/ticket_approve_diff.html @@ -0,0 +1,24 @@ + + + +

{{ approve_info }}

+
+
+ + + {% for item in headers %} + + {% endfor %} + + {% for item in content %} + + {% for child in item %} + + {% endfor %} + + {% endfor %} + +
{{ item }}
{{ child }}
+
+ + From d78981098412cfeacba94a4100b184d8695aca8f Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 12 Jul 2022 16:02:41 +0800 Subject: [PATCH 07/13] fix: condirm (#8572) Co-authored-by: feng626 <1304903146@qq.com> --- apps/authentication/api/confirm.py | 9 ++++++++- apps/authentication/urls/api_urls.py | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/authentication/api/confirm.py b/apps/authentication/api/confirm.py index c085bb017..d3a32a7c8 100644 --- a/apps/authentication/api/confirm.py +++ b/apps/authentication/api/confirm.py @@ -7,11 +7,18 @@ from rest_framework.generics import RetrieveAPIView, CreateAPIView from rest_framework.response import Response from rest_framework import status -from common.permissions import IsValidUser +from common.permissions import IsValidUser, UserConfirmation from ..const import ConfirmType from ..serializers import ConfirmSerializer +class ConfirmBindORUNBindOAuth(RetrieveAPIView): + permission_classes = (UserConfirmation.require(ConfirmType.ReLogin),) + + def retrieve(self, request, *args, **kwargs): + return Response('ok') + + class ConfirmApi(RetrieveAPIView, CreateAPIView): permission_classes = (IsValidUser,) serializer_class = ConfirmSerializer diff --git a/apps/authentication/urls/api_urls.py b/apps/authentication/urls/api_urls.py index dd1faff28..cfbac879f 100644 --- a/apps/authentication/urls/api_urls.py +++ b/apps/authentication/urls/api_urls.py @@ -27,6 +27,7 @@ urlpatterns = [ path('auth/', api.TokenCreateApi.as_view(), name='user-auth'), path('confirm/', api.ConfirmApi.as_view(), name='user-confirm'), + path('confirm-oauth/', api.ConfirmBindORUNBindOAuth.as_view(), name='confirm-oauth'), path('tokens/', api.TokenCreateApi.as_view(), name='auth-token'), path('mfa/verify/', api.MFAChallengeVerifyApi.as_view(), name='mfa-verify'), path('mfa/challenge/', api.MFAChallengeVerifyApi.as_view(), name='mfa-challenge'), From cd119a2999b48655bd8c376d1e31567fe90d74af Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 12 Jul 2022 17:36:40 +0800 Subject: [PATCH 08/13] =?UTF-8?q?fix:=20=E9=A3=9E=E4=B9=A6=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E7=99=BB=E5=BD=95=E6=97=A5=E5=BF=97=E4=B8=8D=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E8=AE=A4=E8=AF=81=E6=96=B9=E5=BC=8F=20(#8574)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/audits/signal_handlers.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/audits/signal_handlers.py b/apps/audits/signal_handlers.py index 9f20057a3..9ac565bc6 100644 --- a/apps/audits/signal_handlers.py +++ b/apps/audits/signal_handlers.py @@ -51,6 +51,7 @@ class AuthBackendLabelMapping(LazyObject): backend_label_mapping[settings.AUTH_BACKEND_SSO] = _('SSO') backend_label_mapping[settings.AUTH_BACKEND_AUTH_TOKEN] = _('Auth Token') backend_label_mapping[settings.AUTH_BACKEND_WECOM] = _('WeCom') + backend_label_mapping[settings.AUTH_BACKEND_FEISHU] = _('FeiShu') backend_label_mapping[settings.AUTH_BACKEND_DINGTALK] = _('DingTalk') backend_label_mapping[settings.AUTH_BACKEND_TEMP_TOKEN] = _('Temporary token') return backend_label_mapping From b262643f0aa560278f9ce464e6a4f2b729125323 Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Tue, 12 Jul 2022 18:27:07 +0800 Subject: [PATCH 09/13] =?UTF-8?q?fix:=20=E8=BF=9E=E6=8E=A5=E4=BB=A4?= =?UTF-8?q?=E7=89=8C=E6=B7=BB=E5=8A=A0=20expire=5Ftime=20=E5=92=8C=20is=5F?= =?UTF-8?q?valid=20=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/authentication/models.py | 8 ++++++++ apps/authentication/serializers/connection_token.py | 6 ++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/authentication/models.py b/apps/authentication/models.py index c0713ac1a..d04a3fa4e 100644 --- a/apps/authentication/models.py +++ b/apps/authentication/models.py @@ -114,6 +114,14 @@ class ConnectionToken(OrgModelMixin, models.JMSModel): def is_expired(self): return self.date_expired < timezone.now() + @property + def expire_time(self): + interval = self.date_expired - timezone.now() + seconds = interval.total_seconds() + if seconds < 0: + seconds = 0 + return int(seconds) + def expire(self): self.date_expired = timezone.now() self.save() diff --git a/apps/authentication/serializers/connection_token.py b/apps/authentication/serializers/connection_token.py index c2af89aff..1b639bec6 100644 --- a/apps/authentication/serializers/connection_token.py +++ b/apps/authentication/serializers/connection_token.py @@ -20,7 +20,8 @@ __all__ = [ class ConnectionTokenSerializer(OrgResourceModelSerializerMixin): type_display = serializers.ReadOnlyField(source='get_type_display', label=_("Type display")) - validity = serializers.BooleanField(source='is_valid', read_only=True, label=_('Validity')) + is_valid = serializers.BooleanField(read_only=True, label=_('Validity')) + expire_time = serializers.IntegerField(read_only=True, label=_('Expired time')) class Meta: model = ConnectionToken @@ -35,7 +36,7 @@ class ConnectionTokenSerializer(OrgResourceModelSerializerMixin): ] read_only_fields = [ # 普通 Token 不支持指定 user - 'user', 'validity', + 'user', 'is_valid', 'expire_time', 'type_display', 'user_display', 'system_user_display', 'asset_display', 'application_display', ] @@ -184,6 +185,7 @@ class ConnectionTokenSecretSerializer(OrgResourceModelSerializerMixin): domain = ConnectionTokenDomainSerializer(read_only=True) cmd_filter_rules = ConnectionTokenCmdFilterRuleSerializer(many=True) actions = ActionsField() + expired_at = serializers.IntegerField() class Meta: model = ConnectionToken From 602192696cc064af4dc7eebfc6a18efaa332248f Mon Sep 17 00:00:00 2001 From: "Jiangjie.Bai" Date: Tue, 12 Jul 2022 18:03:54 +0800 Subject: [PATCH 10/13] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=BF=BB?= =?UTF-8?q?=E8=AF=91=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/ja/LC_MESSAGES/django.po | 275 ++++++++++++++------------- apps/locale/zh/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.po | 272 +++++++++++++------------- 4 files changed, 282 insertions(+), 273 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index 125de4e86..6d3f88208 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9abfbe0feec22996ffa184b7865f99d1357bad8c022bfba5b28c3f5bfbd0783f -size 127716 +oid sha256:326eef1f3134c1500a6641c6616a9d509befd5db42ead551fe5ca01b3e0273c0 +size 128150 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 88cb86c95..9205fb974 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2022-07-11 17:46+0800\n" +"POT-Creation-Date: 2022-07-12 17:58+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -47,7 +47,7 @@ msgstr "優先順位" msgid "1-100, the lower the value will be match first" msgstr "1-100、低い値は最初に一致します" -#: acls/models/base.py:31 authentication/models.py:20 +#: acls/models/base.py:31 authentication/models.py:21 #: authentication/templates/authentication/_access_key_modal.html:32 #: perms/models/base.py:88 terminal/models/sharing.py:28 tickets/const.py:39 msgid "Active" @@ -88,7 +88,7 @@ msgstr "ログイン確認" #: acls/models/login_acl.py:24 acls/models/login_asset_acl.py:20 #: assets/models/cmd_filter.py:30 assets/models/label.py:15 audits/models.py:37 #: audits/models.py:62 audits/models.py:87 audits/serializers.py:100 -#: authentication/models.py:53 authentication/models.py:77 orgs/models.py:214 +#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:214 #: perms/models/base.py:84 rbac/builtin.py:118 rbac/models/rolebinding.py:41 #: terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 terminal/models/session.py:44 @@ -131,7 +131,7 @@ msgstr "システムユーザー" #: assets/models/backup.py:31 assets/models/cmd_filter.py:38 #: assets/models/gathered_user.py:14 assets/serializers/label.py:30 #: assets/serializers/system_user.py:268 audits/models.py:39 -#: authentication/models.py:65 authentication/models.py:89 +#: authentication/models.py:66 authentication/models.py:90 #: perms/models/asset_permission.py:23 terminal/backends/command/models.py:21 #: terminal/backends/command/serializers.py:14 terminal/models/session.py:46 #: terminal/notifications.py:90 @@ -157,7 +157,7 @@ msgstr "コンマ区切り文字列の形式。* はすべて一致すること #: acls/serializers/login_asset_acl.py:51 assets/models/base.py:176 #: assets/models/gathered_user.py:15 audits/models.py:121 #: authentication/forms.py:25 authentication/forms.py:27 -#: authentication/models.py:244 +#: authentication/models.py:245 #: authentication/templates/authentication/_msg_different_city.html:9 #: authentication/templates/authentication/_msg_oauth_bind.html:9 #: ops/models/adhoc.py:159 users/forms/profile.py:32 users/models/user.py:659 @@ -262,14 +262,14 @@ msgstr "カスタム" #: applications/models/account.py:12 applications/models/application.py:234 #: assets/models/backup.py:32 assets/models/cmd_filter.py:45 -#: authentication/models.py:66 authentication/models.py:94 +#: authentication/models.py:67 authentication/models.py:95 #: perms/models/application_permission.py:28 msgid "Application" msgstr "アプリケーション" #: applications/models/account.py:15 assets/models/authbook.py:20 #: assets/models/cmd_filter.py:42 assets/models/user.py:342 audits/models.py:40 -#: authentication/models.py:82 perms/models/application_permission.py:33 +#: authentication/models.py:83 perms/models/application_permission.py:33 #: perms/models/asset_permission.py:25 terminal/backends/command/models.py:22 #: terminal/backends/command/serializers.py:36 terminal/models/session.py:48 #: xpack/plugins/change_auth_plan/models/app.py:36 @@ -307,7 +307,7 @@ msgstr "カテゴリ" #: applications/models/application.py:222 #: applications/serializers/application.py:101 assets/models/backup.py:49 #: assets/models/cmd_filter.py:82 assets/models/user.py:250 -#: authentication/models.py:69 perms/models/application_permission.py:24 +#: authentication/models.py:70 perms/models/application_permission.py:24 #: perms/serializers/application/user_permission.py:34 #: terminal/models/storage.py:58 terminal/models/storage.py:143 #: tickets/models/comment.py:26 tickets/models/flow.py:57 @@ -373,7 +373,7 @@ msgid "Date updated" msgstr "更新日" #: applications/serializers/application.py:121 -#: applications/serializers/application.py:166 authentication/models.py:98 +#: applications/serializers/application.py:166 authentication/models.py:99 msgid "Application display" msgstr "アプリケーション表示" @@ -577,7 +577,7 @@ msgstr "ホスト名生" #: assets/models/asset.py:215 assets/serializers/account.py:16 #: assets/serializers/asset.py:65 perms/serializers/asset/user_permission.py:41 -#: xpack/plugins/cloud/models.py:107 xpack/plugins/cloud/serializers/task.py:42 +#: xpack/plugins/cloud/models.py:107 xpack/plugins/cloud/serializers/task.py:43 msgid "Protocols" msgstr "プロトコル" @@ -590,7 +590,7 @@ msgstr "ノード" #: assets/models/asset.py:219 assets/models/cmd_filter.py:47 #: assets/models/domain.py:66 assets/models/label.py:22 -#: users/serializers/user.py:145 +#: users/serializers/user.py:147 msgid "Is active" msgstr "アクティブです。" @@ -768,7 +768,7 @@ msgstr "失敗しました" msgid "Connectivity" msgstr "接続性" -#: assets/models/base.py:40 authentication/models.py:247 +#: assets/models/base.py:40 authentication/models.py:248 msgid "Date verified" msgstr "確認済みの日付" @@ -778,7 +778,7 @@ msgstr "確認済みの日付" #: authentication/forms.py:32 #: authentication/templates/authentication/login.html:228 #: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:46 -#: users/forms/profile.py:22 users/serializers/user.py:92 +#: users/forms/profile.py:22 users/serializers/user.py:94 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/change_auth_plan/models/base.py:42 @@ -976,7 +976,7 @@ msgid "Parent key" msgstr "親キー" #: assets/models/node.py:559 assets/serializers/system_user.py:267 -#: xpack/plugins/cloud/models.py:96 xpack/plugins/cloud/serializers/task.py:69 +#: xpack/plugins/cloud/models.py:96 xpack/plugins/cloud/serializers/task.py:70 msgid "Node" msgstr "ノード" @@ -1035,7 +1035,7 @@ msgid "SFTP Root" msgstr "SFTPルート" #: assets/models/user.py:258 assets/serializers/system_user.py:37 -#: authentication/models.py:51 +#: authentication/models.py:52 msgid "Token" msgstr "トークン" @@ -1087,7 +1087,7 @@ msgstr "" "定してください暗号化パスワード" #: assets/serializers/account.py:36 assets/serializers/account.py:87 -#: assets/serializers/account_history.py:10 authentication/models.py:86 +#: assets/serializers/account_history.py:10 authentication/models.py:87 msgid "System user display" msgstr "システムユーザー表示" @@ -1581,7 +1581,7 @@ msgstr "として実行" msgid "Run as display" msgstr "ディスプレイとして実行する" -#: audits/serializers.py:102 authentication/models.py:80 +#: audits/serializers.py:102 authentication/models.py:81 #: rbac/serializers/rolebinding.py:21 msgid "User display" msgstr "ユーザー表示" @@ -1604,185 +1604,191 @@ msgstr "認証トークン" msgid "WeCom" msgstr "企業微信" -#: audits/signal_handlers.py:54 authentication/views/dingtalk.py:179 +#: audits/signal_handlers.py:54 authentication/views/feishu.py:144 +#: authentication/views/login.py:79 notifications/backends/__init__.py:14 +#: users/models/user.py:722 +msgid "FeiShu" +msgstr "本を飛ばす" + +#: audits/signal_handlers.py:55 authentication/views/dingtalk.py:179 #: authentication/views/login.py:73 notifications/backends/__init__.py:12 #: users/models/user.py:721 msgid "DingTalk" msgstr "DingTalk" -#: audits/signal_handlers.py:55 authentication/models.py:251 +#: audits/signal_handlers.py:56 authentication/models.py:252 msgid "Temporary token" msgstr "仮パスワード" -#: audits/signal_handlers.py:67 +#: audits/signal_handlers.py:68 msgid "User and Group" msgstr "ユーザーとグループ" -#: audits/signal_handlers.py:68 +#: audits/signal_handlers.py:69 #, python-brace-format msgid "{User} JOINED {UserGroup}" msgstr "{User} に参加 {UserGroup}" -#: audits/signal_handlers.py:69 +#: audits/signal_handlers.py:70 #, python-brace-format msgid "{User} LEFT {UserGroup}" msgstr "{User} のそばを通る {UserGroup}" -#: audits/signal_handlers.py:72 +#: audits/signal_handlers.py:73 msgid "Asset and SystemUser" msgstr "資産およびシステム・ユーザー" -#: audits/signal_handlers.py:73 +#: audits/signal_handlers.py:74 #, python-brace-format msgid "{Asset} ADD {SystemUser}" msgstr "{Asset} 追加 {SystemUser}" -#: audits/signal_handlers.py:74 +#: audits/signal_handlers.py:75 #, python-brace-format msgid "{Asset} REMOVE {SystemUser}" msgstr "{Asset} 削除 {SystemUser}" -#: audits/signal_handlers.py:77 +#: audits/signal_handlers.py:78 msgid "Node and Asset" msgstr "ノードと資産" -#: audits/signal_handlers.py:78 +#: audits/signal_handlers.py:79 #, python-brace-format msgid "{Node} ADD {Asset}" msgstr "{Node} 追加 {Asset}" -#: audits/signal_handlers.py:79 +#: audits/signal_handlers.py:80 #, python-brace-format msgid "{Node} REMOVE {Asset}" msgstr "{Node} 削除 {Asset}" -#: audits/signal_handlers.py:82 +#: audits/signal_handlers.py:83 msgid "User asset permissions" msgstr "ユーザー資産の権限" -#: audits/signal_handlers.py:83 +#: audits/signal_handlers.py:84 #, python-brace-format msgid "{AssetPermission} ADD {User}" msgstr "{AssetPermission} 追加 {User}" -#: audits/signal_handlers.py:84 +#: audits/signal_handlers.py:85 #, python-brace-format msgid "{AssetPermission} REMOVE {User}" msgstr "{AssetPermission} 削除 {User}" -#: audits/signal_handlers.py:87 +#: audits/signal_handlers.py:88 msgid "User group asset permissions" msgstr "ユーザーグループの資産権限" -#: audits/signal_handlers.py:88 +#: audits/signal_handlers.py:89 #, python-brace-format msgid "{AssetPermission} ADD {UserGroup}" msgstr "{AssetPermission} 追加 {UserGroup}" -#: audits/signal_handlers.py:89 +#: audits/signal_handlers.py:90 #, python-brace-format msgid "{AssetPermission} REMOVE {UserGroup}" msgstr "{AssetPermission} 削除 {UserGroup}" -#: audits/signal_handlers.py:92 perms/models/asset_permission.py:29 +#: audits/signal_handlers.py:93 perms/models/asset_permission.py:29 msgid "Asset permission" msgstr "資産権限" -#: audits/signal_handlers.py:93 +#: audits/signal_handlers.py:94 #, python-brace-format msgid "{AssetPermission} ADD {Asset}" msgstr "{AssetPermission} 追加 {Asset}" -#: audits/signal_handlers.py:94 +#: audits/signal_handlers.py:95 #, python-brace-format msgid "{AssetPermission} REMOVE {Asset}" msgstr "{AssetPermission} 削除 {Asset}" -#: audits/signal_handlers.py:97 +#: audits/signal_handlers.py:98 msgid "Node permission" msgstr "ノード権限" -#: audits/signal_handlers.py:98 +#: audits/signal_handlers.py:99 #, python-brace-format msgid "{AssetPermission} ADD {Node}" msgstr "{AssetPermission} 追加 {Node}" -#: audits/signal_handlers.py:99 +#: audits/signal_handlers.py:100 #, python-brace-format msgid "{AssetPermission} REMOVE {Node}" msgstr "{AssetPermission} 削除 {Node}" -#: audits/signal_handlers.py:102 +#: audits/signal_handlers.py:103 msgid "Asset permission and SystemUser" msgstr "資産権限とSystemUser" -#: audits/signal_handlers.py:103 +#: audits/signal_handlers.py:104 #, python-brace-format msgid "{AssetPermission} ADD {SystemUser}" msgstr "{AssetPermission} 追加 {SystemUser}" -#: audits/signal_handlers.py:104 +#: audits/signal_handlers.py:105 #, python-brace-format msgid "{AssetPermission} REMOVE {SystemUser}" msgstr "{AssetPermission} 削除 {SystemUser}" -#: audits/signal_handlers.py:107 +#: audits/signal_handlers.py:108 msgid "User application permissions" msgstr "ユーザーアプリケーションの権限" -#: audits/signal_handlers.py:108 +#: audits/signal_handlers.py:109 #, python-brace-format msgid "{ApplicationPermission} ADD {User}" msgstr "{ApplicationPermission} 追加 {User}" -#: audits/signal_handlers.py:109 +#: audits/signal_handlers.py:110 #, python-brace-format msgid "{ApplicationPermission} REMOVE {User}" msgstr "{ApplicationPermission} 削除 {User}" -#: audits/signal_handlers.py:112 +#: audits/signal_handlers.py:113 msgid "User group application permissions" msgstr "ユーザーグループアプリケーションの権限" -#: audits/signal_handlers.py:113 +#: audits/signal_handlers.py:114 #, python-brace-format msgid "{ApplicationPermission} ADD {UserGroup}" msgstr "{ApplicationPermission} 追加 {UserGroup}" -#: audits/signal_handlers.py:114 +#: audits/signal_handlers.py:115 #, python-brace-format msgid "{ApplicationPermission} REMOVE {UserGroup}" msgstr "{ApplicationPermission} 削除 {UserGroup}" -#: audits/signal_handlers.py:117 perms/models/application_permission.py:38 +#: audits/signal_handlers.py:118 perms/models/application_permission.py:38 msgid "Application permission" msgstr "申請許可" -#: audits/signal_handlers.py:118 +#: audits/signal_handlers.py:119 #, python-brace-format msgid "{ApplicationPermission} ADD {Application}" msgstr "{ApplicationPermission} 追加 {Application}" -#: audits/signal_handlers.py:119 +#: audits/signal_handlers.py:120 #, python-brace-format msgid "{ApplicationPermission} REMOVE {Application}" msgstr "{ApplicationPermission} 削除 {Application}" -#: audits/signal_handlers.py:122 +#: audits/signal_handlers.py:123 msgid "Application permission and SystemUser" msgstr "アプリケーション権限とSystemUser" -#: audits/signal_handlers.py:123 +#: audits/signal_handlers.py:124 #, python-brace-format msgid "{ApplicationPermission} ADD {SystemUser}" msgstr "{ApplicationPermission} 追加 {SystemUser}" -#: audits/signal_handlers.py:124 +#: audits/signal_handlers.py:125 #, python-brace-format msgid "{ApplicationPermission} REMOVE {SystemUser}" msgstr "{ApplicationPermission} 削除 {SystemUser}" -#: authentication/api/confirm.py:33 +#: authentication/api/confirm.py:40 msgid "This action require verify your MFA" msgstr "この操作には、MFAを検証する必要があります" @@ -2084,91 +2090,91 @@ msgstr "MFAタイプ ({}) が有効になっていない" msgid "Please change your password" msgstr "パスワードを変更してください" -#: authentication/models.py:36 +#: authentication/models.py:37 msgid "Access key" msgstr "アクセスキー" -#: authentication/models.py:43 +#: authentication/models.py:44 msgid "Private Token" msgstr "プライベートトークン" -#: authentication/models.py:52 +#: authentication/models.py:53 msgid "Expired" msgstr "期限切れ" -#: authentication/models.py:56 +#: authentication/models.py:57 msgid "SSO token" msgstr "SSO token" -#: authentication/models.py:71 authentication/models.py:245 +#: authentication/models.py:72 authentication/models.py:246 #: authentication/templates/authentication/_access_key_modal.html:31 #: settings/serializers/auth/radius.py:17 msgid "Secret" msgstr "ひみつ" -#: authentication/models.py:73 authentication/models.py:248 +#: authentication/models.py:74 authentication/models.py:249 #: perms/models/base.py:90 tickets/models/ticket/apply_application.py:26 #: tickets/models/ticket/apply_asset.py:24 users/models/user.py:703 msgid "Date expired" msgstr "期限切れの日付" -#: authentication/models.py:92 +#: authentication/models.py:93 msgid "Asset display" msgstr "アセット名" -#: authentication/models.py:103 +#: authentication/models.py:104 msgid "Connection token" msgstr "接続トークン" -#: authentication/models.py:105 +#: authentication/models.py:106 msgid "Can view connection token secret" msgstr "接続トークンの秘密を表示できます" -#: authentication/models.py:140 +#: authentication/models.py:141 msgid "Connection token expired at: {}" msgstr "接続トークンの有効期限: {}" -#: authentication/models.py:145 +#: authentication/models.py:146 msgid "User not exists" msgstr "ユーザーは存在しません" -#: authentication/models.py:149 +#: authentication/models.py:150 msgid "User invalid, disabled or expired" msgstr "ユーザーが無効、無効、または期限切れです" -#: authentication/models.py:154 +#: authentication/models.py:155 msgid "System user not exists" msgstr "システムユーザーが存在しません" -#: authentication/models.py:160 +#: authentication/models.py:161 msgid "Asset not exists" msgstr "アセットが存在しません" -#: authentication/models.py:164 +#: authentication/models.py:165 msgid "Asset inactive" msgstr "アセットがアクティブ化されていません" -#: authentication/models.py:171 +#: authentication/models.py:172 msgid "User has no permission to access asset or permission expired" msgstr "" "ユーザーがアセットにアクセスする権限を持っていないか、権限の有効期限が切れて" "います" -#: authentication/models.py:179 +#: authentication/models.py:180 msgid "Application not exists" msgstr "アプリが存在しません" -#: authentication/models.py:186 +#: authentication/models.py:187 msgid "User has no permission to access application or permission expired" msgstr "" "ユーザーがアプリにアクセスする権限を持っていないか、権限の有効期限が切れてい" "ます" -#: authentication/models.py:246 +#: authentication/models.py:247 msgid "Verified" msgstr "確認済み" -#: authentication/models.py:267 +#: authentication/models.py:268 msgid "Super connection token" msgstr "スーパー接続トークン" @@ -2193,7 +2199,7 @@ msgstr "アセットまたはアプリが必要" #: perms/serializers/application/permission.py:20 #: perms/serializers/application/permission.py:41 #: perms/serializers/asset/permission.py:19 -#: perms/serializers/asset/permission.py:45 users/serializers/user.py:146 +#: perms/serializers/asset/permission.py:45 users/serializers/user.py:148 msgid "Is valid" msgstr "有効です" @@ -2484,11 +2490,6 @@ msgstr "FeiShuクエリユーザーが失敗しました" msgid "The FeiShu is already bound to another user" msgstr "FeiShuはすでに別のユーザーにバインドされています" -#: authentication/views/feishu.py:144 authentication/views/login.py:79 -#: notifications/backends/__init__.py:14 users/models/user.py:722 -msgid "FeiShu" -msgstr "本を飛ばす" - #: authentication/views/feishu.py:145 msgid "Binding FeiShu successfully" msgstr "本を飛ばすのバインドに成功" @@ -3147,8 +3148,8 @@ msgstr "Organization {} のアプリケーション権限" #: perms/serializers/application/permission.py:21 #: perms/serializers/application/permission.py:40 #: perms/serializers/asset/permission.py:20 -#: perms/serializers/asset/permission.py:44 users/serializers/user.py:87 -#: users/serializers/user.py:148 +#: perms/serializers/asset/permission.py:44 users/serializers/user.py:89 +#: users/serializers/user.py:150 msgid "Is expired" msgstr "期限切れです" @@ -4653,10 +4654,6 @@ msgstr "マイクロソフト" msgid "Official" msgstr "公式" -#: templates/resource_download.html:51 -msgid "Offline video player" -msgstr "オフラインビデオプレーヤー" - #: templates/resource_download.html:33 msgid "" "macOS needs to download the client to connect RDP asset, which comes with " @@ -4677,6 +4674,10 @@ msgstr "" "Jmservisorはwindowsリモートアプリケーションパブリケーションサーバでリモートア" "プリケーションを引き出すためのプログラムです" +#: templates/resource_download.html:51 +msgid "Offline video player" +msgstr "オフラインビデオプレーヤー" + #: terminal/api/endpoint.py:26 msgid "Not found protocol query params" msgstr "プロトコルクエリパラメータが見つかりません" @@ -5652,7 +5653,7 @@ msgstr "強制有効" msgid "Local" msgstr "ローカル" -#: users/models/user.py:673 users/serializers/user.py:147 +#: users/models/user.py:673 users/serializers/user.py:149 msgid "Is service account" msgstr "サービスアカウントです" @@ -5751,109 +5752,105 @@ msgstr "新しいパスワードを最後の {} 個のパスワードにする msgid "The newly set password is inconsistent" msgstr "新しく設定されたパスワードが一致しない" -#: users/serializers/profile.py:149 users/serializers/user.py:144 +#: users/serializers/profile.py:149 users/serializers/user.py:146 msgid "Is first login" msgstr "最初のログインです" -#: users/serializers/user.py:26 +#: users/serializers/user.py:28 msgid "System roles" msgstr "システムの役割" -#: users/serializers/user.py:31 +#: users/serializers/user.py:33 msgid "Org roles" msgstr "組織ロール" -#: users/serializers/user.py:33 +#: users/serializers/user.py:35 msgid "System roles display" msgstr "システムロール表示" -#: users/serializers/user.py:34 +#: users/serializers/user.py:36 msgid "Org roles display" msgstr "組織ロール表示" -#: users/serializers/user.py:79 +#: users/serializers/user.py:81 #: xpack/plugins/change_auth_plan/models/base.py:35 #: xpack/plugins/change_auth_plan/serializers/base.py:27 msgid "Password strategy" msgstr "パスワード戦略" -#: users/serializers/user.py:81 +#: users/serializers/user.py:83 msgid "MFA enabled" msgstr "MFA有効化" -#: users/serializers/user.py:82 +#: users/serializers/user.py:84 msgid "MFA force enabled" msgstr "MFAフォース有効化" -#: users/serializers/user.py:84 +#: users/serializers/user.py:86 msgid "MFA level display" msgstr "MFAレベル表示" -#: users/serializers/user.py:86 +#: users/serializers/user.py:88 msgid "Login blocked" msgstr "ログインブロック" -#: users/serializers/user.py:89 +#: users/serializers/user.py:91 msgid "Can public key authentication" msgstr "公開鍵認証が可能" -#: users/serializers/user.py:149 +#: users/serializers/user.py:151 msgid "Avatar url" msgstr "アバターURL" -#: users/serializers/user.py:151 +#: users/serializers/user.py:153 msgid "Groups name" msgstr "グループ名" -#: users/serializers/user.py:152 +#: users/serializers/user.py:154 msgid "Source name" msgstr "ソース名" -#: users/serializers/user.py:153 +#: users/serializers/user.py:155 msgid "Organization role name" msgstr "組織の役割名" -#: users/serializers/user.py:154 +#: users/serializers/user.py:156 msgid "Super role name" msgstr "スーパーロール名" -#: users/serializers/user.py:155 +#: users/serializers/user.py:157 msgid "Total role name" msgstr "合計ロール名" -#: users/serializers/user.py:157 +#: users/serializers/user.py:159 msgid "Is wecom bound" msgstr "企業の微信をバインドしているかどうか" -#: users/serializers/user.py:158 +#: users/serializers/user.py:160 msgid "Is dingtalk bound" msgstr "ピンをバインドしているかどうか" -#: users/serializers/user.py:159 +#: users/serializers/user.py:161 msgid "Is feishu bound" msgstr "飛本を縛ったかどうか" -#: users/serializers/user.py:160 +#: users/serializers/user.py:162 msgid "Is OTP bound" msgstr "仮想MFAがバインドされているか" -#: users/serializers/user.py:162 +#: users/serializers/user.py:164 msgid "System role name" msgstr "システムロール名" -#: users/serializers/user.py:202 -msgid "User cannot self-update fields: {}" -msgstr "ユーザーは自分のフィールドを更新できません: {}" - -#: users/serializers/user.py:259 +#: users/serializers/user.py:263 msgid "Select users" msgstr "ユーザーの選択" -#: users/serializers/user.py:260 +#: users/serializers/user.py:264 msgid "For security, only list several users" msgstr "セキュリティのために、複数のユーザーのみをリストします" -#: users/serializers/user.py:295 +#: users/serializers/user.py:299 msgid "name not unique" msgstr "名前が一意ではない" @@ -6402,11 +6399,11 @@ msgstr "クラウドアカウント" msgid "Test cloud account" msgstr "クラウドアカウントのテスト" -#: xpack/plugins/cloud/models.py:85 xpack/plugins/cloud/serializers/task.py:66 +#: xpack/plugins/cloud/models.py:85 xpack/plugins/cloud/serializers/task.py:67 msgid "Account" msgstr "アカウント" -#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:37 +#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:38 msgid "Regions" msgstr "リージョン" @@ -6414,19 +6411,19 @@ msgstr "リージョン" msgid "Hostname strategy" msgstr "ホスト名戦略" -#: xpack/plugins/cloud/models.py:100 xpack/plugins/cloud/serializers/task.py:67 +#: xpack/plugins/cloud/models.py:100 xpack/plugins/cloud/serializers/task.py:68 msgid "Unix admin user" msgstr "Unix adminユーザー" -#: xpack/plugins/cloud/models.py:104 xpack/plugins/cloud/serializers/task.py:68 +#: xpack/plugins/cloud/models.py:104 xpack/plugins/cloud/serializers/task.py:69 msgid "Windows admin user" msgstr "Windows管理者" -#: xpack/plugins/cloud/models.py:110 xpack/plugins/cloud/serializers/task.py:45 +#: xpack/plugins/cloud/models.py:110 xpack/plugins/cloud/serializers/task.py:46 msgid "IP network segment group" msgstr "IPネットワークセグメントグループ" -#: xpack/plugins/cloud/models.py:113 xpack/plugins/cloud/serializers/task.py:71 +#: xpack/plugins/cloud/models.py:113 xpack/plugins/cloud/serializers/task.py:72 msgid "Always update" msgstr "常に更新" @@ -6700,32 +6697,37 @@ msgstr "ファイルはJSON形式です。" #: xpack/plugins/cloud/serializers/task.py:29 msgid "" -"The IP address that is first matched to will be used as the IP of the " -"created asset.
The default * indicates a random match.
Format for " -"comma-delimited string, Such as: 192.168.1.0/24, 10.1.1.1-10.1.1.20" +"Only instances matching the IP range will be synced.
If the instance " +"contains multiple IP addresses, the first IP address that matches will be " +"used as the IP for the created asset.
The default value of * means sync " +"all instances and randomly match IP addresses.
Format for comma-" +"delimited string, Such as: 192.168.1.0/24, 10.1.1.1-10.1.1.20" msgstr "" -"最初に一致するIPアドレスは、作成された資産のIPとして使用されます。
デフォ" -"ルト*はランダムマッチングを表します。
カンマで区切られた文字列で書式設" -"定,たとえば:192.168.1.0/24,10.1.1.1-10.1.1.20" +"IP範囲に一致するインスタンスのみが同期されます。
" +"インスタンスに複数のIPアドレスが含まれている場合、一致する最初のIPアドレスが作成されたアセットのIPとして使用されます。
" +"デフォルト値の*は、すべてのインスタンスを同期し、IPアドレスをランダムに一致させることを意味します。
" +"形式はコンマ区切りの文字列です。例:192.168.1.0/24,10.1.1.1-10.1.1.20" -#: xpack/plugins/cloud/serializers/task.py:35 + + +#: xpack/plugins/cloud/serializers/task.py:36 msgid "History count" msgstr "実行回数" -#: xpack/plugins/cloud/serializers/task.py:36 +#: xpack/plugins/cloud/serializers/task.py:37 msgid "Instance count" msgstr "インスタンス数" -#: xpack/plugins/cloud/serializers/task.py:65 +#: xpack/plugins/cloud/serializers/task.py:66 msgid "Linux admin user" msgstr "Linux管理者" -#: xpack/plugins/cloud/serializers/task.py:70 +#: xpack/plugins/cloud/serializers/task.py:71 #: xpack/plugins/gathered_user/serializers.py:20 msgid "Periodic display" msgstr "定期的な表示" -#: xpack/plugins/cloud/utils.py:68 +#: xpack/plugins/cloud/utils.py:69 msgid "Account unavailable" msgstr "利用できないアカウント" @@ -6812,3 +6814,6 @@ msgstr "究極のエディション" #: xpack/plugins/license/models.py:77 msgid "Community edition" msgstr "コミュニティ版" + +#~ msgid "User cannot self-update fields: {}" +#~ msgstr "ユーザーは自分のフィールドを更新できません: {}" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 951c7182d..dcc55a77c 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:393289b7bc2842cf9190af0783281a8e8acdb636b0ff4e88ef4ff931c2c11f5c -size 105290 +oid sha256:1efe7f07b0877357a42a7f93e075c152e2bd8ee7adc20bcab17427a86cce5ed3 +size 105644 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index ab6fe167e..1cf1383be 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: 2022-07-11 17:46+0800\n" +"POT-Creation-Date: 2022-07-12 17:58+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -46,7 +46,7 @@ msgstr "优先级" msgid "1-100, the lower the value will be match first" msgstr "优先级可选范围为 1-100 (数值越小越优先)" -#: acls/models/base.py:31 authentication/models.py:20 +#: acls/models/base.py:31 authentication/models.py:21 #: authentication/templates/authentication/_access_key_modal.html:32 #: perms/models/base.py:88 terminal/models/sharing.py:28 tickets/const.py:39 msgid "Active" @@ -87,7 +87,7 @@ msgstr "登录复核" #: acls/models/login_acl.py:24 acls/models/login_asset_acl.py:20 #: assets/models/cmd_filter.py:30 assets/models/label.py:15 audits/models.py:37 #: audits/models.py:62 audits/models.py:87 audits/serializers.py:100 -#: authentication/models.py:53 authentication/models.py:77 orgs/models.py:214 +#: authentication/models.py:54 authentication/models.py:78 orgs/models.py:214 #: perms/models/base.py:84 rbac/builtin.py:118 rbac/models/rolebinding.py:41 #: terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 terminal/models/session.py:44 @@ -130,7 +130,7 @@ msgstr "系统用户" #: assets/models/backup.py:31 assets/models/cmd_filter.py:38 #: assets/models/gathered_user.py:14 assets/serializers/label.py:30 #: assets/serializers/system_user.py:268 audits/models.py:39 -#: authentication/models.py:65 authentication/models.py:89 +#: authentication/models.py:66 authentication/models.py:90 #: perms/models/asset_permission.py:23 terminal/backends/command/models.py:21 #: terminal/backends/command/serializers.py:14 terminal/models/session.py:46 #: terminal/notifications.py:90 @@ -156,7 +156,7 @@ msgstr "格式为逗号分隔的字符串, * 表示匹配所有. " #: acls/serializers/login_asset_acl.py:51 assets/models/base.py:176 #: assets/models/gathered_user.py:15 audits/models.py:121 #: authentication/forms.py:25 authentication/forms.py:27 -#: authentication/models.py:244 +#: authentication/models.py:245 #: authentication/templates/authentication/_msg_different_city.html:9 #: authentication/templates/authentication/_msg_oauth_bind.html:9 #: ops/models/adhoc.py:159 users/forms/profile.py:32 users/models/user.py:659 @@ -257,14 +257,14 @@ msgstr "自定义" #: applications/models/account.py:12 applications/models/application.py:234 #: assets/models/backup.py:32 assets/models/cmd_filter.py:45 -#: authentication/models.py:66 authentication/models.py:94 +#: authentication/models.py:67 authentication/models.py:95 #: perms/models/application_permission.py:28 msgid "Application" msgstr "应用程序" #: applications/models/account.py:15 assets/models/authbook.py:20 #: assets/models/cmd_filter.py:42 assets/models/user.py:342 audits/models.py:40 -#: authentication/models.py:82 perms/models/application_permission.py:33 +#: authentication/models.py:83 perms/models/application_permission.py:33 #: perms/models/asset_permission.py:25 terminal/backends/command/models.py:22 #: terminal/backends/command/serializers.py:36 terminal/models/session.py:48 #: xpack/plugins/change_auth_plan/models/app.py:36 @@ -302,7 +302,7 @@ msgstr "类别" #: applications/models/application.py:222 #: applications/serializers/application.py:101 assets/models/backup.py:49 #: assets/models/cmd_filter.py:82 assets/models/user.py:250 -#: authentication/models.py:69 perms/models/application_permission.py:24 +#: authentication/models.py:70 perms/models/application_permission.py:24 #: perms/serializers/application/user_permission.py:34 #: terminal/models/storage.py:58 terminal/models/storage.py:143 #: tickets/models/comment.py:26 tickets/models/flow.py:57 @@ -368,7 +368,7 @@ msgid "Date updated" msgstr "更新日期" #: applications/serializers/application.py:121 -#: applications/serializers/application.py:166 authentication/models.py:98 +#: applications/serializers/application.py:166 authentication/models.py:99 msgid "Application display" msgstr "应用名称" @@ -572,7 +572,7 @@ msgstr "主机名原始" #: assets/models/asset.py:215 assets/serializers/account.py:16 #: assets/serializers/asset.py:65 perms/serializers/asset/user_permission.py:41 -#: xpack/plugins/cloud/models.py:107 xpack/plugins/cloud/serializers/task.py:42 +#: xpack/plugins/cloud/models.py:107 xpack/plugins/cloud/serializers/task.py:43 msgid "Protocols" msgstr "协议组" @@ -585,7 +585,7 @@ msgstr "节点" #: assets/models/asset.py:219 assets/models/cmd_filter.py:47 #: assets/models/domain.py:66 assets/models/label.py:22 -#: users/serializers/user.py:145 +#: users/serializers/user.py:147 msgid "Is active" msgstr "激活" @@ -763,7 +763,7 @@ msgstr "失败" msgid "Connectivity" msgstr "可连接性" -#: assets/models/base.py:40 authentication/models.py:247 +#: assets/models/base.py:40 authentication/models.py:248 msgid "Date verified" msgstr "校验日期" @@ -773,7 +773,7 @@ msgstr "校验日期" #: authentication/forms.py:32 #: authentication/templates/authentication/login.html:228 #: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:46 -#: users/forms/profile.py:22 users/serializers/user.py:92 +#: users/forms/profile.py:22 users/serializers/user.py:94 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/change_auth_plan/models/base.py:42 @@ -971,7 +971,7 @@ msgid "Parent key" msgstr "ssh私钥" #: assets/models/node.py:559 assets/serializers/system_user.py:267 -#: xpack/plugins/cloud/models.py:96 xpack/plugins/cloud/serializers/task.py:69 +#: xpack/plugins/cloud/models.py:96 xpack/plugins/cloud/serializers/task.py:70 msgid "Node" msgstr "节点" @@ -1030,7 +1030,7 @@ msgid "SFTP Root" msgstr "SFTP根路径" #: assets/models/user.py:258 assets/serializers/system_user.py:37 -#: authentication/models.py:51 +#: authentication/models.py:52 msgid "Token" msgstr "Token" @@ -1079,7 +1079,7 @@ msgstr "" "置加密密码" #: assets/serializers/account.py:36 assets/serializers/account.py:87 -#: assets/serializers/account_history.py:10 authentication/models.py:86 +#: assets/serializers/account_history.py:10 authentication/models.py:87 msgid "System user display" msgstr "系统用户名称" @@ -1569,7 +1569,7 @@ msgstr "运行用户" msgid "Run as display" msgstr "运行用户名称" -#: audits/serializers.py:102 authentication/models.py:80 +#: audits/serializers.py:102 authentication/models.py:81 #: rbac/serializers/rolebinding.py:21 msgid "User display" msgstr "用户名称" @@ -1592,185 +1592,191 @@ msgstr "认证令牌" msgid "WeCom" msgstr "企业微信" -#: audits/signal_handlers.py:54 authentication/views/dingtalk.py:179 +#: audits/signal_handlers.py:54 authentication/views/feishu.py:144 +#: authentication/views/login.py:79 notifications/backends/__init__.py:14 +#: users/models/user.py:722 +msgid "FeiShu" +msgstr "飞书" + +#: audits/signal_handlers.py:55 authentication/views/dingtalk.py:179 #: authentication/views/login.py:73 notifications/backends/__init__.py:12 #: users/models/user.py:721 msgid "DingTalk" msgstr "钉钉" -#: audits/signal_handlers.py:55 authentication/models.py:251 +#: audits/signal_handlers.py:56 authentication/models.py:252 msgid "Temporary token" msgstr "临时密码" -#: audits/signal_handlers.py:67 +#: audits/signal_handlers.py:68 msgid "User and Group" msgstr "用户与用户组" -#: audits/signal_handlers.py:68 +#: audits/signal_handlers.py:69 #, python-brace-format msgid "{User} JOINED {UserGroup}" msgstr "{User} 加入 {UserGroup}" -#: audits/signal_handlers.py:69 +#: audits/signal_handlers.py:70 #, python-brace-format msgid "{User} LEFT {UserGroup}" msgstr "{User} 离开 {UserGroup}" -#: audits/signal_handlers.py:72 +#: audits/signal_handlers.py:73 msgid "Asset and SystemUser" msgstr "资产与系统用户" -#: audits/signal_handlers.py:73 +#: audits/signal_handlers.py:74 #, python-brace-format msgid "{Asset} ADD {SystemUser}" msgstr "{Asset} 添加 {SystemUser}" -#: audits/signal_handlers.py:74 +#: audits/signal_handlers.py:75 #, python-brace-format msgid "{Asset} REMOVE {SystemUser}" msgstr "{Asset} 移除 {SystemUser}" -#: audits/signal_handlers.py:77 +#: audits/signal_handlers.py:78 msgid "Node and Asset" msgstr "节点与资产" -#: audits/signal_handlers.py:78 +#: audits/signal_handlers.py:79 #, python-brace-format msgid "{Node} ADD {Asset}" msgstr "{Node} 添加 {Asset}" -#: audits/signal_handlers.py:79 +#: audits/signal_handlers.py:80 #, python-brace-format msgid "{Node} REMOVE {Asset}" msgstr "{Node} 移除 {Asset}" -#: audits/signal_handlers.py:82 +#: audits/signal_handlers.py:83 msgid "User asset permissions" msgstr "用户资产授权" -#: audits/signal_handlers.py:83 +#: audits/signal_handlers.py:84 #, python-brace-format msgid "{AssetPermission} ADD {User}" msgstr "{AssetPermission} 添加 {User}" -#: audits/signal_handlers.py:84 +#: audits/signal_handlers.py:85 #, python-brace-format msgid "{AssetPermission} REMOVE {User}" msgstr "{AssetPermission} 移除 {User}" -#: audits/signal_handlers.py:87 +#: audits/signal_handlers.py:88 msgid "User group asset permissions" msgstr "用户组资产授权" -#: audits/signal_handlers.py:88 +#: audits/signal_handlers.py:89 #, python-brace-format msgid "{AssetPermission} ADD {UserGroup}" msgstr "{AssetPermission} 添加 {UserGroup}" -#: audits/signal_handlers.py:89 +#: audits/signal_handlers.py:90 #, python-brace-format msgid "{AssetPermission} REMOVE {UserGroup}" msgstr "{AssetPermission} 移除 {UserGroup}" -#: audits/signal_handlers.py:92 perms/models/asset_permission.py:29 +#: audits/signal_handlers.py:93 perms/models/asset_permission.py:29 msgid "Asset permission" msgstr "资产授权" -#: audits/signal_handlers.py:93 +#: audits/signal_handlers.py:94 #, python-brace-format msgid "{AssetPermission} ADD {Asset}" msgstr "{AssetPermission} 添加 {Asset}" -#: audits/signal_handlers.py:94 +#: audits/signal_handlers.py:95 #, python-brace-format msgid "{AssetPermission} REMOVE {Asset}" msgstr "{AssetPermission} 移除 {Asset}" -#: audits/signal_handlers.py:97 +#: audits/signal_handlers.py:98 msgid "Node permission" msgstr "节点授权" -#: audits/signal_handlers.py:98 +#: audits/signal_handlers.py:99 #, python-brace-format msgid "{AssetPermission} ADD {Node}" msgstr "{AssetPermission} 添加 {Node}" -#: audits/signal_handlers.py:99 +#: audits/signal_handlers.py:100 #, python-brace-format msgid "{AssetPermission} REMOVE {Node}" msgstr "{AssetPermission} 移除 {Node}" -#: audits/signal_handlers.py:102 +#: audits/signal_handlers.py:103 msgid "Asset permission and SystemUser" msgstr "资产授权与系统用户" -#: audits/signal_handlers.py:103 +#: audits/signal_handlers.py:104 #, python-brace-format msgid "{AssetPermission} ADD {SystemUser}" msgstr "{AssetPermission} 添加 {SystemUser}" -#: audits/signal_handlers.py:104 +#: audits/signal_handlers.py:105 #, python-brace-format msgid "{AssetPermission} REMOVE {SystemUser}" msgstr "{AssetPermission} 移除 {SystemUser}" -#: audits/signal_handlers.py:107 +#: audits/signal_handlers.py:108 msgid "User application permissions" msgstr "用户应用授权" -#: audits/signal_handlers.py:108 +#: audits/signal_handlers.py:109 #, python-brace-format msgid "{ApplicationPermission} ADD {User}" msgstr "{ApplicationPermission} 添加 {User}" -#: audits/signal_handlers.py:109 +#: audits/signal_handlers.py:110 #, python-brace-format msgid "{ApplicationPermission} REMOVE {User}" msgstr "{ApplicationPermission} 移除 {User}" -#: audits/signal_handlers.py:112 +#: audits/signal_handlers.py:113 msgid "User group application permissions" msgstr "用户组应用授权" -#: audits/signal_handlers.py:113 +#: audits/signal_handlers.py:114 #, python-brace-format msgid "{ApplicationPermission} ADD {UserGroup}" msgstr "{ApplicationPermission} 添加 {UserGroup}" -#: audits/signal_handlers.py:114 +#: audits/signal_handlers.py:115 #, python-brace-format msgid "{ApplicationPermission} REMOVE {UserGroup}" msgstr "{ApplicationPermission} 移除 {UserGroup}" -#: audits/signal_handlers.py:117 perms/models/application_permission.py:38 +#: audits/signal_handlers.py:118 perms/models/application_permission.py:38 msgid "Application permission" msgstr "应用授权" -#: audits/signal_handlers.py:118 +#: audits/signal_handlers.py:119 #, python-brace-format msgid "{ApplicationPermission} ADD {Application}" msgstr "{ApplicationPermission} 添加 {Application}" -#: audits/signal_handlers.py:119 +#: audits/signal_handlers.py:120 #, python-brace-format msgid "{ApplicationPermission} REMOVE {Application}" msgstr "{ApplicationPermission} 移除 {Application}" -#: audits/signal_handlers.py:122 +#: audits/signal_handlers.py:123 msgid "Application permission and SystemUser" msgstr "应用授权与系统用户" -#: audits/signal_handlers.py:123 +#: audits/signal_handlers.py:124 #, python-brace-format msgid "{ApplicationPermission} ADD {SystemUser}" msgstr "{ApplicationPermission} 添加 {SystemUser}" -#: audits/signal_handlers.py:124 +#: audits/signal_handlers.py:125 #, python-brace-format msgid "{ApplicationPermission} REMOVE {SystemUser}" msgstr "{ApplicationPermission} 移除 {SystemUser}" -#: authentication/api/confirm.py:33 +#: authentication/api/confirm.py:40 msgid "This action require verify your MFA" msgstr "此操作需要验证您的 MFA" @@ -2063,87 +2069,87 @@ msgstr "该 MFA ({}) 方式没有启用" msgid "Please change your password" msgstr "请修改密码" -#: authentication/models.py:36 +#: authentication/models.py:37 msgid "Access key" msgstr "Access key" -#: authentication/models.py:43 +#: authentication/models.py:44 msgid "Private Token" msgstr "SSH密钥" -#: authentication/models.py:52 +#: authentication/models.py:53 msgid "Expired" msgstr "过期时间" -#: authentication/models.py:56 +#: authentication/models.py:57 msgid "SSO token" msgstr "SSO token" -#: authentication/models.py:71 authentication/models.py:245 +#: authentication/models.py:72 authentication/models.py:246 #: authentication/templates/authentication/_access_key_modal.html:31 #: settings/serializers/auth/radius.py:17 msgid "Secret" msgstr "密钥" -#: authentication/models.py:73 authentication/models.py:248 +#: authentication/models.py:74 authentication/models.py:249 #: perms/models/base.py:90 tickets/models/ticket/apply_application.py:26 #: tickets/models/ticket/apply_asset.py:24 users/models/user.py:703 msgid "Date expired" msgstr "失效日期" -#: authentication/models.py:92 +#: authentication/models.py:93 msgid "Asset display" msgstr "资产名称" -#: authentication/models.py:103 +#: authentication/models.py:104 msgid "Connection token" msgstr "连接令牌" -#: authentication/models.py:105 +#: authentication/models.py:106 msgid "Can view connection token secret" msgstr "可以查看连接令牌密文" -#: authentication/models.py:140 +#: authentication/models.py:141 msgid "Connection token expired at: {}" msgstr "连接令牌过期: {}" -#: authentication/models.py:145 +#: authentication/models.py:146 msgid "User not exists" msgstr "用户不存在" -#: authentication/models.py:149 +#: authentication/models.py:150 msgid "User invalid, disabled or expired" msgstr "用户无效,已禁用或已过期" -#: authentication/models.py:154 +#: authentication/models.py:155 msgid "System user not exists" msgstr "系统用户不存在" -#: authentication/models.py:160 +#: authentication/models.py:161 msgid "Asset not exists" msgstr "资产不存在" -#: authentication/models.py:164 +#: authentication/models.py:165 msgid "Asset inactive" msgstr "资产未激活" -#: authentication/models.py:171 +#: authentication/models.py:172 msgid "User has no permission to access asset or permission expired" msgstr "用户没有权限访问资产或权限已过期" -#: authentication/models.py:179 +#: authentication/models.py:180 msgid "Application not exists" msgstr "应用不存在" -#: authentication/models.py:186 +#: authentication/models.py:187 msgid "User has no permission to access application or permission expired" msgstr "用户没有权限访问应用或权限已过期" -#: authentication/models.py:246 +#: authentication/models.py:247 msgid "Verified" msgstr "已校验" -#: authentication/models.py:267 +#: authentication/models.py:268 msgid "Super connection token" msgstr "超级连接令牌" @@ -2168,7 +2174,7 @@ msgstr "资产或应用必填" #: perms/serializers/application/permission.py:20 #: perms/serializers/application/permission.py:41 #: perms/serializers/asset/permission.py:19 -#: perms/serializers/asset/permission.py:45 users/serializers/user.py:146 +#: perms/serializers/asset/permission.py:45 users/serializers/user.py:148 msgid "Is valid" msgstr "账号是否有效" @@ -2450,11 +2456,6 @@ msgstr "飞书查询用户失败" msgid "The FeiShu is already bound to another user" msgstr "该飞书已经绑定其他用户" -#: authentication/views/feishu.py:144 authentication/views/login.py:79 -#: notifications/backends/__init__.py:14 users/models/user.py:722 -msgid "FeiShu" -msgstr "飞书" - #: authentication/views/feishu.py:145 msgid "Binding FeiShu successfully" msgstr "绑定 飞书 成功" @@ -3107,8 +3108,8 @@ msgstr "组织 ({}) 的应用授权" #: perms/serializers/application/permission.py:21 #: perms/serializers/application/permission.py:40 #: perms/serializers/asset/permission.py:20 -#: perms/serializers/asset/permission.py:44 users/serializers/user.py:87 -#: users/serializers/user.py:148 +#: perms/serializers/asset/permission.py:44 users/serializers/user.py:89 +#: users/serializers/user.py:150 msgid "Is expired" msgstr "已过期" @@ -4581,10 +4582,6 @@ msgstr "微软" msgid "Official" msgstr "官方" -#: templates/resource_download.html:51 -msgid "Offline video player" -msgstr "离线录像播放器" - #: templates/resource_download.html:33 msgid "" "macOS needs to download the client to connect RDP asset, which comes with " @@ -4601,6 +4598,10 @@ msgid "" "Remote Application publisher" msgstr "Jmservisor 是在 windows 远程应用发布服务器中用来拉起远程应用的程序" +#: templates/resource_download.html:51 +msgid "Offline video player" +msgstr "离线录像播放器" + #: terminal/api/endpoint.py:26 msgid "Not found protocol query params" msgstr "" @@ -5570,7 +5571,7 @@ msgstr "强制启用" msgid "Local" msgstr "数据库" -#: users/models/user.py:673 users/serializers/user.py:147 +#: users/models/user.py:673 users/serializers/user.py:149 msgid "Is service account" msgstr "服务账号" @@ -5669,109 +5670,105 @@ msgstr "新密码不能是最近 {} 次的密码" msgid "The newly set password is inconsistent" msgstr "两次密码不一致" -#: users/serializers/profile.py:149 users/serializers/user.py:144 +#: users/serializers/profile.py:149 users/serializers/user.py:146 msgid "Is first login" msgstr "首次登录" -#: users/serializers/user.py:26 +#: users/serializers/user.py:28 msgid "System roles" msgstr "系统角色" -#: users/serializers/user.py:31 +#: users/serializers/user.py:33 msgid "Org roles" msgstr "组织角色" -#: users/serializers/user.py:33 +#: users/serializers/user.py:35 msgid "System roles display" msgstr "系统角色显示" -#: users/serializers/user.py:34 +#: users/serializers/user.py:36 msgid "Org roles display" msgstr "组织角色显示" -#: users/serializers/user.py:79 +#: users/serializers/user.py:81 #: xpack/plugins/change_auth_plan/models/base.py:35 #: xpack/plugins/change_auth_plan/serializers/base.py:27 msgid "Password strategy" msgstr "密码策略" -#: users/serializers/user.py:81 +#: users/serializers/user.py:83 msgid "MFA enabled" msgstr "MFA 已启用" -#: users/serializers/user.py:82 +#: users/serializers/user.py:84 msgid "MFA force enabled" msgstr "强制 MFA" -#: users/serializers/user.py:84 +#: users/serializers/user.py:86 msgid "MFA level display" msgstr "MFA 等级名称" -#: users/serializers/user.py:86 +#: users/serializers/user.py:88 msgid "Login blocked" msgstr "登录被阻塞" -#: users/serializers/user.py:89 +#: users/serializers/user.py:91 msgid "Can public key authentication" msgstr "能否公钥认证" -#: users/serializers/user.py:149 +#: users/serializers/user.py:151 msgid "Avatar url" msgstr "头像路径" -#: users/serializers/user.py:151 +#: users/serializers/user.py:153 msgid "Groups name" msgstr "用户组名" -#: users/serializers/user.py:152 +#: users/serializers/user.py:154 msgid "Source name" msgstr "用户来源名" -#: users/serializers/user.py:153 +#: users/serializers/user.py:155 msgid "Organization role name" msgstr "组织角色名称" -#: users/serializers/user.py:154 +#: users/serializers/user.py:156 msgid "Super role name" msgstr "超级角色名称" -#: users/serializers/user.py:155 +#: users/serializers/user.py:157 msgid "Total role name" msgstr "汇总角色名称" -#: users/serializers/user.py:157 +#: users/serializers/user.py:159 msgid "Is wecom bound" msgstr "是否绑定了企业微信" -#: users/serializers/user.py:158 +#: users/serializers/user.py:160 msgid "Is dingtalk bound" msgstr "是否绑定了钉钉" -#: users/serializers/user.py:159 +#: users/serializers/user.py:161 msgid "Is feishu bound" msgstr "是否绑定了飞书" -#: users/serializers/user.py:160 +#: users/serializers/user.py:162 msgid "Is OTP bound" msgstr "是否绑定了虚拟 MFA" -#: users/serializers/user.py:162 +#: users/serializers/user.py:164 msgid "System role name" msgstr "系统角色名称" -#: users/serializers/user.py:202 -msgid "User cannot self-update fields: {}" -msgstr "用户不能更新自己的字段: {}" - -#: users/serializers/user.py:259 +#: users/serializers/user.py:263 msgid "Select users" msgstr "选择用户" -#: users/serializers/user.py:260 +#: users/serializers/user.py:264 msgid "For security, only list several users" msgstr "为了安全,仅列出几个用户" -#: users/serializers/user.py:295 +#: users/serializers/user.py:299 msgid "name not unique" msgstr "名称重复" @@ -6307,11 +6304,11 @@ msgstr "云账号" msgid "Test cloud account" msgstr "测试云账号" -#: xpack/plugins/cloud/models.py:85 xpack/plugins/cloud/serializers/task.py:66 +#: xpack/plugins/cloud/models.py:85 xpack/plugins/cloud/serializers/task.py:67 msgid "Account" msgstr "账号" -#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:37 +#: xpack/plugins/cloud/models.py:88 xpack/plugins/cloud/serializers/task.py:38 msgid "Regions" msgstr "地域" @@ -6319,19 +6316,19 @@ msgstr "地域" msgid "Hostname strategy" msgstr "主机名策略" -#: xpack/plugins/cloud/models.py:100 xpack/plugins/cloud/serializers/task.py:67 +#: xpack/plugins/cloud/models.py:100 xpack/plugins/cloud/serializers/task.py:68 msgid "Unix admin user" msgstr "Unix 管理员" -#: xpack/plugins/cloud/models.py:104 xpack/plugins/cloud/serializers/task.py:68 +#: xpack/plugins/cloud/models.py:104 xpack/plugins/cloud/serializers/task.py:69 msgid "Windows admin user" msgstr "Windows 管理员" -#: xpack/plugins/cloud/models.py:110 xpack/plugins/cloud/serializers/task.py:45 +#: xpack/plugins/cloud/models.py:110 xpack/plugins/cloud/serializers/task.py:46 msgid "IP network segment group" msgstr "IP网段组" -#: xpack/plugins/cloud/models.py:113 xpack/plugins/cloud/serializers/task.py:71 +#: xpack/plugins/cloud/models.py:113 xpack/plugins/cloud/serializers/task.py:72 msgid "Always update" msgstr "总是更新" @@ -6605,31 +6602,35 @@ msgstr "JSON 格式的文件" #: xpack/plugins/cloud/serializers/task.py:29 msgid "" -"The IP address that is first matched to will be used as the IP of the " -"created asset.
The default * indicates a random match.
Format for " -"comma-delimited string, Such as: 192.168.1.0/24, 10.1.1.1-10.1.1.20" +"Only instances matching the IP range will be synced.
If the instance " +"contains multiple IP addresses, the first IP address that matches will be " +"used as the IP for the created asset.
The default value of * means sync " +"all instances and randomly match IP addresses.
Format for comma-" +"delimited string, Such as: 192.168.1.0/24, 10.1.1.1-10.1.1.20" msgstr "" -"第一个匹配到的 IP 地址将被用作创建的资产的 IP。
默认值 * 表示随机匹配。" -"
格式为以逗号分隔的字符串,例如:192.168.1.0/24,10.1.1.1-10.1.1.20" +"只有匹配到 IP 段的实例会被同步。
" +"如果实例包含多个 IP 地址,那么第一个匹配到的 IP 地址将被用作创建的资产的 IP。
" +"默认值 * 表示同步所有实例和随机匹配 IP 地址。
" +"格式为以逗号分隔的字符串,例如:192.168.1.0/24,10.1.1.1-10.1.1.20" -#: xpack/plugins/cloud/serializers/task.py:35 +#: xpack/plugins/cloud/serializers/task.py:36 msgid "History count" msgstr "执行次数" -#: xpack/plugins/cloud/serializers/task.py:36 +#: xpack/plugins/cloud/serializers/task.py:37 msgid "Instance count" msgstr "实例个数" -#: xpack/plugins/cloud/serializers/task.py:65 +#: xpack/plugins/cloud/serializers/task.py:66 msgid "Linux admin user" msgstr "Linux 管理员" -#: xpack/plugins/cloud/serializers/task.py:70 +#: xpack/plugins/cloud/serializers/task.py:71 #: xpack/plugins/gathered_user/serializers.py:20 msgid "Periodic display" msgstr "定时执行" -#: xpack/plugins/cloud/utils.py:68 +#: xpack/plugins/cloud/utils.py:69 msgid "Account unavailable" msgstr "账号无效" @@ -6716,3 +6717,6 @@ msgstr "旗舰版" #: xpack/plugins/license/models.py:77 msgid "Community edition" msgstr "社区版" + +#~ msgid "User cannot self-update fields: {}" +#~ msgstr "用户不能更新自己的字段: {}" From 191d37dd56567b0c25f31779767eecede86e3ae4 Mon Sep 17 00:00:00 2001 From: halo Date: Wed, 13 Jul 2022 09:32:17 +0800 Subject: [PATCH 11/13] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81session?= =?UTF-8?q?=E5=AD=98=E5=82=A8=E6=96=B9=E5=BC=8F=E5=8F=AF=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E9=80=89cache=E6=88=96db?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/jumpserver/conf.py | 1 + apps/jumpserver/settings/base.py | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index c3a0a0210..551076192 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -383,6 +383,7 @@ class Config(dict): 'SESSION_COOKIE_SECURE': False, 'CSRF_COOKIE_SECURE': False, 'REFERER_CHECK_ENABLED': False, + 'SESSION_ENGINE': 'cache', 'SESSION_SAVE_EVERY_REQUEST': True, 'SESSION_EXPIRE_AT_BROWSER_CLOSE_FORCE': False, 'SERVER_REPLAY_STORAGE': {}, diff --git a/apps/jumpserver/settings/base.py b/apps/jumpserver/settings/base.py index 9b4cfb668..519623ac9 100644 --- a/apps/jumpserver/settings/base.py +++ b/apps/jumpserver/settings/base.py @@ -3,6 +3,7 @@ import platform if platform.system() == 'Darwin' and platform.machine() == 'arm64': import pymysql + pymysql.version_info = (1, 4, 2, "final", 0) pymysql.install_as_MySQLdb() @@ -109,8 +110,6 @@ MIDDLEWARE = [ 'simple_history.middleware.HistoryRequestMiddleware', ] - - ROOT_URLCONF = 'jumpserver.urls' TEMPLATES = [ @@ -161,7 +160,7 @@ SESSION_EXPIRE_AT_BROWSER_CLOSE = True # 自定义的配置,SESSION_EXPIRE_AT_BROWSER_CLOSE 始终为 True, 下面这个来控制是否强制关闭后过期 cookie SESSION_EXPIRE_AT_BROWSER_CLOSE_FORCE = CONFIG.SESSION_EXPIRE_AT_BROWSER_CLOSE_FORCE SESSION_SAVE_EVERY_REQUEST = CONFIG.SESSION_SAVE_EVERY_REQUEST -SESSION_ENGINE = "django.contrib.sessions.backends.cache" +SESSION_ENGINE = "django.contrib.sessions.backends.{}".format(CONFIG.SESSION_ENGINE) MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage' # Database From e724cdf53d9831bbaccecfc8aa8a91286c2b6851 Mon Sep 17 00:00:00 2001 From: feng626 <1304903146@qq.com> Date: Wed, 13 Jul 2022 10:43:20 +0800 Subject: [PATCH 12/13] fix: OrgManager add bulk_create method --- apps/orgs/mixins/models.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/orgs/mixins/models.py b/apps/orgs/mixins/models.py index d3dc4529d..bb98f7a98 100644 --- a/apps/orgs/mixins/models.py +++ b/apps/orgs/mixins/models.py @@ -41,6 +41,14 @@ class OrgManager(models.Manager): return self + def bulk_create(self, objs, batch_size=None, ignore_conflicts=False): + org = get_current_org() + org_id = org.id + for obj in objs: + obj.org_id = org_id + return super().bulk_create(objs, batch_size, ignore_conflicts) + + class OrgModelMixin(models.Model): org_id = models.CharField(max_length=36, blank=True, default='', verbose_name=_("Organization"), db_index=True) From 5155b3c18494b8a08b9cda4d6d5d0c0725364c4c Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 13 Jul 2022 11:00:12 +0800 Subject: [PATCH 13/13] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dbluk=5Fcreate=20?= =?UTF-8?q?root=20=E7=BB=84=E7=BB=87=E4=B8=8B=E5=88=A4=E6=96=AD=20(#8581)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng626 <1304903146@qq.com> --- apps/orgs/mixins/models.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/orgs/mixins/models.py b/apps/orgs/mixins/models.py index bb98f7a98..3406271b6 100644 --- a/apps/orgs/mixins/models.py +++ b/apps/orgs/mixins/models.py @@ -43,15 +43,19 @@ class OrgManager(models.Manager): def bulk_create(self, objs, batch_size=None, ignore_conflicts=False): org = get_current_org() - org_id = org.id for obj in objs: - obj.org_id = org_id + if org.is_root(): + if not self.org_id: + raise ValidationError('Please save in a organization') + else: + obj.org_id = org.id return super().bulk_create(objs, batch_size, ignore_conflicts) class OrgModelMixin(models.Model): - org_id = models.CharField(max_length=36, blank=True, default='', - verbose_name=_("Organization"), db_index=True) + org_id = models.CharField( + max_length=36, blank=True, default='', verbose_name=_("Organization"), db_index=True + ) objects = OrgManager() sep = '@'