Merge pull request #5029 from jumpserver/dev

Dev
pull/5041/head
Orange 2020-11-17 19:46:36 +08:00 committed by GitHub
commit 49dd611292
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 275 additions and 133 deletions

View File

@ -0,0 +1,17 @@
# Generated by Django 2.2.13 on 2020-11-17 11:38
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('assets', '0061_auto_20201116_1757'),
]
operations = [
migrations.AlterModelOptions(
name='asset',
options={'ordering': ['hostname', 'ip'], 'verbose_name': 'Asset'},
),
]

View File

@ -361,4 +361,4 @@ class Asset(ProtocolsMixin, NodesRelationMixin, OrgModelMixin):
class Meta: class Meta:
unique_together = [('org_id', 'hostname')] unique_together = [('org_id', 'hostname')]
verbose_name = _("Asset") verbose_name = _("Asset")
ordering = ['-date_created'] ordering = ["hostname", "ip"]

View File

@ -20,9 +20,13 @@ class FavoriteAsset(CommonModelMixin):
return cls.objects.filter(user=user).values_list('asset', flat=True) return cls.objects.filter(user=user).values_list('asset', flat=True)
@classmethod @classmethod
def get_user_favorite_assets(cls, user): def get_user_favorite_assets(cls, user, asset_perms_id=None):
from assets.models import Asset from assets.models import Asset
from perms.utils.asset.user_permission import get_user_granted_all_assets from perms.utils.asset.user_permission import get_user_granted_all_assets
asset_ids = get_user_granted_all_assets(user).values_list('id', flat=True) asset_ids = get_user_granted_all_assets(
user,
via_mapping_node=False,
asset_perms_id=asset_perms_id
).values_list('id', flat=True)
query_name = cls.asset.field.related_query_name() query_name = cls.asset.field.related_query_name()
return Asset.org_objects.filter(**{f'{query_name}__user_id': user.id}, id__in=asset_ids).distinct() return Asset.org_objects.filter(**{f'{query_name}__user_id': user.id}, id__in=asset_ids).distinct()

Binary file not shown.

View File

