From c34b7e69eb0f3a8e8238832f9b7e36823e6cb3c5 Mon Sep 17 00:00:00 2001 From: jiangweidong Date: Mon, 30 Jan 2023 17:33:10 +0800 Subject: [PATCH 01/92] =?UTF-8?q?fix:=20mongodb=E6=97=A0=E6=8C=87=E5=AE=9A?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=BA=93=E6=97=B6=EF=BC=8C=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=8C=96=E4=BB=BB=E5=8A=A1=E4=BC=9A=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/serializers/asset/database.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apps/assets/serializers/asset/database.py b/apps/assets/serializers/asset/database.py index c4ad0171d..9ef2232a7 100644 --- a/apps/assets/serializers/asset/database.py +++ b/apps/assets/serializers/asset/database.py @@ -1,3 +1,6 @@ +from rest_framework.serializers import ValidationError +from django.utils.translation import ugettext_lazy as _ + from assets.models import Database from .common import AssetSerializer from ..gateway import GatewayWithAccountSecretSerializer @@ -14,6 +17,13 @@ class DatabaseSerializer(AssetSerializer): ] fields = AssetSerializer.Meta.fields + extra_fields + def validate(self, attrs): + platform = attrs.get('platform') + if platform and getattr(platform, 'name') == 'MongoDB' \ + and not attrs.get('db_name'): + raise ValidationError({'db_name': _('This field is required.')}) + return attrs + class DatabaseWithGatewaySerializer(DatabaseSerializer): gateway = GatewayWithAccountSecretSerializer() From 87ca9cb11d004fd60f11a4393a27de3f0d43d2d4 Mon Sep 17 00:00:00 2001 From: jiangweidong Date: Mon, 30 Jan 2023 20:26:07 +0800 Subject: [PATCH 02/92] =?UTF-8?q?fix:=20=E4=BD=BF=E7=94=A8type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/serializers/asset/database.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/assets/serializers/asset/database.py b/apps/assets/serializers/asset/database.py index 9ef2232a7..4c00c486c 100644 --- a/apps/assets/serializers/asset/database.py +++ b/apps/assets/serializers/asset/database.py @@ -19,7 +19,7 @@ class DatabaseSerializer(AssetSerializer): def validate(self, attrs): platform = attrs.get('platform') - if platform and getattr(platform, 'name') == 'MongoDB' \ + if platform and getattr(platform, 'type') == 'mongodb' \ and not attrs.get('db_name'): raise ValidationError({'db_name': _('This field is required.')}) return attrs From 382201188c8490da96b847725129f3554248a538 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 31 Jan 2023 10:22:25 +0800 Subject: [PATCH 03/92] =?UTF-8?q?perf:=20admin=20user=20=E4=B8=8D=E8=83=BD?= =?UTF-8?q?=E5=88=A0=E9=99=A4=EF=BC=8Cxpack=20=20=E5=BC=95=E7=94=A8?= =?UTF-8?q?=E7=9D=80=EF=BC=8C=E4=B8=8D=E7=A1=AE=E5=AE=9A=E9=A1=BA=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0104_auto_20220817_1544.py | 3 -- apps/assets/models/_user.py | 53 ++++++++++++++----- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/apps/assets/migrations/0104_auto_20220817_1544.py b/apps/assets/migrations/0104_auto_20220817_1544.py index 864eba8f1..972c34e09 100644 --- a/apps/assets/migrations/0104_auto_20220817_1544.py +++ b/apps/assets/migrations/0104_auto_20220817_1544.py @@ -52,9 +52,6 @@ class Migration(migrations.Migration): migrations.DeleteModel( name='Cluster', ), - migrations.DeleteModel( - name='AdminUser', - ), migrations.DeleteModel( name='HistoricalAuthBook', ), diff --git a/apps/assets/models/_user.py b/apps/assets/models/_user.py index d7809a2b3..019147456 100644 --- a/apps/assets/models/_user.py +++ b/apps/assets/models/_user.py @@ -17,7 +17,23 @@ __all__ = ['SystemUser'] logger = logging.getLogger(__name__) -class SystemUser(OrgModelMixin): +class OldBaseUser(models.Model): + id = models.UUIDField(default=uuid.uuid4, primary_key=True) + name = models.CharField(max_length=128, verbose_name=_('Name')) + username = models.CharField(max_length=128, blank=True, verbose_name=_('Username'), db_index=True) + password = fields.EncryptCharField(max_length=256, blank=True, null=True, verbose_name=_('Password')) + private_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH private key')) + public_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH public key')) + comment = models.TextField(blank=True, verbose_name=_('Comment')) + 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')) + + class Meta: + abstract = True + + +class SystemUser(OrgModelMixin, OldBaseUser): LOGIN_AUTO = 'auto' LOGIN_MANUAL = 'manual' LOGIN_MODE_CHOICES = ( @@ -29,19 +45,7 @@ class SystemUser(OrgModelMixin): common = 'common', _('Common user') admin = 'admin', _('Admin user') - id = models.UUIDField(default=uuid.uuid4, primary_key=True) - name = models.CharField(max_length=128, verbose_name=_('Name')) - username = models.CharField(max_length=128, blank=True, verbose_name=_('Username'), db_index=True) - password = fields.EncryptCharField(max_length=256, blank=True, null=True, verbose_name=_('Password')) - private_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH private key')) - public_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH public key')) token = models.TextField(default='', verbose_name=_('Token')) - - comment = models.TextField(blank=True, verbose_name=_('Comment')) - 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')) - username_same_with_user = models.BooleanField(default=False, verbose_name=_("Username same with user")) type = models.CharField(max_length=16, choices=Type.choices, default=Type.common, verbose_name=_('Type')) priority = models.IntegerField(default=81, verbose_name=_("Priority"), help_text=_("1-100, the lower the value will be match first"), validators=[MinValueValidator(1), MaxValueValidator(100)]) @@ -66,3 +70,26 @@ class SystemUser(OrgModelMixin): permissions = [ ('match_systemuser', _('Can match system user')), ] + + +# Deprecated: 准备废弃 +class AdminUser(OrgModelMixin, OldBaseUser): + """ + A privileged user that ansible can use it to push system user and so on + """ + BECOME_METHOD_CHOICES = ( + ('sudo', 'sudo'), + ('su', 'su'), + ) + become = models.BooleanField(default=True) + become_method = models.CharField(choices=BECOME_METHOD_CHOICES, default='sudo', max_length=4) + become_user = models.CharField(default='root', max_length=64) + _become_pass = models.CharField(default='', blank=True, max_length=128) + + def __str__(self): + return self.name + + class Meta: + ordering = ['name'] + unique_together = [('name', 'org_id')] + verbose_name = _("Admin user") \ No newline at end of file From 0c1048ed89f1f7d46bbc48a3f9d39e6867ff2e5b Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 31 Jan 2023 10:42:55 +0800 Subject: [PATCH 04/92] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20migrations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0093_auto_20220403_1627.py | 18 ++++++++++++------ apps/assets/migrations/0107_automation.py | 18 ++---------------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/apps/assets/migrations/0093_auto_20220403_1627.py b/apps/assets/migrations/0093_auto_20220403_1627.py index ee536497e..71d88f773 100644 --- a/apps/assets/migrations/0093_auto_20220403_1627.py +++ b/apps/assets/migrations/0093_auto_20220403_1627.py @@ -71,12 +71,18 @@ class Migration(migrations.Migration): ), 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'}, + options={ + 'ordering': ['name'], + 'permissions': [ + ('refresh_assethardwareinfo', 'Can refresh asset hardware info'), + ('test_assetconnectivity', 'Can test asset connectivity'), + ('push_assetaccount', 'Can push account to asset'), + ('test_account', 'Can verify account'), ('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', diff --git a/apps/assets/migrations/0107_automation.py b/apps/assets/migrations/0107_automation.py index 38bb777e4..56c2cf4eb 100644 --- a/apps/assets/migrations/0107_automation.py +++ b/apps/assets/migrations/0107_automation.py @@ -35,7 +35,7 @@ class Migration(migrations.Migration): ], options={ 'verbose_name': 'Automation task', - 'unique_together': {('org_id', 'name')}, + 'unique_together': {('org_id', 'name', 'type')}, }, ), migrations.CreateModel( @@ -93,18 +93,4 @@ class Migration(migrations.Migration): name='automation', field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='executions', to='assets.baseautomation', verbose_name='Automation task'), ), - migrations.AlterUniqueTogether( - name='baseautomation', - unique_together={('org_id', 'name', 'type')}, - ), - migrations.AlterModelOptions( - name='asset', - options={'ordering': ['name'], - 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), - ('test_assetconnectivity', 'Can test asset connectivity'), - ('push_assetaccount', 'Can push account to asset'), - ('test_account', 'Can verify account'), ('match_asset', 'Can match asset'), - ('add_assettonode', 'Add asset to node'), - ('move_assettonode', 'Move asset to node')], 'verbose_name': 'Asset'}, - ), -] + ] From 3702ba92ead51c187722732a69a4294522676c64 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 31 Jan 2023 11:00:21 +0800 Subject: [PATCH 05/92] perf: celery task delete (#9372) Co-authored-by: feng <1304903146@qq.com> --- apps/ops/api/celery.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/apps/ops/api/celery.py b/apps/ops/api/celery.py index f55c296f9..ba6de12b4 100644 --- a/apps/ops/api/celery.py +++ b/apps/ops/api/celery.py @@ -1,31 +1,26 @@ # -*- coding: utf-8 -*- # - import os import re +from celery.result import AsyncResult +from rest_framework import generics, viewsets, mixins from django.shortcuts import get_object_or_404 from django.utils.translation import ugettext as _ -from rest_framework import viewsets -from celery.result import AsyncResult -from rest_framework import generics from django_celery_beat.models import PeriodicTask - from common.permissions import IsValidUser -from common.api import LogTailApi +from common.api import LogTailApi, CommonApiMixin from ..models import CeleryTaskExecution, CeleryTask -from ..serializers import CeleryResultSerializer, CeleryPeriodTaskSerializer from ..celery.utils import get_celery_task_log_path from ..ansible.utils import get_ansible_task_log_path -from common.api import CommonApiMixin +from ..serializers import CeleryResultSerializer, CeleryPeriodTaskSerializer +from ..serializers.celery import CeleryTaskSerializer, CeleryTaskExecutionSerializer __all__ = [ 'CeleryTaskExecutionLogApi', 'CeleryResultApi', 'CeleryPeriodTaskViewSet', 'AnsibleTaskLogApi', 'CeleryTaskViewSet', 'CeleryTaskExecutionViewSet' ] -from ..serializers.celery import CeleryTaskSerializer, CeleryTaskExecutionSerializer - class CeleryTaskExecutionLogApi(LogTailApi): permission_classes = (IsValidUser,) @@ -103,9 +98,12 @@ class CelerySummaryAPIView(generics.RetrieveAPIView): pass -class CeleryTaskViewSet(CommonApiMixin, viewsets.ReadOnlyModelViewSet): +class CeleryTaskViewSet( + CommonApiMixin, mixins.RetrieveModelMixin, + mixins.ListModelMixin, mixins.DestroyModelMixin, + viewsets.GenericViewSet +): serializer_class = CeleryTaskSerializer - http_method_names = ('get', 'head', 'options',) def get_queryset(self): return CeleryTask.objects.exclude(name__startswith='celery') From d5cc2e77b224aaa0d843b41c2b9ee975cc16854f Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 31 Jan 2023 10:22:25 +0800 Subject: [PATCH 06/92] =?UTF-8?q?perf:=20admin=20user=20=E4=B8=8D=E8=83=BD?= =?UTF-8?q?=E5=88=A0=E9=99=A4=EF=BC=8Cxpack=20=20=E5=BC=95=E7=94=A8?= =?UTF-8?q?=E7=9D=80=EF=BC=8C=E4=B8=8D=E7=A1=AE=E5=AE=9A=E9=A1=BA=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0104_auto_20220817_1544.py | 3 -- apps/assets/models/_user.py | 53 ++++++++++++++----- 2 files changed, 40 insertions(+), 16 deletions(-) diff --git a/apps/assets/migrations/0104_auto_20220817_1544.py b/apps/assets/migrations/0104_auto_20220817_1544.py index 864eba8f1..972c34e09 100644 --- a/apps/assets/migrations/0104_auto_20220817_1544.py +++ b/apps/assets/migrations/0104_auto_20220817_1544.py @@ -52,9 +52,6 @@ class Migration(migrations.Migration): migrations.DeleteModel( name='Cluster', ), - migrations.DeleteModel( - name='AdminUser', - ), migrations.DeleteModel( name='HistoricalAuthBook', ), diff --git a/apps/assets/models/_user.py b/apps/assets/models/_user.py index d7809a2b3..019147456 100644 --- a/apps/assets/models/_user.py +++ b/apps/assets/models/_user.py @@ -17,7 +17,23 @@ __all__ = ['SystemUser'] logger = logging.getLogger(__name__) -class SystemUser(OrgModelMixin): +class OldBaseUser(models.Model): + id = models.UUIDField(default=uuid.uuid4, primary_key=True) + name = models.CharField(max_length=128, verbose_name=_('Name')) + username = models.CharField(max_length=128, blank=True, verbose_name=_('Username'), db_index=True) + password = fields.EncryptCharField(max_length=256, blank=True, null=True, verbose_name=_('Password')) + private_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH private key')) + public_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH public key')) + comment = models.TextField(blank=True, verbose_name=_('Comment')) + 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')) + + class Meta: + abstract = True + + +class SystemUser(OrgModelMixin, OldBaseUser): LOGIN_AUTO = 'auto' LOGIN_MANUAL = 'manual' LOGIN_MODE_CHOICES = ( @@ -29,19 +45,7 @@ class SystemUser(OrgModelMixin): common = 'common', _('Common user') admin = 'admin', _('Admin user') - id = models.UUIDField(default=uuid.uuid4, primary_key=True) - name = models.CharField(max_length=128, verbose_name=_('Name')) - username = models.CharField(max_length=128, blank=True, verbose_name=_('Username'), db_index=True) - password = fields.EncryptCharField(max_length=256, blank=True, null=True, verbose_name=_('Password')) - private_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH private key')) - public_key = fields.EncryptTextField(blank=True, null=True, verbose_name=_('SSH public key')) token = models.TextField(default='', verbose_name=_('Token')) - - comment = models.TextField(blank=True, verbose_name=_('Comment')) - 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')) - username_same_with_user = models.BooleanField(default=False, verbose_name=_("Username same with user")) type = models.CharField(max_length=16, choices=Type.choices, default=Type.common, verbose_name=_('Type')) priority = models.IntegerField(default=81, verbose_name=_("Priority"), help_text=_("1-100, the lower the value will be match first"), validators=[MinValueValidator(1), MaxValueValidator(100)]) @@ -66,3 +70,26 @@ class SystemUser(OrgModelMixin): permissions = [ ('match_systemuser', _('Can match system user')), ] + + +# Deprecated: 准备废弃 +class AdminUser(OrgModelMixin, OldBaseUser): + """ + A privileged user that ansible can use it to push system user and so on + """ + BECOME_METHOD_CHOICES = ( + ('sudo', 'sudo'), + ('su', 'su'), + ) + become = models.BooleanField(default=True) + become_method = models.CharField(choices=BECOME_METHOD_CHOICES, default='sudo', max_length=4) + become_user = models.CharField(default='root', max_length=64) + _become_pass = models.CharField(default='', blank=True, max_length=128) + + def __str__(self): + return self.name + + class Meta: + ordering = ['name'] + unique_together = [('name', 'org_id')] + verbose_name = _("Admin user") \ No newline at end of file From b34af62ec1505ffc140adda1bc99461cd8ad3b45 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 31 Jan 2023 10:42:55 +0800 Subject: [PATCH 07/92] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20migrations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0093_auto_20220403_1627.py | 18 ++++++++++++------ apps/assets/migrations/0107_automation.py | 18 ++---------------- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/apps/assets/migrations/0093_auto_20220403_1627.py b/apps/assets/migrations/0093_auto_20220403_1627.py index ee536497e..71d88f773 100644 --- a/apps/assets/migrations/0093_auto_20220403_1627.py +++ b/apps/assets/migrations/0093_auto_20220403_1627.py @@ -71,12 +71,18 @@ class Migration(migrations.Migration): ), 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'}, + options={ + 'ordering': ['name'], + 'permissions': [ + ('refresh_assethardwareinfo', 'Can refresh asset hardware info'), + ('test_assetconnectivity', 'Can test asset connectivity'), + ('push_assetaccount', 'Can push account to asset'), + ('test_account', 'Can verify account'), ('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', diff --git a/apps/assets/migrations/0107_automation.py b/apps/assets/migrations/0107_automation.py index 38bb777e4..56c2cf4eb 100644 --- a/apps/assets/migrations/0107_automation.py +++ b/apps/assets/migrations/0107_automation.py @@ -35,7 +35,7 @@ class Migration(migrations.Migration): ], options={ 'verbose_name': 'Automation task', - 'unique_together': {('org_id', 'name')}, + 'unique_together': {('org_id', 'name', 'type')}, }, ), migrations.CreateModel( @@ -93,18 +93,4 @@ class Migration(migrations.Migration): name='automation', field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='executions', to='assets.baseautomation', verbose_name='Automation task'), ), - migrations.AlterUniqueTogether( - name='baseautomation', - unique_together={('org_id', 'name', 'type')}, - ), - migrations.AlterModelOptions( - name='asset', - options={'ordering': ['name'], - 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), - ('test_assetconnectivity', 'Can test asset connectivity'), - ('push_assetaccount', 'Can push account to asset'), - ('test_account', 'Can verify account'), ('match_asset', 'Can match asset'), - ('add_assettonode', 'Add asset to node'), - ('move_assettonode', 'Move asset to node')], 'verbose_name': 'Asset'}, - ), -] + ] From 9d59fb736b9dafced335053eb1bf17b3d54f6f04 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 31 Jan 2023 13:03:45 +0800 Subject: [PATCH 08/92] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20database=20?= =?UTF-8?q?=E7=9A=84=20cert=20model=20field?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/migrations/0093_auto_20220403_1627.py | 7 ++++--- apps/assets/models/asset/common.py | 2 ++ apps/assets/models/asset/database.py | 15 ++++----------- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/apps/assets/migrations/0093_auto_20220403_1627.py b/apps/assets/migrations/0093_auto_20220403_1627.py index 71d88f773..45b8e92ed 100644 --- a/apps/assets/migrations/0093_auto_20220403_1627.py +++ b/apps/assets/migrations/0093_auto_20220403_1627.py @@ -2,6 +2,7 @@ import django.db from django.db import migrations, models +import common.db.fields def migrate_to_host(apps, schema_editor): @@ -120,9 +121,9 @@ class Migration(migrations.Migration): primary_key=True, serialize=False, to='assets.asset')), ('db_name', models.CharField(blank=True, max_length=1024, verbose_name='Database')), ('allow_invalid_cert', models.BooleanField(default=False, verbose_name='Allow invalid cert')), - ('ca_cert', models.TextField(blank=True, verbose_name='CA cert')), - ('client_cert', models.TextField(blank=True, verbose_name='Client cert')), - ('client_key', models.TextField(blank=True, verbose_name='Client key'),), + ('ca_cert', common.db.fields.EncryptTextField(blank=True, verbose_name='CA cert')), + ('client_cert', common.db.fields.EncryptTextField(blank=True, verbose_name='Client cert')), + ('client_key', common.db.fields.EncryptTextField(blank=True, verbose_name='Client key'),), ('use_ssl', models.BooleanField(default=False, verbose_name='Use SSL'),), ], options={ diff --git a/apps/assets/models/asset/common.py b/apps/assets/models/asset/common.py index c7d8238e0..3914f000c 100644 --- a/apps/assets/models/asset/common.py +++ b/apps/assets/models/asset/common.py @@ -11,6 +11,7 @@ from django.utils.translation import ugettext_lazy as _ from assets import const from common.utils import lazyproperty +from common.db.fields import EncryptMixin from orgs.mixins.models import OrgManager, JMSOrgBaseModel from ..base import AbsConnectivity from ..platform import Platform @@ -139,6 +140,7 @@ class Asset(NodesRelationMixin, AbsConnectivity, JMSOrgBaseModel): if not instance: return [] specific_fields = self.get_specific_fields(instance) + specific_fields = [i for i in specific_fields if not isinstance(i, EncryptMixin)] info = [ { 'label': i.verbose_name, diff --git a/apps/assets/models/asset/database.py b/apps/assets/models/asset/database.py index 2c033de9e..12da55b30 100644 --- a/apps/assets/models/asset/database.py +++ b/apps/assets/models/asset/database.py @@ -1,28 +1,21 @@ from django.db import models from django.utils.translation import gettext_lazy as _ +from common.db.fields import EncryptTextField from .common import Asset class Database(Asset): db_name = models.CharField(max_length=1024, verbose_name=_("Database"), blank=True) use_ssl = models.BooleanField(default=False, verbose_name=_("Use SSL")) - ca_cert = models.TextField(verbose_name=_("CA cert"), blank=True) - client_cert = models.TextField(verbose_name=_("Client cert"), blank=True) - client_key = models.TextField(verbose_name=_("Client key"), blank=True) + ca_cert = EncryptTextField(verbose_name=_("CA cert"), blank=True) + client_cert = EncryptTextField(verbose_name=_("Client cert"), blank=True) + client_key = EncryptTextField(verbose_name=_("Client key"), blank=True) allow_invalid_cert = models.BooleanField(default=False, verbose_name=_('Allow invalid cert')) def __str__(self): return '{}({}://{}/{})'.format(self.name, self.type, self.address, self.db_name) - @property - def specific(self): - return { - 'db_name': self.db_name, - 'use_ssl': self.use_ssl, - 'allow_invalid_cert': self.allow_invalid_cert, - } - @property def ip(self): return self.address From 9161b1ab1c7781c26005adaba4c0fb9e3daca42f Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 31 Jan 2023 13:41:09 +0800 Subject: [PATCH 09/92] =?UTF-8?q?perf:=20=E8=B5=84=E4=BA=A7=E7=9A=84=20spe?= =?UTF-8?q?cific=20=E4=B8=8D=E8=BF=94=E5=9B=9E=E5=8A=A0=E5=AF=86=E4=BF=A1?= =?UTF-8?q?=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/models/asset/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/assets/models/asset/common.py b/apps/assets/models/asset/common.py index 3914f000c..60f2f3c14 100644 --- a/apps/assets/models/asset/common.py +++ b/apps/assets/models/asset/common.py @@ -140,7 +140,6 @@ class Asset(NodesRelationMixin, AbsConnectivity, JMSOrgBaseModel): if not instance: return [] specific_fields = self.get_specific_fields(instance) - specific_fields = [i for i in specific_fields if not isinstance(i, EncryptMixin)] info = [ { 'label': i.verbose_name, @@ -169,6 +168,7 @@ class Asset(NodesRelationMixin, AbsConnectivity, JMSOrgBaseModel): @staticmethod def get_specific_fields(instance): specific_fields = [i for i in instance._meta.local_fields if i.name != 'asset_ptr'] + specific_fields = [i for i in specific_fields if not isinstance(i, EncryptMixin)] return specific_fields def get_target_ip(self): From 229e89af0335b60b6927459fae9f394cbc1a0f52 Mon Sep 17 00:00:00 2001 From: Bai Date: Tue, 31 Jan 2023 15:00:02 +0800 Subject: [PATCH 10/92] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=BB=88?= =?UTF-8?q?=E7=AB=AF=E5=88=97=E8=A1=A8=E6=A0=B9=E6=8D=AE=E8=B4=9F=E8=BD=BD?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E8=BF=9B=E8=A1=8C=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/api/component/terminal.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/terminal/api/component/terminal.py b/apps/terminal/api/component/terminal.py index e2e1ad22f..d877be1df 100644 --- a/apps/terminal/api/component/terminal.py +++ b/apps/terminal/api/component/terminal.py @@ -25,7 +25,7 @@ class TerminalViewSet(JMSBulkModelViewSet): queryset = Terminal.objects.filter(is_deleted=False) serializer_class = serializers.TerminalSerializer filterset_fields = ['name', 'remote_addr', 'type'] - custom_filter_fields = ['status'] + custom_filter_fields = ['load'] def destroy(self, request, *args, **kwargs): instance = self.get_object() @@ -40,7 +40,7 @@ class TerminalViewSet(JMSBulkModelViewSet): def filter_queryset(self, queryset): queryset = super().filter_queryset(queryset) - s = self.request.query_params.get('status') + s = self.request.query_params.get('load') if not s: return queryset filtered_queryset_id = [str(q.id) for q in queryset if q.load == s] From 6b4dbe655484e134cdb5ddd849e25cec01c356ee Mon Sep 17 00:00:00 2001 From: Bai Date: Tue, 31 Jan 2023 15:43:06 +0800 Subject: [PATCH 11/92] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7=E5=88=97=E8=A1=A8=E5=AF=BC=E5=87=BA500=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/audits/handler.py | 11 +++++++---- apps/common/views/mixins.py | 7 +++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/apps/audits/handler.py b/apps/audits/handler.py index 7aff4c427..9d521824b 100644 --- a/apps/audits/handler.py +++ b/apps/audits/handler.py @@ -183,7 +183,7 @@ class OperatorLogHandler(metaclass=Singleton): return data def create_or_update_operate_log( - self, action, resource_type, resource=None, + self, action, resource_type, resource=None, resource_display=None, force=False, log_id=None, before=None, after=None, object_name=None ): @@ -192,7 +192,9 @@ class OperatorLogHandler(metaclass=Singleton): return remote_addr = get_request_ip(current_request) - resource_display = self.get_resource_display(resource) + if resource_display is None: + resource_display = self.get_resource_display(resource) + resource_id = resource.id if resource is not None else '' before, after = self.data_processing(before, after) if not force and not any([before, after]): # 前后都没变化,没必要生成日志,除非手动强制保存 @@ -200,9 +202,10 @@ class OperatorLogHandler(metaclass=Singleton): data = { 'id': log_id, "user": str(user), 'action': action, - 'resource_type': str(resource_type), 'resource': resource_display, + 'resource_type': str(resource_type), + 'resource_id': resource_id, 'resource': resource_display, 'remote_addr': remote_addr, 'before': before, 'after': after, - 'org_id': get_current_org_id(), 'resource_id': str(resource.id) + 'org_id': get_current_org_id(), } data = self._activity_handle(data, object_name, resource=resource) with transaction.atomic(): diff --git a/apps/common/views/mixins.py b/apps/common/views/mixins.py index 39b146b3f..b0c38dee2 100644 --- a/apps/common/views/mixins.py +++ b/apps/common/views/mixins.py @@ -66,11 +66,11 @@ class RecordViewLogMixin: def list(self, request, *args, **kwargs): response = super().list(request, *args, **kwargs) - resource = self.get_resource_display(request) + resource_display = self.get_resource_display(request) resource_type = self.model._meta.verbose_name create_or_update_operate_log( self.ACTION, resource_type, force=True, - resource=resource + resource_display=resource_display ) return response @@ -78,7 +78,6 @@ class RecordViewLogMixin: response = super().retrieve(request, *args, **kwargs) resource_type = self.model._meta.verbose_name create_or_update_operate_log( - self.ACTION, resource_type, force=True, - resource=self.get_object() + self.ACTION, resource_type, force=True, resource=self.get_object() ) return response From a7b744db1074e87782c4c1f29c00fe3531b41ef5 Mon Sep 17 00:00:00 2001 From: Bai Date: Tue, 31 Jan 2023 16:05:28 +0800 Subject: [PATCH 12/92] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7=E5=88=97=E8=A1=A8=20secret=20=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E5=90=8D=E7=A7=B0=20=E5=AF=86=E9=92=A5/=E5=AF=86=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/serializers/account/base.py | 2 +- apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/ja/LC_MESSAGES/django.po | 481 ++++++++++++---------- apps/locale/zh/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.po | 478 +++++++++++---------- 5 files changed, 518 insertions(+), 451 deletions(-) diff --git a/apps/accounts/serializers/account/base.py b/apps/accounts/serializers/account/base.py index d92c4cc9c..529704ef1 100644 --- a/apps/accounts/serializers/account/base.py +++ b/apps/accounts/serializers/account/base.py @@ -16,7 +16,7 @@ class AuthValidateMixin(serializers.Serializer): choices=SecretType.choices, required=True, label=_('Secret type') ) secret = EncryptedField( - label=_('Secret'), required=False, max_length=40960, allow_blank=True, + label=_('Secret/Password'), required=False, max_length=40960, allow_blank=True, allow_null=True, write_only=True, ) passphrase = serializers.CharField( diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index c4d0c146f..c36e4dc8f 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:eb850ffd130e7cad2ea8c186f94a059c6a882dd1526f7a4c4a16d2fea2a1815b -size 119290 +oid sha256:b3c3f8e65468adb0105f2cbcbb8aa3ed50066c9db439a9921932c6e2adcacec3 +size 119640 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 063cce72e..ac8957e43 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-16 14:24+0800\n" +"POT-Creation-Date: 2023-01-31 16:01+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -24,7 +24,7 @@ msgstr "パラメータ 'action' は [{}] でなければなりません。" #: accounts/const/account.py:6 #: accounts/serializers/automations/change_secret.py:33 -#: assets/models/_user.py:35 audits/signal_handlers.py:51 +#: assets/models/_user.py:24 audits/signal_handlers.py:51 #: authentication/confirm/password.py:9 authentication/forms.py:32 #: authentication/templates/authentication/login.html:288 #: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:47 @@ -45,7 +45,7 @@ msgstr "SSHキー" msgid "Access key" msgstr "アクセスキー" -#: accounts/const/account.py:9 assets/models/_user.py:38 +#: accounts/const/account.py:9 assets/models/_user.py:48 #: authentication/models/sso_token.py:14 msgid "Token" msgstr "トークン" @@ -91,102 +91,107 @@ msgstr "パスワード/キーの確認" msgid "Gather accounts" msgstr "アカウントを集める" -#: accounts/const/automation.py:43 +#: accounts/const/automation.py:26 +#, fuzzy +msgid "Verify gateway account" +msgstr "パスワード/キーの確認" + +#: accounts/const/automation.py:44 #, fuzzy #| msgid "Set password" msgid "Specific password" msgstr "パスワードの設定" -#: accounts/const/automation.py:44 +#: accounts/const/automation.py:45 msgid "Random" msgstr "" -#: accounts/const/automation.py:48 ops/const.py:13 +#: accounts/const/automation.py:49 ops/const.py:13 msgid "Append SSH KEY" msgstr "追加" -#: accounts/const/automation.py:49 ops/const.py:14 +#: accounts/const/automation.py:50 ops/const.py:14 msgid "Empty and append SSH KEY" msgstr "すべてクリアして追加" -#: accounts/const/automation.py:50 ops/const.py:15 +#: accounts/const/automation.py:51 ops/const.py:15 msgid "Replace (The key generated by JumpServer) " msgstr "置換(JumpServerによって生成された鍵)" -#: accounts/const/automation.py:55 +#: accounts/const/automation.py:56 #, fuzzy #| msgid "Date created" msgid "On asset create" msgstr "作成された日付" -#: accounts/const/automation.py:58 +#: accounts/const/automation.py:59 #, fuzzy #| msgid "After change" msgid "On perm add user" msgstr "変更後" -#: accounts/const/automation.py:60 +#: accounts/const/automation.py:61 msgid "On perm add user group" msgstr "" -#: accounts/const/automation.py:62 +#: accounts/const/automation.py:63 #, fuzzy #| msgid "permed assets" msgid "On perm add asset" msgstr "パーマ資産" -#: accounts/const/automation.py:64 +#: accounts/const/automation.py:65 #, fuzzy #| msgid "After change" msgid "On perm add node" msgstr "変更後" -#: accounts/const/automation.py:66 +#: accounts/const/automation.py:67 #, fuzzy msgid "On perm add account" msgstr "アカウントを集める" -#: accounts/const/automation.py:68 +#: accounts/const/automation.py:69 #, fuzzy #| msgid "Add asset to node" msgid "On asset join node" msgstr "ノードにアセットを追加する" -#: accounts/const/automation.py:70 +#: accounts/const/automation.py:71 #, fuzzy #| msgid "User group" msgid "On user join group" msgstr "ユーザーグループ" -#: accounts/const/automation.py:78 +#: accounts/const/automation.py:79 #, fuzzy #| msgid "After change" msgid "On perm change" msgstr "変更後" -#: accounts/const/automation.py:85 +#: accounts/const/automation.py:86 #, fuzzy #| msgid "Perm ungroup node" msgid "Inherit from group or node" msgstr "グループ化されていないノードを表示" -#: accounts/const/automation.py:93 +#: accounts/const/automation.py:94 #, fuzzy #| msgid "Created by" msgid "Create and push" msgstr "によって作成された" -#: accounts/const/automation.py:94 +#: accounts/const/automation.py:95 #, fuzzy #| msgid "Date created" msgid "Only create" msgstr "作成された日付" -#: accounts/models/account.py:47 accounts/serializers/account/account.py:77 +#: accounts/models/account.py:47 accounts/serializers/account/account.py:88 #: accounts/serializers/automations/change_secret.py:107 #: accounts/serializers/automations/change_secret.py:127 acls/models/base.py:96 -#: acls/serializers/base.py:56 assets/models/asset/common.py:96 -#: assets/models/asset/common.py:281 assets/models/cmd_filter.py:36 +#: acls/serializers/base.py:56 assets/models/asset/common.py:97 +#: assets/models/asset/common.py:286 assets/models/cmd_filter.py:36 #: assets/serializers/domain.py:19 assets/serializers/label.py:27 #: audits/models.py:34 authentication/models/connection_token.py:32 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:27 @@ -197,17 +202,17 @@ msgstr "作成された日付" msgid "Asset" msgstr "資産" -#: accounts/models/account.py:51 accounts/serializers/account/account.py:81 +#: accounts/models/account.py:51 accounts/serializers/account/account.py:92 #: authentication/serializers/connect_token_secret.py:49 msgid "Su from" msgstr "から切り替え" #: accounts/models/account.py:53 settings/serializers/auth/cas.py:20 -#: terminal/models/applet/applet.py:25 +#: terminal/models/applet/applet.py:26 msgid "Version" msgstr "バージョン" -#: accounts/models/account.py:55 accounts/serializers/account/account.py:78 +#: accounts/models/account.py:55 accounts/serializers/account/account.py:89 #: users/models/user.py:727 msgid "Source" msgstr "ソース" @@ -215,7 +220,7 @@ msgstr "ソース" #: accounts/models/account.py:58 #: accounts/serializers/automations/change_secret.py:108 #: accounts/serializers/automations/change_secret.py:128 acls/models/base.py:98 -#: acls/serializers/base.py:57 assets/serializers/asset/common.py:125 +#: acls/serializers/base.py:57 assets/serializers/asset/common.py:121 #: assets/serializers/gateway.py:30 audits/models.py:35 ops/models/base.py:18 #: terminal/backends/command/models.py:22 terminal/models/session/session.py:33 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 @@ -238,7 +243,7 @@ msgstr "資産履歴アカウントを表示できます" msgid "Can view asset history account secret" msgstr "資産履歴アカウントパスワードを表示できます" -#: accounts/models/account.py:104 accounts/serializers/account/account.py:16 +#: accounts/models/account.py:104 accounts/serializers/account/account.py:34 #, fuzzy msgid "Account template" msgstr "アカウント名" @@ -255,7 +260,7 @@ msgstr "資産口座の秘密を変更できます" #: accounts/models/automations/backup_account.py:25 #: accounts/models/automations/change_secret.py:47 -#: accounts/serializers/account/backup.py:29 +#: accounts/serializers/account/backup.py:32 #: accounts/serializers/automations/change_secret.py:56 msgid "Recipient" msgstr "受信者" @@ -266,7 +271,7 @@ msgid "Account backup plan" msgstr "アカウントバックアップ計画" #: accounts/models/automations/backup_account.py:77 -#: assets/models/automations/base.py:102 audits/models.py:41 +#: assets/models/automations/base.py:106 audits/models.py:41 #: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:107 #: perms/models/asset_permission.py:72 terminal/models/applet/host.py:108 #: terminal/models/session/session.py:43 @@ -286,13 +291,14 @@ msgid "Account backup snapshot" msgstr "アカウントのバックアップスナップショット" #: accounts/models/automations/backup_account.py:88 -#: accounts/serializers/automations/base.py:42 -#: assets/models/automations/base.py:109 +#: accounts/serializers/account/backup.py:39 +#: accounts/serializers/automations/base.py:44 +#: assets/models/automations/base.py:113 #: assets/serializers/automations/base.py:40 msgid "Trigger mode" msgstr "トリガーモード" -#: accounts/models/automations/backup_account.py:91 audits/models.py:130 +#: accounts/models/automations/backup_account.py:91 audits/models.py:129 #: terminal/models/session/sharing.py:107 xpack/plugins/cloud/models.py:176 msgid "Reason" msgstr "理由" @@ -352,7 +358,7 @@ msgid "Can add push account execution" msgstr "収集アカウントの作成実行" #: accounts/models/automations/change_secret.py:17 accounts/models/base.py:36 -#: accounts/serializers/account/account.py:114 +#: accounts/serializers/account/account.py:125 #: accounts/serializers/account/base.py:16 #: accounts/serializers/automations/change_secret.py:46 #: authentication/serializers/connect_token_secret.py:40 @@ -367,7 +373,6 @@ msgstr "鍵ポリシー" #: accounts/models/automations/change_secret.py:23 #: accounts/models/automations/change_secret.py:72 accounts/models/base.py:38 -#: accounts/serializers/account/base.py:19 #: authentication/models/temp_token.py:10 #: authentication/templates/authentication/_access_key_modal.html:31 #: settings/serializers/auth/radius.py:19 @@ -399,7 +404,7 @@ msgid "Date started" msgstr "開始日" #: accounts/models/automations/change_secret.py:74 -#: assets/models/automations/base.py:103 ops/models/base.py:56 +#: assets/models/automations/base.py:107 ops/models/base.py:56 #: ops/models/celery.py:64 ops/models/job.py:108 #: terminal/models/applet/host.py:109 msgid "Date finished" @@ -429,7 +434,7 @@ msgstr "トリガーモード" #: accounts/models/automations/push_account.py:14 accounts/models/base.py:34 #: acls/serializers/base.py:18 acls/serializers/base.py:49 -#: assets/models/_user.py:34 audits/models.py:115 authentication/forms.py:25 +#: assets/models/_user.py:23 audits/models.py:114 authentication/forms.py:25 #: authentication/forms.py:27 authentication/models/temp_token.py:9 #: authentication/templates/authentication/_msg_different_city.html:9 #: authentication/templates/authentication/_msg_oauth_bind.html:9 @@ -441,7 +446,7 @@ msgstr "ユーザー名" #: accounts/models/automations/push_account.py:15 acls/models/base.py:77 #: acls/serializers/base.py:81 assets/models/cmd_filter.py:81 -#: audits/models.py:51 audits/serializers.py:75 +#: audits/models.py:51 audits/serializers.py:82 #: authentication/serializers/connect_token_secret.py:108 #: authentication/templates/authentication/_access_key_modal.html:34 msgid "Action" @@ -459,18 +464,18 @@ msgstr "パスワード/キーの確認" #: accounts/models/base.py:33 acls/models/base.py:71 #: acls/models/command_acl.py:21 acls/serializers/base.py:34 -#: applications/models.py:9 assets/models/_user.py:33 -#: assets/models/asset/common.py:94 assets/models/asset/common.py:106 +#: applications/models.py:9 assets/models/_user.py:22 +#: assets/models/asset/common.py:95 assets/models/asset/common.py:107 #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 #: assets/models/group.py:20 assets/models/label.py:18 #: assets/models/platform.py:20 assets/models/platform.py:74 -#: assets/serializers/asset/common.py:143 assets/serializers/platform.py:128 +#: assets/serializers/asset/common.py:139 assets/serializers/platform.py:125 #: authentication/serializers/connect_token_secret.py:102 ops/mixin.py:20 #: ops/models/adhoc.py:22 ops/models/celery.py:15 ops/models/celery.py:57 #: ops/models/job.py:25 ops/models/playbook.py:14 orgs/models.py:69 #: perms/models/asset_permission.py:56 rbac/models/role.py:29 #: settings/models.py:33 settings/serializers/sms.py:6 -#: terminal/models/applet/applet.py:23 terminal/models/component/endpoint.py:12 +#: terminal/models/applet/applet.py:24 terminal/models/component/endpoint.py:12 #: terminal/models/component/endpoint.py:90 #: terminal/models/component/storage.py:26 terminal/models/component/task.py:15 #: terminal/models/component/terminal.py:79 users/forms/profile.py:33 @@ -483,11 +488,11 @@ msgstr "名前" msgid "Privileged" msgstr "" -#: accounts/models/base.py:40 assets/models/asset/common.py:113 +#: accounts/models/base.py:40 assets/models/asset/common.py:114 #: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 #: assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:106 -#: terminal/models/applet/applet.py:28 users/serializers/user.py:158 +#: terminal/models/applet/applet.py:29 users/serializers/user.py:158 msgid "Is active" msgstr "アクティブです。" @@ -503,7 +508,7 @@ msgstr "" "{} -アカウントバックアップの通過タスクが完了しました。詳細は添付ファイルをご" "覧ください" -#: accounts/notifications.py:20 +#: accounts/notifications.py:21 msgid "" "{} - The account backup passage task has been completed: the encryption " "password has not been set - please go to personal information -> file " @@ -513,17 +518,17 @@ msgstr "" "されていません-個人情報にアクセスしてください-> ファイル暗号化パスワードを設" "定してください暗号化パスワード" -#: accounts/notifications.py:31 +#: accounts/notifications.py:33 msgid "Notification of implementation result of encryption change plan" msgstr "暗号化変更プランの実装結果の通知" -#: accounts/notifications.py:41 +#: accounts/notifications.py:43 msgid "" "{} - The encryption change task has been completed. See the attachment for " "details" msgstr "{} -暗号化変更タスクが完了しました。詳細は添付ファイルをご覧ください" -#: accounts/notifications.py:42 +#: accounts/notifications.py:46 msgid "" "{} - The encryption change task has been completed: the encryption password " "has not been set - please go to personal information -> file encryption " @@ -532,46 +537,50 @@ msgstr "" "{} -暗号化変更タスクが完了しました: 暗号化パスワードが設定されていません-個人" "情報にアクセスしてください-> ファイル暗号化パスワードを設定してください" -#: accounts/serializers/account/account.py:19 -#: assets/serializers/asset/common.py:52 +#: accounts/serializers/account/account.py:37 +#: assets/serializers/asset/common.py:55 msgid "Push now" msgstr "" -#: accounts/serializers/account/account.py:21 +#: accounts/serializers/account/account.py:39 #: accounts/serializers/account/base.py:64 #, fuzzy msgid "Has secret" msgstr "ひみつ" -#: accounts/serializers/account/account.py:28 -#: assets/serializers/asset/common.py:79 +#: accounts/serializers/account/account.py:46 +#: assets/serializers/asset/common.py:82 msgid "Account template not found" msgstr "" -#: accounts/serializers/account/account.py:73 +#: accounts/serializers/account/account.py:84 #, fuzzy #| msgid "Asset Info" msgid "Asset not found" msgstr "資産情報" -#: accounts/serializers/account/backup.py:27 -#: accounts/serializers/automations/base.py:35 +#: accounts/serializers/account/backup.py:30 +#: accounts/serializers/automations/base.py:36 #: assets/serializers/automations/base.py:34 ops/mixin.py:22 ops/mixin.py:102 #: settings/serializers/auth/ldap.py:66 msgid "Periodic perform" msgstr "定期的なパフォーマンス" -#: accounts/serializers/account/backup.py:28 -#: accounts/serializers/automations/gather_accounts.py:23 +#: accounts/serializers/account/backup.py:31 +#: accounts/serializers/automations/base.py:37 #, fuzzy msgid "Executed amount" msgstr "実行時間" -#: accounts/serializers/account/backup.py:30 +#: accounts/serializers/account/backup.py:33 #: accounts/serializers/automations/change_secret.py:57 msgid "Currently only mail sending is supported" msgstr "現在、メール送信のみがサポートされています" +#: accounts/serializers/account/base.py:19 +msgid "Secret/Password" +msgstr "キー/パスワード" + #: accounts/serializers/account/base.py:24 msgid "Key password" msgstr "キーパスワード" @@ -580,7 +589,7 @@ msgstr "キーパスワード" msgid "Specific" msgstr "" -#: accounts/serializers/automations/base.py:21 +#: accounts/serializers/automations/base.py:22 #: assets/models/automations/base.py:19 #: assets/serializers/automations/base.py:20 ops/models/base.py:17 #: ops/models/job.py:35 @@ -588,28 +597,28 @@ msgstr "" msgid "Assets" msgstr "資産" -#: accounts/serializers/automations/base.py:22 -#: assets/models/asset/common.py:112 assets/models/automations/base.py:18 +#: accounts/serializers/automations/base.py:23 +#: assets/models/asset/common.py:113 assets/models/automations/base.py:18 #: assets/models/cmd_filter.py:32 assets/serializers/automations/base.py:21 #: perms/models/asset_permission.py:67 msgid "Nodes" msgstr "ノード" -#: accounts/serializers/automations/base.py:40 -#: assets/models/automations/base.py:105 +#: accounts/serializers/automations/base.py:42 +#: assets/models/automations/base.py:109 #: assets/serializers/automations/base.py:39 #, fuzzy msgid "Automation snapshot" msgstr "製造オーダスナップショット" -#: accounts/serializers/automations/base.py:41 acls/models/command_acl.py:24 +#: accounts/serializers/automations/base.py:43 acls/models/command_acl.py:24 #: acls/serializers/command_acl.py:18 applications/models.py:14 -#: assets/models/_user.py:46 assets/models/automations/base.py:20 +#: assets/models/_user.py:50 assets/models/automations/base.py:20 #: assets/models/cmd_filter.py:74 assets/models/platform.py:76 -#: assets/serializers/asset/common.py:122 assets/serializers/platform.py:86 -#: audits/serializers.py:47 +#: assets/serializers/asset/common.py:118 assets/serializers/platform.py:86 +#: audits/serializers.py:48 #: authentication/serializers/connect_token_secret.py:115 ops/models/job.py:33 -#: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:27 +#: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:28 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:146 terminal/serializers/applet.py:28 #: terminal/serializers/session.py:26 terminal/serializers/storage.py:181 @@ -633,21 +642,22 @@ msgid "* Password length range 6-30 bits" msgstr "* パスワードの長さの範囲6-30ビット" #: accounts/serializers/automations/change_secret.py:110 -#: assets/models/automations/base.py:114 +#: assets/models/automations/base.py:118 #, fuzzy msgid "Automation task execution" msgstr "インスタンスタスクの同期実行" #: accounts/serializers/automations/change_secret.py:150 audits/const.py:45 -#: audits/models.py:40 common/const/choices.py:18 ops/const.py:51 -#: ops/serializers/celery.py:39 terminal/const.py:59 +#: audits/handler.py:167 audits/models.py:40 common/const/choices.py:18 +#: ops/const.py:51 ops/serializers/celery.py:39 terminal/const.py:59 #: terminal/models/session/sharing.py:103 tickets/views/approve.py:114 msgid "Success" msgstr "成功" #: accounts/serializers/automations/change_secret.py:151 -#: assets/const/automation.py:8 audits/const.py:46 common/const/choices.py:19 -#: ops/const.py:53 terminal/const.py:60 xpack/plugins/cloud/const.py:41 +#: assets/const/automation.py:8 audits/const.py:46 audits/handler.py:167 +#: common/const/choices.py:19 ops/const.py:53 terminal/const.py:60 +#: xpack/plugins/cloud/const.py:41 msgid "Failed" msgstr "失敗しました" @@ -671,11 +681,11 @@ msgstr "資産ユーザーの収集" msgid "Push accounts to assets" msgstr "システムユーザーを資産にプッシュする:" -#: accounts/tasks/verify_account.py:30 +#: accounts/tasks/verify_account.py:41 msgid "Verify asset account availability" msgstr "" -#: accounts/tasks/verify_account.py:36 +#: accounts/tasks/verify_account.py:47 #, fuzzy msgid "Verify accounts connectivity" msgstr "テストアカウント接続:" @@ -713,12 +723,12 @@ msgstr "受け入れられる" msgid "Review" msgstr "レビュー担当者" -#: acls/models/base.py:73 assets/models/_user.py:47 +#: acls/models/base.py:73 assets/models/_user.py:51 #: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:93 msgid "Priority" msgstr "優先順位" -#: acls/models/base.py:74 assets/models/_user.py:47 +#: acls/models/base.py:74 assets/models/_user.py:51 #: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:94 msgid "1-100, the lower the value will be match first" msgstr "1-100、低い値は最初に一致します" @@ -740,12 +750,12 @@ msgstr "アクティブ" #: acls/models/base.py:94 acls/models/login_acl.py:13 #: acls/serializers/base.py:55 acls/serializers/login_acl.py:21 #: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:30 -#: audits/models.py:49 audits/models.py:99 +#: audits/models.py:49 audits/models.py:98 #: authentication/models/connection_token.py:28 #: authentication/models/sso_token.py:16 #: notifications/models/notification.py:12 #: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58 -#: perms/serializers/permission.py:23 rbac/builtin.py:118 +#: perms/serializers/permission.py:23 rbac/builtin.py:119 #: rbac/models/rolebinding.py:41 terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 #: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 @@ -895,7 +905,7 @@ msgstr "" "192.168.10.1、192.168.1.0/24、10.1.1.1-10.1.1.20、2001:db8:2de::e13、2001:" "db8:1a:1110::/64" -#: acls/serializers/rules/rules.py:33 assets/models/asset/common.py:107 +#: acls/serializers/rules/rules.py:33 assets/models/asset/common.py:108 #: authentication/templates/authentication/_msg_oauth_bind.html:12 #: authentication/templates/authentication/_msg_rest_password_success.html:8 #: authentication/templates/authentication/_msg_rest_public_key_success.html:8 @@ -912,9 +922,9 @@ msgid "Applications" msgstr "アプリケーション" #: applications/models.py:11 assets/models/label.py:21 -#: assets/models/platform.py:75 assets/serializers/asset/common.py:121 +#: assets/models/platform.py:75 assets/serializers/asset/common.py:117 #: assets/serializers/cagegory.py:8 assets/serializers/platform.py:87 -#: assets/serializers/platform.py:129 perms/serializers/user_permission.py:25 +#: assets/serializers/platform.py:126 perms/serializers/user_permission.py:25 #: settings/models.py:35 tickets/models/ticket/apply_application.py:13 msgid "Category" msgstr "カテゴリ" @@ -933,7 +943,7 @@ msgid "Can match application" msgstr "アプリケーションを一致させることができます" #: applications/serializers/attrs/application_type/clickhouse.py:11 -#: assets/models/asset/common.py:95 assets/models/platform.py:21 +#: assets/models/asset/common.py:96 assets/models/platform.py:21 #: settings/serializers/auth/radius.py:17 settings/serializers/auth/sms.py:68 #: xpack/plugins/cloud/serializers/account_attrs.py:73 msgid "Port" @@ -1029,7 +1039,7 @@ msgid "Device" msgstr "" #: assets/const/category.py:13 assets/models/asset/database.py:9 -#: assets/models/asset/database.py:32 +#: assets/models/asset/database.py:24 msgid "Database" msgstr "データベース" @@ -1039,11 +1049,11 @@ msgid "Cloud service" msgstr "クラウドセンター" #: assets/const/category.py:15 audits/const.py:33 -#: terminal/models/applet/applet.py:21 +#: terminal/models/applet/applet.py:22 msgid "Web" msgstr "" -#: assets/const/device.py:7 terminal/models/applet/applet.py:20 +#: assets/const/device.py:7 terminal/models/applet/applet.py:21 #: tickets/const.py:8 msgid "General" msgstr "一般" @@ -1072,36 +1082,20 @@ msgstr "MFAタイプ" msgid "Website" msgstr "ウェブサイトのアイコン" -#: assets/models/_user.py:24 -msgid "Automatic managed" -msgstr "自動管理" - #: assets/models/_user.py:25 -msgid "Manually input" -msgstr "手動入力" - -#: assets/models/_user.py:29 -msgid "Common user" -msgstr "共通ユーザー" - -#: assets/models/_user.py:30 -msgid "Admin user" -msgstr "管理ユーザー" - -#: assets/models/_user.py:36 msgid "SSH private key" msgstr "SSH秘密鍵" -#: assets/models/_user.py:37 +#: assets/models/_user.py:26 msgid "SSH public key" msgstr "SSHパブリックキー" -#: assets/models/_user.py:40 assets/models/cmd_filter.py:40 +#: assets/models/_user.py:27 assets/models/cmd_filter.py:40 #: assets/models/cmd_filter.py:88 assets/models/group.py:23 #: assets/models/platform.py:79 common/db/models.py:37 ops/models/adhoc.py:28 #: ops/models/job.py:41 ops/models/playbook.py:17 rbac/models/role.py:37 -#: settings/models.py:38 terminal/models/applet/applet.py:32 -#: terminal/models/applet/applet.py:137 terminal/models/applet/host.py:110 +#: settings/models.py:38 terminal/models/applet/applet.py:33 +#: terminal/models/applet/applet.py:146 terminal/models/applet/host.py:110 #: terminal/models/component/endpoint.py:24 #: terminal/models/component/endpoint.py:100 #: terminal/models/session/session.py:45 tickets/models/comment.py:32 @@ -1110,124 +1104,140 @@ msgstr "SSHパブリックキー" msgid "Comment" msgstr "コメント" -#: assets/models/_user.py:41 assets/models/automations/base.py:101 +#: assets/models/_user.py:28 assets/models/automations/base.py:105 #: assets/models/cmd_filter.py:41 assets/models/group.py:22 #: common/db/models.py:35 ops/models/base.py:54 ops/models/job.py:106 #: users/models/user.py:932 msgid "Date created" msgstr "作成された日付" -#: assets/models/_user.py:42 assets/models/cmd_filter.py:42 +#: assets/models/_user.py:29 assets/models/cmd_filter.py:42 #: common/db/models.py:36 msgid "Date updated" msgstr "更新日" -#: assets/models/_user.py:43 assets/models/cmd_filter.py:44 +#: assets/models/_user.py:30 assets/models/cmd_filter.py:44 #: assets/models/cmd_filter.py:91 assets/models/group.py:21 #: common/db/models.py:33 users/models/user.py:722 #: users/serializers/group.py:33 msgid "Created by" msgstr "によって作成された" +#: assets/models/_user.py:40 +msgid "Automatic managed" +msgstr "自動管理" + +#: assets/models/_user.py:41 +msgid "Manually input" +msgstr "手動入力" + #: assets/models/_user.py:45 +msgid "Common user" +msgstr "共通ユーザー" + +#: assets/models/_user.py:46 assets/models/_user.py:95 +msgid "Admin user" +msgstr "管理ユーザー" + +#: assets/models/_user.py:49 msgid "Username same with user" msgstr "ユーザーと同じユーザー名" -#: assets/models/_user.py:48 authentication/models/connection_token.py:37 +#: assets/models/_user.py:52 authentication/models/connection_token.py:37 #: authentication/serializers/connect_token_secret.py:103 -#: terminal/models/applet/applet.py:30 terminal/serializers/session.py:24 +#: terminal/models/applet/applet.py:31 terminal/serializers/session.py:24 #: terminal/serializers/session.py:45 terminal/serializers/storage.py:68 msgid "Protocol" msgstr "プロトコル" -#: assets/models/_user.py:49 +#: assets/models/_user.py:53 msgid "Auto push" msgstr "オートプッシュ" -#: assets/models/_user.py:50 +#: assets/models/_user.py:54 msgid "Sudo" msgstr "すど" -#: assets/models/_user.py:51 ops/const.py:44 +#: assets/models/_user.py:55 ops/const.py:44 msgid "Shell" msgstr "シェル" -#: assets/models/_user.py:52 +#: assets/models/_user.py:56 msgid "Login mode" msgstr "ログインモード" -#: assets/models/_user.py:53 +#: assets/models/_user.py:57 msgid "SFTP Root" msgstr "SFTPルート" -#: assets/models/_user.py:54 +#: assets/models/_user.py:58 msgid "Home" msgstr "ホーム" -#: assets/models/_user.py:55 +#: assets/models/_user.py:59 msgid "System groups" msgstr "システムグループ" -#: assets/models/_user.py:58 +#: assets/models/_user.py:62 msgid "User switch" msgstr "ユーザースイッチ" -#: assets/models/_user.py:59 +#: assets/models/_user.py:63 msgid "Switch from" msgstr "から切り替え" -#: assets/models/_user.py:65 +#: assets/models/_user.py:69 msgid "System user" msgstr "システムユーザー" -#: assets/models/_user.py:67 +#: assets/models/_user.py:71 msgid "Can match system user" msgstr "システムユーザーに一致できます" -#: assets/models/asset/common.py:108 assets/models/platform.py:112 +#: assets/models/asset/common.py:109 assets/models/platform.py:111 #: authentication/serializers/connect_token_secret.py:107 #: perms/serializers/user_permission.py:23 #: xpack/plugins/cloud/serializers/account_attrs.py:179 msgid "Platform" msgstr "プラットフォーム" -#: assets/models/asset/common.py:110 assets/models/domain.py:21 +#: assets/models/asset/common.py:111 assets/models/domain.py:21 #: authentication/serializers/connect_token_secret.py:125 #: perms/serializers/user_permission.py:27 msgid "Domain" msgstr "ドメイン" -#: assets/models/asset/common.py:114 +#: assets/models/asset/common.py:115 msgid "Labels" msgstr "ラベル" -#: assets/models/asset/common.py:284 +#: assets/models/asset/common.py:289 msgid "Can refresh asset hardware info" msgstr "資産ハードウェア情報を更新できます" -#: assets/models/asset/common.py:285 +#: assets/models/asset/common.py:290 msgid "Can test asset connectivity" msgstr "資産接続をテストできます" -#: assets/models/asset/common.py:286 +#: assets/models/asset/common.py:291 #, fuzzy msgid "Can push account to asset" msgstr "システムユーザーを資産にプッシュできます" -#: assets/models/asset/common.py:287 +#: assets/models/asset/common.py:292 #, fuzzy msgid "Can verify account" msgstr "パスワード/キーの確認" -#: assets/models/asset/common.py:288 +#: assets/models/asset/common.py:293 msgid "Can match asset" msgstr "アセットを一致させることができます" -#: assets/models/asset/common.py:289 +#: assets/models/asset/common.py:294 msgid "Add asset to node" msgstr "ノードにアセットを追加する" -#: assets/models/asset/common.py:290 +#: assets/models/asset/common.py:295 msgid "Move asset to node" msgstr "アセットをノードに移動する" @@ -1288,24 +1298,24 @@ msgid "Submit selector" msgstr "" #: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38 -#: assets/serializers/asset/common.py:241 perms/models/asset_permission.py:70 +#: assets/serializers/asset/common.py:237 perms/models/asset_permission.py:70 #: perms/serializers/permission.py:32 rbac/tree.py:36 msgid "Accounts" msgstr "アカウント" -#: assets/models/automations/base.py:28 assets/models/automations/base.py:98 +#: assets/models/automations/base.py:28 assets/models/automations/base.py:102 #, fuzzy msgid "Automation task" msgstr "自動管理" -#: assets/models/automations/base.py:91 +#: assets/models/automations/base.py:95 #, fuzzy msgid "Asset automation task" msgstr "自動管理" -#: assets/models/automations/base.py:100 audits/models.py:135 -#: audits/serializers.py:48 ops/models/base.py:49 ops/models/job.py:99 -#: terminal/models/applet/applet.py:136 terminal/models/applet/host.py:107 +#: assets/models/automations/base.py:104 audits/models.py:134 +#: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:99 +#: terminal/models/applet/applet.py:145 terminal/models/applet/host.py:107 #: terminal/models/component/status.py:27 terminal/serializers/applet.py:17 #: terminal/serializers/applet_host.py:90 tickets/models/ticket/general.py:283 #: tickets/serializers/super_ticket.py:13 @@ -1363,7 +1373,9 @@ msgid "Command filter rule" msgstr "コマンドフィルタルール" #: assets/models/favorite_asset.py:17 -msgid "Favorite Asset" +#, fuzzy +#| msgid "Favorite Asset" +msgid "Favorite asset" msgstr "お気に入り" #: assets/models/gateway.py:35 assets/serializers/domain.py:16 @@ -1387,7 +1399,7 @@ msgstr "デフォルトアセットグループ" msgid "System" msgstr "システム" -#: assets/models/label.py:19 assets/models/node.py:552 +#: assets/models/label.py:19 assets/models/node.py:558 #: assets/serializers/cagegory.py:7 assets/serializers/cagegory.py:14 #: authentication/models/connection_token.py:25 #: authentication/serializers/connect_token_secret.py:114 @@ -1395,7 +1407,7 @@ msgstr "システム" msgid "Value" msgstr "値" -#: assets/models/label.py:40 assets/serializers/asset/common.py:123 +#: assets/models/label.py:40 assets/serializers/asset/common.py:119 #: assets/serializers/cagegory.py:6 assets/serializers/cagegory.py:13 #: authentication/serializers/connect_token_secret.py:113 #: common/serializers/common.py:81 settings/serializers/sms.py:7 @@ -1406,28 +1418,28 @@ msgstr "ラベル" msgid "New node" msgstr "新しいノード" -#: assets/models/node.py:480 +#: assets/models/node.py:486 audits/backends/db.py:55 audits/backends/db.py:56 msgid "empty" msgstr "空" -#: assets/models/node.py:551 perms/models/perm_node.py:28 +#: assets/models/node.py:557 perms/models/perm_node.py:28 msgid "Key" msgstr "キー" -#: assets/models/node.py:553 assets/serializers/node.py:20 +#: assets/models/node.py:559 assets/serializers/node.py:20 msgid "Full value" msgstr "フルバリュー" -#: assets/models/node.py:557 perms/models/perm_node.py:30 +#: assets/models/node.py:563 perms/models/perm_node.py:30 msgid "Parent key" msgstr "親キー" -#: assets/models/node.py:566 perms/serializers/permission.py:28 +#: assets/models/node.py:572 perms/serializers/permission.py:28 #: tickets/models/ticket/apply_asset.py:14 xpack/plugins/cloud/models.py:96 msgid "Node" msgstr "ノード" -#: assets/models/node.py:569 +#: assets/models/node.py:575 msgid "Can match node" msgstr "ノードを一致させることができます" @@ -1516,22 +1528,17 @@ msgstr "シャーセット" msgid "Domain enabled" msgstr "ドメイン名" -#: assets/models/platform.py:85 -#, fuzzy -msgid "Protocols enabled" -msgstr "プロトコル" - -#: assets/models/platform.py:87 +#: assets/models/platform.py:86 #, fuzzy msgid "Su enabled" msgstr "MFA有効化" -#: assets/models/platform.py:88 +#: assets/models/platform.py:87 #, fuzzy msgid "Su method" msgstr "接続タイムアウト" -#: assets/models/platform.py:90 assets/serializers/platform.py:91 +#: assets/models/platform.py:89 assets/serializers/platform.py:91 #, fuzzy msgid "Automation" msgstr "自動管理" @@ -1541,7 +1548,7 @@ msgstr "自動管理" msgid "%(value)s is not an even number" msgstr "%(value)s は偶数ではありません" -#: assets/serializers/asset/common.py:124 assets/serializers/platform.py:89 +#: assets/serializers/asset/common.py:120 assets/serializers/platform.py:89 #: authentication/serializers/connect_token_secret.py:28 #: authentication/serializers/connect_token_secret.py:65 #: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:107 @@ -1549,30 +1556,36 @@ msgstr "%(value)s は偶数ではありません" msgid "Protocols" msgstr "プロトコル" -#: assets/serializers/asset/common.py:126 +#: assets/serializers/asset/common.py:122 #, fuzzy #| msgid "Enabled" msgid "Enabled info" msgstr "有効化" -#: assets/serializers/asset/common.py:144 +#: assets/serializers/asset/common.py:140 msgid "Address" msgstr "アドレス" -#: assets/serializers/asset/common.py:145 +#: assets/serializers/asset/common.py:141 msgid "Node path" msgstr "ノードパスです" -#: assets/serializers/asset/common.py:205 +#: assets/serializers/asset/common.py:201 #, fuzzy msgid "Platform not exist" msgstr "アプリが存在しません" -#: assets/serializers/asset/common.py:221 +#: assets/serializers/asset/common.py:217 #, fuzzy msgid "Protocol is required: {}" msgstr "プロトコル重複: {}" +#: assets/serializers/asset/database.py:24 common/serializers/fields.py:100 +#: tickets/serializers/ticket/common.py:58 +#: xpack/plugins/cloud/serializers/account_attrs.py:56 +msgid "This field is required." +msgstr "このフィールドは必須です。" + #: assets/serializers/asset/host.py:12 msgid "Vendor" msgstr "ベンダー" @@ -1757,11 +1770,11 @@ msgstr "一致する資産がない、タスクを停止" msgid "Audits" msgstr "監査" -#: audits/backends/db.py:12 +#: audits/backends/db.py:15 msgid "The text content is too long. Use Elasticsearch to store operation logs" msgstr "文章の内容が長すぎる。Elasticsearchで操作履歴を保存する" -#: audits/backends/db.py:25 audits/backends/db.py:27 +#: audits/backends/db.py:76 msgid "Tips" msgstr "謎々" @@ -1834,20 +1847,35 @@ msgstr "ターミナル" msgid "-" msgstr "-" -#: audits/handler.py:136 +#: audits/handler.py:116 msgid "Yes" msgstr "是" -#: audits/handler.py:136 +#: audits/handler.py:116 msgid "No" msgstr "否" -#: audits/models.py:32 audits/models.py:59 audits/models.py:102 +#: audits/handler.py:140 +msgid "{} used account[{}], login method[{}] login the asset." +msgstr "" +"{} トムはアカウント[{}]、ログイン方法[{}]を使ってこの資産を登録しました" + +#: audits/handler.py:155 +msgid "User {} has executed change auth plan for this account.({})" +msgstr "ユーザー {} はこのアカウントのために改密計画を実行しました。({})" + +#: audits/handler.py:168 +#, fuzzy +#| msgid "User {} {} it." +msgid "User {} login into this service.[{}]" +msgstr "ユーザー {} はそれを {} しました" + +#: audits/models.py:32 audits/models.py:59 audits/models.py:101 #: terminal/models/session/session.py:37 terminal/models/session/sharing.py:95 msgid "Remote addr" msgstr "リモートaddr" -#: audits/models.py:37 audits/serializers.py:32 +#: audits/models.py:37 audits/serializers.py:33 msgid "Operate" msgstr "操作" @@ -1859,7 +1887,7 @@ msgstr "ファイル名" msgid "File transfer log" msgstr "ファイル転送ログ" -#: audits/models.py:53 audits/serializers.py:86 +#: audits/models.py:53 audits/serializers.py:93 msgid "Resource Type" msgstr "リソースタイプ" @@ -1867,71 +1895,69 @@ msgstr "リソースタイプ" msgid "Resource" msgstr "リソース" -#: audits/models.py:60 audits/models.py:104 +#: audits/models.py:60 audits/models.py:103 #: terminal/backends/command/serializers.py:41 msgid "Datetime" msgstr "時間" -#: audits/models.py:63 -#, fuzzy -#| msgid "Is active" -msgid "Is Activity" -msgstr "アクティブです。" +#: audits/models.py:62 +msgid "Detail" +msgstr "" -#: audits/models.py:93 +#: audits/models.py:92 msgid "Operate log" msgstr "ログの操作" -#: audits/models.py:100 +#: audits/models.py:99 msgid "Change by" msgstr "による変更" -#: audits/models.py:110 +#: audits/models.py:109 msgid "Password change log" msgstr "パスワード変更ログ" -#: audits/models.py:117 +#: audits/models.py:116 msgid "Login type" msgstr "ログインタイプ" -#: audits/models.py:119 tickets/models/ticket/login_confirm.py:10 +#: audits/models.py:118 tickets/models/ticket/login_confirm.py:10 msgid "Login ip" msgstr "ログインIP" -#: audits/models.py:121 +#: audits/models.py:120 #: authentication/templates/authentication/_msg_different_city.html:11 #: tickets/models/ticket/login_confirm.py:11 msgid "Login city" msgstr "ログイン都市" -#: audits/models.py:124 audits/serializers.py:62 +#: audits/models.py:123 audits/serializers.py:63 msgid "User agent" msgstr "ユーザーエージェント" -#: audits/models.py:127 audits/serializers.py:46 +#: audits/models.py:126 audits/serializers.py:47 #: authentication/templates/authentication/_mfa_confirm_modal.html:14 #: users/forms/profile.py:65 users/models/user.py:698 #: users/serializers/profile.py:126 msgid "MFA" msgstr "MFA" -#: audits/models.py:137 +#: audits/models.py:136 msgid "Date login" msgstr "日付ログイン" -#: audits/models.py:139 audits/serializers.py:64 +#: audits/models.py:138 audits/serializers.py:65 msgid "Authentication backend" msgstr "認証バックエンド" -#: audits/models.py:180 +#: audits/models.py:182 msgid "User login log" msgstr "ユーザーログインログ" -#: audits/serializers.py:63 +#: audits/serializers.py:64 msgid "Reason display" msgstr "理由表示" -#: audits/serializers.py:112 +#: audits/serializers.py:120 #, fuzzy #| msgid "User {} {} it." msgid "User {} {} this resource." @@ -2036,7 +2062,7 @@ msgid "Authentication" msgstr "認証" #: authentication/backends/custom.py:58 -#: authentication/backends/oauth2/backends.py:158 +#: authentication/backends/oauth2/backends.py:167 msgid "User invalid, disabled or expired" msgstr "ユーザーが無効、無効、または期限切れです" @@ -3086,11 +3112,6 @@ msgstr "" msgid "File" msgstr "ファイル名" -#: common/serializers/fields.py:100 tickets/serializers/ticket/common.py:58 -#: xpack/plugins/cloud/serializers/account_attrs.py:56 -msgid "This field is required." -msgstr "このフィールドは必須です。" - #: common/serializers/fields.py:101 #, fuzzy, python-brace-format msgid "Invalid pk \"{pk_value}\" - object does not exist." @@ -3239,7 +3260,7 @@ msgstr "ユーザーが無効になりました。" msgid "Skip hosts below:" msgstr "" -#: ops/api/celery.py:63 ops/api/celery.py:78 +#: ops/api/celery.py:58 ops/api/celery.py:73 msgid "Waiting task start" msgstr "タスク開始待ち" @@ -3515,34 +3536,34 @@ msgstr "テストタイムアウト" msgid "Task" msgstr "タスク" -#: ops/tasks.py:28 +#: ops/tasks.py:27 #, fuzzy msgid "Run ansible task" msgstr "アセットの実行" -#: ops/tasks.py:35 +#: ops/tasks.py:43 #, fuzzy msgid "Run ansible task execution" msgstr "インスタンスタスクの同期実行" -#: ops/tasks.py:49 +#: ops/tasks.py:57 msgid "Periodic clear celery tasks" msgstr "定期的にCeleryタスクをクリア" -#: ops/tasks.py:51 +#: ops/tasks.py:59 msgid "Clean celery log period" msgstr "きれいなセロリログ期間" -#: ops/tasks.py:68 +#: ops/tasks.py:76 #, fuzzy msgid "Clear celery periodic tasks" msgstr "きれいなセロリログ期間" -#: ops/tasks.py:91 +#: ops/tasks.py:99 msgid "Create or update periodic tasks" msgstr "定期的なタスクの作成または更新" -#: ops/tasks.py:99 +#: ops/tasks.py:107 #, fuzzy msgid "Periodic check service performance" msgstr "定期的なパフォーマンス" @@ -3617,7 +3638,7 @@ msgstr "組織" msgid "Org name" msgstr "組織名" -#: orgs/models.py:70 rbac/models/role.py:36 terminal/models/applet/applet.py:29 +#: orgs/models.py:70 rbac/models/role.py:36 terminal/models/applet/applet.py:30 #, fuzzy msgid "Builtin" msgstr "内蔵" @@ -3770,27 +3791,27 @@ msgstr "{} 少なくとも1つのシステムロール" msgid "RBAC" msgstr "RBAC" -#: rbac/builtin.py:109 +#: rbac/builtin.py:110 msgid "SystemAdmin" msgstr "システム管理者" -#: rbac/builtin.py:112 +#: rbac/builtin.py:113 msgid "SystemAuditor" msgstr "システム監査人" -#: rbac/builtin.py:115 +#: rbac/builtin.py:116 msgid "SystemComponent" msgstr "システムコンポーネント" -#: rbac/builtin.py:121 +#: rbac/builtin.py:122 msgid "OrgAdmin" msgstr "組織管理者" -#: rbac/builtin.py:124 +#: rbac/builtin.py:125 msgid "OrgAuditor" msgstr "監査員を組織する" -#: rbac/builtin.py:127 +#: rbac/builtin.py:128 msgid "OrgUser" msgstr "組織ユーザー" @@ -3871,7 +3892,7 @@ msgstr "パーマ" msgid "Users amount" msgstr "ユーザー数" -#: rbac/serializers/role.py:28 terminal/models/applet/applet.py:24 +#: rbac/serializers/role.py:28 terminal/models/applet/applet.py:25 msgid "Display name" msgstr "表示名" @@ -3939,8 +3960,8 @@ msgstr "タスクセンター" msgid "My assets" msgstr "私の資産" -#: rbac/tree.py:57 terminal/models/applet/applet.py:39 -#: terminal/models/applet/applet.py:133 terminal/models/applet/host.py:27 +#: rbac/tree.py:57 terminal/models/applet/applet.py:40 +#: terminal/models/applet/applet.py:142 terminal/models/applet/host.py:27 msgid "Applet" msgstr "リモートアプリケーション" @@ -5356,6 +5377,12 @@ msgstr "" msgid "Offline video player" msgstr "オフラインビデオプレーヤー" +#: terminal/api/applet/applet.py:48 terminal/api/applet/applet.py:51 +#, fuzzy +#| msgid "Invalid ip" +msgid "Invalid zip file" +msgstr "無効なIP" + #: terminal/api/component/endpoint.py:31 msgid "Not found protocol query params" msgstr "プロトコルクエリパラメータが見つかりません" @@ -5495,20 +5522,24 @@ msgstr "一括作成非サポート" msgid "Storage is invalid" msgstr "ストレージが無効です" -#: terminal/models/applet/applet.py:26 +#: terminal/models/applet/applet.py:27 #, fuzzy msgid "Author" msgstr "資産アカウント" -#: terminal/models/applet/applet.py:31 +#: terminal/models/applet/applet.py:32 msgid "Tags" msgstr "" -#: terminal/models/applet/applet.py:35 terminal/serializers/storage.py:157 +#: terminal/models/applet/applet.py:36 terminal/serializers/storage.py:157 msgid "Hosts" msgstr "ホスト" -#: terminal/models/applet/applet.py:135 terminal/models/applet/host.py:33 +#: terminal/models/applet/applet.py:81 +msgid "Applet pkg not valid, Missing file {}" +msgstr "" + +#: terminal/models/applet/applet.py:144 terminal/models/applet/host.py:33 #: terminal/models/applet/host.py:105 #, fuzzy msgid "Hosting" @@ -6152,7 +6183,7 @@ msgstr "製造オーダスナップショット" msgid "Please try again" msgstr "もう一度お試しください" -#: tickets/models/ticket/general.py:458 +#: tickets/models/ticket/general.py:461 msgid "Super ticket" msgstr "スーパーチケット" @@ -7402,6 +7433,15 @@ msgstr "究極のエディション" msgid "Community edition" msgstr "コミュニティ版" +#, fuzzy +#~ msgid "Protocols enabled" +#~ msgstr "プロトコル" + +#, fuzzy +#~| msgid "Is active" +#~ msgid "Is Activity" +#~ msgstr "アクティブです。" + #, fuzzy #~| msgid "Dynamic user" #~ msgid "Dynamic username" @@ -7428,13 +7468,6 @@ msgstr "コミュニティ版" #~ msgid "Change password method" #~ msgstr "パスワードの変更" -#~ msgid "{} used account[{}], login method[{}] login the asset." -#~ msgstr "" -#~ "{} トムはアカウント[{}]、ログイン方法[{}]を使ってこの資産を登録しました" - -#~ msgid "User {} has executed change auth plan for this account.({})" -#~ msgstr "ユーザー {} はこのアカウントのために改密計画を実行しました。({})" - #~ msgid "" #~ "The range of ports that Magnus listens on is modified in the " #~ "configuration file" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 230afb603..1dbea7659 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4af8f2ead4a9d5aaf943efea76305d8cad1ff0692758d21a93937601c6f150fd -size 105736 +oid sha256:0c3f5102d732ffe768f0545cf9271bbba45ba4c159f0a348b518b58cbdb5f20c +size 105947 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 219de87f3..bdbc5b7d0 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-16 14:24+0800\n" +"POT-Creation-Date: 2023-01-31 16:01+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -23,7 +23,7 @@ msgstr "参数 'action' 必须是 [{}]" #: accounts/const/account.py:6 #: accounts/serializers/automations/change_secret.py:33 -#: assets/models/_user.py:35 audits/signal_handlers.py:51 +#: assets/models/_user.py:24 audits/signal_handlers.py:51 #: authentication/confirm/password.py:9 authentication/forms.py:32 #: authentication/templates/authentication/login.html:288 #: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:47 @@ -43,7 +43,7 @@ msgstr "SSH 密钥" msgid "Access key" msgstr "Access key" -#: accounts/const/account.py:9 assets/models/_user.py:38 +#: accounts/const/account.py:9 assets/models/_user.py:48 #: authentication/models/sso_token.py:14 msgid "Token" msgstr "Token" @@ -89,93 +89,99 @@ msgstr "验证账号" msgid "Gather accounts" msgstr "收集账号" -#: accounts/const/automation.py:43 +#: accounts/const/automation.py:26 +#, fuzzy +#| msgid "Verify asset account" +msgid "Verify gateway account" +msgstr "账号验证" + +#: accounts/const/automation.py:44 msgid "Specific password" msgstr "指定" -#: accounts/const/automation.py:44 +#: accounts/const/automation.py:45 msgid "Random" msgstr "" -#: accounts/const/automation.py:48 ops/const.py:13 +#: accounts/const/automation.py:49 ops/const.py:13 msgid "Append SSH KEY" msgstr "追加" -#: accounts/const/automation.py:49 ops/const.py:14 +#: accounts/const/automation.py:50 ops/const.py:14 msgid "Empty and append SSH KEY" msgstr "清空所有并添加" -#: accounts/const/automation.py:50 ops/const.py:15 +#: accounts/const/automation.py:51 ops/const.py:15 msgid "Replace (The key generated by JumpServer) " msgstr "替换 (仅替换由 JumpServer 生成的密钥)" -#: accounts/const/automation.py:55 +#: accounts/const/automation.py:56 msgid "On asset create" msgstr "资产创建时" -#: accounts/const/automation.py:58 +#: accounts/const/automation.py:59 #, fuzzy #| msgid "On perm change" msgid "On perm add user" msgstr "授权变更时" -#: accounts/const/automation.py:60 +#: accounts/const/automation.py:61 msgid "On perm add user group" msgstr "" -#: accounts/const/automation.py:62 +#: accounts/const/automation.py:63 #, fuzzy #| msgid "permed assets" msgid "On perm add asset" msgstr "授权的资产" -#: accounts/const/automation.py:64 +#: accounts/const/automation.py:65 #, fuzzy #| msgid "On perm change" msgid "On perm add node" msgstr "授权变更时" -#: accounts/const/automation.py:66 +#: accounts/const/automation.py:67 #, fuzzy #| msgid "Permed account" msgid "On perm add account" msgstr "授权账号" -#: accounts/const/automation.py:68 +#: accounts/const/automation.py:69 #, fuzzy #| msgid "Add asset to node" msgid "On asset join node" msgstr "添加资产到节点" -#: accounts/const/automation.py:70 +#: accounts/const/automation.py:71 #, fuzzy #| msgid "User group" msgid "On user join group" msgstr "用户组" -#: accounts/const/automation.py:78 +#: accounts/const/automation.py:79 msgid "On perm change" msgstr "授权变更时" -#: accounts/const/automation.py:85 +#: accounts/const/automation.py:86 #, fuzzy #| msgid "Perm ungroup node" msgid "Inherit from group or node" msgstr "显示未分组节点" -#: accounts/const/automation.py:93 +#: accounts/const/automation.py:94 msgid "Create and push" msgstr "创建并推送到资产" -#: accounts/const/automation.py:94 +#: accounts/const/automation.py:95 msgid "Only create" msgstr "仅创建到资产" -#: accounts/models/account.py:47 accounts/serializers/account/account.py:77 +#: accounts/models/account.py:47 accounts/serializers/account/account.py:88 #: accounts/serializers/automations/change_secret.py:107 #: accounts/serializers/automations/change_secret.py:127 acls/models/base.py:96 -#: acls/serializers/base.py:56 assets/models/asset/common.py:96 -#: assets/models/asset/common.py:281 assets/models/cmd_filter.py:36 +#: acls/serializers/base.py:56 assets/models/asset/common.py:97 +#: assets/models/asset/common.py:286 assets/models/cmd_filter.py:36 #: assets/serializers/domain.py:19 assets/serializers/label.py:27 #: audits/models.py:34 authentication/models/connection_token.py:32 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:27 @@ -186,17 +192,17 @@ msgstr "仅创建到资产" msgid "Asset" msgstr "资产" -#: accounts/models/account.py:51 accounts/serializers/account/account.py:81 +#: accounts/models/account.py:51 accounts/serializers/account/account.py:92 #: authentication/serializers/connect_token_secret.py:49 msgid "Su from" msgstr "切换自" #: accounts/models/account.py:53 settings/serializers/auth/cas.py:20 -#: terminal/models/applet/applet.py:25 +#: terminal/models/applet/applet.py:26 msgid "Version" msgstr "版本" -#: accounts/models/account.py:55 accounts/serializers/account/account.py:78 +#: accounts/models/account.py:55 accounts/serializers/account/account.py:89 #: users/models/user.py:727 msgid "Source" msgstr "来源" @@ -204,7 +210,7 @@ msgstr "来源" #: accounts/models/account.py:58 #: accounts/serializers/automations/change_secret.py:108 #: accounts/serializers/automations/change_secret.py:128 acls/models/base.py:98 -#: acls/serializers/base.py:57 assets/serializers/asset/common.py:125 +#: acls/serializers/base.py:57 assets/serializers/asset/common.py:121 #: assets/serializers/gateway.py:30 audits/models.py:35 ops/models/base.py:18 #: terminal/backends/command/models.py:22 terminal/models/session/session.py:33 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 @@ -227,7 +233,7 @@ msgstr "可以查看资产历史账号" msgid "Can view asset history account secret" msgstr "可以查看资产历史账号密码" -#: accounts/models/account.py:104 accounts/serializers/account/account.py:16 +#: accounts/models/account.py:104 accounts/serializers/account/account.py:34 msgid "Account template" msgstr "账号模版" @@ -241,7 +247,7 @@ msgstr "可以更改账号模版密码" #: accounts/models/automations/backup_account.py:25 #: accounts/models/automations/change_secret.py:47 -#: accounts/serializers/account/backup.py:29 +#: accounts/serializers/account/backup.py:32 #: accounts/serializers/automations/change_secret.py:56 msgid "Recipient" msgstr "收件人" @@ -252,7 +258,7 @@ msgid "Account backup plan" msgstr "账号备份计划" #: accounts/models/automations/backup_account.py:77 -#: assets/models/automations/base.py:102 audits/models.py:41 +#: assets/models/automations/base.py:106 audits/models.py:41 #: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:107 #: perms/models/asset_permission.py:72 terminal/models/applet/host.py:108 #: terminal/models/session/session.py:43 @@ -272,13 +278,14 @@ msgid "Account backup snapshot" msgstr "账号备份快照" #: accounts/models/automations/backup_account.py:88 -#: accounts/serializers/automations/base.py:42 -#: assets/models/automations/base.py:109 +#: accounts/serializers/account/backup.py:39 +#: accounts/serializers/automations/base.py:44 +#: assets/models/automations/base.py:113 #: assets/serializers/automations/base.py:40 msgid "Trigger mode" msgstr "触发模式" -#: accounts/models/automations/backup_account.py:91 audits/models.py:130 +#: accounts/models/automations/backup_account.py:91 audits/models.py:129 #: terminal/models/session/sharing.py:107 xpack/plugins/cloud/models.py:176 msgid "Reason" msgstr "原因" @@ -341,7 +348,7 @@ msgid "Can add push account execution" msgstr "创建收集账号执行" #: accounts/models/automations/change_secret.py:17 accounts/models/base.py:36 -#: accounts/serializers/account/account.py:114 +#: accounts/serializers/account/account.py:125 #: accounts/serializers/account/base.py:16 #: accounts/serializers/automations/change_secret.py:46 #: authentication/serializers/connect_token_secret.py:40 @@ -356,7 +363,6 @@ msgstr "密文策略" #: accounts/models/automations/change_secret.py:23 #: accounts/models/automations/change_secret.py:72 accounts/models/base.py:38 -#: accounts/serializers/account/base.py:19 #: authentication/models/temp_token.py:10 #: authentication/templates/authentication/_access_key_modal.html:31 #: settings/serializers/auth/radius.py:19 @@ -384,7 +390,7 @@ msgid "Date started" msgstr "开始日期" #: accounts/models/automations/change_secret.py:74 -#: assets/models/automations/base.py:103 ops/models/base.py:56 +#: assets/models/automations/base.py:107 ops/models/base.py:56 #: ops/models/celery.py:64 ops/models/job.py:108 #: terminal/models/applet/host.py:109 msgid "Date finished" @@ -411,7 +417,7 @@ msgstr "触发方式" #: accounts/models/automations/push_account.py:14 accounts/models/base.py:34 #: acls/serializers/base.py:18 acls/serializers/base.py:49 -#: assets/models/_user.py:34 audits/models.py:115 authentication/forms.py:25 +#: assets/models/_user.py:23 audits/models.py:114 authentication/forms.py:25 #: authentication/forms.py:27 authentication/models/temp_token.py:9 #: authentication/templates/authentication/_msg_different_city.html:9 #: authentication/templates/authentication/_msg_oauth_bind.html:9 @@ -423,7 +429,7 @@ msgstr "用户名" #: accounts/models/automations/push_account.py:15 acls/models/base.py:77 #: acls/serializers/base.py:81 assets/models/cmd_filter.py:81 -#: audits/models.py:51 audits/serializers.py:75 +#: audits/models.py:51 audits/serializers.py:82 #: authentication/serializers/connect_token_secret.py:108 #: authentication/templates/authentication/_access_key_modal.html:34 msgid "Action" @@ -439,18 +445,18 @@ msgstr "账号验证" #: accounts/models/base.py:33 acls/models/base.py:71 #: acls/models/command_acl.py:21 acls/serializers/base.py:34 -#: applications/models.py:9 assets/models/_user.py:33 -#: assets/models/asset/common.py:94 assets/models/asset/common.py:106 +#: applications/models.py:9 assets/models/_user.py:22 +#: assets/models/asset/common.py:95 assets/models/asset/common.py:107 #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 #: assets/models/group.py:20 assets/models/label.py:18 #: assets/models/platform.py:20 assets/models/platform.py:74 -#: assets/serializers/asset/common.py:143 assets/serializers/platform.py:128 +#: assets/serializers/asset/common.py:139 assets/serializers/platform.py:125 #: authentication/serializers/connect_token_secret.py:102 ops/mixin.py:20 #: ops/models/adhoc.py:22 ops/models/celery.py:15 ops/models/celery.py:57 #: ops/models/job.py:25 ops/models/playbook.py:14 orgs/models.py:69 #: perms/models/asset_permission.py:56 rbac/models/role.py:29 #: settings/models.py:33 settings/serializers/sms.py:6 -#: terminal/models/applet/applet.py:23 terminal/models/component/endpoint.py:12 +#: terminal/models/applet/applet.py:24 terminal/models/component/endpoint.py:12 #: terminal/models/component/endpoint.py:90 #: terminal/models/component/storage.py:26 terminal/models/component/task.py:15 #: terminal/models/component/terminal.py:79 users/forms/profile.py:33 @@ -463,11 +469,11 @@ msgstr "名称" msgid "Privileged" msgstr "特权账号" -#: accounts/models/base.py:40 assets/models/asset/common.py:113 +#: accounts/models/base.py:40 assets/models/asset/common.py:114 #: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 #: assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:106 -#: terminal/models/applet/applet.py:28 users/serializers/user.py:158 +#: terminal/models/applet/applet.py:29 users/serializers/user.py:158 msgid "Is active" msgstr "激活" @@ -481,7 +487,7 @@ msgid "" "for details" msgstr "{} - 账号备份任务已完成, 详情见附件" -#: accounts/notifications.py:20 +#: accounts/notifications.py:21 msgid "" "{} - The account backup passage task has been completed: the encryption " "password has not been set - please go to personal information -> file " @@ -490,17 +496,17 @@ msgstr "" "{} - 账号备份任务已完成: 未设置加密密码 - 请前往个人信息 -> 文件加密密码中设" "置加密密码" -#: accounts/notifications.py:31 +#: accounts/notifications.py:33 msgid "Notification of implementation result of encryption change plan" msgstr "改密计划任务结果通知" -#: accounts/notifications.py:41 +#: accounts/notifications.py:43 msgid "" "{} - The encryption change task has been completed. See the attachment for " "details" msgstr "{} - 改密任务已完成, 详情见附件" -#: accounts/notifications.py:42 +#: accounts/notifications.py:46 msgid "" "{} - The encryption change task has been completed: the encryption password " "has not been set - please go to personal information -> file encryption " @@ -509,42 +515,46 @@ msgstr "" "{} - 改密任务已完成: 未设置加密密码 - 请前往个人信息 -> 文件加密密码中设置加" "密密码" -#: accounts/serializers/account/account.py:19 -#: assets/serializers/asset/common.py:52 +#: accounts/serializers/account/account.py:37 +#: assets/serializers/asset/common.py:55 msgid "Push now" msgstr "立即推送" -#: accounts/serializers/account/account.py:21 +#: accounts/serializers/account/account.py:39 #: accounts/serializers/account/base.py:64 msgid "Has secret" msgstr "已托管密码" -#: accounts/serializers/account/account.py:28 -#: assets/serializers/asset/common.py:79 +#: accounts/serializers/account/account.py:46 +#: assets/serializers/asset/common.py:82 msgid "Account template not found" msgstr "账号模版未找到" -#: accounts/serializers/account/account.py:73 +#: accounts/serializers/account/account.py:84 msgid "Asset not found" msgstr "资产不存在" -#: accounts/serializers/account/backup.py:27 -#: accounts/serializers/automations/base.py:35 +#: accounts/serializers/account/backup.py:30 +#: accounts/serializers/automations/base.py:36 #: assets/serializers/automations/base.py:34 ops/mixin.py:22 ops/mixin.py:102 #: settings/serializers/auth/ldap.py:66 msgid "Periodic perform" msgstr "定时执行" -#: accounts/serializers/account/backup.py:28 -#: accounts/serializers/automations/gather_accounts.py:23 +#: accounts/serializers/account/backup.py:31 +#: accounts/serializers/automations/base.py:37 msgid "Executed amount" msgstr "执行次数" -#: accounts/serializers/account/backup.py:30 +#: accounts/serializers/account/backup.py:33 #: accounts/serializers/automations/change_secret.py:57 msgid "Currently only mail sending is supported" msgstr "当前只支持邮件发送" +#: accounts/serializers/account/base.py:19 +msgid "Secret/Password" +msgstr "密钥/密码" + #: accounts/serializers/account/base.py:24 msgid "Key password" msgstr "密钥密码" @@ -553,7 +563,7 @@ msgstr "密钥密码" msgid "Specific" msgstr "指定的" -#: accounts/serializers/automations/base.py:21 +#: accounts/serializers/automations/base.py:22 #: assets/models/automations/base.py:19 #: assets/serializers/automations/base.py:20 ops/models/base.py:17 #: ops/models/job.py:35 @@ -561,27 +571,27 @@ msgstr "指定的" msgid "Assets" msgstr "资产" -#: accounts/serializers/automations/base.py:22 -#: assets/models/asset/common.py:112 assets/models/automations/base.py:18 +#: accounts/serializers/automations/base.py:23 +#: assets/models/asset/common.py:113 assets/models/automations/base.py:18 #: assets/models/cmd_filter.py:32 assets/serializers/automations/base.py:21 #: perms/models/asset_permission.py:67 msgid "Nodes" msgstr "节点" -#: accounts/serializers/automations/base.py:40 -#: assets/models/automations/base.py:105 +#: accounts/serializers/automations/base.py:42 +#: assets/models/automations/base.py:109 #: assets/serializers/automations/base.py:39 msgid "Automation snapshot" msgstr "工单快照" -#: accounts/serializers/automations/base.py:41 acls/models/command_acl.py:24 +#: accounts/serializers/automations/base.py:43 acls/models/command_acl.py:24 #: acls/serializers/command_acl.py:18 applications/models.py:14 -#: assets/models/_user.py:46 assets/models/automations/base.py:20 +#: assets/models/_user.py:50 assets/models/automations/base.py:20 #: assets/models/cmd_filter.py:74 assets/models/platform.py:76 -#: assets/serializers/asset/common.py:122 assets/serializers/platform.py:86 -#: audits/serializers.py:47 +#: assets/serializers/asset/common.py:118 assets/serializers/platform.py:86 +#: audits/serializers.py:48 #: authentication/serializers/connect_token_secret.py:115 ops/models/job.py:33 -#: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:27 +#: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:28 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:146 terminal/serializers/applet.py:28 #: terminal/serializers/session.py:26 terminal/serializers/storage.py:181 @@ -605,20 +615,21 @@ msgid "* Password length range 6-30 bits" msgstr "* 密码长度范围 6-30 位" #: accounts/serializers/automations/change_secret.py:110 -#: assets/models/automations/base.py:114 +#: assets/models/automations/base.py:118 msgid "Automation task execution" msgstr "自动化任务执行历史" #: accounts/serializers/automations/change_secret.py:150 audits/const.py:45 -#: audits/models.py:40 common/const/choices.py:18 ops/const.py:51 -#: ops/serializers/celery.py:39 terminal/const.py:59 +#: audits/handler.py:167 audits/models.py:40 common/const/choices.py:18 +#: ops/const.py:51 ops/serializers/celery.py:39 terminal/const.py:59 #: terminal/models/session/sharing.py:103 tickets/views/approve.py:114 msgid "Success" msgstr "成功" #: accounts/serializers/automations/change_secret.py:151 -#: assets/const/automation.py:8 audits/const.py:46 common/const/choices.py:19 -#: ops/const.py:53 terminal/const.py:60 xpack/plugins/cloud/const.py:41 +#: assets/const/automation.py:8 audits/const.py:46 audits/handler.py:167 +#: common/const/choices.py:19 ops/const.py:53 terminal/const.py:60 +#: xpack/plugins/cloud/const.py:41 msgid "Failed" msgstr "失败" @@ -640,11 +651,11 @@ msgstr "收集资产上的账号" msgid "Push accounts to assets" msgstr "推送账号到资产" -#: accounts/tasks/verify_account.py:30 +#: accounts/tasks/verify_account.py:41 msgid "Verify asset account availability" msgstr "" -#: accounts/tasks/verify_account.py:36 +#: accounts/tasks/verify_account.py:47 msgid "Verify accounts connectivity" msgstr "测试账号可连接性" @@ -681,12 +692,12 @@ msgstr "接受" msgid "Review" msgstr "审批" -#: acls/models/base.py:73 assets/models/_user.py:47 +#: acls/models/base.py:73 assets/models/_user.py:51 #: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:93 msgid "Priority" msgstr "优先级" -#: acls/models/base.py:74 assets/models/_user.py:47 +#: acls/models/base.py:74 assets/models/_user.py:51 #: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:94 msgid "1-100, the lower the value will be match first" msgstr "优先级可选范围为 1-100 (数值越小越优先)" @@ -708,12 +719,12 @@ msgstr "激活中" #: acls/models/base.py:94 acls/models/login_acl.py:13 #: acls/serializers/base.py:55 acls/serializers/login_acl.py:21 #: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:30 -#: audits/models.py:49 audits/models.py:99 +#: audits/models.py:49 audits/models.py:98 #: authentication/models/connection_token.py:28 #: authentication/models/sso_token.py:16 #: notifications/models/notification.py:12 #: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58 -#: perms/serializers/permission.py:23 rbac/builtin.py:118 +#: perms/serializers/permission.py:23 rbac/builtin.py:119 #: rbac/models/rolebinding.py:41 terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 #: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 @@ -861,7 +872,7 @@ msgstr "" "格式为逗号分隔的字符串, * 表示匹配所有。例如: 192.168.10.1, 192.168.1.0/24, " "10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64" -#: acls/serializers/rules/rules.py:33 assets/models/asset/common.py:107 +#: acls/serializers/rules/rules.py:33 assets/models/asset/common.py:108 #: authentication/templates/authentication/_msg_oauth_bind.html:12 #: authentication/templates/authentication/_msg_rest_password_success.html:8 #: authentication/templates/authentication/_msg_rest_public_key_success.html:8 @@ -878,9 +889,9 @@ msgid "Applications" msgstr "应用管理" #: applications/models.py:11 assets/models/label.py:21 -#: assets/models/platform.py:75 assets/serializers/asset/common.py:121 +#: assets/models/platform.py:75 assets/serializers/asset/common.py:117 #: assets/serializers/cagegory.py:8 assets/serializers/platform.py:87 -#: assets/serializers/platform.py:129 perms/serializers/user_permission.py:25 +#: assets/serializers/platform.py:126 perms/serializers/user_permission.py:25 #: settings/models.py:35 tickets/models/ticket/apply_application.py:13 msgid "Category" msgstr "类别" @@ -899,7 +910,7 @@ msgid "Can match application" msgstr "匹配应用" #: applications/serializers/attrs/application_type/clickhouse.py:11 -#: assets/models/asset/common.py:95 assets/models/platform.py:21 +#: assets/models/asset/common.py:96 assets/models/platform.py:21 #: settings/serializers/auth/radius.py:17 settings/serializers/auth/sms.py:68 #: xpack/plugins/cloud/serializers/account_attrs.py:73 msgid "Port" @@ -990,7 +1001,7 @@ msgid "Device" msgstr "网络设备" #: assets/const/category.py:13 assets/models/asset/database.py:9 -#: assets/models/asset/database.py:32 +#: assets/models/asset/database.py:24 msgid "Database" msgstr "数据库" @@ -999,11 +1010,11 @@ msgid "Cloud service" msgstr "云服务" #: assets/const/category.py:15 audits/const.py:33 -#: terminal/models/applet/applet.py:21 +#: terminal/models/applet/applet.py:22 msgid "Web" msgstr "Web" -#: assets/const/device.py:7 terminal/models/applet/applet.py:20 +#: assets/const/device.py:7 terminal/models/applet/applet.py:21 #: tickets/const.py:8 msgid "General" msgstr "一般" @@ -1028,36 +1039,20 @@ msgstr "所有类型" msgid "Website" msgstr "网站" -#: assets/models/_user.py:24 -msgid "Automatic managed" -msgstr "托管密码" - #: assets/models/_user.py:25 -msgid "Manually input" -msgstr "手动输入" - -#: assets/models/_user.py:29 -msgid "Common user" -msgstr "普通用户" - -#: assets/models/_user.py:30 -msgid "Admin user" -msgstr "特权用户" - -#: assets/models/_user.py:36 msgid "SSH private key" msgstr "SSH密钥" -#: assets/models/_user.py:37 +#: assets/models/_user.py:26 msgid "SSH public key" msgstr "SSH公钥" -#: assets/models/_user.py:40 assets/models/cmd_filter.py:40 +#: assets/models/_user.py:27 assets/models/cmd_filter.py:40 #: assets/models/cmd_filter.py:88 assets/models/group.py:23 #: assets/models/platform.py:79 common/db/models.py:37 ops/models/adhoc.py:28 #: ops/models/job.py:41 ops/models/playbook.py:17 rbac/models/role.py:37 -#: settings/models.py:38 terminal/models/applet/applet.py:32 -#: terminal/models/applet/applet.py:137 terminal/models/applet/host.py:110 +#: settings/models.py:38 terminal/models/applet/applet.py:33 +#: terminal/models/applet/applet.py:146 terminal/models/applet/host.py:110 #: terminal/models/component/endpoint.py:24 #: terminal/models/component/endpoint.py:100 #: terminal/models/session/session.py:45 tickets/models/comment.py:32 @@ -1066,124 +1061,140 @@ msgstr "SSH公钥" msgid "Comment" msgstr "备注" -#: assets/models/_user.py:41 assets/models/automations/base.py:101 +#: assets/models/_user.py:28 assets/models/automations/base.py:105 #: assets/models/cmd_filter.py:41 assets/models/group.py:22 #: common/db/models.py:35 ops/models/base.py:54 ops/models/job.py:106 #: users/models/user.py:932 msgid "Date created" msgstr "创建日期" -#: assets/models/_user.py:42 assets/models/cmd_filter.py:42 +#: assets/models/_user.py:29 assets/models/cmd_filter.py:42 #: common/db/models.py:36 msgid "Date updated" msgstr "更新日期" -#: assets/models/_user.py:43 assets/models/cmd_filter.py:44 +#: assets/models/_user.py:30 assets/models/cmd_filter.py:44 #: assets/models/cmd_filter.py:91 assets/models/group.py:21 #: common/db/models.py:33 users/models/user.py:722 #: users/serializers/group.py:33 msgid "Created by" msgstr "创建者" +#: assets/models/_user.py:40 +msgid "Automatic managed" +msgstr "托管密码" + +#: assets/models/_user.py:41 +msgid "Manually input" +msgstr "手动输入" + #: assets/models/_user.py:45 +msgid "Common user" +msgstr "普通用户" + +#: assets/models/_user.py:46 assets/models/_user.py:95 +msgid "Admin user" +msgstr "特权用户" + +#: assets/models/_user.py:49 msgid "Username same with user" msgstr "用户名与用户相同" -#: assets/models/_user.py:48 authentication/models/connection_token.py:37 +#: assets/models/_user.py:52 authentication/models/connection_token.py:37 #: authentication/serializers/connect_token_secret.py:103 -#: terminal/models/applet/applet.py:30 terminal/serializers/session.py:24 +#: terminal/models/applet/applet.py:31 terminal/serializers/session.py:24 #: terminal/serializers/session.py:45 terminal/serializers/storage.py:68 msgid "Protocol" msgstr "协议" -#: assets/models/_user.py:49 +#: assets/models/_user.py:53 msgid "Auto push" msgstr "自动推送" -#: assets/models/_user.py:50 +#: assets/models/_user.py:54 msgid "Sudo" msgstr "Sudo" -#: assets/models/_user.py:51 ops/const.py:44 +#: assets/models/_user.py:55 ops/const.py:44 msgid "Shell" msgstr "Shell" -#: assets/models/_user.py:52 +#: assets/models/_user.py:56 msgid "Login mode" msgstr "认证方式" -#: assets/models/_user.py:53 +#: assets/models/_user.py:57 msgid "SFTP Root" msgstr "SFTP根路径" -#: assets/models/_user.py:54 +#: assets/models/_user.py:58 msgid "Home" msgstr "家目录" -#: assets/models/_user.py:55 +#: assets/models/_user.py:59 msgid "System groups" msgstr "用户组" -#: assets/models/_user.py:58 +#: assets/models/_user.py:62 msgid "User switch" msgstr "用户切换" -#: assets/models/_user.py:59 +#: assets/models/_user.py:63 msgid "Switch from" msgstr "切换自" -#: assets/models/_user.py:65 +#: assets/models/_user.py:69 msgid "System user" msgstr "系统用户" -#: assets/models/_user.py:67 +#: assets/models/_user.py:71 msgid "Can match system user" msgstr "可以匹配系统用户" -#: assets/models/asset/common.py:108 assets/models/platform.py:112 +#: assets/models/asset/common.py:109 assets/models/platform.py:111 #: authentication/serializers/connect_token_secret.py:107 #: perms/serializers/user_permission.py:23 #: xpack/plugins/cloud/serializers/account_attrs.py:179 msgid "Platform" msgstr "系统平台" -#: assets/models/asset/common.py:110 assets/models/domain.py:21 +#: assets/models/asset/common.py:111 assets/models/domain.py:21 #: authentication/serializers/connect_token_secret.py:125 #: perms/serializers/user_permission.py:27 msgid "Domain" msgstr "网域" -#: assets/models/asset/common.py:114 +#: assets/models/asset/common.py:115 msgid "Labels" msgstr "标签管理" -#: assets/models/asset/common.py:284 +#: assets/models/asset/common.py:289 msgid "Can refresh asset hardware info" msgstr "可以更新资产硬件信息" -#: assets/models/asset/common.py:285 +#: assets/models/asset/common.py:290 msgid "Can test asset connectivity" msgstr "可以测试资产连接性" -#: assets/models/asset/common.py:286 +#: assets/models/asset/common.py:291 msgid "Can push account to asset" msgstr "可以推送账号到资产" -#: assets/models/asset/common.py:287 +#: assets/models/asset/common.py:292 #, fuzzy #| msgid "Verify account" msgid "Can verify account" msgstr "验证账号" -#: assets/models/asset/common.py:288 +#: assets/models/asset/common.py:293 msgid "Can match asset" msgstr "可以匹配资产" -#: assets/models/asset/common.py:289 +#: assets/models/asset/common.py:294 msgid "Add asset to node" msgstr "添加资产到节点" -#: assets/models/asset/common.py:290 +#: assets/models/asset/common.py:295 msgid "Move asset to node" msgstr "移动资产到节点" @@ -1238,24 +1249,24 @@ msgid "Submit selector" msgstr "确认按钮选择器" #: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38 -#: assets/serializers/asset/common.py:241 perms/models/asset_permission.py:70 +#: assets/serializers/asset/common.py:237 perms/models/asset_permission.py:70 #: perms/serializers/permission.py:32 rbac/tree.py:36 msgid "Accounts" msgstr "账号管理" -#: assets/models/automations/base.py:28 assets/models/automations/base.py:98 +#: assets/models/automations/base.py:28 assets/models/automations/base.py:102 msgid "Automation task" msgstr "自动化任务" -#: assets/models/automations/base.py:91 +#: assets/models/automations/base.py:95 #, fuzzy #| msgid "Automation task" msgid "Asset automation task" msgstr "自动化任务" -#: assets/models/automations/base.py:100 audits/models.py:135 -#: audits/serializers.py:48 ops/models/base.py:49 ops/models/job.py:99 -#: terminal/models/applet/applet.py:136 terminal/models/applet/host.py:107 +#: assets/models/automations/base.py:104 audits/models.py:134 +#: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:99 +#: terminal/models/applet/applet.py:145 terminal/models/applet/host.py:107 #: terminal/models/component/status.py:27 terminal/serializers/applet.py:17 #: terminal/serializers/applet_host.py:90 tickets/models/ticket/general.py:283 #: tickets/serializers/super_ticket.py:13 @@ -1311,7 +1322,9 @@ msgid "Command filter rule" msgstr "命令过滤规则" #: assets/models/favorite_asset.py:17 -msgid "Favorite Asset" +#, fuzzy +#| msgid "Favorite Asset" +msgid "Favorite asset" msgstr "收藏的资产" #: assets/models/gateway.py:35 assets/serializers/domain.py:16 @@ -1335,7 +1348,7 @@ msgstr "默认资产组" msgid "System" msgstr "系统" -#: assets/models/label.py:19 assets/models/node.py:552 +#: assets/models/label.py:19 assets/models/node.py:558 #: assets/serializers/cagegory.py:7 assets/serializers/cagegory.py:14 #: authentication/models/connection_token.py:25 #: authentication/serializers/connect_token_secret.py:114 @@ -1343,7 +1356,7 @@ msgstr "系统" msgid "Value" msgstr "值" -#: assets/models/label.py:40 assets/serializers/asset/common.py:123 +#: assets/models/label.py:40 assets/serializers/asset/common.py:119 #: assets/serializers/cagegory.py:6 assets/serializers/cagegory.py:13 #: authentication/serializers/connect_token_secret.py:113 #: common/serializers/common.py:81 settings/serializers/sms.py:7 @@ -1354,28 +1367,28 @@ msgstr "标签" msgid "New node" msgstr "新节点" -#: assets/models/node.py:480 +#: assets/models/node.py:486 audits/backends/db.py:55 audits/backends/db.py:56 msgid "empty" msgstr "空" -#: assets/models/node.py:551 perms/models/perm_node.py:28 +#: assets/models/node.py:557 perms/models/perm_node.py:28 msgid "Key" msgstr "键" -#: assets/models/node.py:553 assets/serializers/node.py:20 +#: assets/models/node.py:559 assets/serializers/node.py:20 msgid "Full value" msgstr "全称" -#: assets/models/node.py:557 perms/models/perm_node.py:30 +#: assets/models/node.py:563 perms/models/perm_node.py:30 msgid "Parent key" msgstr "ssh私钥" -#: assets/models/node.py:566 perms/serializers/permission.py:28 +#: assets/models/node.py:572 perms/serializers/permission.py:28 #: tickets/models/ticket/apply_asset.py:14 xpack/plugins/cloud/models.py:96 msgid "Node" msgstr "节点" -#: assets/models/node.py:569 +#: assets/models/node.py:575 msgid "Can match node" msgstr "可以匹配节点" @@ -1457,19 +1470,15 @@ msgstr "编码" msgid "Domain enabled" msgstr "启用网域" -#: assets/models/platform.py:85 -msgid "Protocols enabled" -msgstr "启用协议" - -#: assets/models/platform.py:87 +#: assets/models/platform.py:86 msgid "Su enabled" msgstr "启用账号切换" -#: assets/models/platform.py:88 +#: assets/models/platform.py:87 msgid "Su method" msgstr "账号切换方式" -#: assets/models/platform.py:90 assets/serializers/platform.py:91 +#: assets/models/platform.py:89 assets/serializers/platform.py:91 msgid "Automation" msgstr "自动化" @@ -1478,7 +1487,7 @@ msgstr "自动化" msgid "%(value)s is not an even number" msgstr "%(value)s is not an even number" -#: assets/serializers/asset/common.py:124 assets/serializers/platform.py:89 +#: assets/serializers/asset/common.py:120 assets/serializers/platform.py:89 #: authentication/serializers/connect_token_secret.py:28 #: authentication/serializers/connect_token_secret.py:65 #: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:107 @@ -1486,28 +1495,34 @@ msgstr "%(value)s is not an even number" msgid "Protocols" msgstr "协议组" -#: assets/serializers/asset/common.py:126 +#: assets/serializers/asset/common.py:122 #, fuzzy #| msgid "Enabled" msgid "Enabled info" msgstr "启用" -#: assets/serializers/asset/common.py:144 +#: assets/serializers/asset/common.py:140 msgid "Address" msgstr "地址" -#: assets/serializers/asset/common.py:145 +#: assets/serializers/asset/common.py:141 msgid "Node path" msgstr "节点路径" -#: assets/serializers/asset/common.py:205 +#: assets/serializers/asset/common.py:201 msgid "Platform not exist" msgstr "平台不存在" -#: assets/serializers/asset/common.py:221 +#: assets/serializers/asset/common.py:217 msgid "Protocol is required: {}" msgstr "协议是必填的: {}" +#: assets/serializers/asset/database.py:24 common/serializers/fields.py:100 +#: tickets/serializers/ticket/common.py:58 +#: xpack/plugins/cloud/serializers/account_attrs.py:56 +msgid "This field is required." +msgstr "该字段是必填项。" + #: assets/serializers/asset/host.py:12 msgid "Vendor" msgstr "制造商" @@ -1686,11 +1701,11 @@ msgstr "没有匹配到资产,结束任务" msgid "Audits" msgstr "日志审计" -#: audits/backends/db.py:12 +#: audits/backends/db.py:15 msgid "The text content is too long. Use Elasticsearch to store operation logs" msgstr "文字内容太长。请使用 Elasticsearch 存储操作日志" -#: audits/backends/db.py:25 audits/backends/db.py:27 +#: audits/backends/db.py:76 msgid "Tips" msgstr "提示" @@ -1762,20 +1777,34 @@ msgstr "终端" msgid "-" msgstr "-" -#: audits/handler.py:136 +#: audits/handler.py:116 msgid "Yes" msgstr "是" -#: audits/handler.py:136 +#: audits/handler.py:116 msgid "No" msgstr "否" -#: audits/models.py:32 audits/models.py:59 audits/models.py:102 +#: audits/handler.py:140 +msgid "{} used account[{}], login method[{}] login the asset." +msgstr "{} 使用账户[{}], 登录方式[{}]登录了这个资产." + +#: audits/handler.py:155 +msgid "User {} has executed change auth plan for this account.({})" +msgstr "用户 {} 为这个账号执行了改密计划.({})" + +#: audits/handler.py:168 +#, fuzzy +#| msgid "User {} {} it." +msgid "User {} login into this service.[{}]" +msgstr "用户 {} {}了它." + +#: audits/models.py:32 audits/models.py:59 audits/models.py:101 #: terminal/models/session/session.py:37 terminal/models/session/sharing.py:95 msgid "Remote addr" msgstr "远端地址" -#: audits/models.py:37 audits/serializers.py:32 +#: audits/models.py:37 audits/serializers.py:33 msgid "Operate" msgstr "操作" @@ -1787,7 +1816,7 @@ msgstr "文件名" msgid "File transfer log" msgstr "文件管理" -#: audits/models.py:53 audits/serializers.py:86 +#: audits/models.py:53 audits/serializers.py:93 msgid "Resource Type" msgstr "资源类型" @@ -1795,71 +1824,69 @@ msgstr "资源类型" msgid "Resource" msgstr "资源" -#: audits/models.py:60 audits/models.py:104 +#: audits/models.py:60 audits/models.py:103 #: terminal/backends/command/serializers.py:41 msgid "Datetime" msgstr "日期" -#: audits/models.py:63 -#, fuzzy -#| msgid "Is active" -msgid "Is Activity" -msgstr "激活" +#: audits/models.py:62 +msgid "Detail" +msgstr "" -#: audits/models.py:93 +#: audits/models.py:92 msgid "Operate log" msgstr "操作日志" -#: audits/models.py:100 +#: audits/models.py:99 msgid "Change by" msgstr "修改者" -#: audits/models.py:110 +#: audits/models.py:109 msgid "Password change log" msgstr "改密日志" -#: audits/models.py:117 +#: audits/models.py:116 msgid "Login type" msgstr "登录方式" -#: audits/models.py:119 tickets/models/ticket/login_confirm.py:10 +#: audits/models.py:118 tickets/models/ticket/login_confirm.py:10 msgid "Login ip" msgstr "登录IP" -#: audits/models.py:121 +#: audits/models.py:120 #: authentication/templates/authentication/_msg_different_city.html:11 #: tickets/models/ticket/login_confirm.py:11 msgid "Login city" msgstr "登录城市" -#: audits/models.py:124 audits/serializers.py:62 +#: audits/models.py:123 audits/serializers.py:63 msgid "User agent" msgstr "用户代理" -#: audits/models.py:127 audits/serializers.py:46 +#: audits/models.py:126 audits/serializers.py:47 #: authentication/templates/authentication/_mfa_confirm_modal.html:14 #: users/forms/profile.py:65 users/models/user.py:698 #: users/serializers/profile.py:126 msgid "MFA" msgstr "MFA" -#: audits/models.py:137 +#: audits/models.py:136 msgid "Date login" msgstr "登录日期" -#: audits/models.py:139 audits/serializers.py:64 +#: audits/models.py:138 audits/serializers.py:65 msgid "Authentication backend" msgstr "认证方式" -#: audits/models.py:180 +#: audits/models.py:182 msgid "User login log" msgstr "用户登录日志" -#: audits/serializers.py:63 +#: audits/serializers.py:64 msgid "Reason display" msgstr "原因描述" -#: audits/serializers.py:112 +#: audits/serializers.py:120 #, fuzzy #| msgid "User {} {} it." msgid "User {} {} this resource." @@ -1962,7 +1989,7 @@ msgid "Authentication" msgstr "认证" #: authentication/backends/custom.py:58 -#: authentication/backends/oauth2/backends.py:158 +#: authentication/backends/oauth2/backends.py:167 msgid "User invalid, disabled or expired" msgstr "用户无效,已禁用或已过期" @@ -2985,11 +3012,6 @@ msgstr "节点" msgid "File" msgstr "文件" -#: common/serializers/fields.py:100 tickets/serializers/ticket/common.py:58 -#: xpack/plugins/cloud/serializers/account_attrs.py:56 -msgid "This field is required." -msgstr "该字段是必填项。" - #: common/serializers/fields.py:101 #, python-brace-format msgid "Invalid pk \"{pk_value}\" - object does not exist." @@ -3128,7 +3150,7 @@ msgstr "Ansible 已禁用" msgid "Skip hosts below:" msgstr "跳过以下主机: " -#: ops/api/celery.py:63 ops/api/celery.py:78 +#: ops/api/celery.py:58 ops/api/celery.py:73 msgid "Waiting task start" msgstr "等待任务开始" @@ -3392,31 +3414,31 @@ msgstr "花费时间" msgid "Task" msgstr "任务" -#: ops/tasks.py:28 +#: ops/tasks.py:27 msgid "Run ansible task" msgstr "运行 Ansible 任务" -#: ops/tasks.py:35 +#: ops/tasks.py:43 msgid "Run ansible task execution" msgstr "开始执行 Ansible 任务" -#: ops/tasks.py:49 +#: ops/tasks.py:57 msgid "Periodic clear celery tasks" msgstr "周期清理不可用任务" -#: ops/tasks.py:51 +#: ops/tasks.py:59 msgid "Clean celery log period" msgstr "定期清除任务日志" -#: ops/tasks.py:68 +#: ops/tasks.py:76 msgid "Clear celery periodic tasks" msgstr "清理周期任务" -#: ops/tasks.py:91 +#: ops/tasks.py:99 msgid "Create or update periodic tasks" msgstr "创建或更新周期任务" -#: ops/tasks.py:99 +#: ops/tasks.py:107 msgid "Periodic check service performance" msgstr "周期检测服务性能" @@ -3489,7 +3511,7 @@ msgstr "组织" msgid "Org name" msgstr "组织名称" -#: orgs/models.py:70 rbac/models/role.py:36 terminal/models/applet/applet.py:29 +#: orgs/models.py:70 rbac/models/role.py:36 terminal/models/applet/applet.py:30 msgid "Builtin" msgstr "内置的" @@ -3637,27 +3659,27 @@ msgstr "{} 至少有一个系统角色" msgid "RBAC" msgstr "RBAC" -#: rbac/builtin.py:109 +#: rbac/builtin.py:110 msgid "SystemAdmin" msgstr "系统管理员" -#: rbac/builtin.py:112 +#: rbac/builtin.py:113 msgid "SystemAuditor" msgstr "系统审计员" -#: rbac/builtin.py:115 +#: rbac/builtin.py:116 msgid "SystemComponent" msgstr "系统组件" -#: rbac/builtin.py:121 +#: rbac/builtin.py:122 msgid "OrgAdmin" msgstr "组织管理员" -#: rbac/builtin.py:124 +#: rbac/builtin.py:125 msgid "OrgAuditor" msgstr "组织审计员" -#: rbac/builtin.py:127 +#: rbac/builtin.py:128 msgid "OrgUser" msgstr "组织用户" @@ -3737,7 +3759,7 @@ msgstr "权限" msgid "Users amount" msgstr "用户数量" -#: rbac/serializers/role.py:28 terminal/models/applet/applet.py:24 +#: rbac/serializers/role.py:28 terminal/models/applet/applet.py:25 msgid "Display name" msgstr "显示名称" @@ -3805,8 +3827,8 @@ msgstr "任务中心" msgid "My assets" msgstr "我的资产" -#: rbac/tree.py:57 terminal/models/applet/applet.py:39 -#: terminal/models/applet/applet.py:133 terminal/models/applet/host.py:27 +#: rbac/tree.py:57 terminal/models/applet/applet.py:40 +#: terminal/models/applet/applet.py:142 terminal/models/applet/host.py:27 msgid "Applet" msgstr "远程应用" @@ -5181,6 +5203,12 @@ msgstr "Jmservisor 是在 windows 远程应用发布服务器中用来拉起远 msgid "Offline video player" msgstr "离线录像播放器" +#: terminal/api/applet/applet.py:48 terminal/api/applet/applet.py:51 +#, fuzzy +#| msgid "Invalid ip" +msgid "Invalid zip file" +msgstr "无效IP" + #: terminal/api/component/endpoint.py:31 msgid "Not found protocol query params" msgstr "" @@ -5318,19 +5346,23 @@ msgstr "不支持批量创建" msgid "Storage is invalid" msgstr "存储无效" -#: terminal/models/applet/applet.py:26 +#: terminal/models/applet/applet.py:27 msgid "Author" msgstr "作者" -#: terminal/models/applet/applet.py:31 +#: terminal/models/applet/applet.py:32 msgid "Tags" msgstr "标签" -#: terminal/models/applet/applet.py:35 terminal/serializers/storage.py:157 +#: terminal/models/applet/applet.py:36 terminal/serializers/storage.py:157 msgid "Hosts" msgstr "主机" -#: terminal/models/applet/applet.py:135 terminal/models/applet/host.py:33 +#: terminal/models/applet/applet.py:81 +msgid "Applet pkg not valid, Missing file {}" +msgstr "" + +#: terminal/models/applet/applet.py:144 terminal/models/applet/host.py:33 #: terminal/models/applet/host.py:105 msgid "Hosting" msgstr "宿主机" @@ -5953,7 +5985,7 @@ msgstr "工单快照" msgid "Please try again" msgstr "请再次尝试" -#: tickets/models/ticket/general.py:458 +#: tickets/models/ticket/general.py:461 msgid "Super ticket" msgstr "超级工单" @@ -7185,6 +7217,14 @@ msgstr "旗舰版" msgid "Community edition" msgstr "社区版" +#~ msgid "Protocols enabled" +#~ msgstr "启用协议" + +#, fuzzy +#~| msgid "Is active" +#~ msgid "Is Activity" +#~ msgstr "激活" + #~ msgid "Dynamic username" #~ msgstr "同名账号" @@ -7203,12 +7243,6 @@ msgstr "社区版" #~ msgid "Change password method" #~ msgstr "更改密码方式" -#~ msgid "{} used account[{}], login method[{}] login the asset." -#~ msgstr "{} 使用账户[{}], 登录方式[{}]登录了这个资产." - -#~ msgid "User {} has executed change auth plan for this account.({})" -#~ msgstr "用户 {} 为这个账号执行了改密计划.({})" - #~ msgid "Applet host" #~ msgstr "远程应用发布机" From 2ea8e30ca5dcaa43eb6ee6cb915734cc6f9eaece Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Tue, 31 Jan 2023 16:17:45 +0800 Subject: [PATCH 13/92] =?UTF-8?q?fix:=20=E8=B4=A6=E5=8F=B7=E5=A4=87?= =?UTF-8?q?=E4=BB=BD=E6=97=A0=E6=B3=95=E6=89=A7=E8=A1=8C=20(#9379)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng <1304903146@qq.com> --- apps/accounts/serializers/account/backup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/accounts/serializers/account/backup.py b/apps/accounts/serializers/account/backup.py index 57d4c9ccc..0c601c3f4 100644 --- a/apps/accounts/serializers/account/backup.py +++ b/apps/accounts/serializers/account/backup.py @@ -36,7 +36,7 @@ class AccountBackupSerializer(PeriodTaskSerializerMixin, BulkOrgResourceModelSer class AccountBackupPlanExecutionSerializer(serializers.ModelSerializer): - trigger = LabeledChoiceField(choices=Trigger.choices, label=_("Trigger mode")) + trigger = LabeledChoiceField(choices=Trigger.choices, label=_("Trigger mode"), read_only=True) class Meta: model = AccountBackupExecution From 9ec7a8ac61b61f771ee44442f7938f43a4a7abf0 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 31 Jan 2023 17:46:56 +0800 Subject: [PATCH 14/92] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=20asset=20info?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/asset/asset.py | 8 ++- apps/assets/models/asset/common.py | 52 +++++++++---------- apps/assets/serializers/asset/common.py | 26 +++++++--- .../serializers/connect_token_secret.py | 3 +- apps/ops/ansible/inventory.py | 2 +- apps/terminal/applets/navicat/app.py | 3 +- 6 files changed, 55 insertions(+), 39 deletions(-) diff --git a/apps/assets/api/asset/asset.py b/apps/assets/api/asset/asset.py index c0dda34c7..a02d35121 100644 --- a/apps/assets/api/asset/asset.py +++ b/apps/assets/api/asset/asset.py @@ -2,7 +2,6 @@ # import django_filters from django.db.models import Q -from django.utils.translation import ugettext_lazy as _ from rest_framework.decorators import action from rest_framework.response import Response @@ -72,11 +71,13 @@ class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet): ("platform", serializers.PlatformSerializer), ("suggestion", serializers.MiniAssetSerializer), ("gateways", serializers.GatewaySerializer), + ("spec_info", serializers.SpecSerializer), ) rbac_perms = ( ("match", "assets.match_asset"), ("platform", "assets.view_platform"), ("gateways", "assets.view_gateway"), + ("spec_info", "assets.view_asset"), ) extra_filter_backends = [LabelFilterBackend, IpInFilterBackend, NodeFilterBackend] @@ -94,6 +95,11 @@ class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet): serializer = super().get_serializer(instance=asset.platform) return Response(serializer.data) + @action(methods=["GET"], detail=True, url_path="spec-info") + def spec_info(self, *args, **kwargs): + asset = super().get_object() + return Response(asset.spec_info) + @action(methods=["GET"], detail=True, url_path="gateways") def gateways(self, *args, **kwargs): asset = self.get_object() diff --git a/apps/assets/models/asset/common.py b/apps/assets/models/asset/common.py index 60f2f3c14..dfbf2ecf0 100644 --- a/apps/assets/models/asset/common.py +++ b/apps/assets/models/asset/common.py @@ -10,8 +10,8 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ from assets import const -from common.utils import lazyproperty from common.db.fields import EncryptMixin +from common.utils import lazyproperty from orgs.mixins.models import OrgManager, JMSOrgBaseModel from ..base import AbsConnectivity from ..platform import Platform @@ -113,45 +113,47 @@ class Asset(NodesRelationMixin, AbsConnectivity, JMSOrgBaseModel): verbose_name=_("Nodes")) is_active = models.BooleanField(default=True, verbose_name=_('Is active')) labels = models.ManyToManyField('assets.Label', blank=True, related_name='assets', verbose_name=_("Labels")) - info = models.JSONField(verbose_name='Info', default=dict, blank=True) + info = models.JSONField(verbose_name='Info', default=dict, blank=True) # 资产的一些信息,如 硬件信息 objects = AssetManager.from_queryset(AssetQuerySet)() def __str__(self): return '{0.name}({0.address})'.format(self) - @property - def specific(self): - instance = getattr(self, self.category, None) - if not instance: - return {} - specific_fields = self.get_specific_fields(instance) + @staticmethod + def get_spec_values(instance, fields): info = {} - for i in specific_fields: + for i in fields: v = getattr(instance, i.name) if isinstance(i, models.JSONField) and not isinstance(v, (list, dict)): v = json.loads(v) info[i.name] = v return info - @property + @lazyproperty def spec_info(self): instance = getattr(self, self.category, None) if not instance: - return [] - specific_fields = self.get_specific_fields(instance) - info = [ - { - 'label': i.verbose_name, - 'name': i.name, - 'value': getattr(instance, i.name) - } - for i in specific_fields - ] - return info + return {} + spec_fields = self.get_spec_fields(instance) + return self.get_spec_values(instance, spec_fields) + + @staticmethod + def get_spec_fields(instance, secret=False): + spec_fields = [i for i in instance._meta.local_fields if i.name != 'asset_ptr'] + spec_fields = [i for i in spec_fields if isinstance(i, EncryptMixin) == secret] + return spec_fields @lazyproperty - def enabled_info(self): + def secret_info(self): + instance = getattr(self, self.category, None) + if not instance: + return {} + spec_fields = self.get_spec_fields(instance, secret=True) + return self.get_spec_values(instance, spec_fields) + + @lazyproperty + def auto_info(self): platform = self.platform automation = self.platform.automation return { @@ -165,12 +167,6 @@ class Asset(NodesRelationMixin, AbsConnectivity, JMSOrgBaseModel): 'gather_accounts_enabled': automation.gather_accounts_enabled, } - @staticmethod - def get_specific_fields(instance): - specific_fields = [i for i in instance._meta.local_fields if i.name != 'asset_ptr'] - specific_fields = [i for i in specific_fields if not isinstance(i, EncryptMixin)] - return specific_fields - def get_target_ip(self): return self.address diff --git a/apps/assets/serializers/asset/common.py b/apps/assets/serializers/asset/common.py index 89d5a66eb..47c866603 100644 --- a/apps/assets/serializers/asset/common.py +++ b/apps/assets/serializers/asset/common.py @@ -18,7 +18,7 @@ __all__ = [ 'AssetSerializer', 'AssetSimpleSerializer', 'MiniAssetSerializer', 'AssetTaskSerializer', 'AssetsTaskSerializer', 'AssetProtocolsSerializer', 'AssetDetailSerializer', 'DetailMixin', 'AssetAccountSerializer', - 'AccountSecretSerializer' + 'AccountSecretSerializer', 'SpecSerializer' ] @@ -113,13 +113,25 @@ class AccountSecretSerializer(SecretReadableMixin, CommonModelSerializer): } +class SpecSerializer(serializers.Serializer): + # 数据库 + db_name = serializers.CharField(label=_("Database"), max_length=128, required=False) + use_ssl = serializers.BooleanField(label=_("Use SSL"), required=False) + allow_invalid_cert = serializers.BooleanField(label=_("Allow invalid cert"), required=False) + # Web + autofill = serializers.CharField(label=_("Auto fill"), required=False) + username_selector = serializers.CharField(label=_("Username selector"), required=False) + password_selector = serializers.CharField(label=_("Password selector"), required=False) + submit_selector = serializers.CharField(label=_("Submit selector"), required=False) + script = serializers.JSONField(label=_("Script"), required=False) + + class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSerializer): category = LabeledChoiceField(choices=Category.choices, read_only=True, label=_('Category')) type = LabeledChoiceField(choices=AllTypes.choices(), read_only=True, label=_('Type')) labels = AssetLabelSerializer(many=True, required=False, label=_('Label')) protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols')) accounts = AssetAccountSerializer(many=True, required=False, write_only=True, label=_('Account')) - enabled_info = serializers.DictField(read_only=True, label=_('Enabled info')) class Meta: model = Asset @@ -127,11 +139,11 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali fields_small = fields_mini + ['is_active', 'comment'] fields_fk = ['domain', 'platform'] fields_m2m = [ - 'nodes', 'labels', 'protocols', 'nodes_display', 'accounts' + 'nodes', 'labels', 'protocols', + 'nodes_display', 'accounts' ] read_only_fields = [ - 'category', 'type', 'info', 'enabled_info', - 'connectivity', 'date_verified', + 'category', 'type', 'connectivity', 'date_verified', 'created_by', 'date_created' ] fields = fields_small + fields_fk + fields_m2m + read_only_fields @@ -235,11 +247,13 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali class DetailMixin(serializers.Serializer): accounts = AssetAccountSerializer(many=True, required=False, label=_('Accounts')) + spec_info = serializers.DictField(label=_('Spec info'), read_only=True) + auto_info = serializers.DictField(read_only=True, label=_('Auto info')) def get_field_names(self, declared_fields, info): names = super().get_field_names(declared_fields, info) names.extend([ - 'accounts', 'info', 'specific', 'spec_info' + 'accounts', 'info', 'spec_info', 'auto_info' ]) return names diff --git a/apps/authentication/serializers/connect_token_secret.py b/apps/authentication/serializers/connect_token_secret.py index 4585111ea..41ee8d116 100644 --- a/apps/authentication/serializers/connect_token_secret.py +++ b/apps/authentication/serializers/connect_token_secret.py @@ -31,7 +31,8 @@ class _ConnectionTokenAssetSerializer(serializers.ModelSerializer): model = Asset fields = [ 'id', 'name', 'address', 'protocols', - 'category', 'type', 'org_id', 'specific' + 'category', 'type', 'org_id', 'spec_info', + 'secret_info', ] diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py index e50a0801f..243f1b319 100644 --- a/apps/ops/ansible/inventory.py +++ b/apps/ops/ansible/inventory.py @@ -105,7 +105,7 @@ class JMSInventory: 'id': str(asset.id), 'name': asset.name, 'address': asset.address, 'type': asset.type, 'category': asset.category, 'protocol': asset.protocol, 'port': asset.port, - 'specific': asset.specific, + 'specific': asset.spec, 'protocols': [{'name': p.name, 'port': p.port} for p in protocols], }, 'jms_account': { diff --git a/apps/terminal/applets/navicat/app.py b/apps/terminal/applets/navicat/app.py index 33d89d2d2..37c80f144 100644 --- a/apps/terminal/applets/navicat/app.py +++ b/apps/terminal/applets/navicat/app.py @@ -11,7 +11,6 @@ if sys.platform == 'win32': ) from common import wait_pid, BaseApplication - _default_path = r'C:\Program Files\PremiumSoft\Navicat Premium 16\navicat.exe' @@ -24,7 +23,7 @@ class AppletApplication(BaseApplication): self.privileged = self.account.privileged self.host = self.asset.address self.port = self.asset.get_protocol_port(self.protocol) - self.db = self.asset.specific.db_name + self.db = self.asset.spec.db_name self.name = '%s-%s' % (self.host, self.db) self.pid = None self.app = None From 41154d3793aeba3f476d1928f9f1de7ab17e7aa7 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 31 Jan 2023 17:57:06 +0800 Subject: [PATCH 15/92] asset: specific to spec_info --- .../change_secret/database/mongodb/main.yml | 12 ++-- .../change_secret/database/oracle/main.yml | 10 ++-- .../database/postgresql/main.yml | 10 ++-- .../change_secret/database/sqlserver/main.yml | 58 +++++++++---------- .../gather_accounts/database/mongodb/main.yml | 2 +- .../gather_accounts/database/oracle/main.yml | 2 +- .../database/postgresql/main.yml | 2 +- .../verify_account/database/mongodb/main.yml | 2 +- .../verify_account/database/oracle/main.yml | 2 +- .../database/postgresql/main.yml | 2 +- .../database/sqlserver/main.yml | 2 +- .../gather_facts/database/mongodb/main.yml | 2 +- .../gather_facts/database/oracle/main.yml | 2 +- .../gather_facts/database/postgresql/main.yml | 2 +- .../ping/database/mongodb/main.yml | 2 +- .../automations/ping/database/oracle/main.yml | 2 +- .../ping/database/postgresql/main.yml | 2 +- .../ping/database/sqlserver/main.yml | 2 +- apps/terminal/applets/chrome/app.py | 4 +- apps/terminal/applets/navicat/app.py | 2 +- 20 files changed, 62 insertions(+), 62 deletions(-) diff --git a/apps/accounts/automations/change_secret/database/mongodb/main.yml b/apps/accounts/automations/change_secret/database/mongodb/main.yml index 02a568e0b..95702c8bb 100644 --- a/apps/accounts/automations/change_secret/database/mongodb/main.yml +++ b/apps/accounts/automations/change_secret/database/mongodb/main.yml @@ -10,7 +10,7 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_database: "{{ jms_asset.specific.db_name }}" + login_database: "{{ jms_asset.spec_info.db_name }}" register: db_info - name: Display MongoDB version @@ -24,8 +24,8 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_database: "{{ jms_asset.specific.db_name }}" - db: "{{ jms_asset.specific.db_name }}" + login_database: "{{ jms_asset.spec_info.db_name }}" + db: "{{ jms_asset.spec_info.db_name }}" name: "{{ account.username }}" password: "{{ account.secret }}" when: db_info is succeeded @@ -37,7 +37,7 @@ login_password: "{{ account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_database: "{{ jms_asset.specific.db_name }}" + login_database: "{{ jms_asset.spec_info.db_name }}" when: - - db_info is succeeded - - change_info is succeeded + - db_info is succeeded + - change_info is succeeded diff --git a/apps/accounts/automations/change_secret/database/oracle/main.yml b/apps/accounts/automations/change_secret/database/oracle/main.yml index c7b20a8db..a58d776a7 100644 --- a/apps/accounts/automations/change_secret/database/oracle/main.yml +++ b/apps/accounts/automations/change_secret/database/oracle/main.yml @@ -10,7 +10,7 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_database: "{{ jms_asset.specific.db_name }}" + login_database: "{{ jms_asset.spec_info.db_name }}" mode: "{{ jms_account.mode }}" register: db_info @@ -25,7 +25,7 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_database: "{{ jms_asset.specific.db_name }}" + login_database: "{{ jms_asset.spec_info.db_name }}" mode: "{{ jms_account.mode }}" name: "{{ account.username }}" password: "{{ account.secret }}" @@ -38,8 +38,8 @@ login_password: "{{ account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_database: "{{ jms_asset.specific.db_name }}" + login_database: "{{ jms_asset.spec_info.db_name }}" mode: "{{ account.mode }}" when: - - db_info is succeeded - - change_info is succeeded + - db_info is succeeded + - change_info is succeeded diff --git a/apps/accounts/automations/change_secret/database/postgresql/main.yml b/apps/accounts/automations/change_secret/database/postgresql/main.yml index ada11bbd6..6a903171f 100644 --- a/apps/accounts/automations/change_secret/database/postgresql/main.yml +++ b/apps/accounts/automations/change_secret/database/postgresql/main.yml @@ -10,7 +10,7 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_db: "{{ jms_asset.specific.db_name }}" + login_db: "{{ jms_asset.spec_info.db_name }}" register: db_info - name: Display PostgreSQL version @@ -24,7 +24,7 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - db: "{{ jms_asset.specific.db_name }}" + db: "{{ jms_asset.spec_info.db_name }}" name: "{{ account.username }}" password: "{{ account.secret }}" when: db_info is succeeded @@ -36,7 +36,7 @@ login_password: "{{ account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - db: "{{ jms_asset.specific.db_name }}" + db: "{{ jms_asset.spec_info.db_name }}" when: - - db_info is succeeded - - change_info is succeeded + - db_info is succeeded + - change_info is succeeded diff --git a/apps/accounts/automations/change_secret/database/sqlserver/main.yml b/apps/accounts/automations/change_secret/database/sqlserver/main.yml index a617a1434..d3ea188b0 100644 --- a/apps/accounts/automations/change_secret/database/sqlserver/main.yml +++ b/apps/accounts/automations/change_secret/database/sqlserver/main.yml @@ -10,38 +10,38 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - name: '{{ jms_asset.specific.db_name }}' + name: '{{ jms_asset.spec_info.db_name }}' script: | SELECT @@version register: db_info - - name: SQLServer version - set_fact: - info: - version: "{{ db_info.query_results[0][0][0][0].splitlines()[0] }}" - - debug: - var: info + - name: SQLServer version + set_fact: + info: + version: "{{ db_info.query_results[0][0][0][0].splitlines()[0] }}" + - debug: + var: info - - name: Change SQLServer password - community.general.mssql_script: - login_user: "{{ jms_account.username }}" - login_password: "{{ jms_account.secret }}" - login_host: "{{ jms_asset.address }}" - login_port: "{{ jms_asset.port }}" - name: '{{ jms_asset.specific.db_name }}' - script: "ALTER LOGIN {{ account.username }} WITH PASSWORD = '{{ account.secret }}'; select @@version" - when: db_info is succeeded - register: change_info + - name: Change SQLServer password + community.general.mssql_script: + login_user: "{{ jms_account.username }}" + login_password: "{{ jms_account.secret }}" + login_host: "{{ jms_asset.address }}" + login_port: "{{ jms_asset.port }}" + name: '{{ jms_asset.spec_info.db_name }}' + script: "ALTER LOGIN {{ account.username }} WITH PASSWORD = '{{ account.secret }}'; select @@version" + when: db_info is succeeded + register: change_info - - name: Verify password - community.general.mssql_script: - login_user: "{{ account.username }}" - login_password: "{{ account.secret }}" - login_host: "{{ jms_asset.address }}" - login_port: "{{ jms_asset.port }}" - name: '{{ jms_asset.specific.db_name }}' - script: | - SELECT @@version - when: - - db_info is succeeded - - change_info is succeeded + - name: Verify password + community.general.mssql_script: + login_user: "{{ account.username }}" + login_password: "{{ account.secret }}" + login_host: "{{ jms_asset.address }}" + login_port: "{{ jms_asset.port }}" + name: '{{ jms_asset.spec_info.db_name }}' + script: | + SELECT @@version + when: + - db_info is succeeded + - change_info is succeeded diff --git a/apps/accounts/automations/gather_accounts/database/mongodb/main.yml b/apps/accounts/automations/gather_accounts/database/mongodb/main.yml index fd7a296b7..b94f2be1d 100644 --- a/apps/accounts/automations/gather_accounts/database/mongodb/main.yml +++ b/apps/accounts/automations/gather_accounts/database/mongodb/main.yml @@ -10,7 +10,7 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_database: "{{ jms_asset.specific.db_name }}" + login_database: "{{ jms_asset.spec_info.db_name }}" filter: users register: db_info diff --git a/apps/accounts/automations/gather_accounts/database/oracle/main.yml b/apps/accounts/automations/gather_accounts/database/oracle/main.yml index a0e20ff7b..f492583f4 100644 --- a/apps/accounts/automations/gather_accounts/database/oracle/main.yml +++ b/apps/accounts/automations/gather_accounts/database/oracle/main.yml @@ -10,7 +10,7 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_database: "{{ jms_asset.specific.db_name }}" + login_database: "{{ jms_asset.spec_info.db_name }}" mode: "{{ jms_account.mode }}" filter: users register: db_info diff --git a/apps/accounts/automations/gather_accounts/database/postgresql/main.yml b/apps/accounts/automations/gather_accounts/database/postgresql/main.yml index f282b390d..c1c25c8b4 100644 --- a/apps/accounts/automations/gather_accounts/database/postgresql/main.yml +++ b/apps/accounts/automations/gather_accounts/database/postgresql/main.yml @@ -10,7 +10,7 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_db: "{{ jms_asset.specific.db_name }}" + login_db: "{{ jms_asset.spec_info.db_name }}" filter: "roles" register: db_info diff --git a/apps/accounts/automations/verify_account/database/mongodb/main.yml b/apps/accounts/automations/verify_account/database/mongodb/main.yml index 1cf79b694..a65eee915 100644 --- a/apps/accounts/automations/verify_account/database/mongodb/main.yml +++ b/apps/accounts/automations/verify_account/database/mongodb/main.yml @@ -10,4 +10,4 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_database: "{{ jms_asset.specific.db_name }}" + login_database: "{{ jms_asset.spec_info.db_name }}" diff --git a/apps/accounts/automations/verify_account/database/oracle/main.yml b/apps/accounts/automations/verify_account/database/oracle/main.yml index ed4091401..12896f09a 100644 --- a/apps/accounts/automations/verify_account/database/oracle/main.yml +++ b/apps/accounts/automations/verify_account/database/oracle/main.yml @@ -10,5 +10,5 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_database: "{{ jms_asset.specific.db_name }}" + login_database: "{{ jms_asset.spec_info.db_name }}" mode: "{{ jms_account.mode }}" diff --git a/apps/accounts/automations/verify_account/database/postgresql/main.yml b/apps/accounts/automations/verify_account/database/postgresql/main.yml index 08db4d869..cb6344b39 100644 --- a/apps/accounts/automations/verify_account/database/postgresql/main.yml +++ b/apps/accounts/automations/verify_account/database/postgresql/main.yml @@ -10,4 +10,4 @@ login_password: "{{ account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - db: "{{ jms_asset.specific.db_name }}" + db: "{{ jms_asset.spec_info.db_name }}" diff --git a/apps/accounts/automations/verify_account/database/sqlserver/main.yml b/apps/accounts/automations/verify_account/database/sqlserver/main.yml index 256803702..bb079fa59 100644 --- a/apps/accounts/automations/verify_account/database/sqlserver/main.yml +++ b/apps/accounts/automations/verify_account/database/sqlserver/main.yml @@ -10,6 +10,6 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - name: '{{ jms_asset.specific.db_name }}' + name: '{{ jms_asset.spec_info.db_name }}' script: | SELECT @@version diff --git a/apps/assets/automations/gather_facts/database/mongodb/main.yml b/apps/assets/automations/gather_facts/database/mongodb/main.yml index 37ce8bbd3..7cfe212a4 100644 --- a/apps/assets/automations/gather_facts/database/mongodb/main.yml +++ b/apps/assets/automations/gather_facts/database/mongodb/main.yml @@ -10,7 +10,7 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_database: "{{ jms_asset.specific.db_name }}" + login_database: "{{ jms_asset.spec_info.db_name }}" register: db_info - name: Define info by set_fact diff --git a/apps/assets/automations/gather_facts/database/oracle/main.yml b/apps/assets/automations/gather_facts/database/oracle/main.yml index 21ab639a4..f88fc11a1 100644 --- a/apps/assets/automations/gather_facts/database/oracle/main.yml +++ b/apps/assets/automations/gather_facts/database/oracle/main.yml @@ -10,7 +10,7 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_database: "{{ jms_asset.specific.db_name }}" + login_database: "{{ jms_asset.spec_info.db_name }}" mode: "{{ jms_account.mode }}" register: db_info diff --git a/apps/assets/automations/gather_facts/database/postgresql/main.yml b/apps/assets/automations/gather_facts/database/postgresql/main.yml index a3c481b48..302fe1f9d 100644 --- a/apps/assets/automations/gather_facts/database/postgresql/main.yml +++ b/apps/assets/automations/gather_facts/database/postgresql/main.yml @@ -10,7 +10,7 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_db: "{{ jms_asset.specific.db_name }}" + login_db: "{{ jms_asset.spec_info.db_name }}" register: db_info - name: Define info by set_fact diff --git a/apps/assets/automations/ping/database/mongodb/main.yml b/apps/assets/automations/ping/database/mongodb/main.yml index 867c51ace..f89c44b1e 100644 --- a/apps/assets/automations/ping/database/mongodb/main.yml +++ b/apps/assets/automations/ping/database/mongodb/main.yml @@ -10,4 +10,4 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_database: "{{ jms_asset.specific.db_name }}" + login_database: "{{ jms_asset.spec_info.db_name }}" diff --git a/apps/assets/automations/ping/database/oracle/main.yml b/apps/assets/automations/ping/database/oracle/main.yml index fefad7148..9cc6695ac 100644 --- a/apps/assets/automations/ping/database/oracle/main.yml +++ b/apps/assets/automations/ping/database/oracle/main.yml @@ -10,5 +10,5 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_database: "{{ jms_asset.specific.db_name }}" + login_database: "{{ jms_asset.spec_info.db_name }}" mode: "{{ jms_account.mode }}" diff --git a/apps/assets/automations/ping/database/postgresql/main.yml b/apps/assets/automations/ping/database/postgresql/main.yml index e97b3946d..f48c7d4f7 100644 --- a/apps/assets/automations/ping/database/postgresql/main.yml +++ b/apps/assets/automations/ping/database/postgresql/main.yml @@ -10,4 +10,4 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - login_db: "{{ jms_asset.specific.db_name }}" + login_db: "{{ jms_asset.spec_info.db_name }}" diff --git a/apps/assets/automations/ping/database/sqlserver/main.yml b/apps/assets/automations/ping/database/sqlserver/main.yml index 839a785a5..ca242538e 100644 --- a/apps/assets/automations/ping/database/sqlserver/main.yml +++ b/apps/assets/automations/ping/database/sqlserver/main.yml @@ -10,6 +10,6 @@ login_password: "{{ jms_account.secret }}" login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" - name: '{{ jms_asset.specific.db_name }}' + name: '{{ jms_asset.spec_info.db_name }}' script: | SELECT @@version diff --git a/apps/terminal/applets/chrome/app.py b/apps/terminal/applets/chrome/app.py index 89ae3fc3b..7d9b12c36 100644 --- a/apps/terminal/applets/chrome/app.py +++ b/apps/terminal/applets/chrome/app.py @@ -89,11 +89,11 @@ class WebAPP(object): self.extra_data = self.asset.specific self._steps = list() - autofill_type = self.asset.specific.autofill + autofill_type = self.asset.spec_info.autofill if autofill_type == "basic": self._steps = self._default_custom_steps() elif autofill_type == "script": - script_list = self.asset.specific.script + script_list = self.asset.spec_info.script steps = sorted(script_list, key=lambda step_item: step_item.step) for item in steps: val = item.value diff --git a/apps/terminal/applets/navicat/app.py b/apps/terminal/applets/navicat/app.py index 37c80f144..f7447007b 100644 --- a/apps/terminal/applets/navicat/app.py +++ b/apps/terminal/applets/navicat/app.py @@ -23,7 +23,7 @@ class AppletApplication(BaseApplication): self.privileged = self.account.privileged self.host = self.asset.address self.port = self.asset.get_protocol_port(self.protocol) - self.db = self.asset.spec.db_name + self.db = self.asset.spec_info.db_name self.name = '%s-%s' % (self.host, self.db) self.pid = None self.app = None From ef51e74b8ef900ea501b53b623043ec6366dd393 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 31 Jan 2023 18:06:44 +0800 Subject: [PATCH 16/92] =?UTF-8?q?perf=EF=BC=9A=20=E7=BB=A7=E7=BB=AD?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=20spec?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/models/base.py | 2 +- apps/accounts/serializers/account/base.py | 6 +++--- apps/ops/ansible/inventory.py | 2 +- apps/perms/serializers/user_permission.py | 6 +++--- apps/terminal/applets/chrome/app.py | 10 +++++----- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/apps/accounts/models/base.py b/apps/accounts/models/base.py index ffae7051b..37b97f21a 100644 --- a/apps/accounts/models/base.py +++ b/apps/accounts/models/base.py @@ -50,7 +50,7 @@ class BaseAccount(JMSOrgBaseModel): return bool(self.username) @property - def specific(self): + def spec_info(self): data = {} if self.secret_type != SecretType.SSH_KEY: return data diff --git a/apps/accounts/serializers/account/base.py b/apps/accounts/serializers/account/base.py index d92c4cc9c..fb5b51d6f 100644 --- a/apps/accounts/serializers/account/base.py +++ b/apps/accounts/serializers/account/base.py @@ -68,14 +68,14 @@ class BaseAccountSerializer(AuthValidateMixin, BulkOrgResourceModelSerializer): fields_mini = ['id', 'name', 'username'] fields_small = fields_mini + [ 'secret_type', 'secret', 'has_secret', 'passphrase', - 'privileged', 'is_active', 'specific', + 'privileged', 'is_active', 'spec_info', ] fields_other = ['created_by', 'date_created', 'date_updated', 'comment'] fields = fields_small + fields_other read_only_fields = [ - 'has_secret', 'specific', + 'has_secret', 'spec_info', 'date_verified', 'created_by', 'date_created', ] extra_kwargs = { - 'specific': {'label': _('Specific')}, + 'spec_info': {'label': _('Spec info')}, } diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py index 243f1b319..0a3ce43af 100644 --- a/apps/ops/ansible/inventory.py +++ b/apps/ops/ansible/inventory.py @@ -105,7 +105,7 @@ class JMSInventory: 'id': str(asset.id), 'name': asset.name, 'address': asset.address, 'type': asset.type, 'category': asset.category, 'protocol': asset.protocol, 'port': asset.port, - 'specific': asset.spec, + 'spec_info': asset.spec_info, 'protocols': [{'name': p.name, 'port': p.port} for p in protocols], }, 'jms_account': { diff --git a/apps/perms/serializers/user_permission.py b/apps/perms/serializers/user_permission.py index 8e22623fc..27fde71d1 100644 --- a/apps/perms/serializers/user_permission.py +++ b/apps/perms/serializers/user_permission.py @@ -4,13 +4,13 @@ from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers +from accounts.models import Account from assets.const import Category, AllTypes from assets.models import Node, Asset, Platform -from accounts.models import Account from assets.serializers.asset.common import AssetProtocolsSerializer from common.serializers.fields import ObjectRelatedField, LabeledChoiceField -from perms.serializers.permission import ActionChoicesField from orgs.mixins.serializers import OrgResourceModelSerializerMixin +from perms.serializers.permission import ActionChoicesField __all__ = [ 'NodePermedSerializer', 'AssetPermedSerializer', @@ -32,7 +32,7 @@ class AssetPermedSerializer(OrgResourceModelSerializerMixin): "id", "name", "address", 'domain', 'platform', "comment", "org_id", "is_active", ] - fields = only_fields + ['protocols', 'category', 'type', 'specific'] + ['org_name'] + fields = only_fields + ['protocols', 'category', 'type', 'spec_info'] + ['org_name'] read_only_fields = fields diff --git a/apps/terminal/applets/chrome/app.py b/apps/terminal/applets/chrome/app.py index 7d9b12c36..491f1e09d 100644 --- a/apps/terminal/applets/chrome/app.py +++ b/apps/terminal/applets/chrome/app.py @@ -87,7 +87,7 @@ class WebAPP(object): self.account = account self.platform = platform - self.extra_data = self.asset.specific + self.extra_data = self.asset.spec_info self._steps = list() autofill_type = self.asset.spec_info.autofill if autofill_type == "basic": @@ -105,24 +105,24 @@ class WebAPP(object): def _default_custom_steps(self) -> list: account = self.account - specific_property = self.asset.specific + spec_info = self.asset.spec_info default_steps = [ Step({ "step": 1, "value": account.username, - "target": specific_property.username_selector, + "target": spec_info.username_selector, "command": "type" }), Step({ "step": 2, "value": account.secret, - "target": specific_property.password_selector, + "target": spec_info.password_selector, "command": "type" }), Step({ "step": 3, "value": "", - "target": specific_property.submit_selector, + "target": spec_info.submit_selector, "command": "click" }) ] From ae79584faa80491213fb9242029ddf253c017d83 Mon Sep 17 00:00:00 2001 From: Bai Date: Tue, 31 Jan 2023 18:07:55 +0800 Subject: [PATCH 17/92] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7=E5=88=97=E8=A1=A8=20secret=20=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E5=90=8D=E7=A7=B0=20=E5=AF=86=E9=92=A5/=E5=AF=86=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0100_auto_20220711_1413.py | 76 +++++++++++++++++-- 1 file changed, 71 insertions(+), 5 deletions(-) diff --git a/apps/assets/migrations/0100_auto_20220711_1413.py b/apps/assets/migrations/0100_auto_20220711_1413.py index 62fa1cbd5..16e75cbae 100644 --- a/apps/assets/migrations/0100_auto_20220711_1413.py +++ b/apps/assets/migrations/0100_auto_20220711_1413.py @@ -1,17 +1,17 @@ # Generated by Django 3.2.12 on 2022-07-11 06:13 import time -from django.db import migrations +from django.db import migrations, models from assets.models import Platform -def migrate_accounts(apps, schema_editor): +def migrate_asset_accounts(apps, schema_editor): auth_book_model = apps.get_model('assets', 'AuthBook') account_model = apps.get_model('accounts', 'Account') count = 0 bulk_size = 1000 - print("\n\tStart migrate accounts") + print("\n\tStart migrate asset accounts") while True: start = time.time() auth_books = auth_book_model.objects \ @@ -71,11 +71,76 @@ def migrate_accounts(apps, schema_editor): accounts.append(account) account_model.objects.bulk_create(accounts, ignore_conflicts=True) - print("\t - Create accounts: {}-{} using: {:.2f}s".format( + print("\t - Create asset accounts: {}-{} using: {:.2f}s".format( count - len(auth_books), count, time.time() - start )) +def migrate_db_accounts(apps, schema_editor): + app_perm_model = apps.get_model('perms', 'ApplicationPermission') + account_model = apps.get_model('accounts', 'Account') + perms = app_perm_model.objects.filter(category__in=['db', 'cloud']) + + same_attrs = [ + 'id', 'username', 'comment', 'date_created', 'date_updated', + 'created_by', 'org_id', + ] + auth_attrs = ['password', 'private_key', 'token'] + all_attrs = same_attrs + auth_attrs + + print("\n\tStart migrate app accounts") + + index = 0 + total = perms.count() + + for perm in perms: + index += 1 + start = time.time() + + system_users = perm.system_users.all() + accounts = [] + for s in system_users: + values = {'version': 1} + values.update({attr: getattr(s, attr, '') for attr in all_attrs}) + values['created_by'] = str(s.id) + + auth_infos = [] + username = values['username'] + for attr in auth_attrs: + secret = values.pop(attr, None) + if not secret: + continue + + if attr == 'private_key': + secret_type = 'ssh_key' + name = f'{username}(ssh key)' + elif attr == 'token': + secret_type = 'token' + name = f'{username}(token)' + else: + secret_type = attr + name = username + auth_infos.append((name, secret_type, secret)) + + if not auth_infos: + auth_infos.append((username, 'password', '')) + + for name, secret_type, secret in auth_infos: + account = account_model(**values, name=name, secret=secret, secret_type=secret_type) + accounts.append(account) + + apps = perm.applications.all() + for app in apps: + for account in accounts: + setattr(account, 'asset_id', str(app.id)) + + account_model.objects.bulk_create(accounts, ignore_conflicts=True) + + print("\t - Progress ({}/{}), Create app accounts: {} using: {:.2f}s".format( + index, total, len(accounts), time.time() - start + )) + + class Migration(migrations.Migration): dependencies = [ ('accounts', '0001_initial'), @@ -83,5 +148,6 @@ class Migration(migrations.Migration): ] operations = [ - migrations.RunPython(migrate_accounts), + migrations.RunPython(migrate_asset_accounts), + migrations.RunPython(migrate_db_accounts), ] From 211a0abe9e3d3eb9ac8cfc49fe3f773affc00daa Mon Sep 17 00:00:00 2001 From: jiangweidong Date: Thu, 19 Jan 2023 09:57:58 +0800 Subject: [PATCH 18/92] =?UTF-8?q?feat:=20=E6=B5=8B=E8=AF=95=E5=8F=AF?= =?UTF-8?q?=E8=BF=9E=E6=8E=A5=E6=80=A7mongodb=E6=94=AF=E6=8C=81ssl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../change_secret/database/mongodb/main.yml | 10 +++++++ .../verify_account/database/mongodb/main.yml | 5 ++++ .../gather_facts/database/mongodb/main.yml | 5 ++++ .../ping/database/mongodb/main.yml | 5 ++++ apps/ops/ansible/inventory.py | 26 +++++++++++++++++++ 5 files changed, 51 insertions(+) diff --git a/apps/accounts/automations/change_secret/database/mongodb/main.yml b/apps/accounts/automations/change_secret/database/mongodb/main.yml index 02a568e0b..7f0ae2c6e 100644 --- a/apps/accounts/automations/change_secret/database/mongodb/main.yml +++ b/apps/accounts/automations/change_secret/database/mongodb/main.yml @@ -11,6 +11,11 @@ login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" login_database: "{{ jms_asset.specific.db_name }}" + ssl: "{{ jms_asset.specific.use_ssl }}" + ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}" + ssl_certfile: "{{ jms_asset.specific.client_key }}" + connection_options: + - tlsAllowInvalidHostnames: "{{ jms_asset.specific.allow_invalid_cert}}" register: db_info - name: Display MongoDB version @@ -38,6 +43,11 @@ login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" login_database: "{{ jms_asset.specific.db_name }}" + ssl: "{{ jms_asset.specific.use_ssl }}" + ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}" + ssl_certfile: "{{ jms_asset.specific.client_key }}" + connection_options: + - tlsAllowInvalidHostnames: "{{ jms_asset.specific.allow_invalid_cert}}" when: - db_info is succeeded - change_info is succeeded diff --git a/apps/accounts/automations/verify_account/database/mongodb/main.yml b/apps/accounts/automations/verify_account/database/mongodb/main.yml index 1cf79b694..4467ead07 100644 --- a/apps/accounts/automations/verify_account/database/mongodb/main.yml +++ b/apps/accounts/automations/verify_account/database/mongodb/main.yml @@ -11,3 +11,8 @@ login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" login_database: "{{ jms_asset.specific.db_name }}" + ssl: "{{ jms_asset.specific.use_ssl }}" + ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}" + ssl_certfile: "{{ jms_asset.specific.client_key }}" + connection_options: + - tlsAllowInvalidHostnames: "{{ jms_asset.specific.allow_invalid_cert}}" diff --git a/apps/assets/automations/gather_facts/database/mongodb/main.yml b/apps/assets/automations/gather_facts/database/mongodb/main.yml index 37ce8bbd3..c94c82cd1 100644 --- a/apps/assets/automations/gather_facts/database/mongodb/main.yml +++ b/apps/assets/automations/gather_facts/database/mongodb/main.yml @@ -11,6 +11,11 @@ login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" login_database: "{{ jms_asset.specific.db_name }}" + ssl: "{{ jms_asset.specific.use_ssl }}" + ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}" + ssl_certfile: "{{ jms_asset.specific.client_key }}" + connection_options: + - tlsAllowInvalidHostnames: "{{ jms_asset.specific.allow_invalid_cert}}" register: db_info - name: Define info by set_fact diff --git a/apps/assets/automations/ping/database/mongodb/main.yml b/apps/assets/automations/ping/database/mongodb/main.yml index 867c51ace..c1e1ed496 100644 --- a/apps/assets/automations/ping/database/mongodb/main.yml +++ b/apps/assets/automations/ping/database/mongodb/main.yml @@ -11,3 +11,8 @@ login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" login_database: "{{ jms_asset.specific.db_name }}" + ssl: "{{ jms_asset.specific.use_ssl }}" + ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}" + ssl_certfile: "{{ jms_asset.specific.client_key }}" + connection_options: + - tlsAllowInvalidHostnames: "{{ jms_asset.specific.allow_invalid_cert}}" diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py index e50a0801f..6b0e528a5 100644 --- a/apps/ops/ansible/inventory.py +++ b/apps/ops/ansible/inventory.py @@ -98,6 +98,30 @@ class JMSInventory: if gateway: host.update(self.make_proxy_command(gateway)) + @staticmethod + def write_cert_to_file(filename, content): + if not content: + return '' + with open(filename, 'w') as f: + f.write(content) + return filename + + def convert_cert_to_file(self, host, path_dir): + specific = host.get('jms_asset', {}).get('specific') + if not specific: + return host + + cert_dir = os.path.join(path_dir, 'certs') + if not os.path.exists(cert_dir): + os.makedirs(cert_dir, 0o700, True) + + for i in ('ca_cert', 'client_key', 'client_cert'): + result = self.write_cert_to_file( + os.path.join(cert_dir, i), specific.get(i) + ) + host['jms_asset']['specific'][i] = result + return host + def asset_to_host(self, asset, account, automation, protocols, platform): host = { 'name': '{}'.format(asset.name), @@ -178,6 +202,8 @@ class JMSInventory: if not automation.ansible_enabled: host['error'] = _('Ansible disabled') + else: + host = self.convert_cert_to_file(host, path_dir) if self.host_callback is not None: host = self.host_callback( From 633e12bf86694ba57695bdff8dfdb46cabdeae15 Mon Sep 17 00:00:00 2001 From: jiangweidong Date: Thu, 19 Jan 2023 10:14:31 +0800 Subject: [PATCH 19/92] =?UTF-8?q?feat:=20=E5=85=B6=E4=BB=96mongodb?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=8C=96=E6=93=8D=E4=BD=9C=E6=94=AF=E6=8C=81?= =?UTF-8?q?ssl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../automations/change_secret/database/mongodb/main.yml | 5 +++++ .../automations/gather_accounts/database/mongodb/main.yml | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/apps/accounts/automations/change_secret/database/mongodb/main.yml b/apps/accounts/automations/change_secret/database/mongodb/main.yml index 7f0ae2c6e..517274263 100644 --- a/apps/accounts/automations/change_secret/database/mongodb/main.yml +++ b/apps/accounts/automations/change_secret/database/mongodb/main.yml @@ -30,6 +30,11 @@ login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" login_database: "{{ jms_asset.specific.db_name }}" + ssl: "{{ jms_asset.specific.use_ssl }}" + ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}" + ssl_certfile: "{{ jms_asset.specific.client_key }}" + connection_options: + - tlsAllowInvalidHostnames: "{{ jms_asset.specific.allow_invalid_cert}}" db: "{{ jms_asset.specific.db_name }}" name: "{{ account.username }}" password: "{{ account.secret }}" diff --git a/apps/accounts/automations/gather_accounts/database/mongodb/main.yml b/apps/accounts/automations/gather_accounts/database/mongodb/main.yml index fd7a296b7..d2478d7b5 100644 --- a/apps/accounts/automations/gather_accounts/database/mongodb/main.yml +++ b/apps/accounts/automations/gather_accounts/database/mongodb/main.yml @@ -11,6 +11,11 @@ login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" login_database: "{{ jms_asset.specific.db_name }}" + ssl: "{{ jms_asset.specific.use_ssl }}" + ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}" + ssl_certfile: "{{ jms_asset.specific.client_key }}" + connection_options: + - tlsAllowInvalidHostnames: "{{ jms_asset.specific.allow_invalid_cert}}" filter: users register: db_info From 6cda829f673867b7efd92bb09d4bc229d4cbf90e Mon Sep 17 00:00:00 2001 From: jiangweidong Date: Thu, 19 Jan 2023 10:36:27 +0800 Subject: [PATCH 20/92] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E8=AF=81=E4=B9=A6=E6=96=87=E4=BB=B6=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/ansible/inventory.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py index 6b0e528a5..084c1e733 100644 --- a/apps/ops/ansible/inventory.py +++ b/apps/ops/ansible/inventory.py @@ -100,26 +100,26 @@ class JMSInventory: @staticmethod def write_cert_to_file(filename, content): - if not content: - return '' with open(filename, 'w') as f: f.write(content) return filename def convert_cert_to_file(self, host, path_dir): - specific = host.get('jms_asset', {}).get('specific') - if not specific: + specific = host.get('jms_asset', {}).get('specific', {}) + cert_fields = ('ca_cert', 'client_key', 'client_cert') + filtered = list(filter(lambda x: specific.get(x), cert_fields)) + if not filtered: return host cert_dir = os.path.join(path_dir, 'certs') if not os.path.exists(cert_dir): os.makedirs(cert_dir, 0o700, True) - for i in ('ca_cert', 'client_key', 'client_cert'): + for f in filtered: result = self.write_cert_to_file( - os.path.join(cert_dir, i), specific.get(i) + os.path.join(cert_dir, f), specific.get(f) ) - host['jms_asset']['specific'][i] = result + host['jms_asset']['specific'][f] = result return host def asset_to_host(self, asset, account, automation, protocols, platform): From be670872e58b5e295156accdac0f3b846129e150 Mon Sep 17 00:00:00 2001 From: jiangweidong Date: Sun, 29 Jan 2023 16:25:16 +0800 Subject: [PATCH 21/92] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=8C=E5=B0=86=E8=AF=81=E4=B9=A6=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E8=BD=AC=E6=8D=A2=E6=94=BE=E5=88=B0manager=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../change_secret/database/mongodb/main.yml | 8 ++--- .../automations/change_secret/manager.py | 10 +++++-- .../gather_accounts/database/mongodb/main.yml | 8 ++--- apps/assets/automations/base/manager.py | 29 +++++++++++++++++++ apps/ops/ansible/inventory.py | 26 ----------------- 5 files changed, 45 insertions(+), 36 deletions(-) diff --git a/apps/accounts/automations/change_secret/database/mongodb/main.yml b/apps/accounts/automations/change_secret/database/mongodb/main.yml index 517274263..c64ad7c4c 100644 --- a/apps/accounts/automations/change_secret/database/mongodb/main.yml +++ b/apps/accounts/automations/change_secret/database/mongodb/main.yml @@ -31,10 +31,10 @@ login_port: "{{ jms_asset.port }}" login_database: "{{ jms_asset.specific.db_name }}" ssl: "{{ jms_asset.specific.use_ssl }}" - ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}" - ssl_certfile: "{{ jms_asset.specific.client_key }}" - connection_options: - - tlsAllowInvalidHostnames: "{{ jms_asset.specific.allow_invalid_cert}}" + ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}" + ssl_certfile: "{{ jms_asset.specific.client_key }}" + connection_options: + - tlsAllowInvalidHostnames: "{{ jms_asset.specific.allow_invalid_cert}}" db: "{{ jms_asset.specific.db_name }}" name: "{{ account.username }}" password: "{{ account.secret }}" diff --git a/apps/accounts/automations/change_secret/manager.py b/apps/accounts/automations/change_secret/manager.py index 4360a9311..41b0a4844 100644 --- a/apps/accounts/automations/change_secret/manager.py +++ b/apps/accounts/automations/change_secret/manager.py @@ -70,8 +70,14 @@ class ChangeSecretManager(AccountBasePlaybookManager): else: return self.secret_generator.get_secret() - def host_callback(self, host, asset=None, account=None, automation=None, path_dir=None, **kwargs): - host = super().host_callback(host, asset=asset, account=account, automation=automation, **kwargs) + def host_callback( + self, host, asset=None, account=None, + automation=None, path_dir=None, **kwargs + ): + host = super().host_callback( + host, asset=asset, account=account, automation=automation, + path_dir=path_dir, **kwargs + ) if host.get('error'): return host diff --git a/apps/accounts/automations/gather_accounts/database/mongodb/main.yml b/apps/accounts/automations/gather_accounts/database/mongodb/main.yml index d2478d7b5..c4d6c4ee3 100644 --- a/apps/accounts/automations/gather_accounts/database/mongodb/main.yml +++ b/apps/accounts/automations/gather_accounts/database/mongodb/main.yml @@ -12,10 +12,10 @@ login_port: "{{ jms_asset.port }}" login_database: "{{ jms_asset.specific.db_name }}" ssl: "{{ jms_asset.specific.use_ssl }}" - ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}" - ssl_certfile: "{{ jms_asset.specific.client_key }}" - connection_options: - - tlsAllowInvalidHostnames: "{{ jms_asset.specific.allow_invalid_cert}}" + ssl_ca_certs: "{{ jms_asset.specific.ca_cert }}" + ssl_certfile: "{{ jms_asset.specific.client_key }}" + connection_options: + - tlsAllowInvalidHostnames: "{{ jms_asset.specific.allow_invalid_cert}}" filter: users register: db_info diff --git a/apps/assets/automations/base/manager.py b/apps/assets/automations/base/manager.py index 50a5160e2..f9d06bb73 100644 --- a/apps/assets/automations/base/manager.py +++ b/apps/assets/automations/base/manager.py @@ -63,6 +63,33 @@ class BasePlaybookManager: os.makedirs(path, exist_ok=True, mode=0o755) return path + @staticmethod + def write_cert_to_file(filename, content): + with open(filename, 'w') as f: + f.write(content) + return filename + + def convert_cert_to_file(self, host, path_dir): + if not path_dir: + return host + + specific = host.get('jms_asset', {}).get('specific', {}) + cert_fields = ('ca_cert', 'client_key', 'client_cert') + filtered = list(filter(lambda x: specific.get(x), cert_fields)) + if not filtered: + return host + + cert_dir = os.path.join(path_dir, 'certs') + if not os.path.exists(cert_dir): + os.makedirs(cert_dir, 0o700, True) + + for f in filtered: + result = self.write_cert_to_file( + os.path.join(cert_dir, f), specific.get(f) + ) + host['jms_asset']['specific'][f] = result + return host + def host_callback(self, host, automation=None, **kwargs): enabled_attr = '{}_enabled'.format(self.__class__.method_type()) method_attr = '{}_method'.format(self.__class__.method_type()) @@ -75,6 +102,8 @@ class BasePlaybookManager: if not method_enabled: host['error'] = _('{} disabled'.format(self.__class__.method_type())) return host + + host = self.convert_cert_to_file(host, kwargs.get('path_dir')) return host @staticmethod diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py index 084c1e733..e50a0801f 100644 --- a/apps/ops/ansible/inventory.py +++ b/apps/ops/ansible/inventory.py @@ -98,30 +98,6 @@ class JMSInventory: if gateway: host.update(self.make_proxy_command(gateway)) - @staticmethod - def write_cert_to_file(filename, content): - with open(filename, 'w') as f: - f.write(content) - return filename - - def convert_cert_to_file(self, host, path_dir): - specific = host.get('jms_asset', {}).get('specific', {}) - cert_fields = ('ca_cert', 'client_key', 'client_cert') - filtered = list(filter(lambda x: specific.get(x), cert_fields)) - if not filtered: - return host - - cert_dir = os.path.join(path_dir, 'certs') - if not os.path.exists(cert_dir): - os.makedirs(cert_dir, 0o700, True) - - for f in filtered: - result = self.write_cert_to_file( - os.path.join(cert_dir, f), specific.get(f) - ) - host['jms_asset']['specific'][f] = result - return host - def asset_to_host(self, asset, account, automation, protocols, platform): host = { 'name': '{}'.format(asset.name), @@ -202,8 +178,6 @@ class JMSInventory: if not automation.ansible_enabled: host['error'] = _('Ansible disabled') - else: - host = self.convert_cert_to_file(host, path_dir) if self.host_callback is not None: host = self.host_callback( From 03c0d2edbd6c30895543df31d0ae34e43a9836ff Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 31 Jan 2023 18:51:04 +0800 Subject: [PATCH 22/92] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20connectivity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/automations/verify_account/manager.py | 4 ++-- apps/assets/automations/ping/manager.py | 6 +++--- apps/assets/automations/ping_gateway/manager.py | 10 +++++----- apps/assets/const/automation.py | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/accounts/automations/verify_account/manager.py b/apps/accounts/automations/verify_account/manager.py index 12c247849..fc25794bf 100644 --- a/apps/accounts/automations/verify_account/manager.py +++ b/apps/accounts/automations/verify_account/manager.py @@ -1,7 +1,7 @@ from django.db.models import QuerySet -from common.utils import get_logger from accounts.const import AutomationTypes, Connectivity +from common.utils import get_logger from ..base.manager import PushOrVerifyHostCallbackMixin, AccountBasePlaybookManager logger = get_logger(__name__) @@ -29,4 +29,4 @@ class VerifyAccountManager(PushOrVerifyHostCallbackMixin, AccountBasePlaybookMan def on_host_error(self, host, error, result): account = self.host_account_mapper.get(host) - account.set_connectivity(Connectivity.FAILED) + account.set_connectivity(Connectivity.ERR) diff --git a/apps/assets/automations/ping/manager.py b/apps/assets/automations/ping/manager.py index 305771f0b..0f166d0ad 100644 --- a/apps/assets/automations/ping/manager.py +++ b/apps/assets/automations/ping/manager.py @@ -1,5 +1,5 @@ -from common.utils import get_logger from assets.const import AutomationTypes, Connectivity +from common.utils import get_logger from ..base.manager import BasePlaybookManager logger = get_logger(__name__) @@ -28,7 +28,7 @@ class PingManager(BasePlaybookManager): def on_host_error(self, host, error, result): asset, account = self.host_asset_and_account_mapper.get(host) - asset.set_connectivity(Connectivity.FAILED) + asset.set_connectivity(Connectivity.ERR) if not account: return - account.set_connectivity(Connectivity.FAILED) + account.set_connectivity(Connectivity.ERR) diff --git a/apps/assets/automations/ping_gateway/manager.py b/apps/assets/automations/ping_gateway/manager.py index 5ffbc2734..858717665 100644 --- a/apps/assets/automations/ping_gateway/manager.py +++ b/apps/assets/automations/ping_gateway/manager.py @@ -1,12 +1,12 @@ import socket -import paramiko +import paramiko from django.utils import timezone from django.utils.translation import ugettext_lazy as _ -from common.utils import get_logger -from assets.models import Gateway from assets.const import AutomationTypes, Connectivity +from assets.models import Gateway +from common.utils import get_logger logger = get_logger(__name__) @@ -100,10 +100,10 @@ class PingGatewayManager: @staticmethod def on_host_error(gateway, account, error): logger.info('\033[31m {} -> {} 原因: {} \033[0m\n'.format(gateway, account, error)) - gateway.set_connectivity(Connectivity.FAILED) + gateway.set_connectivity(Connectivity.ERR) if not account: return - account.set_connectivity(Connectivity.FAILED) + account.set_connectivity(Connectivity.ERR) @staticmethod def before_runner_start(): diff --git a/apps/assets/const/automation.py b/apps/assets/const/automation.py index a811cb50b..831b11b66 100644 --- a/apps/assets/const/automation.py +++ b/apps/assets/const/automation.py @@ -3,9 +3,9 @@ from django.utils.translation import ugettext_lazy as _ class Connectivity(TextChoices): - UNKNOWN = 'unknown', _('Unknown') + UNKNOWN = '-', _('Unknown') OK = 'ok', _('Ok') - FAILED = 'failed', _('Failed') + ERR = 'err', _('Error') class AutomationTypes(TextChoices): From 6bbb1f7e86d2d3d7ffb549cb9442a5bbb7c64efb Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 31 Jan 2023 19:02:24 +0800 Subject: [PATCH 23/92] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20connectivity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/migrations/0075_auto_20210705_1759.py | 6 +++--- apps/assets/migrations/0097_auto_20220426_1558.py | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/apps/assets/migrations/0075_auto_20210705_1759.py b/apps/assets/migrations/0075_auto_20210705_1759.py index 84e970075..686d61bf0 100644 --- a/apps/assets/migrations/0075_auto_20210705_1759.py +++ b/apps/assets/migrations/0075_auto_20210705_1759.py @@ -13,7 +13,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='asset', name='connectivity', - field=models.CharField(choices=[('unknown', 'Unknown'), ('ok', 'Ok'), ('failed', 'Failed')], default='unknown', max_length=16, verbose_name='Connectivity'), + field=models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity'), ), migrations.AddField( model_name='asset', @@ -23,7 +23,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='authbook', name='connectivity', - field=models.CharField(choices=[('unknown', 'Unknown'), ('ok', 'Ok'), ('failed', 'Failed')], default='unknown', max_length=16, verbose_name='Connectivity'), + field=models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity'), ), migrations.AddField( model_name='authbook', @@ -33,7 +33,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='historicalauthbook', name='connectivity', - field=models.CharField(choices=[('unknown', 'Unknown'), ('ok', 'Ok'), ('failed', 'Failed')], default='unknown', max_length=16, verbose_name='Connectivity'), + field=models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity'), ), migrations.AddField( model_name='historicalauthbook', diff --git a/apps/assets/migrations/0097_auto_20220426_1558.py b/apps/assets/migrations/0097_auto_20220426_1558.py index ec7f64084..2a16841d5 100644 --- a/apps/assets/migrations/0097_auto_20220426_1558.py +++ b/apps/assets/migrations/0097_auto_20220426_1558.py @@ -34,6 +34,13 @@ def migrate_macos_platform(apps, schema_editor): platform_model.objects.using(db_alias).filter(id=old_macos.id).delete() +def migrate_connectivity(apps, schema_editor): + db_alias = schema_editor.connection.alias + asset_model = apps.get_model('assets', 'Asset') + asset_model.objects.using(db_alias).filter(connectivity='unknown').update(connectivity='-') + asset_model.objects.using(db_alias).filter(connectivity='failed').update(connectivity='err') + + class Migration(migrations.Migration): dependencies = [ ('assets', '0096_auto_20220426_1550'), @@ -43,4 +50,5 @@ class Migration(migrations.Migration): migrations.RunPython(create_internal_platforms), migrations.RunPython(update_user_platforms), migrations.RunPython(migrate_macos_platform), + migrations.RunPython(migrate_connectivity), ] From ae1b134f70516677d1f00c2abd3827f307dbce25 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 31 Jan 2023 19:30:38 +0800 Subject: [PATCH 24/92] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20spec=20for?= =?UTF-8?q?=20cert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../change_secret/database/mongodb/main.yml | 12 ++++++------ .../gather_accounts/database/mongodb/main.yml | 4 ++-- .../verify_account/database/mongodb/main.yml | 4 ++-- .../gather_facts/database/mongodb/main.yml | 4 ++-- .../automations/ping/database/mongodb/main.yml | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/apps/accounts/automations/change_secret/database/mongodb/main.yml b/apps/accounts/automations/change_secret/database/mongodb/main.yml index 880234c4f..42ccd78ea 100644 --- a/apps/accounts/automations/change_secret/database/mongodb/main.yml +++ b/apps/accounts/automations/change_secret/database/mongodb/main.yml @@ -12,8 +12,8 @@ login_port: "{{ jms_asset.port }}" login_database: "{{ jms_asset.spec_info.db_name }}" ssl: "{{ jms_asset.spec_info.use_ssl }}" - ssl_ca_certs: "{{ jms_asset.spec_info.ca_cert }}" - ssl_certfile: "{{ jms_asset.spec_info.client_key }}" + ssl_ca_certs: "{{ jms_asset.secret_info.ca_cert }}" + ssl_certfile: "{{ jms_asset.secret_info.client_key }}" connection_options: - tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}" register: db_info @@ -31,8 +31,8 @@ login_port: "{{ jms_asset.port }}" login_database: "{{ jms_asset.spec_info.db_name }}" ssl: "{{ jms_asset.spec_info.use_ssl }}" - ssl_ca_certs: "{{ jms_asset.spec_info.ca_cert }}" - ssl_certfile: "{{ jms_asset.spec_info.client_key }}" + ssl_ca_certs: "{{ jms_asset.secret_info.ca_cert }}" + ssl_certfile: "{{ jms_asset.secret_info.client_key }}" connection_options: - tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}" db: "{{ jms_asset.spec_info.db_name }}" @@ -49,8 +49,8 @@ login_port: "{{ jms_asset.port }}" login_database: "{{ jms_asset.spec_info.db_name }}" ssl: "{{ jms_asset.spec_info.use_ssl }}" - ssl_ca_certs: "{{ jms_asset.spec_info.ca_cert }}" - ssl_certfile: "{{ jms_asset.spec_info.client_key }}" + ssl_ca_certs: "{{ jms_asset.secret_info.ca_cert }}" + ssl_certfile: "{{ jms_asset.secret_info.client_key }}" connection_options: - tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}" when: diff --git a/apps/accounts/automations/gather_accounts/database/mongodb/main.yml b/apps/accounts/automations/gather_accounts/database/mongodb/main.yml index 1ec0a3af0..452241f6a 100644 --- a/apps/accounts/automations/gather_accounts/database/mongodb/main.yml +++ b/apps/accounts/automations/gather_accounts/database/mongodb/main.yml @@ -12,8 +12,8 @@ login_port: "{{ jms_asset.port }}" login_database: "{{ jms_asset.spec_info.db_name }}" ssl: "{{ jms_asset.spec_info.use_ssl }}" - ssl_ca_certs: "{{ jms_asset.spec_info.ca_cert }}" - ssl_certfile: "{{ jms_asset.spec_info.client_key }}" + ssl_ca_certs: "{{ jms_asset.secret_info.ca_cert }}" + ssl_certfile: "{{ jms_asset.secret_info.client_key }}" connection_options: - tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}" filter: users diff --git a/apps/accounts/automations/verify_account/database/mongodb/main.yml b/apps/accounts/automations/verify_account/database/mongodb/main.yml index ec974f160..261fe63ca 100644 --- a/apps/accounts/automations/verify_account/database/mongodb/main.yml +++ b/apps/accounts/automations/verify_account/database/mongodb/main.yml @@ -12,7 +12,7 @@ login_port: "{{ jms_asset.port }}" login_database: "{{ jms_asset.spec_info.db_name }}" ssl: "{{ jms_asset.spec_info.use_ssl }}" - ssl_ca_certs: "{{ jms_asset.spec_info.ca_cert }}" - ssl_certfile: "{{ jms_asset.spec_info.client_key }}" + ssl_ca_certs: "{{ jms_asset.secret_info.ca_cert }}" + ssl_certfile: "{{ jms_asset.secret_info.client_key }}" connection_options: - tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}" diff --git a/apps/assets/automations/gather_facts/database/mongodb/main.yml b/apps/assets/automations/gather_facts/database/mongodb/main.yml index 1b5602308..084a27348 100644 --- a/apps/assets/automations/gather_facts/database/mongodb/main.yml +++ b/apps/assets/automations/gather_facts/database/mongodb/main.yml @@ -12,8 +12,8 @@ login_port: "{{ jms_asset.port }}" login_database: "{{ jms_asset.spec_info.db_name }}" ssl: "{{ jms_asset.spec_info.use_ssl }}" - ssl_ca_certs: "{{ jms_asset.spec_info.ca_cert }}" - ssl_certfile: "{{ jms_asset.spec_info.client_key }}" + ssl_ca_certs: "{{ jms_asset.secret_info.ca_cert }}" + ssl_certfile: "{{ jms_asset.secret_info.client_key }}" connection_options: - tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}" register: db_info diff --git a/apps/assets/automations/ping/database/mongodb/main.yml b/apps/assets/automations/ping/database/mongodb/main.yml index adf42b2fa..23a06c08d 100644 --- a/apps/assets/automations/ping/database/mongodb/main.yml +++ b/apps/assets/automations/ping/database/mongodb/main.yml @@ -12,7 +12,7 @@ login_port: "{{ jms_asset.port }}" login_database: "{{ jms_asset.spec_info.db_name }}" ssl: "{{ jms_asset.spec_info.use_ssl }}" - ssl_ca_certs: "{{ jms_asset.spec_info.ca_cert }}" - ssl_certfile: "{{ jms_asset.spec_info.client_key }}" + ssl_ca_certs: "{{ jms_asset.secret_info.ca_cert }}" + ssl_certfile: "{{ jms_asset.secret_info.client_key }}" connection_options: - tlsAllowInvalidHostnames: "{{ jms_asset.spec_info.allow_invalid_cert}}" From 34b740583e90a51d1b1d728eaf9d1057bf939244 Mon Sep 17 00:00:00 2001 From: ibuler Date: Tue, 31 Jan 2023 19:37:16 +0800 Subject: [PATCH 25/92] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20asset=20info?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/migrations/0001_initial.py | 3 +-- apps/assets/migrations/0106_auto_20221228_1838.py | 6 +----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/apps/accounts/migrations/0001_initial.py b/apps/accounts/migrations/0001_initial.py index 201a5141d..6e211a7fc 100644 --- a/apps/accounts/migrations/0001_initial.py +++ b/apps/accounts/migrations/0001_initial.py @@ -29,8 +29,7 @@ class Migration(migrations.Migration): ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), ('org_id', models.CharField(blank=True, db_index=True, default='', max_length=36, verbose_name='Organization')), - ('connectivity', models.CharField(choices=[('unknown', 'Unknown'), ('ok', 'Ok'), ('failed', 'Failed')], - default='unknown', max_length=16, verbose_name='Connectivity')), + ('connectivity', models.CharField(choices=[('-', 'Unknown'), ('ok', 'Ok'), ('err', 'Error')], default='-', max_length=16, verbose_name='Connectivity')), ('date_verified', models.DateTimeField(null=True, verbose_name='Date verified')), ('name', models.CharField(max_length=128, verbose_name='Name')), ('username', models.CharField(blank=True, db_index=True, max_length=128, verbose_name='Username')), diff --git a/apps/assets/migrations/0106_auto_20221228_1838.py b/apps/assets/migrations/0106_auto_20221228_1838.py index 9637bbd1d..ce7718ccd 100644 --- a/apps/assets/migrations/0106_auto_20221228_1838.py +++ b/apps/assets/migrations/0106_auto_20221228_1838.py @@ -52,11 +52,7 @@ class Migration(migrations.Migration): migrations.AlterModelOptions( name='asset', options={'ordering': ['name'], - 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), - ('test_assetconnectivity', 'Can test asset connectivity'), - ('push_assetaccount', 'Can push account to asset'), - ('match_asset', 'Can match asset'), ('add_assettonode', 'Add asset to node'), - ('move_assettonode', 'Move asset to node')], 'verbose_name': 'Asset'}, + 'permissions': [('refresh_assethardwareinfo', 'Can refresh asset hardware info'), ('test_assetconnectivity', 'Can test asset connectivity'), ('push_assetaccount', 'Can push account to asset'), ('test_account', 'Can verify account'), ('match_asset', 'Can match asset'), ('add_assettonode', 'Add asset to node'), ('move_assettonode', 'Move asset to node')], 'verbose_name': 'Asset'}, ), migrations.AlterUniqueTogether( name='accountbackupplan', From 142edd9438bb21f13db05c0636dadc4d29cea355 Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 1 Feb 2023 10:27:12 +0800 Subject: [PATCH 26/92] perf: update applet download and deployment --- apps/templates/resource_download.html | 22 +++++++------------ apps/terminal/applets/chrome/common.py | 2 +- apps/terminal/applets/navicat/common.py | 10 ++++----- .../deploy_applet_host/playbook.yml | 14 +++++++++++- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/apps/templates/resource_download.html b/apps/templates/resource_download.html index df0577307..14a7b30c2 100644 --- a/apps/templates/resource_download.html +++ b/apps/templates/resource_download.html @@ -20,10 +20,10 @@ p { {% trans 'JumpServer Client, currently used to launch the client, now only support launch RDP SSH client, The Telnet client will next' %}

@@ -33,7 +33,7 @@ p { {% trans 'macOS needs to download the client to connect RDP asset, which comes with Windows' %}

@@ -42,22 +42,16 @@ p {

{% trans 'Windows Remote application publisher tools' %}

{% trans 'OpenSSH is a program used to connect remote applications in the Windows Remote Application Publisher' %}

- {% if XPACK_ENABLED %} -

{% trans 'Jmservisor is the program used to pull up remote applications in Windows Remote Application publisher' %}

- - {% endif %} diff --git a/apps/terminal/applets/chrome/common.py b/apps/terminal/applets/chrome/common.py index 4bffa5081..dbac3a22b 100644 --- a/apps/terminal/applets/chrome/common.py +++ b/apps/terminal/applets/chrome/common.py @@ -129,7 +129,7 @@ class Asset(DictObj): address: str protocols: list[Protocol] category: Category - specific: Specific + spec_info: Specific def get_protocol_port(self, protocol): for item in self.protocols: diff --git a/apps/terminal/applets/navicat/common.py b/apps/terminal/applets/navicat/common.py index f1e6429de..1802c8d86 100644 --- a/apps/terminal/applets/navicat/common.py +++ b/apps/terminal/applets/navicat/common.py @@ -1,11 +1,11 @@ import abc -import subprocess +import base64 +import json import locale +import os +import subprocess import sys import time -import os -import json -import base64 from subprocess import CREATE_NO_WINDOW _blockInput = None @@ -125,7 +125,7 @@ class Asset(DictObj): address: str protocols: list[Protocol] category: Category - specific: Specific + spec_info: Specific def get_protocol_port(self, protocol): for item in self.protocols: diff --git a/apps/terminal/automations/deploy_applet_host/playbook.yml b/apps/terminal/automations/deploy_applet_host/playbook.yml index 3d86ea52a..763df39a8 100644 --- a/apps/terminal/automations/deploy_applet_host/playbook.yml +++ b/apps/terminal/automations/deploy_applet_host/playbook.yml @@ -13,7 +13,7 @@ RDS_fSingleSessionPerUser: 1 RDS_MaxDisconnectionTime: 60000 RDS_RemoteAppLogoffTimeLimit: 0 - TinkerInstaller: Tinker_Installer_v0.0.1.exe + TinkerInstaller: Tinker_Installer.exe tasks: - name: Install RDS-Licensing (RDS) @@ -151,6 +151,18 @@ state: present arguments: - /quiet + - + - name: Download navicat161_premium_en package (navicat) + ansible.windows.win_get_url: + url: "{{ APPLET_DOWNLOAD_HOST }}/download/applets/navicat161_premium_en_x64.exe" + dest: "{{ ansible_env.TEMP }}\\navicat161_premium_en_x64.exe" + + - name: Install navicat (navicat) + ansible.windows.win_package: + path: "{{ ansible_env.TEMP }}\\navicat161_premium_en_x64.exe" + state: present + arguments: + - /SILENT - name: Generate tinkerd component config ansible.windows.win_shell: From 4956e1147ec38a4cad6c7a6cfc94f4658c7732c0 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 1 Feb 2023 11:26:57 +0800 Subject: [PATCH 27/92] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=88=9B=E5=BB=BA=20=E8=A7=92=E8=89=B2=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/users/serializers/user.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/apps/users/serializers/user.py b/apps/users/serializers/user.py index 7baa4117b..7e2c6ea33 100644 --- a/apps/users/serializers/user.py +++ b/apps/users/serializers/user.py @@ -5,8 +5,8 @@ from functools import partial from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers -from common.serializers.fields import EncryptedField, ObjectRelatedField, LabeledChoiceField from common.serializers import CommonBulkSerializerMixin +from common.serializers.fields import EncryptedField, ObjectRelatedField, LabeledChoiceField from common.utils import pretty_string, get_logger from common.validators import PhoneValidator from rbac.builtin import BuiltinRole @@ -25,24 +25,25 @@ __all__ = [ logger = get_logger(__file__) +def default_system_roles(): + return [BuiltinRole.system_user.get_role()] + + +def default_org_roles(): + return [BuiltinRole.org_user.get_role()] + + class RolesSerializerMixin(serializers.Serializer): system_roles = ObjectRelatedField( queryset=Role.system_roles, attrs=('id', 'display_name'), - label=_("System roles"), many=True + label=_("System roles"), many=True, default=default_system_roles ) org_roles = ObjectRelatedField( queryset=Role.org_roles, attrs=('id', 'display_name'), - label=_("Org roles"), many=True + label=_("Org roles"), many=True, required=False, + default=default_org_roles ) - @staticmethod - def get_system_roles_display(user): - return user.system_roles.display - - @staticmethod - def get_org_roles_display(user): - return user.org_roles.display - def pop_roles_if_need(self, fields): request = self.context.get("request") view = self.context.get("view") @@ -55,6 +56,7 @@ class RolesSerializerMixin(serializers.Serializer): action = view.action or "list" if action in ("partial_bulk_update", "bulk_update", "partial_update", "update"): action = "create" + model_cls_field_mapper = { SystemRoleBinding: ["system_roles"], OrgRoleBinding: ["org_roles"], From 023ca297527aa676eb4624ac268c75395ab1b2ba Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 1 Feb 2023 12:39:38 +0800 Subject: [PATCH 28/92] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E5=88=9B=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/audits/utils.py | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/apps/audits/utils.py b/apps/audits/utils.py index 6f8f9e730..3ff42177c 100644 --- a/apps/audits/utils.py +++ b/apps/audits/utils.py @@ -1,17 +1,14 @@ -import csv import codecs - +import csv from itertools import chain -from django.http import HttpResponse from django.db import models +from django.http import HttpResponse -from settings.serializers import SettingsSerializer from common.utils import validate_ip, get_ip_city, get_logger -from common.db import fields +from settings.serializers import SettingsSerializer from .const import DEFAULT_CITY - logger = get_logger(__name__) @@ -95,7 +92,7 @@ def _get_instance_field_value( def model_to_dict_for_operate_log( - instance, include_model_fields=True, include_related_fields=True + instance, include_model_fields=True, include_related_fields=False ): model_need_continue_fields = ['date_updated'] m2m_need_continue_fields = ['history_passwords'] @@ -106,7 +103,7 @@ def model_to_dict_for_operate_log( if include_related_fields: opts = instance._meta - for f in chain(opts.many_to_many, opts.related_objects): + for f in opts.many_to_many: value = [] if instance.pk is not None: related_name = getattr(f, 'attname', '') or getattr(f, 'related_name', '') From 66c58a2084b4b97676737777e4b8218135a6f10b Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 1 Feb 2023 14:43:58 +0800 Subject: [PATCH 29/92] =?UTF-8?q?perf:=20=E8=B4=A6=E5=8F=B7=20=E6=A8=A1?= =?UTF-8?q?=E7=89=88=E5=88=9B=E5=BB=BA=20(#9386)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng <1304903146@qq.com> --- apps/accounts/serializers/account/account.py | 73 +++++++++----------- apps/assets/serializers/asset/common.py | 32 ++------- 2 files changed, 36 insertions(+), 69 deletions(-) diff --git a/apps/accounts/serializers/account/account.py b/apps/accounts/serializers/account/account.py index 702762be9..a834756f0 100644 --- a/apps/accounts/serializers/account/account.py +++ b/apps/accounts/serializers/account/account.py @@ -11,53 +11,32 @@ from .base import BaseAccountSerializer class AccountSerializerCreateValidateMixin: - replace_attrs: callable + id: str + template: bool push_now: bool + replace_attrs: callable - def validate(self, attrs): - _id = attrs.pop('id', None) - if _id: + def to_internal_value(self, data): + self.id = data.pop('id', None) + self.push_now = data.pop('push_now', False) + self.template = data.pop('template', False) + return super().to_internal_value(data) + + def set_secret(self, attrs): + _id = self.id + template = self.template + + if _id and template: account_template = AccountTemplate.objects.get(id=_id) attrs['secret'] = account_template.secret - account_template = attrs.pop('template', None) - if account_template: - self.replace_attrs(account_template, attrs) - self.push_now = attrs.pop('push_now', False) + elif _id and not template: + account = Account.objects.get(id=_id) + attrs['secret'] = account.secret + + def validate(self, attrs): + self.set_secret(attrs) return super().validate(attrs) - -class AccountSerializerCreateMixin( - AccountSerializerCreateValidateMixin, BulkModelSerializer -): - template = serializers.UUIDField( - required=False, allow_null=True, write_only=True, - label=_('Account template') - ) - push_now = serializers.BooleanField( - default=False, label=_("Push now"), write_only=True - ) - has_secret = serializers.BooleanField(label=_("Has secret"), read_only=True) - - @staticmethod - def validate_template(value): - try: - return AccountTemplate.objects.get(id=value) - except AccountTemplate.DoesNotExist: - raise serializers.ValidationError(_('Account template not found')) - - @staticmethod - def replace_attrs(account_template: AccountTemplate, attrs: dict): - exclude_fields = [ - '_state', 'org_id', 'id', 'date_created', - 'date_updated' - ] - template_attrs = { - k: v for k, v in account_template.__dict__.items() - if k not in exclude_fields - } - for k, v in template_attrs.items(): - attrs.setdefault(k, v) - def create(self, validated_data): instance = super().create(validated_data) if self.push_now: @@ -65,6 +44,18 @@ class AccountSerializerCreateMixin( return instance +class AccountSerializerCreateMixin( + AccountSerializerCreateValidateMixin, BulkModelSerializer +): + template = serializers.BooleanField( + default=False, label=_("Template"), write_only=True + ) + push_now = serializers.BooleanField( + default=False, label=_("Push now"), write_only=True + ) + has_secret = serializers.BooleanField(label=_("Has secret"), read_only=True) + + class AccountAssetSerializer(serializers.ModelSerializer): platform = ObjectRelatedField(read_only=True) diff --git a/apps/assets/serializers/asset/common.py b/apps/assets/serializers/asset/common.py index 47c866603..7f39e2378 100644 --- a/apps/assets/serializers/asset/common.py +++ b/apps/assets/serializers/asset/common.py @@ -54,6 +54,9 @@ class AssetAccountSerializer( push_now = serializers.BooleanField( default=False, label=_("Push now"), write_only=True ) + template = serializers.BooleanField( + default=False, label=_("Template"), write_only=True + ) class Meta: model = Account @@ -62,7 +65,7 @@ class AssetAccountSerializer( 'version', 'secret_type', ] fields_write_only = [ - 'secret', 'push_now' + 'secret', 'push_now', 'template' ] fields = fields_mini + fields_write_only extra_kwargs = { @@ -74,33 +77,6 @@ class AssetAccountSerializer( value = self.initial_data.get('username') return value - @staticmethod - def validate_template(value): - try: - return AccountTemplate.objects.get(id=value) - except AccountTemplate.DoesNotExist: - raise serializers.ValidationError(_('Account template not found')) - - @staticmethod - def replace_attrs(account_template: AccountTemplate, attrs: dict): - exclude_fields = [ - '_state', 'org_id', 'id', 'date_created', - 'date_updated' - ] - template_attrs = { - k: v for k, v in account_template.__dict__.items() - if k not in exclude_fields - } - for k, v in template_attrs.items(): - attrs.setdefault(k, v) - - def create(self, validated_data): - from accounts.tasks import push_accounts_to_assets - instance = super().create(validated_data) - if self.push_now: - push_accounts_to_assets.delay([instance.id], [instance.asset_id]) - return instance - class AccountSecretSerializer(SecretReadableMixin, CommonModelSerializer): class Meta: From acab0b765cbfbce8f14b2ec4e03967dc0a83da1f Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 1 Feb 2023 14:58:49 +0800 Subject: [PATCH 30/92] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=88=9B?= =?UTF-8?q?=E5=BB=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/audits/signal_handlers.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/audits/signal_handlers.py b/apps/audits/signal_handlers.py index 8cc396496..d5da3d1f7 100644 --- a/apps/audits/signal_handlers.py +++ b/apps/audits/signal_handlers.py @@ -121,8 +121,7 @@ def signal_of_operate_log_whether_continue(sender, instance, created, update_fie if instance._meta.object_name == 'Terminal' and created: condition = False # last_login 改变是最后登录日期, 每次登录都会改变 - if instance._meta.object_name == 'User' and \ - update_fields and 'last_login' in update_fields: + if instance._meta.object_name == 'User' and update_fields and 'last_login' in update_fields: condition = False # 不在记录白名单中,跳过 if sender._meta.object_name not in MODELS_NEED_RECORD: @@ -137,8 +136,10 @@ def on_object_pre_create_or_update(sender, instance=None, raw=False, using=None, ) if not ok: return - instance_before_data = {'id': instance.id} - raw_instance = type(instance).objects.filter(pk=instance.id).first() + # users.PrivateToken Model 没有 id 有 pk字段 + instance_id = getattr(instance, 'id', getattr(instance, 'pk', None)) + instance_before_data = {'id': instance_id} + raw_instance = type(instance).objects.filter(pk=instance_id).first() if raw_instance: instance_before_data = model_to_dict(raw_instance) operate_log_id = str(uuid.uuid4()) From e324c46f87e98ade7fe09c0c77d8dff52ec5770d Mon Sep 17 00:00:00 2001 From: jiangweidong <80373698+Hi-JWD@users.noreply.github.com> Date: Wed, 1 Feb 2023 15:06:10 +0800 Subject: [PATCH 31/92] =?UTF-8?q?fix:=20PrivateToken=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E6=8A=A5=E9=94=99=20(#9387)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jiangjie.Bai --- apps/audits/handler.py | 2 +- .../0021_alter_operatelog_resource_id.py | 18 ++++++++++++++++++ apps/audits/models.py | 2 +- apps/audits/signal_handlers.py | 2 ++ 4 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 apps/audits/migrations/0021_alter_operatelog_resource_id.py diff --git a/apps/audits/handler.py b/apps/audits/handler.py index 9d521824b..41fd59c6c 100644 --- a/apps/audits/handler.py +++ b/apps/audits/handler.py @@ -194,7 +194,7 @@ class OperatorLogHandler(metaclass=Singleton): remote_addr = get_request_ip(current_request) if resource_display is None: resource_display = self.get_resource_display(resource) - resource_id = resource.id if resource is not None else '' + resource_id = getattr(resource, 'pk', '') before, after = self.data_processing(before, after) if not force and not any([before, after]): # 前后都没变化,没必要生成日志,除非手动强制保存 diff --git a/apps/audits/migrations/0021_alter_operatelog_resource_id.py b/apps/audits/migrations/0021_alter_operatelog_resource_id.py new file mode 100644 index 000000000..9dadae738 --- /dev/null +++ b/apps/audits/migrations/0021_alter_operatelog_resource_id.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.16 on 2023-02-01 06:52 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('audits', '0020_auto_20230117_1004'), + ] + + operations = [ + migrations.AlterField( + model_name='operatelog', + name='resource_id', + field=models.CharField(blank=True, db_index=True, default='', max_length=128, verbose_name='Resource'), + ), + ] diff --git a/apps/audits/models.py b/apps/audits/models.py index 86c7597a7..93fb6733b 100644 --- a/apps/audits/models.py +++ b/apps/audits/models.py @@ -53,7 +53,7 @@ class OperateLog(OrgModelMixin): resource_type = models.CharField(max_length=64, verbose_name=_("Resource Type")) resource = models.CharField(max_length=128, verbose_name=_("Resource")) resource_id = models.CharField( - max_length=36, blank=True, default='', db_index=True, + max_length=128, blank=True, default='', db_index=True, verbose_name=_("Resource") ) remote_addr = models.CharField(max_length=128, verbose_name=_("Remote addr"), blank=True, null=True) diff --git a/apps/audits/signal_handlers.py b/apps/audits/signal_handlers.py index d5da3d1f7..2f209e09b 100644 --- a/apps/audits/signal_handlers.py +++ b/apps/audits/signal_handlers.py @@ -136,10 +136,12 @@ def on_object_pre_create_or_update(sender, instance=None, raw=False, using=None, ) if not ok: return + # users.PrivateToken Model 没有 id 有 pk字段 instance_id = getattr(instance, 'id', getattr(instance, 'pk', None)) instance_before_data = {'id': instance_id} raw_instance = type(instance).objects.filter(pk=instance_id).first() + if raw_instance: instance_before_data = model_to_dict(raw_instance) operate_log_id = str(uuid.uuid4()) From 4762939daeb8f3c8c5088c5b66eb85cb18bf5076 Mon Sep 17 00:00:00 2001 From: jiangweidong Date: Wed, 1 Feb 2023 15:13:07 +0800 Subject: [PATCH 32/92] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96audits=E7=9A=84?= =?UTF-8?q?migrations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../migrations/0020_auto_20230117_1004.py | 5 +++++ .../0021_alter_operatelog_resource_id.py | 18 ------------------ 2 files changed, 5 insertions(+), 18 deletions(-) delete mode 100644 apps/audits/migrations/0021_alter_operatelog_resource_id.py diff --git a/apps/audits/migrations/0020_auto_20230117_1004.py b/apps/audits/migrations/0020_auto_20230117_1004.py index d3c2c4c70..4261bd635 100644 --- a/apps/audits/migrations/0020_auto_20230117_1004.py +++ b/apps/audits/migrations/0020_auto_20230117_1004.py @@ -47,4 +47,9 @@ class Migration(migrations.Migration): migrations.RunPython(migrate_operate_log_after_before), migrations.RemoveField(model_name='operatelog', name='after', ), migrations.RemoveField(model_name='operatelog', name='before', ), + migrations.AlterField( + model_name='operatelog', + name='resource_id', + field=models.CharField(blank=True, db_index=True, default='', max_length=128, verbose_name='Resource'), + ), ] diff --git a/apps/audits/migrations/0021_alter_operatelog_resource_id.py b/apps/audits/migrations/0021_alter_operatelog_resource_id.py deleted file mode 100644 index 9dadae738..000000000 --- a/apps/audits/migrations/0021_alter_operatelog_resource_id.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 3.2.16 on 2023-02-01 06:52 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('audits', '0020_auto_20230117_1004'), - ] - - operations = [ - migrations.AlterField( - model_name='operatelog', - name='resource_id', - field=models.CharField(blank=True, db_index=True, default='', max_length=128, verbose_name='Resource'), - ), - ] From 4e2c2b652f8c3d5c9cbc2adbd15e8282c6ed45e7 Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 1 Feb 2023 15:48:30 +0800 Subject: [PATCH 33/92] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E6=95=B0=E6=8D=AE=E5=BA=93=E6=97=B6=E5=8C=85=E5=90=AB?= =?UTF-8?q?=E8=B4=A6=E5=8F=B7=E5=A4=B1=E8=B4=A5=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/serializers/account/account.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/accounts/serializers/account/account.py b/apps/accounts/serializers/account/account.py index a834756f0..cc13aced8 100644 --- a/apps/accounts/serializers/account/account.py +++ b/apps/accounts/serializers/account/account.py @@ -17,10 +17,11 @@ class AccountSerializerCreateValidateMixin: replace_attrs: callable def to_internal_value(self, data): - self.id = data.pop('id', None) - self.push_now = data.pop('push_now', False) - self.template = data.pop('template', False) - return super().to_internal_value(data) + ret = super().to_internal_value(data) + self.id = ret.pop('id', None) + self.push_now = ret.pop('push_now', False) + self.template = ret.pop('template', False) + return ret def set_secret(self, attrs): _id = self.id From 1169677286439216a030fd8ab17f49b5f7f4d6ba Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 1 Feb 2023 16:43:43 +0800 Subject: [PATCH 34/92] =?UTF-8?q?perf:=20=E9=87=8D=E6=9E=84=20notification?= =?UTF-8?q?s=20site=20msg?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/audits/signal_handlers.py | 2 +- apps/notifications/api/site_msgs.py | 29 ++++---- apps/notifications/filters.py | 4 +- .../migrations/0004_auto_20230201_1614.py | 72 ++++++++++++++++++ apps/notifications/models/site_msg.py | 16 ++-- apps/notifications/serializers/site_msgs.py | 23 ++++-- apps/notifications/signal_handlers.py | 4 +- apps/notifications/site_msg.py | 73 ++++++------------- apps/notifications/urls/api_urls.py | 10 +-- apps/terminal/notifications.py | 20 ++--- 10 files changed, 156 insertions(+), 97 deletions(-) create mode 100644 apps/notifications/migrations/0004_auto_20230201_1614.py diff --git a/apps/audits/signal_handlers.py b/apps/audits/signal_handlers.py index 8cc396496..4f8be3670 100644 --- a/apps/audits/signal_handlers.py +++ b/apps/audits/signal_handlers.py @@ -291,7 +291,7 @@ def on_django_start_set_operate_log_monitor_models(sender, **kwargs): } exclude_models = { 'UserPasswordHistory', 'ContentType', - 'SiteMessage', 'SiteMessageUsers', + 'MessageContent', 'SiteMessage', 'PlatformAutomation', 'PlatformProtocol', 'Protocol', 'HistoricalAccount', 'GatheredUser', 'ApprovalRule', 'BaseAutomation', 'CeleryTask', 'Command', 'JobAuditLog', diff --git a/apps/notifications/api/site_msgs.py b/apps/notifications/api/site_msgs.py index 5c9257c25..399f332dc 100644 --- a/apps/notifications/api/site_msgs.py +++ b/apps/notifications/api/site_msgs.py @@ -1,17 +1,16 @@ -from rest_framework.response import Response -from rest_framework.mixins import ListModelMixin, RetrieveModelMixin from rest_framework.decorators import action +from rest_framework.mixins import ListModelMixin, RetrieveModelMixin +from rest_framework.response import Response -from common.utils.http import is_true -from common.permissions import IsValidUser -from common.const.http import GET, PATCH, POST from common.api import JMSGenericViewSet +from common.const.http import GET, PATCH, POST +from common.permissions import IsValidUser +from common.utils.http import is_true from ..serializers import ( - SiteMessageDetailSerializer, SiteMessageIdsSerializer, + SiteMessageSerializer, SiteMessageIdsSerializer, SiteMessageSendSerializer, ) from ..site_msg import SiteMessageUtil -from ..filters import SiteMsgFilter __all__ = ('SiteMessageViewSet',) @@ -19,11 +18,11 @@ __all__ = ('SiteMessageViewSet',) class SiteMessageViewSet(ListModelMixin, RetrieveModelMixin, JMSGenericViewSet): permission_classes = (IsValidUser,) serializer_classes = { - 'default': SiteMessageDetailSerializer, + 'default': SiteMessageSerializer, 'mark_as_read': SiteMessageIdsSerializer, 'send': SiteMessageSendSerializer, } - filterset_class = SiteMsgFilter + filterset_fields = ('has_read',) def get_queryset(self): user = self.request.user @@ -44,9 +43,9 @@ class SiteMessageViewSet(ListModelMixin, RetrieveModelMixin, JMSGenericViewSet): @action(methods=[PATCH], detail=False, url_path='mark-as-read') def mark_as_read(self, request, **kwargs): user = request.user - seri = self.get_serializer(data=request.data) - seri.is_valid(raise_exception=True) - ids = seri.validated_data['ids'] + s = self.get_serializer(data=request.data) + s.is_valid(raise_exception=True) + ids = s.validated_data['ids'] SiteMessageUtil.mark_msgs_as_read(user.id, ids) return Response({'detail': 'ok'}) @@ -58,7 +57,7 @@ class SiteMessageViewSet(ListModelMixin, RetrieveModelMixin, JMSGenericViewSet): @action(methods=[POST], detail=False) def send(self, request, **kwargs): - seri = self.get_serializer(data=request.data) - seri.is_valid(raise_exception=True) - SiteMessageUtil.send_msg(**seri.validated_data, sender=request.user) + s = self.get_serializer(data=request.data) + s.is_valid(raise_exception=True) + SiteMessageUtil.send_msg(**s.validated_data, sender=request.user) return Response({'detail': 'ok'}) diff --git a/apps/notifications/filters.py b/apps/notifications/filters.py index c28b8a3f2..ee11eca2b 100644 --- a/apps/notifications/filters.py +++ b/apps/notifications/filters.py @@ -1,7 +1,7 @@ import django_filters from common.drf.filters import BaseFilterSet -from .models import SiteMessage +from .models import MessageContent class SiteMsgFilter(BaseFilterSet): @@ -14,5 +14,5 @@ class SiteMsgFilter(BaseFilterSet): has_read = django_filters.BooleanFilter(method='do_nothing') class Meta: - model = SiteMessage + model = MessageContent fields = ('has_read',) diff --git a/apps/notifications/migrations/0004_auto_20230201_1614.py b/apps/notifications/migrations/0004_auto_20230201_1614.py new file mode 100644 index 000000000..a59aeb8c2 --- /dev/null +++ b/apps/notifications/migrations/0004_auto_20230201_1614.py @@ -0,0 +1,72 @@ +# Generated by Django 3.2.14 on 2023-02-01 08:14 + +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), + ('users', '0041_auto_20221220_1956'), + ('notifications', '0003_auto_20221220_1956'), + ] + + operations = [ + migrations.RemoveField( + model_name='sitemessageusers', + name='sitemessage', + ), + migrations.RemoveField( + model_name='sitemessageusers', + name='user', + ), + migrations.DeleteModel( + name='SiteMessage', + ), + migrations.DeleteModel( + name='SiteMessageUsers', + ), + migrations.CreateModel( + name='MessageContent', + 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)), + ('subject', models.CharField(max_length=1024)), + ('message', models.TextField()), + ('is_broadcast', models.BooleanField(default=False)), + ('groups', models.ManyToManyField(to='users.UserGroup')), + ('sender', models.ForeignKey(db_constraint=False, default=None, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='send_site_message', to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.CreateModel( + name='SiteMessage', + 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)), + ('has_read', models.BooleanField(default=False)), + ('read_at', models.DateTimeField(default=None, null=True)), + ('content', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='notifications.messagecontent')), + ('user', models.ForeignKey(db_constraint=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + options={ + 'abstract': False, + }, + ), + migrations.AddField( + model_name='messagecontent', + name='users', + field=models.ManyToManyField(related_name='recv_site_messages', through='notifications.SiteMessage', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/apps/notifications/models/site_msg.py b/apps/notifications/models/site_msg.py index 170f21a3f..826aa7016 100644 --- a/apps/notifications/models/site_msg.py +++ b/apps/notifications/models/site_msg.py @@ -2,24 +2,24 @@ from django.db import models from common.db.models import JMSBaseModel -__all__ = ('SiteMessageUsers', 'SiteMessage') +__all__ = ('SiteMessage', 'MessageContent') -class SiteMessageUsers(JMSBaseModel): - sitemessage = models.ForeignKey('notifications.SiteMessage', on_delete=models.CASCADE, db_constraint=False, - related_name='m2m_sitemessageusers') - user = models.ForeignKey('users.User', on_delete=models.CASCADE, db_constraint=False, - related_name='m2m_sitemessageusers') +class SiteMessage(JMSBaseModel): + content = models.ForeignKey('notifications.MessageContent', on_delete=models.CASCADE, + db_constraint=False, related_name='messages') + user = models.ForeignKey('users.User', on_delete=models.CASCADE, db_constraint=False) has_read = models.BooleanField(default=False) read_at = models.DateTimeField(default=None, null=True) comment = '' -class SiteMessage(JMSBaseModel): +class MessageContent(JMSBaseModel): subject = models.CharField(max_length=1024) message = models.TextField() users = models.ManyToManyField( - 'users.User', through=SiteMessageUsers, related_name='recv_site_messages' + 'users.User', through=SiteMessage, + related_name='recv_site_messages' ) groups = models.ManyToManyField('users.UserGroup') is_broadcast = models.BooleanField(default=False) diff --git a/apps/notifications/serializers/site_msgs.py b/apps/notifications/serializers/site_msgs.py index 1f157add5..351a04eac 100644 --- a/apps/notifications/serializers/site_msgs.py +++ b/apps/notifications/serializers/site_msgs.py @@ -1,7 +1,7 @@ -from rest_framework.serializers import ModelSerializer from rest_framework import serializers +from rest_framework.serializers import ModelSerializer -from ..models import SiteMessage +from ..models import MessageContent class SenderMixin(ModelSerializer): @@ -15,12 +15,23 @@ class SenderMixin(ModelSerializer): return '' -class SiteMessageDetailSerializer(SenderMixin, ModelSerializer): +class MessageContentSerializer(SenderMixin, ModelSerializer): class Meta: - model = SiteMessage + model = MessageContent fields = [ - 'id', 'subject', 'message', 'has_read', 'read_at', - 'date_created', 'date_updated', 'sender', + 'id', 'subject', 'message', + 'date_created', 'date_updated', + 'sender', + ] + + +class SiteMessageSerializer(SenderMixin, ModelSerializer): + content = MessageContentSerializer(read_only=True) + + class Meta: + model = MessageContent + fields = [ + 'id', 'has_read', 'read_at', 'content', 'date_created' ] diff --git a/apps/notifications/signal_handlers.py b/apps/notifications/signal_handlers.py index c0b1f1c1c..74b700643 100644 --- a/apps/notifications/signal_handlers.py +++ b/apps/notifications/signal_handlers.py @@ -12,7 +12,7 @@ from common.utils import get_logger from common.utils.connection import RedisPubSub from notifications.backends import BACKEND from users.models import User -from .models import SiteMessage, SystemMsgSubscription, UserMsgSubscription +from .models import MessageContent, SystemMsgSubscription, UserMsgSubscription from .notifications import SystemMessage logger = get_logger(__name__) @@ -26,7 +26,7 @@ class NewSiteMsgSubPub(LazyObject): new_site_msg_chan = NewSiteMsgSubPub() -@receiver(post_save, sender=SiteMessage) +@receiver(post_save, sender=MessageContent) @on_transaction_commit def on_site_message_create(sender, instance, created, **kwargs): if not created: diff --git a/apps/notifications/site_msg.py b/apps/notifications/site_msg.py index faa36b5f4..d4e604a51 100644 --- a/apps/notifications/site_msg.py +++ b/apps/notifications/site_msg.py @@ -1,10 +1,9 @@ -from django.db.models import F, Q from django.db import transaction -from common.utils.timezone import local_now from common.utils import get_logger +from common.utils.timezone import local_now from users.models import User -from .models import SiteMessage as SiteMessageModel, SiteMessageUsers +from .models import MessageContent as SiteMessageModel, SiteMessage logger = get_logger(__file__) @@ -17,11 +16,6 @@ class SiteMessageUtil: if not any((user_ids, group_ids, is_broadcast)): raise ValueError('No recipient is specified') - logger.info(f'Site message send: ' - f'user_ids={user_ids} ' - f'group_ids={group_ids} ' - f'subject={subject} ' - f'message={message}') with transaction.atomic(): site_msg = SiteMessageModel.objects.create( subject=subject, message=message, @@ -30,65 +24,46 @@ class SiteMessageUtil: if is_broadcast: user_ids = User.objects.all().values_list('id', flat=True) - else: - if group_ids: - site_msg.groups.add(*group_ids) + elif group_ids: + site_msg.groups.add(*group_ids) - user_ids_from_group = User.groups.through.objects.filter( - usergroup_id__in=group_ids - ).values_list('user_id', flat=True) - user_ids = [*user_ids, *user_ids_from_group] + user_ids_from_group = User.groups.through.objects.filter( + usergroup_id__in=group_ids + ).values_list('user_id', flat=True) + user_ids = [*user_ids, *user_ids_from_group] site_msg.users.add(*user_ids) @classmethod def get_user_all_msgs(cls, user_id): - site_msgs = SiteMessageModel.objects.filter( - m2m_sitemessageusers__user_id=user_id - ).distinct().annotate( - has_read=F('m2m_sitemessageusers__has_read'), - read_at=F('m2m_sitemessageusers__read_at') - ).order_by('-date_created') - - return site_msgs + site_msg_rels = SiteMessage.objects \ + .filter(user=user_id) \ + .prefetch_related('content') \ + .order_by('-date_created') + return site_msg_rels @classmethod def get_user_all_msgs_count(cls, user_id): - site_msgs_count = SiteMessageModel.objects.filter( - m2m_sitemessageusers__user_id=user_id + site_msgs_count = SiteMessage.objects.filter( + user_id=user_id ).distinct().count() return site_msgs_count @classmethod def filter_user_msgs(cls, user_id, has_read=False): - site_msgs = SiteMessageModel.objects.filter( - m2m_sitemessageusers__user_id=user_id, - m2m_sitemessageusers__has_read=has_read - ).distinct().annotate( - has_read=F('m2m_sitemessageusers__has_read'), - read_at=F('m2m_sitemessageusers__read_at') - ).order_by('-date_created') - - return site_msgs + return cls.get_user_all_msgs(user_id).filter(has_read=has_read) @classmethod def get_user_unread_msgs_count(cls, user_id): - site_msgs_count = SiteMessageModel.objects.filter( - m2m_sitemessageusers__user_id=user_id, - m2m_sitemessageusers__has_read=False - ).distinct().count() + site_msgs_count = SiteMessage.objects \ + .filter(user=user_id, has_read=False) \ + .values_list('content', flat=True) \ + .distinct().count() return site_msgs_count @classmethod def mark_msgs_as_read(cls, user_id, msg_ids=None): - q = Q(user_id=user_id) & Q(has_read=False) - if msg_ids is not None: - q &= Q(sitemessage_id__in=msg_ids) - site_msg_users = SiteMessageUsers.objects.filter(q) - - for site_msg_user in site_msg_users: - site_msg_user.has_read = True - site_msg_user.read_at = local_now() - - SiteMessageUsers.objects.bulk_update( - site_msg_users, fields=('has_read', 'read_at')) + site_msgs = SiteMessage.objects.filter(user_id=user_id) + if msg_ids: + site_msgs = site_msgs.filter(id__in=msg_ids) + site_msgs.update(has_read=True, read_at=local_now()) diff --git a/apps/notifications/urls/api_urls.py b/apps/notifications/urls/api_urls.py index a65dd7b79..f35d7754f 100644 --- a/apps/notifications/urls/api_urls.py +++ b/apps/notifications/urls/api_urls.py @@ -1,7 +1,6 @@ - -from rest_framework_bulk.routes import BulkRouter -from django.urls import path from django.conf import settings +from django.urls import path +from rest_framework_bulk.routes import BulkRouter from notifications import api @@ -10,11 +9,12 @@ app_name = 'notifications' router = BulkRouter() router.register('system-msg-subscription', api.SystemMsgSubscriptionViewSet, 'system-msg-subscription') router.register('user-msg-subscription', api.UserMsgSubscriptionViewSet, 'user-msg-subscription') -router.register('site-message', api.SiteMessageViewSet, 'site-message') +router.register('site-messages', api.SiteMessageViewSet, 'site-message') urlpatterns = [ path('backends/', api.BackendListView.as_view(), name='backends') -] + router.urls +] +urlpatterns += router.urls if settings.DEBUG: urlpatterns += [ diff --git a/apps/terminal/notifications.py b/apps/terminal/notifications.py index 700bfde9b..a6b1a69a6 100644 --- a/apps/terminal/notifications.py +++ b/apps/terminal/notifications.py @@ -1,18 +1,17 @@ from typing import Callable -from django.utils.translation import ugettext_lazy as _ from django.conf import settings from django.template.loader import render_to_string +from django.utils.translation import ugettext_lazy as _ -from users.models import User from common.utils import get_logger, reverse -from notifications.notifications import SystemMessage -from terminal.models import Session, Command -from notifications.models import SystemMsgSubscription -from notifications.backends import BACKEND from common.utils import lazyproperty from common.utils.timezone import local_now_display - +from notifications.backends import BACKEND +from notifications.models import SystemMsgSubscription +from notifications.notifications import SystemMessage +from terminal.models import Session, Command +from users.models import User logger = get_logger(__name__) @@ -75,8 +74,11 @@ class CommandAlertMessage(CommandAlertMixin, SystemMessage): @classmethod def gen_test_msg(cls): - command = Command.objects.first().to_dict() - command['session'] = Session.objects.first().id + command = Command.objects.first() + if not command: + command = Command(user='test', asset='test', input='test', session='111111111') + else: + command['session'] = Session.objects.first().id return cls(command) def get_html_msg(self) -> dict: From fc34980f20108ce17f0884e80fa39e3df19c34c7 Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 1 Feb 2023 17:03:42 +0800 Subject: [PATCH 35/92] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=B8=BB?= =?UTF-8?q?=E6=9C=BA=E8=AF=A6=E6=83=85=E6=98=BE=E7=A4=BA=E7=A1=AC=E4=BB=B6?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/asset/asset.py | 2 +- apps/assets/api/asset/host.py | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/apps/assets/api/asset/asset.py b/apps/assets/api/asset/asset.py index a02d35121..d6107631c 100644 --- a/apps/assets/api/asset/asset.py +++ b/apps/assets/api/asset/asset.py @@ -71,7 +71,7 @@ class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet): ("platform", serializers.PlatformSerializer), ("suggestion", serializers.MiniAssetSerializer), ("gateways", serializers.GatewaySerializer), - ("spec_info", serializers.SpecSerializer), + ("spec_info", serializers.SpecSerializer) ) rbac_perms = ( ("match", "assets.match_asset"), diff --git a/apps/assets/api/asset/host.py b/apps/assets/api/asset/host.py index d2ddc954d..3e11b8ad5 100644 --- a/apps/assets/api/asset/host.py +++ b/apps/assets/api/asset/host.py @@ -1,5 +1,8 @@ from assets.models import Host, Asset -from assets.serializers import HostSerializer +from assets.serializers import HostSerializer, HostInfoSerializer +from rest_framework.decorators import action +from rest_framework.response import Response + from .asset import AssetViewSet __all__ = ['HostViewSet'] @@ -12,4 +15,11 @@ class HostViewSet(AssetViewSet): def get_serializer_classes(self): serializer_classes = super().get_serializer_classes() serializer_classes['default'] = HostSerializer + serializer_classes['info'] = HostInfoSerializer return serializer_classes + + @action(methods=["GET"], detail=True, url_path="info") + def info(self, *args, **kwargs): + asset = super().get_object() + return Response(asset.info) + From 7b95859015e625c11451691d7ba01bfbd51730fa Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 1 Feb 2023 18:20:56 +0800 Subject: [PATCH 36/92] perf: device ansible (#9396) Co-authored-by: feng <1304903146@qq.com> --- apps/assets/const/device.py | 4 ++-- apps/assets/const/web.py | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/assets/const/device.py b/apps/assets/const/device.py index a1913994c..d00996dd6 100644 --- a/apps/assets/const/device.py +++ b/apps/assets/const/device.py @@ -31,11 +31,11 @@ class DeviceTypes(BaseType): def _get_automation_constrains(cls) -> dict: return { '*': { - 'ansible_enabled': True, + 'ansible_enabled': False, 'ansible_config': { 'ansible_connection': 'local', }, - 'ping_enabled': True, + 'ping_enabled': False, 'gather_facts_enabled': False, 'gather_accounts_enabled': False, 'verify_account_enabled': False, diff --git a/apps/assets/const/web.py b/apps/assets/const/web.py index 88ff7f8f9..42ea995ac 100644 --- a/apps/assets/const/web.py +++ b/apps/assets/const/web.py @@ -20,6 +20,8 @@ class WebTypes(BaseType): def _get_automation_constrains(cls) -> dict: constrains = { '*': { + 'ansible_enabled': False, + 'ping_enabled': False, 'gather_facts_enabled': False, 'verify_account_enabled': False, 'change_secret_enabled': False, From 9d898f0aec9da06530fef9c04432f2c0fc559e14 Mon Sep 17 00:00:00 2001 From: Aaron3S Date: Wed, 18 Jan 2023 18:03:33 +0800 Subject: [PATCH 37/92] playbook ide --- apps/ops/api/playbook.py | 189 +++++++++++++++++- apps/ops/const.py | 5 + .../ops/migrations/0025_auto_20230117_1130.py | 23 +++ apps/ops/models/playbook.py | 11 +- apps/ops/serializers/playbook.py | 2 +- apps/ops/urls/api_urls.py | 1 + 6 files changed, 219 insertions(+), 12 deletions(-) create mode 100644 apps/ops/migrations/0025_auto_20230117_1130.py diff --git a/apps/ops/api/playbook.py b/apps/ops/api/playbook.py index aaafacd58..c51868c24 100644 --- a/apps/ops/api/playbook.py +++ b/apps/ops/api/playbook.py @@ -1,13 +1,19 @@ import os +import shutil import zipfile from django.conf import settings +from django.shortcuts import get_object_or_404 + from orgs.mixins.api import OrgBulkModelViewSet from ..exception import PlaybookNoValidEntry from ..models import Playbook from ..serializers.playbook import PlaybookSerializer -__all__ = ["PlaybookViewSet"] +__all__ = ["PlaybookViewSet", "PlaybookFileBrowserAPIView"] + +from rest_framework.views import APIView +from rest_framework.response import Response def unzip_playbook(src, dist): @@ -31,12 +37,175 @@ class PlaybookViewSet(OrgBulkModelViewSet): def perform_create(self, serializer): instance = serializer.save() - src_path = os.path.join(settings.MEDIA_ROOT, instance.path.name) - dest_path = os.path.join(settings.DATA_DIR, "ops", "playbook", instance.id.__str__()) - unzip_playbook(src_path, dest_path) - valid_entry = ('main.yml', 'main.yaml', 'main') - for f in os.listdir(dest_path): - if f in valid_entry: - return - os.remove(dest_path) - raise PlaybookNoValidEntry + if instance.create_method == 'blank': + dest_path = os.path.join(settings.DATA_DIR, "ops", "playbook", instance.id.__str__()) + os.makedirs(dest_path) + with open(os.path.join(dest_path, 'main.yml'), 'w') as f: + f.write('## write your playbook here') + + if instance.create_method == 'upload': + src_path = os.path.join(settings.MEDIA_ROOT, instance.path.name) + dest_path = os.path.join(settings.DATA_DIR, "ops", "playbook", instance.id.__str__()) + unzip_playbook(src_path, dest_path) + valid_entry = ('main.yml', 'main.yaml', 'main') + for f in os.listdir(dest_path): + if f in valid_entry: + return + os.remove(dest_path) + raise PlaybookNoValidEntry + + +class PlaybookFileBrowserAPIView(APIView): + rbac_perms = () + permission_classes = () + + def get(self, request, **kwargs): + playbook_id = kwargs.get('pk') + playbook = get_object_or_404(Playbook, id=playbook_id) + work_path = playbook.work_dir + file_key = request.query_params.get('key', '') + if file_key: + file_path = os.path.join(work_path, file_key) + with open(file_path, 'r') as f: + content = f.read() + return Response({'content': content}) + else: + expand_key = request.query_params.get('expand', '') + nodes = self.generate_tree(playbook, work_path, expand_key) + return Response(nodes) + + def post(self, request, **kwargs): + playbook_id = kwargs.get('pk') + playbook = get_object_or_404(Playbook, id=playbook_id) + work_path = playbook.work_dir + + parent_key = request.data.get('key', '') + if parent_key == 'root': + parent_key = '' + if os.path.dirname(parent_key) == 'root': + parent_key = os.path.basename(parent_key) + full_path = os.path.join(work_path, parent_key) + + is_directory = request.data.get('is_directory', False) + content = request.data.get('content', '') + + if is_directory: + new_file_path = os.path.join(full_path, 'new_dir') + i = 0 + while os.path.exists(new_file_path): + i += 1 + new_file_path = os.path.join(full_path, 'new_dir({})'.format(i)) + os.makedirs(new_file_path) + else: + new_file_path = os.path.join(full_path, 'new_file.yml') + i = 0 + while os.path.exists(new_file_path): + i += 1 + new_file_path = os.path.join(full_path, 'new_file({}).yml'.format(i)) + with open(new_file_path, 'w') as f: + f.write(content) + + relative_path = os.path.relpath(os.path.dirname(new_file_path), work_path) + new_node = { + "name": os.path.basename(new_file_path), + "title": os.path.basename(new_file_path), + "id": os.path.join(relative_path, os.path.basename(new_file_path)) + if not os.path.join(relative_path, os.path.basename(new_file_path)).startswith('.') + else os.path.basename(new_file_path), + "isParent": is_directory, + "pId": relative_path if not relative_path.startswith('.') else 'root', + "open": True, + } + if not is_directory: + new_node['iconSkin'] = 'file' + + return Response(new_node) + + def patch(self, request, **kwargs): + playbook_id = kwargs.get('pk') + playbook = get_object_or_404(Playbook, id=playbook_id) + work_path = playbook.work_dir + + file_key = request.data.get('key', '') + if os.path.dirname(file_key) == 'root': + file_key = os.path.basename(file_key) + + new_name = request.data.get('new_name', '') + content = request.data.get('content', '') + is_directory = request.data.get('is_directory', False) + + if not file_key or file_key == 'root': + return Response(status=400) + file_path = os.path.join(work_path, file_key) + + if new_name: + new_file_path = os.path.join(os.path.dirname(file_path), new_name) + os.rename(file_path, new_file_path) + file_path = new_file_path + + if not is_directory and content: + with open(file_path, 'w') as f: + f.write(content) + return Response({'msg': 'ok'}) + + def delete(self, request, **kwargs): + not_delete_allowed = ['root', 'main.yml'] + playbook_id = kwargs.get('pk') + playbook = get_object_or_404(Playbook, id=playbook_id) + work_path = playbook.work_dir + file_key = request.query_params.get('key', '') + if not file_key: + return Response(status=400) + if file_key in not_delete_allowed: + return Response(status=400) + file_path = os.path.join(work_path, file_key) + if os.path.isdir(file_path): + shutil.rmtree(file_path) + else: + os.remove(file_path) + return Response({'msg': 'ok'}) + + @staticmethod + def generate_tree(playbook, root_path, expand_key=None): + nodes = [{ + "name": playbook.name, + "title": playbook.name, + "id": 'root', + "isParent": True, + "open": True, + "pId": '', + "temp": False + }] + for path, dirs, files in os.walk(root_path): + dirs.sort() + files.sort() + + relative_path = os.path.relpath(path, root_path) + for d in dirs: + node = { + "name": d, + "title": d, + "id": os.path.join(relative_path, d) if not os.path.join(relative_path, d).startswith( + '.') else d, + "isParent": True, + "open": False, + "pId": relative_path if not relative_path.startswith('.') else 'root', + "temp": False + } + if expand_key == node['id']: + node['open'] = True + nodes.append(node) + for f in files: + node = { + "name": f, + "title": f, + "iconSkin": 'file', + "id": os.path.join(relative_path, f) if not os.path.join(relative_path, f).startswith( + '.') else f, + "isParent": False, + "open": False, + "pId": relative_path if not relative_path.startswith('.') else 'root', + "temp": False + } + nodes.append(node) + return nodes diff --git a/apps/ops/const.py b/apps/ops/const.py index 8838c31c5..fb394b6bf 100644 --- a/apps/ops/const.py +++ b/apps/ops/const.py @@ -29,6 +29,11 @@ DEFAULT_PASSWORD_RULES = { } +class CreateMethods(models.TextChoices): + blank = 'blank', _('Blank') + vcs = 'vcs', _('VCS') + + class Types(models.TextChoices): adhoc = 'adhoc', _('Adhoc') playbook = 'playbook', _('Playbook') diff --git a/apps/ops/migrations/0025_auto_20230117_1130.py b/apps/ops/migrations/0025_auto_20230117_1130.py new file mode 100644 index 000000000..b6d3881e7 --- /dev/null +++ b/apps/ops/migrations/0025_auto_20230117_1130.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.14 on 2023-01-17 03:30 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ops', '0024_alter_celerytask_date_last_publish'), + ] + + operations = [ + migrations.AddField( + model_name='playbook', + name='create_method', + field=models.CharField(choices=[('blank', 'Blank'), ('upload', 'Upload'), ('vcs', 'VCS')], default='blank', max_length=128, verbose_name='CreateMethod'), + ), + migrations.AddField( + model_name='playbook', + name='vcs_url', + field=models.CharField(blank=True, default='', max_length=1024, null=True, verbose_name='VCS URL'), + ), + ] diff --git a/apps/ops/models/playbook.py b/apps/ops/models/playbook.py index f92968762..0e649532e 100644 --- a/apps/ops/models/playbook.py +++ b/apps/ops/models/playbook.py @@ -5,6 +5,7 @@ from django.conf import settings from django.db import models from django.utils.translation import gettext_lazy as _ +from ops.const import CreateMethods from ops.exception import PlaybookNoValidEntry from orgs.mixins.models import JMSOrgBaseModel @@ -15,12 +16,20 @@ class Playbook(JMSOrgBaseModel): path = models.FileField(upload_to='playbooks/') creator = models.ForeignKey('users.User', verbose_name=_("Creator"), on_delete=models.SET_NULL, null=True) comment = models.CharField(max_length=1024, default='', verbose_name=_('Comment'), null=True, blank=True) + create_method = models.CharField(max_length=128, choices=CreateMethods.choices, default=CreateMethods.blank, + verbose_name=_('CreateMethod')) + vcs_url = models.CharField(max_length=1024, default='', verbose_name=_('VCS URL'), null=True, blank=True) @property def entry(self): - work_dir = os.path.join(settings.DATA_DIR, "ops", "playbook", self.id.__str__()) + work_dir = self.work_dir valid_entry = ('main.yml', 'main.yaml', 'main') for f in os.listdir(work_dir): if f in valid_entry: return os.path.join(work_dir, f) raise PlaybookNoValidEntry + + @property + def work_dir(self): + work_dir = os.path.join(settings.DATA_DIR, "ops", "playbook", self.id.__str__()) + return work_dir diff --git a/apps/ops/serializers/playbook.py b/apps/ops/serializers/playbook.py index a69bab3c9..3429766d5 100644 --- a/apps/ops/serializers/playbook.py +++ b/apps/ops/serializers/playbook.py @@ -27,5 +27,5 @@ class PlaybookSerializer(BulkOrgResourceModelSerializer): model = Playbook read_only_fields = ["id", "date_created", "date_updated"] fields = read_only_fields + [ - "id", 'path', "name", "comment", "creator", + "id", 'path', "name", "comment", "creator", 'create_method', 'vcs_url', ] diff --git a/apps/ops/urls/api_urls.py b/apps/ops/urls/api_urls.py index b0a4ccb14..e637d84fb 100644 --- a/apps/ops/urls/api_urls.py +++ b/apps/ops/urls/api_urls.py @@ -23,6 +23,7 @@ router.register(r'tasks', api.CeleryTaskViewSet, 'task') router.register(r'task-executions', api.CeleryTaskExecutionViewSet, 'task-executions') urlpatterns = [ + path('playbook//file/', api.PlaybookFileBrowserAPIView.as_view(), name='playbook-file'), path('variables/help/', api.JobRunVariableHelpAPIView.as_view(), name='variable-help'), path('job-execution/asset-detail/', api.JobAssetDetail.as_view(), name='asset-detail'), path('job-execution/task-detail//', api.JobExecutionTaskDetail.as_view(), name='task-detail'), From 853f9c422d22ad5088001cbcaac8d2827d76703e Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 1 Feb 2023 18:45:51 +0800 Subject: [PATCH 38/92] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20i18n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/serializers/asset/common.py | 2 +- apps/locale/zh/LC_MESSAGES/django.po | 2 +- apps/users/serializers/user.py | 13 ++++--------- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/apps/assets/serializers/asset/common.py b/apps/assets/serializers/asset/common.py index 7f39e2378..82a163d84 100644 --- a/apps/assets/serializers/asset/common.py +++ b/apps/assets/serializers/asset/common.py @@ -6,7 +6,7 @@ from django.db.transaction import atomic from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers -from accounts.models import Account, AccountTemplate +from accounts.models import Account from accounts.serializers import AccountSerializerCreateValidateMixin from common.serializers import WritableNestedModelSerializer, SecretReadableMixin, CommonModelSerializer from common.serializers.fields import LabeledChoiceField diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index bdbc5b7d0..1f16f7a8f 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -6381,7 +6381,7 @@ msgstr "登录被阻塞" #: users/serializers/user.py:93 msgid "Can public key authentication" -msgstr "能否公钥认证" +msgstr "公钥认证" #: users/serializers/user.py:162 msgid "Avatar url" diff --git a/apps/users/serializers/user.py b/apps/users/serializers/user.py index 7e2c6ea33..d1cd63fc5 100644 --- a/apps/users/serializers/user.py +++ b/apps/users/serializers/user.py @@ -96,11 +96,8 @@ class UserSerializer(RolesSerializerMixin, CommonBulkSerializerMixin, serializer read_only=True ) password = EncryptedField( - label=_("Password"), - required=False, - allow_blank=True, - allow_null=True, - max_length=1024, + label=_("Password"), required=False, allow_blank=True, + allow_null=True, max_length=1024, ) custom_m2m_fields = { "system_roles": [BuiltinRole.system_user], @@ -129,10 +126,8 @@ class UserSerializer(RolesSerializerMixin, CommonBulkSerializerMixin, serializer ] # 包含不太常用的字段,可以没有 fields_verbose = fields_small + [ - "mfa_force_enabled", - "is_first_login", - "date_password_last_updated", - "avatar_url", + "mfa_force_enabled", "is_first_login", + "date_password_last_updated", "avatar_url", ] # 外键的字段 fields_fk = [] From 758d6ae81ba67690c84c059f88c0e942940f636e Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 1 Feb 2023 19:02:41 +0800 Subject: [PATCH 39/92] perf: gateway print (#9398) Co-authored-by: feng <1304903146@qq.com> --- apps/assets/automations/ping_gateway/manager.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/assets/automations/ping_gateway/manager.py b/apps/assets/automations/ping_gateway/manager.py index 858717665..d03e5d22d 100644 --- a/apps/assets/automations/ping_gateway/manager.py +++ b/apps/assets/automations/ping_gateway/manager.py @@ -33,7 +33,7 @@ class PingGatewayManager: err = _('No account') return False, err - logger.debug('Test account: {}'.format(account)) + print('Test account: {}'.format(account)) try: proxy.connect( gateway.address, @@ -91,7 +91,7 @@ class PingGatewayManager: @staticmethod def on_host_success(gateway, account): - logger.info('\033[32m {} -> {}\033[0m\n'.format(gateway, account)) + print('\033[32m {} -> {}\033[0m\n'.format(gateway, account)) gateway.set_connectivity(Connectivity.OK) if not account: return @@ -99,7 +99,7 @@ class PingGatewayManager: @staticmethod def on_host_error(gateway, account, error): - logger.info('\033[31m {} -> {} 原因: {} \033[0m\n'.format(gateway, account, error)) + print('\033[31m {} -> {} 原因: {} \033[0m\n'.format(gateway, account, error)) gateway.set_connectivity(Connectivity.ERR) if not account: return @@ -107,7 +107,7 @@ class PingGatewayManager: @staticmethod def before_runner_start(): - logger.info(">>> 开始执行测试网关可连接性任务") + print(">>> 开始执行测试网关可连接性任务") def get_accounts(self, gateway): account = gateway.select_account From 308077155951ce9d0fcf67a985fd91bd08ea9920 Mon Sep 17 00:00:00 2001 From: jiangweidong <80373698+Hi-JWD@users.noreply.github.com> Date: Thu, 2 Feb 2023 10:32:48 +0800 Subject: [PATCH 40/92] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E6=B2=A1?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=88=B0=E8=AF=81=E4=B9=A6=E7=9A=84mongodb?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E7=9A=84=E6=97=A0=E6=B3=95=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E5=8C=96=E4=BB=BB=E5=8A=A1=20(#9399)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/automations/base/manager.py | 4 ++-- apps/ops/ansible/inventory.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/assets/automations/base/manager.py b/apps/assets/automations/base/manager.py index f9d06bb73..6247c85d7 100644 --- a/apps/assets/automations/base/manager.py +++ b/apps/assets/automations/base/manager.py @@ -73,7 +73,7 @@ class BasePlaybookManager: if not path_dir: return host - specific = host.get('jms_asset', {}).get('specific', {}) + specific = host.get('jms_asset', {}).get('secret_info', {}) cert_fields = ('ca_cert', 'client_key', 'client_cert') filtered = list(filter(lambda x: specific.get(x), cert_fields)) if not filtered: @@ -87,7 +87,7 @@ class BasePlaybookManager: result = self.write_cert_to_file( os.path.join(cert_dir, f), specific.get(f) ) - host['jms_asset']['specific'][f] = result + host['jms_asset']['secret_info'][f] = result return host def host_callback(self, host, automation=None, **kwargs): diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py index 0a3ce43af..a340b510d 100644 --- a/apps/ops/ansible/inventory.py +++ b/apps/ops/ansible/inventory.py @@ -105,7 +105,7 @@ class JMSInventory: 'id': str(asset.id), 'name': asset.name, 'address': asset.address, 'type': asset.type, 'category': asset.category, 'protocol': asset.protocol, 'port': asset.port, - 'spec_info': asset.spec_info, + 'spec_info': asset.spec_info, 'secret_info': asset.secret_info, 'protocols': [{'name': p.name, 'port': p.port} for p in protocols], }, 'jms_account': { From 7a5195e91eee2d328783f2b0e49dcc6ab314ce41 Mon Sep 17 00:00:00 2001 From: jiangweidong <80373698+Hi-JWD@users.noreply.github.com> Date: Thu, 2 Feb 2023 10:33:07 +0800 Subject: [PATCH 41/92] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E9=83=A8?= =?UTF-8?q?=E7=BD=B2=E5=90=8E=EF=BC=8COracle=E6=97=A0=E6=B3=95=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E8=87=AA=E5=8A=A8=E5=8C=96=E4=BB=BB=E5=8A=A1=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20(#9400)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/management/commands/services/services/celery_base.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/common/management/commands/services/services/celery_base.py b/apps/common/management/commands/services/services/celery_base.py index 7d69139b2..8d197d4f8 100644 --- a/apps/common/management/commands/services/services/celery_base.py +++ b/apps/common/management/commands/services/services/celery_base.py @@ -18,6 +18,7 @@ class CeleryBaseService(BaseService): os.environ.setdefault('ANSIBLE_FORCE_COLOR', 'True') os.environ.setdefault('ANSIBLE_CONFIG', ansible_config_path) os.environ.setdefault('ANSIBLE_LIBRARY', ansible_modules_path) + os.environ.setdefault('PYTHONPATH', settings.APPS_DIR) if os.getuid() == 0: os.environ.setdefault('C_FORCE_ROOT', '1') From d68ed57eb918c0c7fe490f5271ea5a5d5ad6de04 Mon Sep 17 00:00:00 2001 From: Aaron3S Date: Thu, 2 Feb 2023 11:34:47 +0800 Subject: [PATCH 42/92] =?UTF-8?q?=E4=BC=98=E5=8C=96=20playbook=20ide?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/api/playbook.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/apps/ops/api/playbook.py b/apps/ops/api/playbook.py index c51868c24..36c1c4994 100644 --- a/apps/ops/api/playbook.py +++ b/apps/ops/api/playbook.py @@ -88,20 +88,26 @@ class PlaybookFileBrowserAPIView(APIView): is_directory = request.data.get('is_directory', False) content = request.data.get('content', '') + name = request.data.get('name', '') + + def find_new_name(p, is_file=False): + if not p: + if is_file: + p = 'new_file.yml' + else: + p = 'new_dir' + np = os.path.join(full_path, p) + n = 0 + while os.path.exists(np): + n += 1 + np = os.path.join(full_path, '{}({})'.format(p, n)) + return np if is_directory: - new_file_path = os.path.join(full_path, 'new_dir') - i = 0 - while os.path.exists(new_file_path): - i += 1 - new_file_path = os.path.join(full_path, 'new_dir({})'.format(i)) + new_file_path = find_new_name(name) os.makedirs(new_file_path) else: - new_file_path = os.path.join(full_path, 'new_file.yml') - i = 0 - while os.path.exists(new_file_path): - i += 1 - new_file_path = os.path.join(full_path, 'new_file({}).yml'.format(i)) + new_file_path = find_new_name(name, True) with open(new_file_path, 'w') as f: f.write(content) @@ -118,7 +124,6 @@ class PlaybookFileBrowserAPIView(APIView): } if not is_directory: new_node['iconSkin'] = 'file' - return Response(new_node) def patch(self, request, **kwargs): From 0aa681620fcf09de38ec08227219c76a06e801ee Mon Sep 17 00:00:00 2001 From: feng <1304903146@qq.com> Date: Thu, 2 Feb 2023 10:41:03 +0800 Subject: [PATCH 43/92] perf: asset tree search --- apps/assets/api/tree.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/assets/api/tree.py b/apps/assets/api/tree.py index 346775069..9c9ffa8c9 100644 --- a/apps/assets/api/tree.py +++ b/apps/assets/api/tree.py @@ -119,7 +119,7 @@ class NodeChildrenAsTreeApi(SerializeToTreeNodeMixin, NodeChildrenApi): query_all = self.request.query_params.get("all", "0") == "all" include_assets = self.request.query_params.get('assets', '0') == '1' if not self.instance or not include_assets: - return [] + return Asset.objects.none() if query_all: assets = self.instance.get_all_assets_for_tree() else: From 5fcd83b587cd020346c830bbc5146b6f02062050 Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 2 Feb 2023 14:37:21 +0800 Subject: [PATCH 44/92] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=20swagger=20api=20=E6=97=B6=EF=BC=8CAssetSerializer?= =?UTF-8?q?=20category,=20type=20=E5=AD=97=E6=AE=B5=E6=89=8B=E5=8A=A8?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=20=5Fchoices=20=E5=B1=9E=E6=80=A7=E6=97=B6?= =?UTF-8?q?=E6=8A=A5=E9=94=99=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/acls/serializers/login_acl.py | 4 ++-- apps/assets/serializers/asset/common.py | 4 ++-- apps/perms/serializers/permission.py | 4 +--- apps/tickets/serializers/ticket/ticket.py | 4 ++-- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/apps/acls/serializers/login_acl.py b/apps/acls/serializers/login_acl.py index 99b1f1077..59b9cf0ad 100644 --- a/apps/acls/serializers/login_acl.py +++ b/apps/acls/serializers/login_acl.py @@ -52,10 +52,10 @@ class LoginACLSerializer(BulkModelSerializer): action = self.fields.get("action") if not action: return - choices = action._choices + choices = action.choices if not has_valid_xpack_license(): choices.pop(LoginACL.ActionChoices.review, None) - action._choices = choices + action.choices = choices def get_rules_serializer(self): return RuleSerializer() diff --git a/apps/assets/serializers/asset/common.py b/apps/assets/serializers/asset/common.py index 82a163d84..e51c4558f 100644 --- a/apps/assets/serializers/asset/common.py +++ b/apps/assets/serializers/asset/common.py @@ -139,9 +139,9 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali return category = request.path.strip('/').split('/')[-1].rstrip('s') field_category = self.fields.get('category') - field_category._choices = Category.filter_choices(category) + field_category.choices = Category.filter_choices(category) field_type = self.fields.get('type') - field_type._choices = AllTypes.filter_choices(category) + field_type.choices = AllTypes.filter_choices(category) @classmethod def setup_eager_loading(cls, queryset): diff --git a/apps/perms/serializers/permission.py b/apps/perms/serializers/permission.py index 63ba3a765..fef9929b8 100644 --- a/apps/perms/serializers/permission.py +++ b/apps/perms/serializers/permission.py @@ -70,9 +70,7 @@ class AssetPermissionSerializer(BulkOrgResourceModelSerializer): actions = self.fields.get("actions") if not actions: return - choices = actions._choices - actions._choices = choices - actions.default = list(choices.keys()) + actions.default = list(actions.choices.keys()) @classmethod def setup_eager_loading(cls, queryset): diff --git a/apps/tickets/serializers/ticket/ticket.py b/apps/tickets/serializers/ticket/ticket.py index 334031e5e..4a36ccf4f 100644 --- a/apps/tickets/serializers/ticket/ticket.py +++ b/apps/tickets/serializers/ticket/ticket.py @@ -39,9 +39,9 @@ class TicketSerializer(OrgResourceModelSerializerMixin): tp = self.fields.get('type') if not tp: return - choices = tp._choices + choices = tp.choices choices.pop(TicketType.general, None) - tp._choices = choices + tp.choices = choices @classmethod def setup_eager_loading(cls, queryset): From d78725f7c5ac51db0ceb43166302b50e1d62b1c2 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Thu, 2 Feb 2023 14:52:44 +0800 Subject: [PATCH 45/92] perf: choice validate (#9404) Co-authored-by: feng <1304903146@qq.com> --- apps/common/serializers/fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/common/serializers/fields.py b/apps/common/serializers/fields.py index 96ff7c103..84d4d5927 100644 --- a/apps/common/serializers/fields.py +++ b/apps/common/serializers/fields.py @@ -66,7 +66,7 @@ class LabeledChoiceField(ChoiceField): def to_internal_value(self, data): if isinstance(data, dict): - return data.get("value") + data = data.get("value") return super(LabeledChoiceField, self).to_internal_value(data) From 6429b56a54282f0a1ddb77535aa65da63522eb80 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Thu, 2 Feb 2023 15:01:56 +0800 Subject: [PATCH 46/92] =?UTF-8?q?fix:=20=E8=B5=84=E4=BA=A7=E5=85=8B?= =?UTF-8?q?=E9=9A=86=E8=B4=A6=E5=8F=B7bug=20(#9407)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng <1304903146@qq.com> --- apps/accounts/serializers/account/account.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/accounts/serializers/account/account.py b/apps/accounts/serializers/account/account.py index cc13aced8..36dff55a9 100644 --- a/apps/accounts/serializers/account/account.py +++ b/apps/accounts/serializers/account/account.py @@ -17,8 +17,8 @@ class AccountSerializerCreateValidateMixin: replace_attrs: callable def to_internal_value(self, data): + self.id = data.pop('id', None) ret = super().to_internal_value(data) - self.id = ret.pop('id', None) self.push_now = ret.pop('push_now', False) self.template = ret.pop('template', False) return ret From 88edc9191cc0292933cf510b1a10a895888f485e Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 2 Feb 2023 14:53:18 +0800 Subject: [PATCH 47/92] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=20ACL=20?= =?UTF-8?q?=E6=8E=92=E5=BA=8F=20priority,=20date=5Fupdated,=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/acls/migrations/0008_commandgroup_comment.py | 6 +++--- apps/acls/models/base.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/acls/migrations/0008_commandgroup_comment.py b/apps/acls/migrations/0008_commandgroup_comment.py index 82e44912c..8937d2a93 100644 --- a/apps/acls/migrations/0008_commandgroup_comment.py +++ b/apps/acls/migrations/0008_commandgroup_comment.py @@ -20,14 +20,14 @@ class Migration(migrations.Migration): ), migrations.AlterModelOptions( name='commandfilteracl', - options={'ordering': ('priority', 'name'), 'verbose_name': 'Command acl'}, + options={'ordering': ('priority', 'date_updated', 'name'), 'verbose_name': 'Command acl'}, ), migrations.AlterModelOptions( name='loginacl', - options={'ordering': ('priority', 'name'), 'verbose_name': 'Login acl'}, + options={'ordering': ('priority', 'date_updated', 'name'), 'verbose_name': 'Login acl'}, ), migrations.AlterModelOptions( name='loginassetacl', - options={'ordering': ('priority', 'name'), 'verbose_name': 'Login asset acl'}, + options={'ordering': ('priority', 'date_updated', 'name'), 'verbose_name': 'Login asset acl'}, ), ] diff --git a/apps/acls/models/base.py b/apps/acls/models/base.py index 7ba48b3c6..53a566048 100644 --- a/apps/acls/models/base.py +++ b/apps/acls/models/base.py @@ -82,7 +82,7 @@ class BaseACL(JMSBaseModel): objects = ACLManager.from_queryset(BaseACLQuerySet)() class Meta: - ordering = ('priority', 'name') + ordering = ('priority', 'date_updated', 'name') abstract = True def is_action(self, action): From 1c55bde8c8fc567b1086db148eefc52e6cf7f7a6 Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 2 Feb 2023 15:03:48 +0800 Subject: [PATCH 48/92] =?UTF-8?q?perf:=20=E5=8F=91=E5=B8=83=E6=9C=BA?= =?UTF-8?q?=E9=83=A8=E7=BD=B2=E6=96=B0=E5=A2=9E=20CORE=5FHOST=20=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/automations/deploy_applet_host/__init__.py | 5 +++-- apps/terminal/serializers/applet_host.py | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/terminal/automations/deploy_applet_host/__init__.py b/apps/terminal/automations/deploy_applet_host/__init__.py index c5e903f35..00f63463b 100644 --- a/apps/terminal/automations/deploy_applet_host/__init__.py +++ b/apps/terminal/automations/deploy_applet_host/__init__.py @@ -53,14 +53,15 @@ class DeployAppletHostManager: if not download_host: download_host = site_url options = self.deployment.host.deploy_options - site_url = site_url.rstrip("/") + core_host = options.get("CORE_HOST", site_url) + core_host = core_host.rstrip("/") download_host = download_host.rstrip("/") def handler(plays): for play in plays: play["vars"].update(options) play["vars"]["APPLET_DOWNLOAD_HOST"] = download_host - play["vars"]["CORE_HOST"] = site_url + play["vars"]["CORE_HOST"] = core_host play["vars"]["BOOTSTRAP_TOKEN"] = bootstrap_token play["vars"]["HOST_ID"] = host_id play["vars"]["HOST_NAME"] = self.deployment.host.name diff --git a/apps/terminal/serializers/applet_host.py b/apps/terminal/serializers/applet_host.py index 9ec4b8104..cf7895a71 100644 --- a/apps/terminal/serializers/applet_host.py +++ b/apps/terminal/serializers/applet_host.py @@ -1,3 +1,4 @@ +from django.conf import settings from django.utils.translation import gettext_lazy as _ from rest_framework import serializers @@ -27,6 +28,8 @@ class DeployOptionsSerializer(serializers.Serializer): (1, _("Disabled")), (0, _("Enabled")), ) + + CORE_HOST = serializers.CharField(default=settings.SITE_URL, label=_('API Server'), max_length=1024) RDS_Licensing = serializers.BooleanField(default=False, label=_("RDS Licensing")) RDS_LicenseServer = serializers.CharField(default='127.0.0.1', label=_('RDS License Server'), max_length=1024) RDS_LicensingMode = serializers.ChoiceField(choices=LICENSE_MODE_CHOICES, default=4, label=_('RDS Licensing Mode')) From 3341d55d1b37183808e0e9535fd41f6d2346881d Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 2 Feb 2023 15:26:19 +0800 Subject: [PATCH 49/92] =?UTF-8?q?perf:=20APPLET=5FDOWNLOAD=5FHOST=20?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/automations/deploy_applet_host/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/terminal/automations/deploy_applet_host/__init__.py b/apps/terminal/automations/deploy_applet_host/__init__.py index 00f63463b..164340098 100644 --- a/apps/terminal/automations/deploy_applet_host/__init__.py +++ b/apps/terminal/automations/deploy_applet_host/__init__.py @@ -50,11 +50,11 @@ class DeployAppletHostManager: host_id = str(self.deployment.host.id) if not site_url: site_url = "http://localhost:8080" - if not download_host: - download_host = site_url options = self.deployment.host.deploy_options core_host = options.get("CORE_HOST", site_url) core_host = core_host.rstrip("/") + if not download_host: + download_host = core_host download_host = download_host.rstrip("/") def handler(plays): From e3e727f97260de3794f6db0f5cbbb81885bc7eb0 Mon Sep 17 00:00:00 2001 From: Aaron3S Date: Thu, 2 Feb 2023 15:55:37 +0800 Subject: [PATCH 50/92] =?UTF-8?q?perf:=20=E9=BB=98=E8=AE=A4=E5=B1=95?= =?UTF-8?q?=E5=BC=80=E7=BC=96=E8=BE=91=E5=99=A8=E6=89=80=E6=9C=89=E7=9B=AE?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/api/playbook.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ops/api/playbook.py b/apps/ops/api/playbook.py index 36c1c4994..322129b8b 100644 --- a/apps/ops/api/playbook.py +++ b/apps/ops/api/playbook.py @@ -193,7 +193,7 @@ class PlaybookFileBrowserAPIView(APIView): "id": os.path.join(relative_path, d) if not os.path.join(relative_path, d).startswith( '.') else d, "isParent": True, - "open": False, + "open": True, "pId": relative_path if not relative_path.startswith('.') else 'root', "temp": False } From 64e48712a578c17f54f51389919806906fe67fb1 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Thu, 2 Feb 2023 16:16:38 +0800 Subject: [PATCH 51/92] perf: gateway migrate (#9412) Co-authored-by: feng <1304903146@qq.com> --- apps/assets/migrations/0100_auto_20220711_1413.py | 3 +-- apps/assets/migrations/0101_auto_20220811_1511.py | 1 - apps/assets/migrations/0103_auto_20220902_1021.py | 14 ++++++++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/apps/assets/migrations/0100_auto_20220711_1413.py b/apps/assets/migrations/0100_auto_20220711_1413.py index 16e75cbae..2412c6df0 100644 --- a/apps/assets/migrations/0100_auto_20220711_1413.py +++ b/apps/assets/migrations/0100_auto_20220711_1413.py @@ -1,8 +1,7 @@ # Generated by Django 3.2.12 on 2022-07-11 06:13 import time -from django.db import migrations, models -from assets.models import Platform +from django.db import migrations def migrate_asset_accounts(apps, schema_editor): diff --git a/apps/assets/migrations/0101_auto_20220811_1511.py b/apps/assets/migrations/0101_auto_20220811_1511.py index 9ca39774e..0287a8414 100644 --- a/apps/assets/migrations/0101_auto_20220811_1511.py +++ b/apps/assets/migrations/0101_auto_20220811_1511.py @@ -1,5 +1,4 @@ # Generated by Django 3.2.14 on 2022-08-11 07:11 -import assets.models.platform import django.db.models from django.db import migrations, models diff --git a/apps/assets/migrations/0103_auto_20220902_1021.py b/apps/assets/migrations/0103_auto_20220902_1021.py index 8d324fa12..dfc731736 100644 --- a/apps/assets/migrations/0103_auto_20220902_1021.py +++ b/apps/assets/migrations/0103_auto_20220902_1021.py @@ -18,6 +18,8 @@ def _create_account_obj(secret, secret_type, gateway, asset, account_model): def migrate_gateway_to_asset(apps, schema_editor): db_alias = schema_editor.connection.alias + node_model = apps.get_model('assets', 'Node') + org_model = apps.get_model('orgs', 'Organization') gateway_model = apps.get_model('assets', 'Gateway') platform_model = apps.get_model('assets', 'Platform') gateway_platform = platform_model.objects.using(db_alias).get(name=GATEWAY_NAME) @@ -28,6 +30,16 @@ def migrate_gateway_to_asset(apps, schema_editor): asset_model = apps.get_model('assets', 'Asset') protocol_model = apps.get_model('assets', 'Protocol') gateways = gateway_model.objects.all() + + org_ids = gateways.order_by('org_id').values_list('org_id', flat=True).distinct() + node_dict = {} + for org_id in org_ids: + org = org_model.objects.using(db_alias).filter(id=org_id).first() + node = node_model.objects.using(db_alias).filter( + org_id=org_id, value=org.name, full_value=f'/{org.name}' + ).first() + node_dict[org_id] = node + for gateway in gateways: comment = gateway.comment if gateway.comment else '' data = { @@ -40,6 +52,8 @@ def migrate_gateway_to_asset(apps, schema_editor): 'platform': gateway_platform, } asset = asset_model.objects.using(db_alias).create(**data) + node = node_dict.get(str(gateway.org_id)) + asset.nodes.set([node]) asset_dict[gateway.id] = asset protocol_model.objects.using(db_alias).create(name='ssh', port=gateway.port, asset=asset) hosts = [host_model(asset_ptr=asset) for asset in asset_dict.values()] From be151523f4c329762ad9eb8cc48bd0dee5771f75 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Thu, 2 Feb 2023 16:40:00 +0800 Subject: [PATCH 52/92] perf: user filter (#9413) Co-authored-by: feng <1304903146@qq.com> --- apps/users/filters.py | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/apps/users/filters.py b/apps/users/filters.py index 8359f8d2e..434faf847 100644 --- a/apps/users/filters.py +++ b/apps/users/filters.py @@ -6,12 +6,8 @@ from rbac.models import Role class UserFilter(BaseFilterSet): - system_roles = filters.ModelChoiceFilter( - queryset=Role.objects.filter(scope='system'), method='filter_system_roles' - ) - org_roles = filters.ModelChoiceFilter( - queryset=Role.objects.filter(scope='org'), method='filter_org_roles' - ) + system_roles = filters.CharFilter(method='filter_system_roles') + org_roles = filters.CharFilter(method='filter_org_roles') class Meta: model = User @@ -22,16 +18,18 @@ class UserFilter(BaseFilterSet): @staticmethod def filter_system_roles(queryset, name, value): - queryset = queryset.prefetch_related('role_bindings')\ - .filter(role_bindings__role_id=value.id)\ - .distinct() + queryset = queryset.prefetch_related('role_bindings') \ + .filter( + role_bindings__role__name=value, + role_bindings__role__scope='system' + ).distinct() return queryset @staticmethod def filter_org_roles(queryset, name, value): queryset = queryset.prefetch_related('role_bindings') \ - .filter(role_bindings__role_id=value.id) \ - .distinct() + .filter( + role_bindings__role__name=value, + role_bindings__role__scope='org' + ).distinct() return queryset - - From a045eb99361a458eccb8b5436a9b3e012b8708f1 Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 2 Feb 2023 16:06:15 +0800 Subject: [PATCH 53/92] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E5=88=97=E8=A1=A8=E6=8E=92=E5=BA=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/migrations/0025_auto_20230117_1130.py | 2 +- apps/rbac/api/role.py | 1 - apps/rbac/migrations/0012_alter_role_options.py | 17 +++++++++++++++++ apps/rbac/models/role.py | 1 + 4 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 apps/rbac/migrations/0012_alter_role_options.py diff --git a/apps/ops/migrations/0025_auto_20230117_1130.py b/apps/ops/migrations/0025_auto_20230117_1130.py index b6d3881e7..7a5aa33b8 100644 --- a/apps/ops/migrations/0025_auto_20230117_1130.py +++ b/apps/ops/migrations/0025_auto_20230117_1130.py @@ -13,7 +13,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='playbook', name='create_method', - field=models.CharField(choices=[('blank', 'Blank'), ('upload', 'Upload'), ('vcs', 'VCS')], default='blank', max_length=128, verbose_name='CreateMethod'), + field=models.CharField(choices=[('blank', 'Blank'), ('vcs', 'VCS')], default='blank', max_length=128, verbose_name='CreateMethod'), ), migrations.AddField( model_name='playbook', diff --git a/apps/rbac/api/role.py b/apps/rbac/api/role.py index 0a4d52706..255299516 100644 --- a/apps/rbac/api/role.py +++ b/apps/rbac/api/role.py @@ -4,7 +4,6 @@ from rest_framework.exceptions import PermissionDenied from rest_framework.decorators import action from common.api import JMSModelViewSet -from common.api import PaginatedResponseMixin from ..filters import RoleFilter from ..serializers import RoleSerializer, RoleUserSerializer from ..models import Role, SystemRole, OrgRole diff --git a/apps/rbac/migrations/0012_alter_role_options.py b/apps/rbac/migrations/0012_alter_role_options.py new file mode 100644 index 000000000..ba98b699e --- /dev/null +++ b/apps/rbac/migrations/0012_alter_role_options.py @@ -0,0 +1,17 @@ +# Generated by Django 3.2.16 on 2023-02-02 08:03 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('rbac', '0011_remove_redundant_permission'), + ] + + operations = [ + migrations.AlterModelOptions( + name='role', + options={'ordering': ('scope', 'name'), 'verbose_name': 'Role'}, + ), + ] diff --git a/apps/rbac/models/role.py b/apps/rbac/models/role.py index 1eff7c15c..e5a18b5e6 100644 --- a/apps/rbac/models/role.py +++ b/apps/rbac/models/role.py @@ -43,6 +43,7 @@ class Role(JMSBaseModel): class Meta: unique_together = [('name', 'scope')] + ordering = ('scope', 'name') verbose_name = _('Role') def __str__(self): From 2d514c0db07d5836f96d4bb6d1905a3010f855c8 Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 2 Feb 2023 16:09:50 +0800 Subject: [PATCH 54/92] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E5=88=97=E8=A1=A8=E6=8E=92=E5=BA=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/rbac/migrations/0012_alter_role_options.py | 2 +- apps/rbac/models/role.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/rbac/migrations/0012_alter_role_options.py b/apps/rbac/migrations/0012_alter_role_options.py index ba98b699e..6c7ce1525 100644 --- a/apps/rbac/migrations/0012_alter_role_options.py +++ b/apps/rbac/migrations/0012_alter_role_options.py @@ -12,6 +12,6 @@ class Migration(migrations.Migration): operations = [ migrations.AlterModelOptions( name='role', - options={'ordering': ('scope', 'name'), 'verbose_name': 'Role'}, + options={'ordering': ('-builtin', 'scope', 'name'), 'verbose_name': 'Role'}, ), ] diff --git a/apps/rbac/models/role.py b/apps/rbac/models/role.py index e5a18b5e6..796b1ab63 100644 --- a/apps/rbac/models/role.py +++ b/apps/rbac/models/role.py @@ -43,7 +43,7 @@ class Role(JMSBaseModel): class Meta: unique_together = [('name', 'scope')] - ordering = ('scope', 'name') + ordering = ('-builtin', 'scope', 'name') verbose_name = _('Role') def __str__(self): From c3d01591e755988422587e21013f96af14f3895f Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 2 Feb 2023 16:28:54 +0800 Subject: [PATCH 55/92] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E5=88=97=E8=A1=A8viewset=E6=8E=92=E5=BA=8F=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/rbac/api/role.py | 4 ++-- apps/rbac/models/role.py | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/rbac/api/role.py b/apps/rbac/api/role.py index 255299516..dd0220692 100644 --- a/apps/rbac/api/role.py +++ b/apps/rbac/api/role.py @@ -17,6 +17,7 @@ __all__ = [ class RoleViewSet(JMSModelViewSet): queryset = Role.objects.all() + ordering = ('-builtin', 'scope', 'name') serializer_classes = { 'default': RoleSerializer, 'users': RoleUserSerializer, @@ -61,8 +62,7 @@ class RoleViewSet(JMSModelViewSet): return super().perform_update(serializer) def get_queryset(self): - queryset = super().get_queryset() \ - .annotate(permissions_amount=Count('permissions')) + queryset = super().get_queryset().annotate(permissions_amount=Count('permissions')) return queryset @action(methods=['GET'], detail=True) diff --git a/apps/rbac/models/role.py b/apps/rbac/models/role.py index 796b1ab63..1eff7c15c 100644 --- a/apps/rbac/models/role.py +++ b/apps/rbac/models/role.py @@ -43,7 +43,6 @@ class Role(JMSBaseModel): class Meta: unique_together = [('name', 'scope')] - ordering = ('-builtin', 'scope', 'name') verbose_name = _('Role') def __str__(self): From 4c9d16b4c1e3f23fdfe7297293c7680a17829f03 Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 2 Feb 2023 16:41:41 +0800 Subject: [PATCH 56/92] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E8=A7=92?= =?UTF-8?q?=E8=89=B2=E5=88=97=E8=A1=A8viewset=E6=8E=92=E5=BA=8F=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/rbac/migrations/0012_alter_role_options.py | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 apps/rbac/migrations/0012_alter_role_options.py diff --git a/apps/rbac/migrations/0012_alter_role_options.py b/apps/rbac/migrations/0012_alter_role_options.py deleted file mode 100644 index 6c7ce1525..000000000 --- a/apps/rbac/migrations/0012_alter_role_options.py +++ /dev/null @@ -1,17 +0,0 @@ -# Generated by Django 3.2.16 on 2023-02-02 08:03 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('rbac', '0011_remove_redundant_permission'), - ] - - operations = [ - migrations.AlterModelOptions( - name='role', - options={'ordering': ('-builtin', 'scope', 'name'), 'verbose_name': 'Role'}, - ), - ] From 1083f5f6f24c2473653e815f00d81a37eaf28ff2 Mon Sep 17 00:00:00 2001 From: Aaron3S Date: Thu, 2 Feb 2023 15:57:06 +0800 Subject: [PATCH 57/92] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20task=20?= =?UTF-8?q?=E7=9A=84=20verbose=5Fname?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/audits/tasks.py | 5 +++-- apps/authentication/tasks.py | 5 +++-- apps/common/utils/verify_code.py | 4 ++-- apps/perms/tasks.py | 5 +++-- apps/terminal/tasks.py | 13 +++++++------ apps/users/tasks.py | 18 +++++++++--------- 6 files changed, 27 insertions(+), 23 deletions(-) diff --git a/apps/audits/tasks.py b/apps/audits/tasks.py index 5b58c5fd2..1dc507c25 100644 --- a/apps/audits/tasks.py +++ b/apps/audits/tasks.py @@ -9,6 +9,7 @@ from ops.celery.decorator import ( ) from .models import UserLoginLog, OperateLog, FTPLog from common.utils import get_log_keep_day +from django.utils.translation import gettext_lazy as _ def clean_login_log_period(): @@ -32,8 +33,8 @@ def clean_ftp_log_period(): FTPLog.objects.filter(date_start__lt=expired_day).delete() -@register_as_period_task(interval=3600*24) -@shared_task +@register_as_period_task(interval=3600 * 24) +@shared_task(verbose_name=_('Clean audits log')) def clean_audits_log_period(): clean_login_log_period() clean_operation_log_period() diff --git a/apps/authentication/tasks.py b/apps/authentication/tasks.py index 08472e931..978e4ace0 100644 --- a/apps/authentication/tasks.py +++ b/apps/authentication/tasks.py @@ -5,9 +5,10 @@ from celery import shared_task from ops.celery.decorator import register_as_period_task from django.contrib.sessions.models import Session from django.utils import timezone +from django.utils.translation import gettext_lazy as _ -@register_as_period_task(interval=3600*24) -@shared_task +@register_as_period_task(interval=3600 * 24) +@shared_task(verbose_name=_('Clean expired session')) def clean_django_sessions(): Session.objects.filter(expire_date__lt=timezone.now()).delete() diff --git a/apps/common/utils/verify_code.py b/apps/common/utils/verify_code.py index 85589de69..0dbf810fd 100644 --- a/apps/common/utils/verify_code.py +++ b/apps/common/utils/verify_code.py @@ -8,12 +8,12 @@ from common.sdk.sms.endpoint import SMS from common.exceptions import JMSException from common.utils.random import random_string from common.utils import get_logger - +from django.utils.translation import gettext_lazy as _ logger = get_logger(__file__) -@shared_task +@shared_task(verbose_name=_('Send email')) def send_async(sender): sender.gen_and_send() diff --git a/apps/perms/tasks.py b/apps/perms/tasks.py index 57b9f48bd..cd4e7bd86 100644 --- a/apps/perms/tasks.py +++ b/apps/perms/tasks.py @@ -19,12 +19,13 @@ from perms.notifications import ( PermedAssetsWillExpireUserMsg, AssetPermsWillExpireForOrgAdminMsg, ) +from django.utils.translation import gettext_lazy as _ logger = get_logger(__file__) @register_as_period_task(interval=settings.PERM_EXPIRED_CHECK_PERIODIC) -@shared_task() +@shared_task(verbose_name=_('Check asset permission expired')) @atomic() @tmp_to_root_org() def check_asset_permission_expired(): @@ -36,7 +37,7 @@ def check_asset_permission_expired(): @register_as_period_task(crontab=CRONTAB_AT_AM_TEN) -@shared_task() +@shared_task(verbose_name=_('Send asset permission expired notification')) @atomic() @tmp_to_root_org() def check_asset_permission_will_expired(): diff --git a/apps/terminal/tasks.py b/apps/terminal/tasks.py index 4e67d1fc7..63b449320 100644 --- a/apps/terminal/tasks.py +++ b/apps/terminal/tasks.py @@ -21,13 +21,14 @@ from .models import ( Status, Session, Command, Task, AppletHostDeployment ) from .utils import find_session_replay_local +from django.utils.translation import gettext_lazy as _ CACHE_REFRESH_INTERVAL = 10 RUNNING = False logger = get_task_logger(__name__) -@shared_task +@shared_task(verbose_name=_('Periodic delete terminal status')) @register_as_period_task(interval=3600) @after_app_ready_start @after_app_shutdown_clean_periodic @@ -36,7 +37,7 @@ def delete_terminal_status_period(): Status.objects.filter(date_created__lt=yesterday).delete() -@shared_task +@shared_task(verbose_name=_('Clean orphan session')) @register_as_period_task(interval=600) @after_app_ready_start @after_app_shutdown_clean_periodic @@ -55,7 +56,7 @@ def clean_orphan_session(): session.save() -@shared_task +@shared_task(verbose_name=_('Periodic clean expired session')) @register_as_period_task(interval=3600 * 24) @after_app_ready_start @after_app_shutdown_clean_periodic @@ -81,7 +82,7 @@ def clean_expired_session_period(): logger.info("Clean session replay done") -@shared_task +@shared_task(verbose_name=_('Upload session replay to external storage')) def upload_session_replay_to_external_storage(session_id): logger.info(f'Start upload session to external storage: {session_id}') session = Session.objects.filter(id=session_id).first() @@ -108,14 +109,14 @@ def upload_session_replay_to_external_storage(session_id): return -@shared_task +@shared_task(verbose_name=_('Run applet host deployment')) def run_applet_host_deployment(did): with tmp_to_builtin_org(system=1): deployment = AppletHostDeployment.objects.get(id=did) deployment.start() -@shared_task +@shared_task(verbose_name=_('Install applet')) def run_applet_host_deployment_install_applet(did, applet_id): with tmp_to_builtin_org(system=1): deployment = AppletHostDeployment.objects.get(id=did) diff --git a/apps/users/tasks.py b/apps/users/tasks.py index cddf0d2ec..2e19678ad 100644 --- a/apps/users/tasks.py +++ b/apps/users/tasks.py @@ -16,12 +16,12 @@ from .models import User from users.notifications import UserExpirationReminderMsg from settings.utils import LDAPServerUtil, LDAPImportUtil from common.const.crontab import CRONTAB_AT_AM_TEN, CRONTAB_AT_PM_TWO - +from django.utils.translation import gettext_lazy as _ logger = get_logger(__file__) -@shared_task +@shared_task(verbose_name=_('Check password expired')) def check_password_expired(): users = User.get_nature_users().filter(source=User.Source.local) for user in users: @@ -35,7 +35,7 @@ def check_password_expired(): PasswordExpirationReminderMsg(user).publish_async() -@shared_task +@shared_task(verbose_name=_('Periodic check password expired')) @after_app_ready_start def check_password_expired_periodic(): tasks = { @@ -49,11 +49,11 @@ def check_password_expired_periodic(): create_or_update_celery_periodic_tasks(tasks) -@shared_task +@shared_task(verbose_name=_('Check user expired')) def check_user_expired(): date_expired_lt = timezone.now() + timezone.timedelta(days=User.DATE_EXPIRED_WARNING_DAYS) - users = User.get_nature_users()\ - .filter(source=User.Source.local)\ + users = User.get_nature_users() \ + .filter(source=User.Source.local) \ .filter(date_expired__lt=date_expired_lt) for user in users: @@ -66,7 +66,7 @@ def check_user_expired(): UserExpirationReminderMsg(user).publish_async() -@shared_task +@shared_task(verbose_name=_('Periodic check user expired')) @after_app_ready_start def check_user_expired_periodic(): tasks = { @@ -80,7 +80,7 @@ def check_user_expired_periodic(): create_or_update_celery_periodic_tasks(tasks) -@shared_task +@shared_task(verbose_name=_('Import ldap user')) def import_ldap_user(): logger.info("Start import ldap user task") util_server = LDAPServerUtil() @@ -101,7 +101,7 @@ def import_ldap_user(): logger.info('Imported {} users successfully'.format(len(users))) -@shared_task +@shared_task(verbose_name=_('Periodic import ldap user')) @after_app_ready_start def import_ldap_user_periodic(): if not settings.AUTH_LDAP: From d0bd35d88c9e1b3c7a37febeef94cae2a18948df Mon Sep 17 00:00:00 2001 From: Bai Date: Thu, 2 Feb 2023 17:05:05 +0800 Subject: [PATCH 58/92] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=B5=8B?= =?UTF-8?q?=E8=AF=95ldap=20attr=20map=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/settings/serializers/auth/ldap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/settings/serializers/auth/ldap.py b/apps/settings/serializers/auth/ldap.py index a6cc22455..472627e8a 100644 --- a/apps/settings/serializers/auth/ldap.py +++ b/apps/settings/serializers/auth/ldap.py @@ -15,7 +15,7 @@ class LDAPTestConfigSerializer(serializers.Serializer): AUTH_LDAP_BIND_PASSWORD = EncryptedField(required=False, allow_blank=True) AUTH_LDAP_SEARCH_OU = serializers.CharField() AUTH_LDAP_SEARCH_FILTER = serializers.CharField() - AUTH_LDAP_USER_ATTR_MAP = serializers.CharField() + AUTH_LDAP_USER_ATTR_MAP = serializers.JSONField() AUTH_LDAP_START_TLS = serializers.BooleanField(required=False) AUTH_LDAP = serializers.BooleanField(required=False) From 77486f07732b31fcdd78d418f1827d237d281875 Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 2 Feb 2023 18:09:31 +0800 Subject: [PATCH 59/92] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E8=BF=87=E6=BB=A4=E8=A7=92=E8=89=B2=E7=9A=84=E9=94=99?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/static/img/login_image.png | Bin 488955 -> 89631 bytes apps/users/filters.py | 45 ++++++++++++++++++++------------ 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/apps/static/img/login_image.png b/apps/static/img/login_image.png index 1cb86eb5f9b208a2ed0ed96a2020edb0edc8fa8d..8188757be026e7996b06384db0841e340ff07016 100644 GIT binary patch literal 89631 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 Z0rRafCS}#>Lg@ePrwq{mm&tt!{2$oyU+4e; literal 488955 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

{KE1kRO`k-Rv0nT4 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

^@v~|Lq!>OIIra&A-0l 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 diff --git a/apps/users/filters.py b/apps/users/filters.py index 8359f8d2e..e72523d00 100644 --- a/apps/users/filters.py +++ b/apps/users/filters.py @@ -1,17 +1,15 @@ +from django.utils.translation import gettext as _ from django_filters import rest_framework as filters from common.drf.filters import BaseFilterSet -from users.models.user import User +from common.utils import is_uuid from rbac.models import Role +from users.models.user import User class UserFilter(BaseFilterSet): - system_roles = filters.ModelChoiceFilter( - queryset=Role.objects.filter(scope='system'), method='filter_system_roles' - ) - org_roles = filters.ModelChoiceFilter( - queryset=Role.objects.filter(scope='org'), method='filter_org_roles' - ) + system_roles = filters.CharFilter(method='filter_system_roles') + org_roles = filters.CharFilter(method='filter_org_roles') class Meta: model = User @@ -21,17 +19,32 @@ class UserFilter(BaseFilterSet): ) @staticmethod - def filter_system_roles(queryset, name, value): - queryset = queryset.prefetch_related('role_bindings')\ - .filter(role_bindings__role_id=value.id)\ - .distinct() - return queryset + def get_role(value): + from rbac.builtin import BuiltinRole + roles = BuiltinRole.get_roles() + for role in roles.values(): + if _(role.name) == value: + return role - @staticmethod - def filter_org_roles(queryset, name, value): + if is_uuid(value): + return Role.objects.filter(id=value).first() + else: + return Role.objects.filter(name=value).first() + + def filter_system_roles(self, queryset, name, value): + role = self.get_role(value) + if not role: + return queryset.none() queryset = queryset.prefetch_related('role_bindings') \ - .filter(role_bindings__role_id=value.id) \ + .filter(role_bindings__role_id=role.id) \ .distinct() return queryset - + def filter_org_roles(self, queryset, name, value): + role = self.get_role(value) + if not role: + return queryset.none() + queryset = queryset.prefetch_related('role_bindings') \ + .filter(role_bindings__role_id=role.id) \ + .distinct() + return queryset From b4068be89cd83921f7dc35cc361bc1f581e00473 Mon Sep 17 00:00:00 2001 From: ibuler Date: Thu, 2 Feb 2023 18:16:40 +0800 Subject: [PATCH 60/92] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E6=8D=A2?= =?UTF-8?q?=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/users/filters.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/users/filters.py b/apps/users/filters.py index 1256dde16..7672826d4 100644 --- a/apps/users/filters.py +++ b/apps/users/filters.py @@ -36,7 +36,8 @@ class UserFilter(BaseFilterSet): if not role: return queryset.none() queryset = queryset.prefetch_related('role_bindings') \ - .filter(role_bindings__role_id=role.id, role_bindings__role__scope='system') \ + .filter(role_bindings__role_id=role.id) \ + .filter(role_bindings__role__scope='system') \ .distinct() return queryset @@ -45,6 +46,7 @@ class UserFilter(BaseFilterSet): if not role: return queryset.none() queryset = queryset.prefetch_related('role_bindings') \ - .filter(role_bindings__role_id=role.id, role_bindings__role__scope='org') \ + .filter(role_bindings__role_id=role.id) \ + .filter(role_bindings__role__scope='org') \ .distinct() return queryset From 93932f1904fa7d47224d1a3c1a6d29f42a4bcce4 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Thu, 2 Feb 2023 20:10:48 +0800 Subject: [PATCH 61/92] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E6=9B=B4=E6=96=B0=20(#9418)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * perf: 优化批量更新 * perf: 优化代码,减少 80%,依然可用 --------- Co-authored-by: ibuler --- apps/assets/serializers/asset/common.py | 4 ++-- apps/common/serializers/common.py | 12 +++++------- apps/common/serializers/mixin.py | 4 ++-- apps/orgs/mixins/serializers.py | 4 ++-- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/apps/assets/serializers/asset/common.py b/apps/assets/serializers/asset/common.py index e51c4558f..d4643d9ac 100644 --- a/apps/assets/serializers/asset/common.py +++ b/apps/assets/serializers/asset/common.py @@ -119,8 +119,8 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali 'nodes_display', 'accounts' ] read_only_fields = [ - 'category', 'type', 'connectivity', 'date_verified', - 'created_by', 'date_created' + 'category', 'type', 'connectivity', + 'date_verified', 'created_by', 'date_created' ] fields = fields_small + fields_fk + fields_m2m + read_only_fields extra_kwargs = { diff --git a/apps/common/serializers/common.py b/apps/common/serializers/common.py index 805aaa453..1515fe911 100644 --- a/apps/common/serializers/common.py +++ b/apps/common/serializers/common.py @@ -1,15 +1,13 @@ - -from rest_framework import serializers -from rest_framework.serializers import Serializer -from rest_framework.serializers import ModelSerializer -from rest_framework_bulk.serializers import BulkListSerializer -from django.utils.translation import gettext_lazy as _ from django.utils.functional import cached_property +from django.utils.translation import gettext_lazy as _ from drf_writable_nested.serializers import WritableNestedModelSerializer as NestedModelSerializer +from rest_framework import serializers +from rest_framework.serializers import ModelSerializer +from rest_framework.serializers import Serializer +from rest_framework_bulk.serializers import BulkListSerializer from .mixin import BulkListSerializerMixin, BulkSerializerMixin - __all__ = [ 'MethodSerializer', 'EmptySerializer', 'BulkModelSerializer', 'AdaptedBulkListSerializer', 'CeleryTaskExecutionSerializer', diff --git a/apps/common/serializers/mixin.py b/apps/common/serializers/mixin.py index 749a39820..734b6b4d9 100644 --- a/apps/common/serializers/mixin.py +++ b/apps/common/serializers/mixin.py @@ -1,4 +1,4 @@ -from collections import Iterable +from collections import Iterable, defaultdict from django.core.exceptions import ObjectDoesNotExist from django.db.models import NOT_PROVIDED @@ -362,7 +362,7 @@ class CommonModelSerializer(CommonSerializerMixin, serializers.ModelSerializer): class CommonBulkSerializerMixin(BulkSerializerMixin, CommonSerializerMixin): - pass + _save_kwargs = defaultdict(dict) class CommonBulkModelSerializer(CommonBulkSerializerMixin, serializers.ModelSerializer): diff --git a/apps/orgs/mixins/serializers.py b/apps/orgs/mixins/serializers.py index 7ff66cf59..e2e5a48a8 100644 --- a/apps/orgs/mixins/serializers.py +++ b/apps/orgs/mixins/serializers.py @@ -4,9 +4,9 @@ from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers from rest_framework.validators import UniqueTogetherValidator -from common.validators import ProjectUniqueValidator -from common.serializers import BulkSerializerMixin, CommonSerializerMixin, CommonModelSerializer, \ +from common.serializers import CommonModelSerializer, \ CommonBulkModelSerializer +from common.validators import ProjectUniqueValidator from ..utils import get_current_org_id_for_serializer __all__ = [ From 003feb1aed84099d92fe68b3985aea3308c1e59a Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Thu, 2 Feb 2023 22:58:18 +0800 Subject: [PATCH 62/92] perf: command log risk choice (#9419) Co-authored-by: feng <1304903146@qq.com> --- apps/audits/signal_handlers.py | 3 +-- apps/terminal/api/session/command.py | 7 ++++--- apps/terminal/backends/__init__.py | 2 -- apps/terminal/serializers/__init__.py | 5 +++-- .../command/serializers.py => serializers/command.py} | 6 ++++-- 5 files changed, 12 insertions(+), 11 deletions(-) rename apps/terminal/{backends/command/serializers.py => serializers/command.py} (92%) diff --git a/apps/audits/signal_handlers.py b/apps/audits/signal_handlers.py index 9a33c2ef2..9741d93f6 100644 --- a/apps/audits/signal_handlers.py +++ b/apps/audits/signal_handlers.py @@ -26,9 +26,8 @@ from common.signals import django_ready from common.utils import get_request_ip, get_logger, get_syslogger from common.utils.encode import data_to_json from jumpserver.utils import current_request -from terminal.backends.command.serializers import SessionCommandSerializer from terminal.models import Session, Command -from terminal.serializers import SessionSerializer +from terminal.serializers import SessionSerializer, SessionCommandSerializer from users.models import User from users.signals import post_user_change_password from . import models, serializers diff --git a/apps/terminal/api/session/command.py b/apps/terminal/api/session/command.py index 3858aca07..86d56b026 100644 --- a/apps/terminal/api/session/command.py +++ b/apps/terminal/api/session/command.py @@ -11,11 +11,12 @@ from terminal.filters import CommandFilter from orgs.utils import current_org from common.api import JMSBulkModelViewSet from common.utils import get_logger -from terminal.backends.command.serializers import InsecureCommandAlertSerializer +from terminal.serializers import ( + SessionCommandSerializer, InsecureCommandAlertSerializer +) from terminal.exceptions import StorageInvalid from terminal.backends import ( - get_command_storage, get_multi_command_storage, - SessionCommandSerializer, + get_command_storage, get_multi_command_storage ) from terminal.notifications import CommandAlertMessage diff --git a/apps/terminal/backends/__init__.py b/apps/terminal/backends/__init__.py index 4b3dbfa5f..450cc5435 100644 --- a/apps/terminal/backends/__init__.py +++ b/apps/terminal/backends/__init__.py @@ -3,8 +3,6 @@ from django.conf import settings from django.utils.functional import LazyObject from common.utils import get_logger -from .command.serializers import SessionCommandSerializer - logger = get_logger(__file__) diff --git a/apps/terminal/serializers/__init__.py b/apps/terminal/serializers/__init__.py index 019c3623c..92d535c65 100644 --- a/apps/terminal/serializers/__init__.py +++ b/apps/terminal/serializers/__init__.py @@ -1,9 +1,10 @@ # -*- coding: utf-8 -*- # -from .terminal import * +from .applet import * +from .command import * from .session import * from .storage import * from .sharing import * +from .terminal import * from .endpoint import * -from .applet import * from .applet_host import * diff --git a/apps/terminal/backends/command/serializers.py b/apps/terminal/serializers/command.py similarity index 92% rename from apps/terminal/backends/command/serializers.py rename to apps/terminal/serializers/command.py index 63920a846..e1ddba74a 100644 --- a/apps/terminal/backends/command/serializers.py +++ b/apps/terminal/serializers/command.py @@ -3,18 +3,20 @@ from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers from common.utils import pretty_string -from .models import AbstractSessionCommand +from common.serializers.fields import LabeledChoiceField +from terminal.backends.command.models import AbstractSessionCommand __all__ = ['SessionCommandSerializer', 'InsecureCommandAlertSerializer'] class SimpleSessionCommandSerializer(serializers.Serializer): + """ 简单Session命令序列类, 用来提取公共字段 """ user = serializers.CharField(label=_("User")) # 限制 64 字符,见 validate_user asset = serializers.CharField(max_length=128, label=_("Asset")) input = serializers.CharField(max_length=2048, label=_("Command")) session = serializers.CharField(max_length=36, label=_("Session ID")) - risk_level = serializers.ChoiceField( + risk_level = LabeledChoiceField( required=False, label=_("Risk level"), choices=AbstractSessionCommand.RISK_LEVEL_CHOICES ) org_id = serializers.CharField( From cb4410391cc6c983f04cda7850c48e7b20b16de6 Mon Sep 17 00:00:00 2001 From: jiangweidong <80373698+Hi-JWD@users.noreply.github.com> Date: Fri, 3 Feb 2023 11:27:04 +0800 Subject: [PATCH 63/92] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8Dmongodb=20ssl?= =?UTF-8?q?=E8=B4=A6=E5=8F=B7=E6=B5=8B=E8=AF=95=E5=A4=B1=E8=B4=A5=EF=BC=8C?= =?UTF-8?q?oracle=E6=8E=A8=E9=80=81=E7=94=A8=E6=88=B7=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20(#9421)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/automations/base/manager.py | 5 ++++- .../automations/change_secret/database/oracle/main.yml | 1 - 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/accounts/automations/base/manager.py b/apps/accounts/automations/base/manager.py index f39a1847e..d2e96c7a6 100644 --- a/apps/accounts/automations/base/manager.py +++ b/apps/accounts/automations/base/manager.py @@ -16,7 +16,10 @@ class PushOrVerifyHostCallbackMixin: generate_private_key_path: callable def host_callback(self, host, asset=None, account=None, automation=None, path_dir=None, **kwargs): - host = super().host_callback(host, asset=asset, account=account, automation=automation, **kwargs) + host = super().host_callback( + host, asset=asset, account=account, automation=automation, + path_dir=path_dir, **kwargs + ) if host.get('error'): return host diff --git a/apps/accounts/automations/change_secret/database/oracle/main.yml b/apps/accounts/automations/change_secret/database/oracle/main.yml index a58d776a7..ad58e0584 100644 --- a/apps/accounts/automations/change_secret/database/oracle/main.yml +++ b/apps/accounts/automations/change_secret/database/oracle/main.yml @@ -39,7 +39,6 @@ login_host: "{{ jms_asset.address }}" login_port: "{{ jms_asset.port }}" login_database: "{{ jms_asset.spec_info.db_name }}" - mode: "{{ account.mode }}" when: - db_info is succeeded - change_info is succeeded From 88638187a510f3fb6af99f19dc8a3d5d70b635a3 Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 3 Feb 2023 11:14:24 +0800 Subject: [PATCH 64/92] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20role=20?= =?UTF-8?q?=E5=85=8B=E9=9A=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/rbac/api/role.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/rbac/api/role.py b/apps/rbac/api/role.py index dd0220692..c828a4978 100644 --- a/apps/rbac/api/role.py +++ b/apps/rbac/api/role.py @@ -1,13 +1,13 @@ from django.db.models import Count from django.utils.translation import ugettext as _ -from rest_framework.exceptions import PermissionDenied from rest_framework.decorators import action +from rest_framework.exceptions import PermissionDenied from common.api import JMSModelViewSet -from ..filters import RoleFilter -from ..serializers import RoleSerializer, RoleUserSerializer -from ..models import Role, SystemRole, OrgRole from .permission import PermissionViewSet +from ..filters import RoleFilter +from ..models import Role, SystemRole, OrgRole +from ..serializers import RoleSerializer, RoleUserSerializer __all__ = [ 'RoleViewSet', 'SystemRoleViewSet', 'OrgRoleViewSet', @@ -52,7 +52,7 @@ class RoleViewSet(JMSModelViewSet): clone = Role.objects.filter(id=clone_from).first() if not clone: return - instance.permissions.set(clone.permissions.all()) + instance.permissions.set(clone.get_permissions()) def perform_update(self, serializer): instance = serializer.instance From 55de785947222810d74f5c68de1a6b31fc15a6d0 Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 3 Feb 2023 12:22:27 +0800 Subject: [PATCH 65/92] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E6=9C=80?= =?UTF-8?q?=E5=90=8E=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/signal_handlers.py | 37 +++++++++++++++++-- apps/locale/zh/LC_MESSAGES/django.po | 2 +- apps/settings/signal_handlers.py | 18 +-------- .../migrations/0042_auto_20230203_1201.py | 23 ++++++++++++ apps/users/models/user.py | 6 +-- apps/users/serializers/user.py | 17 +++++---- 6 files changed, 72 insertions(+), 31 deletions(-) create mode 100644 apps/users/migrations/0042_auto_20230203_1201.py diff --git a/apps/common/signal_handlers.py b/apps/common/signal_handlers.py index 4471edb94..660cb4b95 100644 --- a/apps/common/signal_handlers.py +++ b/apps/common/signal_handlers.py @@ -1,15 +1,16 @@ # -*- coding: utf-8 -*- # -import re -import os import logging +import re from collections import defaultdict + from django.conf import settings from django.core.signals import request_finished from django.db import connection +from django.db.models.signals import pre_save +from django.dispatch import receiver from jumpserver.utils import get_current_request - from .local import thread_local pattern = re.compile(r'FROM `(\w+)`') @@ -83,6 +84,36 @@ def on_request_finished_release_local(sender, **kwargs): thread_local.__release_local__() +def _get_request_user_name(): + user_name = 'System' + current_request = get_current_request() + if current_request and current_request.user.is_authenticated: + user_name = current_request.user.name + if isinstance(user_name, str): + user_name = user_name[:30] + return user_name + + +@receiver(pre_save) +def on_create_set_created_by(sender, instance=None, **kwargs): + if getattr(instance, '_ignore_auto_created_by', False): + return + if not hasattr(instance, 'created_by') or instance.created_by: + return + user_name = _get_request_user_name() + instance.created_by = user_name + + +@receiver(pre_save) +def on_update_set_updated_by(sender, instance=None, created=False, **kwargs): + if getattr(instance, '_ignore_auto_updated_by', False): + return + if not hasattr(instance, 'updated_by'): + return + user_name = _get_request_user_name() + instance.updated_by = user_name + + if settings.DEBUG_DEV: request_finished.connect(on_request_finished_logging_db_query) else: diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 1f16f7a8f..7d6549fe3 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -2887,7 +2887,7 @@ msgstr "忽略时间" #: common/db/models.py:34 msgid "Updated by" -msgstr "更新人" +msgstr "最后更新者" #: common/db/validators.py:9 #, fuzzy diff --git a/apps/settings/signal_handlers.py b/apps/settings/signal_handlers.py index 7568de368..f4f4c74ce 100644 --- a/apps/settings/signal_handlers.py +++ b/apps/settings/signal_handlers.py @@ -3,18 +3,15 @@ import json from django.conf import LazySettings -from django.db.models.signals import post_save, pre_save +from django.db.models.signals import post_save from django.db.utils import ProgrammingError, OperationalError from django.dispatch import receiver from django.utils.functional import LazyObject -from jumpserver.utils import current_request - from common.decorator import on_transaction_commit from common.signals import django_ready from common.utils import get_logger, ssh_key_gen from common.utils.connection import RedisPubSub - from .models import Setting logger = get_logger(__file__) @@ -58,19 +55,6 @@ def auto_generate_terminal_host_key(sender, **kwargs): pass -@receiver(pre_save, dispatch_uid="my_unique_identifier") -def on_create_set_created_by(sender, instance=None, **kwargs): - if getattr(instance, '_ignore_auto_created_by', False) is True: - return - if not hasattr(instance, 'created_by') or instance.created_by: - return - if current_request and current_request.user.is_authenticated: - user_name = current_request.user.name - if isinstance(user_name, str): - user_name = user_name[:30] - instance.created_by = user_name - - @receiver(django_ready) def subscribe_settings_change(sender, **kwargs): logger.debug("Start subscribe setting change") diff --git a/apps/users/migrations/0042_auto_20230203_1201.py b/apps/users/migrations/0042_auto_20230203_1201.py new file mode 100644 index 000000000..d434ea12d --- /dev/null +++ b/apps/users/migrations/0042_auto_20230203_1201.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.14 on 2023-02-03 04:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0041_auto_20221220_1956'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='date_updated', + field=models.DateTimeField(auto_now=True, verbose_name='Date updated'), + ), + migrations.AddField( + model_name='user', + name='updated_by', + field=models.CharField(blank=True, default='', max_length=30, verbose_name='Updated by'), + ), + ] diff --git a/apps/users/models/user.py b/apps/users/models/user.py index b77d1151f..6996f6603 100644 --- a/apps/users/models/user.py +++ b/apps/users/models/user.py @@ -718,9 +718,8 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser): default=date_expired_default, blank=True, null=True, db_index=True, verbose_name=_('Date expired') ) - created_by = models.CharField( - max_length=30, default='', blank=True, verbose_name=_('Created by') - ) + created_by = models.CharField(max_length=30, default='', blank=True, verbose_name=_('Created by')) + updated_by = models.CharField(max_length=30, default='', blank=True, verbose_name=_('Updated by')) source = models.CharField( max_length=30, default=Source.local, choices=Source.choices, @@ -733,6 +732,7 @@ class User(AuthMixin, TokenMixin, RoleMixin, MFAMixin, AbstractUser): need_update_password = models.BooleanField( default=False, verbose_name=_('Need update password') ) + date_updated = models.DateTimeField(auto_now=True, verbose_name=_('Date updated')) wecom_id = models.CharField(null=True, default=None, unique=True, max_length=128, verbose_name=_('WeCom')) dingtalk_id = models.CharField(null=True, default=None, unique=True, max_length=128, verbose_name=_('DingTalk')) feishu_id = models.CharField(null=True, default=None, unique=True, max_length=128, verbose_name=_('FeiShu')) diff --git a/apps/users/serializers/user.py b/apps/users/serializers/user.py index d1cd63fc5..74c182fed 100644 --- a/apps/users/serializers/user.py +++ b/apps/users/serializers/user.py @@ -115,17 +115,21 @@ class UserSerializer(RolesSerializerMixin, CommonBulkSerializerMixin, serializer # small 指的是 不需要计算的直接能从一张表中获取到的数据 fields_small = fields_mini + fields_write_only + [ "email", "wechat", "phone", "mfa_level", "source", - "need_update_password", "mfa_enabled", + "wecom_id", "dingtalk_id", "feishu_id", + "created_by", "updated_by", "comment", # 通用字段 + ] + fields_date = [ + "date_expired", "date_joined", + "last_login", "date_updated" # 日期字段 + ] + fields_bool = [ "is_service_account", "is_valid", "is_expired", "is_active", # 布尔字段 "is_otp_secret_key_bound", "can_public_key_auth", - "date_expired", "date_joined", - "last_login", # 日期字段 - "created_by", "comment", # 通用字段 - "wecom_id", "dingtalk_id", "feishu_id", + "mfa_enabled", "need_update_password", ] # 包含不太常用的字段,可以没有 - fields_verbose = fields_small + [ + fields_verbose = fields_small + fields_date + fields_bool + [ "mfa_force_enabled", "is_first_login", "date_password_last_updated", "avatar_url", ] @@ -281,7 +285,6 @@ class ServiceAccountSerializer(serializers.ModelSerializer): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) from authentication.serializers import AccessKeySerializer - self.fields["access_key"] = AccessKeySerializer(read_only=True) def get_username(self): From d2ae6642ebc83f5cfa436892f916790909c80f68 Mon Sep 17 00:00:00 2001 From: Bai Date: Fri, 3 Feb 2023 14:28:32 +0800 Subject: [PATCH 66/92] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E8=B4=A6=E5=8F=B7=E6=97=B6secret=E4=B8=8D=E6=AD=A3?= =?UTF-8?q?=E7=A1=AE=E5=AF=BC=E8=87=B4=E6=9B=B4=E6=96=B0=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/models/base.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/accounts/models/base.py b/apps/accounts/models/base.py index 37b97f21a..cd1fef5e8 100644 --- a/apps/accounts/models/base.py +++ b/apps/accounts/models/base.py @@ -92,6 +92,9 @@ class BaseAccount(JMSOrgBaseModel): else: return '' + if not public_key: + return '' + public_key_obj = sshpubkeys.SSHKey(public_key) fingerprint = public_key_obj.hash_md5() return fingerprint From c22662a757e54582f2eed2cfb82e0763b2a80b2e Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 3 Feb 2023 14:28:35 +0800 Subject: [PATCH 67/92] perf: use Chromium browser feat: add code dialog --- apps/terminal/applets/chrome/app.py | 7 ++++ apps/terminal/applets/chrome/code_dialog.py | 37 +++++++++++++++++++ .../deploy_applet_host/playbook.yml | 35 +++++++++++------- 3 files changed, 65 insertions(+), 14 deletions(-) create mode 100644 apps/terminal/applets/chrome/code_dialog.py diff --git a/apps/terminal/applets/chrome/app.py b/apps/terminal/applets/chrome/app.py index 491f1e09d..426320f4f 100644 --- a/apps/terminal/applets/chrome/app.py +++ b/apps/terminal/applets/chrome/app.py @@ -7,6 +7,7 @@ from selenium.webdriver.chrome.service import Service from selenium.webdriver.common.by import By from selenium.webdriver.remote.webelement import WebElement +from code_dialog import CodeDialog from common import (Asset, User, Account, Platform, Step) from common import (BaseApplication) from common import (notify_err_message, block_input, unblock_input) @@ -16,6 +17,7 @@ class Command(Enum): TYPE = 'type' CLICK = 'click' OPEN = 'open' + CODE = 'code' def _execute_type(ele: WebElement, value: str): @@ -62,6 +64,11 @@ class StepAction: ele.click() elif self.command in ['open']: driver.get(self.value) + elif self.command == 'code': + unblock_input() + code_string = CodeDialog(title="Code Dialog", label="Code").wait_string() + block_input() + ele.send_keys(code_string) return True def _execute_command_type(self, ele, value): diff --git a/apps/terminal/applets/chrome/code_dialog.py b/apps/terminal/applets/chrome/code_dialog.py new file mode 100644 index 000000000..b3b93730c --- /dev/null +++ b/apps/terminal/applets/chrome/code_dialog.py @@ -0,0 +1,37 @@ +import tkinter as tk +from tkinter import StringVar, messagebox +from tkinter import ttk + + +class CodeDialog(object): + + def __init__(self, title=None, label="Code Dialog"): + self.root = tk.Tk() + self.root.title(title) + self.code = StringVar() + mainframe = ttk.Frame(self.root, padding="12 12 12 12") + mainframe.grid(column=0, row=0, ) + self.label = ttk.Label(mainframe, text=label, width=10) + self.input = ttk.Entry(mainframe, textvariable=self.code, width=20) + self.button = ttk.Button(mainframe, text="ok", command=self.click_ok, width=5,) + self.label.grid(row=1, column=0) + self.input.grid(row=1, column=1) + self.button.grid(row=2, column=1, sticky=tk.E) + self.root.bind('', self.click_ok) + + def wait_string(self): + # 局中 + self.root.eval('tk::PlaceWindow . center') + self.root.mainloop() + return self.code.get() + + def click_ok(self, *args, **kwargs): + if not self.code.get(): + messagebox.showwarning(title="warning", message="code is empty") + return + self.root.destroy() + + +if __name__ == '__main__': + code = CodeDialog(title="Code Dialog", label="Code: ").wait_string() + print(code) diff --git a/apps/terminal/automations/deploy_applet_host/playbook.yml b/apps/terminal/automations/deploy_applet_host/playbook.yml index 763df39a8..56f6a6b9d 100644 --- a/apps/terminal/automations/deploy_applet_host/playbook.yml +++ b/apps/terminal/automations/deploy_applet_host/playbook.yml @@ -125,33 +125,40 @@ pip install -r '{{ ansible_env.TEMP }}\pip_packages\requirements.txt' --no-index --find-links='{{ ansible_env.TEMP }}\pip_packages' - - name: Download chromedriver (chrome) + - name: Download chromedriver (Chromium) ansible.windows.win_get_url: url: "{{ APPLET_DOWNLOAD_HOST }}/download/applets/chromedriver_win32.zip" dest: "{{ ansible_env.TEMP }}\\chromedriver_win32.zip" - - name: Unzip chromedriver (chrome) + - name: Unzip chromedriver (Chromium) community.windows.win_unzip: src: "{{ ansible_env.TEMP }}\\chromedriver_win32.zip" dest: C:\Program Files\JumpServer\drivers - - name: Set chromedriver on the global system path (chrome) + - name: Download chromium zip package (Chromium) + ansible.windows.win_get_url: + url: "{{ APPLET_DOWNLOAD_HOST }}/download/applets/chrome-win.zip" + dest: "{{ ansible_env.TEMP }}\\chrome-win.zip" + + - name: Unzip chromedriver (Chromium) + community.windows.win_unzip: + src: "{{ ansible_env.TEMP }}\\chrome-win.zip" + dest: C:\Program Files\chrome-win + + - name: Set chromium and driver on the global system path (Chromium) ansible.windows.win_path: elements: + - 'C:\Program Files\chrome-win' - 'C:\Program Files\JumpServer\drivers' - - name: Download chrome msi package (chrome) - ansible.windows.win_get_url: - url: "{{ APPLET_DOWNLOAD_HOST }}/download/applets/googlechromestandaloneenterprise64.msi" - dest: "{{ ansible_env.TEMP }}\\googlechromestandaloneenterprise64.msi" + - name: Set Chromium variables diable Google Api (Chromium) + ansible.windows.win_environment: + level: machine + variables: + GOOGLE_API_KEY: '' + GOOGLE_DEFAULT_CLIENT_ID: '' + GOOGLE_DEFAULT_CLIENT_SECRET: '' - - name: Install chrome (chrome) - ansible.windows.win_package: - path: "{{ ansible_env.TEMP }}\\googlechromestandaloneenterprise64.msi" - state: present - arguments: - - /quiet - - - name: Download navicat161_premium_en package (navicat) ansible.windows.win_get_url: url: "{{ APPLET_DOWNLOAD_HOST }}/download/applets/navicat161_premium_en_x64.exe" From 159652ccfed1ba862297eb6c7075cd4ab64818ae Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 3 Feb 2023 14:41:50 +0800 Subject: [PATCH 68/92] fix: chrome path --- apps/terminal/automations/deploy_applet_host/playbook.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/terminal/automations/deploy_applet_host/playbook.yml b/apps/terminal/automations/deploy_applet_host/playbook.yml index 56f6a6b9d..857982583 100644 --- a/apps/terminal/automations/deploy_applet_host/playbook.yml +++ b/apps/terminal/automations/deploy_applet_host/playbook.yml @@ -143,12 +143,12 @@ - name: Unzip chromedriver (Chromium) community.windows.win_unzip: src: "{{ ansible_env.TEMP }}\\chrome-win.zip" - dest: C:\Program Files\chrome-win + dest: C:\Program Files\Chrome - name: Set chromium and driver on the global system path (Chromium) ansible.windows.win_path: elements: - - 'C:\Program Files\chrome-win' + - 'C:\Program Files\Chrome\chrome-win' - 'C:\Program Files\JumpServer\drivers' - name: Set Chromium variables diable Google Api (Chromium) From afb2b53035ab8f1b7cc2abeaf095211a9247ddc5 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 3 Feb 2023 14:48:41 +0800 Subject: [PATCH 69/92] fix: chromedriver path --- apps/terminal/automations/deploy_applet_host/playbook.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/terminal/automations/deploy_applet_host/playbook.yml b/apps/terminal/automations/deploy_applet_host/playbook.yml index 857982583..2d2f9fdbe 100644 --- a/apps/terminal/automations/deploy_applet_host/playbook.yml +++ b/apps/terminal/automations/deploy_applet_host/playbook.yml @@ -140,7 +140,7 @@ url: "{{ APPLET_DOWNLOAD_HOST }}/download/applets/chrome-win.zip" dest: "{{ ansible_env.TEMP }}\\chrome-win.zip" - - name: Unzip chromedriver (Chromium) + - name: Unzip Chromium (Chromium) community.windows.win_unzip: src: "{{ ansible_env.TEMP }}\\chrome-win.zip" dest: C:\Program Files\Chrome @@ -149,7 +149,7 @@ ansible.windows.win_path: elements: - 'C:\Program Files\Chrome\chrome-win' - - 'C:\Program Files\JumpServer\drivers' + - 'C:\Program Files\JumpServer\drivers\chromedriver_win32' - name: Set Chromium variables diable Google Api (Chromium) ansible.windows.win_environment: From ce8ad5f9ccb19400747514001c6277749f98030c Mon Sep 17 00:00:00 2001 From: Bai Date: Fri, 3 Feb 2023 15:01:31 +0800 Subject: [PATCH 70/92] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E8=B5=84?= =?UTF-8?q?=E4=BA=A7=E6=8E=88=E6=9D=83=E8=A7=84=E5=88=99=E8=BF=87=E6=BB=A4?= =?UTF-8?q?=E6=94=AF=E6=8C=81=20accounts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/perms/filters.py | 12 +++++++++++- apps/perms/models/asset_permission.py | 2 +- apps/perms/serializers/permission.py | 4 ++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/apps/perms/filters.py b/apps/perms/filters.py index 56382cf2d..df6a4e7d1 100644 --- a/apps/perms/filters.py +++ b/apps/perms/filters.py @@ -5,7 +5,7 @@ from common.drf.filters import BaseFilterSet from common.utils import get_object_or_none, is_uuid from users.models import User, UserGroup from assets.models import Node, Asset -from perms.models import AssetPermission +from perms.models import AssetPermission, AssetPermissionQuerySet class PermissionBaseFilter(BaseFilterSet): @@ -94,6 +94,7 @@ class AssetPermissionFilter(PermissionBaseFilter): node_name = filters.CharFilter(method='do_nothing') asset_id = filters.UUIDFilter(method='do_nothing') asset_name = filters.CharFilter(method='do_nothing') + accounts = filters.CharFilter(method='do_nothing') ip = filters.CharFilter(method='do_nothing') class Meta: @@ -111,9 +112,18 @@ class AssetPermissionFilter(PermissionBaseFilter): qs = self.filter_effective(qs) qs = self.filter_asset(qs) qs = self.filter_node(qs) + qs = self.filter_accounts(qs) qs = qs.distinct() return qs + def filter_accounts(self, queryset: AssetPermissionQuerySet): + accounts = self.get_query_param('accounts') + if not accounts: + return queryset + accounts = accounts.split(',') + queryset = queryset.filter_by_accounts(accounts) + return queryset + def filter_node(self, queryset: QuerySet): is_query_all = self.get_query_param('all', True) node_id = self.get_query_param('node_id') diff --git a/apps/perms/models/asset_permission.py b/apps/perms/models/asset_permission.py index 1f14c86fa..232df9162 100644 --- a/apps/perms/models/asset_permission.py +++ b/apps/perms/models/asset_permission.py @@ -15,7 +15,7 @@ from common.utils.timezone import local_now from perms.const import ActionChoices from accounts.const import AliasAccount -__all__ = ['AssetPermission', 'ActionChoices'] +__all__ = ['AssetPermission', 'ActionChoices', 'AssetPermissionQuerySet'] # 使用场景 logger = logging.getLogger(__name__) diff --git a/apps/perms/serializers/permission.py b/apps/perms/serializers/permission.py index fef9929b8..39d64f8d1 100644 --- a/apps/perms/serializers/permission.py +++ b/apps/perms/serializers/permission.py @@ -72,6 +72,10 @@ class AssetPermissionSerializer(BulkOrgResourceModelSerializer): return actions.default = list(actions.choices.keys()) + @staticmethod + def validate_accounts(accounts): + return list(set(accounts)) + @classmethod def setup_eager_loading(cls, queryset): """Perform necessary eager loading of data.""" From ef3a1e399df8eaa7d7a32865873ee860f8f45aad Mon Sep 17 00:00:00 2001 From: Bai Date: Fri, 3 Feb 2023 15:20:37 +0800 Subject: [PATCH 71/92] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E8=B5=84=E4=BA=A7ACL=E4=BC=9A=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E6=89=80=E6=9C=89=E7=BB=84=E7=BB=87=E4=B8=8B=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/acls/models/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/acls/models/base.py b/apps/acls/models/base.py index 53a566048..014fec8bd 100644 --- a/apps/acls/models/base.py +++ b/apps/acls/models/base.py @@ -5,7 +5,7 @@ from django.utils.translation import ugettext_lazy as _ from common.db.models import JMSBaseModel from common.utils import contains_ip -from orgs.mixins.models import OrgModelMixin +from orgs.mixins.models import OrgModelMixin, OrgManager __all__ = [ 'ACLManager', @@ -62,7 +62,7 @@ class UserAssetAccountACLQuerySet(BaseACLQuerySet): return self.filter(q) -class ACLManager(models.Manager): +class ACLManager(OrgManager): def valid(self): return self.get_queryset().valid() From 7c429163ce79fdffb807e06e3801a62284cdb41a Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 3 Feb 2023 16:03:34 +0800 Subject: [PATCH 72/92] =?UTF-8?q?perf:=20=E5=8D=8F=E8=AE=AE=E7=AB=AF?= =?UTF-8?q?=E5=8F=A3=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/asset/asset.py | 6 + apps/assets/serializers/asset/common.py | 7 + apps/authentication/api/connection_token.py | 6 +- apps/locale/ja/LC_MESSAGES/django.po | 519 +++++++++++-------- apps/locale/zh/LC_MESSAGES/django.po | 520 ++++++++++++-------- 5 files changed, 659 insertions(+), 399 deletions(-) diff --git a/apps/assets/api/asset/asset.py b/apps/assets/api/asset/asset.py index d6107631c..1838a4f1a 100644 --- a/apps/assets/api/asset/asset.py +++ b/apps/assets/api/asset/asset.py @@ -2,6 +2,7 @@ # import django_filters from django.db.models import Q +from django.utils.translation import gettext as _ from rest_framework.decorators import action from rest_framework.response import Response @@ -109,6 +110,11 @@ class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet): gateways = asset.domain.gateways return self.get_paginated_response_from_queryset(gateways) + def create(self, request, *args, **kwargs): + if request.path.find('/api/v1/assets/assets/') > -1: + return Response({'error': _('Cannot create asset directly, you should create a host or other')}, status=400) + return super().create(request, *args, **kwargs) + class AssetsTaskMixin: def perform_assets_task(self, serializer): diff --git a/apps/assets/serializers/asset/common.py b/apps/assets/serializers/asset/common.py index d4643d9ac..33ede81ad 100644 --- a/apps/assets/serializers/asset/common.py +++ b/apps/assets/serializers/asset/common.py @@ -57,6 +57,7 @@ class AssetAccountSerializer( template = serializers.BooleanField( default=False, label=_("Template"), write_only=True ) + name = serializers.CharField(max_length=128, required=False, label=_("Name")) class Meta: model = Account @@ -193,6 +194,12 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali protocols_default = [p for p in platform_protocols if p.default] protocols_required = [p for p in platform_protocols if p.required or p.primary] + for p in protocols_data: + port = p.get('port', 0) + if port < 1 or port > 65535: + error = p.get('name') + ': ' + _("port out of range (1-65535)") + raise serializers.ValidationError(error) + if not protocols_data_map: protocols_data_map = { p.name: {'name': p.name, 'port': p.port} diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index ab2783b97..8d3703ef2 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -15,10 +15,10 @@ from rest_framework.response import Response from rest_framework.serializers import ValidationError from common.api import JMSModelViewSet -from common.utils.http import is_true +from common.exceptions import JMSException from common.utils import random_string from common.utils.django import get_request_os -from common.exceptions import JMSException +from common.utils.http import is_true from orgs.mixins.api import RootOrgViewMixin from perms.models import ActionChoices from terminal.connect_methods import NativeClient, ConnectMethodUtil @@ -264,7 +264,7 @@ class ConnectionTokenViewSet(ExtraActionApiMixin, RootOrgViewMixin, JMSModelView msg = _('Account not found') raise JMSException(code='perm_account_invalid', detail=msg) if account.date_expired < timezone.now(): - msg = _('Permission Expired') + msg = _('Permission expired') raise JMSException(code='perm_expired', detail=msg) return account diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index ac8957e43..3bdf16c09 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-31 16:01+0800\n" +"POT-Creation-Date: 2023-02-03 15:49+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -24,11 +24,11 @@ msgstr "パラメータ 'action' は [{}] でなければなりません。" #: accounts/const/account.py:6 #: accounts/serializers/automations/change_secret.py:33 -#: assets/models/_user.py:24 audits/signal_handlers.py:51 +#: assets/models/_user.py:24 audits/signal_handlers.py:50 #: authentication/confirm/password.py:9 authentication/forms.py:32 #: authentication/templates/authentication/login.html:288 #: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:47 -#: users/forms/profile.py:22 users/serializers/user.py:97 +#: users/forms/profile.py:22 users/serializers/user.py:99 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/cloud/serializers/account_attrs.py:28 @@ -187,23 +187,22 @@ msgstr "によって作成された" msgid "Only create" msgstr "作成された日付" -#: accounts/models/account.py:47 accounts/serializers/account/account.py:88 +#: accounts/models/account.py:47 accounts/serializers/account/account.py:80 #: accounts/serializers/automations/change_secret.py:107 #: accounts/serializers/automations/change_secret.py:127 acls/models/base.py:96 #: acls/serializers/base.py:56 assets/models/asset/common.py:97 -#: assets/models/asset/common.py:286 assets/models/cmd_filter.py:36 +#: assets/models/asset/common.py:282 assets/models/cmd_filter.py:36 #: assets/serializers/domain.py:19 assets/serializers/label.py:27 #: audits/models.py:34 authentication/models/connection_token.py:32 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:27 -#: terminal/backends/command/models.py:21 -#: terminal/backends/command/serializers.py:14 -#: terminal/models/session/session.py:31 terminal/notifications.py:93 +#: terminal/backends/command/models.py:21 terminal/models/session/session.py:31 +#: terminal/notifications.py:95 terminal/serializers/command.py:16 #: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:220 msgid "Asset" msgstr "資産" -#: accounts/models/account.py:51 accounts/serializers/account/account.py:92 -#: authentication/serializers/connect_token_secret.py:49 +#: accounts/models/account.py:51 accounts/serializers/account/account.py:84 +#: authentication/serializers/connect_token_secret.py:50 msgid "Su from" msgstr "から切り替え" @@ -212,15 +211,15 @@ msgstr "から切り替え" msgid "Version" msgstr "バージョン" -#: accounts/models/account.py:55 accounts/serializers/account/account.py:89 -#: users/models/user.py:727 +#: accounts/models/account.py:55 accounts/serializers/account/account.py:81 +#: users/models/user.py:726 msgid "Source" msgstr "ソース" #: accounts/models/account.py:58 #: accounts/serializers/automations/change_secret.py:108 #: accounts/serializers/automations/change_secret.py:128 acls/models/base.py:98 -#: acls/serializers/base.py:57 assets/serializers/asset/common.py:121 +#: acls/serializers/base.py:57 assets/serializers/asset/common.py:111 #: assets/serializers/gateway.py:30 audits/models.py:35 ops/models/base.py:18 #: terminal/backends/command/models.py:22 terminal/models/session/session.py:33 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 @@ -243,7 +242,7 @@ msgstr "資産履歴アカウントを表示できます" msgid "Can view asset history account secret" msgstr "資産履歴アカウントパスワードを表示できます" -#: accounts/models/account.py:104 accounts/serializers/account/account.py:34 +#: accounts/models/account.py:104 #, fuzzy msgid "Account template" msgstr "アカウント名" @@ -358,11 +357,11 @@ msgid "Can add push account execution" msgstr "収集アカウントの作成実行" #: accounts/models/automations/change_secret.py:17 accounts/models/base.py:36 -#: accounts/serializers/account/account.py:125 +#: accounts/serializers/account/account.py:117 #: accounts/serializers/account/base.py:16 #: accounts/serializers/automations/change_secret.py:46 -#: authentication/serializers/connect_token_secret.py:40 -#: authentication/serializers/connect_token_secret.py:50 +#: authentication/serializers/connect_token_secret.py:41 +#: authentication/serializers/connect_token_secret.py:51 msgid "Secret type" msgstr "鍵の種類" @@ -410,7 +409,8 @@ msgstr "開始日" msgid "Date finished" msgstr "終了日" -#: accounts/models/automations/change_secret.py:76 common/const/choices.py:20 +#: accounts/models/automations/change_secret.py:76 assets/const/automation.py:8 +#: common/const/choices.py:20 #, fuzzy msgid "Error" msgstr "企業微信エラー" @@ -447,7 +447,7 @@ msgstr "ユーザー名" #: accounts/models/automations/push_account.py:15 acls/models/base.py:77 #: acls/serializers/base.py:81 assets/models/cmd_filter.py:81 #: audits/models.py:51 audits/serializers.py:82 -#: authentication/serializers/connect_token_secret.py:108 +#: authentication/serializers/connect_token_secret.py:109 #: authentication/templates/authentication/_access_key_modal.html:34 msgid "Action" msgstr "アクション" @@ -469,10 +469,11 @@ msgstr "パスワード/キーの確認" #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 #: assets/models/group.py:20 assets/models/label.py:18 #: assets/models/platform.py:20 assets/models/platform.py:74 -#: assets/serializers/asset/common.py:139 assets/serializers/platform.py:125 -#: authentication/serializers/connect_token_secret.py:102 ops/mixin.py:20 +#: assets/serializers/asset/common.py:60 assets/serializers/asset/common.py:128 +#: assets/serializers/platform.py:125 +#: authentication/serializers/connect_token_secret.py:103 ops/mixin.py:20 #: ops/models/adhoc.py:22 ops/models/celery.py:15 ops/models/celery.py:57 -#: ops/models/job.py:25 ops/models/playbook.py:14 orgs/models.py:69 +#: ops/models/job.py:25 ops/models/playbook.py:15 orgs/models.py:69 #: perms/models/asset_permission.py:56 rbac/models/role.py:29 #: settings/models.py:33 settings/serializers/sms.py:6 #: terminal/models/applet/applet.py:24 terminal/models/component/endpoint.py:12 @@ -491,8 +492,8 @@ msgstr "" #: accounts/models/base.py:40 assets/models/asset/common.py:114 #: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 #: assets/models/label.py:22 -#: authentication/serializers/connect_token_secret.py:106 -#: terminal/models/applet/applet.py:29 users/serializers/user.py:158 +#: authentication/serializers/connect_token_secret.py:107 +#: terminal/models/applet/applet.py:29 users/serializers/user.py:159 msgid "Is active" msgstr "アクティブです。" @@ -537,23 +538,23 @@ msgstr "" "{} -暗号化変更タスクが完了しました: 暗号化パスワードが設定されていません-個人" "情報にアクセスしてください-> ファイル暗号化パスワードを設定してください" -#: accounts/serializers/account/account.py:37 +#: accounts/serializers/account/account.py:52 +#: assets/serializers/asset/common.py:58 settings/serializers/auth/sms.py:75 +msgid "Template" +msgstr "テンプレート" + +#: accounts/serializers/account/account.py:55 #: assets/serializers/asset/common.py:55 msgid "Push now" msgstr "" -#: accounts/serializers/account/account.py:39 +#: accounts/serializers/account/account.py:57 #: accounts/serializers/account/base.py:64 #, fuzzy msgid "Has secret" msgstr "ひみつ" -#: accounts/serializers/account/account.py:46 -#: assets/serializers/asset/common.py:82 -msgid "Account template not found" -msgstr "" - -#: accounts/serializers/account/account.py:84 +#: accounts/serializers/account/account.py:76 #, fuzzy #| msgid "Asset Info" msgid "Asset not found" @@ -586,8 +587,11 @@ msgid "Key password" msgstr "キーパスワード" #: accounts/serializers/account/base.py:80 -msgid "Specific" -msgstr "" +#: assets/serializers/asset/common.py:233 +#, fuzzy +#| msgid "Ticket flow" +msgid "Spec info" +msgstr "チケットの流れ" #: accounts/serializers/automations/base.py:22 #: assets/models/automations/base.py:19 @@ -615,9 +619,9 @@ msgstr "製造オーダスナップショット" #: acls/serializers/command_acl.py:18 applications/models.py:14 #: assets/models/_user.py:50 assets/models/automations/base.py:20 #: assets/models/cmd_filter.py:74 assets/models/platform.py:76 -#: assets/serializers/asset/common.py:118 assets/serializers/platform.py:86 +#: assets/serializers/asset/common.py:108 assets/serializers/platform.py:86 #: audits/serializers.py:48 -#: authentication/serializers/connect_token_secret.py:115 ops/models/job.py:33 +#: authentication/serializers/connect_token_secret.py:116 ops/models/job.py:33 #: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:28 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:146 terminal/serializers/applet.py:28 @@ -649,15 +653,14 @@ msgstr "インスタンスタスクの同期実行" #: accounts/serializers/automations/change_secret.py:150 audits/const.py:45 #: audits/handler.py:167 audits/models.py:40 common/const/choices.py:18 -#: ops/const.py:51 ops/serializers/celery.py:39 terminal/const.py:59 +#: ops/const.py:56 ops/serializers/celery.py:39 terminal/const.py:59 #: terminal/models/session/sharing.py:103 tickets/views/approve.py:114 msgid "Success" msgstr "成功" -#: accounts/serializers/automations/change_secret.py:151 -#: assets/const/automation.py:8 audits/const.py:46 audits/handler.py:167 -#: common/const/choices.py:19 ops/const.py:53 terminal/const.py:60 -#: xpack/plugins/cloud/const.py:41 +#: accounts/serializers/automations/change_secret.py:151 audits/const.py:46 +#: audits/handler.py:167 common/const/choices.py:19 ops/const.py:58 +#: terminal/const.py:60 xpack/plugins/cloud/const.py:41 msgid "Failed" msgstr "失敗しました" @@ -735,7 +738,7 @@ msgstr "1-100、低い値は最初に一致します" #: acls/models/base.py:78 acls/serializers/base.py:75 #: acls/serializers/login_acl.py:23 assets/models/cmd_filter.py:86 -#: authentication/serializers/connect_token_secret.py:81 +#: authentication/serializers/connect_token_secret.py:82 msgid "Reviewers" msgstr "レビュー担当者" @@ -757,17 +760,17 @@ msgstr "アクティブ" #: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58 #: perms/serializers/permission.py:23 rbac/builtin.py:119 #: rbac/models/rolebinding.py:41 terminal/backends/command/models.py:20 -#: terminal/backends/command/serializers.py:13 #: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 -#: terminal/notifications.py:94 terminal/notifications.py:142 -#: tickets/models/comment.py:21 users/const.py:14 users/models/user.py:900 -#: users/models/user.py:931 users/serializers/group.py:19 +#: terminal/notifications.py:96 terminal/notifications.py:144 +#: terminal/serializers/command.py:15 tickets/models/comment.py:21 +#: users/const.py:14 users/models/user.py:900 users/models/user.py:931 +#: users/serializers/group.py:19 msgid "User" msgstr "ユーザー" #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 -#: ops/serializers/job.py:53 terminal/backends/command/serializers.py:15 -#: terminal/models/session/session.py:41 terminal/serializers/session.py:19 +#: ops/serializers/job.py:53 terminal/models/session/session.py:41 +#: terminal/serializers/command.py:17 terminal/serializers/session.py:19 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 msgid "Command" @@ -792,7 +795,7 @@ msgstr "家を無視する" #: acls/models/command_acl.py:33 acls/models/command_acl.py:96 #: acls/serializers/command_acl.py:28 -#: authentication/serializers/connect_token_secret.py:78 +#: authentication/serializers/connect_token_secret.py:79 msgid "Command group" msgstr "コマンドグループ" @@ -922,7 +925,7 @@ msgid "Applications" msgstr "アプリケーション" #: applications/models.py:11 assets/models/label.py:21 -#: assets/models/platform.py:75 assets/serializers/asset/common.py:117 +#: assets/models/platform.py:75 assets/serializers/asset/common.py:107 #: assets/serializers/cagegory.py:8 assets/serializers/platform.py:87 #: assets/serializers/platform.py:126 perms/serializers/user_permission.py:25 #: settings/models.py:35 tickets/models/ticket/apply_application.py:13 @@ -957,6 +960,10 @@ msgstr "" "デフォルトポートは9000で、HTTPインタフェースとネイティブインタフェースは異な" "るポートを使用する" +#: assets/api/asset/asset.py:115 +msgid "Cannot create asset directly, you should create a host or other" +msgstr "資産を直接作成することはできません。ホストまたはその他を作成する必要があります" + #: assets/api/domain.py:57 msgid "Number required" msgstr "必要な数" @@ -977,7 +984,7 @@ msgstr "削除に失敗し、ノードにアセットが含まれています。 msgid "App assets" msgstr "アプリ資産" -#: assets/automations/base/manager.py:76 +#: assets/automations/base/manager.py:103 #, fuzzy msgid "{} disabled" msgstr "無効" @@ -1039,7 +1046,7 @@ msgid "Device" msgstr "" #: assets/const/category.py:13 assets/models/asset/database.py:9 -#: assets/models/asset/database.py:24 +#: assets/models/asset/database.py:24 assets/serializers/asset/common.py:95 msgid "Database" msgstr "データベース" @@ -1093,7 +1100,7 @@ msgstr "SSHパブリックキー" #: assets/models/_user.py:27 assets/models/cmd_filter.py:40 #: assets/models/cmd_filter.py:88 assets/models/group.py:23 #: assets/models/platform.py:79 common/db/models.py:37 ops/models/adhoc.py:28 -#: ops/models/job.py:41 ops/models/playbook.py:17 rbac/models/role.py:37 +#: ops/models/job.py:41 ops/models/playbook.py:18 rbac/models/role.py:37 #: settings/models.py:38 terminal/models/applet/applet.py:33 #: terminal/models/applet/applet.py:146 terminal/models/applet/host.py:110 #: terminal/models/component/endpoint.py:24 @@ -1112,13 +1119,13 @@ msgid "Date created" msgstr "作成された日付" #: assets/models/_user.py:29 assets/models/cmd_filter.py:42 -#: common/db/models.py:36 +#: common/db/models.py:36 users/models/user.py:735 msgid "Date updated" msgstr "更新日" #: assets/models/_user.py:30 assets/models/cmd_filter.py:44 #: assets/models/cmd_filter.py:91 assets/models/group.py:21 -#: common/db/models.py:33 users/models/user.py:722 +#: common/db/models.py:33 users/models/user.py:721 #: users/serializers/group.py:33 msgid "Created by" msgstr "によって作成された" @@ -1144,7 +1151,7 @@ msgid "Username same with user" msgstr "ユーザーと同じユーザー名" #: assets/models/_user.py:52 authentication/models/connection_token.py:37 -#: authentication/serializers/connect_token_secret.py:103 +#: authentication/serializers/connect_token_secret.py:104 #: terminal/models/applet/applet.py:31 terminal/serializers/session.py:24 #: terminal/serializers/session.py:45 terminal/serializers/storage.py:68 msgid "Protocol" @@ -1158,7 +1165,7 @@ msgstr "オートプッシュ" msgid "Sudo" msgstr "すど" -#: assets/models/_user.py:55 ops/const.py:44 +#: assets/models/_user.py:55 ops/const.py:49 msgid "Shell" msgstr "シェル" @@ -1195,14 +1202,14 @@ msgid "Can match system user" msgstr "システムユーザーに一致できます" #: assets/models/asset/common.py:109 assets/models/platform.py:111 -#: authentication/serializers/connect_token_secret.py:107 +#: authentication/serializers/connect_token_secret.py:108 #: perms/serializers/user_permission.py:23 #: xpack/plugins/cloud/serializers/account_attrs.py:179 msgid "Platform" msgstr "プラットフォーム" #: assets/models/asset/common.py:111 assets/models/domain.py:21 -#: authentication/serializers/connect_token_secret.py:125 +#: authentication/serializers/connect_token_secret.py:126 #: perms/serializers/user_permission.py:27 msgid "Domain" msgstr "ドメイン" @@ -1211,37 +1218,38 @@ msgstr "ドメイン" msgid "Labels" msgstr "ラベル" -#: assets/models/asset/common.py:289 +#: assets/models/asset/common.py:285 msgid "Can refresh asset hardware info" msgstr "資産ハードウェア情報を更新できます" -#: assets/models/asset/common.py:290 +#: assets/models/asset/common.py:286 msgid "Can test asset connectivity" msgstr "資産接続をテストできます" -#: assets/models/asset/common.py:291 +#: assets/models/asset/common.py:287 #, fuzzy msgid "Can push account to asset" msgstr "システムユーザーを資産にプッシュできます" -#: assets/models/asset/common.py:292 +#: assets/models/asset/common.py:288 #, fuzzy msgid "Can verify account" msgstr "パスワード/キーの確認" -#: assets/models/asset/common.py:293 +#: assets/models/asset/common.py:289 msgid "Can match asset" msgstr "アセットを一致させることができます" -#: assets/models/asset/common.py:294 +#: assets/models/asset/common.py:290 msgid "Add asset to node" msgstr "ノードにアセットを追加する" -#: assets/models/asset/common.py:295 +#: assets/models/asset/common.py:291 msgid "Move asset to node" msgstr "アセットをノードに移動する" -#: assets/models/asset/database.py:10 settings/serializers/email.py:37 +#: assets/models/asset/database.py:10 assets/serializers/asset/common.py:96 +#: settings/serializers/email.py:37 msgid "Use SSL" msgstr "SSLの使用" @@ -1260,12 +1268,12 @@ msgstr "クライアント秘密" msgid "Client key" msgstr "クライアント" -#: assets/models/asset/database.py:14 +#: assets/models/asset/database.py:14 assets/serializers/asset/common.py:97 msgid "Allow invalid cert" msgstr "証明書チェックを無視" #: assets/models/asset/web.py:9 audits/const.py:39 -#: terminal/serializers/applet_host.py:27 +#: terminal/serializers/applet_host.py:28 msgid "Disabled" msgstr "無効" @@ -1275,6 +1283,7 @@ msgid "Basic" msgstr "基本" #: assets/models/asset/web.py:11 assets/models/asset/web.py:17 +#: assets/serializers/asset/common.py:103 msgid "Script" msgstr "" @@ -1283,22 +1292,25 @@ msgstr "" msgid "Autofill" msgstr "自動" -#: assets/models/asset/web.py:14 assets/serializers/platform.py:30 +#: assets/models/asset/web.py:14 assets/serializers/asset/common.py:100 +#: assets/serializers/platform.py:30 #, fuzzy msgid "Username selector" msgstr "ユーザー名のプロパティ" -#: assets/models/asset/web.py:15 assets/serializers/platform.py:33 +#: assets/models/asset/web.py:15 assets/serializers/asset/common.py:101 +#: assets/serializers/platform.py:33 #, fuzzy msgid "Password selector" msgstr "パスワードルール" -#: assets/models/asset/web.py:16 assets/serializers/platform.py:36 +#: assets/models/asset/web.py:16 assets/serializers/asset/common.py:102 +#: assets/serializers/platform.py:36 msgid "Submit selector" msgstr "" #: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38 -#: assets/serializers/asset/common.py:237 perms/models/asset_permission.py:70 +#: assets/serializers/asset/common.py:232 perms/models/asset_permission.py:70 #: perms/serializers/permission.py:32 rbac/tree.py:36 msgid "Accounts" msgstr "アカウント" @@ -1317,7 +1329,7 @@ msgstr "自動管理" #: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:99 #: terminal/models/applet/applet.py:145 terminal/models/applet/host.py:107 #: terminal/models/component/status.py:27 terminal/serializers/applet.py:17 -#: terminal/serializers/applet_host.py:90 tickets/models/ticket/general.py:283 +#: terminal/serializers/applet_host.py:93 tickets/models/ticket/general.py:283 #: tickets/serializers/super_ticket.py:13 #: tickets/serializers/ticket/ticket.py:20 xpack/plugins/cloud/models.py:172 #: xpack/plugins/cloud/models.py:224 @@ -1402,15 +1414,15 @@ msgstr "システム" #: assets/models/label.py:19 assets/models/node.py:558 #: assets/serializers/cagegory.py:7 assets/serializers/cagegory.py:14 #: authentication/models/connection_token.py:25 -#: authentication/serializers/connect_token_secret.py:114 -#: common/serializers/common.py:82 settings/models.py:34 +#: authentication/serializers/connect_token_secret.py:115 +#: common/serializers/common.py:80 settings/models.py:34 msgid "Value" msgstr "値" -#: assets/models/label.py:40 assets/serializers/asset/common.py:119 +#: assets/models/label.py:40 assets/serializers/asset/common.py:109 #: assets/serializers/cagegory.py:6 assets/serializers/cagegory.py:13 -#: authentication/serializers/connect_token_secret.py:113 -#: common/serializers/common.py:81 settings/serializers/sms.py:7 +#: authentication/serializers/connect_token_secret.py:114 +#: common/serializers/common.py:79 settings/serializers/sms.py:7 msgid "Label" msgstr "ラベル" @@ -1454,7 +1466,7 @@ msgid "Setting" msgstr "設定" #: assets/models/platform.py:41 audits/const.py:40 settings/models.py:37 -#: terminal/serializers/applet_host.py:28 +#: terminal/serializers/applet_host.py:29 msgid "Enabled" msgstr "有効化" @@ -1548,37 +1560,42 @@ msgstr "自動管理" msgid "%(value)s is not an even number" msgstr "%(value)s は偶数ではありません" -#: assets/serializers/asset/common.py:120 assets/serializers/platform.py:89 +#: assets/serializers/asset/common.py:99 +#, fuzzy +msgid "Auto fill" +msgstr "自動" + +#: assets/serializers/asset/common.py:110 assets/serializers/platform.py:89 #: authentication/serializers/connect_token_secret.py:28 -#: authentication/serializers/connect_token_secret.py:65 +#: authentication/serializers/connect_token_secret.py:66 #: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:107 #: xpack/plugins/cloud/serializers/task.py:38 msgid "Protocols" msgstr "プロトコル" -#: assets/serializers/asset/common.py:122 -#, fuzzy -#| msgid "Enabled" -msgid "Enabled info" -msgstr "有効化" - -#: assets/serializers/asset/common.py:140 +#: assets/serializers/asset/common.py:129 msgid "Address" msgstr "アドレス" -#: assets/serializers/asset/common.py:141 +#: assets/serializers/asset/common.py:130 msgid "Node path" msgstr "ノードパスです" -#: assets/serializers/asset/common.py:201 -#, fuzzy +#: assets/serializers/asset/common.py:190 msgid "Platform not exist" -msgstr "アプリが存在しません" +msgstr "プラットフォームが存在しません" -#: assets/serializers/asset/common.py:217 -#, fuzzy +#: assets/serializers/asset/common.py:200 +msgid "port out of range (1-65535)" +msgstr "ポート番号が範囲外です (1-65535)" + +#: assets/serializers/asset/common.py:212 msgid "Protocol is required: {}" -msgstr "プロトコル重複: {}" +msgstr "プロトコルが必要です: {}" + +#: assets/serializers/asset/common.py:234 +msgid "Auto info" +msgstr "自動情報" #: assets/serializers/asset/database.py:24 common/serializers/fields.py:100 #: tickets/serializers/ticket/common.py:58 @@ -1627,7 +1644,7 @@ msgid "Disk info" msgstr "ディスク情報" #: assets/serializers/asset/host.py:24 -#: authentication/serializers/connect_token_secret.py:104 +#: authentication/serializers/connect_token_secret.py:105 msgid "OS" msgstr "OS" @@ -1895,8 +1912,7 @@ msgstr "リソースタイプ" msgid "Resource" msgstr "リソース" -#: audits/models.py:60 audits/models.py:103 -#: terminal/backends/command/serializers.py:41 +#: audits/models.py:60 audits/models.py:103 terminal/serializers/command.py:43 msgid "Datetime" msgstr "時間" @@ -1963,41 +1979,47 @@ msgstr "理由表示" msgid "User {} {} this resource." msgstr "ユーザー {} はそれを {} しました" -#: audits/signal_handlers.py:50 +#: audits/signal_handlers.py:49 msgid "SSH Key" msgstr "SSHキー" -#: audits/signal_handlers.py:52 settings/serializers/auth/sso.py:10 +#: audits/signal_handlers.py:51 settings/serializers/auth/sso.py:10 msgid "SSO" msgstr "SSO" -#: audits/signal_handlers.py:53 +#: audits/signal_handlers.py:52 msgid "Auth Token" msgstr "認証トークン" -#: audits/signal_handlers.py:54 authentication/notifications.py:73 +#: audits/signal_handlers.py:53 authentication/notifications.py:73 #: authentication/views/login.py:73 authentication/views/wecom.py:177 #: notifications/backends/__init__.py:11 settings/serializers/auth/wecom.py:10 #: users/models/user.py:736 msgid "WeCom" msgstr "企業微信" -#: audits/signal_handlers.py:55 authentication/views/feishu.py:144 +#: audits/signal_handlers.py:54 authentication/views/feishu.py:144 #: authentication/views/login.py:85 notifications/backends/__init__.py:14 #: settings/serializers/auth/feishu.py:10 users/models/user.py:738 msgid "FeiShu" msgstr "本を飛ばす" -#: audits/signal_handlers.py:56 authentication/views/dingtalk.py:179 +#: audits/signal_handlers.py:55 authentication/views/dingtalk.py:179 #: authentication/views/login.py:79 notifications/backends/__init__.py:12 #: settings/serializers/auth/dingtalk.py:10 users/models/user.py:737 msgid "DingTalk" msgstr "DingTalk" -#: audits/signal_handlers.py:57 authentication/models/temp_token.py:16 +#: audits/signal_handlers.py:56 authentication/models/temp_token.py:16 msgid "Temporary token" msgstr "仮パスワード" +#: audits/tasks.py:37 +#, fuzzy +#| msgid "Job audit log" +msgid "Clean audits log" +msgstr "ジョブ監査ログ" + #: authentication/api/confirm.py:40 msgid "This action require verify your MFA" msgstr "この操作には、MFAを検証する必要があります" @@ -2494,27 +2516,27 @@ msgstr "異なる都市ログインのリマインダー" msgid "binding reminder" msgstr "バインディングリマインダー" -#: authentication/serializers/connect_token_secret.py:105 +#: authentication/serializers/connect_token_secret.py:106 #, fuzzy msgid "Is builtin" msgstr "内蔵" -#: authentication/serializers/connect_token_secret.py:109 +#: authentication/serializers/connect_token_secret.py:110 msgid "Options" msgstr "オプション" -#: authentication/serializers/connect_token_secret.py:116 +#: authentication/serializers/connect_token_secret.py:117 #, fuzzy #| msgid "SystemComponent" msgid "Component" msgstr "システムコンポーネント" -#: authentication/serializers/connect_token_secret.py:127 +#: authentication/serializers/connect_token_secret.py:128 #, fuzzy msgid "Expired now" msgstr "期限切れ" -#: authentication/serializers/connect_token_secret.py:147 +#: authentication/serializers/connect_token_secret.py:148 #: authentication/templates/authentication/_access_key_modal.html:30 #: perms/models/perm_node.py:21 users/serializers/group.py:35 msgid "ID" @@ -2546,10 +2568,16 @@ msgid "The {} cannot be empty" msgstr "{} 空にしてはならない" #: authentication/serializers/token.py:79 perms/serializers/permission.py:30 -#: perms/serializers/permission.py:62 users/serializers/user.py:159 +#: perms/serializers/permission.py:62 users/serializers/user.py:160 msgid "Is valid" msgstr "有効です" +#: authentication/tasks.py:12 +#, fuzzy +#| msgid "Can share session" +msgid "Clean expired session" +msgstr "セッションを共有できます" + #: authentication/templates/authentication/_access_key_modal.html:6 msgid "API key list" msgstr "APIキーリスト" @@ -2563,7 +2591,7 @@ msgid "docs" msgstr "ドキュメント" #: authentication/templates/authentication/_access_key_modal.html:33 -#: terminal/notifications.py:96 terminal/notifications.py:144 +#: terminal/notifications.py:98 terminal/notifications.py:146 msgid "Date" msgstr "日付" @@ -2937,7 +2965,7 @@ msgstr "の準備を" msgid "Pending" msgstr "未定" -#: common/const/choices.py:17 ops/const.py:50 +#: common/const/choices.py:17 ops/const.py:55 msgid "Running" msgstr "" @@ -2986,7 +3014,7 @@ msgstr "は破棄されます" msgid "discard time" msgstr "時間を捨てる" -#: common/db/models.py:34 +#: common/db/models.py:34 users/models/user.py:722 msgid "Updated by" msgstr "によって更新" @@ -3103,11 +3131,11 @@ msgstr "確認コードが正しくありません" msgid "Please wait {} seconds before sending" msgstr "{} 秒待ってから送信してください" -#: common/serializers/common.py:86 +#: common/serializers/common.py:84 msgid "Children" msgstr "" -#: common/serializers/common.py:94 +#: common/serializers/common.py:92 #, fuzzy msgid "File" msgstr "ファイル名" @@ -3131,7 +3159,7 @@ msgstr "" msgid "Invalid choice: {}" msgstr "無効なIP" -#: common/tasks.py:13 +#: common/tasks.py:13 common/utils/verify_code.py:16 #, fuzzy msgid "Send email" msgstr "ユーザーを送信" @@ -3294,36 +3322,46 @@ msgid "All assets use different random password" msgstr "すべての資産は異なるランダムパスワードを使用します" #: ops/const.py:33 +msgid "Blank" +msgstr "" + +#: ops/const.py:34 +#, fuzzy +#| msgid "CAS" +msgid "VCS" +msgstr "CAS" + +#: ops/const.py:38 msgid "Adhoc" msgstr "コマンド#コマンド#" -#: ops/const.py:34 ops/models/job.py:32 +#: ops/const.py:39 ops/models/job.py:32 msgid "Playbook" msgstr "Playbook" -#: ops/const.py:38 +#: ops/const.py:43 msgid "Privileged Only" msgstr "特権アカウントのみ" -#: ops/const.py:39 +#: ops/const.py:44 msgid "Privileged First" msgstr "特権アカウント優先" -#: ops/const.py:40 +#: ops/const.py:45 msgid "Skip" msgstr "スキップ" -#: ops/const.py:45 +#: ops/const.py:50 #, fuzzy #| msgid "PowerShell" msgid "Powershell" msgstr "PowerShell" -#: ops/const.py:46 +#: ops/const.py:51 msgid "Python" msgstr "" -#: ops/const.py:52 +#: ops/const.py:57 #, fuzzy #| msgid "Test timeout" msgid "Timeout" @@ -3372,7 +3410,7 @@ msgid "Args" msgstr "アルグ" #: ops/models/adhoc.py:27 ops/models/base.py:16 ops/models/base.py:53 -#: ops/models/job.py:34 ops/models/job.py:105 ops/models/playbook.py:16 +#: ops/models/job.py:34 ops/models/job.py:105 ops/models/playbook.py:17 #: terminal/models/session/sharing.py:23 msgid "Creator" msgstr "作成者" @@ -3483,6 +3521,16 @@ msgstr "ジョブ実行" msgid "Job audit log" msgstr "ジョブ監査ログ" +#: ops/models/playbook.py:20 +#, fuzzy +#| msgid "Create" +msgid "CreateMethod" +msgstr "作成" + +#: ops/models/playbook.py:21 +msgid "VCS URL" +msgstr "" + #: ops/notifications.py:17 msgid "Server performance" msgstr "サーバーのパフォーマンス" @@ -3751,10 +3799,22 @@ msgid "asset permissions of organization {}" msgstr "組織 {} の資産権限" #: perms/serializers/permission.py:31 perms/serializers/permission.py:61 -#: users/serializers/user.py:91 users/serializers/user.py:161 +#: users/serializers/user.py:93 users/serializers/user.py:162 msgid "Is expired" msgstr "期限切れです" +#: perms/tasks.py:28 +#, fuzzy +#| msgid "Asset permissions is about to expire" +msgid "Check asset permission expired" +msgstr "資産権限の有効期限が近づいています" + +#: perms/tasks.py:40 +#, fuzzy +#| msgid "asset permissions of organization {}" +msgid "Send asset permission expired notification" +msgstr "組織 {} の資産権限" + #: perms/templates/perms/_msg_item_permissions_expire.html:7 #: perms/templates/perms/_msg_permed_items_expire.html:7 #, python-format @@ -4429,10 +4489,6 @@ msgstr "元の番号(Src id)" msgid "Business type(Service id)" msgstr "ビジネス・タイプ(Service id)" -#: settings/serializers/auth/sms.py:75 -msgid "Template" -msgstr "テンプレート" - #: settings/serializers/auth/sms.py:76 #, python-brace-format msgid "" @@ -5365,15 +5421,7 @@ msgstr "" "OpenSSHはリモートアプリケーションをWindowsリモートアプリケーションで接続する" "プログラムです" -#: templates/resource_download.html:48 -msgid "" -"Jmservisor is the program used to pull up remote applications in Windows " -"Remote Application publisher" -msgstr "" -"Jmservisorはwindowsリモートアプリケーションパブリケーションサーバでリモートア" -"プリケーションを引き出すためのプログラムです" - -#: templates/resource_download.html:57 +#: templates/resource_download.html:51 msgid "Offline video player" msgstr "オフラインビデオプレーヤー" @@ -5451,8 +5499,7 @@ msgstr "危険" msgid "Input" msgstr "入力" -#: terminal/backends/command/models.py:24 -#: terminal/backends/command/serializers.py:39 +#: terminal/backends/command/models.py:24 terminal/serializers/command.py:41 msgid "Output" msgstr "出力" @@ -5463,29 +5510,10 @@ msgstr "出力" msgid "Session" msgstr "セッション" -#: terminal/backends/command/models.py:26 -#: terminal/backends/command/serializers.py:18 +#: terminal/backends/command/models.py:26 terminal/serializers/command.py:20 msgid "Risk level" msgstr "リスクレベル" -#: terminal/backends/command/serializers.py:16 -msgid "Session ID" -msgstr "セッションID" - -#: terminal/backends/command/serializers.py:38 -#, fuzzy -msgid "Account " -msgstr "アカウント" - -#: terminal/backends/command/serializers.py:40 -msgid "Timestamp" -msgstr "タイムスタンプ" - -#: terminal/backends/command/serializers.py:42 -#: terminal/models/component/terminal.py:84 -msgid "Remote Address" -msgstr "リモートアドレス" - #: terminal/connect_methods.py:47 terminal/connect_methods.py:48 #: terminal/connect_methods.py:49 terminal/connect_methods.py:50 #: terminal/connect_methods.py:51 @@ -5545,7 +5573,7 @@ msgstr "" msgid "Hosting" msgstr "ホスト" -#: terminal/models/applet/host.py:18 terminal/serializers/applet_host.py:40 +#: terminal/models/applet/host.py:18 terminal/serializers/applet_host.py:43 #, fuzzy msgid "Deploy options" msgstr "その他のログインオプション" @@ -5668,6 +5696,10 @@ msgstr "再生ストレージ" msgid "type" msgstr "タイプ" +#: terminal/models/component/terminal.py:84 terminal/serializers/command.py:44 +msgid "Remote Address" +msgstr "リモートアドレス" + #: terminal/models/component/terminal.py:87 msgid "Application User" msgstr "ユーザーの適用" @@ -5768,19 +5800,19 @@ msgstr "セッション参加記録" msgid "Invalid verification code" msgstr "検証コードが無効" -#: terminal/notifications.py:22 +#: terminal/notifications.py:21 msgid "Sessions" msgstr "セッション" -#: terminal/notifications.py:68 +#: terminal/notifications.py:67 msgid "Danger command alert" msgstr "危険コマンドアラート" -#: terminal/notifications.py:95 terminal/notifications.py:143 +#: terminal/notifications.py:97 terminal/notifications.py:145 msgid "Level" msgstr "レベル" -#: terminal/notifications.py:113 +#: terminal/notifications.py:115 msgid "Batch danger command alert" msgstr "一括危険コマンド警告" @@ -5788,44 +5820,63 @@ msgstr "一括危険コマンド警告" msgid "Icon" msgstr "" -#: terminal/serializers/applet_host.py:23 +#: terminal/serializers/applet_host.py:24 #, fuzzy msgid "Per Session" msgstr "セッション" -#: terminal/serializers/applet_host.py:24 +#: terminal/serializers/applet_host.py:25 msgid "Per Device" msgstr "" -#: terminal/serializers/applet_host.py:30 +#: terminal/serializers/applet_host.py:32 +#, fuzzy +#| msgid "LDAP server" +msgid "API Server" +msgstr "LDAPサーバー" + +#: terminal/serializers/applet_host.py:33 #, fuzzy msgid "RDS Licensing" msgstr "ライセンス" -#: terminal/serializers/applet_host.py:31 +#: terminal/serializers/applet_host.py:34 msgid "RDS License Server" msgstr "" -#: terminal/serializers/applet_host.py:32 +#: terminal/serializers/applet_host.py:35 msgid "RDS Licensing Mode" msgstr "" -#: terminal/serializers/applet_host.py:34 +#: terminal/serializers/applet_host.py:37 msgid "RDS fSingleSessionPerUser" msgstr "" -#: terminal/serializers/applet_host.py:35 +#: terminal/serializers/applet_host.py:38 msgid "RDS Max Disconnection Time" msgstr "" -#: terminal/serializers/applet_host.py:36 +#: terminal/serializers/applet_host.py:39 msgid "RDS Remote App Logoff Time Limit" msgstr "" -#: terminal/serializers/applet_host.py:42 terminal/serializers/terminal.py:41 +#: terminal/serializers/applet_host.py:45 terminal/serializers/terminal.py:41 msgid "Load status" msgstr "ロードステータス" +#: terminal/serializers/command.py:18 +msgid "Session ID" +msgstr "セッションID" + +#: terminal/serializers/command.py:40 +#, fuzzy +msgid "Account " +msgstr "アカウント" + +#: terminal/serializers/command.py:42 +msgid "Timestamp" +msgstr "タイムスタンプ" + #: terminal/serializers/endpoint.py:14 msgid "Oracle port" msgstr "Oracle ポート" @@ -5959,6 +6010,40 @@ msgstr "証明書の検証を無視する" msgid "Not found" msgstr "見つかりません" +#: terminal/tasks.py:31 +#, fuzzy +#| msgid "Periodic clear celery tasks" +msgid "Periodic delete terminal status" +msgstr "定期的にCeleryタスクをクリア" + +#: terminal/tasks.py:40 +#, fuzzy +#| msgid "Can share session" +msgid "Clean orphan session" +msgstr "セッションを共有できます" + +#: terminal/tasks.py:59 +#, fuzzy +#| msgid "Periodic clear celery tasks" +msgid "Periodic clean expired session" +msgstr "定期的にCeleryタスクをクリア" + +#: terminal/tasks.py:85 +#, fuzzy +#| msgid "Can upload session replay" +msgid "Upload session replay to external storage" +msgstr "セッションのリプレイをアップロードできます" + +#: terminal/tasks.py:112 +msgid "Run applet host deployment" +msgstr "" + +#: terminal/tasks.py:119 +#, fuzzy +#| msgid "Install app" +msgid "Install applet" +msgstr "アプリのインストール" + #: terminal/templates/terminal/_msg_command_alert.html:10 msgid "view" msgstr "表示" @@ -6444,7 +6529,7 @@ msgstr "公開キー" msgid "Force enable" msgstr "強制有効" -#: users/models/user.py:687 users/serializers/user.py:160 +#: users/models/user.py:687 users/serializers/user.py:161 msgid "Is service account" msgstr "サービスアカウントです" @@ -6473,15 +6558,15 @@ msgid "Secret key" msgstr "秘密キー" #: users/models/user.py:716 users/serializers/profile.py:149 -#: users/serializers/user.py:157 +#: users/serializers/user.py:158 msgid "Is first login" msgstr "最初のログインです" -#: users/models/user.py:731 +#: users/models/user.py:730 msgid "Date password last updated" msgstr "最終更新日パスワード" -#: users/models/user.py:734 +#: users/models/user.py:733 msgid "Need update password" msgstr "更新パスワードが必要" @@ -6556,47 +6641,47 @@ msgstr "新しいパスワードを最後の {} 個のパスワードにする msgid "The newly set password is inconsistent" msgstr "新しく設定されたパスワードが一致しない" -#: users/serializers/user.py:31 +#: users/serializers/user.py:39 msgid "System roles" msgstr "システムの役割" -#: users/serializers/user.py:35 +#: users/serializers/user.py:43 msgid "Org roles" msgstr "組織ロール" -#: users/serializers/user.py:84 +#: users/serializers/user.py:86 msgid "Password strategy" msgstr "パスワード戦略" -#: users/serializers/user.py:86 +#: users/serializers/user.py:88 msgid "MFA enabled" msgstr "MFA有効化" -#: users/serializers/user.py:88 +#: users/serializers/user.py:90 msgid "MFA force enabled" msgstr "MFAフォース有効化" -#: users/serializers/user.py:90 +#: users/serializers/user.py:92 msgid "Login blocked" msgstr "ログインブロック" -#: users/serializers/user.py:93 +#: users/serializers/user.py:95 msgid "Can public key authentication" msgstr "公開鍵認証が可能" -#: users/serializers/user.py:162 +#: users/serializers/user.py:163 msgid "Avatar url" msgstr "アバターURL" -#: users/serializers/user.py:165 +#: users/serializers/user.py:166 msgid "Is OTP bound" msgstr "仮想MFAがバインドされているか" -#: users/serializers/user.py:272 +#: users/serializers/user.py:273 msgid "Select users" msgstr "ユーザーの選択" -#: users/serializers/user.py:273 +#: users/serializers/user.py:274 msgid "For security, only list several users" msgstr "セキュリティのために、複数のユーザーのみをリストします" @@ -6604,6 +6689,39 @@ msgstr "セキュリティのために、複数のユーザーのみをリスト msgid "name not unique" msgstr "名前が一意ではない" +#: users/tasks.py:24 +#, fuzzy +#| msgid "Password expired" +msgid "Check password expired" +msgstr "パスワード期限切れ" + +#: users/tasks.py:38 +#, fuzzy +#| msgid "Password expired" +msgid "Periodic check password expired" +msgstr "パスワード期限切れ" + +#: users/tasks.py:52 +#, fuzzy +#| msgid "Is expired" +msgid "Check user expired" +msgstr "期限切れです" + +#: users/tasks.py:69 +#, fuzzy +msgid "Periodic check user expired" +msgstr "定期的なパフォーマンス" + +#: users/tasks.py:83 +msgid "Import ldap user" +msgstr "" + +#: users/tasks.py:104 +#, fuzzy +#| msgid "Periodic display" +msgid "Periodic import ldap user" +msgstr "定期的な表示" + #: users/templates/users/_msg_account_expire_reminder.html:7 msgid "Your account will expire in" msgstr "アカウントの有効期限は" @@ -7433,6 +7551,18 @@ msgstr "究極のエディション" msgid "Community edition" msgstr "コミュニティ版" +#, fuzzy +#~| msgid "Enabled" +#~ msgid "Enabled info" +#~ msgstr "有効化" + +#~ msgid "" +#~ "Jmservisor is the program used to pull up remote applications in Windows " +#~ "Remote Application publisher" +#~ msgstr "" +#~ "Jmservisorはwindowsリモートアプリケーションパブリケーションサーバでリモー" +#~ "トアプリケーションを引き出すためのプログラムです" + #, fuzzy #~ msgid "Protocols enabled" #~ msgstr "プロトコル" @@ -7527,10 +7657,6 @@ msgstr "コミュニティ版" #~ msgid "Category display" #~ msgstr "カテゴリ表示" -#, fuzzy -#~ msgid "Auto fill" -#~ msgstr "自動" - #~ msgid "Built-in" #~ msgstr "内蔵" @@ -7668,9 +7794,6 @@ msgstr "コミュニティ版" #~ msgid "Data could not be sent to remote" #~ msgstr "データをリモートに送信できませんでした" -#~ msgid "Periodic display" -#~ msgstr "定期的な表示" - #~ msgid "Gathered user" #~ msgstr "収集されたユーザー" diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 7d6549fe3..84742c7d2 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-31 16:01+0800\n" +"POT-Creation-Date: 2023-02-03 15:49+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -23,11 +23,11 @@ msgstr "参数 'action' 必须是 [{}]" #: accounts/const/account.py:6 #: accounts/serializers/automations/change_secret.py:33 -#: assets/models/_user.py:24 audits/signal_handlers.py:51 +#: assets/models/_user.py:24 audits/signal_handlers.py:50 #: authentication/confirm/password.py:9 authentication/forms.py:32 #: authentication/templates/authentication/login.html:288 #: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:47 -#: users/forms/profile.py:22 users/serializers/user.py:97 +#: users/forms/profile.py:22 users/serializers/user.py:99 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/cloud/serializers/account_attrs.py:28 @@ -177,23 +177,22 @@ msgstr "创建并推送到资产" msgid "Only create" msgstr "仅创建到资产" -#: accounts/models/account.py:47 accounts/serializers/account/account.py:88 +#: accounts/models/account.py:47 accounts/serializers/account/account.py:80 #: accounts/serializers/automations/change_secret.py:107 #: accounts/serializers/automations/change_secret.py:127 acls/models/base.py:96 #: acls/serializers/base.py:56 assets/models/asset/common.py:97 -#: assets/models/asset/common.py:286 assets/models/cmd_filter.py:36 +#: assets/models/asset/common.py:282 assets/models/cmd_filter.py:36 #: assets/serializers/domain.py:19 assets/serializers/label.py:27 #: audits/models.py:34 authentication/models/connection_token.py:32 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:27 -#: terminal/backends/command/models.py:21 -#: terminal/backends/command/serializers.py:14 -#: terminal/models/session/session.py:31 terminal/notifications.py:93 +#: terminal/backends/command/models.py:21 terminal/models/session/session.py:31 +#: terminal/notifications.py:95 terminal/serializers/command.py:16 #: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:220 msgid "Asset" msgstr "资产" -#: accounts/models/account.py:51 accounts/serializers/account/account.py:92 -#: authentication/serializers/connect_token_secret.py:49 +#: accounts/models/account.py:51 accounts/serializers/account/account.py:84 +#: authentication/serializers/connect_token_secret.py:50 msgid "Su from" msgstr "切换自" @@ -202,15 +201,15 @@ msgstr "切换自" msgid "Version" msgstr "版本" -#: accounts/models/account.py:55 accounts/serializers/account/account.py:89 -#: users/models/user.py:727 +#: accounts/models/account.py:55 accounts/serializers/account/account.py:81 +#: users/models/user.py:726 msgid "Source" msgstr "来源" #: accounts/models/account.py:58 #: accounts/serializers/automations/change_secret.py:108 #: accounts/serializers/automations/change_secret.py:128 acls/models/base.py:98 -#: acls/serializers/base.py:57 assets/serializers/asset/common.py:121 +#: acls/serializers/base.py:57 assets/serializers/asset/common.py:111 #: assets/serializers/gateway.py:30 audits/models.py:35 ops/models/base.py:18 #: terminal/backends/command/models.py:22 terminal/models/session/session.py:33 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 @@ -233,7 +232,7 @@ msgstr "可以查看资产历史账号" msgid "Can view asset history account secret" msgstr "可以查看资产历史账号密码" -#: accounts/models/account.py:104 accounts/serializers/account/account.py:34 +#: accounts/models/account.py:104 msgid "Account template" msgstr "账号模版" @@ -348,11 +347,11 @@ msgid "Can add push account execution" msgstr "创建收集账号执行" #: accounts/models/automations/change_secret.py:17 accounts/models/base.py:36 -#: accounts/serializers/account/account.py:125 +#: accounts/serializers/account/account.py:117 #: accounts/serializers/account/base.py:16 #: accounts/serializers/automations/change_secret.py:46 -#: authentication/serializers/connect_token_secret.py:40 -#: authentication/serializers/connect_token_secret.py:50 +#: authentication/serializers/connect_token_secret.py:41 +#: authentication/serializers/connect_token_secret.py:51 msgid "Secret type" msgstr "密文类型" @@ -396,7 +395,8 @@ msgstr "开始日期" msgid "Date finished" msgstr "结束日期" -#: accounts/models/automations/change_secret.py:76 common/const/choices.py:20 +#: accounts/models/automations/change_secret.py:76 assets/const/automation.py:8 +#: common/const/choices.py:20 msgid "Error" msgstr "错误" @@ -430,7 +430,7 @@ msgstr "用户名" #: accounts/models/automations/push_account.py:15 acls/models/base.py:77 #: acls/serializers/base.py:81 assets/models/cmd_filter.py:81 #: audits/models.py:51 audits/serializers.py:82 -#: authentication/serializers/connect_token_secret.py:108 +#: authentication/serializers/connect_token_secret.py:109 #: authentication/templates/authentication/_access_key_modal.html:34 msgid "Action" msgstr "动作" @@ -450,10 +450,11 @@ msgstr "账号验证" #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 #: assets/models/group.py:20 assets/models/label.py:18 #: assets/models/platform.py:20 assets/models/platform.py:74 -#: assets/serializers/asset/common.py:139 assets/serializers/platform.py:125 -#: authentication/serializers/connect_token_secret.py:102 ops/mixin.py:20 +#: assets/serializers/asset/common.py:60 assets/serializers/asset/common.py:128 +#: assets/serializers/platform.py:125 +#: authentication/serializers/connect_token_secret.py:103 ops/mixin.py:20 #: ops/models/adhoc.py:22 ops/models/celery.py:15 ops/models/celery.py:57 -#: ops/models/job.py:25 ops/models/playbook.py:14 orgs/models.py:69 +#: ops/models/job.py:25 ops/models/playbook.py:15 orgs/models.py:69 #: perms/models/asset_permission.py:56 rbac/models/role.py:29 #: settings/models.py:33 settings/serializers/sms.py:6 #: terminal/models/applet/applet.py:24 terminal/models/component/endpoint.py:12 @@ -472,8 +473,8 @@ msgstr "特权账号" #: accounts/models/base.py:40 assets/models/asset/common.py:114 #: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 #: assets/models/label.py:22 -#: authentication/serializers/connect_token_secret.py:106 -#: terminal/models/applet/applet.py:29 users/serializers/user.py:158 +#: authentication/serializers/connect_token_secret.py:107 +#: terminal/models/applet/applet.py:29 users/serializers/user.py:159 msgid "Is active" msgstr "激活" @@ -515,22 +516,22 @@ msgstr "" "{} - 改密任务已完成: 未设置加密密码 - 请前往个人信息 -> 文件加密密码中设置加" "密密码" -#: accounts/serializers/account/account.py:37 +#: accounts/serializers/account/account.py:52 +#: assets/serializers/asset/common.py:58 settings/serializers/auth/sms.py:75 +msgid "Template" +msgstr "模板" + +#: accounts/serializers/account/account.py:55 #: assets/serializers/asset/common.py:55 msgid "Push now" msgstr "立即推送" -#: accounts/serializers/account/account.py:39 +#: accounts/serializers/account/account.py:57 #: accounts/serializers/account/base.py:64 msgid "Has secret" msgstr "已托管密码" -#: accounts/serializers/account/account.py:46 -#: assets/serializers/asset/common.py:82 -msgid "Account template not found" -msgstr "账号模版未找到" - -#: accounts/serializers/account/account.py:84 +#: accounts/serializers/account/account.py:76 msgid "Asset not found" msgstr "资产不存在" @@ -560,7 +561,10 @@ msgid "Key password" msgstr "密钥密码" #: accounts/serializers/account/base.py:80 -msgid "Specific" +#: assets/serializers/asset/common.py:233 +#, fuzzy +#| msgid "Specific" +msgid "Spec info" msgstr "指定的" #: accounts/serializers/automations/base.py:22 @@ -588,9 +592,9 @@ msgstr "工单快照" #: acls/serializers/command_acl.py:18 applications/models.py:14 #: assets/models/_user.py:50 assets/models/automations/base.py:20 #: assets/models/cmd_filter.py:74 assets/models/platform.py:76 -#: assets/serializers/asset/common.py:118 assets/serializers/platform.py:86 +#: assets/serializers/asset/common.py:108 assets/serializers/platform.py:86 #: audits/serializers.py:48 -#: authentication/serializers/connect_token_secret.py:115 ops/models/job.py:33 +#: authentication/serializers/connect_token_secret.py:116 ops/models/job.py:33 #: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:28 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:146 terminal/serializers/applet.py:28 @@ -621,15 +625,14 @@ msgstr "自动化任务执行历史" #: accounts/serializers/automations/change_secret.py:150 audits/const.py:45 #: audits/handler.py:167 audits/models.py:40 common/const/choices.py:18 -#: ops/const.py:51 ops/serializers/celery.py:39 terminal/const.py:59 +#: ops/const.py:56 ops/serializers/celery.py:39 terminal/const.py:59 #: terminal/models/session/sharing.py:103 tickets/views/approve.py:114 msgid "Success" msgstr "成功" -#: accounts/serializers/automations/change_secret.py:151 -#: assets/const/automation.py:8 audits/const.py:46 audits/handler.py:167 -#: common/const/choices.py:19 ops/const.py:53 terminal/const.py:60 -#: xpack/plugins/cloud/const.py:41 +#: accounts/serializers/automations/change_secret.py:151 audits/const.py:46 +#: audits/handler.py:167 common/const/choices.py:19 ops/const.py:58 +#: terminal/const.py:60 xpack/plugins/cloud/const.py:41 msgid "Failed" msgstr "失败" @@ -704,7 +707,7 @@ msgstr "优先级可选范围为 1-100 (数值越小越优先)" #: acls/models/base.py:78 acls/serializers/base.py:75 #: acls/serializers/login_acl.py:23 assets/models/cmd_filter.py:86 -#: authentication/serializers/connect_token_secret.py:81 +#: authentication/serializers/connect_token_secret.py:82 msgid "Reviewers" msgstr "审批人" @@ -726,17 +729,17 @@ msgstr "激活中" #: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58 #: perms/serializers/permission.py:23 rbac/builtin.py:119 #: rbac/models/rolebinding.py:41 terminal/backends/command/models.py:20 -#: terminal/backends/command/serializers.py:13 #: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 -#: terminal/notifications.py:94 terminal/notifications.py:142 -#: tickets/models/comment.py:21 users/const.py:14 users/models/user.py:900 -#: users/models/user.py:931 users/serializers/group.py:19 +#: terminal/notifications.py:96 terminal/notifications.py:144 +#: terminal/serializers/command.py:15 tickets/models/comment.py:21 +#: users/const.py:14 users/models/user.py:900 users/models/user.py:931 +#: users/serializers/group.py:19 msgid "User" msgstr "用户" #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 -#: ops/serializers/job.py:53 terminal/backends/command/serializers.py:15 -#: terminal/models/session/session.py:41 terminal/serializers/session.py:19 +#: ops/serializers/job.py:53 terminal/models/session/session.py:41 +#: terminal/serializers/command.py:17 terminal/serializers/session.py:19 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 msgid "Command" @@ -761,7 +764,7 @@ msgstr "忽略大小写" #: acls/models/command_acl.py:33 acls/models/command_acl.py:96 #: acls/serializers/command_acl.py:28 -#: authentication/serializers/connect_token_secret.py:78 +#: authentication/serializers/connect_token_secret.py:79 msgid "Command group" msgstr "命令组" @@ -889,7 +892,7 @@ msgid "Applications" msgstr "应用管理" #: applications/models.py:11 assets/models/label.py:21 -#: assets/models/platform.py:75 assets/serializers/asset/common.py:117 +#: assets/models/platform.py:75 assets/serializers/asset/common.py:107 #: assets/serializers/cagegory.py:8 assets/serializers/platform.py:87 #: assets/serializers/platform.py:126 perms/serializers/user_permission.py:25 #: settings/models.py:35 tickets/models/ticket/apply_application.py:13 @@ -922,6 +925,10 @@ msgid "" "different ports" msgstr "默认端口为9000, HTTP接口和本机接口使用不同的端口" +#: assets/api/asset/asset.py:115 +msgid "Cannot create asset directly, you should create a host or other" +msgstr "不能直接创建资产, 你应该创建主机或其他资产" + #: assets/api/domain.py:57 msgid "Number required" msgstr "需要为数字" @@ -942,7 +949,7 @@ msgstr "删除失败,节点包含资产" msgid "App assets" msgstr "资产管理" -#: assets/automations/base/manager.py:76 +#: assets/automations/base/manager.py:103 msgid "{} disabled" msgstr "{} 已禁用" @@ -1001,7 +1008,7 @@ msgid "Device" msgstr "网络设备" #: assets/const/category.py:13 assets/models/asset/database.py:9 -#: assets/models/asset/database.py:24 +#: assets/models/asset/database.py:24 assets/serializers/asset/common.py:95 msgid "Database" msgstr "数据库" @@ -1050,7 +1057,7 @@ msgstr "SSH公钥" #: assets/models/_user.py:27 assets/models/cmd_filter.py:40 #: assets/models/cmd_filter.py:88 assets/models/group.py:23 #: assets/models/platform.py:79 common/db/models.py:37 ops/models/adhoc.py:28 -#: ops/models/job.py:41 ops/models/playbook.py:17 rbac/models/role.py:37 +#: ops/models/job.py:41 ops/models/playbook.py:18 rbac/models/role.py:37 #: settings/models.py:38 terminal/models/applet/applet.py:33 #: terminal/models/applet/applet.py:146 terminal/models/applet/host.py:110 #: terminal/models/component/endpoint.py:24 @@ -1069,13 +1076,13 @@ msgid "Date created" msgstr "创建日期" #: assets/models/_user.py:29 assets/models/cmd_filter.py:42 -#: common/db/models.py:36 +#: common/db/models.py:36 users/models/user.py:735 msgid "Date updated" msgstr "更新日期" #: assets/models/_user.py:30 assets/models/cmd_filter.py:44 #: assets/models/cmd_filter.py:91 assets/models/group.py:21 -#: common/db/models.py:33 users/models/user.py:722 +#: common/db/models.py:33 users/models/user.py:721 #: users/serializers/group.py:33 msgid "Created by" msgstr "创建者" @@ -1101,7 +1108,7 @@ msgid "Username same with user" msgstr "用户名与用户相同" #: assets/models/_user.py:52 authentication/models/connection_token.py:37 -#: authentication/serializers/connect_token_secret.py:103 +#: authentication/serializers/connect_token_secret.py:104 #: terminal/models/applet/applet.py:31 terminal/serializers/session.py:24 #: terminal/serializers/session.py:45 terminal/serializers/storage.py:68 msgid "Protocol" @@ -1115,7 +1122,7 @@ msgstr "自动推送" msgid "Sudo" msgstr "Sudo" -#: assets/models/_user.py:55 ops/const.py:44 +#: assets/models/_user.py:55 ops/const.py:49 msgid "Shell" msgstr "Shell" @@ -1152,14 +1159,14 @@ msgid "Can match system user" msgstr "可以匹配系统用户" #: assets/models/asset/common.py:109 assets/models/platform.py:111 -#: authentication/serializers/connect_token_secret.py:107 +#: authentication/serializers/connect_token_secret.py:108 #: perms/serializers/user_permission.py:23 #: xpack/plugins/cloud/serializers/account_attrs.py:179 msgid "Platform" msgstr "系统平台" #: assets/models/asset/common.py:111 assets/models/domain.py:21 -#: authentication/serializers/connect_token_secret.py:125 +#: authentication/serializers/connect_token_secret.py:126 #: perms/serializers/user_permission.py:27 msgid "Domain" msgstr "网域" @@ -1168,37 +1175,38 @@ msgstr "网域" msgid "Labels" msgstr "标签管理" -#: assets/models/asset/common.py:289 +#: assets/models/asset/common.py:285 msgid "Can refresh asset hardware info" msgstr "可以更新资产硬件信息" -#: assets/models/asset/common.py:290 +#: assets/models/asset/common.py:286 msgid "Can test asset connectivity" msgstr "可以测试资产连接性" -#: assets/models/asset/common.py:291 +#: assets/models/asset/common.py:287 msgid "Can push account to asset" msgstr "可以推送账号到资产" -#: assets/models/asset/common.py:292 +#: assets/models/asset/common.py:288 #, fuzzy #| msgid "Verify account" msgid "Can verify account" msgstr "验证账号" -#: assets/models/asset/common.py:293 +#: assets/models/asset/common.py:289 msgid "Can match asset" msgstr "可以匹配资产" -#: assets/models/asset/common.py:294 +#: assets/models/asset/common.py:290 msgid "Add asset to node" msgstr "添加资产到节点" -#: assets/models/asset/common.py:295 +#: assets/models/asset/common.py:291 msgid "Move asset to node" msgstr "移动资产到节点" -#: assets/models/asset/database.py:10 settings/serializers/email.py:37 +#: assets/models/asset/database.py:10 assets/serializers/asset/common.py:96 +#: settings/serializers/email.py:37 msgid "Use SSL" msgstr "使用 SSL" @@ -1214,12 +1222,12 @@ msgstr "客户端证书" msgid "Client key" msgstr "客户端密钥" -#: assets/models/asset/database.py:14 +#: assets/models/asset/database.py:14 assets/serializers/asset/common.py:97 msgid "Allow invalid cert" msgstr "忽略证书校验" #: assets/models/asset/web.py:9 audits/const.py:39 -#: terminal/serializers/applet_host.py:27 +#: terminal/serializers/applet_host.py:28 msgid "Disabled" msgstr "禁用" @@ -1229,6 +1237,7 @@ msgid "Basic" msgstr "基本" #: assets/models/asset/web.py:11 assets/models/asset/web.py:17 +#: assets/serializers/asset/common.py:103 msgid "Script" msgstr "" @@ -1236,20 +1245,23 @@ msgstr "" msgid "Autofill" msgstr "自动代填" -#: assets/models/asset/web.py:14 assets/serializers/platform.py:30 +#: assets/models/asset/web.py:14 assets/serializers/asset/common.py:100 +#: assets/serializers/platform.py:30 msgid "Username selector" msgstr "用户名选择器" -#: assets/models/asset/web.py:15 assets/serializers/platform.py:33 +#: assets/models/asset/web.py:15 assets/serializers/asset/common.py:101 +#: assets/serializers/platform.py:33 msgid "Password selector" msgstr "密码选择器" -#: assets/models/asset/web.py:16 assets/serializers/platform.py:36 +#: assets/models/asset/web.py:16 assets/serializers/asset/common.py:102 +#: assets/serializers/platform.py:36 msgid "Submit selector" msgstr "确认按钮选择器" #: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38 -#: assets/serializers/asset/common.py:237 perms/models/asset_permission.py:70 +#: assets/serializers/asset/common.py:232 perms/models/asset_permission.py:70 #: perms/serializers/permission.py:32 rbac/tree.py:36 msgid "Accounts" msgstr "账号管理" @@ -1268,7 +1280,7 @@ msgstr "自动化任务" #: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:99 #: terminal/models/applet/applet.py:145 terminal/models/applet/host.py:107 #: terminal/models/component/status.py:27 terminal/serializers/applet.py:17 -#: terminal/serializers/applet_host.py:90 tickets/models/ticket/general.py:283 +#: terminal/serializers/applet_host.py:93 tickets/models/ticket/general.py:283 #: tickets/serializers/super_ticket.py:13 #: tickets/serializers/ticket/ticket.py:20 xpack/plugins/cloud/models.py:172 #: xpack/plugins/cloud/models.py:224 @@ -1351,15 +1363,15 @@ msgstr "系统" #: assets/models/label.py:19 assets/models/node.py:558 #: assets/serializers/cagegory.py:7 assets/serializers/cagegory.py:14 #: authentication/models/connection_token.py:25 -#: authentication/serializers/connect_token_secret.py:114 -#: common/serializers/common.py:82 settings/models.py:34 +#: authentication/serializers/connect_token_secret.py:115 +#: common/serializers/common.py:80 settings/models.py:34 msgid "Value" msgstr "值" -#: assets/models/label.py:40 assets/serializers/asset/common.py:119 +#: assets/models/label.py:40 assets/serializers/asset/common.py:109 #: assets/serializers/cagegory.py:6 assets/serializers/cagegory.py:13 -#: authentication/serializers/connect_token_secret.py:113 -#: common/serializers/common.py:81 settings/serializers/sms.py:7 +#: authentication/serializers/connect_token_secret.py:114 +#: common/serializers/common.py:79 settings/serializers/sms.py:7 msgid "Label" msgstr "标签" @@ -1402,7 +1414,7 @@ msgid "Setting" msgstr "设置" #: assets/models/platform.py:41 audits/const.py:40 settings/models.py:37 -#: terminal/serializers/applet_host.py:28 +#: terminal/serializers/applet_host.py:29 msgid "Enabled" msgstr "启用" @@ -1487,36 +1499,44 @@ msgstr "自动化" msgid "%(value)s is not an even number" msgstr "%(value)s is not an even number" -#: assets/serializers/asset/common.py:120 assets/serializers/platform.py:89 +#: assets/serializers/asset/common.py:99 +#, fuzzy +#| msgid "Autofill" +msgid "Auto fill" +msgstr "自动代填" + +#: assets/serializers/asset/common.py:110 assets/serializers/platform.py:89 #: authentication/serializers/connect_token_secret.py:28 -#: authentication/serializers/connect_token_secret.py:65 +#: authentication/serializers/connect_token_secret.py:66 #: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:107 #: xpack/plugins/cloud/serializers/task.py:38 msgid "Protocols" msgstr "协议组" -#: assets/serializers/asset/common.py:122 -#, fuzzy -#| msgid "Enabled" -msgid "Enabled info" -msgstr "启用" - -#: assets/serializers/asset/common.py:140 +#: assets/serializers/asset/common.py:129 msgid "Address" msgstr "地址" -#: assets/serializers/asset/common.py:141 +#: assets/serializers/asset/common.py:130 msgid "Node path" msgstr "节点路径" -#: assets/serializers/asset/common.py:201 +#: assets/serializers/asset/common.py:190 msgid "Platform not exist" msgstr "平台不存在" -#: assets/serializers/asset/common.py:217 +#: assets/serializers/asset/common.py:200 +msgid "port out of range (1-65535)" +msgstr "端口超出范围 (1-65535)" + +#: assets/serializers/asset/common.py:212 msgid "Protocol is required: {}" msgstr "协议是必填的: {}" +#: assets/serializers/asset/common.py:234 +msgid "Auto info" +msgstr "自动化信息" + #: assets/serializers/asset/database.py:24 common/serializers/fields.py:100 #: tickets/serializers/ticket/common.py:58 #: xpack/plugins/cloud/serializers/account_attrs.py:56 @@ -1564,7 +1584,7 @@ msgid "Disk info" msgstr "硬盘信息" #: assets/serializers/asset/host.py:24 -#: authentication/serializers/connect_token_secret.py:104 +#: authentication/serializers/connect_token_secret.py:105 msgid "OS" msgstr "操作系统" @@ -1794,10 +1814,8 @@ msgid "User {} has executed change auth plan for this account.({})" msgstr "用户 {} 为这个账号执行了改密计划.({})" #: audits/handler.py:168 -#, fuzzy -#| msgid "User {} {} it." msgid "User {} login into this service.[{}]" -msgstr "用户 {} {}了它." +msgstr "用户 {} 登录了服务.[{}]" #: audits/models.py:32 audits/models.py:59 audits/models.py:101 #: terminal/models/session/session.py:37 terminal/models/session/sharing.py:95 @@ -1824,8 +1842,7 @@ msgstr "资源类型" msgid "Resource" msgstr "资源" -#: audits/models.py:60 audits/models.py:103 -#: terminal/backends/command/serializers.py:41 +#: audits/models.py:60 audits/models.py:103 terminal/serializers/command.py:43 msgid "Datetime" msgstr "日期" @@ -1887,61 +1904,59 @@ msgid "Reason display" msgstr "原因描述" #: audits/serializers.py:120 -#, fuzzy -#| msgid "User {} {} it." msgid "User {} {} this resource." -msgstr "用户 {} {}了它." +msgstr "用户 {} {} 了当前资源." -#: audits/signal_handlers.py:50 +#: audits/signal_handlers.py:49 msgid "SSH Key" msgstr "SSH 密钥" -#: audits/signal_handlers.py:52 settings/serializers/auth/sso.py:10 +#: audits/signal_handlers.py:51 settings/serializers/auth/sso.py:10 msgid "SSO" msgstr "SSO" -#: audits/signal_handlers.py:53 +#: audits/signal_handlers.py:52 msgid "Auth Token" msgstr "认证令牌" -#: audits/signal_handlers.py:54 authentication/notifications.py:73 +#: audits/signal_handlers.py:53 authentication/notifications.py:73 #: authentication/views/login.py:73 authentication/views/wecom.py:177 #: notifications/backends/__init__.py:11 settings/serializers/auth/wecom.py:10 #: users/models/user.py:736 msgid "WeCom" msgstr "企业微信" -#: audits/signal_handlers.py:55 authentication/views/feishu.py:144 +#: audits/signal_handlers.py:54 authentication/views/feishu.py:144 #: authentication/views/login.py:85 notifications/backends/__init__.py:14 #: settings/serializers/auth/feishu.py:10 users/models/user.py:738 msgid "FeiShu" msgstr "飞书" -#: audits/signal_handlers.py:56 authentication/views/dingtalk.py:179 +#: audits/signal_handlers.py:55 authentication/views/dingtalk.py:179 #: authentication/views/login.py:79 notifications/backends/__init__.py:12 #: settings/serializers/auth/dingtalk.py:10 users/models/user.py:737 msgid "DingTalk" msgstr "钉钉" -#: audits/signal_handlers.py:57 authentication/models/temp_token.py:16 +#: audits/signal_handlers.py:56 authentication/models/temp_token.py:16 msgid "Temporary token" msgstr "临时密码" +#: audits/tasks.py:37 +msgid "Clean audits log" +msgstr "清理审计日志" + #: authentication/api/confirm.py:40 msgid "This action require verify your MFA" msgstr "此操作需要验证您的 MFA" #: authentication/api/connection_token.py:264 -#, fuzzy -#| msgid "Account template not found" msgid "Account not found" -msgstr "账号模版未找到" +msgstr "账号未找到" #: authentication/api/connection_token.py:267 -#, fuzzy -#| msgid "Permission name" msgid "Permission Expired" -msgstr "授权规则名称" +msgstr "授权过期" #: authentication/api/connection_token.py:279 msgid "ACL action is reject" @@ -2406,23 +2421,23 @@ msgstr "异地登录提醒" msgid "binding reminder" msgstr "绑定提醒" -#: authentication/serializers/connect_token_secret.py:105 +#: authentication/serializers/connect_token_secret.py:106 msgid "Is builtin" msgstr "内置的" -#: authentication/serializers/connect_token_secret.py:109 +#: authentication/serializers/connect_token_secret.py:110 msgid "Options" msgstr "选项" -#: authentication/serializers/connect_token_secret.py:116 +#: authentication/serializers/connect_token_secret.py:117 msgid "Component" msgstr "组件" -#: authentication/serializers/connect_token_secret.py:127 +#: authentication/serializers/connect_token_secret.py:128 msgid "Expired now" msgstr "立刻过期" -#: authentication/serializers/connect_token_secret.py:147 +#: authentication/serializers/connect_token_secret.py:148 #: authentication/templates/authentication/_access_key_modal.html:30 #: perms/models/perm_node.py:21 users/serializers/group.py:35 msgid "ID" @@ -2454,10 +2469,16 @@ msgid "The {} cannot be empty" msgstr "{} 不能为空" #: authentication/serializers/token.py:79 perms/serializers/permission.py:30 -#: perms/serializers/permission.py:62 users/serializers/user.py:159 +#: perms/serializers/permission.py:62 users/serializers/user.py:160 msgid "Is valid" msgstr "账号是否有效" +#: authentication/tasks.py:12 +#, fuzzy +#| msgid "Can share session" +msgid "Clean expired session" +msgstr "可以分享会话" + #: authentication/templates/authentication/_access_key_modal.html:6 msgid "API key list" msgstr "API Key列表" @@ -2471,7 +2492,7 @@ msgid "docs" msgstr "文档" #: authentication/templates/authentication/_access_key_modal.html:33 -#: terminal/notifications.py:96 terminal/notifications.py:144 +#: terminal/notifications.py:98 terminal/notifications.py:146 msgid "Date" msgstr "日期" @@ -2837,7 +2858,7 @@ msgstr "准备" msgid "Pending" msgstr "待定的" -#: common/const/choices.py:17 ops/const.py:50 +#: common/const/choices.py:17 ops/const.py:55 msgid "Running" msgstr "运行中" @@ -2885,7 +2906,7 @@ msgstr "忽略的" msgid "discard time" msgstr "忽略时间" -#: common/db/models.py:34 +#: common/db/models.py:34 users/models/user.py:722 msgid "Updated by" msgstr "最后更新者" @@ -3004,11 +3025,11 @@ msgstr "验证码错误" msgid "Please wait {} seconds before sending" msgstr "请在 {} 秒后发送" -#: common/serializers/common.py:86 +#: common/serializers/common.py:84 msgid "Children" msgstr "节点" -#: common/serializers/common.py:94 +#: common/serializers/common.py:92 msgid "File" msgstr "文件" @@ -3030,7 +3051,7 @@ msgstr "错误的数据类型,应该是列表" msgid "Invalid choice: {}" msgstr "无效选项: {}" -#: common/tasks.py:13 +#: common/tasks.py:13 common/utils/verify_code.py:16 msgid "Send email" msgstr "发件邮件" @@ -3183,34 +3204,44 @@ msgid "All assets use different random password" msgstr "各自随机" #: ops/const.py:33 +msgid "Blank" +msgstr "" + +#: ops/const.py:34 +#, fuzzy +#| msgid "CAS" +msgid "VCS" +msgstr "CAS" + +#: ops/const.py:38 msgid "Adhoc" msgstr "命令" -#: ops/const.py:34 ops/models/job.py:32 +#: ops/const.py:39 ops/models/job.py:32 msgid "Playbook" msgstr "Playbook" -#: ops/const.py:38 +#: ops/const.py:43 msgid "Privileged Only" msgstr "仅限特权账号" -#: ops/const.py:39 +#: ops/const.py:44 msgid "Privileged First" msgstr "特权账号优先" -#: ops/const.py:40 +#: ops/const.py:45 msgid "Skip" msgstr "跳过" -#: ops/const.py:45 +#: ops/const.py:50 msgid "Powershell" msgstr "PowerShell" -#: ops/const.py:46 +#: ops/const.py:51 msgid "Python" msgstr "" -#: ops/const.py:52 +#: ops/const.py:57 #, fuzzy #| msgid "Test timeout" msgid "Timeout" @@ -3259,7 +3290,7 @@ msgid "Args" msgstr "参数" #: ops/models/adhoc.py:27 ops/models/base.py:16 ops/models/base.py:53 -#: ops/models/job.py:34 ops/models/job.py:105 ops/models/playbook.py:16 +#: ops/models/job.py:34 ops/models/job.py:105 ops/models/playbook.py:17 #: terminal/models/session/sharing.py:23 msgid "Creator" msgstr "创建者" @@ -3365,6 +3396,16 @@ msgstr "作业执行" msgid "Job audit log" msgstr "作业审计日志" +#: ops/models/playbook.py:20 +#, fuzzy +#| msgid "Create" +msgid "CreateMethod" +msgstr "创建" + +#: ops/models/playbook.py:21 +msgid "VCS URL" +msgstr "" + #: ops/notifications.py:17 msgid "Server performance" msgstr "监控告警" @@ -3619,10 +3660,22 @@ msgid "asset permissions of organization {}" msgstr "组织 ({}) 的资产授权" #: perms/serializers/permission.py:31 perms/serializers/permission.py:61 -#: users/serializers/user.py:91 users/serializers/user.py:161 +#: users/serializers/user.py:93 users/serializers/user.py:162 msgid "Is expired" msgstr "已过期" +#: perms/tasks.py:28 +#, fuzzy +#| msgid "Asset permissions is about to expire" +msgid "Check asset permission expired" +msgstr "资产授权规则将要过期" + +#: perms/tasks.py:40 +#, fuzzy +#| msgid "asset permissions of organization {}" +msgid "Send asset permission expired notification" +msgstr "组织 ({}) 的资产授权" + #: perms/templates/perms/_msg_item_permissions_expire.html:7 #: perms/templates/perms/_msg_permed_items_expire.html:7 #, python-format @@ -4293,10 +4346,6 @@ msgstr "原始号码(Src id)" msgid "Business type(Service id)" msgstr "业务类型(Service id)" -#: settings/serializers/auth/sms.py:75 -msgid "Template" -msgstr "模板" - #: settings/serializers/auth/sms.py:76 #, python-brace-format msgid "" @@ -5193,13 +5242,7 @@ msgid "" "Remote Application Publisher" msgstr "OpenSSH 是在 windows 远程应用发布服务器中用来连接远程应用的程序" -#: templates/resource_download.html:48 -msgid "" -"Jmservisor is the program used to pull up remote applications in Windows " -"Remote Application publisher" -msgstr "Jmservisor 是在 windows 远程应用发布服务器中用来拉起远程应用的程序" - -#: templates/resource_download.html:57 +#: templates/resource_download.html:51 msgid "Offline video player" msgstr "离线录像播放器" @@ -5277,8 +5320,7 @@ msgstr "危险" msgid "Input" msgstr "输入" -#: terminal/backends/command/models.py:24 -#: terminal/backends/command/serializers.py:39 +#: terminal/backends/command/models.py:24 terminal/serializers/command.py:41 msgid "Output" msgstr "输出" @@ -5289,28 +5331,10 @@ msgstr "输出" msgid "Session" msgstr "会话" -#: terminal/backends/command/models.py:26 -#: terminal/backends/command/serializers.py:18 +#: terminal/backends/command/models.py:26 terminal/serializers/command.py:20 msgid "Risk level" msgstr "风险等级" -#: terminal/backends/command/serializers.py:16 -msgid "Session ID" -msgstr "会话ID" - -#: terminal/backends/command/serializers.py:38 -msgid "Account " -msgstr "账号" - -#: terminal/backends/command/serializers.py:40 -msgid "Timestamp" -msgstr "时间戳" - -#: terminal/backends/command/serializers.py:42 -#: terminal/models/component/terminal.py:84 -msgid "Remote Address" -msgstr "远端地址" - #: terminal/connect_methods.py:47 terminal/connect_methods.py:48 #: terminal/connect_methods.py:49 terminal/connect_methods.py:50 #: terminal/connect_methods.py:51 @@ -5367,7 +5391,7 @@ msgstr "" msgid "Hosting" msgstr "宿主机" -#: terminal/models/applet/host.py:18 terminal/serializers/applet_host.py:40 +#: terminal/models/applet/host.py:18 terminal/serializers/applet_host.py:43 msgid "Deploy options" msgstr "部署参数" @@ -5481,6 +5505,10 @@ msgstr "录像存储" msgid "type" msgstr "类型" +#: terminal/models/component/terminal.py:84 terminal/serializers/command.py:44 +msgid "Remote Address" +msgstr "远端地址" + #: terminal/models/component/terminal.py:87 msgid "Application User" msgstr "应用用户" @@ -5581,19 +5609,19 @@ msgstr "会话加入记录" msgid "Invalid verification code" msgstr "验证码不正确" -#: terminal/notifications.py:22 +#: terminal/notifications.py:21 msgid "Sessions" msgstr "会话管理" -#: terminal/notifications.py:68 +#: terminal/notifications.py:67 msgid "Danger command alert" msgstr "危险命令告警" -#: terminal/notifications.py:95 terminal/notifications.py:143 +#: terminal/notifications.py:97 terminal/notifications.py:145 msgid "Level" msgstr "级别" -#: terminal/notifications.py:113 +#: terminal/notifications.py:115 msgid "Batch danger command alert" msgstr "批量危险命令告警" @@ -5601,42 +5629,60 @@ msgstr "批量危险命令告警" msgid "Icon" msgstr "图标" -#: terminal/serializers/applet_host.py:23 +#: terminal/serializers/applet_host.py:24 msgid "Per Session" msgstr "每会话" -#: terminal/serializers/applet_host.py:24 +#: terminal/serializers/applet_host.py:25 msgid "Per Device" msgstr "每设备" -#: terminal/serializers/applet_host.py:30 +#: terminal/serializers/applet_host.py:32 +#, fuzzy +#| msgid "LDAP server" +msgid "API Server" +msgstr "LDAP 地址" + +#: terminal/serializers/applet_host.py:33 msgid "RDS Licensing" msgstr "RDS 许可证" -#: terminal/serializers/applet_host.py:31 +#: terminal/serializers/applet_host.py:34 msgid "RDS License Server" msgstr "RDS 许可服务器" -#: terminal/serializers/applet_host.py:32 +#: terminal/serializers/applet_host.py:35 msgid "RDS Licensing Mode" msgstr "RDS 授权模式" -#: terminal/serializers/applet_host.py:34 +#: terminal/serializers/applet_host.py:37 msgid "RDS fSingleSessionPerUser" msgstr "" -#: terminal/serializers/applet_host.py:35 +#: terminal/serializers/applet_host.py:38 msgid "RDS Max Disconnection Time" msgstr "" -#: terminal/serializers/applet_host.py:36 +#: terminal/serializers/applet_host.py:39 msgid "RDS Remote App Logoff Time Limit" msgstr "" -#: terminal/serializers/applet_host.py:42 terminal/serializers/terminal.py:41 +#: terminal/serializers/applet_host.py:45 terminal/serializers/terminal.py:41 msgid "Load status" msgstr "负载状态" +#: terminal/serializers/command.py:18 +msgid "Session ID" +msgstr "会话ID" + +#: terminal/serializers/command.py:40 +msgid "Account " +msgstr "账号" + +#: terminal/serializers/command.py:42 +msgid "Timestamp" +msgstr "时间戳" + #: terminal/serializers/endpoint.py:14 msgid "Oracle port" msgstr "Oracle 端口" @@ -5768,6 +5814,40 @@ msgstr "忽略证书认证" msgid "Not found" msgstr "没有发现" +#: terminal/tasks.py:31 +#, fuzzy +#| msgid "Periodic clear celery tasks" +msgid "Periodic delete terminal status" +msgstr "周期清理不可用任务" + +#: terminal/tasks.py:40 +#, fuzzy +#| msgid "Can share session" +msgid "Clean orphan session" +msgstr "可以分享会话" + +#: terminal/tasks.py:59 +#, fuzzy +#| msgid "Periodic clear celery tasks" +msgid "Periodic clean expired session" +msgstr "周期清理不可用任务" + +#: terminal/tasks.py:85 +#, fuzzy +#| msgid "Can upload session replay" +msgid "Upload session replay to external storage" +msgstr "可以上传会话录像" + +#: terminal/tasks.py:112 +msgid "Run applet host deployment" +msgstr "" + +#: terminal/tasks.py:119 +#, fuzzy +#| msgid "Install app" +msgid "Install applet" +msgstr "安装应用" + #: terminal/templates/terminal/_msg_command_alert.html:10 msgid "view" msgstr "查看" @@ -6243,7 +6323,7 @@ msgstr "SSH公钥" msgid "Force enable" msgstr "强制启用" -#: users/models/user.py:687 users/serializers/user.py:160 +#: users/models/user.py:687 users/serializers/user.py:161 msgid "Is service account" msgstr "服务账号" @@ -6272,15 +6352,15 @@ msgid "Secret key" msgstr "Secret key" #: users/models/user.py:716 users/serializers/profile.py:149 -#: users/serializers/user.py:157 +#: users/serializers/user.py:158 msgid "Is first login" msgstr "首次登录" -#: users/models/user.py:731 +#: users/models/user.py:730 msgid "Date password last updated" msgstr "最后更新密码日期" -#: users/models/user.py:734 +#: users/models/user.py:733 msgid "Need update password" msgstr "需要更新密码" @@ -6355,47 +6435,47 @@ msgstr "新密码不能是最近 {} 次的密码" msgid "The newly set password is inconsistent" msgstr "两次密码不一致" -#: users/serializers/user.py:31 +#: users/serializers/user.py:39 msgid "System roles" msgstr "系统角色" -#: users/serializers/user.py:35 +#: users/serializers/user.py:43 msgid "Org roles" msgstr "组织角色" -#: users/serializers/user.py:84 +#: users/serializers/user.py:86 msgid "Password strategy" msgstr "密码策略" -#: users/serializers/user.py:86 +#: users/serializers/user.py:88 msgid "MFA enabled" msgstr "MFA 已启用" -#: users/serializers/user.py:88 +#: users/serializers/user.py:90 msgid "MFA force enabled" msgstr "强制 MFA" -#: users/serializers/user.py:90 +#: users/serializers/user.py:92 msgid "Login blocked" msgstr "登录被阻塞" -#: users/serializers/user.py:93 +#: users/serializers/user.py:95 msgid "Can public key authentication" msgstr "公钥认证" -#: users/serializers/user.py:162 +#: users/serializers/user.py:163 msgid "Avatar url" msgstr "头像路径" -#: users/serializers/user.py:165 +#: users/serializers/user.py:166 msgid "Is OTP bound" msgstr "是否绑定了虚拟 MFA" -#: users/serializers/user.py:272 +#: users/serializers/user.py:273 msgid "Select users" msgstr "选择用户" -#: users/serializers/user.py:273 +#: users/serializers/user.py:274 msgid "For security, only list several users" msgstr "为了安全,仅列出几个用户" @@ -6403,6 +6483,40 @@ msgstr "为了安全,仅列出几个用户" msgid "name not unique" msgstr "名称重复" +#: users/tasks.py:24 +#, fuzzy +#| msgid "Password expired" +msgid "Check password expired" +msgstr "密码已过期" + +#: users/tasks.py:38 +#, fuzzy +#| msgid "Password expired" +msgid "Periodic check password expired" +msgstr "密码已过期" + +#: users/tasks.py:52 +#, fuzzy +#| msgid "Is expired" +msgid "Check user expired" +msgstr "已过期" + +#: users/tasks.py:69 +#, fuzzy +#| msgid "Periodic check service performance" +msgid "Periodic check user expired" +msgstr "周期检测服务性能" + +#: users/tasks.py:83 +msgid "Import ldap user" +msgstr "" + +#: users/tasks.py:104 +#, fuzzy +#| msgid "Periodic display" +msgid "Periodic import ldap user" +msgstr "定时执行" + #: users/templates/users/_msg_account_expire_reminder.html:7 msgid "Your account will expire in" msgstr "您的账号即将过期" @@ -7217,6 +7331,19 @@ msgstr "旗舰版" msgid "Community edition" msgstr "社区版" +#~ msgid "Account template not found" +#~ msgstr "账号模版未找到" + +#, fuzzy +#~| msgid "Enabled" +#~ msgid "Enabled info" +#~ msgstr "启用" + +#~ msgid "" +#~ "Jmservisor is the program used to pull up remote applications in Windows " +#~ "Remote Application publisher" +#~ msgstr "Jmservisor 是在 windows 远程应用发布服务器中用来拉起远程应用的程序" + #~ msgid "Protocols enabled" #~ msgstr "启用协议" @@ -7433,9 +7560,6 @@ msgstr "社区版" #~ msgid "Data could not be sent to remote" #~ msgstr "无法将数据发送到远程" -#~ msgid "Periodic display" -#~ msgstr "定时执行" - #~ msgid "Gathered user" #~ msgstr "收集用户" From 470d2703f41ef67422a2f1e341ad7e6c8e421274 Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 3 Feb 2023 16:03:34 +0800 Subject: [PATCH 73/92] =?UTF-8?q?perf:=20=E5=8D=8F=E8=AE=AE=E7=AB=AF?= =?UTF-8?q?=E5=8F=A3=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/asset/asset.py | 6 + apps/assets/serializers/asset/common.py | 7 + apps/authentication/api/connection_token.py | 6 +- apps/locale/ja/LC_MESSAGES/django.po | 519 +++++++++++-------- apps/locale/zh/LC_MESSAGES/django.po | 520 ++++++++++++-------- 5 files changed, 659 insertions(+), 399 deletions(-) diff --git a/apps/assets/api/asset/asset.py b/apps/assets/api/asset/asset.py index d6107631c..1838a4f1a 100644 --- a/apps/assets/api/asset/asset.py +++ b/apps/assets/api/asset/asset.py @@ -2,6 +2,7 @@ # import django_filters from django.db.models import Q +from django.utils.translation import gettext as _ from rest_framework.decorators import action from rest_framework.response import Response @@ -109,6 +110,11 @@ class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet): gateways = asset.domain.gateways return self.get_paginated_response_from_queryset(gateways) + def create(self, request, *args, **kwargs): + if request.path.find('/api/v1/assets/assets/') > -1: + return Response({'error': _('Cannot create asset directly, you should create a host or other')}, status=400) + return super().create(request, *args, **kwargs) + class AssetsTaskMixin: def perform_assets_task(self, serializer): diff --git a/apps/assets/serializers/asset/common.py b/apps/assets/serializers/asset/common.py index d4643d9ac..33ede81ad 100644 --- a/apps/assets/serializers/asset/common.py +++ b/apps/assets/serializers/asset/common.py @@ -57,6 +57,7 @@ class AssetAccountSerializer( template = serializers.BooleanField( default=False, label=_("Template"), write_only=True ) + name = serializers.CharField(max_length=128, required=False, label=_("Name")) class Meta: model = Account @@ -193,6 +194,12 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali protocols_default = [p for p in platform_protocols if p.default] protocols_required = [p for p in platform_protocols if p.required or p.primary] + for p in protocols_data: + port = p.get('port', 0) + if port < 1 or port > 65535: + error = p.get('name') + ': ' + _("port out of range (1-65535)") + raise serializers.ValidationError(error) + if not protocols_data_map: protocols_data_map = { p.name: {'name': p.name, 'port': p.port} diff --git a/apps/authentication/api/connection_token.py b/apps/authentication/api/connection_token.py index ab2783b97..8d3703ef2 100644 --- a/apps/authentication/api/connection_token.py +++ b/apps/authentication/api/connection_token.py @@ -15,10 +15,10 @@ from rest_framework.response import Response from rest_framework.serializers import ValidationError from common.api import JMSModelViewSet -from common.utils.http import is_true +from common.exceptions import JMSException from common.utils import random_string from common.utils.django import get_request_os -from common.exceptions import JMSException +from common.utils.http import is_true from orgs.mixins.api import RootOrgViewMixin from perms.models import ActionChoices from terminal.connect_methods import NativeClient, ConnectMethodUtil @@ -264,7 +264,7 @@ class ConnectionTokenViewSet(ExtraActionApiMixin, RootOrgViewMixin, JMSModelView msg = _('Account not found') raise JMSException(code='perm_account_invalid', detail=msg) if account.date_expired < timezone.now(): - msg = _('Permission Expired') + msg = _('Permission expired') raise JMSException(code='perm_expired', detail=msg) return account diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index ac8957e43..3bdf16c09 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-31 16:01+0800\n" +"POT-Creation-Date: 2023-02-03 15:49+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -24,11 +24,11 @@ msgstr "パラメータ 'action' は [{}] でなければなりません。" #: accounts/const/account.py:6 #: accounts/serializers/automations/change_secret.py:33 -#: assets/models/_user.py:24 audits/signal_handlers.py:51 +#: assets/models/_user.py:24 audits/signal_handlers.py:50 #: authentication/confirm/password.py:9 authentication/forms.py:32 #: authentication/templates/authentication/login.html:288 #: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:47 -#: users/forms/profile.py:22 users/serializers/user.py:97 +#: users/forms/profile.py:22 users/serializers/user.py:99 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/cloud/serializers/account_attrs.py:28 @@ -187,23 +187,22 @@ msgstr "によって作成された" msgid "Only create" msgstr "作成された日付" -#: accounts/models/account.py:47 accounts/serializers/account/account.py:88 +#: accounts/models/account.py:47 accounts/serializers/account/account.py:80 #: accounts/serializers/automations/change_secret.py:107 #: accounts/serializers/automations/change_secret.py:127 acls/models/base.py:96 #: acls/serializers/base.py:56 assets/models/asset/common.py:97 -#: assets/models/asset/common.py:286 assets/models/cmd_filter.py:36 +#: assets/models/asset/common.py:282 assets/models/cmd_filter.py:36 #: assets/serializers/domain.py:19 assets/serializers/label.py:27 #: audits/models.py:34 authentication/models/connection_token.py:32 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:27 -#: terminal/backends/command/models.py:21 -#: terminal/backends/command/serializers.py:14 -#: terminal/models/session/session.py:31 terminal/notifications.py:93 +#: terminal/backends/command/models.py:21 terminal/models/session/session.py:31 +#: terminal/notifications.py:95 terminal/serializers/command.py:16 #: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:220 msgid "Asset" msgstr "資産" -#: accounts/models/account.py:51 accounts/serializers/account/account.py:92 -#: authentication/serializers/connect_token_secret.py:49 +#: accounts/models/account.py:51 accounts/serializers/account/account.py:84 +#: authentication/serializers/connect_token_secret.py:50 msgid "Su from" msgstr "から切り替え" @@ -212,15 +211,15 @@ msgstr "から切り替え" msgid "Version" msgstr "バージョン" -#: accounts/models/account.py:55 accounts/serializers/account/account.py:89 -#: users/models/user.py:727 +#: accounts/models/account.py:55 accounts/serializers/account/account.py:81 +#: users/models/user.py:726 msgid "Source" msgstr "ソース" #: accounts/models/account.py:58 #: accounts/serializers/automations/change_secret.py:108 #: accounts/serializers/automations/change_secret.py:128 acls/models/base.py:98 -#: acls/serializers/base.py:57 assets/serializers/asset/common.py:121 +#: acls/serializers/base.py:57 assets/serializers/asset/common.py:111 #: assets/serializers/gateway.py:30 audits/models.py:35 ops/models/base.py:18 #: terminal/backends/command/models.py:22 terminal/models/session/session.py:33 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 @@ -243,7 +242,7 @@ msgstr "資産履歴アカウントを表示できます" msgid "Can view asset history account secret" msgstr "資産履歴アカウントパスワードを表示できます" -#: accounts/models/account.py:104 accounts/serializers/account/account.py:34 +#: accounts/models/account.py:104 #, fuzzy msgid "Account template" msgstr "アカウント名" @@ -358,11 +357,11 @@ msgid "Can add push account execution" msgstr "収集アカウントの作成実行" #: accounts/models/automations/change_secret.py:17 accounts/models/base.py:36 -#: accounts/serializers/account/account.py:125 +#: accounts/serializers/account/account.py:117 #: accounts/serializers/account/base.py:16 #: accounts/serializers/automations/change_secret.py:46 -#: authentication/serializers/connect_token_secret.py:40 -#: authentication/serializers/connect_token_secret.py:50 +#: authentication/serializers/connect_token_secret.py:41 +#: authentication/serializers/connect_token_secret.py:51 msgid "Secret type" msgstr "鍵の種類" @@ -410,7 +409,8 @@ msgstr "開始日" msgid "Date finished" msgstr "終了日" -#: accounts/models/automations/change_secret.py:76 common/const/choices.py:20 +#: accounts/models/automations/change_secret.py:76 assets/const/automation.py:8 +#: common/const/choices.py:20 #, fuzzy msgid "Error" msgstr "企業微信エラー" @@ -447,7 +447,7 @@ msgstr "ユーザー名" #: accounts/models/automations/push_account.py:15 acls/models/base.py:77 #: acls/serializers/base.py:81 assets/models/cmd_filter.py:81 #: audits/models.py:51 audits/serializers.py:82 -#: authentication/serializers/connect_token_secret.py:108 +#: authentication/serializers/connect_token_secret.py:109 #: authentication/templates/authentication/_access_key_modal.html:34 msgid "Action" msgstr "アクション" @@ -469,10 +469,11 @@ msgstr "パスワード/キーの確認" #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 #: assets/models/group.py:20 assets/models/label.py:18 #: assets/models/platform.py:20 assets/models/platform.py:74 -#: assets/serializers/asset/common.py:139 assets/serializers/platform.py:125 -#: authentication/serializers/connect_token_secret.py:102 ops/mixin.py:20 +#: assets/serializers/asset/common.py:60 assets/serializers/asset/common.py:128 +#: assets/serializers/platform.py:125 +#: authentication/serializers/connect_token_secret.py:103 ops/mixin.py:20 #: ops/models/adhoc.py:22 ops/models/celery.py:15 ops/models/celery.py:57 -#: ops/models/job.py:25 ops/models/playbook.py:14 orgs/models.py:69 +#: ops/models/job.py:25 ops/models/playbook.py:15 orgs/models.py:69 #: perms/models/asset_permission.py:56 rbac/models/role.py:29 #: settings/models.py:33 settings/serializers/sms.py:6 #: terminal/models/applet/applet.py:24 terminal/models/component/endpoint.py:12 @@ -491,8 +492,8 @@ msgstr "" #: accounts/models/base.py:40 assets/models/asset/common.py:114 #: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 #: assets/models/label.py:22 -#: authentication/serializers/connect_token_secret.py:106 -#: terminal/models/applet/applet.py:29 users/serializers/user.py:158 +#: authentication/serializers/connect_token_secret.py:107 +#: terminal/models/applet/applet.py:29 users/serializers/user.py:159 msgid "Is active" msgstr "アクティブです。" @@ -537,23 +538,23 @@ msgstr "" "{} -暗号化変更タスクが完了しました: 暗号化パスワードが設定されていません-個人" "情報にアクセスしてください-> ファイル暗号化パスワードを設定してください" -#: accounts/serializers/account/account.py:37 +#: accounts/serializers/account/account.py:52 +#: assets/serializers/asset/common.py:58 settings/serializers/auth/sms.py:75 +msgid "Template" +msgstr "テンプレート" + +#: accounts/serializers/account/account.py:55 #: assets/serializers/asset/common.py:55 msgid "Push now" msgstr "" -#: accounts/serializers/account/account.py:39 +#: accounts/serializers/account/account.py:57 #: accounts/serializers/account/base.py:64 #, fuzzy msgid "Has secret" msgstr "ひみつ" -#: accounts/serializers/account/account.py:46 -#: assets/serializers/asset/common.py:82 -msgid "Account template not found" -msgstr "" - -#: accounts/serializers/account/account.py:84 +#: accounts/serializers/account/account.py:76 #, fuzzy #| msgid "Asset Info" msgid "Asset not found" @@ -586,8 +587,11 @@ msgid "Key password" msgstr "キーパスワード" #: accounts/serializers/account/base.py:80 -msgid "Specific" -msgstr "" +#: assets/serializers/asset/common.py:233 +#, fuzzy +#| msgid "Ticket flow" +msgid "Spec info" +msgstr "チケットの流れ" #: accounts/serializers/automations/base.py:22 #: assets/models/automations/base.py:19 @@ -615,9 +619,9 @@ msgstr "製造オーダスナップショット" #: acls/serializers/command_acl.py:18 applications/models.py:14 #: assets/models/_user.py:50 assets/models/automations/base.py:20 #: assets/models/cmd_filter.py:74 assets/models/platform.py:76 -#: assets/serializers/asset/common.py:118 assets/serializers/platform.py:86 +#: assets/serializers/asset/common.py:108 assets/serializers/platform.py:86 #: audits/serializers.py:48 -#: authentication/serializers/connect_token_secret.py:115 ops/models/job.py:33 +#: authentication/serializers/connect_token_secret.py:116 ops/models/job.py:33 #: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:28 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:146 terminal/serializers/applet.py:28 @@ -649,15 +653,14 @@ msgstr "インスタンスタスクの同期実行" #: accounts/serializers/automations/change_secret.py:150 audits/const.py:45 #: audits/handler.py:167 audits/models.py:40 common/const/choices.py:18 -#: ops/const.py:51 ops/serializers/celery.py:39 terminal/const.py:59 +#: ops/const.py:56 ops/serializers/celery.py:39 terminal/const.py:59 #: terminal/models/session/sharing.py:103 tickets/views/approve.py:114 msgid "Success" msgstr "成功" -#: accounts/serializers/automations/change_secret.py:151 -#: assets/const/automation.py:8 audits/const.py:46 audits/handler.py:167 -#: common/const/choices.py:19 ops/const.py:53 terminal/const.py:60 -#: xpack/plugins/cloud/const.py:41 +#: accounts/serializers/automations/change_secret.py:151 audits/const.py:46 +#: audits/handler.py:167 common/const/choices.py:19 ops/const.py:58 +#: terminal/const.py:60 xpack/plugins/cloud/const.py:41 msgid "Failed" msgstr "失敗しました" @@ -735,7 +738,7 @@ msgstr "1-100、低い値は最初に一致します" #: acls/models/base.py:78 acls/serializers/base.py:75 #: acls/serializers/login_acl.py:23 assets/models/cmd_filter.py:86 -#: authentication/serializers/connect_token_secret.py:81 +#: authentication/serializers/connect_token_secret.py:82 msgid "Reviewers" msgstr "レビュー担当者" @@ -757,17 +760,17 @@ msgstr "アクティブ" #: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58 #: perms/serializers/permission.py:23 rbac/builtin.py:119 #: rbac/models/rolebinding.py:41 terminal/backends/command/models.py:20 -#: terminal/backends/command/serializers.py:13 #: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 -#: terminal/notifications.py:94 terminal/notifications.py:142 -#: tickets/models/comment.py:21 users/const.py:14 users/models/user.py:900 -#: users/models/user.py:931 users/serializers/group.py:19 +#: terminal/notifications.py:96 terminal/notifications.py:144 +#: terminal/serializers/command.py:15 tickets/models/comment.py:21 +#: users/const.py:14 users/models/user.py:900 users/models/user.py:931 +#: users/serializers/group.py:19 msgid "User" msgstr "ユーザー" #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 -#: ops/serializers/job.py:53 terminal/backends/command/serializers.py:15 -#: terminal/models/session/session.py:41 terminal/serializers/session.py:19 +#: ops/serializers/job.py:53 terminal/models/session/session.py:41 +#: terminal/serializers/command.py:17 terminal/serializers/session.py:19 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 msgid "Command" @@ -792,7 +795,7 @@ msgstr "家を無視する" #: acls/models/command_acl.py:33 acls/models/command_acl.py:96 #: acls/serializers/command_acl.py:28 -#: authentication/serializers/connect_token_secret.py:78 +#: authentication/serializers/connect_token_secret.py:79 msgid "Command group" msgstr "コマンドグループ" @@ -922,7 +925,7 @@ msgid "Applications" msgstr "アプリケーション" #: applications/models.py:11 assets/models/label.py:21 -#: assets/models/platform.py:75 assets/serializers/asset/common.py:117 +#: assets/models/platform.py:75 assets/serializers/asset/common.py:107 #: assets/serializers/cagegory.py:8 assets/serializers/platform.py:87 #: assets/serializers/platform.py:126 perms/serializers/user_permission.py:25 #: settings/models.py:35 tickets/models/ticket/apply_application.py:13 @@ -957,6 +960,10 @@ msgstr "" "デフォルトポートは9000で、HTTPインタフェースとネイティブインタフェースは異な" "るポートを使用する" +#: assets/api/asset/asset.py:115 +msgid "Cannot create asset directly, you should create a host or other" +msgstr "資産を直接作成することはできません。ホストまたはその他を作成する必要があります" + #: assets/api/domain.py:57 msgid "Number required" msgstr "必要な数" @@ -977,7 +984,7 @@ msgstr "削除に失敗し、ノードにアセットが含まれています。 msgid "App assets" msgstr "アプリ資産" -#: assets/automations/base/manager.py:76 +#: assets/automations/base/manager.py:103 #, fuzzy msgid "{} disabled" msgstr "無効" @@ -1039,7 +1046,7 @@ msgid "Device" msgstr "" #: assets/const/category.py:13 assets/models/asset/database.py:9 -#: assets/models/asset/database.py:24 +#: assets/models/asset/database.py:24 assets/serializers/asset/common.py:95 msgid "Database" msgstr "データベース" @@ -1093,7 +1100,7 @@ msgstr "SSHパブリックキー" #: assets/models/_user.py:27 assets/models/cmd_filter.py:40 #: assets/models/cmd_filter.py:88 assets/models/group.py:23 #: assets/models/platform.py:79 common/db/models.py:37 ops/models/adhoc.py:28 -#: ops/models/job.py:41 ops/models/playbook.py:17 rbac/models/role.py:37 +#: ops/models/job.py:41 ops/models/playbook.py:18 rbac/models/role.py:37 #: settings/models.py:38 terminal/models/applet/applet.py:33 #: terminal/models/applet/applet.py:146 terminal/models/applet/host.py:110 #: terminal/models/component/endpoint.py:24 @@ -1112,13 +1119,13 @@ msgid "Date created" msgstr "作成された日付" #: assets/models/_user.py:29 assets/models/cmd_filter.py:42 -#: common/db/models.py:36 +#: common/db/models.py:36 users/models/user.py:735 msgid "Date updated" msgstr "更新日" #: assets/models/_user.py:30 assets/models/cmd_filter.py:44 #: assets/models/cmd_filter.py:91 assets/models/group.py:21 -#: common/db/models.py:33 users/models/user.py:722 +#: common/db/models.py:33 users/models/user.py:721 #: users/serializers/group.py:33 msgid "Created by" msgstr "によって作成された" @@ -1144,7 +1151,7 @@ msgid "Username same with user" msgstr "ユーザーと同じユーザー名" #: assets/models/_user.py:52 authentication/models/connection_token.py:37 -#: authentication/serializers/connect_token_secret.py:103 +#: authentication/serializers/connect_token_secret.py:104 #: terminal/models/applet/applet.py:31 terminal/serializers/session.py:24 #: terminal/serializers/session.py:45 terminal/serializers/storage.py:68 msgid "Protocol" @@ -1158,7 +1165,7 @@ msgstr "オートプッシュ" msgid "Sudo" msgstr "すど" -#: assets/models/_user.py:55 ops/const.py:44 +#: assets/models/_user.py:55 ops/const.py:49 msgid "Shell" msgstr "シェル" @@ -1195,14 +1202,14 @@ msgid "Can match system user" msgstr "システムユーザーに一致できます" #: assets/models/asset/common.py:109 assets/models/platform.py:111 -#: authentication/serializers/connect_token_secret.py:107 +#: authentication/serializers/connect_token_secret.py:108 #: perms/serializers/user_permission.py:23 #: xpack/plugins/cloud/serializers/account_attrs.py:179 msgid "Platform" msgstr "プラットフォーム" #: assets/models/asset/common.py:111 assets/models/domain.py:21 -#: authentication/serializers/connect_token_secret.py:125 +#: authentication/serializers/connect_token_secret.py:126 #: perms/serializers/user_permission.py:27 msgid "Domain" msgstr "ドメイン" @@ -1211,37 +1218,38 @@ msgstr "ドメイン" msgid "Labels" msgstr "ラベル" -#: assets/models/asset/common.py:289 +#: assets/models/asset/common.py:285 msgid "Can refresh asset hardware info" msgstr "資産ハードウェア情報を更新できます" -#: assets/models/asset/common.py:290 +#: assets/models/asset/common.py:286 msgid "Can test asset connectivity" msgstr "資産接続をテストできます" -#: assets/models/asset/common.py:291 +#: assets/models/asset/common.py:287 #, fuzzy msgid "Can push account to asset" msgstr "システムユーザーを資産にプッシュできます" -#: assets/models/asset/common.py:292 +#: assets/models/asset/common.py:288 #, fuzzy msgid "Can verify account" msgstr "パスワード/キーの確認" -#: assets/models/asset/common.py:293 +#: assets/models/asset/common.py:289 msgid "Can match asset" msgstr "アセットを一致させることができます" -#: assets/models/asset/common.py:294 +#: assets/models/asset/common.py:290 msgid "Add asset to node" msgstr "ノードにアセットを追加する" -#: assets/models/asset/common.py:295 +#: assets/models/asset/common.py:291 msgid "Move asset to node" msgstr "アセットをノードに移動する" -#: assets/models/asset/database.py:10 settings/serializers/email.py:37 +#: assets/models/asset/database.py:10 assets/serializers/asset/common.py:96 +#: settings/serializers/email.py:37 msgid "Use SSL" msgstr "SSLの使用" @@ -1260,12 +1268,12 @@ msgstr "クライアント秘密" msgid "Client key" msgstr "クライアント" -#: assets/models/asset/database.py:14 +#: assets/models/asset/database.py:14 assets/serializers/asset/common.py:97 msgid "Allow invalid cert" msgstr "証明書チェックを無視" #: assets/models/asset/web.py:9 audits/const.py:39 -#: terminal/serializers/applet_host.py:27 +#: terminal/serializers/applet_host.py:28 msgid "Disabled" msgstr "無効" @@ -1275,6 +1283,7 @@ msgid "Basic" msgstr "基本" #: assets/models/asset/web.py:11 assets/models/asset/web.py:17 +#: assets/serializers/asset/common.py:103 msgid "Script" msgstr "" @@ -1283,22 +1292,25 @@ msgstr "" msgid "Autofill" msgstr "自動" -#: assets/models/asset/web.py:14 assets/serializers/platform.py:30 +#: assets/models/asset/web.py:14 assets/serializers/asset/common.py:100 +#: assets/serializers/platform.py:30 #, fuzzy msgid "Username selector" msgstr "ユーザー名のプロパティ" -#: assets/models/asset/web.py:15 assets/serializers/platform.py:33 +#: assets/models/asset/web.py:15 assets/serializers/asset/common.py:101 +#: assets/serializers/platform.py:33 #, fuzzy msgid "Password selector" msgstr "パスワードルール" -#: assets/models/asset/web.py:16 assets/serializers/platform.py:36 +#: assets/models/asset/web.py:16 assets/serializers/asset/common.py:102 +#: assets/serializers/platform.py:36 msgid "Submit selector" msgstr "" #: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38 -#: assets/serializers/asset/common.py:237 perms/models/asset_permission.py:70 +#: assets/serializers/asset/common.py:232 perms/models/asset_permission.py:70 #: perms/serializers/permission.py:32 rbac/tree.py:36 msgid "Accounts" msgstr "アカウント" @@ -1317,7 +1329,7 @@ msgstr "自動管理" #: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:99 #: terminal/models/applet/applet.py:145 terminal/models/applet/host.py:107 #: terminal/models/component/status.py:27 terminal/serializers/applet.py:17 -#: terminal/serializers/applet_host.py:90 tickets/models/ticket/general.py:283 +#: terminal/serializers/applet_host.py:93 tickets/models/ticket/general.py:283 #: tickets/serializers/super_ticket.py:13 #: tickets/serializers/ticket/ticket.py:20 xpack/plugins/cloud/models.py:172 #: xpack/plugins/cloud/models.py:224 @@ -1402,15 +1414,15 @@ msgstr "システム" #: assets/models/label.py:19 assets/models/node.py:558 #: assets/serializers/cagegory.py:7 assets/serializers/cagegory.py:14 #: authentication/models/connection_token.py:25 -#: authentication/serializers/connect_token_secret.py:114 -#: common/serializers/common.py:82 settings/models.py:34 +#: authentication/serializers/connect_token_secret.py:115 +#: common/serializers/common.py:80 settings/models.py:34 msgid "Value" msgstr "値" -#: assets/models/label.py:40 assets/serializers/asset/common.py:119 +#: assets/models/label.py:40 assets/serializers/asset/common.py:109 #: assets/serializers/cagegory.py:6 assets/serializers/cagegory.py:13 -#: authentication/serializers/connect_token_secret.py:113 -#: common/serializers/common.py:81 settings/serializers/sms.py:7 +#: authentication/serializers/connect_token_secret.py:114 +#: common/serializers/common.py:79 settings/serializers/sms.py:7 msgid "Label" msgstr "ラベル" @@ -1454,7 +1466,7 @@ msgid "Setting" msgstr "設定" #: assets/models/platform.py:41 audits/const.py:40 settings/models.py:37 -#: terminal/serializers/applet_host.py:28 +#: terminal/serializers/applet_host.py:29 msgid "Enabled" msgstr "有効化" @@ -1548,37 +1560,42 @@ msgstr "自動管理" msgid "%(value)s is not an even number" msgstr "%(value)s は偶数ではありません" -#: assets/serializers/asset/common.py:120 assets/serializers/platform.py:89 +#: assets/serializers/asset/common.py:99 +#, fuzzy +msgid "Auto fill" +msgstr "自動" + +#: assets/serializers/asset/common.py:110 assets/serializers/platform.py:89 #: authentication/serializers/connect_token_secret.py:28 -#: authentication/serializers/connect_token_secret.py:65 +#: authentication/serializers/connect_token_secret.py:66 #: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:107 #: xpack/plugins/cloud/serializers/task.py:38 msgid "Protocols" msgstr "プロトコル" -#: assets/serializers/asset/common.py:122 -#, fuzzy -#| msgid "Enabled" -msgid "Enabled info" -msgstr "有効化" - -#: assets/serializers/asset/common.py:140 +#: assets/serializers/asset/common.py:129 msgid "Address" msgstr "アドレス" -#: assets/serializers/asset/common.py:141 +#: assets/serializers/asset/common.py:130 msgid "Node path" msgstr "ノードパスです" -#: assets/serializers/asset/common.py:201 -#, fuzzy +#: assets/serializers/asset/common.py:190 msgid "Platform not exist" -msgstr "アプリが存在しません" +msgstr "プラットフォームが存在しません" -#: assets/serializers/asset/common.py:217 -#, fuzzy +#: assets/serializers/asset/common.py:200 +msgid "port out of range (1-65535)" +msgstr "ポート番号が範囲外です (1-65535)" + +#: assets/serializers/asset/common.py:212 msgid "Protocol is required: {}" -msgstr "プロトコル重複: {}" +msgstr "プロトコルが必要です: {}" + +#: assets/serializers/asset/common.py:234 +msgid "Auto info" +msgstr "自動情報" #: assets/serializers/asset/database.py:24 common/serializers/fields.py:100 #: tickets/serializers/ticket/common.py:58 @@ -1627,7 +1644,7 @@ msgid "Disk info" msgstr "ディスク情報" #: assets/serializers/asset/host.py:24 -#: authentication/serializers/connect_token_secret.py:104 +#: authentication/serializers/connect_token_secret.py:105 msgid "OS" msgstr "OS" @@ -1895,8 +1912,7 @@ msgstr "リソースタイプ" msgid "Resource" msgstr "リソース" -#: audits/models.py:60 audits/models.py:103 -#: terminal/backends/command/serializers.py:41 +#: audits/models.py:60 audits/models.py:103 terminal/serializers/command.py:43 msgid "Datetime" msgstr "時間" @@ -1963,41 +1979,47 @@ msgstr "理由表示" msgid "User {} {} this resource." msgstr "ユーザー {} はそれを {} しました" -#: audits/signal_handlers.py:50 +#: audits/signal_handlers.py:49 msgid "SSH Key" msgstr "SSHキー" -#: audits/signal_handlers.py:52 settings/serializers/auth/sso.py:10 +#: audits/signal_handlers.py:51 settings/serializers/auth/sso.py:10 msgid "SSO" msgstr "SSO" -#: audits/signal_handlers.py:53 +#: audits/signal_handlers.py:52 msgid "Auth Token" msgstr "認証トークン" -#: audits/signal_handlers.py:54 authentication/notifications.py:73 +#: audits/signal_handlers.py:53 authentication/notifications.py:73 #: authentication/views/login.py:73 authentication/views/wecom.py:177 #: notifications/backends/__init__.py:11 settings/serializers/auth/wecom.py:10 #: users/models/user.py:736 msgid "WeCom" msgstr "企業微信" -#: audits/signal_handlers.py:55 authentication/views/feishu.py:144 +#: audits/signal_handlers.py:54 authentication/views/feishu.py:144 #: authentication/views/login.py:85 notifications/backends/__init__.py:14 #: settings/serializers/auth/feishu.py:10 users/models/user.py:738 msgid "FeiShu" msgstr "本を飛ばす" -#: audits/signal_handlers.py:56 authentication/views/dingtalk.py:179 +#: audits/signal_handlers.py:55 authentication/views/dingtalk.py:179 #: authentication/views/login.py:79 notifications/backends/__init__.py:12 #: settings/serializers/auth/dingtalk.py:10 users/models/user.py:737 msgid "DingTalk" msgstr "DingTalk" -#: audits/signal_handlers.py:57 authentication/models/temp_token.py:16 +#: audits/signal_handlers.py:56 authentication/models/temp_token.py:16 msgid "Temporary token" msgstr "仮パスワード" +#: audits/tasks.py:37 +#, fuzzy +#| msgid "Job audit log" +msgid "Clean audits log" +msgstr "ジョブ監査ログ" + #: authentication/api/confirm.py:40 msgid "This action require verify your MFA" msgstr "この操作には、MFAを検証する必要があります" @@ -2494,27 +2516,27 @@ msgstr "異なる都市ログインのリマインダー" msgid "binding reminder" msgstr "バインディングリマインダー" -#: authentication/serializers/connect_token_secret.py:105 +#: authentication/serializers/connect_token_secret.py:106 #, fuzzy msgid "Is builtin" msgstr "内蔵" -#: authentication/serializers/connect_token_secret.py:109 +#: authentication/serializers/connect_token_secret.py:110 msgid "Options" msgstr "オプション" -#: authentication/serializers/connect_token_secret.py:116 +#: authentication/serializers/connect_token_secret.py:117 #, fuzzy #| msgid "SystemComponent" msgid "Component" msgstr "システムコンポーネント" -#: authentication/serializers/connect_token_secret.py:127 +#: authentication/serializers/connect_token_secret.py:128 #, fuzzy msgid "Expired now" msgstr "期限切れ" -#: authentication/serializers/connect_token_secret.py:147 +#: authentication/serializers/connect_token_secret.py:148 #: authentication/templates/authentication/_access_key_modal.html:30 #: perms/models/perm_node.py:21 users/serializers/group.py:35 msgid "ID" @@ -2546,10 +2568,16 @@ msgid "The {} cannot be empty" msgstr "{} 空にしてはならない" #: authentication/serializers/token.py:79 perms/serializers/permission.py:30 -#: perms/serializers/permission.py:62 users/serializers/user.py:159 +#: perms/serializers/permission.py:62 users/serializers/user.py:160 msgid "Is valid" msgstr "有効です" +#: authentication/tasks.py:12 +#, fuzzy +#| msgid "Can share session" +msgid "Clean expired session" +msgstr "セッションを共有できます" + #: authentication/templates/authentication/_access_key_modal.html:6 msgid "API key list" msgstr "APIキーリスト" @@ -2563,7 +2591,7 @@ msgid "docs" msgstr "ドキュメント" #: authentication/templates/authentication/_access_key_modal.html:33 -#: terminal/notifications.py:96 terminal/notifications.py:144 +#: terminal/notifications.py:98 terminal/notifications.py:146 msgid "Date" msgstr "日付" @@ -2937,7 +2965,7 @@ msgstr "の準備を" msgid "Pending" msgstr "未定" -#: common/const/choices.py:17 ops/const.py:50 +#: common/const/choices.py:17 ops/const.py:55 msgid "Running" msgstr "" @@ -2986,7 +3014,7 @@ msgstr "は破棄されます" msgid "discard time" msgstr "時間を捨てる" -#: common/db/models.py:34 +#: common/db/models.py:34 users/models/user.py:722 msgid "Updated by" msgstr "によって更新" @@ -3103,11 +3131,11 @@ msgstr "確認コードが正しくありません" msgid "Please wait {} seconds before sending" msgstr "{} 秒待ってから送信してください" -#: common/serializers/common.py:86 +#: common/serializers/common.py:84 msgid "Children" msgstr "" -#: common/serializers/common.py:94 +#: common/serializers/common.py:92 #, fuzzy msgid "File" msgstr "ファイル名" @@ -3131,7 +3159,7 @@ msgstr "" msgid "Invalid choice: {}" msgstr "無効なIP" -#: common/tasks.py:13 +#: common/tasks.py:13 common/utils/verify_code.py:16 #, fuzzy msgid "Send email" msgstr "ユーザーを送信" @@ -3294,36 +3322,46 @@ msgid "All assets use different random password" msgstr "すべての資産は異なるランダムパスワードを使用します" #: ops/const.py:33 +msgid "Blank" +msgstr "" + +#: ops/const.py:34 +#, fuzzy +#| msgid "CAS" +msgid "VCS" +msgstr "CAS" + +#: ops/const.py:38 msgid "Adhoc" msgstr "コマンド#コマンド#" -#: ops/const.py:34 ops/models/job.py:32 +#: ops/const.py:39 ops/models/job.py:32 msgid "Playbook" msgstr "Playbook" -#: ops/const.py:38 +#: ops/const.py:43 msgid "Privileged Only" msgstr "特権アカウントのみ" -#: ops/const.py:39 +#: ops/const.py:44 msgid "Privileged First" msgstr "特権アカウント優先" -#: ops/const.py:40 +#: ops/const.py:45 msgid "Skip" msgstr "スキップ" -#: ops/const.py:45 +#: ops/const.py:50 #, fuzzy #| msgid "PowerShell" msgid "Powershell" msgstr "PowerShell" -#: ops/const.py:46 +#: ops/const.py:51 msgid "Python" msgstr "" -#: ops/const.py:52 +#: ops/const.py:57 #, fuzzy #| msgid "Test timeout" msgid "Timeout" @@ -3372,7 +3410,7 @@ msgid "Args" msgstr "アルグ" #: ops/models/adhoc.py:27 ops/models/base.py:16 ops/models/base.py:53 -#: ops/models/job.py:34 ops/models/job.py:105 ops/models/playbook.py:16 +#: ops/models/job.py:34 ops/models/job.py:105 ops/models/playbook.py:17 #: terminal/models/session/sharing.py:23 msgid "Creator" msgstr "作成者" @@ -3483,6 +3521,16 @@ msgstr "ジョブ実行" msgid "Job audit log" msgstr "ジョブ監査ログ" +#: ops/models/playbook.py:20 +#, fuzzy +#| msgid "Create" +msgid "CreateMethod" +msgstr "作成" + +#: ops/models/playbook.py:21 +msgid "VCS URL" +msgstr "" + #: ops/notifications.py:17 msgid "Server performance" msgstr "サーバーのパフォーマンス" @@ -3751,10 +3799,22 @@ msgid "asset permissions of organization {}" msgstr "組織 {} の資産権限" #: perms/serializers/permission.py:31 perms/serializers/permission.py:61 -#: users/serializers/user.py:91 users/serializers/user.py:161 +#: users/serializers/user.py:93 users/serializers/user.py:162 msgid "Is expired" msgstr "期限切れです" +#: perms/tasks.py:28 +#, fuzzy +#| msgid "Asset permissions is about to expire" +msgid "Check asset permission expired" +msgstr "資産権限の有効期限が近づいています" + +#: perms/tasks.py:40 +#, fuzzy +#| msgid "asset permissions of organization {}" +msgid "Send asset permission expired notification" +msgstr "組織 {} の資産権限" + #: perms/templates/perms/_msg_item_permissions_expire.html:7 #: perms/templates/perms/_msg_permed_items_expire.html:7 #, python-format @@ -4429,10 +4489,6 @@ msgstr "元の番号(Src id)" msgid "Business type(Service id)" msgstr "ビジネス・タイプ(Service id)" -#: settings/serializers/auth/sms.py:75 -msgid "Template" -msgstr "テンプレート" - #: settings/serializers/auth/sms.py:76 #, python-brace-format msgid "" @@ -5365,15 +5421,7 @@ msgstr "" "OpenSSHはリモートアプリケーションをWindowsリモートアプリケーションで接続する" "プログラムです" -#: templates/resource_download.html:48 -msgid "" -"Jmservisor is the program used to pull up remote applications in Windows " -"Remote Application publisher" -msgstr "" -"Jmservisorはwindowsリモートアプリケーションパブリケーションサーバでリモートア" -"プリケーションを引き出すためのプログラムです" - -#: templates/resource_download.html:57 +#: templates/resource_download.html:51 msgid "Offline video player" msgstr "オフラインビデオプレーヤー" @@ -5451,8 +5499,7 @@ msgstr "危険" msgid "Input" msgstr "入力" -#: terminal/backends/command/models.py:24 -#: terminal/backends/command/serializers.py:39 +#: terminal/backends/command/models.py:24 terminal/serializers/command.py:41 msgid "Output" msgstr "出力" @@ -5463,29 +5510,10 @@ msgstr "出力" msgid "Session" msgstr "セッション" -#: terminal/backends/command/models.py:26 -#: terminal/backends/command/serializers.py:18 +#: terminal/backends/command/models.py:26 terminal/serializers/command.py:20 msgid "Risk level" msgstr "リスクレベル" -#: terminal/backends/command/serializers.py:16 -msgid "Session ID" -msgstr "セッションID" - -#: terminal/backends/command/serializers.py:38 -#, fuzzy -msgid "Account " -msgstr "アカウント" - -#: terminal/backends/command/serializers.py:40 -msgid "Timestamp" -msgstr "タイムスタンプ" - -#: terminal/backends/command/serializers.py:42 -#: terminal/models/component/terminal.py:84 -msgid "Remote Address" -msgstr "リモートアドレス" - #: terminal/connect_methods.py:47 terminal/connect_methods.py:48 #: terminal/connect_methods.py:49 terminal/connect_methods.py:50 #: terminal/connect_methods.py:51 @@ -5545,7 +5573,7 @@ msgstr "" msgid "Hosting" msgstr "ホスト" -#: terminal/models/applet/host.py:18 terminal/serializers/applet_host.py:40 +#: terminal/models/applet/host.py:18 terminal/serializers/applet_host.py:43 #, fuzzy msgid "Deploy options" msgstr "その他のログインオプション" @@ -5668,6 +5696,10 @@ msgstr "再生ストレージ" msgid "type" msgstr "タイプ" +#: terminal/models/component/terminal.py:84 terminal/serializers/command.py:44 +msgid "Remote Address" +msgstr "リモートアドレス" + #: terminal/models/component/terminal.py:87 msgid "Application User" msgstr "ユーザーの適用" @@ -5768,19 +5800,19 @@ msgstr "セッション参加記録" msgid "Invalid verification code" msgstr "検証コードが無効" -#: terminal/notifications.py:22 +#: terminal/notifications.py:21 msgid "Sessions" msgstr "セッション" -#: terminal/notifications.py:68 +#: terminal/notifications.py:67 msgid "Danger command alert" msgstr "危険コマンドアラート" -#: terminal/notifications.py:95 terminal/notifications.py:143 +#: terminal/notifications.py:97 terminal/notifications.py:145 msgid "Level" msgstr "レベル" -#: terminal/notifications.py:113 +#: terminal/notifications.py:115 msgid "Batch danger command alert" msgstr "一括危険コマンド警告" @@ -5788,44 +5820,63 @@ msgstr "一括危険コマンド警告" msgid "Icon" msgstr "" -#: terminal/serializers/applet_host.py:23 +#: terminal/serializers/applet_host.py:24 #, fuzzy msgid "Per Session" msgstr "セッション" -#: terminal/serializers/applet_host.py:24 +#: terminal/serializers/applet_host.py:25 msgid "Per Device" msgstr "" -#: terminal/serializers/applet_host.py:30 +#: terminal/serializers/applet_host.py:32 +#, fuzzy +#| msgid "LDAP server" +msgid "API Server" +msgstr "LDAPサーバー" + +#: terminal/serializers/applet_host.py:33 #, fuzzy msgid "RDS Licensing" msgstr "ライセンス" -#: terminal/serializers/applet_host.py:31 +#: terminal/serializers/applet_host.py:34 msgid "RDS License Server" msgstr "" -#: terminal/serializers/applet_host.py:32 +#: terminal/serializers/applet_host.py:35 msgid "RDS Licensing Mode" msgstr "" -#: terminal/serializers/applet_host.py:34 +#: terminal/serializers/applet_host.py:37 msgid "RDS fSingleSessionPerUser" msgstr "" -#: terminal/serializers/applet_host.py:35 +#: terminal/serializers/applet_host.py:38 msgid "RDS Max Disconnection Time" msgstr "" -#: terminal/serializers/applet_host.py:36 +#: terminal/serializers/applet_host.py:39 msgid "RDS Remote App Logoff Time Limit" msgstr "" -#: terminal/serializers/applet_host.py:42 terminal/serializers/terminal.py:41 +#: terminal/serializers/applet_host.py:45 terminal/serializers/terminal.py:41 msgid "Load status" msgstr "ロードステータス" +#: terminal/serializers/command.py:18 +msgid "Session ID" +msgstr "セッションID" + +#: terminal/serializers/command.py:40 +#, fuzzy +msgid "Account " +msgstr "アカウント" + +#: terminal/serializers/command.py:42 +msgid "Timestamp" +msgstr "タイムスタンプ" + #: terminal/serializers/endpoint.py:14 msgid "Oracle port" msgstr "Oracle ポート" @@ -5959,6 +6010,40 @@ msgstr "証明書の検証を無視する" msgid "Not found" msgstr "見つかりません" +#: terminal/tasks.py:31 +#, fuzzy +#| msgid "Periodic clear celery tasks" +msgid "Periodic delete terminal status" +msgstr "定期的にCeleryタスクをクリア" + +#: terminal/tasks.py:40 +#, fuzzy +#| msgid "Can share session" +msgid "Clean orphan session" +msgstr "セッションを共有できます" + +#: terminal/tasks.py:59 +#, fuzzy +#| msgid "Periodic clear celery tasks" +msgid "Periodic clean expired session" +msgstr "定期的にCeleryタスクをクリア" + +#: terminal/tasks.py:85 +#, fuzzy +#| msgid "Can upload session replay" +msgid "Upload session replay to external storage" +msgstr "セッションのリプレイをアップロードできます" + +#: terminal/tasks.py:112 +msgid "Run applet host deployment" +msgstr "" + +#: terminal/tasks.py:119 +#, fuzzy +#| msgid "Install app" +msgid "Install applet" +msgstr "アプリのインストール" + #: terminal/templates/terminal/_msg_command_alert.html:10 msgid "view" msgstr "表示" @@ -6444,7 +6529,7 @@ msgstr "公開キー" msgid "Force enable" msgstr "強制有効" -#: users/models/user.py:687 users/serializers/user.py:160 +#: users/models/user.py:687 users/serializers/user.py:161 msgid "Is service account" msgstr "サービスアカウントです" @@ -6473,15 +6558,15 @@ msgid "Secret key" msgstr "秘密キー" #: users/models/user.py:716 users/serializers/profile.py:149 -#: users/serializers/user.py:157 +#: users/serializers/user.py:158 msgid "Is first login" msgstr "最初のログインです" -#: users/models/user.py:731 +#: users/models/user.py:730 msgid "Date password last updated" msgstr "最終更新日パスワード" -#: users/models/user.py:734 +#: users/models/user.py:733 msgid "Need update password" msgstr "更新パスワードが必要" @@ -6556,47 +6641,47 @@ msgstr "新しいパスワードを最後の {} 個のパスワードにする msgid "The newly set password is inconsistent" msgstr "新しく設定されたパスワードが一致しない" -#: users/serializers/user.py:31 +#: users/serializers/user.py:39 msgid "System roles" msgstr "システムの役割" -#: users/serializers/user.py:35 +#: users/serializers/user.py:43 msgid "Org roles" msgstr "組織ロール" -#: users/serializers/user.py:84 +#: users/serializers/user.py:86 msgid "Password strategy" msgstr "パスワード戦略" -#: users/serializers/user.py:86 +#: users/serializers/user.py:88 msgid "MFA enabled" msgstr "MFA有効化" -#: users/serializers/user.py:88 +#: users/serializers/user.py:90 msgid "MFA force enabled" msgstr "MFAフォース有効化" -#: users/serializers/user.py:90 +#: users/serializers/user.py:92 msgid "Login blocked" msgstr "ログインブロック" -#: users/serializers/user.py:93 +#: users/serializers/user.py:95 msgid "Can public key authentication" msgstr "公開鍵認証が可能" -#: users/serializers/user.py:162 +#: users/serializers/user.py:163 msgid "Avatar url" msgstr "アバターURL" -#: users/serializers/user.py:165 +#: users/serializers/user.py:166 msgid "Is OTP bound" msgstr "仮想MFAがバインドされているか" -#: users/serializers/user.py:272 +#: users/serializers/user.py:273 msgid "Select users" msgstr "ユーザーの選択" -#: users/serializers/user.py:273 +#: users/serializers/user.py:274 msgid "For security, only list several users" msgstr "セキュリティのために、複数のユーザーのみをリストします" @@ -6604,6 +6689,39 @@ msgstr "セキュリティのために、複数のユーザーのみをリスト msgid "name not unique" msgstr "名前が一意ではない" +#: users/tasks.py:24 +#, fuzzy +#| msgid "Password expired" +msgid "Check password expired" +msgstr "パスワード期限切れ" + +#: users/tasks.py:38 +#, fuzzy +#| msgid "Password expired" +msgid "Periodic check password expired" +msgstr "パスワード期限切れ" + +#: users/tasks.py:52 +#, fuzzy +#| msgid "Is expired" +msgid "Check user expired" +msgstr "期限切れです" + +#: users/tasks.py:69 +#, fuzzy +msgid "Periodic check user expired" +msgstr "定期的なパフォーマンス" + +#: users/tasks.py:83 +msgid "Import ldap user" +msgstr "" + +#: users/tasks.py:104 +#, fuzzy +#| msgid "Periodic display" +msgid "Periodic import ldap user" +msgstr "定期的な表示" + #: users/templates/users/_msg_account_expire_reminder.html:7 msgid "Your account will expire in" msgstr "アカウントの有効期限は" @@ -7433,6 +7551,18 @@ msgstr "究極のエディション" msgid "Community edition" msgstr "コミュニティ版" +#, fuzzy +#~| msgid "Enabled" +#~ msgid "Enabled info" +#~ msgstr "有効化" + +#~ msgid "" +#~ "Jmservisor is the program used to pull up remote applications in Windows " +#~ "Remote Application publisher" +#~ msgstr "" +#~ "Jmservisorはwindowsリモートアプリケーションパブリケーションサーバでリモー" +#~ "トアプリケーションを引き出すためのプログラムです" + #, fuzzy #~ msgid "Protocols enabled" #~ msgstr "プロトコル" @@ -7527,10 +7657,6 @@ msgstr "コミュニティ版" #~ msgid "Category display" #~ msgstr "カテゴリ表示" -#, fuzzy -#~ msgid "Auto fill" -#~ msgstr "自動" - #~ msgid "Built-in" #~ msgstr "内蔵" @@ -7668,9 +7794,6 @@ msgstr "コミュニティ版" #~ msgid "Data could not be sent to remote" #~ msgstr "データをリモートに送信できませんでした" -#~ msgid "Periodic display" -#~ msgstr "定期的な表示" - #~ msgid "Gathered user" #~ msgstr "収集されたユーザー" diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 7d6549fe3..84742c7d2 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-01-31 16:01+0800\n" +"POT-Creation-Date: 2023-02-03 15:49+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -23,11 +23,11 @@ msgstr "参数 'action' 必须是 [{}]" #: accounts/const/account.py:6 #: accounts/serializers/automations/change_secret.py:33 -#: assets/models/_user.py:24 audits/signal_handlers.py:51 +#: assets/models/_user.py:24 audits/signal_handlers.py:50 #: authentication/confirm/password.py:9 authentication/forms.py:32 #: authentication/templates/authentication/login.html:288 #: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:47 -#: users/forms/profile.py:22 users/serializers/user.py:97 +#: users/forms/profile.py:22 users/serializers/user.py:99 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/cloud/serializers/account_attrs.py:28 @@ -177,23 +177,22 @@ msgstr "创建并推送到资产" msgid "Only create" msgstr "仅创建到资产" -#: accounts/models/account.py:47 accounts/serializers/account/account.py:88 +#: accounts/models/account.py:47 accounts/serializers/account/account.py:80 #: accounts/serializers/automations/change_secret.py:107 #: accounts/serializers/automations/change_secret.py:127 acls/models/base.py:96 #: acls/serializers/base.py:56 assets/models/asset/common.py:97 -#: assets/models/asset/common.py:286 assets/models/cmd_filter.py:36 +#: assets/models/asset/common.py:282 assets/models/cmd_filter.py:36 #: assets/serializers/domain.py:19 assets/serializers/label.py:27 #: audits/models.py:34 authentication/models/connection_token.py:32 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:27 -#: terminal/backends/command/models.py:21 -#: terminal/backends/command/serializers.py:14 -#: terminal/models/session/session.py:31 terminal/notifications.py:93 +#: terminal/backends/command/models.py:21 terminal/models/session/session.py:31 +#: terminal/notifications.py:95 terminal/serializers/command.py:16 #: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:220 msgid "Asset" msgstr "资产" -#: accounts/models/account.py:51 accounts/serializers/account/account.py:92 -#: authentication/serializers/connect_token_secret.py:49 +#: accounts/models/account.py:51 accounts/serializers/account/account.py:84 +#: authentication/serializers/connect_token_secret.py:50 msgid "Su from" msgstr "切换自" @@ -202,15 +201,15 @@ msgstr "切换自" msgid "Version" msgstr "版本" -#: accounts/models/account.py:55 accounts/serializers/account/account.py:89 -#: users/models/user.py:727 +#: accounts/models/account.py:55 accounts/serializers/account/account.py:81 +#: users/models/user.py:726 msgid "Source" msgstr "来源" #: accounts/models/account.py:58 #: accounts/serializers/automations/change_secret.py:108 #: accounts/serializers/automations/change_secret.py:128 acls/models/base.py:98 -#: acls/serializers/base.py:57 assets/serializers/asset/common.py:121 +#: acls/serializers/base.py:57 assets/serializers/asset/common.py:111 #: assets/serializers/gateway.py:30 audits/models.py:35 ops/models/base.py:18 #: terminal/backends/command/models.py:22 terminal/models/session/session.py:33 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 @@ -233,7 +232,7 @@ msgstr "可以查看资产历史账号" msgid "Can view asset history account secret" msgstr "可以查看资产历史账号密码" -#: accounts/models/account.py:104 accounts/serializers/account/account.py:34 +#: accounts/models/account.py:104 msgid "Account template" msgstr "账号模版" @@ -348,11 +347,11 @@ msgid "Can add push account execution" msgstr "创建收集账号执行" #: accounts/models/automations/change_secret.py:17 accounts/models/base.py:36 -#: accounts/serializers/account/account.py:125 +#: accounts/serializers/account/account.py:117 #: accounts/serializers/account/base.py:16 #: accounts/serializers/automations/change_secret.py:46 -#: authentication/serializers/connect_token_secret.py:40 -#: authentication/serializers/connect_token_secret.py:50 +#: authentication/serializers/connect_token_secret.py:41 +#: authentication/serializers/connect_token_secret.py:51 msgid "Secret type" msgstr "密文类型" @@ -396,7 +395,8 @@ msgstr "开始日期" msgid "Date finished" msgstr "结束日期" -#: accounts/models/automations/change_secret.py:76 common/const/choices.py:20 +#: accounts/models/automations/change_secret.py:76 assets/const/automation.py:8 +#: common/const/choices.py:20 msgid "Error" msgstr "错误" @@ -430,7 +430,7 @@ msgstr "用户名" #: accounts/models/automations/push_account.py:15 acls/models/base.py:77 #: acls/serializers/base.py:81 assets/models/cmd_filter.py:81 #: audits/models.py:51 audits/serializers.py:82 -#: authentication/serializers/connect_token_secret.py:108 +#: authentication/serializers/connect_token_secret.py:109 #: authentication/templates/authentication/_access_key_modal.html:34 msgid "Action" msgstr "动作" @@ -450,10 +450,11 @@ msgstr "账号验证" #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 #: assets/models/group.py:20 assets/models/label.py:18 #: assets/models/platform.py:20 assets/models/platform.py:74 -#: assets/serializers/asset/common.py:139 assets/serializers/platform.py:125 -#: authentication/serializers/connect_token_secret.py:102 ops/mixin.py:20 +#: assets/serializers/asset/common.py:60 assets/serializers/asset/common.py:128 +#: assets/serializers/platform.py:125 +#: authentication/serializers/connect_token_secret.py:103 ops/mixin.py:20 #: ops/models/adhoc.py:22 ops/models/celery.py:15 ops/models/celery.py:57 -#: ops/models/job.py:25 ops/models/playbook.py:14 orgs/models.py:69 +#: ops/models/job.py:25 ops/models/playbook.py:15 orgs/models.py:69 #: perms/models/asset_permission.py:56 rbac/models/role.py:29 #: settings/models.py:33 settings/serializers/sms.py:6 #: terminal/models/applet/applet.py:24 terminal/models/component/endpoint.py:12 @@ -472,8 +473,8 @@ msgstr "特权账号" #: accounts/models/base.py:40 assets/models/asset/common.py:114 #: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 #: assets/models/label.py:22 -#: authentication/serializers/connect_token_secret.py:106 -#: terminal/models/applet/applet.py:29 users/serializers/user.py:158 +#: authentication/serializers/connect_token_secret.py:107 +#: terminal/models/applet/applet.py:29 users/serializers/user.py:159 msgid "Is active" msgstr "激活" @@ -515,22 +516,22 @@ msgstr "" "{} - 改密任务已完成: 未设置加密密码 - 请前往个人信息 -> 文件加密密码中设置加" "密密码" -#: accounts/serializers/account/account.py:37 +#: accounts/serializers/account/account.py:52 +#: assets/serializers/asset/common.py:58 settings/serializers/auth/sms.py:75 +msgid "Template" +msgstr "模板" + +#: accounts/serializers/account/account.py:55 #: assets/serializers/asset/common.py:55 msgid "Push now" msgstr "立即推送" -#: accounts/serializers/account/account.py:39 +#: accounts/serializers/account/account.py:57 #: accounts/serializers/account/base.py:64 msgid "Has secret" msgstr "已托管密码" -#: accounts/serializers/account/account.py:46 -#: assets/serializers/asset/common.py:82 -msgid "Account template not found" -msgstr "账号模版未找到" - -#: accounts/serializers/account/account.py:84 +#: accounts/serializers/account/account.py:76 msgid "Asset not found" msgstr "资产不存在" @@ -560,7 +561,10 @@ msgid "Key password" msgstr "密钥密码" #: accounts/serializers/account/base.py:80 -msgid "Specific" +#: assets/serializers/asset/common.py:233 +#, fuzzy +#| msgid "Specific" +msgid "Spec info" msgstr "指定的" #: accounts/serializers/automations/base.py:22 @@ -588,9 +592,9 @@ msgstr "工单快照" #: acls/serializers/command_acl.py:18 applications/models.py:14 #: assets/models/_user.py:50 assets/models/automations/base.py:20 #: assets/models/cmd_filter.py:74 assets/models/platform.py:76 -#: assets/serializers/asset/common.py:118 assets/serializers/platform.py:86 +#: assets/serializers/asset/common.py:108 assets/serializers/platform.py:86 #: audits/serializers.py:48 -#: authentication/serializers/connect_token_secret.py:115 ops/models/job.py:33 +#: authentication/serializers/connect_token_secret.py:116 ops/models/job.py:33 #: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:28 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:146 terminal/serializers/applet.py:28 @@ -621,15 +625,14 @@ msgstr "自动化任务执行历史" #: accounts/serializers/automations/change_secret.py:150 audits/const.py:45 #: audits/handler.py:167 audits/models.py:40 common/const/choices.py:18 -#: ops/const.py:51 ops/serializers/celery.py:39 terminal/const.py:59 +#: ops/const.py:56 ops/serializers/celery.py:39 terminal/const.py:59 #: terminal/models/session/sharing.py:103 tickets/views/approve.py:114 msgid "Success" msgstr "成功" -#: accounts/serializers/automations/change_secret.py:151 -#: assets/const/automation.py:8 audits/const.py:46 audits/handler.py:167 -#: common/const/choices.py:19 ops/const.py:53 terminal/const.py:60 -#: xpack/plugins/cloud/const.py:41 +#: accounts/serializers/automations/change_secret.py:151 audits/const.py:46 +#: audits/handler.py:167 common/const/choices.py:19 ops/const.py:58 +#: terminal/const.py:60 xpack/plugins/cloud/const.py:41 msgid "Failed" msgstr "失败" @@ -704,7 +707,7 @@ msgstr "优先级可选范围为 1-100 (数值越小越优先)" #: acls/models/base.py:78 acls/serializers/base.py:75 #: acls/serializers/login_acl.py:23 assets/models/cmd_filter.py:86 -#: authentication/serializers/connect_token_secret.py:81 +#: authentication/serializers/connect_token_secret.py:82 msgid "Reviewers" msgstr "审批人" @@ -726,17 +729,17 @@ msgstr "激活中" #: perms/api/user_permission/mixin.py:55 perms/models/asset_permission.py:58 #: perms/serializers/permission.py:23 rbac/builtin.py:119 #: rbac/models/rolebinding.py:41 terminal/backends/command/models.py:20 -#: terminal/backends/command/serializers.py:13 #: terminal/models/session/session.py:29 terminal/models/session/sharing.py:32 -#: terminal/notifications.py:94 terminal/notifications.py:142 -#: tickets/models/comment.py:21 users/const.py:14 users/models/user.py:900 -#: users/models/user.py:931 users/serializers/group.py:19 +#: terminal/notifications.py:96 terminal/notifications.py:144 +#: terminal/serializers/command.py:15 tickets/models/comment.py:21 +#: users/const.py:14 users/models/user.py:900 users/models/user.py:931 +#: users/serializers/group.py:19 msgid "User" msgstr "用户" #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 -#: ops/serializers/job.py:53 terminal/backends/command/serializers.py:15 -#: terminal/models/session/session.py:41 terminal/serializers/session.py:19 +#: ops/serializers/job.py:53 terminal/models/session/session.py:41 +#: terminal/serializers/command.py:17 terminal/serializers/session.py:19 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 msgid "Command" @@ -761,7 +764,7 @@ msgstr "忽略大小写" #: acls/models/command_acl.py:33 acls/models/command_acl.py:96 #: acls/serializers/command_acl.py:28 -#: authentication/serializers/connect_token_secret.py:78 +#: authentication/serializers/connect_token_secret.py:79 msgid "Command group" msgstr "命令组" @@ -889,7 +892,7 @@ msgid "Applications" msgstr "应用管理" #: applications/models.py:11 assets/models/label.py:21 -#: assets/models/platform.py:75 assets/serializers/asset/common.py:117 +#: assets/models/platform.py:75 assets/serializers/asset/common.py:107 #: assets/serializers/cagegory.py:8 assets/serializers/platform.py:87 #: assets/serializers/platform.py:126 perms/serializers/user_permission.py:25 #: settings/models.py:35 tickets/models/ticket/apply_application.py:13 @@ -922,6 +925,10 @@ msgid "" "different ports" msgstr "默认端口为9000, HTTP接口和本机接口使用不同的端口" +#: assets/api/asset/asset.py:115 +msgid "Cannot create asset directly, you should create a host or other" +msgstr "不能直接创建资产, 你应该创建主机或其他资产" + #: assets/api/domain.py:57 msgid "Number required" msgstr "需要为数字" @@ -942,7 +949,7 @@ msgstr "删除失败,节点包含资产" msgid "App assets" msgstr "资产管理" -#: assets/automations/base/manager.py:76 +#: assets/automations/base/manager.py:103 msgid "{} disabled" msgstr "{} 已禁用" @@ -1001,7 +1008,7 @@ msgid "Device" msgstr "网络设备" #: assets/const/category.py:13 assets/models/asset/database.py:9 -#: assets/models/asset/database.py:24 +#: assets/models/asset/database.py:24 assets/serializers/asset/common.py:95 msgid "Database" msgstr "数据库" @@ -1050,7 +1057,7 @@ msgstr "SSH公钥" #: assets/models/_user.py:27 assets/models/cmd_filter.py:40 #: assets/models/cmd_filter.py:88 assets/models/group.py:23 #: assets/models/platform.py:79 common/db/models.py:37 ops/models/adhoc.py:28 -#: ops/models/job.py:41 ops/models/playbook.py:17 rbac/models/role.py:37 +#: ops/models/job.py:41 ops/models/playbook.py:18 rbac/models/role.py:37 #: settings/models.py:38 terminal/models/applet/applet.py:33 #: terminal/models/applet/applet.py:146 terminal/models/applet/host.py:110 #: terminal/models/component/endpoint.py:24 @@ -1069,13 +1076,13 @@ msgid "Date created" msgstr "创建日期" #: assets/models/_user.py:29 assets/models/cmd_filter.py:42 -#: common/db/models.py:36 +#: common/db/models.py:36 users/models/user.py:735 msgid "Date updated" msgstr "更新日期" #: assets/models/_user.py:30 assets/models/cmd_filter.py:44 #: assets/models/cmd_filter.py:91 assets/models/group.py:21 -#: common/db/models.py:33 users/models/user.py:722 +#: common/db/models.py:33 users/models/user.py:721 #: users/serializers/group.py:33 msgid "Created by" msgstr "创建者" @@ -1101,7 +1108,7 @@ msgid "Username same with user" msgstr "用户名与用户相同" #: assets/models/_user.py:52 authentication/models/connection_token.py:37 -#: authentication/serializers/connect_token_secret.py:103 +#: authentication/serializers/connect_token_secret.py:104 #: terminal/models/applet/applet.py:31 terminal/serializers/session.py:24 #: terminal/serializers/session.py:45 terminal/serializers/storage.py:68 msgid "Protocol" @@ -1115,7 +1122,7 @@ msgstr "自动推送" msgid "Sudo" msgstr "Sudo" -#: assets/models/_user.py:55 ops/const.py:44 +#: assets/models/_user.py:55 ops/const.py:49 msgid "Shell" msgstr "Shell" @@ -1152,14 +1159,14 @@ msgid "Can match system user" msgstr "可以匹配系统用户" #: assets/models/asset/common.py:109 assets/models/platform.py:111 -#: authentication/serializers/connect_token_secret.py:107 +#: authentication/serializers/connect_token_secret.py:108 #: perms/serializers/user_permission.py:23 #: xpack/plugins/cloud/serializers/account_attrs.py:179 msgid "Platform" msgstr "系统平台" #: assets/models/asset/common.py:111 assets/models/domain.py:21 -#: authentication/serializers/connect_token_secret.py:125 +#: authentication/serializers/connect_token_secret.py:126 #: perms/serializers/user_permission.py:27 msgid "Domain" msgstr "网域" @@ -1168,37 +1175,38 @@ msgstr "网域" msgid "Labels" msgstr "标签管理" -#: assets/models/asset/common.py:289 +#: assets/models/asset/common.py:285 msgid "Can refresh asset hardware info" msgstr "可以更新资产硬件信息" -#: assets/models/asset/common.py:290 +#: assets/models/asset/common.py:286 msgid "Can test asset connectivity" msgstr "可以测试资产连接性" -#: assets/models/asset/common.py:291 +#: assets/models/asset/common.py:287 msgid "Can push account to asset" msgstr "可以推送账号到资产" -#: assets/models/asset/common.py:292 +#: assets/models/asset/common.py:288 #, fuzzy #| msgid "Verify account" msgid "Can verify account" msgstr "验证账号" -#: assets/models/asset/common.py:293 +#: assets/models/asset/common.py:289 msgid "Can match asset" msgstr "可以匹配资产" -#: assets/models/asset/common.py:294 +#: assets/models/asset/common.py:290 msgid "Add asset to node" msgstr "添加资产到节点" -#: assets/models/asset/common.py:295 +#: assets/models/asset/common.py:291 msgid "Move asset to node" msgstr "移动资产到节点" -#: assets/models/asset/database.py:10 settings/serializers/email.py:37 +#: assets/models/asset/database.py:10 assets/serializers/asset/common.py:96 +#: settings/serializers/email.py:37 msgid "Use SSL" msgstr "使用 SSL" @@ -1214,12 +1222,12 @@ msgstr "客户端证书" msgid "Client key" msgstr "客户端密钥" -#: assets/models/asset/database.py:14 +#: assets/models/asset/database.py:14 assets/serializers/asset/common.py:97 msgid "Allow invalid cert" msgstr "忽略证书校验" #: assets/models/asset/web.py:9 audits/const.py:39 -#: terminal/serializers/applet_host.py:27 +#: terminal/serializers/applet_host.py:28 msgid "Disabled" msgstr "禁用" @@ -1229,6 +1237,7 @@ msgid "Basic" msgstr "基本" #: assets/models/asset/web.py:11 assets/models/asset/web.py:17 +#: assets/serializers/asset/common.py:103 msgid "Script" msgstr "" @@ -1236,20 +1245,23 @@ msgstr "" msgid "Autofill" msgstr "自动代填" -#: assets/models/asset/web.py:14 assets/serializers/platform.py:30 +#: assets/models/asset/web.py:14 assets/serializers/asset/common.py:100 +#: assets/serializers/platform.py:30 msgid "Username selector" msgstr "用户名选择器" -#: assets/models/asset/web.py:15 assets/serializers/platform.py:33 +#: assets/models/asset/web.py:15 assets/serializers/asset/common.py:101 +#: assets/serializers/platform.py:33 msgid "Password selector" msgstr "密码选择器" -#: assets/models/asset/web.py:16 assets/serializers/platform.py:36 +#: assets/models/asset/web.py:16 assets/serializers/asset/common.py:102 +#: assets/serializers/platform.py:36 msgid "Submit selector" msgstr "确认按钮选择器" #: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38 -#: assets/serializers/asset/common.py:237 perms/models/asset_permission.py:70 +#: assets/serializers/asset/common.py:232 perms/models/asset_permission.py:70 #: perms/serializers/permission.py:32 rbac/tree.py:36 msgid "Accounts" msgstr "账号管理" @@ -1268,7 +1280,7 @@ msgstr "自动化任务" #: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:99 #: terminal/models/applet/applet.py:145 terminal/models/applet/host.py:107 #: terminal/models/component/status.py:27 terminal/serializers/applet.py:17 -#: terminal/serializers/applet_host.py:90 tickets/models/ticket/general.py:283 +#: terminal/serializers/applet_host.py:93 tickets/models/ticket/general.py:283 #: tickets/serializers/super_ticket.py:13 #: tickets/serializers/ticket/ticket.py:20 xpack/plugins/cloud/models.py:172 #: xpack/plugins/cloud/models.py:224 @@ -1351,15 +1363,15 @@ msgstr "系统" #: assets/models/label.py:19 assets/models/node.py:558 #: assets/serializers/cagegory.py:7 assets/serializers/cagegory.py:14 #: authentication/models/connection_token.py:25 -#: authentication/serializers/connect_token_secret.py:114 -#: common/serializers/common.py:82 settings/models.py:34 +#: authentication/serializers/connect_token_secret.py:115 +#: common/serializers/common.py:80 settings/models.py:34 msgid "Value" msgstr "值" -#: assets/models/label.py:40 assets/serializers/asset/common.py:119 +#: assets/models/label.py:40 assets/serializers/asset/common.py:109 #: assets/serializers/cagegory.py:6 assets/serializers/cagegory.py:13 -#: authentication/serializers/connect_token_secret.py:113 -#: common/serializers/common.py:81 settings/serializers/sms.py:7 +#: authentication/serializers/connect_token_secret.py:114 +#: common/serializers/common.py:79 settings/serializers/sms.py:7 msgid "Label" msgstr "标签" @@ -1402,7 +1414,7 @@ msgid "Setting" msgstr "设置" #: assets/models/platform.py:41 audits/const.py:40 settings/models.py:37 -#: terminal/serializers/applet_host.py:28 +#: terminal/serializers/applet_host.py:29 msgid "Enabled" msgstr "启用" @@ -1487,36 +1499,44 @@ msgstr "自动化" msgid "%(value)s is not an even number" msgstr "%(value)s is not an even number" -#: assets/serializers/asset/common.py:120 assets/serializers/platform.py:89 +#: assets/serializers/asset/common.py:99 +#, fuzzy +#| msgid "Autofill" +msgid "Auto fill" +msgstr "自动代填" + +#: assets/serializers/asset/common.py:110 assets/serializers/platform.py:89 #: authentication/serializers/connect_token_secret.py:28 -#: authentication/serializers/connect_token_secret.py:65 +#: authentication/serializers/connect_token_secret.py:66 #: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:107 #: xpack/plugins/cloud/serializers/task.py:38 msgid "Protocols" msgstr "协议组" -#: assets/serializers/asset/common.py:122 -#, fuzzy -#| msgid "Enabled" -msgid "Enabled info" -msgstr "启用" - -#: assets/serializers/asset/common.py:140 +#: assets/serializers/asset/common.py:129 msgid "Address" msgstr "地址" -#: assets/serializers/asset/common.py:141 +#: assets/serializers/asset/common.py:130 msgid "Node path" msgstr "节点路径" -#: assets/serializers/asset/common.py:201 +#: assets/serializers/asset/common.py:190 msgid "Platform not exist" msgstr "平台不存在" -#: assets/serializers/asset/common.py:217 +#: assets/serializers/asset/common.py:200 +msgid "port out of range (1-65535)" +msgstr "端口超出范围 (1-65535)" + +#: assets/serializers/asset/common.py:212 msgid "Protocol is required: {}" msgstr "协议是必填的: {}" +#: assets/serializers/asset/common.py:234 +msgid "Auto info" +msgstr "自动化信息" + #: assets/serializers/asset/database.py:24 common/serializers/fields.py:100 #: tickets/serializers/ticket/common.py:58 #: xpack/plugins/cloud/serializers/account_attrs.py:56 @@ -1564,7 +1584,7 @@ msgid "Disk info" msgstr "硬盘信息" #: assets/serializers/asset/host.py:24 -#: authentication/serializers/connect_token_secret.py:104 +#: authentication/serializers/connect_token_secret.py:105 msgid "OS" msgstr "操作系统" @@ -1794,10 +1814,8 @@ msgid "User {} has executed change auth plan for this account.({})" msgstr "用户 {} 为这个账号执行了改密计划.({})" #: audits/handler.py:168 -#, fuzzy -#| msgid "User {} {} it." msgid "User {} login into this service.[{}]" -msgstr "用户 {} {}了它." +msgstr "用户 {} 登录了服务.[{}]" #: audits/models.py:32 audits/models.py:59 audits/models.py:101 #: terminal/models/session/session.py:37 terminal/models/session/sharing.py:95 @@ -1824,8 +1842,7 @@ msgstr "资源类型" msgid "Resource" msgstr "资源" -#: audits/models.py:60 audits/models.py:103 -#: terminal/backends/command/serializers.py:41 +#: audits/models.py:60 audits/models.py:103 terminal/serializers/command.py:43 msgid "Datetime" msgstr "日期" @@ -1887,61 +1904,59 @@ msgid "Reason display" msgstr "原因描述" #: audits/serializers.py:120 -#, fuzzy -#| msgid "User {} {} it." msgid "User {} {} this resource." -msgstr "用户 {} {}了它." +msgstr "用户 {} {} 了当前资源." -#: audits/signal_handlers.py:50 +#: audits/signal_handlers.py:49 msgid "SSH Key" msgstr "SSH 密钥" -#: audits/signal_handlers.py:52 settings/serializers/auth/sso.py:10 +#: audits/signal_handlers.py:51 settings/serializers/auth/sso.py:10 msgid "SSO" msgstr "SSO" -#: audits/signal_handlers.py:53 +#: audits/signal_handlers.py:52 msgid "Auth Token" msgstr "认证令牌" -#: audits/signal_handlers.py:54 authentication/notifications.py:73 +#: audits/signal_handlers.py:53 authentication/notifications.py:73 #: authentication/views/login.py:73 authentication/views/wecom.py:177 #: notifications/backends/__init__.py:11 settings/serializers/auth/wecom.py:10 #: users/models/user.py:736 msgid "WeCom" msgstr "企业微信" -#: audits/signal_handlers.py:55 authentication/views/feishu.py:144 +#: audits/signal_handlers.py:54 authentication/views/feishu.py:144 #: authentication/views/login.py:85 notifications/backends/__init__.py:14 #: settings/serializers/auth/feishu.py:10 users/models/user.py:738 msgid "FeiShu" msgstr "飞书" -#: audits/signal_handlers.py:56 authentication/views/dingtalk.py:179 +#: audits/signal_handlers.py:55 authentication/views/dingtalk.py:179 #: authentication/views/login.py:79 notifications/backends/__init__.py:12 #: settings/serializers/auth/dingtalk.py:10 users/models/user.py:737 msgid "DingTalk" msgstr "钉钉" -#: audits/signal_handlers.py:57 authentication/models/temp_token.py:16 +#: audits/signal_handlers.py:56 authentication/models/temp_token.py:16 msgid "Temporary token" msgstr "临时密码" +#: audits/tasks.py:37 +msgid "Clean audits log" +msgstr "清理审计日志" + #: authentication/api/confirm.py:40 msgid "This action require verify your MFA" msgstr "此操作需要验证您的 MFA" #: authentication/api/connection_token.py:264 -#, fuzzy -#| msgid "Account template not found" msgid "Account not found" -msgstr "账号模版未找到" +msgstr "账号未找到" #: authentication/api/connection_token.py:267 -#, fuzzy -#| msgid "Permission name" msgid "Permission Expired" -msgstr "授权规则名称" +msgstr "授权过期" #: authentication/api/connection_token.py:279 msgid "ACL action is reject" @@ -2406,23 +2421,23 @@ msgstr "异地登录提醒" msgid "binding reminder" msgstr "绑定提醒" -#: authentication/serializers/connect_token_secret.py:105 +#: authentication/serializers/connect_token_secret.py:106 msgid "Is builtin" msgstr "内置的" -#: authentication/serializers/connect_token_secret.py:109 +#: authentication/serializers/connect_token_secret.py:110 msgid "Options" msgstr "选项" -#: authentication/serializers/connect_token_secret.py:116 +#: authentication/serializers/connect_token_secret.py:117 msgid "Component" msgstr "组件" -#: authentication/serializers/connect_token_secret.py:127 +#: authentication/serializers/connect_token_secret.py:128 msgid "Expired now" msgstr "立刻过期" -#: authentication/serializers/connect_token_secret.py:147 +#: authentication/serializers/connect_token_secret.py:148 #: authentication/templates/authentication/_access_key_modal.html:30 #: perms/models/perm_node.py:21 users/serializers/group.py:35 msgid "ID" @@ -2454,10 +2469,16 @@ msgid "The {} cannot be empty" msgstr "{} 不能为空" #: authentication/serializers/token.py:79 perms/serializers/permission.py:30 -#: perms/serializers/permission.py:62 users/serializers/user.py:159 +#: perms/serializers/permission.py:62 users/serializers/user.py:160 msgid "Is valid" msgstr "账号是否有效" +#: authentication/tasks.py:12 +#, fuzzy +#| msgid "Can share session" +msgid "Clean expired session" +msgstr "可以分享会话" + #: authentication/templates/authentication/_access_key_modal.html:6 msgid "API key list" msgstr "API Key列表" @@ -2471,7 +2492,7 @@ msgid "docs" msgstr "文档" #: authentication/templates/authentication/_access_key_modal.html:33 -#: terminal/notifications.py:96 terminal/notifications.py:144 +#: terminal/notifications.py:98 terminal/notifications.py:146 msgid "Date" msgstr "日期" @@ -2837,7 +2858,7 @@ msgstr "准备" msgid "Pending" msgstr "待定的" -#: common/const/choices.py:17 ops/const.py:50 +#: common/const/choices.py:17 ops/const.py:55 msgid "Running" msgstr "运行中" @@ -2885,7 +2906,7 @@ msgstr "忽略的" msgid "discard time" msgstr "忽略时间" -#: common/db/models.py:34 +#: common/db/models.py:34 users/models/user.py:722 msgid "Updated by" msgstr "最后更新者" @@ -3004,11 +3025,11 @@ msgstr "验证码错误" msgid "Please wait {} seconds before sending" msgstr "请在 {} 秒后发送" -#: common/serializers/common.py:86 +#: common/serializers/common.py:84 msgid "Children" msgstr "节点" -#: common/serializers/common.py:94 +#: common/serializers/common.py:92 msgid "File" msgstr "文件" @@ -3030,7 +3051,7 @@ msgstr "错误的数据类型,应该是列表" msgid "Invalid choice: {}" msgstr "无效选项: {}" -#: common/tasks.py:13 +#: common/tasks.py:13 common/utils/verify_code.py:16 msgid "Send email" msgstr "发件邮件" @@ -3183,34 +3204,44 @@ msgid "All assets use different random password" msgstr "各自随机" #: ops/const.py:33 +msgid "Blank" +msgstr "" + +#: ops/const.py:34 +#, fuzzy +#| msgid "CAS" +msgid "VCS" +msgstr "CAS" + +#: ops/const.py:38 msgid "Adhoc" msgstr "命令" -#: ops/const.py:34 ops/models/job.py:32 +#: ops/const.py:39 ops/models/job.py:32 msgid "Playbook" msgstr "Playbook" -#: ops/const.py:38 +#: ops/const.py:43 msgid "Privileged Only" msgstr "仅限特权账号" -#: ops/const.py:39 +#: ops/const.py:44 msgid "Privileged First" msgstr "特权账号优先" -#: ops/const.py:40 +#: ops/const.py:45 msgid "Skip" msgstr "跳过" -#: ops/const.py:45 +#: ops/const.py:50 msgid "Powershell" msgstr "PowerShell" -#: ops/const.py:46 +#: ops/const.py:51 msgid "Python" msgstr "" -#: ops/const.py:52 +#: ops/const.py:57 #, fuzzy #| msgid "Test timeout" msgid "Timeout" @@ -3259,7 +3290,7 @@ msgid "Args" msgstr "参数" #: ops/models/adhoc.py:27 ops/models/base.py:16 ops/models/base.py:53 -#: ops/models/job.py:34 ops/models/job.py:105 ops/models/playbook.py:16 +#: ops/models/job.py:34 ops/models/job.py:105 ops/models/playbook.py:17 #: terminal/models/session/sharing.py:23 msgid "Creator" msgstr "创建者" @@ -3365,6 +3396,16 @@ msgstr "作业执行" msgid "Job audit log" msgstr "作业审计日志" +#: ops/models/playbook.py:20 +#, fuzzy +#| msgid "Create" +msgid "CreateMethod" +msgstr "创建" + +#: ops/models/playbook.py:21 +msgid "VCS URL" +msgstr "" + #: ops/notifications.py:17 msgid "Server performance" msgstr "监控告警" @@ -3619,10 +3660,22 @@ msgid "asset permissions of organization {}" msgstr "组织 ({}) 的资产授权" #: perms/serializers/permission.py:31 perms/serializers/permission.py:61 -#: users/serializers/user.py:91 users/serializers/user.py:161 +#: users/serializers/user.py:93 users/serializers/user.py:162 msgid "Is expired" msgstr "已过期" +#: perms/tasks.py:28 +#, fuzzy +#| msgid "Asset permissions is about to expire" +msgid "Check asset permission expired" +msgstr "资产授权规则将要过期" + +#: perms/tasks.py:40 +#, fuzzy +#| msgid "asset permissions of organization {}" +msgid "Send asset permission expired notification" +msgstr "组织 ({}) 的资产授权" + #: perms/templates/perms/_msg_item_permissions_expire.html:7 #: perms/templates/perms/_msg_permed_items_expire.html:7 #, python-format @@ -4293,10 +4346,6 @@ msgstr "原始号码(Src id)" msgid "Business type(Service id)" msgstr "业务类型(Service id)" -#: settings/serializers/auth/sms.py:75 -msgid "Template" -msgstr "模板" - #: settings/serializers/auth/sms.py:76 #, python-brace-format msgid "" @@ -5193,13 +5242,7 @@ msgid "" "Remote Application Publisher" msgstr "OpenSSH 是在 windows 远程应用发布服务器中用来连接远程应用的程序" -#: templates/resource_download.html:48 -msgid "" -"Jmservisor is the program used to pull up remote applications in Windows " -"Remote Application publisher" -msgstr "Jmservisor 是在 windows 远程应用发布服务器中用来拉起远程应用的程序" - -#: templates/resource_download.html:57 +#: templates/resource_download.html:51 msgid "Offline video player" msgstr "离线录像播放器" @@ -5277,8 +5320,7 @@ msgstr "危险" msgid "Input" msgstr "输入" -#: terminal/backends/command/models.py:24 -#: terminal/backends/command/serializers.py:39 +#: terminal/backends/command/models.py:24 terminal/serializers/command.py:41 msgid "Output" msgstr "输出" @@ -5289,28 +5331,10 @@ msgstr "输出" msgid "Session" msgstr "会话" -#: terminal/backends/command/models.py:26 -#: terminal/backends/command/serializers.py:18 +#: terminal/backends/command/models.py:26 terminal/serializers/command.py:20 msgid "Risk level" msgstr "风险等级" -#: terminal/backends/command/serializers.py:16 -msgid "Session ID" -msgstr "会话ID" - -#: terminal/backends/command/serializers.py:38 -msgid "Account " -msgstr "账号" - -#: terminal/backends/command/serializers.py:40 -msgid "Timestamp" -msgstr "时间戳" - -#: terminal/backends/command/serializers.py:42 -#: terminal/models/component/terminal.py:84 -msgid "Remote Address" -msgstr "远端地址" - #: terminal/connect_methods.py:47 terminal/connect_methods.py:48 #: terminal/connect_methods.py:49 terminal/connect_methods.py:50 #: terminal/connect_methods.py:51 @@ -5367,7 +5391,7 @@ msgstr "" msgid "Hosting" msgstr "宿主机" -#: terminal/models/applet/host.py:18 terminal/serializers/applet_host.py:40 +#: terminal/models/applet/host.py:18 terminal/serializers/applet_host.py:43 msgid "Deploy options" msgstr "部署参数" @@ -5481,6 +5505,10 @@ msgstr "录像存储" msgid "type" msgstr "类型" +#: terminal/models/component/terminal.py:84 terminal/serializers/command.py:44 +msgid "Remote Address" +msgstr "远端地址" + #: terminal/models/component/terminal.py:87 msgid "Application User" msgstr "应用用户" @@ -5581,19 +5609,19 @@ msgstr "会话加入记录" msgid "Invalid verification code" msgstr "验证码不正确" -#: terminal/notifications.py:22 +#: terminal/notifications.py:21 msgid "Sessions" msgstr "会话管理" -#: terminal/notifications.py:68 +#: terminal/notifications.py:67 msgid "Danger command alert" msgstr "危险命令告警" -#: terminal/notifications.py:95 terminal/notifications.py:143 +#: terminal/notifications.py:97 terminal/notifications.py:145 msgid "Level" msgstr "级别" -#: terminal/notifications.py:113 +#: terminal/notifications.py:115 msgid "Batch danger command alert" msgstr "批量危险命令告警" @@ -5601,42 +5629,60 @@ msgstr "批量危险命令告警" msgid "Icon" msgstr "图标" -#: terminal/serializers/applet_host.py:23 +#: terminal/serializers/applet_host.py:24 msgid "Per Session" msgstr "每会话" -#: terminal/serializers/applet_host.py:24 +#: terminal/serializers/applet_host.py:25 msgid "Per Device" msgstr "每设备" -#: terminal/serializers/applet_host.py:30 +#: terminal/serializers/applet_host.py:32 +#, fuzzy +#| msgid "LDAP server" +msgid "API Server" +msgstr "LDAP 地址" + +#: terminal/serializers/applet_host.py:33 msgid "RDS Licensing" msgstr "RDS 许可证" -#: terminal/serializers/applet_host.py:31 +#: terminal/serializers/applet_host.py:34 msgid "RDS License Server" msgstr "RDS 许可服务器" -#: terminal/serializers/applet_host.py:32 +#: terminal/serializers/applet_host.py:35 msgid "RDS Licensing Mode" msgstr "RDS 授权模式" -#: terminal/serializers/applet_host.py:34 +#: terminal/serializers/applet_host.py:37 msgid "RDS fSingleSessionPerUser" msgstr "" -#: terminal/serializers/applet_host.py:35 +#: terminal/serializers/applet_host.py:38 msgid "RDS Max Disconnection Time" msgstr "" -#: terminal/serializers/applet_host.py:36 +#: terminal/serializers/applet_host.py:39 msgid "RDS Remote App Logoff Time Limit" msgstr "" -#: terminal/serializers/applet_host.py:42 terminal/serializers/terminal.py:41 +#: terminal/serializers/applet_host.py:45 terminal/serializers/terminal.py:41 msgid "Load status" msgstr "负载状态" +#: terminal/serializers/command.py:18 +msgid "Session ID" +msgstr "会话ID" + +#: terminal/serializers/command.py:40 +msgid "Account " +msgstr "账号" + +#: terminal/serializers/command.py:42 +msgid "Timestamp" +msgstr "时间戳" + #: terminal/serializers/endpoint.py:14 msgid "Oracle port" msgstr "Oracle 端口" @@ -5768,6 +5814,40 @@ msgstr "忽略证书认证" msgid "Not found" msgstr "没有发现" +#: terminal/tasks.py:31 +#, fuzzy +#| msgid "Periodic clear celery tasks" +msgid "Periodic delete terminal status" +msgstr "周期清理不可用任务" + +#: terminal/tasks.py:40 +#, fuzzy +#| msgid "Can share session" +msgid "Clean orphan session" +msgstr "可以分享会话" + +#: terminal/tasks.py:59 +#, fuzzy +#| msgid "Periodic clear celery tasks" +msgid "Periodic clean expired session" +msgstr "周期清理不可用任务" + +#: terminal/tasks.py:85 +#, fuzzy +#| msgid "Can upload session replay" +msgid "Upload session replay to external storage" +msgstr "可以上传会话录像" + +#: terminal/tasks.py:112 +msgid "Run applet host deployment" +msgstr "" + +#: terminal/tasks.py:119 +#, fuzzy +#| msgid "Install app" +msgid "Install applet" +msgstr "安装应用" + #: terminal/templates/terminal/_msg_command_alert.html:10 msgid "view" msgstr "查看" @@ -6243,7 +6323,7 @@ msgstr "SSH公钥" msgid "Force enable" msgstr "强制启用" -#: users/models/user.py:687 users/serializers/user.py:160 +#: users/models/user.py:687 users/serializers/user.py:161 msgid "Is service account" msgstr "服务账号" @@ -6272,15 +6352,15 @@ msgid "Secret key" msgstr "Secret key" #: users/models/user.py:716 users/serializers/profile.py:149 -#: users/serializers/user.py:157 +#: users/serializers/user.py:158 msgid "Is first login" msgstr "首次登录" -#: users/models/user.py:731 +#: users/models/user.py:730 msgid "Date password last updated" msgstr "最后更新密码日期" -#: users/models/user.py:734 +#: users/models/user.py:733 msgid "Need update password" msgstr "需要更新密码" @@ -6355,47 +6435,47 @@ msgstr "新密码不能是最近 {} 次的密码" msgid "The newly set password is inconsistent" msgstr "两次密码不一致" -#: users/serializers/user.py:31 +#: users/serializers/user.py:39 msgid "System roles" msgstr "系统角色" -#: users/serializers/user.py:35 +#: users/serializers/user.py:43 msgid "Org roles" msgstr "组织角色" -#: users/serializers/user.py:84 +#: users/serializers/user.py:86 msgid "Password strategy" msgstr "密码策略" -#: users/serializers/user.py:86 +#: users/serializers/user.py:88 msgid "MFA enabled" msgstr "MFA 已启用" -#: users/serializers/user.py:88 +#: users/serializers/user.py:90 msgid "MFA force enabled" msgstr "强制 MFA" -#: users/serializers/user.py:90 +#: users/serializers/user.py:92 msgid "Login blocked" msgstr "登录被阻塞" -#: users/serializers/user.py:93 +#: users/serializers/user.py:95 msgid "Can public key authentication" msgstr "公钥认证" -#: users/serializers/user.py:162 +#: users/serializers/user.py:163 msgid "Avatar url" msgstr "头像路径" -#: users/serializers/user.py:165 +#: users/serializers/user.py:166 msgid "Is OTP bound" msgstr "是否绑定了虚拟 MFA" -#: users/serializers/user.py:272 +#: users/serializers/user.py:273 msgid "Select users" msgstr "选择用户" -#: users/serializers/user.py:273 +#: users/serializers/user.py:274 msgid "For security, only list several users" msgstr "为了安全,仅列出几个用户" @@ -6403,6 +6483,40 @@ msgstr "为了安全,仅列出几个用户" msgid "name not unique" msgstr "名称重复" +#: users/tasks.py:24 +#, fuzzy +#| msgid "Password expired" +msgid "Check password expired" +msgstr "密码已过期" + +#: users/tasks.py:38 +#, fuzzy +#| msgid "Password expired" +msgid "Periodic check password expired" +msgstr "密码已过期" + +#: users/tasks.py:52 +#, fuzzy +#| msgid "Is expired" +msgid "Check user expired" +msgstr "已过期" + +#: users/tasks.py:69 +#, fuzzy +#| msgid "Periodic check service performance" +msgid "Periodic check user expired" +msgstr "周期检测服务性能" + +#: users/tasks.py:83 +msgid "Import ldap user" +msgstr "" + +#: users/tasks.py:104 +#, fuzzy +#| msgid "Periodic display" +msgid "Periodic import ldap user" +msgstr "定时执行" + #: users/templates/users/_msg_account_expire_reminder.html:7 msgid "Your account will expire in" msgstr "您的账号即将过期" @@ -7217,6 +7331,19 @@ msgstr "旗舰版" msgid "Community edition" msgstr "社区版" +#~ msgid "Account template not found" +#~ msgstr "账号模版未找到" + +#, fuzzy +#~| msgid "Enabled" +#~ msgid "Enabled info" +#~ msgstr "启用" + +#~ msgid "" +#~ "Jmservisor is the program used to pull up remote applications in Windows " +#~ "Remote Application publisher" +#~ msgstr "Jmservisor 是在 windows 远程应用发布服务器中用来拉起远程应用的程序" + #~ msgid "Protocols enabled" #~ msgstr "启用协议" @@ -7433,9 +7560,6 @@ msgstr "社区版" #~ msgid "Data could not be sent to remote" #~ msgstr "无法将数据发送到远程" -#~ msgid "Periodic display" -#~ msgstr "定时执行" - #~ msgid "Gathered user" #~ msgstr "收集用户" From 4220c72cd3e94821ab4fff869d7879ce8b53402d Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 3 Feb 2023 16:44:05 +0800 Subject: [PATCH 74/92] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=20ops=20job=20?= =?UTF-8?q?=E7=BA=A6=E6=9D=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.mo | 4 +- .../migrations/0026_alter_jobexecution_job.py | 19 +++++ apps/ops/models/job.py | 70 +++++++++---------- 4 files changed, 58 insertions(+), 39 deletions(-) create mode 100644 apps/ops/migrations/0026_alter_jobexecution_job.py diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index c36e4dc8f..a1783c9eb 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b3c3f8e65468adb0105f2cbcbb8aa3ed50066c9db439a9921932c6e2adcacec3 -size 119640 +oid sha256:ee001334775456ab2034f9ac1905f7a9299ff763d3d2c9d394d340b75ceffb6f +size 119830 diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 1dbea7659..2f6cd1ef1 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0c3f5102d732ffe768f0545cf9271bbba45ba4c159f0a348b518b58cbdb5f20c -size 105947 +oid sha256:51dd2a03462cbc3ae08d6257dec51a867b3431bf6b0800c996847a219a11aee0 +size 106203 diff --git a/apps/ops/migrations/0026_alter_jobexecution_job.py b/apps/ops/migrations/0026_alter_jobexecution_job.py new file mode 100644 index 000000000..e0dba6bb4 --- /dev/null +++ b/apps/ops/migrations/0026_alter_jobexecution_job.py @@ -0,0 +1,19 @@ +# Generated by Django 3.2.14 on 2023-02-03 08:40 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('ops', '0025_auto_20230117_1130'), + ] + + operations = [ + migrations.AlterField( + model_name='jobexecution', + name='job', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='executions', to='ops.job'), + ), + ] diff --git a/apps/ops/models/job.py b/apps/ops/models/job.py index 894ff47d1..f19e63b9d 100644 --- a/apps/ops/models/job.py +++ b/apps/ops/models/job.py @@ -1,4 +1,3 @@ -import datetime import json import logging import os @@ -97,7 +96,7 @@ class JobExecution(JMSOrgBaseModel): id = models.UUIDField(default=uuid.uuid4, primary_key=True) task_id = models.UUIDField(null=True) status = models.CharField(max_length=16, verbose_name=_('Status'), default=JobStatus.running) - job = models.ForeignKey(Job, on_delete=models.CASCADE, related_name='executions', null=True) + job = models.ForeignKey(Job, on_delete=models.SET_NULL, related_name='executions', null=True) job_version = models.IntegerField(default=0) parameters = models.JSONField(default=dict, verbose_name=_('Parameters')) result = models.JSONField(blank=True, null=True, verbose_name=_('Result')) @@ -122,41 +121,42 @@ class JobExecution(JMSOrgBaseModel): @property def assent_result_detail(self): - if self.is_finished and not self.summary.get('error', None): - result = { - "summary": self.count, - "detail": [], + if not self.is_finished or self.summary.get('error'): + return None + result = { + "summary": self.summary, + "detail": [], + } + for asset in self.current_job.assets.all(): + asset_detail = { + "name": asset.name, + "status": "ok", + "tasks": [], } - for asset in self.current_job.assets.all(): - asset_detail = { - "name": asset.name, - "status": "ok", - "tasks": [], - } - if self.summary.get("excludes", None) and self.summary["excludes"].get(asset.name, None): - asset_detail.update({"status": "excludes"}) - result["detail"].append(asset_detail) - break - if self.result["dark"].get(asset.name, None): - asset_detail.update({"status": "failed"}) - for key, task in self.result["dark"][asset.name].items(): - task_detail = {"name": key, - "output": "{}{}".format(task.get("stdout", ""), task.get("stderr", ""))} - asset_detail["tasks"].append(task_detail) - if self.result["failures"].get(asset.name, None): - asset_detail.update({"status": "failed"}) - for key, task in self.result["failures"][asset.name].items(): - task_detail = {"name": key, - "output": "{}{}".format(task.get("stdout", ""), task.get("stderr", ""))} - asset_detail["tasks"].append(task_detail) - - if self.result["ok"].get(asset.name, None): - for key, task in self.result["ok"][asset.name].items(): - task_detail = {"name": key, - "output": "{}{}".format(task.get("stdout", ""), task.get("stderr", ""))} - asset_detail["tasks"].append(task_detail) + if self.summary.get("excludes", None) and self.summary["excludes"].get(asset.name, None): + asset_detail.update({"status": "excludes"}) result["detail"].append(asset_detail) - return result + break + if self.result["dark"].get(asset.name, None): + asset_detail.update({"status": "failed"}) + for key, task in self.result["dark"][asset.name].items(): + task_detail = {"name": key, + "output": "{}{}".format(task.get("stdout", ""), task.get("stderr", ""))} + asset_detail["tasks"].append(task_detail) + if self.result["failures"].get(asset.name, None): + asset_detail.update({"status": "failed"}) + for key, task in self.result["failures"][asset.name].items(): + task_detail = {"name": key, + "output": "{}{}".format(task.get("stdout", ""), task.get("stderr", ""))} + asset_detail["tasks"].append(task_detail) + + if self.result["ok"].get(asset.name, None): + for key, task in self.result["ok"][asset.name].items(): + task_detail = {"name": key, + "output": "{}{}".format(task.get("stdout", ""), task.get("stderr", ""))} + asset_detail["tasks"].append(task_detail) + result["detail"].append(asset_detail) + return result @property def job_type(self): From 20d2efc407acb3664aff12c93b06c812dbbdc2fa Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Fri, 3 Feb 2023 18:23:38 +0800 Subject: [PATCH 75/92] =?UTF-8?q?perf:=20=E4=B8=BB=E6=9C=BA=E7=A1=AC?= =?UTF-8?q?=E4=BB=B6=E4=BF=A1=E6=81=AF=20(#9429)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng <1304903146@qq.com> --- .../verify_account/host/windows/main.yml | 2 +- apps/accounts/serializers/account/account.py | 15 ++++++++------- .../automations/gather_facts/host/posix/main.yml | 13 +++++++++---- apps/assets/serializers/asset/host.py | 9 +++------ 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/apps/accounts/automations/verify_account/host/windows/main.yml b/apps/accounts/automations/verify_account/host/windows/main.yml index da9d40a74..6e126f34d 100644 --- a/apps/accounts/automations/verify_account/host/windows/main.yml +++ b/apps/accounts/automations/verify_account/host/windows/main.yml @@ -1,5 +1,5 @@ - hosts: windows - gather_facts: yes + gather_facts: no tasks: - name: Verify account ansible.windows.win_ping: diff --git a/apps/accounts/serializers/account/account.py b/apps/accounts/serializers/account/account.py index 36dff55a9..579da474d 100644 --- a/apps/accounts/serializers/account/account.py +++ b/apps/accounts/serializers/account/account.py @@ -17,15 +17,14 @@ class AccountSerializerCreateValidateMixin: replace_attrs: callable def to_internal_value(self, data): - self.id = data.pop('id', None) + _id = data.pop('id', None) ret = super().to_internal_value(data) - self.push_now = ret.pop('push_now', False) - self.template = ret.pop('template', False) + self.id = _id return ret def set_secret(self, attrs): _id = self.id - template = self.template + template = attrs.pop('template', None) if _id and template: account_template = AccountTemplate.objects.get(id=_id) @@ -33,14 +32,16 @@ class AccountSerializerCreateValidateMixin: elif _id and not template: account = Account.objects.get(id=_id) attrs['secret'] = account.secret + return attrs def validate(self, attrs): - self.set_secret(attrs) - return super().validate(attrs) + attrs = super().validate(attrs) + return self.set_secret(attrs) def create(self, validated_data): + push_now = validated_data.pop('push_now', None) instance = super().create(validated_data) - if self.push_now: + if push_now: push_accounts_to_assets.delay([instance.id], [instance.asset_id]) return instance diff --git a/apps/assets/automations/gather_facts/host/posix/main.yml b/apps/assets/automations/gather_facts/host/posix/main.yml index 81aef9aac..89c412f57 100644 --- a/apps/assets/automations/gather_facts/host/posix/main.yml +++ b/apps/assets/automations/gather_facts/host/posix/main.yml @@ -4,16 +4,21 @@ - name: Get info ansible.builtin.set_fact: info: - arch: "{{ ansible_architecture }}" - distribution: "{{ ansible_distribution }}" - distribution_version: "{{ ansible_distribution_version }}" - kernel: "{{ ansible_kernel }}" vendor: "{{ ansible_system_vendor }}" model: "{{ ansible_product_name }}" sn: "{{ ansible_product_serial }}" + cpu_model: "{{ ansible_processor }}" + cpu_count: "{{ ansible_processor_count }}" + cpu_cores: "{{ ansible_processor_cores }}" cpu_vcpus: "{{ ansible_processor_vcpus }}" memory: "{{ ansible_memtotal_mb }}" disk_total: "{{ (ansible_mounts | map(attribute='size_total') | sum / 1024 / 1024 / 1024) | round(2) }}" + distribution: "{{ ansible_distribution }}" + distribution_version: "{{ ansible_distribution_version }}" + arch: "{{ ansible_architecture }}" + kernel: "{{ ansible_kernel }}" + + - debug: var: info diff --git a/apps/assets/serializers/asset/host.py b/apps/assets/serializers/asset/host.py index e01e1bab9..dd8d3bc2f 100644 --- a/apps/assets/serializers/asset/host.py +++ b/apps/assets/serializers/asset/host.py @@ -19,13 +19,10 @@ class HostInfoSerializer(serializers.Serializer): cpu_vcpus = serializers.IntegerField(required=False, label=_('CPU vcpus')) memory = serializers.CharField(max_length=64, allow_blank=True, required=False, label=_('Memory')) disk_total = serializers.CharField(max_length=1024, allow_blank=True, required=False, label=_('Disk total')) - disk_info = serializers.CharField(max_length=1024, allow_blank=True, required=False, label=_('Disk info')) - os = serializers.CharField(max_length=128, allow_blank=True, required=False, label=_('OS')) - os_version = serializers.CharField(max_length=16, allow_blank=True, required=False, label=_('OS version')) - os_arch = serializers.CharField(max_length=16, allow_blank=True, required=False, label=_('OS arch')) - hostname_raw = serializers.CharField(max_length=128, allow_blank=True, required=False, label=_('Hostname raw')) - number = serializers.CharField(max_length=128, allow_blank=True, required=False, label=_('Asset number')) + distribution = serializers.CharField(max_length=128, allow_blank=True, required=False, label=_('OS')) + distribution_version = serializers.CharField(max_length=16, allow_blank=True, required=False, label=_('OS version')) + arch = serializers.CharField(max_length=16, allow_blank=True, required=False, label=_('OS arch')) class HostSerializer(AssetSerializer): From 91357b3715d087c0c29f13ea451049fdf06990bf Mon Sep 17 00:00:00 2001 From: ibuler Date: Fri, 3 Feb 2023 19:44:59 +0800 Subject: [PATCH 76/92] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=20gateway=20?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/serializers/asset/common.py | 69 ++++++++++++++++++------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/apps/assets/serializers/asset/common.py b/apps/assets/serializers/asset/common.py index 33ede81ad..348b6015e 100644 --- a/apps/assets/serializers/asset/common.py +++ b/apps/assets/serializers/asset/common.py @@ -10,6 +10,7 @@ from accounts.models import Account from accounts.serializers import AccountSerializerCreateValidateMixin from common.serializers import WritableNestedModelSerializer, SecretReadableMixin, CommonModelSerializer from common.serializers.fields import LabeledChoiceField +from common.utils import lazyproperty from orgs.mixins.serializers import BulkOrgResourceModelSerializer from ...const import Category, AllTypes from ...models import Asset, Node, Platform, Label, Protocol @@ -107,7 +108,7 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali category = LabeledChoiceField(choices=Category.choices, read_only=True, label=_('Category')) type = LabeledChoiceField(choices=AllTypes.choices(), read_only=True, label=_('Type')) labels = AssetLabelSerializer(many=True, required=False, label=_('Label')) - protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols')) + protocols = AssetProtocolsSerializer(many=True, required=False, label=_('Protocols'), default=()) accounts = AssetAccountSerializer(many=True, required=False, write_only=True, label=_('Account')) class Meta: @@ -134,6 +135,27 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali super().__init__(*args, **kwargs) self._init_field_choices() + def _get_protocols_required_default(self): + platform = self._initial_data_platform + platform_protocols = platform.protocols.all() + protocols_default = [p for p in platform_protocols if p.default] + protocols_required = [p for p in platform_protocols if p.required or p.primary] + return protocols_required, protocols_default + + def _set_protocols_default(self): + if not hasattr(self, 'initial_data'): + return + protocols = self.initial_data.get('protocols') + if protocols is not None: + return + + protocols_required, protocols_default = self._get_protocols_required_default() + protocols_data = [ + {'name': p.name, 'port': p.port} + for p in protocols_required + protocols_default + ] + self.initial_data['protocols'] = protocols_data + def _init_field_choices(self): request = self.context.get('request') if not request: @@ -169,6 +191,26 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali nodes_to_set.append(node) instance.nodes.set(nodes_to_set) + @lazyproperty + def _initial_data_platform(self): + if self.instance: + return self.instance.platform + + platform_id = self.initial_data.get('platform') + if isinstance(platform_id, dict): + platform_id = platform_id.get('id') or platform_id.get('pk') + platform = Platform.objects.filter(id=platform_id).first() + if not platform: + raise serializers.ValidationError({'platform': _("Platform not exist")}) + return platform + + def validate_domain(self, value): + platform = self._initial_data_platform + if platform.domain_enabled: + return value + else: + return None + def validate_nodes(self, nodes): if nodes: return nodes @@ -179,33 +221,20 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali if not node_id: return [] + def is_valid(self, raise_exception=False): + self._set_protocols_default() + return super().is_valid(raise_exception) + def validate_protocols(self, protocols_data): - if not protocols_data: - protocols_data = [] - platform_id = self.initial_data.get('platform') - if isinstance(platform_id, dict): - platform_id = platform_id.get('id') or platform_id.get('pk') - platform = Platform.objects.filter(id=platform_id).first() - if not platform: - raise serializers.ValidationError({'platform': _("Platform not exist")}) - + # 目的是去重 protocols_data_map = {p['name']: p for p in protocols_data} - platform_protocols = platform.protocols.all() - protocols_default = [p for p in platform_protocols if p.default] - protocols_required = [p for p in platform_protocols if p.required or p.primary] - for p in protocols_data: port = p.get('port', 0) if port < 1 or port > 65535: error = p.get('name') + ': ' + _("port out of range (1-65535)") raise serializers.ValidationError(error) - if not protocols_data_map: - protocols_data_map = { - p.name: {'name': p.name, 'port': p.port} - for p in protocols_required + protocols_default - } - + protocols_required, protocols_default = self._get_protocols_required_default() protocols_not_found = [p.name for p in protocols_required if p.name not in protocols_data_map] if protocols_not_found: raise serializers.ValidationError({ From 4960c4b260432b437212f8e5e88b9f3205060e29 Mon Sep 17 00:00:00 2001 From: Bai Date: Fri, 3 Feb 2023 19:53:01 +0800 Subject: [PATCH 77/92] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E8=B5=84=E4=BA=A7ACL=E4=BC=9A=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E6=89=80=E6=9C=89=E7=BB=84=E7=BB=87=E4=B8=8B=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/acls/models/base.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/acls/models/base.py b/apps/acls/models/base.py index 014fec8bd..061fcfd01 100644 --- a/apps/acls/models/base.py +++ b/apps/acls/models/base.py @@ -62,11 +62,15 @@ class UserAssetAccountACLQuerySet(BaseACLQuerySet): return self.filter(q) -class ACLManager(OrgManager): +class ACLManager(models.Manager): def valid(self): return self.get_queryset().valid() +class OrgACLManager(OrgManager, ACLManager): + pass + + class BaseACL(JMSBaseModel): name = models.CharField(max_length=128, verbose_name=_('Name')) priority = models.IntegerField( @@ -97,7 +101,7 @@ class UserAssetAccountBaseACL(BaseACL, OrgModelMixin): # username_group accounts = models.JSONField(verbose_name=_('Account')) - objects = ACLManager.from_queryset(UserAssetAccountACLQuerySet)() + objects = OrgACLManager.from_queryset(UserAssetAccountACLQuerySet)() class Meta(BaseACL.Meta): unique_together = ('name', 'org_id') From 47c5f18c6eacaa865359b3c4b74e391d0f1f56e3 Mon Sep 17 00:00:00 2001 From: Eric Date: Fri, 3 Feb 2023 23:40:58 +0800 Subject: [PATCH 78/92] fix: applet deploy pip install --- apps/terminal/automations/deploy_applet_host/playbook.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/terminal/automations/deploy_applet_host/playbook.yml b/apps/terminal/automations/deploy_applet_host/playbook.yml index 2d2f9fdbe..73e0e6c09 100644 --- a/apps/terminal/automations/deploy_applet_host/playbook.yml +++ b/apps/terminal/automations/deploy_applet_host/playbook.yml @@ -122,8 +122,8 @@ - name: Install python requirements offline ansible.windows.win_shell: > - pip install -r '{{ ansible_env.TEMP }}\pip_packages\requirements.txt' - --no-index --find-links='{{ ansible_env.TEMP }}\pip_packages' + pip install -r '{{ ansible_env.TEMP }}\pip_packages\pip_packages\requirements.txt' + --no-index --find-links='{{ ansible_env.TEMP }}\pip_packages\pip_packages' - name: Download chromedriver (Chromium) ansible.windows.win_get_url: From 1e075c3687e760626e21f27dc90b2b45f144fa01 Mon Sep 17 00:00:00 2001 From: ibuler Date: Mon, 6 Feb 2023 10:23:54 +0800 Subject: [PATCH 79/92] =?UTF-8?q?perf:=20=E4=BF=AE=E6=94=B9=E6=94=AF?= =?UTF-8?q?=E6=8C=81=20connect=20methods?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/connect_methods.py | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/terminal/connect_methods.py b/apps/terminal/connect_methods.py index aa04ff6ab..3b915619b 100644 --- a/apps/terminal/connect_methods.py +++ b/apps/terminal/connect_methods.py @@ -64,6 +64,7 @@ class NativeClient(TextChoices): }, Protocol.rdp: [cls.mstsc], Protocol.mysql: [cls.mysql], + Protocol.mariadb: [cls.mysql], Protocol.oracle: [cls.sqlplus], Protocol.postgresql: [cls.psql], Protocol.redis: [cls.redis], From 4af80bfcdf004c7158a37c24c431e5db301c0db5 Mon Sep 17 00:00:00 2001 From: Bai Date: Sat, 4 Feb 2023 20:42:53 +0800 Subject: [PATCH 80/92] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E4=B8=AD?= =?UTF-8?q?=E6=96=87=E7=BF=BB=E8=AF=91=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/const/types.py | 2 +- apps/assets/serializers/platform.py | 33 +- apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/ja/LC_MESSAGES/django.po | 232 +++-- apps/locale/zh/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.po | 1136 ++++------------------ apps/terminal/serializers/applet_host.py | 2 +- 7 files changed, 337 insertions(+), 1076 deletions(-) diff --git a/apps/assets/const/types.py b/apps/assets/const/types.py index 379a0d188..c42695840 100644 --- a/apps/assets/const/types.py +++ b/apps/assets/const/types.py @@ -197,7 +197,7 @@ class AllTypes(ChoicesMixin): category_type_mapper[p.category] += platform_count[p.id] tp_platforms[p.category + '_' + p.type].append(p) - root = dict(id='ROOT', name=_('All types'), title='所有类型', open=True, isParent=True) + root = dict(id='ROOT', name=_('All types'), title=_('All types'), open=True, isParent=True) nodes = [root] for category, type_cls in cls.category_types(): # Category 格式化 diff --git a/apps/assets/serializers/platform.py b/apps/assets/serializers/platform.py index 0bd4cc06f..c7455fbc2 100644 --- a/apps/assets/serializers/platform.py +++ b/apps/assets/serializers/platform.py @@ -51,18 +51,19 @@ class PlatformAutomationSerializer(serializers.ModelSerializer): "gather_accounts_enabled", "gather_accounts_method", ] extra_kwargs = { - "ping_enabled": {"label": "启用资产探测"}, - "ping_method": {"label": "资产探测方式"}, - "gather_facts_enabled": {"label": "收集资产信息"}, - "gather_facts_method": {"label": "收集信息方式"}, - "verify_account_enabled": {"label": "启用校验账号"}, - "verify_account_method": {"label": "校验账号方式"}, - "change_secret_enabled": {"label": "启用账号改密"}, - "change_secret_method": {"label": "账号改密方式"}, - "push_account_enabled": {"label": "启用推送账号"}, - "push_account_method": {"label": "推送账号方式"}, - "gather_accounts_enabled": {"label": "启用账号收集"}, - "gather_accounts_method": {"label": "收集账号方式"}, + # 启用资产探测 + "ping_enabled": {"label": _("Ping enabled")}, + "ping_method": {"label": _("Ping method")}, + "gather_facts_enabled": {"label": _("Gather facts enabled")}, + "gather_facts_method": {"label": _("Gather facts method")}, + "verify_account_enabled": {"label": _("Verify account enabled")}, + "verify_account_method": {"label": _("Verify account method")}, + "change_secret_enabled": {"label": _("Change secret enabled")}, + "change_secret_method": {"label": _("Change secret method")}, + "push_account_enabled": {"label": _("Push account enabled")}, + "push_account_method": {"label": _("Push account method")}, + "gather_accounts_enabled": {"label": _("Gather accounts enabled")}, + "gather_accounts_method": {"label": _("Gather accounts method")}, } @@ -91,7 +92,7 @@ class PlatformSerializer(WritableNestedModelSerializer): automation = PlatformAutomationSerializer(label=_("Automation"), required=False) su_method = LabeledChoiceField( choices=[("sudo", "sudo su -"), ("su", "su - ")], - label="切换方式", required=False, default="sudo", allow_null=True + label=_("Su method"), required=False, default="sudo", allow_null=True ) class Meta: @@ -107,9 +108,9 @@ class PlatformSerializer(WritableNestedModelSerializer): "comment", ] extra_kwargs = { - "su_enabled": {"label": "启用切换账号"}, - "domain_enabled": {"label": "启用网域"}, - "domain_default": {"label": "默认网域"}, + "su_enabled": {"label": _('Su enabled')}, + "domain_enabled": {"label": _('Domain enabled')}, + "domain_default": {"label": _('Default Domain')}, } @classmethod diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index a1783c9eb..d2bcc3533 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ee001334775456ab2034f9ac1905f7a9299ff763d3d2c9d394d340b75ceffb6f -size 119830 +oid sha256:0673bed993591a5545fc55a94a4329a5d2ab0d4006beb36af2598da1f6edd35c +size 119774 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 3bdf16c09..e84a47233 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-02-03 15:49+0800\n" +"POT-Creation-Date: 2023-02-04 20:29+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -187,13 +187,14 @@ msgstr "によって作成された" msgid "Only create" msgstr "作成された日付" -#: accounts/models/account.py:47 accounts/serializers/account/account.py:80 +#: accounts/models/account.py:47 accounts/serializers/account/account.py:81 #: accounts/serializers/automations/change_secret.py:107 -#: accounts/serializers/automations/change_secret.py:127 acls/models/base.py:96 -#: acls/serializers/base.py:56 assets/models/asset/common.py:97 -#: assets/models/asset/common.py:282 assets/models/cmd_filter.py:36 -#: assets/serializers/domain.py:19 assets/serializers/label.py:27 -#: audits/models.py:34 authentication/models/connection_token.py:32 +#: accounts/serializers/automations/change_secret.py:127 +#: acls/models/base.py:100 acls/serializers/base.py:56 +#: assets/models/asset/common.py:97 assets/models/asset/common.py:282 +#: assets/models/cmd_filter.py:36 assets/serializers/domain.py:19 +#: assets/serializers/label.py:27 audits/models.py:34 +#: authentication/models/connection_token.py:32 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:27 #: terminal/backends/command/models.py:21 terminal/models/session/session.py:31 #: terminal/notifications.py:95 terminal/serializers/command.py:16 @@ -201,7 +202,7 @@ msgstr "作成された日付" msgid "Asset" msgstr "資産" -#: accounts/models/account.py:51 accounts/serializers/account/account.py:84 +#: accounts/models/account.py:51 accounts/serializers/account/account.py:85 #: authentication/serializers/connect_token_secret.py:50 msgid "Su from" msgstr "から切り替え" @@ -211,16 +212,17 @@ msgstr "から切り替え" msgid "Version" msgstr "バージョン" -#: accounts/models/account.py:55 accounts/serializers/account/account.py:81 +#: accounts/models/account.py:55 accounts/serializers/account/account.py:82 #: users/models/user.py:726 msgid "Source" msgstr "ソース" #: accounts/models/account.py:58 #: accounts/serializers/automations/change_secret.py:108 -#: accounts/serializers/automations/change_secret.py:128 acls/models/base.py:98 -#: acls/serializers/base.py:57 assets/serializers/asset/common.py:111 -#: assets/serializers/gateway.py:30 audits/models.py:35 ops/models/base.py:18 +#: accounts/serializers/automations/change_secret.py:128 +#: acls/models/base.py:102 acls/serializers/base.py:57 +#: assets/serializers/asset/common.py:112 assets/serializers/gateway.py:30 +#: audits/models.py:35 ops/models/base.py:18 #: terminal/backends/command/models.py:22 terminal/models/session/session.py:33 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 msgid "Account" @@ -271,7 +273,7 @@ msgstr "アカウントバックアップ計画" #: accounts/models/automations/backup_account.py:77 #: assets/models/automations/base.py:106 audits/models.py:41 -#: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:107 +#: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:106 #: perms/models/asset_permission.py:72 terminal/models/applet/host.py:108 #: terminal/models/session/session.py:43 #: tickets/models/ticket/apply_application.py:30 @@ -357,7 +359,7 @@ msgid "Can add push account execution" msgstr "収集アカウントの作成実行" #: accounts/models/automations/change_secret.py:17 accounts/models/base.py:36 -#: accounts/serializers/account/account.py:117 +#: accounts/serializers/account/account.py:118 #: accounts/serializers/account/base.py:16 #: accounts/serializers/automations/change_secret.py:46 #: authentication/serializers/connect_token_secret.py:41 @@ -404,7 +406,7 @@ msgstr "開始日" #: accounts/models/automations/change_secret.py:74 #: assets/models/automations/base.py:107 ops/models/base.py:56 -#: ops/models/celery.py:64 ops/models/job.py:108 +#: ops/models/celery.py:64 ops/models/job.py:107 #: terminal/models/applet/host.py:109 msgid "Date finished" msgstr "終了日" @@ -444,7 +446,7 @@ msgstr "トリガーモード" msgid "Username" msgstr "ユーザー名" -#: accounts/models/automations/push_account.py:15 acls/models/base.py:77 +#: accounts/models/automations/push_account.py:15 acls/models/base.py:81 #: acls/serializers/base.py:81 assets/models/cmd_filter.py:81 #: audits/models.py:51 audits/serializers.py:82 #: authentication/serializers/connect_token_secret.py:109 @@ -462,18 +464,18 @@ msgstr "サービスアカウントです" msgid "Verify asset account" msgstr "パスワード/キーの確認" -#: accounts/models/base.py:33 acls/models/base.py:71 +#: accounts/models/base.py:33 acls/models/base.py:75 #: acls/models/command_acl.py:21 acls/serializers/base.py:34 #: applications/models.py:9 assets/models/_user.py:22 #: assets/models/asset/common.py:95 assets/models/asset/common.py:107 #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 #: assets/models/group.py:20 assets/models/label.py:18 #: assets/models/platform.py:20 assets/models/platform.py:74 -#: assets/serializers/asset/common.py:60 assets/serializers/asset/common.py:128 -#: assets/serializers/platform.py:125 +#: assets/serializers/asset/common.py:61 assets/serializers/asset/common.py:129 +#: assets/serializers/platform.py:137 #: authentication/serializers/connect_token_secret.py:103 ops/mixin.py:20 #: ops/models/adhoc.py:22 ops/models/celery.py:15 ops/models/celery.py:57 -#: ops/models/job.py:25 ops/models/playbook.py:15 orgs/models.py:69 +#: ops/models/job.py:24 ops/models/playbook.py:15 orgs/models.py:69 #: perms/models/asset_permission.py:56 rbac/models/role.py:29 #: settings/models.py:33 settings/serializers/sms.py:6 #: terminal/models/applet/applet.py:24 terminal/models/component/endpoint.py:12 @@ -538,23 +540,23 @@ msgstr "" "{} -暗号化変更タスクが完了しました: 暗号化パスワードが設定されていません-個人" "情報にアクセスしてください-> ファイル暗号化パスワードを設定してください" -#: accounts/serializers/account/account.py:52 -#: assets/serializers/asset/common.py:58 settings/serializers/auth/sms.py:75 +#: accounts/serializers/account/account.py:53 +#: assets/serializers/asset/common.py:59 settings/serializers/auth/sms.py:75 msgid "Template" msgstr "テンプレート" -#: accounts/serializers/account/account.py:55 -#: assets/serializers/asset/common.py:55 +#: accounts/serializers/account/account.py:56 +#: assets/serializers/asset/common.py:56 msgid "Push now" msgstr "" -#: accounts/serializers/account/account.py:57 +#: accounts/serializers/account/account.py:58 #: accounts/serializers/account/base.py:64 #, fuzzy msgid "Has secret" msgstr "ひみつ" -#: accounts/serializers/account/account.py:76 +#: accounts/serializers/account/account.py:77 #, fuzzy #| msgid "Asset Info" msgid "Asset not found" @@ -587,7 +589,7 @@ msgid "Key password" msgstr "キーパスワード" #: accounts/serializers/account/base.py:80 -#: assets/serializers/asset/common.py:233 +#: assets/serializers/asset/common.py:262 #, fuzzy #| msgid "Ticket flow" msgid "Spec info" @@ -596,7 +598,7 @@ msgstr "チケットの流れ" #: accounts/serializers/automations/base.py:22 #: assets/models/automations/base.py:19 #: assets/serializers/automations/base.py:20 ops/models/base.py:17 -#: ops/models/job.py:35 +#: ops/models/job.py:34 #: terminal/templates/terminal/_msg_command_execute_alert.html:16 msgid "Assets" msgstr "資産" @@ -619,9 +621,9 @@ msgstr "製造オーダスナップショット" #: acls/serializers/command_acl.py:18 applications/models.py:14 #: assets/models/_user.py:50 assets/models/automations/base.py:20 #: assets/models/cmd_filter.py:74 assets/models/platform.py:76 -#: assets/serializers/asset/common.py:108 assets/serializers/platform.py:86 +#: assets/serializers/asset/common.py:109 assets/serializers/platform.py:98 #: audits/serializers.py:48 -#: authentication/serializers/connect_token_secret.py:116 ops/models/job.py:33 +#: authentication/serializers/connect_token_secret.py:116 ops/models/job.py:32 #: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:28 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:146 terminal/serializers/applet.py:28 @@ -726,23 +728,23 @@ msgstr "受け入れられる" msgid "Review" msgstr "レビュー担当者" -#: acls/models/base.py:73 assets/models/_user.py:51 +#: acls/models/base.py:77 assets/models/_user.py:51 #: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:93 msgid "Priority" msgstr "優先順位" -#: acls/models/base.py:74 assets/models/_user.py:51 +#: acls/models/base.py:78 assets/models/_user.py:51 #: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:94 msgid "1-100, the lower the value will be match first" msgstr "1-100、低い値は最初に一致します" -#: acls/models/base.py:78 acls/serializers/base.py:75 +#: acls/models/base.py:82 acls/serializers/base.py:75 #: acls/serializers/login_acl.py:23 assets/models/cmd_filter.py:86 #: authentication/serializers/connect_token_secret.py:82 msgid "Reviewers" msgstr "レビュー担当者" -#: acls/models/base.py:79 authentication/models/access_key.py:17 +#: acls/models/base.py:83 authentication/models/access_key.py:17 #: authentication/models/connection_token.py:47 #: authentication/templates/authentication/_access_key_modal.html:32 #: perms/models/asset_permission.py:76 terminal/models/session/sharing.py:27 @@ -750,7 +752,7 @@ msgstr "レビュー担当者" msgid "Active" msgstr "アクティブ" -#: acls/models/base.py:94 acls/models/login_acl.py:13 +#: acls/models/base.py:98 acls/models/login_acl.py:13 #: acls/serializers/base.py:55 acls/serializers/login_acl.py:21 #: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:30 #: audits/models.py:49 audits/models.py:98 @@ -845,7 +847,7 @@ msgstr "" "192.168.10.1、192.168.1.0/24、10.1.1.1-10.1.1.20、2001:db8:2de::e13、2001:" "db8:1a:1110:::/64 (ドメイン名サポート)" -#: acls/serializers/base.py:40 assets/serializers/asset/host.py:40 +#: acls/serializers/base.py:40 assets/serializers/asset/host.py:37 msgid "IP/Host" msgstr "IP/ホスト" @@ -925,9 +927,9 @@ msgid "Applications" msgstr "アプリケーション" #: applications/models.py:11 assets/models/label.py:21 -#: assets/models/platform.py:75 assets/serializers/asset/common.py:107 -#: assets/serializers/cagegory.py:8 assets/serializers/platform.py:87 -#: assets/serializers/platform.py:126 perms/serializers/user_permission.py:25 +#: assets/models/platform.py:75 assets/serializers/asset/common.py:108 +#: assets/serializers/cagegory.py:8 assets/serializers/platform.py:99 +#: assets/serializers/platform.py:138 perms/serializers/user_permission.py:25 #: settings/models.py:35 tickets/models/ticket/apply_application.py:13 msgid "Category" msgstr "カテゴリ" @@ -962,7 +964,9 @@ msgstr "" #: assets/api/asset/asset.py:115 msgid "Cannot create asset directly, you should create a host or other" -msgstr "資産を直接作成することはできません。ホストまたはその他を作成する必要があります" +msgstr "" +"資産を直接作成することはできません。ホストまたはその他を作成する必要がありま" +"す" #: assets/api/domain.py:57 msgid "Number required" @@ -1046,7 +1050,7 @@ msgid "Device" msgstr "" #: assets/const/category.py:13 assets/models/asset/database.py:9 -#: assets/models/asset/database.py:24 assets/serializers/asset/common.py:95 +#: assets/models/asset/database.py:24 assets/serializers/asset/common.py:96 msgid "Database" msgstr "データベース" @@ -1100,7 +1104,7 @@ msgstr "SSHパブリックキー" #: assets/models/_user.py:27 assets/models/cmd_filter.py:40 #: assets/models/cmd_filter.py:88 assets/models/group.py:23 #: assets/models/platform.py:79 common/db/models.py:37 ops/models/adhoc.py:28 -#: ops/models/job.py:41 ops/models/playbook.py:18 rbac/models/role.py:37 +#: ops/models/job.py:40 ops/models/playbook.py:18 rbac/models/role.py:37 #: settings/models.py:38 terminal/models/applet/applet.py:33 #: terminal/models/applet/applet.py:146 terminal/models/applet/host.py:110 #: terminal/models/component/endpoint.py:24 @@ -1113,7 +1117,7 @@ msgstr "コメント" #: assets/models/_user.py:28 assets/models/automations/base.py:105 #: assets/models/cmd_filter.py:41 assets/models/group.py:22 -#: common/db/models.py:35 ops/models/base.py:54 ops/models/job.py:106 +#: common/db/models.py:35 ops/models/base.py:54 ops/models/job.py:105 #: users/models/user.py:932 msgid "Date created" msgstr "作成された日付" @@ -1248,7 +1252,7 @@ msgstr "ノードにアセットを追加する" msgid "Move asset to node" msgstr "アセットをノードに移動する" -#: assets/models/asset/database.py:10 assets/serializers/asset/common.py:96 +#: assets/models/asset/database.py:10 assets/serializers/asset/common.py:97 #: settings/serializers/email.py:37 msgid "Use SSL" msgstr "SSLの使用" @@ -1268,7 +1272,7 @@ msgstr "クライアント秘密" msgid "Client key" msgstr "クライアント" -#: assets/models/asset/database.py:14 assets/serializers/asset/common.py:97 +#: assets/models/asset/database.py:14 assets/serializers/asset/common.py:98 msgid "Allow invalid cert" msgstr "証明書チェックを無視" @@ -1283,7 +1287,7 @@ msgid "Basic" msgstr "基本" #: assets/models/asset/web.py:11 assets/models/asset/web.py:17 -#: assets/serializers/asset/common.py:103 +#: assets/serializers/asset/common.py:104 msgid "Script" msgstr "" @@ -1292,25 +1296,25 @@ msgstr "" msgid "Autofill" msgstr "自動" -#: assets/models/asset/web.py:14 assets/serializers/asset/common.py:100 +#: assets/models/asset/web.py:14 assets/serializers/asset/common.py:101 #: assets/serializers/platform.py:30 #, fuzzy msgid "Username selector" msgstr "ユーザー名のプロパティ" -#: assets/models/asset/web.py:15 assets/serializers/asset/common.py:101 +#: assets/models/asset/web.py:15 assets/serializers/asset/common.py:102 #: assets/serializers/platform.py:33 #, fuzzy msgid "Password selector" msgstr "パスワードルール" -#: assets/models/asset/web.py:16 assets/serializers/asset/common.py:102 +#: assets/models/asset/web.py:16 assets/serializers/asset/common.py:103 #: assets/serializers/platform.py:36 msgid "Submit selector" msgstr "" #: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38 -#: assets/serializers/asset/common.py:232 perms/models/asset_permission.py:70 +#: assets/serializers/asset/common.py:261 perms/models/asset_permission.py:70 #: perms/serializers/permission.py:32 rbac/tree.py:36 msgid "Accounts" msgstr "アカウント" @@ -1326,7 +1330,7 @@ msgid "Asset automation task" msgstr "自動管理" #: assets/models/automations/base.py:104 audits/models.py:134 -#: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:99 +#: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:98 #: terminal/models/applet/applet.py:145 terminal/models/applet/host.py:107 #: terminal/models/component/status.py:27 terminal/serializers/applet.py:17 #: terminal/serializers/applet_host.py:93 tickets/models/ticket/general.py:283 @@ -1419,7 +1423,7 @@ msgstr "システム" msgid "Value" msgstr "値" -#: assets/models/label.py:40 assets/serializers/asset/common.py:109 +#: assets/models/label.py:40 assets/serializers/asset/common.py:110 #: assets/serializers/cagegory.py:6 assets/serializers/cagegory.py:13 #: authentication/serializers/connect_token_secret.py:114 #: common/serializers/common.py:79 settings/serializers/sms.py:7 @@ -1474,51 +1478,53 @@ msgstr "有効化" msgid "Ansible config" msgstr "" -#: assets/models/platform.py:43 +#: assets/models/platform.py:43 assets/serializers/platform.py:55 #, fuzzy msgid "Ping enabled" msgstr "MFA有効化" -#: assets/models/platform.py:44 +#: assets/models/platform.py:44 assets/serializers/platform.py:57 msgid "Ping method" msgstr "" #: assets/models/platform.py:45 assets/models/platform.py:58 +#: assets/serializers/platform.py:59 #, fuzzy msgid "Gather facts enabled" msgstr "資産ユーザーの収集" #: assets/models/platform.py:46 assets/models/platform.py:60 +#: assets/serializers/platform.py:61 #, fuzzy msgid "Gather facts method" msgstr "資産ユーザーの収集" -#: assets/models/platform.py:47 +#: assets/models/platform.py:47 assets/serializers/platform.py:67 #, fuzzy msgid "Change secret enabled" msgstr "パスワードの変更" -#: assets/models/platform.py:49 +#: assets/models/platform.py:49 assets/serializers/platform.py:69 #, fuzzy msgid "Change secret method" msgstr "パスワードの変更" -#: assets/models/platform.py:51 +#: assets/models/platform.py:51 assets/serializers/platform.py:71 #, fuzzy msgid "Push account enabled" msgstr "MFAが有効化されていません" -#: assets/models/platform.py:53 +#: assets/models/platform.py:53 assets/serializers/platform.py:73 #, fuzzy msgid "Push account method" msgstr "サービスアカウントです" -#: assets/models/platform.py:55 +#: assets/models/platform.py:55 assets/serializers/platform.py:63 #, fuzzy msgid "Verify account enabled" msgstr "サービスアカウントキー" -#: assets/models/platform.py:57 +#: assets/models/platform.py:57 assets/serializers/platform.py:65 #, fuzzy msgid "Verify account method" msgstr "パスワード/キーの確認" @@ -1531,26 +1537,25 @@ msgstr "メタ" msgid "Internal" msgstr "ビルトイン" -#: assets/models/platform.py:82 assets/serializers/platform.py:84 +#: assets/models/platform.py:82 assets/serializers/platform.py:96 msgid "Charset" msgstr "シャーセット" -#: assets/models/platform.py:84 +#: assets/models/platform.py:84 assets/serializers/platform.py:123 #, fuzzy msgid "Domain enabled" msgstr "ドメイン名" -#: assets/models/platform.py:86 -#, fuzzy +#: assets/models/platform.py:86 assets/serializers/platform.py:122 msgid "Su enabled" -msgstr "MFA有効化" +msgstr "アカウントの切り替えを有効にする" -#: assets/models/platform.py:87 +#: assets/models/platform.py:87 assets/serializers/platform.py:106 #, fuzzy msgid "Su method" msgstr "接続タイムアウト" -#: assets/models/platform.py:89 assets/serializers/platform.py:91 +#: assets/models/platform.py:89 assets/serializers/platform.py:103 #, fuzzy msgid "Automation" msgstr "自動管理" @@ -1560,12 +1565,12 @@ msgstr "自動管理" msgid "%(value)s is not an even number" msgstr "%(value)s は偶数ではありません" -#: assets/serializers/asset/common.py:99 +#: assets/serializers/asset/common.py:100 #, fuzzy msgid "Auto fill" msgstr "自動" -#: assets/serializers/asset/common.py:110 assets/serializers/platform.py:89 +#: assets/serializers/asset/common.py:111 assets/serializers/platform.py:101 #: authentication/serializers/connect_token_secret.py:28 #: authentication/serializers/connect_token_secret.py:66 #: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:107 @@ -1573,27 +1578,27 @@ msgstr "自動" msgid "Protocols" msgstr "プロトコル" -#: assets/serializers/asset/common.py:129 +#: assets/serializers/asset/common.py:130 msgid "Address" msgstr "アドレス" -#: assets/serializers/asset/common.py:130 +#: assets/serializers/asset/common.py:131 msgid "Node path" msgstr "ノードパスです" -#: assets/serializers/asset/common.py:190 +#: assets/serializers/asset/common.py:204 msgid "Platform not exist" msgstr "プラットフォームが存在しません" -#: assets/serializers/asset/common.py:200 +#: assets/serializers/asset/common.py:234 msgid "port out of range (1-65535)" msgstr "ポート番号が範囲外です (1-65535)" -#: assets/serializers/asset/common.py:212 +#: assets/serializers/asset/common.py:241 msgid "Protocol is required: {}" msgstr "プロトコルが必要です: {}" -#: assets/serializers/asset/common.py:234 +#: assets/serializers/asset/common.py:263 msgid "Auto info" msgstr "自動情報" @@ -1639,31 +1644,19 @@ msgstr "メモリ" msgid "Disk total" msgstr "ディスクの合計" -#: assets/serializers/asset/host.py:22 -msgid "Disk info" -msgstr "ディスク情報" - -#: assets/serializers/asset/host.py:24 +#: assets/serializers/asset/host.py:23 #: authentication/serializers/connect_token_secret.py:105 msgid "OS" msgstr "OS" -#: assets/serializers/asset/host.py:25 +#: assets/serializers/asset/host.py:24 msgid "OS version" msgstr "システムバージョン" -#: assets/serializers/asset/host.py:26 +#: assets/serializers/asset/host.py:25 msgid "OS arch" msgstr "システムアーキテクチャ" -#: assets/serializers/asset/host.py:27 -msgid "Hostname raw" -msgstr "ホスト名生" - -#: assets/serializers/asset/host.py:28 -msgid "Asset number" -msgstr "資産番号" - #: assets/serializers/cagegory.py:9 msgid "Constraints" msgstr "" @@ -1703,10 +1696,26 @@ msgstr "MFA有効化" msgid "SFTP home" msgstr "SFTPルート" -#: assets/serializers/platform.py:71 +#: assets/serializers/platform.py:75 +#, fuzzy +msgid "Gather accounts enabled" +msgstr "資産ユーザーの収集" + +#: assets/serializers/platform.py:77 +#, fuzzy +msgid "Gather accounts method" +msgstr "資産ユーザーの収集" + +#: assets/serializers/platform.py:83 msgid "Primary" msgstr "" +#: assets/serializers/platform.py:124 +#, fuzzy +#| msgid "Default storage" +msgid "Default Domain" +msgstr "デフォルトのストレージ" + #: assets/tasks/automation.py:11 #, fuzzy msgid "Asset execute automation" @@ -2033,7 +2042,7 @@ msgstr "資産情報" #: authentication/api/connection_token.py:267 #, fuzzy #| msgid "Permission name" -msgid "Permission Expired" +msgid "Permission expired" msgstr "認可ルール名" #: authentication/api/connection_token.py:279 @@ -3335,7 +3344,7 @@ msgstr "CAS" msgid "Adhoc" msgstr "コマンド#コマンド#" -#: ops/const.py:39 ops/models/job.py:32 +#: ops/const.py:39 ops/models/job.py:31 msgid "Playbook" msgstr "Playbook" @@ -3400,17 +3409,17 @@ msgstr "定期的または定期的に設定を行う必要があります" msgid "Pattern" msgstr "パターン" -#: ops/models/adhoc.py:25 ops/models/job.py:29 +#: ops/models/adhoc.py:25 ops/models/job.py:28 msgid "Module" msgstr "モジュール" -#: ops/models/adhoc.py:26 ops/models/celery.py:58 ops/models/job.py:27 +#: ops/models/adhoc.py:26 ops/models/celery.py:58 ops/models/job.py:26 #: terminal/models/component/task.py:16 msgid "Args" msgstr "アルグ" #: ops/models/adhoc.py:27 ops/models/base.py:16 ops/models/base.py:53 -#: ops/models/job.py:34 ops/models/job.py:105 ops/models/playbook.py:17 +#: ops/models/job.py:33 ops/models/job.py:104 ops/models/playbook.py:17 #: terminal/models/session/sharing.py:23 msgid "Creator" msgstr "作成者" @@ -3434,12 +3443,12 @@ msgstr "コマンド実行" msgid "Date last run" msgstr "最終同期日" -#: ops/models/base.py:51 ops/models/job.py:103 +#: ops/models/base.py:51 ops/models/job.py:102 #: xpack/plugins/cloud/models.py:170 msgid "Result" msgstr "結果" -#: ops/models/base.py:52 ops/models/job.py:104 +#: ops/models/base.py:52 ops/models/job.py:103 msgid "Summary" msgstr "概要" @@ -3481,35 +3490,35 @@ msgstr "終了日" msgid "Celery Task Execution" msgstr "Celery タスク実行" -#: ops/models/job.py:30 +#: ops/models/job.py:29 msgid "Chdir" msgstr "Chdir" -#: ops/models/job.py:31 +#: ops/models/job.py:30 msgid "Timeout (Seconds)" msgstr "タイムアウト(秒)" -#: ops/models/job.py:36 +#: ops/models/job.py:35 msgid "Runas" msgstr "Runas" -#: ops/models/job.py:38 +#: ops/models/job.py:37 msgid "Runas policy" msgstr "Runas ポリシー" -#: ops/models/job.py:39 +#: ops/models/job.py:38 msgid "Use Parameter Define" msgstr "パラメータ定義を使用する" -#: ops/models/job.py:40 +#: ops/models/job.py:39 msgid "Parameters define" msgstr "パラメータ定義" -#: ops/models/job.py:92 +#: ops/models/job.py:91 msgid "Job" msgstr "ジョブ#ジョブ#" -#: ops/models/job.py:102 +#: ops/models/job.py:101 msgid "Parameters" msgstr "パラメータ" @@ -5849,7 +5858,7 @@ msgid "RDS Licensing Mode" msgstr "" #: terminal/serializers/applet_host.py:37 -msgid "RDS fSingleSessionPerUser" +msgid "RDS Single Session Per User" msgstr "" #: terminal/serializers/applet_host.py:38 @@ -7551,6 +7560,15 @@ msgstr "究極のエディション" msgid "Community edition" msgstr "コミュニティ版" +#~ msgid "Disk info" +#~ msgstr "ディスク情報" + +#~ msgid "Hostname raw" +#~ msgstr "ホスト名生" + +#~ msgid "Asset number" +#~ msgstr "資産番号" + #, fuzzy #~| msgid "Enabled" #~ msgid "Enabled info" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 2f6cd1ef1..155cf328b 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:51dd2a03462cbc3ae08d6257dec51a867b3431bf6b0800c996847a219a11aee0 -size 106203 +oid sha256:5f46cbb3f66e7bb47e3a5830bad87c62d743fd3205373cb3b2b55ad3045633d7 +size 111689 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 84742c7d2..8a4bb7d36 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-02-03 15:49+0800\n" +"POT-Creation-Date: 2023-02-04 20:29+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -66,14 +66,10 @@ msgid "Local" msgstr "数据库" #: accounts/const/account.py:20 -#, fuzzy -#| msgid "Collect" msgid "Collected" msgstr "收集" #: accounts/const/automation.py:22 rbac/tree.py:51 -#, fuzzy -#| msgid "Push asset account" msgid "Push account" msgstr "账号推送" @@ -90,10 +86,8 @@ msgid "Gather accounts" msgstr "收集账号" #: accounts/const/automation.py:26 -#, fuzzy -#| msgid "Verify asset account" msgid "Verify gateway account" -msgstr "账号验证" +msgstr "验证网关账号" #: accounts/const/automation.py:44 msgid "Specific password" @@ -120,54 +114,40 @@ msgid "On asset create" msgstr "资产创建时" #: accounts/const/automation.py:59 -#, fuzzy -#| msgid "On perm change" msgid "On perm add user" -msgstr "授权变更时" +msgstr "授权变更时添加用户" #: accounts/const/automation.py:61 msgid "On perm add user group" -msgstr "" +msgstr "授权变更时添加用户组" #: accounts/const/automation.py:63 -#, fuzzy -#| msgid "permed assets" msgid "On perm add asset" -msgstr "授权的资产" +msgstr "授权变更时添加资产" #: accounts/const/automation.py:65 -#, fuzzy -#| msgid "On perm change" msgid "On perm add node" -msgstr "授权变更时" +msgstr "授权变更时添加节点" #: accounts/const/automation.py:67 -#, fuzzy -#| msgid "Permed account" msgid "On perm add account" -msgstr "授权账号" +msgstr "授权的账号" #: accounts/const/automation.py:69 -#, fuzzy -#| msgid "Add asset to node" msgid "On asset join node" -msgstr "添加资产到节点" +msgstr "资产变更时添加到节点" #: accounts/const/automation.py:71 -#, fuzzy -#| msgid "User group" msgid "On user join group" -msgstr "用户组" +msgstr "用户变更时添加到用户组" #: accounts/const/automation.py:79 msgid "On perm change" msgstr "授权变更时" #: accounts/const/automation.py:86 -#, fuzzy -#| msgid "Perm ungroup node" msgid "Inherit from group or node" -msgstr "显示未分组节点" +msgstr "继承自用户组或资产节点" #: accounts/const/automation.py:94 msgid "Create and push" @@ -177,13 +157,14 @@ msgstr "创建并推送到资产" msgid "Only create" msgstr "仅创建到资产" -#: accounts/models/account.py:47 accounts/serializers/account/account.py:80 +#: accounts/models/account.py:47 accounts/serializers/account/account.py:81 #: accounts/serializers/automations/change_secret.py:107 -#: accounts/serializers/automations/change_secret.py:127 acls/models/base.py:96 -#: acls/serializers/base.py:56 assets/models/asset/common.py:97 -#: assets/models/asset/common.py:282 assets/models/cmd_filter.py:36 -#: assets/serializers/domain.py:19 assets/serializers/label.py:27 -#: audits/models.py:34 authentication/models/connection_token.py:32 +#: accounts/serializers/automations/change_secret.py:127 +#: acls/models/base.py:100 acls/serializers/base.py:56 +#: assets/models/asset/common.py:97 assets/models/asset/common.py:282 +#: assets/models/cmd_filter.py:36 assets/serializers/domain.py:19 +#: assets/serializers/label.py:27 audits/models.py:34 +#: authentication/models/connection_token.py:32 #: perms/models/asset_permission.py:64 perms/serializers/permission.py:27 #: terminal/backends/command/models.py:21 terminal/models/session/session.py:31 #: terminal/notifications.py:95 terminal/serializers/command.py:16 @@ -191,7 +172,7 @@ msgstr "仅创建到资产" msgid "Asset" msgstr "资产" -#: accounts/models/account.py:51 accounts/serializers/account/account.py:84 +#: accounts/models/account.py:51 accounts/serializers/account/account.py:85 #: authentication/serializers/connect_token_secret.py:50 msgid "Su from" msgstr "切换自" @@ -201,16 +182,17 @@ msgstr "切换自" msgid "Version" msgstr "版本" -#: accounts/models/account.py:55 accounts/serializers/account/account.py:81 +#: accounts/models/account.py:55 accounts/serializers/account/account.py:82 #: users/models/user.py:726 msgid "Source" msgstr "来源" #: accounts/models/account.py:58 #: accounts/serializers/automations/change_secret.py:108 -#: accounts/serializers/automations/change_secret.py:128 acls/models/base.py:98 -#: acls/serializers/base.py:57 assets/serializers/asset/common.py:111 -#: assets/serializers/gateway.py:30 audits/models.py:35 ops/models/base.py:18 +#: accounts/serializers/automations/change_secret.py:128 +#: acls/models/base.py:102 acls/serializers/base.py:57 +#: assets/serializers/asset/common.py:112 assets/serializers/gateway.py:30 +#: audits/models.py:35 ops/models/base.py:18 #: terminal/backends/command/models.py:22 terminal/models/session/session.py:33 #: tickets/models/ticket/command_confirm.py:13 xpack/plugins/cloud/models.py:85 msgid "Account" @@ -258,7 +240,7 @@ msgstr "账号备份计划" #: accounts/models/automations/backup_account.py:77 #: assets/models/automations/base.py:106 audits/models.py:41 -#: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:107 +#: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:106 #: perms/models/asset_permission.py:72 terminal/models/applet/host.py:108 #: terminal/models/session/session.py:43 #: tickets/models/ticket/apply_application.py:30 @@ -301,22 +283,16 @@ msgid "Account backup execution" msgstr "账号备份执行" #: accounts/models/automations/base.py:15 -#, fuzzy -#| msgid "Automation task" msgid "Account automation task" -msgstr "自动化任务" +msgstr "账号自动化任务" #: accounts/models/automations/base.py:25 -#, fuzzy -#| msgid "Automation task execution" msgid "Automation execution" -msgstr "自动化任务执行历史" +msgstr "自动化执行" #: accounts/models/automations/base.py:26 -#, fuzzy -#| msgid "Automation task execution" msgid "Automation executions" -msgstr "自动化任务执行历史" +msgstr "自动化执行" #: accounts/models/automations/base.py:28 msgid "Can view change secret execution" @@ -335,19 +311,15 @@ msgid "Can add gather accounts execution" msgstr "创建收集账号执行" #: accounts/models/automations/base.py:34 -#, fuzzy -#| msgid "Can view gather accounts execution" msgid "Can view push account execution" -msgstr "查看收集账号执行" +msgstr "可以查看推送账号执行" #: accounts/models/automations/base.py:35 -#, fuzzy -#| msgid "Can add gather accounts execution" msgid "Can add push account execution" -msgstr "创建收集账号执行" +msgstr "可以创建推送账号执行" #: accounts/models/automations/change_secret.py:17 accounts/models/base.py:36 -#: accounts/serializers/account/account.py:117 +#: accounts/serializers/account/account.py:118 #: accounts/serializers/account/base.py:16 #: accounts/serializers/automations/change_secret.py:46 #: authentication/serializers/connect_token_secret.py:41 @@ -390,7 +362,7 @@ msgstr "开始日期" #: accounts/models/automations/change_secret.py:74 #: assets/models/automations/base.py:107 ops/models/base.py:56 -#: ops/models/celery.py:64 ops/models/job.py:108 +#: ops/models/celery.py:64 ops/models/job.py:107 #: terminal/models/applet/host.py:109 msgid "Date finished" msgstr "结束日期" @@ -410,8 +382,6 @@ msgid "Gather asset accounts" msgstr "收集账号" #: accounts/models/automations/push_account.py:13 -#, fuzzy -#| msgid "Trigger" msgid "Triggers" msgstr "触发方式" @@ -427,7 +397,7 @@ msgstr "触发方式" msgid "Username" msgstr "用户名" -#: accounts/models/automations/push_account.py:15 acls/models/base.py:77 +#: accounts/models/automations/push_account.py:15 acls/models/base.py:81 #: acls/serializers/base.py:81 assets/models/cmd_filter.py:81 #: audits/models.py:51 audits/serializers.py:82 #: authentication/serializers/connect_token_secret.py:109 @@ -443,18 +413,18 @@ msgstr "账号推送" msgid "Verify asset account" msgstr "账号验证" -#: accounts/models/base.py:33 acls/models/base.py:71 +#: accounts/models/base.py:33 acls/models/base.py:75 #: acls/models/command_acl.py:21 acls/serializers/base.py:34 #: applications/models.py:9 assets/models/_user.py:22 #: assets/models/asset/common.py:95 assets/models/asset/common.py:107 #: assets/models/cmd_filter.py:21 assets/models/domain.py:18 #: assets/models/group.py:20 assets/models/label.py:18 #: assets/models/platform.py:20 assets/models/platform.py:74 -#: assets/serializers/asset/common.py:60 assets/serializers/asset/common.py:128 -#: assets/serializers/platform.py:125 +#: assets/serializers/asset/common.py:61 assets/serializers/asset/common.py:129 +#: assets/serializers/platform.py:137 #: authentication/serializers/connect_token_secret.py:103 ops/mixin.py:20 #: ops/models/adhoc.py:22 ops/models/celery.py:15 ops/models/celery.py:57 -#: ops/models/job.py:25 ops/models/playbook.py:15 orgs/models.py:69 +#: ops/models/job.py:24 ops/models/playbook.py:15 orgs/models.py:69 #: perms/models/asset_permission.py:56 rbac/models/role.py:29 #: settings/models.py:33 settings/serializers/sms.py:6 #: terminal/models/applet/applet.py:24 terminal/models/component/endpoint.py:12 @@ -516,22 +486,22 @@ msgstr "" "{} - 改密任务已完成: 未设置加密密码 - 请前往个人信息 -> 文件加密密码中设置加" "密密码" -#: accounts/serializers/account/account.py:52 -#: assets/serializers/asset/common.py:58 settings/serializers/auth/sms.py:75 +#: accounts/serializers/account/account.py:53 +#: assets/serializers/asset/common.py:59 settings/serializers/auth/sms.py:75 msgid "Template" msgstr "模板" -#: accounts/serializers/account/account.py:55 -#: assets/serializers/asset/common.py:55 +#: accounts/serializers/account/account.py:56 +#: assets/serializers/asset/common.py:56 msgid "Push now" msgstr "立即推送" -#: accounts/serializers/account/account.py:57 +#: accounts/serializers/account/account.py:58 #: accounts/serializers/account/base.py:64 msgid "Has secret" msgstr "已托管密码" -#: accounts/serializers/account/account.py:76 +#: accounts/serializers/account/account.py:77 msgid "Asset not found" msgstr "资产不存在" @@ -561,16 +531,14 @@ msgid "Key password" msgstr "密钥密码" #: accounts/serializers/account/base.py:80 -#: assets/serializers/asset/common.py:233 -#, fuzzy -#| msgid "Specific" +#: assets/serializers/asset/common.py:262 msgid "Spec info" -msgstr "指定的" +msgstr "特殊信息" #: accounts/serializers/automations/base.py:22 #: assets/models/automations/base.py:19 #: assets/serializers/automations/base.py:20 ops/models/base.py:17 -#: ops/models/job.py:35 +#: ops/models/job.py:34 #: terminal/templates/terminal/_msg_command_execute_alert.html:16 msgid "Assets" msgstr "资产" @@ -592,9 +560,9 @@ msgstr "工单快照" #: acls/serializers/command_acl.py:18 applications/models.py:14 #: assets/models/_user.py:50 assets/models/automations/base.py:20 #: assets/models/cmd_filter.py:74 assets/models/platform.py:76 -#: assets/serializers/asset/common.py:108 assets/serializers/platform.py:86 +#: assets/serializers/asset/common.py:109 assets/serializers/platform.py:98 #: audits/serializers.py:48 -#: authentication/serializers/connect_token_secret.py:116 ops/models/job.py:33 +#: authentication/serializers/connect_token_secret.py:116 ops/models/job.py:32 #: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:28 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:146 terminal/serializers/applet.py:28 @@ -637,10 +605,8 @@ msgid "Failed" msgstr "失败" #: accounts/tasks/automation.py:11 -#, fuzzy -#| msgid "Execute automation" msgid "Account execute automation" -msgstr "执行自动化任务" +msgstr "账号执行自动化" #: accounts/tasks/backup_account.py:13 msgid "Execute account backup plan" @@ -656,7 +622,7 @@ msgstr "推送账号到资产" #: accounts/tasks/verify_account.py:41 msgid "Verify asset account availability" -msgstr "" +msgstr "验证资产账号可用性" #: accounts/tasks/verify_account.py:47 msgid "Verify accounts connectivity" @@ -695,23 +661,23 @@ msgstr "接受" msgid "Review" msgstr "审批" -#: acls/models/base.py:73 assets/models/_user.py:51 +#: acls/models/base.py:77 assets/models/_user.py:51 #: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:93 msgid "Priority" msgstr "优先级" -#: acls/models/base.py:74 assets/models/_user.py:51 +#: acls/models/base.py:78 assets/models/_user.py:51 #: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:94 msgid "1-100, the lower the value will be match first" msgstr "优先级可选范围为 1-100 (数值越小越优先)" -#: acls/models/base.py:78 acls/serializers/base.py:75 +#: acls/models/base.py:82 acls/serializers/base.py:75 #: acls/serializers/login_acl.py:23 assets/models/cmd_filter.py:86 #: authentication/serializers/connect_token_secret.py:82 msgid "Reviewers" msgstr "审批人" -#: acls/models/base.py:79 authentication/models/access_key.py:17 +#: acls/models/base.py:83 authentication/models/access_key.py:17 #: authentication/models/connection_token.py:47 #: authentication/templates/authentication/_access_key_modal.html:32 #: perms/models/asset_permission.py:76 terminal/models/session/sharing.py:27 @@ -719,7 +685,7 @@ msgstr "审批人" msgid "Active" msgstr "激活中" -#: acls/models/base.py:94 acls/models/login_acl.py:13 +#: acls/models/base.py:98 acls/models/login_acl.py:13 #: acls/serializers/base.py:55 acls/serializers/login_acl.py:21 #: assets/models/cmd_filter.py:24 assets/models/label.py:16 audits/models.py:30 #: audits/models.py:49 audits/models.py:98 @@ -813,39 +779,29 @@ msgstr "" "格式为逗号分隔的字符串, * 表示匹配所有。例如: 192.168.10.1, 192.168.1.0/24, " "10.1.1.1-10.1.1.20, 2001:db8:2de::e13, 2001:db8:1a:1110::/64 (支持网域)" -#: acls/serializers/base.py:40 assets/serializers/asset/host.py:40 +#: acls/serializers/base.py:40 assets/serializers/asset/host.py:37 msgid "IP/Host" msgstr "IP/主机" #: acls/serializers/base.py:60 -#, fuzzy -#| msgid "System user name" msgid "User (username)" -msgstr "系统用户名称" +msgstr "用户(用户名)" #: acls/serializers/base.py:64 -#, fuzzy -#| msgid "Asset hostname" msgid "Asset (name)" -msgstr "资产主机名" +msgstr "资产(名称)" #: acls/serializers/base.py:68 -#, fuzzy -#| msgid "Address" msgid "Asset (address)" -msgstr "地址" +msgstr "资产(地址)" #: acls/serializers/base.py:72 -#, fuzzy -#| msgid "Account name" msgid "Account (username)" -msgstr "账号名称" +msgstr "账号(用户名)" #: acls/serializers/base.py:78 acls/serializers/login_acl.py:27 -#, fuzzy -#| msgid "Reviewers" msgid "Reviewers amount" -msgstr "审批人" +msgstr "审批人数量" #: acls/serializers/base.py:109 tickets/serializers/ticket/ticket.py:76 msgid "The organization `{}` does not exist" @@ -856,10 +812,8 @@ msgid "None of the reviewers belong to Organization `{}`" msgstr "所有复核人都不属于组织 `{}`" #: acls/serializers/command_acl.py:31 -#, fuzzy -#| msgid "Command amount" msgid "Command group amount" -msgstr "命令数量" +msgstr "命令组数量" #: acls/serializers/rules/rules.py:20 #: xpack/plugins/cloud/serializers/task.py:22 @@ -892,9 +846,9 @@ msgid "Applications" msgstr "应用管理" #: applications/models.py:11 assets/models/label.py:21 -#: assets/models/platform.py:75 assets/serializers/asset/common.py:107 -#: assets/serializers/cagegory.py:8 assets/serializers/platform.py:87 -#: assets/serializers/platform.py:126 perms/serializers/user_permission.py:25 +#: assets/models/platform.py:75 assets/serializers/asset/common.py:108 +#: assets/serializers/cagegory.py:8 assets/serializers/platform.py:99 +#: assets/serializers/platform.py:138 perms/serializers/user_permission.py:25 #: settings/models.py:35 tickets/models/ticket/apply_application.py:13 msgid "Category" msgstr "类别" @@ -988,8 +942,6 @@ msgid "Ping" msgstr "" #: assets/const/automation.py:13 -#, fuzzy -#| msgid "Test gateway" msgid "Ping gateway" msgstr "测试网关" @@ -1008,7 +960,7 @@ msgid "Device" msgstr "网络设备" #: assets/const/category.py:13 assets/models/asset/database.py:9 -#: assets/models/asset/database.py:24 assets/serializers/asset/common.py:95 +#: assets/models/asset/database.py:24 assets/serializers/asset/common.py:96 msgid "Database" msgstr "数据库" @@ -1057,7 +1009,7 @@ msgstr "SSH公钥" #: assets/models/_user.py:27 assets/models/cmd_filter.py:40 #: assets/models/cmd_filter.py:88 assets/models/group.py:23 #: assets/models/platform.py:79 common/db/models.py:37 ops/models/adhoc.py:28 -#: ops/models/job.py:41 ops/models/playbook.py:18 rbac/models/role.py:37 +#: ops/models/job.py:40 ops/models/playbook.py:18 rbac/models/role.py:37 #: settings/models.py:38 terminal/models/applet/applet.py:33 #: terminal/models/applet/applet.py:146 terminal/models/applet/host.py:110 #: terminal/models/component/endpoint.py:24 @@ -1070,7 +1022,7 @@ msgstr "备注" #: assets/models/_user.py:28 assets/models/automations/base.py:105 #: assets/models/cmd_filter.py:41 assets/models/group.py:22 -#: common/db/models.py:35 ops/models/base.py:54 ops/models/job.py:106 +#: common/db/models.py:35 ops/models/base.py:54 ops/models/job.py:105 #: users/models/user.py:932 msgid "Date created" msgstr "创建日期" @@ -1188,10 +1140,8 @@ msgid "Can push account to asset" msgstr "可以推送账号到资产" #: assets/models/asset/common.py:288 -#, fuzzy -#| msgid "Verify account" msgid "Can verify account" -msgstr "验证账号" +msgstr "可以验证账号" #: assets/models/asset/common.py:289 msgid "Can match asset" @@ -1205,7 +1155,7 @@ msgstr "添加资产到节点" msgid "Move asset to node" msgstr "移动资产到节点" -#: assets/models/asset/database.py:10 assets/serializers/asset/common.py:96 +#: assets/models/asset/database.py:10 assets/serializers/asset/common.py:97 #: settings/serializers/email.py:37 msgid "Use SSL" msgstr "使用 SSL" @@ -1222,7 +1172,7 @@ msgstr "客户端证书" msgid "Client key" msgstr "客户端密钥" -#: assets/models/asset/database.py:14 assets/serializers/asset/common.py:97 +#: assets/models/asset/database.py:14 assets/serializers/asset/common.py:98 msgid "Allow invalid cert" msgstr "忽略证书校验" @@ -1237,7 +1187,7 @@ msgid "Basic" msgstr "基本" #: assets/models/asset/web.py:11 assets/models/asset/web.py:17 -#: assets/serializers/asset/common.py:103 +#: assets/serializers/asset/common.py:104 msgid "Script" msgstr "" @@ -1245,23 +1195,23 @@ msgstr "" msgid "Autofill" msgstr "自动代填" -#: assets/models/asset/web.py:14 assets/serializers/asset/common.py:100 +#: assets/models/asset/web.py:14 assets/serializers/asset/common.py:101 #: assets/serializers/platform.py:30 msgid "Username selector" msgstr "用户名选择器" -#: assets/models/asset/web.py:15 assets/serializers/asset/common.py:101 +#: assets/models/asset/web.py:15 assets/serializers/asset/common.py:102 #: assets/serializers/platform.py:33 msgid "Password selector" msgstr "密码选择器" -#: assets/models/asset/web.py:16 assets/serializers/asset/common.py:102 +#: assets/models/asset/web.py:16 assets/serializers/asset/common.py:103 #: assets/serializers/platform.py:36 msgid "Submit selector" msgstr "确认按钮选择器" #: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38 -#: assets/serializers/asset/common.py:232 perms/models/asset_permission.py:70 +#: assets/serializers/asset/common.py:261 perms/models/asset_permission.py:70 #: perms/serializers/permission.py:32 rbac/tree.py:36 msgid "Accounts" msgstr "账号管理" @@ -1271,13 +1221,11 @@ msgid "Automation task" msgstr "自动化任务" #: assets/models/automations/base.py:95 -#, fuzzy -#| msgid "Automation task" msgid "Asset automation task" -msgstr "自动化任务" +msgstr "资产自动化任务" #: assets/models/automations/base.py:104 audits/models.py:134 -#: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:99 +#: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:98 #: terminal/models/applet/applet.py:145 terminal/models/applet/host.py:107 #: terminal/models/component/status.py:27 terminal/serializers/applet.py:17 #: terminal/serializers/applet_host.py:93 tickets/models/ticket/general.py:283 @@ -1334,8 +1282,6 @@ msgid "Command filter rule" msgstr "命令过滤规则" #: assets/models/favorite_asset.py:17 -#, fuzzy -#| msgid "Favorite Asset" msgid "Favorite asset" msgstr "收藏的资产" @@ -1368,7 +1314,7 @@ msgstr "系统" msgid "Value" msgstr "值" -#: assets/models/label.py:40 assets/serializers/asset/common.py:109 +#: assets/models/label.py:40 assets/serializers/asset/common.py:110 #: assets/serializers/cagegory.py:6 assets/serializers/cagegory.py:13 #: authentication/serializers/connect_token_secret.py:114 #: common/serializers/common.py:79 settings/serializers/sms.py:7 @@ -1422,47 +1368,45 @@ msgstr "启用" msgid "Ansible config" msgstr "Ansible 配置" -#: assets/models/platform.py:43 +#: assets/models/platform.py:43 assets/serializers/platform.py:55 msgid "Ping enabled" msgstr "启用资产探活" -#: assets/models/platform.py:44 +#: assets/models/platform.py:44 assets/serializers/platform.py:57 msgid "Ping method" msgstr "资产探活方式" #: assets/models/platform.py:45 assets/models/platform.py:58 +#: assets/serializers/platform.py:59 msgid "Gather facts enabled" msgstr "收集资产信息" #: assets/models/platform.py:46 assets/models/platform.py:60 +#: assets/serializers/platform.py:61 msgid "Gather facts method" msgstr "收集信息方式" -#: assets/models/platform.py:47 -#, fuzzy -#| msgid "Change secret record" +#: assets/models/platform.py:47 assets/serializers/platform.py:67 msgid "Change secret enabled" -msgstr "改密记录" +msgstr "启用改密" -#: assets/models/platform.py:49 -#, fuzzy -#| msgid "Change secret record" +#: assets/models/platform.py:49 assets/serializers/platform.py:69 msgid "Change secret method" -msgstr "改密记录" +msgstr "改密方式" -#: assets/models/platform.py:51 +#: assets/models/platform.py:51 assets/serializers/platform.py:71 msgid "Push account enabled" msgstr "启用账号推送" -#: assets/models/platform.py:53 +#: assets/models/platform.py:53 assets/serializers/platform.py:73 msgid "Push account method" msgstr "账号推送方式" -#: assets/models/platform.py:55 +#: assets/models/platform.py:55 assets/serializers/platform.py:63 msgid "Verify account enabled" msgstr "开启账号验证" -#: assets/models/platform.py:57 +#: assets/models/platform.py:57 assets/serializers/platform.py:65 msgid "Verify account method" msgstr "账号验证方式" @@ -1474,23 +1418,23 @@ msgstr "元数据" msgid "Internal" msgstr "内置" -#: assets/models/platform.py:82 assets/serializers/platform.py:84 +#: assets/models/platform.py:82 assets/serializers/platform.py:96 msgid "Charset" msgstr "编码" -#: assets/models/platform.py:84 +#: assets/models/platform.py:84 assets/serializers/platform.py:123 msgid "Domain enabled" msgstr "启用网域" -#: assets/models/platform.py:86 +#: assets/models/platform.py:86 assets/serializers/platform.py:122 msgid "Su enabled" msgstr "启用账号切换" -#: assets/models/platform.py:87 +#: assets/models/platform.py:87 assets/serializers/platform.py:106 msgid "Su method" msgstr "账号切换方式" -#: assets/models/platform.py:89 assets/serializers/platform.py:91 +#: assets/models/platform.py:89 assets/serializers/platform.py:103 msgid "Automation" msgstr "自动化" @@ -1499,13 +1443,11 @@ msgstr "自动化" msgid "%(value)s is not an even number" msgstr "%(value)s is not an even number" -#: assets/serializers/asset/common.py:99 -#, fuzzy -#| msgid "Autofill" +#: assets/serializers/asset/common.py:100 msgid "Auto fill" msgstr "自动代填" -#: assets/serializers/asset/common.py:110 assets/serializers/platform.py:89 +#: assets/serializers/asset/common.py:111 assets/serializers/platform.py:101 #: authentication/serializers/connect_token_secret.py:28 #: authentication/serializers/connect_token_secret.py:66 #: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:107 @@ -1513,27 +1455,27 @@ msgstr "自动代填" msgid "Protocols" msgstr "协议组" -#: assets/serializers/asset/common.py:129 +#: assets/serializers/asset/common.py:130 msgid "Address" msgstr "地址" -#: assets/serializers/asset/common.py:130 +#: assets/serializers/asset/common.py:131 msgid "Node path" msgstr "节点路径" -#: assets/serializers/asset/common.py:190 +#: assets/serializers/asset/common.py:204 msgid "Platform not exist" msgstr "平台不存在" -#: assets/serializers/asset/common.py:200 +#: assets/serializers/asset/common.py:234 msgid "port out of range (1-65535)" msgstr "端口超出范围 (1-65535)" -#: assets/serializers/asset/common.py:212 +#: assets/serializers/asset/common.py:241 msgid "Protocol is required: {}" msgstr "协议是必填的: {}" -#: assets/serializers/asset/common.py:234 +#: assets/serializers/asset/common.py:263 msgid "Auto info" msgstr "自动化信息" @@ -1579,31 +1521,19 @@ msgstr "内存" msgid "Disk total" msgstr "硬盘大小" -#: assets/serializers/asset/host.py:22 -msgid "Disk info" -msgstr "硬盘信息" - -#: assets/serializers/asset/host.py:24 +#: assets/serializers/asset/host.py:23 #: authentication/serializers/connect_token_secret.py:105 msgid "OS" msgstr "操作系统" -#: assets/serializers/asset/host.py:25 +#: assets/serializers/asset/host.py:24 msgid "OS version" msgstr "系统版本" -#: assets/serializers/asset/host.py:26 +#: assets/serializers/asset/host.py:25 msgid "OS arch" msgstr "系统架构" -#: assets/serializers/asset/host.py:27 -msgid "Hostname raw" -msgstr "主机名原始" - -#: assets/serializers/asset/host.py:28 -msgid "Asset number" -msgstr "资产编号" - #: assets/serializers/cagegory.py:9 msgid "Constraints" msgstr "" @@ -1640,15 +1570,25 @@ msgstr "SFTP 已启用" msgid "SFTP home" msgstr "SFTP根路径" -#: assets/serializers/platform.py:71 +#: assets/serializers/platform.py:75 +msgid "Gather accounts enabled" +msgstr "启用账号收集" + +#: assets/serializers/platform.py:77 +msgid "Gather accounts method" +msgstr "收集账号方式" + +#: assets/serializers/platform.py:83 msgid "Primary" msgstr "主要的" +#: assets/serializers/platform.py:124 +msgid "Default Domain" +msgstr "默认网域" + #: assets/tasks/automation.py:11 -#, fuzzy -#| msgid "Execute automation" msgid "Asset execute automation" -msgstr "执行自动化任务" +msgstr "资产执行自动化" #: assets/tasks/gather_facts.py:23 msgid "Update some assets hardware info. " @@ -1688,8 +1628,6 @@ msgid "Test assets connectivity " msgstr "测试资产可连接性" #: assets/tasks/ping.py:50 -#, fuzzy -#| msgid "Manually test the connectivity of a asset" msgid "Manually test the connectivity of a asset" msgstr "手动测试资产连接性" @@ -1955,16 +1893,16 @@ msgid "Account not found" msgstr "账号未找到" #: authentication/api/connection_token.py:267 -msgid "Permission Expired" -msgstr "授权过期" +msgid "Permission expired" +msgstr "授权已过期" #: authentication/api/connection_token.py:279 msgid "ACL action is reject" -msgstr "" +msgstr "ACL 动作是拒绝" #: authentication/api/connection_token.py:283 msgid "ACL action is review" -msgstr "" +msgstr "ACL 动作是复核" #: authentication/api/mfa.py:59 msgid "Current user not support mfa type: {}" @@ -2376,10 +2314,8 @@ msgid "Can view connection token secret" msgstr "可以查看连接令牌密文" #: authentication/models/connection_token.py:100 -#, fuzzy -#| msgid "Connection token" msgid "Connection token inactive" -msgstr "连接令牌" +msgstr "连接令牌不活跃" #: authentication/models/connection_token.py:103 msgid "Connection token expired at: {}" @@ -2448,10 +2384,8 @@ msgid "Expired time" msgstr "过期时间" #: authentication/serializers/connection_token.py:18 -#, fuzzy -#| msgid "Ticket flow" msgid "Ticket info" -msgstr "工单流程" +msgstr "工单信息" #: authentication/serializers/password_mfa.py:16 #: authentication/serializers/password_mfa.py:24 @@ -2474,10 +2408,8 @@ msgid "Is valid" msgstr "账号是否有效" #: authentication/tasks.py:12 -#, fuzzy -#| msgid "Can share session" msgid "Clean expired session" -msgstr "可以分享会话" +msgstr "可以过期会话" #: authentication/templates/authentication/_access_key_modal.html:6 msgid "API key list" @@ -2911,10 +2843,8 @@ msgid "Updated by" msgstr "最后更新者" #: common/db/validators.py:9 -#, fuzzy -#| msgid "Invalid data type, should be list" msgid "Invalid port range, should be like and within {}-{}" -msgstr "错误的数据类型,应该是列表" +msgstr "无效的端口范围,应该在 {}-{} 之内" #: common/drf/exc_handlers.py:26 msgid "Object" @@ -3157,7 +3087,7 @@ msgstr "系统信息" #: notifications/notifications.py:46 msgid "Publish the station message" -msgstr "" +msgstr "发布站内消息" #: ops/ansible/inventory.py:76 msgid "No account available" @@ -3205,19 +3135,17 @@ msgstr "各自随机" #: ops/const.py:33 msgid "Blank" -msgstr "" +msgstr "空白" #: ops/const.py:34 -#, fuzzy -#| msgid "CAS" msgid "VCS" -msgstr "CAS" +msgstr "VCS" #: ops/const.py:38 msgid "Adhoc" msgstr "命令" -#: ops/const.py:39 ops/models/job.py:32 +#: ops/const.py:39 ops/models/job.py:31 msgid "Playbook" msgstr "Playbook" @@ -3242,10 +3170,8 @@ msgid "Python" msgstr "" #: ops/const.py:57 -#, fuzzy -#| msgid "Test timeout" msgid "Timeout" -msgstr "测试超时时间" +msgstr "超时" #: ops/exception.py:6 msgid "no valid program entry found." @@ -3280,17 +3206,17 @@ msgstr "需要周期或定期设置" msgid "Pattern" msgstr "模式" -#: ops/models/adhoc.py:25 ops/models/job.py:29 +#: ops/models/adhoc.py:25 ops/models/job.py:28 msgid "Module" msgstr "模块" -#: ops/models/adhoc.py:26 ops/models/celery.py:58 ops/models/job.py:27 +#: ops/models/adhoc.py:26 ops/models/celery.py:58 ops/models/job.py:26 #: terminal/models/component/task.py:16 msgid "Args" msgstr "参数" #: ops/models/adhoc.py:27 ops/models/base.py:16 ops/models/base.py:53 -#: ops/models/job.py:34 ops/models/job.py:105 ops/models/playbook.py:17 +#: ops/models/job.py:33 ops/models/job.py:104 ops/models/playbook.py:17 #: terminal/models/session/sharing.py:23 msgid "Creator" msgstr "创建者" @@ -3311,12 +3237,12 @@ msgstr "最后执行" msgid "Date last run" msgstr "最后运行日期" -#: ops/models/base.py:51 ops/models/job.py:103 +#: ops/models/base.py:51 ops/models/job.py:102 #: xpack/plugins/cloud/models.py:170 msgid "Result" msgstr "结果" -#: ops/models/base.py:52 ops/models/job.py:104 +#: ops/models/base.py:52 ops/models/job.py:103 msgid "Summary" msgstr "汇总" @@ -3356,37 +3282,37 @@ msgstr "发布日期" msgid "Celery Task Execution" msgstr "Celery 任务执行" -#: ops/models/job.py:30 +#: ops/models/job.py:29 msgid "Chdir" msgstr "运行目录" -#: ops/models/job.py:31 +#: ops/models/job.py:30 msgid "Timeout (Seconds)" msgstr "超时时间(秒)" -#: ops/models/job.py:36 +#: ops/models/job.py:35 msgid "Runas" msgstr "运行用户" -#: ops/models/job.py:38 +#: ops/models/job.py:37 msgid "Runas policy" msgstr "用户策略" -#: ops/models/job.py:39 +#: ops/models/job.py:38 msgid "Use Parameter Define" -msgstr "" +msgstr "使用参数定义" -#: ops/models/job.py:40 +#: ops/models/job.py:39 msgid "Parameters define" -msgstr "" +msgstr "参数定义" -#: ops/models/job.py:92 +#: ops/models/job.py:91 msgid "Job" msgstr "作业" -#: ops/models/job.py:102 +#: ops/models/job.py:101 msgid "Parameters" -msgstr "" +msgstr "参数" #: ops/models/job.py:311 msgid "Job Execution" @@ -3397,10 +3323,8 @@ msgid "Job audit log" msgstr "作业审计日志" #: ops/models/playbook.py:20 -#, fuzzy -#| msgid "Create" msgid "CreateMethod" -msgstr "创建" +msgstr "创建方式" #: ops/models/playbook.py:21 msgid "VCS URL" @@ -3489,39 +3413,39 @@ msgstr "任务列表" #: ops/variables.py:24 msgid "The current user`s username of JumpServer" -msgstr "" +msgstr "JumpServer 当前用户的用户名" #: ops/variables.py:25 msgid "The id of the asset in the JumpServer" -msgstr "" +msgstr "JumpServer 中资产的 id" #: ops/variables.py:26 msgid "The type of the asset in the JumpServer" -msgstr "" +msgstr "JumpServer 中资产的类型" #: ops/variables.py:27 msgid "The category of the asset in the JumpServer" -msgstr "" +msgstr "JumpServer 中资产的类别" #: ops/variables.py:28 msgid "The name of the asset in the JumpServer" -msgstr "" +msgstr "JumpServer 中资产的名称" #: ops/variables.py:29 msgid "Address used to connect this asset in JumpServer" -msgstr "" +msgstr "在 JumpServer 中用于连接此资产的地址" #: ops/variables.py:30 msgid "Port used to connect this asset in JumpServer" -msgstr "" +msgstr "在 JumpServer 中用于连接此资产的端口" #: ops/variables.py:31 msgid "ID of the job" -msgstr "" +msgstr "Job ID" #: ops/variables.py:32 msgid "Name of the job" -msgstr "" +msgstr "Job 名称" #: orgs/api.py:63 msgid "The current organization ({}) cannot be deleted" @@ -3665,16 +3589,12 @@ msgid "Is expired" msgstr "已过期" #: perms/tasks.py:28 -#, fuzzy -#| msgid "Asset permissions is about to expire" msgid "Check asset permission expired" -msgstr "资产授权规则将要过期" +msgstr "校验资产授权规则已过期" #: perms/tasks.py:40 -#, fuzzy -#| msgid "asset permissions of organization {}" msgid "Send asset permission expired notification" -msgstr "组织 ({}) 的资产授权" +msgstr "发送资产权限过期通知" #: perms/templates/perms/_msg_item_permissions_expire.html:7 #: perms/templates/perms/_msg_permed_items_expire.html:7 @@ -4778,10 +4698,8 @@ msgid "" msgstr "单位: 秒, 目前仅在查看账号密码校验 MFA 时生效" #: settings/serializers/security.py:116 -#, fuzzy -#| msgid "Verify code" msgid "Verify code TTL" -msgstr "验证码" +msgstr "验证码有效时间" #: settings/serializers/security.py:121 msgid "Enable Login dynamic code" @@ -5247,14 +5165,12 @@ msgid "Offline video player" msgstr "离线录像播放器" #: terminal/api/applet/applet.py:48 terminal/api/applet/applet.py:51 -#, fuzzy -#| msgid "Invalid ip" msgid "Invalid zip file" -msgstr "无效IP" +msgstr "无效的 zip 文件" #: terminal/api/component/endpoint.py:31 msgid "Not found protocol query params" -msgstr "" +msgstr "未发现 protocol 查询参数" #: terminal/api/component/storage.py:28 msgid "Deleting the default storage is not allowed" @@ -5360,7 +5276,7 @@ msgstr "离线" #: terminal/const.py:61 msgid "Mismatch" -msgstr "" +msgstr "未匹配" #: terminal/exceptions.py:8 msgid "Bulk create not support" @@ -5384,7 +5300,7 @@ msgstr "主机" #: terminal/models/applet/applet.py:81 msgid "Applet pkg not valid, Missing file {}" -msgstr "" +msgstr "Applet pkg 无效,缺少文件 {}" #: terminal/models/applet/applet.py:144 terminal/models/applet/host.py:33 #: terminal/models/applet/host.py:105 @@ -5638,10 +5554,8 @@ msgid "Per Device" msgstr "每设备" #: terminal/serializers/applet_host.py:32 -#, fuzzy -#| msgid "LDAP server" msgid "API Server" -msgstr "LDAP 地址" +msgstr "API 服务" #: terminal/serializers/applet_host.py:33 msgid "RDS Licensing" @@ -5656,16 +5570,16 @@ msgid "RDS Licensing Mode" msgstr "RDS 授权模式" #: terminal/serializers/applet_host.py:37 -msgid "RDS fSingleSessionPerUser" -msgstr "" +msgid "RDS Single Session Per User" +msgstr "RDS 一个用户一个会话" #: terminal/serializers/applet_host.py:38 msgid "RDS Max Disconnection Time" -msgstr "" +msgstr "RDS 最大断开时间" #: terminal/serializers/applet_host.py:39 msgid "RDS Remote App Logoff Time Limit" -msgstr "" +msgstr "RDS 远程应用注销时间限制" #: terminal/serializers/applet_host.py:45 terminal/serializers/terminal.py:41 msgid "Load status" @@ -5706,7 +5620,7 @@ msgstr "如果不同端点下的资产 IP 有冲突,使用资产标签实现" #: terminal/serializers/session.py:18 msgid "Tunnel" -msgstr "" +msgstr "隧道" #: terminal/serializers/session.py:28 terminal/serializers/session.py:50 msgid "Can replay" @@ -5815,36 +5729,26 @@ msgid "Not found" msgstr "没有发现" #: terminal/tasks.py:31 -#, fuzzy -#| msgid "Periodic clear celery tasks" msgid "Periodic delete terminal status" -msgstr "周期清理不可用任务" +msgstr "周期清理终端状态" #: terminal/tasks.py:40 -#, fuzzy -#| msgid "Can share session" msgid "Clean orphan session" -msgstr "可以分享会话" +msgstr "清除孤儿会话" #: terminal/tasks.py:59 -#, fuzzy -#| msgid "Periodic clear celery tasks" msgid "Periodic clean expired session" -msgstr "周期清理不可用任务" +msgstr "周期清理过期会话" #: terminal/tasks.py:85 -#, fuzzy -#| msgid "Can upload session replay" msgid "Upload session replay to external storage" -msgstr "可以上传会话录像" +msgstr "上传会话录像到外部存储" #: terminal/tasks.py:112 msgid "Run applet host deployment" -msgstr "" +msgstr "运行应用机部署" #: terminal/tasks.py:119 -#, fuzzy -#| msgid "Install app" msgid "Install applet" msgstr "安装应用" @@ -6484,38 +6388,28 @@ msgid "name not unique" msgstr "名称重复" #: users/tasks.py:24 -#, fuzzy -#| msgid "Password expired" msgid "Check password expired" -msgstr "密码已过期" +msgstr "校验密码已过期" #: users/tasks.py:38 -#, fuzzy -#| msgid "Password expired" msgid "Periodic check password expired" -msgstr "密码已过期" +msgstr "周期校验密码过期" #: users/tasks.py:52 -#, fuzzy -#| msgid "Is expired" msgid "Check user expired" -msgstr "已过期" +msgstr "校验用户已过期" #: users/tasks.py:69 -#, fuzzy -#| msgid "Periodic check service performance" msgid "Periodic check user expired" -msgstr "周期检测服务性能" +msgstr "周期检测用户过期" #: users/tasks.py:83 msgid "Import ldap user" -msgstr "" +msgstr "导入 LDAP 用户" #: users/tasks.py:104 -#, fuzzy -#| msgid "Periodic display" msgid "Periodic import ldap user" -msgstr "定时执行" +msgstr "周期导入 LDAP 用户" #: users/templates/users/_msg_account_expire_reminder.html:7 msgid "Your account will expire in" @@ -7331,663 +7225,11 @@ msgstr "旗舰版" msgid "Community edition" msgstr "社区版" -#~ msgid "Account template not found" -#~ msgstr "账号模版未找到" +#~ msgid "Disk info" +#~ msgstr "硬盘信息" -#, fuzzy -#~| msgid "Enabled" -#~ msgid "Enabled info" -#~ msgstr "启用" +#~ msgid "Hostname raw" +#~ msgstr "主机名原始" -#~ msgid "" -#~ "Jmservisor is the program used to pull up remote applications in Windows " -#~ "Remote Application publisher" -#~ msgstr "Jmservisor 是在 windows 远程应用发布服务器中用来拉起远程应用的程序" - -#~ msgid "Protocols enabled" -#~ msgstr "启用协议" - -#, fuzzy -#~| msgid "Is active" -#~ msgid "Is Activity" -#~ msgstr "激活" - -#~ msgid "Dynamic username" -#~ msgstr "同名账号" - -#~ msgid "Username already exists" -#~ msgstr "用户名 `{}` 已存在" - -#~ msgid "Dynamic username already exists" -#~ msgstr "动态用户名已存在" - -#~ msgid "Commands" -#~ msgstr "命令" - -#~ msgid "Change password enabled" -#~ msgstr "开启账号改密" - -#~ msgid "Change password method" -#~ msgstr "更改密码方式" - -#~ msgid "Applet host" -#~ msgstr "远程应用发布机" - -#~ msgid "" -#~ "The range of ports that Magnus listens on is modified in the " -#~ "configuration file" -#~ msgstr "请在配置文件中修改 Magnus 监听的端口范围" - -#~ msgid "Magnus Listen port range" -#~ msgstr "Magnus 监听的端口范围" - -#~ msgid "Published" -#~ msgstr "已发布" - -#~ msgid "Unpublished" -#~ msgstr "未发布" - -#~ msgid "Not match" -#~ msgstr "没有匹配的" - -#~ msgid "Magnus listen db port" -#~ msgstr "Magnus 监听的数据库端口" - -#~ msgid "Update task content: {}" -#~ msgstr "更新任务内容: {}" - -#~ msgid "Execute batch command" -#~ msgstr "执行批量命令" - -#~ msgid "Create account" -#~ msgstr "创建账号" - -#~ msgid "Present" -#~ msgstr "存在" - -#~ msgid "Date last login" -#~ msgstr "最后登录日期" - -#~ msgid "IP last login" -#~ msgstr "最后登录IP" - -#~ msgid "GatherUser" -#~ msgstr "收集用户" - -#~ msgid "Welcome back, please enter username and password to login" -#~ msgstr "欢迎回来,请输入用户名和密码登录" - -#~ msgid "Discovery account automation" -#~ msgstr "账号发现" - -#~ msgid "Category display" -#~ msgstr "类别名称" - -#~ msgid "Built-in" -#~ msgstr "内置" - -#~ msgid "Scope display" -#~ msgstr "范围名称" - -#~ msgid "App change auth" -#~ msgstr "应用改密" - -#~ msgid "My apps" -#~ msgstr "我的应用" - -#~ msgid "Risk level display" -#~ msgstr "风险等级名称" - -#~ msgid "From cmd filter" -#~ msgstr "来自命令过滤规则" - -#~ msgid "From cmd filter rule" -#~ msgstr "来自命令过滤规则" - -#~ msgid "System roles display" -#~ msgstr "系统角色显示" - -#~ msgid "Org roles display" -#~ msgstr "组织角色显示" - -#~ msgid "MFA level display" -#~ msgstr "MFA 等级名称" - -#~ msgid "Groups name" -#~ msgstr "用户组名" - -#~ msgid "Source name" -#~ msgstr "用户来源名" - -#~ msgid "Organization role name" -#~ msgstr "组织角色名称" - -#~ msgid "Super role name" -#~ msgstr "超级角色名称" - -#~ msgid "Total role name" -#~ msgstr "汇总角色名称" - -#~ msgid "Is wecom bound" -#~ msgstr "是否绑定了企业微信" - -#~ msgid "Is dingtalk bound" -#~ msgstr "是否绑定了钉钉" - -#~ msgid "Is feishu bound" -#~ msgstr "是否绑定了飞书" - -#~ msgid "System role name" -#~ msgstr "系统角色名称" - -#~ msgid "Change auth plan" -#~ msgstr "改密计划" - -#~ msgid "Application change auth plan" -#~ msgstr "应用改密计划" - -#~ msgid "Application change auth plan execution" -#~ msgstr "应用改密计划执行" - -#~ msgid "App" -#~ msgstr "应用" - -#~ msgid "Application change auth plan task" -#~ msgstr "应用改密计划任务" - -#~ msgid "Password cannot be set to blank, exit. " -#~ msgstr "密码不能设置为空, 退出. " - -#~ msgid "Asset change auth plan" -#~ msgstr "资产改密计划" - -#~ msgid "Asset change auth plan execution" -#~ msgstr "资产改密计划执行" - -#~ msgid "Change auth plan execution" -#~ msgstr "改密计划执行" - -#~ msgid "Asset change auth plan task" -#~ msgstr "资产改密计划任务" - -#~ msgid "This asset does not have a privileged user set: " -#~ msgstr "该资产没有设置特权用户: " - -#~ msgid "" -#~ "The password and key of the current asset privileged user cannot be " -#~ "changed: " -#~ msgstr "不能更改当前资产特权用户的密码及密钥: " - -#~ msgid "Public key cannot be set to null, exit. " -#~ msgstr "公钥不能设置为空, 退出. " - -#~ msgid "Change auth plan snapshot" -#~ msgstr "改密计划快照" - -#~ msgid "Preflight check" -#~ msgstr "改密前的校验" - -#~ msgid "Change auth" -#~ msgstr "执行改密" - -#~ msgid "Verify auth" -#~ msgstr "验证密码/密钥" - -#~ msgid "Keep auth" -#~ msgstr "保存密码/密钥" - -#~ msgid "Step" -#~ msgstr "步骤" - -#~ msgid "Change Password" -#~ msgstr "更改密码" - -#~ msgid "Change SSH Key" -#~ msgstr "修改 SSH Key" - -#~ msgid "Run times" -#~ msgstr "执行次数" - -#~ msgid "After many attempts to change the secret, it still failed" -#~ msgstr "多次尝试改密后, 依然失败" - -#~ msgid "Invalid/incorrect password" -#~ msgstr "无效/错误 密码" - -#~ msgid "Failed to connect to the host" -#~ msgstr "连接主机失败" - -#~ msgid "Data could not be sent to remote" -#~ msgstr "无法将数据发送到远程" - -#~ msgid "Gathered user" -#~ msgstr "收集用户" - -#~ msgid "Gather user task" -#~ msgstr "收集用户任务" - -#~ msgid "gather user task execution" -#~ msgstr "收集用户执行" - -#~ msgid "Assets is empty, please change nodes" -#~ msgstr "资产为空,请更改节点" - -#~ msgid "Executed times" -#~ msgstr "执行次数" - -#~ msgid "System User" -#~ msgstr "系统用户" - -#~ msgid "" -#~ "Format for comma-delimited string, with * indicating a match all. " -#~ "Protocol options: {}" -#~ msgstr "格式为逗号分隔的字符串, * 表示匹配所有. 可选的协议有: {}" - -#~ msgid "Unsupported protocols: {}" -#~ msgstr "不支持的协议: {}" - -#~ msgid "Remote app" -#~ msgstr "远程应用" - -#~ msgid "Custom" -#~ msgstr "自定义" - -#~ msgid "Can view application account secret" -#~ msgstr "可以查看应用账号密码" - -#~ msgid "Can change application account secret" -#~ msgstr "可以查看应用账号密码" - -#~ msgid "Application user" -#~ msgstr "应用用户" - -#~ msgid "Type display" -#~ msgstr "类型名称" - -#~ msgid "Application display" -#~ msgstr "应用名称" - -#~ msgid "Cluster" -#~ msgstr "集群" - -#~ msgid "CA certificate" -#~ msgstr "CA 证书" - -#~ msgid "Client certificate file" -#~ msgstr "客户端证书" - -#~ msgid "Certificate key file" -#~ msgstr "证书秘钥" - -#~ msgid "Application path" -#~ msgstr "应用路径" - -#~ msgid "Target URL" -#~ msgstr "目标URL" - -#~ msgid "Chrome username" -#~ msgstr "Chrome 用户名" - -#~ msgid "Chrome password" -#~ msgstr "Chrome 密码" - -#~ msgid "Operating parameter" -#~ msgstr "运行参数" - -#~ msgid "Target url" -#~ msgstr "目标URL" - -#~ msgid "Mysql workbench username" -#~ msgstr "Mysql 工作台 用户名" - -#~ msgid "Mysql workbench password" -#~ msgstr "Mysql 工作台 密码" - -#~ msgid "Vmware username" -#~ msgstr "Vmware 用户名" - -#~ msgid "Vmware password" -#~ msgstr "Vmware 密码" - -#~ msgid "Base" -#~ msgstr "基础" - -#~ msgid "Can test asset account connectivity" -#~ msgstr "可以测试资产账号连接性" - -#~ msgid "Bandwidth" -#~ msgstr "带宽" - -#~ msgid "Contact" -#~ msgstr "联系人" - -#~ msgid "Intranet" -#~ msgstr "内网" - -#~ msgid "Extranet" -#~ msgstr "外网" - -#~ msgid "Operator" -#~ msgstr "运营商" - -#~ msgid "Default Cluster" -#~ msgstr "默认Cluster" - -#~ msgid "User groups" -#~ msgstr "用户组" - -#~ msgid "System user display" -#~ msgstr "系统用户名称" - -#~ msgid "Protocol format should {}/{}" -#~ msgstr "协议格式 {}/{}" - -#~ msgid "Nodes name" -#~ msgstr "节点名称" - -#~ msgid "Labels name" -#~ msgstr "标签名称" - -#~ msgid "Hardware info" -#~ msgstr "硬件信息" - -#~ msgid "Admin user display" -#~ msgstr "特权用户名称" - -#~ msgid "CPU info" -#~ msgstr "CPU信息" - -#~ msgid "Action display" -#~ msgstr "动作名称" - -#~ msgid "Applications amount" -#~ msgstr "应用数量" - -#~ msgid "Gateways count" -#~ msgstr "网关数量" - -#~ msgid "SSH key fingerprint" -#~ msgstr "密钥指纹" - -#~ msgid "Apps amount" -#~ msgstr "应用数量" - -#~ msgid "Login mode display" -#~ msgstr "认证方式名称" - -#~ msgid "Ad domain" -#~ msgstr "Ad 网域" - -#~ msgid "Is asset protocol" -#~ msgstr "资产协议" - -#~ msgid "Only ssh and automatic login system users are supported" -#~ msgstr "仅支持ssh协议和自动登录的系统用户" - -#~ msgid "Username same with user with protocol {} only allow 1" -#~ msgstr "用户名和用户相同的一种协议只允许存在一个" - -#~ msgid "* Automatic login mode must fill in the username." -#~ msgstr "自动登录模式,必须填写用户名" - -#~ msgid "Path should starts with /" -#~ msgstr "路径应该以 / 开头" - -#~ msgid "Password or private key required" -#~ msgstr "密码或密钥密码需要一个" - -#~ msgid "Only ssh protocol system users are allowed" -#~ msgstr "仅允许ssh协议的系统用户" - -#~ msgid "The protocol must be consistent with the current user: {}" -#~ msgstr "协议必须和当前用户保持一致: {}" - -#~ msgid "Only system users with automatic login are allowed" -#~ msgstr "仅允许自动登录的系统用户" - -#~ msgid "The asset {} system platform {} does not support run Ansible tasks" -#~ msgstr "资产 {} 系统平台 {} 不支持运行 Ansible 任务" - -#~ msgid "Test assets connectivity: " -#~ msgstr "测试资产可连接性: " - -#~ msgid "Unreachable" -#~ msgstr "不可达" - -#~ msgid "Reachable" -#~ msgstr "可连接" - -#~ msgid "Get asset info failed: {}" -#~ msgstr "获取资产信息失败:{}" - -#~ msgid "Update asset hardware info: " -#~ msgstr "更新资产硬件信息: " - -#~ msgid "System user is dynamic: {}" -#~ msgstr "系统用户是动态的: {}" - -#~ msgid "Start push system user for platform: [{}]" -#~ msgstr "推送系统用户到平台: [{}]" - -#~ msgid "Hosts count: {}" -#~ msgstr "主机数量: {}" - -#~ msgid "Push system users to asset: " -#~ msgstr "推送系统用户到入资产: " - -#~ msgid "Dynamic system user not support test" -#~ msgstr "动态系统用户不支持测试" - -#~ msgid "Start test system user connectivity for platform: [{}]" -#~ msgstr "开始测试系统用户在该系统平台的可连接性: [{}]" - -#~ msgid "Test system user connectivity: " -#~ msgstr "测试系统用户可连接性: " - -#~ msgid "Test system user connectivity period: " -#~ msgstr "定期测试系统用户可连接性: " - -#~ msgid "Operate display" -#~ msgstr "操作名称" - -#~ msgid "Status display" -#~ msgstr "状态名称" - -#~ msgid "MFA display" -#~ msgstr "MFA名称" - -#~ msgid "Hosts display" -#~ msgstr "主机名称" - -#~ msgid "Run as" -#~ msgstr "运行用户" - -#~ msgid "Run as display" -#~ msgstr "运行用户名称" - -#~ msgid "User not exists" -#~ msgstr "用户不存在" - -#~ msgid "System user not exists" -#~ msgstr "系统用户不存在" - -#~ msgid "Asset not exists" -#~ msgstr "资产不存在" - -#~ msgid "User has no permission to access asset or permission expired" -#~ msgstr "用户没有权限访问资产或权限已过期" - -#~ msgid "User has no permission to access application or permission expired" -#~ msgstr "用户没有权限访问应用或权限已过期" - -#~ msgid "Asset or application required" -#~ msgstr "资产或应用必填" - -#~ msgid "Not has host {} permission" -#~ msgstr "没有该主机 {} 权限" - -#~ msgid "" -#~ "eg: Every Sunday 03:05 run <5 3 * * 0>
Tips: Using 5 digits linux " -#~ "crontab expressions (
Online tools)
Note: If both Regularly " -#~ "perform and Cycle perform are set, give priority to Regularly perform" -#~ msgstr "" -#~ "eg:每周日 03:05 执行 <5 3 * * 0>
提示: 使用5位 Linux crontab 表达" -#~ "式 <分 时 日 月 星期> (在线工具
注意: 如果同时设置了定期执行和周期执" -#~ "行,优先使用定期执行" - -#~ msgid "Unit: hour" -#~ msgstr "单位: 时" - -#~ msgid "Callback" -#~ msgstr "回调" - -#~ msgid "Tasks" -#~ msgstr "任务" - -#~ msgid "Run as admin" -#~ msgstr "再次执行" - -#~ msgid "Become" -#~ msgstr "Become" - -#~ msgid "Create by" -#~ msgstr "创建者" - -#~ msgid "Task display" -#~ msgstr "任务名称" - -#~ msgid "Host amount" -#~ msgstr "主机数量" - -#~ msgid "Start time" -#~ msgstr "开始时间" - -#~ msgid "End time" -#~ msgstr "完成时间" - -#~ msgid "Adhoc raw result" -#~ msgstr "结果" - -#~ msgid "Adhoc result summary" -#~ msgstr "汇总" - -#~ msgid "AdHoc execution" -#~ msgstr "任务执行" - -#~ msgid "Task start" -#~ msgstr "任务开始" - -#~ msgid "Command `{}` is forbidden ........" -#~ msgstr "命令 `{}` 不允许被执行 ......." - -#~ msgid "Task end" -#~ msgstr "任务结束" - -#~ msgid "Clean task history period" -#~ msgstr "定期清除任务历史" - -#~ msgid "The administrator is modifying permissions. Please wait" -#~ msgstr "管理员正在修改授权,请稍等" - -#~ msgid "The authorization cannot be revoked for the time being" -#~ msgstr "该授权暂时不能撤销" - -#~ msgid "Application permission" -#~ msgstr "应用授权" - -#~ msgid "Permed application" -#~ msgstr "授权的应用" - -#~ msgid "Can view my apps" -#~ msgstr "可以查看我的应用" - -#~ msgid "Can view user apps" -#~ msgstr "可以查看用户授权的应用" - -#~ msgid "Can view usergroup apps" -#~ msgstr "可以查看用户组授权的应用" - -#~ msgid "Upload file" -#~ msgstr "上传文件" - -#~ msgid "Download file" -#~ msgstr "下载文件" - -#~ msgid "Upload download" -#~ msgstr "上传下载" - -#~ msgid "Clipboard paste" -#~ msgstr "剪贴板粘贴" - -#~ msgid "Clipboard copy paste" -#~ msgstr "剪贴板复制粘贴" - -#~ msgid "Your permed applications is about to expire" -#~ msgstr "你授权的应用即将过期" - -#~ msgid "permed applications" -#~ msgstr "授权的应用" - -#~ msgid "Application permissions is about to expire" -#~ msgstr "应用授权规则即将过期" - -#~ msgid "application permissions of organization {}" -#~ msgstr "组织 ({}) 的应用授权" - -#~ msgid "User groups amount" -#~ msgstr "用户组数量" - -#~ msgid "System users amount" -#~ msgstr "系统用户数量" - -#~ msgid "" -#~ "The application list contains applications that are different from the " -#~ "permission type. ({})" -#~ msgstr "应用列表中包含与授权类型不同的应用。({})" - -#~ msgid "Users display" -#~ msgstr "用户名称" - -#~ msgid "User groups display" -#~ msgstr "用户组名称" - -#~ msgid "Assets display" -#~ msgstr "资产名称" - -#~ msgid "Nodes display" -#~ msgstr "节点名称" - -#~ msgid "System users display" -#~ msgstr "系统用户名称" - -#~ msgid "My applications" -#~ msgstr "我的应用" - -#~ msgid "Empty" -#~ msgstr "空" - -#~ msgid "System user ID" -#~ msgstr "系统用户 ID" - -#~ msgid "Apply for application" -#~ msgstr "申请应用" - -#~ msgid "" -#~ "Created by the ticket, ticket title: {}, ticket applicant: {}, ticket " -#~ "processor: {}, ticket ID: {}" -#~ msgstr "" -#~ "通过工单创建, 工单标题: {}, 工单申请人: {}, 工单处理人: {}, 工单 ID: {}" - -#~ msgid "Applied login IP" -#~ msgstr "申请登录的IP" - -#~ msgid "Applied login city" -#~ msgstr "申请登录的城市" - -#~ msgid "Applied login datetime" -#~ msgstr "申请登录的日期" - -#~ msgid "Login system user" -#~ msgstr "登录系统用户" +#~ msgid "Asset number" +#~ msgstr "资产编号" diff --git a/apps/terminal/serializers/applet_host.py b/apps/terminal/serializers/applet_host.py index cf7895a71..b2b7f2de1 100644 --- a/apps/terminal/serializers/applet_host.py +++ b/apps/terminal/serializers/applet_host.py @@ -34,7 +34,7 @@ class DeployOptionsSerializer(serializers.Serializer): RDS_LicenseServer = serializers.CharField(default='127.0.0.1', label=_('RDS License Server'), max_length=1024) RDS_LicensingMode = serializers.ChoiceField(choices=LICENSE_MODE_CHOICES, default=4, label=_('RDS Licensing Mode')) RDS_fSingleSessionPerUser = serializers.ChoiceField(choices=SESSION_PER_USER, default=1, - label=_("RDS fSingleSessionPerUser")) + label=_("RDS Single Session Per User")) RDS_MaxDisconnectionTime = serializers.IntegerField(default=60000, label=_("RDS Max Disconnection Time")) RDS_RemoteAppLogoffTimeLimit = serializers.IntegerField(default=0, label=_("RDS Remote App Logoff Time Limit")) From 9a1109e13d89ea4814021c2562edf30bd910a6db Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 6 Feb 2023 11:00:36 +0800 Subject: [PATCH 81/92] =?UTF-8?q?perf:=20=E8=B5=84=E4=BA=A7=E5=88=9B?= =?UTF-8?q?=E5=BB=BA=E6=B7=BB=E5=8A=A0=E8=B4=A6=E5=8F=B7=20=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E6=90=BA=E5=B8=A6=E5=AF=86=E7=A0=81=20(#9436)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng <1304903146@qq.com> --- apps/assets/serializers/asset/common.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/assets/serializers/asset/common.py b/apps/assets/serializers/asset/common.py index 348b6015e..4d6ea76c6 100644 --- a/apps/assets/serializers/asset/common.py +++ b/apps/assets/serializers/asset/common.py @@ -242,10 +242,18 @@ class AssetSerializer(BulkOrgResourceModelSerializer, WritableNestedModelSeriali }) return protocols_data_map.values() + @staticmethod + def accounts_create(accounts_data, asset): + for data in accounts_data: + data['asset'] = asset + AssetAccountSerializer().create(data) + @atomic def create(self, validated_data): nodes_display = validated_data.pop('nodes_display', '') + accounts = validated_data.pop('accounts', []) instance = super().create(validated_data) + self.accounts_create(accounts, instance) self.perform_nodes_display_create(instance, nodes_display) return instance From a3baac67632ed20125c4c575ea12f1965c92ea8d Mon Sep 17 00:00:00 2001 From: Aaron3S Date: Mon, 6 Feb 2023 11:27:21 +0800 Subject: [PATCH 82/92] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E6=9B=B4=E6=96=B0=E5=91=BD=E4=BB=A4=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/rbac/const.py | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/rbac/const.py b/apps/rbac/const.py index 192a0fe18..50d3a4c11 100644 --- a/apps/rbac/const.py +++ b/apps/rbac/const.py @@ -70,7 +70,6 @@ exclude_permissions = ( ('rbac', 'orgrolebinding', 'change', 'orgrolebinding'), ('rbac', 'menupermission', '*', 'menupermission'), ('rbac', 'role', '*', '*'), - ('ops', 'adhoc', 'delete,change', '*'), ('ops', 'adhocexecution', 'add,delete,change', '*'), ('ops', 'jobexecution', 'change,delete', 'jobexecution'), ('ops', 'historicaljob', '*', '*'), From dbd3cb35ec34fcad7ba6ffe38a7fd3c7c2d283b2 Mon Sep 17 00:00:00 2001 From: Aaron3S Date: Mon, 6 Feb 2023 11:27:21 +0800 Subject: [PATCH 83/92] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E6=9B=B4=E6=96=B0=E5=91=BD=E4=BB=A4=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/rbac/const.py | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/rbac/const.py b/apps/rbac/const.py index 192a0fe18..50d3a4c11 100644 --- a/apps/rbac/const.py +++ b/apps/rbac/const.py @@ -70,7 +70,6 @@ exclude_permissions = ( ('rbac', 'orgrolebinding', 'change', 'orgrolebinding'), ('rbac', 'menupermission', '*', 'menupermission'), ('rbac', 'role', '*', '*'), - ('ops', 'adhoc', 'delete,change', '*'), ('ops', 'adhocexecution', 'add,delete,change', '*'), ('ops', 'jobexecution', 'change,delete', 'jobexecution'), ('ops', 'historicaljob', '*', '*'), From 500124f4858a13f87c2ed317da77ecd0daf2cf31 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 6 Feb 2023 13:37:03 +0800 Subject: [PATCH 84/92] perf: asset automation filter (#9440) Co-authored-by: feng <1304903146@qq.com> --- apps/assets/api/asset/asset.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/apps/assets/api/asset/asset.py b/apps/assets/api/asset/asset.py index 1838a4f1a..13f4b86ac 100644 --- a/apps/assets/api/asset/asset.py +++ b/apps/assets/api/asset/asset.py @@ -29,10 +29,31 @@ __all__ = [ class AssetFilterSet(BaseFilterSet): + labels = django_filters.CharFilter(method='filter_labels') + platform = django_filters.CharFilter(method='filter_platform') type = django_filters.CharFilter(field_name="platform__type", lookup_expr="exact") category = django_filters.CharFilter(field_name="platform__category", lookup_expr="exact") - platform = django_filters.CharFilter(method='filter_platform') - labels = django_filters.CharFilter(method='filter_labels') + domain_enabled = django_filters.BooleanFilter( + field_name="platform__domain_enabled", lookup_expr="exact" + ) + ping_enabled = django_filters.BooleanFilter( + field_name="platform__automation__ping_enabled", lookup_expr="exact" + ) + gather_facts_enabled = django_filters.BooleanFilter( + field_name="platform__automation__gather_facts_enabled", lookup_expr="exact" + ) + change_secret_enabled = django_filters.BooleanFilter( + field_name="platform__automation__change_secret_enabled", lookup_expr="exact" + ) + push_account_enabled = django_filters.BooleanFilter( + field_name="platform__automation__push_account_enabled", lookup_expr="exact" + ) + verify_account_enabled = django_filters.BooleanFilter( + field_name="platform__automation__verify_account_enabled", lookup_expr="exact" + ) + gather_accounts_enabled = django_filters.BooleanFilter( + field_name="platform__automation__gather_accounts_enabled", lookup_expr="exact" + ) class Meta: model = Asset From f52a2ea47fc48044cc5b2d0177a1c94185218474 Mon Sep 17 00:00:00 2001 From: Bai Date: Mon, 6 Feb 2023 13:31:12 +0800 Subject: [PATCH 85/92] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E6=97=A5?= =?UTF-8?q?=E6=96=87=E7=BF=BB=E8=AF=91=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/ja/LC_MESSAGES/django.mo | 4 +- apps/locale/ja/LC_MESSAGES/django.po | 1427 +++++--------------------- apps/locale/zh/LC_MESSAGES/django.mo | 4 +- apps/locale/zh/LC_MESSAGES/django.po | 86 +- 4 files changed, 300 insertions(+), 1221 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index d2bcc3533..dcece3719 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0673bed993591a5545fc55a94a4329a5d2ab0d4006beb36af2598da1f6edd35c -size 119774 +oid sha256:7e35d73f8576a0ea30a0da3886b24033f61f1019f6e15466d7b5904b5dd15ef9 +size 136075 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index e84a47233..4819919d4 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-02-04 20:29+0800\n" +"POT-Creation-Date: 2023-02-06 13:10+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -37,9 +37,8 @@ msgstr "パスワード" #: accounts/const/account.py:7 #: accounts/serializers/automations/change_secret.py:34 -#, fuzzy msgid "SSH key" -msgstr "SSHキー" +msgstr "SSH キー" #: accounts/const/account.py:8 authentication/models/access_key.py:33 msgid "Access key" @@ -72,39 +71,32 @@ msgid "Collected" msgstr "" #: accounts/const/automation.py:22 rbac/tree.py:51 -#, fuzzy msgid "Push account" -msgstr "サービスアカウントです" +msgstr "アカウントプッシュ" #: accounts/const/automation.py:23 -#, fuzzy msgid "Change secret" -msgstr "秘密を改める" +msgstr "パスワードを変更する" #: accounts/const/automation.py:24 -#, fuzzy msgid "Verify account" -msgstr "パスワード/キーの確認" +msgstr "アカウントを確認" #: accounts/const/automation.py:25 -#, fuzzy msgid "Gather accounts" -msgstr "アカウントを集める" +msgstr "アカウントのコレクション" #: accounts/const/automation.py:26 -#, fuzzy msgid "Verify gateway account" -msgstr "パスワード/キーの確認" +msgstr "ゲートウェイ アカウントを確認する" #: accounts/const/automation.py:44 -#, fuzzy -#| msgid "Set password" msgid "Specific password" -msgstr "パスワードの設定" +msgstr "特定" #: accounts/const/automation.py:45 msgid "Random" -msgstr "" +msgstr "ランダム" #: accounts/const/automation.py:49 ops/const.py:13 msgid "Append SSH KEY" @@ -119,73 +111,52 @@ msgid "Replace (The key generated by JumpServer) " msgstr "置換(JumpServerによって生成された鍵)" #: accounts/const/automation.py:56 -#, fuzzy -#| msgid "Date created" msgid "On asset create" -msgstr "作成された日付" +msgstr "アセットが作成されたとき" #: accounts/const/automation.py:59 -#, fuzzy -#| msgid "After change" msgid "On perm add user" -msgstr "変更後" +msgstr "承認が変更されたときにユーザーを追加する" #: accounts/const/automation.py:61 msgid "On perm add user group" -msgstr "" +msgstr "権限変更時にユーザーグループを追加" #: accounts/const/automation.py:63 -#, fuzzy -#| msgid "permed assets" msgid "On perm add asset" -msgstr "パーマ資産" +msgstr "変更の承認時にアセットを追加する" #: accounts/const/automation.py:65 -#, fuzzy -#| msgid "After change" msgid "On perm add node" -msgstr "変更後" +msgstr "承認変更時のノードの追加" #: accounts/const/automation.py:67 -#, fuzzy msgid "On perm add account" -msgstr "アカウントを集める" +msgstr "承認が変更されたときにアカウントを追加する" #: accounts/const/automation.py:69 -#, fuzzy -#| msgid "Add asset to node" msgid "On asset join node" -msgstr "ノードにアセットを追加する" +msgstr "アセットの変更時にノードに追加" #: accounts/const/automation.py:71 -#, fuzzy -#| msgid "User group" msgid "On user join group" -msgstr "ユーザーグループ" +msgstr "ユーザー変更時にユーザーグループに追加" #: accounts/const/automation.py:79 -#, fuzzy -#| msgid "After change" msgid "On perm change" -msgstr "変更後" +msgstr "権限が変更されたとき" #: accounts/const/automation.py:86 -#, fuzzy -#| msgid "Perm ungroup node" msgid "Inherit from group or node" -msgstr "グループ化されていないノードを表示" +msgstr "ユーザーグループまたはアセットノードから継承" #: accounts/const/automation.py:94 -#, fuzzy -#| msgid "Created by" msgid "Create and push" -msgstr "によって作成された" +msgstr "作成してプッシュ" #: accounts/const/automation.py:95 -#, fuzzy -#| msgid "Date created" msgid "Only create" -msgstr "作成された日付" +msgstr "作成のみ" #: accounts/models/account.py:47 accounts/serializers/account/account.py:81 #: accounts/serializers/automations/change_secret.py:107 @@ -245,19 +216,16 @@ msgid "Can view asset history account secret" msgstr "資産履歴アカウントパスワードを表示できます" #: accounts/models/account.py:104 -#, fuzzy msgid "Account template" -msgstr "アカウント名" +msgstr "アカウント テンプレート" #: accounts/models/account.py:109 -#, fuzzy msgid "Can view asset account template secret" -msgstr "資産アカウントの秘密を表示できます" +msgstr "アセット アカウント テンプレートのパスワードを表示できます" #: accounts/models/account.py:110 -#, fuzzy msgid "Can change asset account template secret" -msgstr "資産口座の秘密を変更できます" +msgstr "アセット アカウント テンプレートのパスワードを変更できます" #: accounts/models/automations/backup_account.py:25 #: accounts/models/automations/change_secret.py:47 @@ -316,19 +284,16 @@ msgid "Account backup execution" msgstr "アカウントバックアップの実行" #: accounts/models/automations/base.py:15 -#, fuzzy msgid "Account automation task" -msgstr "自動管理" +msgstr "アカウント自動化タスク" #: accounts/models/automations/base.py:25 -#, fuzzy msgid "Automation execution" -msgstr "インスタンスタスクの同期実行" +msgstr "自動実行" #: accounts/models/automations/base.py:26 -#, fuzzy msgid "Automation executions" -msgstr "インスタンスタスクの同期実行" +msgstr "自動実行" #: accounts/models/automations/base.py:28 msgid "Can view change secret execution" @@ -340,23 +305,19 @@ msgstr "改密実行の作成" #: accounts/models/automations/base.py:31 msgid "Can view gather accounts execution" -msgstr "収集アカウント実行の表示" +msgstr "コレクションアカウントの実行を表示" #: accounts/models/automations/base.py:32 msgid "Can add gather accounts execution" -msgstr "収集アカウントの作成実行" +msgstr "回収口座作成の実行" #: accounts/models/automations/base.py:34 -#, fuzzy -#| msgid "Can view gather accounts execution" msgid "Can view push account execution" -msgstr "収集アカウント実行の表示" +msgstr "プッシュ アカウントの実行を表示する" #: accounts/models/automations/base.py:35 -#, fuzzy -#| msgid "Can add gather accounts execution" msgid "Can add push account execution" -msgstr "収集アカウントの作成実行" +msgstr "プッシュ アカウントの作成の実行" #: accounts/models/automations/change_secret.py:17 accounts/models/base.py:36 #: accounts/serializers/account/account.py:118 @@ -385,22 +346,18 @@ msgid "Password rules" msgstr "パスワードルール" #: accounts/models/automations/change_secret.py:27 -#, fuzzy msgid "SSH key change strategy" -msgstr "SSHキー戦略" +msgstr "SSHキープッシュ方式" #: accounts/models/automations/change_secret.py:54 -#, fuzzy msgid "Change secret automation" -msgstr "セキュリティ設定を変更できます" +msgstr "自動暗号化" #: accounts/models/automations/change_secret.py:71 -#, fuzzy msgid "Old secret" -msgstr "OTP 秘密" +msgstr "以前のパスワード" #: accounts/models/automations/change_secret.py:73 -#, fuzzy msgid "Date started" msgstr "開始日" @@ -413,26 +370,21 @@ msgstr "終了日" #: accounts/models/automations/change_secret.py:76 assets/const/automation.py:8 #: common/const/choices.py:20 -#, fuzzy msgid "Error" -msgstr "企業微信エラー" +msgstr "間違い" #: accounts/models/automations/change_secret.py:80 -#, fuzzy msgid "Change secret record" -msgstr "パスワードの変更" +msgstr "パスワード レコードの変更" #: accounts/models/automations/gather_account.py:15 #: accounts/tasks/gather_accounts.py:28 -#, fuzzy msgid "Gather asset accounts" -msgstr "アカウントを集める" +msgstr "アカウントのコレクション" #: accounts/models/automations/push_account.py:13 -#, fuzzy -#| msgid "Trigger mode" msgid "Triggers" -msgstr "トリガーモード" +msgstr "トリガー方式" #: accounts/models/automations/push_account.py:14 accounts/models/base.py:34 #: acls/serializers/base.py:18 acls/serializers/base.py:49 @@ -455,14 +407,12 @@ msgid "Action" msgstr "アクション" #: accounts/models/automations/push_account.py:41 -#, fuzzy msgid "Push asset account" -msgstr "サービスアカウントです" +msgstr "アカウントプッシュ" #: accounts/models/automations/verify_account.py:15 -#, fuzzy msgid "Verify asset account" -msgstr "パスワード/キーの確認" +msgstr "アカウントの確認" #: accounts/models/base.py:33 acls/models/base.py:75 #: acls/models/command_acl.py:21 acls/serializers/base.py:34 @@ -472,7 +422,7 @@ msgstr "パスワード/キーの確認" #: assets/models/group.py:20 assets/models/label.py:18 #: assets/models/platform.py:20 assets/models/platform.py:74 #: assets/serializers/asset/common.py:61 assets/serializers/asset/common.py:129 -#: assets/serializers/platform.py:137 +#: assets/serializers/platform.py:126 #: authentication/serializers/connect_token_secret.py:103 ops/mixin.py:20 #: ops/models/adhoc.py:22 ops/models/celery.py:15 ops/models/celery.py:57 #: ops/models/job.py:24 ops/models/playbook.py:15 orgs/models.py:69 @@ -489,7 +439,7 @@ msgstr "名前" #: accounts/models/base.py:39 msgid "Privileged" -msgstr "" +msgstr "特権アカウント" #: accounts/models/base.py:40 assets/models/asset/common.py:114 #: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 @@ -548,19 +498,16 @@ msgstr "テンプレート" #: accounts/serializers/account/account.py:56 #: assets/serializers/asset/common.py:56 msgid "Push now" -msgstr "" +msgstr "今すぐプッシュ" #: accounts/serializers/account/account.py:58 #: accounts/serializers/account/base.py:64 -#, fuzzy msgid "Has secret" -msgstr "ひみつ" +msgstr "エスクローされたパスワード" #: accounts/serializers/account/account.py:77 -#, fuzzy -#| msgid "Asset Info" msgid "Asset not found" -msgstr "資産情報" +msgstr "資産が存在しません" #: accounts/serializers/account/backup.py:30 #: accounts/serializers/automations/base.py:36 @@ -571,9 +518,8 @@ msgstr "定期的なパフォーマンス" #: accounts/serializers/account/backup.py:31 #: accounts/serializers/automations/base.py:37 -#, fuzzy msgid "Executed amount" -msgstr "実行時間" +msgstr "実行回数" #: accounts/serializers/account/backup.py:33 #: accounts/serializers/automations/change_secret.py:57 @@ -590,10 +536,8 @@ msgstr "キーパスワード" #: accounts/serializers/account/base.py:80 #: assets/serializers/asset/common.py:262 -#, fuzzy -#| msgid "Ticket flow" msgid "Spec info" -msgstr "チケットの流れ" +msgstr "特別情報" #: accounts/serializers/automations/base.py:22 #: assets/models/automations/base.py:19 @@ -613,15 +557,14 @@ msgstr "ノード" #: accounts/serializers/automations/base.py:42 #: assets/models/automations/base.py:109 #: assets/serializers/automations/base.py:39 -#, fuzzy msgid "Automation snapshot" -msgstr "製造オーダスナップショット" +msgstr "自動スナップショット" #: accounts/serializers/automations/base.py:43 acls/models/command_acl.py:24 #: acls/serializers/command_acl.py:18 applications/models.py:14 #: assets/models/_user.py:50 assets/models/automations/base.py:20 #: assets/models/cmd_filter.py:74 assets/models/platform.py:76 -#: assets/serializers/asset/common.py:109 assets/serializers/platform.py:98 +#: assets/serializers/asset/common.py:109 assets/serializers/platform.py:87 #: audits/serializers.py:48 #: authentication/serializers/connect_token_secret.py:116 ops/models/job.py:32 #: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:28 @@ -649,9 +592,8 @@ msgstr "* パスワードの長さの範囲6-30ビット" #: accounts/serializers/automations/change_secret.py:110 #: assets/models/automations/base.py:118 -#, fuzzy msgid "Automation task execution" -msgstr "インスタンスタスクの同期実行" +msgstr "自動タスク実行履歴" #: accounts/serializers/automations/change_secret.py:150 audits/const.py:45 #: audits/handler.py:167 audits/models.py:40 common/const/choices.py:18 @@ -667,33 +609,28 @@ msgid "Failed" msgstr "失敗しました" #: accounts/tasks/automation.py:11 -#, fuzzy msgid "Account execute automation" -msgstr "バッチ実行コマンド" +msgstr "アカウント実行の自動化" #: accounts/tasks/backup_account.py:13 -#, fuzzy msgid "Execute account backup plan" -msgstr "アカウントバックアップ計画" +msgstr "アカウントのバックアップ計画を実施する" #: accounts/tasks/gather_accounts.py:31 -#, fuzzy msgid "Gather assets accounts" -msgstr "資産ユーザーの収集" +msgstr "資産の口座番号を収集する" #: accounts/tasks/push_account.py:30 accounts/tasks/push_account.py:36 -#, fuzzy msgid "Push accounts to assets" -msgstr "システムユーザーを資産にプッシュする:" +msgstr "アカウントをアセットにプッシュ:" #: accounts/tasks/verify_account.py:41 msgid "Verify asset account availability" -msgstr "" +msgstr "アセット アカウントの可用性を確認する" #: accounts/tasks/verify_account.py:47 -#, fuzzy msgid "Verify accounts connectivity" -msgstr "テストアカウント接続:" +msgstr "アカウント接続のテスト" #: accounts/utils.py:42 msgid "Password can not contains `{{` " @@ -852,34 +789,24 @@ msgid "IP/Host" msgstr "IP/ホスト" #: acls/serializers/base.py:60 -#, fuzzy -#| msgid "System user name" msgid "User (username)" -msgstr "システムユーザー名" +msgstr "ユーザー (ユーザー名)" #: acls/serializers/base.py:64 -#, fuzzy -#| msgid "Asset hostname" msgid "Asset (name)" -msgstr "資産ホスト名" +msgstr "資産(名前)" #: acls/serializers/base.py:68 -#, fuzzy -#| msgid "Address" msgid "Asset (address)" -msgstr "アドレス" +msgstr "資産(住所)" #: acls/serializers/base.py:72 -#, fuzzy -#| msgid "Account name" msgid "Account (username)" -msgstr "アカウント名" +msgstr "アカウント (ユーザー名)" #: acls/serializers/base.py:78 acls/serializers/login_acl.py:27 -#, fuzzy -#| msgid "Reviewers" msgid "Reviewers amount" -msgstr "レビュー担当者" +msgstr "承認者数" #: acls/serializers/base.py:109 tickets/serializers/ticket/ticket.py:76 msgid "The organization `{}` does not exist" @@ -890,10 +817,8 @@ msgid "None of the reviewers belong to Organization `{}`" msgstr "いずれのレビューアも組織 '{}' に属していません" #: acls/serializers/command_acl.py:31 -#, fuzzy -#| msgid "Command amount" msgid "Command group amount" -msgstr "コマンド量" +msgstr "コマンドグループ数" #: acls/serializers/rules/rules.py:20 #: xpack/plugins/cloud/serializers/task.py:22 @@ -928,8 +853,8 @@ msgstr "アプリケーション" #: applications/models.py:11 assets/models/label.py:21 #: assets/models/platform.py:75 assets/serializers/asset/common.py:108 -#: assets/serializers/cagegory.py:8 assets/serializers/platform.py:99 -#: assets/serializers/platform.py:138 perms/serializers/user_permission.py:25 +#: assets/serializers/cagegory.py:8 assets/serializers/platform.py:88 +#: assets/serializers/platform.py:127 perms/serializers/user_permission.py:25 #: settings/models.py:35 tickets/models/ticket/apply_application.py:13 msgid "Category" msgstr "カテゴリ" @@ -989,20 +914,18 @@ msgid "App assets" msgstr "アプリ資産" #: assets/automations/base/manager.py:103 -#, fuzzy msgid "{} disabled" -msgstr "無効" +msgstr "{} 無効" #: assets/automations/ping_gateway/manager.py:33 #: authentication/models/connection_token.py:113 -#, fuzzy msgid "No account" -msgstr "アカウント" +msgstr "アカウントなし" #: assets/automations/ping_gateway/manager.py:55 -#, fuzzy, python-brace-format +#, python-brace-format msgid "Unable to connect to port {port} on {address}" -msgstr "{ip} でポート {port} に接続できません" +msgstr "{port} のポート {address} に接続できません" #: assets/automations/ping_gateway/manager.py:58 #: authentication/middleware.py:76 xpack/plugins/cloud/providers/fc.py:48 @@ -1026,18 +949,15 @@ msgstr "OK" #: assets/const/automation.py:12 msgid "Ping" -msgstr "" +msgstr "テスト" #: assets/const/automation.py:13 -#, fuzzy -#| msgid "Test gateway" msgid "Ping gateway" msgstr "テストゲートウェイ" #: assets/const/automation.py:14 -#, fuzzy msgid "Gather facts" -msgstr "アカウントを集める" +msgstr "資産情報の収集" #: assets/const/category.py:11 settings/serializers/auth/radius.py:16 #: settings/serializers/auth/sms.py:67 terminal/models/component/endpoint.py:13 @@ -1047,7 +967,7 @@ msgstr "ホスト" #: assets/const/category.py:12 msgid "Device" -msgstr "" +msgstr "インターネット機器" #: assets/const/category.py:13 assets/models/asset/database.py:9 #: assets/models/asset/database.py:24 assets/serializers/asset/common.py:96 @@ -1055,14 +975,13 @@ msgid "Database" msgstr "データベース" #: assets/const/category.py:14 -#, fuzzy msgid "Cloud service" -msgstr "クラウドセンター" +msgstr "クラウド サービス" #: assets/const/category.py:15 audits/const.py:33 #: terminal/models/applet/applet.py:22 msgid "Web" -msgstr "" +msgstr "Web" #: assets/const/device.py:7 terminal/models/applet/applet.py:21 #: tickets/const.py:8 @@ -1070,28 +989,24 @@ msgid "General" msgstr "一般" #: assets/const/device.py:8 -#, fuzzy msgid "Switch" -msgstr "から切り替え" +msgstr "スイッチ" #: assets/const/device.py:9 msgid "Router" -msgstr "" +msgstr "ルーター" #: assets/const/device.py:10 msgid "Firewall" -msgstr "" +msgstr "ファイアウォール" #: assets/const/types.py:200 -#, fuzzy -#| msgid "MFA type" msgid "All types" -msgstr "MFAタイプ" +msgstr "いろんなタイプ" #: assets/const/web.py:7 -#, fuzzy msgid "Website" -msgstr "ウェブサイトのアイコン" +msgstr "Webサイト" #: assets/models/_user.py:25 msgid "SSH private key" @@ -1231,14 +1146,12 @@ msgid "Can test asset connectivity" msgstr "資産接続をテストできます" #: assets/models/asset/common.py:287 -#, fuzzy msgid "Can push account to asset" -msgstr "システムユーザーを資産にプッシュできます" +msgstr "アカウントをアセットにプッシュできます" #: assets/models/asset/common.py:288 -#, fuzzy msgid "Can verify account" -msgstr "パスワード/キーの確認" +msgstr "アカウントを確認できます" #: assets/models/asset/common.py:289 msgid "Can match asset" @@ -1258,19 +1171,16 @@ msgid "Use SSL" msgstr "SSLの使用" #: assets/models/asset/database.py:11 -#, fuzzy msgid "CA cert" -msgstr "SP 証明書" +msgstr "CA 証明書" #: assets/models/asset/database.py:12 -#, fuzzy msgid "Client cert" -msgstr "クライアント秘密" +msgstr "クライアント証明書" #: assets/models/asset/database.py:13 -#, fuzzy msgid "Client key" -msgstr "クライアント" +msgstr "クライアントキー" #: assets/models/asset/database.py:14 assets/serializers/asset/common.py:98 msgid "Allow invalid cert" @@ -1289,29 +1199,26 @@ msgstr "基本" #: assets/models/asset/web.py:11 assets/models/asset/web.py:17 #: assets/serializers/asset/common.py:104 msgid "Script" -msgstr "" +msgstr "脚本" #: assets/models/asset/web.py:13 assets/serializers/platform.py:28 -#, fuzzy msgid "Autofill" -msgstr "自動" +msgstr "自動充填" #: assets/models/asset/web.py:14 assets/serializers/asset/common.py:101 #: assets/serializers/platform.py:30 -#, fuzzy msgid "Username selector" -msgstr "ユーザー名のプロパティ" +msgstr "ユーザー名ピッカー" #: assets/models/asset/web.py:15 assets/serializers/asset/common.py:102 #: assets/serializers/platform.py:33 -#, fuzzy msgid "Password selector" -msgstr "パスワードルール" +msgstr "パスワードセレクター" #: assets/models/asset/web.py:16 assets/serializers/asset/common.py:103 #: assets/serializers/platform.py:36 msgid "Submit selector" -msgstr "" +msgstr "ボタンセレクターを確認する" #: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38 #: assets/serializers/asset/common.py:261 perms/models/asset_permission.py:70 @@ -1320,14 +1227,12 @@ msgid "Accounts" msgstr "アカウント" #: assets/models/automations/base.py:28 assets/models/automations/base.py:102 -#, fuzzy msgid "Automation task" -msgstr "自動管理" +msgstr "自動化されたタスク" #: assets/models/automations/base.py:95 -#, fuzzy msgid "Asset automation task" -msgstr "自動管理" +msgstr "アセットの自動化タスク" #: assets/models/automations/base.py:104 audits/models.py:134 #: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:98 @@ -1341,14 +1246,12 @@ msgid "Status" msgstr "ステータス" #: assets/models/automations/gather_facts.py:15 -#, fuzzy msgid "Gather asset facts" -msgstr "資産ユーザーの収集" +msgstr "資産情報の収集" #: assets/models/automations/ping.py:15 -#, fuzzy msgid "Ping asset" -msgstr "ログイン資産" +msgstr "テストアセット" #: assets/models/base.py:19 msgid "Connectivity" @@ -1389,10 +1292,8 @@ msgid "Command filter rule" msgstr "コマンドフィルタルール" #: assets/models/favorite_asset.py:17 -#, fuzzy -#| msgid "Favorite Asset" msgid "Favorite asset" -msgstr "お気に入り" +msgstr "お気に入りのアセット" #: assets/models/gateway.py:35 assets/serializers/domain.py:16 msgid "Gateway" @@ -1460,9 +1361,8 @@ msgid "Can match node" msgstr "ノードを一致させることができます" #: assets/models/platform.py:19 -#, fuzzy msgid "Required" -msgstr "MFAが必要" +msgstr "必要" #: assets/models/platform.py:22 settings/serializers/settings.py:61 #: users/templates/users/reset_password.html:29 @@ -1476,58 +1376,49 @@ msgstr "有効化" #: assets/models/platform.py:42 msgid "Ansible config" -msgstr "" +msgstr "Ansible 構成" #: assets/models/platform.py:43 assets/serializers/platform.py:55 -#, fuzzy msgid "Ping enabled" -msgstr "MFA有効化" +msgstr "アセット ディスカバリを有効にする" -#: assets/models/platform.py:44 assets/serializers/platform.py:57 +#: assets/models/platform.py:44 assets/serializers/platform.py:56 msgid "Ping method" -msgstr "" +msgstr "資産検出方法" #: assets/models/platform.py:45 assets/models/platform.py:58 -#: assets/serializers/platform.py:59 -#, fuzzy +#: assets/serializers/platform.py:57 msgid "Gather facts enabled" -msgstr "資産ユーザーの収集" +msgstr "資産情報の収集を有効にする" #: assets/models/platform.py:46 assets/models/platform.py:60 -#: assets/serializers/platform.py:61 -#, fuzzy +#: assets/serializers/platform.py:58 msgid "Gather facts method" -msgstr "資産ユーザーの収集" +msgstr "情報収集の方法" -#: assets/models/platform.py:47 assets/serializers/platform.py:67 -#, fuzzy +#: assets/models/platform.py:47 assets/serializers/platform.py:61 msgid "Change secret enabled" -msgstr "パスワードの変更" +msgstr "パスワードの変更が有効" -#: assets/models/platform.py:49 assets/serializers/platform.py:69 -#, fuzzy +#: assets/models/platform.py:49 assets/serializers/platform.py:62 msgid "Change secret method" -msgstr "パスワードの変更" +msgstr "パスワード変更モード" -#: assets/models/platform.py:51 assets/serializers/platform.py:71 -#, fuzzy +#: assets/models/platform.py:51 assets/serializers/platform.py:63 msgid "Push account enabled" -msgstr "MFAが有効化されていません" +msgstr "アカウントのプッシュを有効にする" -#: assets/models/platform.py:53 assets/serializers/platform.py:73 -#, fuzzy +#: assets/models/platform.py:53 assets/serializers/platform.py:64 msgid "Push account method" -msgstr "サービスアカウントです" +msgstr "アカウントプッシュ方式" -#: assets/models/platform.py:55 assets/serializers/platform.py:63 -#, fuzzy +#: assets/models/platform.py:55 assets/serializers/platform.py:59 msgid "Verify account enabled" -msgstr "サービスアカウントキー" +msgstr "アカウントの確認をオンにする" -#: assets/models/platform.py:57 assets/serializers/platform.py:65 -#, fuzzy +#: assets/models/platform.py:57 assets/serializers/platform.py:60 msgid "Verify account method" -msgstr "パスワード/キーの確認" +msgstr "アカウント認証方法" #: assets/models/platform.py:77 tickets/models/ticket/general.py:300 msgid "Meta" @@ -1537,28 +1428,25 @@ msgstr "メタ" msgid "Internal" msgstr "ビルトイン" -#: assets/models/platform.py:82 assets/serializers/platform.py:96 +#: assets/models/platform.py:82 assets/serializers/platform.py:85 msgid "Charset" msgstr "シャーセット" -#: assets/models/platform.py:84 assets/serializers/platform.py:123 -#, fuzzy +#: assets/models/platform.py:84 assets/serializers/platform.py:112 msgid "Domain enabled" -msgstr "ドメイン名" +msgstr "ドメインを有効にする" -#: assets/models/platform.py:86 assets/serializers/platform.py:122 +#: assets/models/platform.py:86 assets/serializers/platform.py:111 msgid "Su enabled" msgstr "アカウントの切り替えを有効にする" -#: assets/models/platform.py:87 assets/serializers/platform.py:106 -#, fuzzy +#: assets/models/platform.py:87 assets/serializers/platform.py:95 msgid "Su method" -msgstr "接続タイムアウト" +msgstr "アカウントの切り替え方法" -#: assets/models/platform.py:89 assets/serializers/platform.py:103 -#, fuzzy +#: assets/models/platform.py:89 assets/serializers/platform.py:92 msgid "Automation" -msgstr "自動管理" +msgstr "オートメーション" #: assets/models/utils.py:18 #, python-format @@ -1566,11 +1454,10 @@ msgid "%(value)s is not an even number" msgstr "%(value)s は偶数ではありません" #: assets/serializers/asset/common.py:100 -#, fuzzy msgid "Auto fill" -msgstr "自動" +msgstr "自動充填" -#: assets/serializers/asset/common.py:111 assets/serializers/platform.py:101 +#: assets/serializers/asset/common.py:111 assets/serializers/platform.py:90 #: authentication/serializers/connect_token_secret.py:28 #: authentication/serializers/connect_token_secret.py:66 #: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:107 @@ -1659,10 +1546,9 @@ msgstr "システムアーキテクチャ" #: assets/serializers/cagegory.py:9 msgid "Constraints" -msgstr "" +msgstr "制約" #: assets/serializers/cagegory.py:15 -#, fuzzy msgid "Types" msgstr "タイプ" @@ -1687,48 +1573,40 @@ msgid "The same level node name cannot be the same" msgstr "同じレベルのノード名を同じにすることはできません。" #: assets/serializers/platform.py:24 -#, fuzzy msgid "SFTP enabled" -msgstr "MFA有効化" +msgstr "SFTP が有効" #: assets/serializers/platform.py:25 -#, fuzzy msgid "SFTP home" -msgstr "SFTPルート" +msgstr "SFTP ルート パス" -#: assets/serializers/platform.py:75 -#, fuzzy +#: assets/serializers/platform.py:65 msgid "Gather accounts enabled" -msgstr "資産ユーザーの収集" +msgstr "アカウント収集を有効にする" -#: assets/serializers/platform.py:77 -#, fuzzy +#: assets/serializers/platform.py:66 msgid "Gather accounts method" -msgstr "資産ユーザーの収集" +msgstr "アカウントの収集方法" -#: assets/serializers/platform.py:83 +#: assets/serializers/platform.py:72 msgid "Primary" -msgstr "" +msgstr "主要" -#: assets/serializers/platform.py:124 -#, fuzzy -#| msgid "Default storage" +#: assets/serializers/platform.py:113 msgid "Default Domain" -msgstr "デフォルトのストレージ" +msgstr "デフォルト ドメイン" #: assets/tasks/automation.py:11 -#, fuzzy msgid "Asset execute automation" -msgstr "バッチ実行コマンド" +msgstr "アセット実行の自動化" #: assets/tasks/gather_facts.py:23 msgid "Update some assets hardware info. " msgstr "一部の資産ハードウェア情報を更新します。" #: assets/tasks/gather_facts.py:53 -#, fuzzy msgid "Manually update the hardware information of assets" -msgstr "ノード資産のハードウェア情報を更新します。" +msgstr "アセット情報を手動で更新する" #: assets/tasks/gather_facts.py:57 msgid "Update assets hardware info: " @@ -1736,7 +1614,7 @@ msgstr "資産のハードウェア情報を更新する:" #: assets/tasks/gather_facts.py:61 msgid "Manually update the hardware information of assets under a node" -msgstr "" +msgstr "ノードの下の資産情報を手動で更新する" #: assets/tasks/gather_facts.py:65 msgid "Update node asset hardware information: " @@ -1744,7 +1622,7 @@ msgstr "ノード資産のハードウェア情報を更新します。" #: assets/tasks/nodes_amount.py:16 msgid "Check the amount of assets under the node" -msgstr "" +msgstr "ノード下のアセット数を確認する" #: assets/tasks/nodes_amount.py:28 msgid "" @@ -1755,26 +1633,23 @@ msgstr "" #: assets/tasks/nodes_amount.py:34 msgid "Periodic check the amount of assets under the node" -msgstr "" +msgstr "ノードの下にあるアセットの数を定期的に確認する" #: assets/tasks/ping.py:37 assets/tasks/ping.py:54 -#, fuzzy msgid "Test assets connectivity " -msgstr "資産の接続性をテストします。" +msgstr "アセット接続のテスト。" #: assets/tasks/ping.py:50 -#, fuzzy msgid "Manually test the connectivity of a asset" -msgstr "資産接続をテストできます" +msgstr "アセットの接続を手動でテストする" #: assets/tasks/ping.py:58 msgid "Manually test the connectivity of assets under a node" -msgstr "" +msgstr "ノードの下のアセットの接続を手動でテストする" #: assets/tasks/ping.py:62 -#, fuzzy msgid "Test if the assets under the node are connectable " -msgstr "ノードの下のアセットが接続可能かどうかをテストします。" +msgstr "ノード配下のアセットが接続できるかテストする" #: assets/tasks/utils.py:17 msgid "Asset has been disabled, skipped: {}" @@ -1860,9 +1735,8 @@ msgid "Login" msgstr "ログイン" #: audits/const.py:29 ops/const.py:9 -#, fuzzy msgid "Change password" -msgstr "パスワードの変更" +msgstr "パスワードを変更する" #: audits/const.py:34 settings/serializers/terminal.py:6 #: terminal/models/applet/host.py:24 terminal/models/component/terminal.py:156 @@ -1891,10 +1765,8 @@ msgid "User {} has executed change auth plan for this account.({})" msgstr "ユーザー {} はこのアカウントのために改密計画を実行しました。({})" #: audits/handler.py:168 -#, fuzzy -#| msgid "User {} {} it." msgid "User {} login into this service.[{}]" -msgstr "ユーザー {} はそれを {} しました" +msgstr "ユーザー {} がサービスにログインしました。[{}]" #: audits/models.py:32 audits/models.py:59 audits/models.py:101 #: terminal/models/session/session.py:37 terminal/models/session/sharing.py:95 @@ -1983,10 +1855,8 @@ msgid "Reason display" msgstr "理由表示" #: audits/serializers.py:120 -#, fuzzy -#| msgid "User {} {} it." msgid "User {} {} this resource." -msgstr "ユーザー {} はそれを {} しました" +msgstr "ユーザー {} {} が現在のリソースをサブスクライブしました。" #: audits/signal_handlers.py:49 msgid "SSH Key" @@ -2024,34 +1894,28 @@ msgid "Temporary token" msgstr "仮パスワード" #: audits/tasks.py:37 -#, fuzzy -#| msgid "Job audit log" msgid "Clean audits log" -msgstr "ジョブ監査ログ" +msgstr "監査ログのクリーンアップ" #: authentication/api/confirm.py:40 msgid "This action require verify your MFA" msgstr "この操作には、MFAを検証する必要があります" #: authentication/api/connection_token.py:264 -#, fuzzy -#| msgid "Asset Info" msgid "Account not found" -msgstr "資産情報" +msgstr "アカウントが見つかりません" #: authentication/api/connection_token.py:267 -#, fuzzy -#| msgid "Permission name" msgid "Permission expired" -msgstr "認可ルール名" +msgstr "承認の有効期限が切れています" #: authentication/api/connection_token.py:279 msgid "ACL action is reject" -msgstr "" +msgstr "ACL アクションは拒否です" #: authentication/api/connection_token.py:283 msgid "ACL action is review" -msgstr "" +msgstr "ACL アクションはレビューです" #: authentication/api/mfa.py:59 msgid "Current user not support mfa type: {}" @@ -2230,13 +2094,12 @@ msgstr "" "にもう一度お試しください)" #: authentication/errors/const.py:51 -#, fuzzy msgid "" "The address has been locked (please contact admin to unlock it or try again " "after {} minutes)" msgstr "" -"IPがロックされています (管理者に連絡してロックを解除するか、 {} 分後にもう一" -"度お試しください)" +"IP がロックされています (管理者に連絡してロックを解除するか、{} 分後に再試行" +"してください)" #: authentication/errors/const.py:59 #, python-brace-format @@ -2434,20 +2297,17 @@ msgid "Account name" msgstr "アカウント名" #: authentication/models/connection_token.py:35 -#, fuzzy msgid "Input username" -msgstr "カスタムユーザー名" +msgstr "カスタム ユーザー名" #: authentication/models/connection_token.py:36 #: authentication/serializers/connection_token.py:16 -#, fuzzy msgid "Input secret" -msgstr "クライアント秘密" +msgstr "カスタムパスワード" #: authentication/models/connection_token.py:38 -#, fuzzy msgid "Connect method" -msgstr "接続タイムアウト" +msgstr "接続方法" #: authentication/models/connection_token.py:39 #: rbac/serializers/rolebinding.py:21 @@ -2479,10 +2339,8 @@ msgid "Can view connection token secret" msgstr "接続トークンの秘密を表示できます" #: authentication/models/connection_token.py:100 -#, fuzzy -#| msgid "Connection token" msgid "Connection token inactive" -msgstr "接続トークン" +msgstr "接続トークンがアクティブ化されていません" #: authentication/models/connection_token.py:103 msgid "Connection token expired at: {}" @@ -2490,12 +2348,11 @@ msgstr "接続トークンの有効期限: {}" #: authentication/models/connection_token.py:106 msgid "No user or invalid user" -msgstr "" +msgstr "ユーザーなしまたは期限切れのユーザー" #: authentication/models/connection_token.py:110 -#, fuzzy msgid "No asset or inactive asset" -msgstr "アセットがアクティブ化されていません" +msgstr "アセットがないか、有効化されていないアセット" #: authentication/models/connection_token.py:257 msgid "Super connection token" @@ -2526,24 +2383,20 @@ msgid "binding reminder" msgstr "バインディングリマインダー" #: authentication/serializers/connect_token_secret.py:106 -#, fuzzy msgid "Is builtin" -msgstr "内蔵" +msgstr "ビルトイン" #: authentication/serializers/connect_token_secret.py:110 msgid "Options" msgstr "オプション" #: authentication/serializers/connect_token_secret.py:117 -#, fuzzy -#| msgid "SystemComponent" msgid "Component" -msgstr "システムコンポーネント" +msgstr "コンポーネント" #: authentication/serializers/connect_token_secret.py:128 -#, fuzzy msgid "Expired now" -msgstr "期限切れ" +msgstr "すぐに期限切れ" #: authentication/serializers/connect_token_secret.py:148 #: authentication/templates/authentication/_access_key_modal.html:30 @@ -2556,10 +2409,8 @@ msgid "Expired time" msgstr "期限切れ時間" #: authentication/serializers/connection_token.py:18 -#, fuzzy -#| msgid "Ticket flow" msgid "Ticket info" -msgstr "チケットの流れ" +msgstr "作業指示情報" #: authentication/serializers/password_mfa.py:16 #: authentication/serializers/password_mfa.py:24 @@ -2582,10 +2433,8 @@ msgid "Is valid" msgstr "有効です" #: authentication/tasks.py:12 -#, fuzzy -#| msgid "Can share session" msgid "Clean expired session" -msgstr "セッションを共有できます" +msgstr "期限切れのセッションをクリアする" #: authentication/templates/authentication/_access_key_modal.html:6 msgid "API key list" @@ -2979,7 +2828,6 @@ msgid "Running" msgstr "" #: common/const/choices.py:21 -#, fuzzy msgid "Canceled" msgstr "キャンセル" @@ -3145,46 +2993,42 @@ msgid "Children" msgstr "" #: common/serializers/common.py:92 -#, fuzzy msgid "File" -msgstr "ファイル名" +msgstr "書類" #: common/serializers/fields.py:101 -#, fuzzy, python-brace-format +#, python-brace-format msgid "Invalid pk \"{pk_value}\" - object does not exist." -msgstr "%s オブジェクトは存在しません。" +msgstr "無効な pk \"{pk_value}\" - オブジェクトが存在しません" #: common/serializers/fields.py:102 #, python-brace-format msgid "Incorrect type. Expected pk value, received {data_type}." -msgstr "" +msgstr "エラータイプ。 予想される pk 値、受信 {data_type}。" #: common/serializers/fields.py:172 msgid "Invalid data type, should be list" -msgstr "" +msgstr "間違ったデータ タイプです。リストにする必要があります" #: common/serializers/fields.py:187 -#, fuzzy msgid "Invalid choice: {}" -msgstr "無効なIP" +msgstr "無効なオプション: {}" #: common/tasks.py:13 common/utils/verify_code.py:16 -#, fuzzy msgid "Send email" -msgstr "ユーザーを送信" +msgstr "メールを送る" #: common/tasks.py:40 msgid "Send email attachment" -msgstr "" +msgstr "メールの添付ファイルを送信" #: common/utils/ip/geoip/utils.py:26 msgid "Invalid ip" -msgstr "無効なIP" +msgstr "無効な IP" #: common/utils/ip/utils.py:78 -#, fuzzy msgid "Invalid address" -msgstr "署名が無効です。" +msgstr "無効なアドレス。" #: common/validators.py:14 msgid "Special char not allowed" @@ -3281,21 +3125,19 @@ msgstr "システムメッセージ" #: notifications/notifications.py:46 msgid "Publish the station message" -msgstr "" +msgstr "投稿サイトニュース" #: ops/ansible/inventory.py:76 -#, fuzzy msgid "No account available" -msgstr "利用できないアカウント" +msgstr "利用可能なアカウントがありません" #: ops/ansible/inventory.py:180 -#, fuzzy msgid "Ansible disabled" -msgstr "ユーザーが無効になりました。" +msgstr "Ansible 無効" #: ops/ansible/inventory.py:196 msgid "Skip hosts below:" -msgstr "" +msgstr "次のホストをスキップします: " #: ops/api/celery.py:58 ops/api/celery.py:73 msgid "Waiting task start" @@ -3307,16 +3149,15 @@ msgstr "アプリ操作" #: ops/const.py:6 msgid "Push" -msgstr "" +msgstr "プッシュする" #: ops/const.py:7 -#, fuzzy msgid "Verify" -msgstr "確認済み" +msgstr "校验" #: ops/const.py:8 msgid "Collect" -msgstr "" +msgstr "収集" #: ops/const.py:19 msgid "Custom password" @@ -3332,13 +3173,11 @@ msgstr "すべての資産は異なるランダムパスワードを使用しま #: ops/const.py:33 msgid "Blank" -msgstr "" +msgstr "空欄" #: ops/const.py:34 -#, fuzzy -#| msgid "CAS" msgid "VCS" -msgstr "CAS" +msgstr "VCS" #: ops/const.py:38 msgid "Adhoc" @@ -3361,8 +3200,6 @@ msgid "Skip" msgstr "スキップ" #: ops/const.py:50 -#, fuzzy -#| msgid "PowerShell" msgid "Powershell" msgstr "PowerShell" @@ -3371,10 +3208,8 @@ msgid "Python" msgstr "" #: ops/const.py:57 -#, fuzzy -#| msgid "Test timeout" msgid "Timeout" -msgstr "テストタイムアウト" +msgstr "タイムアウト" #: ops/exception.py:6 msgid "no valid program entry found." @@ -3429,19 +3264,16 @@ msgid "AdHoc" msgstr "タスクの各バージョン" #: ops/models/base.py:19 -#, fuzzy msgid "Account policy" -msgstr "アカウントキー" +msgstr "アカウント ポリシー" #: ops/models/base.py:20 -#, fuzzy msgid "Last execution" -msgstr "コマンド実行" +msgstr "最後の実行" #: ops/models/base.py:22 ops/serializers/job.py:16 -#, fuzzy msgid "Date last run" -msgstr "最終同期日" +msgstr "最終実行日" #: ops/models/base.py:51 ops/models/job.py:102 #: xpack/plugins/cloud/models.py:170 @@ -3453,9 +3285,8 @@ msgid "Summary" msgstr "概要" #: ops/models/celery.py:16 -#, fuzzy msgid "Date last publish" -msgstr "終了日" +msgstr "発売日" #: ops/models/celery.py:47 msgid "Celery Task" @@ -3482,9 +3313,8 @@ msgid "Finished" msgstr "終了" #: ops/models/celery.py:62 -#, fuzzy msgid "Date published" -msgstr "終了日" +msgstr "発売日" #: ops/models/celery.py:86 msgid "Celery Task Execution" @@ -3492,7 +3322,7 @@ msgstr "Celery タスク実行" #: ops/models/job.py:29 msgid "Chdir" -msgstr "Chdir" +msgstr "実行ディレクトリ" #: ops/models/job.py:30 msgid "Timeout (Seconds)" @@ -3500,11 +3330,11 @@ msgstr "タイムアウト(秒)" #: ops/models/job.py:35 msgid "Runas" -msgstr "Runas" +msgstr "ユーザーとして実行" #: ops/models/job.py:37 msgid "Runas policy" -msgstr "Runas ポリシー" +msgstr "ユーザー ポリシー" #: ops/models/job.py:38 msgid "Use Parameter Define" @@ -3531,10 +3361,8 @@ msgid "Job audit log" msgstr "ジョブ監査ログ" #: ops/models/playbook.py:20 -#, fuzzy -#| msgid "Create" msgid "CreateMethod" -msgstr "作成" +msgstr "创建方式" #: ops/models/playbook.py:21 msgid "VCS URL" @@ -3569,24 +3397,20 @@ msgid "CPU load more than {max_threshold}: => {value}" msgstr "{max_threshold} を超えるCPUロード: => {value}" #: ops/serializers/job.py:14 -#, fuzzy msgid "Run after save" -msgstr "システムユーザーの実行" +msgstr "保存後に実行" #: ops/serializers/job.py:52 -#, fuzzy msgid "Job type" -msgstr "Docタイプ" +msgstr "タスクの種類" #: ops/serializers/job.py:55 terminal/serializers/session.py:53 msgid "Is finished" msgstr "終了しました" #: ops/serializers/job.py:56 -#, fuzzy -#| msgid "Test timeout" msgid "Time cost" -msgstr "テストタイムアウト" +msgstr "時を過ごす" #: ops/signal_handlers.py:74 terminal/models/applet/host.py:111 #: terminal/models/component/task.py:24 @@ -3594,14 +3418,12 @@ msgid "Task" msgstr "タスク" #: ops/tasks.py:27 -#, fuzzy msgid "Run ansible task" -msgstr "アセットの実行" +msgstr "Ansible タスクを実行する" #: ops/tasks.py:43 -#, fuzzy msgid "Run ansible task execution" -msgstr "インスタンスタスクの同期実行" +msgstr "Ansible タスクの実行を開始する" #: ops/tasks.py:57 msgid "Periodic clear celery tasks" @@ -3612,18 +3434,16 @@ msgid "Clean celery log period" msgstr "きれいなセロリログ期間" #: ops/tasks.py:76 -#, fuzzy msgid "Clear celery periodic tasks" -msgstr "きれいなセロリログ期間" +msgstr "タスクログを定期的にクリアする" #: ops/tasks.py:99 msgid "Create or update periodic tasks" msgstr "定期的なタスクの作成または更新" #: ops/tasks.py:107 -#, fuzzy msgid "Periodic check service performance" -msgstr "定期的なパフォーマンス" +msgstr "サービスのパフォーマンスを定期的に確認する" #: ops/templates/ops/celery_task_log.html:4 msgid "Task log" @@ -3696,9 +3516,8 @@ msgid "Org name" msgstr "組織名" #: orgs/models.py:70 rbac/models/role.py:36 terminal/models/applet/applet.py:30 -#, fuzzy msgid "Builtin" -msgstr "内蔵" +msgstr "ビルトイン" #: orgs/models.py:76 msgid "GLOBAL" @@ -3721,18 +3540,16 @@ msgid "Can view all joined org" msgstr "参加しているすべての組織を表示できます" #: orgs/tasks.py:9 -#, fuzzy msgid "Refresh organization cache" -msgstr "グローバル組織名" +msgstr "組織キャッシュを更新する" #: perms/apps.py:9 msgid "App permissions" msgstr "アプリの権限" #: perms/const.py:15 -#, fuzzy msgid "Copy" -msgstr "リンクのコピー" +msgstr "コピー" #: perms/const.py:16 msgid "Paste" @@ -3743,9 +3560,8 @@ msgid "Transfer" msgstr "転送" #: perms/const.py:27 -#, fuzzy msgid "Clipboard" -msgstr "クリップボードのコピー" +msgstr "クリップボード" #: perms/models/asset_permission.py:71 perms/serializers/permission.py:29 #: perms/serializers/permission.py:60 @@ -3783,13 +3599,12 @@ msgid "Can view usergroup assets" msgstr "ユーザーグループの資産を表示できます" #: perms/models/perm_node.py:136 -#, fuzzy msgid "Permed account" -msgstr "アカウントを集める" +msgstr "認定アカウント" #: perms/notifications.py:12 perms/notifications.py:44 msgid "today" -msgstr "今" +msgstr "今日" #: perms/notifications.py:15 msgid "You permed assets is about to expire" @@ -3813,16 +3628,12 @@ msgid "Is expired" msgstr "期限切れです" #: perms/tasks.py:28 -#, fuzzy -#| msgid "Asset permissions is about to expire" msgid "Check asset permission expired" -msgstr "資産権限の有効期限が近づいています" +msgstr "アセット認証ルールの有効期限が切れていることを確認する" #: perms/tasks.py:40 -#, fuzzy -#| msgid "asset permissions of organization {}" msgid "Send asset permission expired notification" -msgstr "組織 {} の資産権限" +msgstr "アセット許可の有効期限通知を送信する" #: perms/templates/perms/_msg_item_permissions_expire.html:7 #: perms/templates/perms/_msg_permed_items_expire.html:7 @@ -4353,15 +4164,12 @@ msgstr "" "グする方法、username, name,emailはjumpserverのユーザーが必要とする属性です" #: settings/serializers/auth/oidc.py:41 -#, fuzzy -#| msgid "Enable OTP" msgid "Enable PKCE" -msgstr "OTPの有効化" +msgstr "有効 PKCE" #: settings/serializers/auth/oidc.py:43 -#, fuzzy msgid "Code challenge method" -msgstr "接続タイムアウト" +msgstr "接続方法" #: settings/serializers/auth/oidc.py:51 msgid "Use Keycloak" @@ -4948,10 +4756,8 @@ msgstr "" "ます。" #: settings/serializers/security.py:116 -#, fuzzy -#| msgid "Verify code" msgid "Verify code TTL" -msgstr "コードの確認" +msgstr "認証コード有効時間" #: settings/serializers/security.py:121 msgid "Enable Login dynamic code" @@ -5435,10 +5241,8 @@ msgid "Offline video player" msgstr "オフラインビデオプレーヤー" #: terminal/api/applet/applet.py:48 terminal/api/applet/applet.py:51 -#, fuzzy -#| msgid "Invalid ip" msgid "Invalid zip file" -msgstr "無効なIP" +msgstr "zip ファイルが無効です" #: terminal/api/component/endpoint.py:31 msgid "Not found protocol query params" @@ -5526,9 +5330,8 @@ msgstr "リスクレベル" #: terminal/connect_methods.py:47 terminal/connect_methods.py:48 #: terminal/connect_methods.py:49 terminal/connect_methods.py:50 #: terminal/connect_methods.py:51 -#, fuzzy msgid "DB Client" -msgstr "クライアント" +msgstr "データベース クライアント" #: terminal/const.py:30 msgid "Critical" @@ -5549,7 +5352,7 @@ msgstr "オフライン" #: terminal/const.py:61 msgid "Mismatch" -msgstr "" +msgstr "一致しない" #: terminal/exceptions.py:8 msgid "Bulk create not support" @@ -5560,13 +5363,12 @@ msgid "Storage is invalid" msgstr "ストレージが無効です" #: terminal/models/applet/applet.py:27 -#, fuzzy msgid "Author" -msgstr "資産アカウント" +msgstr "著者" #: terminal/models/applet/applet.py:32 msgid "Tags" -msgstr "" +msgstr "ラベル" #: terminal/models/applet/applet.py:36 terminal/serializers/storage.py:157 msgid "Hosts" @@ -5574,36 +5376,32 @@ msgstr "ホスト" #: terminal/models/applet/applet.py:81 msgid "Applet pkg not valid, Missing file {}" -msgstr "" +msgstr "無効なアプレット パッケージ、ファイル {} がありません" #: terminal/models/applet/applet.py:144 terminal/models/applet/host.py:33 #: terminal/models/applet/host.py:105 -#, fuzzy msgid "Hosting" -msgstr "ホスト" +msgstr "ホスト マシン" #: terminal/models/applet/host.py:18 terminal/serializers/applet_host.py:43 -#, fuzzy msgid "Deploy options" -msgstr "その他のログインオプション" +msgstr "展開パラメーター" #: terminal/models/applet/host.py:19 msgid "Inited" -msgstr "" +msgstr "初期化された" #: terminal/models/applet/host.py:20 -#, fuzzy msgid "Date inited" -msgstr "終了日" +msgstr "" #: terminal/models/applet/host.py:21 -#, fuzzy msgid "Date synced" -msgstr "日付の同期" +msgstr "同期日" #: terminal/models/applet/host.py:106 msgid "Initial" -msgstr "" +msgstr "初期化" #: terminal/models/component/endpoint.py:15 msgid "HTTPS port" @@ -5622,26 +5420,20 @@ msgid "RDP port" msgstr "RDP ポート" #: terminal/models/component/endpoint.py:19 -#, fuzzy -#| msgid "SSH port" msgid "MySQL port" -msgstr "SSH ポート" +msgstr "MySQL ポート" #: terminal/models/component/endpoint.py:20 -#, fuzzy -#| msgid "RDP port" msgid "MariaDB port" -msgstr "RDP ポート" +msgstr "MariaDB ポート" #: terminal/models/component/endpoint.py:21 msgid "PostgreSQL port" -msgstr "" +msgstr "PostgreSQL ポート" #: terminal/models/component/endpoint.py:22 -#, fuzzy -#| msgid "Test port" msgid "Redis port" -msgstr "テストポート" +msgstr "Redis ポート" #: terminal/models/component/endpoint.py:29 #: terminal/models/component/endpoint.py:98 terminal/serializers/endpoint.py:64 @@ -5827,47 +5619,43 @@ msgstr "一括危険コマンド警告" #: terminal/serializers/applet.py:27 msgid "Icon" -msgstr "" +msgstr "アイコン" #: terminal/serializers/applet_host.py:24 -#, fuzzy msgid "Per Session" -msgstr "セッション" +msgstr "セッションごと" #: terminal/serializers/applet_host.py:25 msgid "Per Device" -msgstr "" +msgstr "デバイスごと" #: terminal/serializers/applet_host.py:32 -#, fuzzy -#| msgid "LDAP server" msgid "API Server" -msgstr "LDAPサーバー" +msgstr "API 仕える" #: terminal/serializers/applet_host.py:33 -#, fuzzy msgid "RDS Licensing" -msgstr "ライセンス" +msgstr "RDS ライセンス" #: terminal/serializers/applet_host.py:34 msgid "RDS License Server" -msgstr "" +msgstr "RDS ライセンス サーバー" #: terminal/serializers/applet_host.py:35 msgid "RDS Licensing Mode" -msgstr "" +msgstr "RDS 認可モード" #: terminal/serializers/applet_host.py:37 msgid "RDS Single Session Per User" -msgstr "" +msgstr "RDS シングル ユーザー シングル セッション" #: terminal/serializers/applet_host.py:38 msgid "RDS Max Disconnection Time" -msgstr "" +msgstr "最大切断時間" #: terminal/serializers/applet_host.py:39 msgid "RDS Remote App Logoff Time Limit" -msgstr "" +msgstr "RDS 远程应用注销时间限制" #: terminal/serializers/applet_host.py:45 terminal/serializers/terminal.py:41 msgid "Load status" @@ -5878,7 +5666,6 @@ msgid "Session ID" msgstr "セッションID" #: terminal/serializers/command.py:40 -#, fuzzy msgid "Account " msgstr "アカウント" @@ -6020,38 +5807,28 @@ msgid "Not found" msgstr "見つかりません" #: terminal/tasks.py:31 -#, fuzzy -#| msgid "Periodic clear celery tasks" msgid "Periodic delete terminal status" -msgstr "定期的にCeleryタスクをクリア" +msgstr "端末の状態を定期的にクリーンアップする" #: terminal/tasks.py:40 -#, fuzzy -#| msgid "Can share session" msgid "Clean orphan session" -msgstr "セッションを共有できます" +msgstr "孤立したセッションをクリアする" #: terminal/tasks.py:59 -#, fuzzy -#| msgid "Periodic clear celery tasks" msgid "Periodic clean expired session" -msgstr "定期的にCeleryタスクをクリア" +msgstr "期限切れのセッションを定期的にクリーンアップする" #: terminal/tasks.py:85 -#, fuzzy -#| msgid "Can upload session replay" msgid "Upload session replay to external storage" -msgstr "セッションのリプレイをアップロードできます" +msgstr "セッションの記録を外部ストレージにアップロードする" #: terminal/tasks.py:112 msgid "Run applet host deployment" -msgstr "" +msgstr "アプリケーション マシンの展開を実行する" #: terminal/tasks.py:119 -#, fuzzy -#| msgid "Install app" msgid "Install applet" -msgstr "アプリのインストール" +msgstr "アプリをインストールする" #: terminal/templates/terminal/_msg_command_alert.html:10 msgid "view" @@ -6219,9 +5996,8 @@ msgid "Select at least one asset or node" msgstr "少なくとも1つのアセットまたはノードを選択します。" #: tickets/models/ticket/apply_asset.py:17 -#, fuzzy msgid "Apply accounts" -msgstr "アプリケーションアカウント" +msgstr "アカウントを申請する" #: tickets/models/ticket/apply_asset.py:26 msgid "Apply Asset Ticket" @@ -6240,10 +6016,8 @@ msgid "Run command" msgstr "実行コマンド" #: tickets/models/ticket/command_confirm.py:19 -#, fuzzy -#| msgid "Command filter" msgid "Command filter acl" -msgstr "コマンドフィルター" +msgstr "コマンド フィルタ" #: tickets/models/ticket/general.py:76 msgid "Ticket step" @@ -6290,9 +6064,8 @@ msgid "Login asset" msgstr "ログイン資産" #: tickets/models/ticket/login_asset_confirm.py:17 -#, fuzzy msgid "Login account" -msgstr "ログインacl" +msgstr "ログインアカウント" #: tickets/models/ticket/login_confirm.py:12 msgid "Login datetime" @@ -6699,37 +6472,28 @@ msgid "name not unique" msgstr "名前が一意ではない" #: users/tasks.py:24 -#, fuzzy -#| msgid "Password expired" msgid "Check password expired" -msgstr "パスワード期限切れ" +msgstr "パスワードの有効期限が切れていることを確認する" #: users/tasks.py:38 -#, fuzzy -#| msgid "Password expired" msgid "Periodic check password expired" -msgstr "パスワード期限切れ" +msgstr "定期認証パスワードの有効期限" #: users/tasks.py:52 -#, fuzzy -#| msgid "Is expired" msgid "Check user expired" -msgstr "期限切れです" +msgstr "ユーザーの有効期限が切れていることを確認する" #: users/tasks.py:69 -#, fuzzy msgid "Periodic check user expired" -msgstr "定期的なパフォーマンス" +msgstr "ユーザーの有効期限の定期的な検出" #: users/tasks.py:83 msgid "Import ldap user" -msgstr "" +msgstr "LDAP ユーザーのインポート" #: users/tasks.py:104 -#, fuzzy -#| msgid "Periodic display" msgid "Periodic import ldap user" -msgstr "定期的な表示" +msgstr "LDAP ユーザーを定期的にインポートする" #: users/templates/users/_msg_account_expire_reminder.html:7 msgid "Your account will expire in" @@ -7559,688 +7323,3 @@ msgstr "究極のエディション" #: xpack/plugins/license/models.py:85 msgid "Community edition" msgstr "コミュニティ版" - -#~ msgid "Disk info" -#~ msgstr "ディスク情報" - -#~ msgid "Hostname raw" -#~ msgstr "ホスト名生" - -#~ msgid "Asset number" -#~ msgstr "資産番号" - -#, fuzzy -#~| msgid "Enabled" -#~ msgid "Enabled info" -#~ msgstr "有効化" - -#~ msgid "" -#~ "Jmservisor is the program used to pull up remote applications in Windows " -#~ "Remote Application publisher" -#~ msgstr "" -#~ "Jmservisorはwindowsリモートアプリケーションパブリケーションサーバでリモー" -#~ "トアプリケーションを引き出すためのプログラムです" - -#, fuzzy -#~ msgid "Protocols enabled" -#~ msgstr "プロトコル" - -#, fuzzy -#~| msgid "Is active" -#~ msgid "Is Activity" -#~ msgstr "アクティブです。" - -#, fuzzy -#~| msgid "Dynamic user" -#~ msgid "Dynamic username" -#~ msgstr "動的コード" - -#, fuzzy -#~| msgid "Permission named `{}` already exists" -#~ msgid "Username already exists" -#~ msgstr "'{}'という名前の権限は既に存在します" - -#, fuzzy -#~| msgid "Permission named `{}` already exists" -#~ msgid "Dynamic username already exists" -#~ msgstr "'{}'という名前の権限は既に存在します" - -#~ msgid "Commands" -#~ msgstr "コマンド#コマンド#" - -#, fuzzy -#~ msgid "Change password enabled" -#~ msgstr "パスワードの変更" - -#, fuzzy -#~ msgid "Change password method" -#~ msgstr "パスワードの変更" - -#~ msgid "" -#~ "The range of ports that Magnus listens on is modified in the " -#~ "configuration file" -#~ msgstr "Magnus がリッスンするポート範囲を構成ファイルで変更してください" - -#~ msgid "Magnus Listen port range" -#~ msgstr "Magnus がリッスンするポート範囲" - -#, fuzzy -#~ msgid "Published" -#~ msgstr "公開キー" - -#, fuzzy -#~ msgid "Unpublished" -#~ msgstr "終了" - -#, fuzzy -#~ msgid "Not match" -#~ msgstr "ユーザーにマッチしなかった" - -#~ msgid "Magnus listen db port" -#~ msgstr "Magnus がリッスンするデータベース ポート" - -#~ msgid "Update task content: {}" -#~ msgstr "タスク内容の更新: {}" - -#~ msgid "Material" -#~ msgstr "マテリアル" - -#~ msgid "Execute batch command" -#~ msgstr "バッチ実行コマンド" - -#, fuzzy -#~ msgid "Create account" -#~ msgstr "アカウントを集める" - -#~ msgid "Present" -#~ msgstr "プレゼント" - -#~ msgid "Date last login" -#~ msgstr "最終ログイン日" - -#~ msgid "IP last login" -#~ msgstr "IP最終ログイン" - -#~ msgid "GatherUser" -#~ msgstr "収集ユーザー" - -#~ msgid "Welcome back, please enter username and password to login" -#~ msgstr "" -#~ "おかえりなさい、ログインするためにユーザー名とパスワードを入力してください" - -#, fuzzy -#~ msgid "Run account" -#~ msgstr "アカウント" - -#~ msgid "Category display" -#~ msgstr "カテゴリ表示" - -#~ msgid "Built-in" -#~ msgstr "内蔵" - -#~ msgid "Scope display" -#~ msgstr "スコープ表示" - -#~ msgid "App change auth" -#~ msgstr "応用改密" - -#~ msgid "My apps" -#~ msgstr "マイアプリ" - -#~ msgid "Risk level display" -#~ msgstr "リスクレベル表示" - -#~ msgid "From cmd filter" -#~ msgstr "コマンドフィルタ規則から" - -#~ msgid "From cmd filter rule" -#~ msgstr "コマンドフィルタ規則から" - -#~ msgid "System roles display" -#~ msgstr "システムロール表示" - -#~ msgid "Org roles display" -#~ msgstr "組織ロール表示" - -#~ msgid "MFA level display" -#~ msgstr "MFAレベル表示" - -#~ msgid "Groups name" -#~ msgstr "グループ名" - -#~ msgid "Source name" -#~ msgstr "ソース名" - -#~ msgid "Organization role name" -#~ msgstr "組織の役割名" - -#~ msgid "Super role name" -#~ msgstr "スーパーロール名" - -#~ msgid "Total role name" -#~ msgstr "合計ロール名" - -#~ msgid "Is wecom bound" -#~ msgstr "企業の微信をバインドしているかどうか" - -#~ msgid "Is dingtalk bound" -#~ msgstr "ピンをバインドしているかどうか" - -#~ msgid "Is feishu bound" -#~ msgstr "飛本を縛ったかどうか" - -#~ msgid "System role name" -#~ msgstr "システムロール名" - -#~ msgid "Change auth plan" -#~ msgstr "密かな計画" - -#~ msgid "Application change auth plan" -#~ msgstr "改密計画の適用" - -#~ msgid "Application change auth plan execution" -#~ msgstr "改密計画実行の適用" - -#~ msgid "App" -#~ msgstr "適用" - -#~ msgid "Application change auth plan task" -#~ msgstr "改密計画タスクの適用" - -#~ msgid "Password cannot be set to blank, exit. " -#~ msgstr "パスワードを空白に設定することはできません。" - -#~ msgid "Asset change auth plan" -#~ msgstr "資産変更のオースプラン" - -#~ msgid "Asset change auth plan execution" -#~ msgstr "資産変更のオースプランの実行" - -#~ msgid "Change auth plan execution" -#~ msgstr "改密計画の実行" - -#~ msgid "Asset change auth plan task" -#~ msgstr "資産改密計画タスク" - -#~ msgid "This asset does not have a privileged user set: " -#~ msgstr "このアセットには特権ユーザーセットがありません。" - -#~ msgid "" -#~ "The password and key of the current asset privileged user cannot be " -#~ "changed: " -#~ msgstr "現在のアセット特権ユーザーのパスワードとキーは変更できません。" - -#~ msgid "Public key cannot be set to null, exit. " -#~ msgstr "公開鍵をnull、exitに設定することはできません。" - -#~ msgid "Change auth plan snapshot" -#~ msgstr "計画スナップショットの暗号化" - -#~ msgid "Preflight check" -#~ msgstr "プリフライトチェック" - -#~ msgid "Change auth" -#~ msgstr "秘密を改める" - -#~ msgid "Verify auth" -#~ msgstr "パスワード/キーの確認" - -#~ msgid "Keep auth" -#~ msgstr "パスワード/キーの保存" - -#~ msgid "Step" -#~ msgstr "ステップ" - -#~ msgid "Change Password" -#~ msgstr "パスワードの変更" - -#~ msgid "Change SSH Key" -#~ msgstr "SSHキーの変更" - -#~ msgid "Run times" -#~ msgstr "実行時間" - -#~ msgid "After many attempts to change the secret, it still failed" -#~ msgstr "秘密を変更しようとする多くの試みの後、それはまだ失敗しました" - -#~ msgid "Invalid/incorrect password" -#~ msgstr "パスワードが無効/間違っている" - -#~ msgid "Failed to connect to the host" -#~ msgstr "ホストへの接続に失敗しました" - -#~ msgid "Data could not be sent to remote" -#~ msgstr "データをリモートに送信できませんでした" - -#~ msgid "Gathered user" -#~ msgstr "収集されたユーザー" - -#~ msgid "Gather user task" -#~ msgstr "ユーザータスクの収集" - -#~ msgid "Assets is empty, please change nodes" -#~ msgstr "資産は空です。ノードを変更してください" - -#~ msgid "Executed times" -#~ msgstr "実行時間" - -#~ msgid "System User" -#~ msgstr "システムユーザー" - -#~ msgid "" -#~ "Format for comma-delimited string, with * indicating a match all. " -#~ "Protocol options: {}" -#~ msgstr "" -#~ "コンマ区切り文字列の形式。* はすべて一致することを示します。プロトコルオプ" -#~ "ション: {}" - -#~ msgid "Unsupported protocols: {}" -#~ msgstr "サポートされていないプロトコル: {}" - -#~ msgid "Remote app" -#~ msgstr "リモートアプリ" - -#~ msgid "Custom" -#~ msgstr "カスタム" - -#~ msgid "Can view application account secret" -#~ msgstr "アプリケーションアカウントの秘密を表示できます" - -#~ msgid "Can change application account secret" -#~ msgstr "アプリケーションアカウントの秘密を変更できます" - -#~ msgid "Application user" -#~ msgstr "アプリケーションユーザー" - -#~ msgid "Type display" -#~ msgstr "タイプ表示" - -#~ msgid "Application display" -#~ msgstr "アプリケーション表示" - -#~ msgid "Cluster" -#~ msgstr "クラスター" - -#~ msgid "CA certificate" -#~ msgstr "CA 証明書" - -#~ msgid "Client certificate file" -#~ msgstr "クライアント証明書" - -#~ msgid "Certificate key file" -#~ msgstr "証明書キー" - -#~ msgid "Application path" -#~ msgstr "アプリケーションパス" - -#~ msgid "Target URL" -#~ msgstr "ターゲットURL" - -#~ msgid "Chrome username" -#~ msgstr "Chromeユーザー名" - -#~ msgid "Chrome password" -#~ msgstr "Chromeパスワード" - -#~ msgid "Operating parameter" -#~ msgstr "操作パラメータ" - -#~ msgid "Target url" -#~ msgstr "ターゲットURL" - -#~ msgid "Mysql workbench username" -#~ msgstr "Mysql workbench のユーザー名" - -#~ msgid "Mysql workbench password" -#~ msgstr "Mysql workbench パスワード" - -#~ msgid "Vmware username" -#~ msgstr "Vmware ユーザー名" - -#~ msgid "Vmware password" -#~ msgstr "Vmware パスワード" - -#~ msgid "Base" -#~ msgstr "ベース" - -#~ msgid "Can test asset account connectivity" -#~ msgstr "アセットアカウントの接続性をテストできます" - -#~ msgid "Bandwidth" -#~ msgstr "帯域幅" - -#~ msgid "Contact" -#~ msgstr "連絡先" - -#~ msgid "Intranet" -#~ msgstr "イントラネット" - -#~ msgid "Extranet" -#~ msgstr "エクストラネット" - -#~ msgid "Operator" -#~ msgstr "オペレーター" - -#~ msgid "Default Cluster" -#~ msgstr "デフォルトクラスター" - -#~ msgid "User groups" -#~ msgstr "ユーザーグループ" - -#~ msgid "System user display" -#~ msgstr "システムユーザー表示" - -#~ msgid "Protocol format should {}/{}" -#~ msgstr "プロトコル形式は {}/{}" - -#~ msgid "Nodes name" -#~ msgstr "ノード名" - -#~ msgid "Labels name" -#~ msgstr "ラベル名" - -#~ msgid "Hardware info" -#~ msgstr "ハードウェア情報" - -#~ msgid "Admin user display" -#~ msgstr "管理者ユーザー表示" - -#~ msgid "CPU info" -#~ msgstr "CPU情報" - -#~ msgid "Action display" -#~ msgstr "アクション表示" - -#~ msgid "Applications amount" -#~ msgstr "申し込み金額" - -#~ msgid "Gateways count" -#~ msgstr "ゲートウェイ数" - -#~ msgid "SSH key fingerprint" -#~ msgstr "SSHキー指紋" - -#~ msgid "Apps amount" -#~ msgstr "アプリの量" - -#~ msgid "Login mode display" -#~ msgstr "ログインモード表示" - -#~ msgid "Ad domain" -#~ msgstr "広告ドメイン" - -#~ msgid "Is asset protocol" -#~ msgstr "資産プロトコルです" - -#~ msgid "Only ssh and automatic login system users are supported" -#~ msgstr "sshと自動ログインシステムのユーザーのみがサポートされています" - -#~ msgid "Username same with user with protocol {} only allow 1" -#~ msgstr "プロトコル {} のユーザーと同じユーザー名は1のみ許可します" - -#~ msgid "* Automatic login mode must fill in the username." -#~ msgstr "* 自動ログインモードはユーザー名を入力する必要があります。" - -#~ msgid "Path should starts with /" -#~ msgstr "パスは/で始まる必要があります" - -#~ msgid "Password or private key required" -#~ msgstr "パスワードまたは秘密鍵が必要" - -#~ msgid "Only ssh protocol system users are allowed" -#~ msgstr "Sshプロトコルシステムユーザーのみが許可されています" - -#~ msgid "The protocol must be consistent with the current user: {}" -#~ msgstr "プロトコルは現在のユーザーと一致している必要があります: {}" - -#~ msgid "Only system users with automatic login are allowed" -#~ msgstr "自動ログインを持つシステムユーザーのみが許可されます" - -#~ msgid "The asset {} system platform {} does not support run Ansible tasks" -#~ msgstr "" -#~ "資産 {} システムプラットフォーム {} はAnsibleタスクの実行をサポートしてい" -#~ "ません。" - -#~ msgid "Test assets connectivity: " -#~ msgstr "資産の接続性のテスト:" - -#~ msgid "Unreachable" -#~ msgstr "達成できない" - -#~ msgid "Reachable" -#~ msgstr "接続可能" - -#~ msgid "Get asset info failed: {}" -#~ msgstr "資産情報の取得に失敗しました: {}" - -#~ msgid "Update asset hardware info: " -#~ msgstr "資産ハードウェア情報の更新:" - -#~ msgid "System user is dynamic: {}" -#~ msgstr "システムユーザーは動的です: {}" - -#~ msgid "Start push system user for platform: [{}]" -#~ msgstr "プラットフォームのプッシュシステムユーザーを開始: [{}]" - -#~ msgid "Hosts count: {}" -#~ msgstr "ホスト数: {}" - -#~ msgid "Push system users to asset: " -#~ msgstr "システムユーザーをアセットにプッシュする:" - -#~ msgid "Dynamic system user not support test" -#~ msgstr "動的システムユーザーがテストをサポートしていない" - -#~ msgid "Start test system user connectivity for platform: [{}]" -#~ msgstr "プラットフォームのテストシステムのユーザー接続を開始: [{}]" - -#~ msgid "Test system user connectivity: " -#~ msgstr "テストシステムユーザー接続:" - -#~ msgid "Test system user connectivity period: " -#~ msgstr "テストシステムユーザー接続期间:" - -#~ msgid "Operate display" -#~ msgstr "ディスプレイを操作する" - -#~ msgid "Status display" -#~ msgstr "ステータス表示" - -#~ msgid "MFA display" -#~ msgstr "MFAディスプレイ" - -#~ msgid "Hosts display" -#~ msgstr "ホスト表示" - -#~ msgid "Run as" -#~ msgstr "として実行" - -#~ msgid "Run as display" -#~ msgstr "ディスプレイとして実行する" - -#~ msgid "User not exists" -#~ msgstr "ユーザーは存在しません" - -#~ msgid "System user not exists" -#~ msgstr "システムユーザーが存在しません" - -#~ msgid "Asset not exists" -#~ msgstr "アセットが存在しません" - -#~ msgid "User has no permission to access asset or permission expired" -#~ msgstr "" -#~ "ユーザーがアセットにアクセスする権限を持っていないか、権限の有効期限が切れ" -#~ "ています" - -#~ msgid "User has no permission to access application or permission expired" -#~ msgstr "" -#~ "ユーザーがアプリにアクセスする権限を持っていないか、権限の有効期限が切れて" -#~ "います" - -#~ msgid "Asset or application required" -#~ msgstr "アセットまたはアプリが必要" - -#~ msgid "Not has host {} permission" -#~ msgstr "ホスト {} 権限がありません" - -#~ msgid "" -#~ "eg: Every Sunday 03:05 run <5 3 * * 0>
Tips: Using 5 digits linux " -#~ "crontab expressions (Online tools)
Note: If both Regularly " -#~ "perform and Cycle perform are set, give priority to Regularly perform" -#~ msgstr "" -#~ "eg:毎週日03:05<5 3**0>
ヒント:5ビットLinux crontab式<分時日月曜日>(オンラインワーク)
" -#~ "注意:定期実行と周期実行を同時に設定した場合は、定期実行を優先します。" - -#~ msgid "Unit: hour" -#~ msgstr "単位: 時間" - -#~ msgid "Callback" -#~ msgstr "コールバック" - -#~ msgid "Tasks" -#~ msgstr "タスク" - -#~ msgid "Run as admin" -#~ msgstr "再実行" - -#~ msgid "Become" -#~ msgstr "になる" - -#~ msgid "Create by" -#~ msgstr "による作成" - -#~ msgid "Task display" -#~ msgstr "タスク表示" - -#~ msgid "Host amount" -#~ msgstr "ホスト量" - -#~ msgid "Start time" -#~ msgstr "開始時間" - -#~ msgid "End time" -#~ msgstr "終了時間" - -#~ msgid "Adhoc raw result" -#~ msgstr "アドホック生の結果" - -#~ msgid "Adhoc result summary" -#~ msgstr "アドホック結果の概要" - -#~ msgid "Task start" -#~ msgstr "タスクの開始" - -#~ msgid "Command `{}` is forbidden ........" -#~ msgstr "コマンド '{}' は禁止されています ........" - -#~ msgid "Clean task history period" -#~ msgstr "クリーンなタスク履歴期間" - -#~ msgid "The administrator is modifyidng permissions. Please wait" -#~ msgstr "管理者は権限を変更しています。お待ちください" - -#~ msgid "The authorization cannot be revoked for the time being" -#~ msgstr "当分の間、承認を取り消すことはできません。" - -#~ msgid "Application permission" -#~ msgstr "申請許可" - -#~ msgid "Permed application" -#~ msgstr "許可されたアプリケーション" - -#~ msgid "Can view my apps" -#~ msgstr "自分のアプリを表示できます" - -#~ msgid "Can view user apps" -#~ msgstr "ユーザーアプリを表示できます" - -#~ msgid "Can view usergroup apps" -#~ msgstr "ユーザー・グループ認可の適用を表示できます" - -#~ msgid "Upload file" -#~ msgstr "ファイルのアップロード" - -#~ msgid "Download file" -#~ msgstr "ファイルのダウンロード" - -#~ msgid "Upload download" -#~ msgstr "ダウンロードのアップロード" - -#~ msgid "Clipboard paste" -#~ msgstr "クリップボードペースト" - -#~ msgid "Clipboard copy paste" -#~ msgstr "クリップボードコピーペースト" - -#~ msgid "Your permed applications is about to expire" -#~ msgstr "パーマアプリケーションの有効期限が近づいています" - -#~ msgid "permed applications" -#~ msgstr "Permedアプリケーション" - -#~ msgid "Application permissions is about to expire" -#~ msgstr "アプリケーション権限の有効期限が近づいています" - -#~ msgid "application permissions of organization {}" -#~ msgstr "Organization {} のアプリケーション権限" - -#~ msgid "User groups amount" -#~ msgstr "ユーザーグループの量" - -#~ msgid "System users amount" -#~ msgstr "システムユーザー数" - -#~ msgid "" -#~ "The application list contains applications that are different from the " -#~ "permission type. ({})" -#~ msgstr "" -#~ "アプリケーションリストには、権限タイプとは異なるアプリケーションが含まれて" -#~ "います。({})" - -#~ msgid "Users display" -#~ msgstr "ユーザー表示" - -#~ msgid "User groups display" -#~ msgstr "ユーザーグループの表示" - -#~ msgid "Assets display" -#~ msgstr "資産表示" - -#~ msgid "Nodes display" -#~ msgstr "ノード表示" - -#~ msgid "System users display" -#~ msgstr "システムユーザーの表示" - -#~ msgid "My applications" -#~ msgstr "私のアプリケーション" - -#~ msgid "Empty" -#~ msgstr "空" - -#~ msgid "System user ID" -#~ msgstr "システムユーザーID" - -#~ msgid "Apply for application" -#~ msgstr "申し込み" - -#~ msgid "" -#~ "Created by the ticket, ticket title: {}, ticket applicant: {}, ticket " -#~ "processor: {}, ticket ID: {}" -#~ msgstr "" -#~ "チケットによって作成されたチケットタイトル: {}、チケット申請者: {}、チケッ" -#~ "ト処理者: {}、チケットID: {}" - -#~ msgid "Applied login IP" -#~ msgstr "応用ログインIP" - -#~ msgid "Applied login city" -#~ msgstr "応用ログイン都市" - -#~ msgid "Applied login datetime" -#~ msgstr "適用されたログインの日付時間" - -#~ msgid "Login system user" -#~ msgstr "ログインシステムユーザー" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index 155cf328b..08386beda 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5f46cbb3f66e7bb47e3a5830bad87c62d743fd3205373cb3b2b55ad3045633d7 -size 111689 +oid sha256:1d3093d239e72a1ab35464fcdebd157330dbde7ae1cfd0f89a7d75c52eade900 +size 111883 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 8a4bb7d36..e84e4b3ec 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-02-04 20:29+0800\n" +"POT-Creation-Date: 2023-02-06 13:10+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -95,7 +95,7 @@ msgstr "指定" #: accounts/const/automation.py:45 msgid "Random" -msgstr "" +msgstr "随机" #: accounts/const/automation.py:49 ops/const.py:13 msgid "Append SSH KEY" @@ -131,7 +131,7 @@ msgstr "授权变更时添加节点" #: accounts/const/automation.py:67 msgid "On perm add account" -msgstr "授权的账号" +msgstr "授权变更时添加账号" #: accounts/const/automation.py:69 msgid "On asset join node" @@ -151,11 +151,11 @@ msgstr "继承自用户组或资产节点" #: accounts/const/automation.py:94 msgid "Create and push" -msgstr "创建并推送到资产" +msgstr "创建并推送" #: accounts/const/automation.py:95 msgid "Only create" -msgstr "仅创建到资产" +msgstr "仅创建" #: accounts/models/account.py:47 accounts/serializers/account/account.py:81 #: accounts/serializers/automations/change_secret.py:107 @@ -220,11 +220,11 @@ msgstr "账号模版" #: accounts/models/account.py:109 msgid "Can view asset account template secret" -msgstr "可以查看资产账号密码" +msgstr "可以查看资产账号模版密码" #: accounts/models/account.py:110 msgid "Can change asset account template secret" -msgstr "可以更改账号模版密码" +msgstr "可以更改资产账号模版密码" #: accounts/models/automations/backup_account.py:25 #: accounts/models/automations/change_secret.py:47 @@ -312,11 +312,11 @@ msgstr "创建收集账号执行" #: accounts/models/automations/base.py:34 msgid "Can view push account execution" -msgstr "可以查看推送账号执行" +msgstr "查看推送账号执行" #: accounts/models/automations/base.py:35 msgid "Can add push account execution" -msgstr "可以创建推送账号执行" +msgstr "创建推送账号执行" #: accounts/models/automations/change_secret.py:17 accounts/models/base.py:36 #: accounts/serializers/account/account.py:118 @@ -421,7 +421,7 @@ msgstr "账号验证" #: assets/models/group.py:20 assets/models/label.py:18 #: assets/models/platform.py:20 assets/models/platform.py:74 #: assets/serializers/asset/common.py:61 assets/serializers/asset/common.py:129 -#: assets/serializers/platform.py:137 +#: assets/serializers/platform.py:126 #: authentication/serializers/connect_token_secret.py:103 ops/mixin.py:20 #: ops/models/adhoc.py:22 ops/models/celery.py:15 ops/models/celery.py:57 #: ops/models/job.py:24 ops/models/playbook.py:15 orgs/models.py:69 @@ -554,13 +554,13 @@ msgstr "节点" #: assets/models/automations/base.py:109 #: assets/serializers/automations/base.py:39 msgid "Automation snapshot" -msgstr "工单快照" +msgstr "自动化快照" #: accounts/serializers/automations/base.py:43 acls/models/command_acl.py:24 #: acls/serializers/command_acl.py:18 applications/models.py:14 #: assets/models/_user.py:50 assets/models/automations/base.py:20 #: assets/models/cmd_filter.py:74 assets/models/platform.py:76 -#: assets/serializers/asset/common.py:109 assets/serializers/platform.py:98 +#: assets/serializers/asset/common.py:109 assets/serializers/platform.py:87 #: audits/serializers.py:48 #: authentication/serializers/connect_token_secret.py:116 ops/models/job.py:32 #: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:28 @@ -847,8 +847,8 @@ msgstr "应用管理" #: applications/models.py:11 assets/models/label.py:21 #: assets/models/platform.py:75 assets/serializers/asset/common.py:108 -#: assets/serializers/cagegory.py:8 assets/serializers/platform.py:99 -#: assets/serializers/platform.py:138 perms/serializers/user_permission.py:25 +#: assets/serializers/cagegory.py:8 assets/serializers/platform.py:88 +#: assets/serializers/platform.py:127 perms/serializers/user_permission.py:25 #: settings/models.py:35 tickets/models/ticket/apply_application.py:13 msgid "Category" msgstr "类别" @@ -939,7 +939,7 @@ msgstr "成功" #: assets/const/automation.py:12 msgid "Ping" -msgstr "" +msgstr "测试" #: assets/const/automation.py:13 msgid "Ping gateway" @@ -1189,7 +1189,7 @@ msgstr "基本" #: assets/models/asset/web.py:11 assets/models/asset/web.py:17 #: assets/serializers/asset/common.py:104 msgid "Script" -msgstr "" +msgstr "脚本" #: assets/models/asset/web.py:13 assets/serializers/platform.py:28 msgid "Autofill" @@ -1372,41 +1372,41 @@ msgstr "Ansible 配置" msgid "Ping enabled" msgstr "启用资产探活" -#: assets/models/platform.py:44 assets/serializers/platform.py:57 +#: assets/models/platform.py:44 assets/serializers/platform.py:56 msgid "Ping method" msgstr "资产探活方式" #: assets/models/platform.py:45 assets/models/platform.py:58 -#: assets/serializers/platform.py:59 +#: assets/serializers/platform.py:57 msgid "Gather facts enabled" -msgstr "收集资产信息" +msgstr "启用收集资产信息" #: assets/models/platform.py:46 assets/models/platform.py:60 -#: assets/serializers/platform.py:61 +#: assets/serializers/platform.py:58 msgid "Gather facts method" msgstr "收集信息方式" -#: assets/models/platform.py:47 assets/serializers/platform.py:67 +#: assets/models/platform.py:47 assets/serializers/platform.py:61 msgid "Change secret enabled" msgstr "启用改密" -#: assets/models/platform.py:49 assets/serializers/platform.py:69 +#: assets/models/platform.py:49 assets/serializers/platform.py:62 msgid "Change secret method" msgstr "改密方式" -#: assets/models/platform.py:51 assets/serializers/platform.py:71 +#: assets/models/platform.py:51 assets/serializers/platform.py:63 msgid "Push account enabled" msgstr "启用账号推送" -#: assets/models/platform.py:53 assets/serializers/platform.py:73 +#: assets/models/platform.py:53 assets/serializers/platform.py:64 msgid "Push account method" msgstr "账号推送方式" -#: assets/models/platform.py:55 assets/serializers/platform.py:63 +#: assets/models/platform.py:55 assets/serializers/platform.py:59 msgid "Verify account enabled" msgstr "开启账号验证" -#: assets/models/platform.py:57 assets/serializers/platform.py:65 +#: assets/models/platform.py:57 assets/serializers/platform.py:60 msgid "Verify account method" msgstr "账号验证方式" @@ -1418,23 +1418,23 @@ msgstr "元数据" msgid "Internal" msgstr "内置" -#: assets/models/platform.py:82 assets/serializers/platform.py:96 +#: assets/models/platform.py:82 assets/serializers/platform.py:85 msgid "Charset" msgstr "编码" -#: assets/models/platform.py:84 assets/serializers/platform.py:123 +#: assets/models/platform.py:84 assets/serializers/platform.py:112 msgid "Domain enabled" msgstr "启用网域" -#: assets/models/platform.py:86 assets/serializers/platform.py:122 +#: assets/models/platform.py:86 assets/serializers/platform.py:111 msgid "Su enabled" msgstr "启用账号切换" -#: assets/models/platform.py:87 assets/serializers/platform.py:106 +#: assets/models/platform.py:87 assets/serializers/platform.py:95 msgid "Su method" msgstr "账号切换方式" -#: assets/models/platform.py:89 assets/serializers/platform.py:103 +#: assets/models/platform.py:89 assets/serializers/platform.py:92 msgid "Automation" msgstr "自动化" @@ -1447,7 +1447,7 @@ msgstr "%(value)s is not an even number" msgid "Auto fill" msgstr "自动代填" -#: assets/serializers/asset/common.py:111 assets/serializers/platform.py:101 +#: assets/serializers/asset/common.py:111 assets/serializers/platform.py:90 #: authentication/serializers/connect_token_secret.py:28 #: authentication/serializers/connect_token_secret.py:66 #: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:107 @@ -1536,7 +1536,7 @@ msgstr "系统架构" #: assets/serializers/cagegory.py:9 msgid "Constraints" -msgstr "" +msgstr "约束" #: assets/serializers/cagegory.py:15 msgid "Types" @@ -1568,21 +1568,21 @@ msgstr "SFTP 已启用" #: assets/serializers/platform.py:25 msgid "SFTP home" -msgstr "SFTP根路径" +msgstr "SFTP 根路径" -#: assets/serializers/platform.py:75 +#: assets/serializers/platform.py:65 msgid "Gather accounts enabled" msgstr "启用账号收集" -#: assets/serializers/platform.py:77 +#: assets/serializers/platform.py:66 msgid "Gather accounts method" msgstr "收集账号方式" -#: assets/serializers/platform.py:83 +#: assets/serializers/platform.py:72 msgid "Primary" msgstr "主要的" -#: assets/serializers/platform.py:124 +#: assets/serializers/platform.py:113 msgid "Default Domain" msgstr "默认网域" @@ -2315,7 +2315,7 @@ msgstr "可以查看连接令牌密文" #: authentication/models/connection_token.py:100 msgid "Connection token inactive" -msgstr "连接令牌不活跃" +msgstr "连接令牌未激活" #: authentication/models/connection_token.py:103 msgid "Connection token expired at: {}" @@ -2409,7 +2409,7 @@ msgstr "账号是否有效" #: authentication/tasks.py:12 msgid "Clean expired session" -msgstr "可以过期会话" +msgstr "清除过期会话" #: authentication/templates/authentication/_access_key_modal.html:6 msgid "API key list" @@ -2966,7 +2966,7 @@ msgstr "文件" #: common/serializers/fields.py:101 #, python-brace-format msgid "Invalid pk \"{pk_value}\" - object does not exist." -msgstr "错误的 id \"{pk_value}\" - 对象不存在" +msgstr "错误的 pk \"{pk_value}\" - 对象不存在" #: common/serializers/fields.py:102 #, python-brace-format @@ -2991,7 +2991,7 @@ msgstr "发送邮件附件" #: common/utils/ip/geoip/utils.py:26 msgid "Invalid ip" -msgstr "无效IP" +msgstr "无效 IP" #: common/utils/ip/utils.py:78 msgid "Invalid address" @@ -5571,7 +5571,7 @@ msgstr "RDS 授权模式" #: terminal/serializers/applet_host.py:37 msgid "RDS Single Session Per User" -msgstr "RDS 一个用户一个会话" +msgstr "RDS 单用户单会话" #: terminal/serializers/applet_host.py:38 msgid "RDS Max Disconnection Time" From 654cbe7bd0911db36c63141553ce07d390db22d2 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 6 Feb 2023 14:54:30 +0800 Subject: [PATCH 86/92] =?UTF-8?q?perf:=20=E5=88=9B=E5=BB=BA=E7=BD=91?= =?UTF-8?q?=E5=85=B3=20=E6=B2=A1=E6=9C=89=E5=85=B3=E8=81=94=E7=BD=91?= =?UTF-8?q?=E5=9F=9F=20(#9441)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: feng <1304903146@qq.com> --- apps/assets/const/host.py | 2 +- apps/assets/serializers/domain.py | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/assets/const/host.py b/apps/assets/const/host.py index 97233e284..0a5ff60da 100644 --- a/apps/assets/const/host.py +++ b/apps/assets/const/host.py @@ -71,7 +71,7 @@ class HostTypes(BaseType): {'name': 'Linux'}, { 'name': GATEWAY_NAME, - 'domain_enabled': False, + 'domain_enabled': True, } ], cls.UNIX: [ diff --git a/apps/assets/serializers/domain.py b/apps/assets/serializers/domain.py index 33dcffbe1..74eb1117a 100644 --- a/apps/assets/serializers/domain.py +++ b/apps/assets/serializers/domain.py @@ -34,6 +34,13 @@ class DomainSerializer(BulkOrgResourceModelSerializer): data['assets'] = [i for i in assets if str(i['id']) not in gateway_ids] return data + def update(self, instance, validated_data): + assets = validated_data.pop('assets', []) + assets = assets + list(instance.gateways) + validated_data['assets'] = assets + instance = super().update(instance, validated_data) + return instance + class DomainWithGatewaySerializer(serializers.ModelSerializer): gateways = GatewayWithAccountSecretSerializer(many=True, read_only=True) From 8afe28773d8dede9d359521cd06e1e3f4eab167b Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 6 Feb 2023 15:05:38 +0800 Subject: [PATCH 87/92] perf: clone plateform charset (#9442) Co-authored-by: feng <1304903146@qq.com> --- apps/assets/models/platform.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/assets/models/platform.py b/apps/assets/models/platform.py index 1bb560e7e..1133969b8 100644 --- a/apps/assets/models/platform.py +++ b/apps/assets/models/platform.py @@ -68,7 +68,7 @@ class Platform(models.Model): """ class CharsetChoices(models.TextChoices): - utf8 = 'utf8', 'UTF-8' + utf8 = 'utf-8', 'UTF-8' gbk = 'gbk', 'GBK' name = models.SlugField(verbose_name=_("Name"), unique=True, allow_unicode=True) From 462dc2543bb89b12aa42d0566f7b8ed1274799e4 Mon Sep 17 00:00:00 2001 From: Aaron3S Date: Mon, 6 Feb 2023 16:19:43 +0800 Subject: [PATCH 88/92] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E5=91=BD=E4=BB=A4=E4=BD=9C=E4=B8=9A=E6=8C=87=E5=AE=9A?= =?UTF-8?q?=E5=BD=93=E5=89=8D=E8=B7=AF=E5=BE=84=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/models/job.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/ops/models/job.py b/apps/ops/models/job.py index f19e63b9d..c8c16718b 100644 --- a/apps/ops/models/job.py +++ b/apps/ops/models/job.py @@ -176,9 +176,7 @@ class JobExecution(JMSOrgBaseModel): shell = self.current_job.args if self.current_job.chdir: - if module == self.current_job.module: - shell += " path={}".format(self.current_job.chdir) - else: + if module == "shell": shell += " chdir={}".format(self.current_job.chdir) if self.current_job.module in ['python']: shell += " executable={}".format(self.current_job.module) From 7dae491691221cf4c5abf5214b8e1342c1bbb563 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 6 Feb 2023 17:02:27 +0800 Subject: [PATCH 89/92] perf: account asset category (#9444) Co-authored-by: feng <1304903146@qq.com> --- apps/accounts/serializers/account/account.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/accounts/serializers/account/account.py b/apps/accounts/serializers/account/account.py index 579da474d..afcf5af37 100644 --- a/apps/accounts/serializers/account/account.py +++ b/apps/accounts/serializers/account/account.py @@ -60,10 +60,11 @@ class AccountSerializerCreateMixin( class AccountAssetSerializer(serializers.ModelSerializer): platform = ObjectRelatedField(read_only=True) + category = serializers.CharField(source='platform.category', read_only=True) class Meta: model = Asset - fields = ['id', 'name', 'address', 'platform'] + fields = ['id', 'name', 'address', 'category', 'platform'] def to_internal_value(self, data): if isinstance(data, dict): From c7ce53563054b71af3358b7cbe9cbaae575ae47c Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 6 Feb 2023 18:30:17 +0800 Subject: [PATCH 90/92] perf: account seri type category (#9445) Co-authored-by: feng <1304903146@qq.com> --- apps/accounts/automations/gather_accounts/manager.py | 2 +- apps/accounts/serializers/account/account.py | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/accounts/automations/gather_accounts/manager.py b/apps/accounts/automations/gather_accounts/manager.py index efbe1a965..de6db61af 100644 --- a/apps/accounts/automations/gather_accounts/manager.py +++ b/apps/accounts/automations/gather_accounts/manager.py @@ -53,7 +53,7 @@ class GatherAccountsManager(AccountBasePlaybookManager): info = result.get('debug', {}).get('res', {}).get('info', {}) asset = self.host_asset_mapper.get(host) if asset and info: - result = self.filter_success_result(host, info) + result = self.filter_success_result(asset.type, info) self.bulk_create_accounts(asset, result) else: logger.error("Not found info".format(host)) diff --git a/apps/accounts/serializers/account/account.py b/apps/accounts/serializers/account/account.py index afcf5af37..454708265 100644 --- a/apps/accounts/serializers/account/account.py +++ b/apps/accounts/serializers/account/account.py @@ -5,6 +5,7 @@ from assets.models import Asset from accounts.const import SecretType, Source from accounts.models import Account, AccountTemplate from accounts.tasks import push_accounts_to_assets +from assets.const import Category, AllTypes from common.serializers.fields import ObjectRelatedField, LabeledChoiceField from common.serializers import SecretReadableMixin, BulkModelSerializer from .base import BaseAccountSerializer @@ -60,11 +61,12 @@ class AccountSerializerCreateMixin( class AccountAssetSerializer(serializers.ModelSerializer): platform = ObjectRelatedField(read_only=True) - category = serializers.CharField(source='platform.category', read_only=True) + category = LabeledChoiceField(choices=Category.choices, read_only=True, label=_('Category')) + type = LabeledChoiceField(choices=AllTypes.choices(), read_only=True, label=_('Type')) class Meta: model = Asset - fields = ['id', 'name', 'address', 'category', 'platform'] + fields = ['id', 'name', 'address', 'type', 'category', 'platform'] def to_internal_value(self, data): if isinstance(data, dict): From 0deb093e7aa9a332f02392358b498eb962f61996 Mon Sep 17 00:00:00 2001 From: Bai Date: Mon, 6 Feb 2023 19:28:56 +0800 Subject: [PATCH 91/92] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E5=B7=A5?= =?UTF-8?q?=E5=8D=95close=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/tickets/api/ticket.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/tickets/api/ticket.py b/apps/tickets/api/ticket.py index 19bffa952..4927527ce 100644 --- a/apps/tickets/api/ticket.py +++ b/apps/tickets/api/ticket.py @@ -86,7 +86,7 @@ class TicketViewSet(CommonApiMixin, viewsets.ModelViewSet): instance.reject(processor=request.user) return Response('ok') - @action(detail=True, methods=[PUT], permission_classes=[IsAssignee, ]) + @action(detail=True, methods=[PUT], permission_classes=[IsAssignee | IsApplicant, ]) def close(self, request, *args, **kwargs): instance = self.get_object() instance.close() From 1dd915cefd4f619fd6172dcfbf3f5a46dea3c134 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Mon, 6 Feb 2023 19:45:08 +0800 Subject: [PATCH 92/92] perf: win shell (#9448) Co-authored-by: feng <1304903146@qq.com> --- .../accounts/automations/gather_accounts/host/windows/main.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/accounts/automations/gather_accounts/host/windows/main.yml b/apps/accounts/automations/gather_accounts/host/windows/main.yml index 97326431d..d117e6a2e 100644 --- a/apps/accounts/automations/gather_accounts/host/windows/main.yml +++ b/apps/accounts/automations/gather_accounts/host/windows/main.yml @@ -2,8 +2,7 @@ gather_facts: no tasks: - name: Gather posix account - ansible.builtin.win_shell: - cmd: net user + ansible.builtin.win_shell: net user register: result - name: Define info by set_fact