Merge pull request #6458 from jumpserver/dev

v2.12.0 rc5
pull/6468/head
Jiangjie.Bai 2021-07-15 18:00:27 +08:00 committed by GitHub
commit 2f0fcddc29
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 42 additions and 57 deletions

View File

@ -42,7 +42,6 @@ class AssetViewSet(FilterAssetByNodeMixin, OrgBulkModelViewSet):
ordering_fields = ("hostname", "ip", "port", "cpu_cores") ordering_fields = ("hostname", "ip", "port", "cpu_cores")
serializer_classes = { serializer_classes = {
'default': serializers.AssetSerializer, 'default': serializers.AssetSerializer,
'single': serializers.AssetVerboseSerializer,
} }
permission_classes = (IsOrgAdminOrAppUser,) permission_classes = (IsOrgAdminOrAppUser,)
extra_filter_backends = [FilterAssetByNodeFilterBackend, LabelFilterBackend, IpInFilterBackend] extra_filter_backends = [FilterAssetByNodeFilterBackend, LabelFilterBackend, IpInFilterBackend]

View File

@ -1,6 +1,8 @@
# Generated by Django 3.1.6 on 2021-06-04 16:46 # Generated by Django 3.1.6 on 2021-06-04 16:46
from django.db import migrations, models, transaction from django.db import migrations, models, transaction
import django.db.models.deletion
from django.db.models import F
def migrate_admin_user_to_system_user(apps, schema_editor): def migrate_admin_user_to_system_user(apps, schema_editor):
@ -40,6 +42,13 @@ def migrate_admin_user_to_system_user(apps, schema_editor):
s.assets.set(assets) s.assets.set(assets)
def migrate_assets_admin_user(apps, schema_editor):
asset_model = apps.get_model("assets", "Asset")
db_alias = schema_editor.connection.alias
assets = asset_model.objects.using(db_alias).all()
assets.update(admin_user=F('_admin_user'))
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
@ -62,5 +71,20 @@ class Migration(migrations.Migration):
name='protocol', name='protocol',
field=models.CharField(choices=[('ssh', 'SSH'), ('rdp', 'RDP'), ('telnet', 'Telnet'), ('vnc', 'VNC'), ('mysql', 'MySQL'), ('oracle', 'Oracle'), ('mariadb', 'MariaDB'), ('postgresql', 'PostgreSQL'), ('k8s', 'K8S')], default='ssh', max_length=16, verbose_name='Protocol'), field=models.CharField(choices=[('ssh', 'SSH'), ('rdp', 'RDP'), ('telnet', 'Telnet'), ('vnc', 'VNC'), ('mysql', 'MySQL'), ('oracle', 'Oracle'), ('mariadb', 'MariaDB'), ('postgresql', 'PostgreSQL'), ('k8s', 'K8S')], default='ssh', max_length=16, verbose_name='Protocol'),
), ),
migrations.RunPython(migrate_admin_user_to_system_user) migrations.RunPython(migrate_admin_user_to_system_user),
migrations.RenameField(
model_name='asset',
old_name='admin_user',
new_name='_admin_user',
),
migrations.AddField(
model_name='asset',
name='admin_user',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='admin_assets', to='assets.systemuser', verbose_name='Admin user'),
),
migrations.RunPython(migrate_assets_admin_user),
migrations.RemoveField(
model_name='asset',
name='_admin_user',
),
] ]

View File

