Merge pull request #6224 from jumpserver/feat_account_manager

feat: 添加账号管理相关API
pull/6231/head
Jiangjie.Bai 2021-06-04 11:15:53 +08:00 committed by GitHub
commit f26483c9cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 109 additions and 79 deletions

View File

@ -2,18 +2,49 @@
#
from orgs.mixins.api import OrgBulkModelViewSet
from rest_framework import generics
from ..hands import IsOrgAdminOrAppUser
from ..hands import IsOrgAdminOrAppUser, IsOrgAdmin
from .. import models, serializers
from ..models import Application
from assets.models import SystemUser
from assets.serializers import SystemUserListSerializer
from perms.models import ApplicationPermission
from ..const import ApplicationCategoryChoices
__all__ = ['ApplicationViewSet']
__all__ = ['ApplicationViewSet', 'ApplicationUserListApi']
class ApplicationViewSet(OrgBulkModelViewSet):
model = models.Application
model = Application
filterset_fields = ('name', 'type', 'category')
search_fields = filterset_fields
permission_classes = (IsOrgAdminOrAppUser,)
serializer_class = serializers.ApplicationSerializer
class ApplicationUserListApi(generics.ListAPIView):
permission_classes = (IsOrgAdmin, )
filterset_fields = ('name', 'username')
search_fields = filterset_fields
serializer_class = SystemUserListSerializer
def get_application(self):
application = None
app_id = self.request.query_params.get('application_id')
if app_id:
application = Application.objects.get(id=app_id)
return application
def get_queryset(self):
queryset = SystemUser.objects.none()
application = self.get_application()
if not application:
return queryset
system_user_ids = ApplicationPermission.objects.filter(applications=application)\
.values_list('system_users', flat=True)
if not system_user_ids:
return queryset
queryset = SystemUser.objects.filter(id__in=system_user_ids)
return queryset

View File

@ -14,6 +14,7 @@ router.register(r'applications', api.ApplicationViewSet, 'application')
urlpatterns = [
path('remote-apps/<uuid:pk>/connection-info/', api.RemoteAppConnectionInfoApi.as_view(), name='remote-app-connection-info'),
path('application-users/', api.ApplicationUserListApi.as_view(), name='application-user')
]

View File

@ -31,11 +31,11 @@ class BaseBackend:
def qs_to_values(qs):
values = qs.values(
'hostname', 'ip', "asset_id",
'username', 'password', 'private_key', 'public_key',
'name', 'username', 'password', 'private_key', 'public_key',
'score', 'version',
"asset_username", "union_id",
'date_created', 'date_updated',
'org_id', 'backend',
'org_id', 'backend', 'backend_display'
)
return values

View File

