Merge pull request #8119 from jumpserver/dev

v2.21.0-rc6
pull/8133/head
Jiangjie.Bai 2022-04-20 20:25:43 +08:00 committed by GitHub
commit e83d676712
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 281 additions and 198 deletions

View File

@ -156,10 +156,7 @@ class AccountBackupHandler:
logger.info('步骤完成: 用时 {}s'.format(timedelta)) logger.info('步骤完成: 用时 {}s'.format(timedelta))
return files return files
def send_backup_mail(self, files): def send_backup_mail(self, files, recipients):
recipients = self.execution.plan_snapshot.get('recipients')
if not recipients:
return
if not files: if not files:
return return
recipients = User.objects.filter(id__in=list(recipients)) recipients = User.objects.filter(id__in=list(recipients))
@ -198,8 +195,16 @@ class AccountBackupHandler:
is_success = False is_success = False
error = '-' error = '-'
try: try:
recipients = self.execution.plan_snapshot.get('recipients')
if not recipients:
logger.info(
'\n'
'\033[32m>>> 该备份任务未分配收件人\033[0m'
''
)
else:
files = self.create_excel() files = self.create_excel()
self.send_backup_mail(files) self.send_backup_mail(files, recipients)
except Exception as e: except Exception as e:
self.is_frozen = True self.is_frozen = True
logger.error('任务执行被异常中断') logger.error('任务执行被异常中断')

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:4e6962699271d0f5402223321e65211f1c7ad0b7a9b43524f3a0fac7ea2541d9 oid sha256:f2c88ade4bfae213bdcdafad656af73f764e3b1b3f2b0c59aa39626e967730ca
size 125623 size 125911

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-04-19 15:57+0800\n" "POT-Creation-Date: 2022-04-20 16:35+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -29,7 +29,7 @@ msgstr "Acls"
#: assets/models/group.py:20 assets/models/label.py:18 ops/mixin.py:24 #: assets/models/group.py:20 assets/models/label.py:18 ops/mixin.py:24
#: orgs/models.py:65 perms/models/base.py:83 rbac/models/role.py:29 #: orgs/models.py:65 perms/models/base.py:83 rbac/models/role.py:29
#: settings/models.py:29 settings/serializers/sms.py:6 #: settings/models.py:29 settings/serializers/sms.py:6
#: terminal/models/endpoint.py:10 terminal/models/endpoint.py:55 #: terminal/models/endpoint.py:10 terminal/models/endpoint.py:58
#: terminal/models/storage.py:23 terminal/models/task.py:16 #: terminal/models/storage.py:23 terminal/models/task.py:16
#: terminal/models/terminal.py:100 users/forms/profile.py:32 #: terminal/models/terminal.py:100 users/forms/profile.py:32
#: users/models/group.py:15 users/models/user.py:661 #: users/models/group.py:15 users/models/user.py:661
@ -38,12 +38,12 @@ msgid "Name"
msgstr "名前" msgstr "名前"
#: acls/models/base.py:27 assets/models/cmd_filter.py:84 #: acls/models/base.py:27 assets/models/cmd_filter.py:84
#: assets/models/user.py:247 terminal/models/endpoint.py:58 #: assets/models/user.py:247 terminal/models/endpoint.py:61
msgid "Priority" msgid "Priority"
msgstr "優先順位" msgstr "優先順位"
#: acls/models/base.py:28 assets/models/cmd_filter.py:84 #: acls/models/base.py:28 assets/models/cmd_filter.py:84
#: assets/models/user.py:247 terminal/models/endpoint.py:59 #: assets/models/user.py:247 terminal/models/endpoint.py:62
msgid "1-100, the lower the value will be match first" msgid "1-100, the lower the value will be match first"
msgstr "1-100、低い値は最初に一致します" msgstr "1-100、低い値は最初に一致します"
@ -61,7 +61,7 @@ msgstr "アクティブ"
#: assets/models/domain.py:64 assets/models/group.py:23 #: assets/models/domain.py:64 assets/models/group.py:23
#: assets/models/label.py:23 ops/models/adhoc.py:38 orgs/models.py:68 #: assets/models/label.py:23 ops/models/adhoc.py:38 orgs/models.py:68
#: perms/models/base.py:93 rbac/models/role.py:37 settings/models.py:34 #: perms/models/base.py:93 rbac/models/role.py:37 settings/models.py:34
#: terminal/models/endpoint.py:20 terminal/models/endpoint.py:65 #: terminal/models/endpoint.py:20 terminal/models/endpoint.py:68
#: terminal/models/storage.py:26 terminal/models/terminal.py:114 #: terminal/models/storage.py:26 terminal/models/terminal.py:114
#: tickets/models/comment.py:24 tickets/models/ticket.py:154 #: tickets/models/comment.py:24 tickets/models/ticket.py:154
#: users/models/group.py:16 users/models/user.py:698 #: users/models/group.py:16 users/models/user.py:698
@ -1360,7 +1360,7 @@ msgstr "監査"
#: audits/models.py:27 audits/models.py:57 #: audits/models.py:27 audits/models.py:57
#: authentication/templates/authentication/_access_key_modal.html:65 #: authentication/templates/authentication/_access_key_modal.html:65
#: rbac/tree.py:166 #: rbac/tree.py:168
msgid "Delete" msgid "Delete"
msgstr "削除" msgstr "削除"
@ -1413,11 +1413,11 @@ msgstr "ファイル転送ログ"
#: audits/models.py:55 #: audits/models.py:55
#: authentication/templates/authentication/_access_key_modal.html:22 #: authentication/templates/authentication/_access_key_modal.html:22
#: rbac/tree.py:163 #: rbac/tree.py:165
msgid "Create" msgid "Create"
msgstr "作成" msgstr "作成"
#: audits/models.py:56 rbac/tree.py:165 templates/_csv_import_export.html:18 #: audits/models.py:56 rbac/tree.py:167 templates/_csv_import_export.html:18
#: templates/_csv_update_modal.html:6 #: templates/_csv_update_modal.html:6
msgid "Update" msgid "Update"
msgstr "更新" msgstr "更新"
@ -2886,15 +2886,22 @@ msgstr "タスクログ"
msgid "Update task content: {}" msgid "Update task content: {}"
msgstr "タスク内容の更新: {}" msgstr "タスク内容の更新: {}"
#: orgs/api.py:68 #: orgs/api.py:69
msgid "The current organization ({}) cannot be deleted" msgid "The current organization ({}) cannot be deleted"
msgstr "現在の組織 ({}) は削除できません" msgstr "現在の組織 ({}) は削除できません"
#: orgs/api.py:76 #: orgs/api.py:74
msgid ""
"LDAP synchronization is set to the current organization. Please switch to "
"another organization before deleting"
msgstr ""
"LDAP 同期は現在の組織に設定されます。削除する前に別の組織に切り替えてください"
#: orgs/api.py:83
msgid "The organization have resource ({}) cannot be deleted" msgid "The organization have resource ({}) cannot be deleted"
msgstr "組織のリソース ({}) は削除できません" msgstr "組織のリソース ({}) は削除できません"
#: orgs/apps.py:7 rbac/tree.py:112 #: orgs/apps.py:7 rbac/tree.py:114
msgid "App organizations" msgid "App organizations"
msgstr "アプリ組織" msgstr "アプリ組織"
@ -3202,18 +3209,18 @@ msgstr "組織の役割"
msgid "Role binding" msgid "Role binding"
msgstr "ロールバインディング" msgstr "ロールバインディング"
#: rbac/models/rolebinding.py:150 #: rbac/models/rolebinding.py:151
msgid "" msgid ""
"User last role in org, can not be delete, you can remove user from org " "User last role in org, can not be delete, you can remove user from org "
"instead" "instead"
msgstr "" msgstr ""
"ユーザーの最後のロールは削除できません。ユーザーを組織から削除できます。" "ユーザーの最後のロールは削除できません。ユーザーを組織から削除できます。"
#: rbac/models/rolebinding.py:157 #: rbac/models/rolebinding.py:158
msgid "Organization role binding" msgid "Organization role binding"
msgstr "組織の役割バインディング" msgstr "組織の役割バインディング"
#: rbac/models/rolebinding.py:172 #: rbac/models/rolebinding.py:173
msgid "System role binding" msgid "System role binding"
msgstr "システムロールバインディング" msgstr "システムロールバインディング"
@ -3301,27 +3308,27 @@ msgstr "私の資産"
msgid "My apps" msgid "My apps"
msgstr "マイアプリ" msgstr "マイアプリ"
#: rbac/tree.py:113 #: rbac/tree.py:115
msgid "Ticket comment" msgid "Ticket comment"
msgstr "チケットコメント" msgstr "チケットコメント"
#: rbac/tree.py:114 tickets/models/ticket.py:163 #: rbac/tree.py:116 tickets/models/ticket.py:163
msgid "Ticket" msgid "Ticket"
msgstr "チケット" msgstr "チケット"
#: rbac/tree.py:115 #: rbac/tree.py:117
msgid "Common setting" msgid "Common setting"
msgstr "共通設定" msgstr "共通設定"
#: rbac/tree.py:116 #: rbac/tree.py:118
msgid "View permission tree" msgid "View permission tree"
msgstr "権限ツリーの表示" msgstr "権限ツリーの表示"
#: rbac/tree.py:117 #: rbac/tree.py:119
msgid "Execute batch command" msgid "Execute batch command"
msgstr "バッチ実行コマンド" msgstr "バッチ実行コマンド"
#: rbac/tree.py:164 #: rbac/tree.py:166
msgid "View" msgid "View"
msgstr "表示" msgstr "表示"
@ -4228,8 +4235,8 @@ msgid ""
"Tips: The login success message varies with devices. if you cannot log in to " "Tips: The login success message varies with devices. if you cannot log in to "
"the device through Telnet, set this parameter" "the device through Telnet, set this parameter"
msgstr "" msgstr ""
"ヒント: ログイン成功メッセージはデバイスによって異なります。Telnet経由でデバイスにロ" "ヒント: ログイン成功メッセージはデバイスによって異なります。Telnet経由でデバ"
"グインできない場合は、このパラメーターを設定します。" "イスにログインできない場合は、このパラメーターを設定します。"
#: settings/serializers/terminal.py:36 #: settings/serializers/terminal.py:36
msgid "Enable database proxy" msgid "Enable database proxy"
@ -4243,104 +4250,104 @@ msgstr "XRDPの有効化"
msgid "Enable KoKo SSH" msgid "Enable KoKo SSH"
msgstr "KoKo SSHの有効化" msgstr "KoKo SSHの有効化"
#: settings/utils/ldap.py:417 #: settings/utils/ldap.py:419
msgid "ldap:// or ldaps:// protocol is used." msgid "ldap:// or ldaps:// protocol is used."
msgstr "ldap:// または ldaps:// プロトコルが使用されます。" msgstr "ldap:// または ldaps:// プロトコルが使用されます。"
#: settings/utils/ldap.py:428 #: settings/utils/ldap.py:430
msgid "Host or port is disconnected: {}" msgid "Host or port is disconnected: {}"
msgstr "ホストまたはポートが切断されました: {}" msgstr "ホストまたはポートが切断されました: {}"
#: settings/utils/ldap.py:430 #: settings/utils/ldap.py:432
msgid "The port is not the port of the LDAP service: {}" msgid "The port is not the port of the LDAP service: {}"
msgstr "ポートはLDAPサービスのポートではありません: {}" msgstr "ポートはLDAPサービスのポートではありません: {}"
#: settings/utils/ldap.py:432 #: settings/utils/ldap.py:434
msgid "Please add certificate: {}" msgid "Please add certificate: {}"
msgstr "証明書を追加してください: {}" msgstr "証明書を追加してください: {}"
#: settings/utils/ldap.py:436 settings/utils/ldap.py:463 #: settings/utils/ldap.py:438 settings/utils/ldap.py:465
#: settings/utils/ldap.py:493 settings/utils/ldap.py:521 #: settings/utils/ldap.py:495 settings/utils/ldap.py:523
msgid "Unknown error: {}" msgid "Unknown error: {}"
msgstr "不明なエラー: {}" msgstr "不明なエラー: {}"
#: settings/utils/ldap.py:450 #: settings/utils/ldap.py:452
msgid "Bind DN or Password incorrect" msgid "Bind DN or Password incorrect"
msgstr "DNまたはパスワードのバインドが正しくありません" msgstr "DNまたはパスワードのバインドが正しくありません"
#: settings/utils/ldap.py:457 #: settings/utils/ldap.py:459
msgid "Please enter Bind DN: {}" msgid "Please enter Bind DN: {}"
msgstr "バインドDN: {} を入力してください" msgstr "バインドDN: {} を入力してください"
#: settings/utils/ldap.py:459 #: settings/utils/ldap.py:461
msgid "Please enter Password: {}" msgid "Please enter Password: {}"
msgstr "パスワードを入力してください: {}" msgstr "パスワードを入力してください: {}"
#: settings/utils/ldap.py:461 #: settings/utils/ldap.py:463
msgid "Please enter correct Bind DN and Password: {}" msgid "Please enter correct Bind DN and Password: {}"
msgstr "正しいバインドDNとパスワードを入力してください: {}" msgstr "正しいバインドDNとパスワードを入力してください: {}"
#: settings/utils/ldap.py:479 #: settings/utils/ldap.py:481
msgid "Invalid User OU or User search filter: {}" msgid "Invalid User OU or User search filter: {}"
msgstr "無効なユーザー OU またはユーザー検索フィルター: {}" msgstr "無効なユーザー OU またはユーザー検索フィルター: {}"
#: settings/utils/ldap.py:510 #: settings/utils/ldap.py:512
msgid "LDAP User attr map not include: {}" msgid "LDAP User attr map not include: {}"
msgstr "LDAP ユーザーattrマップは含まれません: {}" msgstr "LDAP ユーザーattrマップは含まれません: {}"
#: settings/utils/ldap.py:517 #: settings/utils/ldap.py:519
msgid "LDAP User attr map is not dict" msgid "LDAP User attr map is not dict"
msgstr "LDAPユーザーattrマップはdictではありません" msgstr "LDAPユーザーattrマップはdictではありません"
#: settings/utils/ldap.py:536 #: settings/utils/ldap.py:538
msgid "LDAP authentication is not enabled" msgid "LDAP authentication is not enabled"
msgstr "LDAP 認証が有効になっていない" msgstr "LDAP 認証が有効になっていない"
#: settings/utils/ldap.py:554 #: settings/utils/ldap.py:556
msgid "Error (Invalid LDAP server): {}" msgid "Error (Invalid LDAP server): {}"
msgstr "エラー (LDAPサーバーが無効): {}" msgstr "エラー (LDAPサーバーが無効): {}"
#: settings/utils/ldap.py:556 #: settings/utils/ldap.py:558
msgid "Error (Invalid Bind DN): {}" msgid "Error (Invalid Bind DN): {}"
msgstr "エラー (DNのバインドが無効): {}" msgstr "エラー (DNのバインドが無効): {}"
#: settings/utils/ldap.py:558 #: settings/utils/ldap.py:560
msgid "Error (Invalid LDAP User attr map): {}" msgid "Error (Invalid LDAP User attr map): {}"
msgstr "エラー (LDAPユーザーattrマップが無効): {}" msgstr "エラー (LDAPユーザーattrマップが無効): {}"
#: settings/utils/ldap.py:560 #: settings/utils/ldap.py:562
msgid "Error (Invalid User OU or User search filter): {}" msgid "Error (Invalid User OU or User search filter): {}"
msgstr "エラー (ユーザーOUまたはユーザー検索フィルターが無効): {}" msgstr "エラー (ユーザーOUまたはユーザー検索フィルターが無効): {}"
#: settings/utils/ldap.py:562 #: settings/utils/ldap.py:564
msgid "Error (Not enabled LDAP authentication): {}" msgid "Error (Not enabled LDAP authentication): {}"
msgstr "エラー (LDAP認証が有効化されていません): {}" msgstr "エラー (LDAP認証が有効化されていません): {}"
#: settings/utils/ldap.py:564 #: settings/utils/ldap.py:566
msgid "Error (Unknown): {}" msgid "Error (Unknown): {}"
msgstr "エラー (不明): {}" msgstr "エラー (不明): {}"
#: settings/utils/ldap.py:567 #: settings/utils/ldap.py:569
msgid "Succeed: Match {} s user" msgid "Succeed: Match {} s user"
msgstr "成功: {} 人のユーザーに一致" msgstr "成功: {} 人のユーザーに一致"
#: settings/utils/ldap.py:600 #: settings/utils/ldap.py:602
msgid "Authentication failed (configuration incorrect): {}" msgid "Authentication failed (configuration incorrect): {}"
msgstr "認証に失敗しました (設定が正しくありません): {}" msgstr "認証に失敗しました (設定が正しくありません): {}"
#: settings/utils/ldap.py:602 #: settings/utils/ldap.py:604
msgid "Authentication failed (before login check failed): {}" msgid "Authentication failed (before login check failed): {}"
msgstr "認証に失敗しました (ログインチェックが失敗する前): {}" msgstr "認証に失敗しました (ログインチェックが失敗する前): {}"
#: settings/utils/ldap.py:604 #: settings/utils/ldap.py:606
msgid "Authentication failed (username or password incorrect): {}" msgid "Authentication failed (username or password incorrect): {}"
msgstr "認証に失敗しました (ユーザー名またはパスワードが正しくありません): {}" msgstr "認証に失敗しました (ユーザー名またはパスワードが正しくありません): {}"
#: settings/utils/ldap.py:606 #: settings/utils/ldap.py:608
msgid "Authentication failed (Unknown): {}" msgid "Authentication failed (Unknown): {}"
msgstr "認証に失敗しました (不明): {}" msgstr "認証に失敗しました (不明): {}"
#: settings/utils/ldap.py:609 #: settings/utils/ldap.py:611
msgid "Authentication success: {}" msgid "Authentication success: {}"
msgstr "認証成功: {}" msgstr "認証成功: {}"
@ -4725,18 +4732,18 @@ msgstr "MariaDB ポート"
msgid "PostgreSQL Port" msgid "PostgreSQL Port"
msgstr "PostgreSQL ポート" msgstr "PostgreSQL ポート"
#: terminal/models/endpoint.py:25 terminal/models/endpoint.py:63 #: terminal/models/endpoint.py:25 terminal/models/endpoint.py:66
#: terminal/serializers/endpoint.py:40 terminal/serializers/storage.py:37 #: terminal/serializers/endpoint.py:40 terminal/serializers/storage.py:37
#: terminal/serializers/storage.py:49 terminal/serializers/storage.py:79 #: terminal/serializers/storage.py:49 terminal/serializers/storage.py:79
#: terminal/serializers/storage.py:89 terminal/serializers/storage.py:97 #: terminal/serializers/storage.py:89 terminal/serializers/storage.py:97
msgid "Endpoint" msgid "Endpoint"
msgstr "エンドポイント" msgstr "エンドポイント"
#: terminal/models/endpoint.py:56 #: terminal/models/endpoint.py:59
msgid "IP group" msgid "IP group"
msgstr "IP グループ" msgstr "IP グループ"
#: terminal/models/endpoint.py:68 #: terminal/models/endpoint.py:71
msgid "Endpoint rule" msgid "Endpoint rule"
msgstr "エンドポイントルール" msgstr "エンドポイントルール"

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:3462a9a3eef8f372bf341f2066a33d85e1f01aca5a8fe506528a1cd0a37e98b4 oid sha256:c75e0a1f2a047dac1374916c630bc0e8ef5ad5eea7518ffc21e93f747fc1235e
size 103951 size 104165

