mirror of https://github.com/jumpserver/jumpserver
perf: 修改系统用户
parent
43d3791ddc
commit
fb0fb71ea3
|
@ -1,9 +1,7 @@
|
||||||
from .mixin import *
|
from .mixin import *
|
||||||
from .admin_user import *
|
|
||||||
from .asset import *
|
from .asset import *
|
||||||
from .label import *
|
from .label import *
|
||||||
from .system_user import *
|
from .system_user import *
|
||||||
from .system_user_relation import *
|
|
||||||
from .accounts import *
|
from .accounts import *
|
||||||
from .node import *
|
from .node import *
|
||||||
from .domain 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 = {
|
filterset_fields = {
|
||||||
'hostname': ['exact'],
|
'hostname': ['exact'],
|
||||||
'ip': ['exact'],
|
'ip': ['exact'],
|
||||||
'system_users__id': ['exact'],
|
|
||||||
'platform__base': ['exact'],
|
'platform__base': ['exact'],
|
||||||
'is_active': ['exact'],
|
'is_active': ['exact'],
|
||||||
'protocols': ['exact', 'icontains']
|
'protocols': ['exact', 'icontains']
|
||||||
|
|
|
@ -5,23 +5,17 @@ from rest_framework.decorators import action
|
||||||
from rest_framework.viewsets import GenericViewSet
|
from rest_framework.viewsets import GenericViewSet
|
||||||
|
|
||||||
from common.utils import get_logger, get_object_or_none
|
from common.utils import get_logger, get_object_or_none
|
||||||
from common.permissions import IsValidUser
|
|
||||||
from common.mixins.api import SuggestionMixin
|
from common.mixins.api import SuggestionMixin
|
||||||
from orgs.mixins.api import OrgBulkModelViewSet
|
from orgs.mixins.api import OrgBulkModelViewSet
|
||||||
from orgs.mixins import generics
|
from orgs.mixins import generics
|
||||||
from orgs.utils import tmp_to_root_org
|
|
||||||
from ..models import SystemUser, CommandFilterRule, Account
|
from ..models import SystemUser, CommandFilterRule, Account
|
||||||
from .. import serializers
|
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__)
|
logger = get_logger(__file__)
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'SystemUserViewSet', 'SystemUserAuthInfoApi', 'SystemUserAssetAuthInfoApi',
|
'SystemUserViewSet', 'SystemUserAuthInfoApi',
|
||||||
'SystemUserCommandFilterRuleListApi', 'SystemUserTaskApi', 'SystemUserAssetsListView',
|
'SystemUserCommandFilterRuleListApi',
|
||||||
'SystemUserTempAuthInfoApi', 'SystemUserAppAuthInfoApi', 'SystemUserAssetAccountApi',
|
'SystemUserAssetAccountApi',
|
||||||
'SystemUserAssetAccountSecretApi',
|
'SystemUserAssetAccountSecretApi',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -35,7 +29,6 @@ class SystemUserViewSet(SuggestionMixin, OrgBulkModelViewSet):
|
||||||
'name': ['exact'],
|
'name': ['exact'],
|
||||||
'username': ['exact'],
|
'username': ['exact'],
|
||||||
'protocol': ['exact', 'in'],
|
'protocol': ['exact', 'in'],
|
||||||
'type': ['exact', 'in'],
|
|
||||||
}
|
}
|
||||||
search_fields = filterset_fields
|
search_fields = filterset_fields
|
||||||
serializer_class = serializers.SystemUserSerializer
|
serializer_class = serializers.SystemUserSerializer
|
||||||
|
@ -154,116 +147,6 @@ class SystemUserAuthInfoApi(generics.RetrieveUpdateDestroyAPIView):
|
||||||
return Response(status=204)
|
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):
|
class SystemUserCommandFilterRuleListApi(generics.ListAPIView):
|
||||||
rbac_perms = {
|
rbac_perms = {
|
||||||
'list': 'assets.view_commandfilterule'
|
'list': 'assets.view_commandfilterule'
|
||||||
|
@ -291,19 +174,3 @@ class SystemUserCommandFilterRuleListApi(generics.ListAPIView):
|
||||||
)
|
)
|
||||||
return rules
|
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 .asset import *
|
||||||
from .label import Label
|
from .label import Label
|
||||||
from .user import *
|
from .user import *
|
||||||
from .cluster import *
|
|
||||||
from .group import *
|
from .group import *
|
||||||
from .domain import *
|
from .domain import *
|
||||||
from .node import *
|
from .node import *
|
||||||
|
@ -12,5 +11,5 @@ from .utils import *
|
||||||
from .authbook import *
|
from .authbook import *
|
||||||
from .gathered_user import *
|
from .gathered_user import *
|
||||||
from .favorite_asset import *
|
from .favorite_asset import *
|
||||||
from .backup import *
|
|
||||||
from .account 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.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
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.shortcuts import get_object_or_404
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
|
|
||||||
from common.utils import signer
|
|
||||||
from users.models import User
|
|
||||||
from .base import BaseUser
|
from .base import BaseUser
|
||||||
from .asset import Asset
|
from .protocol import ProtocolMixin
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['AdminUser', 'SystemUser', 'ProtocolMixin']
|
__all__ = ['SystemUser']
|
||||||
logger = logging.getLogger(__name__)
|
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):
|
class SystemUser(ProtocolMixin, BaseUser):
|
||||||
LOGIN_AUTO = 'auto'
|
LOGIN_AUTO = 'auto'
|
||||||
LOGIN_MANUAL = 'manual'
|
LOGIN_MANUAL = 'manual'
|
||||||
|
@ -91,39 +25,10 @@ class SystemUser(ProtocolMixin, BaseUser):
|
||||||
(LOGIN_MANUAL, _('Manually input'))
|
(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"))
|
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'))
|
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'))
|
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)
|
# linux su 命令 (switch user)
|
||||||
# Todo: 修改为 username, 不必系统用户了
|
# Todo: 修改为 username, 不必系统用户了
|
||||||
su_enabled = models.BooleanField(default=False, verbose_name=_('User switch'))
|
su_enabled = models.BooleanField(default=False, verbose_name=_('User switch'))
|
||||||
|
@ -135,32 +40,6 @@ class SystemUser(ProtocolMixin, BaseUser):
|
||||||
username = '*'
|
username = '*'
|
||||||
return '{0.name}({1})'.format(self, 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
|
@property
|
||||||
def cmd_filter_rules(self):
|
def cmd_filter_rules(self):
|
||||||
from .cmd_filter import CommandFilterRule
|
from .cmd_filter import CommandFilterRule
|
||||||
|
@ -178,30 +57,6 @@ class SystemUser(ProtocolMixin, BaseUser):
|
||||||
return False, matched_cmd
|
return False, matched_cmd
|
||||||
return True, None
|
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
|
@classmethod
|
||||||
def create_accounts_with_assets(cls, asset_ids, system_user_ids):
|
def create_accounts_with_assets(cls, asset_ids, system_user_ids):
|
||||||
pass
|
pass
|
||||||
|
@ -216,6 +71,7 @@ class SystemUser(ProtocolMixin, BaseUser):
|
||||||
|
|
||||||
def get_auto_account(self, user_id, asset_id):
|
def get_auto_account(self, user_id, asset_id):
|
||||||
from .account import Account
|
from .account import Account
|
||||||
|
from users.models import User
|
||||||
username = self.username
|
username = self.username
|
||||||
if self.username_same_with_user:
|
if self.username_same_with_user:
|
||||||
user = get_object_or_404(User, id=user_id)
|
user = get_object_or_404(User, id=user_id)
|
||||||
|
@ -235,52 +91,3 @@ class SystemUser(ProtocolMixin, BaseUser):
|
||||||
permissions = [
|
permissions = [
|
||||||
('match_systemuser', _('Can match system user')),
|
('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 .asset import *
|
||||||
from .admin_user import *
|
|
||||||
from .label import *
|
from .label import *
|
||||||
from .system_user import *
|
from .system_user import *
|
||||||
from .node 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',
|
'cpu_info', 'hardware_info',
|
||||||
]
|
]
|
||||||
fields_fk = [
|
fields_fk = [
|
||||||
'domain', 'domain_display', 'platform', 'admin_user', 'admin_user_display'
|
'domain', 'domain_display', 'platform',
|
||||||
]
|
]
|
||||||
fields_m2m = [
|
fields_m2m = [
|
||||||
'nodes', 'nodes_display', 'labels', 'labels_display', 'accounts'
|
'nodes', 'nodes_display', 'labels', 'labels_display', 'accounts'
|
||||||
|
@ -114,19 +114,10 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
|
||||||
self.accounts_data = data.pop('accounts', [])
|
self.accounts_data = data.pop('accounts', [])
|
||||||
super().__init__(*args, **kwargs)
|
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
|
@classmethod
|
||||||
def setup_eager_loading(cls, queryset):
|
def setup_eager_loading(cls, queryset):
|
||||||
""" Perform necessary eager loading of data. """
|
""" 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')
|
queryset = queryset.prefetch_related('nodes', 'labels')
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
@ -162,7 +153,6 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
|
||||||
def add_accounts(instance, accounts_data):
|
def add_accounts(instance, accounts_data):
|
||||||
for data in accounts_data:
|
for data in accounts_data:
|
||||||
data['asset'] = instance.id
|
data['asset'] = instance.id
|
||||||
print("Data: ", accounts_data)
|
|
||||||
serializer = AccountSerializer(data=accounts_data, many=True)
|
serializer = AccountSerializer(data=accounts_data, many=True)
|
||||||
try:
|
try:
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
|
|
|
@ -1,97 +1,38 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from django.utils.translation import ugettext_lazy as _
|
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 common.validators import alphanumeric_re, alphanumeric_cn_re, alphanumeric_win_re
|
||||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||||
from ..models import SystemUser, Asset
|
from ..models import SystemUser
|
||||||
from .utils import validate_password_for_ansible
|
|
||||||
from .base import AuthSerializerMixin
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'SystemUserSerializer', 'MiniSystemUserSerializer',
|
'SystemUserSerializer', 'MiniSystemUserSerializer',
|
||||||
'SystemUserSimpleSerializer', 'SystemUserAssetRelationSerializer',
|
'SystemUserSimpleSerializer',
|
||||||
'SystemUserNodeRelationSerializer', 'SystemUserTaskSerializer',
|
|
||||||
'SystemUserUserRelationSerializer', 'SystemUserWithAuthInfoSerializer',
|
|
||||||
'SystemUserTempAuthSerializer', 'RelationMixin',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
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:
|
class Meta:
|
||||||
model = SystemUser
|
model = SystemUser
|
||||||
fields_mini = ['id', 'name', 'username']
|
fields_mini = ['id', 'name', 'username', 'protocol']
|
||||||
fields_write_only = ['password', 'public_key', 'private_key', 'passphrase']
|
fields_small = fields_mini + [
|
||||||
fields_small = fields_mini + fields_write_only + [
|
'login_mode', 'su_enabled', 'su_from',
|
||||||
'token', 'ssh_key_fingerprint',
|
'date_created', 'date_updated', 'comment',
|
||||||
'type', 'type_display', 'protocol', 'is_asset_protocol',
|
'created_by',
|
||||||
'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_m2m = ['cmd_filters', 'assets_amount', 'applications_amount', 'nodes']
|
fields = fields_small
|
||||||
fields = fields_small + fields_m2m
|
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
'cmd_filters': {"required": False, 'label': _('Command filter')},
|
'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')},
|
'login_mode_display': {'label': _('Login mode display')},
|
||||||
'created_by': {'read_only': True},
|
'created_by': {'read_only': True},
|
||||||
'ad_domain': {'required': False, 'allow_blank': True, 'label': _('Ad domain')},
|
'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')}
|
'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):
|
def validate_username_same_with_user(self, username_same_with_user):
|
||||||
if not username_same_with_user:
|
if not username_same_with_user:
|
||||||
return username_same_with_user
|
return username_same_with_user
|
||||||
|
@ -132,12 +73,6 @@ class SystemUserSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
||||||
raise serializers.ValidationError(msg)
|
raise serializers.ValidationError(msg)
|
||||||
return username
|
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
|
@staticmethod
|
||||||
def validate_sftp_root(value):
|
def validate_sftp_root(value):
|
||||||
if value in ['home', 'tmp']:
|
if value in ['home', 'tmp']:
|
||||||
|
@ -147,17 +82,6 @@ class SystemUserSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
||||||
raise serializers.ValidationError(error)
|
raise serializers.ValidationError(error)
|
||||||
return value
|
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):
|
def validate_su_from(self, su_from: SystemUser):
|
||||||
# self: su enabled
|
# self: su enabled
|
||||||
su_enabled = self.get_initial_value('su_enabled', default=False)
|
su_enabled = self.get_initial_value('su_enabled', default=False)
|
||||||
|
@ -181,70 +105,6 @@ class SystemUserSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
||||||
raise serializers.ValidationError(error)
|
raise serializers.ValidationError(error)
|
||||||
return su_from
|
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 MiniSystemUserSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -252,28 +112,6 @@ class MiniSystemUserSerializer(serializers.ModelSerializer):
|
||||||
fields = SystemUserSerializer.Meta.fields_mini
|
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):
|
class SystemUserSimpleSerializer(serializers.ModelSerializer):
|
||||||
"""
|
"""
|
||||||
系统用户最基本信息的数据结构
|
系统用户最基本信息的数据结构
|
||||||
|
@ -284,70 +122,6 @@ class SystemUserSimpleSerializer(serializers.ModelSerializer):
|
||||||
fields = ('id', 'name', 'username')
|
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):
|
class SystemUserTempAuthSerializer(SystemUserSerializer):
|
||||||
instance_id = serializers.CharField()
|
instance_id = serializers.CharField()
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
from .asset import *
|
from .asset import *
|
||||||
from .system_user import *
|
from .account import *
|
||||||
from .authbook import *
|
|
||||||
from .node_assets_amount import *
|
from .node_assets_amount import *
|
||||||
from .node_assets_mapping 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'account-history-secrets', api.AccountHistorySecretsViewSet, 'account-history-secret')
|
||||||
router.register(r'platforms', api.AssetPlatformViewSet, 'platform')
|
router.register(r'platforms', api.AssetPlatformViewSet, 'platform')
|
||||||
router.register(r'system-users', api.SystemUserViewSet, 'system-user')
|
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'labels', api.LabelViewSet, 'label')
|
||||||
router.register(r'nodes', api.NodeViewSet, 'node')
|
router.register(r'nodes', api.NodeViewSet, 'node')
|
||||||
router.register(r'domains', api.DomainViewSet, 'domain')
|
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'cmd-filters', api.CommandFilterViewSet, 'cmd-filter')
|
||||||
router.register(r'gathered-users', api.GatheredUserViewSet, 'gathered-user')
|
router.register(r'gathered-users', api.GatheredUserViewSet, 'gathered-user')
|
||||||
router.register(r'favorite-assets', api.FavoriteAssetViewSet, 'favorite-asset')
|
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-plans', api.AccountBackupPlanViewSet, 'account-backup')
|
||||||
router.register(r'account-backup-plan-executions', api.AccountBackupPlanExecutionViewSet, 'account-backup-execution')
|
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/', 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('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/', 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>/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('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'),
|
path('cmd-filter-rules/', api.SystemUserCommandFilterRuleListApi.as_view(), name='cmd-filter-rules'),
|
||||||
|
|
||||||
|
|
|
@ -69,11 +69,6 @@ M2M_NEED_RECORD = {
|
||||||
_('{User} JOINED {UserGroup}'),
|
_('{User} JOINED {UserGroup}'),
|
||||||
_('{User} LEFT {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: (
|
Asset.nodes.through._meta.object_name: (
|
||||||
_('Node and Asset'),
|
_('Node and Asset'),
|
||||||
_('{Node} ADD {Asset}'),
|
_('{Node} ADD {Asset}'),
|
||||||
|
@ -99,11 +94,6 @@ M2M_NEED_RECORD = {
|
||||||
_('{AssetPermission} ADD {Node}'),
|
_('{AssetPermission} ADD {Node}'),
|
||||||
_('{AssetPermission} REMOVE {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: (
|
ApplicationPermission.users.through._meta.object_name: (
|
||||||
_('User application permissions'),
|
_('User application permissions'),
|
||||||
_('{ApplicationPermission} ADD {User}'),
|
_('{ApplicationPermission} ADD {User}'),
|
||||||
|
|
|
@ -62,20 +62,19 @@ class ValidateUserApplicationPermissionApi(APIView):
|
||||||
def get(self, request, *args, **kwargs):
|
def get(self, request, *args, **kwargs):
|
||||||
user_id = request.query_params.get('user_id', '')
|
user_id = request.query_params.get('user_id', '')
|
||||||
application_id = request.query_params.get('application_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 = {
|
data = {
|
||||||
'has_permission': False,
|
'has_permission': False,
|
||||||
'expire_at': int(time.time()),
|
'expire_at': int(time.time()),
|
||||||
'actions': []
|
'actions': []
|
||||||
}
|
}
|
||||||
if not all((user_id, application_id, system_user_id)):
|
if not all((user_id, application_id, account)):
|
||||||
return Response(data)
|
return Response(data)
|
||||||
|
|
||||||
user = User.objects.get(id=user_id)
|
user = User.objects.get(id=user_id)
|
||||||
application = Application.objects.get(id=application_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, account)
|
||||||
has_perm, actions, expire_at = validate_permission(user, application, system_user)
|
|
||||||
status_code = status.HTTP_200_OK if has_perm else status.HTTP_403_FORBIDDEN
|
status_code = status.HTTP_200_OK if has_perm else status.HTTP_403_FORBIDDEN
|
||||||
data = {
|
data = {
|
||||||
'has_permission': has_perm,
|
'has_permission': has_perm,
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
from rest_framework import generics
|
from rest_framework import generics
|
||||||
from django.db.models import F, Value
|
from django.db.models import F
|
||||||
from django.db.models.functions import Concat
|
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
|
|
||||||
from orgs.mixins.api import OrgRelationMixin
|
from orgs.mixins.api import OrgRelationMixin
|
||||||
|
@ -15,8 +14,7 @@ from perms.utils.asset.user_permission import UserGrantedAssetsQueryUtils
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'AssetPermissionUserRelationViewSet', 'AssetPermissionUserGroupRelationViewSet',
|
'AssetPermissionUserRelationViewSet', 'AssetPermissionUserGroupRelationViewSet',
|
||||||
'AssetPermissionAssetRelationViewSet', 'AssetPermissionNodeRelationViewSet',
|
'AssetPermissionAssetRelationViewSet', 'AssetPermissionNodeRelationViewSet',
|
||||||
'AssetPermissionSystemUserRelationViewSet', 'AssetPermissionAllAssetListApi',
|
'AssetPermissionAllAssetListApi', 'AssetPermissionAllUserListApi',
|
||||||
'AssetPermissionAllUserListApi',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -117,21 +115,3 @@ class AssetPermissionNodeRelationViewSet(RelationMixin):
|
||||||
.annotate(node_key=F('node__key'))
|
.annotate(node_key=F('node__key'))
|
||||||
return queryset
|
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):
|
class AssetPermission(BasePermission):
|
||||||
assets = models.ManyToManyField('assets.Asset', related_name='granted_by_permissions', blank=True, verbose_name=_("Asset"))
|
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"))
|
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:
|
class Meta:
|
||||||
unique_together = [('org_id', 'name')]
|
unique_together = [('org_id', 'name')]
|
||||||
verbose_name = _("Asset permission")
|
verbose_name = _("Asset permission")
|
||||||
ordering = ('name',)
|
ordering = ('name',)
|
||||||
permissions = [
|
permissions = []
|
||||||
]
|
|
||||||
|
|
||||||
@lazyproperty
|
@lazyproperty
|
||||||
def users_amount(self):
|
def users_amount(self):
|
||||||
|
@ -47,10 +46,6 @@ class AssetPermission(BasePermission):
|
||||||
def nodes_amount(self):
|
def nodes_amount(self):
|
||||||
return self.nodes.count()
|
return self.nodes.count()
|
||||||
|
|
||||||
@lazyproperty
|
|
||||||
def system_users_amount(self):
|
|
||||||
return self.system_users.count()
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_queryset_with_prefetch(cls):
|
def get_queryset_with_prefetch(cls):
|
||||||
return cls.objects.all().valid().prefetch_related(
|
return cls.objects.all().valid().prefetch_related(
|
||||||
|
@ -80,10 +75,6 @@ class AssetPermission(BasePermission):
|
||||||
names = [asset.hostname for asset in self.assets.all()]
|
names = [asset.hostname for asset in self.assets.all()]
|
||||||
return names
|
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):
|
def nodes_display(self):
|
||||||
names = [node.full_value for node in self.nodes.all()]
|
names = [node.full_value for node in self.nodes.all()]
|
||||||
return names
|
return names
|
||||||
|
|
|
@ -22,7 +22,6 @@ class AssetPermissionSerializer(BasePermissionSerializer):
|
||||||
user_groups_display = serializers.ListField(child=serializers.CharField(), label=_('User groups display'), required=False)
|
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)
|
assets_display = serializers.ListField(child=serializers.CharField(), label=_('Assets display'), required=False)
|
||||||
nodes_display = serializers.ListField(child=serializers.CharField(), label=_('Nodes 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:
|
class Meta:
|
||||||
model = AssetPermission
|
model = AssetPermission
|
||||||
|
@ -34,9 +33,9 @@ class AssetPermissionSerializer(BasePermissionSerializer):
|
||||||
]
|
]
|
||||||
fields_m2m = [
|
fields_m2m = [
|
||||||
'users', 'users_display', 'user_groups', 'user_groups_display', 'assets',
|
'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',
|
'users_amount', 'user_groups_amount', 'assets_amount',
|
||||||
'nodes_amount', 'system_users_amount',
|
'nodes_amount',
|
||||||
]
|
]
|
||||||
fields = fields_small + fields_m2m
|
fields = fields_small + fields_m2m
|
||||||
read_only_fields = ['created_by', 'date_created', 'from_ticket']
|
read_only_fields = ['created_by', 'date_created', 'from_ticket']
|
||||||
|
@ -48,30 +47,16 @@ class AssetPermissionSerializer(BasePermissionSerializer):
|
||||||
'user_groups_amount': {'label': _('User groups amount')},
|
'user_groups_amount': {'label': _('User groups amount')},
|
||||||
'assets_amount': {'label': _('Assets amount')},
|
'assets_amount': {'label': _('Assets amount')},
|
||||||
'nodes_amount': {'label': _('Nodes amount')},
|
'nodes_amount': {'label': _('Nodes amount')},
|
||||||
'system_users_amount': {'label': _('System users amount')},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def setup_eager_loading(cls, queryset):
|
def setup_eager_loading(cls, queryset):
|
||||||
""" Perform necessary eager loading of data. """
|
""" Perform necessary eager loading of data. """
|
||||||
queryset = queryset.prefetch_related(
|
queryset = queryset.prefetch_related(
|
||||||
'users', 'user_groups', 'assets', 'nodes', 'system_users'
|
'users', 'user_groups', 'assets', 'nodes',
|
||||||
)
|
)
|
||||||
return queryset
|
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
|
@staticmethod
|
||||||
def perform_display_create(instance, **kwargs):
|
def perform_display_create(instance, **kwargs):
|
||||||
# 用户
|
# 用户
|
||||||
|
|
|
@ -12,7 +12,6 @@ __all__ = [
|
||||||
'AssetPermissionUserGroupRelationSerializer',
|
'AssetPermissionUserGroupRelationSerializer',
|
||||||
"AssetPermissionAssetRelationSerializer",
|
"AssetPermissionAssetRelationSerializer",
|
||||||
'AssetPermissionNodeRelationSerializer',
|
'AssetPermissionNodeRelationSerializer',
|
||||||
'AssetPermissionSystemUserRelationSerializer',
|
|
||||||
'AssetPermissionAllAssetSerializer',
|
'AssetPermissionAllAssetSerializer',
|
||||||
'AssetPermissionAllUserSerializer',
|
'AssetPermissionAllUserSerializer',
|
||||||
]
|
]
|
||||||
|
@ -99,13 +98,3 @@ class AssetPermissionNodeRelationSerializer(RelationMixin, serializers.ModelSeri
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'node', "node_display",
|
'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 -*-
|
# -*- 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-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-assets-relations', api.AssetPermissionAssetRelationViewSet, 'asset-permissions-assets-relation')
|
||||||
router.register('asset-permissions-nodes-relations', api.AssetPermissionNodeRelationViewSet, 'asset-permissions-nodes-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 = [
|
user_permission_urlpatterns = [
|
||||||
# 统一说明:
|
# 统一说明:
|
||||||
|
|
|
@ -11,11 +11,7 @@ from perms.utils.asset.user_permission import get_user_all_asset_perm_ids
|
||||||
logger = get_logger(__file__)
|
logger = get_logger(__file__)
|
||||||
|
|
||||||
|
|
||||||
def validate_permission(user, asset, system_user, action='connect'):
|
def validate_permission(user, asset, account, action='connect'):
|
||||||
|
|
||||||
if not system_user.protocol in asset.protocols_as_dict.keys():
|
|
||||||
return False, time.time()
|
|
||||||
|
|
||||||
asset_perm_ids = get_user_all_asset_perm_ids(user)
|
asset_perm_ids = get_user_all_asset_perm_ids(user)
|
||||||
|
|
||||||
asset_perm_ids_from_asset = AssetPermission.assets.through.objects.filter(
|
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:
|
for node in nodes:
|
||||||
ancestor_keys = node.get_ancestor_keys(with_self=True)
|
ancestor_keys = node.get_ancestor_keys(with_self=True)
|
||||||
node_keys.update(ancestor_keys)
|
node_keys.update(ancestor_keys)
|
||||||
node_ids = Node.objects.filter(key__in=node_keys).values_list('id', flat=True)
|
node_ids = set(Node.objects.filter(key__in=node_keys).values_list('id', flat=True))
|
||||||
|
|
||||||
node_ids = set(node_ids)
|
|
||||||
|
|
||||||
asset_perm_ids_from_node = AssetPermission.nodes.through.objects.filter(
|
asset_perm_ids_from_node = AssetPermission.nodes.through.objects.filter(
|
||||||
assetpermission_id__in=asset_perm_ids,
|
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 = {*asset_perm_ids_from_asset, *asset_perm_ids_from_node}
|
||||||
|
|
||||||
asset_perm_ids = AssetPermission.system_users.through.objects.filter(
|
asset_perms = AssetPermission.objects\
|
||||||
assetpermission_id__in=asset_perm_ids,
|
.filter(id__in=asset_perm_ids, accounts__contains=account)\
|
||||||
systemuser_id=system_user.id
|
.order_by('-date_expired')
|
||||||
).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')
|
|
||||||
|
|
||||||
if asset_perms:
|
if asset_perms:
|
||||||
actions = set()
|
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'
|
relation_name = 'node_id'
|
||||||
self.set_relations(perms, through, relation_name, choices)
|
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):
|
def set_relations(self, perms, through, relation_name, choices, choice_count=None):
|
||||||
relations = []
|
relations = []
|
||||||
|
|
||||||
|
@ -79,4 +73,3 @@ class AssetPermissionGenerator(FakeDataGenerator):
|
||||||
self.set_user_groups(created)
|
self.set_user_groups(created)
|
||||||
self.set_assets(created)
|
self.set_assets(created)
|
||||||
self.set_nodes(created)
|
self.set_nodes(created)
|
||||||
self.set_system_users(created)
|
|
||||||
|
|
Loading…
Reference in New Issue