mirror of https://github.com/jumpserver/jumpserver
perf: 修改系统用户
parent
43d3791ddc
commit
fb0fb71ea3
|
@ -1,9 +1,7 @@
|
|||
from .mixin import *
|
||||
from .admin_user import *
|
||||
from .asset import *
|
||||
from .label import *
|
||||
from .system_user import *
|
||||
from .system_user_relation import *
|
||||
from .accounts import *
|
||||
from .node import *
|
||||
from .domain import *
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
from django.db.models import Count
|
||||
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
from common.utils import get_logger
|
||||
from ..models import SystemUser
|
||||
from .. import serializers
|
||||
from rbac.permissions import RBACPermission
|
||||
|
||||
|
||||
logger = get_logger(__file__)
|
||||
__all__ = ['AdminUserViewSet']
|
||||
|
||||
|
||||
# 兼容一下老的 api
|
||||
class AdminUserViewSet(OrgBulkModelViewSet):
|
||||
"""
|
||||
Admin user api set, for add,delete,update,list,retrieve resource
|
||||
"""
|
||||
model = SystemUser
|
||||
filterset_fields = ("name", "username")
|
||||
search_fields = filterset_fields
|
||||
serializer_class = serializers.AdminUserSerializer
|
||||
permission_classes = (RBACPermission,)
|
||||
ordering_fields = ('name',)
|
||||
ordering = ('name', )
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset().filter(type=SystemUser.Type.admin)
|
||||
queryset = queryset.annotate(assets_amount=Count('assets'))
|
||||
return queryset
|
|
@ -42,7 +42,6 @@ class AssetViewSet(SuggestionMixin, FilterAssetByNodeMixin, OrgBulkModelViewSet)
|
|||
filterset_fields = {
|
||||
'hostname': ['exact'],
|
||||
'ip': ['exact'],
|
||||
'system_users__id': ['exact'],
|
||||
'platform__base': ['exact'],
|
||||
'is_active': ['exact'],
|
||||
'protocols': ['exact', 'icontains']
|
||||
|
|
|
@ -5,23 +5,17 @@ from rest_framework.decorators import action
|
|||
from rest_framework.viewsets import GenericViewSet
|
||||
|
||||
from common.utils import get_logger, get_object_or_none
|
||||
from common.permissions import IsValidUser
|
||||
from common.mixins.api import SuggestionMixin
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
from orgs.mixins import generics
|
||||
from orgs.utils import tmp_to_root_org
|
||||
from ..models import SystemUser, CommandFilterRule, Account
|
||||
from .. import serializers
|
||||
from ..tasks import (
|
||||
push_system_user_to_assets_manual, test_system_user_connectivity_manual,
|
||||
push_system_user_to_assets
|
||||
)
|
||||
|
||||
logger = get_logger(__file__)
|
||||
__all__ = [
|
||||
'SystemUserViewSet', 'SystemUserAuthInfoApi', 'SystemUserAssetAuthInfoApi',
|
||||
'SystemUserCommandFilterRuleListApi', 'SystemUserTaskApi', 'SystemUserAssetsListView',
|
||||
'SystemUserTempAuthInfoApi', 'SystemUserAppAuthInfoApi', 'SystemUserAssetAccountApi',
|
||||
'SystemUserViewSet', 'SystemUserAuthInfoApi',
|
||||
'SystemUserCommandFilterRuleListApi',
|
||||
'SystemUserAssetAccountApi',
|
||||
'SystemUserAssetAccountSecretApi',
|
||||
]
|
||||
|
||||
|
@ -35,7 +29,6 @@ class SystemUserViewSet(SuggestionMixin, OrgBulkModelViewSet):
|
|||
'name': ['exact'],
|
||||
'username': ['exact'],
|
||||
'protocol': ['exact', 'in'],
|
||||
'type': ['exact', 'in'],
|
||||
}
|
||||
search_fields = filterset_fields
|
||||
serializer_class = serializers.SystemUserSerializer
|
||||
|
@ -154,116 +147,6 @@ class SystemUserAuthInfoApi(generics.RetrieveUpdateDestroyAPIView):
|
|||
return Response(status=204)
|
||||
|
||||
|
||||
class SystemUserTempAuthInfoApi(generics.CreateAPIView):
|
||||
model = SystemUser
|
||||
permission_classes = (IsValidUser,)
|
||||
serializer_class = serializers.SystemUserTempAuthSerializer
|
||||
|
||||
def create(self, request, *args, **kwargs):
|
||||
serializer = super().get_serializer(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
pk = kwargs.get('pk')
|
||||
data = serializer.validated_data
|
||||
asset_or_app_id = data.get('instance_id')
|
||||
|
||||
with tmp_to_root_org():
|
||||
instance = get_object_or_404(SystemUser, pk=pk)
|
||||
instance.set_temp_auth(asset_or_app_id, self.request.user.id, data)
|
||||
return Response(serializer.data, status=201)
|
||||
|
||||
|
||||
class SystemUserAssetAuthInfoApi(generics.RetrieveAPIView):
|
||||
"""
|
||||
Get system user with asset auth info
|
||||
"""
|
||||
model = SystemUser
|
||||
serializer_class = serializers.SystemUserWithAuthInfoSerializer
|
||||
|
||||
def get_object(self):
|
||||
instance = super().get_object()
|
||||
asset_id = self.kwargs.get('asset_id')
|
||||
user_id = self.request.query_params.get("user_id")
|
||||
username = self.request.query_params.get("username")
|
||||
instance.load_asset_more_auth(asset_id, username, user_id)
|
||||
return instance
|
||||
|
||||
|
||||
class SystemUserAppAuthInfoApi(generics.RetrieveAPIView):
|
||||
"""
|
||||
Get system user with asset auth info
|
||||
"""
|
||||
model = SystemUser
|
||||
serializer_class = serializers.SystemUserWithAuthInfoSerializer
|
||||
rbac_perms = {
|
||||
'retrieve': 'assets.view_systemusersecret',
|
||||
}
|
||||
|
||||
def get_object(self):
|
||||
instance = super().get_object()
|
||||
app_id = self.kwargs.get('app_id')
|
||||
user_id = self.request.query_params.get("user_id")
|
||||
username = self.request.query_params.get("username")
|
||||
instance.load_app_more_auth(app_id, username, user_id)
|
||||
return instance
|
||||
|
||||
|
||||
class SystemUserTaskApi(generics.CreateAPIView):
|
||||
serializer_class = serializers.SystemUserTaskSerializer
|
||||
|
||||
def do_push(self, system_user, asset_ids=None):
|
||||
if asset_ids is None:
|
||||
task = push_system_user_to_assets_manual.delay(system_user)
|
||||
else:
|
||||
username = self.request.query_params.get('username')
|
||||
task = push_system_user_to_assets.delay(
|
||||
system_user.id, asset_ids, username=username
|
||||
)
|
||||
return task
|
||||
|
||||
@staticmethod
|
||||
def do_test(system_user, asset_ids):
|
||||
task = test_system_user_connectivity_manual.delay(system_user, asset_ids)
|
||||
return task
|
||||
|
||||
def get_object(self):
|
||||
pk = self.kwargs.get('pk')
|
||||
return get_object_or_404(SystemUser, pk=pk)
|
||||
|
||||
def check_permissions(self, request):
|
||||
action = request.data.get('action')
|
||||
action_perm_require = {
|
||||
'push': 'assets.push_assetsystemuser',
|
||||
'test': 'assets.test_assetconnectivity'
|
||||
}
|
||||
perm_required = action_perm_require.get(action)
|
||||
has = self.request.user.has_perm(perm_required)
|
||||
|
||||
if not has:
|
||||
self.permission_denied(request)
|
||||
|
||||
def perform_create(self, serializer):
|
||||
action = serializer.validated_data["action"]
|
||||
asset = serializer.validated_data.get('asset')
|
||||
|
||||
if asset:
|
||||
assets = [asset]
|
||||
else:
|
||||
assets = serializer.validated_data.get('assets') or []
|
||||
|
||||
asset_ids = [asset.id for asset in assets]
|
||||
asset_ids = asset_ids if asset_ids else None
|
||||
|
||||
system_user = self.get_object()
|
||||
if action == 'push':
|
||||
task = self.do_push(system_user, asset_ids)
|
||||
else:
|
||||
task = self.do_test(system_user, asset_ids)
|
||||
data = getattr(serializer, '_data', {})
|
||||
data["task"] = task.id
|
||||
setattr(serializer, '_data', data)
|
||||
|
||||
|
||||
class SystemUserCommandFilterRuleListApi(generics.ListAPIView):
|
||||
rbac_perms = {
|
||||
'list': 'assets.view_commandfilterule'
|
||||
|
@ -291,19 +174,3 @@ class SystemUserCommandFilterRuleListApi(generics.ListAPIView):
|
|||
)
|
||||
return rules
|
||||
|
||||
|
||||
class SystemUserAssetsListView(generics.ListAPIView):
|
||||
serializer_class = serializers.AssetSimpleSerializer
|
||||
filterset_fields = ("hostname", "ip")
|
||||
search_fields = filterset_fields
|
||||
rbac_perms = {
|
||||
'list': 'assets.view_asset'
|
||||
}
|
||||
|
||||
def get_object(self):
|
||||
pk = self.kwargs.get('pk')
|
||||
return get_object_or_404(SystemUser, pk=pk)
|
||||
|
||||
def get_queryset(self):
|
||||
system_user = self.get_object()
|
||||
return system_user.get_all_assets()
|
||||
|
|
|
@ -1,138 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from collections import defaultdict
|
||||
from django.db.models import F, Value, Model
|
||||
from django.db.models.signals import m2m_changed
|
||||
from django.db.models.functions import Concat
|
||||
|
||||
from common.utils import get_logger
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
from orgs.utils import current_org
|
||||
from .. import models, serializers
|
||||
|
||||
__all__ = [
|
||||
'SystemUserAssetRelationViewSet', 'SystemUserNodeRelationViewSet',
|
||||
'SystemUserUserRelationViewSet', 'BaseRelationViewSet',
|
||||
]
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
class RelationMixin:
|
||||
model: Model
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = self.model.objects.all()
|
||||
if not current_org.is_root():
|
||||
org_id = current_org.org_id()
|
||||
queryset = queryset.filter(systemuser__org_id=org_id)
|
||||
|
||||
queryset = queryset.annotate(systemuser_display=Concat(
|
||||
F('systemuser__name'), Value('('),
|
||||
F('systemuser__username'), Value(')')
|
||||
))
|
||||
return queryset
|
||||
|
||||
def send_post_add_signal(self, instance):
|
||||
if not isinstance(instance, list):
|
||||
instance = [instance]
|
||||
|
||||
system_users_objects_map = defaultdict(list)
|
||||
model, object_field = self.get_objects_attr()
|
||||
|
||||
for i in instance:
|
||||
_id = getattr(i, object_field).id
|
||||
system_users_objects_map[i.systemuser].append(_id)
|
||||
|
||||
sender = self.get_sender()
|
||||
for system_user, object_ids in system_users_objects_map.items():
|
||||
logger.debug('System user relation changed, send m2m_changed signals')
|
||||
m2m_changed.send(
|
||||
sender=sender, instance=system_user, action='post_add',
|
||||
reverse=False, model=model, pk_set=set(object_ids)
|
||||
)
|
||||
|
||||
def get_sender(self):
|
||||
return self.model
|
||||
|
||||
def get_objects_attr(self):
|
||||
return models.Asset, 'asset'
|
||||
|
||||
def perform_create(self, serializer):
|
||||
instance = serializer.save()
|
||||
self.send_post_add_signal(instance)
|
||||
|
||||
|
||||
class BaseRelationViewSet(RelationMixin, OrgBulkModelViewSet):
|
||||
perm_model = models.SystemUser
|
||||
|
||||
|
||||
class SystemUserAssetRelationViewSet(BaseRelationViewSet):
|
||||
serializer_class = serializers.SystemUserAssetRelationSerializer
|
||||
model = models.SystemUser.assets.through
|
||||
filterset_fields = [
|
||||
'id', 'asset', 'systemuser',
|
||||
]
|
||||
search_fields = [
|
||||
"id", "asset__hostname", "asset__ip",
|
||||
"systemuser__name", "systemuser__username",
|
||||
]
|
||||
|
||||
def get_objects_attr(self):
|
||||
return models.Asset, 'asset'
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset.annotate(
|
||||
asset_display=Concat(
|
||||
F('asset__hostname'), Value('('),
|
||||
F('asset__ip'), Value(')')
|
||||
)
|
||||
)
|
||||
return queryset
|
||||
|
||||
|
||||
class SystemUserNodeRelationViewSet(BaseRelationViewSet):
|
||||
serializer_class = serializers.SystemUserNodeRelationSerializer
|
||||
model = models.SystemUser.nodes.through
|
||||
filterset_fields = [
|
||||
'id', 'node', 'systemuser',
|
||||
]
|
||||
search_fields = [
|
||||
"node__value", "systemuser__name", "systemuser__username"
|
||||
]
|
||||
|
||||
def get_objects_attr(self):
|
||||
return models.Node, 'node'
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset \
|
||||
.annotate(node_key=F('node__key'))
|
||||
return queryset
|
||||
|
||||
|
||||
class SystemUserUserRelationViewSet(BaseRelationViewSet):
|
||||
serializer_class = serializers.SystemUserUserRelationSerializer
|
||||
model = models.SystemUser.users.through
|
||||
filterset_fields = [
|
||||
'id', 'user', 'systemuser',
|
||||
]
|
||||
search_fields = [
|
||||
"user__username", "user__name",
|
||||
"systemuser__name", "systemuser__username",
|
||||
]
|
||||
|
||||
def get_objects_attr(self):
|
||||
from users.models import User
|
||||
return User, 'user'
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset.annotate(
|
||||
user_display=Concat(
|
||||
F('user__name'), Value('('),
|
||||
F('user__username'), Value(')')
|
||||
)
|
||||
)
|
||||
return queryset
|
|
@ -0,0 +1,89 @@
|
|||
# Generated by Django 3.2.14 on 2022-07-28 03:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0093_auto_20220711_1413'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='cluster',
|
||||
name='admin_user',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='systemuser',
|
||||
name='ad_domain',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='systemuser',
|
||||
name='assets',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='systemuser',
|
||||
name='auto_push',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='systemuser',
|
||||
name='groups',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='systemuser',
|
||||
name='home',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='systemuser',
|
||||
name='nodes',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='systemuser',
|
||||
name='priority',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='systemuser',
|
||||
name='sftp_root',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='systemuser',
|
||||
name='shell',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='systemuser',
|
||||
name='sudo',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='systemuser',
|
||||
name='system_groups',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='systemuser',
|
||||
name='token',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='systemuser',
|
||||
name='type',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='systemuser',
|
||||
name='users',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='historicalaccount',
|
||||
name='version',
|
||||
field=models.IntegerField(default=0, verbose_name='Version'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='systemuser',
|
||||
name='login_mode',
|
||||
field=models.CharField(choices=[('auto', '使用账号'), ('manual', 'Manually input')], default='auto', max_length=10, verbose_name='Login mode'),
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='AdminUser',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='Cluster',
|
||||
),
|
||||
]
|
|
@ -2,7 +2,6 @@ from .base import *
|
|||
from .asset import *
|
||||
from .label import Label
|
||||
from .user import *
|
||||
from .cluster import *
|
||||
from .group import *
|
||||
from .domain import *
|
||||
from .node import *
|
||||
|
@ -12,5 +11,5 @@ from .utils import *
|
|||
from .authbook import *
|
||||
from .gathered_user import *
|
||||
from .favorite_asset import *
|
||||
from .backup import *
|
||||
from .account import *
|
||||
from .backup import *
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
import logging
|
||||
import uuid
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
__all__ = ['Cluster']
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Cluster(models.Model):
|
||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
name = models.CharField(max_length=32, verbose_name=_('Name'))
|
||||
admin_user = models.ForeignKey('assets.AdminUser', null=True, blank=True, on_delete=models.SET_NULL, verbose_name=_("Admin user"))
|
||||
bandwidth = models.CharField(max_length=32, blank=True, verbose_name=_('Bandwidth'))
|
||||
contact = models.CharField(max_length=128, blank=True, verbose_name=_('Contact'))
|
||||
phone = models.CharField(max_length=32, blank=True, verbose_name=_('Phone'))
|
||||
address = models.CharField(max_length=128, blank=True, verbose_name=_("Address"))
|
||||
intranet = models.TextField(blank=True, verbose_name=_('Intranet'))
|
||||
extranet = models.TextField(blank=True, verbose_name=_('Extranet'))
|
||||
date_created = models.DateTimeField(auto_now_add=True, null=True, verbose_name=_('Date created'))
|
||||
operator = models.CharField(max_length=32, blank=True, verbose_name=_('Operator'))
|
||||
created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by'))
|
||||
comment = models.TextField(blank=True, verbose_name=_('Comment'))
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@classmethod
|
||||
def initial(cls):
|
||||
return cls.objects.get_or_create(name=_('Default'), created_by=_('System'), comment=_('Default Cluster'))[0]
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
verbose_name = _("Cluster")
|
|
@ -0,0 +1,65 @@
|
|||
from django.db import models
|
||||
|
||||
|
||||
class ProtocolMixin:
|
||||
protocol: str
|
||||
|
||||
class Protocol(models.TextChoices):
|
||||
ssh = 'ssh', 'SSH'
|
||||
rdp = 'rdp', 'RDP'
|
||||
telnet = 'telnet', 'Telnet'
|
||||
vnc = 'vnc', 'VNC'
|
||||
mysql = 'mysql', 'MySQL'
|
||||
oracle = 'oracle', 'Oracle'
|
||||
mariadb = 'mariadb', 'MariaDB'
|
||||
postgresql = 'postgresql', 'PostgreSQL'
|
||||
sqlserver = 'sqlserver', 'SQLServer'
|
||||
redis = 'redis', 'Redis'
|
||||
mongodb = 'mongodb', 'MongoDB'
|
||||
k8s = 'k8s', 'K8S'
|
||||
|
||||
SUPPORT_PUSH_PROTOCOLS = [Protocol.ssh, Protocol.rdp]
|
||||
|
||||
ASSET_CATEGORY_PROTOCOLS = [
|
||||
Protocol.ssh, Protocol.rdp, Protocol.telnet, Protocol.vnc
|
||||
]
|
||||
APPLICATION_CATEGORY_REMOTE_APP_PROTOCOLS = [
|
||||
Protocol.rdp
|
||||
]
|
||||
APPLICATION_CATEGORY_DB_PROTOCOLS = [
|
||||
Protocol.mysql, Protocol.mariadb, Protocol.oracle,
|
||||
Protocol.postgresql, Protocol.sqlserver,
|
||||
Protocol.redis, Protocol.mongodb
|
||||
]
|
||||
APPLICATION_CATEGORY_CLOUD_PROTOCOLS = [
|
||||
Protocol.k8s
|
||||
]
|
||||
APPLICATION_CATEGORY_PROTOCOLS = [
|
||||
*APPLICATION_CATEGORY_REMOTE_APP_PROTOCOLS,
|
||||
*APPLICATION_CATEGORY_DB_PROTOCOLS,
|
||||
*APPLICATION_CATEGORY_CLOUD_PROTOCOLS
|
||||
]
|
||||
|
||||
@property
|
||||
def is_protocol_support_push(self):
|
||||
return self.protocol in self.SUPPORT_PUSH_PROTOCOLS
|
||||
|
||||
@classmethod
|
||||
def get_protocol_by_application_type(cls, app_type):
|
||||
from applications.const import AppType
|
||||
if app_type in cls.APPLICATION_CATEGORY_PROTOCOLS:
|
||||
protocol = app_type
|
||||
elif app_type in AppType.remote_app_types():
|
||||
protocol = cls.Protocol.rdp
|
||||
else:
|
||||
protocol = None
|
||||
return protocol
|
||||
|
||||
@property
|
||||
def can_perm_to_asset(self):
|
||||
return self.protocol in self.ASSET_CATEGORY_PROTOCOLS
|
||||
|
||||
@property
|
||||
def is_asset_protocol(self):
|
||||
return self.protocol in self.ASSET_CATEGORY_PROTOCOLS
|
||||
|
|
@ -6,83 +6,17 @@ import logging
|
|||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.core.validators import MinValueValidator, MaxValueValidator
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.core.cache import cache
|
||||
|
||||
from common.utils import signer
|
||||
from users.models import User
|
||||
from .base import BaseUser
|
||||
from .asset import Asset
|
||||
from .protocol import ProtocolMixin
|
||||
|
||||
|
||||
__all__ = ['AdminUser', 'SystemUser', 'ProtocolMixin']
|
||||
__all__ = ['SystemUser']
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ProtocolMixin:
|
||||
protocol: str
|
||||
|
||||
class Protocol(models.TextChoices):
|
||||
ssh = 'ssh', 'SSH'
|
||||
rdp = 'rdp', 'RDP'
|
||||
telnet = 'telnet', 'Telnet'
|
||||
vnc = 'vnc', 'VNC'
|
||||
mysql = 'mysql', 'MySQL'
|
||||
oracle = 'oracle', 'Oracle'
|
||||
mariadb = 'mariadb', 'MariaDB'
|
||||
postgresql = 'postgresql', 'PostgreSQL'
|
||||
sqlserver = 'sqlserver', 'SQLServer'
|
||||
redis = 'redis', 'Redis'
|
||||
mongodb = 'mongodb', 'MongoDB'
|
||||
k8s = 'k8s', 'K8S'
|
||||
|
||||
SUPPORT_PUSH_PROTOCOLS = [Protocol.ssh, Protocol.rdp]
|
||||
|
||||
ASSET_CATEGORY_PROTOCOLS = [
|
||||
Protocol.ssh, Protocol.rdp, Protocol.telnet, Protocol.vnc
|
||||
]
|
||||
APPLICATION_CATEGORY_REMOTE_APP_PROTOCOLS = [
|
||||
Protocol.rdp
|
||||
]
|
||||
APPLICATION_CATEGORY_DB_PROTOCOLS = [
|
||||
Protocol.mysql, Protocol.mariadb, Protocol.oracle,
|
||||
Protocol.postgresql, Protocol.sqlserver,
|
||||
Protocol.redis, Protocol.mongodb
|
||||
]
|
||||
APPLICATION_CATEGORY_CLOUD_PROTOCOLS = [
|
||||
Protocol.k8s
|
||||
]
|
||||
APPLICATION_CATEGORY_PROTOCOLS = [
|
||||
*APPLICATION_CATEGORY_REMOTE_APP_PROTOCOLS,
|
||||
*APPLICATION_CATEGORY_DB_PROTOCOLS,
|
||||
*APPLICATION_CATEGORY_CLOUD_PROTOCOLS
|
||||
]
|
||||
|
||||
@property
|
||||
def is_protocol_support_push(self):
|
||||
return self.protocol in self.SUPPORT_PUSH_PROTOCOLS
|
||||
|
||||
@classmethod
|
||||
def get_protocol_by_application_type(cls, app_type):
|
||||
from applications.const import AppType
|
||||
if app_type in cls.APPLICATION_CATEGORY_PROTOCOLS:
|
||||
protocol = app_type
|
||||
elif app_type in AppType.remote_app_types():
|
||||
protocol = cls.Protocol.rdp
|
||||
else:
|
||||
protocol = None
|
||||
return protocol
|
||||
|
||||
@property
|
||||
def can_perm_to_asset(self):
|
||||
return self.protocol in self.ASSET_CATEGORY_PROTOCOLS
|
||||
|
||||
@property
|
||||
def is_asset_protocol(self):
|
||||
return self.protocol in self.ASSET_CATEGORY_PROTOCOLS
|
||||
|
||||
|
||||
class SystemUser(ProtocolMixin, BaseUser):
|
||||
LOGIN_AUTO = 'auto'
|
||||
LOGIN_MANUAL = 'manual'
|
||||
|
@ -91,39 +25,10 @@ class SystemUser(ProtocolMixin, BaseUser):
|
|||
(LOGIN_MANUAL, _('Manually input'))
|
||||
)
|
||||
|
||||
class Type(models.TextChoices):
|
||||
common = 'common', _('Common user')
|
||||
admin = 'admin', _('Admin user')
|
||||
|
||||
username_same_with_user = models.BooleanField(default=False, verbose_name=_("Username same with user"))
|
||||
nodes = models.ManyToManyField('assets.Node', blank=True, verbose_name=_("Nodes"))
|
||||
assets = models.ManyToManyField(
|
||||
'assets.Asset', blank=True, verbose_name=_("Assets"),
|
||||
related_name='system_users'
|
||||
)
|
||||
users = models.ManyToManyField('users.User', blank=True, verbose_name=_("Users"))
|
||||
groups = models.ManyToManyField('users.UserGroup', blank=True, verbose_name=_("User groups"))
|
||||
priority = models.IntegerField(
|
||||
default=81, verbose_name=_("Priority"),
|
||||
help_text=_("1-100, the lower the value will be match first"),
|
||||
validators=[MinValueValidator(1), MaxValueValidator(100)]
|
||||
)
|
||||
protocol = models.CharField(max_length=16, choices=ProtocolMixin.Protocol.choices, default='ssh', verbose_name=_('Protocol'))
|
||||
login_mode = models.CharField(choices=LOGIN_MODE_CHOICES, default=LOGIN_AUTO, max_length=10, verbose_name=_('Login mode'))
|
||||
|
||||
# Todo: 重构平台后或许这里也得变化
|
||||
# 账号模版
|
||||
account_template_enabled = models.BooleanField(default=False, verbose_name=_("启用账号模版"))
|
||||
auto_push_account = models.BooleanField(default=True, verbose_name=_('自动推送账号'))
|
||||
type = models.CharField(max_length=16, choices=Type.choices, default=Type.common, verbose_name=_('Type'))
|
||||
sudo = models.TextField(default='/bin/whoami', verbose_name=_('Sudo'))
|
||||
shell = models.CharField(max_length=64, default='/bin/bash', verbose_name=_('Shell'))
|
||||
sftp_root = models.CharField(default='tmp', max_length=128, verbose_name=_("SFTP Root"))
|
||||
token = models.TextField(default='', verbose_name=_('Token'))
|
||||
home = models.CharField(max_length=4096, default='', verbose_name=_('Home'), blank=True)
|
||||
system_groups = models.CharField(default='', max_length=4096, verbose_name=_('System groups'), blank=True)
|
||||
ad_domain = models.CharField(default='', max_length=256)
|
||||
|
||||
# linux su 命令 (switch user)
|
||||
# Todo: 修改为 username, 不必系统用户了
|
||||
su_enabled = models.BooleanField(default=False, verbose_name=_('User switch'))
|
||||
|
@ -135,32 +40,6 @@ class SystemUser(ProtocolMixin, BaseUser):
|
|||
username = '*'
|
||||
return '{0.name}({1})'.format(self, username)
|
||||
|
||||
@property
|
||||
def nodes_amount(self):
|
||||
return self.nodes.all().count()
|
||||
|
||||
@property
|
||||
def login_mode_display(self):
|
||||
return self.get_login_mode_display()
|
||||
|
||||
def is_need_push(self):
|
||||
if self.auto_push_account and self.is_protocol_support_push:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_admin_user(self):
|
||||
return self.type == self.Type.admin
|
||||
|
||||
@property
|
||||
def is_need_cmd_filter(self):
|
||||
return self.protocol not in [self.Protocol.rdp, self.Protocol.vnc]
|
||||
|
||||
@property
|
||||
def is_need_test_asset_connective(self):
|
||||
return self.protocol in self.ASSET_CATEGORY_PROTOCOLS
|
||||
|
||||
@property
|
||||
def cmd_filter_rules(self):
|
||||
from .cmd_filter import CommandFilterRule
|
||||
|
@ -178,30 +57,6 @@ class SystemUser(ProtocolMixin, BaseUser):
|
|||
return False, matched_cmd
|
||||
return True, None
|
||||
|
||||
def get_all_assets(self):
|
||||
from assets.models import Node
|
||||
nodes_keys = self.nodes.all().values_list('key', flat=True)
|
||||
asset_ids = set(self.assets.all().values_list('id', flat=True))
|
||||
nodes_asset_ids = Node.get_nodes_all_asset_ids_by_keys(nodes_keys)
|
||||
asset_ids.update(nodes_asset_ids)
|
||||
assets = Asset.objects.filter(id__in=asset_ids)
|
||||
return assets
|
||||
|
||||
def add_related_assets(self, assets_or_ids):
|
||||
self.assets.add(*tuple(assets_or_ids))
|
||||
self.add_related_assets_to_su_from_if_need(assets_or_ids)
|
||||
|
||||
def add_related_assets_to_su_from_if_need(self, assets_or_ids):
|
||||
if self.protocol not in [self.Protocol.ssh.value]:
|
||||
return
|
||||
if not self.su_enabled:
|
||||
return
|
||||
if not self.su_from:
|
||||
return
|
||||
if self.su_from.protocol != self.protocol:
|
||||
return
|
||||
self.su_from.assets.add(*tuple(assets_or_ids))
|
||||
|
||||
@classmethod
|
||||
def create_accounts_with_assets(cls, asset_ids, system_user_ids):
|
||||
pass
|
||||
|
@ -216,6 +71,7 @@ class SystemUser(ProtocolMixin, BaseUser):
|
|||
|
||||
def get_auto_account(self, user_id, asset_id):
|
||||
from .account import Account
|
||||
from users.models import User
|
||||
username = self.username
|
||||
if self.username_same_with_user:
|
||||
user = get_object_or_404(User, id=user_id)
|
||||
|
@ -235,52 +91,3 @@ class SystemUser(ProtocolMixin, BaseUser):
|
|||
permissions = [
|
||||
('match_systemuser', _('Can match system user')),
|
||||
]
|
||||
|
||||
|
||||
# Deprecated: 准备废弃
|
||||
class AdminUser(BaseUser):
|
||||
"""
|
||||
A privileged user that ansible can use it to push system user and so on
|
||||
"""
|
||||
BECOME_METHOD_CHOICES = (
|
||||
('sudo', 'sudo'),
|
||||
('su', 'su'),
|
||||
)
|
||||
become = models.BooleanField(default=True)
|
||||
become_method = models.CharField(choices=BECOME_METHOD_CHOICES, default='sudo', max_length=4)
|
||||
become_user = models.CharField(default='root', max_length=64)
|
||||
_become_pass = models.CharField(default='', blank=True, max_length=128)
|
||||
CONNECTIVITY_CACHE_KEY = '_ADMIN_USER_CONNECTIVE_{}'
|
||||
_prefer = "admin_user"
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def become_pass(self):
|
||||
password = signer.unsign(self._become_pass)
|
||||
if password:
|
||||
return password
|
||||
else:
|
||||
return ""
|
||||
|
||||
@become_pass.setter
|
||||
def become_pass(self, password):
|
||||
self._become_pass = signer.sign(password)
|
||||
|
||||
@property
|
||||
def become_info(self):
|
||||
if self.become:
|
||||
info = {
|
||||
"method": self.become_method,
|
||||
"user": self.become_user,
|
||||
"pass": self.become_pass,
|
||||
}
|
||||
else:
|
||||
info = None
|
||||
return info
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
unique_together = [('name', 'org_id')]
|
||||
verbose_name = _("Admin user")
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
#
|
||||
|
||||
from .asset import *
|
||||
from .admin_user import *
|
||||
from .label import *
|
||||
from .system_user import *
|
||||
from .node import *
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from ..models import SystemUser
|
||||
from .system_user import SystemUserSerializer as SuS
|
||||
|
||||
|
||||
class AdminUserSerializer(SuS):
|
||||
"""
|
||||
管理用户
|
||||
"""
|
||||
|
||||
class Meta(SuS.Meta):
|
||||
fields = SuS.Meta.fields_mini + \
|
||||
SuS.Meta.fields_write_only + \
|
||||
SuS.Meta.fields_m2m + \
|
||||
[
|
||||
'type', 'protocol', "priority", 'sftp_root', 'ssh_key_fingerprint',
|
||||
'su_enabled', 'su_from',
|
||||
'date_created', 'date_updated', 'comment', 'created_by',
|
||||
]
|
||||
|
||||
def validate_type(self, val):
|
||||
return SystemUser.Type.admin
|
||||
|
||||
def validate_protocol(self, val):
|
||||
return 'ssh'
|
|
@ -91,7 +91,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
|
|||
'cpu_info', 'hardware_info',
|
||||
]
|
||||
fields_fk = [
|
||||
'domain', 'domain_display', 'platform', 'admin_user', 'admin_user_display'
|
||||
'domain', 'domain_display', 'platform',
|
||||
]
|
||||
fields_m2m = [
|
||||
'nodes', 'nodes_display', 'labels', 'labels_display', 'accounts'
|
||||
|
@ -114,19 +114,10 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
|
|||
self.accounts_data = data.pop('accounts', [])
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def get_fields(self):
|
||||
fields = super().get_fields()
|
||||
|
||||
admin_user_field = fields.get('admin_user')
|
||||
# 因为 mixin 中对 fields 有处理,可能不需要返回 admin_user
|
||||
if admin_user_field:
|
||||
admin_user_field.queryset = SystemUser.objects.filter(type=SystemUser.Type.admin)
|
||||
return fields
|
||||
|
||||
@classmethod
|
||||
def setup_eager_loading(cls, queryset):
|
||||
""" Perform necessary eager loading of data. """
|
||||
queryset = queryset.prefetch_related('domain', 'platform', 'admin_user')
|
||||
queryset = queryset.prefetch_related('domain', 'platform')
|
||||
queryset = queryset.prefetch_related('nodes', 'labels')
|
||||
return queryset
|
||||
|
||||
|
@ -162,7 +153,6 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
|
|||
def add_accounts(instance, accounts_data):
|
||||
for data in accounts_data:
|
||||
data['asset'] = instance.id
|
||||
print("Data: ", accounts_data)
|
||||
serializer = AccountSerializer(data=accounts_data, many=True)
|
||||
try:
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
|
|
@ -1,97 +1,38 @@
|
|||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.db.models import Count
|
||||
|
||||
from common.mixins.serializers import BulkSerializerMixin
|
||||
from common.utils import ssh_pubkey_gen
|
||||
from common.drf.fields import EncryptedField
|
||||
from common.drf.serializers import SecretReadableMixin
|
||||
from common.validators import alphanumeric_re, alphanumeric_cn_re, alphanumeric_win_re
|
||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
from ..models import SystemUser, Asset
|
||||
from .utils import validate_password_for_ansible
|
||||
from .base import AuthSerializerMixin
|
||||
from ..models import SystemUser
|
||||
|
||||
__all__ = [
|
||||
'SystemUserSerializer', 'MiniSystemUserSerializer',
|
||||
'SystemUserSimpleSerializer', 'SystemUserAssetRelationSerializer',
|
||||
'SystemUserNodeRelationSerializer', 'SystemUserTaskSerializer',
|
||||
'SystemUserUserRelationSerializer', 'SystemUserWithAuthInfoSerializer',
|
||||
'SystemUserTempAuthSerializer', 'RelationMixin',
|
||||
'SystemUserSimpleSerializer',
|
||||
]
|
||||
|
||||
|
||||
class SystemUserSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
||||
class SystemUserSerializer(BulkOrgResourceModelSerializer):
|
||||
"""
|
||||
系统用户
|
||||
"""
|
||||
password = EncryptedField(
|
||||
label=_('Password'), required=False, allow_blank=True, allow_null=True, max_length=1024,
|
||||
trim_whitespace=False, validators=[validate_password_for_ansible],
|
||||
write_only=True
|
||||
)
|
||||
auto_generate_key = serializers.BooleanField(initial=True, required=False, write_only=True)
|
||||
type_display = serializers.ReadOnlyField(source='get_type_display', label=_('Type display'))
|
||||
ssh_key_fingerprint = serializers.ReadOnlyField(label=_('SSH key fingerprint'))
|
||||
token = EncryptedField(
|
||||
label=_('Token'), required=False, write_only=True, style={'base_template': 'textarea.html'}
|
||||
)
|
||||
applications_amount = serializers.IntegerField(
|
||||
source='apps_amount', read_only=True, label=_('Apps amount')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = SystemUser
|
||||
fields_mini = ['id', 'name', 'username']
|
||||
fields_write_only = ['password', 'public_key', 'private_key', 'passphrase']
|
||||
fields_small = fields_mini + fields_write_only + [
|
||||
'token', 'ssh_key_fingerprint',
|
||||
'type', 'type_display', 'protocol', 'is_asset_protocol',
|
||||
'account_template_enabled', 'login_mode', 'login_mode_display', 'priority',
|
||||
'sudo', 'shell', 'sftp_root', 'home', 'system_groups', 'ad_domain',
|
||||
'username_same_with_user', 'auto_push_account', 'auto_generate_key',
|
||||
'su_enabled', 'su_from',
|
||||
'date_created', 'date_updated', 'comment', 'created_by',
|
||||
fields_mini = ['id', 'name', 'username', 'protocol']
|
||||
fields_small = fields_mini + [
|
||||
'login_mode', 'su_enabled', 'su_from',
|
||||
'date_created', 'date_updated', 'comment',
|
||||
'created_by',
|
||||
]
|
||||
fields_m2m = ['cmd_filters', 'assets_amount', 'applications_amount', 'nodes']
|
||||
fields = fields_small + fields_m2m
|
||||
fields = fields_small
|
||||
extra_kwargs = {
|
||||
'cmd_filters': {"required": False, 'label': _('Command filter')},
|
||||
'public_key': {"write_only": True},
|
||||
'private_key': {"write_only": True},
|
||||
'nodes_amount': {'label': _('Nodes amount')},
|
||||
'assets_amount': {'label': _('Assets amount')},
|
||||
'login_mode_display': {'label': _('Login mode display')},
|
||||
'created_by': {'read_only': True},
|
||||
'ad_domain': {'required': False, 'allow_blank': True, 'label': _('Ad domain')},
|
||||
'is_asset_protocol': {'label': _('Is asset protocol')},
|
||||
'su_from': {'help_text': _('Only ssh and automatic login system users are supported')}
|
||||
}
|
||||
|
||||
def validate_auto_push(self, value):
|
||||
login_mode = self.get_initial_value("login_mode")
|
||||
protocol = self.get_initial_value("protocol")
|
||||
|
||||
if login_mode == SystemUser.LOGIN_MANUAL:
|
||||
value = False
|
||||
elif protocol not in SystemUser.SUPPORT_PUSH_PROTOCOLS:
|
||||
value = False
|
||||
return value
|
||||
|
||||
def validate_auto_generate_key(self, value):
|
||||
login_mode = self.get_initial_value("login_mode")
|
||||
protocol = self.get_initial_value("protocol")
|
||||
|
||||
if self.context["request"].method.lower() != "post":
|
||||
value = False
|
||||
elif self.instance:
|
||||
value = False
|
||||
elif login_mode == SystemUser.LOGIN_MANUAL:
|
||||
value = False
|
||||
elif protocol not in SystemUser.SUPPORT_PUSH_PROTOCOLS:
|
||||
value = False
|
||||
return value
|
||||
|
||||
def validate_username_same_with_user(self, username_same_with_user):
|
||||
if not username_same_with_user:
|
||||
return username_same_with_user
|
||||
|
@ -132,12 +73,6 @@ class SystemUserSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
|||
raise serializers.ValidationError(msg)
|
||||
return username
|
||||
|
||||
def validate_home(self, home):
|
||||
username_same_with_user = self.get_initial_value("username_same_with_user")
|
||||
if username_same_with_user:
|
||||
return ''
|
||||
return home
|
||||
|
||||
@staticmethod
|
||||
def validate_sftp_root(value):
|
||||
if value in ['home', 'tmp']:
|
||||
|
@ -147,17 +82,6 @@ class SystemUserSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
|||
raise serializers.ValidationError(error)
|
||||
return value
|
||||
|
||||
def validate_password(self, password):
|
||||
super().validate_password(password)
|
||||
auto_gen_key = self.get_initial_value('auto_generate_key', False)
|
||||
private_key = self.get_initial_value('private_key')
|
||||
login_mode = self.get_initial_value('login_mode')
|
||||
|
||||
if not self.instance and not auto_gen_key and not password and \
|
||||
not private_key and login_mode == SystemUser.LOGIN_AUTO:
|
||||
raise serializers.ValidationError(_("Password or private key required"))
|
||||
return password
|
||||
|
||||
def validate_su_from(self, su_from: SystemUser):
|
||||
# self: su enabled
|
||||
su_enabled = self.get_initial_value('su_enabled', default=False)
|
||||
|
@ -181,70 +105,6 @@ class SystemUserSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
|||
raise serializers.ValidationError(error)
|
||||
return su_from
|
||||
|
||||
def _validate_admin_user(self, attrs):
|
||||
if self.instance:
|
||||
tp = self.instance.type
|
||||
else:
|
||||
tp = attrs.get('type')
|
||||
if tp != SystemUser.Type.admin:
|
||||
return attrs
|
||||
attrs['protocol'] = SystemUser.Protocol.ssh
|
||||
attrs['login_mode'] = SystemUser.LOGIN_AUTO
|
||||
attrs['username_same_with_user'] = False
|
||||
attrs['auto_push_account'] = False
|
||||
return attrs
|
||||
|
||||
def _validate_gen_key(self, attrs):
|
||||
username = attrs.get('username', 'manual')
|
||||
auto_gen_key = attrs.pop('auto_generate_key', False)
|
||||
protocol = attrs.get('protocol')
|
||||
|
||||
if protocol not in SystemUser.SUPPORT_PUSH_PROTOCOLS:
|
||||
return attrs
|
||||
|
||||
# 自动生成
|
||||
if auto_gen_key and not self.instance:
|
||||
password = SystemUser.gen_password()
|
||||
attrs['password'] = password
|
||||
if protocol == SystemUser.Protocol.ssh:
|
||||
private_key, public_key = SystemUser.gen_key(username)
|
||||
attrs['private_key'] = private_key
|
||||
attrs['public_key'] = public_key
|
||||
# 如果设置了private key,没有设置public key则生成
|
||||
elif attrs.get('private_key'):
|
||||
private_key = attrs['private_key']
|
||||
password = attrs.get('password')
|
||||
public_key = ssh_pubkey_gen(private_key, password=password, username=username)
|
||||
attrs['public_key'] = public_key
|
||||
return attrs
|
||||
|
||||
def _validate_login_mode(self, attrs):
|
||||
if 'login_mode' in attrs:
|
||||
login_mode = attrs['login_mode']
|
||||
else:
|
||||
login_mode = self.instance.login_mode if self.instance else SystemUser.LOGIN_AUTO
|
||||
|
||||
if login_mode == SystemUser.LOGIN_MANUAL:
|
||||
attrs['password'] = ''
|
||||
attrs['private_key'] = ''
|
||||
attrs['public_key'] = ''
|
||||
|
||||
return attrs
|
||||
|
||||
def validate(self, attrs):
|
||||
attrs = self._validate_admin_user(attrs)
|
||||
attrs = self._validate_gen_key(attrs)
|
||||
attrs = self._validate_login_mode(attrs)
|
||||
return attrs
|
||||
|
||||
@classmethod
|
||||
def setup_eager_loading(cls, queryset):
|
||||
""" Perform necessary eager loading of data. """
|
||||
queryset = queryset \
|
||||
.annotate(assets_amount=Count("assets")) \
|
||||
.prefetch_related('nodes', 'cmd_filters')
|
||||
return queryset
|
||||
|
||||
|
||||
class MiniSystemUserSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
|
@ -252,28 +112,6 @@ class MiniSystemUserSerializer(serializers.ModelSerializer):
|
|||
fields = SystemUserSerializer.Meta.fields_mini
|
||||
|
||||
|
||||
class SystemUserWithAuthInfoSerializer(SecretReadableMixin, SystemUserSerializer):
|
||||
class Meta(SystemUserSerializer.Meta):
|
||||
fields_mini = ['id', 'name', 'username']
|
||||
fields_write_only = ['password', 'public_key', 'private_key']
|
||||
fields_small = fields_mini + fields_write_only + [
|
||||
'protocol', 'login_mode', 'login_mode_display', 'priority',
|
||||
'sudo', 'shell', 'ad_domain', 'sftp_root', 'token',
|
||||
"username_same_with_user", 'auto_push_account', 'auto_generate_key',
|
||||
'comment',
|
||||
]
|
||||
fields = fields_small
|
||||
extra_kwargs = {
|
||||
'nodes_amount': {'label': _('Node')},
|
||||
'assets_amount': {'label': _('Asset')},
|
||||
'login_mode_display': {'label': _('Login mode display')},
|
||||
'created_by': {'read_only': True},
|
||||
'password': {'write_only': False},
|
||||
'private_key': {'write_only': False},
|
||||
'token': {'write_only': False}
|
||||
}
|
||||
|
||||
|
||||
class SystemUserSimpleSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
系统用户最基本信息的数据结构
|
||||
|
@ -284,70 +122,6 @@ class SystemUserSimpleSerializer(serializers.ModelSerializer):
|
|||
fields = ('id', 'name', 'username')
|
||||
|
||||
|
||||
class RelationMixin(BulkSerializerMixin, serializers.Serializer):
|
||||
systemuser_display = serializers.ReadOnlyField(label=_("System user name"))
|
||||
org_name = serializers.ReadOnlyField(label=_("Org name"))
|
||||
|
||||
def get_field_names(self, declared_fields, info):
|
||||
fields = super().get_field_names(declared_fields, info)
|
||||
fields.extend(['systemuser', "systemuser_display", "org_name"])
|
||||
return fields
|
||||
|
||||
|
||||
class SystemUserAssetRelationSerializer(RelationMixin, serializers.ModelSerializer):
|
||||
asset_display = serializers.ReadOnlyField(label=_('Asset hostname'))
|
||||
|
||||
class Meta:
|
||||
model = SystemUser.assets.through
|
||||
fields = [
|
||||
"id", "asset", "asset_display",
|
||||
"systemuser", "systemuser_display",
|
||||
]
|
||||
use_model_bulk_create = True
|
||||
model_bulk_create_kwargs = {
|
||||
'ignore_conflicts': True
|
||||
}
|
||||
|
||||
|
||||
class SystemUserNodeRelationSerializer(RelationMixin, serializers.ModelSerializer):
|
||||
node_display = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = SystemUser.nodes.through
|
||||
fields = [
|
||||
'id', 'node', "node_display",
|
||||
]
|
||||
|
||||
def get_node_display(self, obj):
|
||||
return obj.node.full_value
|
||||
|
||||
|
||||
class SystemUserUserRelationSerializer(RelationMixin, serializers.ModelSerializer):
|
||||
user_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = SystemUser.users.through
|
||||
fields = [
|
||||
'id', "user", "user_display",
|
||||
]
|
||||
|
||||
|
||||
class SystemUserTaskSerializer(serializers.Serializer):
|
||||
ACTION_CHOICES = (
|
||||
("test", "test"),
|
||||
("push", "push"),
|
||||
)
|
||||
action = serializers.ChoiceField(choices=ACTION_CHOICES, write_only=True)
|
||||
asset = serializers.PrimaryKeyRelatedField(
|
||||
queryset=Asset.objects, allow_null=True, required=False, write_only=True
|
||||
)
|
||||
assets = serializers.PrimaryKeyRelatedField(
|
||||
queryset=Asset.objects, allow_null=True, required=False, write_only=True,
|
||||
many=True
|
||||
)
|
||||
task = serializers.CharField(read_only=True)
|
||||
|
||||
|
||||
class SystemUserTempAuthSerializer(SystemUserSerializer):
|
||||
instance_id = serializers.CharField()
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
from .asset import *
|
||||
from .system_user import *
|
||||
from .authbook import *
|
||||
from .account import *
|
||||
from .node_assets_amount import *
|
||||
from .node_assets_mapping import *
|
||||
|
|
|
@ -17,7 +17,6 @@ router.register(r'accounts-history', api.AccountHistoryViewSet, 'account-history
|
|||
router.register(r'account-history-secrets', api.AccountHistorySecretsViewSet, 'account-history-secret')
|
||||
router.register(r'platforms', api.AssetPlatformViewSet, 'platform')
|
||||
router.register(r'system-users', api.SystemUserViewSet, 'system-user')
|
||||
router.register(r'admin-users', api.AdminUserViewSet, 'admin-user')
|
||||
router.register(r'labels', api.LabelViewSet, 'label')
|
||||
router.register(r'nodes', api.NodeViewSet, 'node')
|
||||
router.register(r'domains', api.DomainViewSet, 'domain')
|
||||
|
@ -25,9 +24,6 @@ router.register(r'gateways', api.GatewayViewSet, 'gateway')
|
|||
router.register(r'cmd-filters', api.CommandFilterViewSet, 'cmd-filter')
|
||||
router.register(r'gathered-users', api.GatheredUserViewSet, 'gathered-user')
|
||||
router.register(r'favorite-assets', api.FavoriteAssetViewSet, 'favorite-asset')
|
||||
router.register(r'system-users-assets-relations', api.SystemUserAssetRelationViewSet, 'system-users-assets-relation')
|
||||
router.register(r'system-users-nodes-relations', api.SystemUserNodeRelationViewSet, 'system-users-nodes-relation')
|
||||
router.register(r'system-users-users-relations', api.SystemUserUserRelationViewSet, 'system-users-users-relation')
|
||||
router.register(r'account-backup-plans', api.AccountBackupPlanViewSet, 'account-backup')
|
||||
router.register(r'account-backup-plan-executions', api.AccountBackupPlanExecutionViewSet, 'account-backup-execution')
|
||||
|
||||
|
@ -45,11 +41,8 @@ urlpatterns = [
|
|||
path('assets/<uuid:pk>/perm-user-groups/', api.AssetPermUserGroupListApi.as_view(), name='asset-perm-user-group-list'),
|
||||
path('assets/<uuid:pk>/perm-user-groups/<uuid:perm_user_group_id>/permissions/', api.AssetPermUserGroupPermissionsListApi.as_view(), name='asset-perm-user-group-permission-list'),
|
||||
|
||||
path('system-users/<uuid:pk>/assets/', api.SystemUserAssetsListView.as_view(), name='system-user-assets'),
|
||||
path('system-users/<uuid:pk>/applications/<uuid:app_id>/auth-info/', api.SystemUserAppAuthInfoApi.as_view(), name='system-user-app-auth-info'),
|
||||
path('system-users/<uuid:pk>/assets/<uuid:asset_id>/users/<uuid:user_id>/account/', api.SystemUserAssetAccountApi.as_view(), name='system-user-asset-account'),
|
||||
path('system-users/<uuid:pk>/assets/<uuid:asset_id>/users/<uuid:user_id>/account-secret/', api.SystemUserAssetAccountSecretApi.as_view(), name='system-user-asset-account-secret'),
|
||||
path('system-users/<uuid:pk>/tasks/', api.SystemUserTaskApi.as_view(), name='system-user-task-create'),
|
||||
path('system-users/<uuid:pk>/cmd-filter-rules/', api.SystemUserCommandFilterRuleListApi.as_view(), name='system-user-cmd-filter-rule-list'),
|
||||
path('cmd-filter-rules/', api.SystemUserCommandFilterRuleListApi.as_view(), name='cmd-filter-rules'),
|
||||
|
||||
|
|
|
@ -69,11 +69,6 @@ M2M_NEED_RECORD = {
|
|||
_('{User} JOINED {UserGroup}'),
|
||||
_('{User} LEFT {UserGroup}')
|
||||
),
|
||||
SystemUser.assets.through._meta.object_name: (
|
||||
_('Asset and SystemUser'),
|
||||
_('{Asset} ADD {SystemUser}'),
|
||||
_('{Asset} REMOVE {SystemUser}')
|
||||
),
|
||||
Asset.nodes.through._meta.object_name: (
|
||||
_('Node and Asset'),
|
||||
_('{Node} ADD {Asset}'),
|
||||
|
@ -99,11 +94,6 @@ M2M_NEED_RECORD = {
|
|||
_('{AssetPermission} ADD {Node}'),
|
||||
_('{AssetPermission} REMOVE {Node}'),
|
||||
),
|
||||
AssetPermission.system_users.through._meta.object_name: (
|
||||
_('Asset permission and SystemUser'),
|
||||
_('{AssetPermission} ADD {SystemUser}'),
|
||||
_('{AssetPermission} REMOVE {SystemUser}'),
|
||||
),
|
||||
ApplicationPermission.users.through._meta.object_name: (
|
||||
_('User application permissions'),
|
||||
_('{ApplicationPermission} ADD {User}'),
|
||||
|
|
|
@ -62,20 +62,19 @@ class ValidateUserApplicationPermissionApi(APIView):
|
|||
def get(self, request, *args, **kwargs):
|
||||
user_id = request.query_params.get('user_id', '')
|
||||
application_id = request.query_params.get('application_id', '')
|
||||
system_user_id = request.query_params.get('system_user_id', '')
|
||||
account = system_user_id = request.query_params.get('account', '')
|
||||
|
||||
data = {
|
||||
'has_permission': False,
|
||||
'expire_at': int(time.time()),
|
||||
'actions': []
|
||||
}
|
||||
if not all((user_id, application_id, system_user_id)):
|
||||
if not all((user_id, application_id, account)):
|
||||
return Response(data)
|
||||
|
||||
user = User.objects.get(id=user_id)
|
||||
application = Application.objects.get(id=application_id)
|
||||
system_user = SystemUser.objects.get(id=system_user_id)
|
||||
has_perm, actions, expire_at = validate_permission(user, application, system_user)
|
||||
has_perm, actions, expire_at = validate_permission(user, application, account)
|
||||
status_code = status.HTTP_200_OK if has_perm else status.HTTP_403_FORBIDDEN
|
||||
data = {
|
||||
'has_permission': has_perm,
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from rest_framework import generics
|
||||
from django.db.models import F, Value
|
||||
from django.db.models.functions import Concat
|
||||
from django.db.models import F
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from orgs.mixins.api import OrgRelationMixin
|
||||
|
@ -15,8 +14,7 @@ from perms.utils.asset.user_permission import UserGrantedAssetsQueryUtils
|
|||
__all__ = [
|
||||
'AssetPermissionUserRelationViewSet', 'AssetPermissionUserGroupRelationViewSet',
|
||||
'AssetPermissionAssetRelationViewSet', 'AssetPermissionNodeRelationViewSet',
|
||||
'AssetPermissionSystemUserRelationViewSet', 'AssetPermissionAllAssetListApi',
|
||||
'AssetPermissionAllUserListApi',
|
||||
'AssetPermissionAllAssetListApi', 'AssetPermissionAllUserListApi',
|
||||
]
|
||||
|
||||
|
||||
|
@ -117,21 +115,3 @@ class AssetPermissionNodeRelationViewSet(RelationMixin):
|
|||
.annotate(node_key=F('node__key'))
|
||||
return queryset
|
||||
|
||||
|
||||
class AssetPermissionSystemUserRelationViewSet(RelationMixin):
|
||||
serializer_class = serializers.AssetPermissionSystemUserRelationSerializer
|
||||
m2m_field = models.AssetPermission.system_users.field
|
||||
filterset_fields = [
|
||||
'id', 'systemuser', 'assetpermission',
|
||||
]
|
||||
search_fields = [
|
||||
"assetpermission__name", "systemuser__name", "systemuser__username"
|
||||
]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset.annotate(
|
||||
systemuser_display=Concat(
|
||||
F('systemuser__name'), Value('('), F('systemuser__username'), Value(')')
|
||||
))
|
||||
return queryset
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# Generated by Django 3.2.14 on 2022-07-28 09:10
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def migrate_system_user_to_accounts(apps, schema_editor):
|
||||
# Todo: 迁移 系统用户为账号
|
||||
pass
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('perms', '0028_auto_20220316_2028'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='assetpermission',
|
||||
name='accounts',
|
||||
field=models.JSONField(default=list, verbose_name='Accounts'),
|
||||
),
|
||||
migrations.RunPython(migrate_system_user_to_accounts),
|
||||
migrations.RemoveField(
|
||||
model_name='assetpermission',
|
||||
name='system_users',
|
||||
),
|
||||
]
|
|
@ -22,14 +22,13 @@ logger = logging.getLogger(__name__)
|
|||
class AssetPermission(BasePermission):
|
||||
assets = models.ManyToManyField('assets.Asset', related_name='granted_by_permissions', blank=True, verbose_name=_("Asset"))
|
||||
nodes = models.ManyToManyField('assets.Node', related_name='granted_by_permissions', blank=True, verbose_name=_("Nodes"))
|
||||
system_users = models.ManyToManyField('assets.SystemUser', related_name='granted_by_permissions', blank=True, verbose_name=_("System user"))
|
||||
accounts = models.JSONField(default=list, verbose_name=_("Accounts"))
|
||||
|
||||
class Meta:
|
||||
unique_together = [('org_id', 'name')]
|
||||
verbose_name = _("Asset permission")
|
||||
ordering = ('name',)
|
||||
permissions = [
|
||||
]
|
||||
permissions = []
|
||||
|
||||
@lazyproperty
|
||||
def users_amount(self):
|
||||
|
@ -47,10 +46,6 @@ class AssetPermission(BasePermission):
|
|||
def nodes_amount(self):
|
||||
return self.nodes.count()
|
||||
|
||||
@lazyproperty
|
||||
def system_users_amount(self):
|
||||
return self.system_users.count()
|
||||
|
||||
@classmethod
|
||||
def get_queryset_with_prefetch(cls):
|
||||
return cls.objects.all().valid().prefetch_related(
|
||||
|
@ -80,10 +75,6 @@ class AssetPermission(BasePermission):
|
|||
names = [asset.hostname for asset in self.assets.all()]
|
||||
return names
|
||||
|
||||
def system_users_display(self):
|
||||
names = [system_user.name for system_user in self.system_users.all()]
|
||||
return names
|
||||
|
||||
def nodes_display(self):
|
||||
names = [node.full_value for node in self.nodes.all()]
|
||||
return names
|
||||
|
|
|
@ -22,7 +22,6 @@ class AssetPermissionSerializer(BasePermissionSerializer):
|
|||
user_groups_display = serializers.ListField(child=serializers.CharField(), label=_('User groups display'), required=False)
|
||||
assets_display = serializers.ListField(child=serializers.CharField(), label=_('Assets display'), required=False)
|
||||
nodes_display = serializers.ListField(child=serializers.CharField(), label=_('Nodes display'), required=False)
|
||||
system_users_display = serializers.ListField(child=serializers.CharField(), label=_('System users display'), required=False)
|
||||
|
||||
class Meta:
|
||||
model = AssetPermission
|
||||
|
@ -34,9 +33,9 @@ class AssetPermissionSerializer(BasePermissionSerializer):
|
|||
]
|
||||
fields_m2m = [
|
||||
'users', 'users_display', 'user_groups', 'user_groups_display', 'assets',
|
||||
'assets_display', 'nodes', 'nodes_display', 'system_users', 'system_users_display',
|
||||
'assets_display', 'nodes', 'nodes_display', 'accounts',
|
||||
'users_amount', 'user_groups_amount', 'assets_amount',
|
||||
'nodes_amount', 'system_users_amount',
|
||||
'nodes_amount',
|
||||
]
|
||||
fields = fields_small + fields_m2m
|
||||
read_only_fields = ['created_by', 'date_created', 'from_ticket']
|
||||
|
@ -48,30 +47,16 @@ class AssetPermissionSerializer(BasePermissionSerializer):
|
|||
'user_groups_amount': {'label': _('User groups amount')},
|
||||
'assets_amount': {'label': _('Assets amount')},
|
||||
'nodes_amount': {'label': _('Nodes amount')},
|
||||
'system_users_amount': {'label': _('System users amount')},
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def setup_eager_loading(cls, queryset):
|
||||
""" Perform necessary eager loading of data. """
|
||||
queryset = queryset.prefetch_related(
|
||||
'users', 'user_groups', 'assets', 'nodes', 'system_users'
|
||||
'users', 'user_groups', 'assets', 'nodes',
|
||||
)
|
||||
return queryset
|
||||
|
||||
def to_internal_value(self, data):
|
||||
if 'system_users_display' in data:
|
||||
# system_users_display 转化为 system_users
|
||||
system_users = data.get('system_users', [])
|
||||
system_users_display = data.pop('system_users_display')
|
||||
|
||||
for name in system_users_display:
|
||||
system_user = SystemUser.objects.filter(name=name).first()
|
||||
if system_user and system_user.id not in system_users:
|
||||
system_users.append(system_user.id)
|
||||
data['system_users'] = system_users
|
||||
return super().to_internal_value(data)
|
||||
|
||||
@staticmethod
|
||||
def perform_display_create(instance, **kwargs):
|
||||
# 用户
|
||||
|
|
|
@ -12,7 +12,6 @@ __all__ = [
|
|||
'AssetPermissionUserGroupRelationSerializer',
|
||||
"AssetPermissionAssetRelationSerializer",
|
||||
'AssetPermissionNodeRelationSerializer',
|
||||
'AssetPermissionSystemUserRelationSerializer',
|
||||
'AssetPermissionAllAssetSerializer',
|
||||
'AssetPermissionAllUserSerializer',
|
||||
]
|
||||
|
@ -99,13 +98,3 @@ class AssetPermissionNodeRelationSerializer(RelationMixin, serializers.ModelSeri
|
|||
fields = [
|
||||
'id', 'node', "node_display",
|
||||
]
|
||||
|
||||
|
||||
class AssetPermissionSystemUserRelationSerializer(RelationMixin, serializers.ModelSerializer):
|
||||
systemuser_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = AssetPermission.system_users.through
|
||||
fields = [
|
||||
'id', 'systemuser', 'systemuser_display'
|
||||
]
|
||||
|
|
|
@ -1,138 +1,10 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from django.db.models.signals import m2m_changed
|
||||
from django.dispatch import receiver
|
||||
|
||||
from users.models import User
|
||||
from assets.models import SystemUser
|
||||
from common.utils import get_logger
|
||||
from common.decorator import on_transaction_commit
|
||||
from common.exceptions import M2MReverseNotAllowed
|
||||
from common.const.signals import POST_ADD
|
||||
from perms.models import AssetPermission
|
||||
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
@receiver(m2m_changed, sender=User.groups.through)
|
||||
@on_transaction_commit
|
||||
def on_user_groups_change(sender, instance, action, reverse, pk_set, **kwargs):
|
||||
"""
|
||||
UserGroup 增加 User 时,增加的 User 需要与 UserGroup 关联的动态系统用户相关联
|
||||
"""
|
||||
user: User
|
||||
|
||||
if action != POST_ADD:
|
||||
return
|
||||
|
||||
if not reverse:
|
||||
# 一个用户添加了多个用户组
|
||||
user_ids = [instance.id]
|
||||
system_users = SystemUser.objects.filter(groups__id__in=pk_set).distinct()
|
||||
else:
|
||||
# 一个用户组添加了多个用户
|
||||
user_ids = pk_set
|
||||
system_users = SystemUser.objects.filter(groups__id=instance.pk).distinct()
|
||||
|
||||
for system_user in system_users:
|
||||
system_user.users.add(*user_ids)
|
||||
|
||||
|
||||
@receiver(m2m_changed, sender=AssetPermission.nodes.through)
|
||||
@on_transaction_commit
|
||||
def on_permission_nodes_changed(instance, action, reverse, pk_set, model, **kwargs):
|
||||
if reverse:
|
||||
raise M2MReverseNotAllowed
|
||||
if action != POST_ADD:
|
||||
return
|
||||
|
||||
logger.debug("Asset permission nodes change signal received")
|
||||
nodes = model.objects.filter(pk__in=pk_set)
|
||||
system_users = instance.system_users.all()
|
||||
|
||||
# TODO 待优化
|
||||
for system_user in system_users:
|
||||
system_user.nodes.add(*nodes)
|
||||
|
||||
|
||||
@receiver(m2m_changed, sender=AssetPermission.assets.through)
|
||||
@on_transaction_commit
|
||||
def on_permission_assets_changed(instance, action, reverse, pk_set, model, **kwargs):
|
||||
if reverse:
|
||||
raise M2MReverseNotAllowed
|
||||
if action != POST_ADD:
|
||||
return
|
||||
|
||||
logger.debug("Asset permission assets change signal received")
|
||||
assets = model.objects.filter(pk__in=pk_set)
|
||||
|
||||
# TODO 待优化
|
||||
system_users = instance.system_users.all()
|
||||
for system_user in system_users:
|
||||
system_user: SystemUser
|
||||
system_user.add_related_assets(assets)
|
||||
|
||||
|
||||
@receiver(m2m_changed, sender=AssetPermission.system_users.through)
|
||||
@on_transaction_commit
|
||||
def on_asset_permission_system_users_changed(instance, action, reverse, **kwargs):
|
||||
if reverse:
|
||||
raise M2MReverseNotAllowed
|
||||
if action != POST_ADD:
|
||||
return
|
||||
|
||||
logger.debug("Asset permission system_users change signal received")
|
||||
system_users = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
|
||||
assets = instance.assets.all().values_list('id', flat=True)
|
||||
nodes = instance.nodes.all().values_list('id', flat=True)
|
||||
|
||||
for system_user in system_users:
|
||||
system_user.nodes.add(*tuple(nodes))
|
||||
system_user.add_related_assets(assets)
|
||||
|
||||
# 动态系统用户,需要关联用户和用户组了
|
||||
if system_user.username_same_with_user:
|
||||
users = instance.users.all().values_list('id', flat=True)
|
||||
groups = instance.user_groups.all().values_list('id', flat=True)
|
||||
system_user.groups.add(*tuple(groups))
|
||||
system_user.users.add(*tuple(users))
|
||||
|
||||
|
||||
@receiver(m2m_changed, sender=AssetPermission.users.through)
|
||||
@on_transaction_commit
|
||||
def on_asset_permission_users_changed(instance, action, reverse, pk_set, model, **kwargs):
|
||||
if reverse:
|
||||
raise M2MReverseNotAllowed
|
||||
if action != POST_ADD:
|
||||
return
|
||||
|
||||
logger.debug("Asset permission users change signal received")
|
||||
users = model.objects.filter(pk__in=pk_set)
|
||||
system_users = instance.system_users.all()
|
||||
|
||||
# TODO 待优化
|
||||
for system_user in system_users:
|
||||
if system_user.username_same_with_user:
|
||||
system_user.users.add(*tuple(users))
|
||||
|
||||
|
||||
@receiver(m2m_changed, sender=AssetPermission.user_groups.through)
|
||||
@on_transaction_commit
|
||||
def on_asset_permission_user_groups_changed(instance, action, pk_set, model, reverse, **kwargs):
|
||||
if reverse:
|
||||
raise M2MReverseNotAllowed
|
||||
if action != POST_ADD:
|
||||
return
|
||||
|
||||
logger.debug("Asset permission user groups change signal received")
|
||||
groups = model.objects.filter(pk__in=pk_set)
|
||||
system_users = instance.system_users.all()
|
||||
|
||||
# TODO 待优化
|
||||
for system_user in system_users:
|
||||
if system_user.username_same_with_user:
|
||||
system_user.groups.add(*tuple(groups))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ router.register('asset-permissions-users-relations', api.AssetPermissionUserRela
|
|||
router.register('asset-permissions-user-groups-relations', api.AssetPermissionUserGroupRelationViewSet, 'asset-permissions-user-groups-relation')
|
||||
router.register('asset-permissions-assets-relations', api.AssetPermissionAssetRelationViewSet, 'asset-permissions-assets-relation')
|
||||
router.register('asset-permissions-nodes-relations', api.AssetPermissionNodeRelationViewSet, 'asset-permissions-nodes-relation')
|
||||
router.register('asset-permissions-system-users-relations', api.AssetPermissionSystemUserRelationViewSet, 'asset-permissions-system-users-relation')
|
||||
|
||||
user_permission_urlpatterns = [
|
||||
# 统一说明:
|
||||
|
|
|
@ -11,11 +11,7 @@ from perms.utils.asset.user_permission import get_user_all_asset_perm_ids
|
|||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
def validate_permission(user, asset, system_user, action='connect'):
|
||||
|
||||
if not system_user.protocol in asset.protocols_as_dict.keys():
|
||||
return False, time.time()
|
||||
|
||||
def validate_permission(user, asset, account, action='connect'):
|
||||
asset_perm_ids = get_user_all_asset_perm_ids(user)
|
||||
|
||||
asset_perm_ids_from_asset = AssetPermission.assets.through.objects.filter(
|
||||
|
@ -28,9 +24,7 @@ def validate_permission(user, asset, system_user, action='connect'):
|
|||
for node in nodes:
|
||||
ancestor_keys = node.get_ancestor_keys(with_self=True)
|
||||
node_keys.update(ancestor_keys)
|
||||
node_ids = Node.objects.filter(key__in=node_keys).values_list('id', flat=True)
|
||||
|
||||
node_ids = set(node_ids)
|
||||
node_ids = set(Node.objects.filter(key__in=node_keys).values_list('id', flat=True))
|
||||
|
||||
asset_perm_ids_from_node = AssetPermission.nodes.through.objects.filter(
|
||||
assetpermission_id__in=asset_perm_ids,
|
||||
|
@ -39,16 +33,9 @@ def validate_permission(user, asset, system_user, action='connect'):
|
|||
|
||||
asset_perm_ids = {*asset_perm_ids_from_asset, *asset_perm_ids_from_node}
|
||||
|
||||
asset_perm_ids = AssetPermission.system_users.through.objects.filter(
|
||||
assetpermission_id__in=asset_perm_ids,
|
||||
systemuser_id=system_user.id
|
||||
).values_list('assetpermission_id', flat=True)
|
||||
|
||||
asset_perm_ids = set(asset_perm_ids)
|
||||
|
||||
asset_perms = AssetPermission.objects.filter(
|
||||
id__in=asset_perm_ids
|
||||
).order_by('-date_expired')
|
||||
asset_perms = AssetPermission.objects\
|
||||
.filter(id__in=asset_perm_ids, accounts__contains=account)\
|
||||
.order_by('-date_expired')
|
||||
|
||||
if asset_perms:
|
||||
actions = set()
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# Generated by Django 3.2.14 on 2022-07-28 03:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('tickets', '0017_auto_20220623_1027'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='applyapplicationticket',
|
||||
name='apply_permission_name',
|
||||
field=models.CharField(max_length=128, verbose_name='Permission name'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='applyassetticket',
|
||||
name='apply_permission_name',
|
||||
field=models.CharField(max_length=128, verbose_name='Permission name'),
|
||||
),
|
||||
]
|
|
@ -47,12 +47,6 @@ class AssetPermissionGenerator(FakeDataGenerator):
|
|||
relation_name = 'node_id'
|
||||
self.set_relations(perms, through, relation_name, choices)
|
||||
|
||||
def set_system_users(self, perms):
|
||||
through = AssetPermission.system_users.through
|
||||
choices = self.system_user_ids
|
||||
relation_name = 'systemuser_id'
|
||||
self.set_relations(perms, through, relation_name, choices)
|
||||
|
||||
def set_relations(self, perms, through, relation_name, choices, choice_count=None):
|
||||
relations = []
|
||||
|
||||
|
@ -79,4 +73,3 @@ class AssetPermissionGenerator(FakeDataGenerator):
|
|||
self.set_user_groups(created)
|
||||
self.set_assets(created)
|
||||
self.set_nodes(created)
|
||||
self.set_system_users(created)
|
||||
|
|
Loading…
Reference in New Issue