@ -8,7 +8,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: 2020-11-12 10:49+0800\n" "POT-Creation-Date: 2020-11-17 17:24+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\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"
@ -35,7 +35,7 @@ msgstr "远程应用"
#: applications/models/application.py:122 #: applications/models/application.py:122
#: applications/models/database_app.py:18 applications/models/k8s_app.py:11 #: applications/models/database_app.py:18 applications/models/k8s_app.py:11
#: applications/models/remote_app.py:21 assets/models/asset.py:149 #: applications/models/remote_app.py:21 assets/models/asset.py:149
#: assets/models/base.py:232 assets/models/cluster.py:18 #: assets/models/base.py:234 assets/models/cluster.py:18
#: assets/models/cmd_filter.py:21 assets/models/domain.py:21 #: assets/models/cmd_filter.py:21 assets/models/domain.py:21
#: 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:23 perms/models/base.py:48 settings/models.py:27 #: orgs/models.py:23 perms/models/base.py:48 settings/models.py:27
@ -54,7 +54,7 @@ msgstr "远程应用"
#: users/templates/users/user_profile.html:51 #: users/templates/users/user_profile.html:51
#: users/templates/users/user_pubkey_update.html:57 #: users/templates/users/user_pubkey_update.html:57
#: users/templates/users/user_remote_app_permission.html:36 #: users/templates/users/user_remote_app_permission.html:36
#: xpack/plugins/cloud/models.py:37 #: xpack/plugins/cloud/models.py:36
msgid "Name" msgid "Name"
msgstr "名称" msgstr "名称"
@ -87,7 +87,7 @@ msgstr "类型"
#: applications/models/application.py:128 #: applications/models/application.py:128
#: applications/models/database_app.py:33 applications/models/k8s_app.py:18 #: applications/models/database_app.py:33 applications/models/k8s_app.py:18
#: applications/models/remote_app.py:45 assets/models/asset.py:154 #: applications/models/remote_app.py:45 assets/models/asset.py:154
#: assets/models/asset.py:230 assets/models/base.py:237 #: assets/models/asset.py:230 assets/models/base.py:239
#: assets/models/cluster.py:29 assets/models/cmd_filter.py:23 #: assets/models/cluster.py:29 assets/models/cmd_filter.py:23
#: assets/models/cmd_filter.py:57 assets/models/domain.py:22 #: assets/models/cmd_filter.py:57 assets/models/domain.py:22
#: assets/models/domain.py:55 assets/models/group.py:23 #: assets/models/domain.py:55 assets/models/group.py:23
@ -101,8 +101,8 @@ msgstr "类型"
#: users/templates/users/user_group_detail.html:62 #: users/templates/users/user_group_detail.html:62
#: users/templates/users/user_group_list.html:16 #: users/templates/users/user_group_list.html:16
#: users/templates/users/user_profile.html:138 #: users/templates/users/user_profile.html:138
#: xpack/plugins/change_auth_plan/models.py:77 xpack/plugins/cloud/models.py:56 #: xpack/plugins/change_auth_plan/models.py:77 xpack/plugins/cloud/models.py:54
#: xpack/plugins/cloud/models.py:151 xpack/plugins/gathered_user/models.py:26 #: xpack/plugins/cloud/models.py:149 xpack/plugins/gathered_user/models.py:26
msgid "Comment" msgid "Comment"
msgstr "备注" msgstr "备注"
@ -159,7 +159,7 @@ msgstr "Kubernetes应用"
#: users/templates/users/user_asset_permission.html:70 #: users/templates/users/user_asset_permission.html:70
#: users/templates/users/user_granted_remote_app.html:36 #: users/templates/users/user_granted_remote_app.html:36
#: xpack/plugins/change_auth_plan/models.py:282 #: xpack/plugins/change_auth_plan/models.py:282
#: xpack/plugins/cloud/models.py:280 #: xpack/plugins/cloud/models.py:278
msgid "Asset" msgid "Asset"
msgstr "资产" msgstr "资产"
@ -178,27 +178,27 @@ msgid "Parameters"
msgstr "参数" msgstr "参数"
#: applications/models/remote_app.py:39 assets/models/asset.py:228 #: applications/models/remote_app.py:39 assets/models/asset.py:228
#: assets/models/base.py:240 assets/models/cluster.py:28 #: assets/models/base.py:242 assets/models/cluster.py:28
#: assets/models/cmd_filter.py:26 assets/models/cmd_filter.py:60 #: assets/models/cmd_filter.py:26 assets/models/cmd_filter.py:60
#: assets/models/group.py:21 common/db/models.py:67 common/mixins/models.py:49 #: assets/models/group.py:21 common/db/models.py:67 common/mixins/models.py:49
#: orgs/models.py:24 orgs/models.py:400 perms/models/base.py:54 #: orgs/models.py:24 orgs/models.py:400 perms/models/base.py:54
#: users/models/user.py:546 users/serializers/group.py:35 #: users/models/user.py:546 users/serializers/group.py:35
#: users/templates/users/user_detail.html:97 #: users/templates/users/user_detail.html:97
#: xpack/plugins/change_auth_plan/models.py:81 xpack/plugins/cloud/models.py:59 #: xpack/plugins/change_auth_plan/models.py:81 xpack/plugins/cloud/models.py:57
#: xpack/plugins/cloud/models.py:157 xpack/plugins/gathered_user/models.py:30 #: xpack/plugins/cloud/models.py:155 xpack/plugins/gathered_user/models.py:30
msgid "Created by" msgid "Created by"
msgstr "创建者" msgstr "创建者"
# msgid "Created by" # msgid "Created by"
# msgstr "创建者" # msgstr "创建者"
#: applications/models/remote_app.py:42 assets/models/asset.py:229 #: applications/models/remote_app.py:42 assets/models/asset.py:229
#: assets/models/base.py:238 assets/models/cluster.py:26 #: assets/models/base.py:240 assets/models/cluster.py:26
#: assets/models/domain.py:24 assets/models/gathered_user.py:19 #: assets/models/domain.py:24 assets/models/gathered_user.py:19
#: assets/models/group.py:22 assets/models/label.py:25 common/db/models.py:69 #: assets/models/group.py:22 assets/models/label.py:25 common/db/models.py:69
#: common/mixins/models.py:50 ops/models/adhoc.py:38 ops/models/command.py:27 #: common/mixins/models.py:50 ops/models/adhoc.py:38 ops/models/command.py:27
#: orgs/models.py:25 orgs/models.py:398 perms/models/base.py:55 #: orgs/models.py:25 orgs/models.py:398 perms/models/base.py:55
#: users/models/group.py:18 users/templates/users/user_group_detail.html:58 #: users/models/group.py:18 users/templates/users/user_group_detail.html:58
#: xpack/plugins/cloud/models.py:62 xpack/plugins/cloud/models.py:160 #: xpack/plugins/cloud/models.py:60 xpack/plugins/cloud/models.py:158
msgid "Date created" msgid "Date created"
msgstr "创建日期" msgstr "创建日期"
@ -232,7 +232,7 @@ msgstr "目标URL"
#: applications/serializers/remote_app.py:60 #: applications/serializers/remote_app.py:60
#: applications/serializers/remote_app.py:70 #: applications/serializers/remote_app.py:70
#: applications/serializers/remote_app.py:78 #: applications/serializers/remote_app.py:78
#: applications/serializers/remote_app.py:85 assets/models/base.py:233 #: applications/serializers/remote_app.py:85 assets/models/base.py:235
#: assets/models/gathered_user.py:15 audits/models.py:99 #: assets/models/gathered_user.py:15 audits/models.py:99
#: authentication/forms.py:11 #: authentication/forms.py:11
#: authentication/templates/authentication/login.html:21 #: authentication/templates/authentication/login.html:21
@ -250,7 +250,7 @@ msgstr "用户名"
#: applications/serializers/remote_app.py:61 #: applications/serializers/remote_app.py:61
#: applications/serializers/remote_app.py:71 #: applications/serializers/remote_app.py:71
#: applications/serializers/remote_app.py:79 #: applications/serializers/remote_app.py:79
#: applications/serializers/remote_app.py:86 assets/models/base.py:234 #: applications/serializers/remote_app.py:86 assets/models/base.py:236
#: assets/serializers/asset_user.py:71 authentication/forms.py:13 #: assets/serializers/asset_user.py:71 authentication/forms.py:13
#: authentication/templates/authentication/login.html:29 #: authentication/templates/authentication/login.html:29
#: authentication/templates/authentication/xpack_login.html:109 #: authentication/templates/authentication/xpack_login.html:109
@ -334,6 +334,7 @@ msgstr "系统平台"
#: assets/models/asset.py:191 assets/serializers/asset_user.py:45 #: assets/models/asset.py:191 assets/serializers/asset_user.py:45
#: assets/serializers/gathered_user.py:20 settings/serializers/settings.py:51 #: assets/serializers/gathered_user.py:20 settings/serializers/settings.py:51
#: tickets/api/request_asset_perm.py:63
#: tickets/serializers/request_asset_perm.py:25 #: tickets/serializers/request_asset_perm.py:25
#: users/templates/users/_granted_assets.html:25 #: users/templates/users/_granted_assets.html:25
#: users/templates/users/user_asset_permission.html:157 #: users/templates/users/user_asset_permission.html:157
@ -365,7 +366,7 @@ msgstr "激活"
#: assets/models/asset.py:203 assets/models/cluster.py:19 #: assets/models/asset.py:203 assets/models/cluster.py:19
#: assets/models/user.py:66 templates/_nav.html:44 #: assets/models/user.py:66 templates/_nav.html:44
#: xpack/plugins/cloud/models.py:144 xpack/plugins/cloud/serializers.py:115 #: xpack/plugins/cloud/models.py:142 xpack/plugins/cloud/serializers.py:84
msgid "Admin user" msgid "Admin user"
msgstr "管理用户" msgstr "管理用户"
@ -453,19 +454,19 @@ msgstr "版本"
msgid "AuthBook" msgid "AuthBook"
msgstr "" msgstr ""
#: assets/models/base.py:235 xpack/plugins/change_auth_plan/models.py:72 #: assets/models/base.py:237 xpack/plugins/change_auth_plan/models.py:72
#: xpack/plugins/change_auth_plan/models.py:197 #: xpack/plugins/change_auth_plan/models.py:197
#: xpack/plugins/change_auth_plan/models.py:292 #: xpack/plugins/change_auth_plan/models.py:292
msgid "SSH private key" msgid "SSH private key"
msgstr "SSH密钥" msgstr "SSH密钥"
#: assets/models/base.py:236 xpack/plugins/change_auth_plan/models.py:75 #: assets/models/base.py:238 xpack/plugins/change_auth_plan/models.py:75
#: xpack/plugins/change_auth_plan/models.py:193 #: xpack/plugins/change_auth_plan/models.py:193
#: xpack/plugins/change_auth_plan/models.py:288 #: xpack/plugins/change_auth_plan/models.py:288
msgid "SSH public key" msgid "SSH public key"
msgstr "SSH公钥" msgstr "SSH公钥"
#: assets/models/base.py:239 assets/models/gathered_user.py:20 #: assets/models/base.py:241 assets/models/gathered_user.py:20
#: common/db/models.py:70 common/mixins/models.py:51 ops/models/adhoc.py:39 #: common/db/models.py:70 common/mixins/models.py:51 ops/models/adhoc.py:39
#: orgs/models.py:399 #: orgs/models.py:399
msgid "Date updated" msgid "Date updated"
@ -630,7 +631,7 @@ msgstr "默认资产组"
msgid "User" msgid "User"
msgstr "用户" msgstr "用户"
#: assets/models/label.py:19 assets/models/node.py:396 settings/models.py:28 #: assets/models/label.py:19 assets/models/node.py:398 settings/models.py:28
msgid "Value" msgid "Value"
msgstr "值" msgstr "值"
@ -638,28 +639,28 @@ msgstr "值"
msgid "New node" msgid "New node"
msgstr "新节点" msgstr "新节点"
#: assets/models/node.py:302 users/templates/users/_granted_assets.html:130 #: assets/models/node.py:304 users/templates/users/_granted_assets.html:130
msgid "empty" msgid "empty"
msgstr "空" msgstr "空"
#: assets/models/node.py:395 perms/models/asset_permission.py:144 #: assets/models/node.py:397 perms/models/asset_permission.py:144
msgid "Key" msgid "Key"
msgstr "键" msgstr "键"
#: assets/models/node.py:397 #: assets/models/node.py:399
msgid "Full value" msgid "Full value"
msgstr "全称" msgstr "全称"
#: assets/models/node.py:400 perms/models/asset_permission.py:148 #: assets/models/node.py:402 perms/models/asset_permission.py:148
msgid "Parent key" msgid "Parent key"
msgstr "ssh私钥" msgstr "ssh私钥"
#: assets/models/node.py:409 assets/serializers/system_user.py:190 #: assets/models/node.py:411 assets/serializers/system_user.py:190
#: perms/forms/asset_permission.py:92 perms/forms/asset_permission.py:99 #: perms/forms/asset_permission.py:92 perms/forms/asset_permission.py:99
#: users/templates/users/user_asset_permission.html:41 #: users/templates/users/user_asset_permission.html:41
#: users/templates/users/user_asset_permission.html:73 #: users/templates/users/user_asset_permission.html:73
#: users/templates/users/user_asset_permission.html:158 #: users/templates/users/user_asset_permission.html:158
#: xpack/plugins/cloud/models.py:140 xpack/plugins/cloud/serializers.py:116 #: xpack/plugins/cloud/models.py:138 xpack/plugins/cloud/serializers.py:85
msgid "Node" msgid "Node"
msgstr "节点" msgstr "节点"
@ -722,7 +723,7 @@ msgstr "家目录"
msgid "System groups" msgid "System groups"
msgstr "用户组" msgstr "用户组"
#: assets/models/user.py:206 audits/models.py:39 #: assets/models/user.py:211 audits/models.py:39
#: perms/forms/asset_permission.py:95 perms/forms/remote_app_permission.py:49 #: perms/forms/asset_permission.py:95 perms/forms/remote_app_permission.py:49
#: perms/models/application_permission.py:22 #: perms/models/application_permission.py:22
#: perms/models/asset_permission.py:94 #: perms/models/asset_permission.py:94
@ -731,6 +732,7 @@ msgstr "用户组"
#: perms/models/remote_app_permission.py:16 templates/_nav.html:45 #: perms/models/remote_app_permission.py:16 templates/_nav.html:45
#: terminal/backends/command/models.py:20 #: terminal/backends/command/models.py:20
#: terminal/backends/command/serializers.py:14 terminal/models.py:194 #: terminal/backends/command/serializers.py:14 terminal/models.py:194
#: tickets/api/request_asset_perm.py:64
#: tickets/serializers/request_asset_perm.py:27 #: tickets/serializers/request_asset_perm.py:27
#: users/templates/users/_granted_assets.html:27 #: users/templates/users/_granted_assets.html:27
#: users/templates/users/user_asset_permission.html:42 #: users/templates/users/user_asset_permission.html:42
@ -930,25 +932,25 @@ msgstr "更新节点资产硬件信息: {}"
msgid "Gather assets users" msgid "Gather assets users"
msgstr "收集资产上的用户" msgstr "收集资产上的用户"
#: assets/tasks/push_system_user.py:183 #: assets/tasks/push_system_user.py:184
#: assets/tasks/system_user_connectivity.py:89 #: assets/tasks/system_user_connectivity.py:89
msgid "System user is dynamic: {}" msgid "System user is dynamic: {}"
msgstr "系统用户是动态的: {}" msgstr "系统用户是动态的: {}"
#: assets/tasks/push_system_user.py:214 #: assets/tasks/push_system_user.py:215
msgid "Start push system user for platform: [{}]" msgid "Start push system user for platform: [{}]"
msgstr "推送系统用户到平台: [{}]" msgstr "推送系统用户到平台: [{}]"
#: assets/tasks/push_system_user.py:215 #: assets/tasks/push_system_user.py:216
#: assets/tasks/system_user_connectivity.py:81 #: assets/tasks/system_user_connectivity.py:81
msgid "Hosts count: {}" msgid "Hosts count: {}"
msgstr "主机数量: {}" msgstr "主机数量: {}"
#: assets/tasks/push_system_user.py:233 assets/tasks/push_system_user.py:251 #: assets/tasks/push_system_user.py:235 assets/tasks/push_system_user.py:253
msgid "Push system users to assets: {}" msgid "Push system users to assets: {}"
msgstr "推送系统用户到入资产: {}" msgstr "推送系统用户到入资产: {}"
#: assets/tasks/push_system_user.py:241 #: assets/tasks/push_system_user.py:243
msgid "Push system users to asset: {}({}) => {}" msgid "Push system users to asset: {}({}) => {}"
msgstr "推送系统用户到入资产: {}({}) => {}" msgstr "推送系统用户到入资产: {}({}) => {}"
@ -1103,7 +1105,7 @@ msgstr "启用"
msgid "-" msgid "-"
msgstr "" msgstr ""
#: audits/models.py:96 xpack/plugins/cloud/models.py:215 #: audits/models.py:96 xpack/plugins/cloud/models.py:213
msgid "Failed" msgid "Failed"
msgstr "失败" msgstr "失败"
@ -1133,13 +1135,13 @@ msgid "MFA"
msgstr "多因子认证" msgstr "多因子认证"
#: audits/models.py:105 xpack/plugins/change_auth_plan/models.py:303 #: audits/models.py:105 xpack/plugins/change_auth_plan/models.py:303
#: xpack/plugins/cloud/models.py:228 #: xpack/plugins/cloud/models.py:226
msgid "Reason" msgid "Reason"
msgstr "原因" msgstr "原因"
#: audits/models.py:106 tickets/serializers/request_asset_perm.py:64 #: audits/models.py:106 tickets/serializers/request_asset_perm.py:64
#: tickets/serializers/ticket.py:29 xpack/plugins/cloud/models.py:225 #: tickets/serializers/ticket.py:29 xpack/plugins/cloud/models.py:223
#: xpack/plugins/cloud/models.py:283 #: xpack/plugins/cloud/models.py:281
msgid "Status" msgid "Status"
msgstr "状态" msgstr "状态"
@ -1165,7 +1167,7 @@ msgid "Is success"
msgstr "是否成功" msgstr "是否成功"
#: audits/serializers.py:76 ops/models/command.py:24 #: audits/serializers.py:76 ops/models/command.py:24
#: xpack/plugins/cloud/models.py:223 #: xpack/plugins/cloud/models.py:221
msgid "Result" msgid "Result"
msgstr "结果" msgstr "结果"
@ -1836,7 +1838,7 @@ msgid "The current organization cannot be deleted"
msgstr "当前组织不能被删除" msgstr "当前组织不能被删除"
#: orgs/mixins/models.py:56 orgs/mixins/serializers.py:25 orgs/models.py:41 #: orgs/mixins/models.py:56 orgs/mixins/serializers.py:25 orgs/models.py:41
#: orgs/models.py:395 #: orgs/models.py:395 orgs/serializers.py:80 orgs/serializers.py:91
msgid "Organization" msgid "Organization"
msgstr "组织" msgstr "组织"
@ -2847,32 +2849,46 @@ msgstr ""
msgid "Ticket has %s" msgid "Ticket has %s"
msgstr "工单已%s" msgstr "工单已%s"
#: tickets/api/request_asset_perm.py:81 #: tickets/api/request_asset_perm.py:62
#: tickets/serializers/request_asset_perm.py:23
msgid "IP group"
msgstr "IP组"
#: tickets/api/request_asset_perm.py:65
#: tickets/serializers/request_asset_perm.py:35
msgid "Confirmed assets"
msgstr "确认的资产"
#: tickets/api/request_asset_perm.py:66
msgid "Confirmed system users"
msgstr "确认的系统用户"
#: tickets/api/request_asset_perm.py:87
msgid "Confirm assets first" msgid "Confirm assets first"
msgstr "请先确认资产" msgstr "请先确认资产"
#: tickets/api/request_asset_perm.py:84 #: tickets/api/request_asset_perm.py:90
msgid "Confirmed assets changed" msgid "Confirmed assets changed"
msgstr "确认的资产变更了" msgstr "确认的资产变更了"
#: tickets/api/request_asset_perm.py:88 #: tickets/api/request_asset_perm.py:94
msgid "Confirm system-users first" msgid "Confirm system-users first"
msgstr "请先确认系统用户" msgstr "请先确认系统用户"
#: tickets/api/request_asset_perm.py:92 #: tickets/api/request_asset_perm.py:98
msgid "Confirmed system-users changed" msgid "Confirmed system-users changed"
msgstr "确认的系统用户变更了" msgstr "确认的系统用户变更了"
#: tickets/api/request_asset_perm.py:98 tickets/api/request_asset_perm.py:105 #: tickets/api/request_asset_perm.py:104 tickets/api/request_asset_perm.py:111
#: xpack/plugins/cloud/models.py:216 #: xpack/plugins/cloud/models.py:214
msgid "Succeed" msgid "Succeed"
msgstr "成功" msgstr "成功"
#: tickets/api/request_asset_perm.py:112 #: tickets/api/request_asset_perm.py:118
msgid "From request ticket: {} {}" msgid "From request ticket: {} {}"
msgstr "来自工单申请: {} {}" msgstr "来自工单申请: {} {}"
#: tickets/api/request_asset_perm.py:114 #: tickets/api/request_asset_perm.py:120
msgid "{} request assets, approved by {}" msgid "{} request assets, approved by {}"
msgstr "{} 申请资产,通过人 {}" msgstr "{} 申请资产,通过人 {}"
@ -2948,14 +2964,6 @@ msgstr "{} {} 这个工单"
msgid "this ticket" msgid "this ticket"
msgstr "这个工单" msgstr "这个工单"
#: tickets/serializers/request_asset_perm.py:23
msgid "IP group"
msgstr "IP组"
#: tickets/serializers/request_asset_perm.py:35
msgid "Confirmed assets"
msgstr "确认的资产"
#: tickets/serializers/request_asset_perm.py:39 #: tickets/serializers/request_asset_perm.py:39
msgid "Confirmed system user" msgid "Confirmed system user"
msgstr "确认的系统用户" msgstr "确认的系统用户"
@ -3290,7 +3298,7 @@ msgstr "安全令牌验证"
#: users/templates/users/_base_otp.html:14 users/templates/users/_user.html:13 #: users/templates/users/_base_otp.html:14 users/templates/users/_user.html:13
#: users/templates/users/user_profile_update.html:55 #: users/templates/users/user_profile_update.html:55
#: xpack/plugins/cloud/models.py:126 xpack/plugins/cloud/serializers.py:114 #: xpack/plugins/cloud/models.py:124 xpack/plugins/cloud/serializers.py:83
msgid "Account" msgid "Account"
msgstr "账户" msgstr "账户"
@ -3454,7 +3462,7 @@ msgstr "很强"
#: users/templates/users/user_database_app_permission.html:41 #: users/templates/users/user_database_app_permission.html:41
#: users/templates/users/user_list.html:19 #: users/templates/users/user_list.html:19
#: users/templates/users/user_remote_app_permission.html:41 #: users/templates/users/user_remote_app_permission.html:41
#: xpack/plugins/cloud/models.py:53 #: xpack/plugins/cloud/models.py:51
msgid "Validity" msgid "Validity"
msgstr "有效" msgstr "有效"
@ -4212,95 +4220,95 @@ msgstr "无法将数据发送到远程"
msgid "Cloud center" msgid "Cloud center"
msgstr "云管中心" msgstr "云管中心"
#: xpack/plugins/cloud/models.py:31 #: xpack/plugins/cloud/models.py:30
msgid "Available" msgid "Available"
msgstr "有效" msgstr "有效"
#: xpack/plugins/cloud/models.py:32 #: xpack/plugins/cloud/models.py:31
msgid "Unavailable" msgid "Unavailable"
msgstr "无效" msgstr "无效"
#: xpack/plugins/cloud/models.py:41 #: xpack/plugins/cloud/models.py:40
msgid "Provider" msgid "Provider"
msgstr "云服务商" msgstr "云服务商"
#: xpack/plugins/cloud/models.py:44 #: xpack/plugins/cloud/models.py:43
msgid "Access key id" msgid "Access key id"
msgstr "" msgstr ""
#: xpack/plugins/cloud/models.py:48 #: xpack/plugins/cloud/models.py:47
msgid "Access key secret" msgid "Access key secret"
msgstr "" msgstr ""
#: xpack/plugins/cloud/models.py:67 #: xpack/plugins/cloud/models.py:65
msgid "Cloud account" msgid "Cloud account"
msgstr "云账号" msgstr "云账号"
#: xpack/plugins/cloud/models.py:122 #: xpack/plugins/cloud/models.py:120
msgid "Instance name" msgid "Instance name"
msgstr "实例名称" msgstr "实例名称"
#: xpack/plugins/cloud/models.py:123 #: xpack/plugins/cloud/models.py:121
msgid "Instance name and Partial IP" msgid "Instance name and Partial IP"
msgstr "实例名称和部分IP" msgstr "实例名称和部分IP"
#: xpack/plugins/cloud/models.py:129 xpack/plugins/cloud/serializers.py:90 #: xpack/plugins/cloud/models.py:127 xpack/plugins/cloud/serializers.py:59
msgid "Regions" msgid "Regions"
msgstr "地域" msgstr "地域"
#: xpack/plugins/cloud/models.py:132 #: xpack/plugins/cloud/models.py:130
msgid "Instances" msgid "Instances"
msgstr "实例" msgstr "实例"
#: xpack/plugins/cloud/models.py:136 #: xpack/plugins/cloud/models.py:134
msgid "Hostname strategy" msgid "Hostname strategy"
msgstr "主机名策略" msgstr "主机名策略"
#: xpack/plugins/cloud/models.py:148 xpack/plugins/cloud/serializers.py:118 #: xpack/plugins/cloud/models.py:146 xpack/plugins/cloud/serializers.py:87
msgid "Always update" msgid "Always update"
msgstr "总是更新" msgstr "总是更新"
#: xpack/plugins/cloud/models.py:154 #: xpack/plugins/cloud/models.py:152
msgid "Date last sync" msgid "Date last sync"
msgstr "最后同步日期" msgstr "最后同步日期"
#: xpack/plugins/cloud/models.py:165 xpack/plugins/cloud/models.py:221 #: xpack/plugins/cloud/models.py:163 xpack/plugins/cloud/models.py:219
msgid "Sync instance task" msgid "Sync instance task"
msgstr "同步实例任务" msgstr "同步实例任务"
#: xpack/plugins/cloud/models.py:231 xpack/plugins/cloud/models.py:286 #: xpack/plugins/cloud/models.py:229 xpack/plugins/cloud/models.py:284
msgid "Date sync" msgid "Date sync"
msgstr "同步日期" msgstr "同步日期"
#: xpack/plugins/cloud/models.py:259 #: xpack/plugins/cloud/models.py:257
msgid "Unsync" msgid "Unsync"
msgstr "未同步" msgstr "未同步"
#: xpack/plugins/cloud/models.py:260 #: xpack/plugins/cloud/models.py:258
msgid "New Sync" msgid "New Sync"
msgstr "新同步" msgstr "新同步"
#: xpack/plugins/cloud/models.py:261 #: xpack/plugins/cloud/models.py:259
msgid "Synced" msgid "Synced"
msgstr "已同步" msgstr "已同步"
#: xpack/plugins/cloud/models.py:262 #: xpack/plugins/cloud/models.py:260
msgid "Released" msgid "Released"
msgstr "已释放" msgstr "已释放"
#: xpack/plugins/cloud/models.py:267 #: xpack/plugins/cloud/models.py:265
msgid "Sync task" msgid "Sync task"
msgstr "同步任务" msgstr "同步任务"
#: xpack/plugins/cloud/models.py:271 #: xpack/plugins/cloud/models.py:269
msgid "Sync instance task history" msgid "Sync instance task history"
msgstr "同步实例任务历史" msgstr "同步实例任务历史"
#: xpack/plugins/cloud/models.py:274 #: xpack/plugins/cloud/models.py:272
msgid "Instance" msgid "Instance"
msgstr "实例" msgstr "实例"
#: xpack/plugins/cloud/models.py:277 #: xpack/plugins/cloud/models.py:275
msgid "Region" msgid "Region"
msgstr "地域" msgstr "地域"
@ -4316,10 +4324,6 @@ msgstr "AWS (国际)"
msgid "AWS (China)" msgid "AWS (China)"
msgstr "AWS (中国)" msgstr "AWS (中国)"
#: xpack/plugins/cloud/providers/azure_.py:18
msgid "Azure (China)"
msgstr "Azure (中国)"
#: xpack/plugins/cloud/providers/huaweicloud.py:20 #: xpack/plugins/cloud/providers/huaweicloud.py:20
msgid "Huawei Cloud" msgid "Huawei Cloud"
msgstr "华为云" msgstr "华为云"
@ -4380,23 +4384,15 @@ msgstr "拉美-圣地亚哥"
msgid "Tencent Cloud" msgid "Tencent Cloud"
msgstr "腾讯云" msgstr "腾讯云"
#: xpack/plugins/cloud/serializers.py:26 #: xpack/plugins/cloud/serializers.py:57
msgid "Tenant ID"
msgstr ""
#: xpack/plugins/cloud/serializers.py:30
msgid "Subscription ID"
msgstr ""
#: xpack/plugins/cloud/serializers.py:88
msgid "History count" msgid "History count"
msgstr "执行次数" msgstr "执行次数"
#: xpack/plugins/cloud/serializers.py:89 #: xpack/plugins/cloud/serializers.py:58
msgid "Instance count" msgid "Instance count"
msgstr "实例个数" msgstr "实例个数"
#: xpack/plugins/cloud/serializers.py:117 #: xpack/plugins/cloud/serializers.py:86
#: xpack/plugins/gathered_user/serializers.py:20 #: xpack/plugins/gathered_user/serializers.py:20
msgid "Periodic display" msgid "Periodic display"
msgstr "定时执行" msgstr "定时执行"
@ -4489,6 +4485,14 @@ msgstr "旗舰版"
msgid "Community edition" msgid "Community edition"
msgstr "社区版" msgstr "社区版"
#, fuzzy
#~| msgid "Confirmed system user"
#~ msgid "Confirmed systemusers"
#~ msgstr "确认的系统用户"
#~ msgid "Azure (China)"
#~ msgstr "Azure (中国)"
#~ msgid "MFA level" #~ msgid "MFA level"
#~ msgstr "多因子认证级别" #~ msgstr "多因子认证级别"

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import abc import abc
from django.conf import settings
from rest_framework.generics import ( from rest_framework.generics import (
ListAPIView ListAPIView
) )
@ -16,7 +17,8 @@ from perms.utils.asset.user_permission import (
get_indirect_granted_node_children, get_indirect_granted_node_children,
get_user_granted_nodes_list_via_mapping_node, get_user_granted_nodes_list_via_mapping_node,
get_top_level_granted_nodes, get_top_level_granted_nodes,
rebuild_user_tree_if_need, rebuild_user_tree_if_need, get_favorite_node,
get_ungrouped_node
) )
@ -113,7 +115,12 @@ class UserGrantedNodesMixin:
user: User user: User
def get_nodes(self): def get_nodes(self):
return get_user_granted_nodes_list_via_mapping_node(self.user) nodes = []
if settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
nodes.append(get_ungrouped_node(self.user))
nodes.append(get_favorite_node(self.user))
nodes.extend(get_user_granted_nodes_list_via_mapping_node(self.user))
return nodes
# ------------------------------------------ # ------------------------------------------

