From d4469aeaf70d8bdd471767f2496ce827134440d9 Mon Sep 17 00:00:00 2001 From: jiangweidong Date: Tue, 29 Aug 2023 14:21:06 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20=E6=9F=A5=E7=9C=8B/=E4=B8=8B?= =?UTF-8?q?=E8=BD=BD=E5=BD=95=E5=83=8F=E8=A2=AB=E8=AE=B0=E5=BD=95=E5=9C=A8?= =?UTF-8?q?=E6=B4=BB=E5=8A=A8=E6=97=A5=E5=BF=97=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/accounts/api/account/account.py | 6 +-- apps/accounts/api/account/template.py | 4 +- apps/accounts/mixins.py | 75 +++++++++++++++++++++++++++ apps/audits/const.py | 1 + apps/common/api/patch.py | 4 ++ apps/common/views/mixins.py | 67 ++++-------------------- apps/terminal/api/session/session.py | 31 +++++++++-- 7 files changed, 121 insertions(+), 67 deletions(-) create mode 100644 apps/accounts/mixins.py diff --git a/apps/accounts/api/account/account.py b/apps/accounts/api/account/account.py index 201e63a20..740ccf041 100644 --- a/apps/accounts/api/account/account.py +++ b/apps/accounts/api/account/account.py @@ -7,10 +7,10 @@ from rest_framework.status import HTTP_200_OK from accounts import serializers from accounts.filters import AccountFilterSet from accounts.models import Account +from accounts.mixins import AccountRecordViewLogMixin from assets.models import Asset, Node from common.api.mixin import ExtraFilterFieldsMixin from common.permissions import UserConfirmation, ConfirmType, IsValidUser -from common.views.mixins import RecordViewLogMixin from orgs.mixins.api import OrgBulkModelViewSet from rbac.permissions import RBACPermission @@ -86,7 +86,7 @@ class AccountViewSet(OrgBulkModelViewSet): return Response(status=HTTP_200_OK) -class AccountSecretsViewSet(RecordViewLogMixin, AccountViewSet): +class AccountSecretsViewSet(AccountRecordViewLogMixin, AccountViewSet): """ 因为可能要导出所有账号,所以单独建立了一个 viewset """ @@ -115,7 +115,7 @@ class AssetAccountBulkCreateApi(CreateAPIView): return Response(data=serializer.data, status=HTTP_200_OK) -class AccountHistoriesSecretAPI(ExtraFilterFieldsMixin, RecordViewLogMixin, ListAPIView): +class AccountHistoriesSecretAPI(ExtraFilterFieldsMixin, AccountRecordViewLogMixin, ListAPIView): model = Account.history.model serializer_class = serializers.AccountHistorySerializer http_method_names = ['get', 'options'] diff --git a/apps/accounts/api/account/template.py b/apps/accounts/api/account/template.py index 1d2508764..f9c3637f8 100644 --- a/apps/accounts/api/account/template.py +++ b/apps/accounts/api/account/template.py @@ -4,10 +4,10 @@ from rest_framework.response import Response from accounts import serializers from accounts.models import AccountTemplate +from accounts.mixins import AccountRecordViewLogMixin from assets.const import Protocol from common.drf.filters import BaseFilterSet from common.permissions import UserConfirmation, ConfirmType -from common.views.mixins import RecordViewLogMixin from orgs.mixins.api import OrgBulkModelViewSet from rbac.permissions import RBACPermission @@ -55,7 +55,7 @@ class AccountTemplateViewSet(OrgBulkModelViewSet): return Response(data=serializer.data) -class AccountTemplateSecretsViewSet(RecordViewLogMixin, AccountTemplateViewSet): +class AccountTemplateSecretsViewSet(AccountRecordViewLogMixin, AccountTemplateViewSet): serializer_classes = { 'default': serializers.AccountTemplateSecretSerializer, } diff --git a/apps/accounts/mixins.py b/apps/accounts/mixins.py new file mode 100644 index 000000000..f4bacc2ce --- /dev/null +++ b/apps/accounts/mixins.py @@ -0,0 +1,75 @@ +from rest_framework.response import Response +from rest_framework import status +from django.utils import translation +from django.utils.translation import gettext_noop + +from audits.const import ActionChoices +from common.views.mixins import RecordViewLogMixin +from common.utils import i18n_fmt + + +class AccountRecordViewLogMixin(RecordViewLogMixin): + get_object: callable + get_queryset: callable + + @staticmethod + def _filter_params(params): + new_params = {} + need_pop_params = ('format', 'order') + for key, value in params.items(): + if key in need_pop_params: + continue + if isinstance(value, list): + value = list(filter(None, value)) + if value: + new_params[key] = value + return new_params + + def get_resource_display(self, request): + query_params = dict(request.query_params) + params = self._filter_params(query_params) + + spm_filter = params.pop("spm", None) + + if not params and not spm_filter: + display_message = gettext_noop("Export all") + elif spm_filter: + display_message = gettext_noop("Export only selected items") + else: + query = ",".join( + ["%s=%s" % (key, value) for key, value in params.items()] + ) + display_message = i18n_fmt(gettext_noop("Export filtered: %s"), query) + return display_message + + @property + def detail_msg(self): + return i18n_fmt( + gettext_noop('User %s view/export secret'), self.request.user + ) + + def list(self, request, *args, **kwargs): + list_func = getattr(super(), 'list') + if not callable(list_func): + return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED) + response = list_func(request, *args, **kwargs) + with translation.override('en'): + resource_display = self.get_resource_display(request) + ids = [q.id for q in self.get_queryset()] + self.record_logs( + ids, ActionChoices.view, self.detail_msg, resource_display=resource_display + ) + return response + + def retrieve(self, request, *args, **kwargs): + retrieve_func = getattr(super(), 'retrieve') + if not callable(retrieve_func): + return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED) + response = retrieve_func(request, *args, **kwargs) + with translation.override('en'): + resource = self.get_object() + self.record_logs( + [resource.id], ActionChoices.view, self.detail_msg, resource=resource + ) + return response + diff --git a/apps/audits/const.py b/apps/audits/const.py index a2832ef9d..44d3a556f 100644 --- a/apps/audits/const.py +++ b/apps/audits/const.py @@ -25,6 +25,7 @@ class ActionChoices(TextChoices): delete = "delete", _("Delete") create = "create", _("Create") # Activities action + download = "download", _("Download") connect = "connect", _("Connect") login = "login", _("Login") change_auth = "change_password", _("Change password") diff --git a/apps/common/api/patch.py b/apps/common/api/patch.py index f79957546..821dff4ea 100644 --- a/apps/common/api/patch.py +++ b/apps/common/api/patch.py @@ -88,6 +88,7 @@ class AsyncApiMixin(InterceptMixin): if not self.is_need_async(): return handler(*args, **kwargs) resp = self.do_async(handler, *args, **kwargs) + self.async_callback(*args, **kwargs) return resp def is_need_refresh(self): @@ -98,6 +99,9 @@ class AsyncApiMixin(InterceptMixin): def is_need_async(self): return False + def async_callback(self, params): + pass + def do_async(self, handler, *args, **kwargs): data = self.get_cache_data() if not data: diff --git a/apps/common/views/mixins.py b/apps/common/views/mixins.py index 6240fee5a..be9f7347f 100644 --- a/apps/common/views/mixins.py +++ b/apps/common/views/mixins.py @@ -2,16 +2,14 @@ # from django.contrib.auth.mixins import UserPassesTestMixin from django.http.response import JsonResponse -from django.utils import translation -from django.utils.translation import gettext_noop +from django.db.models import Model from rest_framework import permissions from rest_framework.request import Request -from audits.const import ActionChoices, ActivityChoices +from audits.const import ActivityChoices from audits.handler import create_or_update_operate_log from audits.models import ActivityLog from common.exceptions import UserConfirmRequired -from common.utils import i18n_fmt from orgs.utils import current_org __all__ = [ @@ -49,66 +47,19 @@ class PermissionsMixin(UserPassesTestMixin): class RecordViewLogMixin: - ACTION = ActionChoices.view + model: Model - @staticmethod - def _filter_params(params): - new_params = {} - need_pop_params = ('format', 'order') - for key, value in params.items(): - if key in need_pop_params: - continue - if isinstance(value, list): - value = list(filter(None, value)) - if value: - new_params[key] = value - return new_params - - def get_resource_display(self, request): - query_params = dict(request.query_params) - params = self._filter_params(query_params) - - spm_filter = params.pop("spm", None) - - if not params and not spm_filter: - display_message = gettext_noop("Export all") - elif spm_filter: - display_message = gettext_noop("Export only selected items") - else: - query = ",".join( - ["%s=%s" % (key, value) for key, value in params.items()] - ) - display_message = i18n_fmt(gettext_noop("Export filtered: %s"), query) - return display_message - - def record_logs(self, ids, **kwargs): - resource_type = self.model._meta.verbose_name + def record_logs(self, ids, action, detail, model=None, **kwargs): + model = model or self.model + resource_type = model._meta.verbose_name create_or_update_operate_log( - self.ACTION, resource_type, force=True, **kwargs - ) - detail = i18n_fmt( - gettext_noop('User %s view/export secret'), self.request.user + action, resource_type, force=True, **kwargs ) activities = [ ActivityLog( - resource_id=getattr(resource_id, 'pk', resource_id), - type=ActivityChoices.operate_log, detail=detail, org_id=current_org.id, + resource_id=resource_id, type=ActivityChoices.operate_log, + detail=detail, org_id=current_org.id, ) for resource_id in ids ] ActivityLog.objects.bulk_create(activities) - - def list(self, request, *args, **kwargs): - response = super().list(request, *args, **kwargs) - with translation.override('en'): - resource_display = self.get_resource_display(request) - ids = [q.id for q in self.get_queryset()] - self.record_logs(ids, resource_display=resource_display) - return response - - def retrieve(self, request, *args, **kwargs): - response = super().retrieve(request, *args, **kwargs) - with translation.override('en'): - resource = self.get_object() - self.record_logs([resource.id], resource=resource) - return response diff --git a/apps/terminal/api/session/session.py b/apps/terminal/api/session/session.py index 1782b0207..98a1fe73c 100644 --- a/apps/terminal/api/session/session.py +++ b/apps/terminal/api/session/session.py @@ -8,7 +8,7 @@ from django.db.models import F from django.http import FileResponse from django.shortcuts import get_object_or_404, reverse from django.utils.encoding import escape_uri_path -from django.utils.translation import gettext as _ +from django.utils.translation import gettext_noop, gettext as _ from django_filters import rest_framework as filters from rest_framework import generics from rest_framework import viewsets, views @@ -16,14 +16,16 @@ from rest_framework.decorators import action from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response +from audits.const import ActionChoices from common.api import AsyncApiMixin from common.const.http import GET from common.drf.filters import BaseFilterSet from common.drf.filters import DatetimeRangeFilterBackend from common.drf.renders import PassthroughRenderer from common.storage.replay import ReplayStorageHandler -from common.utils import data_to_json, is_uuid +from common.utils import data_to_json, is_uuid, i18n_fmt from common.utils import get_logger, get_object_or_none +from common.views.mixins import RecordViewLogMixin from orgs.mixins.api import OrgBulkModelViewSet from orgs.utils import tmp_to_root_org, tmp_to_org from rbac.permissions import RBACPermission @@ -70,7 +72,7 @@ class SessionFilterSet(BaseFilterSet): return queryset.filter(terminal__name=value) -class SessionViewSet(OrgBulkModelViewSet): +class SessionViewSet(RecordViewLogMixin, OrgBulkModelViewSet): model = Session serializer_classes = { 'default': serializers.SessionSerializer, @@ -132,6 +134,15 @@ class SessionViewSet(OrgBulkModelViewSet): filename = escape_uri_path('{}.tar'.format(storage.obj.id)) disposition = "attachment; filename*=UTF-8''{}".format(filename) response["Content-Disposition"] = disposition + + detail = i18n_fmt( + gettext_noop(f'User %s %s session %s replay'), self.request.user, + gettext_noop(ActionChoices.download), str(storage.obj) + ) + self.record_logs( + [storage.obj.asset_id], ActionChoices.download, detail, + model=Session, resource_display=str(storage.obj) + ) return response def get_queryset(self): @@ -152,7 +163,7 @@ class SessionViewSet(OrgBulkModelViewSet): return super().perform_create(serializer) -class SessionReplayViewSet(AsyncApiMixin, viewsets.ViewSet): +class SessionReplayViewSet(AsyncApiMixin, RecordViewLogMixin, viewsets.ViewSet): serializer_class = serializers.ReplaySerializer download_cache_key = "SESSION_REPLAY_DOWNLOAD_{}" session = None @@ -215,6 +226,18 @@ class SessionReplayViewSet(AsyncApiMixin, viewsets.ViewSet): return False return True + def async_callback(self, *args, **kwargs): + session_id = kwargs.get('pk') + session = get_object_or_404(Session, id=session_id) + detail = i18n_fmt( + gettext_noop(f'User %s %s session %s replay'), self.request.user, + gettext_noop(ActionChoices.view), str(session) + ) + self.record_logs( + [session.asset_id], ActionChoices.download, detail, + model=Session, resource_display=str(session) + ) + def retrieve(self, request, *args, **kwargs): session_id = kwargs.get('pk') session = get_object_or_404(Session, id=session_id) From d70770775aba543936e4b50652e85e60ef185273 Mon Sep 17 00:00:00 2001 From: jiangweidong Date: Tue, 29 Aug 2023 15:16:02 +0800 Subject: [PATCH 2/3] =?UTF-8?q?perf:=20=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/views/mixins.py | 26 +++--- apps/locale/ja/LC_MESSAGES/django.po | 133 ++++++++++++++------------- apps/locale/zh/LC_MESSAGES/django.po | 131 +++++++++++++------------- apps/terminal/api/session/session.py | 8 +- 4 files changed, 156 insertions(+), 142 deletions(-) diff --git a/apps/common/views/mixins.py b/apps/common/views/mixins.py index be9f7347f..6f59ac21a 100644 --- a/apps/common/views/mixins.py +++ b/apps/common/views/mixins.py @@ -3,6 +3,7 @@ from django.contrib.auth.mixins import UserPassesTestMixin from django.http.response import JsonResponse from django.db.models import Model +from django.utils import translation from rest_framework import permissions from rest_framework.request import Request @@ -50,16 +51,17 @@ class RecordViewLogMixin: model: Model def record_logs(self, ids, action, detail, model=None, **kwargs): - model = model or self.model - resource_type = model._meta.verbose_name - create_or_update_operate_log( - action, resource_type, force=True, **kwargs - ) - activities = [ - ActivityLog( - resource_id=resource_id, type=ActivityChoices.operate_log, - detail=detail, org_id=current_org.id, + with translation.override('en'): + model = model or self.model + resource_type = model._meta.verbose_name + create_or_update_operate_log( + action, resource_type, force=True, **kwargs ) - for resource_id in ids - ] - ActivityLog.objects.bulk_create(activities) + activities = [ + ActivityLog( + resource_id=resource_id, type=ActivityChoices.operate_log, + detail=detail, org_id=current_org.id, + ) + for resource_id in ids + ] + ActivityLog.objects.bulk_create(activities) diff --git a/apps/locale/ja/LC_MESSAGES/django.po b/apps/locale/ja/LC_MESSAGES/django.po index 1829db862..8355a63d7 100644 --- a/apps/locale/ja/LC_MESSAGES/django.po +++ b/apps/locale/ja/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-08-28 10:55+0800\n" +"POT-Creation-Date: 2023-08-29 15:14+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -93,7 +93,7 @@ msgid "Update" msgstr "更新" #: accounts/const/account.py:33 -#: accounts/serializers/automations/change_secret.py:156 audits/const.py:54 +#: accounts/serializers/automations/change_secret.py:156 audits/const.py:55 #: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 #: ops/const.py:61 terminal/const.py:77 xpack/plugins/cloud/const.py:43 msgid "Failed" @@ -227,7 +227,7 @@ msgstr "から切り替え" #: accounts/models/account.py:54 assets/const/protocol.py:162 #: settings/serializers/auth/cas.py:20 settings/serializers/auth/feishu.py:20 -#: terminal/models/applet/applet.py:34 +#: terminal/models/applet/applet.py:35 msgid "Version" msgstr "バージョン" @@ -331,56 +331,56 @@ msgstr "成功は" msgid "Account backup execution" msgstr "アカウントバックアップの実行" -#: accounts/models/automations/base.py:20 +#: accounts/models/automations/base.py:19 msgid "Account automation task" msgstr "アカウント自動化タスク" -#: accounts/models/automations/base.py:34 +#: accounts/models/automations/base.py:33 msgid "Automation execution" msgstr "自動実行" -#: accounts/models/automations/base.py:35 +#: accounts/models/automations/base.py:34 msgid "Automation executions" msgstr "自動実行" -#: accounts/models/automations/base.py:37 +#: accounts/models/automations/base.py:36 msgid "Can view change secret execution" msgstr "改密実行の表示" -#: accounts/models/automations/base.py:38 +#: accounts/models/automations/base.py:37 msgid "Can add change secret execution" msgstr "改密実行の作成" -#: accounts/models/automations/base.py:40 +#: accounts/models/automations/base.py:39 msgid "Can view gather accounts execution" msgstr "コレクションアカウントの実行を表示" -#: accounts/models/automations/base.py:41 +#: accounts/models/automations/base.py:40 msgid "Can add gather accounts execution" msgstr "回収口座作成の実行" -#: accounts/models/automations/base.py:43 +#: accounts/models/automations/base.py:42 msgid "Can view push account execution" msgstr "プッシュ アカウントの実行を表示する" -#: accounts/models/automations/base.py:44 +#: accounts/models/automations/base.py:43 msgid "Can add push account execution" msgstr "プッシュ アカウントの作成の実行" -#: accounts/models/automations/base.py:56 accounts/models/template.py:21 +#: accounts/models/automations/base.py:55 accounts/models/template.py:21 #: accounts/serializers/automations/change_secret.py:40 msgid "Secret strategy" msgstr "鍵ポリシー" -#: accounts/models/automations/base.py:58 +#: accounts/models/automations/base.py:57 msgid "Password rules" msgstr "パスワードルール" -#: accounts/models/automations/base.py:61 +#: accounts/models/automations/base.py:60 msgid "SSH key change strategy" msgstr "SSHキープッシュ方式" -#: accounts/models/automations/base.py:71 accounts/models/base.py:36 +#: accounts/models/automations/base.py:70 accounts/models/base.py:36 #: accounts/serializers/account/account.py:429 #: accounts/serializers/account/base.py:16 #: accounts/serializers/automations/change_secret.py:46 @@ -389,7 +389,7 @@ msgstr "SSHキープッシュ方式" msgid "Secret type" msgstr "鍵の種類" -#: accounts/models/automations/base.py:73 accounts/models/mixins/vault.py:48 +#: accounts/models/automations/base.py:72 accounts/models/mixins/vault.py:48 #: accounts/serializers/account/base.py:19 #: authentication/models/temp_token.py:10 #: authentication/templates/authentication/_access_key_modal.html:31 @@ -510,7 +510,7 @@ msgstr "アカウントの確認" #: ops/models/job.py:126 ops/models/playbook.py:28 ops/serializers/job.py:20 #: orgs/models.py:82 perms/models/asset_permission.py:56 rbac/models/role.py:29 #: settings/models.py:32 settings/serializers/msg.py:82 -#: terminal/models/applet/applet.py:32 terminal/models/component/endpoint.py:12 +#: terminal/models/applet/applet.py:33 terminal/models/component/endpoint.py:12 #: terminal/models/component/endpoint.py:94 #: terminal/models/component/storage.py:26 terminal/models/component/task.py:13 #: terminal/models/component/terminal.py:84 users/forms/profile.py:33 @@ -528,7 +528,7 @@ msgstr "特権アカウント" #: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 #: assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:114 -#: terminal/models/applet/applet.py:39 +#: terminal/models/applet/applet.py:40 #: terminal/models/component/endpoint.py:105 users/serializers/user.py:170 msgid "Is active" msgstr "アクティブです。" @@ -652,7 +652,7 @@ msgstr "カテゴリ" #: assets/serializers/asset/common.py:122 assets/serializers/platform.py:112 #: assets/serializers/platform.py:127 audits/serializers.py:49 #: authentication/serializers/connect_token_secret.py:123 ops/models/job.py:137 -#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:38 +#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:39 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29 #: terminal/serializers/session.py:21 terminal/serializers/storage.py:226 @@ -792,8 +792,8 @@ msgstr "关联平台,可以配置推送参数,如果不关联,则使用默 #: assets/models/cmd_filter.py:40 assets/models/cmd_filter.py:88 #: assets/models/group.py:20 common/db/models.py:36 ops/models/adhoc.py:26 #: ops/models/job.py:145 ops/models/playbook.py:31 rbac/models/role.py:37 -#: settings/models.py:37 terminal/models/applet/applet.py:44 -#: terminal/models/applet/applet.py:284 terminal/models/applet/host.py:142 +#: settings/models.py:37 terminal/models/applet/applet.py:45 +#: terminal/models/applet/applet.py:302 terminal/models/applet/host.py:142 #: terminal/models/component/endpoint.py:24 #: terminal/models/component/endpoint.py:104 #: terminal/models/session/session.py:46 tickets/models/comment.py:32 @@ -844,7 +844,7 @@ msgstr "* パスワードの長さの範囲6-30ビット" msgid "Automation task execution" msgstr "自動タスク実行履歴" -#: accounts/serializers/automations/change_secret.py:155 audits/const.py:53 +#: accounts/serializers/automations/change_secret.py:155 audits/const.py:54 #: audits/models.py:59 audits/signal_handlers/activity_log.py:33 #: common/const/choices.py:18 ops/const.py:59 ops/serializers/celery.py:40 #: terminal/const.py:76 terminal/models/session/sharing.py:121 @@ -852,7 +852,8 @@ msgstr "自動タスク実行履歴" msgid "Success" msgstr "成功" -#: accounts/signal_handlers.py:47 +#: accounts/signal_handlers.py:46 +#, python-format msgid "Push related accounts to assets: %s, by system" msgstr "関連するアカウントをアセットにプッシュ: %s, by system" @@ -1166,7 +1167,7 @@ msgstr "認証に失敗しました" msgid "Connect failed" msgstr "接続に失敗しました" -#: assets/const/automation.py:6 audits/const.py:6 audits/const.py:36 +#: assets/const/automation.py:6 audits/const.py:6 audits/const.py:37 #: audits/signal_handlers/activity_log.py:62 common/utils/ip/geoip/utils.py:31 #: common/utils/ip/geoip/utils.py:37 common/utils/ip/utils.py:104 msgid "Unknown" @@ -1188,7 +1189,7 @@ msgstr "テストゲートウェイ" msgid "Gather facts" msgstr "資産情報の収集" -#: assets/const/base.py:33 audits/const.py:47 +#: assets/const/base.py:33 audits/const.py:48 #: terminal/serializers/applet_host.py:32 msgid "Disabled" msgstr "無効" @@ -1219,8 +1220,8 @@ msgid "Cloud service" msgstr "クラウド サービス" #: assets/const/category.py:14 assets/models/asset/gpt.py:11 -#: assets/models/asset/web.py:16 audits/const.py:34 -#: terminal/models/applet/applet.py:26 +#: assets/models/asset/web.py:16 audits/const.py:35 +#: terminal/models/applet/applet.py:27 msgid "Web" msgstr "Web" @@ -1240,7 +1241,7 @@ msgstr "私有雲" msgid "Kubernetes" msgstr "Kubernetes" -#: assets/const/device.py:7 terminal/models/applet/applet.py:25 +#: assets/const/device.py:7 terminal/models/applet/applet.py:26 #: tickets/const.py:8 msgid "General" msgstr "一般" @@ -1433,7 +1434,7 @@ msgstr "ユーザーと同じユーザー名" #: assets/models/_user.py:52 authentication/models/connection_token.py:41 #: authentication/serializers/connect_token_secret.py:111 -#: terminal/models/applet/applet.py:41 terminal/serializers/session.py:19 +#: terminal/models/applet/applet.py:42 terminal/serializers/session.py:19 #: terminal/serializers/session.py:42 terminal/serializers/storage.py:70 msgid "Protocol" msgstr "プロトコル" @@ -1572,7 +1573,7 @@ msgstr "アセットの自動化タスク" #: assets/models/automations/base.py:113 audits/models.py:199 #: audits/serializers.py:50 ops/models/base.py:49 ops/models/job.py:220 -#: terminal/models/applet/applet.py:283 terminal/models/applet/host.py:139 +#: terminal/models/applet/applet.py:301 terminal/models/applet/host.py:139 #: terminal/models/component/status.py:30 terminal/serializers/applet.py:18 #: terminal/serializers/applet_host.py:115 tickets/models/ticket/general.py:283 #: tickets/serializers/super_ticket.py:13 @@ -1717,7 +1718,7 @@ msgstr "開ける" msgid "Setting" msgstr "設定" -#: assets/models/platform.py:38 audits/const.py:48 settings/models.py:36 +#: assets/models/platform.py:38 audits/const.py:49 settings/models.py:36 #: terminal/serializers/applet_host.py:33 msgid "Enabled" msgstr "有効化" @@ -2129,7 +2130,8 @@ msgstr "名前の変更" msgid "Symlink" msgstr "Symlink" -#: audits/const.py:18 perms/const.py:14 +#: audits/const.py:18 audits/const.py:28 perms/const.py:14 +#: terminal/api/session/session.py:141 msgid "Download" msgstr "ダウンロード" @@ -2137,7 +2139,7 @@ msgstr "ダウンロード" msgid "Rename dir" msgstr "マップディレクトリ" -#: audits/const.py:23 rbac/tree.py:232 +#: audits/const.py:23 rbac/tree.py:232 terminal/api/session/session.py:234 #: terminal/templates/terminal/_msg_command_warning.html:18 #: terminal/templates/terminal/_msg_session_sharing.html:10 msgid "View" @@ -2149,44 +2151,44 @@ msgstr "表示" msgid "Create" msgstr "作成" -#: audits/const.py:28 perms/const.py:12 +#: audits/const.py:29 perms/const.py:12 msgid "Connect" msgstr "接続" -#: audits/const.py:29 authentication/templates/authentication/login.html:252 +#: audits/const.py:30 authentication/templates/authentication/login.html:252 #: authentication/templates/authentication/login.html:325 #: templates/_header_bar.html:89 msgid "Login" msgstr "ログイン" -#: audits/const.py:30 ops/const.py:9 +#: audits/const.py:31 ops/const.py:9 msgid "Change password" msgstr "パスワードを変更する" -#: audits/const.py:35 settings/serializers/terminal.py:6 +#: audits/const.py:36 settings/serializers/terminal.py:6 #: terminal/models/applet/host.py:26 terminal/models/component/terminal.py:164 #: terminal/serializers/session.py:49 terminal/serializers/session.py:63 msgid "Terminal" msgstr "ターミナル" -#: audits/const.py:40 audits/models.py:127 +#: audits/const.py:41 audits/models.py:127 msgid "Operate log" msgstr "ログの操作" -#: audits/const.py:41 +#: audits/const.py:42 msgid "Session log" msgstr "セッションログ" -#: audits/const.py:42 +#: audits/const.py:43 msgid "Login log" msgstr "ログインログ" -#: audits/const.py:43 terminal/models/applet/host.py:143 +#: audits/const.py:44 terminal/models/applet/host.py:143 #: terminal/models/component/task.py:22 msgid "Task" msgstr "タスク" -#: audits/const.py:49 +#: audits/const.py:50 msgid "-" msgstr "-" @@ -2412,7 +2414,7 @@ msgstr "ACL アクションはレビューです" msgid "Current user not support mfa type: {}" msgstr "現在のユーザーはmfaタイプをサポートしていません: {}" -#: authentication/api/password.py:32 terminal/api/session/session.py:259 +#: authentication/api/password.py:32 terminal/api/session/session.py:282 #: users/views/profile/reset.py:44 msgid "User does not exist: {}" msgstr "ユーザーが存在しない: {}" @@ -4099,7 +4101,7 @@ msgstr "デフォルト組織" msgid "SYSTEM" msgstr "システム組織" -#: orgs/models.py:83 rbac/models/role.py:36 terminal/models/applet/applet.py:40 +#: orgs/models.py:83 rbac/models/role.py:36 terminal/models/applet/applet.py:41 msgid "Builtin" msgstr "ビルトイン" @@ -4336,7 +4338,7 @@ msgstr "パーマ" msgid "Users amount" msgstr "ユーザー数" -#: rbac/serializers/role.py:28 terminal/models/applet/applet.py:33 +#: rbac/serializers/role.py:28 terminal/models/applet/applet.py:34 msgid "Display name" msgstr "表示名" @@ -4396,8 +4398,8 @@ msgstr "タスクセンター" msgid "My assets" msgstr "私の資産" -#: rbac/tree.py:56 terminal/models/applet/applet.py:51 -#: terminal/models/applet/applet.py:280 terminal/models/applet/host.py:29 +#: rbac/tree.py:56 terminal/models/applet/applet.py:52 +#: terminal/models/applet/applet.py:298 terminal/models/applet/host.py:29 #: terminal/serializers/applet.py:15 msgid "Applet" msgstr "リモートアプリケーション" @@ -5902,15 +5904,20 @@ msgstr "テスト失敗: アカウントが無効" msgid "Have online sessions" msgstr "オンラインセッションを持つ" -#: terminal/api/session/session.py:251 +#: terminal/api/session/session.py:46 +#, python-format +msgid "User %s %s session %s replay" +msgstr "ユーザー%s %sこのセッション %s の録画です" + +#: terminal/api/session/session.py:274 msgid "Session does not exist: {}" msgstr "セッションが存在しません: {}" -#: terminal/api/session/session.py:254 +#: terminal/api/session/session.py:277 msgid "Session is finished or the protocol not supported" msgstr "セッションが終了したか、プロトコルがサポートされていません" -#: terminal/api/session/session.py:267 +#: terminal/api/session/session.py:290 msgid "User does not have permission" msgstr "ユーザーに権限がありません" @@ -6028,51 +6035,51 @@ msgstr "一括作成非サポート" msgid "Storage is invalid" msgstr "ストレージが無効です" -#: terminal/models/applet/applet.py:29 +#: terminal/models/applet/applet.py:30 msgid "Community" msgstr "コミュニティ版" -#: terminal/models/applet/applet.py:30 +#: terminal/models/applet/applet.py:31 msgid "Enterprise" msgstr "エンタープライズ版" -#: terminal/models/applet/applet.py:35 +#: terminal/models/applet/applet.py:36 msgid "Author" msgstr "著者" -#: terminal/models/applet/applet.py:37 terminal/serializers/applet.py:31 +#: terminal/models/applet/applet.py:38 terminal/serializers/applet.py:31 msgid "Edition" msgstr "バージョン" -#: terminal/models/applet/applet.py:42 +#: terminal/models/applet/applet.py:43 msgid "Can concurrent" msgstr "同時実行可能" -#: terminal/models/applet/applet.py:43 +#: terminal/models/applet/applet.py:44 msgid "Tags" msgstr "ラベル" -#: terminal/models/applet/applet.py:47 terminal/serializers/storage.py:159 +#: terminal/models/applet/applet.py:48 terminal/serializers/storage.py:159 msgid "Hosts" msgstr "ホスト" -#: terminal/models/applet/applet.py:92 +#: terminal/models/applet/applet.py:93 msgid "Applet pkg not valid, Missing file {}" msgstr "無効なアプレット パッケージ、ファイル {} がありません" -#: terminal/models/applet/applet.py:111 +#: terminal/models/applet/applet.py:112 msgid "Load platform.yml failed: {}" msgstr "platform.ymlのロードに失敗しました:{}" -#: terminal/models/applet/applet.py:114 +#: terminal/models/applet/applet.py:115 msgid "Only support custom platform" msgstr "カスタムプラットフォームのみをサポート" -#: terminal/models/applet/applet.py:119 +#: terminal/models/applet/applet.py:120 msgid "Missing type in platform.yml" msgstr "platform.ymlにタイプがありません" -#: terminal/models/applet/applet.py:282 terminal/models/applet/host.py:35 +#: terminal/models/applet/applet.py:300 terminal/models/applet/host.py:35 #: terminal/models/applet/host.py:137 msgid "Hosting" msgstr "ホスト マシン" diff --git a/apps/locale/zh/LC_MESSAGES/django.po b/apps/locale/zh/LC_MESSAGES/django.po index 4c1db1387..df1a28780 100644 --- a/apps/locale/zh/LC_MESSAGES/django.po +++ b/apps/locale/zh/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: JumpServer 0.3.3\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-08-28 10:55+0800\n" +"POT-Creation-Date: 2023-08-29 14:45+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\n" "Last-Translator: ibuler \n" "Language-Team: JumpServer team\n" @@ -92,7 +92,7 @@ msgid "Update" msgstr "更新" #: accounts/const/account.py:33 -#: accounts/serializers/automations/change_secret.py:156 audits/const.py:54 +#: accounts/serializers/automations/change_secret.py:156 audits/const.py:55 #: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19 #: ops/const.py:61 terminal/const.py:77 xpack/plugins/cloud/const.py:43 msgid "Failed" @@ -226,7 +226,7 @@ msgstr "切换自" #: accounts/models/account.py:54 assets/const/protocol.py:162 #: settings/serializers/auth/cas.py:20 settings/serializers/auth/feishu.py:20 -#: terminal/models/applet/applet.py:34 +#: terminal/models/applet/applet.py:35 msgid "Version" msgstr "版本" @@ -330,56 +330,56 @@ msgstr "是否成功" msgid "Account backup execution" msgstr "账号备份执行" -#: accounts/models/automations/base.py:20 +#: accounts/models/automations/base.py:19 msgid "Account automation task" msgstr "账号自动化任务" -#: accounts/models/automations/base.py:34 +#: accounts/models/automations/base.py:33 msgid "Automation execution" msgstr "自动化执行" -#: accounts/models/automations/base.py:35 +#: accounts/models/automations/base.py:34 msgid "Automation executions" msgstr "自动化执行" -#: accounts/models/automations/base.py:37 +#: accounts/models/automations/base.py:36 msgid "Can view change secret execution" msgstr "查看改密执行" -#: accounts/models/automations/base.py:38 +#: accounts/models/automations/base.py:37 msgid "Can add change secret execution" msgstr "创建改密执行" -#: accounts/models/automations/base.py:40 +#: accounts/models/automations/base.py:39 msgid "Can view gather accounts execution" msgstr "查看收集账号执行" -#: accounts/models/automations/base.py:41 +#: accounts/models/automations/base.py:40 msgid "Can add gather accounts execution" msgstr "创建收集账号执行" -#: accounts/models/automations/base.py:43 +#: accounts/models/automations/base.py:42 msgid "Can view push account execution" msgstr "查看推送账号执行" -#: accounts/models/automations/base.py:44 +#: accounts/models/automations/base.py:43 msgid "Can add push account execution" msgstr "创建推送账号执行" -#: accounts/models/automations/base.py:56 accounts/models/template.py:21 +#: accounts/models/automations/base.py:55 accounts/models/template.py:21 #: accounts/serializers/automations/change_secret.py:40 msgid "Secret strategy" msgstr "密文策略" -#: accounts/models/automations/base.py:58 +#: accounts/models/automations/base.py:57 msgid "Password rules" msgstr "密码规则" -#: accounts/models/automations/base.py:61 +#: accounts/models/automations/base.py:60 msgid "SSH key change strategy" msgstr "SSH 密钥推送方式" -#: accounts/models/automations/base.py:71 accounts/models/base.py:36 +#: accounts/models/automations/base.py:70 accounts/models/base.py:36 #: accounts/serializers/account/account.py:429 #: accounts/serializers/account/base.py:16 #: accounts/serializers/automations/change_secret.py:46 @@ -388,7 +388,7 @@ msgstr "SSH 密钥推送方式" msgid "Secret type" msgstr "密文类型" -#: accounts/models/automations/base.py:73 accounts/models/mixins/vault.py:48 +#: accounts/models/automations/base.py:72 accounts/models/mixins/vault.py:48 #: accounts/serializers/account/base.py:19 #: authentication/models/temp_token.py:10 #: authentication/templates/authentication/_access_key_modal.html:31 @@ -509,7 +509,7 @@ msgstr "账号验证" #: ops/models/job.py:126 ops/models/playbook.py:28 ops/serializers/job.py:20 #: orgs/models.py:82 perms/models/asset_permission.py:56 rbac/models/role.py:29 #: settings/models.py:32 settings/serializers/msg.py:82 -#: terminal/models/applet/applet.py:32 terminal/models/component/endpoint.py:12 +#: terminal/models/applet/applet.py:33 terminal/models/component/endpoint.py:12 #: terminal/models/component/endpoint.py:94 #: terminal/models/component/storage.py:26 terminal/models/component/task.py:13 #: terminal/models/component/terminal.py:84 users/forms/profile.py:33 @@ -527,7 +527,7 @@ msgstr "特权账号" #: assets/models/automations/base.py:21 assets/models/cmd_filter.py:39 #: assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:114 -#: terminal/models/applet/applet.py:39 +#: terminal/models/applet/applet.py:40 #: terminal/models/component/endpoint.py:105 users/serializers/user.py:170 msgid "Is active" msgstr "激活" @@ -650,7 +650,7 @@ msgstr "类别" #: assets/serializers/asset/common.py:122 assets/serializers/platform.py:112 #: assets/serializers/platform.py:127 audits/serializers.py:49 #: authentication/serializers/connect_token_secret.py:123 ops/models/job.py:137 -#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:38 +#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:39 #: terminal/models/component/storage.py:57 #: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29 #: terminal/serializers/session.py:21 terminal/serializers/storage.py:226 @@ -790,8 +790,8 @@ msgstr "关联平台,可配置推送参数,如果不关联,将使用默认 #: assets/models/cmd_filter.py:40 assets/models/cmd_filter.py:88 #: assets/models/group.py:20 common/db/models.py:36 ops/models/adhoc.py:26 #: ops/models/job.py:145 ops/models/playbook.py:31 rbac/models/role.py:37 -#: settings/models.py:37 terminal/models/applet/applet.py:44 -#: terminal/models/applet/applet.py:284 terminal/models/applet/host.py:142 +#: settings/models.py:37 terminal/models/applet/applet.py:45 +#: terminal/models/applet/applet.py:302 terminal/models/applet/host.py:142 #: terminal/models/component/endpoint.py:24 #: terminal/models/component/endpoint.py:104 #: terminal/models/session/session.py:46 tickets/models/comment.py:32 @@ -842,7 +842,7 @@ msgstr "* 密码长度范围 6-30 位" msgid "Automation task execution" msgstr "自动化任务执行历史" -#: accounts/serializers/automations/change_secret.py:155 audits/const.py:53 +#: accounts/serializers/automations/change_secret.py:155 audits/const.py:54 #: audits/models.py:59 audits/signal_handlers/activity_log.py:33 #: common/const/choices.py:18 ops/const.py:59 ops/serializers/celery.py:40 #: terminal/const.py:76 terminal/models/session/sharing.py:121 @@ -850,8 +850,8 @@ msgstr "自动化任务执行历史" msgid "Success" msgstr "成功" -#: accounts/signal_handlers.py:47 -#, fpython-format +#: accounts/signal_handlers.py:46 +#, python-format msgid "Push related accounts to assets: %s, by system" msgstr "推送账号到资产: %s, 由系统执行" @@ -1162,7 +1162,7 @@ msgstr "认证失败" msgid "Connect failed" msgstr "连接失败" -#: assets/const/automation.py:6 audits/const.py:6 audits/const.py:36 +#: assets/const/automation.py:6 audits/const.py:6 audits/const.py:37 #: audits/signal_handlers/activity_log.py:62 common/utils/ip/geoip/utils.py:31 #: common/utils/ip/geoip/utils.py:37 common/utils/ip/utils.py:104 msgid "Unknown" @@ -1184,7 +1184,7 @@ msgstr "测试网关" msgid "Gather facts" msgstr "收集资产信息" -#: assets/const/base.py:33 audits/const.py:47 +#: assets/const/base.py:33 audits/const.py:48 #: terminal/serializers/applet_host.py:32 msgid "Disabled" msgstr "禁用" @@ -1215,8 +1215,8 @@ msgid "Cloud service" msgstr "云服务" #: assets/const/category.py:14 assets/models/asset/gpt.py:11 -#: assets/models/asset/web.py:16 audits/const.py:34 -#: terminal/models/applet/applet.py:26 +#: assets/models/asset/web.py:16 audits/const.py:35 +#: terminal/models/applet/applet.py:27 msgid "Web" msgstr "Web" @@ -1236,7 +1236,7 @@ msgstr "私有云" msgid "Kubernetes" msgstr "Kubernetes" -#: assets/const/device.py:7 terminal/models/applet/applet.py:25 +#: assets/const/device.py:7 terminal/models/applet/applet.py:26 #: tickets/const.py:8 msgid "General" msgstr "一般" @@ -1430,7 +1430,7 @@ msgstr "用户名与用户相同" #: assets/models/_user.py:52 authentication/models/connection_token.py:41 #: authentication/serializers/connect_token_secret.py:111 -#: terminal/models/applet/applet.py:41 terminal/serializers/session.py:19 +#: terminal/models/applet/applet.py:42 terminal/serializers/session.py:19 #: terminal/serializers/session.py:42 terminal/serializers/storage.py:70 msgid "Protocol" msgstr "协议" @@ -1569,7 +1569,7 @@ msgstr "资产自动化任务" #: assets/models/automations/base.py:113 audits/models.py:199 #: audits/serializers.py:50 ops/models/base.py:49 ops/models/job.py:220 -#: terminal/models/applet/applet.py:283 terminal/models/applet/host.py:139 +#: terminal/models/applet/applet.py:301 terminal/models/applet/host.py:139 #: terminal/models/component/status.py:30 terminal/serializers/applet.py:18 #: terminal/serializers/applet_host.py:115 tickets/models/ticket/general.py:283 #: tickets/serializers/super_ticket.py:13 @@ -1714,7 +1714,7 @@ msgstr "开放的" msgid "Setting" msgstr "设置" -#: assets/models/platform.py:38 audits/const.py:48 settings/models.py:36 +#: assets/models/platform.py:38 audits/const.py:49 settings/models.py:36 #: terminal/serializers/applet_host.py:33 msgid "Enabled" msgstr "启用" @@ -2117,7 +2117,7 @@ msgstr "重命名" msgid "Symlink" msgstr "建立软链接" -#: audits/const.py:18 perms/const.py:14 +#: audits/const.py:18 audits/const.py:28 perms/const.py:14 msgid "Download" msgstr "下载" @@ -2137,44 +2137,44 @@ msgstr "查看" msgid "Create" msgstr "创建" -#: audits/const.py:28 perms/const.py:12 +#: audits/const.py:29 perms/const.py:12 msgid "Connect" msgstr "连接" -#: audits/const.py:29 authentication/templates/authentication/login.html:252 +#: audits/const.py:30 authentication/templates/authentication/login.html:252 #: authentication/templates/authentication/login.html:325 #: templates/_header_bar.html:89 msgid "Login" msgstr "登录" -#: audits/const.py:30 ops/const.py:9 +#: audits/const.py:31 ops/const.py:9 msgid "Change password" msgstr "改密" -#: audits/const.py:35 settings/serializers/terminal.py:6 +#: audits/const.py:36 settings/serializers/terminal.py:6 #: terminal/models/applet/host.py:26 terminal/models/component/terminal.py:164 #: terminal/serializers/session.py:49 terminal/serializers/session.py:63 msgid "Terminal" msgstr "终端" -#: audits/const.py:40 audits/models.py:127 +#: audits/const.py:41 audits/models.py:127 msgid "Operate log" msgstr "操作日志" -#: audits/const.py:41 +#: audits/const.py:42 msgid "Session log" msgstr "会话日志" -#: audits/const.py:42 +#: audits/const.py:43 msgid "Login log" msgstr "登录日志" -#: audits/const.py:43 terminal/models/applet/host.py:143 +#: audits/const.py:44 terminal/models/applet/host.py:143 #: terminal/models/component/task.py:22 msgid "Task" msgstr "任务" -#: audits/const.py:49 +#: audits/const.py:50 msgid "-" msgstr "-" @@ -2398,7 +2398,7 @@ msgstr "ACL 动作是复核" msgid "Current user not support mfa type: {}" msgstr "当前用户不支持 MFA 类型: {}" -#: authentication/api/password.py:32 terminal/api/session/session.py:259 +#: authentication/api/password.py:32 terminal/api/session/session.py:284 #: users/views/profile/reset.py:44 msgid "User does not exist: {}" msgstr "用户不存在: {}" @@ -4055,7 +4055,7 @@ msgstr "默认组织" msgid "SYSTEM" msgstr "系统组织" -#: orgs/models.py:83 rbac/models/role.py:36 terminal/models/applet/applet.py:40 +#: orgs/models.py:83 rbac/models/role.py:36 terminal/models/applet/applet.py:41 msgid "Builtin" msgstr "内置的" @@ -4291,7 +4291,7 @@ msgstr "权限" msgid "Users amount" msgstr "用户数量" -#: rbac/serializers/role.py:28 terminal/models/applet/applet.py:33 +#: rbac/serializers/role.py:28 terminal/models/applet/applet.py:34 msgid "Display name" msgstr "显示名称" @@ -4351,8 +4351,8 @@ msgstr "任务中心" msgid "My assets" msgstr "我的资产" -#: rbac/tree.py:56 terminal/models/applet/applet.py:51 -#: terminal/models/applet/applet.py:280 terminal/models/applet/host.py:29 +#: rbac/tree.py:56 terminal/models/applet/applet.py:52 +#: terminal/models/applet/applet.py:298 terminal/models/applet/host.py:29 #: terminal/serializers/applet.py:15 msgid "Applet" msgstr "远程应用" @@ -5818,15 +5818,20 @@ msgstr "测试失败: 账号无效" msgid "Have online sessions" msgstr "有在线会话" -#: terminal/api/session/session.py:251 +#: terminal/api/session/session.py:47 +#, python-format +msgid "User %s %s session %s replay" +msgstr "用户 %s %s 了会话 %s 的录像" + +#: terminal/api/session/session.py:276 msgid "Session does not exist: {}" msgstr "会话不存在: {}" -#: terminal/api/session/session.py:254 +#: terminal/api/session/session.py:279 msgid "Session is finished or the protocol not supported" msgstr "会话已经完成或协议不支持" -#: terminal/api/session/session.py:267 +#: terminal/api/session/session.py:292 msgid "User does not have permission" msgstr "用户没有权限" @@ -5944,51 +5949,51 @@ msgstr "不支持批量创建" msgid "Storage is invalid" msgstr "存储无效" -#: terminal/models/applet/applet.py:29 +#: terminal/models/applet/applet.py:30 msgid "Community" msgstr "社区版" -#: terminal/models/applet/applet.py:30 +#: terminal/models/applet/applet.py:31 msgid "Enterprise" msgstr "企业版" -#: terminal/models/applet/applet.py:35 +#: terminal/models/applet/applet.py:36 msgid "Author" msgstr "作者" -#: terminal/models/applet/applet.py:37 terminal/serializers/applet.py:31 +#: terminal/models/applet/applet.py:38 terminal/serializers/applet.py:31 msgid "Edition" msgstr "版本" -#: terminal/models/applet/applet.py:42 +#: terminal/models/applet/applet.py:43 msgid "Can concurrent" msgstr "可以并发" -#: terminal/models/applet/applet.py:43 +#: terminal/models/applet/applet.py:44 msgid "Tags" msgstr "标签" -#: terminal/models/applet/applet.py:47 terminal/serializers/storage.py:159 +#: terminal/models/applet/applet.py:48 terminal/serializers/storage.py:159 msgid "Hosts" msgstr "主机" -#: terminal/models/applet/applet.py:92 +#: terminal/models/applet/applet.py:93 msgid "Applet pkg not valid, Missing file {}" msgstr "Applet pkg 无效,缺少文件 {}" -#: terminal/models/applet/applet.py:111 +#: terminal/models/applet/applet.py:112 msgid "Load platform.yml failed: {}" msgstr "加载 platform.yml 失败: {}" -#: terminal/models/applet/applet.py:114 +#: terminal/models/applet/applet.py:115 msgid "Only support custom platform" msgstr "只支持自定义平台" -#: terminal/models/applet/applet.py:119 +#: terminal/models/applet/applet.py:120 msgid "Missing type in platform.yml" msgstr "在 platform.yml 中缺少类型" -#: terminal/models/applet/applet.py:282 terminal/models/applet/host.py:35 +#: terminal/models/applet/applet.py:300 terminal/models/applet/host.py:35 #: terminal/models/applet/host.py:137 msgid "Hosting" msgstr "宿主机" diff --git a/apps/terminal/api/session/session.py b/apps/terminal/api/session/session.py index 98a1fe73c..7277cdd9e 100644 --- a/apps/terminal/api/session/session.py +++ b/apps/terminal/api/session/session.py @@ -43,6 +43,8 @@ __all__ = [ logger = get_logger(__name__) +REPLAY_OP = gettext_noop('User %s %s session %s replay') + class MySessionAPIView(generics.ListAPIView): permission_classes = (IsAuthenticated,) @@ -136,8 +138,7 @@ class SessionViewSet(RecordViewLogMixin, OrgBulkModelViewSet): response["Content-Disposition"] = disposition detail = i18n_fmt( - gettext_noop(f'User %s %s session %s replay'), self.request.user, - gettext_noop(ActionChoices.download), str(storage.obj) + REPLAY_OP, self.request.user, _('Download'), str(storage.obj) ) self.record_logs( [storage.obj.asset_id], ActionChoices.download, detail, @@ -230,8 +231,7 @@ class SessionReplayViewSet(AsyncApiMixin, RecordViewLogMixin, viewsets.ViewSet): session_id = kwargs.get('pk') session = get_object_or_404(Session, id=session_id) detail = i18n_fmt( - gettext_noop(f'User %s %s session %s replay'), self.request.user, - gettext_noop(ActionChoices.view), str(session) + REPLAY_OP, self.request.user, _('View'), str(session) ) self.record_logs( [session.asset_id], ActionChoices.download, detail, From 7c3a3d599b63fc5227c7aaaca042674647a67553 Mon Sep 17 00:00:00 2001 From: jiangweidong Date: Tue, 29 Aug 2023 15:18:51 +0800 Subject: [PATCH 3/3] =?UTF-8?q?perf:=20=E5=8F=82=E6=95=B0=E4=BF=AE?= =?UTF-8?q?=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/common/api/patch.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/common/api/patch.py b/apps/common/api/patch.py index 821dff4ea..71dd8a18f 100644 --- a/apps/common/api/patch.py +++ b/apps/common/api/patch.py @@ -99,7 +99,7 @@ class AsyncApiMixin(InterceptMixin): def is_need_async(self): return False - def async_callback(self, params): + def async_callback(self, *args, **kwargs): pass def do_async(self, handler, *args, **kwargs):