@ -1,6 +1,7 @@
# Generated by Django 3.1.6 on 2021-06-06 03:40 # Generated by Django 3.1.6 on 2021-06-06 03:40
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -14,11 +15,7 @@ class Migration(migrations.Migration):
model_name='systemuser', model_name='systemuser',
name='assets', name='assets',
), ),
migrations.RenameField(
model_name='asset',
old_name='admin_user',
new_name='_admin_user',
),
migrations.AddField( migrations.AddField(
model_name='systemuser', model_name='systemuser',
name='assets', name='assets',

View File

@ -7,7 +7,6 @@ import logging
from functools import reduce from functools import reduce
from collections import OrderedDict from collections import OrderedDict
from django.utils import timezone
from django.db import models from django.db import models
from common.db.models import TextChoices from common.db.models import TextChoices
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -191,7 +190,7 @@ class Asset(AbsConnectivity, ProtocolsMixin, NodesRelationMixin, OrgModelMixin):
is_active = models.BooleanField(default=True, verbose_name=_('Is active')) is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
# Auth # Auth
_admin_user = models.ForeignKey('assets.AdminUser', on_delete=models.PROTECT, null=True, verbose_name=_("Admin user"), related_name='assets') admin_user = models.ForeignKey('assets.SystemUser', on_delete=models.SET_NULL, null=True, verbose_name=_("Admin user"), related_name='admin_assets')
# Some information # Some information
public_ip = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Public IP')) public_ip = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Public IP'))
@ -225,22 +224,15 @@ class Asset(AbsConnectivity, ProtocolsMixin, NodesRelationMixin, OrgModelMixin):
def __str__(self): def __str__(self):
return '{0.hostname}({0.ip})'.format(self) return '{0.hostname}({0.ip})'.format(self)
__admin_user = None def set_admin_user_relation(self):
from .authbook import AuthBook
@property if not self.admin_user:
def admin_user(self):
# 解决每次获取资产管理用户时都是最新的对象
if self.__admin_user is None:
self.__admin_user = self.system_users.filter(type='admin').first()
return self.__admin_user
@admin_user.setter
def admin_user(self, system_user):
if not system_user:
return return
if system_user.type != 'admin': if self.admin_user.type != 'admin':
raise ValidationError('System user should be type admin') raise ValidationError('System user should be type admin')
system_user.assets.add(self)
defaults = {'asset': self, 'systemuser': self.admin_user, 'org_id': self.org_id}
AuthBook.objects.get_or_create(defaults=defaults, asset=self, systemuser=self.admin_user)
@property @property
def admin_user_display(self): def admin_user_display(self):
@ -248,10 +240,6 @@ class Asset(AbsConnectivity, ProtocolsMixin, NodesRelationMixin, OrgModelMixin):
return '' return ''
return str(self.admin_user) return str(self.admin_user)
def remove_admin_user(self):
from ..models import AuthBook
AuthBook.objects.filter(asset=self, systemuser__type='admin').delete()
@property @property
def is_valid(self): def is_valid(self):
warning = '' warning = ''

View File