View File

@ -1,9 +1,12 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from itertools import chain
from rest_framework.generics import ListAPIView from rest_framework.generics import ListAPIView
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response from rest_framework.response import Response
from django.db.models import F from django.db.models import F, Value, CharField, Q
from django.conf import settings
from orgs.utils import tmp_to_root_org from orgs.utils import tmp_to_root_org
from common.permissions import IsValidUser from common.permissions import IsValidUser
@ -14,9 +17,12 @@ from perms.utils.asset.user_permission import (
get_user_direct_granted_assets, get_top_level_granted_nodes, get_user_direct_granted_assets, get_top_level_granted_nodes,
get_user_granted_nodes_list_via_mapping_node, get_user_granted_nodes_list_via_mapping_node,
get_user_granted_all_assets, rebuild_user_tree_if_need, get_user_granted_all_assets, rebuild_user_tree_if_need,
get_user_all_assetpermissions_id, get_user_all_assetpermissions_id, get_favorite_node,
get_ungrouped_node, compute_tmp_mapping_node_from_perm,
TMP_GRANTED_FIELD, count_direct_granted_node_assets,
count_node_all_granted_assets
) )
from perms.models import AssetPermission
from assets.models import Asset, FavoriteAsset from assets.models import Asset, FavoriteAsset
from assets.api import SerializeToTreeNodeMixin from assets.api import SerializeToTreeNodeMixin
from perms.hands import Node from perms.hands import Node
@ -27,6 +33,78 @@ logger = get_logger(__name__)
class MyGrantedNodesWithAssetsAsTreeApi(SerializeToTreeNodeMixin, ListAPIView): class MyGrantedNodesWithAssetsAsTreeApi(SerializeToTreeNodeMixin, ListAPIView):
permission_classes = (IsValidUser,) permission_classes = (IsValidUser,)
def add_ungrouped_resource(self, data: list, user, asset_perms_id):
if not settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
return
ungrouped_node = get_ungrouped_node(user, asset_perms_id=asset_perms_id)
direct_granted_assets = get_user_direct_granted_assets(
user, asset_perms_id=asset_perms_id
).annotate(
parent_key=Value(ungrouped_node.key, output_field=CharField())
).prefetch_related('platform')
data.extend(self.serialize_nodes([ungrouped_node], with_asset_amount=True))
data.extend(self.serialize_assets(direct_granted_assets))
def add_favorite_resource(self, data: list, user, asset_perms_id):
favorite_node = get_favorite_node(user, asset_perms_id)
favorite_assets = FavoriteAsset.get_user_favorite_assets(
user, asset_perms_id=asset_perms_id
).annotate(
parent_key=Value(favorite_node.key, output_field=CharField())
).prefetch_related('platform')
data.extend(self.serialize_nodes([favorite_node], with_asset_amount=True))
data.extend(self.serialize_assets(favorite_assets))
def add_node_filtered_by_system_user(self, data: list, user, asset_perms_id):
tmp_nodes = compute_tmp_mapping_node_from_perm(user, asset_perms_id=asset_perms_id)
granted_nodes_key = []
for _node in tmp_nodes:
_granted = getattr(_node, TMP_GRANTED_FIELD, False)
if not _granted:
if settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
assets_amount = count_direct_granted_node_assets(user, _node.key, asset_perms_id)
else:
assets_amount = count_node_all_granted_assets(user, _node.key, asset_perms_id)
_node.assets_amount = assets_amount
else:
granted_nodes_key.append(_node.key)
# 查询他们的子节点
q = Q()
for _key in granted_nodes_key:
q |= Q(key__startswith=f'{_key}:')
if q:
descendant_nodes = Node.objects.filter(q).distinct()
else:
descendant_nodes = Node.objects.none()
data.extend(self.serialize_nodes(chain(tmp_nodes, descendant_nodes), with_asset_amount=True))
def add_assets(self, data: list, user, asset_perms_id):
if settings.PERM_SINGLE_ASSET_TO_UNGROUP_NODE:
all_assets = get_user_granted_all_assets(
user,
via_mapping_node=False,
include_direct_granted_assets=False,
asset_perms_id=asset_perms_id
)
else:
all_assets = get_user_granted_all_assets(
user,
via_mapping_node=False,
include_direct_granted_assets=True,
asset_perms_id=asset_perms_id
)
all_assets = all_assets.annotate(
parent_key=F('nodes__key')
).prefetch_related('platform')
data.extend(self.serialize_assets(all_assets))
@tmp_to_root_org() @tmp_to_root_org()
def list(self, request: Request, *args, **kwargs): def list(self, request: Request, *args, **kwargs):
""" """
@ -38,16 +116,25 @@ class MyGrantedNodesWithAssetsAsTreeApi(SerializeToTreeNodeMixin, ListAPIView):
""" """
user = request.user user = request.user
rebuild_user_tree_if_need(request, user) data = []
all_nodes = get_user_granted_nodes_list_via_mapping_node(user) asset_perms_id = get_user_all_assetpermissions_id(user)
all_assets = get_user_granted_all_assets(user)
all_assets = all_assets.annotate(parent_key=F('nodes__key'))
all_assets = all_assets.prefetch_related('platform')
data = [ system_user_id = request.query_params.get('system_user')
*self.serialize_nodes(all_nodes, with_asset_amount=True), if system_user_id:
*self.serialize_assets(all_assets) asset_perms_id = list(AssetPermission.objects.valid().filter(
] id__in=asset_perms_id, system_users__id=system_user_id, actions__gt=0
).values_list('id', flat=True).distinct())
self.add_ungrouped_resource(data, user, asset_perms_id)
self.add_favorite_resource(data, user, asset_perms_id)
if system_user_id:
self.add_node_filtered_by_system_user(data, user, asset_perms_id)
else:
all_nodes = get_user_granted_nodes_list_via_mapping_node(user)
data.extend(self.serialize_nodes(all_nodes, with_asset_amount=True))
self.add_assets(data, user, asset_perms_id)
return Response(data=data) return Response(data=data)