View File

@ -7,7 +7,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: JumpServer 0.3.3\n" "Project-Id-Version: JumpServer 0.3.3\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-04-19 15:57+0800\n" "POT-Creation-Date: 2022-04-20 16:35+0800\n"
"PO-Revision-Date: 2021-05-20 10:54+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n"
"Last-Translator: ibuler <ibuler@qq.com>\n" "Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: JumpServer team<ibuler@qq.com>\n" "Language-Team: JumpServer team<ibuler@qq.com>\n"
@ -28,7 +28,7 @@ msgstr "访问控制"
#: assets/models/group.py:20 assets/models/label.py:18 ops/mixin.py:24 #: assets/models/group.py:20 assets/models/label.py:18 ops/mixin.py:24
#: orgs/models.py:65 perms/models/base.py:83 rbac/models/role.py:29 #: orgs/models.py:65 perms/models/base.py:83 rbac/models/role.py:29
#: settings/models.py:29 settings/serializers/sms.py:6 #: settings/models.py:29 settings/serializers/sms.py:6
#: terminal/models/endpoint.py:10 terminal/models/endpoint.py:55 #: terminal/models/endpoint.py:10 terminal/models/endpoint.py:58
#: terminal/models/storage.py:23 terminal/models/task.py:16 #: terminal/models/storage.py:23 terminal/models/task.py:16
#: terminal/models/terminal.py:100 users/forms/profile.py:32 #: terminal/models/terminal.py:100 users/forms/profile.py:32
#: users/models/group.py:15 users/models/user.py:661 #: users/models/group.py:15 users/models/user.py:661
@ -37,12 +37,12 @@ msgid "Name"
msgstr "名称" msgstr "名称"
#: acls/models/base.py:27 assets/models/cmd_filter.py:84 #: acls/models/base.py:27 assets/models/cmd_filter.py:84
#: assets/models/user.py:247 terminal/models/endpoint.py:58 #: assets/models/user.py:247 terminal/models/endpoint.py:61
msgid "Priority" msgid "Priority"
msgstr "优先级" msgstr "优先级"
#: acls/models/base.py:28 assets/models/cmd_filter.py:84 #: acls/models/base.py:28 assets/models/cmd_filter.py:84
#: assets/models/user.py:247 terminal/models/endpoint.py:59 #: assets/models/user.py:247 terminal/models/endpoint.py:62
msgid "1-100, the lower the value will be match first" msgid "1-100, the lower the value will be match first"
msgstr "优先级可选范围为 1-100 (数值越小越优先)" msgstr "优先级可选范围为 1-100 (数值越小越优先)"
@ -60,7 +60,7 @@ msgstr "激活中"
#: assets/models/domain.py:64 assets/models/group.py:23 #: assets/models/domain.py:64 assets/models/group.py:23
#: assets/models/label.py:23 ops/models/adhoc.py:38 orgs/models.py:68 #: assets/models/label.py:23 ops/models/adhoc.py:38 orgs/models.py:68
#: perms/models/base.py:93 rbac/models/role.py:37 settings/models.py:34 #: perms/models/base.py:93 rbac/models/role.py:37 settings/models.py:34
#: terminal/models/endpoint.py:20 terminal/models/endpoint.py:65 #: terminal/models/endpoint.py:20 terminal/models/endpoint.py:68
#: terminal/models/storage.py:26 terminal/models/terminal.py:114 #: terminal/models/storage.py:26 terminal/models/terminal.py:114
#: tickets/models/comment.py:24 tickets/models/ticket.py:154 #: tickets/models/comment.py:24 tickets/models/ticket.py:154
#: users/models/group.py:16 users/models/user.py:698 #: users/models/group.py:16 users/models/user.py:698
@ -1348,7 +1348,7 @@ msgstr "日志审计"
#: audits/models.py:27 audits/models.py:57 #: audits/models.py:27 audits/models.py:57
#: authentication/templates/authentication/_access_key_modal.html:65 #: authentication/templates/authentication/_access_key_modal.html:65
#: rbac/tree.py:166 #: rbac/tree.py:168
msgid "Delete" msgid "Delete"
msgstr "删除" msgstr "删除"
@ -1401,11 +1401,11 @@ msgstr "文件管理"
#: audits/models.py:55 #: audits/models.py:55
#: authentication/templates/authentication/_access_key_modal.html:22 #: authentication/templates/authentication/_access_key_modal.html:22
#: rbac/tree.py:163 #: rbac/tree.py:165
msgid "Create" msgid "Create"
msgstr "创建" msgstr "创建"
#: audits/models.py:56 rbac/tree.py:165 templates/_csv_import_export.html:18 #: audits/models.py:56 rbac/tree.py:167 templates/_csv_import_export.html:18
#: templates/_csv_update_modal.html:6 #: templates/_csv_update_modal.html:6
msgid "Update" msgid "Update"
msgstr "更新" msgstr "更新"
@ -2851,15 +2851,21 @@ msgstr "任务列表"
msgid "Update task content: {}" msgid "Update task content: {}"
msgstr "更新任务内容: {}" msgstr "更新任务内容: {}"
#: orgs/api.py:68 #: orgs/api.py:69
msgid "The current organization ({}) cannot be deleted" msgid "The current organization ({}) cannot be deleted"
msgstr "当前组织 ({}) 不能被删除" msgstr "当前组织 ({}) 不能被删除"
#: orgs/api.py:76 #: orgs/api.py:74
msgid ""
"LDAP synchronization is set to the current organization. Please switch to "
"another organization before deleting"
msgstr "LDAP 同步设置组织为当前组织,请切换其他组织后再进行删除操作"
#: orgs/api.py:83
msgid "The organization have resource ({}) cannot be deleted" msgid "The organization have resource ({}) cannot be deleted"
msgstr "组织存在资源 ({}) 不能被删除" msgstr "组织存在资源 ({}) 不能被删除"
#: orgs/apps.py:7 rbac/tree.py:112 #: orgs/apps.py:7 rbac/tree.py:114
msgid "App organizations" msgid "App organizations"
msgstr "组织管理" msgstr "组织管理"
@ -3165,17 +3171,17 @@ msgstr "组织角色"
msgid "Role binding" msgid "Role binding"
msgstr "角色绑定" msgstr "角色绑定"
#: rbac/models/rolebinding.py:150 #: rbac/models/rolebinding.py:151
msgid "" msgid ""
"User last role in org, can not be delete, you can remove user from org " "User last role in org, can not be delete, you can remove user from org "
"instead" "instead"
msgstr "用户最后一个角色,不能删除,你可以将用户从组织移除" msgstr "用户最后一个角色,不能删除,你可以将用户从组织移除"
#: rbac/models/rolebinding.py:157 #: rbac/models/rolebinding.py:158
msgid "Organization role binding" msgid "Organization role binding"
msgstr "组织角色绑定" msgstr "组织角色绑定"
#: rbac/models/rolebinding.py:172 #: rbac/models/rolebinding.py:173
msgid "System role binding" msgid "System role binding"
msgstr "系统角色绑定" msgstr "系统角色绑定"
@ -3263,27 +3269,27 @@ msgstr "我的资产"
msgid "My apps" msgid "My apps"
msgstr "我的应用" msgstr "我的应用"
#: rbac/tree.py:113 #: rbac/tree.py:115
msgid "Ticket comment" msgid "Ticket comment"
msgstr "工单评论" msgstr "工单评论"
#: rbac/tree.py:114 tickets/models/ticket.py:163 #: rbac/tree.py:116 tickets/models/ticket.py:163
msgid "Ticket" msgid "Ticket"
msgstr "工单管理" msgstr "工单管理"
#: rbac/tree.py:115 #: rbac/tree.py:117
msgid "Common setting" msgid "Common setting"
msgstr "一般设置" msgstr "一般设置"
#: rbac/tree.py:116 #: rbac/tree.py:118
msgid "View permission tree" msgid "View permission tree"
msgstr "查看授权树" msgstr "查看授权树"
#: rbac/tree.py:117 #: rbac/tree.py:119
msgid "Execute batch command" msgid "Execute batch command"
msgstr "执行批量命令" msgstr "执行批量命令"
#: rbac/tree.py:164 #: rbac/tree.py:166
msgid "View" msgid "View"
msgstr "查看" msgstr "查看"
@ -4167,7 +4173,8 @@ msgstr "Telnet 成功正则表达式"
msgid "" msgid ""
"Tips: The login success message varies with devices. if you cannot log in to " "Tips: The login success message varies with devices. if you cannot log in to "
"the device through Telnet, set this parameter" "the device through Telnet, set this parameter"
msgstr "提示: 不同设备登录成功提示不一样,所以如果 telnet 不能正常登录,可以这里设置" msgstr ""
"提示: 不同设备登录成功提示不一样,所以如果 telnet 不能正常登录,可以这里设置"
#: settings/serializers/terminal.py:36 #: settings/serializers/terminal.py:36
msgid "Enable database proxy" msgid "Enable database proxy"
@ -4181,104 +4188,104 @@ msgstr "启用 XRDP 服务"
msgid "Enable KoKo SSH" msgid "Enable KoKo SSH"
msgstr "启用 KoKo SSH" msgstr "启用 KoKo SSH"
#: settings/utils/ldap.py:417 #: settings/utils/ldap.py:419
msgid "ldap:// or ldaps:// protocol is used." msgid "ldap:// or ldaps:// protocol is used."
msgstr "使用 ldap:// 或 ldaps:// 协议" msgstr "使用 ldap:// 或 ldaps:// 协议"
#: settings/utils/ldap.py:428 #: settings/utils/ldap.py:430
msgid "Host or port is disconnected: {}" msgid "Host or port is disconnected: {}"
msgstr "主机或端口不可连接: {}" msgstr "主机或端口不可连接: {}"
#: settings/utils/ldap.py:430 #: settings/utils/ldap.py:432
msgid "The port is not the port of the LDAP service: {}" msgid "The port is not the port of the LDAP service: {}"
msgstr "端口不是LDAP服务端口: {}" msgstr "端口不是LDAP服务端口: {}"
#: settings/utils/ldap.py:432 #: settings/utils/ldap.py:434
msgid "Please add certificate: {}" msgid "Please add certificate: {}"
msgstr "请添加证书" msgstr "请添加证书"
#: settings/utils/ldap.py:436 settings/utils/ldap.py:463 #: settings/utils/ldap.py:438 settings/utils/ldap.py:465
#: settings/utils/ldap.py:493 settings/utils/ldap.py:521 #: settings/utils/ldap.py:495 settings/utils/ldap.py:523
msgid "Unknown error: {}" msgid "Unknown error: {}"
msgstr "未知错误: {}" msgstr "未知错误: {}"
#: settings/utils/ldap.py:450 #: settings/utils/ldap.py:452
msgid "Bind DN or Password incorrect" msgid "Bind DN or Password incorrect"
msgstr "绑定DN或密码错误" msgstr "绑定DN或密码错误"
#: settings/utils/ldap.py:457 #: settings/utils/ldap.py:459
msgid "Please enter Bind DN: {}" msgid "Please enter Bind DN: {}"
msgstr "请输入绑定DN: {}" msgstr "请输入绑定DN: {}"
#: settings/utils/ldap.py:459 #: settings/utils/ldap.py:461
msgid "Please enter Password: {}" msgid "Please enter Password: {}"
msgstr "请输入密码: {}" msgstr "请输入密码: {}"
#: settings/utils/ldap.py:461 #: settings/utils/ldap.py:463
msgid "Please enter correct Bind DN and Password: {}" msgid "Please enter correct Bind DN and Password: {}"
msgstr "请输入正确的绑定DN和密码: {}" msgstr "请输入正确的绑定DN和密码: {}"
#: settings/utils/ldap.py:479 #: settings/utils/ldap.py:481
msgid "Invalid User OU or User search filter: {}" msgid "Invalid User OU or User search filter: {}"
msgstr "不合法的用户OU或用户过滤器: {}" msgstr "不合法的用户OU或用户过滤器: {}"
#: settings/utils/ldap.py:510 #: settings/utils/ldap.py:512
msgid "LDAP User attr map not include: {}" msgid "LDAP User attr map not include: {}"
msgstr "LDAP属性映射没有包含: {}" msgstr "LDAP属性映射没有包含: {}"
#: settings/utils/ldap.py:517 #: settings/utils/ldap.py:519
msgid "LDAP User attr map is not dict" msgid "LDAP User attr map is not dict"
msgstr "LDAP属性映射不合法" msgstr "LDAP属性映射不合法"
#: settings/utils/ldap.py:536 #: settings/utils/ldap.py:538
msgid "LDAP authentication is not enabled" msgid "LDAP authentication is not enabled"
msgstr "LDAP认证没有启用" msgstr "LDAP认证没有启用"
#: settings/utils/ldap.py:554 #: settings/utils/ldap.py:556
msgid "Error (Invalid LDAP server): {}" msgid "Error (Invalid LDAP server): {}"
msgstr "错误 不合法的LDAP服务器地址: {}" msgstr "错误 不合法的LDAP服务器地址: {}"
#: settings/utils/ldap.py:556 #: settings/utils/ldap.py:558
msgid "Error (Invalid Bind DN): {}" msgid "Error (Invalid Bind DN): {}"
msgstr "错误不合法的绑定DN: {}" msgstr "错误不合法的绑定DN: {}"
#: settings/utils/ldap.py:558 #: settings/utils/ldap.py:560
msgid "Error (Invalid LDAP User attr map): {}" msgid "Error (Invalid LDAP User attr map): {}"
msgstr "错误不合法的LDAP属性映射: {}" msgstr "错误不合法的LDAP属性映射: {}"
#: settings/utils/ldap.py:560 #: settings/utils/ldap.py:562
msgid "Error (Invalid User OU or User search filter): {}" msgid "Error (Invalid User OU or User search filter): {}"
msgstr "错误不合法的用户OU或用户过滤器: {}" msgstr "错误不合法的用户OU或用户过滤器: {}"
#: settings/utils/ldap.py:562 #: settings/utils/ldap.py:564
msgid "Error (Not enabled LDAP authentication): {}" msgid "Error (Not enabled LDAP authentication): {}"
msgstr "错误没有启用LDAP认证: {}" msgstr "错误没有启用LDAP认证: {}"
#: settings/utils/ldap.py:564 #: settings/utils/ldap.py:566
msgid "Error (Unknown): {}" msgid "Error (Unknown): {}"
msgstr "错误(未知): {}" msgstr "错误(未知): {}"
#: settings/utils/ldap.py:567 #: settings/utils/ldap.py:569
msgid "Succeed: Match {} s user" msgid "Succeed: Match {} s user"
msgstr "成功匹配 {} 个用户" msgstr "成功匹配 {} 个用户"
#: settings/utils/ldap.py:600 #: settings/utils/ldap.py:602
msgid "Authentication failed (configuration incorrect): {}" msgid "Authentication failed (configuration incorrect): {}"
msgstr "认证失败(配置错误): {}" msgstr "认证失败(配置错误): {}"
#: settings/utils/ldap.py:602 #: settings/utils/ldap.py:604
msgid "Authentication failed (before login check failed): {}" msgid "Authentication failed (before login check failed): {}"
msgstr "认证失败(登录前检查失败): {}" msgstr "认证失败(登录前检查失败): {}"
#: settings/utils/ldap.py:604 #: settings/utils/ldap.py:606
msgid "Authentication failed (username or password incorrect): {}" msgid "Authentication failed (username or password incorrect): {}"
msgstr "认证失败 (用户名或密码不正确): {}" msgstr "认证失败 (用户名或密码不正确): {}"
#: settings/utils/ldap.py:606 #: settings/utils/ldap.py:608
msgid "Authentication failed (Unknown): {}" msgid "Authentication failed (Unknown): {}"
msgstr "认证失败: (未知): {}" msgstr "认证失败: (未知): {}"
#: settings/utils/ldap.py:609 #: settings/utils/ldap.py:611
msgid "Authentication success: {}" msgid "Authentication success: {}"
msgstr "认证成功: {}" msgstr "认证成功: {}"
@ -4651,18 +4658,18 @@ msgstr "MariaDB 端口"
msgid "PostgreSQL Port" msgid "PostgreSQL Port"
msgstr "PostgreSQL 端口" msgstr "PostgreSQL 端口"
#: terminal/models/endpoint.py:25 terminal/models/endpoint.py:63 #: terminal/models/endpoint.py:25 terminal/models/endpoint.py:66
#: terminal/serializers/endpoint.py:40 terminal/serializers/storage.py:37 #: terminal/serializers/endpoint.py:40 terminal/serializers/storage.py:37
#: terminal/serializers/storage.py:49 terminal/serializers/storage.py:79 #: terminal/serializers/storage.py:49 terminal/serializers/storage.py:79
#: terminal/serializers/storage.py:89 terminal/serializers/storage.py:97 #: terminal/serializers/storage.py:89 terminal/serializers/storage.py:97
msgid "Endpoint" msgid "Endpoint"
msgstr "端点" msgstr "端点"
#: terminal/models/endpoint.py:56 #: terminal/models/endpoint.py:59
msgid "IP group" msgid "IP group"
msgstr "IP 组" msgstr "IP 组"
#: terminal/models/endpoint.py:68 #: terminal/models/endpoint.py:71
msgid "Endpoint rule" msgid "Endpoint rule"
msgstr "端点规则" msgstr "端点规则"

