mirror of https://github.com/jumpserver/jumpserver
perf: 干掉 applications
parent
05e2f8aaf6
commit
3011b18eaa
|
@ -1,3 +0,0 @@
|
|||
from django.contrib import admin
|
||||
|
||||
# Register your models here.
|
|
@ -1,3 +0,0 @@
|
|||
from .application import *
|
||||
from .account import *
|
||||
from .remote_app import *
|
|
@ -1,66 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django_filters import rest_framework as filters
|
||||
from django.db.models import Q
|
||||
|
||||
from common.drf.filters import BaseFilterSet
|
||||
from common.drf.api import JMSBulkModelViewSet
|
||||
from common.mixins import RecordViewLogMixin
|
||||
from common.permissions import UserConfirmation
|
||||
from authentication.const import ConfirmType
|
||||
from rbac.permissions import RBACPermission
|
||||
from assets.models import SystemUser
|
||||
from ..models import Account
|
||||
from .. import serializers
|
||||
|
||||
|
||||
class AccountFilterSet(BaseFilterSet):
|
||||
username = filters.CharFilter(method='do_nothing')
|
||||
type = filters.CharFilter(field_name='type', lookup_expr='exact')
|
||||
category = filters.CharFilter(field_name='category', lookup_expr='exact')
|
||||
app_display = filters.CharFilter(field_name='app_display', lookup_expr='exact')
|
||||
|
||||
class Meta:
|
||||
model = Account
|
||||
fields = ['app', 'systemuser']
|
||||
|
||||
@property
|
||||
def qs(self):
|
||||
qs = super().qs
|
||||
qs = self.filter_username(qs)
|
||||
return qs
|
||||
|
||||
def filter_username(self, qs):
|
||||
username = self.get_query_param('username')
|
||||
if not username:
|
||||
return qs
|
||||
q = Q(username=username) | Q(systemuser__username=username)
|
||||
qs = qs.filter(q).distinct()
|
||||
return qs
|
||||
|
||||
|
||||
class ApplicationAccountViewSet(JMSBulkModelViewSet):
|
||||
model = Account
|
||||
search_fields = ['username', 'app_display']
|
||||
filterset_class = AccountFilterSet
|
||||
filterset_fields = ['username', 'app_display', 'type', 'category', 'app']
|
||||
serializer_class = serializers.AppAccountSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = Account.get_queryset()
|
||||
return queryset
|
||||
|
||||
|
||||
class SystemUserAppRelationViewSet(ApplicationAccountViewSet):
|
||||
perm_model = SystemUser
|
||||
|
||||
|
||||
class ApplicationAccountSecretViewSet(RecordViewLogMixin, ApplicationAccountViewSet):
|
||||
serializer_class = serializers.AppAccountSecretSerializer
|
||||
permission_classes = [RBACPermission, UserConfirmation.require(ConfirmType.MFA)]
|
||||
http_method_names = ['get', 'options']
|
||||
rbac_perms = {
|
||||
'retrieve': 'applications.view_applicationaccountsecret',
|
||||
'list': 'applications.view_applicationaccountsecret',
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.response import Response
|
||||
|
||||
from common.tree import TreeNodeSerializer
|
||||
from common.mixins.api import SuggestionMixin
|
||||
from .. import serializers
|
||||
from ..models import Application
|
||||
|
||||
__all__ = ['ApplicationViewSet']
|
||||
|
||||
|
||||
class ApplicationViewSet(SuggestionMixin, OrgBulkModelViewSet):
|
||||
model = Application
|
||||
filterset_fields = {
|
||||
'name': ['exact'],
|
||||
'category': ['exact', 'in'],
|
||||
'type': ['exact', 'in'],
|
||||
}
|
||||
search_fields = ('name', 'type', 'category')
|
||||
serializer_classes = {
|
||||
'default': serializers.AppSerializer,
|
||||
'get_tree': TreeNodeSerializer,
|
||||
'suggestion': serializers.MiniAppSerializer
|
||||
}
|
||||
rbac_perms = {
|
||||
'get_tree': 'applications.view_application',
|
||||
'match': 'applications.match_application'
|
||||
}
|
||||
|
||||
@action(methods=['GET'], detail=False, url_path='tree')
|
||||
def get_tree(self, request, *args, **kwargs):
|
||||
show_count = request.query_params.get('show_count', '1') == '1'
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
tree_nodes = Application.create_tree_nodes(queryset, show_count=show_count)
|
||||
serializer = self.get_serializer(tree_nodes, many=True)
|
||||
return Response(serializer.data)
|
|
@ -1,16 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from orgs.mixins import generics
|
||||
from .. import models
|
||||
from ..serializers import RemoteAppConnectionInfoSerializer
|
||||
|
||||
|
||||
__all__ = [
|
||||
'RemoteAppConnectionInfoApi',
|
||||
]
|
||||
|
||||
|
||||
class RemoteAppConnectionInfoApi(generics.RetrieveAPIView):
|
||||
model = models.Application
|
||||
serializer_class = RemoteAppConnectionInfoSerializer
|
|
@ -1,14 +0,0 @@
|
|||
"""
|
||||
jumpserver.__app__.hands.py
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
This app depends other apps api, function .. should be import or write mack here.
|
||||
|
||||
Other module of this app shouldn't connect with other app.
|
||||
|
||||
:copyright: (c) 2014-2018 by JumpServer Team.
|
||||
:license: GPL v2, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
|
||||
from users.models import User, UserGroup
|
|
@ -5,7 +5,6 @@ from django.utils.translation import ugettext_lazy as _
|
|||
from django.conf import settings
|
||||
|
||||
from common.tree import TreeNode
|
||||
from ..utils import KubernetesTree
|
||||
from .. import const
|
||||
|
||||
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
from rest_framework import permissions
|
||||
|
||||
|
||||
__all__ = ['IsRemoteApp']
|
||||
|
||||
|
||||
class IsRemoteApp(permissions.BasePermission):
|
||||
def has_object_permission(self, request, view, obj):
|
||||
return obj.category_remote_app
|
|
@ -1,2 +0,0 @@
|
|||
from .application import *
|
||||
from .remote_app import *
|
|
@ -1,168 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
from assets.serializers.base import AuthSerializerMixin
|
||||
from common.drf.serializers import MethodSerializer, SecretReadableMixin
|
||||
from .attrs import (
|
||||
category_serializer_classes_mapping,
|
||||
type_serializer_classes_mapping,
|
||||
type_secret_serializer_classes_mapping
|
||||
)
|
||||
from .. import models
|
||||
from .. import const
|
||||
|
||||
__all__ = [
|
||||
'AppSerializer', 'MiniAppSerializer', 'AppSerializerMixin',
|
||||
'AppAccountSerializer', 'AppAccountSecretSerializer'
|
||||
]
|
||||
|
||||
|
||||
class AppSerializerMixin(serializers.Serializer):
|
||||
attrs = MethodSerializer()
|
||||
|
||||
@property
|
||||
def app(self):
|
||||
if isinstance(self.instance, models.Application):
|
||||
instance = self.instance
|
||||
else:
|
||||
instance = None
|
||||
return instance
|
||||
|
||||
def get_attrs_serializer(self):
|
||||
default_serializer = serializers.Serializer(read_only=True)
|
||||
instance = self.app
|
||||
if instance:
|
||||
_type = instance.type
|
||||
_category = instance.category
|
||||
else:
|
||||
_type = self.context['request'].query_params.get('type')
|
||||
_category = self.context['request'].query_params.get('category')
|
||||
if _type:
|
||||
if isinstance(self, AppAccountSecretSerializer):
|
||||
serializer_class = type_secret_serializer_classes_mapping.get(_type)
|
||||
else:
|
||||
serializer_class = type_serializer_classes_mapping.get(_type)
|
||||
elif _category:
|
||||
serializer_class = category_serializer_classes_mapping.get(_category)
|
||||
else:
|
||||
serializer_class = default_serializer
|
||||
|
||||
if not serializer_class:
|
||||
serializer_class = default_serializer
|
||||
|
||||
if isinstance(serializer_class, type):
|
||||
serializer = serializer_class()
|
||||
else:
|
||||
serializer = serializer_class
|
||||
return serializer
|
||||
|
||||
def create(self, validated_data):
|
||||
return super().create(validated_data)
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
return super().update(instance, validated_data)
|
||||
|
||||
|
||||
class AppSerializer(AppSerializerMixin, BulkOrgResourceModelSerializer):
|
||||
category_display = serializers.ReadOnlyField(source='get_category_display', label=_('Category display'))
|
||||
type_display = serializers.ReadOnlyField(source='get_type_display', label=_('Type display'))
|
||||
|
||||
class Meta:
|
||||
model = models.Application
|
||||
fields_mini = ['id', 'name']
|
||||
fields_small = fields_mini + [
|
||||
'category', 'category_display', 'type', 'type_display',
|
||||
'attrs', 'date_created', 'date_updated', 'created_by', 'comment'
|
||||
]
|
||||
fields_fk = ['domain']
|
||||
fields = fields_small + fields_fk
|
||||
read_only_fields = [
|
||||
'created_by', 'date_created', 'date_updated', 'get_type_display',
|
||||
]
|
||||
|
||||
def validate_attrs(self, attrs):
|
||||
_attrs = self.instance.attrs if self.instance else {}
|
||||
_attrs.update(attrs)
|
||||
return _attrs
|
||||
|
||||
|
||||
class MiniAppSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = models.Application
|
||||
fields = AppSerializer.Meta.fields_mini
|
||||
|
||||
|
||||
class AppAccountSerializer(AppSerializerMixin, AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
||||
category = serializers.ChoiceField(label=_('Category'), choices=const.AppCategory.choices, read_only=True)
|
||||
category_display = serializers.SerializerMethodField(label=_('Category display'))
|
||||
type = serializers.ChoiceField(label=_('Type'), choices=const.AppType.choices, read_only=True)
|
||||
type_display = serializers.SerializerMethodField(label=_('Type display'))
|
||||
date_created = serializers.DateTimeField(label=_('Date created'), format="%Y/%m/%d %H:%M:%S", read_only=True)
|
||||
date_updated = serializers.DateTimeField(label=_('Date updated'), format="%Y/%m/%d %H:%M:%S", read_only=True)
|
||||
|
||||
category_mapper = dict(const.AppCategory.choices)
|
||||
type_mapper = dict(const.AppType.choices)
|
||||
|
||||
class Meta:
|
||||
model = models.Account
|
||||
fields_mini = ['id', 'username', 'version']
|
||||
fields_write_only = ['password', 'private_key', 'public_key', 'passphrase']
|
||||
fields_other = ['date_created', 'date_updated']
|
||||
fields_fk = ['systemuser', 'systemuser_display', 'app', 'app_display']
|
||||
fields = fields_mini + fields_fk + fields_write_only + fields_other + [
|
||||
'type', 'type_display', 'category', 'category_display', 'attrs'
|
||||
]
|
||||
extra_kwargs = {
|
||||
'username': {'default': '', 'required': False},
|
||||
'password': {'write_only': True},
|
||||
'app_display': {'label': _('Application display')},
|
||||
'systemuser_display': {'label': _('System User')},
|
||||
'account': {'label': _('account')}
|
||||
}
|
||||
use_model_bulk_create = True
|
||||
model_bulk_create_kwargs = {
|
||||
'ignore_conflicts': True
|
||||
}
|
||||
|
||||
@property
|
||||
def app(self):
|
||||
if isinstance(self.instance, models.Account):
|
||||
instance = self.instance.app
|
||||
else:
|
||||
instance = None
|
||||
return instance
|
||||
|
||||
def get_category_display(self, obj):
|
||||
return self.category_mapper.get(obj.category)
|
||||
|
||||
def get_type_display(self, obj):
|
||||
return self.type_mapper.get(obj.type)
|
||||
|
||||
@classmethod
|
||||
def setup_eager_loading(cls, queryset):
|
||||
""" Perform necessary eager loading of data. """
|
||||
queryset = queryset.prefetch_related('systemuser', 'app')
|
||||
return queryset
|
||||
|
||||
def to_representation(self, instance):
|
||||
instance.load_auth()
|
||||
return super().to_representation(instance)
|
||||
|
||||
|
||||
class AppAccountSecretSerializer(SecretReadableMixin, AppAccountSerializer):
|
||||
class Meta(AppAccountSerializer.Meta):
|
||||
fields_backup = [
|
||||
'id', 'app_display', 'attrs', 'username', 'password', 'private_key',
|
||||
'public_key', 'date_created', 'date_updated', 'version'
|
||||
]
|
||||
|
||||
extra_kwargs = {
|
||||
'password': {'write_only': False},
|
||||
'private_key': {'write_only': False},
|
||||
'public_key': {'write_only': False},
|
||||
'app_display': {'label': _('Application display')},
|
||||
'systemuser_display': {'label': _('System User')}
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
from .attrs import *
|
|
@ -1,3 +0,0 @@
|
|||
from .remote_app import *
|
||||
from .db import *
|
||||
from .cloud import *
|
|
@ -1,8 +0,0 @@
|
|||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
__all__ = ['CloudSerializer']
|
||||
|
||||
|
||||
class CloudSerializer(serializers.Serializer):
|
||||
cluster = serializers.CharField(max_length=1024, label=_('Cluster'), allow_null=True)
|
|
@ -1,15 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
__all__ = ['DBSerializer']
|
||||
|
||||
|
||||
class DBSerializer(serializers.Serializer):
|
||||
host = serializers.CharField(max_length=128, label=_('Host'), allow_null=True)
|
||||
port = serializers.IntegerField(label=_('Port'), allow_null=True)
|
||||
database = serializers.CharField(
|
||||
max_length=128, required=True, allow_null=True, label=_('Database')
|
||||
)
|
|
@ -1,60 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
||||
from common.utils import get_logger, is_uuid, get_object_or_none
|
||||
from assets.models import Asset
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
__all__ = ['RemoteAppSerializer']
|
||||
|
||||
|
||||
class ExistAssetPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
|
||||
|
||||
def to_internal_value(self, data):
|
||||
instance = super().to_internal_value(data)
|
||||
return str(instance.id)
|
||||
|
||||
def to_representation(self, _id):
|
||||
# _id 是 instance.id
|
||||
if self.pk_field is not None:
|
||||
return self.pk_field.to_representation(_id)
|
||||
# 解决删除资产后,远程应用更新页面会显示资产ID的问题
|
||||
asset = get_object_or_none(Asset, id=_id)
|
||||
if not asset:
|
||||
return None
|
||||
return _id
|
||||
|
||||
|
||||
class RemoteAppSerializer(serializers.Serializer):
|
||||
asset_info = serializers.SerializerMethodField()
|
||||
asset = ExistAssetPrimaryKeyRelatedField(
|
||||
queryset=Asset.objects, required=True, label=_("Asset"), allow_null=True
|
||||
)
|
||||
path = serializers.CharField(
|
||||
max_length=128, label=_('Application path'), allow_null=True
|
||||
)
|
||||
|
||||
def validate_asset(self, asset):
|
||||
if not asset:
|
||||
raise serializers.ValidationError(_('This field is required.'))
|
||||
return asset
|
||||
|
||||
@staticmethod
|
||||
def get_asset_info(obj):
|
||||
asset_id = obj.get('asset')
|
||||
if not asset_id or not is_uuid(asset_id):
|
||||
return {}
|
||||
try:
|
||||
asset = Asset.objects.get(id=str(asset_id))
|
||||
except ObjectDoesNotExist as e:
|
||||
logger.error(e)
|
||||
return {}
|
||||
if not asset:
|
||||
return {}
|
||||
asset_info = {'id': str(asset.id), 'hostname': asset.hostname}
|
||||
return asset_info
|
|
@ -1,15 +0,0 @@
|
|||
|
||||
from .mysql import *
|
||||
from .mariadb import *
|
||||
from .oracle import *
|
||||
from .pgsql import *
|
||||
from .sqlserver import *
|
||||
from .redis import *
|
||||
from .mongodb import *
|
||||
|
||||
from .chrome import *
|
||||
from .mysql_workbench import *
|
||||
from .vmware_client import *
|
||||
from .custom import *
|
||||
|
||||
from .k8s import *
|
|
@ -1,34 +0,0 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.drf.fields import EncryptedField
|
||||
from ..application_category import RemoteAppSerializer
|
||||
|
||||
__all__ = ['ChromeSerializer', 'ChromeSecretSerializer']
|
||||
|
||||
|
||||
class ChromeSerializer(RemoteAppSerializer):
|
||||
CHROME_PATH = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
|
||||
|
||||
path = serializers.CharField(
|
||||
max_length=128, label=_('Application path'), default=CHROME_PATH, allow_null=True,
|
||||
)
|
||||
chrome_target = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False,
|
||||
label=_('Target URL'), allow_null=True,
|
||||
)
|
||||
chrome_username = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False,
|
||||
label=_('Chrome username'), allow_null=True,
|
||||
)
|
||||
chrome_password = EncryptedField(
|
||||
max_length=128, allow_blank=True, required=False,
|
||||
label=_('Chrome password'), allow_null=True
|
||||
)
|
||||
|
||||
|
||||
class ChromeSecretSerializer(ChromeSerializer):
|
||||
chrome_password = EncryptedField(
|
||||
max_length=128, allow_blank=True, required=False,
|
||||
label=_('Chrome password'), allow_null=True, write_only=False
|
||||
)
|
|
@ -1,33 +0,0 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.drf.fields import EncryptedField
|
||||
from ..application_category import RemoteAppSerializer
|
||||
|
||||
__all__ = ['CustomSerializer', 'CustomSecretSerializer']
|
||||
|
||||
|
||||
class CustomSerializer(RemoteAppSerializer):
|
||||
custom_cmdline = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Operating parameter'),
|
||||
allow_null=True,
|
||||
)
|
||||
custom_target = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Target url'),
|
||||
allow_null=True,
|
||||
)
|
||||
custom_username = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Custom Username'),
|
||||
allow_null=True,
|
||||
)
|
||||
custom_password = EncryptedField(
|
||||
max_length=128, allow_blank=True, required=False,
|
||||
label=_('Custom password'), allow_null=True,
|
||||
)
|
||||
|
||||
|
||||
class CustomSecretSerializer(RemoteAppSerializer):
|
||||
custom_password = EncryptedField(
|
||||
max_length=128, allow_blank=True, required=False, write_only=False,
|
||||
label=_('Custom password'), allow_null=True,
|
||||
)
|
|
@ -1,7 +0,0 @@
|
|||
from ..application_category import CloudSerializer
|
||||
|
||||
__all__ = ['K8SSerializer']
|
||||
|
||||
|
||||
class K8SSerializer(CloudSerializer):
|
||||
pass
|
|
@ -1,7 +0,0 @@
|
|||
from .mysql import MySQLSerializer
|
||||
|
||||
__all__ = ['MariaDBSerializer']
|
||||
|
||||
|
||||
class MariaDBSerializer(MySQLSerializer):
|
||||
pass
|
|
@ -1,11 +0,0 @@
|
|||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from ..application_category import DBSerializer
|
||||
|
||||
__all__ = ['MongoDBSerializer']
|
||||
|
||||
|
||||
class MongoDBSerializer(DBSerializer):
|
||||
port = serializers.IntegerField(default=27017, label=_('Port'), allow_null=True)
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from ..application_category import DBSerializer
|
||||
|
||||
__all__ = ['MySQLSerializer']
|
||||
|
||||
|
||||
class MySQLSerializer(DBSerializer):
|
||||
port = serializers.IntegerField(default=3306, label=_('Port'), allow_null=True)
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.drf.fields import EncryptedField
|
||||
from ..application_category import RemoteAppSerializer
|
||||
|
||||
__all__ = ['MySQLWorkbenchSerializer', 'MySQLWorkbenchSecretSerializer']
|
||||
|
||||
|
||||
class MySQLWorkbenchSerializer(RemoteAppSerializer):
|
||||
MYSQL_WORKBENCH_PATH = 'C:\Program Files\MySQL\MySQL Workbench 8.0 CE\MySQLWorkbench.exe'
|
||||
|
||||
path = serializers.CharField(
|
||||
max_length=128, label=_('Application path'), default=MYSQL_WORKBENCH_PATH,
|
||||
allow_null=True,
|
||||
)
|
||||
mysql_workbench_ip = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('IP'),
|
||||
allow_null=True,
|
||||
)
|
||||
mysql_workbench_port = serializers.IntegerField(
|
||||
required=False, label=_('Port'),
|
||||
allow_null=True,
|
||||
)
|
||||
mysql_workbench_name = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Database'),
|
||||
allow_null=True,
|
||||
)
|
||||
mysql_workbench_username = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Mysql workbench username'),
|
||||
allow_null=True,
|
||||
)
|
||||
mysql_workbench_password = EncryptedField(
|
||||
max_length=128, allow_blank=True, required=False,
|
||||
label=_('Mysql workbench password'), allow_null=True,
|
||||
)
|
||||
|
||||
|
||||
class MySQLWorkbenchSecretSerializer(RemoteAppSerializer):
|
||||
mysql_workbench_password = EncryptedField(
|
||||
max_length=128, allow_blank=True, required=False, write_only=False,
|
||||
label=_('Mysql workbench password'), allow_null=True,
|
||||
)
|
|
@ -1,10 +0,0 @@
|
|||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from ..application_category import DBSerializer
|
||||
|
||||
__all__ = ['OracleSerializer']
|
||||
|
||||
|
||||
class OracleSerializer(DBSerializer):
|
||||
port = serializers.IntegerField(default=1521, label=_('Port'), allow_null=True)
|
|
@ -1,10 +0,0 @@
|
|||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from ..application_category import DBSerializer
|
||||
|
||||
__all__ = ['PostgreSerializer']
|
||||
|
||||
|
||||
class PostgreSerializer(DBSerializer):
|
||||
port = serializers.IntegerField(default=5432, label=_('Port'), allow_null=True)
|
|
@ -1,11 +0,0 @@
|
|||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from ..application_category import DBSerializer
|
||||
|
||||
__all__ = ['RedisSerializer']
|
||||
|
||||
|
||||
class RedisSerializer(DBSerializer):
|
||||
port = serializers.IntegerField(default=6379, label=_('Port'), allow_null=True)
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from ..application_category import DBSerializer
|
||||
|
||||
__all__ = ['SQLServerSerializer']
|
||||
|
||||
|
||||
class SQLServerSerializer(DBSerializer):
|
||||
port = serializers.IntegerField(default=1433, label=_('Port'), allow_null=True)
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.drf.fields import EncryptedField
|
||||
from ..application_category import RemoteAppSerializer
|
||||
|
||||
__all__ = ['VMwareClientSerializer', 'VMwareClientSecretSerializer']
|
||||
|
||||
|
||||
class VMwareClientSerializer(RemoteAppSerializer):
|
||||
PATH = r'''
|
||||
C:\Program Files (x86)\VMware\Infrastructure\Virtual Infrastructure Client\Launcher\VpxClient
|
||||
.exe
|
||||
'''
|
||||
VMWARE_CLIENT_PATH = ''.join(PATH.split())
|
||||
|
||||
path = serializers.CharField(
|
||||
max_length=128, label=_('Application path'), default=VMWARE_CLIENT_PATH,
|
||||
allow_null=True
|
||||
)
|
||||
vmware_target = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Target URL'),
|
||||
allow_null=True
|
||||
)
|
||||
vmware_username = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Vmware username'),
|
||||
allow_null=True
|
||||
)
|
||||
vmware_password = EncryptedField(
|
||||
max_length=128, allow_blank=True, required=False,
|
||||
label=_('Vmware password'), allow_null=True
|
||||
)
|
||||
|
||||
|
||||
class VMwareClientSecretSerializer(RemoteAppSerializer):
|
||||
vmware_password = EncryptedField(
|
||||
max_length=128, allow_blank=True, required=False, write_only=False,
|
||||
label=_('Vmware password'), allow_null=True
|
||||
)
|
|
@ -1,62 +0,0 @@
|
|||
import copy
|
||||
|
||||
from applications import const
|
||||
from . import application_category, application_type
|
||||
|
||||
__all__ = [
|
||||
'category_serializer_classes_mapping',
|
||||
'type_serializer_classes_mapping',
|
||||
'get_serializer_class_by_application_type',
|
||||
'type_secret_serializer_classes_mapping'
|
||||
]
|
||||
|
||||
# define `attrs` field `category serializers mapping`
|
||||
# ---------------------------------------------------
|
||||
|
||||
category_serializer_classes_mapping = {
|
||||
const.AppCategory.db.value: application_category.DBSerializer,
|
||||
const.AppCategory.remote_app.value: application_category.RemoteAppSerializer,
|
||||
const.AppCategory.cloud.value: application_category.CloudSerializer,
|
||||
}
|
||||
|
||||
# define `attrs` field `type serializers mapping`
|
||||
# -----------------------------------------------
|
||||
|
||||
type_serializer_classes_mapping = {
|
||||
# db
|
||||
const.AppType.mysql.value: application_type.MySQLSerializer,
|
||||
const.AppType.mariadb.value: application_type.MariaDBSerializer,
|
||||
const.AppType.oracle.value: application_type.OracleSerializer,
|
||||
const.AppType.pgsql.value: application_type.PostgreSerializer,
|
||||
const.AppType.sqlserver.value: application_type.SQLServerSerializer,
|
||||
const.AppType.redis.value: application_type.RedisSerializer,
|
||||
const.AppType.mongodb.value: application_type.MongoDBSerializer,
|
||||
# cloud
|
||||
const.AppType.k8s.value: application_type.K8SSerializer
|
||||
}
|
||||
|
||||
remote_app_serializer_classes_mapping = {
|
||||
# remote-app
|
||||
const.AppType.chrome.value: application_type.ChromeSerializer,
|
||||
const.AppType.mysql_workbench.value: application_type.MySQLWorkbenchSerializer,
|
||||
const.AppType.vmware_client.value: application_type.VMwareClientSerializer,
|
||||
const.AppType.custom.value: application_type.CustomSerializer
|
||||
}
|
||||
|
||||
type_serializer_classes_mapping.update(remote_app_serializer_classes_mapping)
|
||||
|
||||
remote_app_secret_serializer_classes_mapping = {
|
||||
# remote-app
|
||||
const.AppType.chrome.value: application_type.ChromeSecretSerializer,
|
||||
const.AppType.mysql_workbench.value: application_type.MySQLWorkbenchSecretSerializer,
|
||||
const.AppType.vmware_client.value: application_type.VMwareClientSecretSerializer,
|
||||
const.AppType.custom.value: application_type.CustomSecretSerializer
|
||||
}
|
||||
|
||||
type_secret_serializer_classes_mapping = copy.deepcopy(type_serializer_classes_mapping)
|
||||
|
||||
type_secret_serializer_classes_mapping.update(remote_app_secret_serializer_classes_mapping)
|
||||
|
||||
|
||||
def get_serializer_class_by_application_type(_application_type):
|
||||
return type_serializer_classes_mapping.get(_application_type)
|
|
@ -1,31 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
from rest_framework import serializers
|
||||
from common.utils import get_logger
|
||||
from ..models import Application
|
||||
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
__all__ = ['RemoteAppConnectionInfoSerializer']
|
||||
|
||||
|
||||
class RemoteAppConnectionInfoSerializer(serializers.ModelSerializer):
|
||||
parameter_remote_app = serializers.SerializerMethodField()
|
||||
asset = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
model = Application
|
||||
fields = [
|
||||
'id', 'name', 'asset', 'parameter_remote_app',
|
||||
]
|
||||
read_only_fields = ['parameter_remote_app']
|
||||
|
||||
@staticmethod
|
||||
def get_asset(obj):
|
||||
return obj.attrs.get('asset')
|
||||
|
||||
@staticmethod
|
||||
def get_parameter_remote_app(obj):
|
||||
return obj.get_rdp_remote_app_setting()
|
|
@ -1,3 +0,0 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -1,7 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
|
||||
__all__ = [
|
||||
|
||||
]
|
|
@ -1,25 +0,0 @@
|
|||
# coding:utf-8
|
||||
#
|
||||
from django.urls import path
|
||||
from rest_framework_bulk.routes import BulkRouter
|
||||
from .. import api
|
||||
|
||||
|
||||
app_name = 'applications'
|
||||
|
||||
|
||||
router = BulkRouter()
|
||||
router.register(r'applications', api.ApplicationViewSet, 'application')
|
||||
router.register(r'accounts', api.ApplicationAccountViewSet, 'application-account')
|
||||
router.register(r'system-users-apps-relations', api.SystemUserAppRelationViewSet, 'system-users-apps-relation')
|
||||
router.register(r'account-secrets', api.ApplicationAccountSecretViewSet, 'application-account-secret')
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('remote-apps/<uuid:pk>/connection-info/', api.RemoteAppConnectionInfoApi.as_view(), name='remote-app-connection-info'),
|
||||
# path('accounts/', api.ApplicationAccountViewSet.as_view(), name='application-account'),
|
||||
# path('account-secrets/', api.ApplicationAccountSecretViewSet.as_view(), name='application-account-secret')
|
||||
]
|
||||
|
||||
|
||||
urlpatterns += router.urls
|
|
@ -1,4 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from .kubernetes_util import *
|
|
@ -1,186 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from urllib3.exceptions import MaxRetryError
|
||||
from urllib.parse import urlencode
|
||||
|
||||
from kubernetes.client import api_client
|
||||
from kubernetes.client.api import core_v1_api
|
||||
from kubernetes import client
|
||||
from kubernetes.client.exceptions import ApiException
|
||||
|
||||
from rest_framework.generics import get_object_or_404
|
||||
|
||||
from common.utils import get_logger
|
||||
from common.tree import TreeNode
|
||||
from assets.models import SystemUser
|
||||
|
||||
from .. import const
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
class KubernetesClient:
|
||||
def __init__(self, url, token):
|
||||
self.url = url
|
||||
self.token = token
|
||||
|
||||
def get_api(self):
|
||||
configuration = client.Configuration()
|
||||
configuration.host = self.url
|
||||
configuration.verify_ssl = False
|
||||
configuration.api_key = {"authorization": "Bearer " + self.token}
|
||||
c = api_client.ApiClient(configuration=configuration)
|
||||
api = core_v1_api.CoreV1Api(c)
|
||||
return api
|
||||
|
||||
def get_namespace_list(self):
|
||||
api = self.get_api()
|
||||
namespace_list = []
|
||||
for ns in api.list_namespace().items:
|
||||
namespace_list.append(ns.metadata.name)
|
||||
return namespace_list
|
||||
|
||||
def get_services(self):
|
||||
api = self.get_api()
|
||||
ret = api.list_service_for_all_namespaces(watch=False)
|
||||
for i in ret.items:
|
||||
print("%s \t%s \t%s \t%s \t%s \n" % (
|
||||
i.kind, i.metadata.namespace, i.metadata.name, i.spec.cluster_ip, i.spec.ports))
|
||||
|
||||
def get_pod_info(self, namespace, pod):
|
||||
api = self.get_api()
|
||||
resp = api.read_namespaced_pod(namespace=namespace, name=pod)
|
||||
return resp
|
||||
|
||||
def get_pod_logs(self, namespace, pod):
|
||||
api = self.get_api()
|
||||
log_content = api.read_namespaced_pod_log(pod, namespace, pretty=True, tail_lines=200)
|
||||
return log_content
|
||||
|
||||
def get_pods(self):
|
||||
api = self.get_api()
|
||||
try:
|
||||
ret = api.list_pod_for_all_namespaces(watch=False, _request_timeout=(3, 3))
|
||||
except MaxRetryError:
|
||||
logger.warning('Kubernetes connection timed out')
|
||||
return
|
||||
except ApiException as e:
|
||||
if e.status == 401:
|
||||
logger.warning('Kubernetes User not authenticated')
|
||||
else:
|
||||
logger.warning(e)
|
||||
return
|
||||
data = {}
|
||||
for i in ret.items:
|
||||
namespace = i.metadata.namespace
|
||||
pod_info = {
|
||||
'pod_name': i.metadata.name,
|
||||
'containers': [j.name for j in i.spec.containers]
|
||||
}
|
||||
if namespace in data:
|
||||
data[namespace].append(pod_info)
|
||||
else:
|
||||
data[namespace] = [pod_info, ]
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def get_kubernetes_data(app_id, system_user_id):
|
||||
from ..models import Application
|
||||
app = get_object_or_404(Application, id=app_id)
|
||||
system_user = get_object_or_404(SystemUser, id=system_user_id)
|
||||
k8s = KubernetesClient(app.attrs['cluster'], system_user.token)
|
||||
return k8s.get_pods()
|
||||
|
||||
|
||||
class KubernetesTree:
|
||||
def __init__(self, tree_id):
|
||||
self.tree_id = tree_id
|
||||
|
||||
def as_tree_node(self, app):
|
||||
pid = app.create_app_tree_pid(self.tree_id)
|
||||
app_id = str(app.id)
|
||||
parent_info = {'app_id': app_id}
|
||||
node = self.create_tree_node(
|
||||
app_id, pid, app.name, 'k8s', parent_info
|
||||
)
|
||||
return node
|
||||
|
||||
def as_system_user_tree_node(self, system_user, parent_info):
|
||||
from ..models import ApplicationTreeNodeMixin
|
||||
system_user_id = str(system_user.id)
|
||||
username = system_user.username
|
||||
username = username if username else '*'
|
||||
name = f'{system_user.name}({username})'
|
||||
pid = urlencode({'app_id': self.tree_id})
|
||||
i = ApplicationTreeNodeMixin.create_tree_id(pid, 'system_user_id', system_user_id)
|
||||
parent_info.update({'system_user_id': system_user_id})
|
||||
node = self.create_tree_node(
|
||||
i, pid, name, 'system_user', parent_info, icon='user-tie'
|
||||
)
|
||||
return node
|
||||
|
||||
def as_namespace_pod_tree_node(self, name, meta, type, counts=0, is_container=False):
|
||||
from ..models import ApplicationTreeNodeMixin
|
||||
i = ApplicationTreeNodeMixin.create_tree_id(self.tree_id, type, name)
|
||||
meta.update({type: name})
|
||||
name = name if is_container else f'{name}({counts})'
|
||||
node = self.create_tree_node(
|
||||
i, self.tree_id, name, type, meta, icon='cloud', is_container=is_container
|
||||
)
|
||||
return node
|
||||
|
||||
@staticmethod
|
||||
def create_tree_node(id_, pid, name, identity, parent_info, icon='', is_container=False):
|
||||
node = TreeNode(**{
|
||||
'id': id_,
|
||||
'name': name,
|
||||
'title': name,
|
||||
'pId': pid,
|
||||
'isParent': not is_container,
|
||||
'open': False,
|
||||
'iconSkin': icon,
|
||||
'parentInfo': urlencode(parent_info),
|
||||
'meta': {
|
||||
'type': 'application',
|
||||
'data': {
|
||||
'category': const.AppCategory.cloud,
|
||||
'type': const.AppType.k8s,
|
||||
'identity': identity
|
||||
}
|
||||
}
|
||||
})
|
||||
return node
|
||||
|
||||
def async_tree_node(self, parent_info):
|
||||
pod_name = parent_info.get('pod')
|
||||
app_id = parent_info.get('app_id')
|
||||
namespace = parent_info.get('namespace')
|
||||
system_user_id = parent_info.get('system_user_id')
|
||||
|
||||
tree_nodes = []
|
||||
data = KubernetesClient.get_kubernetes_data(app_id, system_user_id)
|
||||
if not data:
|
||||
return tree_nodes
|
||||
|
||||
if pod_name:
|
||||
for container in next(
|
||||
filter(
|
||||
lambda x: x['pod_name'] == pod_name, data[namespace]
|
||||
)
|
||||
)['containers']:
|
||||
container_node = self.as_namespace_pod_tree_node(
|
||||
container, parent_info, 'container', is_container=True
|
||||
)
|
||||
tree_nodes.append(container_node)
|
||||
elif namespace:
|
||||
for pod in data[namespace]:
|
||||
pod_nodes = self.as_namespace_pod_tree_node(
|
||||
pod['pod_name'], parent_info, 'pod', len(pod['containers'])
|
||||
)
|
||||
tree_nodes.append(pod_nodes)
|
||||
elif system_user_id:
|
||||
for namespace, pods in data.items():
|
||||
namespace_node = self.as_namespace_pod_tree_node(
|
||||
namespace, parent_info, 'namespace', len(pods)
|
||||
)
|
||||
tree_nodes.append(namespace_node)
|
||||
return tree_nodes
|
|
@ -5,7 +5,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||
|
||||
from common.drf.serializers import JMSWritableNestedModelSerializer
|
||||
from orgs.mixins.serializers import OrgResourceModelSerializerMixin
|
||||
from ...models import Asset, Node, Platform, Protocol, Label, Domain
|
||||
from ...models import Asset, Node, Platform, Protocol, Label, Domain, Account
|
||||
from ..mixin import CategoryDisplayMixin
|
||||
from ..account import AccountSerializer
|
||||
|
||||
|
@ -59,7 +59,7 @@ class AssetSerializer(CategoryDisplayMixin,
|
|||
OrgResourceModelSerializerMixin):
|
||||
domain = AssetDomainSerializer(required=False)
|
||||
nodes_display = serializers.ListField(
|
||||
child=serializers.CharField(), label=_('Nodes name'), required=False
|
||||
child=serializers.CharField(), label=_('Nodes name'), required=False,
|
||||
)
|
||||
labels = AssetLabelSerializer(many=True, required=False)
|
||||
nodes = AssetNodesSerializer(many=True, required=False)
|
||||
|
@ -105,7 +105,6 @@ class AssetSerializer(CategoryDisplayMixin,
|
|||
super().__init__(*args, **kwargs)
|
||||
|
||||
def validate_type(self, value):
|
||||
print(self.initial_data)
|
||||
return value
|
||||
|
||||
def validate_category(self, value):
|
||||
|
|
|
@ -21,7 +21,6 @@ api_v1 = [
|
|||
path('settings/', include('settings.urls.api_urls', namespace='api-settings')),
|
||||
path('authentication/', include('authentication.urls.api_urls', namespace='api-auth')),
|
||||
path('common/', include('common.urls.api_urls', namespace='api-common')),
|
||||
path('applications/', include('applications.urls.api_urls', namespace='api-applications')),
|
||||
path('tickets/', include('tickets.urls.api_urls', namespace='api-tickets')),
|
||||
path('acls/', include('acls.urls.api_urls', namespace='api-acls')),
|
||||
path('notifications/', include('notifications.urls.api_urls', namespace='api-notifications')),
|
||||
|
|
|
@ -2,5 +2,4 @@
|
|||
#
|
||||
|
||||
from .asset import *
|
||||
from .application import *
|
||||
from .system_user_permission import *
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
from .user_permission import *
|
||||
from .application_permission import *
|
||||
from .application_permission_relation import *
|
||||
from .user_group_permission import *
|
|
@ -1,55 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from applications.models import Application
|
||||
from perms.models import ApplicationPermission
|
||||
from perms import serializers
|
||||
from ..base import BasePermissionViewSet
|
||||
|
||||
|
||||
class ApplicationPermissionViewSet(BasePermissionViewSet):
|
||||
"""
|
||||
应用授权列表的增删改查API
|
||||
"""
|
||||
model = ApplicationPermission
|
||||
serializer_class = serializers.ApplicationPermissionSerializer
|
||||
filterset_fields = {
|
||||
'name': ['exact'],
|
||||
'category': ['exact'],
|
||||
'type': ['exact', 'in'],
|
||||
'from_ticket': ['exact']
|
||||
}
|
||||
search_fields = ['name', 'category', 'type']
|
||||
custom_filter_fields = BasePermissionViewSet.custom_filter_fields + [
|
||||
'application_id', 'application', 'app', 'app_name'
|
||||
]
|
||||
ordering_fields = ('name',)
|
||||
ordering = ('name', )
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset().prefetch_related(
|
||||
"applications", "users", "user_groups", "system_users"
|
||||
)
|
||||
return queryset
|
||||
|
||||
def filter_application(self, queryset):
|
||||
app_id = self.request.query_params.get('application_id') or \
|
||||
self.request.query_params.get('app')
|
||||
app_name = self.request.query_params.get('application') or \
|
||||
self.request.query_params.get('app_name')
|
||||
|
||||
if app_id:
|
||||
applications = Application.objects.filter(pk=app_id)
|
||||
elif app_name:
|
||||
applications = Application.objects.filter(name=app_name)
|
||||
else:
|
||||
return queryset
|
||||
if not applications:
|
||||
return queryset.none()
|
||||
queryset = queryset.filter(applications__in=applications)
|
||||
return queryset
|
||||
|
||||
def filter_queryset(self, queryset):
|
||||
queryset = super().filter_queryset(queryset)
|
||||
queryset = self.filter_application(queryset)
|
||||
return queryset
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from rest_framework import generics
|
||||
from django.db.models import F, Value
|
||||
from django.db.models.functions import Concat
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from applications.models import Application
|
||||
from orgs.mixins.api import OrgRelationMixin
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
from orgs.utils import current_org
|
||||
from perms import serializers
|
||||
from perms import models
|
||||
|
||||
__all__ = [
|
||||
'ApplicationPermissionUserRelationViewSet',
|
||||
'ApplicationPermissionUserGroupRelationViewSet',
|
||||
'ApplicationPermissionApplicationRelationViewSet',
|
||||
'ApplicationPermissionSystemUserRelationViewSet',
|
||||
'ApplicationPermissionAllApplicationListApi',
|
||||
'ApplicationPermissionAllUserListApi',
|
||||
]
|
||||
|
||||
|
||||
class RelationMixin(OrgRelationMixin, OrgBulkModelViewSet):
|
||||
perm_model = models.ApplicationPermission
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
org_id = current_org.org_id()
|
||||
if org_id is not None:
|
||||
queryset = queryset.filter(applicationpermission__org_id=org_id)
|
||||
queryset = queryset.annotate(applicationpermission_display=F('applicationpermission__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class ApplicationPermissionUserRelationViewSet(RelationMixin):
|
||||
serializer_class = serializers.ApplicationPermissionUserRelationSerializer
|
||||
m2m_field = models.ApplicationPermission.users.field
|
||||
filterset_fields = [
|
||||
'id', "user", "applicationpermission",
|
||||
]
|
||||
search_fields = ("user__name", "user__username", "applicationpermission__name")
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset.annotate(user_display=F('user__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class ApplicationPermissionUserGroupRelationViewSet(RelationMixin):
|
||||
serializer_class = serializers.ApplicationPermissionUserGroupRelationSerializer
|
||||
m2m_field = models.ApplicationPermission.user_groups.field
|
||||
filterset_fields = [
|
||||
'id', "usergroup", "applicationpermission"
|
||||
]
|
||||
search_fields = ["usergroup__name", "applicationpermission__name"]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset.annotate(usergroup_display=F('usergroup__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class ApplicationPermissionApplicationRelationViewSet(RelationMixin):
|
||||
serializer_class = serializers.ApplicationPermissionApplicationRelationSerializer
|
||||
m2m_field = models.ApplicationPermission.applications.field
|
||||
filterset_fields = [
|
||||
'id', 'application', 'applicationpermission',
|
||||
]
|
||||
search_fields = ["id", "application__name", "applicationpermission__name"]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset.annotate(application_display=F('application__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class ApplicationPermissionSystemUserRelationViewSet(RelationMixin):
|
||||
serializer_class = serializers.ApplicationPermissionSystemUserRelationSerializer
|
||||
m2m_field = models.ApplicationPermission.system_users.field
|
||||
filterset_fields = [
|
||||
'id', 'systemuser', 'applicationpermission',
|
||||
]
|
||||
search_fields = [
|
||||
"applicactionpermission__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
|
||||
|
||||
|
||||
class ApplicationPermissionAllApplicationListApi(generics.ListAPIView):
|
||||
serializer_class = serializers.ApplicationPermissionAllApplicationSerializer
|
||||
only_fields = serializers.ApplicationPermissionAllApplicationSerializer.Meta.only_fields
|
||||
filterset_fields = ('name',)
|
||||
search_fields = filterset_fields
|
||||
|
||||
def get_queryset(self):
|
||||
pk = self.kwargs.get('pk')
|
||||
perm = get_object_or_404(models.ApplicationPermission, pk=pk)
|
||||
applications = Application.objects.filter(granted_by_permissions=perm) \
|
||||
.only(*self.only_fields).distinct()
|
||||
return applications
|
||||
|
||||
|
||||
class ApplicationPermissionAllUserListApi(generics.ListAPIView):
|
||||
serializer_class = serializers.ApplicationPermissionAllUserSerializer
|
||||
only_fields = serializers.ApplicationPermissionAllUserSerializer.Meta.only_fields
|
||||
filterset_fields = ('username', 'name')
|
||||
search_fields = filterset_fields
|
||||
|
||||
def get_queryset(self):
|
||||
pk = self.kwargs.get('pk')
|
||||
perm = get_object_or_404(models.ApplicationPermission, pk=pk)
|
||||
users = perm.get_all_users().only(*self.only_fields).distinct()
|
||||
return users
|
|
@ -1,36 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from django.db.models import Q
|
||||
from rest_framework.generics import ListAPIView
|
||||
|
||||
from common.mixins.api import CommonApiMixin
|
||||
from applications.models import Application
|
||||
from perms import serializers
|
||||
|
||||
__all__ = [
|
||||
'UserGroupGrantedApplicationsApi'
|
||||
]
|
||||
|
||||
|
||||
class UserGroupGrantedApplicationsApi(CommonApiMixin, ListAPIView):
|
||||
"""
|
||||
获取用户组直接授权的应用
|
||||
"""
|
||||
serializer_class = serializers.AppGrantedSerializer
|
||||
only_fields = serializers.AppGrantedSerializer.Meta.only_fields
|
||||
filterset_fields = ['id', 'name', 'category', 'type', 'comment']
|
||||
search_fields = ['name', 'comment']
|
||||
rbac_perms = {
|
||||
'list': 'perms.view_applicationpermission'
|
||||
}
|
||||
|
||||
def get_queryset(self):
|
||||
user_group_id = self.kwargs.get('pk')
|
||||
if not user_group_id:
|
||||
return Application.objects.none()
|
||||
|
||||
queryset = Application.objects\
|
||||
.filter(Q(granted_by_permissions__user_groups__id=user_group_id))\
|
||||
.distinct().only(*self.only_fields)
|
||||
return queryset
|
|
@ -1,2 +0,0 @@
|
|||
from .user_permission_applications import *
|
||||
from .common import *
|
|
@ -1,83 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
import time
|
||||
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.decorators import method_decorator
|
||||
from rest_framework.views import APIView, Response
|
||||
from rest_framework import status
|
||||
from rest_framework.generics import (
|
||||
ListAPIView, get_object_or_404
|
||||
)
|
||||
|
||||
from orgs.utils import tmp_to_root_org
|
||||
from applications.models import Application
|
||||
from perms.utils.application.permission import (
|
||||
get_application_system_user_ids,
|
||||
validate_permission,
|
||||
)
|
||||
from .mixin import AppRoleAdminMixin, AppRoleUserMixin
|
||||
from perms.hands import User, SystemUser
|
||||
from perms import serializers
|
||||
|
||||
__all__ = [
|
||||
'UserGrantedApplicationSystemUsersApi',
|
||||
'MyGrantedApplicationSystemUsersApi',
|
||||
'ValidateUserApplicationPermissionApi'
|
||||
]
|
||||
|
||||
|
||||
class BaseGrantedApplicationSystemUsersApi(ListAPIView):
|
||||
serializer_class = serializers.ApplicationSystemUserSerializer
|
||||
only_fields = serializers.ApplicationSystemUserSerializer.Meta.only_fields
|
||||
user: None
|
||||
|
||||
def get_application_system_user_ids(self, application):
|
||||
return get_application_system_user_ids(self.user, application)
|
||||
|
||||
def get_queryset(self):
|
||||
application_id = self.kwargs.get('application_id')
|
||||
application = get_object_or_404(Application, id=application_id)
|
||||
system_user_ids = self.get_application_system_user_ids(application)
|
||||
system_users = SystemUser.objects.filter(id__in=system_user_ids) \
|
||||
.only(*self.only_fields).order_by('priority')
|
||||
return system_users
|
||||
|
||||
|
||||
class UserGrantedApplicationSystemUsersApi(AppRoleAdminMixin, BaseGrantedApplicationSystemUsersApi):
|
||||
pass
|
||||
|
||||
|
||||
class MyGrantedApplicationSystemUsersApi(AppRoleUserMixin, BaseGrantedApplicationSystemUsersApi):
|
||||
pass
|
||||
|
||||
|
||||
@method_decorator(tmp_to_root_org(), name='get')
|
||||
class ValidateUserApplicationPermissionApi(APIView):
|
||||
rbac_perms = {
|
||||
'GET': 'perms.view_applicationpermission'
|
||||
}
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
user_id = request.query_params.get('user_id', '')
|
||||
application_id = request.query_params.get('application_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, account)):
|
||||
return Response(data)
|
||||
|
||||
user = User.objects.get(id=user_id)
|
||||
application = Application.objects.get(id=application_id)
|
||||
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,
|
||||
'expire_at': int(expire_at),
|
||||
'actions': actions
|
||||
}
|
||||
return Response(data, status=status_code)
|
|
@ -1,24 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from common.mixins.api import RoleAdminMixin as _RoleAdminMixin
|
||||
from common.mixins.api import RoleUserMixin as _RoleUserMixin
|
||||
from orgs.utils import tmp_to_root_org
|
||||
|
||||
|
||||
class AppRoleAdminMixin(_RoleAdminMixin):
|
||||
rbac_perms = (
|
||||
('list', 'perms.view_userapp'),
|
||||
('retrieve', 'perms.view_userapps'),
|
||||
('get_tree', 'perms.view_userapps'),
|
||||
('GET', 'perms.view_userapps'),
|
||||
)
|
||||
|
||||
|
||||
class AppRoleUserMixin(_RoleUserMixin):
|
||||
rbac_perms = (
|
||||
('list', 'perms.view_myapps'),
|
||||
('retrieve', 'perms.view_myapps'),
|
||||
('get_tree', 'perms.view_myapps'),
|
||||
('GET', 'perms.view_myapps'),
|
||||
)
|
|
@ -1,81 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from typing import Callable
|
||||
|
||||
from rest_framework.generics import ListAPIView
|
||||
from rest_framework.response import Response
|
||||
|
||||
from common.mixins.api import CommonApiMixin
|
||||
from common.tree import TreeNodeSerializer
|
||||
from perms import serializers
|
||||
from perms.tree.app import GrantedAppTreeUtil
|
||||
from perms.utils.application.user_permission import (
|
||||
get_user_granted_all_applications
|
||||
)
|
||||
from .mixin import AppRoleAdminMixin, AppRoleUserMixin
|
||||
|
||||
|
||||
__all__ = [
|
||||
'UserAllGrantedApplicationsApi',
|
||||
'MyAllGrantedApplicationsApi',
|
||||
'UserAllGrantedApplicationsAsTreeApi',
|
||||
'MyAllGrantedApplicationsAsTreeApi',
|
||||
]
|
||||
|
||||
|
||||
class AllGrantedApplicationsApi(CommonApiMixin, ListAPIView):
|
||||
only_fields = serializers.AppGrantedSerializer.Meta.only_fields
|
||||
serializer_class = serializers.AppGrantedSerializer
|
||||
filterset_fields = {
|
||||
'id': ['exact'],
|
||||
'name': ['exact'],
|
||||
'category': ['exact'],
|
||||
'type': ['exact', 'in'],
|
||||
'comment': ['exact'],
|
||||
}
|
||||
search_fields = ['name', 'comment']
|
||||
user: None
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = get_user_granted_all_applications(self.user)
|
||||
return queryset.only(*self.only_fields)
|
||||
|
||||
|
||||
class UserAllGrantedApplicationsApi(AppRoleAdminMixin, AllGrantedApplicationsApi):
|
||||
pass
|
||||
|
||||
|
||||
class MyAllGrantedApplicationsApi(AppRoleUserMixin, AllGrantedApplicationsApi):
|
||||
pass
|
||||
|
||||
|
||||
class ApplicationsAsTreeMixin:
|
||||
"""
|
||||
将应用序列化成树的结构返回
|
||||
"""
|
||||
serializer_class = TreeNodeSerializer
|
||||
user: None
|
||||
filter_queryset: Callable
|
||||
get_queryset: Callable
|
||||
get_serializer: Callable
|
||||
|
||||
def list(self, request, *args, **kwargs):
|
||||
tree_id = request.query_params.get('tree_id', None)
|
||||
parent_info = request.query_params.get('parentInfo', None)
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
util = GrantedAppTreeUtil()
|
||||
|
||||
if not tree_id:
|
||||
tree_nodes = util.create_tree_nodes(queryset)
|
||||
else:
|
||||
tree_nodes = util.get_children_nodes(tree_id, parent_info, self.user)
|
||||
serializer = self.get_serializer(tree_nodes, many=True)
|
||||
return Response(data=serializer.data)
|
||||
|
||||
|
||||
class UserAllGrantedApplicationsAsTreeApi(ApplicationsAsTreeMixin, UserAllGrantedApplicationsApi):
|
||||
pass
|
||||
|
||||
|
||||
class MyAllGrantedApplicationsAsTreeApi(ApplicationsAsTreeMixin, MyAllGrantedApplicationsApi):
|
||||
pass
|
|
@ -2,5 +2,4 @@
|
|||
#
|
||||
from .base import *
|
||||
from .asset import *
|
||||
from .application import *
|
||||
from .system_user_permission import *
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
from .permission import *
|
||||
from .permission_relation import *
|
||||
from .user_permission import *
|
|
@ -1,83 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
from perms.models import ApplicationPermission, Action
|
||||
from ..base import ActionsField, BasePermissionSerializer
|
||||
|
||||
__all__ = [
|
||||
'ApplicationPermissionSerializer'
|
||||
]
|
||||
|
||||
|
||||
class ApplicationPermissionSerializer(BasePermissionSerializer):
|
||||
actions = ActionsField(required=False, allow_null=True, label=_("Actions"))
|
||||
category_display = serializers.ReadOnlyField(source='get_category_display', label=_('Category display'))
|
||||
type_display = serializers.ReadOnlyField(source='get_type_display', label=_('Type display'))
|
||||
is_valid = serializers.BooleanField(read_only=True, label=_('Is valid'))
|
||||
is_expired = serializers.BooleanField(read_only=True, label=_("Is expired"))
|
||||
|
||||
class Meta:
|
||||
model = ApplicationPermission
|
||||
fields_mini = ['id', 'name']
|
||||
fields_small = fields_mini + [
|
||||
'category', 'category_display', 'type', 'type_display',
|
||||
'actions',
|
||||
'is_active', 'is_expired', 'is_valid',
|
||||
'created_by', 'date_created', 'date_expired', 'date_start', 'comment', 'from_ticket'
|
||||
]
|
||||
fields_m2m = [
|
||||
'users', 'user_groups', 'applications', 'system_users',
|
||||
'users_amount', 'user_groups_amount', 'applications_amount',
|
||||
'system_users_amount',
|
||||
]
|
||||
fields = fields_small + fields_m2m
|
||||
read_only_fields = ['created_by', 'date_created', 'from_ticket']
|
||||
extra_kwargs = {
|
||||
'is_expired': {'label': _('Is expired')},
|
||||
'is_valid': {'label': _('Is valid')},
|
||||
'actions': {'label': _('Actions')},
|
||||
'users_amount': {'label': _('Users amount')},
|
||||
'user_groups_amount': {'label': _('User groups amount')},
|
||||
'system_users_amount': {'label': _('System users amount')},
|
||||
'applications_amount': {'label': _('Apps amount')},
|
||||
}
|
||||
|
||||
def _filter_actions_choices(self, choices):
|
||||
if request := self.context.get('request'):
|
||||
category = request.query_params.get('category')
|
||||
else:
|
||||
category = None
|
||||
exclude_choices = ApplicationPermission.get_exclude_actions_choices(category=category)
|
||||
for choice in exclude_choices:
|
||||
choices.pop(choice, None)
|
||||
return choices
|
||||
|
||||
@classmethod
|
||||
def setup_eager_loading(cls, queryset):
|
||||
""" Perform necessary eager loading of data. """
|
||||
queryset = queryset.prefetch_related(
|
||||
'users', 'user_groups', 'applications', 'system_users'
|
||||
)
|
||||
return queryset
|
||||
|
||||
def validate_applications(self, applications):
|
||||
if self.instance:
|
||||
permission_type = self.instance.type
|
||||
else:
|
||||
permission_type = self.initial_data['type']
|
||||
|
||||
other_type_applications = [
|
||||
application for application in applications
|
||||
if application.type != permission_type
|
||||
]
|
||||
if len(other_type_applications) > 0:
|
||||
error = _(
|
||||
'The application list contains applications '
|
||||
'that are different from the permission type. ({})'
|
||||
).format(', '.join([application.name for application in other_type_applications]))
|
||||
raise serializers.ValidationError(error)
|
||||
return applications
|
|
@ -1,88 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.mixins import BulkSerializerMixin
|
||||
from perms.models import ApplicationPermission
|
||||
|
||||
__all__ = [
|
||||
'ApplicationPermissionUserRelationSerializer',
|
||||
'ApplicationPermissionUserGroupRelationSerializer',
|
||||
'ApplicationPermissionApplicationRelationSerializer',
|
||||
'ApplicationPermissionSystemUserRelationSerializer',
|
||||
'ApplicationPermissionAllApplicationSerializer',
|
||||
'ApplicationPermissionAllUserSerializer'
|
||||
]
|
||||
|
||||
|
||||
class RelationMixin(BulkSerializerMixin, serializers.Serializer):
|
||||
applicationpermission_display = serializers.ReadOnlyField()
|
||||
|
||||
def get_field_names(self, declared_fields, info):
|
||||
fields = super().get_field_names(declared_fields, info)
|
||||
fields.extend(['applicationpermission', "applicationpermission_display"])
|
||||
return fields
|
||||
|
||||
|
||||
class ApplicationPermissionUserRelationSerializer(RelationMixin, serializers.ModelSerializer):
|
||||
user_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = ApplicationPermission.users.through
|
||||
fields = [
|
||||
'id', 'user', 'user_display',
|
||||
]
|
||||
|
||||
|
||||
class ApplicationPermissionUserGroupRelationSerializer(RelationMixin, serializers.ModelSerializer):
|
||||
usergroup_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = ApplicationPermission.user_groups.through
|
||||
fields = [
|
||||
'id', 'usergroup', "usergroup_display",
|
||||
]
|
||||
|
||||
|
||||
class ApplicationPermissionApplicationRelationSerializer(RelationMixin, serializers.ModelSerializer):
|
||||
application_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = ApplicationPermission.applications.through
|
||||
fields = [
|
||||
'id', "application", "application_display",
|
||||
]
|
||||
|
||||
|
||||
class ApplicationPermissionSystemUserRelationSerializer(RelationMixin, serializers.ModelSerializer):
|
||||
systemuser_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = ApplicationPermission.system_users.through
|
||||
fields = [
|
||||
'id', 'systemuser', 'systemuser_display'
|
||||
]
|
||||
|
||||
|
||||
class ApplicationPermissionAllApplicationSerializer(serializers.Serializer):
|
||||
application = serializers.UUIDField(read_only=True, source='id')
|
||||
application_display = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
only_fields = ['id', 'name']
|
||||
|
||||
@staticmethod
|
||||
def get_application_display(obj):
|
||||
return str(obj)
|
||||
|
||||
|
||||
class ApplicationPermissionAllUserSerializer(serializers.Serializer):
|
||||
user = serializers.UUIDField(read_only=True, source='id')
|
||||
user_display = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
only_fields = ['id', 'username', 'name']
|
||||
|
||||
@staticmethod
|
||||
def get_user_display(obj):
|
||||
return str(obj)
|
|
@ -1,42 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from assets.models import SystemUser
|
||||
from applications.models import Application
|
||||
from applications.serializers import AppSerializerMixin
|
||||
|
||||
__all__ = [
|
||||
'AppGrantedSerializer', 'ApplicationSystemUserSerializer'
|
||||
]
|
||||
|
||||
|
||||
class ApplicationSystemUserSerializer(serializers.ModelSerializer):
|
||||
"""
|
||||
查看授权的应用系统用户的数据结构,这个和SystemUserSerializer不同,字段少
|
||||
"""
|
||||
class Meta:
|
||||
model = SystemUser
|
||||
only_fields = (
|
||||
'id', 'name', 'username', 'priority', 'protocol', 'login_mode'
|
||||
)
|
||||
fields = list(only_fields)
|
||||
read_only_fields = fields
|
||||
|
||||
|
||||
class AppGrantedSerializer(AppSerializerMixin, serializers.ModelSerializer):
|
||||
"""
|
||||
被授权应用的数据结构
|
||||
"""
|
||||
category_display = serializers.ReadOnlyField(source='get_category_display', label=_('Category'))
|
||||
type_display = serializers.ReadOnlyField(source='get_type_display', label=_('Type'))
|
||||
|
||||
class Meta:
|
||||
model = Application
|
||||
only_fields = [
|
||||
'id', 'name', 'domain', 'category', 'type', 'attrs', 'comment', 'org_id'
|
||||
]
|
||||
fields = only_fields + ['category_display', 'type_display', 'org_name']
|
||||
read_only_fields = fields
|
|
@ -1,3 +1,2 @@
|
|||
from . import asset_permission
|
||||
from . import app_permission
|
||||
from . import refresh_perms
|
||||
|
|
|
@ -1,106 +0,0 @@
|
|||
import itertools
|
||||
|
||||
from django.db.models.signals import m2m_changed
|
||||
from django.dispatch import receiver
|
||||
|
||||
from users.models import User, UserGroup
|
||||
from assets.models import Asset, SystemUser
|
||||
from applications.models import Application
|
||||
from common.utils import get_logger
|
||||
from common.exceptions import M2MReverseNotAllowed
|
||||
from common.decorator import on_transaction_commit
|
||||
from common.const.signals import POST_ADD
|
||||
from perms.models import ApplicationPermission
|
||||
from applications.models import Account as AppAccount
|
||||
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
@receiver(m2m_changed, sender=ApplicationPermission.applications.through)
|
||||
@on_transaction_commit
|
||||
def on_app_permission_applications_changed(sender, instance, action, reverse, pk_set, **kwargs):
|
||||
if reverse:
|
||||
raise M2MReverseNotAllowed
|
||||
if action != POST_ADD:
|
||||
return
|
||||
|
||||
logger.debug("Application permission applications change signal received")
|
||||
system_users = instance.system_users.all()
|
||||
set_remote_app_asset_system_users_if_need(instance, system_users=system_users)
|
||||
|
||||
apps = Application.objects.filter(pk__in=pk_set)
|
||||
set_app_accounts(apps, system_users)
|
||||
|
||||
|
||||
def set_app_accounts(apps, system_users):
|
||||
for app, system_user in itertools.product(apps, system_users):
|
||||
AppAccount.objects.get_or_create(
|
||||
defaults={'app': app, 'systemuser': system_user},
|
||||
app=app, systemuser=system_user
|
||||
)
|
||||
|
||||
|
||||
def set_remote_app_asset_system_users_if_need(instance: ApplicationPermission, system_users=None,
|
||||
users=None, groups=None):
|
||||
if not instance.category_remote_app:
|
||||
return
|
||||
|
||||
attrs = instance.applications.all().values_list('attrs', flat=True)
|
||||
asset_ids = [attr['asset'] for attr in attrs if attr.get('asset')]
|
||||
# 远程应用中资产可能在资产表里不存在
|
||||
asset_ids = Asset.objects.filter(id__in=asset_ids).values_list('id', flat=True)
|
||||
if not asset_ids:
|
||||
return
|
||||
|
||||
system_users = system_users or instance.system_users.all()
|
||||
for system_user in system_users:
|
||||
system_user.add_related_assets(asset_ids)
|
||||
|
||||
if system_user.username_same_with_user:
|
||||
users = users or instance.users.all()
|
||||
groups = groups or instance.user_groups.all()
|
||||
system_user.groups.add(*groups)
|
||||
system_user.users.add(*users)
|
||||
|
||||
|
||||
@receiver(m2m_changed, sender=ApplicationPermission.system_users.through)
|
||||
@on_transaction_commit
|
||||
def on_app_permission_system_users_changed(sender, instance, action, reverse, pk_set, **kwargs):
|
||||
if reverse:
|
||||
raise M2MReverseNotAllowed
|
||||
if action != POST_ADD:
|
||||
return
|
||||
|
||||
logger.debug("Application permission system_users change signal received")
|
||||
system_users = SystemUser.objects.filter(pk__in=pk_set)
|
||||
|
||||
set_remote_app_asset_system_users_if_need(instance, system_users=system_users)
|
||||
apps = instance.applications.all()
|
||||
set_app_accounts(apps, system_users)
|
||||
|
||||
|
||||
@receiver(m2m_changed, sender=ApplicationPermission.users.through)
|
||||
@on_transaction_commit
|
||||
def on_app_permission_users_changed(sender, instance, action, reverse, pk_set, **kwargs):
|
||||
if reverse:
|
||||
raise M2MReverseNotAllowed
|
||||
if action != POST_ADD:
|
||||
return
|
||||
|
||||
logger.debug("Application permission users change signal received")
|
||||
users = User.objects.filter(pk__in=pk_set)
|
||||
set_remote_app_asset_system_users_if_need(instance, users=users)
|
||||
|
||||
|
||||
@receiver(m2m_changed, sender=ApplicationPermission.user_groups.through)
|
||||
@on_transaction_commit
|
||||
def on_app_permission_user_groups_changed(sender, instance, action, reverse, pk_set, **kwargs):
|
||||
if reverse:
|
||||
raise M2MReverseNotAllowed
|
||||
if action != POST_ADD:
|
||||
return
|
||||
|
||||
logger.debug("Application permission user groups change signal received")
|
||||
groups = UserGroup.objects.filter(pk__in=pk_set)
|
||||
set_remote_app_asset_system_users_if_need(instance, groups=groups)
|
|
@ -1,103 +0,0 @@
|
|||
from urllib.parse import urlencode, parse_qsl
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from rest_framework.generics import get_object_or_404
|
||||
|
||||
from common.tree import TreeNode
|
||||
from orgs.models import Organization
|
||||
from assets.models import SystemUser
|
||||
from applications.utils import KubernetesTree
|
||||
from applications.models import Application
|
||||
from perms.utils.application.permission import get_application_system_user_ids
|
||||
|
||||
|
||||
class GrantedAppTreeUtil:
|
||||
@staticmethod
|
||||
def filter_organizations(applications):
|
||||
organization_ids = set(applications.values_list('org_id', flat=True))
|
||||
organizations = [Organization.get_instance(org_id) for org_id in organization_ids]
|
||||
organizations.sort(key=lambda x: x.name)
|
||||
return organizations
|
||||
|
||||
@staticmethod
|
||||
def create_root_node():
|
||||
name = _('My applications')
|
||||
node = TreeNode(**{
|
||||
'id': 'applications',
|
||||
'name': name,
|
||||
'title': name,
|
||||
'pId': '',
|
||||
'open': True,
|
||||
'iconSkin': 'applications',
|
||||
'isParent': True,
|
||||
'meta': {
|
||||
'type': 'root'
|
||||
}
|
||||
})
|
||||
return node
|
||||
|
||||
@staticmethod
|
||||
def create_empty_node():
|
||||
name = _("Empty")
|
||||
node = TreeNode(**{
|
||||
'id': 'empty',
|
||||
'name': name,
|
||||
'title': name,
|
||||
'pId': '',
|
||||
'isParent': True,
|
||||
'children': [],
|
||||
'meta': {
|
||||
'type': 'application'
|
||||
}
|
||||
})
|
||||
return node
|
||||
|
||||
@staticmethod
|
||||
def get_children_nodes(tree_id, parent_info, user):
|
||||
tree_nodes = []
|
||||
parent_info = dict(parse_qsl(parent_info))
|
||||
pod_name = parent_info.get('pod')
|
||||
app_id = parent_info.get('app_id')
|
||||
namespace = parent_info.get('namespace')
|
||||
system_user_id = parent_info.get('system_user_id')
|
||||
|
||||
if app_id and not any([pod_name, namespace, system_user_id]):
|
||||
app = get_object_or_404(Application, id=app_id)
|
||||
system_user_ids = get_application_system_user_ids(user, app)
|
||||
system_users = SystemUser.objects.filter(id__in=system_user_ids).order_by('priority')
|
||||
for system_user in system_users:
|
||||
system_user_node = KubernetesTree(tree_id).as_system_user_tree_node(
|
||||
system_user, parent_info
|
||||
)
|
||||
tree_nodes.append(system_user_node)
|
||||
return tree_nodes
|
||||
tree_nodes = KubernetesTree(tree_id).async_tree_node(parent_info)
|
||||
return tree_nodes
|
||||
|
||||
def create_tree_nodes(self, applications):
|
||||
tree_nodes = []
|
||||
if not applications:
|
||||
return [self.create_empty_node()]
|
||||
|
||||
root_node = self.create_root_node()
|
||||
organizations = self.filter_organizations(applications)
|
||||
|
||||
for i, org in enumerate(organizations):
|
||||
tree_id = urlencode({'org_id': str(org.id)})
|
||||
apps = applications.filter(org_id=org.id)
|
||||
|
||||
# 组织节点
|
||||
org_node = org.as_tree_node(oid=tree_id, pid=root_node.id)
|
||||
org_node.name += '({})'.format(apps.count())
|
||||
tree_nodes.append(org_node)
|
||||
|
||||
# 类别节点
|
||||
category_type_nodes = Application.create_category_type_tree_nodes(
|
||||
apps, tree_id, show_empty=False
|
||||
)
|
||||
tree_nodes += category_type_nodes
|
||||
|
||||
for app in apps:
|
||||
app_node = app.as_tree_node(tree_id, k8s_as_tree=True)
|
||||
tree_nodes.append(app_node)
|
||||
return tree_nodes
|
|
@ -1,19 +1,8 @@
|
|||
# coding:utf-8
|
||||
|
||||
from django.urls import re_path
|
||||
from common import api as capi
|
||||
from .asset_permission import asset_permission_urlpatterns
|
||||
from .application_permission import application_permission_urlpatterns
|
||||
from .system_user_permission import system_users_permission_urlpatterns
|
||||
|
||||
app_name = 'perms'
|
||||
|
||||
old_version_urlpatterns = [
|
||||
re_path('(?P<resource>user|user-group|asset-permission|remote-app-permission)/.*', capi.redirect_plural_name_api)
|
||||
]
|
||||
|
||||
urlpatterns = []
|
||||
urlpatterns += asset_permission_urlpatterns
|
||||
urlpatterns += application_permission_urlpatterns
|
||||
urlpatterns += system_users_permission_urlpatterns
|
||||
urlpatterns += old_version_urlpatterns
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.urls import path, include
|
||||
from rest_framework_bulk.routes import BulkRouter
|
||||
from .. import api
|
||||
|
||||
|
||||
router = BulkRouter()
|
||||
router.register('application-permissions', api.ApplicationPermissionViewSet, 'application-permission')
|
||||
router.register('application-permissions-users-relations', api.ApplicationPermissionUserRelationViewSet, 'application-permissions-users-relation')
|
||||
router.register('application-permissions-user-groups-relations', api.ApplicationPermissionUserGroupRelationViewSet, 'application-permissions-user-groups-relation')
|
||||
router.register('application-permissions-applications-relations', api.ApplicationPermissionApplicationRelationViewSet, 'application-permissions-application-relation')
|
||||
router.register('application-permissions-system-users-relations', api.ApplicationPermissionSystemUserRelationViewSet, 'application-permissions-system-users-relation')
|
||||
|
||||
user_permission_urlpatterns = [
|
||||
path('<uuid:pk>/applications/', api.UserAllGrantedApplicationsApi.as_view(), name='user-applications'),
|
||||
path('applications/', api.MyAllGrantedApplicationsApi.as_view(), name='my-applications'),
|
||||
|
||||
# Application As Tree
|
||||
path('<uuid:pk>/applications/tree/', api.UserAllGrantedApplicationsAsTreeApi.as_view(), name='user-applications-as-tree'),
|
||||
path('applications/tree/', api.MyAllGrantedApplicationsAsTreeApi.as_view(), name='my-applications-as-tree'),
|
||||
|
||||
# Application System Users
|
||||
path('<uuid:pk>/applications/<uuid:application_id>/system-users/', api.UserGrantedApplicationSystemUsersApi.as_view(), name='user-application-system-users'),
|
||||
path('applications/<uuid:application_id>/system-users/', api.MyGrantedApplicationSystemUsersApi.as_view(), name='my-application-system-users'),
|
||||
]
|
||||
|
||||
user_group_permission_urlpatterns = [
|
||||
path('<uuid:pk>/applications/', api.UserGroupGrantedApplicationsApi.as_view(), name='user-group-applications'),
|
||||
]
|
||||
|
||||
permission_urlpatterns = [
|
||||
# 授权规则中授权的用户和应用
|
||||
path('<uuid:pk>/applications/all/', api.ApplicationPermissionAllApplicationListApi.as_view(), name='application-permission-all-applications'),
|
||||
path('<uuid:pk>/users/all/', api.ApplicationPermissionAllUserListApi.as_view(), name='application-permission-all-users'),
|
||||
|
||||
# 验证用户是否有某个应用的权限
|
||||
path('user/validate/', api.ValidateUserApplicationPermissionApi.as_view(), name='validate-user-application-permission'),
|
||||
]
|
||||
|
||||
application_permission_urlpatterns = [
|
||||
path('users/', include(user_permission_urlpatterns)),
|
||||
path('user-groups/', include(user_group_permission_urlpatterns)),
|
||||
path('application-permissions/', include(permission_urlpatterns))
|
||||
]
|
||||
|
||||
application_permission_urlpatterns += router.urls
|
|
@ -1,6 +0,0 @@
|
|||
from django.urls import path
|
||||
from .. import api
|
||||
|
||||
system_users_permission_urlpatterns = [
|
||||
path('system-users-permission/', api.SystemUserPermission.as_view(), name='system-users-permission'),
|
||||
]
|
Loading…
Reference in New Issue