diff --git a/apps/assets/migrations/0002_auto_20180105_1807_squashed_0009_auto_20180307_1212.py b/apps/assets/migrations/0002_auto_20180105_1807_squashed_0009_auto_20180307_1212.py index 7cbf78a43..6392158fd 100644 --- a/apps/assets/migrations/0002_auto_20180105_1807_squashed_0009_auto_20180307_1212.py +++ b/apps/assets/migrations/0002_auto_20180105_1807_squashed_0009_auto_20180307_1212.py @@ -123,7 +123,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='asset', name='nodes', - field=models.ManyToManyField(default=assets.models.asset.default_node, related_name='assets', to='assets.Node', verbose_name='Nodes'), + field=models.ManyToManyField(default=assets.models.asset.default_node, related_name='assets', to='assets.Node', verbose_name='Node'), ), migrations.AddField( model_name='systemuser', diff --git a/apps/assets/migrations/0007_auto_20180225_1815.py b/apps/assets/migrations/0007_auto_20180225_1815.py index 4ce2b1e05..1097dd182 100644 --- a/apps/assets/migrations/0007_auto_20180225_1815.py +++ b/apps/assets/migrations/0007_auto_20180225_1815.py @@ -50,7 +50,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='asset', name='nodes', - field=models.ManyToManyField(default=assets.models.default_node, related_name='assets', to='assets.Node', verbose_name='Nodes'), + field=models.ManyToManyField(default=assets.models.default_node, related_name='assets', to='assets.Node', verbose_name='Node'), ), migrations.AddField( model_name='systemuser', diff --git a/apps/assets/migrations/0107_automation.py b/apps/assets/migrations/0107_automation.py index 56c2cf4eb..6841cb912 100644 --- a/apps/assets/migrations/0107_automation.py +++ b/apps/assets/migrations/0107_automation.py @@ -31,7 +31,7 @@ class Migration(migrations.Migration): ('type', models.CharField(max_length=16, verbose_name='Type')), ('is_active', models.BooleanField(default=True, verbose_name='Is active')), ('assets', models.ManyToManyField(blank=True, to='assets.Asset', verbose_name='Assets')), - ('nodes', models.ManyToManyField(blank=True, to='assets.Node', verbose_name='Nodes')), + ('nodes', models.ManyToManyField(blank=True, to='assets.Node', verbose_name='Node')), ], options={ 'verbose_name': 'Automation task', diff --git a/apps/assets/models/asset/common.py b/apps/assets/models/asset/common.py index 93294fd5b..558164df6 100644 --- a/apps/assets/models/asset/common.py +++ b/apps/assets/models/asset/common.py @@ -162,7 +162,7 @@ class Asset(NodesRelationMixin, LabeledMixin, AbsConnectivity, JSONFilterMixin, domain = models.ForeignKey("assets.Domain", null=True, blank=True, related_name='assets', verbose_name=_("Domain"), on_delete=models.SET_NULL) nodes = models.ManyToManyField('assets.Node', default=default_node, related_name='assets', - verbose_name=_("Nodes")) + verbose_name=_("Node")) is_active = models.BooleanField(default=True, verbose_name=_('Is active')) gathered_info = models.JSONField(verbose_name=_('Gathered info'), default=dict, blank=True) # 资产的一些信息,如 硬件信息 custom_info = models.JSONField(verbose_name=_('Custom info'), default=dict) diff --git a/apps/assets/models/automations/base.py b/apps/assets/models/automations/base.py index 27e5ed74a..c3e1fa639 100644 --- a/apps/assets/models/automations/base.py +++ b/apps/assets/models/automations/base.py @@ -15,7 +15,7 @@ from orgs.mixins.models import OrgModelMixin, JMSOrgBaseModel class BaseAutomation(PeriodTaskModelMixin, JMSOrgBaseModel): accounts = models.JSONField(default=list, verbose_name=_("Accounts")) - nodes = models.ManyToManyField('assets.Node', blank=True, verbose_name=_("Nodes")) + nodes = models.ManyToManyField('assets.Node', blank=True, verbose_name=_("Node")) assets = models.ManyToManyField('assets.Asset', blank=True, verbose_name=_("Assets")) type = models.CharField(max_length=16, verbose_name=_('Type')) is_active = models.BooleanField(default=True, verbose_name=_("Is active")) diff --git a/apps/assets/models/cmd_filter.py b/apps/assets/models/cmd_filter.py index ec6f1be3e..63fd7ca34 100644 --- a/apps/assets/models/cmd_filter.py +++ b/apps/assets/models/cmd_filter.py @@ -29,7 +29,7 @@ class CommandFilter(OrgModelMixin): ) nodes = models.ManyToManyField( 'assets.Node', related_name='cmd_filters', blank=True, - verbose_name=_("Nodes") + verbose_name=_("Node") ) assets = models.ManyToManyField( 'assets.Asset', related_name='cmd_filters', blank=True, diff --git a/apps/audits/backends/db.py b/apps/audits/backends/db.py index 870c25c9c..e8fe43c22 100644 --- a/apps/audits/backends/db.py +++ b/apps/audits/backends/db.py @@ -2,6 +2,7 @@ from django.utils.translation import gettext_lazy as _ from audits.models import OperateLog +from perms.const import ActionChoices class OperateLogStore(object): @@ -45,20 +46,29 @@ class OperateLogStore(object): before[k], after[k] = before_value, after_value return before, after + @staticmethod + def _get_special_handler(resource_type): + # 根据资源类型,处理特殊字段 + resource_map = { + 'Asset permission': lambda k, v: ActionChoices.display(int(v)) if k == 'Actions' else v + } + return resource_map.get(resource_type, lambda k, v: v) + @classmethod - def convert_diff_friendly(cls, raw_diff): + def convert_diff_friendly(cls, op_log): diff_list = list() - for k, v in raw_diff.items(): + handler = cls._get_special_handler(op_log.resource_type) + for k, v in op_log.diff.items(): before, after = v.split(cls.SEP, 1) diff_list.append({ 'field': _(k), - 'before': before if before else _('empty'), - 'after': after if after else _('empty'), + 'before': handler(k, before) if before else _('empty'), + 'after': handler(k, after) if after else _('empty'), }) return diff_list def save(self, **kwargs): - log_id = kwargs.pop('id', None) + log_id = kwargs.get('id', None) before = kwargs.pop('before') or {} after = kwargs.pop('after') or {} diff --git a/apps/audits/serializers.py b/apps/audits/serializers.py index b68d1a516..78c42fdd0 100644 --- a/apps/audits/serializers.py +++ b/apps/audits/serializers.py @@ -77,10 +77,7 @@ class OperateLogActionDetailSerializer(serializers.ModelSerializer): fields = ('diff',) def to_representation(self, instance): - data = super().to_representation(instance) - diff = OperateLogStore.convert_diff_friendly(data['diff']) - data['diff'] = diff - return data + return {'diff': OperateLogStore.convert_diff_friendly(instance)} class OperateLogSerializer(BulkOrgResourceModelSerializer): diff --git a/apps/audits/signal_handlers/operate_log.py b/apps/audits/signal_handlers/operate_log.py index 7d89f77bd..d095a7ad6 100644 --- a/apps/audits/signal_handlers/operate_log.py +++ b/apps/audits/signal_handlers/operate_log.py @@ -33,7 +33,9 @@ def on_m2m_changed(sender, action, instance, reverse, model, pk_set, **kwargs): with translation.override('en'): resource_type = instance._meta.verbose_name - current_instance = model_to_dict(instance, include_model_fields=False) + current_instance = model_to_dict( + instance, include_model_fields=False, include_related_fields=[model] + ) instance_id = current_instance.get('id') log_id, before_instance = get_instance_dict_from_cache(instance_id) @@ -176,7 +178,7 @@ def on_django_start_set_operate_log_monitor_models(sender, **kwargs): 'PermedAsset', 'PermedAccount', 'MenuPermission', 'Permission', 'TicketSession', 'ApplyLoginTicket', 'ApplyCommandTicket', 'ApplyLoginAssetTicket', - 'FavoriteAsset', + 'FavoriteAsset', 'Asset' } for i, app in enumerate(apps.get_models(), 1): app_name = app._meta.app_label diff --git a/apps/audits/utils.py b/apps/audits/utils.py index 244df5d22..5813c3db8 100644 --- a/apps/audits/utils.py +++ b/apps/audits/utils.py @@ -78,31 +78,37 @@ def _get_instance_field_value( return data -def model_to_dict_for_operate_log(instance, include_model_fields=True, include_related_fields=False): - model_need_continue_fields = ['date_updated'] - m2m_need_continue_fields = ['history_passwords'] +def model_to_dict_for_operate_log( + instance, include_model_fields=True, include_related_fields=None +): + def get_related_values(f): + value = [] + if instance.pk is not None: + related_name = getattr(f, 'attname', '') or getattr(f, 'related_name', '') + if not related_name or related_name in ['history_passwords']: + return + try: + value = [str(i) for i in getattr(instance, related_name).all()] + except: + pass + if not value: + return + try: + field_key = getattr(f, 'verbose_name', None) or f.related_model._meta.verbose_name + data.setdefault(str(field_key), value) + except: + pass data = _get_instance_field_value( - instance, include_model_fields, model_need_continue_fields + instance, include_model_fields, ['date_updated'] ) if include_related_fields: opts = instance._meta - for f in opts.many_to_many: - value = [] - if instance.pk is not None: - related_name = getattr(f, 'attname', '') or getattr(f, 'related_name', '') - if not related_name or related_name in m2m_need_continue_fields: - continue - try: - value = [str(i) for i in getattr(instance, related_name).all()] - except: - pass - if not value: + for f in chain(opts.many_to_many, opts.related_objects): + related_model = getattr(f, 'related_model', None) + if related_model not in include_related_fields: continue - try: - field_key = getattr(f, 'verbose_name', None) or f.related_model._meta.verbose_name - data.setdefault(str(field_key), value) - except: - pass + get_related_values(f) + return data diff --git a/apps/jumpserver/conf.py b/apps/jumpserver/conf.py index 7492f5c4d..a0ecff1d1 100644 --- a/apps/jumpserver/conf.py +++ b/apps/jumpserver/conf.py @@ -584,7 +584,7 @@ class Config(dict): 'APPLET_DOWNLOAD_HOST': '', # FTP 文件上传下载备份阈值,单位(M),当值小于等于0时,不备份 - 'FTP_FILE_MAX_STORE': 100, + 'FTP_FILE_MAX_STORE': 0, # API 分页 'MAX_LIMIT_PER_PAGE': 10000, diff --git a/apps/perms/migrations/0002_auto_20171228_0025_squashed_0009_auto_20180903_1132.py b/apps/perms/migrations/0002_auto_20171228_0025_squashed_0009_auto_20180903_1132.py index f7f191f4a..12d8e70ce 100644 --- a/apps/perms/migrations/0002_auto_20171228_0025_squashed_0009_auto_20180903_1132.py +++ b/apps/perms/migrations/0002_auto_20171228_0025_squashed_0009_auto_20180903_1132.py @@ -80,7 +80,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='assetpermission', name='nodes', - field=models.ManyToManyField(blank=True, related_name='granted_by_permissions', to='assets.Node', verbose_name='Nodes'), + field=models.ManyToManyField(blank=True, related_name='granted_by_permissions', to='assets.Node', verbose_name='Node'), ), # migrations.RunPython( # code=migrate_node_permissions, diff --git a/apps/perms/models/asset_permission.py b/apps/perms/models/asset_permission.py index 9db73e5df..5ecf824c0 100644 --- a/apps/perms/models/asset_permission.py +++ b/apps/perms/models/asset_permission.py @@ -69,7 +69,7 @@ class AssetPermission(LabeledMixin, JMSOrgBaseModel): 'assets.Asset', related_name='granted_by_permissions', blank=True, verbose_name=_("Asset") ) nodes = models.ManyToManyField( - 'assets.Node', related_name='granted_by_permissions', blank=True, verbose_name=_("Nodes") + 'assets.Node', related_name='granted_by_permissions', blank=True, verbose_name=_("Node") ) # 特殊的账号: @ALL, @INPUT @USER 默认包含,将来在全局设置中进行控制. accounts = models.JSONField(default=list, verbose_name=_("Account")) diff --git a/apps/terminal/models/component/task.py b/apps/terminal/models/component/task.py index c69a89423..572167cf3 100644 --- a/apps/terminal/models/component/task.py +++ b/apps/terminal/models/component/task.py @@ -20,3 +20,6 @@ class Task(JMSBaseModel): class Meta: db_table = "terminal_task" verbose_name = _("Task") + + def __str__(self): + return str(dict(SessionTaskChoices.choices).get(self.name))