diff --git a/apps/acls/serializers/login_asset_acl.py b/apps/acls/serializers/login_asset_acl.py index 34d6711c8..b30876f27 100644 --- a/apps/acls/serializers/login_asset_acl.py +++ b/apps/acls/serializers/login_asset_acl.py @@ -3,7 +3,6 @@ from django.utils.translation import ugettext_lazy as _ from orgs.mixins.serializers import BulkOrgResourceModelSerializer from orgs.models import Organization -from assets.models import SystemUser from assets.const import Protocol from acls import models @@ -60,14 +59,6 @@ class LoginAssetACLSystemUsersSerializer(serializers.Serializer): ) ) - @staticmethod - def validate_protocol_group(protocol_group): - unsupported_protocols = set(protocol_group) - set(SystemUser.ASSET_CATEGORY_PROTOCOLS + ['*']) - if unsupported_protocols: - error = _('Unsupported protocols: {}').format(unsupported_protocols) - raise serializers.ValidationError(error) - return protocol_group - class LoginAssetACLSerializer(BulkOrgResourceModelSerializer): users = LoginAssetACLUsersSerializer() diff --git a/apps/acls/serializers/login_asset_check.py b/apps/acls/serializers/login_asset_check.py index ec7a7c35c..2c52506d5 100644 --- a/apps/acls/serializers/login_asset_check.py +++ b/apps/acls/serializers/login_asset_check.py @@ -1,9 +1,8 @@ -from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers from orgs.utils import tmp_to_root_org from common.utils import get_object_or_none, lazyproperty from users.models import User -from assets.models import Asset, SystemUser +from assets.models import Asset __all__ = ['LoginAssetCheckSerializer'] @@ -30,21 +29,21 @@ class LoginAssetCheckSerializer(serializers.Serializer): self.asset = self.validate_object_exist(Asset, asset_id) return asset_id - def validate_system_user_id(self, system_user_id): - self._system_user = self.validate_object_exist(SystemUser, system_user_id) - return system_user_id - - def validate_system_user_username(self, system_user_username): - system_user_id = self.initial_data.get('system_user_id') - system_user = self.validate_object_exist(SystemUser, system_user_id) - if self._system_user.login_mode == SystemUser.LOGIN_MANUAL \ - and not system_user.username \ - and not system_user.username_same_with_user \ - and not system_user_username: - error = 'Missing parameter: system_user_username' - raise serializers.ValidationError(error) - self._system_user_username = system_user_username - return system_user_username + # def validate_system_user_id(self, system_user_id): + # self._system_user = self.validate_object_exist(SystemUser, system_user_id) + # return system_user_id + # + # def validate_system_user_username(self, system_user_username): + # system_user_id = self.initial_data.get('system_user_id') + # system_user = self.validate_object_exist(SystemUser, system_user_id) + # if self._system_user.login_mode == SystemUser.LOGIN_MANUAL \ + # and not system_user.username \ + # and not system_user.username_same_with_user \ + # and not system_user_username: + # error = 'Missing parameter: system_user_username' + # raise serializers.ValidationError(error) + # self._system_user_username = system_user_username + # return system_user_username @staticmethod def validate_object_exist(model, field_id): @@ -55,16 +54,16 @@ class LoginAssetCheckSerializer(serializers.Serializer): raise serializers.ValidationError(error) return obj - @lazyproperty - def system_user(self): - if self._system_user.username_same_with_user: - username = self.user.username - elif self._system_user.login_mode == SystemUser.LOGIN_MANUAL: - username = self._system_user_username - else: - username = self._system_user.username - self._system_user.username = username - return self._system_user + # @lazyproperty + # def system_user(self): + # if self._system_user.username_same_with_user: + # username = self.user.username + # elif self._system_user.login_mode == SystemUser.LOGIN_MANUAL: + # username = self._system_user_username + # else: + # username = self._system_user.username + # self._system_user.username = username + # return self._system_user @lazyproperty def org(self): diff --git a/apps/applications/const.py b/apps/applications/const.py deleted file mode 100644 index 313477c25..000000000 --- a/apps/applications/const.py +++ /dev/null @@ -1,85 +0,0 @@ -# coding: utf-8 -# -from django.db import models -from django.utils.translation import ugettext_lazy as _ - - -class AppCategory(models.TextChoices): - db = 'db', _('Database') - remote_app = 'remote_app', _('Remote app') - cloud = 'cloud', 'Cloud' - - @classmethod - def get_label(cls, category): - return dict(cls.choices).get(category, '') - - @classmethod - def is_xpack(cls, category): - return category in ['remote_app'] - - -class AppType(models.TextChoices): - # db category - mysql = 'mysql', 'MySQL' - mariadb = 'mariadb', 'MariaDB' - oracle = 'oracle', 'Oracle' - pgsql = 'postgresql', 'PostgreSQL' - sqlserver = 'sqlserver', 'SQLServer' - redis = 'redis', 'Redis' - mongodb = 'mongodb', 'MongoDB' - - # remote-app category - chrome = 'chrome', 'Chrome' - mysql_workbench = 'mysql_workbench', 'MySQL Workbench' - vmware_client = 'vmware_client', 'vSphere Client' - custom = 'custom', _('Custom') - - # cloud category - k8s = 'k8s', 'Kubernetes' - - @classmethod - def category_types_mapper(cls): - return { - AppCategory.db: [ - cls.mysql, cls.mariadb, cls.oracle, cls.pgsql, - cls.sqlserver, cls.redis, cls.mongodb - ], - AppCategory.remote_app: [ - cls.chrome, cls.mysql_workbench, - cls.vmware_client, cls.custom - ], - AppCategory.cloud: [cls.k8s] - } - - @classmethod - def type_category_mapper(cls): - mapper = {} - for category, tps in cls.category_types_mapper().items(): - for tp in tps: - mapper[tp] = category - return mapper - - @classmethod - def get_label(cls, tp): - return dict(cls.choices).get(tp, '') - - @classmethod - def db_types(cls): - return [tp.value for tp in cls.category_types_mapper()[AppCategory.db]] - - @classmethod - def remote_app_types(cls): - return [tp.value for tp in cls.category_types_mapper()[AppCategory.remote_app]] - - @classmethod - def cloud_types(cls): - return [tp.value for tp in cls.category_types_mapper()[AppCategory.cloud]] - - @classmethod - def is_xpack(cls, tp): - tp_category_mapper = cls.type_category_mapper() - category = tp_category_mapper[tp] - - if AppCategory.is_xpack(category): - return True - return tp in ['oracle', 'postgresql', 'sqlserver'] diff --git a/apps/applications/migrations/0024_auto_20220816_1629.py b/apps/applications/migrations/0024_auto_20220816_1629.py deleted file mode 100644 index 4e8f88cff..000000000 --- a/apps/applications/migrations/0024_auto_20220816_1629.py +++ /dev/null @@ -1,59 +0,0 @@ -# Generated by Django 3.2.14 on 2022-08-16 08:29 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('tickets', '0019_delete_applyapplicationticket'), - ('authentication', '0012_auto_20220816_1629'), - ('applications', '0023_auto_20220816_1021'), - ] - - operations = [ - migrations.AlterUniqueTogether( - name='account', - unique_together=None, - ), - migrations.RemoveField( - model_name='account', - name='app', - ), - migrations.RemoveField( - model_name='account', - name='systemuser', - ), - migrations.AlterUniqueTogether( - name='application', - unique_together=None, - ), - migrations.RemoveField( - model_name='application', - name='domain', - ), - migrations.RemoveField( - model_name='historicalaccount', - name='app', - ), - migrations.RemoveField( - model_name='historicalaccount', - name='history_user', - ), - migrations.RemoveField( - model_name='historicalaccount', - name='systemuser', - ), - migrations.DeleteModel( - name='ApplicationUser', - ), - migrations.DeleteModel( - name='Account', - ), - migrations.DeleteModel( - name='Application', - ), - migrations.DeleteModel( - name='HistoricalAccount', - ), - ] diff --git a/apps/applications/models/__init__.py b/apps/applications/models/__init__.py deleted file mode 100644 index 268bbae0d..000000000 --- a/apps/applications/models/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# from .application import * -# from .account import * diff --git a/apps/applications/models/account.py b/apps/applications/models/account.py deleted file mode 100644 index 3828b5995..000000000 --- a/apps/applications/models/account.py +++ /dev/null @@ -1,117 +0,0 @@ -from django.db import models -from simple_history.models import HistoricalRecords -from django.db.models import F -from django.utils.translation import ugettext_lazy as _ - -from common.utils import lazyproperty -from assets.models.base import BaseAccount -from assets.models import SystemUser - - -class Account(BaseAccount): - app = models.ForeignKey( - 'applications.Application', on_delete=models.CASCADE, null=True, verbose_name=_('Application') - ) - systemuser = models.ForeignKey( - 'assets.SystemUser', on_delete=models.CASCADE, null=True, verbose_name=_("System user") - ) - version = models.IntegerField(default=1, verbose_name=_('Version')) - history = HistoricalRecords() - - auth_attrs = ['username', 'password', 'private_key', 'public_key'] - - class Meta: - verbose_name = _('Application account') - unique_together = [('username', 'app', 'systemuser')] - permissions = [ - ('view_applicationaccountsecret', _('Can view application account secret')), - ('change_appplicationaccountsecret', _('Can change application account secret')), - ] - - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - self.auth_snapshot = {} - - def get_or_systemuser_attr(self, attr): - val = getattr(self, attr, None) - if val: - return val - if self.systemuser: - return getattr(self.systemuser, attr, '') - return '' - - def load_auth(self): - for attr in self.auth_attrs: - value = self.get_or_systemuser_attr(attr) - self.auth_snapshot[attr] = [getattr(self, attr), value] - setattr(self, attr, value) - - def unload_auth(self): - if not self.systemuser: - return - - for attr, values in self.auth_snapshot.items(): - origin_value, loaded_value = values - current_value = getattr(self, attr, '') - if current_value == loaded_value: - setattr(self, attr, origin_value) - - def save(self, *args, **kwargs): - self.unload_auth() - instance = super().save(*args, **kwargs) - self.load_auth() - return instance - - @lazyproperty - def category(self): - return self.app.category - - @lazyproperty - def type(self): - return self.app.type - - @lazyproperty - def attrs(self): - return self.app.attrs - - @lazyproperty - def app_display(self): - return self.systemuser.name - - @property - def username_display(self): - return self.get_or_systemuser_attr('username') or '' - - @lazyproperty - def systemuser_display(self): - if not self.systemuser: - return '' - return str(self.systemuser) - - @property - def smart_name(self): - username = self.username_display - - if self.app: - app = str(self.app) - else: - app = '*' - return '{}@{}'.format(username, app) - - @classmethod - def get_queryset(cls): - queryset = cls.objects.all() \ - .annotate(type=F('app__type')) \ - .annotate(app_display=F('app__name')) \ - .annotate(systemuser_display=F('systemuser__name')) \ - .annotate(category=F('app__category')) - return queryset - - def __str__(self): - return self.smart_name - - -class ApplicationUser(SystemUser): - class Meta: - proxy = True - verbose_name = _('Application user') diff --git a/apps/applications/models/application.py b/apps/applications/models/application.py deleted file mode 100644 index ca45b043a..000000000 --- a/apps/applications/models/application.py +++ /dev/null @@ -1,97 +0,0 @@ -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.utils import is_uuid -from assets.models import Asset - -from .. import const -from .tree import ApplicationTreeNodeMixin - - -class Application(CommonModelMixin, OrgModelMixin, ApplicationTreeNodeMixin): - name = models.CharField(max_length=128, verbose_name=_('Name')) - category = models.CharField( - max_length=16, choices=const.AppCategory.choices, verbose_name=_('Category') - ) - type = models.CharField( - max_length=16, choices=const.AppType.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') - ) - - class Meta: - verbose_name = _('Application') - unique_together = [('org_id', 'name')] - ordering = ('name',) - permissions = [ - ('match_application', _('Can match application')), - ] - - def __str__(self): - category_display = self.get_category_display() - type_display = self.get_type_display() - return f'{self.name}({type_display})[{category_display}]' - - @property - def category_remote_app(self): - return self.category == const.AppCategory.remote_app.value - - @property - def category_cloud(self): - return self.category == const.AppCategory.cloud.value - - @property - def category_db(self): - return self.category == const.AppCategory.db.value - - def get_rdp_remote_app_setting(self): - from applications.serializers.attrs import get_serializer_class_by_application_type - if not self.category_remote_app: - raise ValueError(f"Not a remote app application: {self.name}") - serializer_class = get_serializer_class_by_application_type(self.type) - fields = serializer_class().get_fields() - - parameters = [self.type] - for field_name in list(fields.keys()): - if field_name in ['asset']: - continue - value = self.attrs.get(field_name) - if not value: - continue - if field_name == 'path': - value = '\"%s\"' % value - parameters.append(str(value)) - - parameters = ' '.join(parameters) - return { - 'program': '||jmservisor', - 'working_directory': '', - 'parameters': parameters - } - - def get_remote_app_asset(self, raise_exception=True): - asset_id = self.attrs.get('asset') - if is_uuid(asset_id): - return Asset.objects.filter(id=asset_id).first() - if raise_exception: - raise ValueError("Remote App not has asset attr") - - def get_target_ip(self): - target_ip = '' - if self.category_remote_app: - asset = self.get_remote_app_asset() - target_ip = asset.ip if asset else target_ip - elif self.category_cloud: - target_ip = self.attrs.get('cluster') - elif self.category_db: - target_ip = self.attrs.get('host') - return target_ip - diff --git a/apps/applications/models/database.py b/apps/applications/models/database.py deleted file mode 100644 index f964dd737..000000000 --- a/apps/applications/models/database.py +++ /dev/null @@ -1,13 +0,0 @@ -from django.db import models -from django.utils.translation import gettext_lazy as _ - -from .application import Application - - -class Database(Application): - host = models.CharField(max_length=1024, verbose_name=_('Host')) - port = models.IntegerField(verbose_name=_("Port")) - database = models.CharField(max_length=1024, blank=True, null=True, verbose_name=_("Database")) - - class Meta: - verbose_name = _("Database") diff --git a/apps/applications/models/remote_app.py b/apps/applications/models/remote_app.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/apps/applications/models/tree.py b/apps/applications/models/tree.py deleted file mode 100644 index cd3c43717..000000000 --- a/apps/applications/models/tree.py +++ /dev/null @@ -1,207 +0,0 @@ -from collections import defaultdict -from urllib.parse import urlencode, parse_qsl - -from django.utils.translation import ugettext_lazy as _ -from django.conf import settings - -from common.tree import TreeNode -from .. import const - - -class ApplicationTreeNodeMixin: - id: str - name: str - type: str - category: str - attrs: dict - - @staticmethod - def create_tree_id(pid, type, v): - i = dict(parse_qsl(pid)) - i[type] = v - tree_id = urlencode(i) - return tree_id - - @classmethod - def create_choice_node(cls, c, id_, pid, tp, opened=False, counts=None, - show_empty=True, show_count=True): - count = counts.get(c.value, 0) - if count == 0 and not show_empty: - return None - label = c.label - if count is not None and show_count: - label = '{} ({})'.format(label, count) - data = { - 'id': id_, - 'name': label, - 'title': label, - 'pId': pid, - 'isParent': bool(count), - 'open': opened, - 'iconSkin': '', - 'meta': { - 'type': tp, - 'data': { - 'name': c.name, - 'value': c.value - } - } - } - return TreeNode(**data) - - @classmethod - def create_root_tree_node(cls, queryset, show_count=True): - count = queryset.count() if show_count else None - root_id = 'applications' - root_name = _('Applications') - if count is not None and show_count: - root_name = '{} ({})'.format(root_name, count) - node = TreeNode(**{ - 'id': root_id, - 'name': root_name, - 'title': root_name, - 'pId': '', - 'isParent': True, - 'open': True, - 'iconSkin': '', - 'meta': { - 'type': 'applications_root', - } - }) - return node - - @classmethod - def create_category_tree_nodes(cls, pid, counts=None, show_empty=True, show_count=True): - nodes = [] - categories = const.AppType.category_types_mapper().keys() - for category in categories: - if not settings.XPACK_ENABLED and const.AppCategory.is_xpack(category): - continue - i = cls.create_tree_id(pid, 'category', category.value) - node = cls.create_choice_node( - category, i, pid=pid, tp='category', - counts=counts, opened=False, show_empty=show_empty, - show_count=show_count - ) - if not node: - continue - nodes.append(node) - return nodes - - @classmethod - def create_types_tree_nodes(cls, pid, counts, show_empty=True, show_count=True): - nodes = [] - temp_pid = pid - type_category_mapper = const.AppType.type_category_mapper() - types = const.AppType.type_category_mapper().keys() - - for tp in types: - if not settings.XPACK_ENABLED and const.AppType.is_xpack(tp): - continue - category = type_category_mapper.get(tp) - pid = cls.create_tree_id(pid, 'category', category.value) - i = cls.create_tree_id(pid, 'type', tp.value) - node = cls.create_choice_node( - tp, i, pid, tp='type', counts=counts, opened=False, - show_empty=show_empty, show_count=show_count - ) - pid = temp_pid - if not node: - continue - nodes.append(node) - return nodes - - @staticmethod - def get_tree_node_counts(queryset): - counts = defaultdict(int) - values = queryset.values_list('type', 'category') - for i in values: - tp = i[0] - category = i[1] - counts[tp] += 1 - counts[category] += 1 - return counts - - @classmethod - def create_category_type_tree_nodes(cls, queryset, pid, show_empty=True, show_count=True): - counts = cls.get_tree_node_counts(queryset) - tree_nodes = [] - - # 类别的节点 - tree_nodes += cls.create_category_tree_nodes( - pid, counts, show_empty=show_empty, - show_count=show_count - ) - - # 类型的节点 - tree_nodes += cls.create_types_tree_nodes( - pid, counts, show_empty=show_empty, - show_count=show_count - ) - return tree_nodes - - @classmethod - def create_tree_nodes(cls, queryset, root_node=None, show_empty=True, show_count=True): - tree_nodes = [] - - # 根节点有可能是组织名称 - if root_node is None: - root_node = cls.create_root_tree_node(queryset, show_count=show_count) - tree_nodes.append(root_node) - - tree_nodes += cls.create_category_type_tree_nodes( - queryset, root_node.id, show_empty=show_empty, show_count=show_count - ) - - # 应用的节点 - for app in queryset: - if not settings.XPACK_ENABLED and const.AppType.is_xpack(app.type): - continue - node = app.as_tree_node(root_node.id) - tree_nodes.append(node) - return tree_nodes - - def create_app_tree_pid(self, root_id): - pid = self.create_tree_id(root_id, 'category', self.category) - pid = self.create_tree_id(pid, 'type', self.type) - return pid - - def as_tree_node(self, pid, k8s_as_tree=False): - if self.type == const.AppType.k8s and k8s_as_tree: - node = KubernetesTree(pid).as_tree_node(self) - else: - node = self._as_tree_node(pid) - return node - - def _attrs_to_tree(self): - if self.category == const.AppCategory.db: - return self.attrs - return {} - - def _as_tree_node(self, pid): - icon_skin_category_mapper = { - 'remote_app': 'chrome', - 'db': 'database', - 'cloud': 'cloud' - } - icon_skin = icon_skin_category_mapper.get(self.category, 'file') - pid = self.create_app_tree_pid(pid) - node = TreeNode(**{ - 'id': str(self.id), - 'name': self.name, - 'title': self.name, - 'pId': pid, - 'isParent': False, - 'open': False, - 'iconSkin': icon_skin, - 'meta': { - 'type': 'application', - 'data': { - 'category': self.category, - 'type': self.type, - 'attrs': self._attrs_to_tree() - } - } - }) - return node - diff --git a/apps/assets/migrations/0106_auto_20220811_1358.py b/apps/assets/migrations/0106_auto_20220811_1358.py index 640dd8adb..63b7509dd 100644 --- a/apps/assets/migrations/0106_auto_20220811_1358.py +++ b/apps/assets/migrations/0106_auto_20220811_1358.py @@ -11,19 +11,6 @@ class Migration(migrations.Migration): ] operations = [ - migrations.CreateModel( - name='AccountTemplate', - fields=[ - ('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')), - ('updated_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by')), - ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), - ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), - ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ], - options={ - 'abstract': False, - }, - ), migrations.RemoveField( model_name='account', name='protocol', diff --git a/apps/assets/migrations/0111_auto_20220816_1022.py b/apps/assets/migrations/0111_auto_20220816_1022.py index 296aaa99a..55c286ce5 100644 --- a/apps/assets/migrations/0111_auto_20220816_1022.py +++ b/apps/assets/migrations/0111_auto_20220816_1022.py @@ -1,6 +1,7 @@ # Generated by Django 3.2.14 on 2022-08-16 02:22 import time from django.db import migrations, models +from django.db.models import Count def migrate_command_filter_to_assets(apps, schema_editor): @@ -50,9 +51,6 @@ class Migration(migrations.Migration): ] operations = [ - migrations.DeleteModel( - name='AccountTemplate', - ), migrations.AddField( model_name='commandfilter', name='accounts', diff --git a/apps/assets/models/__init__.py b/apps/assets/models/__init__.py index f257d6e8d..d81856923 100644 --- a/apps/assets/models/__init__.py +++ b/apps/assets/models/__init__.py @@ -1,6 +1,6 @@ from .base import * from .platform import * -from ._user import * +# from ._user import * from .asset import * from .label import Label from .group import * @@ -12,7 +12,7 @@ from .favorite_asset import * from .account import * from .backup import * # 废弃以下 -from ._authbook import * +# from ._authbook import * from .protocol import * from .cmd_filter import * diff --git a/apps/assets/models/utils.py b/apps/assets/models/utils.py index 90b0ee178..bc6bdb21f 100644 --- a/apps/assets/models/utils.py +++ b/apps/assets/models/utils.py @@ -11,24 +11,10 @@ from common.utils import validate_ssh_private_key __all__ = [ - 'init_model', 'generate_fake', 'private_key_validator', + 'private_key_validator', ] -def init_model(): - from . import SystemUser, AdminUser, Asset - for cls in [SystemUser, AdminUser, Asset]: - if hasattr(cls, 'initial'): - cls.initial() - - -def generate_fake(): - from . import SystemUser, AdminUser, Asset - for cls in [SystemUser, AdminUser, Asset]: - if hasattr(cls, 'generate_fake'): - cls.generate_fake() - - def private_key_validator(value): if not validate_ssh_private_key(value): raise ValidationError( diff --git a/apps/audits/signal_handlers.py b/apps/audits/signal_handlers.py index 9173a6d9f..206b5e5f8 100644 --- a/apps/audits/signal_handlers.py +++ b/apps/audits/signal_handlers.py @@ -16,7 +16,7 @@ from django.utils import translation from rest_framework.renderers import JSONRenderer from rest_framework.request import Request -from assets.models import Asset, SystemUser +from assets.models import Asset from authentication.signals import post_auth_failed, post_auth_success from authentication.utils import check_different_city_login_if_need from jumpserver.utils import current_request diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index 7b7a17aed..ce84cb74e 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -13,7 +13,7 @@ from rest_framework.request import Request from common.drf.api import JMSModelViewSet from common.http import is_true from orgs.mixins.api import RootOrgViewMixin -from perms.models.base import Action +from perms.models import Action from terminal.models import EndpointRule from ..serializers import ( ConnectionTokenSerializer, ConnectionTokenSecretSerializer, SuperConnectionTokenSerializer, diff --git a/apps/authentication/migrations/0012_auto_20220816_1629.py b/apps/authentication/migrations/0012_auto_20220816_1629.py index 1f76da99c..dac9d1302 100644 --- a/apps/authentication/migrations/0012_auto_20220816_1629.py +++ b/apps/authentication/migrations/0012_auto_20220816_1629.py @@ -3,14 +3,14 @@ from django.db import migrations, models -def migrate_system_user_to_accounts(apps, schema_editor): - connection_token_model = apps.get_model("perms", "ConnectionToken") +def migrate_system_user_to_account(apps, schema_editor): + connection_token_model = apps.get_model("authentication", "ConnectionToken") count = 0 bulk_size = 10000 while True: connection_tokens = connection_token_model.objects \ - .prefect_related('system_users')[count:bulk_size] + .prefetch_related('system_users')[count:bulk_size] if not connection_tokens: break count += len(connection_tokens) @@ -45,7 +45,7 @@ class Migration(migrations.Migration): name='account', field=models.CharField(default='', max_length=128, verbose_name='Account'), ), - migrations.RunPython(migrate_system_user_to_accounts), + migrations.RunPython(migrate_system_user_to_account), migrations.RemoveField( model_name='connectiontoken', name='system_user', diff --git a/apps/authentication/serializers/connection_token.py b/apps/authentication/serializers/connection_token.py index 284c35663..acbce801e 100644 --- a/apps/authentication/serializers/connection_token.py +++ b/apps/authentication/serializers/connection_token.py @@ -5,7 +5,7 @@ from orgs.mixins.serializers import OrgResourceModelSerializerMixin from authentication.models import ConnectionToken from common.utils import pretty_string from common.utils.random import random_string -from assets.models import Asset, SystemUser, Gateway, Domain, CommandFilterRule +from assets.models import Asset, Gateway, Domain, CommandFilterRule from users.models import User from perms.serializers.base import ActionsField @@ -123,15 +123,6 @@ class ConnectionTokenAssetSerializer(serializers.ModelSerializer): fields = ['id', 'name', 'ip', 'protocols', 'org_id'] -class ConnectionTokenSystemUserSerializer(serializers.ModelSerializer): - class Meta: - model = SystemUser - fields = [ - 'id', 'name', 'username', 'password', 'private_key', - 'protocol', 'ad_domain', 'org_id' - ] - - class ConnectionTokenGatewaySerializer(serializers.ModelSerializer): class Meta: model = Gateway @@ -165,7 +156,7 @@ class ConnectionTokenSecretSerializer(OrgResourceModelSerializerMixin): user = ConnectionTokenUserSerializer(read_only=True) asset = ConnectionTokenAssetSerializer(read_only=True) remote_app = ConnectionTokenRemoteAppSerializer(read_only=True) - system_user = ConnectionTokenSystemUserSerializer(read_only=True) + account = serializers.CharField(read_only=True) gateway = ConnectionTokenGatewaySerializer(read_only=True) domain = ConnectionTokenDomainSerializer(read_only=True) cmd_filter_rules = ConnectionTokenCmdFilterRuleSerializer(many=True) diff --git a/apps/ops/models/adhoc.py b/apps/ops/models/adhoc.py index 0d1b32ba5..1d2920206 100644 --- a/apps/ops/models/adhoc.py +++ b/apps/ops/models/adhoc.py @@ -157,7 +157,6 @@ class AdHoc(OrgModelMixin): hosts = models.ManyToManyField('assets.Asset', verbose_name=_("Host")) run_as_admin = models.BooleanField(default=False, verbose_name=_('Run as admin')) run_as = models.CharField(max_length=64, default='', blank=True, null=True, verbose_name=_('Username')) - run_system_user = models.ForeignKey('assets.SystemUser', null=True, on_delete=models.CASCADE) become = EncryptJsonDictCharField(max_length=1024, default='', blank=True, null=True, verbose_name=_("Become")) created_by = models.CharField(max_length=64, default='', blank=True, null=True, verbose_name=_('Create by')) date_created = models.DateTimeField(auto_now_add=True, db_index=True) diff --git a/apps/ops/models/command.py b/apps/ops/models/command.py index 8df5005c4..0c1038f89 100644 --- a/apps/ops/models/command.py +++ b/apps/ops/models/command.py @@ -23,6 +23,7 @@ class CommandExecution(OrgModelMixin): id = models.UUIDField(default=uuid.uuid4, primary_key=True) hosts = models.ManyToManyField('assets.Asset') run_as = models.ForeignKey('assets.SystemUser', on_delete=models.CASCADE) + account = models.CharField(max_length=128, verbose_name=_('account')) command = models.TextField(verbose_name=_("Command")) _result = models.TextField(blank=True, null=True, verbose_name=_('Result')) user = models.ForeignKey('users.User', on_delete=models.CASCADE, null=True) diff --git a/apps/orgs/api.py b/apps/orgs/api.py index d61e137bc..16fde4d69 100644 --- a/apps/orgs/api.py +++ b/apps/orgs/api.py @@ -14,7 +14,7 @@ from .serializers import ( ) from users.models import User, UserGroup from assets.models import ( - Asset, Domain, SystemUser, Label, Node, Gateway, + Asset, Domain, Label, Node, Gateway, CommandFilter, CommandFilterRule, GatheredUser ) from perms.models import AssetPermission @@ -27,7 +27,7 @@ logger = get_logger(__file__) # 部分 org 相关的 model,需要清空这些数据之后才能删除该组织 org_related_models = [ - User, UserGroup, Asset, Label, Domain, Gateway, Node, SystemUser, Label, + User, UserGroup, Asset, Label, Domain, Gateway, Node, Label, CommandFilter, CommandFilterRule, GatheredUser, AssetPermission, ] diff --git a/apps/orgs/caches.py b/apps/orgs/caches.py index 33fc87f3e..e9e5bc700 100644 --- a/apps/orgs/caches.py +++ b/apps/orgs/caches.py @@ -6,7 +6,7 @@ from orgs.utils import current_org, tmp_to_org from common.cache import Cache, IntegerField from common.utils import get_logger from users.models import UserGroup, User -from assets.models import Node, SystemUser, Domain, Gateway, Asset +from assets.models import Node, Domain, Gateway, Asset from terminal.models import Session from perms.models import AssetPermission @@ -71,12 +71,6 @@ class OrgResourceStatisticsCache(OrgRelatedCache): def get_current_org(self): return self.org - def compute_admin_users_amount(self): - return SystemUser.objects.filter(type=SystemUser.Type.admin).count() - - def compute_system_users_amount(self): - return SystemUser.objects.filter(type=SystemUser.Type.common).count() - def compute_users_amount(self): amount = User.get_org_users(self.org).count() return amount diff --git a/apps/orgs/signal_handlers/cache.py b/apps/orgs/signal_handlers/cache.py index 6acf1ac7a..1e3343931 100644 --- a/apps/orgs/signal_handlers/cache.py +++ b/apps/orgs/signal_handlers/cache.py @@ -8,7 +8,7 @@ from users.models import UserGroup, User from users.signals import pre_user_leave_org from terminal.models import Session from rbac.models import OrgRoleBinding, SystemRoleBinding, RoleBinding -from assets.models import Asset, SystemUser, Domain, Gateway +from assets.models import Asset, Domain, Gateway from orgs.caches import OrgResourceStatisticsCache from orgs.utils import current_org from common.utils import get_logger @@ -77,7 +77,6 @@ class OrgResourceStatisticsRefreshUtil: AssetPermission: ['asset_perms_amount'], Gateway: ['gateways_amount'], Domain: ['domains_amount'], - SystemUser: ['system_users_amount', 'admin_users_amount'], Node: ['nodes_amount'], Asset: ['assets_amount'], UserGroup: ['groups_amount'], diff --git a/apps/orgs/signal_handlers/common.py b/apps/orgs/signal_handlers/common.py index bc0ac64cd..f2396231b 100644 --- a/apps/orgs/signal_handlers/common.py +++ b/apps/orgs/signal_handlers/common.py @@ -14,7 +14,6 @@ from orgs.models import Organization from orgs.hands import set_current_org, Node, get_current_org from perms.models import AssetPermission from users.models import UserGroup, User -from assets.models import SystemUser from common.const.signals import PRE_REMOVE, POST_REMOVE from common.decorator import on_transaction_commit from common.signals import django_ready @@ -135,7 +134,7 @@ def _clear_users_from_org(org, users): if not users: return - models = (AssetPermission, UserGroup, SystemUser) + models = (AssetPermission, UserGroup) for m in models: _remove_users(m, users, org) diff --git a/apps/perms/api/__init__.py b/apps/perms/api/__init__.py index e4983cd95..e5e3698dd 100644 --- a/apps/perms/api/__init__.py +++ b/apps/perms/api/__init__.py @@ -2,4 +2,3 @@ # from .asset import * -from .system_user_permission import * diff --git a/apps/perms/api/asset/user_permission/common.py b/apps/perms/api/asset/user_permission/common.py index 86bff2123..5e8e839e4 100644 --- a/apps/perms/api/asset/user_permission/common.py +++ b/apps/perms/api/asset/user_permission/common.py @@ -8,7 +8,7 @@ from django.utils.decorators import method_decorator from rest_framework.views import APIView, Response from rest_framework import status from rest_framework.generics import ( - ListAPIView, get_object_or_404, RetrieveAPIView, DestroyAPIView + ListAPIView, get_object_or_404, RetrieveAPIView ) from orgs.utils import tmp_to_root_org @@ -16,7 +16,7 @@ from perms.utils.asset.permission import get_asset_system_user_ids_with_actions_ from common.permissions import IsValidUser from common.utils import get_logger, lazyproperty -from perms.hands import User, Asset, SystemUser +from perms.hands import User, Asset from perms import serializers logger = get_logger(__name__) @@ -25,7 +25,6 @@ __all__ = [ 'UserGrantedAssetSystemUsersForAdminApi', 'ValidateUserAssetPermissionApi', 'GetUserAssetPermissionActionsApi', - 'UserAssetPermissionsCacheApi', 'MyGrantedAssetSystemUsersApi', ] @@ -45,19 +44,18 @@ class GetUserAssetPermissionActionsApi(RetrieveAPIView): def get_object(self): asset_id = self.request.query_params.get('asset_id', '') - system_id = self.request.query_params.get('system_user_id', '') + account = self.request.query_params.get('account', '') try: asset_id = uuid.UUID(asset_id) - system_id = uuid.UUID(system_id) except ValueError: return Response({'msg': False}, status=403) asset = get_object_or_404(Asset, id=asset_id) - system_user = get_object_or_404(SystemUser, id=system_id) system_users_actions = get_asset_system_user_ids_with_actions_by_user(self.get_user(), asset) - actions = system_users_actions.get(system_user.id) + # actions = system_users_actions.get(system_user.id) + actions = system_users_actions.get(account) return {"actions": actions} @@ -70,7 +68,7 @@ class ValidateUserAssetPermissionApi(APIView): def get(self, request, *args, **kwargs): user_id = self.request.query_params.get('user_id', '') asset_id = request.query_params.get('asset_id', '') - system_id = request.query_params.get('system_user_id', '') + account = request.query_params.get('account', '') action_name = request.query_params.get('action_name', '') data = { @@ -79,14 +77,13 @@ class ValidateUserAssetPermissionApi(APIView): 'actions': [] } - if not all((user_id, asset_id, system_id, action_name)): + if not all((user_id, asset_id, account, action_name)): return Response(data) user = User.objects.get(id=user_id) asset = Asset.objects.valid().get(id=asset_id) - system_user = SystemUser.objects.get(id=system_id) - has_perm, actions, expire_at = validate_permission(user, asset, system_user, action_name) + has_perm, actions, expire_at = validate_permission(user, asset, account, action_name) status_code = status.HTTP_200_OK if has_perm else status.HTTP_403_FORBIDDEN data = { 'has_permission': has_perm, @@ -97,8 +94,6 @@ class ValidateUserAssetPermissionApi(APIView): class UserGrantedAssetSystemUsersForAdminApi(ListAPIView): - serializer_class = serializers.AssetSystemUserSerializer - only_fields = serializers.AssetSystemUserSerializer.Meta.only_fields rbac_perms = { 'list': 'perms.view_userassets' } @@ -117,13 +112,6 @@ class UserGrantedAssetSystemUsersForAdminApi(ListAPIView): def get_asset_system_user_ids_with_actions(self, asset): return get_asset_system_user_ids_with_actions_by_user(self.user, asset) - def get_queryset(self): - system_user_ids = self.system_users_with_actions.keys() - system_users = SystemUser.objects.filter(id__in=system_user_ids) \ - .only(*self.serializer_class.Meta.only_fields) \ - .order_by('name') - return system_users - def paginate_queryset(self, queryset): page = super().paginate_queryset(queryset) @@ -148,8 +136,3 @@ class MyGrantedAssetSystemUsersApi(UserGrantedAssetSystemUsersForAdminApi): def user(self): return self.request.user - -# TODO 删除 -class UserAssetPermissionsCacheApi(DestroyAPIView): - def destroy(self, request, *args, **kwargs): - return Response(status=204) diff --git a/apps/perms/api/system_user_permission.py b/apps/perms/api/system_user_permission.py deleted file mode 100644 index 6d7569192..000000000 --- a/apps/perms/api/system_user_permission.py +++ /dev/null @@ -1,21 +0,0 @@ -from rest_framework import generics - -from assets.models import SystemUser -from common.permissions import IsValidUser -from perms.utils.asset.user_permission import get_user_all_asset_perm_ids -from .. import serializers - - -class SystemUserPermission(generics.ListAPIView): - permission_classes = (IsValidUser,) - serializer_class = serializers.SystemUserSerializer - - def get_queryset(self): - user = self.request.user - - asset_perm_ids = get_user_all_asset_perm_ids(user) - queryset = SystemUser.objects.filter( - granted_by_permissions__id__in=asset_perm_ids - ).distinct() - - return queryset diff --git a/apps/perms/filters.py b/apps/perms/filters.py index 1699ff4e7..ac23b691c 100644 --- a/apps/perms/filters.py +++ b/apps/perms/filters.py @@ -5,7 +5,7 @@ from common.db.models import UnionQuerySet from common.drf.filters import BaseFilterSet from common.utils import get_object_or_none from users.models import User, UserGroup -from assets.models import Node, Asset, SystemUser +from assets.models import Node, Asset from perms.models import AssetPermission @@ -30,7 +30,6 @@ class PermissionBaseFilter(BaseFilterSet): qs = super().qs qs = self.filter_valid(qs) qs = self.filter_user(qs) - qs = self.filter_system_user(qs) qs = self.filter_user_group(qs) return qs @@ -74,21 +73,6 @@ class PermissionBaseFilter(BaseFilterSet): ).distinct() return queryset - def filter_system_user(self, queryset): - system_user_id = self.get_query_param('system_user_id') - system_user_name = self.get_query_param('system_user') - - if system_user_id: - system_user = get_object_or_none(SystemUser, pk=system_user_id) - elif system_user_name: - system_user = get_object_or_none(SystemUser, name=system_user_name) - else: - return queryset - if not system_user: - return queryset.none() - queryset = queryset.filter(system_users=system_user) - return queryset - def filter_user_group(self, queryset): user_group_id = self.get_query_param('user_group_id') user_group_name = self.get_query_param('user_group') diff --git a/apps/perms/hands.py b/apps/perms/hands.py index 25902fddf..1537b7260 100644 --- a/apps/perms/hands.py +++ b/apps/perms/hands.py @@ -2,12 +2,12 @@ # from users.models import User, UserGroup -from assets.models import Asset, SystemUser, Node, Label, FavoriteAsset +from assets.models import Asset, Node, Label, FavoriteAsset from assets.serializers import NodeSerializer __all__ = [ 'User', 'UserGroup', - 'Asset', 'SystemUser', 'Node', 'Label', 'FavoriteAsset', + 'Asset', 'Node', 'Label', 'FavoriteAsset', 'NodeSerializer', ] diff --git a/apps/perms/migrations/0030_auto_20220816_1132.py b/apps/perms/migrations/0030_auto_20220816_1132.py index d80bc0dfc..348000823 100644 --- a/apps/perms/migrations/0030_auto_20220816_1132.py +++ b/apps/perms/migrations/0030_auto_20220816_1132.py @@ -1,8 +1,4 @@ # Generated by Django 3.2.14 on 2022-08-16 03:32 - - - -import time from django.db import migrations, models diff --git a/apps/perms/models/__init__.py b/apps/perms/models/__init__.py index 37e04577d..0c7e25c70 100644 --- a/apps/perms/models/__init__.py +++ b/apps/perms/models/__init__.py @@ -2,5 +2,3 @@ # from .asset_permission import * -# from .application_permission import * -from .base import * diff --git a/apps/perms/models/asset_permission.py b/apps/perms/models/asset_permission.py index 6d2401885..bf70e9b6f 100644 --- a/apps/perms/models/asset_permission.py +++ b/apps/perms/models/asset_permission.py @@ -13,7 +13,9 @@ from common.db.models import BaseCreateUpdateModel, BitOperationChoice, UnionQue __all__ = [ - 'AssetPermission', 'PermNode', 'UserAssetGrantedTreeNodeRelation', + 'AssetPermission', 'PermNode', + 'UserAssetGrantedTreeNodeRelation', + 'Action' ] # 使用场景 diff --git a/apps/perms/models/base.py b/apps/perms/models/base.py deleted file mode 100644 index 729ce7df1..000000000 --- a/apps/perms/models/base.py +++ /dev/null @@ -1,160 +0,0 @@ -# coding: utf-8 -# - -# TODO: v3 delete 整个文件 - - -import uuid -from django.utils.translation import ugettext_lazy as _ -from django.db import models -from django.db.models import Q -from django.utils import timezone -from orgs.mixins.models import OrgModelMixin - -from common.db.models import UnionQuerySet, BitOperationChoice -from common.utils import date_expired_default, lazyproperty -from orgs.mixins.models import OrgManager - -__all__ = [ - 'BasePermission', 'BasePermissionQuerySet', 'Action' -] - - -class BasePermissionQuerySet(models.QuerySet): - def active(self): - return self.filter(is_active=True) - - def valid(self): - return self.active().filter(date_start__lt=timezone.now()) \ - .filter(date_expired__gt=timezone.now()) - - def inactive(self): - return self.filter(is_active=False) - - def invalid(self): - now = timezone.now() - q = (Q(is_active=False) | Q(date_start__gt=now) | Q(date_expired__lt=now)) - return self.filter(q) - - -class BasePermissionManager(OrgManager): - def valid(self): - return self.get_queryset().valid() - - -class Action(BitOperationChoice): - ALL = 0xff - - CONNECT = 0b1 - UPLOAD = 0b1 << 1 - DOWNLOAD = 0b1 << 2 - CLIPBOARD_COPY = 0b1 << 3 - CLIPBOARD_PASTE = 0b1 << 4 - UPDOWNLOAD = UPLOAD | DOWNLOAD - CLIPBOARD_COPY_PASTE = CLIPBOARD_COPY | CLIPBOARD_PASTE - - DB_CHOICES = ( - (ALL, _('All')), - (CONNECT, _('Connect')), - (UPLOAD, _('Upload file')), - (DOWNLOAD, _('Download file')), - (UPDOWNLOAD, _("Upload download")), - (CLIPBOARD_COPY, _('Clipboard copy')), - (CLIPBOARD_PASTE, _('Clipboard paste')), - (CLIPBOARD_COPY_PASTE, _('Clipboard copy paste')) - ) - - NAME_MAP = { - ALL: "all", - CONNECT: "connect", - UPLOAD: "upload_file", - DOWNLOAD: "download_file", - UPDOWNLOAD: "updownload", - CLIPBOARD_COPY: 'clipboard_copy', - CLIPBOARD_PASTE: 'clipboard_paste', - CLIPBOARD_COPY_PASTE: 'clipboard_copy_paste' - } - - NAME_MAP_REVERSE = {v: k for k, v in NAME_MAP.items()} - CHOICES = [] - for i, j in DB_CHOICES: - CHOICES.append((NAME_MAP[i], j)) - - -class BasePermission(OrgModelMixin): - id = models.UUIDField(default=uuid.uuid4, primary_key=True) - name = models.CharField(max_length=128, verbose_name=_('Name')) - users = models.ManyToManyField('users.User', blank=True, verbose_name=_("User"), related_name='%(class)ss') - user_groups = models.ManyToManyField( - 'users.UserGroup', blank=True, verbose_name=_("User group"), related_name='%(class)ss') - actions = models.IntegerField(choices=Action.DB_CHOICES, default=Action.ALL, verbose_name=_("Actions")) - is_active = models.BooleanField(default=True, verbose_name=_('Active')) - date_start = models.DateTimeField(default=timezone.now, db_index=True, verbose_name=_("Date start")) - date_expired = models.DateTimeField(default=date_expired_default, db_index=True, verbose_name=_('Date expired')) - created_by = models.CharField(max_length=128, blank=True, verbose_name=_('Created by')) - date_created = models.DateTimeField(auto_now_add=True, verbose_name=_('Date created')) - comment = models.TextField(verbose_name=_('Comment'), blank=True) - from_ticket = models.BooleanField(default=False, verbose_name=_('From ticket')) - - objects = BasePermissionManager.from_queryset(BasePermissionQuerySet)() - - class Meta: - abstract = True - - def __str__(self): - return self.name - - @property - def id_str(self): - return str(self.id) - - @property - def is_expired(self): - if self.date_expired > timezone.now() > self.date_start: - return False - return True - - @property - def is_valid(self): - if not self.is_expired and self.is_active: - return True - return False - - @property - def all_users(self): - from users.models import User - - users_query = self._meta.get_field('users').related_query_name() - user_groups_query = self._meta.get_field('user_groups').related_query_name() - - users_q = Q(**{ - f'{users_query}': self - }) - - user_groups_q = Q(**{ - f'groups__{user_groups_query}': self - }) - - return User.objects.filter(users_q | user_groups_q).distinct() - - def get_all_users(self): - from users.models import User - user_ids = self.users.all().values_list('id', flat=True) - group_ids = self.user_groups.all().values_list('id', flat=True) - - user_ids = list(user_ids) - group_ids = list(group_ids) - - qs1 = User.objects.filter(id__in=user_ids).distinct() - qs2 = User.objects.filter(groups__id__in=group_ids).distinct() - - qs = UnionQuerySet(qs1, qs2) - return qs - - @lazyproperty - def users_amount(self): - return self.users.count() - - @lazyproperty - def user_groups_amount(self): - return self.user_groups.count() diff --git a/apps/perms/serializers/__init__.py b/apps/perms/serializers/__init__.py index 5e26adc99..39f7912a3 100644 --- a/apps/perms/serializers/__init__.py +++ b/apps/perms/serializers/__init__.py @@ -2,4 +2,3 @@ # from .base import * from .asset import * -from .system_user_permission import * diff --git a/apps/perms/serializers/asset/permission.py b/apps/perms/serializers/asset/permission.py index 9476dfaa3..490b9e57a 100644 --- a/apps/perms/serializers/asset/permission.py +++ b/apps/perms/serializers/asset/permission.py @@ -5,9 +5,8 @@ from rest_framework import serializers from django.utils.translation import ugettext_lazy as _ from django.db.models import Q -from orgs.mixins.serializers import BulkOrgResourceModelSerializer from perms.models import AssetPermission, Action -from assets.models import Asset, Node, SystemUser +from assets.models import Asset, Node from users.models import User, UserGroup from ..base import ActionsField, BasePermissionSerializer diff --git a/apps/perms/serializers/asset/user_permission.py b/apps/perms/serializers/asset/user_permission.py index ac42b97ba..f05834f1b 100644 --- a/apps/perms/serializers/asset/user_permission.py +++ b/apps/perms/serializers/asset/user_permission.py @@ -4,35 +4,16 @@ from rest_framework import serializers from django.utils.translation import ugettext_lazy as _ -from assets.models import Node, SystemUser, Asset, Platform +from assets.models import Node, Asset, Platform from perms.serializers.base import ActionsField __all__ = [ 'NodeGrantedSerializer', 'AssetGrantedSerializer', - 'ActionsSerializer', 'AssetSystemUserSerializer', - 'RemoteAppSystemUserSerializer', - 'DatabaseAppSystemUserSerializer', - 'K8sAppSystemUserSerializer', + 'ActionsSerializer', ] -class AssetSystemUserSerializer(serializers.ModelSerializer): - """ - 查看授权的资产系统用户的数据结构,这个和AssetSerializer不同,字段少 - """ - actions = ActionsField(read_only=True) - - class Meta: - model = SystemUser - only_fields = ( - 'id', 'name', 'username', 'priority', 'protocol', 'login_mode', - 'sftp_root', 'username_same_with_user', 'su_enabled', 'su_from', - ) - fields = list(only_fields) + ["actions"] - read_only_fields = fields - - class AssetGrantedSerializer(serializers.ModelSerializer): """ 被授权资产的数据结构 @@ -63,34 +44,3 @@ class NodeGrantedSerializer(serializers.ModelSerializer): class ActionsSerializer(serializers.Serializer): actions = ActionsField(read_only=True) - -# TODO: 删除 -class RemoteAppSystemUserSerializer(serializers.ModelSerializer): - class Meta: - model = SystemUser - only_fields = ( - 'id', 'name', 'username', 'priority', 'protocol', 'login_mode', - ) - fields = list(only_fields) - read_only_fields = fields - - -class DatabaseAppSystemUserSerializer(serializers.ModelSerializer): - class Meta: - model = SystemUser - only_fields = ( - 'id', 'name', 'username', 'priority', 'protocol', 'login_mode', - ) - fields = list(only_fields) - read_only_fields = fields - - -class K8sAppSystemUserSerializer(serializers.ModelSerializer): - class Meta: - model = SystemUser - only_fields = ( - 'id', 'name', 'username', 'priority', 'protocol', 'login_mode', - ) - fields = list(only_fields) - read_only_fields = fields - diff --git a/apps/perms/serializers/system_user_permission.py b/apps/perms/serializers/system_user_permission.py deleted file mode 100644 index def2516d6..000000000 --- a/apps/perms/serializers/system_user_permission.py +++ /dev/null @@ -1,19 +0,0 @@ -from rest_framework import serializers -from ..hands import SystemUser - -__all__ = [ - 'SystemUserSerializer', -] - - -class SystemUserSerializer(serializers.ModelSerializer): - class Meta: - model = SystemUser - fields = [ - 'id', 'name', 'username', 'protocol', - 'login_mode', 'login_mode_display', - 'priority', 'username_same_with_user', - 'auto_push_account', 'cmd_filters', 'sudo', 'shell', 'comment', - 'sftp_root', 'date_created', 'created_by' - ] - ref_name = 'PermedSystemUserSerializer' diff --git a/apps/perms/urls/asset_permission.py b/apps/perms/urls/asset_permission.py index 17fb22990..a39f61a80 100644 --- a/apps/perms/urls/asset_permission.py +++ b/apps/perms/urls/asset_permission.py @@ -73,11 +73,6 @@ user_permission_urlpatterns = [ # Asset System users path('/assets//system-users/', api.UserGrantedAssetSystemUsersForAdminApi.as_view(), name='user-asset-system-users'), path('assets//system-users/', api.MyGrantedAssetSystemUsersApi.as_view(), name='my-asset-system-users'), - - # TODO 要废弃 Expire user permission cache - path('/asset-permissions/cache/', api.UserAssetPermissionsCacheApi.as_view(), - name='user-asset-permission-cache'), - path('asset-permissions/cache/', api.UserAssetPermissionsCacheApi.as_view(), name='my-asset-permission-cache'), ] user_group_permission_urlpatterns = [ diff --git a/apps/perms/utils/asset/permission.py b/apps/perms/utils/asset/permission.py index 8b9991715..a6a68f6eb 100644 --- a/apps/perms/utils/asset/permission.py +++ b/apps/perms/utils/asset/permission.py @@ -5,7 +5,7 @@ from django.db.models import Q from common.utils import get_logger from perms.models import AssetPermission, Action -from perms.hands import Asset, User, UserGroup, SystemUser, Node +from perms.hands import Asset, User, UserGroup, Node from perms.utils.asset.user_permission import get_user_all_asset_perm_ids logger = get_logger(__file__) @@ -83,7 +83,7 @@ def get_asset_system_user_ids_with_actions_by_user(user: User, asset: Asset): return get_asset_system_user_ids_with_actions(asset_perm_ids, asset) -def has_asset_system_permission(user: User, asset: Asset, system_user: SystemUser): +def has_asset_system_permission(user: User, asset: Asset, account: str): systemuser_actions_mapper = get_asset_system_user_ids_with_actions_by_user(user, asset) actions = systemuser_actions_mapper.get(system_user.id, 0) if actions: diff --git a/apps/tickets/models/ticket/apply_application.py b/apps/tickets/models/ticket/apply_application.py deleted file mode 100644 index 6bd721677..000000000 --- a/apps/tickets/models/ticket/apply_application.py +++ /dev/null @@ -1,34 +0,0 @@ -from django.db import models -from django.utils.translation import gettext_lazy as _ - -from .general import Ticket -from applications.const import AppCategory, AppType - -__all__ = ['ApplyApplicationTicket'] - - -class ApplyApplicationTicket(Ticket): - apply_permission_name = models.CharField(max_length=128, verbose_name=_('Permission name')) - # 申请信息 - apply_category = models.CharField( - max_length=16, choices=AppCategory.choices, verbose_name=_('Category') - ) - apply_type = models.CharField( - max_length=16, choices=AppType.choices, verbose_name=_('Type') - ) - apply_applications = models.ManyToManyField( - 'applications.Application', verbose_name=_('Apply applications'), - ) - apply_system_users = models.ManyToManyField( - 'assets.SystemUser', verbose_name=_('Apply system users'), - ) - apply_date_start = models.DateTimeField(verbose_name=_('Date start'), null=True) - apply_date_expired = models.DateTimeField(verbose_name=_('Date expired'), null=True) - - @property - def apply_category_display(self): - return AppCategory.get_label(self.apply_category) - - @property - def apply_type_display(self): - return AppType.get_label(self.apply_type) diff --git a/apps/tickets/models/ticket/apply_asset.py b/apps/tickets/models/ticket/apply_asset.py index c3759dc9a..1b358f5c1 100644 --- a/apps/tickets/models/ticket/apply_asset.py +++ b/apps/tickets/models/ticket/apply_asset.py @@ -17,6 +17,7 @@ class ApplyAssetTicket(Ticket): apply_system_users = models.ManyToManyField( 'assets.SystemUser', verbose_name=_('Apply system users') ) + apply_accounts = models.JSONField(default=list, verbose_name=_('Apply accounts')) apply_actions = models.IntegerField( choices=Action.DB_CHOICES, default=Action.ALL, verbose_name=_('Actions') ) diff --git a/apps/tickets/models/ticket/command_confirm.py b/apps/tickets/models/ticket/command_confirm.py index eb6b838ea..b8c37ec54 100644 --- a/apps/tickets/models/ticket/command_confirm.py +++ b/apps/tickets/models/ticket/command_confirm.py @@ -14,6 +14,7 @@ class ApplyCommandTicket(Ticket): 'assets.SystemUser', on_delete=models.SET_NULL, null=True, verbose_name=_('Run system user') ) + apply_run_account = models.CharField(max_length=128, verbose_name=_('Run account')) apply_run_command = models.CharField(max_length=4096, verbose_name=_('Run command')) apply_from_session = models.ForeignKey( 'terminal.Session', on_delete=models.SET_NULL, diff --git a/apps/tickets/models/ticket/login_asset_confirm.py b/apps/tickets/models/ticket/login_asset_confirm.py index 5e5c53a47..43130e052 100644 --- a/apps/tickets/models/ticket/login_asset_confirm.py +++ b/apps/tickets/models/ticket/login_asset_confirm.py @@ -19,3 +19,4 @@ class ApplyLoginAssetTicket(Ticket): 'assets.SystemUser', on_delete=models.SET_NULL, null=True, verbose_name=_('Login system user'), ) + apply_login_account = models.CharField(max_length=128, verbose_name=_('Login account')) diff --git a/apps/tickets/serializers/ticket/common.py b/apps/tickets/serializers/ticket/common.py index 6957da3b0..8da30e458 100644 --- a/apps/tickets/serializers/ticket/common.py +++ b/apps/tickets/serializers/ticket/common.py @@ -3,7 +3,6 @@ from django.db.models import Model from django.utils.translation import ugettext as _ from rest_framework import serializers -from assets.models import SystemUser from orgs.utils import tmp_to_org from tickets.models import Ticket @@ -54,7 +53,7 @@ class BaseApplyAssetApplicationSerializer(serializers.Serializer): qs = model.objects.filter(id__in=ids, **kwargs).values_list('id', flat=True) return list(qs) - def validate_apply_system_users(self, system_users): + def validate_apply_account(self, system_users): if self.is_final_approval and not system_users: raise serializers.ValidationError(_('This field is required.')) return self.filter_many_to_many_field(SystemUser, system_users) diff --git a/utils/generate_fake_data/resources/assets.py b/utils/generate_fake_data/resources/assets.py index de97a27a9..e14df6932 100644 --- a/utils/generate_fake_data/resources/assets.py +++ b/utils/generate_fake_data/resources/assets.py @@ -5,45 +5,6 @@ import forgery_py from .base import FakeDataGenerator from assets.models import * -from assets.const import Protocol - - -class AdminUsersGenerator(FakeDataGenerator): - resource = 'admin_user' - - def do_generate(self, batch, batch_size): - admin_users = [] - for i in batch: - username = forgery_py.internet.user_name(True) - password = forgery_py.basic.password() - admin_users.append(AdminUser( - name=username.title(), - username=username, - password=password, - org_id=self.org.id, - created_by='Fake', - )) - AdminUser.objects.bulk_create(admin_users, ignore_conflicts=True) - - -class SystemUsersGenerator(FakeDataGenerator): - def do_generate(self, batch, batch_size): - system_users = [] - protocols = list(dict(Protocol.choices).keys()) - for i in batch: - username = forgery_py.internet.user_name(True) - protocol = random.choice(protocols) - name = username.title() - name = f'{name}-{protocol}' - system_users.append(SystemUser( - name=name, - username=username, - password=forgery_py.basic.password(), - protocol=protocol, - org_id=self.org.id, - created_by='Fake', - )) - SystemUser.objects.bulk_create(system_users, ignore_conflicts=True) class NodesGenerator(FakeDataGenerator): @@ -62,7 +23,6 @@ class AssetsGenerator(FakeDataGenerator): node_ids: list def pre_generate(self): - self.admin_user_ids = list(AdminUser.objects.all().values_list('id', flat=True)) self.node_ids = list(Node.objects.all().values_list('id', flat=True)) def set_assets_nodes(self, assets): diff --git a/utils/generate_fake_data/resources/perms.py b/utils/generate_fake_data/resources/perms.py index e3e866feb..d6a5248cb 100644 --- a/utils/generate_fake_data/resources/perms.py +++ b/utils/generate_fake_data/resources/perms.py @@ -19,7 +19,6 @@ class AssetPermissionGenerator(FakeDataGenerator): def pre_generate(self): self.node_ids = list(Node.objects.all().values_list('id', flat=True)) self.asset_ids = list(Asset.objects.all().values_list('id', flat=True)) - self.system_user_ids = list(SystemUser.objects.all().values_list('id', flat=True)) self.user_ids = list(User.objects.all().values_list('id', flat=True)) self.user_group_ids = list(UserGroup.objects.all().values_list('id', flat=True))