mirror of https://github.com/jumpserver/jumpserver
perf: 账号管理api
parent
389094f615
commit
108ccf5a8b
|
@ -1,45 +1,19 @@
|
|||
from django_filters import rest_framework as filters
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.generics import CreateAPIView
|
||||
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
from rbac.permissions import RBACPermission
|
||||
from common.drf.filters import BaseFilterSet, UUIDInFilter
|
||||
|
||||
from common.mixins import RecordViewLogMixin
|
||||
from common.permissions import UserConfirmation
|
||||
from authentication.const import ConfirmType
|
||||
from assets.models import Account
|
||||
from assets.filters import AccountFilterSet
|
||||
from assets.tasks.account_connectivity import test_accounts_connectivity_manual
|
||||
from assets.models import Account, Node
|
||||
from assets import serializers
|
||||
|
||||
__all__ = ['AccountFilterSet', 'AccountViewSet', 'AccountSecretsViewSet', 'AccountTaskCreateAPI']
|
||||
|
||||
|
||||
class AccountFilterSet(BaseFilterSet):
|
||||
ip = filters.CharFilter(field_name='ip', lookup_expr='exact')
|
||||
hostname = filters.CharFilter(field_name='name', lookup_expr='exact')
|
||||
username = filters.CharFilter(field_name="username", lookup_expr='exact')
|
||||
assets = UUIDInFilter(field_name='asset_id', lookup_expr='in')
|
||||
nodes = UUIDInFilter(method='filter_nodes')
|
||||
|
||||
def filter_nodes(self, queryset, name, value):
|
||||
nodes = Node.objects.filter(id__in=value)
|
||||
if not nodes:
|
||||
return queryset
|
||||
|
||||
node_qs = Node.objects.none()
|
||||
for node in nodes:
|
||||
node_qs |= node.get_all_children(with_self=True)
|
||||
node_ids = list(node_qs.values_list('id', flat=True))
|
||||
queryset = queryset.filter(asset__nodes__in=node_ids)
|
||||
return queryset
|
||||
|
||||
class Meta:
|
||||
model = Account
|
||||
fields = [
|
||||
'asset', 'id'
|
||||
]
|
||||
__all__ = ['AccountViewSet', 'AccountSecretsViewSet', 'AccountTaskCreateAPI']
|
||||
|
||||
|
||||
class AccountViewSet(OrgBulkModelViewSet):
|
||||
|
@ -52,7 +26,7 @@ class AccountViewSet(OrgBulkModelViewSet):
|
|||
'verify': serializers.AssetTaskSerializer
|
||||
}
|
||||
rbac_perms = {
|
||||
'verify': 'assets.test_authbook',
|
||||
'verify': 'assets.test_account',
|
||||
'partial_update': 'assets.change_assetaccountsecret',
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
from .account import (
|
||||
AccountFilterSet, AccountViewSet, AccountSecretsViewSet
|
||||
)
|
||||
from common.mixins import RecordViewLogMixin
|
||||
from assets import serializers
|
||||
from assets.models import Account
|
||||
from assets.filters import AccountFilterSet
|
||||
from common.mixins import RecordViewLogMixin
|
||||
from .account import AccountViewSet, AccountSecretsViewSet
|
||||
|
||||
__all__ = ['AccountHistoryViewSet', 'AccountHistorySecretsViewSet']
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from rest_framework.compat import coreapi, coreschema
|
||||
from rest_framework import filters
|
||||
from django.db.models import Q
|
||||
from rest_framework import filters
|
||||
from rest_framework.compat import coreapi, coreschema
|
||||
|
||||
from .models import Label
|
||||
from common.drf.filters import BaseFilterSet, UUIDInFilter
|
||||
from assets.utils import is_query_node_all_assets, get_node_from_request
|
||||
from .models import Label, Node, Account
|
||||
|
||||
|
||||
class AssetByNodeFilterBackend(filters.BaseFilterBackend):
|
||||
|
@ -154,3 +154,30 @@ class IpInFilterBackend(filters.BaseFilterBackend):
|
|||
)
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
class AccountFilterSet(BaseFilterSet):
|
||||
from django_filters import rest_framework as filters
|
||||
ip = filters.CharFilter(field_name='ip', lookup_expr='exact')
|
||||
hostname = filters.CharFilter(field_name='name', lookup_expr='exact')
|
||||
username = filters.CharFilter(field_name="username", lookup_expr='exact')
|
||||
assets = UUIDInFilter(field_name='asset_id', lookup_expr='in')
|
||||
nodes = UUIDInFilter(method='filter_nodes')
|
||||
|
||||
def filter_nodes(self, queryset, name, value):
|
||||
nodes = Node.objects.filter(id__in=value)
|
||||
if not nodes:
|
||||
return queryset
|
||||
|
||||
node_qs = Node.objects.none()
|
||||
for node in nodes:
|
||||
node_qs |= node.get_all_children(with_self=True)
|
||||
node_ids = list(node_qs.values_list('id', flat=True))
|
||||
queryset = queryset.filter(asset__nodes__in=node_ids)
|
||||
return queryset
|
||||
|
||||
class Meta:
|
||||
model = Account
|
||||
fields = [
|
||||
'asset', 'id'
|
||||
]
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
from django.db.models import F
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
|
@ -21,20 +20,20 @@ class AccountSerializerCreateMixin(serializers.ModelSerializer):
|
|||
|
||||
@staticmethod
|
||||
def validate_template(value):
|
||||
AccountTemplate.objects.get_or_create()
|
||||
model = AccountTemplate
|
||||
try:
|
||||
return model.objects.get(id=value)
|
||||
return AccountTemplate.objects.get(id=value)
|
||||
except AccountTemplate.DoesNotExist:
|
||||
raise serializers.ValidationError(_('Account template not found'))
|
||||
|
||||
@staticmethod
|
||||
def replace_attrs(account_template: AccountTemplate, attrs: dict):
|
||||
exclude_fields = [
|
||||
'_state', 'org_id', 'date_verified', 'id',
|
||||
'date_created', 'date_updated', 'created_by'
|
||||
'_state', 'org_id', 'id', 'date_created', 'date_updated'
|
||||
]
|
||||
template_attrs = {k: v for k, v in account_template.__dict__.items() if k not in exclude_fields}
|
||||
template_attrs = {
|
||||
k: v for k, v in account_template.__dict__.items()
|
||||
if k not in exclude_fields
|
||||
}
|
||||
for k, v in template_attrs.items():
|
||||
attrs.setdefault(k, v)
|
||||
|
||||
|
@ -48,17 +47,19 @@ class AccountSerializerCreateMixin(serializers.ModelSerializer):
|
|||
def create(self, validated_data):
|
||||
instance = super().create(validated_data)
|
||||
if self.push_now:
|
||||
print("Start push account to asset")
|
||||
# Todo: push it
|
||||
pass
|
||||
print("Start push account to asset")
|
||||
return instance
|
||||
|
||||
|
||||
class AccountSerializer(AuthValidateMixin,
|
||||
AccountSerializerCreateMixin,
|
||||
AccountFieldsSerializerMixin,
|
||||
BulkOrgResourceModelSerializer):
|
||||
asset = ObjectRelatedField(required=False, queryset=Asset.objects, label=_('Asset'), attrs=('id', 'name', 'ip'))
|
||||
class AccountSerializer(
|
||||
AuthValidateMixin, AccountSerializerCreateMixin,
|
||||
AccountFieldsSerializerMixin, BulkOrgResourceModelSerializer
|
||||
):
|
||||
asset = ObjectRelatedField(
|
||||
required=False, queryset=Asset.objects,
|
||||
label=_('Asset'), attrs=('id', 'name', 'ip')
|
||||
)
|
||||
platform = serializers.ReadOnlyField(label=_("Platform"))
|
||||
|
||||
class Meta(AccountFieldsSerializerMixin.Meta):
|
||||
|
|
|
@ -74,7 +74,7 @@ def test_user_connectivity(task_name, asset, username, password=None, private_ke
|
|||
@org_aware_func("account")
|
||||
def test_account_connectivity_util(account, task_name):
|
||||
"""
|
||||
:param account: <AuthBook>对象
|
||||
:param account: <Account>对象
|
||||
:param task_name:
|
||||
:return:
|
||||
"""
|
||||
|
@ -101,7 +101,7 @@ def test_account_connectivity_util(account, task_name):
|
|||
@shared_task(queue="ansible")
|
||||
def test_accounts_connectivity_manual(accounts):
|
||||
"""
|
||||
:param accounts: <AuthBook>对象
|
||||
:param accounts: <Account>对象
|
||||
"""
|
||||
for account in accounts:
|
||||
task_name = gettext_noop("Test account connectivity: ") + str(account)
|
||||
|
|
|
@ -35,14 +35,14 @@ exclude_permissions = (
|
|||
('assets', 'assetgroup', '*', '*'),
|
||||
('assets', 'cluster', '*', '*'),
|
||||
('assets', 'favoriteasset', '*', '*'),
|
||||
('assets', 'historicalauthbook', '*', '*'),
|
||||
('assets', 'historicalaccount', '*', '*'),
|
||||
('assets', 'assetuser', '*', '*'),
|
||||
('assets', 'gathereduser', 'add,delete,change', 'gathereduser'),
|
||||
('assets', 'accountbackupplanexecution', 'delete,change', 'accountbackupplanexecution'),
|
||||
('assets', 'authbook', 'change', 'authbook'),
|
||||
('assets', 'account', 'change', 'account'),
|
||||
# TODO 暂时去掉历史账号的权限
|
||||
('assets', 'authbook', '*', 'assethistoryaccount'),
|
||||
('assets', 'authbook', '*', 'assethistoryaccountsecret'),
|
||||
('assets', 'account', '*', 'assethistoryaccount'),
|
||||
('assets', 'account', '*', 'assethistoryaccountsecret'),
|
||||
|
||||
('perms', 'userassetgrantedtreenoderelation', '*', '*'),
|
||||
('perms', 'usergrantedmappingnode', '*', '*'),
|
||||
|
|
|
@ -61,7 +61,7 @@ extra_nodes_data = [
|
|||
# 将 model 放到其它节点下,而不是本来的 app 中
|
||||
special_pid_mapper = {
|
||||
'common.permission': 'view_other',
|
||||
"assets.authbook": "accounts",
|
||||
"assets.account": "accounts",
|
||||
"applications.account": "accounts",
|
||||
'xpack.account': 'cloud_import',
|
||||
'xpack.syncinstancedetail': 'cloud_import',
|
||||
|
|
Loading…
Reference in New Issue