View File

@ -2,6 +2,7 @@
# #
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.conf import settings
from rest_framework_bulk import BulkModelViewSet from rest_framework_bulk import BulkModelViewSet
from rest_framework.generics import RetrieveAPIView from rest_framework.generics import RetrieveAPIView
from rest_framework.exceptions import PermissionDenied from rest_framework.exceptions import PermissionDenied
@ -68,6 +69,12 @@ class OrgViewSet(BulkModelViewSet):
msg = _('The current organization ({}) cannot be deleted').format(current_org) msg = _('The current organization ({}) cannot be deleted').format(current_org)
raise PermissionDenied(detail=msg) raise PermissionDenied(detail=msg)
if str(instance.id) == settings.AUTH_LDAP_SYNC_ORG_ID:
msg = _(
'LDAP synchronization is set to the current organization. Please switch to another organization before deleting'
)
raise PermissionDenied(detail=msg)
for model in org_related_models: for model in org_related_models:
data = self.get_data_from_model(instance, model) data = self.get_data_from_model(instance, model)
if not data: if not data:

View File

@ -90,7 +90,7 @@ class SystemRolePermissionsViewSet(BaseRolePermissionsViewSet):
role_pk = 'system_role_pk' role_pk = 'system_role_pk'
model = SystemRole model = SystemRole
rbac_perms = ( rbac_perms = (
('get_tree', 'rbac.view_systemrole'), ('get_tree', 'rbac.view_permission'),
) )
@ -99,6 +99,6 @@ class OrgRolePermissionsViewSet(BaseRolePermissionsViewSet):
role_pk = 'org_role_pk' role_pk = 'org_role_pk'
model = OrgRole model = OrgRole
rbac_perms = ( rbac_perms = (
('get_tree', 'rbac.view_orgrole'), ('get_tree', 'rbac.view_permission'),
) )