@ -106,6 +106,7 @@ class DBBackend(BaseBackend):
class SystemUserBackend(DBBackend):
model = SystemUser.assets.through
backend = 'system_user'
backend_display = _('System user')
prefer = backend
base_score = 0
union_id_length = 2
@ -138,6 +139,7 @@ class SystemUserBackend(DBBackend):
kwargs = dict(
hostname=F("asset__hostname"),
ip=F("asset__ip"),
name=F("systemuser__name"),
username=F("systemuser__username"),
password=F("systemuser__password"),
private_key=F("systemuser__private_key"),
@ -152,7 +154,8 @@ class SystemUserBackend(DBBackend):
union_id=Concat(F("systemuser_id"), Value("_"), F("asset_id"),
output_field=CharField()),
org_id=F("asset__org_id"),
backend=Value(self.backend, CharField())
backend=Value(self.backend, CharField()),
backend_display=Value(self.backend_display, CharField()),
)
return kwargs
@ -174,12 +177,17 @@ class SystemUserBackend(DBBackend):
class DynamicSystemUserBackend(SystemUserBackend):
backend = 'system_user_dynamic'
backend_display = _('System user(Dynamic)')
prefer = 'system_user'
union_id_length = 3
def get_annotate(self):
kwargs = super().get_annotate()
kwargs.update(dict(
name=Concat(
F("systemuser__users__name"), Value('('), F("systemuser__name"), Value(')'),
output_field=CharField()
),
username=F("systemuser__users__username"),
asset_username=Concat(
F("asset__id"), Value("_"),
@ -221,6 +229,7 @@ class DynamicSystemUserBackend(SystemUserBackend):
class AdminUserBackend(DBBackend):
model = Asset
backend = 'admin_user'
backend_display = _('Admin user')
prefer = backend
base_score = 200
@ -246,6 +255,7 @@ class AdminUserBackend(DBBackend):
def all(self):
qs = self.model.objects.all().annotate(
asset_id=F("id"),
name=F("admin_user__name"),
username=F("admin_user__username"),
password=F("admin_user__password"),
private_key=F("admin_user__private_key"),
@ -256,6 +266,7 @@ class AdminUserBackend(DBBackend):
asset_username=Concat(F("id"), Value("_"), F("admin_user__username"), output_field=CharField()),
union_id=Concat(F("admin_user_id"), Value("_"), F("id"), output_field=CharField()),
backend=Value(self.backend, CharField()),
backend_display=Value(self.backend_display, CharField()),
)
qs = self.qs_to_values(qs)
return qs
@ -264,6 +275,7 @@ class AdminUserBackend(DBBackend):
class AuthbookBackend(DBBackend):
model = AuthBook
backend = 'db'
backend_display = _('Database')
prefer = backend
base_score = 400
@ -313,6 +325,7 @@ class AuthbookBackend(DBBackend):
asset_username=Concat(F("asset__id"), Value("_"), F("username"), output_field=CharField()),
union_id=Concat(F("id"), Value("_"), F("asset_id"), output_field=CharField()),
backend=Value(self.backend, CharField()),
backend_display=Value(self.backend_display, CharField()),
)
qs = self.qs_to_values(qs)
return qs

View File

@ -7,6 +7,7 @@ class AssetUser(AuthBook):
hostname = ""
ip = ""
backend = ""
backend_display = ""
union_id = ""
asset_username = ""

View File

@ -47,16 +47,17 @@ class AssetUserReadSerializer(AssetUserWriteSerializer):
ip = serializers.CharField(read_only=True, label=_("IP"))
asset = serializers.CharField(source='asset_id', label=_('Asset'))
backend = serializers.CharField(read_only=True, label=_("Backend"))
backend_display = serializers.CharField(read_only=True, label=_("Source"))
class Meta(AssetUserWriteSerializer.Meta):
read_only_fields = (
'date_created', 'date_updated',
'created_by', 'version',
)
fields_mini = ['id', 'username']
fields_mini = ['id', 'name', 'username']
fields_write_only = ['password', 'private_key', "public_key"]
fields_small = fields_mini + fields_write_only + [
'backend', 'version',
'backend', 'backend_display', 'version',
'date_created', "date_updated",
'comment'
]

Binary file not shown.

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: JumpServer 0.3.3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-05-22 16:56+0800\n"
"POT-Creation-Date: 2021-06-04 11:11+0800\n"
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
"Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: JumpServer team<ibuler@qq.com>\n"
@ -121,7 +121,7 @@ msgstr "系统用户"
#: applications/serializers/attrs/application_category/remote_app.py:33
#: assets/models/asset.py:355 assets/models/authbook.py:26
#: assets/models/gathered_user.py:14 assets/serializers/admin_user.py:34
#: assets/serializers/asset_user.py:48 assets/serializers/asset_user.py:89
#: assets/serializers/asset_user.py:48 assets/serializers/asset_user.py:90
#: assets/serializers/system_user.py:201 audits/models.py:38
#: perms/models/asset_permission.py:99 templates/index.html:82
#: terminal/backends/command/models.py:19
@ -184,7 +184,7 @@ msgstr "格式为逗号分隔的字符串, * 表示匹配所有. "
#: users/templates/users/_select_user_modal.html:14
#: xpack/plugins/change_auth_plan/models.py:47
#: xpack/plugins/change_auth_plan/models.py:278
#: xpack/plugins/cloud/serializers.py:51
#: xpack/plugins/cloud/serializers.py:65
msgid "Username"
msgstr "用户名"
@ -233,6 +233,7 @@ msgstr "所有复核人都不属于组织 `{}`"
#: applications/const.py:9
#: applications/serializers/attrs/application_category/db.py:14
#: applications/serializers/attrs/application_type/mysql_workbench.py:26
#: assets/backends/db.py:278
msgid "Database"
msgstr "数据库"
@ -285,7 +286,7 @@ msgid "Cluster"
msgstr "集群"
#: applications/serializers/attrs/application_category/db.py:11
#: ops/models/adhoc.py:146 xpack/plugins/cloud/serializers.py:49
#: ops/models/adhoc.py:146 xpack/plugins/cloud/serializers.py:63
msgid "Host"
msgstr "主机"
@ -295,7 +296,7 @@ msgstr "主机"
#: applications/serializers/attrs/application_type/oracle.py:11
#: applications/serializers/attrs/application_type/pgsql.py:11
#: assets/models/asset.py:188 assets/models/domain.py:53
#: xpack/plugins/cloud/serializers.py:50
#: xpack/plugins/cloud/serializers.py:64
msgid "Port"
msgstr "端口"
@ -315,7 +316,7 @@ msgstr "目标URL"
#: applications/serializers/attrs/application_type/custom.py:25
#: applications/serializers/attrs/application_type/mysql_workbench.py:34
#: applications/serializers/attrs/application_type/vmware_client.py:30
#: assets/models/base.py:252 assets/serializers/asset_user.py:76
#: assets/models/base.py:252 assets/serializers/asset_user.py:77
#: audits/signals_handler.py:58 authentication/forms.py:22
#: authentication/templates/authentication/login.html:164
#: settings/serializers/settings.py:93 users/forms/profile.py:21
@ -325,7 +326,7 @@ msgstr "目标URL"
#: xpack/plugins/change_auth_plan/models.py:68
#: xpack/plugins/change_auth_plan/models.py:190
#: xpack/plugins/change_auth_plan/models.py:285
#: xpack/plugins/cloud/serializers.py:53
#: xpack/plugins/cloud/serializers.py:67
msgid "Password"
msgstr "密码"
@ -357,11 +358,35 @@ msgstr "不能删除根节点 ({})"
msgid "Deletion failed and the node contains assets"
msgstr "删除失败,节点包含资产"
#: assets/backends/db.py:244
#: assets/backends/db.py:109 assets/models/user.py:228 audits/models.py:39
#: perms/models/application_permission.py:31
#: perms/models/asset_permission.py:101 templates/_nav.html:45
#: terminal/backends/command/models.py:20
#: terminal/backends/command/serializers.py:14 terminal/models/session.py:42
#: users/templates/users/_granted_assets.html:27
#: users/templates/users/user_asset_permission.html:42
#: users/templates/users/user_asset_permission.html:76
#: users/templates/users/user_asset_permission.html:159
#: users/templates/users/user_database_app_permission.html:40
#: users/templates/users/user_database_app_permission.html:67
msgid "System user"
msgstr "系统用户"
#: assets/backends/db.py:180
msgid "System user(Dynamic)"
msgstr "系统用户(动态)"
#: assets/backends/db.py:232 assets/models/asset.py:196
#: assets/models/cluster.py:19 assets/models/user.py:66 templates/_nav.html:44
#: xpack/plugins/cloud/models.py:92 xpack/plugins/cloud/serializers.py:160
msgid "Admin user"
msgstr "管理用户"
#: assets/backends/db.py:253
msgid "Could not remove asset admin user"
msgstr "不能移除资产的管理用户账号"
#: assets/backends/db.py:305
#: assets/backends/db.py:317
msgid "Latest version could not be delete"
msgstr "最新版本的不能被删除"
@ -405,12 +430,6 @@ msgstr "节点"
msgid "Is active"
msgstr "激活"
#: assets/models/asset.py:196 assets/models/cluster.py:19
#: assets/models/user.py:66 templates/_nav.html:44
#: xpack/plugins/cloud/models.py:92 xpack/plugins/cloud/serializers.py:146
msgid "Admin user"
msgstr "管理用户"
#: assets/models/asset.py:199
msgid "Public IP"
msgstr "公网IP"
@ -678,7 +697,7 @@ msgstr "ssh私钥"
#: users/templates/users/user_asset_permission.html:41
#: users/templates/users/user_asset_permission.html:73
#: users/templates/users/user_asset_permission.html:158
#: xpack/plugins/cloud/models.py:89 xpack/plugins/cloud/serializers.py:147
#: xpack/plugins/cloud/models.py:89 xpack/plugins/cloud/serializers.py:161
msgid "Node"
msgstr "节点"
@ -740,20 +759,6 @@ msgstr "家目录"
msgid "System groups"
msgstr "用户组"
#: assets/models/user.py:228 audits/models.py:39
#: perms/models/application_permission.py:31
#: perms/models/asset_permission.py:101 templates/_nav.html:45
#: terminal/backends/command/models.py:20
#: terminal/backends/command/serializers.py:14 terminal/models/session.py:42
#: users/templates/users/_granted_assets.html:27
#: users/templates/users/user_asset_permission.html:42
#: users/templates/users/user_asset_permission.html:76
#: users/templates/users/user_asset_permission.html:159
#: users/templates/users/user_database_app_permission.html:40
#: users/templates/users/user_database_app_permission.html:67
msgid "System user"
msgstr "系统用户"
#: assets/models/utils.py:35
#, python-format
msgid "%(value)s is not an even number"
@ -813,12 +818,16 @@ msgstr "ID"
msgid "Backend"
msgstr "后端"
#: assets/serializers/asset_user.py:80 users/forms/profile.py:160
#: assets/serializers/asset_user.py:50
msgid "Source"
msgstr "来源"
#: assets/serializers/asset_user.py:81 users/forms/profile.py:160
#: users/models/user.py:580 users/templates/users/user_password_update.html:48
msgid "Public key"
msgstr "SSH公钥"
#: assets/serializers/asset_user.py:84 users/models/user.py:577
#: assets/serializers/asset_user.py:85 users/models/user.py:577
msgid "Private key"
msgstr "ssh私钥"
@ -3890,7 +3899,7 @@ msgid "Wechat"
msgstr "微信"
#: users/models/user.py:596
msgid "Source"
msgid "User source"
msgstr "用户来源"
#: users/models/user.py:600
@ -4003,7 +4012,7 @@ msgid "Security token validation"
msgstr "安全令牌验证"
#: users/templates/users/_base_otp.html:14 xpack/plugins/cloud/models.py:78
#: xpack/plugins/cloud/serializers.py:145
#: xpack/plugins/cloud/serializers.py:159
msgid "Account"
msgstr "账户"
@ -4744,7 +4753,7 @@ msgstr "云服务商"
msgid "Cloud account"
msgstr "云账号"
#: xpack/plugins/cloud/models.py:81 xpack/plugins/cloud/serializers.py:126
#: xpack/plugins/cloud/models.py:81 xpack/plugins/cloud/serializers.py:140
msgid "Regions"
msgstr "地域"
@ -4752,7 +4761,7 @@ msgstr "地域"
msgid "Hostname strategy"
msgstr "主机名策略"
#: xpack/plugins/cloud/models.py:95 xpack/plugins/cloud/serializers.py:149
#: xpack/plugins/cloud/models.py:95 xpack/plugins/cloud/serializers.py:163
msgid "Always update"
msgstr "总是更新"
@ -4944,20 +4953,24 @@ msgstr ""
msgid "Subscription ID"
msgstr ""
#: xpack/plugins/cloud/serializers.py:124
#: xpack/plugins/cloud/serializers.py:49
msgid "This field is required"
msgstr "这个字段是必填项"
#: xpack/plugins/cloud/serializers.py:138
msgid "History count"
msgstr "执行次数"
#: xpack/plugins/cloud/serializers.py:125
#: xpack/plugins/cloud/serializers.py:139
msgid "Instance count"
msgstr "实例个数"
#: xpack/plugins/cloud/serializers.py:148
#: xpack/plugins/cloud/serializers.py:162
#: xpack/plugins/gathered_user/serializers.py:20
msgid "Periodic display"
msgstr "定时执行"
#: xpack/plugins/cloud/utils.py:64
#: xpack/plugins/cloud/utils.py:65
msgid "Account unavailable"
msgstr "账户无效"
@ -5044,33 +5057,3 @@ msgstr "旗舰版"
#: xpack/plugins/license/models.py:77
msgid "Community edition"
msgstr "社区版"
#~ msgid "This field is required"
#~ msgstr "这个字段是必填项"
#~ msgid "{} is required"
#~ msgstr "{} 字段是必填项"
#~ msgid "AppSecret is required"
#~ msgstr "AppSecret 是必须的"
#~ msgid "Corporation ID(corpid)"
#~ msgstr "企业 ID(CorpId)"
#~ msgid "Agent ID(agentid)"
#~ msgstr "应用 ID(AgentId)"
#~ msgid "Secret(secret)"
#~ msgstr "秘钥(secret)"
#~ msgid "AgentId"
#~ msgstr "应用 ID(AgentId)"
#~ msgid "AppKey"
#~ msgstr "应用 Key(AppKey)"
#~ msgid "AppSecret"
#~ msgstr "应用密文(AppSecret)"
#~ msgid "No"
#~ msgstr "无"

View File

@ -593,7 +593,7 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser):
source = models.CharField(
max_length=30, default=Source.local,
choices=Source.choices,
verbose_name=_('Source')
verbose_name=_('User source')
)
date_password_last_updated = models.DateTimeField(
auto_now_add=True, blank=True, null=True,