mirror of https://github.com/jumpserver/jumpserver
reactor&remove: 重构applications模块 & 移除applications、perms中已不再使用的模块 (#5374)
* reactor: 重构applications模块 & 删除applications、perms中已不再使用的模块 * reactor: 1. 针对application.attrs字段的view-serializer映射逻辑,采用DynamicMapping的方案重写; * reactor: 2. 删除applications和perms模块中已不再使用的database-app/k8s-app/remote-app模块; * reactor: 添加迁移文件(删除perms/databaseperrmission/remoteapppermission/k8sapppermission) * reactor: 修改细节 Co-authored-by: Bai <bugatti_it@163.com>pull/5377/head
parent
428e8bf2a0
commit
7e7e24f51f
|
@ -1,5 +1,3 @@
|
|||
from .application import *
|
||||
from .mixin import *
|
||||
from .remote_app import *
|
||||
from .database_app import *
|
||||
from .k8s_app import *
|
||||
|
|
|
@ -3,18 +3,18 @@
|
|||
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
|
||||
from .mixin import ApplicationAttrsSerializerViewMixin
|
||||
from ..hands import IsOrgAdminOrAppUser
|
||||
from .. import models, serializers
|
||||
|
||||
__all__ = [
|
||||
'ApplicationViewSet',
|
||||
]
|
||||
from .mixin import ApplicationViewMixin
|
||||
|
||||
|
||||
class ApplicationViewSet(ApplicationAttrsSerializerViewMixin, OrgBulkModelViewSet):
|
||||
__all__ = ['ApplicationViewSet']
|
||||
|
||||
|
||||
class ApplicationViewSet(ApplicationViewMixin, OrgBulkModelViewSet):
|
||||
model = models.Application
|
||||
filter_fields = ('name', 'type', 'category')
|
||||
search_fields = filter_fields
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = serializers.ApplicationSerializer
|
||||
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
|
||||
from .. import models
|
||||
from .. import serializers
|
||||
from ..hands import IsOrgAdminOrAppUser
|
||||
|
||||
__all__ = [
|
||||
'DatabaseAppViewSet',
|
||||
]
|
||||
|
||||
|
||||
class DatabaseAppViewSet(OrgBulkModelViewSet):
|
||||
model = models.DatabaseApp
|
||||
filter_fields = ('name',)
|
||||
search_fields = filter_fields
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = serializers.DatabaseAppSerializer
|
|
@ -1,20 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
|
||||
from .. import models
|
||||
from .. import serializers
|
||||
from ..hands import IsOrgAdminOrAppUser
|
||||
|
||||
__all__ = [
|
||||
'K8sAppViewSet',
|
||||
]
|
||||
|
||||
|
||||
class K8sAppViewSet(OrgBulkModelViewSet):
|
||||
model = models.K8sApp
|
||||
filter_fields = ('name',)
|
||||
search_fields = filter_fields
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = serializers.K8sAppSerializer
|
|
@ -1,57 +1,16 @@
|
|||
import uuid
|
||||
|
||||
from common.exceptions import JMSException
|
||||
from orgs.models import Organization
|
||||
from .. import models
|
||||
from ..serializers.utils import get_dynamic_mapping_fields_mapping_rule_by_view
|
||||
|
||||
|
||||
class ApplicationAttrsSerializerViewMixin:
|
||||
__all__ = ['ApplicationViewMixin', 'SerializeApplicationToTreeNodeMixin']
|
||||
|
||||
def get_serializer_class(self):
|
||||
serializer_class = super().get_serializer_class()
|
||||
if getattr(self, 'swagger_fake_view', False):
|
||||
return serializer_class
|
||||
app_type = self.request.query_params.get('type')
|
||||
app_category = self.request.query_params.get('category')
|
||||
type_options = list(dict(models.Category.get_all_type_serializer_mapper()).keys())
|
||||
category_options = list(dict(models.Category.get_category_serializer_mapper()).keys())
|
||||
|
||||
# ListAPIView 没有 action 属性
|
||||
# 不使用method属性,因为options请求时为method为post
|
||||
action = getattr(self, 'action', 'list')
|
||||
class ApplicationViewMixin:
|
||||
""" 实现 `get_dynamic_mapping_fields_mapping_rule` 方法, 供其他和 Application 相关的 View 继承使用"""
|
||||
|
||||
if app_type and app_type not in type_options:
|
||||
raise JMSException(
|
||||
'Invalid query parameter `type`, select from the following options: {}'
|
||||
''.format(type_options)
|
||||
)
|
||||
if app_category and app_category not in category_options:
|
||||
raise JMSException(
|
||||
'Invalid query parameter `category`, select from the following options: {}'
|
||||
''.format(category_options)
|
||||
)
|
||||
|
||||
if action in [
|
||||
'create', 'update', 'partial_update', 'bulk_update', 'partial_bulk_update'
|
||||
] and not app_type:
|
||||
# action: create / update
|
||||
raise JMSException(
|
||||
'The `{}` action must take the `type` query parameter'.format(action)
|
||||
)
|
||||
|
||||
if app_type:
|
||||
# action: create / update / list / retrieve / metadata
|
||||
attrs_cls = models.Category.get_type_serializer_cls(app_type)
|
||||
class_name = 'ApplicationDynamicSerializer{}'.format(app_type.title())
|
||||
elif app_category:
|
||||
# action: list / retrieve / metadata
|
||||
attrs_cls = models.Category.get_category_serializer_cls(app_category)
|
||||
class_name = 'ApplicationDynamicSerializer{}'.format(app_category.title())
|
||||
else:
|
||||
attrs_cls = models.Category.get_no_password_serializer_cls()
|
||||
class_name = 'ApplicationDynamicSerializer'
|
||||
cls = type(class_name, (serializer_class,), {'attrs': attrs_cls()})
|
||||
return cls
|
||||
def get_dynamic_mapping_fields_mapping_rule(self):
|
||||
fields_mapping_rule = get_dynamic_mapping_fields_mapping_rule_by_view(view=self)
|
||||
return fields_mapping_rule
|
||||
|
||||
|
||||
class SerializeApplicationToTreeNodeMixin:
|
||||
|
|
|
@ -1,40 +1,19 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
from orgs.mixins import generics
|
||||
from common.exceptions import JMSException
|
||||
from ..hands import IsOrgAdmin, IsAppUser
|
||||
from ..hands import IsAppUser
|
||||
from .. import models
|
||||
from ..serializers import RemoteAppSerializer, RemoteAppConnectionInfoSerializer
|
||||
from ..serializers import RemoteAppConnectionInfoSerializer
|
||||
from ..permissions import IsRemoteApp
|
||||
|
||||
|
||||
__all__ = [
|
||||
'RemoteAppViewSet', 'RemoteAppConnectionInfoApi',
|
||||
'RemoteAppConnectionInfoApi',
|
||||
]
|
||||
|
||||
|
||||
class RemoteAppViewSet(OrgBulkModelViewSet):
|
||||
model = models.RemoteApp
|
||||
filter_fields = ('name', 'type', 'comment')
|
||||
search_fields = filter_fields
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = RemoteAppSerializer
|
||||
|
||||
|
||||
class RemoteAppConnectionInfoApi(generics.RetrieveAPIView):
|
||||
model = models.Application
|
||||
permission_classes = (IsAppUser, )
|
||||
permission_classes = (IsAppUser, IsRemoteApp)
|
||||
serializer_class = RemoteAppConnectionInfoSerializer
|
||||
|
||||
@staticmethod
|
||||
def check_category_allowed(obj):
|
||||
if not obj.category_is_remote_app:
|
||||
raise JMSException(
|
||||
'The request instance(`{}`) is not of category `remote_app`'.format(obj.category)
|
||||
)
|
||||
|
||||
def get_object(self):
|
||||
obj = super().get_object()
|
||||
self.check_category_allowed(obj)
|
||||
return obj
|
||||
|
|
|
@ -1,64 +1,49 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.db.models import TextChoices
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
|
||||
# RemoteApp
|
||||
class ApplicationCategoryChoices(TextChoices):
|
||||
db = 'db', _('Database')
|
||||
remote_app = 'remote_app', _('Remote app')
|
||||
cloud = 'cloud', 'Cloud'
|
||||
|
||||
REMOTE_APP_BOOT_PROGRAM_NAME = '||jmservisor'
|
||||
|
||||
REMOTE_APP_TYPE_CHROME = 'chrome'
|
||||
REMOTE_APP_TYPE_MYSQL_WORKBENCH = 'mysql_workbench'
|
||||
REMOTE_APP_TYPE_VMWARE_CLIENT = 'vmware_client'
|
||||
REMOTE_APP_TYPE_CUSTOM = 'custom'
|
||||
|
||||
# Fields attribute write_only default => False
|
||||
|
||||
REMOTE_APP_TYPE_CHROME_FIELDS = [
|
||||
{'name': 'chrome_target'},
|
||||
{'name': 'chrome_username'},
|
||||
{'name': 'chrome_password', 'write_only': True}
|
||||
]
|
||||
REMOTE_APP_TYPE_MYSQL_WORKBENCH_FIELDS = [
|
||||
{'name': 'mysql_workbench_ip'},
|
||||
{'name': 'mysql_workbench_name'},
|
||||
{'name': 'mysql_workbench_port'},
|
||||
{'name': 'mysql_workbench_username'},
|
||||
{'name': 'mysql_workbench_password', 'write_only': True}
|
||||
]
|
||||
REMOTE_APP_TYPE_VMWARE_CLIENT_FIELDS = [
|
||||
{'name': 'vmware_target'},
|
||||
{'name': 'vmware_username'},
|
||||
{'name': 'vmware_password', 'write_only': True}
|
||||
]
|
||||
REMOTE_APP_TYPE_CUSTOM_FIELDS = [
|
||||
{'name': 'custom_cmdline'},
|
||||
{'name': 'custom_target'},
|
||||
{'name': 'custom_username'},
|
||||
{'name': 'custom_password', 'write_only': True}
|
||||
]
|
||||
|
||||
REMOTE_APP_TYPE_FIELDS_MAP = {
|
||||
REMOTE_APP_TYPE_CHROME: REMOTE_APP_TYPE_CHROME_FIELDS,
|
||||
REMOTE_APP_TYPE_MYSQL_WORKBENCH: REMOTE_APP_TYPE_MYSQL_WORKBENCH_FIELDS,
|
||||
REMOTE_APP_TYPE_VMWARE_CLIENT: REMOTE_APP_TYPE_VMWARE_CLIENT_FIELDS,
|
||||
REMOTE_APP_TYPE_CUSTOM: REMOTE_APP_TYPE_CUSTOM_FIELDS
|
||||
}
|
||||
|
||||
REMOTE_APP_TYPE_CHOICES = (
|
||||
(REMOTE_APP_TYPE_CHROME, 'Chrome'),
|
||||
(REMOTE_APP_TYPE_MYSQL_WORKBENCH, 'MySQL Workbench'),
|
||||
(REMOTE_APP_TYPE_VMWARE_CLIENT, 'vSphere Client'),
|
||||
(REMOTE_APP_TYPE_CUSTOM, _('Custom')),
|
||||
)
|
||||
@classmethod
|
||||
def get_label(cls, category):
|
||||
return dict(cls.choices).get(category, '')
|
||||
|
||||
|
||||
# DatabaseApp
|
||||
class ApplicationTypeChoices(TextChoices):
|
||||
# db category
|
||||
mysql = 'mysql', 'MySQL'
|
||||
oracle = 'oracle', 'Oracle'
|
||||
pgsql = 'postgresql', 'PostgreSQL'
|
||||
mariadb = 'mariadb', 'MariaDB'
|
||||
|
||||
# remote-app category
|
||||
chrome = 'chrome', 'Chrome'
|
||||
mysql_workbench = 'mysql_workbench', 'MySQL Workbench'
|
||||
vmware_client = 'vmware_client', 'vSphere Client'
|
||||
custom = 'custom', _('Custom')
|
||||
|
||||
DATABASE_APP_TYPE_MYSQL = 'mysql'
|
||||
# cloud category
|
||||
k8s = 'k8s', 'Kubernetes'
|
||||
|
||||
@classmethod
|
||||
def get_label(cls, tp):
|
||||
return dict(cls.choices).get(tp, '')
|
||||
|
||||
@classmethod
|
||||
def db_types(cls):
|
||||
return [cls.mysql.value, cls.oracle.value, cls.pgsql.value, cls.mariadb.value]
|
||||
|
||||
@classmethod
|
||||
def remote_app_types(cls):
|
||||
return [cls.chrome.value, cls.mysql_workbench.value, cls.vmware_client.value, cls.custom.value]
|
||||
|
||||
@classmethod
|
||||
def cloud_types(cls):
|
||||
return [cls.k8s.value]
|
||||
|
||||
DATABASE_APP_TYPE_CHOICES = (
|
||||
(DATABASE_APP_TYPE_MYSQL, 'MySQL'),
|
||||
)
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# Generated by Django 3.1 on 2021-01-03 20:35
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('perms', '0017_auto_20210104_0435'),
|
||||
('applications', '0007_auto_20201119_1110'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.DeleteModel(
|
||||
name='DatabaseApp',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='K8sApp',
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='application',
|
||||
name='attrs',
|
||||
field=models.JSONField(default=dict, verbose_name='Attrs'),
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='RemoteApp',
|
||||
),
|
||||
]
|
|
@ -1,4 +1 @@
|
|||
from .application import *
|
||||
from .remote_app import *
|
||||
from .database_app import *
|
||||
from .k8s_app import *
|
||||
|
|
|
@ -1,128 +1,24 @@
|
|||
from itertools import chain
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orgs.mixins.models import OrgModelMixin
|
||||
from common.mixins import CommonModelMixin
|
||||
from common.db.models import ChoiceSet
|
||||
|
||||
|
||||
class DBType(ChoiceSet):
|
||||
mysql = 'mysql', 'MySQL'
|
||||
oracle = 'oracle', 'Oracle'
|
||||
pgsql = 'postgresql', 'PostgreSQL'
|
||||
mariadb = 'mariadb', 'MariaDB'
|
||||
|
||||
@classmethod
|
||||
def get_type_serializer_cls_mapper(cls):
|
||||
from ..serializers import database_app
|
||||
mapper = {
|
||||
cls.mysql: database_app.MySQLAttrsSerializer,
|
||||
cls.oracle: database_app.OracleAttrsSerializer,
|
||||
cls.pgsql: database_app.PostgreAttrsSerializer,
|
||||
cls.mariadb: database_app.MariaDBAttrsSerializer,
|
||||
}
|
||||
return mapper
|
||||
|
||||
|
||||
class RemoteAppType(ChoiceSet):
|
||||
chrome = 'chrome', 'Chrome'
|
||||
mysql_workbench = 'mysql_workbench', 'MySQL Workbench'
|
||||
vmware_client = 'vmware_client', 'vSphere Client'
|
||||
custom = 'custom', _('Custom')
|
||||
|
||||
@classmethod
|
||||
def get_type_serializer_cls_mapper(cls):
|
||||
from ..serializers import remote_app
|
||||
mapper = {
|
||||
cls.chrome: remote_app.ChromeAttrsSerializer,
|
||||
cls.mysql_workbench: remote_app.MySQLWorkbenchAttrsSerializer,
|
||||
cls.vmware_client: remote_app.VMwareClientAttrsSerializer,
|
||||
cls.custom: remote_app.CustomRemoteAppAttrsSeralizers,
|
||||
}
|
||||
return mapper
|
||||
|
||||
|
||||
class CloudType(ChoiceSet):
|
||||
k8s = 'k8s', 'Kubernetes'
|
||||
|
||||
@classmethod
|
||||
def get_type_serializer_cls_mapper(cls):
|
||||
from ..serializers import k8s_app
|
||||
mapper = {
|
||||
cls.k8s: k8s_app.K8sAttrsSerializer,
|
||||
}
|
||||
return mapper
|
||||
|
||||
|
||||
class Category(ChoiceSet):
|
||||
db = 'db', _('Database')
|
||||
remote_app = 'remote_app', _('Remote app')
|
||||
cloud = 'cloud', 'Cloud'
|
||||
|
||||
@classmethod
|
||||
def get_category_type_mapper(cls):
|
||||
return {
|
||||
cls.db: DBType,
|
||||
cls.remote_app: RemoteAppType,
|
||||
cls.cloud: CloudType
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def get_category_type_choices_mapper(cls):
|
||||
return {
|
||||
name: tp.choices
|
||||
for name, tp in cls.get_category_type_mapper().items()
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def get_type_choices(cls, category):
|
||||
return cls.get_category_type_choices_mapper().get(category, [])
|
||||
|
||||
@classmethod
|
||||
def get_all_type_choices(cls):
|
||||
all_grouped_choices = tuple(cls.get_category_type_choices_mapper().values())
|
||||
return tuple(chain(*all_grouped_choices))
|
||||
|
||||
@classmethod
|
||||
def get_all_type_serializer_mapper(cls):
|
||||
mapper = {}
|
||||
for tp in cls.get_category_type_mapper().values():
|
||||
mapper.update(tp.get_type_serializer_cls_mapper())
|
||||
return mapper
|
||||
|
||||
@classmethod
|
||||
def get_type_serializer_cls(cls, tp):
|
||||
mapper = cls.get_all_type_serializer_mapper()
|
||||
return mapper.get(tp, None)
|
||||
|
||||
@classmethod
|
||||
def get_category_serializer_mapper(cls):
|
||||
from ..serializers import remote_app, database_app, k8s_app
|
||||
return {
|
||||
cls.db: database_app.DBAttrsSerializer,
|
||||
cls.remote_app: remote_app.RemoteAppAttrsSerializer,
|
||||
cls.cloud: k8s_app.CloudAttrsSerializer,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def get_category_serializer_cls(cls, cg):
|
||||
mapper = cls.get_category_serializer_mapper()
|
||||
return mapper.get(cg, None)
|
||||
|
||||
@classmethod
|
||||
def get_no_password_serializer_cls(cls):
|
||||
from ..serializers import common
|
||||
return common.NoPasswordSerializer
|
||||
from .. import const
|
||||
|
||||
|
||||
class Application(CommonModelMixin, OrgModelMixin):
|
||||
name = models.CharField(max_length=128, verbose_name=_('Name'))
|
||||
domain = models.ForeignKey('assets.Domain', null=True, blank=True, related_name='applications', verbose_name=_("Domain"), on_delete=models.SET_NULL)
|
||||
category = models.CharField(max_length=16, choices=Category.choices, verbose_name=_('Category'))
|
||||
type = models.CharField(max_length=16, choices=Category.get_all_type_choices(), verbose_name=_('Type'))
|
||||
attrs = models.JSONField()
|
||||
category = models.CharField(
|
||||
max_length=16, choices=const.ApplicationCategoryChoices.choices, verbose_name=_('Category')
|
||||
)
|
||||
type = models.CharField(
|
||||
max_length=16, choices=const.ApplicationTypeChoices.choices, verbose_name=_('Type')
|
||||
)
|
||||
domain = models.ForeignKey(
|
||||
'assets.Domain', null=True, blank=True, related_name='applications',
|
||||
on_delete=models.SET_NULL, verbose_name=_("Domain"),
|
||||
)
|
||||
attrs = models.JSONField(default=dict, verbose_name=_('Attrs'))
|
||||
comment = models.TextField(
|
||||
max_length=128, default='', blank=True, verbose_name=_('Comment')
|
||||
)
|
||||
|
@ -136,5 +32,6 @@ class Application(CommonModelMixin, OrgModelMixin):
|
|||
type_display = self.get_type_display()
|
||||
return f'{self.name}({type_display})[{category_display}]'
|
||||
|
||||
def category_is_remote_app(self):
|
||||
return self.category == Category.remote_app
|
||||
@property
|
||||
def category_remote_app(self):
|
||||
return self.category == const.ApplicationCategoryChoices.remote_app.value
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
import uuid
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orgs.mixins.models import OrgModelMixin
|
||||
from common.mixins import CommonModelMixin
|
||||
from .. import const
|
||||
|
||||
|
||||
__all__ = ['DatabaseApp']
|
||||
|
||||
|
||||
class DatabaseApp(CommonModelMixin, OrgModelMixin):
|
||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
name = models.CharField(max_length=128, verbose_name=_('Name'))
|
||||
type = models.CharField(
|
||||
default=const.DATABASE_APP_TYPE_MYSQL,
|
||||
choices=const.DATABASE_APP_TYPE_CHOICES,
|
||||
max_length=128, verbose_name=_('Type')
|
||||
)
|
||||
host = models.CharField(
|
||||
max_length=128, verbose_name=_('Host'), db_index=True
|
||||
)
|
||||
port = models.IntegerField(default=3306, verbose_name=_('Port'))
|
||||
database = models.CharField(
|
||||
max_length=128, blank=True, null=True, verbose_name=_('Database'),
|
||||
db_index=True
|
||||
)
|
||||
comment = models.TextField(
|
||||
max_length=128, default='', blank=True, verbose_name=_('Comment')
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
unique_together = [('org_id', 'name'), ]
|
||||
verbose_name = _("DatabaseApp")
|
||||
ordering = ('name', )
|
|
@ -1,27 +0,0 @@
|
|||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from common.db import models
|
||||
from orgs.mixins.models import OrgModelMixin
|
||||
|
||||
|
||||
class K8sApp(OrgModelMixin, models.JMSModel):
|
||||
class TYPE(models.ChoiceSet):
|
||||
K8S = 'k8s', _('Kubernetes')
|
||||
|
||||
name = models.CharField(max_length=128, verbose_name=_('Name'))
|
||||
type = models.CharField(
|
||||
default=TYPE.K8S, choices=TYPE.choices,
|
||||
max_length=128, verbose_name=_('Type')
|
||||
)
|
||||
cluster = models.CharField(max_length=1024, verbose_name=_('Cluster'))
|
||||
comment = models.TextField(
|
||||
max_length=128, default='', blank=True, verbose_name=_('Comment')
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
class Meta:
|
||||
unique_together = [('org_id', 'name'), ]
|
||||
verbose_name = _('KubernetesApp')
|
||||
ordering = ('name', )
|
|
@ -1,78 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
import uuid
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orgs.mixins.models import OrgModelMixin
|
||||
from common.fields.model import EncryptJsonDictTextField
|
||||
|
||||
from .. import const
|
||||
|
||||
|
||||
__all__ = [
|
||||
'RemoteApp',
|
||||
]
|
||||
|
||||
|
||||
class RemoteApp(OrgModelMixin):
|
||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||
name = models.CharField(max_length=128, verbose_name=_('Name'))
|
||||
asset = models.ForeignKey(
|
||||
'assets.Asset', on_delete=models.CASCADE, verbose_name=_('Asset')
|
||||
)
|
||||
type = models.CharField(
|
||||
default=const.REMOTE_APP_TYPE_CHROME,
|
||||
choices=const.REMOTE_APP_TYPE_CHOICES,
|
||||
max_length=128, verbose_name=_('App type')
|
||||
)
|
||||
path = models.CharField(
|
||||
max_length=128, blank=False, null=False,
|
||||
verbose_name=_('App path')
|
||||
)
|
||||
params = EncryptJsonDictTextField(
|
||||
max_length=4096, default={}, blank=True, null=True,
|
||||
verbose_name=_('Parameters')
|
||||
)
|
||||
created_by = models.CharField(
|
||||
max_length=32, null=True, blank=True, verbose_name=_('Created by')
|
||||
)
|
||||
date_created = models.DateTimeField(
|
||||
auto_now_add=True, null=True, blank=True, verbose_name=_('Date created')
|
||||
)
|
||||
comment = models.TextField(
|
||||
max_length=128, default='', blank=True, verbose_name=_('Comment')
|
||||
)
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("RemoteApp")
|
||||
unique_together = [('org_id', 'name')]
|
||||
ordering = ('name', )
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def parameters(self):
|
||||
"""
|
||||
返回Guacamole需要的RemoteApp配置参数信息中的parameters参数
|
||||
"""
|
||||
_parameters = list()
|
||||
_parameters.append(self.type)
|
||||
path = '\"%s\"' % self.path
|
||||
_parameters.append(path)
|
||||
for field in const.REMOTE_APP_TYPE_FIELDS_MAP[self.type]:
|
||||
value = self.params.get(field['name'])
|
||||
if value is None:
|
||||
continue
|
||||
_parameters.append(value)
|
||||
_parameters = ' '.join(_parameters)
|
||||
return _parameters
|
||||
|
||||
@property
|
||||
def asset_info(self):
|
||||
return {
|
||||
'id': self.asset.id,
|
||||
'hostname': self.asset.hostname
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
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,5 +1,2 @@
|
|||
from .application import *
|
||||
from .remote_app import *
|
||||
from .database_app import *
|
||||
from .k8s_app import *
|
||||
from .common import *
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
from common.drf.fields import DynamicMappingField
|
||||
from .attrs import get_attrs_field_dynamic_mapping_rules
|
||||
|
||||
from .. import models
|
||||
|
||||
|
@ -15,6 +17,7 @@ __all__ = [
|
|||
class ApplicationSerializer(BulkOrgResourceModelSerializer):
|
||||
category_display = serializers.ReadOnlyField(source='get_category_display', label=_('Category'))
|
||||
type_display = serializers.ReadOnlyField(source='get_type_display', label=_('Type'))
|
||||
attrs = DynamicMappingField(mapping_rules=get_attrs_field_dynamic_mapping_rules())
|
||||
|
||||
class Meta:
|
||||
model = models.Application
|
||||
|
@ -26,17 +29,7 @@ class ApplicationSerializer(BulkOrgResourceModelSerializer):
|
|||
'created_by', 'date_created', 'date_updated', 'get_type_display',
|
||||
]
|
||||
|
||||
def create(self, validated_data):
|
||||
validated_data['attrs'] = validated_data.pop('attrs', {})
|
||||
instance = super().create(validated_data)
|
||||
return instance
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
new_attrs = validated_data.pop('attrs', {})
|
||||
instance = super().update(instance, validated_data)
|
||||
attrs = instance.attrs
|
||||
attrs.update(new_attrs)
|
||||
instance.attrs = attrs
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
def validate_attrs(self, attrs):
|
||||
_attrs = self.instance.attrs if self.instance else {}
|
||||
_attrs.update(attrs)
|
||||
return _attrs
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
from .attrs import *
|
|
@ -0,0 +1,94 @@
|
|||
import copy
|
||||
from applications import const
|
||||
from common.drf.fields import IgnoreSensitiveInfoReadOnlyJSONField
|
||||
from . import category, type as application_type
|
||||
|
||||
|
||||
__all__ = [
|
||||
'get_attrs_field_dynamic_mapping_rules', 'get_attrs_field_mapping_rule_by_view',
|
||||
'get_serializer_by_application_type',
|
||||
]
|
||||
|
||||
|
||||
# application category
|
||||
# --------------------
|
||||
|
||||
category_db = const.ApplicationCategoryChoices.db.value
|
||||
category_remote_app = const.ApplicationCategoryChoices.remote_app.value
|
||||
category_cloud = const.ApplicationCategoryChoices.cloud.value
|
||||
|
||||
|
||||
# application type
|
||||
# ----------------
|
||||
|
||||
# db
|
||||
type_mysql = const.ApplicationTypeChoices.mysql.value
|
||||
type_mariadb = const.ApplicationTypeChoices.mariadb.value
|
||||
type_oracle = const.ApplicationTypeChoices.oracle.value
|
||||
type_pgsql = const.ApplicationTypeChoices.pgsql.value
|
||||
# remote-app
|
||||
type_chrome = const.ApplicationTypeChoices.chrome.value
|
||||
type_mysql_workbench = const.ApplicationTypeChoices.mysql_workbench.value
|
||||
type_vmware_client = const.ApplicationTypeChoices.vmware_client.value
|
||||
type_custom = const.ApplicationTypeChoices.custom.value
|
||||
# cloud
|
||||
type_k8s = const.ApplicationTypeChoices.k8s.value
|
||||
|
||||
|
||||
# define `attrs` field `DynamicMappingField` mapping_rules
|
||||
# -----------------------------------------------------
|
||||
|
||||
|
||||
__ATTRS_FIELD_DYNAMIC_MAPPING_RULES = {
|
||||
'default': IgnoreSensitiveInfoReadOnlyJSONField,
|
||||
'category': {
|
||||
category_db: category.DBSerializer,
|
||||
category_remote_app: category.RemoteAppSerializer,
|
||||
category_cloud: category.CloudSerializer,
|
||||
},
|
||||
'type': {
|
||||
# db
|
||||
type_mysql: application_type.MySQLSerializer,
|
||||
type_mariadb: application_type.MariaDBSerializer,
|
||||
type_oracle: application_type.OracleSerializer,
|
||||
type_pgsql: application_type.PostgreSerializer,
|
||||
# remote-app
|
||||
type_chrome: application_type.ChromeSerializer,
|
||||
type_mysql_workbench: application_type.MySQLWorkbenchSerializer,
|
||||
type_vmware_client: application_type.VMwareClientSerializer,
|
||||
type_custom: application_type.CustomSerializer,
|
||||
# cloud
|
||||
type_k8s: application_type.K8SSerializer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Note:
|
||||
# The dynamic mapping rules of `attrs` field is obtained
|
||||
# through call method `get_attrs_field_dynamic_mapping_rules`
|
||||
|
||||
def get_attrs_field_dynamic_mapping_rules():
|
||||
return copy.deepcopy(__ATTRS_FIELD_DYNAMIC_MAPPING_RULES)
|
||||
|
||||
|
||||
# get `attrs dynamic field` mapping rule by `view object`
|
||||
# ----------------------------------------------------
|
||||
|
||||
|
||||
def get_attrs_field_mapping_rule_by_view(view):
|
||||
query_type = view.request.query_params.get('type')
|
||||
query_category = view.request.query_params.get('category')
|
||||
if query_type:
|
||||
mapping_rule = ['type', query_type]
|
||||
elif query_category:
|
||||
mapping_rule = ['category', query_category]
|
||||
else:
|
||||
mapping_rule = ['default']
|
||||
return mapping_rule
|
||||
|
||||
|
||||
# get `category` mapping `serializer`
|
||||
# -----------------------------------
|
||||
|
||||
def get_serializer_by_application_type(app_tp):
|
||||
return __ATTRS_FIELD_DYNAMIC_MAPPING_RULES['type'].get(app_tp)
|
|
@ -0,0 +1,3 @@
|
|||
from .remote_app import *
|
||||
from .db import *
|
||||
from .cloud import *
|
|
@ -0,0 +1,9 @@
|
|||
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'))
|
|
@ -0,0 +1,16 @@
|
|||
# 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'))
|
||||
port = serializers.IntegerField(label=_('Port'))
|
||||
# 添加allow_null=True,兼容之前数据库中database字段为None的情况
|
||||
database = serializers.CharField(
|
||||
max_length=128, required=True, allow_null=True, label=_('Database')
|
||||
)
|
|
@ -0,0 +1,48 @@
|
|||
# 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
|
||||
from assets.models import Asset
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
__all__ = ['RemoteAppSerializer']
|
||||
|
||||
|
||||
class CharPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
|
||||
|
||||
def to_internal_value(self, data):
|
||||
instance = super().to_internal_value(data)
|
||||
return str(instance.id)
|
||||
|
||||
def to_representation(self, value):
|
||||
# value is instance.id
|
||||
if self.pk_field is not None:
|
||||
return self.pk_field.to_representation(value)
|
||||
return value
|
||||
|
||||
|
||||
class RemoteAppSerializer(serializers.Serializer):
|
||||
asset_info = serializers.SerializerMethodField()
|
||||
asset = CharPrimaryKeyRelatedField(queryset=Asset.objects, required=False, label=_("Asset"))
|
||||
path = serializers.CharField(max_length=128, label=_('Application path'))
|
||||
|
||||
@staticmethod
|
||||
def get_asset_info(obj):
|
||||
asset_id = obj.get('asset')
|
||||
if not asset_id or is_uuid(asset_id):
|
||||
return {}
|
||||
try:
|
||||
asset = Asset.objects.filter(id=str(asset_id)).values_list('id', 'hostname')
|
||||
except ObjectDoesNotExist as e:
|
||||
logger.error(e)
|
||||
return {}
|
||||
if not asset:
|
||||
return {}
|
||||
asset_info = {'id': str(asset[0]), 'hostname': asset[1]}
|
||||
return asset_info
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
from .mysql import *
|
||||
from .mariadb import *
|
||||
from .oracle import *
|
||||
from .pgsql import *
|
||||
|
||||
from .chrome import *
|
||||
from .mysql_workbench import *
|
||||
from .vmware_client import *
|
||||
from .custom import *
|
||||
|
||||
from .k8s import *
|
|
@ -0,0 +1,25 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from ..category import RemoteAppSerializer
|
||||
|
||||
|
||||
__all__ = ['ChromeSerializer']
|
||||
|
||||
|
||||
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
|
||||
)
|
||||
chrome_target = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Target URL')
|
||||
)
|
||||
chrome_username = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Username')
|
||||
)
|
||||
chrome_password = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, write_only=True, label=_('Password')
|
||||
)
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from ..category import RemoteAppSerializer
|
||||
|
||||
|
||||
__all__ = ['CustomSerializer']
|
||||
|
||||
|
||||
class CustomSerializer(RemoteAppSerializer):
|
||||
custom_cmdline = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Operating parameter')
|
||||
)
|
||||
custom_target = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Target url')
|
||||
)
|
||||
custom_username = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Username')
|
||||
)
|
||||
custom_password = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, write_only=True, label=_('Password')
|
||||
)
|
|
@ -0,0 +1,8 @@
|
|||
from ..category import CloudSerializer
|
||||
|
||||
|
||||
__all__ = ['K8SSerializer']
|
||||
|
||||
|
||||
class K8SSerializer(CloudSerializer):
|
||||
pass
|
|
@ -0,0 +1,8 @@
|
|||
from .mysql import MySQLSerializer
|
||||
|
||||
|
||||
__all__ = ['MariaDBSerializer']
|
||||
|
||||
|
||||
class MariaDBSerializer(MySQLSerializer):
|
||||
pass
|
|
@ -0,0 +1,15 @@
|
|||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from ..category import DBSerializer
|
||||
|
||||
|
||||
__all__ = ['MySQLSerializer']
|
||||
|
||||
|
||||
class MySQLSerializer(DBSerializer):
|
||||
port = serializers.IntegerField(default=3306, label=_('Port'))
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from ..category import RemoteAppSerializer
|
||||
|
||||
|
||||
__all__ = ['MySQLWorkbenchSerializer']
|
||||
|
||||
|
||||
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
|
||||
)
|
||||
mysql_workbench_ip = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('IP')
|
||||
)
|
||||
mysql_workbench_port = serializers.IntegerField(
|
||||
required=False, label=_('Port')
|
||||
)
|
||||
mysql_workbench_name = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Database')
|
||||
)
|
||||
mysql_workbench_username = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Username')
|
||||
)
|
||||
mysql_workbench_password = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, write_only=True, label=_('Password')
|
||||
)
|
|
@ -0,0 +1,12 @@
|
|||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from ..category import DBSerializer
|
||||
|
||||
|
||||
__all__ = ['OracleSerializer']
|
||||
|
||||
|
||||
class OracleSerializer(DBSerializer):
|
||||
port = serializers.IntegerField(default=1521, label=_('Port'))
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from ..category import DBSerializer
|
||||
|
||||
|
||||
__all__ = ['PostgreSerializer']
|
||||
|
||||
|
||||
class PostgreSerializer(DBSerializer):
|
||||
port = serializers.IntegerField(default=5432, label=_('Port'))
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from ..category import RemoteAppSerializer
|
||||
|
||||
|
||||
__all__ = ['VMwareClientSerializer']
|
||||
|
||||
|
||||
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
|
||||
)
|
||||
vmware_target = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Target URL')
|
||||
)
|
||||
vmware_username = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Username')
|
||||
)
|
||||
vmware_password = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, write_only=True, label=_('Password')
|
||||
)
|
|
@ -1,11 +0,0 @@
|
|||
from rest_framework import serializers
|
||||
|
||||
|
||||
class NoPasswordSerializer(serializers.JSONField):
|
||||
def to_representation(self, value):
|
||||
new_value = {}
|
||||
for k, v in value.items():
|
||||
if 'password' not in k:
|
||||
new_value[k] = v
|
||||
return new_value
|
||||
|
|
@ -1,50 +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 common.drf.serializers import AdaptedBulkListSerializer
|
||||
|
||||
from .. import models
|
||||
|
||||
|
||||
class DBAttrsSerializer(serializers.Serializer):
|
||||
host = serializers.CharField(max_length=128, label=_('Host'))
|
||||
port = serializers.IntegerField(label=_('Port'))
|
||||
# 添加allow_null=True,兼容之前数据库中database字段为None的情况
|
||||
database = serializers.CharField(max_length=128, required=True, allow_null=True, label=_('Database'))
|
||||
|
||||
|
||||
class MySQLAttrsSerializer(DBAttrsSerializer):
|
||||
port = serializers.IntegerField(default=3306, label=_('Port'))
|
||||
|
||||
|
||||
class PostgreAttrsSerializer(DBAttrsSerializer):
|
||||
port = serializers.IntegerField(default=5432, label=_('Port'))
|
||||
|
||||
|
||||
class OracleAttrsSerializer(DBAttrsSerializer):
|
||||
port = serializers.IntegerField(default=1521, label=_('Port'))
|
||||
|
||||
|
||||
class MariaDBAttrsSerializer(MySQLAttrsSerializer):
|
||||
pass
|
||||
|
||||
|
||||
class DatabaseAppSerializer(BulkOrgResourceModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = models.DatabaseApp
|
||||
list_serializer_class = AdaptedBulkListSerializer
|
||||
fields = [
|
||||
'id', 'name', 'type', 'get_type_display', 'host', 'port',
|
||||
'database', 'comment', 'created_by', 'date_created', 'date_updated',
|
||||
]
|
||||
read_only_fields = [
|
||||
'created_by', 'date_created', 'date_updated'
|
||||
'get_type_display',
|
||||
]
|
||||
extra_kwargs = {
|
||||
'get_type_display': {'label': _('Type for display')},
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
from .. import models
|
||||
|
||||
|
||||
class CloudAttrsSerializer(serializers.Serializer):
|
||||
cluster = serializers.CharField(max_length=1024, label=_('Cluster'))
|
||||
|
||||
|
||||
class K8sAttrsSerializer(CloudAttrsSerializer):
|
||||
pass
|
||||
|
||||
|
||||
class K8sAppSerializer(BulkOrgResourceModelSerializer):
|
||||
type_display = serializers.CharField(source='get_type_display', read_only=True, label=_('Type for display'))
|
||||
|
||||
class Meta:
|
||||
model = models.K8sApp
|
||||
fields = [
|
||||
'id', 'name', 'type', 'type_display', 'comment', 'created_by',
|
||||
'date_created', 'date_updated', 'cluster'
|
||||
]
|
||||
read_only_fields = [
|
||||
'id', 'created_by', 'date_created', 'date_updated',
|
||||
]
|
|
@ -1,89 +1,14 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
import copy
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.drf.serializers import AdaptedBulkListSerializer
|
||||
from common.drf.fields import CustomMetaDictField
|
||||
from common.utils import get_logger
|
||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
from assets.models import Asset
|
||||
from ..models import Application
|
||||
|
||||
from .. import const
|
||||
from ..models import RemoteApp, Category, Application
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
class CharPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
|
||||
|
||||
def to_internal_value(self, data):
|
||||
instance = super().to_internal_value(data)
|
||||
return str(instance.id)
|
||||
|
||||
def to_representation(self, value):
|
||||
# value is instance.id
|
||||
if self.pk_field is not None:
|
||||
return self.pk_field.to_representation(value)
|
||||
return value
|
||||
|
||||
|
||||
class RemoteAppAttrsSerializer(serializers.Serializer):
|
||||
asset_info = serializers.SerializerMethodField()
|
||||
asset = CharPrimaryKeyRelatedField(queryset=Asset.objects, required=False, label=_("Asset"))
|
||||
path = serializers.CharField(max_length=128, label=_('Application path'))
|
||||
|
||||
@staticmethod
|
||||
def get_asset_info(obj):
|
||||
asset_info = {}
|
||||
asset_id = obj.get('asset')
|
||||
if not asset_id:
|
||||
return asset_info
|
||||
try:
|
||||
asset = Asset.objects.get(id=asset_id)
|
||||
asset_info.update({
|
||||
'id': str(asset.id),
|
||||
'hostname': asset.hostname
|
||||
})
|
||||
except ObjectDoesNotExist as e:
|
||||
logger.error(e)
|
||||
return asset_info
|
||||
|
||||
|
||||
class ChromeAttrsSerializer(RemoteAppAttrsSerializer):
|
||||
REMOTE_APP_PATH = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
|
||||
path = serializers.CharField(max_length=128, label=_('Application path'), default=REMOTE_APP_PATH)
|
||||
chrome_target = serializers.CharField(max_length=128, allow_blank=True, required=False, label=_('Target URL'))
|
||||
chrome_username = serializers.CharField(max_length=128, allow_blank=True, required=False, label=_('Username'))
|
||||
chrome_password = serializers.CharField(max_length=128, allow_blank=True, required=False, write_only=True, label=_('Password'))
|
||||
|
||||
|
||||
class MySQLWorkbenchAttrsSerializer(RemoteAppAttrsSerializer):
|
||||
REMOTE_APP_PATH = 'C:\Program Files\MySQL\MySQL Workbench 8.0 CE\MySQLWorkbench.exe'
|
||||
path = serializers.CharField(max_length=128, label=_('Application path'), default=REMOTE_APP_PATH)
|
||||
mysql_workbench_ip = serializers.CharField(max_length=128, allow_blank=True, required=False, label=_('IP'))
|
||||
mysql_workbench_port = serializers.IntegerField(required=False, label=_('Port'))
|
||||
mysql_workbench_name = serializers.CharField(max_length=128, allow_blank=True, required=False, label=_('Database'))
|
||||
mysql_workbench_username = serializers.CharField(max_length=128, allow_blank=True, required=False, label=_('Username'))
|
||||
mysql_workbench_password = serializers.CharField(max_length=128, allow_blank=True, required=False, write_only=True, label=_('Password'))
|
||||
|
||||
|
||||
class VMwareClientAttrsSerializer(RemoteAppAttrsSerializer):
|
||||
REMOTE_APP_PATH = 'C:\Program Files (x86)\VMware\Infrastructure\Virtual Infrastructure Client\Launcher\VpxClient.exe'
|
||||
path = serializers.CharField(max_length=128, label=_('Application path'), default=REMOTE_APP_PATH)
|
||||
vmware_target = serializers.CharField(max_length=128, allow_blank=True, required=False, label=_('Target URL'))
|
||||
vmware_username = serializers.CharField(max_length=128, allow_blank=True, required=False, label=_('Username'))
|
||||
vmware_password = serializers.CharField(max_length=128, allow_blank=True, required=False, write_only=True, label=_('Password'))
|
||||
|
||||
|
||||
class CustomRemoteAppAttrsSeralizers(RemoteAppAttrsSerializer):
|
||||
custom_cmdline = serializers.CharField(max_length=128, allow_blank=True, required=False, label=_('Operating parameter'))
|
||||
custom_target = serializers.CharField(max_length=128, allow_blank=True, required=False, label=_('Target url'))
|
||||
custom_username = serializers.CharField(max_length=128, allow_blank=True, required=False, label=_('Username'))
|
||||
custom_password = serializers.CharField(max_length=128, allow_blank=True, required=False, write_only=True, label=_('Password'))
|
||||
__all__ = ['RemoteAppConnectionInfoSerializer']
|
||||
|
||||
|
||||
class RemoteAppConnectionInfoSerializer(serializers.ModelSerializer):
|
||||
|
@ -97,94 +22,36 @@ class RemoteAppConnectionInfoSerializer(serializers.ModelSerializer):
|
|||
]
|
||||
read_only_fields = ['parameter_remote_app']
|
||||
|
||||
@staticmethod
|
||||
def get_asset(obj):
|
||||
return obj.attrs.get('asset')
|
||||
|
||||
@staticmethod
|
||||
def get_parameters(obj):
|
||||
"""
|
||||
返回Guacamole需要的RemoteApp配置参数信息中的parameters参数
|
||||
"""
|
||||
serializer_cls = Category.get_type_serializer_cls(obj.type)
|
||||
fields = serializer_cls().get_fields()
|
||||
fields.pop('asset', None)
|
||||
fields_name = list(fields.keys())
|
||||
attrs = obj.attrs
|
||||
_parameters = list()
|
||||
_parameters.append(obj.type)
|
||||
for field_name in list(fields_name):
|
||||
value = attrs.get(field_name, None)
|
||||
from .attrs import get_serializer_by_application_type
|
||||
serializer_class = get_serializer_by_application_type(obj.type)
|
||||
fields = serializer_class().get_fields()
|
||||
|
||||
parameters = [obj.type]
|
||||
for field_name in list(fields.keys()):
|
||||
if field_name in ['asset']:
|
||||
continue
|
||||
value = obj.attrs.get(field_name)
|
||||
if not value:
|
||||
continue
|
||||
if field_name == 'path':
|
||||
value = '\"%s\"' % value
|
||||
_parameters.append(str(value))
|
||||
_parameters = ' '.join(_parameters)
|
||||
return _parameters
|
||||
parameters.append(str(value))
|
||||
|
||||
parameters = ' '.join(parameters)
|
||||
return parameters
|
||||
|
||||
def get_parameter_remote_app(self, obj):
|
||||
parameters = self.get_parameters(obj)
|
||||
parameter = {
|
||||
'program': const.REMOTE_APP_BOOT_PROGRAM_NAME,
|
||||
return {
|
||||
'program': '||jmservisor',
|
||||
'working_directory': '',
|
||||
'parameters': parameters,
|
||||
'parameters': self.get_parameters(obj)
|
||||
}
|
||||
return parameter
|
||||
|
||||
@staticmethod
|
||||
def get_asset(obj):
|
||||
return obj.attrs.get('asset')
|
||||
|
||||
|
||||
# TODO: DELETE
|
||||
class RemoteAppParamsDictField(CustomMetaDictField):
|
||||
type_fields_map = const.REMOTE_APP_TYPE_FIELDS_MAP
|
||||
default_type = const.REMOTE_APP_TYPE_CHROME
|
||||
convert_key_remove_type_prefix = False
|
||||
convert_key_to_upper = False
|
||||
|
||||
|
||||
# TODO: DELETE
|
||||
class RemoteAppSerializer(BulkOrgResourceModelSerializer):
|
||||
params = RemoteAppParamsDictField(label=_('Parameters'))
|
||||
type_fields_map = const.REMOTE_APP_TYPE_FIELDS_MAP
|
||||
|
||||
class Meta:
|
||||
model = RemoteApp
|
||||
list_serializer_class = AdaptedBulkListSerializer
|
||||
fields = [
|
||||
'id', 'name', 'asset', 'asset_info', 'type', 'get_type_display',
|
||||
'path', 'params', 'date_created', 'created_by', 'comment',
|
||||
]
|
||||
read_only_fields = [
|
||||
'created_by', 'date_created', 'asset_info',
|
||||
'get_type_display'
|
||||
]
|
||||
extra_kwargs = {
|
||||
'asset_info': {'label': _('Asset info')},
|
||||
'get_type_display': {'label': _('Type for display')},
|
||||
}
|
||||
|
||||
def process_params(self, instance, validated_data):
|
||||
new_params = copy.deepcopy(validated_data.get('params', {}))
|
||||
tp = validated_data.get('type', '')
|
||||
|
||||
if tp != instance.type:
|
||||
return new_params
|
||||
|
||||
old_params = instance.params
|
||||
fields = self.type_fields_map.get(instance.type, [])
|
||||
for field in fields:
|
||||
if not field.get('write_only', False):
|
||||
continue
|
||||
field_name = field['name']
|
||||
new_value = new_params.get(field_name, '')
|
||||
old_value = old_params.get(field_name, '')
|
||||
field_value = new_value if new_value else old_value
|
||||
new_params[field_name] = field_value
|
||||
|
||||
return new_params
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
params = self.process_params(instance, validated_data)
|
||||
validated_data['params'] = params
|
||||
return super().update(instance, validated_data)
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
from .attrs import get_attrs_field_mapping_rule_by_view
|
||||
|
||||
__all__ = [
|
||||
'get_dynamic_mapping_fields_mapping_rule_by_view'
|
||||
]
|
||||
|
||||
|
||||
#
|
||||
# get `dynamic fields` mapping rule by `view object`
|
||||
# ----------------------------------------------------
|
||||
|
||||
|
||||
def get_dynamic_mapping_fields_mapping_rule_by_view(view):
|
||||
return {
|
||||
'attrs': get_attrs_field_mapping_rule_by_view(view=view),
|
||||
}
|
|
@ -1,26 +1,20 @@
|
|||
# coding:utf-8
|
||||
#
|
||||
|
||||
from django.urls import path, re_path
|
||||
from django.urls import path
|
||||
from rest_framework_bulk.routes import BulkRouter
|
||||
|
||||
from common import api as capi
|
||||
from .. import api
|
||||
|
||||
|
||||
app_name = 'applications'
|
||||
|
||||
|
||||
router = BulkRouter()
|
||||
router.register(r'applications', api.ApplicationViewSet, 'application')
|
||||
router.register(r'remote-apps', api.RemoteAppViewSet, 'remote-app')
|
||||
router.register(r'database-apps', api.DatabaseAppViewSet, 'database-app')
|
||||
router.register(r'k8s-apps', api.K8sAppViewSet, 'k8s-app')
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path('remote-apps/<uuid:pk>/connection-info/', api.RemoteAppConnectionInfoApi.as_view(), name='remote-app-connection-info'),
|
||||
]
|
||||
|
||||
old_version_urlpatterns = [
|
||||
re_path('(?P<resource>remote-app)/.*', capi.redirect_plural_name_api)
|
||||
]
|
||||
|
||||
urlpatterns += router.urls + old_version_urlpatterns
|
||||
urlpatterns += router.urls
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
# coding:utf-8
|
||||
from django.urls import path
|
||||
|
||||
app_name = 'applications'
|
||||
|
||||
urlpatterns = [
|
||||
]
|
|
@ -205,16 +205,15 @@ class SystemUser(BaseUser):
|
|||
return assets
|
||||
|
||||
@classmethod
|
||||
def get_protocol_by_application_type(cls, application_type):
|
||||
from applications.models import Category
|
||||
remote_app_types = list(dict(Category.get_type_choices(Category.remote_app)).keys())
|
||||
if application_type in remote_app_types:
|
||||
def get_protocol_by_application_type(cls, app_type):
|
||||
from applications.const import ApplicationTypeChoices
|
||||
if app_type in ApplicationTypeChoices.remote_app_types():
|
||||
return cls.PROTOCOL_RDP
|
||||
cloud_types = list(dict(Category.get_type_choices(Category.cloud)).keys())
|
||||
db_types = list(dict(Category.get_type_choices(Category.db)).keys())
|
||||
other_types = [*cloud_types, *db_types]
|
||||
if application_type in other_types:
|
||||
return application_type
|
||||
protocol = None
|
||||
other_types = [*ApplicationTypeChoices.db_types(), *ApplicationTypeChoices.cloud_types()]
|
||||
if app_type in other_types and app_type in cls.APPLICATION_CATEGORY_PROTOCOLS:
|
||||
protocol = app_type
|
||||
return protocol
|
||||
|
||||
class Meta:
|
||||
ordering = ['name']
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
import data_tree
|
||||
import copy
|
||||
from rest_framework import serializers
|
||||
|
||||
|
||||
__all__ = [
|
||||
'DynamicMappingField', 'ReadableHiddenField',
|
||||
'CustomMetaDictField',
|
||||
'CustomMetaDictField', 'IgnoreSensitiveInfoReadOnlyJSONField',
|
||||
]
|
||||
|
||||
|
||||
|
@ -49,18 +49,12 @@ class DynamicMappingField(serializers.Field):
|
|||
''.format(type(mapping_rules))
|
||||
)
|
||||
|
||||
assert 'default' in mapping_rules, (
|
||||
"mapping_rules['default'] is a required, but only get `{}`"
|
||||
"".format(list(mapping_rules.keys()))
|
||||
)
|
||||
|
||||
self.mapping_rules = mapping_rules
|
||||
self.mapping_tree = self._build_mapping_tree()
|
||||
self.__mapping_rules = mapping_rules
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def _build_mapping_tree(self):
|
||||
tree = data_tree.Data_tree_node(arg_data=self.mapping_rules)
|
||||
return tree
|
||||
@property
|
||||
def mapping_rules(self):
|
||||
return copy.deepcopy(self.__mapping_rules)
|
||||
|
||||
def to_internal_value(self, data):
|
||||
""" 实际是一个虚拟字段所以不返回任何值 """
|
||||
|
@ -70,6 +64,29 @@ class DynamicMappingField(serializers.Field):
|
|||
""" 实际是一个虚拟字段所以不返回任何值 """
|
||||
pass
|
||||
|
||||
|
||||
# A Ignore read-only fields for sensitive information
|
||||
# ----------------------------------------------------------
|
||||
|
||||
|
||||
class IgnoreSensitiveInfoReadOnlyJSONField(serializers.JSONField):
|
||||
""" A ignore read-only fields for sensitive information """
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
kwargs['read_only'] = True
|
||||
super().__init__(**kwargs)
|
||||
|
||||
def to_representation(self, value):
|
||||
sensitive_ignored_value = {}
|
||||
sensitive_names = ['password']
|
||||
for field_name, field_value in value.items():
|
||||
for sensitive_name in sensitive_names:
|
||||
if sensitive_name in field_name.lower():
|
||||
continue
|
||||
sensitive_ignored_value[field_name] = field_value
|
||||
return super().to_representation(sensitive_ignored_value)
|
||||
|
||||
|
||||
#
|
||||
# ReadableHiddenField
|
||||
# -------------------
|
||||
|
|
|
@ -7,6 +7,7 @@ from rest_framework_bulk.serializers import BulkListSerializer
|
|||
from common.mixins import BulkListSerializerMixin
|
||||
from common.drf.fields import DynamicMappingField
|
||||
from common.mixins.serializers import BulkSerializerMixin
|
||||
from common.utils import QuickLookupDict
|
||||
|
||||
__all__ = [
|
||||
'IncludeDynamicMappingFieldSerializerMetaClass',
|
||||
|
@ -69,18 +70,29 @@ class IncludeDynamicMappingFieldSerializerMetaClass(serializers.SerializerMetacl
|
|||
def get_dynamic_mapping_fields(mcs, bases, attrs):
|
||||
fields = {}
|
||||
|
||||
fields_mapping_rules = attrs.get('dynamic_mapping_fields_mapping_rule')
|
||||
# get `fields mapping rule` from attrs `dynamic_mapping_fields_mapping_rule`
|
||||
fields_mapping_rule = attrs.get('dynamic_mapping_fields_mapping_rule')
|
||||
|
||||
assert isinstance(fields_mapping_rules, dict), (
|
||||
# check `fields_mapping_rule` type
|
||||
assert isinstance(fields_mapping_rule, dict), (
|
||||
'`dynamic_mapping_fields_mapping_rule` must be `dict` type , but get `{}`'
|
||||
''.format(type(fields_mapping_rules))
|
||||
''.format(type(fields_mapping_rule))
|
||||
)
|
||||
|
||||
fields_mapping_rules = copy.deepcopy(fields_mapping_rules)
|
||||
|
||||
# get `serializer class` declared fields
|
||||
declared_fields = mcs._get_declared_fields(bases, attrs)
|
||||
declared_fields_names = list(declared_fields.keys())
|
||||
|
||||
for field_name, field_mapping_rule in fields_mapping_rules.items():
|
||||
fields_mapping_rule = copy.deepcopy(fields_mapping_rule)
|
||||
|
||||
for field_name, field_mapping_rule in fields_mapping_rule.items():
|
||||
|
||||
if field_name not in declared_fields_names:
|
||||
continue
|
||||
|
||||
declared_field = declared_fields[field_name]
|
||||
if not isinstance(declared_field, DynamicMappingField):
|
||||
continue
|
||||
|
||||
assert isinstance(field_mapping_rule, (list, str)), (
|
||||
'`dynamic_mapping_fields_mapping_rule.field_mapping_rule` '
|
||||
|
@ -90,34 +102,21 @@ class IncludeDynamicMappingFieldSerializerMetaClass(serializers.SerializerMetacl
|
|||
''.format(type(field_mapping_rule), field_mapping_rule)
|
||||
)
|
||||
|
||||
if field_name not in declared_fields.keys():
|
||||
continue
|
||||
|
||||
declared_field = declared_fields[field_name]
|
||||
if not isinstance(declared_field, DynamicMappingField):
|
||||
continue
|
||||
|
||||
dynamic_field = declared_field
|
||||
|
||||
mapping_tree = dynamic_field.mapping_tree.copy()
|
||||
|
||||
def get_field(rule):
|
||||
return mapping_tree.get(arg_path=rule)
|
||||
|
||||
if isinstance(field_mapping_rule, str):
|
||||
field_mapping_rule = field_mapping_rule.split('.')
|
||||
|
||||
field_mapping_rule[-1] = field_mapping_rule[-1] or 'default'
|
||||
# construct `field mapping rules` sequence list
|
||||
field_mapping_rules = [
|
||||
field_mapping_rule,
|
||||
copy.deepcopy(field_mapping_rule)[:-1] + ['default'],
|
||||
['default']
|
||||
]
|
||||
|
||||
field = get_field(rule=field_mapping_rule)
|
||||
dynamic_field = declared_field
|
||||
|
||||
if not field:
|
||||
field_mapping_rule[-1] = 'default'
|
||||
field = get_field(rule=field_mapping_rule)
|
||||
field_finder = QuickLookupDict(dynamic_field.mapping_rules)
|
||||
|
||||
if field is None:
|
||||
field_mapping_rule = ['default']
|
||||
field = get_field(rule=field_mapping_rule)
|
||||
field = field_finder.find_one(key_paths=field_mapping_rules)
|
||||
|
||||
if isinstance(field, type):
|
||||
field = field()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
import re
|
||||
import data_tree
|
||||
from collections import OrderedDict
|
||||
from itertools import chain
|
||||
import logging
|
||||
|
@ -10,6 +11,8 @@ from functools import wraps
|
|||
import time
|
||||
import ipaddress
|
||||
import psutil
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from ..exceptions import JMSException
|
||||
|
||||
|
||||
UUID_PATTERN = re.compile(r'\w{8}(-\w{4}){3}-\w{12}')
|
||||
|
@ -251,3 +254,152 @@ def get_disk_usage():
|
|||
mount_points = [p.mountpoint for p in partitions]
|
||||
usages = {p: psutil.disk_usage(p) for p in mount_points}
|
||||
return usages
|
||||
|
||||
|
||||
# Verify that `value` is in `choices` and throw an `JMSException`
|
||||
# ---------------------------------------------------------------
|
||||
|
||||
|
||||
def check_value_in_choices(value, choices, **kwargs):
|
||||
# get raise parameters from kwargs
|
||||
raise_exception = kwargs.get('raise_exception', False)
|
||||
raise_error_msg = kwargs.get('raise_error_msg', None)
|
||||
raise_reverse = kwargs.get('raise_reverse', False)
|
||||
|
||||
def should_raise():
|
||||
"""
|
||||
Simplify the following logic:
|
||||
|
||||
if raise_exception:
|
||||
if raise_reverse and value_in_choices:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
if not raise_reverse and not value_in_choices:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
"""
|
||||
return raise_exception and raise_reverse == value_in_choices
|
||||
|
||||
value_in_choices = True if value in choices else False
|
||||
|
||||
if not should_raise():
|
||||
return value_in_choices
|
||||
|
||||
if raise_error_msg is None:
|
||||
raise_error_msg = _('Value `{}` is not in Choices: `{}`'.format(value, choices))
|
||||
|
||||
raise JMSException(raise_error_msg)
|
||||
|
||||
|
||||
# Quick lookup dict
|
||||
# -----------------
|
||||
|
||||
|
||||
class QuickLookupDict(object):
|
||||
"""
|
||||
说明:
|
||||
dict 类型数据的快速查找
|
||||
作用:
|
||||
可根据指定 key 的深度 path 快速查找出对应的 value 值
|
||||
依赖:
|
||||
data-tree==0.0.1
|
||||
实现:
|
||||
通过对 data-tree 库的封装来实现
|
||||
"""
|
||||
|
||||
def __init__(self, data, key_delimiter='.'):
|
||||
self._check_data_type(data, type_choices=(dict, ), error='Expected `data` type is dict')
|
||||
self.data = data
|
||||
self.key_delimiter = key_delimiter
|
||||
self._data_tree = self._get_data_tree(data, key_delimiter)
|
||||
|
||||
# Method encapsulated of `data-tree`
|
||||
# ----------------------------------
|
||||
|
||||
@staticmethod
|
||||
def _get_data_tree(data, key_delimiter):
|
||||
tree = data_tree.Data_tree_node(
|
||||
arg_data=data, arg_string_delimiter_for_path=key_delimiter
|
||||
)
|
||||
return tree
|
||||
|
||||
def _get_data_tree_node(self, path):
|
||||
return self._data_tree.get(arg_path=path)
|
||||
|
||||
@staticmethod
|
||||
def _get_data_tree_node_original_data(tree_node):
|
||||
if isinstance(tree_node, data_tree.Data_tree_node):
|
||||
data = tree_node.get_data_in_format_for_export()
|
||||
else:
|
||||
data = tree_node
|
||||
return data
|
||||
|
||||
# Method called internally
|
||||
# ------------------------
|
||||
|
||||
@staticmethod
|
||||
def _check_data_type(data, type_choices, error=None):
|
||||
error = error or '`data` type error, {} => {}'.format(type(data), type_choices)
|
||||
assert isinstance(data, type_choices), error
|
||||
|
||||
@staticmethod
|
||||
def _check_object_callable(_object):
|
||||
if _object is None:
|
||||
return False
|
||||
if not callable(_object):
|
||||
return False
|
||||
return True
|
||||
|
||||
# Method called externally
|
||||
# ------------------------
|
||||
|
||||
def get(self, key_path, default=None):
|
||||
error = 'key_path - can be either a list of keys, or a delimited string.'
|
||||
self._check_data_type(key_path, (list, str,), error=error)
|
||||
|
||||
tree_node = self._get_data_tree_node(key_path)
|
||||
if tree_node is None:
|
||||
return default
|
||||
value = self._get_data_tree_node_original_data(tree_node)
|
||||
return value
|
||||
|
||||
def get_many(self, key_paths, default=None):
|
||||
values = [
|
||||
self.get(key_path, default=default) for key_path in key_paths
|
||||
]
|
||||
return values
|
||||
|
||||
def find_one(self, key_paths, default=None, callable_filter=None):
|
||||
"""
|
||||
按照 key_paths 顺序查找,返回第一个满足 `callable_filter` 规则的值
|
||||
"""
|
||||
|
||||
def get_data_filter():
|
||||
if self._check_object_callable(callable_filter):
|
||||
return callable_filter
|
||||
return self.__default_find_callable_filter
|
||||
|
||||
_filter = get_data_filter()
|
||||
|
||||
for key_path in key_paths:
|
||||
value = self.get(key_path=key_path)
|
||||
if _filter(key_path, value):
|
||||
return value
|
||||
|
||||
return default
|
||||
|
||||
# Method default
|
||||
# --------------
|
||||
|
||||
@staticmethod
|
||||
def __default_find_callable_filter(key_path, value):
|
||||
return value is not None
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -3,15 +3,4 @@
|
|||
|
||||
from .asset import *
|
||||
from .application import *
|
||||
|
||||
# TODO: 删除
|
||||
from .remote_app_permission import *
|
||||
from .remote_app_permission_relation import *
|
||||
from .user_remote_app_permission import *
|
||||
from .database_app_permission import *
|
||||
from .database_app_permission_relation import *
|
||||
from .user_database_app_permission import *
|
||||
from .system_user_permission import *
|
||||
from .k8s_app_permission import *
|
||||
from .k8s_app_permission_relation import *
|
||||
from .user_k8s_app_permission import *
|
||||
|
|
|
@ -5,8 +5,9 @@ from django.db.models import Q
|
|||
from rest_framework.generics import ListAPIView
|
||||
|
||||
from common.permissions import IsOrgAdminOrAppUser
|
||||
from common.mixins.api import CommonApiMixin
|
||||
from applications.models import Application
|
||||
from applications.api.mixin import ApplicationAttrsSerializerViewMixin
|
||||
from applications.api.mixin import ApplicationViewMixin
|
||||
from perms import serializers
|
||||
|
||||
__all__ = [
|
||||
|
@ -14,9 +15,9 @@ __all__ = [
|
|||
]
|
||||
|
||||
|
||||
class UserGroupGrantedApplicationsApi(ApplicationAttrsSerializerViewMixin, ListAPIView):
|
||||
class UserGroupGrantedApplicationsApi(ApplicationViewMixin, CommonApiMixin, ListAPIView):
|
||||
"""
|
||||
获取用户组直接授权的资产
|
||||
获取用户组直接授权的应用
|
||||
"""
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = serializers.ApplicationGrantedSerializer
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
from rest_framework.generics import ListAPIView
|
||||
from rest_framework.response import Response
|
||||
|
||||
from common.mixins.api import CommonApiMixin
|
||||
from applications.api.mixin import (
|
||||
SerializeApplicationToTreeNodeMixin, ApplicationAttrsSerializerViewMixin
|
||||
SerializeApplicationToTreeNodeMixin, ApplicationViewMixin
|
||||
)
|
||||
from perms import serializers
|
||||
from perms.api.asset.user_permission.mixin import ForAdminMixin, ForUserMixin
|
||||
|
@ -21,7 +22,7 @@ __all__ = [
|
|||
]
|
||||
|
||||
|
||||
class AllGrantedApplicationsMixin(ApplicationAttrsSerializerViewMixin, ListAPIView):
|
||||
class AllGrantedApplicationsMixin(ApplicationViewMixin, CommonApiMixin, ListAPIView):
|
||||
only_fields = serializers.ApplicationGrantedSerializer.Meta.only_fields
|
||||
serializer_class = serializers.ApplicationGrantedSerializer
|
||||
filter_fields = ['id', 'name', 'category', 'type', 'comment']
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
from django.db.models import F
|
||||
from orgs.mixins.api import OrgRelationMixin
|
||||
from django.db.models import Q
|
||||
from common.permissions import IsOrgAdmin
|
||||
from common.utils import get_object_or_none
|
||||
|
@ -8,9 +6,7 @@ from assets.models import SystemUser
|
|||
from users.models import User, UserGroup
|
||||
|
||||
|
||||
__all__ = [
|
||||
'RelationViewSet', 'BasePermissionViewSet'
|
||||
]
|
||||
__all__ = ['BasePermissionViewSet']
|
||||
|
||||
|
||||
class BasePermissionViewSet(OrgBulkModelViewSet):
|
||||
|
@ -99,10 +95,3 @@ class BasePermissionViewSet(OrgBulkModelViewSet):
|
|||
queryset = self.filter_keyword(queryset)
|
||||
queryset = queryset.distinct()
|
||||
return queryset
|
||||
|
||||
|
||||
class RelationViewSet(OrgRelationMixin, OrgBulkModelViewSet):
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset.annotate(**{f'{self.from_field}_display': F(f'{self.from_field}__name')})
|
||||
return queryset
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
|
||||
from .. import models, serializers
|
||||
from common.permissions import IsOrgAdmin
|
||||
|
||||
|
||||
__all__ = ['DatabaseAppPermissionViewSet']
|
||||
|
||||
|
||||
class DatabaseAppPermissionViewSet(OrgBulkModelViewSet):
|
||||
model = models.DatabaseAppPermission
|
||||
serializer_classes = {
|
||||
'default': serializers.DatabaseAppPermissionSerializer,
|
||||
'display': serializers.DatabaseAppPermissionListSerializer
|
||||
}
|
||||
filter_fields = ('name',)
|
||||
search_fields = filter_fields
|
||||
permission_classes = (IsOrgAdmin,)
|
|
@ -1,120 +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 common.permissions import IsOrgAdmin
|
||||
from .base import RelationViewSet
|
||||
from .. import models, serializers
|
||||
|
||||
__all__ = [
|
||||
'DatabaseAppPermissionUserRelationViewSet',
|
||||
'DatabaseAppPermissionUserGroupRelationViewSet',
|
||||
'DatabaseAppPermissionAllUserListApi',
|
||||
'DatabaseAppPermissionDatabaseAppRelationViewSet',
|
||||
'DatabaseAppPermissionAllDatabaseAppListApi',
|
||||
'DatabaseAppPermissionSystemUserRelationViewSet',
|
||||
]
|
||||
|
||||
|
||||
class DatabaseAppPermissionUserRelationViewSet(RelationViewSet):
|
||||
serializer_class = serializers.DatabaseAppPermissionUserRelationSerializer
|
||||
m2m_field = models.DatabaseAppPermission.users.field
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filter_fields = [
|
||||
'id', 'user', 'databaseapppermission'
|
||||
]
|
||||
search_fields = ('user__name', 'user__username', 'databaseapppermission__name')
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset.annotate(user_display=F('user__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class DatabaseAppPermissionUserGroupRelationViewSet(RelationViewSet):
|
||||
serializer_class = serializers.DatabaseAppPermissionUserGroupRelationSerializer
|
||||
m2m_field = models.DatabaseAppPermission.user_groups.field
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filter_fields = [
|
||||
'id', "usergroup", "databaseapppermission"
|
||||
]
|
||||
search_fields = ["usergroup__name", "databaseapppermission__name"]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset \
|
||||
.annotate(usergroup_display=F('usergroup__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class DatabaseAppPermissionAllUserListApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = serializers.DatabaseAppPermissionAllUserSerializer
|
||||
filter_fields = ("username", "name")
|
||||
search_fields = filter_fields
|
||||
|
||||
def get_queryset(self):
|
||||
pk = self.kwargs.get("pk")
|
||||
perm = get_object_or_404(models.DatabaseAppPermission, pk=pk)
|
||||
users = perm.get_all_users().only(
|
||||
*self.serializer_class.Meta.only_fields
|
||||
)
|
||||
return users
|
||||
|
||||
|
||||
class DatabaseAppPermissionDatabaseAppRelationViewSet(RelationViewSet):
|
||||
serializer_class = serializers.DatabaseAppPermissionDatabaseAppRelationSerializer
|
||||
m2m_field = models.DatabaseAppPermission.database_apps.field
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filter_fields = [
|
||||
'id', 'databaseapp', 'databaseapppermission',
|
||||
]
|
||||
search_fields = [
|
||||
"id", "databaseapp__name", "databaseapppermission__name"
|
||||
]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset \
|
||||
.annotate(databaseapp_display=F('databaseapp__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class DatabaseAppPermissionAllDatabaseAppListApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = serializers.DatabaseAppPermissionAllDatabaseAppSerializer
|
||||
filter_fields = ("name",)
|
||||
search_fields = filter_fields
|
||||
|
||||
def get_queryset(self):
|
||||
pk = self.kwargs.get("pk")
|
||||
perm = get_object_or_404(models.DatabaseAppPermission, pk=pk)
|
||||
database_apps = perm.get_all_database_apps().only(
|
||||
*self.serializer_class.Meta.only_fields
|
||||
)
|
||||
return database_apps
|
||||
|
||||
|
||||
class DatabaseAppPermissionSystemUserRelationViewSet(RelationViewSet):
|
||||
serializer_class = serializers.DatabaseAppPermissionSystemUserRelationSerializer
|
||||
m2m_field = models.DatabaseAppPermission.system_users.field
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filter_fields = [
|
||||
'id', 'systemuser', 'databaseapppermission'
|
||||
]
|
||||
search_fields = [
|
||||
'databaseapppermission__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
|
|
@ -1,21 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from orgs.mixins.api import OrgBulkModelViewSet
|
||||
|
||||
from .. import models, serializers
|
||||
from common.permissions import IsOrgAdmin
|
||||
|
||||
|
||||
__all__ = ['K8sAppPermissionViewSet']
|
||||
|
||||
|
||||
class K8sAppPermissionViewSet(OrgBulkModelViewSet):
|
||||
model = models.K8sAppPermission
|
||||
serializer_classes = {
|
||||
'default': serializers.K8sAppPermissionSerializer,
|
||||
'display': serializers.K8sAppPermissionListSerializer
|
||||
}
|
||||
filter_fields = ('name',)
|
||||
search_fields = filter_fields
|
||||
permission_classes = (IsOrgAdmin,)
|
|
@ -1,111 +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 common.permissions import IsOrgAdmin
|
||||
from .base import RelationViewSet
|
||||
from .. import models, serializers
|
||||
|
||||
|
||||
class K8sAppPermissionUserRelationViewSet(RelationViewSet):
|
||||
serializer_class = serializers.K8sAppPermissionUserRelationSerializer
|
||||
m2m_field = models.K8sAppPermission.users.field
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filter_fields = [
|
||||
'id', 'user', 'k8sapppermission'
|
||||
]
|
||||
search_fields = ('user__name', 'user__username', 'k8sapppermission__name')
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset.annotate(user_display=F('user__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class K8sAppPermissionUserGroupRelationViewSet(RelationViewSet):
|
||||
serializer_class = serializers.K8sAppPermissionUserGroupRelationSerializer
|
||||
m2m_field = models.K8sAppPermission.user_groups.field
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filter_fields = [
|
||||
'id', "usergroup", "k8sapppermission"
|
||||
]
|
||||
search_fields = ["usergroup__name", "k8sapppermission__name"]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset \
|
||||
.annotate(usergroup_display=F('usergroup__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class K8sAppPermissionAllUserListApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = serializers.K8sAppPermissionAllUserSerializer
|
||||
filter_fields = ("username", "name")
|
||||
search_fields = filter_fields
|
||||
|
||||
def get_queryset(self):
|
||||
pk = self.kwargs.get("pk")
|
||||
perm = get_object_or_404(models.K8sAppPermission, pk=pk)
|
||||
users = perm.get_all_users().only(
|
||||
*self.serializer_class.Meta.only_fields
|
||||
)
|
||||
return users
|
||||
|
||||
|
||||
class K8sAppPermissionK8sAppRelationViewSet(RelationViewSet):
|
||||
serializer_class = serializers.K8sAppPermissionK8sAppRelationSerializer
|
||||
m2m_field = models.K8sAppPermission.k8s_apps.field
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filter_fields = [
|
||||
'id', 'k8sapp', 'k8sapppermission',
|
||||
]
|
||||
search_fields = [
|
||||
"id", "k8sapp__name", "k8sapppermission__name"
|
||||
]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset \
|
||||
.annotate(k8sapp_display=F('k8sapp__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class K8sAppPermissionAllK8sAppListApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = serializers.K8sAppPermissionAllK8sAppSerializer
|
||||
filter_fields = ("name",)
|
||||
search_fields = filter_fields
|
||||
|
||||
def get_queryset(self):
|
||||
pk = self.kwargs.get("pk")
|
||||
perm = get_object_or_404(models.K8sAppPermission, pk=pk)
|
||||
database_apps = perm.get_all_k8s_apps().only(
|
||||
*self.serializer_class.Meta.only_fields
|
||||
)
|
||||
return database_apps
|
||||
|
||||
|
||||
class K8sAppPermissionSystemUserRelationViewSet(RelationViewSet):
|
||||
serializer_class = serializers.K8sAppPermissionSystemUserRelationSerializer
|
||||
m2m_field = models.K8sAppPermission.system_users.field
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filter_fields = [
|
||||
'id', 'systemuser', 'k8sapppermission'
|
||||
]
|
||||
search_fields = [
|
||||
'k8sapppermission__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
|
|
@ -1,58 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from rest_framework.generics import get_object_or_404
|
||||
from common.permissions import IsValidUser, IsOrgAdminOrAppUser
|
||||
from common.utils import get_logger
|
||||
from orgs.utils import set_to_root_org, set_current_org, get_current_org
|
||||
from ..hands import User, UserGroup
|
||||
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
__all__ = [
|
||||
'UserPermissionMixin', 'UserGroupPermissionMixin',
|
||||
]
|
||||
|
||||
|
||||
class UserPermissionMixin:
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
current_org = None
|
||||
obj = None
|
||||
|
||||
def initial(self, *args, **kwargs):
|
||||
super().initial(*args, **kwargs)
|
||||
self.obj = self.get_obj()
|
||||
|
||||
def get_obj(self):
|
||||
user_id = self.kwargs.get('pk', '')
|
||||
if user_id:
|
||||
user = get_object_or_404(User, id=user_id)
|
||||
else:
|
||||
self.current_org = get_current_org()
|
||||
set_to_root_org()
|
||||
user = self.request.user
|
||||
return user
|
||||
|
||||
def get_permissions(self):
|
||||
if self.kwargs.get('pk') is None:
|
||||
self.permission_classes = (IsValidUser,)
|
||||
return super().get_permissions()
|
||||
|
||||
def finalize_response(self, request, response, *args, **kwargs):
|
||||
response = super().finalize_response(request, response, *args, **kwargs)
|
||||
org = getattr(self, 'current_org', None)
|
||||
if org:
|
||||
set_current_org(org)
|
||||
return response
|
||||
|
||||
|
||||
class UserGroupPermissionMixin:
|
||||
obj = None
|
||||
|
||||
def get_obj(self):
|
||||
user_group_id = self.kwargs.get('pk', '')
|
||||
user_group = get_object_or_404(UserGroup, id=user_group_id)
|
||||
return user_group
|
||||
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from rest_framework.views import Response
|
||||
|
||||
from common.permissions import IsOrgAdmin
|
||||
from orgs.mixins.api import OrgModelViewSet
|
||||
from orgs.mixins import generics
|
||||
from ..models import RemoteAppPermission
|
||||
from ..serializers import (
|
||||
RemoteAppPermissionSerializer,
|
||||
RemoteAppPermissionUpdateUserSerializer,
|
||||
RemoteAppPermissionUpdateRemoteAppSerializer,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
'RemoteAppPermissionViewSet',
|
||||
'RemoteAppPermissionAddUserApi', 'RemoteAppPermissionAddRemoteAppApi',
|
||||
'RemoteAppPermissionRemoveUserApi', 'RemoteAppPermissionRemoveRemoteAppApi',
|
||||
]
|
||||
|
||||
|
||||
class RemoteAppPermissionViewSet(OrgModelViewSet):
|
||||
model = RemoteAppPermission
|
||||
filter_fields = ('name', )
|
||||
search_fields = filter_fields
|
||||
serializer_class = RemoteAppPermissionSerializer
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
|
||||
|
||||
class RemoteAppPermissionAddUserApi(generics.RetrieveUpdateAPIView):
|
||||
model = RemoteAppPermission
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = RemoteAppPermissionUpdateUserSerializer
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
perm = self.get_object()
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
if serializer.is_valid():
|
||||
users = serializer.validated_data.get('users')
|
||||
if users:
|
||||
perm.users.add(*tuple(users))
|
||||
return Response({"msg": "ok"})
|
||||
else:
|
||||
return Response({"error": serializer.errors})
|
||||
|
||||
|
||||
class RemoteAppPermissionRemoveUserApi(generics.RetrieveUpdateAPIView):
|
||||
model = RemoteAppPermission
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = RemoteAppPermissionUpdateUserSerializer
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
perm = self.get_object()
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
if serializer.is_valid():
|
||||
users = serializer.validated_data.get('users')
|
||||
if users:
|
||||
perm.users.remove(*tuple(users))
|
||||
return Response({"msg": "ok"})
|
||||
else:
|
||||
return Response({"error": serializer.errors})
|
||||
|
||||
|
||||
class RemoteAppPermissionAddRemoteAppApi(generics.RetrieveUpdateAPIView):
|
||||
model = RemoteAppPermission
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = RemoteAppPermissionUpdateRemoteAppSerializer
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
perm = self.get_object()
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
if serializer.is_valid():
|
||||
remote_apps = serializer.validated_data.get('remote_apps')
|
||||
if remote_apps:
|
||||
perm.remote_apps.add(*tuple(remote_apps))
|
||||
return Response({"msg": "ok"})
|
||||
else:
|
||||
return Response({"error": serializer.errors})
|
||||
|
||||
|
||||
class RemoteAppPermissionRemoveRemoteAppApi(generics.RetrieveUpdateAPIView):
|
||||
model = RemoteAppPermission
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = RemoteAppPermissionUpdateRemoteAppSerializer
|
||||
|
||||
def update(self, request, *args, **kwargs):
|
||||
perm = self.get_object()
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
if serializer.is_valid():
|
||||
remote_apps = serializer.validated_data.get('remote_apps')
|
||||
if remote_apps:
|
||||
perm.remote_apps.remove(*tuple(remote_apps))
|
||||
return Response({"msg": "ok"})
|
||||
else:
|
||||
return Response({"error": serializer.errors})
|
||||
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
from perms.api.base import RelationViewSet
|
||||
from rest_framework import generics
|
||||
from django.db.models import F
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from common.permissions import IsOrgAdmin
|
||||
from .. import models, serializers
|
||||
|
||||
__all__ = [
|
||||
'RemoteAppPermissionUserRelationViewSet',
|
||||
'RemoteAppPermissionRemoteAppRelationViewSet',
|
||||
'RemoteAppPermissionAllRemoteAppListApi',
|
||||
'RemoteAppPermissionAllUserListApi',
|
||||
]
|
||||
|
||||
|
||||
class RemoteAppPermissionAllUserListApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = serializers.PermissionAllUserSerializer
|
||||
filter_fields = ("username", "name")
|
||||
search_fields = filter_fields
|
||||
|
||||
def get_queryset(self):
|
||||
pk = self.kwargs.get("pk")
|
||||
perm = get_object_or_404(models.RemoteAppPermission, pk=pk)
|
||||
users = perm.all_users.only(
|
||||
*self.serializer_class.Meta.only_fields
|
||||
)
|
||||
return users
|
||||
|
||||
|
||||
class RemoteAppPermissionUserRelationViewSet(RelationViewSet):
|
||||
serializer_class = serializers.RemoteAppPermissionUserRelationSerializer
|
||||
m2m_field = models.RemoteAppPermission.users.field
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filter_fields = [
|
||||
'id', 'user', 'remoteapppermission'
|
||||
]
|
||||
search_fields = ('user__name', 'user__username', 'remoteapppermission__name')
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset.annotate(user_display=F('user__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class RemoteAppPermissionRemoteAppRelationViewSet(RelationViewSet):
|
||||
serializer_class = serializers.RemoteAppPermissionRemoteAppRelationSerializer
|
||||
m2m_field = models.RemoteAppPermission.remote_apps.field
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
filter_fields = [
|
||||
'id', 'remoteapp', 'remoteapppermission',
|
||||
]
|
||||
search_fields = [
|
||||
"id", "remoteapp__name", "remoteapppermission__name"
|
||||
]
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
queryset = queryset \
|
||||
.annotate(remoteapp_display=F('remoteapp__name'))
|
||||
return queryset
|
||||
|
||||
|
||||
class RemoteAppPermissionAllRemoteAppListApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdmin,)
|
||||
serializer_class = serializers.RemoteAppPermissionAllRemoteAppSerializer
|
||||
filter_fields = ("name",)
|
||||
search_fields = filter_fields
|
||||
|
||||
def get_queryset(self):
|
||||
pk = self.kwargs.get("pk")
|
||||
perm = get_object_or_404(models.RemoteAppPermission, pk=pk)
|
||||
remote_apps = perm.all_remote_apps.only(
|
||||
*self.serializer_class.Meta.only_fields
|
||||
)
|
||||
return remote_apps
|
|
@ -1,128 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
import uuid
|
||||
from django.shortcuts import get_object_or_404
|
||||
from rest_framework.views import APIView, Response
|
||||
from common.permissions import IsOrgAdminOrAppUser, IsValidUser
|
||||
from common.tree import TreeNodeSerializer
|
||||
from orgs.mixins import generics
|
||||
from users.models import User, UserGroup
|
||||
from applications.serializers import DatabaseAppSerializer
|
||||
from applications.models import DatabaseApp
|
||||
from assets.models import SystemUser
|
||||
from .. import utils, serializers
|
||||
from .mixin import UserPermissionMixin
|
||||
|
||||
__all__ = [
|
||||
'UserGrantedDatabaseAppsApi',
|
||||
'UserGrantedDatabaseAppsAsTreeApi',
|
||||
'UserGroupGrantedDatabaseAppsApi',
|
||||
'ValidateUserDatabaseAppPermissionApi',
|
||||
'UserGrantedDatabaseAppSystemUsersApi',
|
||||
]
|
||||
|
||||
|
||||
class UserGrantedDatabaseAppsApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = DatabaseAppSerializer
|
||||
filter_fields = ['id', 'name', 'type', 'comment']
|
||||
search_fields = ['name', 'comment']
|
||||
|
||||
def get_object(self):
|
||||
user_id = self.kwargs.get('pk', '')
|
||||
if user_id:
|
||||
user = get_object_or_404(User, id=user_id)
|
||||
else:
|
||||
user = self.request.user
|
||||
return user
|
||||
|
||||
def get_queryset(self):
|
||||
util = utils.DatabaseAppPermissionUtil(self.get_object())
|
||||
queryset = util.get_database_apps()
|
||||
return queryset
|
||||
|
||||
def get_permissions(self):
|
||||
if self.kwargs.get('pk') is None:
|
||||
self.permission_classes = (IsValidUser,)
|
||||
return super().get_permissions()
|
||||
|
||||
|
||||
class UserGrantedDatabaseAppsAsTreeApi(UserGrantedDatabaseAppsApi):
|
||||
serializer_class = TreeNodeSerializer
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
|
||||
def get_serializer(self, database_apps, *args, **kwargs):
|
||||
if database_apps is None:
|
||||
database_apps = []
|
||||
only_database_app = self.request.query_params.get('only', '0') == '1'
|
||||
tree_root = None
|
||||
data = []
|
||||
if not only_database_app:
|
||||
amount = len(database_apps)
|
||||
tree_root = utils.construct_database_apps_tree_root(amount)
|
||||
data.append(tree_root)
|
||||
for database_app in database_apps:
|
||||
node = utils.parse_database_app_to_tree_node(tree_root, database_app)
|
||||
data.append(node)
|
||||
data.sort()
|
||||
return super().get_serializer(data, many=True)
|
||||
|
||||
|
||||
class UserGrantedDatabaseAppSystemUsersApi(UserPermissionMixin, generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = serializers.DatabaseAppSystemUserSerializer
|
||||
only_fields = serializers.DatabaseAppSystemUserSerializer.Meta.only_fields
|
||||
|
||||
def get_queryset(self):
|
||||
util = utils.DatabaseAppPermissionUtil(self.obj)
|
||||
database_app_id = self.kwargs.get('database_app_id')
|
||||
database_app = get_object_or_404(DatabaseApp, id=database_app_id)
|
||||
system_users = util.get_database_app_system_users(database_app)
|
||||
return system_users
|
||||
|
||||
|
||||
# Validate
|
||||
|
||||
class ValidateUserDatabaseAppPermissionApi(APIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
user_id = request.query_params.get('user_id', '')
|
||||
database_app_id = request.query_params.get('database_app_id', '')
|
||||
system_user_id = request.query_params.get('system_user_id', '')
|
||||
|
||||
try:
|
||||
user_id = uuid.UUID(user_id)
|
||||
database_app_id = uuid.UUID(database_app_id)
|
||||
system_user_id = uuid.UUID(system_user_id)
|
||||
except ValueError:
|
||||
return Response({'msg': False}, status=403)
|
||||
|
||||
user = get_object_or_404(User, id=user_id)
|
||||
database_app = get_object_or_404(DatabaseApp, id=database_app_id)
|
||||
system_user = get_object_or_404(SystemUser, id=system_user_id)
|
||||
|
||||
util = utils.DatabaseAppPermissionUtil(user)
|
||||
system_users = util.get_database_app_system_users(database_app)
|
||||
if system_user in system_users:
|
||||
return Response({'msg': True}, status=200)
|
||||
|
||||
return Response({'msg': False}, status=403)
|
||||
|
||||
|
||||
# UserGroup
|
||||
|
||||
class UserGroupGrantedDatabaseAppsApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = DatabaseAppSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = []
|
||||
user_group_id = self.kwargs.get('pk')
|
||||
if not user_group_id:
|
||||
return queryset
|
||||
user_group = get_object_or_404(UserGroup, id=user_group_id)
|
||||
util = utils.DatabaseAppPermissionUtil(user_group)
|
||||
queryset = util.get_database_apps()
|
||||
return queryset
|
|
@ -1,120 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
import uuid
|
||||
from django.shortcuts import get_object_or_404
|
||||
from rest_framework.views import APIView, Response
|
||||
from common.permissions import IsOrgAdminOrAppUser, IsValidUser
|
||||
from common.tree import TreeNodeSerializer
|
||||
from orgs.mixins import generics
|
||||
from users.models import User, UserGroup
|
||||
from applications.serializers import K8sAppSerializer
|
||||
from applications.models import K8sApp
|
||||
from assets.models import SystemUser
|
||||
from .. import utils, serializers
|
||||
from .mixin import UserPermissionMixin
|
||||
|
||||
|
||||
class UserGrantedK8sAppsApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = K8sAppSerializer
|
||||
filter_fields = ['id', 'name', 'type', 'comment']
|
||||
search_fields = ['name', 'comment']
|
||||
|
||||
def get_object(self):
|
||||
user_id = self.kwargs.get('pk', '')
|
||||
if user_id:
|
||||
user = get_object_or_404(User, id=user_id)
|
||||
else:
|
||||
user = self.request.user
|
||||
return user
|
||||
|
||||
def get_queryset(self):
|
||||
util = utils.K8sAppPermissionUtil(self.get_object())
|
||||
queryset = util.get_k8s_apps()
|
||||
return queryset
|
||||
|
||||
def get_permissions(self):
|
||||
if self.kwargs.get('pk') is None:
|
||||
self.permission_classes = (IsValidUser,)
|
||||
return super().get_permissions()
|
||||
|
||||
|
||||
class UserGrantedK8sAppsAsTreeApi(UserGrantedK8sAppsApi):
|
||||
serializer_class = TreeNodeSerializer
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
|
||||
def get_serializer(self, k8s_apps, *args, **kwargs):
|
||||
if k8s_apps is None:
|
||||
k8s_apps = []
|
||||
only_k8s_app = self.request.query_params.get('only', '0') == '1'
|
||||
tree_root = None
|
||||
data = []
|
||||
if not only_k8s_app:
|
||||
amount = len(k8s_apps)
|
||||
tree_root = utils.construct_k8s_apps_tree_root(amount)
|
||||
data.append(tree_root)
|
||||
for k8s_app in k8s_apps:
|
||||
node = utils.parse_k8s_app_to_tree_node(tree_root, k8s_app)
|
||||
data.append(node)
|
||||
data.sort()
|
||||
return super().get_serializer(data, many=True)
|
||||
|
||||
|
||||
class UserGrantedK8sAppSystemUsersApi(UserPermissionMixin, generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = serializers.K8sAppSystemUserSerializer
|
||||
only_fields = serializers.K8sAppSystemUserSerializer.Meta.only_fields
|
||||
|
||||
def get_queryset(self):
|
||||
util = utils.K8sAppPermissionUtil(self.obj)
|
||||
k8s_app_id = self.kwargs.get('k8s_app_id')
|
||||
k8s_app = get_object_or_404(K8sApp, id=k8s_app_id)
|
||||
system_users = util.get_k8s_app_system_users(k8s_app)
|
||||
return system_users
|
||||
|
||||
|
||||
# Validate
|
||||
|
||||
class ValidateUserK8sAppPermissionApi(APIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
user_id = request.query_params.get('user_id', '')
|
||||
k8s_app_id = request.query_params.get('k8s_app_id', '')
|
||||
system_user_id = request.query_params.get('system_user_id', '')
|
||||
|
||||
try:
|
||||
user_id = uuid.UUID(user_id)
|
||||
k8s_app_id = uuid.UUID(k8s_app_id)
|
||||
system_user_id = uuid.UUID(system_user_id)
|
||||
except ValueError:
|
||||
return Response({'msg': False}, status=403)
|
||||
|
||||
user = get_object_or_404(User, id=user_id)
|
||||
k8s_app = get_object_or_404(K8sApp, id=k8s_app_id)
|
||||
system_user = get_object_or_404(SystemUser, id=system_user_id)
|
||||
|
||||
util = utils.K8sAppPermissionUtil(user)
|
||||
system_users = util.get_k8s_app_system_users(k8s_app)
|
||||
if system_user in system_users:
|
||||
return Response({'msg': True}, status=200)
|
||||
|
||||
return Response({'msg': False}, status=403)
|
||||
|
||||
|
||||
# UserGroup
|
||||
|
||||
class UserGroupGrantedK8sAppsApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = K8sAppSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = []
|
||||
user_group_id = self.kwargs.get('pk')
|
||||
if not user_group_id:
|
||||
return queryset
|
||||
user_group = get_object_or_404(UserGroup, id=user_group_id)
|
||||
util = utils.K8sAppPermissionUtil(user_group)
|
||||
queryset = util.get_k8s_apps()
|
||||
return queryset
|
|
@ -1,126 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import uuid
|
||||
from django.shortcuts import get_object_or_404
|
||||
from rest_framework.views import APIView, Response
|
||||
|
||||
from common.permissions import IsValidUser, IsOrgAdminOrAppUser
|
||||
from common.tree import TreeNodeSerializer
|
||||
from orgs.mixins import generics
|
||||
from ..utils import (
|
||||
RemoteAppPermissionUtil, construct_remote_apps_tree_root,
|
||||
parse_remote_app_to_tree_node,
|
||||
)
|
||||
from ..hands import User, RemoteApp, RemoteAppSerializer, UserGroup, SystemUser
|
||||
from .mixin import UserPermissionMixin
|
||||
from .. import serializers
|
||||
|
||||
|
||||
__all__ = [
|
||||
'UserGrantedRemoteAppsApi', 'ValidateUserRemoteAppPermissionApi',
|
||||
'UserGrantedRemoteAppsAsTreeApi', 'UserGroupGrantedRemoteAppsApi',
|
||||
'UserGrantedRemoteAppSystemUsersApi',
|
||||
]
|
||||
|
||||
|
||||
class UserGrantedRemoteAppsApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = RemoteAppSerializer
|
||||
filter_fields = ['name', 'id', 'type', 'comment']
|
||||
search_fields = ['name', 'comment']
|
||||
|
||||
def get_object(self):
|
||||
user_id = self.kwargs.get('pk', '')
|
||||
if user_id:
|
||||
user = get_object_or_404(User, id=user_id)
|
||||
else:
|
||||
user = self.request.user
|
||||
return user
|
||||
|
||||
def get_queryset(self):
|
||||
util = RemoteAppPermissionUtil(self.get_object())
|
||||
queryset = util.get_remote_apps()
|
||||
return queryset
|
||||
|
||||
def get_permissions(self):
|
||||
if self.kwargs.get('pk') is None:
|
||||
self.permission_classes = (IsValidUser,)
|
||||
return super().get_permissions()
|
||||
|
||||
|
||||
class UserGrantedRemoteAppsAsTreeApi(UserGrantedRemoteAppsApi):
|
||||
serializer_class = TreeNodeSerializer
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
|
||||
def get_serializer(self, remote_apps=None, *args, **kwargs):
|
||||
if remote_apps is None:
|
||||
remote_apps = []
|
||||
only_remote_app = self.request.query_params.get('only', '0') == '1'
|
||||
tree_root = None
|
||||
data = []
|
||||
if not only_remote_app:
|
||||
amount = len(remote_apps)
|
||||
tree_root = construct_remote_apps_tree_root(amount)
|
||||
data.append(tree_root)
|
||||
for remote_app in remote_apps:
|
||||
node = parse_remote_app_to_tree_node(tree_root, remote_app)
|
||||
data.append(node)
|
||||
data.sort()
|
||||
return super().get_serializer(data, many=True)
|
||||
|
||||
|
||||
class UserGrantedRemoteAppSystemUsersApi(UserPermissionMixin, generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
serializer_class = serializers.RemoteAppSystemUserSerializer
|
||||
only_fields = serializers.RemoteAppSystemUserSerializer.Meta.only_fields
|
||||
|
||||
def get_queryset(self):
|
||||
util = RemoteAppPermissionUtil(self.obj)
|
||||
remote_app_id = self.kwargs.get('remote_app_id')
|
||||
remote_app = get_object_or_404(RemoteApp, id=remote_app_id)
|
||||
system_users = util.get_remote_app_system_users(remote_app)
|
||||
return system_users
|
||||
|
||||
|
||||
class ValidateUserRemoteAppPermissionApi(APIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser,)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
user_id = request.query_params.get('user_id', '')
|
||||
remote_app_id = request.query_params.get('remote_app_id', '')
|
||||
system_id = request.query_params.get('system_user_id', '')
|
||||
|
||||
try:
|
||||
user_id = uuid.UUID(user_id)
|
||||
remote_app_id = uuid.UUID(remote_app_id)
|
||||
system_id = uuid.UUID(system_id)
|
||||
except ValueError:
|
||||
return Response({'msg': False}, status=403)
|
||||
|
||||
user = get_object_or_404(User, id=user_id)
|
||||
remote_app = get_object_or_404(RemoteApp, id=remote_app_id)
|
||||
system_user = get_object_or_404(SystemUser, id=system_id)
|
||||
|
||||
util = RemoteAppPermissionUtil(user)
|
||||
system_users = util.get_remote_app_system_users(remote_app)
|
||||
if system_user in system_users:
|
||||
return Response({'msg': True}, status=200)
|
||||
|
||||
return Response({'msg': False}, status=403)
|
||||
|
||||
|
||||
# RemoteApp permission
|
||||
|
||||
class UserGroupGrantedRemoteAppsApi(generics.ListAPIView):
|
||||
permission_classes = (IsOrgAdminOrAppUser, )
|
||||
serializer_class = RemoteAppSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = []
|
||||
user_group_id = self.kwargs.get('pk')
|
||||
if not user_group_id:
|
||||
return queryset
|
||||
user_group = get_object_or_404(UserGroup, id=user_group_id)
|
||||
util = RemoteAppPermissionUtil(user_group)
|
||||
queryset = util.get_remote_apps()
|
||||
return queryset
|
|
@ -1,6 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from .asset_permission import *
|
||||
from .remote_app_permission import *
|
||||
from .database_app_permission import *
|
|
@ -1,119 +0,0 @@
|
|||
# ~*~ coding: utf-8 ~*~
|
||||
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
from django import forms
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orgs.mixins.forms import OrgModelForm
|
||||
from assets.models import Asset, Node, SystemUser
|
||||
from ..models import AssetPermission, Action
|
||||
|
||||
__all__ = [
|
||||
'AssetPermissionForm',
|
||||
]
|
||||
|
||||
|
||||
class ActionField(forms.MultipleChoiceField):
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['choices'] = Action.CHOICES
|
||||
kwargs['initial'] = Action.ALL
|
||||
kwargs['label'] = _("Action")
|
||||
kwargs['widget'] = forms.CheckboxSelectMultiple()
|
||||
kwargs['help_text'] = _(
|
||||
'Tips: The RDP protocol does not support separate controls '
|
||||
'for uploading or downloading files'
|
||||
)
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def to_python(self, value):
|
||||
value = super().to_python(value)
|
||||
return Action.choices_to_value(value)
|
||||
|
||||
def prepare_value(self, value):
|
||||
if value is None:
|
||||
return value
|
||||
value = Action.value_to_choices(value)
|
||||
return value
|
||||
|
||||
|
||||
class AssetPermissionForm(OrgModelForm):
|
||||
actions = ActionField()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
if self.data:
|
||||
return
|
||||
# 前端渲染优化, 防止过多资产
|
||||
users_field = self.fields.get('users')
|
||||
assets_field = self.fields['assets']
|
||||
nodes_field = self.fields['nodes']
|
||||
if self.instance:
|
||||
assets_field.queryset = self.instance.assets.all()
|
||||
nodes_field.queryset = self.instance.nodes.all()
|
||||
users_field.queryset = self.instance.users.all()
|
||||
else:
|
||||
assets_field.queryset = Asset.objects.none()
|
||||
nodes_field.queryset = Node.objects.none()
|
||||
users_field.queryset = []
|
||||
|
||||
# 过滤系统用户
|
||||
system_users_field = self.fields.get('system_users')
|
||||
system_users_field.queryset = SystemUser.objects.exclude(
|
||||
protocol__in=SystemUser.ASSET_CATEGORY_PROTOCOLS
|
||||
)
|
||||
|
||||
def set_nodes_initial(self, nodes):
|
||||
field = self.fields['nodes']
|
||||
field.choices = [(n.id, n.full_value) for n in nodes]
|
||||
field.initial = nodes
|
||||
|
||||
def set_assets_initial(self, assets):
|
||||
field = self.fields['assets']
|
||||
field.choices = [(a.id, a.hostname) for a in assets]
|
||||
field.initial = assets
|
||||
|
||||
class Meta:
|
||||
model = AssetPermission
|
||||
exclude = (
|
||||
'id', 'date_created', 'created_by', 'org_id'
|
||||
)
|
||||
widgets = {
|
||||
'users': forms.SelectMultiple(
|
||||
attrs={'class': 'users-select2', 'data-placeholder': _("User")}
|
||||
),
|
||||
'user_groups': forms.SelectMultiple(
|
||||
attrs={'class': 'select2', 'data-placeholder': _("User group")}
|
||||
),
|
||||
'assets': forms.SelectMultiple(
|
||||
attrs={'class': 'select2', 'data-placeholder': _("Asset")}
|
||||
),
|
||||
'nodes': forms.SelectMultiple(
|
||||
attrs={'class': 'nodes-select2', 'data-placeholder': _("Node")}
|
||||
),
|
||||
'system_users': forms.SelectMultiple(
|
||||
attrs={'class': 'select2', 'data-placeholder': _('System user')}
|
||||
),
|
||||
}
|
||||
labels = {
|
||||
'nodes': _("Node"),
|
||||
}
|
||||
|
||||
def clean_user_groups(self):
|
||||
users = self.cleaned_data.get('users')
|
||||
user_groups = self.cleaned_data.get('user_groups')
|
||||
|
||||
if not users and not user_groups:
|
||||
raise forms.ValidationError(
|
||||
_("User or group at least one required"))
|
||||
return self.cleaned_data["user_groups"]
|
||||
|
||||
def clean_asset_groups(self):
|
||||
assets = self.cleaned_data.get('assets')
|
||||
asset_groups = self.cleaned_data.get('asset_groups')
|
||||
|
||||
if not assets and not asset_groups:
|
||||
raise forms.ValidationError(
|
||||
_("Asset or group at least one required"))
|
||||
|
||||
return self.cleaned_data["asset_groups"]
|
|
@ -1,49 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django import forms
|
||||
from orgs.mixins.forms import OrgModelForm
|
||||
from assets.models import SystemUser
|
||||
|
||||
from ..models import DatabaseAppPermission
|
||||
|
||||
|
||||
__all__ = ['DatabaseAppPermissionCreateUpdateForm']
|
||||
|
||||
|
||||
class DatabaseAppPermissionCreateUpdateForm(OrgModelForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
users_field = self.fields.get('users')
|
||||
if self.instance:
|
||||
users_field.queryset = self.instance.users.all()
|
||||
else:
|
||||
users_field.queryset = []
|
||||
|
||||
# 过滤系统用户
|
||||
system_users_field = self.fields.get('system_users')
|
||||
system_users_field.queryset = SystemUser.objects.filter(
|
||||
protocol__in=SystemUser.APPLICATION_CATEGORY_DB_PROTOCOLS
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = DatabaseAppPermission
|
||||
exclude = (
|
||||
'id', 'date_created', 'created_by', 'org_id'
|
||||
)
|
||||
widgets = {
|
||||
'users': forms.SelectMultiple(
|
||||
attrs={'class': 'users-select2', 'data-placeholder': _('User')}
|
||||
),
|
||||
'user_groups': forms.SelectMultiple(
|
||||
attrs={'class': 'select2', 'data-placeholder': _('User group')}
|
||||
),
|
||||
'database_apps': forms.SelectMultiple(
|
||||
attrs={'class': 'select2', 'data-placeholder': _('DatabaseApp')}
|
||||
),
|
||||
'system_users': forms.SelectMultiple(
|
||||
attrs={'class': 'select2', 'data-placeholder': _('System users')}
|
||||
),
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django import forms
|
||||
from orgs.mixins.forms import OrgModelForm
|
||||
from assets.models import SystemUser
|
||||
|
||||
from ..models import RemoteAppPermission
|
||||
|
||||
|
||||
__all__ = [
|
||||
'RemoteAppPermissionCreateUpdateForm',
|
||||
]
|
||||
|
||||
|
||||
class RemoteAppPermissionCreateUpdateForm(OrgModelForm):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
users_field = self.fields.get('users')
|
||||
if self.instance:
|
||||
users_field.queryset = self.instance.users.all()
|
||||
else:
|
||||
users_field.queryset = []
|
||||
|
||||
# 过滤系统用户
|
||||
system_users_field = self.fields.get('system_users')
|
||||
system_users_field.queryset = SystemUser.objects.filter(
|
||||
protocol=SystemUser.PROTOCOL_RDP
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = RemoteAppPermission
|
||||
exclude = (
|
||||
'id', 'date_created', 'created_by', 'org_id'
|
||||
)
|
||||
widgets = {
|
||||
'users': forms.SelectMultiple(
|
||||
attrs={'class': 'users-select2', 'data-placeholder': _('User')}
|
||||
),
|
||||
'user_groups': forms.SelectMultiple(
|
||||
attrs={'class': 'select2', 'data-placeholder': _('User group')}
|
||||
),
|
||||
'remote_apps': forms.SelectMultiple(
|
||||
attrs={'class': 'select2', 'data-placeholder': _('RemoteApp')}
|
||||
),
|
||||
'system_users': forms.SelectMultiple(
|
||||
attrs={'class': 'select2', 'data-placeholder': _('System user')}
|
||||
)
|
||||
}
|
|
@ -4,13 +4,10 @@
|
|||
from users.models import User, UserGroup
|
||||
from assets.models import Asset, SystemUser, Node, Label, FavoriteAsset
|
||||
from assets.serializers import NodeSerializer
|
||||
from applications.serializers import RemoteAppSerializer
|
||||
from applications.models import RemoteApp
|
||||
|
||||
__all__ = [
|
||||
'User', 'UserGroup',
|
||||
'Asset', 'SystemUser', 'Node', 'Label', 'FavoriteAsset',
|
||||
'NodeSerializer', 'RemoteAppSerializer',
|
||||
'RemoteApp'
|
||||
'NodeSerializer',
|
||||
]
|
||||
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
# Generated by Django 3.1 on 2021-01-03 20:35
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('perms', '0016_applicationpermission'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterUniqueTogether(
|
||||
name='k8sapppermission',
|
||||
unique_together=None,
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='k8sapppermission',
|
||||
name='k8s_apps',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='k8sapppermission',
|
||||
name='system_users',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='k8sapppermission',
|
||||
name='user_groups',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='k8sapppermission',
|
||||
name='users',
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='remoteapppermission',
|
||||
unique_together=None,
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='remoteapppermission',
|
||||
name='remote_apps',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='remoteapppermission',
|
||||
name='system_users',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='remoteapppermission',
|
||||
name='user_groups',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='remoteapppermission',
|
||||
name='users',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='DatabaseAppPermission',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='K8sAppPermission',
|
||||
),
|
||||
migrations.DeleteModel(
|
||||
name='RemoteAppPermission',
|
||||
),
|
||||
]
|
|
@ -1,22 +0,0 @@
|
|||
# ~*~ coding: utf-8 ~*~
|
||||
#
|
||||
|
||||
from orgs.utils import set_to_root_org
|
||||
|
||||
__all__ = [
|
||||
'ChangeOrgIfNeedMixin',
|
||||
]
|
||||
|
||||
|
||||
class ChangeOrgIfNeedMixin(object):
|
||||
|
||||
@staticmethod
|
||||
def change_org_if_need(request, kwargs):
|
||||
if request.user.is_authenticated and request.user.is_superuser \
|
||||
or request.user.is_app \
|
||||
or kwargs.get('pk') is None:
|
||||
set_to_root_org()
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.change_org_if_need(request, kwargs)
|
||||
return super().get(request, *args, **kwargs)
|
|
@ -3,6 +3,3 @@
|
|||
|
||||
from .asset_permission import *
|
||||
from .application_permission import *
|
||||
from .remote_app_permission import *
|
||||
from .database_app_permission import *
|
||||
from .k8s_app_permission import *
|
||||
|
|
|
@ -8,7 +8,7 @@ from django.utils.translation import ugettext_lazy as _
|
|||
from common.utils import lazyproperty
|
||||
from .base import BasePermission
|
||||
from users.models import User
|
||||
from applications.models import Category
|
||||
from applications.const import ApplicationCategoryChoices, ApplicationTypeChoices
|
||||
|
||||
__all__ = [
|
||||
'ApplicationPermission',
|
||||
|
@ -16,16 +16,38 @@ __all__ = [
|
|||
|
||||
|
||||
class ApplicationPermission(BasePermission):
|
||||
category = models.CharField(max_length=16, choices=Category.choices, verbose_name=_('Category'))
|
||||
type = models.CharField(max_length=16, choices=Category.get_all_type_choices(), verbose_name=_('Type'))
|
||||
applications = models.ManyToManyField('applications.Application', related_name='granted_by_permissions', blank=True, verbose_name=_("Application"))
|
||||
system_users = models.ManyToManyField('assets.SystemUser', related_name='granted_by_application_permissions', verbose_name=_("System user"))
|
||||
category = models.CharField(
|
||||
max_length=16, choices=ApplicationCategoryChoices.choices, verbose_name=_('Category')
|
||||
)
|
||||
type = models.CharField(
|
||||
max_length=16, choices=ApplicationTypeChoices.choices, verbose_name=_('Type')
|
||||
)
|
||||
applications = models.ManyToManyField(
|
||||
'applications.Application', related_name='granted_by_permissions', blank=True,
|
||||
verbose_name=_("Application")
|
||||
)
|
||||
system_users = models.ManyToManyField(
|
||||
'assets.SystemUser', related_name='granted_by_application_permissions',
|
||||
verbose_name=_("System user")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
unique_together = [('org_id', 'name')]
|
||||
verbose_name = _('Application permission')
|
||||
ordering = ('name',)
|
||||
|
||||
@property
|
||||
def category_remote_app(self):
|
||||
return self.category == ApplicationCategoryChoices.remote_app.value
|
||||
|
||||
@property
|
||||
def category_db(self):
|
||||
return self.category == ApplicationCategoryChoices.db.value
|
||||
|
||||
@property
|
||||
def category_cloud(self):
|
||||
return self.category == ApplicationCategoryChoices.cloud.value
|
||||
|
||||
@lazyproperty
|
||||
def users_amount(self):
|
||||
return self.users.count()
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
import uuid
|
||||
import logging
|
||||
from functools import reduce
|
||||
|
||||
|
@ -6,8 +5,6 @@ from django.utils.translation import ugettext_lazy as _
|
|||
|
||||
from common.db import models
|
||||
from common.utils import lazyproperty
|
||||
from orgs.models import Organization
|
||||
from orgs.utils import get_current_org
|
||||
from assets.models import Asset, SystemUser, Node, FamilyMixin
|
||||
|
||||
from .base import BasePermission
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.utils import lazyproperty
|
||||
from .base import BasePermission
|
||||
|
||||
__all__ = [
|
||||
'DatabaseAppPermission',
|
||||
]
|
||||
|
||||
|
||||
class DatabaseAppPermission(BasePermission):
|
||||
database_apps = models.ManyToManyField(
|
||||
'applications.DatabaseApp', related_name='granted_by_permissions',
|
||||
blank=True, verbose_name=_("DatabaseApp")
|
||||
)
|
||||
system_users = models.ManyToManyField(
|
||||
'assets.SystemUser', related_name='granted_by_database_app_permissions',
|
||||
verbose_name=_("System user")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
unique_together = [('org_id', 'name')]
|
||||
verbose_name = _('DatabaseApp permission')
|
||||
ordering = ('name',)
|
||||
|
||||
def get_all_database_apps(self):
|
||||
return self.database_apps.all()
|
||||
|
||||
@lazyproperty
|
||||
def database_apps_amount(self):
|
||||
return self.database_apps.count()
|
||||
|
||||
@lazyproperty
|
||||
def system_users_amount(self):
|
||||
return self.system_users.count()
|
|
@ -1,39 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.utils import lazyproperty
|
||||
from .base import BasePermission
|
||||
|
||||
__all__ = [
|
||||
'K8sAppPermission',
|
||||
]
|
||||
|
||||
|
||||
class K8sAppPermission(BasePermission):
|
||||
k8s_apps = models.ManyToManyField(
|
||||
'applications.K8sApp', related_name='granted_by_permissions',
|
||||
blank=True, verbose_name=_("KubernetesApp")
|
||||
)
|
||||
system_users = models.ManyToManyField(
|
||||
'assets.SystemUser', related_name='granted_by_k8s_app_permissions',
|
||||
verbose_name=_("System user")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
unique_together = [('org_id', 'name')]
|
||||
verbose_name = _('KubernetesApp permission')
|
||||
ordering = ('name',)
|
||||
|
||||
def get_all_k8s_apps(self):
|
||||
return self.k8s_apps.all()
|
||||
|
||||
@lazyproperty
|
||||
def k8s_apps_amount(self):
|
||||
return self.k8s_apps.count()
|
||||
|
||||
@lazyproperty
|
||||
def system_users_amount(self):
|
||||
return self.system_users.count()
|
|
@ -1,36 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.utils import lazyproperty
|
||||
from .base import BasePermission
|
||||
|
||||
__all__ = [
|
||||
'RemoteAppPermission',
|
||||
]
|
||||
|
||||
|
||||
class RemoteAppPermission(BasePermission):
|
||||
remote_apps = models.ManyToManyField('applications.RemoteApp', related_name='granted_by_permissions', blank=True, verbose_name=_("RemoteApp"))
|
||||
system_users = models.ManyToManyField('assets.SystemUser', related_name='granted_by_remote_app_permissions', verbose_name=_("System user"))
|
||||
|
||||
class Meta:
|
||||
unique_together = [('org_id', 'name')]
|
||||
verbose_name = _('RemoteApp permission')
|
||||
ordering = ('name',)
|
||||
|
||||
def get_all_remote_apps(self):
|
||||
return set(self.remote_apps.all())
|
||||
|
||||
@property
|
||||
def all_remote_apps(self):
|
||||
return self.remote_apps.all()
|
||||
|
||||
@lazyproperty
|
||||
def remote_apps_amount(self):
|
||||
return self.remote_apps.count()
|
||||
|
||||
@lazyproperty
|
||||
def system_users_amount(self):
|
||||
return self.system_users.count()
|
|
@ -3,12 +3,3 @@
|
|||
from .asset import *
|
||||
from .application import *
|
||||
from .system_user_permission import *
|
||||
|
||||
# TODO: 删除
|
||||
from .remote_app_permission import *
|
||||
from .remote_app_permission_relation import *
|
||||
from .database_app_permission import *
|
||||
from .database_app_permission_relation import *
|
||||
from .base import *
|
||||
from .k8s_app_permission import *
|
||||
from .k8s_app_permission_relation import *
|
||||
|
|
|
@ -6,10 +6,11 @@ from django.utils.translation import ugettext_lazy as _
|
|||
|
||||
from assets.models import SystemUser
|
||||
from applications.models import Application
|
||||
from applications.serializers.attrs import get_attrs_field_dynamic_mapping_rules
|
||||
from common.drf.fields import DynamicMappingField
|
||||
|
||||
__all__ = [
|
||||
'ApplicationGrantedSerializer',
|
||||
'ApplicationSystemUserSerializer'
|
||||
'ApplicationGrantedSerializer', 'ApplicationSystemUserSerializer'
|
||||
]
|
||||
|
||||
|
||||
|
@ -32,6 +33,7 @@ class ApplicationGrantedSerializer(serializers.ModelSerializer):
|
|||
"""
|
||||
category_display = serializers.ReadOnlyField(source='get_category_display', label=_('Category'))
|
||||
type_display = serializers.ReadOnlyField(source='get_type_display', label=_('Type'))
|
||||
attrs = DynamicMappingField(mapping_rules=get_attrs_field_dynamic_mapping_rules())
|
||||
|
||||
class Meta:
|
||||
model = Application
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
from rest_framework import serializers
|
||||
|
||||
|
||||
class PermissionAllUserSerializer(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,67 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
from django.db.models import Count
|
||||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.drf.serializers import AdaptedBulkListSerializer
|
||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
from .. import models
|
||||
|
||||
__all__ = [
|
||||
'DatabaseAppPermissionSerializer', 'DatabaseAppPermissionListSerializer'
|
||||
]
|
||||
|
||||
|
||||
class AmountMixin:
|
||||
@classmethod
|
||||
def setup_eager_loading(cls, queryset):
|
||||
""" Perform necessary eager loading of data. """
|
||||
queryset = queryset.annotate(
|
||||
users_amount=Count('users', distinct=True), user_groups_amount=Count('user_groups', distinct=True),
|
||||
database_apps_amount=Count('database_apps', distinct=True),
|
||||
system_users_amount=Count('system_users', distinct=True)
|
||||
)
|
||||
return queryset
|
||||
|
||||
|
||||
class DatabaseAppPermissionSerializer(AmountMixin, BulkOrgResourceModelSerializer):
|
||||
class Meta:
|
||||
model = models.DatabaseAppPermission
|
||||
list_serializer_class = AdaptedBulkListSerializer
|
||||
fields = [
|
||||
'id', 'name', 'users', 'user_groups', 'database_apps', 'system_users',
|
||||
'comment', 'is_active', 'date_start', 'date_expired', 'is_valid',
|
||||
'created_by', 'date_created', 'users_amount', 'user_groups_amount',
|
||||
'database_apps_amount', 'system_users_amount',
|
||||
]
|
||||
read_only_fields = [
|
||||
'created_by', 'date_created', 'users_amount', 'user_groups_amount',
|
||||
'database_apps_amount', 'system_users_amount',
|
||||
]
|
||||
extra_kwargs = {
|
||||
'is_valid': {'label': _('Is valid')},
|
||||
'users_amount': {'label': _('Users amount')},
|
||||
'user_groups_amount': {'label': _('User groups amount')},
|
||||
'system_users_amount': {'label': _('System users amount')},
|
||||
'database_apps_amount': {'label': _('Database apps amount')},
|
||||
}
|
||||
|
||||
|
||||
class DatabaseAppPermissionListSerializer(AmountMixin, BulkOrgResourceModelSerializer):
|
||||
is_expired = serializers.BooleanField()
|
||||
|
||||
class Meta:
|
||||
model = models.DatabaseAppPermission
|
||||
fields = [
|
||||
'id', 'name', 'comment', 'is_active', 'users_amount', 'user_groups_amount',
|
||||
'date_start', 'date_expired', 'is_valid', 'database_apps_amount', 'system_users_amount',
|
||||
'created_by', 'date_created', 'is_expired'
|
||||
]
|
||||
extra_kwargs = {
|
||||
'is_valid': {'label': _('Is valid')},
|
||||
'users_amount': {'label': _('Users amount')},
|
||||
'user_groups_amount': {'label': _('User groups amount')},
|
||||
'system_users_amount': {'label': _('System users amount')},
|
||||
'database_apps_amount': {'label': _('Database apps amount')},
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
from perms.serializers.base import PermissionAllUserSerializer
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.mixins import BulkSerializerMixin
|
||||
from common.drf.serializers import AdaptedBulkListSerializer
|
||||
|
||||
from .. import models
|
||||
|
||||
__all__ = [
|
||||
'DatabaseAppPermissionUserRelationSerializer',
|
||||
'DatabaseAppPermissionUserGroupRelationSerializer',
|
||||
'DatabaseAppPermissionAllUserSerializer',
|
||||
'DatabaseAppPermissionDatabaseAppRelationSerializer',
|
||||
'DatabaseAppPermissionAllDatabaseAppSerializer',
|
||||
'DatabaseAppPermissionSystemUserRelationSerializer',
|
||||
]
|
||||
|
||||
|
||||
class RelationMixin(BulkSerializerMixin, serializers.Serializer):
|
||||
databaseapppermission_display = serializers.ReadOnlyField()
|
||||
|
||||
def get_field_names(self, declared_fields, info):
|
||||
fields = super().get_field_names(declared_fields, info)
|
||||
fields.extend(['databaseapppermission', "databaseapppermission_display"])
|
||||
return fields
|
||||
|
||||
class Meta:
|
||||
list_serializer_class = AdaptedBulkListSerializer
|
||||
|
||||
|
||||
class DatabaseAppPermissionUserRelationSerializer(RelationMixin, serializers.ModelSerializer):
|
||||
user_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta(RelationMixin.Meta):
|
||||
model = models.DatabaseAppPermission.users.through
|
||||
fields = [
|
||||
'id', 'user', 'user_display',
|
||||
]
|
||||
|
||||
|
||||
class DatabaseAppPermissionUserGroupRelationSerializer(RelationMixin, serializers.ModelSerializer):
|
||||
usergroup_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta(RelationMixin.Meta):
|
||||
model = models.DatabaseAppPermission.user_groups.through
|
||||
fields = [
|
||||
'id', 'usergroup', "usergroup_display",
|
||||
]
|
||||
|
||||
|
||||
class DatabaseAppPermissionAllUserSerializer(PermissionAllUserSerializer):
|
||||
class Meta(PermissionAllUserSerializer.Meta):
|
||||
pass
|
||||
|
||||
|
||||
class DatabaseAppPermissionDatabaseAppRelationSerializer(RelationMixin, serializers.ModelSerializer):
|
||||
databaseapp_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta(RelationMixin.Meta):
|
||||
model = models.DatabaseAppPermission.database_apps.through
|
||||
fields = [
|
||||
'id', "databaseapp", "databaseapp_display",
|
||||
]
|
||||
|
||||
|
||||
class DatabaseAppPermissionAllDatabaseAppSerializer(serializers.Serializer):
|
||||
databaseapp = serializers.UUIDField(read_only=True, source='id')
|
||||
databaseapp_display = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
only_fields = ['id', 'name']
|
||||
|
||||
@staticmethod
|
||||
def get_databaseapp_display(obj):
|
||||
return str(obj)
|
||||
|
||||
|
||||
class DatabaseAppPermissionSystemUserRelationSerializer(RelationMixin, serializers.ModelSerializer):
|
||||
systemuser_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta(RelationMixin.Meta):
|
||||
model = models.DatabaseAppPermission.system_users.through
|
||||
fields = [
|
||||
'id', 'systemuser', 'systemuser_display'
|
||||
]
|
|
@ -1,65 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
from django.db.models import Count
|
||||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
from .. import models
|
||||
|
||||
__all__ = [
|
||||
'K8sAppPermissionSerializer', 'K8sAppPermissionListSerializer'
|
||||
]
|
||||
|
||||
|
||||
class AmountMixin:
|
||||
@classmethod
|
||||
def setup_eager_loading(cls, queryset):
|
||||
""" Perform necessary eager loading of data. """
|
||||
queryset = queryset.annotate(
|
||||
users_amount=Count('users', distinct=True), user_groups_amount=Count('user_groups', distinct=True),
|
||||
k8s_apps_amount=Count('k8s_apps', distinct=True),
|
||||
system_users_amount=Count('system_users', distinct=True)
|
||||
)
|
||||
return queryset
|
||||
|
||||
|
||||
class K8sAppPermissionSerializer(AmountMixin, BulkOrgResourceModelSerializer):
|
||||
class Meta:
|
||||
model = models.K8sAppPermission
|
||||
fields = [
|
||||
'id', 'name', 'users', 'user_groups', 'k8s_apps', 'system_users',
|
||||
'comment', 'is_active', 'date_start', 'date_expired', 'is_valid',
|
||||
'created_by', 'date_created', 'users_amount', 'user_groups_amount',
|
||||
'k8s_apps_amount', 'system_users_amount',
|
||||
]
|
||||
read_only_fields = [
|
||||
'created_by', 'date_created', 'users_amount', 'user_groups_amount',
|
||||
'k8s_apps_amount', 'system_users_amount', 'id'
|
||||
]
|
||||
extra_kwargs = {
|
||||
'is_valid': {'label': _('Is valid')},
|
||||
'users_amount': {'label': _('Users amount')},
|
||||
'user_groups_amount': {'label': _('User groups amount')},
|
||||
'system_users_amount': {'label': _('System users amount')},
|
||||
'database_apps_amount': {'label': _('Database apps amount')},
|
||||
}
|
||||
|
||||
|
||||
class K8sAppPermissionListSerializer(AmountMixin, BulkOrgResourceModelSerializer):
|
||||
is_expired = serializers.BooleanField()
|
||||
|
||||
class Meta:
|
||||
model = models.K8sAppPermission
|
||||
fields = [
|
||||
'id', 'name', 'comment', 'is_active', 'users_amount', 'user_groups_amount',
|
||||
'date_start', 'date_expired', 'is_valid', 'k8s_apps_amount', 'system_users_amount',
|
||||
'created_by', 'date_created', 'is_expired'
|
||||
]
|
||||
extra_kwargs = {
|
||||
'is_valid': {'label': _('Is valid')},
|
||||
'users_amount': {'label': _('Users amount')},
|
||||
'user_groups_amount': {'label': _('User groups amount')},
|
||||
'system_users_amount': {'label': _('System users amount')},
|
||||
'k8s_apps_amount': {'label': _('K8s apps amount')},
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
from perms.serializers.base import PermissionAllUserSerializer
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.drf.serializers import BulkModelSerializer
|
||||
|
||||
from .. import models
|
||||
|
||||
|
||||
class K8sAppPermissionUserRelationSerializer(BulkModelSerializer):
|
||||
user_display = serializers.ReadOnlyField()
|
||||
k8sapppermission_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = models.K8sAppPermission.users.through
|
||||
fields = [
|
||||
'id', 'user', 'user_display', 'k8sapppermission',
|
||||
'k8sapppermission_display'
|
||||
]
|
||||
|
||||
|
||||
class K8sAppPermissionUserGroupRelationSerializer(BulkModelSerializer):
|
||||
usergroup_display = serializers.ReadOnlyField()
|
||||
k8sapppermission_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = models.K8sAppPermission.user_groups.through
|
||||
fields = [
|
||||
'id', 'usergroup', 'usergroup_display', 'k8sapppermission',
|
||||
'k8sapppermission_display'
|
||||
]
|
||||
|
||||
|
||||
class K8sAppPermissionAllUserSerializer(PermissionAllUserSerializer):
|
||||
class Meta(PermissionAllUserSerializer.Meta):
|
||||
pass
|
||||
|
||||
|
||||
class K8sAppPermissionK8sAppRelationSerializer(BulkModelSerializer):
|
||||
k8sapp_display = serializers.ReadOnlyField()
|
||||
k8sapppermission_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = models.K8sAppPermission.k8s_apps.through
|
||||
fields = [
|
||||
'id', "k8sapp", "k8sapp_display", 'k8sapppermission',
|
||||
'k8sapppermission_display'
|
||||
]
|
||||
|
||||
|
||||
class K8sAppPermissionAllK8sAppSerializer(serializers.Serializer):
|
||||
k8sapp = serializers.UUIDField(read_only=True, source='id')
|
||||
k8sapp_display = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
only_fields = ['id', 'name']
|
||||
|
||||
@staticmethod
|
||||
def get_k8sapp_display(obj):
|
||||
return str(obj)
|
||||
|
||||
|
||||
class K8sAppPermissionSystemUserRelationSerializer(BulkModelSerializer):
|
||||
systemuser_display = serializers.ReadOnlyField()
|
||||
k8sapppermission_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = models.K8sAppPermission.system_users.through
|
||||
fields = [
|
||||
'id', 'systemuser', 'systemuser_display', 'k8sapppermission',
|
||||
'k8sapppermission_display'
|
||||
]
|
|
@ -1,62 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
from rest_framework import serializers
|
||||
from django.db.models import Count
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.drf.serializers import AdaptedBulkListSerializer
|
||||
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
|
||||
from ..models import RemoteAppPermission
|
||||
|
||||
|
||||
__all__ = [
|
||||
'RemoteAppPermissionSerializer',
|
||||
'RemoteAppPermissionUpdateUserSerializer',
|
||||
'RemoteAppPermissionUpdateRemoteAppSerializer',
|
||||
]
|
||||
|
||||
|
||||
class RemoteAppPermissionSerializer(BulkOrgResourceModelSerializer):
|
||||
class Meta:
|
||||
model = RemoteAppPermission
|
||||
list_serializer_class = AdaptedBulkListSerializer
|
||||
mini_fields = ['id', 'name']
|
||||
small_fields = mini_fields + [
|
||||
'comment', 'is_active', 'date_start', 'date_expired', 'is_valid',
|
||||
'created_by', 'date_created'
|
||||
]
|
||||
m2m_fields = [
|
||||
'users', 'user_groups', 'remote_apps', 'system_users',
|
||||
'users_amount', 'user_groups_amount', 'remote_apps_amount',
|
||||
'system_users_amount'
|
||||
]
|
||||
fields = small_fields + m2m_fields
|
||||
read_only_fields = ['created_by', 'date_created']
|
||||
extra_kwargs = {
|
||||
'is_valid': {'label': _('Is valid')},
|
||||
'users_amount': {'label': _('Users amount')},
|
||||
'user_groups_amount': {'label': _('User groups amount')},
|
||||
'system_users_amount': {'label': _('System users amount')},
|
||||
'remote_apps_amount': {'label': _('Remote apps amount')},
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def setup_eager_loading(cls, queryset):
|
||||
""" Perform necessary eager loading of data. """
|
||||
queryset = queryset.annotate(
|
||||
users_amount=Count('users', distinct=True), user_groups_amount=Count('user_groups', distinct=True),
|
||||
remote_apps_amount=Count('remote_apps', distinct=True), system_users_amount=Count('system_users', distinct=True)
|
||||
)
|
||||
return queryset
|
||||
|
||||
|
||||
class RemoteAppPermissionUpdateUserSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = RemoteAppPermission
|
||||
fields = ['id', 'users']
|
||||
|
||||
|
||||
class RemoteAppPermissionUpdateRemoteAppSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = RemoteAppPermission
|
||||
fields = ['id', 'remote_apps']
|
|
@ -1,49 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
from rest_framework import serializers
|
||||
|
||||
from common.drf.serializers import AdaptedBulkListSerializer
|
||||
from ..models import RemoteAppPermission
|
||||
|
||||
|
||||
__all__ = [
|
||||
'RemoteAppPermissionRemoteAppRelationSerializer',
|
||||
'RemoteAppPermissionAllRemoteAppSerializer',
|
||||
'RemoteAppPermissionUserRelationSerializer',
|
||||
]
|
||||
|
||||
|
||||
class RemoteAppPermissionRemoteAppRelationSerializer(serializers.ModelSerializer):
|
||||
remoteapp_display = serializers.ReadOnlyField()
|
||||
remoteapppermission_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = RemoteAppPermission.remote_apps.through
|
||||
list_serializer_class = AdaptedBulkListSerializer
|
||||
fields = [
|
||||
'id', 'remoteapp', 'remoteapp_display', 'remoteapppermission', 'remoteapppermission_display'
|
||||
]
|
||||
|
||||
|
||||
class RemoteAppPermissionAllRemoteAppSerializer(serializers.Serializer):
|
||||
remoteapp = serializers.UUIDField(read_only=True, source='id')
|
||||
remoteapp_display = serializers.SerializerMethodField()
|
||||
|
||||
class Meta:
|
||||
only_fields = ['id', 'name']
|
||||
|
||||
@staticmethod
|
||||
def get_remoteapp_display(obj):
|
||||
return str(obj)
|
||||
|
||||
|
||||
class RemoteAppPermissionUserRelationSerializer(serializers.ModelSerializer):
|
||||
user_display = serializers.ReadOnlyField()
|
||||
remoteapppermission_display = serializers.ReadOnlyField()
|
||||
|
||||
class Meta:
|
||||
model = RemoteAppPermission.users.through
|
||||
list_serializer_class = AdaptedBulkListSerializer
|
||||
fields = [
|
||||
'id', 'user', 'user_display', 'remoteapppermission', 'remoteapppermission_display'
|
||||
]
|
|
@ -7,11 +7,11 @@ from perms.tasks import create_rebuild_user_tree_task, \
|
|||
create_rebuild_user_tree_task_by_related_nodes_or_assets
|
||||
from users.models import User, UserGroup
|
||||
from assets.models import Asset, SystemUser
|
||||
from applications.models import Application, Category
|
||||
from applications.models import Application
|
||||
from common.utils import get_logger
|
||||
from common.exceptions import M2MReverseNotAllowed
|
||||
from common.const.signals import POST_ADD, POST_REMOVE, POST_CLEAR
|
||||
from .models import AssetPermission, RemoteAppPermission, ApplicationPermission
|
||||
from .models import AssetPermission, ApplicationPermission
|
||||
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
@ -187,51 +187,6 @@ def on_asset_permission_user_groups_changed(instance, action, pk_set, model,
|
|||
system_user.groups.add(*tuple(groups))
|
||||
|
||||
|
||||
@receiver(m2m_changed, sender=RemoteAppPermission.system_users.through)
|
||||
def on_remote_app_permission_system_users_changed(sender, instance=None,
|
||||
action='', reverse=False, **kwargs):
|
||||
if action != POST_ADD or reverse:
|
||||
return
|
||||
system_users = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
|
||||
logger.debug("Remote app permission system_users change signal received")
|
||||
assets = instance.remote_apps.all().values_list('asset__id', flat=True)
|
||||
users = instance.users.all().values_list('id', flat=True)
|
||||
groups = instance.user_groups.all().values_list('id', flat=True)
|
||||
for system_user in system_users:
|
||||
system_user.assets.add(*tuple(assets))
|
||||
if system_user.username_same_with_user:
|
||||
system_user.groups.add(*tuple(groups))
|
||||
system_user.users.add(*tuple(users))
|
||||
|
||||
|
||||
@receiver(m2m_changed, sender=RemoteAppPermission.users.through)
|
||||
def on_remoteapps_permission_users_changed(sender, instance=None, action='',
|
||||
reverse=False, **kwargs):
|
||||
if action != POST_ADD and reverse:
|
||||
return
|
||||
logger.debug("Asset permission users change signal received")
|
||||
users = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
|
||||
system_users = instance.system_users.all()
|
||||
|
||||
for system_user in system_users:
|
||||
if system_user.username_same_with_user:
|
||||
system_user.users.add(*tuple(users))
|
||||
|
||||
|
||||
@receiver(m2m_changed, sender=RemoteAppPermission.user_groups.through)
|
||||
def on_remoteapps_permission_user_groups_changed(sender, instance=None, action='',
|
||||
reverse=False, **kwargs):
|
||||
if action != POST_ADD and reverse:
|
||||
return
|
||||
logger.debug("Asset permission user groups change signal received")
|
||||
groups = kwargs['model'].objects.filter(pk__in=kwargs['pk_set'])
|
||||
system_users = instance.system_users.all()
|
||||
|
||||
for system_user in system_users:
|
||||
if system_user.username_same_with_user:
|
||||
system_user.groups.add(*tuple(groups))
|
||||
|
||||
|
||||
@receiver(m2m_changed, sender=Asset.nodes.through)
|
||||
def on_node_asset_change(action, instance, reverse, pk_set, **kwargs):
|
||||
if not need_rebuild_mapping_node(action):
|
||||
|
@ -249,7 +204,7 @@ def on_node_asset_change(action, instance, reverse, pk_set, **kwargs):
|
|||
|
||||
@receiver(m2m_changed, sender=ApplicationPermission.system_users.through)
|
||||
def on_application_permission_system_users_changed(sender, instance: ApplicationPermission, action, reverse, pk_set, **kwargs):
|
||||
if instance.category != Category.remote_app:
|
||||
if not instance.category_remote_app:
|
||||
return
|
||||
|
||||
if reverse:
|
||||
|
@ -277,7 +232,7 @@ def on_application_permission_system_users_changed(sender, instance: Application
|
|||
|
||||
@receiver(m2m_changed, sender=ApplicationPermission.users.through)
|
||||
def on_application_permission_users_changed(sender, instance, action, reverse, pk_set, **kwargs):
|
||||
if instance.category != Category.remote_app:
|
||||
if not instance.category_remote_app:
|
||||
return
|
||||
|
||||
if reverse:
|
||||
|
@ -297,7 +252,7 @@ def on_application_permission_users_changed(sender, instance, action, reverse, p
|
|||
|
||||
@receiver(m2m_changed, sender=ApplicationPermission.user_groups.through)
|
||||
def on_application_permission_user_groups_changed(sender, instance, action, reverse, pk_set, **kwargs):
|
||||
if instance.category != Category.remote_app:
|
||||
if not instance.category_remote_app:
|
||||
return
|
||||
|
||||
if reverse:
|
||||
|
@ -317,7 +272,7 @@ def on_application_permission_user_groups_changed(sender, instance, action, reve
|
|||
|
||||
@receiver(m2m_changed, sender=ApplicationPermission.applications.through)
|
||||
def on_application_permission_applications_changed(sender, instance, action, reverse, pk_set, **kwargs):
|
||||
if instance.category != Category.remote_app:
|
||||
if not instance.category_remote_app:
|
||||
return
|
||||
|
||||
if reverse:
|
||||
|
|
|
@ -4,11 +4,7 @@ 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 .remote_app_permission import remote_app_permission_urlpatterns
|
||||
from .database_app_permission import database_app_permission_urlpatterns
|
||||
from .system_user_permission import system_users_permission_urlpatterns
|
||||
from .k8s_app_permission import k8s_app_permission_urlpatterns
|
||||
|
||||
app_name = 'perms'
|
||||
|
||||
|
@ -16,10 +12,8 @@ old_version_urlpatterns = [
|
|||
re_path('(?P<resource>user|user-group|asset-permission|remote-app-permission)/.*', capi.redirect_plural_name_api)
|
||||
]
|
||||
|
||||
urlpatterns = asset_permission_urlpatterns + \
|
||||
application_permission_urlpatterns + \
|
||||
remote_app_permission_urlpatterns + \
|
||||
database_app_permission_urlpatterns + \
|
||||
k8s_app_permission_urlpatterns + \
|
||||
old_version_urlpatterns + \
|
||||
system_users_permission_urlpatterns
|
||||
urlpatterns = []
|
||||
urlpatterns += asset_permission_urlpatterns
|
||||
urlpatterns += application_permission_urlpatterns
|
||||
urlpatterns += system_users_permission_urlpatterns
|
||||
urlpatterns += old_version_urlpatterns
|
||||
|
|
|
@ -1,47 +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('database-app-permissions', api.DatabaseAppPermissionViewSet, 'database-app-permission')
|
||||
router.register('database-app-permissions-users-relations', api.DatabaseAppPermissionUserRelationViewSet, 'database-app-permissions-users-relation')
|
||||
router.register('database-app-permissions-user-groups-relations', api.DatabaseAppPermissionUserGroupRelationViewSet, 'database-app-permissions-user-groups-relation')
|
||||
router.register('database-app-permissions-database-apps-relations', api.DatabaseAppPermissionDatabaseAppRelationViewSet, 'database-app-permissions-database-apps-relation')
|
||||
router.register('database-app-permissions-system-users-relations', api.DatabaseAppPermissionSystemUserRelationViewSet, 'database-app-permissions-system-users-relation')
|
||||
|
||||
user_permission_urlpatterns = [
|
||||
path('<uuid:pk>/database-apps/', api.UserGrantedDatabaseAppsApi.as_view(), name='user-database-apps'),
|
||||
path('database-apps/', api.UserGrantedDatabaseAppsApi.as_view(), name='my-database-apps'),
|
||||
|
||||
# DatabaseApps as tree
|
||||
path('<uuid:pk>/database-apps/tree/', api.UserGrantedDatabaseAppsAsTreeApi.as_view(), name='user-databases-apps-tree'),
|
||||
path('database-apps/tree/', api.UserGrantedDatabaseAppsAsTreeApi.as_view(), name='my-databases-apps-tree'),
|
||||
|
||||
path('<uuid:pk>/database-apps/<uuid:database_app_id>/system-users/', api.UserGrantedDatabaseAppSystemUsersApi.as_view(), name='user-database-app-system-users'),
|
||||
path('database-apps/<uuid:database_app_id>/system-users/', api.UserGrantedDatabaseAppSystemUsersApi.as_view(), name='user-database-app-system-users'),
|
||||
]
|
||||
|
||||
user_group_permission_urlpatterns = [
|
||||
path('<uuid:pk>/database-apps/', api.UserGroupGrantedDatabaseAppsApi.as_view(), name='user-group-database-apps'),
|
||||
]
|
||||
|
||||
permission_urlpatterns = [
|
||||
# 授权规则中授权的用户和数据库应用
|
||||
path('<uuid:pk>/users/all/', api.DatabaseAppPermissionAllUserListApi.as_view(), name='database-app-permission-all-users'),
|
||||
path('<uuid:pk>/database-apps/all/', api.DatabaseAppPermissionAllDatabaseAppListApi.as_view(), name='database-app-permission-all-database-apps'),
|
||||
|
||||
# 验证用户是否有某个数据库应用的权限
|
||||
path('user/validate/', api.ValidateUserDatabaseAppPermissionApi.as_view(), name='validate-user-database-app-permission'),
|
||||
]
|
||||
|
||||
database_app_permission_urlpatterns = [
|
||||
path('users/', include(user_permission_urlpatterns)),
|
||||
path('user-groups/', include(user_group_permission_urlpatterns)),
|
||||
path('database-app-permissions/', include(permission_urlpatterns))
|
||||
]
|
||||
|
||||
database_app_permission_urlpatterns += router.urls
|
|
@ -1,45 +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('k8s-app-permissions', api.K8sAppPermissionViewSet, 'k8s-app-permission')
|
||||
router.register('k8s-app-permissions-users-relations', api.K8sAppPermissionUserRelationViewSet, 'k8s-app-permissions-users-relation')
|
||||
router.register('k8s-app-permissions-user-groups-relations', api.K8sAppPermissionUserGroupRelationViewSet, 'k8s-app-permissions-user-groups-relation')
|
||||
router.register('k8s-app-permissions-k8s-apps-relations', api.K8sAppPermissionK8sAppRelationViewSet, 'k8s-app-permissions-k8s-apps-relation')
|
||||
router.register('k8s-app-permissions-system-users-relations', api.K8sAppPermissionSystemUserRelationViewSet, 'k8s-app-permissions-system-users-relation')
|
||||
|
||||
user_permission_urlpatterns = [
|
||||
path('<uuid:pk>/k8s-apps/', api.UserGrantedK8sAppsApi.as_view(), name='user-k8s-apps'),
|
||||
path('k8s-apps/', api.UserGrantedK8sAppsApi.as_view(), name='my-k8s-apps'),
|
||||
|
||||
# k8sApps as tree
|
||||
path('<uuid:pk>/k8s-apps/tree/', api.UserGrantedK8sAppsAsTreeApi.as_view(), name='user-k8ss-apps-tree'),
|
||||
path('k8s-apps/tree/', api.UserGrantedK8sAppsAsTreeApi.as_view(), name='my-k8ss-apps-tree'),
|
||||
|
||||
path('<uuid:pk>/k8s-apps/<uuid:k8s_app_id>/system-users/', api.UserGrantedK8sAppSystemUsersApi.as_view(), name='user-k8s-app-system-users'),
|
||||
path('k8s-apps/<uuid:k8s_app_id>/system-users/', api.UserGrantedK8sAppSystemUsersApi.as_view(), name='user-k8s-app-system-users'),
|
||||
]
|
||||
|
||||
user_group_permission_urlpatterns = [
|
||||
path('<uuid:pk>/k8s-apps/', api.UserGroupGrantedK8sAppsApi.as_view(), name='user-group-k8s-apps'),
|
||||
]
|
||||
|
||||
permission_urlpatterns = [
|
||||
path('<uuid:pk>/users/all/', api.K8sAppPermissionAllUserListApi.as_view(), name='k8s-app-permission-all-users'),
|
||||
path('<uuid:pk>/k8s-apps/all/', api.K8sAppPermissionAllK8sAppListApi.as_view(), name='k8s-app-permission-all-k8s-apps'),
|
||||
|
||||
path('user/validate/', api.ValidateUserK8sAppPermissionApi.as_view(), name='validate-user-k8s-app-permission'),
|
||||
]
|
||||
|
||||
k8s_app_permission_urlpatterns = [
|
||||
path('users/', include(user_permission_urlpatterns)),
|
||||
path('user-groups/', include(user_group_permission_urlpatterns)),
|
||||
path('k8s-app-permissions/', include(permission_urlpatterns))
|
||||
]
|
||||
|
||||
k8s_app_permission_urlpatterns += router.urls
|
|
@ -1,43 +0,0 @@
|
|||
# coding:utf-8
|
||||
|
||||
from django.urls import path
|
||||
from rest_framework_bulk.routes import BulkRouter
|
||||
from .. import api
|
||||
|
||||
|
||||
router = BulkRouter()
|
||||
router.register('remote-app-permissions', api.RemoteAppPermissionViewSet, 'remote-app-permission')
|
||||
router.register('remote-app-permissions-users-relations', api.RemoteAppPermissionUserRelationViewSet, 'remote-app-permissions-users-relation')
|
||||
router.register('remote-app-permissions-remote-apps-relations', api.RemoteAppPermissionRemoteAppRelationViewSet, 'remote-app-permissions-remote-apps-relation')
|
||||
|
||||
|
||||
remote_app_permission_urlpatterns = [
|
||||
# 查询用户授权的RemoteApp
|
||||
path('users/<uuid:pk>/remote-apps/', api.UserGrantedRemoteAppsApi.as_view(), name='user-remote-apps'),
|
||||
path('users/remote-apps/', api.UserGrantedRemoteAppsApi.as_view(), name='my-remote-apps'),
|
||||
|
||||
# 获取用户授权的RemoteApp树
|
||||
path('users/<uuid:pk>/remote-apps/tree/', api.UserGrantedRemoteAppsAsTreeApi.as_view(), name='user-remote-apps-as-tree'),
|
||||
path('users/remote-apps/tree/', api.UserGrantedRemoteAppsAsTreeApi.as_view(), name='my-remote-apps-as-tree'),
|
||||
|
||||
# 查询用户组授权的RemoteApp
|
||||
path('user-groups/<uuid:pk>/remote-apps/', api.UserGroupGrantedRemoteAppsApi.as_view(), name='user-group-remote-apps'),
|
||||
|
||||
# RemoteApp System users
|
||||
path('users/<uuid:pk>/remote-apps/<uuid:remote_app_id>/system-users/', api.UserGrantedRemoteAppSystemUsersApi.as_view(), name='user-remote-app-system-users'),
|
||||
path('users/remote-apps/<uuid:remote_app_id>/system-users/', api.UserGrantedRemoteAppSystemUsersApi.as_view(), name='my-remote-app-system-users'),
|
||||
|
||||
# 校验用户对RemoteApp的权限
|
||||
path('remote-app-permissions/user/validate/', api.ValidateUserRemoteAppPermissionApi.as_view(), name='validate-user-remote-app-permission'),
|
||||
|
||||
# 用户和RemoteApp变更
|
||||
path('remote-app-permissions/<uuid:pk>/users/add/', api.RemoteAppPermissionAddUserApi.as_view(), name='remote-app-permission-add-user'),
|
||||
path('remote-app-permissions/<uuid:pk>/users/remove/', api.RemoteAppPermissionRemoveUserApi.as_view(), name='remote-app-permission-remove-user'),
|
||||
path('remote-app-permissions/<uuid:pk>/remote-apps/remove/', api.RemoteAppPermissionRemoveRemoteAppApi.as_view(), name='remote-app-permission-remove-remote-app'),
|
||||
path('remote-app-permissions/<uuid:pk>/remote-apps/add/', api.RemoteAppPermissionAddRemoteAppApi.as_view(), name='remote-app-permission-add-remote-app'),
|
||||
|
||||
path('remote-app-permissions/<uuid:pk>/remote-apps/all/', api.RemoteAppPermissionAllRemoteAppListApi.as_view(), name='remote-app-permission-all-remote-apps'),
|
||||
path('remote-app-permissions/<uuid:pk>/users/all/', api.RemoteAppPermissionAllUserListApi.as_view(), name='remote-app-permission-all-users'),
|
||||
]
|
||||
|
||||
remote_app_permission_urlpatterns += router.urls
|
|
@ -1,5 +0,0 @@
|
|||
# coding:utf-8
|
||||
app_name = 'perms'
|
||||
|
||||
urlpatterns = [
|
||||
]
|
|
@ -3,8 +3,3 @@
|
|||
|
||||
from .asset import *
|
||||
from .application import *
|
||||
|
||||
# TODO: 删除
|
||||
from .remote_app_permission import *
|
||||
from .database_app_permission import *
|
||||
from .k8s_app_permission import *
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.db.models import Q
|
||||
|
||||
from orgs.utils import set_to_root_org
|
||||
from ..models import DatabaseAppPermission
|
||||
from common.tree import TreeNode
|
||||
from applications.models import DatabaseApp
|
||||
from assets.models import SystemUser
|
||||
|
||||
|
||||
__all__ = [
|
||||
'DatabaseAppPermissionUtil',
|
||||
'construct_database_apps_tree_root',
|
||||
'parse_database_app_to_tree_node'
|
||||
]
|
||||
|
||||
|
||||
def get_user_database_app_permissions(user, include_group=True):
|
||||
if include_group:
|
||||
groups = user.groups.all()
|
||||
arg = Q(users=user) | Q(user_groups__in=groups)
|
||||
else:
|
||||
arg = Q(users=user)
|
||||
return DatabaseAppPermission.objects.all().valid().filter(arg)
|
||||
|
||||
|
||||
def get_user_group_database_app_permission(user_group):
|
||||
return DatabaseAppPermission.objects.all().valid().filter(
|
||||
user_groups=user_group
|
||||
)
|
||||
|
||||
|
||||
class DatabaseAppPermissionUtil:
|
||||
get_permissions_map = {
|
||||
'User': get_user_database_app_permissions,
|
||||
'UserGroup': get_user_group_database_app_permission
|
||||
}
|
||||
|
||||
def __init__(self, obj):
|
||||
self.object = obj
|
||||
self.change_org_if_need()
|
||||
|
||||
@staticmethod
|
||||
def change_org_if_need():
|
||||
set_to_root_org()
|
||||
|
||||
@property
|
||||
def permissions(self):
|
||||
obj_class = self.object.__class__.__name__
|
||||
func = self.get_permissions_map[obj_class]
|
||||
_permissions = func(self.object)
|
||||
return _permissions
|
||||
|
||||
def get_database_apps(self):
|
||||
database_apps = DatabaseApp.objects.filter(
|
||||
granted_by_permissions__in=self.permissions
|
||||
).distinct()
|
||||
return database_apps
|
||||
|
||||
def get_database_app_system_users(self, database_app):
|
||||
queryset = self.permissions
|
||||
kwargs = {'database_apps': database_app}
|
||||
queryset = queryset.filter(**kwargs)
|
||||
system_users_ids = queryset.values_list('system_users', flat=True)
|
||||
system_users_ids = system_users_ids.distinct()
|
||||
system_users = SystemUser.objects.filter(id__in=system_users_ids)
|
||||
system_users = system_users.order_by('-priority')
|
||||
return system_users
|
||||
|
||||
|
||||
def construct_database_apps_tree_root(amount):
|
||||
tree_root = {
|
||||
'id': 'ID_DATABASE_APP_ROOT',
|
||||
'name': '{} ({})'.format(_('DatabaseApp'), amount),
|
||||
'title': 'DatabaseApp',
|
||||
'pId': '',
|
||||
'open': False,
|
||||
'isParent': True,
|
||||
'iconSkin': '',
|
||||
'meta': {'type': 'database_app'}
|
||||
}
|
||||
return TreeNode(**tree_root)
|
||||
|
||||
|
||||
def parse_database_app_to_tree_node(parent, database_app):
|
||||
pid = parent.id if parent else ''
|
||||
tree_node = {
|
||||
'id': database_app.id,
|
||||
'name': database_app.name,
|
||||
'title': database_app.name,
|
||||
'pId': pid,
|
||||
'open': False,
|
||||
'isParent': False,
|
||||
'iconSkin': 'file',
|
||||
'meta': {'type': 'database_app'}
|
||||
}
|
||||
return TreeNode(**tree_node)
|
|
@ -1,93 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.db.models import Q
|
||||
|
||||
from orgs.utils import set_to_root_org
|
||||
from ..models import K8sAppPermission
|
||||
from common.tree import TreeNode
|
||||
from applications.models import K8sApp
|
||||
from assets.models import SystemUser
|
||||
|
||||
|
||||
def get_user_k8s_app_permissions(user, include_group=True):
|
||||
if include_group:
|
||||
groups = user.groups.all()
|
||||
arg = Q(users=user) | Q(user_groups__in=groups)
|
||||
else:
|
||||
arg = Q(users=user)
|
||||
return K8sAppPermission.objects.all().valid().filter(arg)
|
||||
|
||||
|
||||
def get_user_group_k8s_app_permission(user_group):
|
||||
return K8sAppPermission.objects.all().valid().filter(
|
||||
user_groups=user_group
|
||||
)
|
||||
|
||||
|
||||
class K8sAppPermissionUtil:
|
||||
get_permissions_map = {
|
||||
'User': get_user_k8s_app_permissions,
|
||||
'UserGroup': get_user_group_k8s_app_permission
|
||||
}
|
||||
|
||||
def __init__(self, obj):
|
||||
self.object = obj
|
||||
self.change_org_if_need()
|
||||
|
||||
@staticmethod
|
||||
def change_org_if_need():
|
||||
set_to_root_org()
|
||||
|
||||
@property
|
||||
def permissions(self):
|
||||
obj_class = self.object.__class__.__name__
|
||||
func = self.get_permissions_map[obj_class]
|
||||
_permissions = func(self.object)
|
||||
return _permissions
|
||||
|
||||
def get_k8s_apps(self):
|
||||
k8s_apps = K8sApp.objects.filter(
|
||||
granted_by_permissions__in=self.permissions
|
||||
).distinct()
|
||||
return k8s_apps
|
||||
|
||||
def get_k8s_app_system_users(self, k8s_app):
|
||||
queryset = self.permissions
|
||||
kwargs = {'k8s_apps': k8s_app}
|
||||
queryset = queryset.filter(**kwargs)
|
||||
system_users_ids = queryset.values_list('system_users', flat=True)
|
||||
system_users_ids = system_users_ids.distinct()
|
||||
system_users = SystemUser.objects.filter(id__in=system_users_ids)
|
||||
system_users = system_users.order_by('-priority')
|
||||
return system_users
|
||||
|
||||
|
||||
def construct_k8s_apps_tree_root(amount):
|
||||
tree_root = {
|
||||
'id': 'ID_K8S_APP_ROOT',
|
||||
'name': '{} ({})'.format(_('KubernetesApp'), amount),
|
||||
'title': 'K8sApp',
|
||||
'pId': '',
|
||||
'open': False,
|
||||
'isParent': True,
|
||||
'iconSkin': '',
|
||||
'meta': {'type': 'k8s_app'}
|
||||
}
|
||||
return TreeNode(**tree_root)
|
||||
|
||||
|
||||
def parse_k8s_app_to_tree_node(parent, k8s_app):
|
||||
pid = parent.id if parent else ''
|
||||
tree_node = {
|
||||
'id': k8s_app.id,
|
||||
'name': k8s_app.name,
|
||||
'title': k8s_app.name,
|
||||
'pId': pid,
|
||||
'open': False,
|
||||
'isParent': False,
|
||||
'iconSkin': 'file',
|
||||
'meta': {'type': 'k8s_app'}
|
||||
}
|
||||
return TreeNode(**tree_node)
|
|
@ -1,99 +0,0 @@
|
|||
# coding: utf-8
|
||||
#
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.db.models import Q
|
||||
|
||||
from common.tree import TreeNode
|
||||
from orgs.utils import set_to_root_org
|
||||
|
||||
from ..models import RemoteAppPermission
|
||||
from ..hands import RemoteApp, SystemUser
|
||||
|
||||
__all__ = [
|
||||
'RemoteAppPermissionUtil',
|
||||
'construct_remote_apps_tree_root',
|
||||
'parse_remote_app_to_tree_node',
|
||||
]
|
||||
|
||||
|
||||
def get_user_remote_app_permissions(user, include_group=True):
|
||||
if include_group:
|
||||
groups = user.groups.all()
|
||||
arg = Q(users=user) | Q(user_groups__in=groups)
|
||||
else:
|
||||
arg = Q(users=user)
|
||||
return RemoteAppPermission.objects.all().valid().filter(arg)
|
||||
|
||||
|
||||
def get_user_group_remote_app_permissions(user_group):
|
||||
return RemoteAppPermission.objects.all().valid().filter(
|
||||
user_groups=user_group
|
||||
)
|
||||
|
||||
|
||||
class RemoteAppPermissionUtil:
|
||||
get_permissions_map = {
|
||||
"User": get_user_remote_app_permissions,
|
||||
"UserGroup": get_user_group_remote_app_permissions,
|
||||
}
|
||||
|
||||
def __init__(self, obj):
|
||||
self.object = obj
|
||||
self.change_org_if_need()
|
||||
|
||||
@staticmethod
|
||||
def change_org_if_need():
|
||||
set_to_root_org()
|
||||
|
||||
@property
|
||||
def permissions(self):
|
||||
obj_class = self.object.__class__.__name__
|
||||
func = self.get_permissions_map[obj_class]
|
||||
_permissions = func(self.object)
|
||||
return _permissions
|
||||
|
||||
def get_remote_apps(self):
|
||||
remote_apps = RemoteApp.objects.filter(
|
||||
granted_by_permissions__in=self.permissions
|
||||
).distinct()
|
||||
return remote_apps
|
||||
|
||||
def get_remote_app_system_users(self, remote_app):
|
||||
queryset = self.permissions
|
||||
kwargs = {"remote_apps": remote_app}
|
||||
queryset = queryset.filter(**kwargs)
|
||||
system_users_ids = queryset.values_list('system_users', flat=True)
|
||||
system_users_ids = system_users_ids.distinct()
|
||||
system_users = SystemUser.objects.filter(id__in=system_users_ids)
|
||||
system_users = system_users.order_by('-priority')
|
||||
return system_users
|
||||
|
||||
|
||||
def construct_remote_apps_tree_root(amount):
|
||||
tree_root = {
|
||||
'id': 'ID_REMOTE_APP_ROOT',
|
||||
'name': '{} ({})'.format(_('RemoteApp'), amount),
|
||||
'title': 'RemoteApp',
|
||||
'pId': '',
|
||||
'open': False,
|
||||
'isParent': True,
|
||||
'iconSkin': '',
|
||||
'meta': {'type': 'remote_app'}
|
||||
}
|
||||
return TreeNode(**tree_root)
|
||||
|
||||
|
||||
def parse_remote_app_to_tree_node(parent, remote_app):
|
||||
pid = parent.id if parent else ''
|
||||
tree_node = {
|
||||
'id': remote_app.id,
|
||||
'name': remote_app.name,
|
||||
'title': remote_app.name,
|
||||
'pId': pid,
|
||||
'open': False,
|
||||
'isParent': False,
|
||||
'iconSkin': 'file',
|
||||
'meta': {'type': 'remote_app'}
|
||||
}
|
||||
return TreeNode(**tree_node)
|
|
@ -12,6 +12,7 @@ from common.permissions import IsValidUser, IsOrgAdmin
|
|||
from tickets import serializers
|
||||
from tickets.models import Ticket
|
||||
from tickets.permissions.ticket import IsAssignee, NotClosed
|
||||
from tickets.serializers.ticket.utils import get_dynamic_mapping_fields_mapping_rule_by_view
|
||||
|
||||
|
||||
__all__ = ['TicketViewSet']
|
||||
|
@ -66,8 +67,5 @@ class TicketViewSet(CommonApiMixin, viewsets.ModelViewSet):
|
|||
return super().update(request, *args, **kwargs)
|
||||
|
||||
def get_dynamic_mapping_fields_mapping_rule(self):
|
||||
from tickets.serializers.ticket.meta import get_meta_field_mapping_rule_by_view
|
||||
meta_field_mapping_rule = get_meta_field_mapping_rule_by_view(self)
|
||||
return {
|
||||
'meta': meta_field_mapping_rule,
|
||||
}
|
||||
fields_mapping_rule = get_dynamic_mapping_fields_mapping_rule_by_view(view=self)
|
||||
return fields_mapping_rule
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
from django.utils.translation import ugettext as __
|
||||
from orgs.utils import tmp_to_org, tmp_to_root_org
|
||||
from applications.models import Application, Category
|
||||
from applications.models import Application
|
||||
from applications.const import ApplicationCategoryChoices, ApplicationTypeChoices
|
||||
from assets.models import SystemUser
|
||||
from perms.models import ApplicationPermission
|
||||
from tickets.utils import convert_model_data_field_name_to_verbose_name
|
||||
|
@ -10,9 +11,9 @@ class ConstructDisplayFieldMixin:
|
|||
def construct_meta_apply_application_open_fields_display(self):
|
||||
meta_display_fields = ['apply_category_display', 'apply_type_display']
|
||||
apply_category = self.meta['apply_category']
|
||||
apply_category_display = dict(Category.choices)[apply_category]
|
||||
apply_category_display = ApplicationCategoryChoices.get_label(apply_category)
|
||||
apply_type = self.meta['apply_type']
|
||||
apply_type_display = dict(Category.get_type_choices(apply_category))[apply_type]
|
||||
apply_type_display = ApplicationTypeChoices.get_label(apply_type)
|
||||
meta_display_values = [apply_category_display, apply_type_display]
|
||||
meta_display = dict(zip(meta_display_fields, meta_display_values))
|
||||
return meta_display
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
from .ticket import *
|
||||
from .meta import *
|
||||
from .utils import *
|
||||
|
|
|
@ -1 +1 @@
|
|||
from .base import *
|
||||
from .meta import *
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from applications.models import Category, Application
|
||||
from applications.models import Application
|
||||
from applications.const import ApplicationCategoryChoices, ApplicationTypeChoices
|
||||
from assets.models import SystemUser
|
||||
from .mixin import BaseApproveSerializerMixin
|
||||
|
||||
|
@ -13,13 +14,13 @@ __all__ = [
|
|||
class ApplySerializer(serializers.Serializer):
|
||||
# 申请信息
|
||||
apply_category = serializers.ChoiceField(
|
||||
required=True, choices=Category.choices, label=_('Category')
|
||||
required=True, choices=ApplicationCategoryChoices.choices, label=_('Category')
|
||||
)
|
||||
apply_category_display = serializers.CharField(
|
||||
read_only=True, label=_('Category display')
|
||||
)
|
||||
apply_type = serializers.ChoiceField(
|
||||
required=True, choices=Category.get_all_type_choices(), label=_('Type')
|
||||
required=True, choices=ApplicationTypeChoices.choices, label=_('Type')
|
||||
)
|
||||
apply_type_display = serializers.CharField(
|
||||
required=False, read_only=True, label=_('Type display')
|
||||
|
@ -39,16 +40,6 @@ class ApplySerializer(serializers.Serializer):
|
|||
required=True, label=_('Date expired')
|
||||
)
|
||||
|
||||
def validate_apply_type(self, tp):
|
||||
category = self.root.initial_data['meta'].get('apply_category')
|
||||
if not category:
|
||||
return tp
|
||||
valid_type_types = list((dict(Category.get_type_choices(category)).keys()))
|
||||
if tp in valid_type_types:
|
||||
return tp
|
||||
error = _('Type `{}` is not a valid choice `({}){}`'.format(tp, category, valid_type_types))
|
||||
raise serializers.ValidationError(error)
|
||||
|
||||
|
||||
class ApproveSerializer(BaseApproveSerializerMixin, serializers.Serializer):
|
||||
# 审批信息
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
import copy
|
||||
from rest_framework import serializers
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.exceptions import JMSException
|
||||
from tickets import const
|
||||
from . import apply_asset, apply_application, login_confirm
|
||||
|
||||
__all__ = [
|
||||
'meta_dynamic_mapping_fields_mapping_rules',
|
||||
'get_meta_field_mapping_rule_by_view',
|
||||
]
|
||||
|
||||
#
|
||||
# ticket type
|
||||
# -----------
|
||||
|
||||
|
||||
types = const.TicketTypeChoices.values
|
||||
type_apply_asset = const.TicketTypeChoices.apply_asset.value
|
||||
type_apply_application = const.TicketTypeChoices.apply_application.value
|
||||
type_login_confirm = const.TicketTypeChoices.login_confirm.value
|
||||
|
||||
#
|
||||
# ticket type
|
||||
# -----------
|
||||
|
||||
|
||||
actions = const.TicketActionChoices.values
|
||||
action_open = const.TicketActionChoices.open.value
|
||||
action_approve = const.TicketActionChoices.approve.value
|
||||
action_reject = const.TicketActionChoices.reject.value
|
||||
action_close = const.TicketActionChoices.close.value
|
||||
|
||||
|
||||
#
|
||||
# define meta field `DynamicMappingField` mapping_rules
|
||||
# -----------------------------------------------------
|
||||
|
||||
|
||||
meta_dynamic_mapping_fields_mapping_rules = {
|
||||
'default': serializers.ReadOnlyField,
|
||||
'type': {
|
||||
type_apply_asset: {
|
||||
action_open: apply_asset.ApplySerializer,
|
||||
action_approve: apply_asset.ApproveSerializer,
|
||||
},
|
||||
type_apply_application: {
|
||||
action_open: apply_application.ApplySerializer,
|
||||
action_approve: apply_application.ApproveSerializer,
|
||||
},
|
||||
type_login_confirm: {
|
||||
action_open: login_confirm.ApplySerializer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#
|
||||
# get meta dynamic field mapping rule by view
|
||||
# -------------------------------------------
|
||||
|
||||
|
||||
def get_meta_field_mapping_rule_by_view(view):
|
||||
mapping_rules = copy.deepcopy(meta_dynamic_mapping_fields_mapping_rules)
|
||||
request = view.request
|
||||
|
||||
# type
|
||||
tp = request.query_params.get('type')
|
||||
if not tp:
|
||||
return ['default']
|
||||
if tp not in types:
|
||||
error = _('Query parameter `type` ({}) not in choices: {}'.format(tp, types))
|
||||
raise JMSException(error)
|
||||
if tp not in mapping_rules['type']:
|
||||
return ['default']
|
||||
|
||||
# action
|
||||
action = view.action
|
||||
if action in ['metadata']:
|
||||
# options
|
||||
action = request.query_params.get('action')
|
||||
if not action:
|
||||
error = _('Please carry query parameter `action`')
|
||||
raise JMSException(error)
|
||||
if action not in actions:
|
||||
error = _('Query parameter `action` ({}) not in choices: {}'.format(action, actions))
|
||||
raise JMSException(error)
|
||||
if action not in mapping_rules['type'][tp]:
|
||||
return ['default']
|
||||
|
||||
# display
|
||||
if action in ['list', 'retrieve']:
|
||||
return ['default']
|
||||
|
||||
if not mapping_rules['type'][tp].get(action):
|
||||
return ['default']
|
||||
|
||||
return ['type', tp, action]
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
import copy
|
||||
from common.drf.fields import IgnoreSensitiveInfoReadOnlyJSONField
|
||||
from tickets import const
|
||||
from . import apply_asset, apply_application, login_confirm
|
||||
|
||||
__all__ = [
|
||||
'get_meta_field_dynamic_mapping_rules',
|
||||
'get_meta_field_mapping_rule_by_view',
|
||||
]
|
||||
|
||||
#
|
||||
# ticket type
|
||||
# -----------
|
||||
|
||||
|
||||
type_apply_asset = const.TicketTypeChoices.apply_asset.value
|
||||
type_apply_application = const.TicketTypeChoices.apply_application.value
|
||||
type_login_confirm = const.TicketTypeChoices.login_confirm.value
|
||||
|
||||
#
|
||||
# ticket action
|
||||
# -------------
|
||||
|
||||
|
||||
actions = const.TicketActionChoices.values
|
||||
action_open = const.TicketActionChoices.open.value
|
||||
action_approve = const.TicketActionChoices.approve.value
|
||||
action_reject = const.TicketActionChoices.reject.value
|
||||
action_close = const.TicketActionChoices.close.value
|
||||
|
||||
|
||||
#
|
||||
# defines the dynamic mapping rules for the DynamicMappingField `meta`
|
||||
# --------------------------------------------------------------------
|
||||
|
||||
|
||||
__META_FIELD_DYNAMIC_MAPPING_RULES = {
|
||||
'default': IgnoreSensitiveInfoReadOnlyJSONField,
|
||||
'type': {
|
||||
type_apply_asset: {
|
||||
action_open: apply_asset.ApplySerializer,
|
||||
action_approve: apply_asset.ApproveSerializer,
|
||||
},
|
||||
type_apply_application: {
|
||||
action_open: apply_application.ApplySerializer,
|
||||
action_approve: apply_application.ApproveSerializer,
|
||||
},
|
||||
type_login_confirm: {
|
||||
action_open: login_confirm.ApplySerializer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Note:
|
||||
# The dynamic mapping rules of `meta` field is obtained
|
||||
# through call method `get_meta_field_dynamic_mapping_rules`
|
||||
|
||||
def get_meta_field_dynamic_mapping_rules():
|
||||
return copy.deepcopy(__META_FIELD_DYNAMIC_MAPPING_RULES)
|
||||
|
||||
|
||||
#
|
||||
# get `meta dynamic field` mapping rule by `view object`
|
||||
# ------------------------------------------------------
|
||||
|
||||
|
||||
def get_meta_field_mapping_rule_by_view(view):
|
||||
query_type = view.request.query_params.get('type')
|
||||
query_action = view.request.query_params.get('action')
|
||||
action = query_action if query_action else view.action
|
||||
mapping_rule = ['type', query_type, action]
|
||||
return mapping_rule
|
|
@ -8,7 +8,7 @@ from orgs.mixins.serializers import OrgResourceModelSerializerMixin
|
|||
from users.models import User
|
||||
from tickets import const
|
||||
from tickets.models import Ticket
|
||||
from .meta import meta_dynamic_mapping_fields_mapping_rules
|
||||
from .meta import get_meta_field_dynamic_mapping_rules
|
||||
|
||||
__all__ = [
|
||||
'TicketSerializer', 'TicketDisplaySerializer',
|
||||
|
@ -21,7 +21,7 @@ class TicketSerializer(OrgResourceModelSerializerMixin):
|
|||
type_display = serializers.ReadOnlyField(source='get_type_display', label=_('Type'))
|
||||
action_display = serializers.ReadOnlyField(source='get_action_display', label=_('Action'))
|
||||
status_display = serializers.ReadOnlyField(source='get_status_display', label=_('Status'))
|
||||
meta = DynamicMappingField(mapping_rules=meta_dynamic_mapping_fields_mapping_rules)
|
||||
meta = DynamicMappingField(mapping_rules=get_meta_field_dynamic_mapping_rules())
|
||||
|
||||
class Meta:
|
||||
model = Ticket
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
from .meta import get_meta_field_mapping_rule_by_view
|
||||
|
||||
__all__ = [
|
||||
'get_dynamic_mapping_fields_mapping_rule_by_view'
|
||||
]
|
||||
|
||||
|
||||
#
|
||||
# get `dynamic fields` mapping rule by `view object`
|
||||
# ----------------------------------------------------
|
||||
|
||||
|
||||
def get_dynamic_mapping_fields_mapping_rule_by_view(view):
|
||||
return {
|
||||
'meta': get_meta_field_mapping_rule_by_view(view=view)
|
||||
}
|
Loading…
Reference in New Issue