View File

@ -2,15 +2,10 @@ from django.utils.translation import ugettext_noop
from .const import Scope, system_exclude_permissions, org_exclude_permissions from .const import Scope, system_exclude_permissions, org_exclude_permissions
system_user_perms = ( _view_root_perms = (
('authentication', 'connectiontoken', 'add', 'connectiontoken'),
('authentication', 'temptoken', 'add,change,view', 'temptoken'),
('authentication', 'accesskey', '*', '*'),
('tickets', 'ticket', 'view', 'ticket'),
('orgs', 'organization', 'view', 'rootorg'), ('orgs', 'organization', 'view', 'rootorg'),
) )
# Todo: 获取应该区分 系统用户,和组织用户的权限
# 工作台也区分组织后再考虑 # 工作台也区分组织后再考虑
user_perms = ( user_perms = (
('rbac', 'menupermission', 'view', 'workbench'), ('rbac', 'menupermission', 'view', 'workbench'),
@ -25,16 +20,28 @@ user_perms = (
('ops', 'commandexecution', 'add', 'commandexecution'), ('ops', 'commandexecution', 'add', 'commandexecution'),
) )
auditor_perms = user_perms + ( system_user_perms = (
('authentication', 'connectiontoken', 'add', 'connectiontoken'),
('authentication', 'temptoken', 'add,change,view', 'temptoken'),
('authentication', 'accesskey', '*', '*'),
('tickets', 'ticket', 'view', 'ticket'),
) + user_perms
_auditor_perms = (
('rbac', 'menupermission', 'view', 'audit'), ('rbac', 'menupermission', 'view', 'audit'),
('audits', '*', '*', '*'), ('audits', '*', '*', '*'),
('terminal', 'commandstorage', 'view', 'commandstorage'), ('terminal', 'commandstorage', 'view', 'commandstorage'),
('terminal', 'sessionreplay', 'view,download', 'sessionreplay'), ('terminal', 'sessionreplay', 'view,download', 'sessionreplay'),
('terminal', 'session', '*', '*'), ('terminal', 'session', '*', '*'),
('terminal', 'command', '*', '*'), ('terminal', 'command', '*', '*'),
('ops', 'commandexecution', 'view', 'commandexecution') ('ops', 'commandexecution', 'view', 'commandexecution'),
) )
auditor_perms = user_perms + _auditor_perms
system_auditor_perms = system_user_perms + _auditor_perms + _view_root_perms
app_exclude_perms = [ app_exclude_perms = [
('users', 'user', 'add,delete', 'user'), ('users', 'user', 'add,delete', 'user'),
('orgs', 'org', 'add,delete,change', 'org'), ('orgs', 'org', 'add,delete,change', 'org'),
@ -102,7 +109,7 @@ class BuiltinRole:
'1', ugettext_noop('SystemAdmin'), Scope.system, [] '1', ugettext_noop('SystemAdmin'), Scope.system, []
) )
system_auditor = PredefineRole( system_auditor = PredefineRole(
'2', ugettext_noop('SystemAuditor'), Scope.system, auditor_perms '2', ugettext_noop('SystemAuditor'), Scope.system, system_auditor_perms
) )
system_component = PredefineRole( system_component = PredefineRole(
'4', ugettext_noop('SystemComponent'), Scope.system, app_exclude_perms, 'exclude' '4', ugettext_noop('SystemComponent'), Scope.system, app_exclude_perms, 'exclude'

View File

@ -108,8 +108,11 @@ only_system_permissions = (
('terminal', 'replaystorage', '*', '*'), ('terminal', 'replaystorage', '*', '*'),
('terminal', 'status', '*', '*'), ('terminal', 'status', '*', '*'),
('terminal', 'task', '*', '*'), ('terminal', 'task', '*', '*'),
('terminal', 'endpoint', '*', '*'),
('terminal', 'endpointrule', '*', '*'),
('authentication', '*', '*', '*'), ('authentication', '*', '*', '*'),
('tickets', '*', '*', '*'), ('tickets', '*', '*', '*'),
('orgs', 'organization', 'view', 'rootorg'),
) )
only_org_permissions = ( only_org_permissions = (

View File

@ -6,7 +6,7 @@ from rest_framework.serializers import ValidationError
from common.db.models import JMSModel from common.db.models import JMSModel
from common.utils import lazyproperty from common.utils import lazyproperty
from orgs.utils import current_org from orgs.utils import current_org, tmp_to_root_org
from .role import Role from .role import Role
from ..const import Scope from ..const import Scope
@ -105,20 +105,25 @@ class RoleBinding(JMSModel):
from orgs.models import Organization from orgs.models import Organization
roles = Role.get_roles_by_perm(perm) roles = Role.get_roles_by_perm(perm)
with tmp_to_root_org():
bindings = list(cls.objects.root_all().filter(role__in=roles, user=user)) bindings = list(cls.objects.root_all().filter(role__in=roles, user=user))
system_bindings = [b for b in bindings if b.scope == Role.Scope.system.value]
system_bindings = [b for b in bindings if b.scope == Role.Scope.system.value]
# 工作台仅限于自己加入的组织
if perm == 'rbac.view_workbench': if perm == 'rbac.view_workbench':
all_orgs = user.orgs.all() all_orgs = user.orgs.all()
else: else:
all_orgs = Organization.objects.all() all_orgs = Organization.objects.all()
# 有系统级别的绑定,就代表在所有组织有这个权限
if system_bindings: if system_bindings:
orgs = all_orgs orgs = all_orgs
else: else:
org_ids = [b.org.id for b in bindings if b.org] org_ids = [b.org.id for b in bindings if b.org]
orgs = all_orgs.filter(id__in=org_ids) orgs = all_orgs.filter(id__in=org_ids)
if orgs and user.has_perm('orgs.view_rootorg'):
# 全局组织
if orgs and perm != 'rbac.view_workbench' and user.has_perm('orgs.view_rootorg'):
orgs = [Organization.root(), *list(orgs)] orgs = [Organization.root(), *list(orgs)]
return orgs return orgs

View File

@ -1,7 +1,8 @@
#!/usr/bin/python #!/usr/bin/python
import os import os
from collections import defaultdict
from typing import Callable from typing import Callable
from treelib import Tree
from treelib.exceptions import NodeIDAbsentError
from django.utils.translation import gettext_lazy as _, gettext, get_language from django.utils.translation import gettext_lazy as _, gettext, get_language
from django.conf import settings from django.conf import settings
@ -159,6 +160,65 @@ def sort_nodes(node):
return value return value
class CounterTree(Tree):
def get_total_count(self, node):
count = getattr(node, '_total_count', None)
if count is not None:
return count
if not node.data.isParent:
return 1
count = 0
children = self.children(node.identifier)
for child in children:
if child.data.isParent:
count += self.get_total_count(child)
else:
count += 1
node._total_count = count
return count
def get_checked_count(self, node):
count = getattr(node, '_checked_count', None)
if count is not None:
return count
if not node.data.isParent:
if node.data.checked:
return 1
else:
return 0
count = 0
children = self.children(node.identifier)
for child in children:
if child.data.isParent:
count += self.get_checked_count(child)
else:
if child.data.checked:
count += 1
node._checked_count = count
return count
def add_nodes_to_tree(self, ztree_nodes, retry=0):
failed = []
for node in ztree_nodes:
pid = node.pId
if retry == 2:
pid = '$ROOT$'
try:
self.create_node(node.name, node.id, pid, data=node)
except NodeIDAbsentError:
failed.append(node)
if retry > 2:
return
if failed:
retry += 1
return self.add_nodes_to_tree(failed, retry)
class PermissionTreeUtil: class PermissionTreeUtil:
get_permissions: Callable get_permissions: Callable
action_mapper = { action_mapper = {
@ -183,8 +243,6 @@ class PermissionTreeUtil:
Permission.get_permissions(scope) Permission.get_permissions(scope)
) )
self.check_disabled = check_disabled self.check_disabled = check_disabled
self.total_counts = defaultdict(int)
self.checked_counts = defaultdict(int)
self.lang = get_language() self.lang = get_language()
@staticmethod @staticmethod
@ -211,38 +269,10 @@ class PermissionTreeUtil:
'name': name, 'name': name,
'pId': view, 'pId': view,
} }
total_count = self.total_counts[app] node = self._create_node(app_data, 'app', is_open=False)
checked_count = self.checked_counts[app]
if total_count == 0:
continue
self.total_counts[view] += total_count
self.checked_counts[view] += checked_count
node = self._create_node(
app_data, total_count, checked_count,
'app', is_open=False
)
nodes.append(node) nodes.append(node)
return nodes return nodes
def _get_model_counts_mapper(self):
model_counts = self.all_permissions \
.values('model', 'app', 'content_type') \
.order_by('content_type') \
.annotate(count=Count('content_type'))
model_check_counts = self.permissions \
.values('content_type', 'model') \
.order_by('content_type') \
.annotate(count=Count('content_type'))
model_counts_mapper = {
i['content_type']: i['count']
for i in model_counts
}
model_check_counts_mapper = {
i['content_type']: i['count']
for i in model_check_counts
}
return model_counts_mapper, model_check_counts_mapper
@staticmethod @staticmethod
def _check_model_xpack(model_id): def _check_model_xpack(model_id):
app, model = model_id.split('.', 2) app, model = model_id.split('.', 2)
@ -263,17 +293,10 @@ class PermissionTreeUtil:
if not self._check_model_xpack(model_id): if not self._check_model_xpack(model_id):
continue continue
total_count = self.total_counts[model_id]
checked_count = self.checked_counts[model_id]
if total_count == 0:
continue
# 获取 pid # 获取 pid
app = ct.app_label app = ct.app_label
if model_id in special_pid_mapper: if model_id in special_pid_mapper:
app = special_pid_mapper[model_id] app = special_pid_mapper[model_id]
self.total_counts[app] += total_count
self.checked_counts[app] += checked_count
# 获取 name # 获取 name
name = f'{ct.name}' name = f'{ct.name}'
@ -284,7 +307,7 @@ class PermissionTreeUtil:
'id': model_id, 'id': model_id,
'name': name, 'name': name,
'pId': app, 'pId': app,
}, total_count, checked_count, 'model', is_open=False) }, 'model', is_open=False)
nodes.append(node) nodes.append(node)
return nodes return nodes
@ -334,10 +357,7 @@ class PermissionTreeUtil:
if title in special_pid_mapper: if title in special_pid_mapper:
pid = special_pid_mapper[title] pid = special_pid_mapper[title]
self.total_counts[pid] += 1
checked = p.id in permissions_id checked = p.id in permissions_id
if checked:
self.checked_counts[pid] += 1
node = TreeNode(**{ node = TreeNode(**{
'id': p.id, 'id': p.id,
@ -347,7 +367,7 @@ class PermissionTreeUtil:
'isParent': False, 'isParent': False,
'chkDisabled': self.check_disabled, 'chkDisabled': self.check_disabled,
'iconSkin': icon, 'iconSkin': icon,
'checked': p.id in permissions_id, 'checked': checked,
'open': False, 'open': False,
'meta': { 'meta': {
'type': 'perm', 'type': 'perm',
@ -356,13 +376,11 @@ class PermissionTreeUtil:
nodes.append(node) nodes.append(node)
return nodes return nodes
def _create_node(self, data, total_count, checked_count, tp, def _create_node(self, data, tp, is_parent=True, is_open=True, icon='', checked=None):
is_parent=True, is_open=True, icon='', checked=None):
assert data.get('id') assert data.get('id')
assert data.get('name') assert data.get('name')
assert data.get('pId') is not None assert data.get('pId') is not None
if checked is None:
checked = total_count == checked_count
node_data = { node_data = {
'isParent': is_parent, 'isParent': is_parent,
'iconSkin': icon, 'iconSkin': icon,
@ -380,46 +398,58 @@ class PermissionTreeUtil:
node.name += ('[' + node.id + ']') node.name += ('[' + node.id + ']')
if DEBUG_DB: if DEBUG_DB:
node.name += ('-' + node.id) node.name += ('-' + node.id)
node.name += f'({checked_count}/{total_count})'
return node return node
def _create_root_tree_node(self): def _create_root_tree_node(self):
total_count = self.all_permissions.count() node = self._create_node(root_node_data, 'root')
checked_count = self.permissions.count()
node = self._create_node(root_node_data, total_count, checked_count, 'root')
return node return node
def _create_views_node(self): def _create_views_node(self):
nodes = [] nodes = []
for view_data in view_nodes_data: for view_data in view_nodes_data:
view = view_data['id']
data = { data = {
**view_data, **view_data,
'pId': '$ROOT$', 'pId': '$ROOT$',
} }
total_count = self.total_counts[view] node = self._create_node(data, 'view', is_open=True)
checked_count = self.checked_counts[view]
if total_count == 0:
continue
node = self._create_node(data, total_count, checked_count, 'view', is_open=True)
nodes.append(node) nodes.append(node)
return nodes return nodes
def _create_extra_nodes(self): def _create_extra_nodes(self):
nodes = [] nodes = []
for data in extra_nodes_data: for data in extra_nodes_data:
i = data['id'] node = self._create_node(data, 'extra', is_open=False)
pid = data['pId'] nodes.append(node)
checked_count = self.checked_counts[i] return nodes
total_count = self.total_counts[i]
@staticmethod
def compute_nodes_count(ztree_nodes):
tree = CounterTree()
reverse_nodes = ztree_nodes[::-1]
root = reverse_nodes[0]
tree.create_node(root.name, root.id, data=root)
tree.add_nodes_to_tree(reverse_nodes[1:])
counter_nodes = tree.all_nodes()
node_counts = {}
for n in counter_nodes:
if not n:
continue
total_count = tree.get_total_count(n)
checked_count = tree.get_checked_count(n)
node_counts[n.identifier] = [checked_count, total_count]
nodes = []
for node in ztree_nodes:
counter = node_counts[node.id]
if not counter:
counter = [0, 0]
checked_count, total_count = counter
if total_count == 0: if total_count == 0:
continue continue
self.total_counts[pid] += total_count node.name += '({}/{})'.format(checked_count, total_count)
self.checked_counts[pid] += checked_count if checked_count != 0:
node = self._create_node( node.checked = True
data, total_count, checked_count,
'extra', is_open=False
)
nodes.append(node) nodes.append(node)
return nodes return nodes
@ -431,5 +461,6 @@ class PermissionTreeUtil:
nodes += self._create_views_node() nodes += self._create_views_node()
nodes += [self._create_root_tree_node()] nodes += [self._create_root_tree_node()]
nodes = self.compute_nodes_count(nodes)
nodes.sort(key=sort_nodes) nodes.sort(key=sort_nodes)
return nodes return nodes

View File

@ -376,7 +376,9 @@ class LDAPImportUtil(object):
except Exception as e: except Exception as e:
errors.append({user['username']: str(e)}) errors.append({user['username']: str(e)})
logger.error(e) logger.error(e)
if org and org.is_root(): if not org:
return
if org.is_root():
return return
for obj in objs: for obj in objs:
org.add_member(obj) org.add_member(obj)

View File

@ -63,7 +63,7 @@ class SessionViewSet(OrgBulkModelViewSet):
] ]
extra_filter_backends = [DatetimeRangeFilter] extra_filter_backends = [DatetimeRangeFilter]
rbac_perms = { rbac_perms = {
'download': ['terminal.download_sessionreplay|terminal.view_sessionreplay'] 'download': ['terminal.download_sessionreplay']
} }
@staticmethod @staticmethod

View File

@ -81,8 +81,14 @@ def import_ldap_user():
util_server = LDAPServerUtil() util_server = LDAPServerUtil()
util_import = LDAPImportUtil() util_import = LDAPImportUtil()
users = util_server.search() users = util_server.search()
if settings.XPACK_ENABLED:
org_id = settings.AUTH_LDAP_SYNC_ORG_ID org_id = settings.AUTH_LDAP_SYNC_ORG_ID
org = Organization.get_instance(org_id) default_org = None
else:
# 社区版默认导入Default组织
org_id = Organization.DEFAULT_ID
default_org = Organization.default()
org = Organization.get_instance(org_id, default=default_org)
errors = util_import.perform_import(users, org) errors = util_import.perform_import(users, org)
if errors: if errors:
logger.error("Imported LDAP users errors: {}".format(errors)) logger.error("Imported LDAP users errors: {}".format(errors))
@ -106,6 +112,9 @@ def import_ldap_user_periodic():
else: else:
interval = None interval = None
crontab = settings.AUTH_LDAP_SYNC_CRONTAB crontab = settings.AUTH_LDAP_SYNC_CRONTAB
if crontab:
# 优先使用 crontab
interval = None
tasks = { tasks = {
task_name: { task_name: {
'task': import_ldap_user.name, 'task': import_ldap_user.name,