View File

@ -311,8 +311,12 @@ def get_user_granted_nodes_list_via_mapping_node(user):
return all_nodes return all_nodes
def get_user_granted_all_assets(user, via_mapping_node=True): def get_user_granted_all_assets(
asset_perms_id = get_user_all_assetpermissions_id(user) user, via_mapping_node=True,
include_direct_granted_assets=True, asset_perms_id=None):
if asset_perms_id is None:
asset_perms_id = get_user_all_assetpermissions_id(user)
if via_mapping_node: if via_mapping_node:
granted_node_keys = UserGrantedMappingNode.objects.filter( granted_node_keys = UserGrantedMappingNode.objects.filter(
user=user, granted=True, user=user, granted=True,
@ -328,10 +332,16 @@ def get_user_granted_all_assets(user, via_mapping_node=True):
granted_node_q |= Q(nodes__key__startswith=f'{_key}:') granted_node_q |= Q(nodes__key__startswith=f'{_key}:')
granted_node_q |= Q(nodes__key=_key) granted_node_q |= Q(nodes__key=_key)
assets__id = get_user_direct_granted_assets(user, asset_perms_id).values_list('id', flat=True) if include_direct_granted_assets:
assets__id = get_user_direct_granted_assets(user, asset_perms_id).values_list('id', flat=True)
q = granted_node_q | Q(id__in=list(assets__id))
else:
q = granted_node_q
q = granted_node_q | Q(id__in=list(assets__id)) if q:
return Asset.org_objects.filter(q).distinct() return Asset.org_objects.filter(q).distinct()
else:
return Asset.org_objects.none()
def get_node_all_granted_assets(user: User, key): def get_node_all_granted_assets(user: User, key):
@ -484,13 +494,15 @@ def get_user_direct_granted_assets(user, asset_perms_id=None):
return assets return assets
def count_user_direct_granted_assets(user): def count_user_direct_granted_assets(user, asset_perms_id=None):
count = get_user_direct_granted_assets(user).values_list('id').count() count = get_user_direct_granted_assets(
user, asset_perms_id=asset_perms_id
).values_list('id').count()
return count return count
def get_ungrouped_node(user): def get_ungrouped_node(user, asset_perms_id=None):
assets_amount = count_user_direct_granted_assets(user) assets_amount = count_user_direct_granted_assets(user, asset_perms_id)
return Node( return Node(
id=UNGROUPED_NODE_KEY, id=UNGROUPED_NODE_KEY,
key=UNGROUPED_NODE_KEY, key=UNGROUPED_NODE_KEY,
@ -499,10 +511,10 @@ def get_ungrouped_node(user):
) )
def get_favorite_node(user): def get_favorite_node(user, asset_perms_id=None):
assets_amount = FavoriteAsset.get_user_favorite_assets(user)\ assets_amount = FavoriteAsset.get_user_favorite_assets(
.values_list('id')\ user, asset_perms_id=asset_perms_id
.count() ).values_list('id').count()
return Node( return Node(
id=FAVORITE_NODE_KEY, id=FAVORITE_NODE_KEY,
key=FAVORITE_NODE_KEY, key=FAVORITE_NODE_KEY,

View File

@ -279,6 +279,7 @@ class PublicSettingApi(generics.RetrieveAPIView):
"SECURITY_MFA_VERIFY_TTL": settings.SECURITY_MFA_VERIFY_TTL, "SECURITY_MFA_VERIFY_TTL": settings.SECURITY_MFA_VERIFY_TTL,
"SECURITY_COMMAND_EXECUTION": settings.SECURITY_COMMAND_EXECUTION, "SECURITY_COMMAND_EXECUTION": settings.SECURITY_COMMAND_EXECUTION,
"LOGIN_TITLE": settings.XPACK_INTERFACE_LOGIN_TITLE, "LOGIN_TITLE": settings.XPACK_INTERFACE_LOGIN_TITLE,
"SECURITY_PASSWORD_EXPIRATION_TIME": settings.SECURITY_PASSWORD_EXPIRATION_TIME,
"LOGO_URLS": settings.LOGO_URLS, "LOGO_URLS": settings.LOGO_URLS,
"TICKETS_ENABLED": settings.TICKETS_ENABLED, "TICKETS_ENABLED": settings.TICKETS_ENABLED,
"PASSWORD_RULE": { "PASSWORD_RULE": {

View File

@ -83,7 +83,7 @@ class SecuritySettingSerializer(serializers.Serializer):
SECURITY_PASSWORD_NUMBER = serializers.BooleanField(required=False) SECURITY_PASSWORD_NUMBER = serializers.BooleanField(required=False)
SECURITY_PASSWORD_SPECIAL_CHAR = serializers.BooleanField(required=False) SECURITY_PASSWORD_SPECIAL_CHAR = serializers.BooleanField(required=False)
SECURITY_INSECURE_COMMAND = serializers.BooleanField(required=False) SECURITY_INSECURE_COMMAND = serializers.BooleanField(required=False)
SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER = serializers.CharField(max_length=8192, required=False) SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER = serializers.CharField(max_length=8192, required=False, allow_blank=True)
class SettingsSerializer(serializers.Serializer): class SettingsSerializer(serializers.Serializer):

View File

@ -49,16 +49,26 @@ class RequestAssetPermTicketViewSet(JMSModelViewSet):
def _get_extra_comment(self, instance): def _get_extra_comment(self, instance):
meta = instance.meta meta = instance.meta
ips = ', '.join(meta.get('ips', [])) ips = ', '.join(meta.get('ips', []))
confirmed_assets = ', '.join(meta.get('confirmed_assets', [])) confirmed_assets_id = meta.get('confirmed_assets', [])
confirmed_system_users = ', '.join(meta.get('confirmed_system_users', [])) confirmed_system_users_id = meta.get('confirmed_system_users', [])
confirmed_assets = Asset.objects.filter(id__in=confirmed_assets_id)
confirmed_system_users = SystemUser.objects.filter(id__in=confirmed_system_users_id)
confirmed_assets_display = ', '.join([str(i) for i in confirmed_assets])
confirmed_system_users_display = ', '.join([str(i) for i in confirmed_system_users])
return textwrap.dedent(f'''\ return textwrap.dedent('''
{_('IP group')}: {ips} {}: {}
{_('Hostname')}: {meta.get('hostname', '')} {}: {}
{_('System user')}: {meta.get('system_user', '')} {}: {}
{_('Confirmed assets')}: {confirmed_assets} {}: {}
{_('Confirmed system users')}: {confirmed_system_users} {}: {}
''') '''.format(
_('IP group'), ips,
_('Hostname'), meta.get('hostname', ''),
_('System user'), meta.get('system_user', ''),
_('Confirmed assets'), confirmed_assets_display,
_('Confirmed system users'), confirmed_system_users_display
))
@action(detail=True, methods=[POST], permission_classes=[IsAssignee, IsValidUser]) @action(detail=True, methods=[POST], permission_classes=[IsAssignee, IsValidUser])
def reject(self, request, *args, **kwargs): def reject(self, request, *args, **kwargs):