diff --git a/apps/assets/api/account/account.py b/apps/assets/api/account/account.py index 31aaccb96..3275dc67d 100644 --- a/apps/assets/api/account/account.py +++ b/apps/assets/api/account/account.py @@ -1,6 +1,6 @@ from rest_framework.decorators import action from rest_framework.response import Response -from rest_framework.generics import CreateAPIView, get_object_or_404 +from rest_framework.generics import CreateAPIView, ListAPIView from orgs.mixins.api import OrgBulkModelViewSet from rbac.permissions import RBACPermission @@ -13,7 +13,7 @@ from assets.filters import AccountFilterSet from assets.tasks.account_connectivity import test_accounts_connectivity_manual from assets import serializers -__all__ = ['AccountViewSet', 'AccountSecretsViewSet', 'AccountTaskCreateAPI'] +__all__ = ['AccountViewSet', 'AccountSecretsViewSet', 'AccountTaskCreateAPI', 'AccountHistoriesSecretAPI'] class AccountViewSet(OrgBulkModelViewSet): @@ -42,7 +42,6 @@ class AccountSecretsViewSet(RecordViewLogMixin, AccountViewSet): """ serializer_classes = { 'default': serializers.AccountSecretSerializer, - 'histories': serializers.AccountHistorySerializer, } http_method_names = ['get', 'options'] # Todo: 记得打开 @@ -50,14 +49,21 @@ class AccountSecretsViewSet(RecordViewLogMixin, AccountViewSet): rbac_perms = { 'list': 'assets.view_accountsecret', 'retrieve': 'assets.view_accountsecret', - 'histories': ['assets.view_accountsecret'], } - @action(methods=['get'], detail=True, url_path='histories') - def histories(self, request, *args, **kwargs): - account = get_object_or_404(self.get_queryset(), **kwargs) - self.queryset = account.history.all() - return super().list(request, *args, **kwargs) + +class AccountHistoriesSecretAPI(RecordViewLogMixin, ListAPIView): + model = Account.history.model + serializer_class = serializers.AccountHistorySerializer + http_method_names = ['get', 'options'] + # Todo: 记得打开 + # permission_classes = [RBACPermission, UserConfirmation.require(ConfirmType.MFA)] + rbac_perms = { + 'list': 'assets.view_accountsecret', + } + + def get_queryset(self): + return self.model.objects.filter(id=self.kwargs.get('pk')) class AccountTaskCreateAPI(CreateAPIView): diff --git a/apps/assets/api/asset/asset.py b/apps/assets/api/asset/asset.py index f1d09f6a5..bcc4e99cf 100644 --- a/apps/assets/api/asset/asset.py +++ b/apps/assets/api/asset/asset.py @@ -12,7 +12,8 @@ from orgs.mixins import generics from assets import serializers from assets.models import Asset, Gateway from assets.tasks import ( - update_assets_hardware_info_manual, test_assets_connectivity_manual, + test_assets_connectivity_manual, + update_assets_hardware_info_manual, ) from assets.filters import NodeFilterBackend, LabelFilterBackend, IpInFilterBackend from ..mixin import NodeFilterMixin @@ -78,12 +79,10 @@ class AssetViewSet(SuggestionMixin, NodeFilterMixin, OrgBulkModelViewSet): class AssetsTaskMixin: def perform_assets_task(self, serializer): data = serializer.validated_data - action = data['action'] assets = data.get('assets', []) - if action == "refresh": + if data['action'] == "refresh": task = update_assets_hardware_info_manual.delay(assets) else: - # action == 'test': task = test_assets_connectivity_manual.delay(assets) return task diff --git a/apps/assets/api/node.py b/apps/assets/api/node.py index a32e6644d..85935dec2 100644 --- a/apps/assets/api/node.py +++ b/apps/assets/api/node.py @@ -4,11 +4,11 @@ from collections import namedtuple, defaultdict from django.core.exceptions import PermissionDenied from rest_framework import status +from rest_framework.generics import get_object_or_404 from rest_framework.serializers import ValidationError from rest_framework.response import Response from rest_framework.decorators import action from django.utils.translation import ugettext_lazy as _ -from django.shortcuts import get_object_or_404, Http404 from django.db.models.signals import m2m_changed from common.const.http import POST @@ -16,7 +16,7 @@ from common.exceptions import SomeoneIsDoingThis from common.const.signals import PRE_REMOVE, POST_REMOVE from common.mixins.api import SuggestionMixin from assets.models import Asset -from common.utils import get_logger, get_object_or_none +from common.utils import get_logger from common.tree import TreeNodeSerializer from orgs.mixins.api import OrgBulkModelViewSet from orgs.mixins import generics @@ -339,7 +339,7 @@ class NodeTaskCreateApi(generics.CreateAPIView): def get_object(self): node_id = self.kwargs.get('pk') - node = get_object_or_none(self.model, id=node_id) + node = get_object_or_404(self.model, id=node_id) return node @staticmethod @@ -361,8 +361,6 @@ class NodeTaskCreateApi(generics.CreateAPIView): task = self.refresh_nodes_cache() self.set_serializer_data(serializer, task) return - if node is None: - raise Http404() if action == "refresh": task = update_node_assets_hardware_info_manual.delay(node) else: diff --git a/apps/assets/automations/ping/manager.py b/apps/assets/automations/ping/manager.py index 791009e36..34c05a8f4 100644 --- a/apps/assets/automations/ping/manager.py +++ b/apps/assets/automations/ping/manager.py @@ -1,5 +1,5 @@ from common.utils import get_logger -from assets.const import AutomationTypes +from assets.const import AutomationTypes, Connectivity from ..base.manager import BasePlaybookManager logger = get_logger(__name__) @@ -8,13 +8,27 @@ logger = get_logger(__name__) class PingManager(BasePlaybookManager): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.host_asset_mapper = {} + self.host_asset_and_account_mapper = {} @classmethod def method_type(cls): return AutomationTypes.ping - def host_callback(self, host, asset=None, **kwargs): - super().host_callback(host, asset=asset, **kwargs) - self.host_asset_mapper[host['name']] = asset + def host_callback(self, host, asset=None, account=None, **kwargs): + super().host_callback(host, asset=asset, account=account, **kwargs) + self.host_asset_and_account_mapper[host['name']] = (asset, account) return host + + def on_host_success(self, host, result): + asset, account = self.host_asset_and_account_mapper.get(host) + asset.set_connectivity(Connectivity.ok) + if not account: + return + account.set_connectivity(Connectivity.ok) + + def on_host_error(self, host, error, result): + asset, account = self.host_asset_and_account_mapper.get(host) + asset.set_connectivity(Connectivity.failed) + if not account: + return + account.set_connectivity(Connectivity.failed) diff --git a/apps/assets/migrations/0108_auto_20221027_1053.py b/apps/assets/migrations/0108_auto_20221027_1053.py index c59dcf7e7..ac8069207 100644 --- a/apps/assets/migrations/0108_auto_20221027_1053.py +++ b/apps/assets/migrations/0108_auto_20221027_1053.py @@ -26,4 +26,16 @@ class Migration(migrations.Migration): name='type', field=models.CharField(choices=[('ping', 'Ping'), ('gather_facts', 'Gather facts'), ('push_account', 'Create account'), ('change_secret', 'Change secret'), ('verify_account', 'Verify account'), ('gather_accounts', 'Gather accounts')], max_length=16, verbose_name='Type'), ), + migrations.CreateModel( + name='PingAutomation', + fields=[ + ('baseautomation_ptr', + models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, + primary_key=True, serialize=False, to='assets.baseautomation')), + ], + options={ + 'verbose_name': 'Ping asset', + }, + bases=('assets.baseautomation',), + ), ] diff --git a/apps/assets/models/account.py b/apps/assets/models/account.py index 70ddc81b0..c2bb40a99 100644 --- a/apps/assets/models/account.py +++ b/apps/assets/models/account.py @@ -71,7 +71,7 @@ class Account(AbsConnectivity, BaseAccount): return self.asset.platform def __str__(self): - return '{}@{}'.format(self.username, self.asset.name) + return '{}'.format(self.username) @classmethod def get_input_account(cls): diff --git a/apps/assets/models/automations/__init__.py b/apps/assets/models/automations/__init__.py index 5c2a3e031..e579fc10f 100644 --- a/apps/assets/models/automations/__init__.py +++ b/apps/assets/models/automations/__init__.py @@ -4,3 +4,4 @@ from .push_account import * from .gather_facts import * from .gather_accounts import * from .verify_account import * +from .ping import * diff --git a/apps/assets/models/automations/base.py b/apps/assets/models/automations/base.py index a60a0e060..ac1fdb046 100644 --- a/apps/assets/models/automations/base.py +++ b/apps/assets/models/automations/base.py @@ -28,6 +28,15 @@ class BaseAutomation(CommonModelMixin, PeriodTaskModelMixin, OrgModelMixin): def __str__(self): return self.name + '@' + str(self.created_by) + @classmethod + def generate_unique_name(cls, name): + while True: + name = name + str(uuid.uuid4())[:8] + try: + cls.objects.get(name=name) + except cls.DoesNotExist: + return name + def get_all_assets(self): nodes = self.nodes.all() node_asset_ids = Node.get_nodes_all_assets(*nodes).values_list('id', flat=True) diff --git a/apps/assets/models/automations/ping.py b/apps/assets/models/automations/ping.py new file mode 100644 index 000000000..b327bc4ea --- /dev/null +++ b/apps/assets/models/automations/ping.py @@ -0,0 +1,15 @@ +from django.utils.translation import ugettext_lazy as _ + +from assets.const import AutomationTypes +from .base import BaseAutomation + +__all__ = ['PingAutomation'] + + +class PingAutomation(BaseAutomation): + def save(self, *args, **kwargs): + self.type = AutomationTypes.ping + super().save(*args, **kwargs) + + class Meta: + verbose_name = _("Ping asset") diff --git a/apps/assets/signal_handlers/asset.py b/apps/assets/signal_handlers/asset.py index 6caef6385..5aac26319 100644 --- a/apps/assets/signal_handlers/asset.py +++ b/apps/assets/signal_handlers/asset.py @@ -19,14 +19,12 @@ logger = get_logger(__file__) def update_asset_hardware_info_on_created(asset): logger.debug("Update asset `{}` hardware info".format(asset)) - # Todo: - # update_assets_hardware_info_util.delay([asset]) + update_assets_hardware_info_util.delay([asset]) def test_asset_conn_on_created(asset): logger.debug("Test asset `{}` connectivity".format(asset)) - # Todo: - # test_asset_connectivity_util.delay([asset]) + test_asset_connectivity_util.delay([asset]) @receiver(pre_save, sender=Node) diff --git a/apps/assets/tasks/asset_connectivity.py b/apps/assets/tasks/asset_connectivity.py index ce379832a..68bfe7e6b 100644 --- a/apps/assets/tasks/asset_connectivity.py +++ b/apps/assets/tasks/asset_connectivity.py @@ -1,124 +1,50 @@ # ~*~ coding: utf-8 ~*~ -from itertools import groupby -from collections import defaultdict from celery import shared_task from django.utils.translation import gettext_noop from common.utils import get_logger from orgs.utils import org_aware_func, tmp_to_root_org -from ..models import Asset, Connectivity, Account, Node -from . import const -from .utils import clean_ansible_task_hosts, group_asset_by_platform - logger = get_logger(__file__) __all__ = [ - 'test_asset_connectivity_util', 'test_asset_connectivity_manual', - 'test_node_assets_connectivity_manual', 'test_assets_connectivity_manual', + 'test_asset_connectivity_util', + 'test_assets_connectivity_manual', + 'test_node_assets_connectivity_manual', ] -# Todo: 这里可能有问题了 -def set_assets_accounts_connectivity(assets, results_summary): - asset_ids_ok = set() - asset_ids_failed = set() - - asset_hostnames_ok = results_summary.get('contacted', {}).keys() - - for asset in assets: - if asset.name in asset_hostnames_ok: - asset_ids_ok.add(asset.id) - else: - asset_ids_failed.add(asset.id) - - Asset.bulk_set_connectivity(asset_ids_ok, Connectivity.ok) - Asset.bulk_set_connectivity(asset_ids_failed, Connectivity.failed) - - accounts_ok = Account.objects.filter(asset_id__in=asset_ids_ok,) - accounts_failed = Account.objects.filter(asset_id__in=asset_ids_faile) - - Account.bulk_set_connectivity(accounts_ok, Connectivity.ok) - Account.bulk_set_connectivity(accounts_failed, Connectivity.failed) - - @org_aware_func('assets') def test_asset_connectivity_util(assets, task_name=None): - from ops.utils import update_or_create_ansible_task - + from assets.models import PingAutomation if task_name is None: task_name = gettext_noop("Test assets connectivity. ") - hosts = clean_ansible_task_hosts(assets) - if not hosts: - return {} - platform_hosts_map = {} - hosts_sorted = sorted(hosts, key=group_asset_by_platform) - platform_hosts = groupby(hosts_sorted, key=group_asset_by_platform) - for i in platform_hosts: - platform_hosts_map[i[0]] = list(i[1]) - - platform_tasks_map = { - "unixlike": const.PING_UNIXLIKE_TASKS, - "windows": const.PING_WINDOWS_TASKS + task_name = PingAutomation.generate_unique_name(task_name) + data = { + 'name': task_name, + 'comment': ', '.join([str(i) for i in assets]) } - results_summary = dict( - contacted=defaultdict(dict), dark=defaultdict(dict), success=True - ) - for platform, _hosts in platform_hosts_map.items(): - if not _hosts: - continue - logger.debug("System user not has special auth") - tasks = platform_tasks_map.get(platform) - task, created = update_or_create_ansible_task( - task_name=task_name, hosts=_hosts, tasks=tasks, - pattern='all', options=const.TASK_OPTIONS, run_as_admin=True, - ) - raw, summary = task.run() - success = summary.get('success', False) - contacted = summary.get('contacted', {}) - dark = summary.get('dark', {}) - - results_summary['success'] &= success - results_summary['contacted'].update(contacted) - results_summary['dark'].update(dark) - continue - set_assets_accounts_connectivity(assets, results_summary) - return results_summary - - -@shared_task(queue="ansible") -def test_asset_connectivity_manual(asset_id): - asset = Asset.objects.filter(id=asset_id).first() - if not asset: - return - task_name = gettext_noop("Test assets connectivity: ") + str(asset) - summary = test_asset_connectivity_util([asset], task_name=task_name) - - if summary.get('dark'): - return False, summary['dark'] - else: - return True, "" + instance = PingAutomation.objects.create(**data) + instance.assets.add(*assets) + instance.execute() @shared_task(queue="ansible") def test_assets_connectivity_manual(asset_ids): + from assets.models import Asset with tmp_to_root_org(): assets = Asset.objects.filter(id__in=asset_ids) - task_name = gettext_noop("Test assets connectivity: ") + str([asset.name for asset in assets]) - summary = test_asset_connectivity_util(assets, task_name=task_name) - if summary.get('dark'): - return False, summary['dark'] - else: - return True, "" + task_name = gettext_noop("Test assets connectivity: ") + test_asset_connectivity_util(assets, task_name=task_name) @shared_task(queue="ansible") def test_node_assets_connectivity_manual(node_id): + from assets.models import Node with tmp_to_root_org(): node = Node.objects.get(id=node_id) - task_name = gettext_noop("Test if the assets under the node are connectable: ") + node.name + task_name = gettext_noop("Test if the assets under the node are connectable: ") assets = node.get_all_assets() - result = test_asset_connectivity_util(assets, task_name=task_name) - return result + test_asset_connectivity_util(assets, task_name=task_name) diff --git a/apps/assets/tasks/gather_asset_hardware_info.py b/apps/assets/tasks/gather_asset_hardware_info.py index 1973dd4ff..9c667a078 100644 --- a/apps/assets/tasks/gather_asset_hardware_info.py +++ b/apps/assets/tasks/gather_asset_hardware_info.py @@ -1,149 +1,50 @@ # -*- coding: utf-8 -*- # -import json -import re - from celery import shared_task -from django.utils.translation import ugettext as _, gettext_noop +from django.utils.translation import gettext_noop -from common.utils import ( - capacity_convert, sum_capacity, get_logger -) +from common.utils import get_logger from orgs.utils import org_aware_func, tmp_to_root_org -from . import const -from ..models import Asset, Node -from .utils import clean_ansible_task_hosts - logger = get_logger(__file__) -disk_pattern = re.compile(r'^hd|sd|xvd|vd|nv') __all__ = [ - 'update_assets_hardware_info_util', 'update_asset_hardware_info_manual', - 'update_assets_hardware_info_period', 'update_node_assets_hardware_info_manual', + 'update_assets_hardware_info_util', + 'update_node_assets_hardware_info_manual', 'update_assets_hardware_info_manual', ] -def set_assets_hardware_info(assets, result, **kwargs): - """ - Using ops task run result, to update asset info - - be a celery task also - :param assets: - :param result: - :param kwargs: {task_name: ""} - :return: - """ - result_raw = result[0] - assets_updated = [] - success_result = result_raw.get('ok', {}) - - for asset in assets: - hostname = asset.name - info = success_result.get(hostname, {}) - info = info.get('setup', {}).get('ansible_facts', {}) - if not info: - logger.error(_("Get asset info failed: {}").format(hostname)) - continue - ___vendor = info.get('ansible_system_vendor', 'Unknown') - ___model = info.get('ansible_product_name', 'Unknown') - ___sn = info.get('ansible_product_serial', 'Unknown') - - for ___cpu_model in info.get('ansible_processor', []): - if ___cpu_model.endswith('GHz') or ___cpu_model.startswith("Intel"): - break - else: - ___cpu_model = 'Unknown' - ___cpu_model = ___cpu_model[:48] - ___cpu_count = info.get('ansible_processor_count', 0) - ___cpu_cores = info.get('ansible_processor_cores', None) or \ - len(info.get('ansible_processor', [])) - ___cpu_vcpus = info.get('ansible_processor_vcpus', 0) - ___memory = '%s %s' % capacity_convert( - '{} MB'.format(info.get('ansible_memtotal_mb')) - ) - disk_info = {} - for dev, dev_info in info.get('ansible_devices', {}).items(): - if disk_pattern.match(dev) and dev_info['removable'] == '0': - disk_info[dev] = dev_info['size'] - ___disk_total = '%.1f %s' % sum_capacity(disk_info.values()) - ___disk_info = json.dumps(disk_info) - - # ___platform = info.get('ansible_system', 'Unknown') - ___os = info.get('ansible_distribution', 'Unknown') - ___os_version = info.get('ansible_distribution_version', 'Unknown') - ___os_arch = info.get('ansible_architecture', 'Unknown') - ___hostname_raw = info.get('ansible_hostname', 'Unknown') - - for k, v in locals().items(): - if k.startswith('___'): - setattr(asset, k.strip('_'), v) - asset.save() - assets_updated.append(asset) - return assets_updated - - @org_aware_func('assets') def update_assets_hardware_info_util(assets, task_name=None): - """ - Using ansible api to update asset hardware info - :param asset_ids: asset seq - :param task_name: task_name running - :return: result summary ['contacted': {}, 'dark': {}] - """ - - from ops.utils import update_or_create_ansible_task + from assets.models import GatherFactsAutomation if task_name is None: task_name = gettext_noop("Update some assets hardware info. ") - tasks = const.UPDATE_ASSETS_HARDWARE_TASKS - hosts = clean_ansible_task_hosts(assets) - if not hosts: - return {} - task, created = update_or_create_ansible_task( - task_name, hosts=hosts, tasks=tasks, - pattern='all', options=const.TASK_OPTIONS, - run_as_admin=True, - ) - result = task.run() - set_assets_hardware_info(assets, result) - return True - -@shared_task(queue="ansible") -def update_asset_hardware_info_manual(asset_id): - with tmp_to_root_org(): - asset = Asset.objects.filter(id=asset_id).first() - if not asset: - return - task_name = gettext_noop("Update asset hardware info: ") + str(asset.name) - update_assets_hardware_info_util([asset], task_name=task_name) + task_name = GatherFactsAutomation.generate_unique_name(task_name) + data = { + 'name': task_name, + 'comment': ', '.join([str(i) for i in assets]) + } + instance = GatherFactsAutomation.objects.create(**data) + instance.assets.add(*assets) + instance.execute() @shared_task(queue="ansible") def update_assets_hardware_info_manual(asset_ids): - task_name = gettext_noop("Update assets hardware info: ") + str([asset.name for asset in assets]) - update_assets_hardware_info_util(asset_ids, task_name=task_name) - - -@shared_task(queue="ansible") -def update_assets_hardware_info_period(): - """ - Update asset hardware period task - :return: - """ - if not const.PERIOD_TASK_ENABLED: - logger.debug("Period task disabled, update assets hardware info pass") - return + from assets.models import Asset + with tmp_to_root_org(): + assets = Asset.objects.filter(id__in=asset_ids) + task_name = gettext_noop("Update assets hardware info: ") + update_assets_hardware_info_util(assets, task_name=task_name) @shared_task(queue="ansible") def update_node_assets_hardware_info_manual(node_id): + from assets.models import Node with tmp_to_root_org(): - node = Node.objects.filter(id=node_id).first() - if not node: - return + node = Node.objects.get(id=node_id) - task_name = gettext_noop("Update node asset hardware information: ") + str(node.name) + task_name = gettext_noop("Update node asset hardware information: ") assets = node.get_all_assets() - result = update_assets_hardware_info_util(assets, task_name=task_name) - return result + update_assets_hardware_info_util(assets, task_name=task_name) diff --git a/apps/assets/urls/api_urls.py b/apps/assets/urls/api_urls.py index 688319ef6..f1c286054 100644 --- a/apps/assets/urls/api_urls.py +++ b/apps/assets/urls/api_urls.py @@ -37,6 +37,7 @@ urlpatterns = [ path('assets//perm-user-groups//permissions/', api.AssetPermUserGroupPermissionsListApi.as_view(), name='asset-perm-user-group-permission-list'), path('accounts/tasks/', api.AccountTaskCreateAPI.as_view(), name='account-task-create'), + path('account-secrets//histories/', api.AccountHistoriesSecretAPI.as_view(), name='account-secret-history'), path('nodes/category/tree/', api.CategoryTreeApi.as_view(), name='asset-category-tree'), path('nodes/tree/', api.NodeListAsTreeApi.as_view(), name='node-tree'), diff --git a/apps/locale/ja/LC_MESSAGES/django.mo b/apps/locale/ja/LC_MESSAGES/django.mo index cbc8ff533..c95e1d78e 100644 --- a/apps/locale/ja/LC_MESSAGES/django.mo +++ b/apps/locale/ja/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e0070188de11b8ace3a23cdf03ac803b50bf98beccef49b94bcfd0131fea8604 -size 119875 +oid sha256:c4c889e251a4de3161f462e042882ba3c4ab40eaf34799e2d49d4788ad961586 +size 119171 diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 545f1231e..4b15fdcde 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: 2022-10-26 16:41+0800\n" +"POT-Creation-Date: 2022-11-01 15:30+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -32,7 +32,7 @@ msgstr "Acls" #: assets/serializers/platform.py:104 ops/mixin.py:20 ops/models/playbook.py:9 #: orgs/models.py:70 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:25 terminal/models/component/endpoint.py:11 +#: terminal/models/applet/applet.py:20 terminal/models/component/endpoint.py:11 #: terminal/models/component/endpoint.py:87 #: terminal/models/component/storage.py:25 terminal/models/component/task.py:16 #: terminal/models/component/terminal.py:100 users/forms/profile.py:33 @@ -51,7 +51,7 @@ msgstr "優先順位" msgid "1-100, the lower the value will be match first" msgstr "1-100、低い値は最初に一致します" -#: acls/models/base.py:31 authentication/models.py:22 +#: acls/models/base.py:31 authentication/models/access_key.py:15 #: authentication/templates/authentication/_access_key_modal.html:32 #: perms/models/asset_permission.py:74 terminal/models/session/sharing.py:28 #: tickets/const.py:38 @@ -59,17 +59,17 @@ msgid "Active" msgstr "アクティブ" #: acls/models/base.py:32 applications/models.py:19 assets/models/_user.py:40 -#: assets/models/asset/common.py:100 assets/models/automations/base.py:25 +#: assets/models/asset/common.py:100 assets/models/automations/base.py:26 #: assets/models/backup.py:30 assets/models/base.py:66 #: assets/models/cmd_filter.py:40 assets/models/cmd_filter.py:88 #: assets/models/domain.py:25 assets/models/domain.py:69 #: assets/models/group.py:23 assets/models/label.py:22 #: assets/models/platform.py:73 ops/models/playbook.py:11 -#: ops/models/playbook.py:25 orgs/models.py:73 +#: ops/models/playbook.py:25 orgs/models.py:74 #: perms/models/asset_permission.py:84 rbac/models/role.py:37 -#: settings/models.py:38 terminal/models/applet/applet.py:33 -#: terminal/models/applet/applet.py:62 terminal/models/applet/host.py:12 -#: terminal/models/applet/host.py:28 terminal/models/component/endpoint.py:24 +#: settings/models.py:38 terminal/models/applet/applet.py:28 +#: terminal/models/applet/applet.py:58 terminal/models/applet/host.py:34 +#: terminal/models/component/endpoint.py:24 #: terminal/models/component/endpoint.py:97 #: terminal/models/component/storage.py:28 #: terminal/models/component/terminal.py:114 tickets/models/comment.py:32 @@ -96,8 +96,9 @@ msgstr "ログイン確認" #: acls/models/login_acl.py:24 acls/models/login_asset_acl.py:20 #: assets/models/cmd_filter.py:28 assets/models/label.py:15 audits/models.py:37 -#: audits/models.py:62 audits/models.py:87 authentication/models.py:55 -#: authentication/models.py:72 perms/models/asset_permission.py:58 +#: audits/models.py:62 audits/models.py:87 +#: authentication/models/connection_token.py:22 +#: authentication/models/sso_token.py:15 perms/models/asset_permission.py:58 #: rbac/builtin.py:120 rbac/models/rolebinding.py:41 #: terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 @@ -129,7 +130,7 @@ msgid "Login acl" msgstr "ログインacl" #: acls/models/login_asset_acl.py:21 assets/models/account.py:57 -#: authentication/models.py:82 ops/models/base.py:18 +#: authentication/models/connection_token.py:33 ops/models/base.py:18 #: terminal/models/session/session.py:34 xpack/plugins/cloud/models.py:87 #: xpack/plugins/cloud/serializers/task.py:65 msgid "Account" @@ -139,7 +140,7 @@ msgstr "アカウント" #: assets/models/asset/common.py:83 assets/models/asset/common.py:227 #: assets/models/cmd_filter.py:36 assets/models/gathered_user.py:14 #: assets/serializers/account/account.py:58 assets/serializers/label.py:30 -#: audits/models.py:39 authentication/models.py:77 +#: audits/models.py:39 authentication/models/connection_token.py:26 #: perms/models/asset_permission.py:64 terminal/backends/command/models.py:21 #: terminal/backends/command/serializers.py:14 #: terminal/models/session/session.py:32 terminal/notifications.py:90 @@ -165,7 +166,7 @@ msgstr "コンマ区切り文字列の形式。* はすべて一致すること #: acls/serializers/login_asset_acl.py:52 assets/models/_user.py:34 #: assets/models/base.py:60 assets/models/gathered_user.py:15 #: audits/models.py:121 authentication/forms.py:25 authentication/forms.py:27 -#: authentication/models.py:245 +#: authentication/models/temp_token.py:9 #: authentication/templates/authentication/_msg_different_city.html:9 #: authentication/templates/authentication/_msg_oauth_bind.html:9 #: users/forms/profile.py:32 users/models/user.py:663 @@ -250,9 +251,9 @@ msgid "Category" msgstr "カテゴリ" #: applications/models.py:15 assets/models/_user.py:46 -#: assets/models/automations/base.py:23 assets/models/cmd_filter.py:74 +#: assets/models/automations/base.py:24 assets/models/cmd_filter.py:74 #: assets/models/platform.py:70 assets/serializers/asset/common.py:63 -#: assets/serializers/platform.py:75 terminal/models/applet/applet.py:29 +#: assets/serializers/platform.py:75 terminal/models/applet/applet.py:24 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:142 terminal/serializers/applet.py:20 #: tickets/models/comment.py:26 tickets/models/flow.py:57 @@ -296,7 +297,7 @@ msgstr "削除に失敗し、ノードにアセットが含まれています。 msgid "App assets" msgstr "アプリ資産" -#: assets/automations/base/manager.py:74 +#: assets/automations/base/manager.py:122 #, fuzzy #| msgid "Disabled" msgid "{} disabled" @@ -312,7 +313,7 @@ msgstr "不明" msgid "Ok" msgstr "OK" -#: assets/const/account.py:8 audits/models.py:118 +#: assets/const/account.py:8 audits/models.py:118 common/const/choices.py:18 #: xpack/plugins/change_auth_plan/serializers/asset.py:190 #: xpack/plugins/cloud/const.py:33 msgid "Failed" @@ -343,12 +344,12 @@ msgid "SSH key" msgstr "SSHキー" #: assets/const/account.py:14 assets/models/base.py:55 -#: authentication/models.py:38 +#: authentication/models/access_key.py:31 msgid "Access key" msgstr "アクセスキー" #: assets/const/account.py:15 assets/models/_user.py:38 -#: assets/models/base.py:56 authentication/models.py:53 +#: assets/models/base.py:56 authentication/models/sso_token.py:13 msgid "Token" msgstr "トークン" @@ -380,8 +381,10 @@ msgstr "秘密を改める" msgid "Verify account" msgstr "パスワード/キーの確認" -#: assets/const/automation.py:18 rbac/tree.py:53 -msgid "Gather account" +#: assets/const/automation.py:18 +#, fuzzy +#| msgid "Gather account" +msgid "Gather accounts" msgstr "アカウントを集める" #: assets/const/automation.py:22 @@ -414,8 +417,8 @@ msgid "Replace (The key generated by JumpServer) " msgstr "置換(JumpServerによって生成された鍵)" #: assets/const/category.py:11 settings/serializers/auth/radius.py:14 -#: settings/serializers/auth/sms.py:56 terminal/models/applet/applet.py:60 -#: terminal/models/applet/host.py:11 terminal/models/component/endpoint.py:12 +#: settings/serializers/auth/sms.py:56 terminal/models/applet/applet.py:56 +#: terminal/models/component/endpoint.py:12 #: xpack/plugins/cloud/serializers/account_attrs.py:72 msgid "Host" msgstr "ホスト" @@ -496,11 +499,11 @@ msgstr "SSH秘密鍵" msgid "SSH public key" msgstr "SSHパブリックキー" -#: assets/models/_user.py:41 assets/models/automations/base.py:86 +#: assets/models/_user.py:41 assets/models/automations/base.py:87 #: assets/models/base.py:67 assets/models/domain.py:26 #: assets/models/gathered_user.py:19 assets/models/group.py:22 #: common/db/models.py:76 common/mixins/models.py:50 ops/models/base.py:53 -#: orgs/models.py:72 perms/models/asset_permission.py:82 +#: orgs/models.py:73 perms/models/asset_permission.py:82 #: users/models/group.py:18 users/models/user.py:927 msgid "Date created" msgstr "作成された日付" @@ -525,7 +528,8 @@ msgid "Username same with user" msgstr "ユーザーと同じユーザー名" #: assets/models/_user.py:48 assets/models/domain.py:67 -#: terminal/models/applet/applet.py:31 terminal/serializers/session.py:18 +#: authentication/models/connection_token.py:29 +#: terminal/models/applet/applet.py:26 terminal/serializers/session.py:18 #: terminal/serializers/session.py:32 terminal/serializers/storage.py:68 msgid "Protocol" msgstr "プロトコル" @@ -585,7 +589,7 @@ msgid "Su from" msgstr "から切り替え" #: assets/models/account.py:53 settings/serializers/auth/cas.py:18 -#: terminal/models/applet/applet.py:27 +#: terminal/models/applet/applet.py:22 msgid "Version" msgstr "バージョン" @@ -630,16 +634,16 @@ msgstr "プラットフォーム" msgid "Domain" msgstr "ドメイン" -#: assets/models/asset/common.py:97 assets/models/automations/base.py:18 +#: assets/models/asset/common.py:97 assets/models/automations/base.py:19 #: assets/serializers/asset/common.py:66 perms/models/asset_permission.py:67 #: xpack/plugins/change_auth_plan/models/asset.py:44 #: xpack/plugins/gathered_user/models.py:24 msgid "Nodes" msgstr "ノード" -#: assets/models/asset/common.py:98 assets/models/automations/base.py:24 +#: assets/models/asset/common.py:98 assets/models/automations/base.py:25 #: assets/models/cmd_filter.py:39 assets/models/domain.py:70 -#: assets/models/label.py:21 terminal/models/applet/applet.py:30 +#: assets/models/label.py:21 terminal/models/applet/applet.py:25 #: users/serializers/user.py:147 msgid "Is active" msgstr "アクティブです。" @@ -706,28 +710,29 @@ msgstr "パスワードルール" msgid "Submit selector" msgstr "" -#: assets/models/automations/base.py:16 assets/models/cmd_filter.py:38 +#: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38 #: assets/serializers/asset/common.py:68 perms/models/asset_permission.py:70 #: rbac/tree.py:37 msgid "Accounts" msgstr "アカウント" -#: assets/models/automations/base.py:21 assets/serializers/domain.py:29 +#: assets/models/automations/base.py:22 assets/serializers/domain.py:29 #: ops/models/base.py:17 #: terminal/templates/terminal/_msg_command_execute_alert.html:16 #: xpack/plugins/change_auth_plan/models/asset.py:40 msgid "Assets" msgstr "資産" -#: assets/models/automations/base.py:76 assets/models/automations/base.py:83 +#: assets/models/automations/base.py:77 assets/models/automations/base.py:84 #, fuzzy #| msgid "Automatic managed" msgid "Automation task" msgstr "自動管理" -#: assets/models/automations/base.py:87 assets/models/backup.py:77 +#: assets/models/automations/base.py:88 assets/models/backup.py:77 #: audits/models.py:44 ops/models/base.py:54 -#: perms/models/asset_permission.py:76 terminal/models/session/session.py:43 +#: perms/models/asset_permission.py:76 terminal/models/applet/host.py:32 +#: terminal/models/session/session.py:43 #: tickets/models/ticket/apply_application.py:28 #: tickets/models/ticket/apply_asset.py:21 #: xpack/plugins/change_auth_plan/models/base.py:108 @@ -736,63 +741,65 @@ msgstr "自動管理" msgid "Date start" msgstr "開始日" -#: assets/models/automations/base.py:88 -#: assets/models/automations/change_secret.py:59 ops/models/base.py:55 +#: assets/models/automations/base.py:89 +#: assets/models/automations/change_secret.py:58 ops/models/base.py:55 +#: terminal/models/applet/host.py:33 msgid "Date finished" msgstr "終了日" -#: assets/models/automations/base.py:90 +#: assets/models/automations/base.py:91 #, fuzzy #| msgid "Relation snapshot" msgid "Automation snapshot" msgstr "製造オーダスナップショット" -#: assets/models/automations/base.py:94 assets/models/backup.py:88 +#: assets/models/automations/base.py:95 assets/models/backup.py:88 #: assets/serializers/account/backup.py:36 #: xpack/plugins/change_auth_plan/models/base.py:121 #: xpack/plugins/change_auth_plan/serializers/base.py:78 msgid "Trigger mode" msgstr "トリガーモード" -#: assets/models/automations/base.py:98 +#: assets/models/automations/base.py:99 #, fuzzy #| msgid "Command execution" msgid "Automation task execution" msgstr "コマンド実行" -#: assets/models/automations/change_secret.py:16 assets/models/base.py:62 +#: assets/models/automations/change_secret.py:15 assets/models/base.py:62 #, fuzzy #| msgid "Secret key" msgid "Secret type" msgstr "秘密キー" -#: assets/models/automations/change_secret.py:20 +#: assets/models/automations/change_secret.py:19 #, fuzzy #| msgid "SSH Key strategy" msgid "Secret strategy" msgstr "SSHキー戦略" -#: assets/models/automations/change_secret.py:22 -#: assets/models/automations/change_secret.py:57 assets/models/base.py:64 -#: assets/serializers/account/base.py:17 authentication/models.py:66 -#: authentication/models.py:246 +#: assets/models/automations/change_secret.py:21 +#: assets/models/automations/change_secret.py:56 assets/models/base.py:64 +#: assets/serializers/account/base.py:17 +#: authentication/models/connection_token.py:34 +#: authentication/models/temp_token.py:10 #: authentication/templates/authentication/_access_key_modal.html:31 #: settings/serializers/auth/radius.py:17 msgid "Secret" msgstr "ひみつ" -#: assets/models/automations/change_secret.py:23 +#: assets/models/automations/change_secret.py:22 #: xpack/plugins/change_auth_plan/models/base.py:39 msgid "Password rules" msgstr "パスワードルール" -#: assets/models/automations/change_secret.py:26 +#: assets/models/automations/change_secret.py:25 #, fuzzy #| msgid "SSH Key strategy" msgid "SSH key change strategy" msgstr "SSHキー戦略" -#: assets/models/automations/change_secret.py:28 assets/models/backup.py:28 +#: assets/models/automations/change_secret.py:27 assets/models/backup.py:28 #: assets/serializers/account/backup.py:28 #: xpack/plugins/change_auth_plan/models/app.py:40 #: xpack/plugins/change_auth_plan/models/asset.py:63 @@ -800,31 +807,31 @@ msgstr "SSHキー戦略" msgid "Recipient" msgstr "受信者" -#: assets/models/automations/change_secret.py:35 +#: assets/models/automations/change_secret.py:34 #, fuzzy #| msgid "Change auth" msgid "Change secret automation" msgstr "秘密を改める" -#: assets/models/automations/change_secret.py:56 +#: assets/models/automations/change_secret.py:55 #, fuzzy #| msgid "Secret" msgid "Old secret" msgstr "ひみつ" -#: assets/models/automations/change_secret.py:58 +#: assets/models/automations/change_secret.py:57 #, fuzzy #| msgid "Date start" msgid "Date started" msgstr "開始日" -#: assets/models/automations/change_secret.py:61 +#: assets/models/automations/change_secret.py:60 common/const/choices.py:19 #, fuzzy #| msgid "WeCom Error" msgid "Error" msgstr "企業微信エラー" -#: assets/models/automations/change_secret.py:64 +#: assets/models/automations/change_secret.py:63 #, fuzzy #| msgid "Change auth" msgid "Change secret record" @@ -836,22 +843,28 @@ msgstr "秘密を改める" msgid "Discovery account automation" msgstr "パスワード/キーの確認" +#: assets/models/automations/gather_accounts.py:15 +#, fuzzy +#| msgid "Gather assets users" +msgid "Gather asset accounts" +msgstr "資産ユーザーの収集" + #: assets/models/automations/gather_facts.py:15 #, fuzzy #| msgid "Gather assets users" msgid "Gather asset facts" msgstr "資産ユーザーの収集" -#: assets/models/automations/push_account.py:8 +#: assets/models/automations/push_account.py:16 #, fuzzy -#| msgid "Automatic managed" -msgid "Push automation" -msgstr "自動管理" +#| msgid "Is service account" +msgid "Push asset account" +msgstr "サービスアカウントです" -#: assets/models/automations/verify_secret.py:8 +#: assets/models/automations/verify_account.py:15 #, fuzzy #| msgid "Verify auth" -msgid "Verify account automation" +msgid "Verify asset account" msgstr "パスワード/キーの確認" #: assets/models/backup.py:38 assets/models/backup.py:96 @@ -893,7 +906,7 @@ msgstr "アカウントバックアップの実行" msgid "Connectivity" msgstr "接続性" -#: assets/models/base.py:32 authentication/models.py:248 +#: assets/models/base.py:32 authentication/models/temp_token.py:12 msgid "Date verified" msgstr "確認済みの日付" @@ -1352,7 +1365,6 @@ msgid "Category display" msgstr "カテゴリ表示" #: assets/serializers/mixin.py:10 audits/serializers.py:27 -#: authentication/serializers/connection_token.py:20 #: tickets/serializers/flow.py:49 tickets/serializers/ticket/ticket.py:17 msgid "Type display" msgstr "タイプ表示" @@ -1527,7 +1539,7 @@ msgstr "操作" msgid "Filename" msgstr "ファイル名" -#: audits/models.py:43 audits/models.py:117 +#: audits/models.py:43 audits/models.py:117 common/const/choices.py:17 #: terminal/models/session/sharing.py:104 tickets/views/approve.py:114 #: xpack/plugins/change_auth_plan/serializers/asset.py:189 msgid "Success" @@ -1607,8 +1619,8 @@ msgid "MFA" msgstr "MFA" #: audits/models.py:128 ops/models/base.py:48 -#: terminal/models/applet/applet.py:61 terminal/models/applet/host.py:15 -#: terminal/models/applet/host.py:27 terminal/models/component/status.py:33 +#: terminal/models/applet/applet.py:57 terminal/models/applet/host.py:19 +#: terminal/models/applet/host.py:31 terminal/models/component/status.py:33 #: tickets/models/ticket/general.py:281 xpack/plugins/cloud/models.py:171 #: xpack/plugins/cloud/models.py:223 msgid "Status" @@ -1672,7 +1684,7 @@ msgstr "本を飛ばす" msgid "DingTalk" msgstr "DingTalk" -#: audits/signal_handlers.py:56 authentication/models.py:252 +#: audits/signal_handlers.py:56 authentication/models/temp_token.py:16 msgid "Temporary token" msgstr "仮パスワード" @@ -1825,7 +1837,7 @@ msgstr "" msgid "Invalid token or cache refreshed." msgstr "無効なトークンまたはキャッシュの更新。" -#: authentication/backends/oauth2/backends.py:155 authentication/models.py:143 +#: authentication/backends/oauth2/backends.py:155 msgid "User invalid, disabled or expired" msgstr "ユーザーが無効、無効、または期限切れです" @@ -2088,91 +2100,76 @@ msgstr "MFAタイプ ({}) が有効になっていない" msgid "Please change your password" msgstr "パスワードを変更してください" -#: authentication/models.py:45 -msgid "Private Token" -msgstr "プライベートトークン" +#: authentication/models/connection_token.py:31 +#: rbac/serializers/rolebinding.py:21 +msgid "User display" +msgstr "ユーザー表示" -#: authentication/models.py:54 -msgid "Expired" -msgstr "期限切れ" +#: authentication/models/connection_token.py:32 +msgid "Asset display" +msgstr "アセット名" -#: authentication/models.py:58 -msgid "SSO token" -msgstr "SSO token" - -#: authentication/models.py:68 authentication/models.py:249 -#: perms/models/asset_permission.py:79 +#: authentication/models/connection_token.py:36 +#: authentication/models/temp_token.py:13 perms/models/asset_permission.py:79 #: tickets/models/ticket/apply_application.py:29 #: tickets/models/ticket/apply_asset.py:22 users/models/user.py:707 msgid "Date expired" msgstr "期限切れの日付" -#: authentication/models.py:75 rbac/serializers/rolebinding.py:21 -msgid "User display" -msgstr "ユーザー表示" - -#: authentication/models.py:80 -msgid "Asset display" -msgstr "アセット名" - -#: authentication/models.py:85 -#, fuzzy -#| msgid "Action display" -msgid "Account display" -msgstr "アクション表示" - -#: authentication/models.py:89 +#: authentication/models/connection_token.py:41 msgid "Connection token" msgstr "接続トークン" -#: authentication/models.py:91 +#: authentication/models/connection_token.py:43 msgid "Can view connection token secret" msgstr "接続トークンの秘密を表示できます" -#: authentication/models.py:134 +#: authentication/models/connection_token.py:82 msgid "Connection token expired at: {}" msgstr "接続トークンの有効期限: {}" -#: authentication/models.py:139 -msgid "User not exists" -msgstr "ユーザーは存在しません" +#: authentication/models/connection_token.py:86 +msgid "No user or invalid user" +msgstr "" -#: authentication/models.py:148 -msgid "System user not exists" -msgstr "システムユーザーが存在しません" - -#: authentication/models.py:154 -msgid "Asset not exists" -msgstr "アセットが存在しません" - -#: authentication/models.py:158 -msgid "Asset inactive" +#: authentication/models/connection_token.py:90 +#, fuzzy +#| msgid "Asset inactive" +msgid "No asset or inactive asset" msgstr "アセットがアクティブ化されていません" -#: authentication/models.py:165 +#: authentication/models/connection_token.py:94 +#, fuzzy +#| msgid "Login acl" +msgid "No account" +msgstr "ログインacl" + +#: authentication/models/connection_token.py:103 msgid "User has no permission to access asset or permission expired" msgstr "" "ユーザーがアセットにアクセスする権限を持っていないか、権限の有効期限が切れて" "います" -#: authentication/models.py:173 -msgid "Application not exists" -msgstr "アプリが存在しません" - -#: authentication/models.py:180 -msgid "User has no permission to access application or permission expired" -msgstr "" -"ユーザーがアプリにアクセスする権限を持っていないか、権限の有効期限が切れてい" -"ます" - -#: authentication/models.py:247 -msgid "Verified" -msgstr "確認済み" - -#: authentication/models.py:268 +#: authentication/models/connection_token.py:145 msgid "Super connection token" msgstr "スーパー接続トークン" +#: authentication/models/private_token.py:9 +msgid "Private Token" +msgstr "プライベートトークン" + +#: authentication/models/sso_token.py:14 +msgid "Expired" +msgstr "期限切れ" + +#: authentication/models/sso_token.py:18 +msgid "SSO token" +msgstr "SSO token" + +#: authentication/models/temp_token.py:11 +msgid "Verified" +msgstr "確認済み" + #: authentication/notifications.py:19 msgid "Different city login reminder" msgstr "異なる都市ログインのリマインダー" @@ -2181,19 +2178,15 @@ msgstr "異なる都市ログインのリマインダー" msgid "binding reminder" msgstr "バインディングリマインダー" -#: authentication/serializers/connection_token.py:21 +#: authentication/serializers/connection_token.py:20 #: xpack/plugins/cloud/models.py:36 msgid "Validity" msgstr "有効性" -#: authentication/serializers/connection_token.py:22 +#: authentication/serializers/connection_token.py:21 msgid "Expired time" msgstr "期限切れ時間" -#: authentication/serializers/connection_token.py:68 -msgid "Asset or application required" -msgstr "アセットまたはアプリが必要" - #: authentication/serializers/token.py:79 perms/serializers/permission.py:60 #: perms/serializers/permission.py:87 users/serializers/user.py:148 msgid "Is valid" @@ -2282,7 +2275,7 @@ msgstr "コードエラー" #: authentication/templates/authentication/_msg_reset_password.html:3 #: authentication/templates/authentication/_msg_rest_password_success.html:2 #: authentication/templates/authentication/_msg_rest_public_key_success.html:2 -#: jumpserver/conf.py:390 ops/tasks.py:146 ops/tasks.py:152 ops/tasks.py:155 +#: jumpserver/conf.py:390 ops/tasks.py:147 ops/tasks.py:153 ops/tasks.py:156 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: perms/templates/perms/_msg_permed_items_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:33 @@ -2583,6 +2576,20 @@ msgstr "手動トリガー" msgid "Timing trigger" msgstr "タイミングトリガー" +#: common/const/choices.py:15 tickets/const.py:29 tickets/const.py:37 +msgid "Pending" +msgstr "未定" + +#: common/const/choices.py:16 +msgid "Running" +msgstr "" + +#: common/const/choices.py:20 +#, fuzzy +#| msgid "Cancel" +msgid "Canceled" +msgstr "キャンセル" + #: common/db/encoder.py:11 msgid "ugettext_lazy" msgstr "ugettext_lazy" @@ -2841,17 +2848,17 @@ msgstr "サイトメッセージ" msgid "No account available" msgstr "利用できないアカウント" -#: ops/ansible/inventory.py:173 +#: ops/ansible/inventory.py:175 #, fuzzy #| msgid "User disabled." msgid "Ansible disabled" msgstr "ユーザーが無効になりました。" -#: ops/ansible/inventory.py:189 +#: ops/ansible/inventory.py:191 msgid "Skip hosts below:" msgstr "" -#: ops/api/celery.py:61 ops/api/celery.py:76 +#: ops/api/celery.py:63 ops/api/celery.py:78 msgid "Waiting task start" msgstr "タスク開始待ち" @@ -2916,7 +2923,7 @@ msgstr "パターン" msgid "Module" msgstr "" -#: ops/models/adhoc.py:20 ops/models/celery.py:15 +#: ops/models/adhoc.py:20 ops/models/celery.py:45 #: terminal/models/component/task.py:17 msgid "Args" msgstr "アルグ" @@ -2960,16 +2967,16 @@ msgstr "結果" msgid "Summary" msgstr "" -#: ops/models/celery.py:16 terminal/models/component/task.py:18 +#: ops/models/celery.py:46 terminal/models/component/task.py:18 msgid "Kwargs" msgstr "クワーグ" -#: ops/models/celery.py:17 tickets/models/comment.py:13 +#: ops/models/celery.py:47 tickets/models/comment.py:13 #: tickets/models/ticket/general.py:41 tickets/models/ticket/general.py:277 msgid "State" msgstr "状態" -#: ops/models/celery.py:18 terminal/models/session/sharing.py:111 +#: ops/models/celery.py:48 terminal/models/session/sharing.py:111 #: tickets/const.py:25 xpack/plugins/change_auth_plan/models/base.py:188 msgid "Finished" msgstr "終了" @@ -2994,7 +3001,8 @@ msgstr "" msgid "Template" msgstr "テンプレート" -#: ops/models/playbook.py:38 terminal/models/component/task.py:26 +#: ops/models/playbook.py:38 ops/signal_handlers.py:63 +#: terminal/models/component/task.py:26 #: xpack/plugins/gathered_user/models.py:68 msgid "Task" msgstr "タスク" @@ -3033,23 +3041,23 @@ msgstr "{max_threshold}%: => {value} を超える使用メモリ" msgid "CPU load more than {max_threshold}: => {value}" msgstr "{max_threshold} を超えるCPUロード: => {value}" -#: ops/tasks.py:33 +#: ops/tasks.py:34 #, fuzzy #| msgid "Run asset" msgid "Run ansible task" msgstr "アセットの実行" -#: ops/tasks.py:57 +#: ops/tasks.py:58 #, fuzzy #| msgid "Run command" msgid "Run ansible command" msgstr "実行コマンド" -#: ops/tasks.py:79 +#: ops/tasks.py:80 msgid "Clean task history period" msgstr "クリーンなタスク履歴期間" -#: ops/tasks.py:92 +#: ops/tasks.py:93 msgid "Clean celery log period" msgstr "きれいなセロリログ期間" @@ -3080,7 +3088,7 @@ msgstr "組織のリソース ({}) は削除できません" msgid "App organizations" msgstr "アプリ組織" -#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:87 +#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:88 #: rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 #: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:71 @@ -3091,23 +3099,29 @@ msgstr "組織" msgid "Org name" msgstr "組織名" -#: orgs/models.py:79 +#: orgs/models.py:72 +#, fuzzy +#| msgid "Built-in" +msgid "Builtin" +msgstr "内蔵" + +#: orgs/models.py:80 msgid "GLOBAL" msgstr "グローバル組織" -#: orgs/models.py:81 +#: orgs/models.py:82 msgid "DEFAULT" msgstr "" -#: orgs/models.py:83 +#: orgs/models.py:84 msgid "SYSTEM" msgstr "" -#: orgs/models.py:89 +#: orgs/models.py:90 msgid "Can view root org" msgstr "グローバル組織を表示できます" -#: orgs/models.py:90 +#: orgs/models.py:91 msgid "Can view all joined org" msgstr "参加しているすべての組織を表示できます" @@ -3385,7 +3399,7 @@ msgstr "パーマ" msgid "Scope display" msgstr "スコープ表示" -#: rbac/serializers/role.py:27 terminal/models/applet/applet.py:26 +#: rbac/serializers/role.py:27 terminal/models/applet/applet.py:21 msgid "Display name" msgstr "表示名" @@ -3433,6 +3447,10 @@ msgstr "クラウドインポート" msgid "Backup account" msgstr "バックアップアカウント" +#: rbac/tree.py:53 +msgid "Gather account" +msgstr "アカウントを集める" + #: rbac/tree.py:54 msgid "App change auth" msgstr "応用改密" @@ -4900,51 +4918,55 @@ msgstr "一括作成非サポート" msgid "Storage is invalid" msgstr "ストレージが無効です" -#: terminal/models/applet/applet.py:21 -#, fuzzy -#| msgid "Manually input" -msgid "Manual" -msgstr "手動入力" - -#: terminal/models/applet/applet.py:22 -msgid "Git" -msgstr "" - #: terminal/models/applet/applet.py:23 #, fuzzy -#| msgid "Remote app" -msgid "Remote gzip" -msgstr "リモートアプリ" - -#: terminal/models/applet/applet.py:28 -#, fuzzy #| msgid "Auth url" msgid "Author" msgstr "認証アドレス" -#: terminal/models/applet/applet.py:32 +#: terminal/models/applet/applet.py:27 msgid "Tags" msgstr "" -#: terminal/models/applet/applet.py:59 terminal/models/applet/host.py:17 +#: terminal/models/applet/applet.py:29 terminal/serializers/storage.py:157 +msgid "Hosts" +msgstr "ホスト" + +#: terminal/models/applet/applet.py:55 terminal/models/applet/host.py:21 #, fuzzy #| msgid "Apply assets" msgid "Applet" msgstr "資産の適用" -#: terminal/models/applet/host.py:13 +#: terminal/models/applet/host.py:14 #, fuzzy #| msgid "Verify auth" msgid "Account automation" msgstr "パスワード/キーの確認" -#: terminal/models/applet/host.py:14 +#: terminal/models/applet/host.py:15 terminal/serializers/applet.py:66 +#, fuzzy +#| msgid "More login options" +msgid "Deploy options" +msgstr "その他のログインオプション" + +#: terminal/models/applet/host.py:16 +msgid "Inited" +msgstr "" + +#: terminal/models/applet/host.py:17 +#, fuzzy +#| msgid "Date finished" +msgid "Date inited" +msgstr "終了日" + +#: terminal/models/applet/host.py:18 #, fuzzy #| msgid "Date sync" msgid "Date synced" msgstr "日付の同期" -#: terminal/models/applet/host.py:26 +#: terminal/models/applet/host.py:30 #, fuzzy #| msgid "Host" msgid "Hosting" @@ -5178,6 +5200,48 @@ msgstr "一括危険コマンド警告" msgid "Icon" msgstr "" +#: terminal/serializers/applet.py:53 +#, fuzzy +#| msgid "Phone not set" +msgid "Not set" +msgstr "電話が設定されていない" + +#: terminal/serializers/applet.py:54 +#, fuzzy +#| msgid "Session" +msgid "Per Session" +msgstr "セッション" + +#: terminal/serializers/applet.py:55 +msgid "Per Device" +msgstr "" + +#: terminal/serializers/applet.py:57 +#, fuzzy +#| msgid "License" +msgid "RDS Licensing" +msgstr "ライセンス" + +#: terminal/serializers/applet.py:58 +msgid "RDS License Server" +msgstr "" + +#: terminal/serializers/applet.py:59 +msgid "RDS Licensing Mode" +msgstr "" + +#: terminal/serializers/applet.py:60 +msgid "RDS fSingleSessionPerUser" +msgstr "" + +#: terminal/serializers/applet.py:61 +msgid "RDS Max Disconnection Time" +msgstr "" + +#: terminal/serializers/applet.py:62 +msgid "RDS Remote App Logoff Time Limit" +msgstr "" + #: terminal/serializers/endpoint.py:12 msgid "Oracle port" msgstr "" @@ -5279,10 +5343,6 @@ msgstr "ホスト無効" msgid "Port invalid" msgstr "ポートが無効" -#: terminal/serializers/storage.py:157 -msgid "Hosts" -msgstr "ホスト" - #: terminal/serializers/storage.py:160 msgid "Index by date" msgstr "日付による索引付け" @@ -5339,10 +5399,6 @@ msgstr "拒否" msgid "Reopen" msgstr "" -#: tickets/const.py:29 tickets/const.py:37 -msgid "Pending" -msgstr "未定" - #: tickets/const.py:32 tickets/const.py:39 msgid "Closed" msgstr "クローズ" @@ -6963,6 +7019,51 @@ msgstr "究極のエディション" msgid "Community edition" msgstr "コミュニティ版" +#, fuzzy +#~| msgid "Automatic managed" +#~ msgid "Push automation" +#~ msgstr "自動管理" + +#, fuzzy +#~| msgid "Verify auth" +#~ msgid "Verify account automation" +#~ msgstr "パスワード/キーの確認" + +#, fuzzy +#~| msgid "Action display" +#~ msgid "Account display" +#~ msgstr "アクション表示" + +#~ msgid "User not exists" +#~ msgstr "ユーザーは存在しません" + +#~ msgid "System user not exists" +#~ msgstr "システムユーザーが存在しません" + +#~ msgid "Asset not exists" +#~ msgstr "アセットが存在しません" + +#~ msgid "Application not exists" +#~ msgstr "アプリが存在しません" + +#~ msgid "User has no permission to access application or permission expired" +#~ msgstr "" +#~ "ユーザーがアプリにアクセスする権限を持っていないか、権限の有効期限が切れて" +#~ "います" + +#~ msgid "Asset or application required" +#~ msgstr "アセットまたはアプリが必要" + +#, fuzzy +#~| msgid "Manually input" +#~ msgid "Manual" +#~ msgstr "手動入力" + +#, fuzzy +#~| msgid "Remote app" +#~ msgid "Remote gzip" +#~ msgstr "リモートアプリ" + #, fuzzy #~| msgid "Verify code" #~ msgid "Verify secret" @@ -6973,11 +7074,6 @@ msgstr "コミュニティ版" #~ msgid "Secret types" #~ msgstr "秘密キー" -#, fuzzy -#~| msgid "Gather account" -#~ msgid "Gather accounts" -#~ msgstr "アカウントを集める" - #, fuzzy #~| msgid "Hostname strategy" #~ msgid "Automation strategy" diff --git a/apps/locale/zh/LC_MESSAGES/django.mo b/apps/locale/zh/LC_MESSAGES/django.mo index eada29942..6e116b000 100644 --- a/apps/locale/zh/LC_MESSAGES/django.mo +++ b/apps/locale/zh/LC_MESSAGES/django.mo @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:97b2aa050b5846dd3399d45286d34f282acb55dca3e2b18a79c16b9d34ec938f -size 103818 +oid sha256:08529907ac3879f60c2026f91e7ba3f48a3a7d288f7b29cd35c0f73bc3999c21 +size 103630 diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index aeda480a1..013be87be 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: 2022-10-26 16:41+0800\n" +"POT-Creation-Date: 2022-11-01 15:30+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -31,7 +31,7 @@ msgstr "访问控制" #: assets/serializers/platform.py:104 ops/mixin.py:20 ops/models/playbook.py:9 #: orgs/models.py:70 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:25 terminal/models/component/endpoint.py:11 +#: terminal/models/applet/applet.py:20 terminal/models/component/endpoint.py:11 #: terminal/models/component/endpoint.py:87 #: terminal/models/component/storage.py:25 terminal/models/component/task.py:16 #: terminal/models/component/terminal.py:100 users/forms/profile.py:33 @@ -50,7 +50,7 @@ msgstr "优先级" msgid "1-100, the lower the value will be match first" msgstr "优先级可选范围为 1-100 (数值越小越优先)" -#: acls/models/base.py:31 authentication/models.py:22 +#: acls/models/base.py:31 authentication/models/access_key.py:15 #: authentication/templates/authentication/_access_key_modal.html:32 #: perms/models/asset_permission.py:74 terminal/models/session/sharing.py:28 #: tickets/const.py:38 @@ -58,17 +58,17 @@ msgid "Active" msgstr "激活中" #: acls/models/base.py:32 applications/models.py:19 assets/models/_user.py:40 -#: assets/models/asset/common.py:100 assets/models/automations/base.py:25 +#: assets/models/asset/common.py:100 assets/models/automations/base.py:26 #: assets/models/backup.py:30 assets/models/base.py:66 #: assets/models/cmd_filter.py:40 assets/models/cmd_filter.py:88 #: assets/models/domain.py:25 assets/models/domain.py:69 #: assets/models/group.py:23 assets/models/label.py:22 #: assets/models/platform.py:73 ops/models/playbook.py:11 -#: ops/models/playbook.py:25 orgs/models.py:73 +#: ops/models/playbook.py:25 orgs/models.py:74 #: perms/models/asset_permission.py:84 rbac/models/role.py:37 -#: settings/models.py:38 terminal/models/applet/applet.py:33 -#: terminal/models/applet/applet.py:62 terminal/models/applet/host.py:12 -#: terminal/models/applet/host.py:28 terminal/models/component/endpoint.py:24 +#: settings/models.py:38 terminal/models/applet/applet.py:28 +#: terminal/models/applet/applet.py:58 terminal/models/applet/host.py:34 +#: terminal/models/component/endpoint.py:24 #: terminal/models/component/endpoint.py:97 #: terminal/models/component/storage.py:28 #: terminal/models/component/terminal.py:114 tickets/models/comment.py:32 @@ -95,8 +95,9 @@ msgstr "登录复核" #: acls/models/login_acl.py:24 acls/models/login_asset_acl.py:20 #: assets/models/cmd_filter.py:28 assets/models/label.py:15 audits/models.py:37 -#: audits/models.py:62 audits/models.py:87 authentication/models.py:55 -#: authentication/models.py:72 perms/models/asset_permission.py:58 +#: audits/models.py:62 audits/models.py:87 +#: authentication/models/connection_token.py:22 +#: authentication/models/sso_token.py:15 perms/models/asset_permission.py:58 #: rbac/builtin.py:120 rbac/models/rolebinding.py:41 #: terminal/backends/command/models.py:20 #: terminal/backends/command/serializers.py:13 @@ -128,7 +129,7 @@ msgid "Login acl" msgstr "登录访问控制" #: acls/models/login_asset_acl.py:21 assets/models/account.py:57 -#: authentication/models.py:82 ops/models/base.py:18 +#: authentication/models/connection_token.py:33 ops/models/base.py:18 #: terminal/models/session/session.py:34 xpack/plugins/cloud/models.py:87 #: xpack/plugins/cloud/serializers/task.py:65 msgid "Account" @@ -138,7 +139,7 @@ msgstr "账号" #: assets/models/asset/common.py:83 assets/models/asset/common.py:227 #: assets/models/cmd_filter.py:36 assets/models/gathered_user.py:14 #: assets/serializers/account/account.py:58 assets/serializers/label.py:30 -#: audits/models.py:39 authentication/models.py:77 +#: audits/models.py:39 authentication/models/connection_token.py:26 #: perms/models/asset_permission.py:64 terminal/backends/command/models.py:21 #: terminal/backends/command/serializers.py:14 #: terminal/models/session/session.py:32 terminal/notifications.py:90 @@ -164,7 +165,7 @@ msgstr "格式为逗号分隔的字符串, * 表示匹配所有. " #: acls/serializers/login_asset_acl.py:52 assets/models/_user.py:34 #: assets/models/base.py:60 assets/models/gathered_user.py:15 #: audits/models.py:121 authentication/forms.py:25 authentication/forms.py:27 -#: authentication/models.py:245 +#: authentication/models/temp_token.py:9 #: authentication/templates/authentication/_msg_different_city.html:9 #: authentication/templates/authentication/_msg_oauth_bind.html:9 #: users/forms/profile.py:32 users/models/user.py:663 @@ -245,9 +246,9 @@ msgid "Category" msgstr "类别" #: applications/models.py:15 assets/models/_user.py:46 -#: assets/models/automations/base.py:23 assets/models/cmd_filter.py:74 +#: assets/models/automations/base.py:24 assets/models/cmd_filter.py:74 #: assets/models/platform.py:70 assets/serializers/asset/common.py:63 -#: assets/serializers/platform.py:75 terminal/models/applet/applet.py:29 +#: assets/serializers/platform.py:75 terminal/models/applet/applet.py:24 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:142 terminal/serializers/applet.py:20 #: tickets/models/comment.py:26 tickets/models/flow.py:57 @@ -291,7 +292,7 @@ msgstr "删除失败,节点包含资产" msgid "App assets" msgstr "资产管理" -#: assets/automations/base/manager.py:74 +#: assets/automations/base/manager.py:122 msgid "{} disabled" msgstr "{} 已禁用" @@ -305,7 +306,7 @@ msgstr "未知" msgid "Ok" msgstr "成功" -#: assets/const/account.py:8 audits/models.py:118 +#: assets/const/account.py:8 audits/models.py:118 common/const/choices.py:18 #: xpack/plugins/change_auth_plan/serializers/asset.py:190 #: xpack/plugins/cloud/const.py:33 msgid "Failed" @@ -334,12 +335,12 @@ msgid "SSH key" msgstr "SSH 密钥" #: assets/const/account.py:14 assets/models/base.py:55 -#: authentication/models.py:38 +#: authentication/models/access_key.py:31 msgid "Access key" msgstr "Access key" #: assets/const/account.py:15 assets/models/_user.py:38 -#: assets/models/base.py:56 authentication/models.py:53 +#: assets/models/base.py:56 authentication/models/sso_token.py:13 msgid "Token" msgstr "Token" @@ -363,8 +364,8 @@ msgstr "改密" msgid "Verify account" msgstr "验证密钥" -#: assets/const/automation.py:18 rbac/tree.py:53 -msgid "Gather account" +#: assets/const/automation.py:18 +msgid "Gather accounts" msgstr "收集账号" #: assets/const/automation.py:22 @@ -397,8 +398,8 @@ msgid "Replace (The key generated by JumpServer) " msgstr "替换 (由 JumpServer 生成的密钥)" #: assets/const/category.py:11 settings/serializers/auth/radius.py:14 -#: settings/serializers/auth/sms.py:56 terminal/models/applet/applet.py:60 -#: terminal/models/applet/host.py:11 terminal/models/component/endpoint.py:12 +#: settings/serializers/auth/sms.py:56 terminal/models/applet/applet.py:56 +#: terminal/models/component/endpoint.py:12 #: xpack/plugins/cloud/serializers/account_attrs.py:72 msgid "Host" msgstr "主机" @@ -473,11 +474,11 @@ msgstr "SSH 密钥" msgid "SSH public key" msgstr "SSH 公钥" -#: assets/models/_user.py:41 assets/models/automations/base.py:86 +#: assets/models/_user.py:41 assets/models/automations/base.py:87 #: assets/models/base.py:67 assets/models/domain.py:26 #: assets/models/gathered_user.py:19 assets/models/group.py:22 #: common/db/models.py:76 common/mixins/models.py:50 ops/models/base.py:53 -#: orgs/models.py:72 perms/models/asset_permission.py:82 +#: orgs/models.py:73 perms/models/asset_permission.py:82 #: users/models/group.py:18 users/models/user.py:927 msgid "Date created" msgstr "创建日期" @@ -502,7 +503,8 @@ msgid "Username same with user" msgstr "用户名与用户相同" #: assets/models/_user.py:48 assets/models/domain.py:67 -#: terminal/models/applet/applet.py:31 terminal/serializers/session.py:18 +#: authentication/models/connection_token.py:29 +#: terminal/models/applet/applet.py:26 terminal/serializers/session.py:18 #: terminal/serializers/session.py:32 terminal/serializers/storage.py:68 msgid "Protocol" msgstr "协议" @@ -560,7 +562,7 @@ msgid "Su from" msgstr "切换自" #: assets/models/account.py:53 settings/serializers/auth/cas.py:18 -#: terminal/models/applet/applet.py:27 +#: terminal/models/applet/applet.py:22 msgid "Version" msgstr "版本" @@ -603,16 +605,16 @@ msgstr "资产平台" msgid "Domain" msgstr "网域" -#: assets/models/asset/common.py:97 assets/models/automations/base.py:18 +#: assets/models/asset/common.py:97 assets/models/automations/base.py:19 #: assets/serializers/asset/common.py:66 perms/models/asset_permission.py:67 #: xpack/plugins/change_auth_plan/models/asset.py:44 #: xpack/plugins/gathered_user/models.py:24 msgid "Nodes" msgstr "节点" -#: assets/models/asset/common.py:98 assets/models/automations/base.py:24 +#: assets/models/asset/common.py:98 assets/models/automations/base.py:25 #: assets/models/cmd_filter.py:39 assets/models/domain.py:70 -#: assets/models/label.py:21 terminal/models/applet/applet.py:30 +#: assets/models/label.py:21 terminal/models/applet/applet.py:25 #: users/serializers/user.py:147 msgid "Is active" msgstr "激活" @@ -673,26 +675,27 @@ msgstr "密码选择器" msgid "Submit selector" msgstr "提交按钮选择器" -#: assets/models/automations/base.py:16 assets/models/cmd_filter.py:38 +#: assets/models/automations/base.py:17 assets/models/cmd_filter.py:38 #: assets/serializers/asset/common.py:68 perms/models/asset_permission.py:70 #: rbac/tree.py:37 msgid "Accounts" msgstr "账号管理" -#: assets/models/automations/base.py:21 assets/serializers/domain.py:29 +#: assets/models/automations/base.py:22 assets/serializers/domain.py:29 #: ops/models/base.py:17 #: terminal/templates/terminal/_msg_command_execute_alert.html:16 #: xpack/plugins/change_auth_plan/models/asset.py:40 msgid "Assets" msgstr "资产" -#: assets/models/automations/base.py:76 assets/models/automations/base.py:83 +#: assets/models/automations/base.py:77 assets/models/automations/base.py:84 msgid "Automation task" msgstr "自动化任务" -#: assets/models/automations/base.py:87 assets/models/backup.py:77 +#: assets/models/automations/base.py:88 assets/models/backup.py:77 #: audits/models.py:44 ops/models/base.py:54 -#: perms/models/asset_permission.py:76 terminal/models/session/session.py:43 +#: perms/models/asset_permission.py:76 terminal/models/applet/host.py:32 +#: terminal/models/session/session.py:43 #: tickets/models/ticket/apply_application.py:28 #: tickets/models/ticket/apply_asset.py:21 #: xpack/plugins/change_auth_plan/models/base.py:108 @@ -701,53 +704,55 @@ msgstr "自动化任务" msgid "Date start" msgstr "开始日期" -#: assets/models/automations/base.py:88 -#: assets/models/automations/change_secret.py:59 ops/models/base.py:55 +#: assets/models/automations/base.py:89 +#: assets/models/automations/change_secret.py:58 ops/models/base.py:55 +#: terminal/models/applet/host.py:33 msgid "Date finished" msgstr "结束日期" -#: assets/models/automations/base.py:90 +#: assets/models/automations/base.py:91 msgid "Automation snapshot" msgstr "自动化快照" -#: assets/models/automations/base.py:94 assets/models/backup.py:88 +#: assets/models/automations/base.py:95 assets/models/backup.py:88 #: assets/serializers/account/backup.py:36 #: xpack/plugins/change_auth_plan/models/base.py:121 #: xpack/plugins/change_auth_plan/serializers/base.py:78 msgid "Trigger mode" msgstr "触发模式" -#: assets/models/automations/base.py:98 +#: assets/models/automations/base.py:99 msgid "Automation task execution" msgstr "自动化任务执行" -#: assets/models/automations/change_secret.py:16 assets/models/base.py:62 +#: assets/models/automations/change_secret.py:15 assets/models/base.py:62 msgid "Secret type" msgstr "密文类型" -#: assets/models/automations/change_secret.py:20 +#: assets/models/automations/change_secret.py:19 msgid "Secret strategy" msgstr "密钥策略" -#: assets/models/automations/change_secret.py:22 -#: assets/models/automations/change_secret.py:57 assets/models/base.py:64 -#: assets/serializers/account/base.py:17 authentication/models.py:66 -#: authentication/models.py:246 +#: assets/models/automations/change_secret.py:21 +#: assets/models/automations/change_secret.py:56 assets/models/base.py:64 +#: assets/serializers/account/base.py:17 +#: authentication/models/connection_token.py:34 +#: authentication/models/temp_token.py:10 #: authentication/templates/authentication/_access_key_modal.html:31 #: settings/serializers/auth/radius.py:17 msgid "Secret" msgstr "密钥" -#: assets/models/automations/change_secret.py:23 +#: assets/models/automations/change_secret.py:22 #: xpack/plugins/change_auth_plan/models/base.py:39 msgid "Password rules" msgstr "密码规则" -#: assets/models/automations/change_secret.py:26 +#: assets/models/automations/change_secret.py:25 msgid "SSH key change strategy" msgstr "SSH 密钥策略" -#: assets/models/automations/change_secret.py:28 assets/models/backup.py:28 +#: assets/models/automations/change_secret.py:27 assets/models/backup.py:28 #: assets/serializers/account/backup.py:28 #: xpack/plugins/change_auth_plan/models/app.py:40 #: xpack/plugins/change_auth_plan/models/asset.py:63 @@ -755,23 +760,23 @@ msgstr "SSH 密钥策略" msgid "Recipient" msgstr "收件人" -#: assets/models/automations/change_secret.py:35 +#: assets/models/automations/change_secret.py:34 msgid "Change secret automation" msgstr "自动化改密" -#: assets/models/automations/change_secret.py:56 +#: assets/models/automations/change_secret.py:55 msgid "Old secret" msgstr "原来密码" -#: assets/models/automations/change_secret.py:58 +#: assets/models/automations/change_secret.py:57 msgid "Date started" msgstr "开始日期" -#: assets/models/automations/change_secret.py:61 +#: assets/models/automations/change_secret.py:60 common/const/choices.py:19 msgid "Error" msgstr "错误" -#: assets/models/automations/change_secret.py:64 +#: assets/models/automations/change_secret.py:63 msgid "Change secret record" msgstr "改密记录" @@ -779,17 +784,27 @@ msgstr "改密记录" msgid "Discovery account automation" msgstr "自动化账号发现" +#: assets/models/automations/gather_accounts.py:15 +#, fuzzy +#| msgid "Gather asset facts" +msgid "Gather asset accounts" +msgstr "收集资产信息" + #: assets/models/automations/gather_facts.py:15 msgid "Gather asset facts" msgstr "收集资产信息" -#: assets/models/automations/push_account.py:8 -msgid "Push automation" -msgstr "自动化推送" +#: assets/models/automations/push_account.py:16 +#, fuzzy +#| msgid "Is service account" +msgid "Push asset account" +msgstr "服务账号" -#: assets/models/automations/verify_secret.py:8 -msgid "Verify account automation" -msgstr "账号校验自动化" +#: assets/models/automations/verify_account.py:15 +#, fuzzy +#| msgid "Verify account" +msgid "Verify asset account" +msgstr "验证密钥" #: assets/models/backup.py:38 assets/models/backup.py:96 msgid "Account backup plan" @@ -830,7 +845,7 @@ msgstr "账号备份执行" msgid "Connectivity" msgstr "可连接性" -#: assets/models/base.py:32 authentication/models.py:248 +#: assets/models/base.py:32 authentication/models/temp_token.py:12 msgid "Date verified" msgstr "校验日期" @@ -1247,7 +1262,6 @@ msgid "Category display" msgstr "类别名称" #: assets/serializers/mixin.py:10 audits/serializers.py:27 -#: authentication/serializers/connection_token.py:20 #: tickets/serializers/flow.py:49 tickets/serializers/ticket/ticket.py:17 msgid "Type display" msgstr "类型名称" @@ -1412,7 +1426,7 @@ msgstr "操作" msgid "Filename" msgstr "文件名" -#: audits/models.py:43 audits/models.py:117 +#: audits/models.py:43 audits/models.py:117 common/const/choices.py:17 #: terminal/models/session/sharing.py:104 tickets/views/approve.py:114 #: xpack/plugins/change_auth_plan/serializers/asset.py:189 msgid "Success" @@ -1492,8 +1506,8 @@ msgid "MFA" msgstr "MFA" #: audits/models.py:128 ops/models/base.py:48 -#: terminal/models/applet/applet.py:61 terminal/models/applet/host.py:15 -#: terminal/models/applet/host.py:27 terminal/models/component/status.py:33 +#: terminal/models/applet/applet.py:57 terminal/models/applet/host.py:19 +#: terminal/models/applet/host.py:31 terminal/models/component/status.py:33 #: tickets/models/ticket/general.py:281 xpack/plugins/cloud/models.py:171 #: xpack/plugins/cloud/models.py:223 msgid "Status" @@ -1557,7 +1571,7 @@ msgstr "飞书" msgid "DingTalk" msgstr "钉钉" -#: audits/signal_handlers.py:56 authentication/models.py:252 +#: audits/signal_handlers.py:56 authentication/models/temp_token.py:16 msgid "Temporary token" msgstr "临时密码" @@ -1708,7 +1722,7 @@ msgstr "无效的令牌头。符号字符串不应包含无效字符。" msgid "Invalid token or cache refreshed." msgstr "刷新的令牌或缓存无效。" -#: authentication/backends/oauth2/backends.py:155 authentication/models.py:143 +#: authentication/backends/oauth2/backends.py:155 msgid "User invalid, disabled or expired" msgstr "用户无效,已禁用或已过期" @@ -1960,85 +1974,74 @@ msgstr "该 MFA ({}) 方式没有启用" msgid "Please change your password" msgstr "请修改密码" -#: authentication/models.py:45 -msgid "Private Token" -msgstr "SSH 密钥" +#: authentication/models/connection_token.py:31 +#: rbac/serializers/rolebinding.py:21 +msgid "User display" +msgstr "用户名称" -#: authentication/models.py:54 -msgid "Expired" -msgstr "过期时间" +#: authentication/models/connection_token.py:32 +msgid "Asset display" +msgstr "资产名称" -#: authentication/models.py:58 -msgid "SSO token" -msgstr "SSO token" - -#: authentication/models.py:68 authentication/models.py:249 -#: perms/models/asset_permission.py:79 +#: authentication/models/connection_token.py:36 +#: authentication/models/temp_token.py:13 perms/models/asset_permission.py:79 #: tickets/models/ticket/apply_application.py:29 #: tickets/models/ticket/apply_asset.py:22 users/models/user.py:707 msgid "Date expired" msgstr "失效日期" -#: authentication/models.py:75 rbac/serializers/rolebinding.py:21 -msgid "User display" -msgstr "用户名称" - -#: authentication/models.py:80 -msgid "Asset display" -msgstr "资产名称" - -#: authentication/models.py:85 -msgid "Account display" -msgstr "账号显示" - -#: authentication/models.py:89 +#: authentication/models/connection_token.py:41 msgid "Connection token" msgstr "连接令牌" -#: authentication/models.py:91 +#: authentication/models/connection_token.py:43 msgid "Can view connection token secret" msgstr "可以查看连接令牌密文" -#: authentication/models.py:134 +#: authentication/models/connection_token.py:82 msgid "Connection token expired at: {}" msgstr "连接令牌过期: {}" -#: authentication/models.py:139 -msgid "User not exists" -msgstr "用户不存在" +#: authentication/models/connection_token.py:86 +msgid "No user or invalid user" +msgstr "" -#: authentication/models.py:148 -msgid "System user not exists" -msgstr "系统用户不存在" - -#: authentication/models.py:154 -msgid "Asset not exists" -msgstr "资产不存在" - -#: authentication/models.py:158 -msgid "Asset inactive" +#: authentication/models/connection_token.py:90 +#, fuzzy +#| msgid "Asset inactive" +msgid "No asset or inactive asset" msgstr "资产未激活" -#: authentication/models.py:165 +#: authentication/models/connection_token.py:94 +#, fuzzy +#| msgid "Login account" +msgid "No account" +msgstr "登录账号" + +#: authentication/models/connection_token.py:103 msgid "User has no permission to access asset or permission expired" msgstr "用户没有权限访问资产或权限已过期" -#: authentication/models.py:173 -msgid "Application not exists" -msgstr "应用不存在" - -#: authentication/models.py:180 -msgid "User has no permission to access application or permission expired" -msgstr "用户没有权限访问应用或权限已过期" - -#: authentication/models.py:247 -msgid "Verified" -msgstr "已校验" - -#: authentication/models.py:268 +#: authentication/models/connection_token.py:145 msgid "Super connection token" msgstr "超级连接令牌" +#: authentication/models/private_token.py:9 +msgid "Private Token" +msgstr "SSH 密钥" + +#: authentication/models/sso_token.py:14 +msgid "Expired" +msgstr "过期时间" + +#: authentication/models/sso_token.py:18 +msgid "SSO token" +msgstr "SSO token" + +#: authentication/models/temp_token.py:11 +msgid "Verified" +msgstr "已校验" + #: authentication/notifications.py:19 msgid "Different city login reminder" msgstr "异地登录提醒" @@ -2047,19 +2050,15 @@ msgstr "异地登录提醒" msgid "binding reminder" msgstr "绑定提醒" -#: authentication/serializers/connection_token.py:21 +#: authentication/serializers/connection_token.py:20 #: xpack/plugins/cloud/models.py:36 msgid "Validity" msgstr "有效" -#: authentication/serializers/connection_token.py:22 +#: authentication/serializers/connection_token.py:21 msgid "Expired time" msgstr "过期时间" -#: authentication/serializers/connection_token.py:68 -msgid "Asset or application required" -msgstr "资产或应用必填" - #: authentication/serializers/token.py:79 perms/serializers/permission.py:60 #: perms/serializers/permission.py:87 users/serializers/user.py:148 msgid "Is valid" @@ -2148,7 +2147,7 @@ msgstr "代码错误" #: authentication/templates/authentication/_msg_reset_password.html:3 #: authentication/templates/authentication/_msg_rest_password_success.html:2 #: authentication/templates/authentication/_msg_rest_public_key_success.html:2 -#: jumpserver/conf.py:390 ops/tasks.py:146 ops/tasks.py:152 ops/tasks.py:155 +#: jumpserver/conf.py:390 ops/tasks.py:147 ops/tasks.py:153 ops/tasks.py:156 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: perms/templates/perms/_msg_permed_items_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:33 @@ -2440,6 +2439,20 @@ msgstr "手动触发" msgid "Timing trigger" msgstr "定时触发" +#: common/const/choices.py:15 tickets/const.py:29 tickets/const.py:37 +msgid "Pending" +msgstr "待定的" + +#: common/const/choices.py:16 +msgid "Running" +msgstr "" + +#: common/const/choices.py:20 +#, fuzzy +#| msgid "Cancel" +msgid "Canceled" +msgstr "取消" + #: common/db/encoder.py:11 msgid "ugettext_lazy" msgstr "ugettext_lazy" @@ -2688,15 +2701,15 @@ msgstr "站内信" msgid "No account available" msgstr "没有账号可以使用" -#: ops/ansible/inventory.py:173 +#: ops/ansible/inventory.py:175 msgid "Ansible disabled" msgstr "Ansible 已禁用" -#: ops/ansible/inventory.py:189 +#: ops/ansible/inventory.py:191 msgid "Skip hosts below:" msgstr "跳过一下主机:" -#: ops/api/celery.py:61 ops/api/celery.py:76 +#: ops/api/celery.py:63 ops/api/celery.py:78 msgid "Waiting task start" msgstr "等待任务开始" @@ -2757,7 +2770,7 @@ msgstr "模式" msgid "Module" msgstr "" -#: ops/models/adhoc.py:20 ops/models/celery.py:15 +#: ops/models/adhoc.py:20 ops/models/celery.py:45 #: terminal/models/component/task.py:17 msgid "Args" msgstr "参数" @@ -2795,16 +2808,16 @@ msgstr "结果" msgid "Summary" msgstr "汇总" -#: ops/models/celery.py:16 terminal/models/component/task.py:18 +#: ops/models/celery.py:46 terminal/models/component/task.py:18 msgid "Kwargs" msgstr "其它参数" -#: ops/models/celery.py:17 tickets/models/comment.py:13 +#: ops/models/celery.py:47 tickets/models/comment.py:13 #: tickets/models/ticket/general.py:41 tickets/models/ticket/general.py:277 msgid "State" msgstr "状态" -#: ops/models/celery.py:18 terminal/models/session/sharing.py:111 +#: ops/models/celery.py:48 terminal/models/session/sharing.py:111 #: tickets/const.py:25 xpack/plugins/change_auth_plan/models/base.py:188 msgid "Finished" msgstr "结束" @@ -2829,7 +2842,8 @@ msgstr "Owner" msgid "Template" msgstr "模板" -#: ops/models/playbook.py:38 terminal/models/component/task.py:26 +#: ops/models/playbook.py:38 ops/signal_handlers.py:63 +#: terminal/models/component/task.py:26 #: xpack/plugins/gathered_user/models.py:68 msgid "Task" msgstr "任务" @@ -2866,19 +2880,19 @@ msgstr "内存使用率超过 {max_threshold}%: => {value}" msgid "CPU load more than {max_threshold}: => {value}" msgstr "CPU 使用率超过 {max_threshold}: => {value}" -#: ops/tasks.py:33 +#: ops/tasks.py:34 msgid "Run ansible task" msgstr "运行 ansible 任务" -#: ops/tasks.py:57 +#: ops/tasks.py:58 msgid "Run ansible command" msgstr "运行 ansible 命令" -#: ops/tasks.py:79 +#: ops/tasks.py:80 msgid "Clean task history period" msgstr "定期清除任务历史" -#: ops/tasks.py:92 +#: ops/tasks.py:93 msgid "Clean celery log period" msgstr "定期清除Celery日志" @@ -2908,7 +2922,7 @@ msgstr "组织存在资源 ({}) 不能被删除" msgid "App organizations" msgstr "组织管理" -#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:87 +#: orgs/mixins/models.py:57 orgs/mixins/serializers.py:25 orgs/models.py:88 #: rbac/const.py:7 rbac/models/rolebinding.py:48 #: rbac/serializers/rolebinding.py:40 settings/serializers/auth/ldap.py:62 #: tickets/models/ticket/general.py:300 tickets/serializers/ticket/ticket.py:71 @@ -2919,23 +2933,29 @@ msgstr "组织" msgid "Org name" msgstr "组织名称" -#: orgs/models.py:79 +#: orgs/models.py:72 +#, fuzzy +#| msgid "Built-in" +msgid "Builtin" +msgstr "内置" + +#: orgs/models.py:80 msgid "GLOBAL" msgstr "全局组织" -#: orgs/models.py:81 +#: orgs/models.py:82 msgid "DEFAULT" msgstr "" -#: orgs/models.py:83 +#: orgs/models.py:84 msgid "SYSTEM" msgstr "" -#: orgs/models.py:89 +#: orgs/models.py:90 msgid "Can view root org" msgstr "可以查看全局组织" -#: orgs/models.py:90 +#: orgs/models.py:91 msgid "Can view all joined org" msgstr "可以查看所有加入的组织" @@ -3212,7 +3232,7 @@ msgstr "权限" msgid "Scope display" msgstr "范围名称" -#: rbac/serializers/role.py:27 terminal/models/applet/applet.py:26 +#: rbac/serializers/role.py:27 terminal/models/applet/applet.py:21 msgid "Display name" msgstr "显示名称" @@ -3260,6 +3280,10 @@ msgstr "云同步" msgid "Backup account" msgstr "备份账号" +#: rbac/tree.py:53 +msgid "Gather account" +msgstr "收集账号" + #: rbac/tree.py:54 msgid "App change auth" msgstr "应用改密" @@ -4693,39 +4717,47 @@ msgstr "不支持批量创建" msgid "Storage is invalid" msgstr "存储无效" -#: terminal/models/applet/applet.py:21 -msgid "Manual" -msgstr "手动" - -#: terminal/models/applet/applet.py:22 -msgid "Git" -msgstr "" - #: terminal/models/applet/applet.py:23 -msgid "Remote gzip" -msgstr "远程应用" - -#: terminal/models/applet/applet.py:28 msgid "Author" msgstr "作者" -#: terminal/models/applet/applet.py:32 +#: terminal/models/applet/applet.py:27 msgid "Tags" msgstr "标签" -#: terminal/models/applet/applet.py:59 terminal/models/applet/host.py:17 +#: terminal/models/applet/applet.py:29 terminal/serializers/storage.py:157 +msgid "Hosts" +msgstr "主机" + +#: terminal/models/applet/applet.py:55 terminal/models/applet/host.py:21 msgid "Applet" msgstr "远程应用" -#: terminal/models/applet/host.py:13 +#: terminal/models/applet/host.py:14 msgid "Account automation" msgstr "账号自动化" -#: terminal/models/applet/host.py:14 +#: terminal/models/applet/host.py:15 terminal/serializers/applet.py:66 +#, fuzzy +#| msgid "More login options" +msgid "Deploy options" +msgstr "其他方式登录" + +#: terminal/models/applet/host.py:16 +msgid "Inited" +msgstr "" + +#: terminal/models/applet/host.py:17 +#, fuzzy +#| msgid "Date finished" +msgid "Date inited" +msgstr "结束日期" + +#: terminal/models/applet/host.py:18 msgid "Date synced" msgstr "最后同步日期" -#: terminal/models/applet/host.py:26 +#: terminal/models/applet/host.py:30 msgid "Hosting" msgstr "主机" @@ -4957,6 +4989,42 @@ msgstr "批量危险命令告警" msgid "Icon" msgstr "图标" +#: terminal/serializers/applet.py:53 +msgid "Not set" +msgstr "不设置" + +#: terminal/serializers/applet.py:54 +msgid "Per Session" +msgstr "按会话" + +#: terminal/serializers/applet.py:55 +msgid "Per Device" +msgstr "按设备" + +#: terminal/serializers/applet.py:57 +msgid "RDS Licensing" +msgstr "部署 RDS 许可服务" + +#: terminal/serializers/applet.py:58 +msgid "RDS License Server" +msgstr "RDS 许可服务主机" + +#: terminal/serializers/applet.py:59 +msgid "RDS Licensing Mode" +msgstr "RDS 许可模式" + +#: terminal/serializers/applet.py:60 +msgid "RDS fSingleSessionPerUser" +msgstr "RDS 会话用户数" + +#: terminal/serializers/applet.py:61 +msgid "RDS Max Disconnection Time" +msgstr "RDS 会话断开时间" + +#: terminal/serializers/applet.py:62 +msgid "RDS Remote App Logoff Time Limit" +msgstr "RDS 远程应用注销时间" + #: terminal/serializers/endpoint.py:12 msgid "Oracle port" msgstr "" @@ -5056,10 +5124,6 @@ msgstr "主机无效" msgid "Port invalid" msgstr "端口无效" -#: terminal/serializers/storage.py:157 -msgid "Hosts" -msgstr "主机" - #: terminal/serializers/storage.py:160 msgid "Index by date" msgstr "按日期建索引" @@ -5116,10 +5180,6 @@ msgstr "已拒绝" msgid "Reopen" msgstr "" -#: tickets/const.py:29 tickets/const.py:37 -msgid "Pending" -msgstr "待定的" - #: tickets/const.py:32 tickets/const.py:39 msgid "Closed" msgstr "关闭的" @@ -6715,6 +6775,39 @@ msgstr "旗舰版" msgid "Community edition" msgstr "社区版" +#~ msgid "Push automation" +#~ msgstr "自动化推送" + +#~ msgid "Verify account automation" +#~ msgstr "账号校验自动化" + +#~ msgid "Account display" +#~ msgstr "账号显示" + +#~ msgid "User not exists" +#~ msgstr "用户不存在" + +#~ msgid "System user not exists" +#~ msgstr "系统用户不存在" + +#~ msgid "Asset not exists" +#~ msgstr "资产不存在" + +#~ msgid "Application not exists" +#~ msgstr "应用不存在" + +#~ msgid "User has no permission to access application or permission expired" +#~ msgstr "用户没有权限访问应用或权限已过期" + +#~ msgid "Asset or application required" +#~ msgstr "资产或应用必填" + +#~ msgid "Manual" +#~ msgstr "手动" + +#~ msgid "Remote gzip" +#~ msgstr "远程应用" + #~ msgid "Verify secret" #~ msgstr "校验密码" @@ -6726,9 +6819,6 @@ msgstr "社区版" #~ msgid "Verify secret automation" #~ msgstr "自动化验证" -#~ msgid "Gather accounts" -#~ msgstr "收集账号" - #, fuzzy #~| msgid "Hostname strategy" #~ msgid "Automation strategy" diff --git a/apps/ops/signal_handlers.py b/apps/ops/signal_handlers.py index b713ccbf4..dd49a4d94 100644 --- a/apps/ops/signal_handlers.py +++ b/apps/ops/signal_handlers.py @@ -3,6 +3,7 @@ import ast from django.db import transaction from django.dispatch import receiver from django.utils import translation, timezone +from django.utils.translation import gettext as _ from django.core.cache import cache from celery import signals, current_app @@ -44,7 +45,8 @@ def before_task_publish(headers=None, **kwargs): @signals.task_prerun.connect def on_celery_task_pre_run(task_id='', **kwargs): # 更新状态 - CeleryTaskExecution.objects.filter(id=task_id).update(state='RUNNING', date_start=timezone.now()) + CeleryTaskExecution.objects.filter(id=task_id)\ + .update(state='RUNNING', date_start=timezone.now()) # 关闭之前的数据库连接 close_old_connections() @@ -58,7 +60,7 @@ def on_celery_task_pre_run(task_id='', **kwargs): @signals.task_postrun.connect def on_celery_task_post_run(task_id='', state='', **kwargs): close_old_connections() - print("Task post run: ", task_id, state) + print(_("Task") + ": {} {}".format(task_id, state)) CeleryTaskExecution.objects.filter(id=task_id).update( state=state, date_finished=timezone.now(), is_finished=True diff --git a/apps/orgs/mixins/models.py b/apps/orgs/mixins/models.py index 80674ddc6..0795edc2e 100644 --- a/apps/orgs/mixins/models.py +++ b/apps/orgs/mixins/models.py @@ -60,7 +60,7 @@ class OrgModelMixin(models.Model): sep = '@' def save(self, *args, **kwargs): - locking_org = getattr(self, 'locking_org', None) + locking_org = getattr(self, 'LOCKING_ORG', None) if locking_org: org = Organization.get_instance(locking_org) else: diff --git a/apps/orgs/utils.py b/apps/orgs/utils.py index a80c7854d..38cd0e764 100644 --- a/apps/orgs/utils.py +++ b/apps/orgs/utils.py @@ -105,14 +105,11 @@ def tmp_to_builtin_org(system=0, default=0): def filter_org_queryset(queryset): locking_org = getattr(queryset.model, 'LOCKING_ORG', None) - if locking_org: - org = Organization.get_instance(locking_org) - else: - org = get_current_org() + org = get_current_org() - if org is None: - kwargs = {} - elif org.is_root(): + if locking_org: + kwargs = {'org_id': locking_org} + elif org is None or org.is_root(): kwargs = {} else: kwargs = {'org_id': org.id} diff --git a/apps/terminal/api/applet/applet.py b/apps/terminal/api/applet/applet.py index bce0738d6..7e3092755 100644 --- a/apps/terminal/api/applet/applet.py +++ b/apps/terminal/api/applet/applet.py @@ -5,6 +5,7 @@ import os.path from django.core.files.storage import default_storage from rest_framework import viewsets +from django.http import HttpResponse from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.serializers import ValidationError @@ -22,6 +23,7 @@ class AppletViewSet(viewsets.ModelViewSet): serializer_class = serializers.AppletSerializer rbac_perms = { 'upload': 'terminal.add_applet', + 'download': 'terminal.view_applet', } def perform_destroy(self, instance): @@ -52,7 +54,7 @@ class AppletViewSet(viewsets.ModelViewSet): zp.extractall(extract_to) tmp_dir = os.path.join(extract_to, file.name.replace('.zip', '')) - files = ['manifest.yml', 'icon.png', 'i18n.yml'] + files = ['manifest.yml', 'icon.png', 'i18n.yml', 'setup.yml'] for name in files: path = os.path.join(tmp_dir, name) if not os.path.exists(path): @@ -84,6 +86,16 @@ class AppletViewSet(viewsets.ModelViewSet): serializer.save() return Response(serializer.data, status=201) + @action(detail=True, methods=['get']) + def download(self, request, *args, **kwargs): + instance = super().get_object() + path = default_storage.path('applets/{}'.format(instance.name)) + zip_path = shutil.make_archive(path, 'zip', path) + with open(zip_path, 'rb') as f: + response = HttpResponse(f.read(), status=200, content_type='application/octet-stream') + response['Content-Disposition'] = 'attachment; filename*=UTF-8\'\'{}.zip'.format(instance.name) + return response + class AppletPublicationViewSet(viewsets.ModelViewSet): queryset = AppletPublication.objects.all() diff --git a/apps/terminal/automations/deploy_applet_host/__init__.py b/apps/terminal/automations/deploy_applet_host/__init__.py index 287d44b3e..c02aa491a 100644 --- a/apps/terminal/automations/deploy_applet_host/__init__.py +++ b/apps/terminal/automations/deploy_applet_host/__init__.py @@ -2,6 +2,7 @@ import os import datetime import shutil +import yaml from django.utils import timezone from django.conf import settings @@ -26,10 +27,20 @@ class DeployAppletHostManager: def generate_playbook(self): playbook_src = os.path.join(CURRENT_DIR, 'playbook.yml') + with open(playbook_src) as f: + plays = yaml.safe_load(f) + for play in plays: + play['vars'].update(self.deployment.host.deploy_options) + play['vars']['DownloadHost'] = settings.BASE_URL + '/download/' + play['vars']['CORE_HOST'] = settings.BASE_URL + play['vars']['BOOTSTRAP_TOKEN'] = settings.BOOSTRAP_TOKEN + play['vars']['HOST_NAME'] = self.deployment.host.name + playbook_dir = os.path.join(self.run_dir, 'playbook') playbook_dst = os.path.join(playbook_dir, 'main.yml') os.makedirs(playbook_dir, exist_ok=True) - shutil.copy(playbook_src, playbook_dst) + with open(playbook_dst, 'w') as f: + yaml.safe_dump(plays, f) return playbook_dst def generate_inventory(self): diff --git a/apps/terminal/automations/deploy_applet_host/playbook.yml b/apps/terminal/automations/deploy_applet_host/playbook.yml index 20970c952..0c115e91a 100644 --- a/apps/terminal/automations/deploy_applet_host/playbook.yml +++ b/apps/terminal/automations/deploy_applet_host/playbook.yml @@ -2,13 +2,17 @@ - hosts: all vars: - - DownloadHost: https://demo.jumpserver.org/download - - RDS_Licensing: enabled - - RDS_LicenseServer: 127.0.0.1 - - RDS_LicensingMode: 4 - - RDS_fSingleSessionPerUser: 1 - - RDS_MaxDisconnectionTime: 60000 - - RDS_RemoteAppLogoffTimeLimit: 0 + DownloadHost: https://demo.jumpserver.org/download + Initial: 0 + HOST_NAME: test + CORE_HOST: https://demo.jumpserver.org + BOOTSTRAP_TOKEN: PleaseChangeMe + RDS_Licensing: true + RDS_LicenseServer: 127.0.0.1 + RDS_LicensingMode: 4 + RDS_fSingleSessionPerUser: 1 + RDS_MaxDisconnectionTime: 60000 + RDS_RemoteAppLogoffTimeLimit: 0 tasks: - name: Install RDS-Licensing (RDS) @@ -16,7 +20,7 @@ name: RDS-Licensing state: present include_management_tools: yes - when: RDS_Licensing == "enabled" + when: RDS_Licensing - name: Install RDS-RD-Server (RDS) ansible.windows.win_feature: @@ -136,3 +140,12 @@ state: present arguments: - /quiet + + - name: Generate component config + ansible.windows.win_shell: > + echo "Todo: Set config" + + - name: Sync all remote applets + ansible.windows.win_shell: > + echo "TODO: Sync all remote applets" + when: Initial diff --git a/apps/terminal/migrations/0054_auto_20221027_1125.py b/apps/terminal/migrations/0054_auto_20221027_1125.py index 4589d6970..b35108ca0 100644 --- a/apps/terminal/migrations/0054_auto_20221027_1125.py +++ b/apps/terminal/migrations/0054_auto_20221027_1125.py @@ -56,7 +56,7 @@ class Migration(migrations.Migration): ('date_created', models.DateTimeField(auto_now_add=True, null=True, verbose_name='Date created')), ('date_updated', models.DateTimeField(auto_now=True, verbose_name='Date updated')), ('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)), - ('status', models.CharField(max_length=16, verbose_name='Status')), + ('status', models.CharField(default='', max_length=16, verbose_name='Status')), ('comment', models.TextField(blank=True, default='', verbose_name='Comment')), ('applet', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='terminal.applet', verbose_name='Applet')), ('host', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='terminal.applethost', verbose_name='Host')), diff --git a/apps/terminal/migrations/0056_auto_20221101_1353.py b/apps/terminal/migrations/0056_auto_20221101_1353.py new file mode 100644 index 000000000..798420e2c --- /dev/null +++ b/apps/terminal/migrations/0056_auto_20221101_1353.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.14 on 2022-11-01 05:53 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('terminal', '0055_auto_20221031_1848'), + ] + + operations = [ + migrations.AddField( + model_name='applethost', + name='deploy_options', + field=models.JSONField(default=dict, verbose_name='Deploy options'), + ), + migrations.AddField( + model_name='applethostdeployment', + name='initial', + field=models.BooleanField(default=False, verbose_name='Initial'), + ), + ] diff --git a/apps/terminal/models/applet/applet.py b/apps/terminal/models/applet/applet.py index 14f363517..80be76e89 100644 --- a/apps/terminal/models/applet/applet.py +++ b/apps/terminal/models/applet/applet.py @@ -54,8 +54,7 @@ class Applet(JMSBaseModel): class AppletPublication(JMSBaseModel): applet = models.ForeignKey('Applet', on_delete=models.PROTECT, related_name='publications', verbose_name=_('Applet')) host = models.ForeignKey('AppletHost', on_delete=models.PROTECT, related_name='publications', verbose_name=_('Host')) - status = models.CharField(max_length=16, verbose_name=_('Status')) - published = models.BooleanField(default=False, verbose_name=_('Published')) + status = models.CharField(max_length=16, default='', verbose_name=_('Status')) comment = models.TextField(default='', blank=True, verbose_name=_('Comment')) class Meta: diff --git a/apps/terminal/models/applet/host.py b/apps/terminal/models/applet/host.py index e1edc2239..9c2338591 100644 --- a/apps/terminal/models/applet/host.py +++ b/apps/terminal/models/applet/host.py @@ -9,9 +9,10 @@ __all__ = ['AppletHost', 'AppletHostDeployment'] class AppletHost(Host): - LOCKING_ORG = 'SYSTEM' + LOCKING_ORG = '00000000-0000-0000-0000-000000000004' account_automation = models.BooleanField(default=False, verbose_name=_('Account automation')) + deploy_options = models.JSONField(default=dict, verbose_name=_('Deploy options')) inited = models.BooleanField(default=False, verbose_name=_('Inited')) date_inited = models.DateTimeField(null=True, blank=True, verbose_name=_('Date inited')) date_synced = models.DateTimeField(null=True, blank=True, verbose_name=_('Date synced')) @@ -27,6 +28,7 @@ class AppletHost(Host): class AppletHostDeployment(JMSBaseModel): host = models.ForeignKey('AppletHost', on_delete=models.CASCADE, verbose_name=_('Hosting')) + initial = models.BooleanField(default=False, verbose_name=_('Initial')) status = models.CharField(max_length=16, default='', verbose_name=_('Status')) date_start = models.DateTimeField(null=True, verbose_name=_('Date start'), db_index=True) date_finished = models.DateTimeField(null=True, verbose_name=_("Date finished")) diff --git a/apps/terminal/serializers/applet.py b/apps/terminal/serializers/applet.py index aad7e10ae..9530120b9 100644 --- a/apps/terminal/serializers/applet.py +++ b/apps/terminal/serializers/applet.py @@ -48,11 +48,30 @@ class AppletPublicationSerializer(serializers.ModelSerializer): ] + read_only_fields +class DeployOptionsSerializer(serializers.Serializer): + LICENSE_MODE_CHOICES = ( + (4, _('Per Session')), + (2, _('Per Device')), + ) + SESSION_PER_USER = ( + (1, _("Disabled")), + (0, _("Enabled")), + ) + RDS_Licensing = serializers.BooleanField(default=False, label=_("RDS Licensing")) + RDS_LicenseServer = serializers.CharField(default='127.0.0.1', label=_('RDS License Server'), max_length=1024) + RDS_LicensingMode = serializers.ChoiceField(choices=LICENSE_MODE_CHOICES, default=4, label=_('RDS Licensing Mode')) + RDS_fSingleSessionPerUser = serializers.ChoiceField(choices=SESSION_PER_USER, default=1, label=_("RDS fSingleSessionPerUser")) + RDS_MaxDisconnectionTime = serializers.IntegerField(default=60000, label=_("RDS Max Disconnection Time")) + RDS_RemoteAppLogoffTimeLimit = serializers.IntegerField(default=0, label=_("RDS Remote App Logoff Time Limit")) + + class AppletHostSerializer(HostSerializer): + deploy_options = DeployOptionsSerializer(required=False, label=_("Deploy options")) + class Meta(HostSerializer.Meta): model = AppletHost fields = HostSerializer.Meta.fields + [ - 'account_automation', 'status', 'date_synced' + 'account_automation', 'status', 'date_synced', 'deploy_options' ] extra_kwargs = { 'status': {'read_only': True}, diff --git a/apps/terminal/signal_handlers.py b/apps/terminal/signal_handlers.py index ec51c5a2b..5c92fd2ab 100644 --- a/apps/terminal/signal_handlers.py +++ b/apps/terminal/signal_handlers.py @@ -1,2 +1,18 @@ # -*- coding: utf-8 -*- # + +from django.db.models.signals import post_save +from django.dispatch import receiver + + +from .models import Applet, AppletHost + + +@receiver(post_save, sender=AppletHost) +def on_applet_host_create(sender, instance, created=False, **kwargs): + pass + + +@receiver(post_save, sender=Applet) +def on_applet_create(sender, instance, created=False, **kwargs): + pass