mirror of https://github.com/jumpserver/jumpserver
feat: Allow users to customize asset name and comment
parent
0c73acd4b9
commit
38e3d9de8b
|
@ -7,3 +7,4 @@ from .node import *
|
|||
from .platform import *
|
||||
from .protocol import *
|
||||
from .tree import *
|
||||
from .my_asset import *
|
||||
|
|
|
@ -2,7 +2,7 @@ from typing import List
|
|||
|
||||
from rest_framework.request import Request
|
||||
|
||||
from assets.models import Node, Platform, Protocol
|
||||
from assets.models import Node, Platform, Protocol, MyAsset
|
||||
from assets.utils import get_node_from_request, is_query_node_all_assets
|
||||
from common.utils import lazyproperty, timeit
|
||||
|
||||
|
@ -82,6 +82,7 @@ class SerializeToTreeNodeMixin:
|
|||
|
||||
data = []
|
||||
root_assets_count = 0
|
||||
MyAsset.set_asset_custom_value(assets, self.request.user)
|
||||
for asset in assets:
|
||||
platform = platform_map.get(asset.platform_id)
|
||||
if not platform:
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from common.api import GenericViewSet
|
||||
from rest_framework.mixins import CreateModelMixin
|
||||
from common.permissions import IsValidUser
|
||||
from ..serializers import MyAssetSerializer
|
||||
|
||||
__all__ = ['MyAssetViewSet']
|
||||
|
||||
|
||||
class MyAssetViewSet(CreateModelMixin, GenericViewSet):
|
||||
serializer_class = MyAssetSerializer
|
||||
permission_classes = (IsValidUser,)
|
|
@ -0,0 +1,35 @@
|
|||
# Generated by Django 4.1.13 on 2024-08-06 09:11
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('assets', '0004_auto_20240709_1819'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='MyAsset',
|
||||
fields=[
|
||||
('created_by', models.CharField(blank=True, max_length=128, null=True, verbose_name='Created by')),
|
||||
('updated_by', models.CharField(blank=True, max_length=128, 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)),
|
||||
('name', models.CharField(default='', max_length=128, verbose_name='Custom Name')),
|
||||
('comment', models.CharField(default='', max_length=512, verbose_name='Custom Comment')),
|
||||
('asset', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='my_assets', to='assets.asset')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'My asset',
|
||||
'unique_together': {('user', 'asset')},
|
||||
},
|
||||
),
|
||||
]
|
|
@ -7,3 +7,4 @@ from .domain import *
|
|||
from .node import *
|
||||
from .favorite_asset import *
|
||||
from .automations import *
|
||||
from .my_asset import *
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from common.db.models import JMSBaseModel
|
||||
|
||||
__all__ = ['MyAsset']
|
||||
|
||||
|
||||
class MyAsset(JMSBaseModel):
|
||||
user = models.ForeignKey('users.User', on_delete=models.CASCADE)
|
||||
asset = models.ForeignKey('assets.Asset', on_delete=models.CASCADE, related_name='my_assets')
|
||||
name = models.CharField(verbose_name=_("Custom Name"), max_length=128, default='')
|
||||
comment = models.CharField(verbose_name=_("Custom Comment"), max_length=512, default='')
|
||||
custom_fields = ['name', 'comment']
|
||||
|
||||
class Meta:
|
||||
unique_together = ('user', 'asset')
|
||||
verbose_name = _("My asset")
|
||||
|
||||
def custom_to_dict(self):
|
||||
data = {}
|
||||
for field in self.custom_fields:
|
||||
value = getattr(self, field)
|
||||
if value == "":
|
||||
continue
|
||||
data.update({field: value})
|
||||
return data
|
||||
|
||||
@staticmethod
|
||||
def set_asset_custom_value(assets, user):
|
||||
my_assets = MyAsset.objects.filter(asset__in=assets, user=user).all()
|
||||
customs = {my_asset.asset.id: my_asset.custom_to_dict() for my_asset in my_assets}
|
||||
for asset in assets:
|
||||
custom = customs.get(asset.id)
|
||||
if not custom:
|
||||
continue
|
||||
for field, value in custom.items():
|
||||
if not hasattr(asset, field):
|
||||
continue
|
||||
setattr(asset, field, value)
|
||||
|
||||
def __str__(self):
|
||||
return f'{self.user}-{self.asset}'
|
|
@ -9,3 +9,4 @@ from .favorite_asset import *
|
|||
from .gateway import *
|
||||
from .node import *
|
||||
from .platform import *
|
||||
from .my_asset import *
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
from rest_framework import serializers
|
||||
|
||||
from orgs.utils import tmp_to_root_org
|
||||
from common.serializers import BulkSerializerMixin
|
||||
from ..models import FavoriteAsset
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from rest_framework import serializers
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from ..models import MyAsset
|
||||
|
||||
__all__ = ['MyAssetSerializer']
|
||||
|
||||
|
||||
class MyAssetSerializer(serializers.ModelSerializer):
|
||||
user = serializers.HiddenField(
|
||||
default=serializers.CurrentUserDefault()
|
||||
)
|
||||
name = serializers.CharField(label=_("Custom Name"), max_length=128, allow_blank=True, required=False)
|
||||
comment = serializers.CharField(label=_("Custom Comment"), max_length=512, allow_blank=True, required=False)
|
||||
|
||||
class Meta:
|
||||
model = MyAsset
|
||||
fields = ['user', 'asset', 'name', 'comment']
|
||||
validators = []
|
||||
|
||||
def create(self, data):
|
||||
custom_fields = MyAsset.custom_fields
|
||||
asset = data['asset']
|
||||
user = self.context['request'].user
|
||||
defaults = {field: data.get(field, '') for field in custom_fields}
|
||||
obj, created = MyAsset.objects.get_or_create(defaults=defaults, user=user, asset=asset)
|
||||
if created:
|
||||
return obj
|
||||
for field in custom_fields:
|
||||
value = data.get(field)
|
||||
if value is None:
|
||||
continue
|
||||
setattr(obj, field, value)
|
||||
obj.save()
|
||||
return obj
|
|
@ -24,6 +24,7 @@ router.register(r'gateways', api.GatewayViewSet, 'gateway')
|
|||
router.register(r'favorite-assets', api.FavoriteAssetViewSet, 'favorite-asset')
|
||||
router.register(r'protocol-settings', api.PlatformProtocolViewSet, 'protocol-setting')
|
||||
router.register(r'labels', LabelViewSet, 'label')
|
||||
router.register(r'my-asset', api.MyAssetViewSet, 'my-asset')
|
||||
|
||||
urlpatterns = [
|
||||
# path('assets/<uuid:pk>/gateways/', api.AssetGatewayListApi.as_view(), name='asset-gateway-list'),
|
||||
|
|
|
@ -4,7 +4,7 @@ from django.conf import settings
|
|||
from rest_framework.generics import ListAPIView, RetrieveAPIView
|
||||
|
||||
from assets.api.asset.asset import AssetFilterSet
|
||||
from assets.models import Asset, Node
|
||||
from assets.models import Asset, Node, MyAsset
|
||||
from common.api.mixin import ExtraFilterFieldsMixin
|
||||
from common.utils import get_logger, lazyproperty, is_uuid
|
||||
from orgs.utils import tmp_to_root_org
|
||||
|
@ -55,6 +55,11 @@ class BaseUserPermedAssetsApi(SelfOrPKUserMixin, ExtraFilterFieldsMixin, ListAPI
|
|||
assets = self.serializer_class.setup_eager_loading(assets)
|
||||
return assets
|
||||
|
||||
def get_serializer(self, *args, **kwargs):
|
||||
if len(args) == 1 and kwargs.get('many', False) and self.request_user_is_self():
|
||||
MyAsset.set_asset_custom_value(args[0], self.request.user)
|
||||
return super().get_serializer(*args, **kwargs)
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_assets(self):
|
||||
return Asset.objects.none()
|
||||
|
|
Loading…
Reference in New Issue