@ -8,7 +8,7 @@ from orgs.mixins.serializers import BulkOrgResourceModelSerializer
from ..models import Asset, Node, Platform, SystemUser from ..models import Asset, Node, Platform, SystemUser
__all__ = [ __all__ = [
'AssetSerializer', 'AssetSimpleSerializer', 'AssetVerboseSerializer', 'AssetSerializer', 'AssetSimpleSerializer',
'ProtocolsField', 'PlatformSerializer', 'ProtocolsField', 'PlatformSerializer',
'AssetTaskSerializer', 'AssetTaskSerializer',
] ]
@ -62,9 +62,6 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
platform = serializers.SlugRelatedField( platform = serializers.SlugRelatedField(
slug_field='name', queryset=Platform.objects.all(), label=_("Platform") slug_field='name', queryset=Platform.objects.all(), label=_("Platform")
) )
admin_user = serializers.PrimaryKeyRelatedField(
queryset=SystemUser.objects, label=_('Admin user'), write_only=True
)
protocols = ProtocolsField(label=_('Protocols'), required=False, default=['ssh/22']) protocols = ProtocolsField(label=_('Protocols'), required=False, default=['ssh/22'])
domain_display = serializers.ReadOnlyField(source='domain.name', label=_('Domain name')) domain_display = serializers.ReadOnlyField(source='domain.name', label=_('Domain name'))
nodes_display = serializers.ListField(child=serializers.CharField(), label=_('Nodes name'), required=False) nodes_display = serializers.ListField(child=serializers.CharField(), label=_('Nodes name'), required=False)
@ -83,7 +80,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
'hardware_info', 'connectivity', 'date_verified' 'hardware_info', 'connectivity', 'date_verified'
] ]
fields_fk = [ fields_fk = [
'domain', 'domain_display', 'platform', 'admin_user', 'domain', 'domain_display', 'platform', 'admin_user', 'admin_user_display'
] ]
fields_m2m = [ fields_m2m = [
'nodes', 'nodes_display', 'labels', 'nodes', 'nodes_display', 'labels',
@ -112,7 +109,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
@classmethod @classmethod
def setup_eager_loading(cls, queryset): def setup_eager_loading(cls, queryset):
""" Perform necessary eager loading of data. """ """ Perform necessary eager loading of data. """
queryset = queryset.prefetch_related('domain', 'platform') queryset = queryset.prefetch_related('domain', 'platform', 'admin_user')
queryset = queryset.prefetch_related('nodes', 'labels') queryset = queryset.prefetch_related('nodes', 'labels')
return queryset return queryset
@ -147,31 +144,18 @@ class AssetSerializer(BulkOrgResourceModelSerializer):
def create(self, validated_data): def create(self, validated_data):
self.compatible_with_old_protocol(validated_data) self.compatible_with_old_protocol(validated_data)
nodes_display = validated_data.pop('nodes_display', '') nodes_display = validated_data.pop('nodes_display', '')
admin_user = validated_data.pop('admin_user', '')
instance = super().create(validated_data) instance = super().create(validated_data)
self.perform_nodes_display_create(instance, nodes_display) self.perform_nodes_display_create(instance, nodes_display)
instance.admin_user = admin_user
return instance return instance
def update(self, instance, validated_data): def update(self, instance, validated_data):
nodes_display = validated_data.pop('nodes_display', '') nodes_display = validated_data.pop('nodes_display', '')
self.compatible_with_old_protocol(validated_data) self.compatible_with_old_protocol(validated_data)
admin_user = validated_data.pop('admin_user', '')
instance = super().update(instance, validated_data) instance = super().update(instance, validated_data)
self.perform_nodes_display_create(instance, nodes_display) self.perform_nodes_display_create(instance, nodes_display)
instance.admin_user = admin_user
return instance return instance
class AssetVerboseSerializer(AssetSerializer):
admin_user = serializers.PrimaryKeyRelatedField(
queryset=SystemUser.objects, label=_('Admin user')
)
class Meta(AssetSerializer.Meta):
fields = AssetSerializer.Meta.fields + ['admin_user_display']
class PlatformSerializer(serializers.ModelSerializer): class PlatformSerializer(serializers.ModelSerializer):
meta = serializers.DictField(required=False, allow_null=True, label=_('Meta')) meta = serializers.DictField(required=False, allow_null=True, label=_('Meta'))

View File

@ -52,6 +52,8 @@ def on_asset_created_or_update(sender, instance=None, created=False, **kwargs):
if not has_node: if not has_node:
instance.nodes.add(Node.org_root()) instance.nodes.add(Node.org_root())
instance.set_admin_user_relation()
@receiver(m2m_changed, sender=Asset.nodes.through) @receiver(m2m_changed, sender=Asset.nodes.through)
def on_asset_nodes_add(instance, action, reverse, pk_set, **kwargs): def on_asset_nodes_add(instance, action, reverse, pk_set, **kwargs):
@ -96,7 +98,8 @@ def on_asset_nodes_add(instance, action, reverse, pk_set, **kwargs):
asset_ids_to_push.append(asset_id) asset_ids_to_push.append(asset_id)
to_create.append(m2m_model( to_create.append(m2m_model(
systemuser_id=system_user_id, systemuser_id=system_user_id,
asset_id=asset_id asset_id=asset_id,
org_id=instance.org_id
)) ))
if asset_ids_to_push: if asset_ids_to_push:
push_system_user_to_assets.delay(system_user_id, asset_ids_to_push) push_system_user_to_assets.delay(system_user_id, asset_ids_to_push)

View File

@ -4,7 +4,6 @@ from simple_history.signals import pre_create_historical_record
from django.db.models.signals import post_save, pre_save from django.db.models.signals import post_save, pre_save
from common.utils import get_logger from common.utils import get_logger
from orgs.utils import tmp_to_root_org
from ..models import AuthBook, SystemUser from ..models import AuthBook, SystemUser
AuthBookHistory = apps.get_model('assets', 'HistoricalAuthBook') AuthBookHistory = apps.get_model('assets', 'HistoricalAuthBook')
@ -31,15 +30,6 @@ def pre_create_historical_record_callback(sender, history_instance=None, **kwarg
@receiver(post_save, sender=AuthBook) @receiver(post_save, sender=AuthBook)
def on_authbook_post_create(sender, instance, **kwargs): def on_authbook_post_create(sender, instance, **kwargs):
# 去掉这个资产的管理用户
if instance.systemuser and instance.systemuser.is_admin_user:
with tmp_to_root_org():
deleted_count, other = AuthBook.objects.filter(
asset=instance.asset,
systemuser__type=SystemUser.Type.admin
).exclude(id=instance.id).delete()
logger.debug('Remove asset old admin user: {}'.format(deleted_count))
if not instance.systemuser: if not instance.systemuser:
instance.sync_to_system_user_account() instance.sync_to_system_user_account()