mirror of https://github.com/jumpserver/jumpserver
feat: 支持设置默认存储(命令、录像) (#6336)
* fix: 修改LDAP用户导入的组织为当前组织 * fix: 修改翻译信息 * feat: 支持设置默认存储 * feat: 支持设置默认存储(2) * feat: 支持设置默认存储(3)pull/6343/head
parent
aa6e550ba2
commit
c0ec0f1343
|
@ -0,0 +1,25 @@
|
|||
# Generated by Django 3.1.6 on 2021-06-23 09:48
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('assets', '0070_auto_20210426_1515'),
|
||||
('applications', '0008_auto_20210104_0435'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ApplicationUser',
|
||||
fields=[
|
||||
],
|
||||
options={
|
||||
'proxy': True,
|
||||
'indexes': [],
|
||||
'constraints': [],
|
||||
},
|
||||
bases=('assets.systemuser',),
|
||||
),
|
||||
]
|
Binary file not shown.
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: JumpServer 0.3.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-06-22 19:04+0800\n"
|
||||
"POT-Creation-Date: 2021-06-25 17:12+0800\n"
|
||||
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
|
||||
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
||||
"Language-Team: JumpServer team<ibuler@qq.com>\n"
|
||||
|
@ -23,9 +23,9 @@ msgstr ""
|
|||
#: assets/models/cmd_filter.py:21 assets/models/domain.py:21
|
||||
#: assets/models/group.py:20 assets/models/label.py:18 ops/mixin.py:24
|
||||
#: orgs/models.py:23 perms/models/base.py:49 settings/models.py:29
|
||||
#: terminal/models/storage.py:23 terminal/models/storage.py:90
|
||||
#: terminal/models/task.py:16 terminal/models/terminal.py:100
|
||||
#: users/forms/profile.py:32 users/models/group.py:15 users/models/user.py:550
|
||||
#: terminal/models/storage.py:23 terminal/models/task.py:16
|
||||
#: terminal/models/terminal.py:100 users/forms/profile.py:32
|
||||
#: users/models/group.py:15 users/models/user.py:550
|
||||
#: users/templates/users/_select_user_modal.html:13
|
||||
#: users/templates/users/user_asset_permission.html:37
|
||||
#: users/templates/users/user_asset_permission.html:154
|
||||
|
@ -59,11 +59,11 @@ msgstr "激活中"
|
|||
#: assets/models/domain.py:22 assets/models/domain.py:56
|
||||
#: assets/models/group.py:23 assets/models/label.py:23 ops/models/adhoc.py:37
|
||||
#: orgs/models.py:26 perms/models/base.py:57 settings/models.py:34
|
||||
#: terminal/models/storage.py:29 terminal/models/storage.py:96
|
||||
#: terminal/models/terminal.py:114 tickets/models/ticket.py:73
|
||||
#: users/models/group.py:16 users/models/user.py:583
|
||||
#: xpack/plugins/change_auth_plan/models.py:77 xpack/plugins/cloud/models.py:35
|
||||
#: xpack/plugins/cloud/models.py:98 xpack/plugins/gathered_user/models.py:26
|
||||
#: terminal/models/storage.py:26 terminal/models/terminal.py:114
|
||||
#: tickets/models/ticket.py:73 users/models/group.py:16
|
||||
#: users/models/user.py:583 xpack/plugins/change_auth_plan/models.py:77
|
||||
#: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:98
|
||||
#: xpack/plugins/gathered_user/models.py:26
|
||||
msgid "Comment"
|
||||
msgstr "备注"
|
||||
|
||||
|
@ -257,7 +257,7 @@ msgstr "类别"
|
|||
#: perms/models/application_permission.py:23
|
||||
#: perms/serializers/application/permission.py:17
|
||||
#: perms/serializers/application/user_permission.py:34
|
||||
#: terminal/models/storage.py:26 terminal/models/storage.py:93
|
||||
#: terminal/models/storage.py:47 terminal/models/storage.py:108
|
||||
#: tickets/models/ticket.py:38
|
||||
#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:27
|
||||
msgid "Type"
|
||||
|
@ -1202,7 +1202,7 @@ msgstr "主机 (显示名称)"
|
|||
msgid "Result"
|
||||
msgstr "结果"
|
||||
|
||||
#: audits/serializers.py:92 terminal/serializers/storage.py:189
|
||||
#: audits/serializers.py:92 terminal/serializers/storage.py:195
|
||||
msgid "Hosts"
|
||||
msgstr "主机"
|
||||
|
||||
|
@ -3252,6 +3252,10 @@ msgstr "线程数"
|
|||
msgid "Boot Time"
|
||||
msgstr "运行时间"
|
||||
|
||||
#: terminal/models/storage.py:25
|
||||
msgid "Default storage"
|
||||
msgstr "默认存储"
|
||||
|
||||
#: terminal/models/task.py:17
|
||||
msgid "Args"
|
||||
msgstr "参数"
|
||||
|
@ -3426,27 +3430,27 @@ msgstr "账户密钥"
|
|||
msgid "Endpoint suffix"
|
||||
msgstr "端点后缀"
|
||||
|
||||
#: terminal/serializers/storage.py:166
|
||||
#: terminal/serializers/storage.py:172
|
||||
msgid "The address format is incorrect"
|
||||
msgstr "地址格式不正确"
|
||||
|
||||
#: terminal/serializers/storage.py:173
|
||||
#: terminal/serializers/storage.py:179
|
||||
msgid "Host invalid"
|
||||
msgstr "主机无效"
|
||||
|
||||
#: terminal/serializers/storage.py:176
|
||||
#: terminal/serializers/storage.py:182
|
||||
msgid "Port invalid"
|
||||
msgstr "端口无效"
|
||||
|
||||
#: terminal/serializers/storage.py:192
|
||||
#: terminal/serializers/storage.py:198
|
||||
msgid "Index"
|
||||
msgstr "索引"
|
||||
|
||||
#: terminal/serializers/storage.py:194
|
||||
#: terminal/serializers/storage.py:200
|
||||
msgid "Doc type"
|
||||
msgstr "文档类型"
|
||||
|
||||
#: terminal/serializers/storage.py:196
|
||||
#: terminal/serializers/storage.py:202
|
||||
msgid "Ignore Certificate Verification"
|
||||
msgstr "忽略证书认证"
|
||||
|
||||
|
@ -5114,6 +5118,3 @@ msgstr "旗舰版"
|
|||
#: xpack/plugins/license/models.py:77
|
||||
msgid "Community edition"
|
||||
msgstr "社区版"
|
||||
|
||||
#~ msgid "Terminal command alert"
|
||||
#~ msgstr "终端命令告警"
|
||||
|
|
|
@ -36,7 +36,7 @@ class BaseStorageViewSetMixin:
|
|||
|
||||
|
||||
class CommandStorageViewSet(BaseStorageViewSetMixin, viewsets.ModelViewSet):
|
||||
search_fields = ('name', 'type',)
|
||||
search_fields = ('name', 'type')
|
||||
queryset = CommandStorage.objects.all()
|
||||
serializer_class = CommandStorageSerializer
|
||||
permission_classes = (IsSuperUser,)
|
||||
|
@ -103,7 +103,7 @@ class CommandStorageViewSet(BaseStorageViewSetMixin, viewsets.ModelViewSet):
|
|||
|
||||
|
||||
class ReplayStorageViewSet(BaseStorageViewSetMixin, viewsets.ModelViewSet):
|
||||
filterset_fields = ('name', 'type',)
|
||||
filterset_fields = ('name', 'type', 'is_default')
|
||||
search_fields = filterset_fields
|
||||
queryset = ReplayStorage.objects.all()
|
||||
serializer_class = ReplayStorageSerializer
|
||||
|
|
|
@ -71,7 +71,7 @@ class CommandStorageFilter(filters.FilterSet):
|
|||
|
||||
class Meta:
|
||||
model = CommandStorage
|
||||
fields = ['real', 'name', 'type']
|
||||
fields = ['real', 'name', 'type', 'is_default']
|
||||
|
||||
def filter_real(self, queryset, name, value):
|
||||
if value:
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
# Generated by Django 3.1.6 on 2021-06-23 09:48
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
def set_default_storage(apps, schema_editor):
|
||||
command_storage_model = apps.get_model("terminal", "CommandStorage")
|
||||
command_storage = command_storage_model.objects.filter(name='default', type='server').first()
|
||||
if command_storage:
|
||||
command_storage.is_default = True
|
||||
command_storage.save()
|
||||
replay_storage_model = apps.get_model("terminal", "ReplayStorage")
|
||||
replay_storage = replay_storage_model.objects.filter(name='default', type='server').first()
|
||||
if replay_storage:
|
||||
replay_storage.is_default = True
|
||||
replay_storage.save()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('terminal', '0036_auto_20210604_1124'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='commandstorage',
|
||||
name='is_default',
|
||||
field=models.BooleanField(default=False, verbose_name='Default storage'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='replaystorage',
|
||||
name='is_default',
|
||||
field=models.BooleanField(default=False, verbose_name='Default storage'),
|
||||
),
|
||||
migrations.RunPython(set_default_storage)
|
||||
]
|
|
@ -19,17 +19,41 @@ from .. import const
|
|||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
class CommandStorage(CommonModelMixin):
|
||||
class CommonStorageModelMixin(models.Model):
|
||||
name = models.CharField(max_length=128, verbose_name=_("Name"), unique=True)
|
||||
meta = EncryptJsonDictTextField(default={})
|
||||
is_default = models.BooleanField(default=False, verbose_name=_('Default storage'))
|
||||
comment = models.TextField(default='', blank=True, verbose_name=_('Comment'))
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def set_to_default(self):
|
||||
self.is_default = True
|
||||
self.save()
|
||||
self.__class__.objects.select_for_update()\
|
||||
.filter(is_default=True)\
|
||||
.exclude(id=self.id)\
|
||||
.update(is_default=False)
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
objs = cls.objects.filter(is_default=True)
|
||||
if not objs:
|
||||
objs = cls.objects.filter(name='default', type='server')
|
||||
if not objs:
|
||||
objs = cls.objects.all()
|
||||
return objs.first()
|
||||
|
||||
|
||||
class CommandStorage(CommonStorageModelMixin, CommonModelMixin):
|
||||
type = models.CharField(
|
||||
max_length=16, choices=const.CommandStorageTypeChoices.choices,
|
||||
default=const.CommandStorageTypeChoices.server.value, verbose_name=_('Type'),
|
||||
)
|
||||
meta = EncryptJsonDictTextField(default={})
|
||||
comment = models.TextField(default='', blank=True, verbose_name=_('Comment'))
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def type_null(self):
|
||||
|
@ -86,17 +110,11 @@ class CommandStorage(CommonModelMixin):
|
|||
backend.pre_use_check()
|
||||
|
||||
|
||||
class ReplayStorage(CommonModelMixin):
|
||||
name = models.CharField(max_length=128, verbose_name=_("Name"), unique=True)
|
||||
class ReplayStorage(CommonStorageModelMixin, CommonModelMixin):
|
||||
type = models.CharField(
|
||||
max_length=16, choices=const.ReplayStorageTypeChoices.choices,
|
||||
default=const.ReplayStorageTypeChoices.server.value, verbose_name=_('Type')
|
||||
)
|
||||
meta = EncryptJsonDictTextField(default={})
|
||||
comment = models.TextField(default='', blank=True, verbose_name=_('Comment'))
|
||||
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@property
|
||||
def type_null(self):
|
||||
|
|
|
@ -176,6 +176,12 @@ class Terminal(StorageMixin, TerminalStatusMixin, models.Model):
|
|||
self.save()
|
||||
return
|
||||
|
||||
def save(self, **kwargs):
|
||||
from .storage import CommandStorage, ReplayStorage
|
||||
self.command_storage = CommandStorage.default().name
|
||||
self.replay_storage = ReplayStorage.default().name
|
||||
return super().save(**kwargs)
|
||||
|
||||
def __str__(self):
|
||||
status = "Active"
|
||||
if not self.is_accepted:
|
||||
|
|
|
@ -119,44 +119,6 @@ replay_storage_type_serializer_classes_mapping = {
|
|||
const.ReplayStorageTypeChoices.obs.value: ReplayStorageTypeOBSSerializer
|
||||
}
|
||||
|
||||
# ReplayStorageSerializer
|
||||
|
||||
|
||||
class ReplayStorageSerializer(serializers.ModelSerializer):
|
||||
meta = MethodSerializer()
|
||||
|
||||
class Meta:
|
||||
model = ReplayStorage
|
||||
fields = ['id', 'name', 'type', 'meta', 'comment']
|
||||
|
||||
def validate_meta(self, meta):
|
||||
_meta = self.instance.meta if self.instance else {}
|
||||
_meta.update(meta)
|
||||
return _meta
|
||||
|
||||
def get_meta_serializer(self):
|
||||
default_serializer = serializers.Serializer(read_only=True)
|
||||
|
||||
if isinstance(self.instance, ReplayStorage):
|
||||
_type = self.instance.type
|
||||
else:
|
||||
_type = self.context['request'].query_params.get('type')
|
||||
|
||||
if _type:
|
||||
serializer_class = replay_storage_type_serializer_classes_mapping.get(_type)
|
||||
else:
|
||||
serializer_class = default_serializer
|
||||
|
||||
if not serializer_class:
|
||||
serializer_class = default_serializer
|
||||
|
||||
if isinstance(serializer_class, type):
|
||||
serializer = serializer_class()
|
||||
else:
|
||||
serializer = serializer_class
|
||||
return serializer
|
||||
|
||||
|
||||
# Command storage serializers
|
||||
# ---------------------------
|
||||
|
||||
|
@ -204,15 +166,17 @@ command_storage_type_serializer_classes_mapping = {
|
|||
const.CommandStorageTypeChoices.es.value: CommandStorageTypeESSerializer
|
||||
}
|
||||
|
||||
# CommandStorageSerializer
|
||||
|
||||
# BaseStorageSerializer
|
||||
|
||||
|
||||
class CommandStorageSerializer(serializers.ModelSerializer):
|
||||
class BaseStorageSerializer(serializers.ModelSerializer):
|
||||
storage_type_serializer_classes_mapping = {}
|
||||
meta = MethodSerializer()
|
||||
|
||||
class Meta:
|
||||
model = CommandStorage
|
||||
fields = ['id', 'name', 'type', 'meta', 'comment']
|
||||
model = None
|
||||
fields = ['id', 'name', 'type', 'meta', 'is_default', 'comment']
|
||||
|
||||
def validate_meta(self, meta):
|
||||
_meta = self.instance.meta if self.instance else {}
|
||||
|
@ -222,13 +186,13 @@ class CommandStorageSerializer(serializers.ModelSerializer):
|
|||
def get_meta_serializer(self):
|
||||
default_serializer = serializers.Serializer(read_only=True)
|
||||
|
||||
if isinstance(self.instance, CommandStorage):
|
||||
if isinstance(self.instance, self.__class__.Meta.model):
|
||||
_type = self.instance.type
|
||||
else:
|
||||
_type = self.context['request'].query_params.get('type')
|
||||
|
||||
if _type:
|
||||
serializer_class = command_storage_type_serializer_classes_mapping.get(_type)
|
||||
serializer_class = self.storage_type_serializer_classes_mapping.get(_type)
|
||||
else:
|
||||
serializer_class = default_serializer
|
||||
|
||||
|
@ -240,3 +204,30 @@ class CommandStorageSerializer(serializers.ModelSerializer):
|
|||
else:
|
||||
serializer = serializer_class
|
||||
return serializer
|
||||
|
||||
def save(self, **kwargs):
|
||||
instance = super().save(**kwargs)
|
||||
if self.validated_data.get('is_default', False):
|
||||
instance.set_to_default()
|
||||
return instance
|
||||
|
||||
|
||||
# CommandStorageSerializer
|
||||
|
||||
|
||||
class CommandStorageSerializer(BaseStorageSerializer):
|
||||
storage_type_serializer_classes_mapping = command_storage_type_serializer_classes_mapping
|
||||
|
||||
class Meta(BaseStorageSerializer.Meta):
|
||||
model = CommandStorage
|
||||
|
||||
|
||||
# ReplayStorageSerializer
|
||||
|
||||
|
||||
class ReplayStorageSerializer(BaseStorageSerializer):
|
||||
storage_type_serializer_classes_mapping = replay_storage_type_serializer_classes_mapping
|
||||
|
||||
class Meta(BaseStorageSerializer.Meta):
|
||||
model = ReplayStorage
|
||||
|
||||
|
|
Loading…
Reference in New Issue