mirror of https://github.com/jumpserver/jumpserver
perf: 修改资产名称
parent
4021baf758
commit
d402ba5d92
|
@ -61,7 +61,7 @@ class LoginAssetACL(BaseACL, OrgModelMixin):
|
||||||
@classmethod
|
@classmethod
|
||||||
def filter_asset(cls, asset, queryset):
|
def filter_asset(cls, asset, queryset):
|
||||||
queryset = queryset.filter(
|
queryset = queryset.filter(
|
||||||
Q(assets__hostname_group__contains=asset.hostname) |
|
Q(assets__hostname_group__contains=asset.name) |
|
||||||
Q(assets__hostname_group__contains='*')
|
Q(assets__hostname_group__contains='*')
|
||||||
)
|
)
|
||||||
ids = [q.id for q in queryset if contains_ip(asset.ip, q.assets.get('ip_group', []))]
|
ids = [q.id for q in queryset if contains_ip(asset.ip, q.assets.get('ip_group', []))]
|
||||||
|
|
|
@ -21,7 +21,7 @@ __all__ = ['AccountFilterSet', 'AccountViewSet', 'AccountSecretsViewSet', 'Accou
|
||||||
class AccountFilterSet(BaseFilterSet):
|
class AccountFilterSet(BaseFilterSet):
|
||||||
username = filters.CharFilter(method='do_nothing')
|
username = filters.CharFilter(method='do_nothing')
|
||||||
ip = filters.CharFilter(field_name='ip', lookup_expr='exact')
|
ip = filters.CharFilter(field_name='ip', lookup_expr='exact')
|
||||||
hostname = filters.CharFilter(field_name='hostname', lookup_expr='exact')
|
hostname = filters.CharFilter(field_name='name', lookup_expr='exact')
|
||||||
node = filters.CharFilter(method='do_nothing')
|
node = filters.CharFilter(method='do_nothing')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -58,8 +58,8 @@ class AccountFilterSet(BaseFilterSet):
|
||||||
|
|
||||||
class AccountViewSet(OrgBulkModelViewSet):
|
class AccountViewSet(OrgBulkModelViewSet):
|
||||||
model = Account
|
model = Account
|
||||||
filterset_fields = ("username", "asset", 'ip', 'hostname')
|
filterset_fields = ("username", "asset", 'ip', 'name')
|
||||||
search_fields = ('username', 'ip', 'hostname')
|
search_fields = ('username', 'ip', 'name')
|
||||||
filterset_class = AccountFilterSet
|
filterset_class = AccountFilterSet
|
||||||
serializer_classes = {
|
serializer_classes = {
|
||||||
'default': serializers.AccountSerializer,
|
'default': serializers.AccountSerializer,
|
||||||
|
|
|
@ -27,15 +27,15 @@ class AssetViewSet(SuggestionMixin, FilterAssetByNodeMixin, OrgBulkModelViewSet)
|
||||||
"""
|
"""
|
||||||
model = Asset
|
model = Asset
|
||||||
filterset_fields = {
|
filterset_fields = {
|
||||||
'hostname': ['exact'],
|
'name': ['exact'],
|
||||||
'ip': ['exact'],
|
'ip': ['exact'],
|
||||||
'system_users__id': ['exact'],
|
'system_users__id': ['exact'],
|
||||||
'is_active': ['exact'],
|
'is_active': ['exact'],
|
||||||
'protocols': ['exact', 'icontains']
|
'protocols': ['exact', 'icontains']
|
||||||
}
|
}
|
||||||
search_fields = ("hostname", "ip")
|
search_fields = ("name", "ip")
|
||||||
ordering_fields = ("hostname", "ip", "port")
|
ordering_fields = ("name", "ip", "port")
|
||||||
ordering = ('hostname', )
|
ordering = ('name', )
|
||||||
serializer_classes = (
|
serializer_classes = (
|
||||||
('default', serializers.AssetSerializer),
|
('default', serializers.AssetSerializer),
|
||||||
('suggestion', serializers.MiniAssetSerializer),
|
('suggestion', serializers.MiniAssetSerializer),
|
||||||
|
|
|
@ -56,7 +56,7 @@ class SerializeToTreeNodeMixin:
|
||||||
data = [
|
data = [
|
||||||
{
|
{
|
||||||
'id': str(asset.id),
|
'id': str(asset.id),
|
||||||
'name': asset.hostname,
|
'name': asset.name,
|
||||||
'title': asset.ip,
|
'title': asset.ip,
|
||||||
'pId': get_pid(asset),
|
'pId': get_pid(asset),
|
||||||
'isParent': False,
|
'isParent': False,
|
||||||
|
@ -67,7 +67,7 @@ class SerializeToTreeNodeMixin:
|
||||||
'type': 'asset',
|
'type': 'asset',
|
||||||
'data': {
|
'data': {
|
||||||
'id': asset.id,
|
'id': asset.id,
|
||||||
'hostname': asset.hostname,
|
'name': asset.name,
|
||||||
'ip': asset.ip,
|
'ip': asset.ip,
|
||||||
'protocols': asset.protocols_as_list,
|
'protocols': asset.protocols_as_list,
|
||||||
'platform': asset.platform_base,
|
'platform': asset.platform_base,
|
||||||
|
|
|
@ -192,7 +192,7 @@ class NodeChildrenAsTreeApi(SerializeToTreeNodeMixin, NodeChildrenApi):
|
||||||
if not self.instance or not include_assets:
|
if not self.instance or not include_assets:
|
||||||
return []
|
return []
|
||||||
assets = self.instance.get_assets().only(
|
assets = self.instance.get_assets().only(
|
||||||
"id", "hostname", "ip", "os", "platform_id",
|
"id", "name", "ip", "os", "platform_id",
|
||||||
"org_id", "protocols", "is_active",
|
"org_id", "protocols", "is_active",
|
||||||
).prefetch_related('platform')
|
).prefetch_related('platform')
|
||||||
return self.serialize_assets(assets, self.instance.key)
|
return self.serialize_assets(assets, self.instance.key)
|
||||||
|
|
|
@ -40,6 +40,7 @@ class Migration(migrations.Migration):
|
||||||
('os_arch', models.CharField(blank=True, max_length=16, null=True, verbose_name='OS arch')),
|
('os_arch', models.CharField(blank=True, max_length=16, null=True, verbose_name='OS arch')),
|
||||||
('hostname_raw', models.CharField(blank=True, max_length=128, null=True, verbose_name='Hostname raw')),
|
('hostname_raw', models.CharField(blank=True, max_length=128, null=True, verbose_name='Hostname raw')),
|
||||||
('host', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.host', verbose_name='Host')),
|
('host', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='assets.host', verbose_name='Host')),
|
||||||
|
('number', models.CharField(blank=True, max_length=128, null=True, verbose_name='Asset number')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'verbose_name': 'DeviceInfo',
|
'verbose_name': 'DeviceInfo',
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Generated by Django 3.2.14 on 2022-08-11 06:49
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('assets', '0106_auto_20220811_1358'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='asset',
|
||||||
|
name='_protocols',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='asset',
|
||||||
|
name='admin_user',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='asset',
|
||||||
|
name='category',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='asset',
|
||||||
|
name='number',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='asset',
|
||||||
|
name='public_ip',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='asset',
|
||||||
|
name='type',
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,41 @@
|
||||||
|
# Generated by Django 3.2.14 on 2022-08-11 07:11
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('assets', '0107_auto_20220811_1449'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='asset',
|
||||||
|
options={'ordering': ['name'], 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), ('test_assetconnectivity', 'Can test asset connectivity'), ('push_assetsystemuser', 'Can push system user to asset'), ('match_asset', 'Can match asset'), ('add_assettonode', 'Add asset to node'), ('move_assettonode', 'Move asset to node')], 'verbose_name': 'Asset'},
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='asset',
|
||||||
|
old_name='hostname',
|
||||||
|
new_name='name',
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='asset',
|
||||||
|
name='date_updated',
|
||||||
|
field=models.DateTimeField(auto_now=True, verbose_name='Date updated'),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='asset',
|
||||||
|
name='updated_by',
|
||||||
|
field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Updated by'),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='asset',
|
||||||
|
name='created_by',
|
||||||
|
field=models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by'),
|
||||||
|
),
|
||||||
|
migrations.AlterUniqueTogether(
|
||||||
|
name='asset',
|
||||||
|
unique_together={('org_id', 'name')},
|
||||||
|
),
|
||||||
|
]
|
|
@ -15,3 +15,4 @@ from .backup import *
|
||||||
from ._authbook import *
|
from ._authbook import *
|
||||||
from .protocol import *
|
from .protocol import *
|
||||||
from .cmd_filter import *
|
from .cmd_filter import *
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ class Account(BaseUser, AbsConnectivity):
|
||||||
]
|
]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '{}@{}'.format(self.username, self.asset.hostname)
|
return '{}@{}'.format(self.username, self.asset.name)
|
||||||
|
|
||||||
|
|
||||||
class AccountTemplate(JMSBaseModel):
|
class AccountTemplate(JMSBaseModel):
|
||||||
|
|
|
@ -8,4 +8,4 @@ class Cloud(Asset):
|
||||||
cluster = models.CharField(max_length=4096, verbose_name=_("Cluster"))
|
cluster = models.CharField(max_length=4096, verbose_name=_("Cluster"))
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.hostname
|
return self.name
|
||||||
|
|
|
@ -2,16 +2,14 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
|
|
||||||
import uuid
|
|
||||||
import logging
|
import logging
|
||||||
|
import uuid
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
from common.utils import lazyproperty
|
from orgs.mixins.models import OrgManager, JMSOrgBaseModel
|
||||||
from orgs.mixins.models import OrgModelMixin, OrgManager
|
|
||||||
from assets.const import Category, AllTypes
|
|
||||||
from ..platform import Platform
|
from ..platform import Platform
|
||||||
from ..base import AbsConnectivity
|
from ..base import AbsConnectivity
|
||||||
|
|
||||||
|
@ -67,14 +65,10 @@ class NodesRelationMixin:
|
||||||
return nodes
|
return nodes
|
||||||
|
|
||||||
|
|
||||||
class Asset(AbsConnectivity, NodesRelationMixin, OrgModelMixin):
|
class Asset(AbsConnectivity, NodesRelationMixin, JMSOrgBaseModel):
|
||||||
Category = Category
|
|
||||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||||
hostname = models.CharField(max_length=128, verbose_name=_('Hostname'))
|
name = models.CharField(max_length=128, verbose_name=_('Hostname'))
|
||||||
ip = models.CharField(max_length=128, verbose_name=_('IP'), db_index=True)
|
ip = models.CharField(max_length=128, verbose_name=_('IP'), db_index=True)
|
||||||
category = models.CharField(max_length=16, choices=Category.choices, verbose_name=_("Category"))
|
|
||||||
type = models.CharField(max_length=128, choices=AllTypes.choices, verbose_name=_("Type"))
|
|
||||||
_protocols = models.CharField(max_length=128, default='ssh/22', blank=True, verbose_name=_("Protocols"))
|
|
||||||
protocols = models.ManyToManyField('Protocol', verbose_name=_("Protocols"), blank=True)
|
protocols = models.ManyToManyField('Protocol', verbose_name=_("Protocols"), blank=True)
|
||||||
platform = models.ForeignKey(Platform, default=Platform.default, on_delete=models.PROTECT,
|
platform = models.ForeignKey(Platform, default=Platform.default, on_delete=models.PROTECT,
|
||||||
verbose_name=_("Platform"), related_name='assets')
|
verbose_name=_("Platform"), related_name='assets')
|
||||||
|
@ -84,16 +78,7 @@ class Asset(AbsConnectivity, NodesRelationMixin, OrgModelMixin):
|
||||||
verbose_name=_("Nodes"))
|
verbose_name=_("Nodes"))
|
||||||
is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
|
is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
|
||||||
|
|
||||||
# Auth
|
|
||||||
admin_user = models.ForeignKey('assets.SystemUser', on_delete=models.SET_NULL, null=True,
|
|
||||||
verbose_name=_("Admin user"), related_name='admin_assets')
|
|
||||||
# Some information
|
|
||||||
public_ip = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Public IP'))
|
|
||||||
number = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Asset number'))
|
|
||||||
|
|
||||||
labels = models.ManyToManyField('assets.Label', blank=True, related_name='assets', verbose_name=_("Labels"))
|
labels = models.ManyToManyField('assets.Label', blank=True, related_name='assets', verbose_name=_("Labels"))
|
||||||
created_by = models.CharField(max_length=128, 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(default='', blank=True, verbose_name=_('Comment'))
|
comment = models.TextField(default='', blank=True, verbose_name=_('Comment'))
|
||||||
|
|
||||||
objects = AssetManager.from_queryset(AssetQuerySet)()
|
objects = AssetManager.from_queryset(AssetQuerySet)()
|
||||||
|
@ -104,12 +89,6 @@ class Asset(AbsConnectivity, NodesRelationMixin, OrgModelMixin):
|
||||||
def get_target_ip(self):
|
def get_target_ip(self):
|
||||||
return self.ip
|
return self.ip
|
||||||
|
|
||||||
@property
|
|
||||||
def admin_user_display(self):
|
|
||||||
if not self.admin_user:
|
|
||||||
return ''
|
|
||||||
return str(self.admin_user)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_valid(self):
|
def is_valid(self):
|
||||||
warning = ''
|
warning = ''
|
||||||
|
@ -119,17 +98,6 @@ class Asset(AbsConnectivity, NodesRelationMixin, OrgModelMixin):
|
||||||
return False, warning
|
return False, warning
|
||||||
return True, warning
|
return True, warning
|
||||||
|
|
||||||
@lazyproperty
|
|
||||||
def platform_base(self):
|
|
||||||
return self.platform.type
|
|
||||||
|
|
||||||
@lazyproperty
|
|
||||||
def admin_user_username(self):
|
|
||||||
"""求可连接性时,直接用用户名去取,避免再查一次admin user
|
|
||||||
serializer 中直接通过annotate方式返回了这个
|
|
||||||
"""
|
|
||||||
return self.admin_user.username
|
|
||||||
|
|
||||||
def nodes_display(self):
|
def nodes_display(self):
|
||||||
names = []
|
names = []
|
||||||
for n in self.nodes.all():
|
for n in self.nodes.all():
|
||||||
|
@ -142,12 +110,20 @@ class Asset(AbsConnectivity, NodesRelationMixin, OrgModelMixin):
|
||||||
names.append(n.name + ':' + n.value)
|
names.append(n.name + ':' + n.value)
|
||||||
return names
|
return names
|
||||||
|
|
||||||
|
@property
|
||||||
|
def type(self):
|
||||||
|
return self.platform.type
|
||||||
|
|
||||||
|
@property
|
||||||
|
def category(self):
|
||||||
|
return self.platform.category
|
||||||
|
|
||||||
def as_node(self):
|
def as_node(self):
|
||||||
from assets.models import Node
|
from assets.models import Node
|
||||||
fake_node = Node()
|
fake_node = Node()
|
||||||
fake_node.id = self.id
|
fake_node.id = self.id
|
||||||
fake_node.key = self.id
|
fake_node.key = self.id
|
||||||
fake_node.value = self.hostname
|
fake_node.value = self.name
|
||||||
fake_node.asset = self
|
fake_node.asset = self
|
||||||
fake_node.is_node = False
|
fake_node.is_node = False
|
||||||
return fake_node
|
return fake_node
|
||||||
|
@ -155,13 +131,14 @@ class Asset(AbsConnectivity, NodesRelationMixin, OrgModelMixin):
|
||||||
def as_tree_node(self, parent_node):
|
def as_tree_node(self, parent_node):
|
||||||
from common.tree import TreeNode
|
from common.tree import TreeNode
|
||||||
icon_skin = 'file'
|
icon_skin = 'file'
|
||||||
if self.platform_base.lower() == 'windows':
|
platform_type = self.platform.type.lower()
|
||||||
|
if platform_type == 'windows':
|
||||||
icon_skin = 'windows'
|
icon_skin = 'windows'
|
||||||
elif self.platform_base.lower() == 'linux':
|
elif platform_type == 'linux':
|
||||||
icon_skin = 'linux'
|
icon_skin = 'linux'
|
||||||
data = {
|
data = {
|
||||||
'id': str(self.id),
|
'id': str(self.id),
|
||||||
'name': self.hostname,
|
'name': self.name,
|
||||||
'title': self.ip,
|
'title': self.ip,
|
||||||
'pId': parent_node.key,
|
'pId': parent_node.key,
|
||||||
'isParent': False,
|
'isParent': False,
|
||||||
|
@ -171,10 +148,9 @@ class Asset(AbsConnectivity, NodesRelationMixin, OrgModelMixin):
|
||||||
'type': 'asset',
|
'type': 'asset',
|
||||||
'data': {
|
'data': {
|
||||||
'id': self.id,
|
'id': self.id,
|
||||||
'hostname': self.hostname,
|
'name': self.name,
|
||||||
'ip': self.ip,
|
'ip': self.ip,
|
||||||
'protocols': self.protocols,
|
'protocols': self.protocols,
|
||||||
'platform': self.platform_base,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,20 +164,10 @@ class Asset(AbsConnectivity, NodesRelationMixin, OrgModelMixin):
|
||||||
system_users = SystemUser.objects.filter(id__in=system_user_ids)
|
system_users = SystemUser.objects.filter(id__in=system_user_ids)
|
||||||
return system_users
|
return system_users
|
||||||
|
|
||||||
def save(self, *args, **kwargs):
|
|
||||||
self.type = self.platform.type
|
|
||||||
self.category = self.platform.category
|
|
||||||
return super().save(*args, **kwargs)
|
|
||||||
|
|
||||||
# TODO 暂时为了接口文档添加
|
|
||||||
@property
|
|
||||||
def os(self):
|
|
||||||
return
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
unique_together = [('org_id', 'hostname')]
|
unique_together = [('org_id', 'name')]
|
||||||
verbose_name = _("Asset")
|
verbose_name = _("Asset")
|
||||||
ordering = ["hostname", ]
|
ordering = ["name", ]
|
||||||
permissions = [
|
permissions = [
|
||||||
('refresh_assethardwareinfo', _('Can refresh asset hardware info')),
|
('refresh_assethardwareinfo', _('Can refresh asset hardware info')),
|
||||||
('test_assetconnectivity', _('Can test asset connectivity')),
|
('test_assetconnectivity', _('Can test asset connectivity')),
|
||||||
|
|
|
@ -8,7 +8,7 @@ class Database(Asset):
|
||||||
db_name = models.CharField(max_length=1024, verbose_name=_("Database"), blank=True)
|
db_name = models.CharField(max_length=1024, verbose_name=_("Database"), blank=True)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '{}({}://{}/{})'.format(self.hostname, self.type, self.ip, self.db_name)
|
return '{}({}://{}/{})'.format(self.name, self.type, self.ip, self.db_name)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Database")
|
verbose_name = _("Database")
|
||||||
|
|
|
@ -31,6 +31,7 @@ class DeviceInfo(CommonModelMixin):
|
||||||
os_version = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('OS version'))
|
os_version = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('OS version'))
|
||||||
os_arch = models.CharField(max_length=16, blank=True, null=True, verbose_name=_('OS arch'))
|
os_arch = models.CharField(max_length=16, blank=True, null=True, verbose_name=_('OS arch'))
|
||||||
hostname_raw = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Hostname raw'))
|
hostname_raw = models.CharField(max_length=128, blank=True, null=True, verbose_name=_('Hostname raw'))
|
||||||
|
number = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Asset number'))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cpu_info(self):
|
def cpu_info(self):
|
||||||
|
@ -52,7 +53,7 @@ class DeviceInfo(CommonModelMixin):
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '{} of {}'.format(self.hardware_info, self.host.hostname)
|
return '{} of {}'.format(self.hardware_info, self.host.name)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("DeviceInfo")
|
verbose_name = _("DeviceInfo")
|
||||||
|
|
|
@ -21,7 +21,7 @@ class GatheredUser(OrgModelMixin):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hostname(self):
|
def hostname(self):
|
||||||
return self.asset.hostname
|
return self.asset.name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ip(self):
|
def ip(self):
|
||||||
|
@ -32,7 +32,7 @@ class GatheredUser(OrgModelMixin):
|
||||||
ordering = ['asset']
|
ordering = ['asset']
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '{}: {}'.format(self.asset.hostname, self.username)
|
return '{}: {}'.format(self.asset.name, self.username)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ from common.drf.serializers import SecretReadableMixin
|
||||||
|
|
||||||
class AccountSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
class AccountSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
||||||
ip = serializers.ReadOnlyField(label=_("IP"))
|
ip = serializers.ReadOnlyField(label=_("IP"))
|
||||||
hostname = serializers.ReadOnlyField(label=_("Hostname"))
|
asset = serializers.ReadOnlyField(label=_("Asset"))
|
||||||
platform = serializers.ReadOnlyField(label=_("Platform"))
|
platform = serializers.ReadOnlyField(label=_("Platform"))
|
||||||
date_created = serializers.DateTimeField(
|
date_created = serializers.DateTimeField(
|
||||||
label=_('Date created'), format="%Y/%m/%d %H:%M:%S", read_only=True
|
label=_('Date created'), format="%Y/%m/%d %H:%M:%S", read_only=True
|
||||||
|
@ -24,7 +24,7 @@ class AccountSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Account
|
model = Account
|
||||||
fields_mini = [
|
fields_mini = [
|
||||||
'id', 'type', 'username', 'ip', 'hostname',
|
'id', 'type', 'username', 'ip', 'name',
|
||||||
'platform', 'version'
|
'platform', 'version'
|
||||||
]
|
]
|
||||||
fields_write_only = ['password', 'private_key', 'public_key', 'passphrase']
|
fields_write_only = ['password', 'private_key', 'public_key', 'passphrase']
|
||||||
|
@ -59,14 +59,14 @@ class AccountSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializer):
|
||||||
""" Perform necessary eager loading of data. """
|
""" Perform necessary eager loading of data. """
|
||||||
queryset = queryset.prefetch_related('asset')\
|
queryset = queryset.prefetch_related('asset')\
|
||||||
.annotate(ip=F('asset__ip')) \
|
.annotate(ip=F('asset__ip')) \
|
||||||
.annotate(hostname=F('asset__hostname'))
|
.annotate(asset=F('asset__name'))
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
class AccountSecretSerializer(SecretReadableMixin, AccountSerializer):
|
class AccountSecretSerializer(SecretReadableMixin, AccountSerializer):
|
||||||
class Meta(AccountSerializer.Meta):
|
class Meta(AccountSerializer.Meta):
|
||||||
fields_backup = [
|
fields_backup = [
|
||||||
'hostname', 'ip', 'platform', 'protocols', 'username', 'password',
|
'name', 'ip', 'platform', 'protocols', 'username', 'password',
|
||||||
'private_key', 'public_key', 'date_created', 'date_updated', 'version'
|
'private_key', 'public_key', 'date_created', 'date_updated', 'version'
|
||||||
]
|
]
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
|
|
|
@ -14,7 +14,7 @@ class DeviceSerializer(serializers.ModelSerializer):
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'vendor', 'model', 'sn', 'cpu_model', 'cpu_count',
|
'id', 'vendor', 'model', 'sn', 'cpu_model', 'cpu_count',
|
||||||
'cpu_cores', 'cpu_vcpus', 'memory', 'disk_total', 'disk_info',
|
'cpu_cores', 'cpu_vcpus', 'memory', 'disk_total', 'disk_info',
|
||||||
'os', 'os_version', 'os_arch', 'hostname_raw',
|
'os', 'os_version', 'os_arch', 'hostname_raw', 'number',
|
||||||
'cpu_info', 'hardware_info', 'date_updated'
|
'cpu_info', 'hardware_info', 'date_updated'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ class DatabaseSerializer(AssetSerializer):
|
||||||
class Meta(AssetSerializer.Meta):
|
class Meta(AssetSerializer.Meta):
|
||||||
model = Database
|
model = Database
|
||||||
fields_mini = [
|
fields_mini = [
|
||||||
'id', 'hostname', 'ip', 'port', 'db_name',
|
'id', 'name', 'ip', 'port', 'db_name',
|
||||||
]
|
]
|
||||||
fields_small = fields_mini + [
|
fields_small = fields_mini + [
|
||||||
'is_active', 'comment',
|
'is_active', 'comment',
|
||||||
|
|
|
@ -57,8 +57,6 @@ class AssetNodesSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
|
|
||||||
class AssetSerializer(JMSWritableNestedModelSerializer):
|
class AssetSerializer(JMSWritableNestedModelSerializer):
|
||||||
# category = ChoiceDisplayField(choices=Category.choices, required=False)
|
|
||||||
# type = ChoiceDisplayField(choices=AllTypes.choices, required=False)
|
|
||||||
domain = AssetDomainSerializer(required=False)
|
domain = AssetDomainSerializer(required=False)
|
||||||
platform = AssetPlatformSerializer(required=False)
|
platform = AssetPlatformSerializer(required=False)
|
||||||
labels = AssetLabelSerializer(many=True, required=False)
|
labels = AssetLabelSerializer(many=True, required=False)
|
||||||
|
@ -72,10 +70,10 @@ class AssetSerializer(JMSWritableNestedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Asset
|
model = Asset
|
||||||
fields_mini = [
|
fields_mini = [
|
||||||
'id', 'hostname', 'ip',
|
'id', 'name', 'ip',
|
||||||
]
|
]
|
||||||
fields_small = fields_mini + [
|
fields_small = fields_mini + [
|
||||||
'is_active', 'number', 'comment',
|
'is_active', 'comment',
|
||||||
]
|
]
|
||||||
fields_fk = [
|
fields_fk = [
|
||||||
'domain', 'platform', 'platform',
|
'domain', 'platform', 'platform',
|
||||||
|
@ -90,7 +88,7 @@ class AssetSerializer(JMSWritableNestedModelSerializer):
|
||||||
]
|
]
|
||||||
fields = fields_small + fields_fk + fields_m2m + read_only_fields
|
fields = fields_small + fields_fk + fields_m2m + read_only_fields
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
'hostname': {'label': _("Name")},
|
'name': {'label': _("Name")},
|
||||||
'ip': {'label': _('IP/Host')},
|
'ip': {'label': _('IP/Host')},
|
||||||
'protocol': {'write_only': True},
|
'protocol': {'write_only': True},
|
||||||
'port': {'write_only': True},
|
'port': {'write_only': True},
|
||||||
|
@ -102,12 +100,6 @@ class AssetSerializer(JMSWritableNestedModelSerializer):
|
||||||
self.accounts_data = data.pop('accounts', [])
|
self.accounts_data = data.pop('accounts', [])
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
def validate_type(self, value):
|
|
||||||
return value
|
|
||||||
|
|
||||||
def validate_category(self, value):
|
|
||||||
return value
|
|
||||||
|
|
||||||
@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. """
|
||||||
|
@ -164,7 +156,7 @@ class AssetSimpleSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Asset
|
model = Asset
|
||||||
fields = [
|
fields = [
|
||||||
'id', 'hostname', 'ip', 'port',
|
'id', 'name', 'ip', 'port',
|
||||||
'connectivity', 'date_verified'
|
'connectivity', 'date_verified'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,10 @@ class GatheredUserSerializer(OrgResourceModelSerializerMixin):
|
||||||
'present',
|
'present',
|
||||||
'date_last_login', 'date_created', 'date_updated'
|
'date_last_login', 'date_created', 'date_updated'
|
||||||
]
|
]
|
||||||
fields_fk = ['asset', 'hostname', 'ip']
|
fields_fk = ['asset', 'name', 'ip']
|
||||||
fields = fields_small + fields_fk
|
fields = fields_small + fields_fk
|
||||||
read_only_fields = fields
|
read_only_fields = fields
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
'hostname': {'label': _("Hostname")},
|
'name': {'label': _("Hostname")},
|
||||||
'ip': {'label': 'IP'},
|
'ip': {'label': 'IP'},
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ def get_test_account_connectivity_tasks(asset):
|
||||||
else:
|
else:
|
||||||
msg = _(
|
msg = _(
|
||||||
"The asset {} system platform {} does not "
|
"The asset {} system platform {} does not "
|
||||||
"support run Ansible tasks".format(asset.hostname, asset.platform)
|
"support run Ansible tasks".format(asset.name, asset.platform)
|
||||||
)
|
)
|
||||||
logger.info(msg)
|
logger.info(msg)
|
||||||
tasks = []
|
tasks = []
|
||||||
|
|
|
@ -26,7 +26,7 @@ def set_assets_accounts_connectivity(assets, results_summary):
|
||||||
asset_hostnames_ok = results_summary.get('contacted', {}).keys()
|
asset_hostnames_ok = results_summary.get('contacted', {}).keys()
|
||||||
|
|
||||||
for asset in assets:
|
for asset in assets:
|
||||||
if asset.hostname in asset_hostnames_ok:
|
if asset.name in asset_hostnames_ok:
|
||||||
asset_ids_ok.add(asset.id)
|
asset_ids_ok.add(asset.id)
|
||||||
else:
|
else:
|
||||||
asset_ids_failed.add(asset.id)
|
asset_ids_failed.add(asset.id)
|
||||||
|
@ -100,7 +100,7 @@ def test_asset_connectivity_manual(asset):
|
||||||
|
|
||||||
@shared_task(queue="ansible")
|
@shared_task(queue="ansible")
|
||||||
def test_assets_connectivity_manual(assets):
|
def test_assets_connectivity_manual(assets):
|
||||||
task_name = gettext_noop("Test assets connectivity: ") + str([asset.hostname for asset in assets])
|
task_name = gettext_noop("Test assets connectivity: ") + str([asset.name for asset in assets])
|
||||||
summary = test_asset_connectivity_util(assets, task_name=task_name)
|
summary = test_asset_connectivity_util(assets, task_name=task_name)
|
||||||
|
|
||||||
if summary.get('dark'):
|
if summary.get('dark'):
|
||||||
|
|
|
@ -39,7 +39,7 @@ def set_assets_hardware_info(assets, result, **kwargs):
|
||||||
success_result = result_raw.get('ok', {})
|
success_result = result_raw.get('ok', {})
|
||||||
|
|
||||||
for asset in assets:
|
for asset in assets:
|
||||||
hostname = asset.hostname
|
hostname = asset.name
|
||||||
info = success_result.get(hostname, {})
|
info = success_result.get(hostname, {})
|
||||||
info = info.get('setup', {}).get('ansible_facts', {})
|
info = info.get('setup', {}).get('ansible_facts', {})
|
||||||
if not info:
|
if not info:
|
||||||
|
@ -111,13 +111,13 @@ def update_assets_hardware_info_util(assets, task_name=None):
|
||||||
|
|
||||||
@shared_task(queue="ansible")
|
@shared_task(queue="ansible")
|
||||||
def update_asset_hardware_info_manual(asset):
|
def update_asset_hardware_info_manual(asset):
|
||||||
task_name = gettext_noop("Update asset hardware info: ") + str(asset.hostname)
|
task_name = gettext_noop("Update asset hardware info: ") + str(asset.name)
|
||||||
update_assets_hardware_info_util([asset], task_name=task_name)
|
update_assets_hardware_info_util([asset], task_name=task_name)
|
||||||
|
|
||||||
|
|
||||||
@shared_task(queue="ansible")
|
@shared_task(queue="ansible")
|
||||||
def update_assets_hardware_info_manual(assets):
|
def update_assets_hardware_info_manual(assets):
|
||||||
task_name = gettext_noop("Update assets hardware info: ") + str([asset.hostname for asset in assets])
|
task_name = gettext_noop("Update assets hardware info: ") + str([asset.name for asset in assets])
|
||||||
update_assets_hardware_info_util(assets, task_name=task_name)
|
update_assets_hardware_info_util(assets, task_name=task_name)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ def parse_windows_result_to_users(result):
|
||||||
|
|
||||||
|
|
||||||
def add_asset_users(assets, results):
|
def add_asset_users(assets, results):
|
||||||
assets_map = {a.hostname: a for a in assets}
|
assets_map = {a.name: a for a in assets}
|
||||||
parser_map = {
|
parser_map = {
|
||||||
'linux': parse_linux_result_to_users,
|
'linux': parse_linux_result_to_users,
|
||||||
'windows': parse_windows_result_to_users
|
'windows': parse_windows_result_to_users
|
||||||
|
|
|
@ -160,7 +160,7 @@ class ConnectionTokenMixin:
|
||||||
rdp_options['audiomode:i'] = self.parse_env_bool('JUMPSERVER_DISABLE_AUDIO', 'false', '2', '0')
|
rdp_options['audiomode:i'] = self.parse_env_bool('JUMPSERVER_DISABLE_AUDIO', 'false', '2', '0')
|
||||||
|
|
||||||
if token.asset:
|
if token.asset:
|
||||||
name = token.asset.hostname
|
name = token.asset.name
|
||||||
elif token.application and token.application.category_remote_app:
|
elif token.application and token.application.category_remote_app:
|
||||||
app = '||jmservisor'
|
app = '||jmservisor'
|
||||||
name = token.application.name
|
name = token.application.name
|
||||||
|
@ -182,7 +182,7 @@ class ConnectionTokenMixin:
|
||||||
|
|
||||||
def get_ssh_token(self, token: ConnectionToken):
|
def get_ssh_token(self, token: ConnectionToken):
|
||||||
if token.asset:
|
if token.asset:
|
||||||
name = token.asset.hostname
|
name = token.asset.name
|
||||||
elif token.application:
|
elif token.application:
|
||||||
name = token.application.name
|
name = token.application.name
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -124,7 +124,7 @@ class ConnectionTokenAssetSerializer(serializers.ModelSerializer):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Asset
|
model = Asset
|
||||||
fields = ['id', 'hostname', 'ip', 'protocols', 'org_id']
|
fields = ['id', 'name', 'ip', 'protocols', 'org_id']
|
||||||
|
|
||||||
|
|
||||||
class ConnectionTokenSystemUserSerializer(serializers.ModelSerializer):
|
class ConnectionTokenSystemUserSerializer(serializers.ModelSerializer):
|
||||||
|
|
|
@ -315,7 +315,7 @@ class Config(dict):
|
||||||
'TERMINAL_PASSWORD_AUTH': True,
|
'TERMINAL_PASSWORD_AUTH': True,
|
||||||
'TERMINAL_PUBLIC_KEY_AUTH': True,
|
'TERMINAL_PUBLIC_KEY_AUTH': True,
|
||||||
'TERMINAL_HEARTBEAT_INTERVAL': 20,
|
'TERMINAL_HEARTBEAT_INTERVAL': 20,
|
||||||
'TERMINAL_ASSET_LIST_SORT_BY': 'hostname',
|
'TERMINAL_ASSET_LIST_SORT_BY': 'name',
|
||||||
'TERMINAL_ASSET_LIST_PAGE_SIZE': 'auto',
|
'TERMINAL_ASSET_LIST_PAGE_SIZE': 'auto',
|
||||||
'TERMINAL_SESSION_KEEP_DURATION': 200,
|
'TERMINAL_SESSION_KEEP_DURATION': 200,
|
||||||
'TERMINAL_HOST_KEY': '',
|
'TERMINAL_HOST_KEY': '',
|
||||||
|
|
|
@ -15,7 +15,7 @@ class BaseHost(Host):
|
||||||
"""
|
"""
|
||||||
初始化
|
初始化
|
||||||
:param host_data: {
|
:param host_data: {
|
||||||
"hostname": "",
|
"name": "",
|
||||||
"ip": "",
|
"ip": "",
|
||||||
"port": "",
|
"port": "",
|
||||||
# behind is not must be required
|
# behind is not must be required
|
||||||
|
@ -32,7 +32,7 @@ class BaseHost(Host):
|
||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
self.host_data = host_data
|
self.host_data = host_data
|
||||||
hostname = host_data.get('hostname') or host_data.get('ip')
|
hostname = host_data.get('name') or host_data.get('ip')
|
||||||
port = host_data.get('port') or 22
|
port = host_data.get('port') or 22
|
||||||
super().__init__(hostname, port)
|
super().__init__(hostname, port)
|
||||||
self.__set_required_variables()
|
self.__set_required_variables()
|
||||||
|
@ -82,7 +82,7 @@ class BaseInventory(InventoryManager):
|
||||||
"""
|
"""
|
||||||
用于生成动态构建Ansible Inventory. super().__init__ 会自动调用
|
用于生成动态构建Ansible Inventory. super().__init__ 会自动调用
|
||||||
host_list: [{
|
host_list: [{
|
||||||
"hostname": "",
|
"name": "",
|
||||||
"ip": "",
|
"ip": "",
|
||||||
"port": "",
|
"port": "",
|
||||||
"username": "",
|
"username": "",
|
||||||
|
@ -136,7 +136,7 @@ class BaseInventory(InventoryManager):
|
||||||
ungrouped = self.get_or_create_group('ungrouped')
|
ungrouped = self.get_or_create_group('ungrouped')
|
||||||
for host_data in self.host_list:
|
for host_data in self.host_list:
|
||||||
host = self.host_manager_class(host_data=host_data)
|
host = self.host_manager_class(host_data=host_data)
|
||||||
self.hosts[host_data['hostname']] = host
|
self.hosts[host_data['name']] = host
|
||||||
groups_data = host_data.get('groups')
|
groups_data = host_data.get('groups')
|
||||||
if groups_data:
|
if groups_data:
|
||||||
for group_name in groups_data:
|
for group_name in groups_data:
|
||||||
|
|
|
@ -12,7 +12,7 @@ from ops.ansible.inventory import BaseInventory
|
||||||
class TestJMSInventory(unittest.TestCase):
|
class TestJMSInventory(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
host_list = [{
|
host_list = [{
|
||||||
"hostname": "testserver1",
|
"name": "testserver1",
|
||||||
"ip": "102.1.1.1",
|
"ip": "102.1.1.1",
|
||||||
"port": 22,
|
"port": 22,
|
||||||
"username": "root",
|
"username": "root",
|
||||||
|
@ -26,7 +26,7 @@ class TestJMSInventory(unittest.TestCase):
|
||||||
"groups": ["group1", "group2"],
|
"groups": ["group1", "group2"],
|
||||||
"vars": {"sexy": "yes"},
|
"vars": {"sexy": "yes"},
|
||||||
}, {
|
}, {
|
||||||
"hostname": "testserver2",
|
"name": "testserver2",
|
||||||
"ip": "8.8.8.8",
|
"ip": "8.8.8.8",
|
||||||
"port": 2222,
|
"port": 2222,
|
||||||
"username": "root",
|
"username": "root",
|
||||||
|
|
|
@ -14,7 +14,7 @@ class TestAdHocRunner(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
host_data = [
|
host_data = [
|
||||||
{
|
{
|
||||||
"hostname": "testserver",
|
"name": "testserver",
|
||||||
"ip": "192.168.244.185",
|
"ip": "192.168.244.185",
|
||||||
"port": 22,
|
"port": 22,
|
||||||
"username": "root",
|
"username": "root",
|
||||||
|
@ -38,7 +38,7 @@ class TestCommandRunner(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
host_data = [
|
host_data = [
|
||||||
{
|
{
|
||||||
"hostname": "testserver",
|
"name": "testserver",
|
||||||
"ip": "192.168.244.168",
|
"ip": "192.168.244.168",
|
||||||
"port": 22,
|
"port": 22,
|
||||||
"username": "root",
|
"username": "root",
|
||||||
|
|
|
@ -20,7 +20,7 @@ class JMSBaseInventory(BaseInventory):
|
||||||
def convert_to_ansible(self, asset, run_as_admin=False):
|
def convert_to_ansible(self, asset, run_as_admin=False):
|
||||||
info = {
|
info = {
|
||||||
'id': asset.id,
|
'id': asset.id,
|
||||||
'hostname': asset.hostname,
|
'name': asset.name,
|
||||||
'ip': asset.ip,
|
'ip': asset.ip,
|
||||||
'port': asset.ssh_port,
|
'port': asset.ssh_port,
|
||||||
'vars': dict(),
|
'vars': dict(),
|
||||||
|
|
|
@ -57,7 +57,7 @@ class CommandExecution(OrgModelMixin):
|
||||||
|
|
||||||
@lazyproperty
|
@lazyproperty
|
||||||
def hosts_display(self):
|
def hosts_display(self):
|
||||||
return ','.join(self.hosts.all().values_list('hostname', flat=True))
|
return ','.join(self.hosts.all().values_list('name', flat=True))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def result(self):
|
def result(self):
|
||||||
|
@ -77,7 +77,7 @@ class CommandExecution(OrgModelMixin):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_hosts_names(self):
|
def get_hosts_names(self):
|
||||||
return ','.join(self.hosts.all().values_list('hostname', flat=True))
|
return ','.join(self.hosts.all().values_list('name', flat=True))
|
||||||
|
|
||||||
def cmd_filter_rules(self, asset_id=None):
|
def cmd_filter_rules(self, asset_id=None):
|
||||||
from assets.models import CommandFilterRule
|
from assets.models import CommandFilterRule
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
# Generated by Django 3.2.14 on 2022-08-11 07:11
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('orgs', '0012_auto_20220118_1054'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name='OrganizationMember',
|
||||||
|
),
|
||||||
|
]
|
|
@ -6,6 +6,7 @@ from django.utils.translation import ugettext_lazy as _
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
|
|
||||||
from common.utils import get_logger
|
from common.utils import get_logger
|
||||||
|
from common.db.models import JMSBaseModel
|
||||||
from ..utils import (
|
from ..utils import (
|
||||||
set_current_org, get_current_org, current_org, filter_org_queryset
|
set_current_org, get_current_org, current_org, filter_org_queryset
|
||||||
)
|
)
|
||||||
|
@ -14,7 +15,7 @@ from ..models import Organization
|
||||||
logger = get_logger(__file__)
|
logger = get_logger(__file__)
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'OrgManager', 'OrgModelMixin', 'Organization'
|
'OrgManager', 'OrgModelMixin', 'JMSOrgBaseModel'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,7 +41,6 @@ class OrgManager(models.Manager):
|
||||||
set_current_org(org)
|
set_current_org(org)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
def bulk_create(self, objs, batch_size=None, ignore_conflicts=False):
|
def bulk_create(self, objs, batch_size=None, ignore_conflicts=False):
|
||||||
org = get_current_org()
|
org = get_current_org()
|
||||||
for obj in objs:
|
for obj in objs:
|
||||||
|
@ -87,7 +87,7 @@ class OrgModelMixin(models.Model):
|
||||||
name = getattr(self, attr)
|
name = getattr(self, attr)
|
||||||
elif hasattr(self, 'name'):
|
elif hasattr(self, 'name'):
|
||||||
name = self.name
|
name = self.name
|
||||||
elif hasattr(self, 'hostname'):
|
elif hasattr(self, 'name'):
|
||||||
name = self.hostname
|
name = self.hostname
|
||||||
return name + self.sep + self.org_name
|
return name + self.sep + self.org_name
|
||||||
|
|
||||||
|
@ -113,3 +113,8 @@ class OrgModelMixin(models.Model):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
|
|
||||||
|
class JMSOrgBaseModel(JMSBaseModel, OrgModelMixin):
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
|
@ -199,30 +199,3 @@ class Organization(OrgRoleMixin, models.Model):
|
||||||
def delete(self, *args, **kwargs):
|
def delete(self, *args, **kwargs):
|
||||||
self.delete_related_models()
|
self.delete_related_models()
|
||||||
return super().delete(*args, **kwargs)
|
return super().delete(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class OrganizationMember(models.Model):
|
|
||||||
"""
|
|
||||||
注意:直接调用该 `Model.delete` `Model.objects.delete` 不会触发清理该用户的信号
|
|
||||||
"""
|
|
||||||
|
|
||||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
|
||||||
org = models.ForeignKey(
|
|
||||||
Organization, related_name='m2m_org_members', on_delete=models.CASCADE, verbose_name=_('Organization')
|
|
||||||
)
|
|
||||||
user = models.ForeignKey(
|
|
||||||
'users.User', related_name='m2m_org_members', on_delete=models.CASCADE, verbose_name=_('User')
|
|
||||||
)
|
|
||||||
role = models.CharField(max_length=16, default='User', verbose_name=_("Role"))
|
|
||||||
date_created = models.DateTimeField(auto_now_add=True, verbose_name=_("Date created"))
|
|
||||||
date_updated = models.DateTimeField(auto_now=True, verbose_name=_("Date updated"))
|
|
||||||
created_by = models.CharField(max_length=128, null=True, verbose_name=_('Created by'))
|
|
||||||
|
|
||||||
# objects = OrgMemberManager()
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
unique_together = [('org', 'user', 'role')]
|
|
||||||
db_table = 'orgs_organization_members'
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return '{} | {}'.format(self.user, self.org)
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ class AssetPermissionAssetRelationViewSet(RelationMixin):
|
||||||
|
|
||||||
class AssetPermissionAllAssetListApi(generics.ListAPIView):
|
class AssetPermissionAllAssetListApi(generics.ListAPIView):
|
||||||
serializer_class = serializers.AssetPermissionAllAssetSerializer
|
serializer_class = serializers.AssetPermissionAllAssetSerializer
|
||||||
filterset_fields = ("hostname", "ip")
|
filterset_fields = ("name", "ip")
|
||||||
search_fields = filterset_fields
|
search_fields = filterset_fields
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
|
|
@ -33,8 +33,8 @@ class UserGroupMixin:
|
||||||
class UserGroupGrantedAssetsApi(ListAPIView):
|
class UserGroupGrantedAssetsApi(ListAPIView):
|
||||||
serializer_class = serializers.AssetGrantedSerializer
|
serializer_class = serializers.AssetGrantedSerializer
|
||||||
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
||||||
filterset_fields = ['hostname', 'ip', 'id', 'comment']
|
filterset_fields = ['name', 'ip', 'id', 'comment']
|
||||||
search_fields = ['hostname', 'ip', 'comment']
|
search_fields = ['name', 'ip', 'comment']
|
||||||
rbac_perms = {
|
rbac_perms = {
|
||||||
'list': 'perms.view_usergroupassets',
|
'list': 'perms.view_usergroupassets',
|
||||||
}
|
}
|
||||||
|
@ -70,8 +70,8 @@ class UserGroupGrantedAssetsApi(ListAPIView):
|
||||||
class UserGroupGrantedNodeAssetsApi(ListAPIView):
|
class UserGroupGrantedNodeAssetsApi(ListAPIView):
|
||||||
serializer_class = serializers.AssetGrantedSerializer
|
serializer_class = serializers.AssetGrantedSerializer
|
||||||
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
only_fields = serializers.AssetGrantedSerializer.Meta.only_fields
|
||||||
filterset_fields = ['hostname', 'ip', 'id', 'comment']
|
filterset_fields = ['name', 'ip', 'id', 'comment']
|
||||||
search_fields = ['hostname', 'ip', 'comment']
|
search_fields = ['name', 'ip', 'comment']
|
||||||
rbac_perms = {
|
rbac_perms = {
|
||||||
'list': 'perms.view_usergroupassets',
|
'list': 'perms.view_usergroupassets',
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,16 +81,16 @@ class UserGrantedNodeAssetsMixin:
|
||||||
|
|
||||||
class AssetsSerializerFormatMixin:
|
class AssetsSerializerFormatMixin:
|
||||||
serializer_class = serializers.AssetGrantedSerializer
|
serializer_class = serializers.AssetGrantedSerializer
|
||||||
filterset_fields = ['hostname', 'ip', 'id', 'comment']
|
filterset_fields = ['name', 'ip', 'id', 'comment']
|
||||||
search_fields = ['hostname', 'ip', 'comment']
|
search_fields = ['name', 'ip', 'comment']
|
||||||
|
|
||||||
|
|
||||||
class AssetsTreeFormatMixin(SerializeToTreeNodeMixin):
|
class AssetsTreeFormatMixin(SerializeToTreeNodeMixin):
|
||||||
"""
|
"""
|
||||||
将 资产 序列化成树的结构返回
|
将 资产 序列化成树的结构返回
|
||||||
"""
|
"""
|
||||||
filterset_fields = ['hostname', 'ip', 'id', 'comment']
|
filterset_fields = ['name', 'ip', 'id', 'comment']
|
||||||
search_fields = ['hostname', 'ip', 'comment']
|
search_fields = ['name', 'ip', 'comment']
|
||||||
|
|
||||||
def list(self, request: Request, *args, **kwargs):
|
def list(self, request: Request, *args, **kwargs):
|
||||||
queryset = self.filter_queryset(self.get_queryset())
|
queryset = self.filter_queryset(self.get_queryset())
|
||||||
|
@ -99,6 +99,6 @@ class AssetsTreeFormatMixin(SerializeToTreeNodeMixin):
|
||||||
# 如果用户搜索的条件不精准,会导致返回大量的无意义数据。
|
# 如果用户搜索的条件不精准,会导致返回大量的无意义数据。
|
||||||
# 这里限制一下返回数据的最大条数
|
# 这里限制一下返回数据的最大条数
|
||||||
queryset = queryset[:999]
|
queryset = queryset[:999]
|
||||||
queryset = sorted(queryset, key=lambda asset: asset.hostname)
|
queryset = sorted(queryset, key=lambda asset: asset.name)
|
||||||
data = self.serialize_assets(queryset, None)
|
data = self.serialize_assets(queryset, None)
|
||||||
return Response(data=data)
|
return Response(data=data)
|
||||||
|
|
|
@ -117,7 +117,7 @@ class AssetPermissionFilter(PermissionBaseFilter):
|
||||||
model = AssetPermission
|
model = AssetPermission
|
||||||
fields = (
|
fields = (
|
||||||
'user_id', 'username', 'system_user_id', 'system_user', 'user_group_id',
|
'user_id', 'username', 'system_user_id', 'system_user', 'user_group_id',
|
||||||
'user_group', 'node_id', 'node', 'asset_id', 'hostname', 'ip', 'name',
|
'user_group', 'node_id', 'node', 'asset_id', 'name', 'ip', 'name',
|
||||||
'all', 'asset_id', 'is_valid', 'is_effective', 'from_ticket'
|
'all', 'asset_id', 'is_valid', 'is_effective', 'from_ticket'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ class AssetPermissionFilter(PermissionBaseFilter):
|
||||||
def filter_asset(self, queryset):
|
def filter_asset(self, queryset):
|
||||||
is_query_all = self.get_query_param('all', True)
|
is_query_all = self.get_query_param('all', True)
|
||||||
asset_id = self.get_query_param('asset_id')
|
asset_id = self.get_query_param('asset_id')
|
||||||
hostname = self.get_query_param('hostname')
|
hostname = self.get_query_param('name')
|
||||||
ip = self.get_query_param('ip')
|
ip = self.get_query_param('ip')
|
||||||
|
|
||||||
if asset_id:
|
if asset_id:
|
||||||
|
|
|
@ -185,7 +185,7 @@ class AssetPermission(OrgModelMixin):
|
||||||
return names
|
return names
|
||||||
|
|
||||||
def assets_display(self):
|
def assets_display(self):
|
||||||
names = [asset.hostname for asset in self.assets.all()]
|
names = [asset.name for asset in self.assets.all()]
|
||||||
return names
|
return names
|
||||||
|
|
||||||
def nodes_display(self):
|
def nodes_display(self):
|
||||||
|
|
|
@ -83,7 +83,7 @@ class AssetPermissionAllAssetSerializer(serializers.Serializer):
|
||||||
asset_display = serializers.SerializerMethodField()
|
asset_display = serializers.SerializerMethodField()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
only_fields = ['id', 'hostname', 'ip']
|
only_fields = ['id', 'name', 'ip']
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_asset_display(obj):
|
def get_asset_display(obj):
|
||||||
|
|
|
@ -44,7 +44,7 @@ class AssetGrantedSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Asset
|
model = Asset
|
||||||
only_fields = [
|
only_fields = [
|
||||||
"id", "hostname", "ip", "protocols", "os", 'domain',
|
"id", "name", "ip", "protocols", "os", 'domain',
|
||||||
"platform", "comment", "org_id", "is_active"
|
"platform", "comment", "org_id", "is_active"
|
||||||
]
|
]
|
||||||
fields = only_fields + ['org_name']
|
fields = only_fields + ['org_name']
|
||||||
|
|
|
@ -513,7 +513,7 @@ class UserGrantedAssetsQueryUtils(UserGrantedUtilsBase):
|
||||||
assets = self._get_indirect_granted_node_assets(node.id)
|
assets = self._get_indirect_granted_node_assets(node.id)
|
||||||
else:
|
else:
|
||||||
assets = Asset.objects.none()
|
assets = Asset.objects.none()
|
||||||
assets = assets.order_by('hostname')
|
assets = assets.order_by('name')
|
||||||
return assets
|
return assets
|
||||||
|
|
||||||
def _get_indirect_granted_node_assets(self, id) -> AssetQuerySet:
|
def _get_indirect_granted_node_assets(self, id) -> AssetQuerySet:
|
||||||
|
|
|
@ -4,7 +4,7 @@ from rest_framework import serializers
|
||||||
|
|
||||||
class TerminalSettingSerializer(serializers.Serializer):
|
class TerminalSettingSerializer(serializers.Serializer):
|
||||||
SORT_BY_CHOICES = (
|
SORT_BY_CHOICES = (
|
||||||
('hostname', _('Hostname')),
|
('name', _('Hostname')),
|
||||||
('ip', _('IP'))
|
('ip', _('IP'))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ def sync_node(src, target, cut=False):
|
||||||
asset.save()
|
asset.save()
|
||||||
new_asset = asset
|
new_asset = asset
|
||||||
else:
|
else:
|
||||||
new_asset = get_object_or_none(Asset, hostname=asset.hostname, org_id=target.org_id)
|
new_asset = get_object_or_none(Asset, hostname=asset.name, org_id=target.org_id)
|
||||||
if new_asset is None:
|
if new_asset is None:
|
||||||
asset.id = None
|
asset.id = None
|
||||||
asset.org_id = target.org_id
|
asset.org_id = target.org_id
|
||||||
|
|
Loading…
Reference in New Issue