From d9a11900a938e90ab9fd1ab8b9a74c0ef3aa2e55 Mon Sep 17 00:00:00 2001 From: Aaron3S Date: Wed, 22 Feb 2023 15:35:59 +0800 Subject: [PATCH 01/15] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=BD=9C?= =?UTF-8?q?=E4=B8=9A=E4=B8=AD=E5=BF=83=E8=B5=84=E4=BA=A7=E5=92=8C=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E6=B2=A1=E6=9C=89=E8=BF=87=E6=BB=A4=E6=8E=88=E6=9D=83?= =?UTF-8?q?=E8=A7=84=E5=88=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/ops/ansible/inventory.py | 5 ++- apps/ops/models/job.py | 69 ++++++++++++++++++++++++++++++++++- apps/ops/serializers/job.py | 10 ++++- 3 files changed, 80 insertions(+), 4 deletions(-) diff --git a/apps/ops/ansible/inventory.py b/apps/ops/ansible/inventory.py index de273cfd7..ba3be6bde 100644 --- a/apps/ops/ansible/inventory.py +++ b/apps/ops/ansible/inventory.py @@ -139,8 +139,11 @@ class JMSInventory: self.make_ssh_account_vars(host, asset, account, automation, protocols, platform, gateway) return host + def get_asset_accounts(self, asset): + return list(asset.accounts.filter(is_active=True)) + def select_account(self, asset): - accounts = list(asset.accounts.filter(is_active=True)) + accounts = self.get_asset_accounts(asset) if not accounts: return None account_selected = None diff --git a/apps/ops/models/job.py b/apps/ops/models/job.py index d17dcd442..911ca2c97 100644 --- a/apps/ops/models/job.py +++ b/apps/ops/models/job.py @@ -2,26 +2,91 @@ import json import logging import os import uuid +from collections import defaultdict from celery import current_task from django.conf import settings from django.db import models +from django.db.models import Q from django.utils import timezone from django.utils.translation import gettext_lazy as _ -__all__ = ["Job", "JobExecution"] +__all__ = ["Job", "JobExecution", "JMSPermedInventory"] from simple_history.models import HistoricalRecords +from accounts.models import Account from acls.models import CommandFilterACL +from assets.models import Asset from ops.ansible import JMSInventory, AdHocRunner, PlaybookRunner from ops.mixin import PeriodTaskModelMixin from ops.variables import * from ops.const import Types, Modules, RunasPolicies, JobStatus from orgs.mixins.models import JMSOrgBaseModel +from perms.models import AssetPermission +from perms.utils import UserPermAssetUtil from terminal.notifications import CommandExecutionAlert +def get_parent_keys(key, include_self=True): + keys = [] + split_keys = key.split(':') + for i in range(len(split_keys)): + keys.append(':'.join(split_keys[:i + 1])) + if not include_self: + keys.pop() + return keys + + +class JMSPermedInventory(JMSInventory): + def __init__(self, assets, account_policy='privileged_first', + account_prefer='root,Administrator', host_callback=None, exclude_localhost=False, user=None): + super().__init__(assets, account_policy, account_prefer, host_callback, exclude_localhost) + self.user = user + self.assets_accounts_mapper = self.get_assets_accounts_mapper() + + def get_asset_accounts(self, asset): + return self.assets_accounts_mapper.get(asset.id, []) + + def get_permed_assets(self): + permed_assets = UserPermAssetUtil(self.user).get_all_assets() + return set(self.assets) & (set(permed_assets)) + + def get_assets_accounts_mapper(self): + mapper = defaultdict(set) + asset_ids = self.assets.values_list('id', flat=True) + asset_node_keys = Asset.nodes.through.objects. \ + filter(asset_id__in=asset_ids).values_list('asset_id', 'node__key') + + node_asset_map = defaultdict(set) + for asset_id, node_key in asset_node_keys: + all_keys = get_parent_keys(node_key) + for key in all_keys: + node_asset_map[key].add(asset_id) + + perms = AssetPermission.objects \ + .filter(is_active=True) \ + .filter(Q(users=self.user) | Q(user_groups__in=self.user.groups.all())) \ + .filter(Q(assets__in=asset_ids) | Q(nodes__key__in=[i[1] for i in asset_node_keys if len(i) == 2])) \ + .values_list('assets', 'nodes__key', 'accounts') + + asset_permed_accounts_mapper = defaultdict(set) + for asset_id, node_id, accounts in perms: + if asset_id: + asset_permed_accounts_mapper[asset_id].update(accounts) + if node_id and asset_id in node_asset_map[node_id]: + asset_permed_accounts_mapper[asset_id].update(accounts) + + accounts = Account.objects.filter(asset__in=asset_ids) + for account in accounts: + if account.asset_id not in asset_permed_accounts_mapper: + continue + permed_usernames = asset_permed_accounts_mapper[account.asset_id] + if "@ALL" in permed_usernames or account.username in permed_usernames: + mapper[account.asset_id].add(account) + return mapper + + class Job(JMSOrgBaseModel, PeriodTaskModelMixin): name = models.CharField(max_length=128, null=True, verbose_name=_('Name')) @@ -90,7 +155,7 @@ class Job(JMSOrgBaseModel, PeriodTaskModelMixin): @property def inventory(self): - return JMSInventory(self.assets.all(), self.runas_policy, self.runas) + return JMSPermedInventory(self.assets.all(), self.runas_policy, self.runas, user=self.creator) @property def material(self): diff --git a/apps/ops/serializers/job.py b/apps/ops/serializers/job.py index 792a23acd..cbf7b8936 100644 --- a/apps/ops/serializers/job.py +++ b/apps/ops/serializers/job.py @@ -3,7 +3,7 @@ import uuid from django.utils.translation import gettext_lazy as _ from rest_framework import serializers -from assets.models import Node +from assets.models import Node, Asset from perms.utils.user_perm import UserPermAssetUtil from common.serializers.fields import ReadableHiddenField from ops.mixin import PeriodTaskSerializerMixin @@ -17,6 +17,8 @@ class JobSerializer(BulkOrgResourceModelSerializer, PeriodTaskSerializerMixin): nodes = serializers.ListField(required=False, child=serializers.CharField()) date_last_run = serializers.DateTimeField(label=_('Date last run'), read_only=True) name = serializers.CharField(label=_('Name'), max_length=128, allow_blank=True, required=False) + assets = serializers.PrimaryKeyRelatedField(label=_('Assets'), queryset=Asset.objects.all(), many=True, + required=False) def to_internal_value(self, data): instant = data.get('instant', False) @@ -30,6 +32,12 @@ class JobSerializer(BulkOrgResourceModelSerializer, PeriodTaskSerializerMixin): user = request.user if request else None return user + def validate_assets(self, assets): + permed_assets = UserPermAssetUtil(self.get_request_user()).get_all_assets() + if not set(assets).issubset(set(permed_assets)): + raise serializers.ValidationError(_('Assets not in user perm')) + return assets + def create(self, validated_data): assets = validated_data.__getitem__('assets') node_ids = validated_data.pop('nodes', None) From 7ceb27301b5a64d48f80014ce0fd6cab2402bc7e Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 22 Feb 2023 16:23:18 +0800 Subject: [PATCH 02/15] perf: automation task name validate (#9690) Co-authored-by: feng <1304903146@qq.com> --- apps/accounts/serializers/automations/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/accounts/serializers/automations/base.py b/apps/accounts/serializers/automations/base.py index 6b3792559..cdb08bf36 100644 --- a/apps/accounts/serializers/automations/base.py +++ b/apps/accounts/serializers/automations/base.py @@ -38,7 +38,7 @@ class BaseAutomationSerializer(PeriodTaskSerializerMixin, BulkOrgResourceModelSe } def validate_name(self, name): - if self.instance: + if self.instance and self.instance.name == name: return name if BaseAutomation.objects.filter(name=name, type=self.model_type).exists(): raise serializers.ValidationError(_('Name already exists')) From 8eaf3fa781a6b6cd9ff327407c6a638d61ac3221 Mon Sep 17 00:00:00 2001 From: Eric Date: Wed, 22 Feb 2023 16:48:49 +0800 Subject: [PATCH 03/15] =?UTF-8?q?perf:=20=E9=83=A8=E5=88=86=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=20label=20=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/terminal/serializers/applet.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/terminal/serializers/applet.py b/apps/terminal/serializers/applet.py index f05f424c2..3e656747f 100644 --- a/apps/terminal/serializers/applet.py +++ b/apps/terminal/serializers/applet.py @@ -12,8 +12,9 @@ __all__ = [ class AppletPublicationSerializer(serializers.ModelSerializer): - applet = ObjectRelatedField(attrs=('id', 'name', 'display_name', 'icon', 'version'), queryset=Applet.objects.all()) - host = ObjectRelatedField(queryset=AppletHost.objects.all()) + applet = ObjectRelatedField(attrs=('id', 'name', 'display_name', 'icon', 'version'), label=_("Applet"), + queryset=Applet.objects.all()) + host = ObjectRelatedField(queryset=AppletHost.objects.all(), label=_("Host")) status = LabeledChoiceField(choices=PublishStatus.choices, label=_("Status"), default=Status.pending) class Meta: From 042108a9c0db0995cc31b22a738207064b50a8c9 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 22 Feb 2023 17:56:20 +0800 Subject: [PATCH 04/15] perf: k8s account @input (#9692) Co-authored-by: feng <1304903146@qq.com> --- .../user_permission/tree/node_with_asset.py | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/apps/perms/api/user_permission/tree/node_with_asset.py b/apps/perms/api/user_permission/tree/node_with_asset.py index 576a5615d..021933d40 100644 --- a/apps/perms/api/user_permission/tree/node_with_asset.py +++ b/apps/perms/api/user_permission/tree/node_with_asset.py @@ -3,23 +3,22 @@ from urllib.parse import parse_qsl from django.conf import settings from django.db.models import F, Value, CharField -from rest_framework.request import Request -from rest_framework.response import Response +from rest_framework.exceptions import PermissionDenied, NotFound from rest_framework.generics import ListAPIView from rest_framework.generics import get_object_or_404 -from rest_framework.exceptions import PermissionDenied, NotFound +from rest_framework.request import Request +from rest_framework.response import Response -from assets.utils import KubernetesTree -from assets.models import Asset from accounts.const import AliasAccount from assets.api import SerializeToTreeNodeMixin -from accounts.models import Account +from assets.models import Asset +from assets.utils import KubernetesTree from authentication.models import ConnectionToken from common.utils import get_object_or_none, lazyproperty from common.utils.common import timeit from perms.hands import Node from perms.models import PermNode -from perms.utils import PermAccountUtil, UserPermNodeUtil, AssetPermissionUtil +from perms.utils import PermAccountUtil, UserPermNodeUtil from perms.utils import UserPermAssetUtil from .mixin import RebuildTreeMixin from ..mixin import SelfOrPKUserMixin @@ -153,16 +152,16 @@ class UserGrantedK8sAsTreeApi(SelfOrPKUserMixin, ListAPIView): util = PermAccountUtil() accounts = util.get_permed_accounts_for_user(self.user, token.asset) account_name = token.account - accounts = filter(lambda x: x.name == account_name, accounts) - accounts = list(accounts) - if not accounts: - raise NotFound('Account is not found') - account = accounts[0] - if account.name in [ + if account_name in [ AliasAccount.INPUT, AliasAccount.USER ]: return token.input_secret else: + accounts = filter(lambda x: x.name == account_name, accounts) + accounts = list(accounts) + if not accounts: + raise NotFound('Account is not found') + account = accounts[0] return account.secret @staticmethod From 5d8d0a320bc564e7f435b2f05d342812d74a2195 Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 22 Feb 2023 17:58:00 +0800 Subject: [PATCH 05/15] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7=E5=8E=86=E5=8F=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/api/account/account.py | 14 +++++++++++++- apps/accounts/models/account.py | 4 ++++ apps/accounts/serializers/account/account.py | 7 ++++--- apps/accounts/signal_handlers.py | 12 ++++++++++++ apps/locale/zh/LC_MESSAGES/django.po | 2 +- 5 files changed, 34 insertions(+), 5 deletions(-) diff --git a/apps/accounts/api/account/account.py b/apps/accounts/api/account/account.py index 17938358c..73540126b 100644 --- a/apps/accounts/api/account/account.py +++ b/apps/accounts/api/account/account.py @@ -74,5 +74,17 @@ class AccountHistoriesSecretAPI(RecordViewLogMixin, ListAPIView): 'list': 'accounts.view_accountsecret', } + def get_object(self): + return get_object_or_404(Account, pk=self.kwargs.get('pk')) + def get_queryset(self): - return self.model.objects.filter(id=self.kwargs.get('pk')) + account = self.get_object() + histories = account.history.all() + last_history = account.history.first() + if not last_history: + return histories + + if account.secret == last_history.secret \ + and account.secret_type == last_history.secret_type: + histories = histories.exclude(history_id=last_history.history_id) + return histories diff --git a/apps/accounts/models/account.py b/apps/accounts/models/account.py index 00934b759..008318c7e 100644 --- a/apps/accounts/models/account.py +++ b/apps/accounts/models/account.py @@ -90,6 +90,10 @@ class Account(AbsConnectivity, BaseAccount): """ @INPUT 手动登录的账号(any) """ return cls(name=AliasAccount.INPUT.label, username=AliasAccount.INPUT.value, secret=None) + @lazyproperty + def versions(self): + return self.history.count() + @classmethod def get_user_account(cls): """ @USER 动态用户的账号(self) """ diff --git a/apps/accounts/serializers/account/account.py b/apps/accounts/serializers/account/account.py index 34333cfe4..9198dc1d7 100644 --- a/apps/accounts/serializers/account/account.py +++ b/apps/accounts/serializers/account/account.py @@ -102,8 +102,8 @@ class AccountSerializer(AccountSerializerCreateMixin, BaseAccountSerializer): class Meta(BaseAccountSerializer.Meta): model = Account fields = BaseAccountSerializer.Meta.fields + [ - 'su_from', 'asset', 'template', - 'push_now', 'source', 'connectivity' + 'su_from', 'asset', 'template', 'version', + 'push_now', 'source', 'connectivity', ] extra_kwargs = { **BaseAccountSerializer.Meta.extra_kwargs, @@ -118,7 +118,8 @@ class AccountSerializer(AccountSerializerCreateMixin, BaseAccountSerializer): @classmethod def setup_eager_loading(cls, queryset): """ Perform necessary eager loading of data. """ - queryset = queryset.prefetch_related('asset', 'asset__platform') + queryset = queryset \ + .prefetch_related('asset', 'asset__platform') return queryset diff --git a/apps/accounts/signal_handlers.py b/apps/accounts/signal_handlers.py index bb4eaedb8..b47588192 100644 --- a/apps/accounts/signal_handlers.py +++ b/apps/accounts/signal_handlers.py @@ -1,3 +1,15 @@ +from django.db.models.signals import pre_save +from django.dispatch import receiver + from common.utils import get_logger +from .models import Account logger = get_logger(__name__) + + +@receiver(pre_save, sender=Account) +def on_account_pre_save(sender, instance, created=False, **kwargs): + if created: + instance.version = 1 + else: + instance.version = instance.history.count() diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index c3f661344..9ddcbed50 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -1954,7 +1954,7 @@ msgstr "清理审计会话任务日志" #: authentication/api/confirm.py:40 msgid "This action require verify your MFA" -msgstr "此操作需要验证您的 MFA" +msgstr "该操作需要验证您的 MFA, 请先开启并配置" #: authentication/api/connection_token.py:268 msgid "Account not found" From 34386bd6fbf469a38a86c9b6475644bcbd624826 Mon Sep 17 00:00:00 2001 From: Aaron3S Date: Wed, 22 Feb 2023 18:06:46 +0800 Subject: [PATCH 06/15] =?UTF-8?q?fix:=20=E4=BF=AE=E6=94=B9=E7=94=9F?= =?UTF-8?q?=E6=88=90=20inventory=20=E9=94=99=E8=AF=AF=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=EF=BC=8C=E5=A2=9E=E5=8A=A0=E8=BF=90=E8=A1=8C=E4=BD=9C=E4=B8=9A?= =?UTF-8?q?=E6=9D=83=E9=99=90=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/models/job.py | 35 +++++++++++++++++++++++------------ apps/ops/serializers/job.py | 8 +------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/apps/ops/models/job.py b/apps/ops/models/job.py index 911ca2c97..51a8db528 100644 --- a/apps/ops/models/job.py +++ b/apps/ops/models/job.py @@ -48,15 +48,12 @@ class JMSPermedInventory(JMSInventory): def get_asset_accounts(self, asset): return self.assets_accounts_mapper.get(asset.id, []) - def get_permed_assets(self): - permed_assets = UserPermAssetUtil(self.user).get_all_assets() - return set(self.assets) & (set(permed_assets)) - def get_assets_accounts_mapper(self): mapper = defaultdict(set) asset_ids = self.assets.values_list('id', flat=True) - asset_node_keys = Asset.nodes.through.objects. \ - filter(asset_id__in=asset_ids).values_list('asset_id', 'node__key') + asset_node_keys = Asset.nodes.through.objects \ + .filter(asset_id__in=asset_ids) \ + .values_list('asset_id', 'node__key') node_asset_map = defaultdict(set) for asset_id, node_key in asset_node_keys: @@ -64,18 +61,20 @@ class JMSPermedInventory(JMSInventory): for key in all_keys: node_asset_map[key].add(asset_id) + groups = self.user.groups.all() perms = AssetPermission.objects \ + .filter(date_expired__gte=timezone.now()) \ .filter(is_active=True) \ - .filter(Q(users=self.user) | Q(user_groups__in=self.user.groups.all())) \ - .filter(Q(assets__in=asset_ids) | Q(nodes__key__in=[i[1] for i in asset_node_keys if len(i) == 2])) \ + .filter(Q(users=self.user) | Q(user_groups__in=groups)) \ + .filter(Q(assets__in=asset_ids) | Q(nodes__key__in=node_asset_map.keys())) \ .values_list('assets', 'nodes__key', 'accounts') asset_permed_accounts_mapper = defaultdict(set) - for asset_id, node_id, accounts in perms: - if asset_id: - asset_permed_accounts_mapper[asset_id].update(accounts) - if node_id and asset_id in node_asset_map[node_id]: + for asset_id, node_key, accounts in perms: + if asset_id in asset_ids: asset_permed_accounts_mapper[asset_id].update(accounts) + for my_asset in node_asset_map[node_key]: + asset_permed_accounts_mapper[my_asset].update(accounts) accounts = Account.objects.filter(asset__in=asset_ids) for account in accounts: @@ -404,7 +403,19 @@ class JobExecution(JMSOrgBaseModel): 'dangerous keyword \'{}\'\033[0m'.format(line['line'], line['file'], line['keyword'])) raise Exception("Playbook contains dangerous keywords") + def check_assets_perms(self): + all_permed_assets = UserPermAssetUtil(self.creator).get_all_assets() + has_permed_assets = set(self.current_job.assets.all()) & set(all_permed_assets) + + for asset in self.current_job.assets.all(): + if asset not in has_permed_assets: + print("\033[31mAsset {}({}) has no access permission\033[0m".format(asset.name, asset.address)) + + if self.current_job.assets.count() != len(has_permed_assets): + raise Exception("You do not have access rights to some assets") + def before_start(self): + self.check_assets_perms() if self.current_job.type == 'playbook': self.check_danger_keywords() if self.current_job.type == 'adhoc': diff --git a/apps/ops/serializers/job.py b/apps/ops/serializers/job.py index cbf7b8936..5e714976d 100644 --- a/apps/ops/serializers/job.py +++ b/apps/ops/serializers/job.py @@ -17,7 +17,7 @@ class JobSerializer(BulkOrgResourceModelSerializer, PeriodTaskSerializerMixin): nodes = serializers.ListField(required=False, child=serializers.CharField()) date_last_run = serializers.DateTimeField(label=_('Date last run'), read_only=True) name = serializers.CharField(label=_('Name'), max_length=128, allow_blank=True, required=False) - assets = serializers.PrimaryKeyRelatedField(label=_('Assets'), queryset=Asset.objects.all(), many=True, + assets = serializers.PrimaryKeyRelatedField(label=_('Assets'), queryset=Asset.objects, many=True, required=False) def to_internal_value(self, data): @@ -32,12 +32,6 @@ class JobSerializer(BulkOrgResourceModelSerializer, PeriodTaskSerializerMixin): user = request.user if request else None return user - def validate_assets(self, assets): - permed_assets = UserPermAssetUtil(self.get_request_user()).get_all_assets() - if not set(assets).issubset(set(permed_assets)): - raise serializers.ValidationError(_('Assets not in user perm')) - return assets - def create(self, validated_data): assets = validated_data.__getitem__('assets') node_ids = validated_data.pop('nodes', None) From ddcd09c6a6353708ce953d02fdf0af4622f89814 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 22 Feb 2023 18:53:35 +0800 Subject: [PATCH 07/15] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=9C=80?= =?UTF-8?q?=E5=90=8E=E6=89=A7=E8=A1=8C=E6=97=B6=E9=97=B4=E4=B8=8D=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E7=9A=84=E9=97=AE=E9=A2=98=20(#9694)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Aaron3S --- apps/ops/models/job.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ops/models/job.py b/apps/ops/models/job.py index 51a8db528..bd410a8e7 100644 --- a/apps/ops/models/job.py +++ b/apps/ops/models/job.py @@ -118,7 +118,7 @@ class Job(JMSOrgBaseModel, PeriodTaskModelMixin): @property def last_execution(self): - return self.executions.last() + return self.executions.first() @property def date_last_run(self): From ec4cdc801fa4a4b8b0f841d378b09b5632582e09 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 22 Feb 2023 19:42:40 +0800 Subject: [PATCH 08/15] perf: operate log amount (#9695) Co-authored-by: feng <1304903146@qq.com> --- apps/audits/api.py | 3 +-- apps/jumpserver/api.py | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/audits/api.py b/apps/audits/api.py index 968fe19db..82c8b43e5 100644 --- a/apps/audits/api.py +++ b/apps/audits/api.py @@ -147,8 +147,7 @@ class OperateLogViewSet(OrgReadonlyModelViewSet): return super().get_serializer_class() def get_queryset(self): - with tmp_to_root_org(): - qs = OperateLog.objects.all() + qs = OperateLog.objects.all() es_config = settings.OPERATE_LOG_ELASTICSEARCH_CONFIG if es_config: engine_mod = import_module(TYPE_ENGINE_MAPPING['es']) diff --git a/apps/jumpserver/api.py b/apps/jumpserver/api.py index 1c766a972..b5ebd9ebc 100644 --- a/apps/jumpserver/api.py +++ b/apps/jumpserver/api.py @@ -101,9 +101,9 @@ class DateTimeMixin: @lazyproperty def operate_logs_queryset(self): + from audits.api import OperateLogViewSet t = self.days_to_datetime - queryset = OperateLog.objects.filter(datetime__gte=t) - queryset = self.get_logs_queryset(queryset, 'user') + queryset = OperateLogViewSet().get_queryset().filter(datetime__gte=t) return queryset @lazyproperty From d14010d4fa5f9714fe8cb55ef66b8441d6d25c3a Mon Sep 17 00:00:00 2001 From: Aaron3S Date: Wed, 22 Feb 2023 20:04:00 +0800 Subject: [PATCH 09/15] =?UTF-8?q?fix:=20=E6=B7=BB=E5=8A=A0=20api=20permiss?= =?UTF-8?q?ion=5Fclasses?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/api/adhoc.py | 3 ++- apps/ops/api/job.py | 5 +++-- apps/ops/api/playbook.py | 12 +++++++++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/apps/ops/api/adhoc.py b/apps/ops/api/adhoc.py index d7759d88e..9be055101 100644 --- a/apps/ops/api/adhoc.py +++ b/apps/ops/api/adhoc.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- from orgs.mixins.api import OrgBulkModelViewSet +from rbac.permissions import RBACPermission from ..models import AdHoc from ..serializers import ( AdHocSerializer @@ -12,7 +13,7 @@ __all__ = [ class AdHocViewSet(OrgBulkModelViewSet): serializer_class = AdHocSerializer - permission_classes = () + permission_classes = (RBACPermission,) search_fields = ('name', 'comment') model = AdHoc diff --git a/apps/ops/api/job.py b/apps/ops/api/job.py index 67447def8..280ab5b98 100644 --- a/apps/ops/api/job.py +++ b/apps/ops/api/job.py @@ -17,6 +17,7 @@ from ops.variables import JMS_JOB_VARIABLE_HELP from orgs.mixins.api import OrgBulkModelViewSet from orgs.utils import tmp_to_org, get_current_org from accounts.models import Account +from rbac.permissions import RBACPermission def set_task_to_serializer_data(serializer, task): @@ -27,7 +28,7 @@ def set_task_to_serializer_data(serializer, task): class JobViewSet(OrgBulkModelViewSet): serializer_class = JobSerializer - permission_classes = () + permission_classes = (RBACPermission,) search_fields = ('name', 'comment') model = Job @@ -69,7 +70,7 @@ class JobViewSet(OrgBulkModelViewSet): class JobExecutionViewSet(OrgBulkModelViewSet): serializer_class = JobExecutionSerializer http_method_names = ('get', 'post', 'head', 'options',) - permission_classes = () + permission_classes = (RBACPermission,) model = JobExecution search_fields = ('material',) diff --git a/apps/ops/api/playbook.py b/apps/ops/api/playbook.py index b3c1fe564..dce2e18d9 100644 --- a/apps/ops/api/playbook.py +++ b/apps/ops/api/playbook.py @@ -8,6 +8,7 @@ from rest_framework import status from common.exceptions import JMSException from orgs.mixins.api import OrgBulkModelViewSet +from rbac.permissions import RBACPermission from ..exception import PlaybookNoValidEntry from ..models import Playbook from ..serializers.playbook import PlaybookSerializer @@ -26,7 +27,7 @@ def unzip_playbook(src, dist): class PlaybookViewSet(OrgBulkModelViewSet): serializer_class = PlaybookSerializer - permission_classes = () + permission_classes = (RBACPermission,) model = Playbook search_fields = ('name', 'comment') @@ -58,8 +59,13 @@ class PlaybookViewSet(OrgBulkModelViewSet): class PlaybookFileBrowserAPIView(APIView): rbac_perms = () - permission_classes = () - + permission_classes = (RBACPermission,) + rbac_perms = { + 'GET': 'ops.change_playbooks', + 'POST': 'ops.change_playbooks', + 'DELETE': 'ops.change_playbooks', + 'PATCH': 'ops.change_playbooks', + } protected_files = ['root', 'main.yml'] def get(self, request, **kwargs): From 9207ee73ea4ba88bc23d0d9035679611ff457ae1 Mon Sep 17 00:00:00 2001 From: jiangweidong Date: Wed, 22 Feb 2023 20:16:04 +0800 Subject: [PATCH 10/15] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3Oracle=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E8=B4=A6=E5=8F=B7=E4=BB=BB=E5=8A=A1=E5=A4=B1=E8=B4=A5?= =?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/accounts/automations/verify_account/manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/accounts/automations/verify_account/manager.py b/apps/accounts/automations/verify_account/manager.py index 3d07a95da..bf43eff46 100644 --- a/apps/accounts/automations/verify_account/manager.py +++ b/apps/accounts/automations/verify_account/manager.py @@ -57,9 +57,9 @@ class VerifyAccountManager(AccountBasePlaybookManager): 'secret': secret, 'private_key_path': private_key_path } + if account.platform.type == 'oracle': + h['account']['mode'] = 'sysdba' if account.privileged else None inventory_hosts.append(h) - # print("Host: ") - # print(self.json_dumps(inventory_hosts)) return inventory_hosts @classmethod From ea31de0b2ba4ed8f8093b830813ba770547f0b9e Mon Sep 17 00:00:00 2001 From: ibuler Date: Wed, 22 Feb 2023 20:30:43 +0800 Subject: [PATCH 11/15] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E9=83=A8?= =?UTF-8?q?=E5=88=86=20field?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/assets/api/platform.py | 7 +++---- apps/common/api/mixin.py | 3 --- apps/rbac/api/role.py | 13 +++++++------ apps/users/api/user.py | 9 +++++---- apps/users/serializers/group.py | 14 ++++++-------- apps/users/serializers/user.py | 4 +++- 6 files changed, 24 insertions(+), 26 deletions(-) diff --git a/apps/assets/api/platform.py b/apps/assets/api/platform.py index 2d68b2350..be9456ff7 100644 --- a/apps/assets/api/platform.py +++ b/apps/assets/api/platform.py @@ -1,9 +1,8 @@ -from jumpserver.utils import has_valid_xpack_license +from assets.const import AllTypes +from assets.models import Platform +from assets.serializers import PlatformSerializer from common.api import JMSModelViewSet from common.serializers import GroupedChoiceSerializer -from assets.models import Platform -from assets.const import AllTypes -from assets.serializers import PlatformSerializer __all__ = ['AssetPlatformViewSet'] diff --git a/apps/common/api/mixin.py b/apps/common/api/mixin.py index 3c8c2d487..cb8d6ec3e 100644 --- a/apps/common/api/mixin.py +++ b/apps/common/api/mixin.py @@ -16,9 +16,6 @@ __all__ = [ class PaginatedResponseMixin: - paginate_queryset: Callable - get_serializer: Callable - get_paginated_response: Callable def get_paginated_response_from_queryset(self, queryset): page = self.paginate_queryset(queryset) diff --git a/apps/rbac/api/role.py b/apps/rbac/api/role.py index 3340a37fd..3bccdc573 100644 --- a/apps/rbac/api/role.py +++ b/apps/rbac/api/role.py @@ -59,6 +59,8 @@ class RoleViewSet(JMSModelViewSet): @staticmethod def set_users_amount(queryset): """设置角色的用户绑定数量,以减少查询""" + ids = [role.id for role in queryset] + queryset = Role.objects.filter(id__in=ids) org_id = current_org.id q = Q(role__scope=Role.Scope.system) | Q(role__scope=Role.Scope.org, org_id=org_id) role_bindings = RoleBinding.objects.filter(q).values_list('role_id').annotate(user_count=Count('user_id')) @@ -69,12 +71,11 @@ class RoleViewSet(JMSModelViewSet): role.users_amount = role_user_amount_mapper.get(role.id, 0) return queryset - def paginate_queryset(self, queryset): - page_queryset = super().paginate_queryset(queryset) # 返回是 list 对象 - page_queryset_ids = [str(i.id) for i in page_queryset] - queryset = queryset.filter(id__in=page_queryset_ids) - queryset = self.set_users_amount(queryset) - return queryset + def get_serializer(self, *args, **kwargs): + if len(args) == 1: + queryset = self.set_users_amount(args[0]) + args = (queryset,) + return super().get_serializer(*args, **kwargs) def perform_update(self, serializer): instance = serializer.instance diff --git a/apps/users/api/user.py b/apps/users/api/user.py index 2b08418bf..c7f2d62eb 100644 --- a/apps/users/api/user.py +++ b/apps/users/api/user.py @@ -51,10 +51,11 @@ class UserViewSet(CommonApiMixin, UserQuerysetMixin, SuggestionMixin, BulkModelV queryset = super().get_queryset().prefetch_related('groups') return queryset - def paginate_queryset(self, queryset): - page = super().paginate_queryset(queryset) - self.set_users_roles_for_cache(page or queryset) - return page + def get_serializer(self, *args, **kwargs): + if len(args) == 0: + queryset = self.set_users_roles_for_cache(args[0]) + args = (queryset,) + return super().get_serializer(*args, **kwargs) @action(methods=['get'], detail=False, url_path='suggestions') def match(self, request, *args, **kwargs): diff --git a/apps/users/serializers/group.py b/apps/users/serializers/group.py index 6f75b402a..90228d681 100644 --- a/apps/users/serializers/group.py +++ b/apps/users/serializers/group.py @@ -1,13 +1,12 @@ # -*- coding: utf-8 -*- # -from django.utils.translation import ugettext_lazy as _ -from django.db.models import Prefetch -from rest_framework import serializers - -from orgs.mixins.serializers import BulkOrgResourceModelSerializer from django.db.models import Count -from ..models import User, UserGroup +from django.utils.translation import ugettext_lazy as _ + +from common.serializers.mixin import ObjectRelatedField +from orgs.mixins.serializers import BulkOrgResourceModelSerializer from .. import utils +from ..models import User, UserGroup __all__ = [ 'UserGroupSerializer', @@ -15,9 +14,8 @@ __all__ = [ class UserGroupSerializer(BulkOrgResourceModelSerializer): - users = serializers.PrimaryKeyRelatedField( + users = ObjectRelatedField( required=False, many=True, queryset=User.objects, label=_('User'), - # write_only=True, # group can return many to many on detail ) class Meta: diff --git a/apps/users/serializers/user.py b/apps/users/serializers/user.py index 74c182fed..c04f21018 100644 --- a/apps/users/serializers/user.py +++ b/apps/users/serializers/user.py @@ -39,7 +39,7 @@ class RolesSerializerMixin(serializers.Serializer): label=_("System roles"), many=True, default=default_system_roles ) org_roles = ObjectRelatedField( - queryset=Role.org_roles, attrs=('id', 'display_name'), + queryset=Role.org_roles, attrs=('id', 'display_name', 'name'), label=_("Org roles"), many=True, required=False, default=default_org_roles ) @@ -91,6 +91,8 @@ class UserSerializer(RolesSerializerMixin, CommonBulkSerializerMixin, serializer ) login_blocked = serializers.BooleanField(read_only=True, label=_("Login blocked")) is_expired = serializers.BooleanField(read_only=True, label=_("Is expired")) + is_valid = serializers.BooleanField(read_only=True, label=_("Is valid")) + is_otp_secret_key_bound = serializers.BooleanField(read_only=True, label=_("Is OTP bound")) can_public_key_auth = serializers.BooleanField( source="can_use_ssh_key_login", label=_("Can public key authentication"), read_only=True From b83667bbd5e658d286b02b2712e09e8d69ef2902 Mon Sep 17 00:00:00 2001 From: fit2bot <68588906+fit2bot@users.noreply.github.com> Date: Wed, 22 Feb 2023 20:31:20 +0800 Subject: [PATCH 12/15] perf: celery task and add org single (#9698) Co-authored-by: feng <1304903146@qq.com> --- apps/accounts/api/account/task.py | 2 +- apps/accounts/serializers/account/account.py | 2 +- apps/assets/api/asset/asset.py | 4 ++-- apps/assets/tasks/ping.py | 3 ++- apps/orgs/signal_handlers/common.py | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/accounts/api/account/task.py b/apps/accounts/api/account/task.py index e5d4b36bb..a042323f5 100644 --- a/apps/accounts/api/account/task.py +++ b/apps/accounts/api/account/task.py @@ -24,7 +24,7 @@ class AccountsTaskCreateAPI(CreateAPIView): def perform_create(self, serializer): data = serializer.validated_data accounts = data.get('accounts', []) - account_ids = [a.id for a in accounts] + account_ids = [str(a.id) for a in accounts] if data['action'] == 'push': task = push_accounts_to_assets_task.delay(account_ids) diff --git a/apps/accounts/serializers/account/account.py b/apps/accounts/serializers/account/account.py index 34333cfe4..4a5e82c6b 100644 --- a/apps/accounts/serializers/account/account.py +++ b/apps/accounts/serializers/account/account.py @@ -43,7 +43,7 @@ class AccountSerializerCreateValidateMixin: def push_account(instance, push_now): if not push_now: return - push_accounts_to_assets_task.delay([instance.id]) + push_accounts_to_assets_task.delay([str(instance.id)]) def create(self, validated_data): push_now = validated_data.pop('push_now', None) diff --git a/apps/assets/api/asset/asset.py b/apps/assets/api/asset/asset.py index 5b67e9114..d8b46baab 100644 --- a/apps/assets/api/asset/asset.py +++ b/apps/assets/api/asset/asset.py @@ -204,8 +204,8 @@ class AssetTaskCreateApi(AssetsTaskMixin, generics.CreateAPIView): if not accounts: accounts = asset.accounts.all() - asset_ids = [asset.id] - account_ids = accounts.values_list("id", flat=True) + account_ids = accounts.values_list('id', flat=True) + account_ids = [str(_id) for _id in account_ids] if action == "push_account": task = push_accounts_to_assets_task.delay(account_ids) elif action == "test_account": diff --git a/apps/assets/tasks/ping.py b/apps/assets/tasks/ping.py index 7dab3c869..3882fe0b3 100644 --- a/apps/assets/tasks/ping.py +++ b/apps/assets/tasks/ping.py @@ -33,7 +33,7 @@ def test_assets_connectivity_task(asset_ids, org_id, task_name=None): def test_assets_connectivity_manual(assets): task_name = gettext_noop("Test assets connectivity ") - asset_ids = [i.id for i in assets] + asset_ids = [str(i.id) for i in assets] org_id = str(current_org.id) return test_assets_connectivity_task.delay(asset_ids, org_id, task_name) @@ -41,5 +41,6 @@ def test_assets_connectivity_manual(assets): def test_node_assets_connectivity_manual(node): task_name = gettext_noop("Test if the assets under the node are connectable ") asset_ids = node.get_all_asset_ids() + asset_ids = [str(i) for i in asset_ids] org_id = str(current_org.id) return test_assets_connectivity_task.delay(asset_ids, org_id, task_name) diff --git a/apps/orgs/signal_handlers/common.py b/apps/orgs/signal_handlers/common.py index f6d5c4132..01ce911c4 100644 --- a/apps/orgs/signal_handlers/common.py +++ b/apps/orgs/signal_handlers/common.py @@ -59,7 +59,7 @@ def expire_user_orgs(*args): @receiver(post_save, sender=Organization) def on_org_create(sender, instance, created=False, **kwargs): - if created: + if not created: return expire_user_orgs() From 49c7a12bb303a5f56a810a70497fd311c706ead2 Mon Sep 17 00:00:00 2001 From: Bai Date: Wed, 22 Feb 2023 21:04:44 +0800 Subject: [PATCH 13/15] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=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?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/perms/filters.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/perms/filters.py b/apps/perms/filters.py index d585d8382..202720480 100644 --- a/apps/perms/filters.py +++ b/apps/perms/filters.py @@ -95,6 +95,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') + address = filters.CharFilter(method='do_nothing') accounts = filters.CharFilter(method='do_nothing') ip = filters.CharFilter(method='do_nothing') @@ -153,14 +154,14 @@ class AssetPermissionFilter(PermissionBaseFilter): is_query_all = self.get_query_param('all', True) asset_id = self.get_query_param('asset_id') asset_name = self.get_query_param('asset_name') - ip = self.get_query_param('address') + address = self.get_query_param('address') if asset_id: assets = Asset.objects.filter(pk=asset_id) elif asset_name: assets = Asset.objects.filter(name=asset_name) - elif ip: - assets = Asset.objects.filter(ip=ip) + elif address: + assets = Asset.objects.filter(address=address) else: return queryset if not assets: From 9b2f422622de292304b6645e98935ca5921b983e Mon Sep 17 00:00:00 2001 From: Aaron3S Date: Wed, 22 Feb 2023 20:05:31 +0800 Subject: [PATCH 14/15] =?UTF-8?q?perf:=20=E4=BC=98=E5=8C=96=E6=8A=A5?= =?UTF-8?q?=E9=94=99=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/ops/models/job.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/ops/models/job.py b/apps/ops/models/job.py index bd410a8e7..4cb297191 100644 --- a/apps/ops/models/job.py +++ b/apps/ops/models/job.py @@ -407,12 +407,14 @@ class JobExecution(JMSOrgBaseModel): all_permed_assets = UserPermAssetUtil(self.creator).get_all_assets() has_permed_assets = set(self.current_job.assets.all()) & set(all_permed_assets) + error_assets_count = 0 for asset in self.current_job.assets.all(): if asset not in has_permed_assets: print("\033[31mAsset {}({}) has no access permission\033[0m".format(asset.name, asset.address)) + error_assets_count += 1 - if self.current_job.assets.count() != len(has_permed_assets): - raise Exception("You do not have access rights to some assets") + if error_assets_count > 0: + raise Exception("You do not have access rights to {} assets".format(error_assets_count)) def before_start(self): self.check_assets_perms() From 25bd5c71d1dee84cd7498cc9b9d13ffaac00254e Mon Sep 17 00:00:00 2001 From: Aaron3S Date: Wed, 22 Feb 2023 21:27:01 +0800 Subject: [PATCH 15/15] =?UTF-8?q?fix:=20=E5=A2=9E=E5=8A=A0=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E8=AF=BB=E5=8F=96=E7=9A=84=E6=96=87=E4=BB=B6=E6=8F=90?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/locale/ja/LC_MESSAGES/django.po | 267 ++++++++++++++------------ apps/locale/zh/LC_MESSAGES/django.po | 270 ++++++++++++++------------- apps/ops/api/playbook.py | 10 +- 3 files changed, 290 insertions(+), 257 deletions(-) diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 6e38486bd..91c1abe30 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-21 22:44+0800\n" +"POT-Creation-Date: 2023-02-22 21:23+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -28,7 +28,7 @@ msgstr "パラメータ 'action' は [{}] でなければなりません。" #: authentication/confirm/password.py:9 authentication/forms.py:32 #: authentication/templates/authentication/login.html:274 #: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:47 -#: users/forms/profile.py:22 users/serializers/user.py:99 +#: users/forms/profile.py:22 users/serializers/user.py:101 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/cloud/serializers/account_attrs.py:28 @@ -172,7 +172,7 @@ msgstr "作成のみ" #: perms/models/asset_permission.py:64 perms/serializers/permission.py:27 #: terminal/backends/command/models.py:20 terminal/models/session/session.py:32 #: terminal/notifications.py:95 terminal/serializers/command.py:17 -#: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:212 +#: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:220 msgid "Asset" msgstr "資産" @@ -223,15 +223,15 @@ msgstr "アカウントを確認できます" msgid "Can push account" msgstr "アカウントをプッシュできます" -#: accounts/models/account.py:113 +#: accounts/models/account.py:109 msgid "Account template" msgstr "アカウント テンプレート" -#: accounts/models/account.py:118 +#: accounts/models/account.py:114 msgid "Can view asset account template secret" msgstr "アセット アカウント テンプレートのパスワードを表示できます" -#: accounts/models/account.py:119 +#: accounts/models/account.py:115 msgid "Can change asset account template secret" msgstr "アセット アカウント テンプレートのパスワードを変更できます" @@ -249,7 +249,7 @@ msgstr "アカウントバックアップ計画" #: accounts/models/automations/backup_account.py:83 #: assets/models/automations/base.py:114 audits/models.py:55 -#: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:122 +#: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:186 #: perms/models/asset_permission.py:72 terminal/models/applet/host.py:109 #: terminal/models/session/session.py:45 #: tickets/models/ticket/apply_application.py:30 @@ -269,21 +269,21 @@ msgstr "アカウントのバックアップスナップショット" #: accounts/models/automations/backup_account.py:94 #: accounts/serializers/account/backup.py:42 -#: accounts/serializers/automations/base.py:53 +#: accounts/serializers/automations/base.py:55 #: assets/models/automations/base.py:121 #: assets/serializers/automations/base.py:40 msgid "Trigger mode" msgstr "トリガーモード" #: accounts/models/automations/backup_account.py:97 audits/models.py:172 -#: terminal/models/session/sharing.py:107 xpack/plugins/cloud/models.py:168 +#: terminal/models/session/sharing.py:107 xpack/plugins/cloud/models.py:176 msgid "Reason" msgstr "理由" #: accounts/models/automations/backup_account.py:99 #: accounts/serializers/automations/change_secret.py:110 #: accounts/serializers/automations/change_secret.py:133 -#: ops/serializers/job.py:64 terminal/serializers/session.py:45 +#: ops/serializers/job.py:66 terminal/serializers/session.py:45 msgid "Is success" msgstr "成功は" @@ -328,7 +328,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:132 +#: accounts/serializers/account/account.py:134 #: accounts/serializers/account/base.py:16 #: accounts/serializers/automations/change_secret.py:46 #: authentication/serializers/connect_token_secret.py:41 @@ -371,7 +371,7 @@ msgstr "開始日" #: accounts/models/automations/change_secret.py:74 #: assets/models/automations/base.py:115 ops/models/base.py:56 -#: ops/models/celery.py:64 ops/models/job.py:123 +#: ops/models/celery.py:64 ops/models/job.py:187 #: terminal/models/applet/host.py:110 msgid "Date finished" msgstr "終了日" @@ -450,7 +450,7 @@ msgstr "アカウントの確認" #: assets/serializers/platform.py:91 assets/serializers/platform.py:136 #: authentication/serializers/connect_token_secret.py:103 ops/mixin.py:21 #: ops/models/adhoc.py:21 ops/models/celery.py:15 ops/models/celery.py:57 -#: ops/models/job.py:26 ops/models/playbook.py:23 ops/serializers/job.py:19 +#: ops/models/job.py:90 ops/models/playbook.py:23 ops/serializers/job.py:19 #: 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:27 terminal/models/component/endpoint.py:12 @@ -470,7 +470,7 @@ msgstr "特権アカウント" #: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 #: assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:107 -#: terminal/models/applet/applet.py:32 users/serializers/user.py:159 +#: terminal/models/applet/applet.py:32 users/serializers/user.py:161 msgid "Is active" msgstr "アクティブです。" @@ -540,16 +540,16 @@ msgid "Category" msgstr "カテゴリ" #: accounts/serializers/account/account.py:76 -#: accounts/serializers/automations/base.py:52 acls/models/command_acl.py:24 +#: accounts/serializers/automations/base.py:54 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:78 #: assets/serializers/asset/common.py:122 assets/serializers/platform.py:96 #: audits/serializers.py:48 -#: authentication/serializers/connect_token_secret.py:116 ops/models/job.py:37 +#: authentication/serializers/connect_token_secret.py:116 ops/models/job.py:101 #: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:31 #: terminal/models/component/storage.py:57 -#: terminal/models/component/storage.py:146 terminal/serializers/applet.py:28 +#: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29 #: terminal/serializers/session.py:22 terminal/serializers/storage.py:224 #: terminal/serializers/storage.py:236 tickets/models/comment.py:26 #: tickets/models/flow.py:56 tickets/models/ticket/apply_application.py:16 @@ -592,14 +592,14 @@ msgid "Key password" msgstr "キーパスワード" #: accounts/serializers/account/base.py:79 -#: assets/serializers/asset/common.py:288 +#: assets/serializers/asset/common.py:290 msgid "Spec info" 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:39 +#: ops/models/job.py:103 ops/serializers/job.py:20 #: terminal/templates/terminal/_msg_command_execute_alert.html:16 msgid "Assets" msgstr "資産" @@ -611,11 +611,11 @@ msgstr "資産" msgid "Nodes" msgstr "ノード" -#: accounts/serializers/automations/base.py:42 +#: accounts/serializers/automations/base.py:44 msgid "Name already exists" msgstr "名前は既に存在します。" -#: accounts/serializers/automations/base.py:51 +#: accounts/serializers/automations/base.py:53 #: assets/models/automations/base.py:117 #: assets/serializers/automations/base.py:39 msgid "Automation snapshot" @@ -747,12 +747,12 @@ msgstr "アクティブ" #: terminal/notifications.py:96 terminal/notifications.py:144 #: terminal/serializers/command.py:16 tickets/models/comment.py:21 #: users/const.py:14 users/models/user.py:911 users/models/user.py:942 -#: users/serializers/group.py:19 +#: users/serializers/group.py:18 msgid "User" msgstr "ユーザー" #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 -#: ops/serializers/job.py:63 terminal/const.py:67 +#: ops/serializers/job.py:65 terminal/const.py:67 #: terminal/models/session/session.py:43 terminal/serializers/command.py:18 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 @@ -934,7 +934,7 @@ msgstr "削除に失敗し、ノードにアセットが含まれています。 msgid "App assets" msgstr "アプリ資産" -#: assets/automations/base/manager.py:107 +#: assets/automations/base/manager.py:114 msgid "{} disabled" msgstr "{} 無効" @@ -988,7 +988,7 @@ msgstr "資産情報の収集" #: assets/const/category.py:11 assets/models/asset/host.py:8 #: settings/serializers/auth/radius.py:16 settings/serializers/auth/sms.py:67 -#: terminal/models/component/endpoint.py:13 +#: terminal/models/component/endpoint.py:13 terminal/serializers/applet.py:17 #: xpack/plugins/cloud/serializers/account_attrs.py:72 msgid "Host" msgstr "ホスト" @@ -1065,20 +1065,20 @@ msgstr "SSHパブリックキー" #: assets/models/_user.py:27 assets/models/cmd_filter.py:40 #: assets/models/cmd_filter.py:88 assets/models/group.py:23 -#: common/db/models.py:37 ops/models/adhoc.py:27 ops/models/job.py:45 +#: common/db/models.py:37 ops/models/adhoc.py:27 ops/models/job.py:109 #: ops/models/playbook.py:26 rbac/models/role.py:37 settings/models.py:38 -#: terminal/models/applet/applet.py:36 terminal/models/applet/applet.py:155 +#: terminal/models/applet/applet.py:36 terminal/models/applet/applet.py:158 #: terminal/models/applet/host.py:111 terminal/models/component/endpoint.py:24 #: terminal/models/component/endpoint.py:100 #: terminal/models/session/session.py:47 tickets/models/comment.py:32 #: tickets/models/ticket/general.py:297 users/models/user.py:756 -#: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:111 +#: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:119 msgid "Comment" msgstr "コメント" #: assets/models/_user.py:28 assets/models/automations/base.py:113 #: 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:121 +#: common/db/models.py:35 ops/models/base.py:54 ops/models/job.py:185 #: users/models/user.py:943 msgid "Date created" msgstr "作成された日付" @@ -1091,7 +1091,7 @@ 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:763 -#: users/serializers/group.py:33 +#: users/serializers/group.py:31 msgid "Created by" msgstr "によって作成された" @@ -1183,7 +1183,7 @@ msgstr "アドレス" #: assets/models/asset/common.py:104 assets/models/platform.py:112 #: authentication/serializers/connect_token_secret.py:108 #: perms/serializers/user_permission.py:23 -#: xpack/plugins/cloud/serializers/account_attrs.py:187 +#: xpack/plugins/cloud/serializers/account_attrs.py:179 msgid "Platform" msgstr "プラットフォーム" @@ -1254,7 +1254,7 @@ msgid "Submit selector" msgstr "ボタンセレクターを確認する" #: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38 -#: assets/serializers/asset/common.py:287 rbac/tree.py:36 +#: assets/serializers/asset/common.py:289 rbac/tree.py:36 msgid "Accounts" msgstr "アカウント" @@ -1267,13 +1267,13 @@ msgid "Asset automation task" msgstr "アセットの自動化タスク" #: assets/models/automations/base.py:112 audits/models.py:177 -#: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:114 -#: terminal/models/applet/applet.py:154 terminal/models/applet/host.py:108 -#: terminal/models/component/status.py:27 terminal/serializers/applet.py:17 +#: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:178 +#: terminal/models/applet/applet.py:157 terminal/models/applet/host.py:108 +#: terminal/models/component/status.py:27 terminal/serializers/applet.py:18 #: 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:164 -#: xpack/plugins/cloud/models.py:216 +#: tickets/serializers/ticket/ticket.py:20 xpack/plugins/cloud/models.py:172 +#: xpack/plugins/cloud/models.py:224 msgid "Status" msgstr "ステータス" @@ -1492,7 +1492,8 @@ msgstr "自動充填" #: assets/serializers/asset/common.py:124 assets/serializers/platform.py:99 #: 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:99 +#: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:107 +#: xpack/plugins/cloud/serializers/task.py:38 msgid "Protocols" msgstr "プロトコル" @@ -1512,15 +1513,13 @@ msgstr "ポート番号が範囲外です (1-65535)" msgid "Protocol is required: {}" msgstr "プロトコルが必要です: {}" -#: assets/serializers/asset/common.py:289 +#: assets/serializers/asset/common.py:291 msgid "Auto info" msgstr "自動情報" #: assets/serializers/asset/database.py:25 common/serializers/fields.py:100 #: tickets/serializers/ticket/common.py:58 #: xpack/plugins/cloud/serializers/account_attrs.py:56 -#: xpack/plugins/cloud/serializers/account_attrs.py:79 -#: xpack/plugins/cloud/serializers/account_attrs.py:143 msgid "This field is required." msgstr "このフィールドは必須です。" @@ -2465,7 +2464,7 @@ msgstr "すぐに期限切れ" #: 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 +#: perms/models/perm_node.py:21 users/serializers/group.py:33 msgid "ID" msgstr "ID" @@ -2487,7 +2486,7 @@ msgstr "アクション" #: authentication/serializers/connection_token.py:41 #: perms/serializers/permission.py:31 perms/serializers/permission.py:61 -#: users/serializers/user.py:93 users/serializers/user.py:162 +#: users/serializers/user.py:93 users/serializers/user.py:164 msgid "Is expired" msgstr "期限切れです" @@ -2507,7 +2506,8 @@ 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:160 +#: perms/serializers/permission.py:62 users/serializers/user.py:94 +#: users/serializers/user.py:162 msgid "Is valid" msgstr "有効です" @@ -3235,6 +3235,10 @@ msgstr "タスクは存在しません" msgid "Task {} args or kwargs error" msgstr "タスク実行パラメータエラー" +#: ops/api/playbook.py:83 +msgid "Unsupported file content" +msgstr "サポートされていないファイルの内容" + #: ops/apps.py:9 ops/notifications.py:16 rbac/tree.py:56 msgid "App ops" msgstr "アプリ操作" @@ -3275,7 +3279,7 @@ msgstr "VCS" msgid "Adhoc" msgstr "コマンド#コマンド#" -#: ops/const.py:39 ops/models/job.py:35 +#: ops/const.py:39 ops/models/job.py:99 msgid "Playbook" msgstr "Playbook" @@ -3336,17 +3340,17 @@ msgstr "定期的または定期的に設定を行う必要があります" msgid "Pattern" msgstr "パターン" -#: ops/models/adhoc.py:24 ops/models/job.py:30 +#: ops/models/adhoc.py:24 ops/models/job.py:94 msgid "Module" msgstr "モジュール" -#: ops/models/adhoc.py:25 ops/models/celery.py:58 ops/models/job.py:29 +#: ops/models/adhoc.py:25 ops/models/celery.py:58 ops/models/job.py:93 #: terminal/models/component/task.py:16 msgid "Args" msgstr "アルグ" #: ops/models/adhoc.py:26 ops/models/base.py:16 ops/models/base.py:53 -#: ops/models/job.py:38 ops/models/job.py:120 ops/models/playbook.py:25 +#: ops/models/job.py:102 ops/models/job.py:184 ops/models/playbook.py:25 #: terminal/models/session/sharing.py:23 msgid "Creator" msgstr "作成者" @@ -3363,12 +3367,12 @@ msgstr "最後の実行" msgid "Date last run" msgstr "最終実行日" -#: ops/models/base.py:51 ops/models/job.py:118 -#: xpack/plugins/cloud/models.py:162 +#: ops/models/base.py:51 ops/models/job.py:182 +#: xpack/plugins/cloud/models.py:170 msgid "Result" msgstr "結果" -#: ops/models/base.py:52 ops/models/job.py:119 +#: ops/models/base.py:52 ops/models/job.py:183 msgid "Summary" msgstr "概要" @@ -3408,47 +3412,47 @@ msgstr "発売日" msgid "Celery Task Execution" msgstr "Celery タスク実行" -#: ops/models/job.py:32 +#: ops/models/job.py:96 msgid "Chdir" msgstr "実行ディレクトリ" -#: ops/models/job.py:33 +#: ops/models/job.py:97 msgid "Timeout (Seconds)" msgstr "タイムアウト(秒)" -#: ops/models/job.py:40 +#: ops/models/job.py:104 msgid "Use Parameter Define" msgstr "パラメータ定義を使用する" -#: ops/models/job.py:41 +#: ops/models/job.py:105 msgid "Parameters define" msgstr "パラメータ定義" -#: ops/models/job.py:42 +#: ops/models/job.py:106 msgid "Runas" msgstr "ユーザーとして実行" -#: ops/models/job.py:44 +#: ops/models/job.py:108 msgid "Runas policy" msgstr "ユーザー ポリシー" -#: ops/models/job.py:106 +#: ops/models/job.py:170 msgid "Job" msgstr "ジョブ#ジョブ#" -#: ops/models/job.py:117 +#: ops/models/job.py:181 msgid "Parameters" msgstr "パラメータ" -#: ops/models/job.py:125 +#: ops/models/job.py:189 msgid "Material" msgstr "" -#: ops/models/job.py:127 +#: ops/models/job.py:191 msgid "Material Type" msgstr "" -#: ops/models/job.py:364 +#: ops/models/job.py:442 msgid "Job Execution" msgstr "ジョブ実行" @@ -3492,15 +3496,15 @@ msgstr "{max_threshold} を超えるCPUロード: => {value}" msgid "Run after save" msgstr "保存後に実行" -#: ops/serializers/job.py:62 +#: ops/serializers/job.py:64 msgid "Job type" msgstr "タスクの種類" -#: ops/serializers/job.py:65 terminal/serializers/session.py:49 +#: ops/serializers/job.py:67 terminal/serializers/session.py:49 msgid "Is finished" msgstr "終了しました" -#: ops/serializers/job.py:66 +#: ops/serializers/job.py:68 msgid "Time cost" msgstr "時を過ごす" @@ -3726,7 +3730,7 @@ msgstr "内部の役割は、破壊することはできません" msgid "The role has been bound to users, can't be destroy" msgstr "ロールはユーザーにバインドされており、破壊することはできません" -#: rbac/api/role.py:82 +#: rbac/api/role.py:83 msgid "Internal role, can't be update" msgstr "内部ロール、更新できません" @@ -3835,7 +3839,7 @@ msgstr "システムロールバインディング" msgid "Perms" msgstr "パーマ" -#: rbac/serializers/role.py:27 users/serializers/group.py:34 +#: rbac/serializers/role.py:27 users/serializers/group.py:32 msgid "Users amount" msgstr "ユーザー数" @@ -3904,7 +3908,8 @@ msgid "My assets" msgstr "私の資産" #: rbac/tree.py:57 terminal/models/applet/applet.py:43 -#: terminal/models/applet/applet.py:151 terminal/models/applet/host.py:28 +#: terminal/models/applet/applet.py:154 terminal/models/applet/host.py:28 +#: terminal/serializers/applet.py:15 msgid "Applet" msgstr "リモートアプリケーション" @@ -4403,7 +4408,7 @@ msgid "SSO auth key TTL" msgstr "Token有効期間" #: settings/serializers/auth/sso.py:17 -#: xpack/plugins/cloud/serializers/account_attrs.py:184 +#: xpack/plugins/cloud/serializers/account_attrs.py:176 msgid "Unit: second" msgstr "単位: 秒" @@ -5444,7 +5449,7 @@ msgstr "ホスト" msgid "Applet pkg not valid, Missing file {}" msgstr "無効なアプレット パッケージ、ファイル {} がありません" -#: terminal/models/applet/applet.py:153 terminal/models/applet/host.py:34 +#: terminal/models/applet/applet.py:156 terminal/models/applet/host.py:34 #: terminal/models/applet/host.py:106 msgid "Hosting" msgstr "ホスト マシン" @@ -5687,7 +5692,7 @@ msgstr "レベル" msgid "Batch danger command alert" msgstr "一括危険コマンド警告" -#: terminal/serializers/applet.py:27 +#: terminal/serializers/applet.py:28 msgid "Icon" msgstr "アイコン" @@ -5816,7 +5821,7 @@ msgstr "アクセスキー" msgid "Access key secret" msgstr "アクセスキーシークレット" -#: terminal/serializers/storage.py:65 xpack/plugins/cloud/models.py:209 +#: terminal/serializers/storage.py:65 xpack/plugins/cloud/models.py:217 msgid "Region" msgstr "リージョン" @@ -6250,7 +6255,7 @@ msgstr "無効な承認アクション" msgid "This user is not authorized to approve this ticket" msgstr "このユーザーはこの作業指示を承認する権限がありません" -#: users/api/user.py:178 +#: users/api/user.py:179 msgid "Could not reset self otp, use profile reset instead" msgstr "自己otpをリセットできませんでした、代わりにプロファイルリセットを使用" @@ -6369,7 +6374,7 @@ msgstr "公開キー" msgid "Force enable" msgstr "強制有効" -#: users/models/user.py:729 users/serializers/user.py:161 +#: users/models/user.py:729 users/serializers/user.py:163 msgid "Is service account" msgstr "サービスアカウントです" @@ -6398,7 +6403,7 @@ msgid "Secret key" msgstr "秘密キー" #: users/models/user.py:758 users/serializers/profile.py:147 -#: users/serializers/user.py:158 +#: users/serializers/user.py:160 msgid "Is first login" msgstr "最初のログインです" @@ -6505,27 +6510,27 @@ msgstr "MFAフォース有効化" msgid "Login blocked" msgstr "ログインブロック" -#: users/serializers/user.py:95 -msgid "Can public key authentication" -msgstr "公開鍵認証が可能" - -#: users/serializers/user.py:163 -msgid "Avatar url" -msgstr "アバターURL" - -#: users/serializers/user.py:166 +#: users/serializers/user.py:95 users/serializers/user.py:168 msgid "Is OTP bound" msgstr "仮想MFAがバインドされているか" -#: users/serializers/user.py:273 +#: users/serializers/user.py:97 +msgid "Can public key authentication" +msgstr "公開鍵認証が可能" + +#: users/serializers/user.py:165 +msgid "Avatar url" +msgstr "アバターURL" + +#: users/serializers/user.py:275 msgid "Select users" msgstr "ユーザーの選択" -#: users/serializers/user.py:274 +#: users/serializers/user.py:276 msgid "For security, only list several users" msgstr "セキュリティのために、複数のユーザーのみをリストします" -#: users/serializers/user.py:307 +#: users/serializers/user.py:309 msgid "name not unique" msgstr "名前が一意ではない" @@ -6947,47 +6952,59 @@ msgstr "リージョン" msgid "Hostname strategy" msgstr "ホスト名戦略" -#: xpack/plugins/cloud/models.py:102 xpack/plugins/cloud/serializers/task.py:40 +#: xpack/plugins/cloud/models.py:100 +#, fuzzy +#| msgid "Only admin users" +msgid "Unix admin user" +msgstr "管理者のみ" + +#: xpack/plugins/cloud/models.py:104 +#, fuzzy +#| msgid "Only admin users" +msgid "Windows admin user" +msgstr "管理者のみ" + +#: xpack/plugins/cloud/models.py:110 xpack/plugins/cloud/serializers/task.py:41 msgid "IP network segment group" msgstr "IPネットワークセグメントグループ" -#: xpack/plugins/cloud/models.py:105 xpack/plugins/cloud/serializers/task.py:45 +#: xpack/plugins/cloud/models.py:113 xpack/plugins/cloud/serializers/task.py:46 msgid "Sync IP type" msgstr "同期IPタイプ" -#: xpack/plugins/cloud/models.py:108 xpack/plugins/cloud/serializers/task.py:62 +#: xpack/plugins/cloud/models.py:116 xpack/plugins/cloud/serializers/task.py:64 msgid "Always update" msgstr "常に更新" -#: xpack/plugins/cloud/models.py:114 +#: xpack/plugins/cloud/models.py:122 msgid "Date last sync" msgstr "最終同期日" -#: xpack/plugins/cloud/models.py:119 xpack/plugins/cloud/models.py:160 +#: xpack/plugins/cloud/models.py:127 xpack/plugins/cloud/models.py:168 msgid "Sync instance task" msgstr "インスタンスの同期タスク" -#: xpack/plugins/cloud/models.py:171 xpack/plugins/cloud/models.py:219 +#: xpack/plugins/cloud/models.py:179 xpack/plugins/cloud/models.py:227 msgid "Date sync" msgstr "日付の同期" -#: xpack/plugins/cloud/models.py:175 +#: xpack/plugins/cloud/models.py:183 msgid "Sync instance task execution" msgstr "インスタンスタスクの同期実行" -#: xpack/plugins/cloud/models.py:199 +#: xpack/plugins/cloud/models.py:207 msgid "Sync task" msgstr "同期タスク" -#: xpack/plugins/cloud/models.py:203 +#: xpack/plugins/cloud/models.py:211 msgid "Sync instance task history" msgstr "インスタンスタスク履歴の同期" -#: xpack/plugins/cloud/models.py:206 +#: xpack/plugins/cloud/models.py:214 msgid "Instance" msgstr "インスタンス" -#: xpack/plugins/cloud/models.py:223 +#: xpack/plugins/cloud/models.py:231 msgid "Sync instance detail" msgstr "同期インスタンスの詳細" @@ -7201,52 +7218,52 @@ msgstr "テナントID" msgid "Subscription ID" msgstr "サブスクリプションID" -#: xpack/plugins/cloud/serializers/account_attrs.py:98 -#: xpack/plugins/cloud/serializers/account_attrs.py:103 -#: xpack/plugins/cloud/serializers/account_attrs.py:119 -#: xpack/plugins/cloud/serializers/account_attrs.py:149 +#: xpack/plugins/cloud/serializers/account_attrs.py:95 +#: xpack/plugins/cloud/serializers/account_attrs.py:100 +#: xpack/plugins/cloud/serializers/account_attrs.py:116 +#: xpack/plugins/cloud/serializers/account_attrs.py:141 msgid "API Endpoint" msgstr "APIエンドポイント" -#: xpack/plugins/cloud/serializers/account_attrs.py:109 +#: xpack/plugins/cloud/serializers/account_attrs.py:106 msgid "Auth url" msgstr "認証アドレス" -#: xpack/plugins/cloud/serializers/account_attrs.py:110 +#: xpack/plugins/cloud/serializers/account_attrs.py:107 msgid "eg: http://openstack.example.com:5000/v3" msgstr "例えば: http://openstack.example.com:5000/v3" -#: xpack/plugins/cloud/serializers/account_attrs.py:113 +#: xpack/plugins/cloud/serializers/account_attrs.py:110 msgid "User domain" msgstr "ユーザードメイン" -#: xpack/plugins/cloud/serializers/account_attrs.py:120 +#: xpack/plugins/cloud/serializers/account_attrs.py:117 msgid "Cert File" msgstr "証明書ファイル" -#: xpack/plugins/cloud/serializers/account_attrs.py:121 +#: xpack/plugins/cloud/serializers/account_attrs.py:118 msgid "Key File" msgstr "キーファイル" -#: xpack/plugins/cloud/serializers/account_attrs.py:137 +#: xpack/plugins/cloud/serializers/account_attrs.py:134 msgid "Service account key" msgstr "サービスアカウントキー" -#: xpack/plugins/cloud/serializers/account_attrs.py:138 +#: xpack/plugins/cloud/serializers/account_attrs.py:135 msgid "The file is in JSON format" msgstr "ファイルはJSON形式です。" -#: xpack/plugins/cloud/serializers/account_attrs.py:156 +#: xpack/plugins/cloud/serializers/account_attrs.py:148 msgid "IP address invalid `{}`, {}" msgstr "IPアドレスが無効: '{}', {}" -#: xpack/plugins/cloud/serializers/account_attrs.py:162 +#: xpack/plugins/cloud/serializers/account_attrs.py:154 msgid "" "Format for comma-delimited string,Such as: 192.168.1.0/24, " "10.0.0.0-10.0.0.255" msgstr "形式はコンマ区切りの文字列です,例:192.168.1.0/24,10.0.0.0-10.0.0.255" -#: xpack/plugins/cloud/serializers/account_attrs.py:166 +#: xpack/plugins/cloud/serializers/account_attrs.py:158 msgid "" "The port is used to detect the validity of the IP address. When the " "synchronization task is executed, only the valid IP address will be " @@ -7256,19 +7273,19 @@ msgstr "" "実行されると、有効な IP アドレスのみが同期されます。
ポートが0の場合、す" "べてのIPアドレスが有効です。" -#: xpack/plugins/cloud/serializers/account_attrs.py:174 +#: xpack/plugins/cloud/serializers/account_attrs.py:166 msgid "Hostname prefix" msgstr "ホスト名プレフィックス" -#: xpack/plugins/cloud/serializers/account_attrs.py:177 +#: xpack/plugins/cloud/serializers/account_attrs.py:169 msgid "IP segment" msgstr "IP セグメント" -#: xpack/plugins/cloud/serializers/account_attrs.py:181 +#: xpack/plugins/cloud/serializers/account_attrs.py:173 msgid "Test port" msgstr "テストポート" -#: xpack/plugins/cloud/serializers/account_attrs.py:184 +#: xpack/plugins/cloud/serializers/account_attrs.py:176 msgid "Test timeout" msgstr "テストタイムアウト" @@ -7294,13 +7311,11 @@ msgstr "実行回数" msgid "Instance count" msgstr "インスタンス数" -#: xpack/plugins/cloud/tasks.py:27 -msgid "Run sync instance task" -msgstr "同期インスタンス タスクを実行する" - -#: xpack/plugins/cloud/tasks.py:41 -msgid "Period clean sync instance task execution" -msgstr "同期インスタンス タスクの実行記録を定期的にクリアする" +#: xpack/plugins/cloud/serializers/task.py:63 +#, fuzzy +#| msgid "Only admin users" +msgid "Linux admin user" +msgstr "管理者のみ" #: xpack/plugins/cloud/utils.py:69 msgid "Account unavailable" @@ -7370,6 +7385,12 @@ msgstr "究極のエディション" msgid "Community edition" msgstr "コミュニティ版" +#~ msgid "Run sync instance task" +#~ msgstr "同期インスタンス タスクを実行する" + +#~ msgid "Period clean sync instance task execution" +#~ msgstr "同期インスタンス タスクの実行記録を定期的にクリアする" + #~ msgid "Can push account to asset" #~ msgstr "アカウントをアセットにプッシュできます" diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 9ddcbed50..89a9dbcc4 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-21 22:44+0800\n" +"POT-Creation-Date: 2023-02-22 21:23+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -27,7 +27,7 @@ msgstr "参数 'action' 必须是 [{}]" #: authentication/confirm/password.py:9 authentication/forms.py:32 #: authentication/templates/authentication/login.html:274 #: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:47 -#: users/forms/profile.py:22 users/serializers/user.py:99 +#: users/forms/profile.py:22 users/serializers/user.py:101 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/cloud/serializers/account_attrs.py:28 @@ -171,7 +171,7 @@ msgstr "仅创建" #: perms/models/asset_permission.py:64 perms/serializers/permission.py:27 #: terminal/backends/command/models.py:20 terminal/models/session/session.py:32 #: terminal/notifications.py:95 terminal/serializers/command.py:17 -#: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:212 +#: tickets/models/ticket/apply_asset.py:16 xpack/plugins/cloud/models.py:220 msgid "Asset" msgstr "资产" @@ -222,15 +222,15 @@ msgstr "可以验证账号" msgid "Can push account" msgstr "可以推送账号" -#: accounts/models/account.py:113 +#: accounts/models/account.py:109 msgid "Account template" msgstr "账号模版" -#: accounts/models/account.py:118 +#: accounts/models/account.py:114 msgid "Can view asset account template secret" msgstr "可以查看资产账号模版密码" -#: accounts/models/account.py:119 +#: accounts/models/account.py:115 msgid "Can change asset account template secret" msgstr "可以更改资产账号模版密码" @@ -248,7 +248,7 @@ msgstr "账号备份计划" #: accounts/models/automations/backup_account.py:83 #: assets/models/automations/base.py:114 audits/models.py:55 -#: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:122 +#: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:186 #: perms/models/asset_permission.py:72 terminal/models/applet/host.py:109 #: terminal/models/session/session.py:45 #: tickets/models/ticket/apply_application.py:30 @@ -268,21 +268,21 @@ msgstr "账号备份快照" #: accounts/models/automations/backup_account.py:94 #: accounts/serializers/account/backup.py:42 -#: accounts/serializers/automations/base.py:53 +#: accounts/serializers/automations/base.py:55 #: assets/models/automations/base.py:121 #: assets/serializers/automations/base.py:40 msgid "Trigger mode" msgstr "触发模式" #: accounts/models/automations/backup_account.py:97 audits/models.py:172 -#: terminal/models/session/sharing.py:107 xpack/plugins/cloud/models.py:168 +#: terminal/models/session/sharing.py:107 xpack/plugins/cloud/models.py:176 msgid "Reason" msgstr "原因" #: accounts/models/automations/backup_account.py:99 #: accounts/serializers/automations/change_secret.py:110 #: accounts/serializers/automations/change_secret.py:133 -#: ops/serializers/job.py:64 terminal/serializers/session.py:45 +#: ops/serializers/job.py:66 terminal/serializers/session.py:45 msgid "Is success" msgstr "是否成功" @@ -327,7 +327,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:132 +#: accounts/serializers/account/account.py:134 #: accounts/serializers/account/base.py:16 #: accounts/serializers/automations/change_secret.py:46 #: authentication/serializers/connect_token_secret.py:41 @@ -370,7 +370,7 @@ msgstr "开始日期" #: accounts/models/automations/change_secret.py:74 #: assets/models/automations/base.py:115 ops/models/base.py:56 -#: ops/models/celery.py:64 ops/models/job.py:123 +#: ops/models/celery.py:64 ops/models/job.py:187 #: terminal/models/applet/host.py:110 msgid "Date finished" msgstr "结束日期" @@ -449,7 +449,7 @@ msgstr "账号验证" #: assets/serializers/platform.py:91 assets/serializers/platform.py:136 #: authentication/serializers/connect_token_secret.py:103 ops/mixin.py:21 #: ops/models/adhoc.py:21 ops/models/celery.py:15 ops/models/celery.py:57 -#: ops/models/job.py:26 ops/models/playbook.py:23 ops/serializers/job.py:19 +#: ops/models/job.py:90 ops/models/playbook.py:23 ops/serializers/job.py:19 #: 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:27 terminal/models/component/endpoint.py:12 @@ -469,7 +469,7 @@ msgstr "特权账号" #: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 #: assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:107 -#: terminal/models/applet/applet.py:32 users/serializers/user.py:159 +#: terminal/models/applet/applet.py:32 users/serializers/user.py:161 msgid "Is active" msgstr "激活" @@ -536,16 +536,16 @@ msgid "Category" msgstr "类别" #: accounts/serializers/account/account.py:76 -#: accounts/serializers/automations/base.py:52 acls/models/command_acl.py:24 +#: accounts/serializers/automations/base.py:54 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:78 #: assets/serializers/asset/common.py:122 assets/serializers/platform.py:96 #: audits/serializers.py:48 -#: authentication/serializers/connect_token_secret.py:116 ops/models/job.py:37 +#: authentication/serializers/connect_token_secret.py:116 ops/models/job.py:101 #: perms/serializers/user_permission.py:26 terminal/models/applet/applet.py:31 #: terminal/models/component/storage.py:57 -#: terminal/models/component/storage.py:146 terminal/serializers/applet.py:28 +#: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29 #: terminal/serializers/session.py:22 terminal/serializers/storage.py:224 #: terminal/serializers/storage.py:236 tickets/models/comment.py:26 #: tickets/models/flow.py:56 tickets/models/ticket/apply_application.py:16 @@ -588,14 +588,14 @@ msgid "Key password" msgstr "密钥密码" #: accounts/serializers/account/base.py:79 -#: assets/serializers/asset/common.py:288 +#: assets/serializers/asset/common.py:290 msgid "Spec info" 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:39 +#: ops/models/job.py:103 ops/serializers/job.py:20 #: terminal/templates/terminal/_msg_command_execute_alert.html:16 msgid "Assets" msgstr "资产" @@ -607,11 +607,11 @@ msgstr "资产" msgid "Nodes" msgstr "节点" -#: accounts/serializers/automations/base.py:42 +#: accounts/serializers/automations/base.py:44 msgid "Name already exists" msgstr "名称已存在" -#: accounts/serializers/automations/base.py:51 +#: accounts/serializers/automations/base.py:53 #: assets/models/automations/base.py:117 #: assets/serializers/automations/base.py:39 msgid "Automation snapshot" @@ -743,12 +743,12 @@ msgstr "激活中" #: terminal/notifications.py:96 terminal/notifications.py:144 #: terminal/serializers/command.py:16 tickets/models/comment.py:21 #: users/const.py:14 users/models/user.py:911 users/models/user.py:942 -#: users/serializers/group.py:19 +#: users/serializers/group.py:18 msgid "User" msgstr "用户" #: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60 -#: ops/serializers/job.py:63 terminal/const.py:67 +#: ops/serializers/job.py:65 terminal/const.py:67 #: terminal/models/session/session.py:43 terminal/serializers/command.py:18 #: terminal/templates/terminal/_msg_command_alert.html:12 #: terminal/templates/terminal/_msg_command_execute_alert.html:10 @@ -926,7 +926,7 @@ msgstr "删除失败,节点包含资产" msgid "App assets" msgstr "资产管理" -#: assets/automations/base/manager.py:107 +#: assets/automations/base/manager.py:114 msgid "{} disabled" msgstr "{} 已禁用" @@ -980,7 +980,7 @@ msgstr "收集资产信息" #: assets/const/category.py:11 assets/models/asset/host.py:8 #: settings/serializers/auth/radius.py:16 settings/serializers/auth/sms.py:67 -#: terminal/models/component/endpoint.py:13 +#: terminal/models/component/endpoint.py:13 terminal/serializers/applet.py:17 #: xpack/plugins/cloud/serializers/account_attrs.py:72 msgid "Host" msgstr "主机" @@ -1057,20 +1057,20 @@ msgstr "SSH公钥" #: assets/models/_user.py:27 assets/models/cmd_filter.py:40 #: assets/models/cmd_filter.py:88 assets/models/group.py:23 -#: common/db/models.py:37 ops/models/adhoc.py:27 ops/models/job.py:45 +#: common/db/models.py:37 ops/models/adhoc.py:27 ops/models/job.py:109 #: ops/models/playbook.py:26 rbac/models/role.py:37 settings/models.py:38 -#: terminal/models/applet/applet.py:36 terminal/models/applet/applet.py:155 +#: terminal/models/applet/applet.py:36 terminal/models/applet/applet.py:158 #: terminal/models/applet/host.py:111 terminal/models/component/endpoint.py:24 #: terminal/models/component/endpoint.py:100 #: terminal/models/session/session.py:47 tickets/models/comment.py:32 #: tickets/models/ticket/general.py:297 users/models/user.py:756 -#: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:111 +#: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:119 msgid "Comment" msgstr "备注" #: assets/models/_user.py:28 assets/models/automations/base.py:113 #: 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:121 +#: common/db/models.py:35 ops/models/base.py:54 ops/models/job.py:185 #: users/models/user.py:943 msgid "Date created" msgstr "创建日期" @@ -1083,7 +1083,7 @@ 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:763 -#: users/serializers/group.py:33 +#: users/serializers/group.py:31 msgid "Created by" msgstr "创建者" @@ -1175,7 +1175,7 @@ msgstr "地址" #: assets/models/asset/common.py:104 assets/models/platform.py:112 #: authentication/serializers/connect_token_secret.py:108 #: perms/serializers/user_permission.py:23 -#: xpack/plugins/cloud/serializers/account_attrs.py:187 +#: xpack/plugins/cloud/serializers/account_attrs.py:179 msgid "Platform" msgstr "系统平台" @@ -1246,7 +1246,7 @@ msgid "Submit selector" msgstr "确认按钮选择器" #: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38 -#: assets/serializers/asset/common.py:287 rbac/tree.py:36 +#: assets/serializers/asset/common.py:289 rbac/tree.py:36 msgid "Accounts" msgstr "账号管理" @@ -1259,13 +1259,13 @@ msgid "Asset automation task" msgstr "资产自动化任务" #: assets/models/automations/base.py:112 audits/models.py:177 -#: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:114 -#: terminal/models/applet/applet.py:154 terminal/models/applet/host.py:108 -#: terminal/models/component/status.py:27 terminal/serializers/applet.py:17 +#: audits/serializers.py:49 ops/models/base.py:49 ops/models/job.py:178 +#: terminal/models/applet/applet.py:157 terminal/models/applet/host.py:108 +#: terminal/models/component/status.py:27 terminal/serializers/applet.py:18 #: 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:164 -#: xpack/plugins/cloud/models.py:216 +#: tickets/serializers/ticket/ticket.py:20 xpack/plugins/cloud/models.py:172 +#: xpack/plugins/cloud/models.py:224 msgid "Status" msgstr "状态" @@ -1484,7 +1484,8 @@ msgstr "自动代填" #: assets/serializers/asset/common.py:124 assets/serializers/platform.py:99 #: 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:99 +#: perms/serializers/user_permission.py:24 xpack/plugins/cloud/models.py:107 +#: xpack/plugins/cloud/serializers/task.py:38 msgid "Protocols" msgstr "协议组" @@ -1504,15 +1505,13 @@ msgstr "端口超出范围 (1-65535)" msgid "Protocol is required: {}" msgstr "协议是必填的: {}" -#: assets/serializers/asset/common.py:289 +#: assets/serializers/asset/common.py:291 msgid "Auto info" msgstr "自动化信息" #: assets/serializers/asset/database.py:25 common/serializers/fields.py:100 #: tickets/serializers/ticket/common.py:58 #: xpack/plugins/cloud/serializers/account_attrs.py:56 -#: xpack/plugins/cloud/serializers/account_attrs.py:79 -#: xpack/plugins/cloud/serializers/account_attrs.py:143 msgid "This field is required." msgstr "该字段是必填项。" @@ -2443,7 +2442,7 @@ msgstr "立刻过期" #: 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 +#: perms/models/perm_node.py:21 users/serializers/group.py:33 msgid "ID" msgstr "ID" @@ -2465,7 +2464,7 @@ msgstr "动作" #: authentication/serializers/connection_token.py:41 #: perms/serializers/permission.py:31 perms/serializers/permission.py:61 -#: users/serializers/user.py:93 users/serializers/user.py:162 +#: users/serializers/user.py:93 users/serializers/user.py:164 msgid "Is expired" msgstr "已过期" @@ -2485,7 +2484,8 @@ 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:160 +#: perms/serializers/permission.py:62 users/serializers/user.py:94 +#: users/serializers/user.py:162 msgid "Is valid" msgstr "是否有效" @@ -3200,6 +3200,10 @@ msgstr "任务 {} 不存在" msgid "Task {} args or kwargs error" msgstr "任务 {} 执行参数错误" +#: ops/api/playbook.py:83 +msgid "Unsupported file content" +msgstr "不支持的文件内容" + #: ops/apps.py:9 ops/notifications.py:16 rbac/tree.py:56 msgid "App ops" msgstr "作业中心" @@ -3240,7 +3244,7 @@ msgstr "VCS" msgid "Adhoc" msgstr "命令" -#: ops/const.py:39 ops/models/job.py:35 +#: ops/const.py:39 ops/models/job.py:99 msgid "Playbook" msgstr "Playbook" @@ -3301,17 +3305,17 @@ msgstr "需要周期或定期设置" msgid "Pattern" msgstr "模式" -#: ops/models/adhoc.py:24 ops/models/job.py:30 +#: ops/models/adhoc.py:24 ops/models/job.py:94 msgid "Module" msgstr "模块" -#: ops/models/adhoc.py:25 ops/models/celery.py:58 ops/models/job.py:29 +#: ops/models/adhoc.py:25 ops/models/celery.py:58 ops/models/job.py:93 #: terminal/models/component/task.py:16 msgid "Args" msgstr "参数" #: ops/models/adhoc.py:26 ops/models/base.py:16 ops/models/base.py:53 -#: ops/models/job.py:38 ops/models/job.py:120 ops/models/playbook.py:25 +#: ops/models/job.py:102 ops/models/job.py:184 ops/models/playbook.py:25 #: terminal/models/session/sharing.py:23 msgid "Creator" msgstr "创建者" @@ -3328,12 +3332,12 @@ msgstr "最后执行" msgid "Date last run" msgstr "最后运行日期" -#: ops/models/base.py:51 ops/models/job.py:118 -#: xpack/plugins/cloud/models.py:162 +#: ops/models/base.py:51 ops/models/job.py:182 +#: xpack/plugins/cloud/models.py:170 msgid "Result" msgstr "结果" -#: ops/models/base.py:52 ops/models/job.py:119 +#: ops/models/base.py:52 ops/models/job.py:183 msgid "Summary" msgstr "汇总" @@ -3373,47 +3377,47 @@ msgstr "发布日期" msgid "Celery Task Execution" msgstr "Celery 任务执行" -#: ops/models/job.py:32 +#: ops/models/job.py:96 msgid "Chdir" msgstr "运行目录" -#: ops/models/job.py:33 +#: ops/models/job.py:97 msgid "Timeout (Seconds)" msgstr "超时时间(秒)" -#: ops/models/job.py:40 +#: ops/models/job.py:104 msgid "Use Parameter Define" msgstr "使用参数定义" -#: ops/models/job.py:41 +#: ops/models/job.py:105 msgid "Parameters define" msgstr "参数定义" -#: ops/models/job.py:42 +#: ops/models/job.py:106 msgid "Runas" msgstr "运行用户" -#: ops/models/job.py:44 +#: ops/models/job.py:108 msgid "Runas policy" msgstr "用户策略" -#: ops/models/job.py:106 +#: ops/models/job.py:170 msgid "Job" msgstr "作业" -#: ops/models/job.py:117 +#: ops/models/job.py:181 msgid "Parameters" msgstr "参数" -#: ops/models/job.py:125 +#: ops/models/job.py:189 msgid "Material" msgstr "" -#: ops/models/job.py:127 +#: ops/models/job.py:191 msgid "Material Type" msgstr "" -#: ops/models/job.py:364 +#: ops/models/job.py:442 msgid "Job Execution" msgstr "作业执行" @@ -3457,15 +3461,15 @@ msgstr "CPU 使用率超过 {max_threshold}: => {value}" msgid "Run after save" msgstr "保存后执行" -#: ops/serializers/job.py:62 +#: ops/serializers/job.py:64 msgid "Job type" msgstr "任务类型" -#: ops/serializers/job.py:65 terminal/serializers/session.py:49 +#: ops/serializers/job.py:67 terminal/serializers/session.py:49 msgid "Is finished" msgstr "是否完成" -#: ops/serializers/job.py:66 +#: ops/serializers/job.py:68 msgid "Time cost" msgstr "花费时间" @@ -3690,7 +3694,7 @@ msgstr "内部角色,不能删除" msgid "The role has been bound to users, can't be destroy" msgstr "角色已绑定用户,不能删除" -#: rbac/api/role.py:82 +#: rbac/api/role.py:83 msgid "Internal role, can't be update" msgstr "内部角色,不能更新" @@ -3798,7 +3802,7 @@ msgstr "系统角色绑定" msgid "Perms" msgstr "权限" -#: rbac/serializers/role.py:27 users/serializers/group.py:34 +#: rbac/serializers/role.py:27 users/serializers/group.py:32 msgid "Users amount" msgstr "用户数量" @@ -3867,7 +3871,8 @@ msgid "My assets" msgstr "我的资产" #: rbac/tree.py:57 terminal/models/applet/applet.py:43 -#: terminal/models/applet/applet.py:151 terminal/models/applet/host.py:28 +#: terminal/models/applet/applet.py:154 terminal/models/applet/host.py:28 +#: terminal/serializers/applet.py:15 msgid "Applet" msgstr "远程应用" @@ -4364,7 +4369,7 @@ msgid "SSO auth key TTL" msgstr "令牌有效期" #: settings/serializers/auth/sso.py:17 -#: xpack/plugins/cloud/serializers/account_attrs.py:184 +#: xpack/plugins/cloud/serializers/account_attrs.py:176 msgid "Unit: second" msgstr "单位: 秒" @@ -5372,7 +5377,7 @@ msgstr "主机" msgid "Applet pkg not valid, Missing file {}" msgstr "Applet pkg 无效,缺少文件 {}" -#: terminal/models/applet/applet.py:153 terminal/models/applet/host.py:34 +#: terminal/models/applet/applet.py:156 terminal/models/applet/host.py:34 #: terminal/models/applet/host.py:106 msgid "Hosting" msgstr "宿主机" @@ -5615,7 +5620,7 @@ msgstr "级别" msgid "Batch danger command alert" msgstr "批量危险命令告警" -#: terminal/serializers/applet.py:27 +#: terminal/serializers/applet.py:28 msgid "Icon" msgstr "图标" @@ -5742,7 +5747,7 @@ msgstr "Access key ID(AK)" msgid "Access key secret" msgstr "Access key secret(SK)" -#: terminal/serializers/storage.py:65 xpack/plugins/cloud/models.py:209 +#: terminal/serializers/storage.py:65 xpack/plugins/cloud/models.py:217 msgid "Region" msgstr "地域" @@ -6170,7 +6175,7 @@ msgstr "无效的审批动作" msgid "This user is not authorized to approve this ticket" msgstr "此用户无权审批此工单" -#: users/api/user.py:178 +#: users/api/user.py:179 msgid "Could not reset self otp, use profile reset instead" msgstr "不能在该页面重置 MFA 多因子认证, 请去个人信息页面重置" @@ -6289,7 +6294,7 @@ msgstr "SSH公钥" msgid "Force enable" msgstr "强制启用" -#: users/models/user.py:729 users/serializers/user.py:161 +#: users/models/user.py:729 users/serializers/user.py:163 msgid "Is service account" msgstr "服务账号" @@ -6318,7 +6323,7 @@ msgid "Secret key" msgstr "Secret key" #: users/models/user.py:758 users/serializers/profile.py:147 -#: users/serializers/user.py:158 +#: users/serializers/user.py:160 msgid "Is first login" msgstr "首次登录" @@ -6425,27 +6430,27 @@ msgstr "强制 MFA" msgid "Login blocked" msgstr "登录被阻塞" -#: users/serializers/user.py:95 -msgid "Can public key authentication" -msgstr "公钥认证" - -#: users/serializers/user.py:163 -msgid "Avatar url" -msgstr "头像路径" - -#: users/serializers/user.py:166 +#: users/serializers/user.py:95 users/serializers/user.py:168 msgid "Is OTP bound" msgstr "是否绑定了虚拟 MFA" -#: users/serializers/user.py:273 +#: users/serializers/user.py:97 +msgid "Can public key authentication" +msgstr "公钥认证" + +#: users/serializers/user.py:165 +msgid "Avatar url" +msgstr "头像路径" + +#: users/serializers/user.py:275 msgid "Select users" msgstr "选择用户" -#: users/serializers/user.py:274 +#: users/serializers/user.py:276 msgid "For security, only list several users" msgstr "为了安全,仅列出几个用户" -#: users/serializers/user.py:307 +#: users/serializers/user.py:309 msgid "name not unique" msgstr "名称重复" @@ -6855,47 +6860,55 @@ msgstr "地域" msgid "Hostname strategy" msgstr "主机名策略" -#: xpack/plugins/cloud/models.py:102 xpack/plugins/cloud/serializers/task.py:40 +#: xpack/plugins/cloud/models.py:100 +msgid "Unix admin user" +msgstr "Unix 管理员" + +#: xpack/plugins/cloud/models.py:104 +msgid "Windows admin user" +msgstr "Windows 管理员" + +#: xpack/plugins/cloud/models.py:110 xpack/plugins/cloud/serializers/task.py:41 msgid "IP network segment group" msgstr "IP网段组" -#: xpack/plugins/cloud/models.py:105 xpack/plugins/cloud/serializers/task.py:45 +#: xpack/plugins/cloud/models.py:113 xpack/plugins/cloud/serializers/task.py:46 msgid "Sync IP type" msgstr "同步IP类型" -#: xpack/plugins/cloud/models.py:108 xpack/plugins/cloud/serializers/task.py:62 +#: xpack/plugins/cloud/models.py:116 xpack/plugins/cloud/serializers/task.py:64 msgid "Always update" msgstr "总是更新" -#: xpack/plugins/cloud/models.py:114 +#: xpack/plugins/cloud/models.py:122 msgid "Date last sync" msgstr "最后同步日期" -#: xpack/plugins/cloud/models.py:119 xpack/plugins/cloud/models.py:160 +#: xpack/plugins/cloud/models.py:127 xpack/plugins/cloud/models.py:168 msgid "Sync instance task" msgstr "同步实例任务" -#: xpack/plugins/cloud/models.py:171 xpack/plugins/cloud/models.py:219 +#: xpack/plugins/cloud/models.py:179 xpack/plugins/cloud/models.py:227 msgid "Date sync" msgstr "同步日期" -#: xpack/plugins/cloud/models.py:175 +#: xpack/plugins/cloud/models.py:183 msgid "Sync instance task execution" msgstr "同步实例任务执行" -#: xpack/plugins/cloud/models.py:199 +#: xpack/plugins/cloud/models.py:207 msgid "Sync task" msgstr "同步任务" -#: xpack/plugins/cloud/models.py:203 +#: xpack/plugins/cloud/models.py:211 msgid "Sync instance task history" msgstr "同步实例任务历史" -#: xpack/plugins/cloud/models.py:206 +#: xpack/plugins/cloud/models.py:214 msgid "Instance" msgstr "实例" -#: xpack/plugins/cloud/models.py:223 +#: xpack/plugins/cloud/models.py:231 msgid "Sync instance detail" msgstr "同步实例详情" @@ -7109,52 +7122,52 @@ msgstr "租户 ID" msgid "Subscription ID" msgstr "订阅 ID" -#: xpack/plugins/cloud/serializers/account_attrs.py:98 -#: xpack/plugins/cloud/serializers/account_attrs.py:103 -#: xpack/plugins/cloud/serializers/account_attrs.py:119 -#: xpack/plugins/cloud/serializers/account_attrs.py:149 +#: xpack/plugins/cloud/serializers/account_attrs.py:95 +#: xpack/plugins/cloud/serializers/account_attrs.py:100 +#: xpack/plugins/cloud/serializers/account_attrs.py:116 +#: xpack/plugins/cloud/serializers/account_attrs.py:141 msgid "API Endpoint" msgstr "API 端点" -#: xpack/plugins/cloud/serializers/account_attrs.py:109 +#: xpack/plugins/cloud/serializers/account_attrs.py:106 msgid "Auth url" msgstr "认证地址" -#: xpack/plugins/cloud/serializers/account_attrs.py:110 +#: xpack/plugins/cloud/serializers/account_attrs.py:107 msgid "eg: http://openstack.example.com:5000/v3" msgstr "如: http://openstack.example.com:5000/v3" -#: xpack/plugins/cloud/serializers/account_attrs.py:113 +#: xpack/plugins/cloud/serializers/account_attrs.py:110 msgid "User domain" msgstr "用户域" -#: xpack/plugins/cloud/serializers/account_attrs.py:120 +#: xpack/plugins/cloud/serializers/account_attrs.py:117 msgid "Cert File" msgstr "证书文件" -#: xpack/plugins/cloud/serializers/account_attrs.py:121 +#: xpack/plugins/cloud/serializers/account_attrs.py:118 msgid "Key File" msgstr "密钥文件" -#: xpack/plugins/cloud/serializers/account_attrs.py:137 +#: xpack/plugins/cloud/serializers/account_attrs.py:134 msgid "Service account key" msgstr "服务账号密钥" -#: xpack/plugins/cloud/serializers/account_attrs.py:138 +#: xpack/plugins/cloud/serializers/account_attrs.py:135 msgid "The file is in JSON format" msgstr "JSON 格式的文件" -#: xpack/plugins/cloud/serializers/account_attrs.py:156 +#: xpack/plugins/cloud/serializers/account_attrs.py:148 msgid "IP address invalid `{}`, {}" msgstr "IP 地址无效: `{}`, {}" -#: xpack/plugins/cloud/serializers/account_attrs.py:162 +#: xpack/plugins/cloud/serializers/account_attrs.py:154 msgid "" "Format for comma-delimited string,Such as: 192.168.1.0/24, " "10.0.0.0-10.0.0.255" msgstr "格式为逗号分隔的字符串,如:192.168.1.0/24,10.0.0.0-10.0.0.255" -#: xpack/plugins/cloud/serializers/account_attrs.py:166 +#: xpack/plugins/cloud/serializers/account_attrs.py:158 msgid "" "The port is used to detect the validity of the IP address. When the " "synchronization task is executed, only the valid IP address will be " @@ -7163,19 +7176,19 @@ msgstr "" "端口用来检测 IP 地址的有效性,在同步任务执行时,只会同步有效的 IP 地址。
" "如果端口为 0,则表示所有 IP 地址均有效。" -#: xpack/plugins/cloud/serializers/account_attrs.py:174 +#: xpack/plugins/cloud/serializers/account_attrs.py:166 msgid "Hostname prefix" msgstr "主机名前缀" -#: xpack/plugins/cloud/serializers/account_attrs.py:177 +#: xpack/plugins/cloud/serializers/account_attrs.py:169 msgid "IP segment" msgstr "IP 网段" -#: xpack/plugins/cloud/serializers/account_attrs.py:181 +#: xpack/plugins/cloud/serializers/account_attrs.py:173 msgid "Test port" msgstr "测试端口" -#: xpack/plugins/cloud/serializers/account_attrs.py:184 +#: xpack/plugins/cloud/serializers/account_attrs.py:176 msgid "Test timeout" msgstr "测试超时时间" @@ -7199,13 +7212,9 @@ msgstr "执行次数" msgid "Instance count" msgstr "实例个数" -#: xpack/plugins/cloud/tasks.py:27 -msgid "Run sync instance task" -msgstr "执行同步实例任务" - -#: xpack/plugins/cloud/tasks.py:41 -msgid "Period clean sync instance task execution" -msgstr "定期清除同步实例任务执行记录" +#: xpack/plugins/cloud/serializers/task.py:63 +msgid "Linux admin user" +msgstr "Linux 管理员" #: xpack/plugins/cloud/utils.py:69 msgid "Account unavailable" @@ -7275,6 +7284,12 @@ msgstr "旗舰版" msgid "Community edition" msgstr "社区版" +#~ msgid "Run sync instance task" +#~ msgstr "执行同步实例任务" + +#~ msgid "Period clean sync instance task execution" +#~ msgstr "定期清除同步实例任务执行记录" + #~ msgid "Can push account to asset" #~ msgstr "可以推送账号到资产" @@ -7319,15 +7334,6 @@ msgstr "社区版" #~ msgid "Periodic clean expired session" #~ msgstr "周期清理过期会话" -#~ msgid "Unix admin user" -#~ msgstr "Unix 管理员" - -#~ msgid "Windows admin user" -#~ msgstr "Windows 管理员" - -#~ msgid "Linux admin user" -#~ msgstr "Linux 管理员" - #~ msgid "AdHoc" #~ msgstr "任务各版本" diff --git a/apps/ops/api/playbook.py b/apps/ops/api/playbook.py index dce2e18d9..12e5b0659 100644 --- a/apps/ops/api/playbook.py +++ b/apps/ops/api/playbook.py @@ -12,6 +12,7 @@ from rbac.permissions import RBACPermission from ..exception import PlaybookNoValidEntry from ..models import Playbook from ..serializers.playbook import PlaybookSerializer +from django.utils.translation import ugettext_lazy as _ __all__ = ["PlaybookViewSet", "PlaybookFileBrowserAPIView"] @@ -76,7 +77,10 @@ class PlaybookFileBrowserAPIView(APIView): if file_key: file_path = os.path.join(work_path, file_key) with open(file_path, 'r') as f: - content = f.read() + try: + content = f.read() + except UnicodeDecodeError: + content = _('Unsupported file content') return Response({'content': content}) else: expand_key = request.query_params.get('expand', '') @@ -159,6 +163,8 @@ class PlaybookFileBrowserAPIView(APIView): # rename if new_name: new_file_path = os.path.join(os.path.dirname(file_path), new_name) + if new_file_path == file_path: + return Response(status=status.HTTP_200_OK) if os.path.exists(new_file_path): return Response({'msg': '{} already exists'.format(new_name)}, status=status.HTTP_400_BAD_REQUEST) os.rename(file_path, new_file_path) @@ -167,7 +173,7 @@ class PlaybookFileBrowserAPIView(APIView): if not is_directory: with open(file_path, 'w') as f: f.write(content) - return Response({'msg': 'ok'}) + return Response(status=status.HTTP_200_OK) def delete(self, request, **kwargs): playbook_id = kwargs.get('pk')