perf: 账号备份增加sftp方式 (#12032)

* perf: 添加sftp支持

* perf: 账号备份增加sftp方式

---------

Co-authored-by: wangruidong <940853815@qq.com>
Co-authored-by: Bryan <jiangjie.bai@fit2cloud.com>
pull/12054/head
fit2bot 2023-11-07 15:10:46 +08:00 committed by GitHub
parent 54b89f6fee
commit f01bfc44b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 601 additions and 289 deletions

View File

@ -6,11 +6,14 @@ from django.conf import settings
from openpyxl import Workbook
from rest_framework import serializers
from accounts.notifications import AccountBackupExecutionTaskMsg
from accounts.const.automation import AccountBackupType
from accounts.notifications import AccountBackupExecutionTaskMsg, AccountBackupByObjStorageExecutionTaskMsg
from accounts.serializers import AccountSecretSerializer
from accounts.models.automations.backup_account import AccountBackupAutomation
from assets.const import AllTypes
from common.utils.file import encrypt_and_compress_zip_file
from common.utils.file import encrypt_and_compress_zip_file, zip_files
from common.utils.timezone import local_now_display
from terminal.models.component.storage import ReplayStorage
from users.models import User
PATH = os.path.join(os.path.dirname(settings.BASE_DIR), 'tmp')
@ -169,6 +172,29 @@ class AccountBackupHandler:
for file in files:
os.remove(file)
def send_backup_obj_storage(self, files, recipients, password):
if not files:
return
recipients = ReplayStorage.objects.filter(id__in=list(recipients))
print(
'\n'
'\033[32m>>> 发送备份文件到sftp服务器\033[0m'
''
)
plan_name = self.plan_name
for rec in recipients:
attachment = os.path.join(PATH, f'{plan_name}-{local_now_display()}-{time.time()}.zip')
if password:
password = password.encode('utf8')
encrypt_and_compress_zip_file(attachment, password, files)
else:
zip_files(attachment, files)
attachment_list = attachment
AccountBackupByObjStorageExecutionTaskMsg(plan_name, rec).publish(attachment_list)
print('备份文件将发送至{}({})'.format(rec.name, rec.id))
for file in files:
os.remove(file)
def step_perform_task_update(self, is_success, reason):
self.execution.reason = reason[:1024]
self.execution.is_success = is_success
@ -186,24 +212,11 @@ class AccountBackupHandler:
is_success = False
error = '-'
try:
recipients_part_one = self.execution.snapshot.get('recipients_part_one', [])
recipients_part_two = self.execution.snapshot.get('recipients_part_two', [])
if not recipients_part_one and not recipients_part_two:
print(
'\n'
'\033[32m>>> 该备份任务未分配收件人\033[0m'
''
)
if recipients_part_one and recipients_part_two:
files = self.create_excel(section='front')
self.send_backup_mail(files, recipients_part_one)
files = self.create_excel(section='back')
self.send_backup_mail(files, recipients_part_two)
else:
recipients = recipients_part_one or recipients_part_two
files = self.create_excel()
self.send_backup_mail(files, recipients)
backup_type = self.execution.snapshot.get('backup_type', AccountBackupType.email.value)
if backup_type == AccountBackupType.email.value:
self.backup_by_email()
elif backup_type == AccountBackupType.object_storage.value:
self.backup_by_obj_storage()
except Exception as e:
self.is_frozen = True
print('任务执行被异常中断')
@ -217,6 +230,48 @@ class AccountBackupHandler:
self.step_perform_task_update(is_success, reason)
self.step_finished(is_success)
def backup_by_obj_storage(self):
object_id = self.execution.snapshot.get('id')
zip_encrypt_password = AccountBackupAutomation.objects.get(id=object_id).zip_encrypt_password
obj_recipients_part_one = self.execution.snapshot.get('obj_recipients_part_one', [])
obj_recipients_part_two = self.execution.snapshot.get('obj_recipients_part_two', [])
if not obj_recipients_part_one and not obj_recipients_part_two:
print(
'\n'
'\033[32m>>> 该备份任务未分配sftp服务器\033[0m'
''
)
if obj_recipients_part_one and obj_recipients_part_two:
files = self.create_excel(section='front')
self.send_backup_obj_storage(files, obj_recipients_part_one, zip_encrypt_password)
files = self.create_excel(section='back')
self.send_backup_obj_storage(files, obj_recipients_part_two, zip_encrypt_password)
else:
recipients = obj_recipients_part_one or obj_recipients_part_two
files = self.create_excel()
self.send_backup_obj_storage(files, recipients, zip_encrypt_password)
def backup_by_email(self):
recipients_part_one = self.execution.snapshot.get('recipients_part_one', [])
recipients_part_two = self.execution.snapshot.get('recipients_part_two', [])
if not recipients_part_one and not recipients_part_two:
print(
'\n'
'\033[32m>>> 该备份任务未分配收件人\033[0m'
''
)
if recipients_part_one and recipients_part_two:
files = self.create_excel(section='front')
self.send_backup_mail(files, recipients_part_one)
files = self.create_excel(section='back')
self.send_backup_mail(files, recipients_part_two)
else:
recipients = recipients_part_one or recipients_part_two
files = self.create_excel()
self.send_backup_mail(files, recipients)
def run(self):
print('任务开始: {}'.format(local_now_display()))
time_start = time.time()

View File

@ -16,7 +16,7 @@ DEFAULT_PASSWORD_RULES = {
__all__ = [
'AutomationTypes', 'SecretStrategy', 'SSHKeyStrategy', 'Connectivity',
'DEFAULT_PASSWORD_LENGTH', 'DEFAULT_PASSWORD_RULES', 'TriggerChoice',
'PushAccountActionChoice',
'PushAccountActionChoice', 'AccountBackupType'
]
@ -95,3 +95,10 @@ class TriggerChoice(models.TextChoices, TreeChoices):
class PushAccountActionChoice(models.TextChoices):
create_and_push = 'create_and_push', _('Create and push')
only_create = 'only_create', _('Only create')
class AccountBackupType(models.TextChoices):
"""Backup type"""
email = 'email', _('Email')
# 目前只支持sftp方式
object_storage = 'object_storage', _('SFTP')

View File

@ -0,0 +1,45 @@
# Generated by Django 4.1.10 on 2023-11-03 07:10
import common.db.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('terminal', '0067_alter_replaystorage_type'),
('accounts', '0017_alter_automationexecution_options'),
]
operations = [
migrations.AddField(
model_name='accountbackupautomation',
name='backup_type',
field=models.CharField(choices=[('email', 'Email'), ('object_storage', 'Object Storage')], default='email', max_length=128),
),
migrations.AddField(
model_name='accountbackupautomation',
name='is_password_divided_by_email',
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name='accountbackupautomation',
name='is_password_divided_by_obj_storage',
field=models.BooleanField(default=True),
),
migrations.AddField(
model_name='accountbackupautomation',
name='obj_recipients_part_one',
field=models.ManyToManyField(blank=True, related_name='obj_recipient_part_one_plans', to='terminal.replaystorage', verbose_name='Object Storage Recipient part one'),
),
migrations.AddField(
model_name='accountbackupautomation',
name='obj_recipients_part_two',
field=models.ManyToManyField(blank=True, related_name='obj_recipient_part_two_plans', to='terminal.replaystorage', verbose_name='Object Storage Recipient part two'),
),
migrations.AddField(
model_name='accountbackupautomation',
name='zip_encrypt_password',
field=common.db.fields.EncryptCharField(blank=True, max_length=4096, null=True, verbose_name='Zip Encrypt Password'),
),
]

View File

@ -8,10 +8,11 @@ from django.db import models
from django.db.models import F
from django.utils.translation import gettext_lazy as _
from accounts.const.automation import AccountBackupType
from common.const.choices import Trigger
from common.db import fields
from common.db.encoder import ModelJSONFieldEncoder
from common.utils import get_logger
from common.utils import lazyproperty
from common.utils import get_logger, lazyproperty
from ops.mixin import PeriodTaskModelMixin
from orgs.mixins.models import OrgModelMixin, JMSOrgBaseModel
@ -22,6 +23,10 @@ logger = get_logger(__file__)
class AccountBackupAutomation(PeriodTaskModelMixin, JMSOrgBaseModel):
types = models.JSONField(default=list)
backup_type = models.CharField(max_length=128, choices=AccountBackupType.choices,
default=AccountBackupType.email.value, verbose_name=_('Backup Type'))
is_password_divided_by_email = models.BooleanField(default=True, verbose_name=_('Is Password Divided'))
is_password_divided_by_obj_storage = models.BooleanField(default=True, verbose_name=_('Is Password Divided'))
recipients_part_one = models.ManyToManyField(
'users.User', related_name='recipient_part_one_plans', blank=True,
verbose_name=_("Recipient part one")
@ -30,6 +35,16 @@ class AccountBackupAutomation(PeriodTaskModelMixin, JMSOrgBaseModel):
'users.User', related_name='recipient_part_two_plans', blank=True,
verbose_name=_("Recipient part two")
)
obj_recipients_part_one = models.ManyToManyField(
'terminal.ReplayStorage', related_name='obj_recipient_part_one_plans', blank=True,
verbose_name=_("Object Storage Recipient part one")
)
obj_recipients_part_two = models.ManyToManyField(
'terminal.ReplayStorage', related_name='obj_recipient_part_two_plans', blank=True,
verbose_name=_("Object Storage Recipient part two")
)
zip_encrypt_password = fields.EncryptCharField(max_length=4096, blank=True, null=True,
verbose_name=_('Zip Encrypt Password'))
def __str__(self):
return f'{self.name}({self.org_id})'
@ -49,6 +64,7 @@ class AccountBackupAutomation(PeriodTaskModelMixin, JMSOrgBaseModel):
def to_attr_json(self):
return {
'id': self.id,
'name': self.name,
'is_periodic': self.is_periodic,
'interval': self.interval,
@ -56,6 +72,10 @@ class AccountBackupAutomation(PeriodTaskModelMixin, JMSOrgBaseModel):
'org_id': self.org_id,
'created_by': self.created_by,
'types': self.types,
'backup_type': self.backup_type,
'is_password_divided_by_email': self.is_password_divided_by_email,
'is_password_divided_by_obj_storage': self.is_password_divided_by_obj_storage,
'zip_encrypt_password': self.zip_encrypt_password,
'recipients_part_one': {
str(user.id): (str(user), bool(user.secret_key))
for user in self.recipients_part_one.all()
@ -63,7 +83,15 @@ class AccountBackupAutomation(PeriodTaskModelMixin, JMSOrgBaseModel):
'recipients_part_two': {
str(user.id): (str(user), bool(user.secret_key))
for user in self.recipients_part_two.all()
}
},
'obj_recipients_part_one': {
str(obj_storage.id): (str(obj_storage.name), str(obj_storage.type))
for obj_storage in self.obj_recipients_part_one.all()
},
'obj_recipients_part_two': {
str(obj_storage.id): (str(obj_storage.name), str(obj_storage.type))
for obj_storage in self.obj_recipients_part_two.all()
},
}
@property

View File

@ -1,9 +1,10 @@
from django.template.loader import render_to_string
from django.utils.translation import gettext_lazy as _
from common.tasks import send_mail_attachment_async
from common.tasks import send_mail_attachment_async, upload_backup_to_obj_storage
from notifications.notifications import UserMessage
from users.models import User
from terminal.models.component.storage import ReplayStorage
class AccountBackupExecutionTaskMsg(object):
@ -31,6 +32,25 @@ class AccountBackupExecutionTaskMsg(object):
)
class AccountBackupByObjStorageExecutionTaskMsg(object):
subject = _('Notification of account backup route task results')
def __init__(self, name: str, obj_storage: ReplayStorage):
self.name = name
self.obj_storage = obj_storage
@property
def message(self):
name = self.name
return _('{} - The account backup passage task has been completed.'
' See the attachment for details').format(name)
def publish(self, attachment_list=None):
upload_backup_to_obj_storage(
self.obj_storage, attachment_list
)
class ChangeSecretExecutionTaskMsg(object):
subject = _('Notification of implementation result of encryption change plan')

View File

@ -5,7 +5,7 @@ from rest_framework import serializers
from accounts.models import AccountBackupAutomation, AccountBackupExecution
from common.const.choices import Trigger
from common.serializers.fields import LabeledChoiceField
from common.serializers.fields import LabeledChoiceField, EncryptedField
from common.utils import get_logger
from ops.mixin import PeriodTaskSerializerMixin
from orgs.mixins.serializers import BulkOrgResourceModelSerializer
@ -16,6 +16,11 @@ __all__ = ['AccountBackupSerializer', 'AccountBackupPlanExecutionSerializer']
class AccountBackupSerializer(PeriodTaskSerializerMixin, BulkOrgResourceModelSerializer):
zip_encrypt_password = EncryptedField(
label=_('Zip Encrypt Password'), required=False, max_length=40960, allow_blank=True,
allow_null=True, write_only=True,
)
class Meta:
model = AccountBackupAutomation
read_only_fields = [
@ -24,7 +29,9 @@ class AccountBackupSerializer(PeriodTaskSerializerMixin, BulkOrgResourceModelSer
]
fields = read_only_fields + [
'id', 'name', 'is_periodic', 'interval', 'crontab',
'comment', 'types', 'recipients_part_one', 'recipients_part_two'
'comment', 'types', 'recipients_part_one', 'recipients_part_two', 'backup_type',
'is_password_divided_by_email', 'is_password_divided_by_obj_storage', 'obj_recipients_part_one',
'obj_recipients_part_two', 'zip_encrypt_password'
]
extra_kwargs = {
'name': {'required': True},

View File

@ -4,6 +4,7 @@ from celery import shared_task
from django.conf import settings
from django.core.mail import send_mail, EmailMultiAlternatives
from django.utils.translation import gettext_lazy as _
import jms_storage
from .utils import get_logger
@ -63,3 +64,18 @@ def send_mail_attachment_async(subject, message, recipient_list, attachment_list
return email.send()
except Exception as e:
logger.error("Sending mail attachment error: {}".format(e))
@shared_task(verbose_name=_('Upload session replay to external storage'))
def upload_backup_to_obj_storage(recipient, upload_file):
logger.info(f'Start upload file : {upload_file}')
remote_path = os.path.join('account_backup', os.path.basename(upload_file))
storage = jms_storage.get_object_storage(recipient.config)
ok, err = storage.upload(src=upload_file, target=remote_path)
if not ok:
logger.error(f'upload {upload_file} failed, error: {err}')
return
try:
os.remove(upload_file)
except Exception as e:
print(f'remove upload file : {upload_file} error: {e}')

View File

@ -3,6 +3,7 @@ import csv
import pyzipper
import requests
import zipfile
from hashlib import md5
@ -10,7 +11,7 @@ from django.conf import settings
def create_csv_file(filename, headers, rows, ):
with open(filename, 'w', encoding='utf-8-sig')as f:
with open(filename, 'w', encoding='utf-8-sig') as f:
w = csv.writer(f)
w.writerow(headers)
w.writerows(rows)
@ -26,6 +27,20 @@ def encrypt_and_compress_zip_file(filename, secret_password, encrypted_filenames
zf.writestr(os.path.basename(encrypted_filename), f.read())
def zip_files(output_file, file_list):
"""
将多个文件打包成zip文件
Args:
output_file (str): 打包后的zip文件路径
file_list (list): 需要打包的文件列表
Returns:
None
"""
with zipfile.ZipFile(output_file, 'w') as zipf:
for file in file_list:
zipf.write(file, arcname=os.path.basename(file))
def download_file(src, path):
with requests.get(src, stream=True) as r:
r.raise_for_status()

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cde05981ba0517af982f7ef197aed433c52510098589e4a6ce5101e48c26556e
size 163803
oid sha256:5a5207051b4a959f750ebd48c770a552c460f864547aea8d6bb62d8920e24e32
size 164428

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-03 16:52+0800\n"
"POT-Creation-Date: 2023-11-03 18:29+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -24,11 +24,12 @@ msgstr "パラメータ 'action' は [{}] でなければなりません。"
#: accounts/const/account.py:6
#: accounts/serializers/automations/change_secret.py:32
#: assets/models/_user.py:24 audits/signal_handlers/login_log.py:34
#: assets/models/_user.py:23 audits/signal_handlers/login_log.py:34
#: authentication/confirm/password.py:9 authentication/confirm/password.py:24
#: authentication/confirm/password.py:26 authentication/forms.py:32
#: authentication/templates/authentication/login.html:330
#: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:47
#: terminal/serializers/storage.py:123 terminal/serializers/storage.py:142
#: users/forms/profile.py:22 users/serializers/user.py:104
#: users/templates/users/_msg_user_created.html:13
#: users/templates/users/user_password_verify.html:18
@ -38,6 +39,7 @@ msgstr "パスワード"
#: accounts/const/account.py:7
#: accounts/serializers/automations/change_secret.py:33
#: terminal/serializers/storage.py:124
msgid "SSH key"
msgstr "SSH キー"
@ -45,7 +47,7 @@ msgstr "SSH キー"
msgid "Access key"
msgstr "アクセスキー"
#: accounts/const/account.py:9 assets/models/_user.py:48
#: accounts/const/account.py:9 assets/models/_user.py:47
#: authentication/backends/passkey/models.py:16
#: authentication/models/sso_token.py:14 settings/serializers/feature.py:50
msgid "Token"
@ -97,7 +99,7 @@ msgstr "更新"
#: accounts/const/account.py:33
#: accounts/serializers/automations/change_secret.py:150 audits/const.py:62
#: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19
#: ops/const.py:74 terminal/const.py:77 xpack/plugins/cloud/const.py:43
#: ops/const.py:74 terminal/const.py:78 xpack/plugins/cloud/const.py:43
msgid "Failed"
msgstr "失敗しました"
@ -189,6 +191,21 @@ msgstr "作成してプッシュ"
msgid "Only create"
msgstr "作成のみ"
#: accounts/const/automation.py:102
#: authentication/serializers/password_mfa.py:16
#: authentication/serializers/password_mfa.py:24
#: notifications/backends/__init__.py:10 settings/serializers/msg.py:22
#: settings/serializers/msg.py:57 users/forms/profile.py:102
#: users/forms/profile.py:109 users/models/user.py:794
#: users/templates/users/forgot_password.html:117
#: users/views/profile/reset.py:92
msgid "Email"
msgstr "メール"
#: accounts/const/automation.py:104 terminal/const.py:86
msgid "SFTP"
msgstr "SFTP"
#: accounts/const/vault.py:8 assets/const/category.py:12
#: assets/models/asset/database.py:9 assets/models/asset/database.py:24
msgid "Database"
@ -295,20 +312,42 @@ msgstr "アカウントを確認できます"
msgid "Can push account"
msgstr "アカウントをプッシュできます"
#: accounts/models/automations/backup_account.py:27
#: accounts/models/automations/backup_account.py:28
msgid "Backup Type"
msgstr "バックアップの種類"
#: accounts/models/automations/backup_account.py:29
#: accounts/models/automations/backup_account.py:30
msgid "Is Password Divided"
msgstr "キーが 2 つの部分に分割されているかどうか"
#: accounts/models/automations/backup_account.py:33
msgid "Recipient part one"
msgstr "受信者 1"
#: accounts/models/automations/backup_account.py:31
#: accounts/models/automations/backup_account.py:37
msgid "Recipient part two"
msgstr "受信者 2"
#: accounts/models/automations/backup_account.py:40
#: accounts/models/automations/backup_account.py:110
#: accounts/models/automations/backup_account.py:41
msgid "Object Storage Recipient part one"
msgstr "受信サーバー 1"
#: accounts/models/automations/backup_account.py:45
msgid "Object Storage Recipient part two"
msgstr "受信サーバー 2"
#: accounts/models/automations/backup_account.py:48
#: accounts/serializers/account/backup.py:20
msgid "Zip Encrypt Password"
msgstr "新しいファイルの暗号化パスワード"
#: accounts/models/automations/backup_account.py:56
#: accounts/models/automations/backup_account.py:139
msgid "Account backup plan"
msgstr "アカウントバックアップ計画"
#: accounts/models/automations/backup_account.py:91
#: accounts/models/automations/backup_account.py:120
#: assets/models/automations/base.py:115 audits/models.py:64
#: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:228
#: ops/templates/ops/celery_task_log.html:75
@ -319,37 +358,37 @@ msgstr "アカウントバックアップ計画"
msgid "Date start"
msgstr "開始日"
#: accounts/models/automations/backup_account.py:94
#: accounts/models/automations/backup_account.py:123
#: authentication/templates/authentication/_msg_oauth_bind.html:11
#: notifications/notifications.py:186
msgid "Time"
msgstr "時間"
#: accounts/models/automations/backup_account.py:98
#: accounts/models/automations/backup_account.py:127
msgid "Account backup snapshot"
msgstr "アカウントのバックアップスナップショット"
#: accounts/models/automations/backup_account.py:102
#: accounts/serializers/account/backup.py:42
#: accounts/models/automations/backup_account.py:131
#: accounts/serializers/account/backup.py:49
#: accounts/serializers/automations/base.py:55
#: assets/models/automations/base.py:122
#: assets/serializers/automations/base.py:40
msgid "Trigger mode"
msgstr "トリガーモード"
#: accounts/models/automations/backup_account.py:105 audits/models.py:202
#: accounts/models/automations/backup_account.py:134 audits/models.py:202
#: terminal/models/session/sharing.py:125 xpack/plugins/cloud/models.py:205
msgid "Reason"
msgstr "理由"
#: accounts/models/automations/backup_account.py:107
#: accounts/models/automations/backup_account.py:136
#: accounts/serializers/automations/change_secret.py:105
#: accounts/serializers/automations/change_secret.py:128
#: ops/serializers/job.py:56 terminal/serializers/session.py:49
msgid "Is success"
msgstr "成功は"
#: accounts/models/automations/backup_account.py:115
#: accounts/models/automations/backup_account.py:144
msgid "Account backup execution"
msgstr "アカウントバックアップの実行"
@ -394,7 +433,7 @@ msgid "SSH key change strategy"
msgstr "SSHキープッシュ方式"
#: accounts/models/automations/change_secret.py:15
#: accounts/serializers/account/backup.py:34
#: accounts/serializers/account/backup.py:41
#: accounts/serializers/automations/change_secret.py:56
msgid "Recipient"
msgstr "受信者"
@ -458,13 +497,14 @@ msgstr "最終ログイン日"
#: accounts/models/automations/push_account.py:15 accounts/models/base.py:65
#: accounts/serializers/account/virtual.py:21 acls/serializers/base.py:19
#: acls/serializers/base.py:50 acls/templates/acls/asset_login_reminder.html:5
#: acls/templates/acls/user_login_reminder.html:5 assets/models/_user.py:23
#: acls/templates/acls/user_login_reminder.html:5 assets/models/_user.py:22
#: audits/models.py:187 authentication/forms.py:25 authentication/forms.py:27
#: authentication/models/temp_token.py:9
#: authentication/templates/authentication/_msg_different_city.html:9
#: authentication/templates/authentication/_msg_oauth_bind.html:9
#: users/forms/profile.py:32 users/forms/profile.py:115
#: users/models/user.py:790 users/templates/users/_msg_user_created.html:12
#: terminal/serializers/storage.py:136 users/forms/profile.py:32
#: users/forms/profile.py:115 users/models/user.py:790
#: users/templates/users/_msg_user_created.html:12
#: xpack/plugins/cloud/serializers/account_attrs.py:26
msgid "Username"
msgstr "ユーザー名"
@ -512,6 +552,7 @@ msgstr "アカウントの確認"
#: accounts/serializers/automations/change_secret.py:45
#: authentication/serializers/connect_token_secret.py:41
#: authentication/serializers/connect_token_secret.py:50
#: terminal/serializers/storage.py:140
msgid "Secret type"
msgstr "鍵の種類"
@ -536,7 +577,7 @@ msgstr "パスワードルール"
#: accounts/models/base.py:64 accounts/serializers/account/virtual.py:20
#: acls/models/base.py:35 acls/models/base.py:96 acls/models/command_acl.py:21
#: acls/serializers/base.py:35 applications/models.py:9
#: assets/models/_user.py:22 assets/models/asset/common.py:91
#: assets/models/_user.py:21 assets/models/asset/common.py:91
#: assets/models/asset/common.py:149 assets/models/cmd_filter.py:21
#: assets/models/domain.py:18 assets/models/group.py:17
#: assets/models/label.py:18 assets/models/platform.py:15
@ -572,7 +613,7 @@ msgstr "特権アカウント"
msgid "Is active"
msgstr "アクティブです。"
#: accounts/models/template.py:17 assets/models/_user.py:53
#: accounts/models/template.py:17 assets/models/_user.py:54
msgid "Auto push"
msgstr "オートプッシュ"
@ -625,11 +666,11 @@ msgstr ""
"ユーザー名とパスワードを使用せずにアセットに接続します。Webベースとカスタムタ"
"イプのアセットのみをサポートします"
#: accounts/notifications.py:8
#: accounts/notifications.py:9 accounts/notifications.py:34
msgid "Notification of account backup route task results"
msgstr "アカウントバックアップルートタスクの結果の通知"
#: accounts/notifications.py:18
#: accounts/notifications.py:19 accounts/notifications.py:43
msgid ""
"{} - The account backup passage task has been completed. See the attachment "
"for details"
@ -637,7 +678,7 @@ msgstr ""
"{} -アカウントバックアップの通過タスクが完了しました。詳細は添付ファイルをご"
"覧ください"
#: accounts/notifications.py:21
#: accounts/notifications.py:22
msgid ""
"{} - The account backup passage task has been completed: the encryption "
"password has not been set - please go to personal information -> file "
@ -647,17 +688,17 @@ msgstr ""
"されていません-個人情報にアクセスしてください-> ファイル暗号化パスワードを設"
"定してください暗号化パスワード"
#: accounts/notifications.py:33
#: accounts/notifications.py:53
msgid "Notification of implementation result of encryption change plan"
msgstr "暗号化変更プランの実装結果の通知"
#: accounts/notifications.py:43
#: accounts/notifications.py:63
msgid ""
"{} - The encryption change task has been completed. See the attachment for "
"details"
msgstr "{} -暗号化変更タスクが完了しました。詳細は添付ファイルをご覧ください"
#: accounts/notifications.py:46
#: accounts/notifications.py:66
msgid ""
"{} - The encryption change task has been completed: the encryption password "
"has not been set - please go to personal information -> file encryption "
@ -686,7 +727,7 @@ msgstr "カテゴリ"
#: accounts/serializers/account/account.py:191
#: accounts/serializers/automations/base.py:54 acls/models/command_acl.py:24
#: acls/serializers/command_acl.py:19 applications/models.py:14
#: assets/models/_user.py:50 assets/models/automations/base.py:20
#: assets/models/_user.py:49 assets/models/automations/base.py:20
#: assets/models/cmd_filter.py:74 assets/models/platform.py:90
#: assets/serializers/asset/common.py:122 assets/serializers/platform.py:113
#: assets/serializers/platform.py:132 audits/serializers.py:50
@ -695,8 +736,8 @@ msgstr "カテゴリ"
#: perms/serializers/user_permission.py:26 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:228
#: terminal/serializers/storage.py:240 tickets/models/comment.py:26
#: terminal/serializers/session.py:21 terminal/serializers/storage.py:264
#: terminal/serializers/storage.py:276 tickets/models/comment.py:26
#: tickets/models/flow.py:56 tickets/models/ticket/apply_application.py:16
#: tickets/models/ticket/general.py:275 tickets/serializers/flow.py:53
#: tickets/serializers/ticket/ticket.py:19
@ -778,28 +819,28 @@ msgstr "ユーザー"
msgid "Date"
msgstr "日付"
#: accounts/serializers/account/backup.py:31
#: accounts/serializers/account/backup.py:38
#: accounts/serializers/automations/base.py:36
#: assets/serializers/automations/base.py:34 ops/mixin.py:23 ops/mixin.py:104
#: settings/serializers/auth/ldap.py:66
msgid "Periodic perform"
msgstr "定期的なパフォーマンス"
#: accounts/serializers/account/backup.py:32
#: accounts/serializers/account/backup.py:39
#: accounts/serializers/automations/base.py:37
msgid "Executed amount"
msgstr "実行回数"
#: accounts/serializers/account/backup.py:35
#: accounts/serializers/account/backup.py:42
#: accounts/serializers/automations/change_secret.py:57
msgid "Currently only mail sending is supported"
msgstr "現在、メール送信のみがサポートされています"
#: accounts/serializers/account/backup.py:37
#: accounts/serializers/account/backup.py:44
msgid "Asset type"
msgstr "資産タイプ"
#: accounts/serializers/account/base.py:24
#: accounts/serializers/account/base.py:24 terminal/serializers/storage.py:149
msgid "Key password"
msgstr "キーパスワード"
@ -850,7 +891,7 @@ msgid ""
"default parameters will be used"
msgstr "关联平台,可以配置推送参数,如果不关联,则使用默认参数"
#: accounts/serializers/account/virtual.py:19 assets/models/_user.py:27
#: accounts/serializers/account/virtual.py:19 assets/models/_user.py:26
#: 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
@ -912,7 +953,7 @@ msgstr "自動タスク実行履歴"
#: accounts/serializers/automations/change_secret.py:149 audits/const.py:61
#: audits/models.py:63 audits/signal_handlers/activity_log.py:33
#: common/const/choices.py:18 ops/const.py:72 ops/serializers/celery.py:40
#: terminal/const.py:76 terminal/models/session/sharing.py:121
#: terminal/const.py:77 terminal/models/session/sharing.py:121
#: tickets/views/approve.py:117
msgid "Success"
msgstr "成功"
@ -937,8 +978,6 @@ msgid "Account execute automation"
msgstr "アカウント実行の自動化"
#: accounts/tasks/automation.py:51 accounts/tasks/automation.py:62
#, fuzzy
#| msgid "Asset execute automation"
msgid "Execute automation record"
msgstr "アセット実行の自動化"
@ -1015,7 +1054,7 @@ msgstr "警告"
msgid "Notifications"
msgstr "通知"
#: acls/models/base.py:37 assets/models/_user.py:51
#: acls/models/base.py:37 assets/models/_user.py:50
#: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:97
#: xpack/plugins/cloud/models.py:275
msgid "Priority"
@ -1051,7 +1090,7 @@ msgid "Accounts"
msgstr "アカウント"
#: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60
#: ops/serializers/job.py:55 terminal/const.py:84
#: ops/serializers/job.py:55 terminal/const.py:85
#: terminal/models/session/session.py:42 terminal/serializers/command.py:18
#: terminal/templates/terminal/_msg_command_alert.html:12
#: terminal/templates/terminal/_msg_command_execute_alert.html:10
@ -1305,7 +1344,7 @@ msgid "Authentication failed"
msgstr "認証に失敗しました"
#: assets/automations/ping_gateway/manager.py:60
#: assets/automations/ping_gateway/manager.py:86 terminal/const.py:100
#: assets/automations/ping_gateway/manager.py:86 terminal/const.py:101
msgid "Connect failed"
msgstr "接続に失敗しました"
@ -1541,97 +1580,97 @@ msgstr "Webサイト"
msgid "This function is not supported temporarily"
msgstr "この機能は一時的にサポートされていません"
#: assets/models/_user.py:25
#: assets/models/_user.py:24
msgid "SSH private key"
msgstr "SSH秘密鍵"
#: assets/models/_user.py:26
#: assets/models/_user.py:25
msgid "SSH public key"
msgstr "SSHパブリックキー"
#: assets/models/_user.py:28 assets/models/automations/base.py:114
#: assets/models/_user.py:27 assets/models/automations/base.py:114
#: assets/models/cmd_filter.py:41 assets/models/group.py:19
#: audits/models.py:266 common/db/models.py:34 ops/models/base.py:54
#: ops/models/job.py:227 users/models/user.py:1024
msgid "Date created"
msgstr "作成された日付"
#: assets/models/_user.py:29 assets/models/cmd_filter.py:42
#: assets/models/_user.py:28 assets/models/cmd_filter.py:42
#: common/db/models.py:35 users/models/user.py:846
msgid "Date updated"
msgstr "更新日"
#: assets/models/_user.py:30 assets/models/cmd_filter.py:44
#: assets/models/_user.py:29 assets/models/cmd_filter.py:44
#: assets/models/cmd_filter.py:91 assets/models/group.py:18
#: common/db/models.py:32 users/models/user.py:835
#: users/serializers/group.py:29
msgid "Created by"
msgstr "によって作成された"
#: assets/models/_user.py:40
#: assets/models/_user.py:39
msgid "Automatic managed"
msgstr "自動管理"
#: assets/models/_user.py:41
#: assets/models/_user.py:40
msgid "Manually input"
msgstr "手動入力"
#: assets/models/_user.py:45
#: assets/models/_user.py:44
msgid "Common user"
msgstr "共通ユーザー"
#: assets/models/_user.py:46 assets/models/_user.py:95
#: assets/models/_user.py:45 assets/models/_user.py:98
msgid "Admin user"
msgstr "管理ユーザー"
#: assets/models/_user.py:49
#: assets/models/_user.py:48
msgid "Username same with user"
msgstr "ユーザーと同じユーザー名"
#: assets/models/_user.py:52 authentication/models/connection_token.py:41
#: assets/models/_user.py:53 authentication/models/connection_token.py:41
#: authentication/serializers/connect_token_secret.py:111
#: terminal/models/applet/applet.py:42 terminal/serializers/session.py:19
#: terminal/serializers/session.py:45 terminal/serializers/storage.py:70
#: terminal/serializers/session.py:45 terminal/serializers/storage.py:71
msgid "Protocol"
msgstr "プロトコル"
#: assets/models/_user.py:54
#: assets/models/_user.py:55
msgid "Sudo"
msgstr "すど"
#: assets/models/_user.py:55 ops/const.py:49 ops/const.py:59
#: assets/models/_user.py:56 ops/const.py:49 ops/const.py:59
msgid "Shell"
msgstr "シェル"
#: assets/models/_user.py:56
#: assets/models/_user.py:58
msgid "Login mode"
msgstr "ログインモード"
#: assets/models/_user.py:57
#: assets/models/_user.py:59 terminal/serializers/storage.py:152
msgid "SFTP Root"
msgstr "SFTPルート"
#: assets/models/_user.py:58
#: assets/models/_user.py:60
msgid "Home"
msgstr "ホーム"
#: assets/models/_user.py:59
#: assets/models/_user.py:61
msgid "System groups"
msgstr "システムグループ"
#: assets/models/_user.py:62
#: assets/models/_user.py:64
msgid "User switch"
msgstr "ユーザースイッチ"
#: assets/models/_user.py:63
#: assets/models/_user.py:66
msgid "Switch from"
msgstr "から切り替え"
#: assets/models/_user.py:69
#: assets/models/_user.py:72
msgid "System user"
msgstr "システムユーザー"
#: assets/models/_user.py:71
#: assets/models/_user.py:74
msgid "Can match system user"
msgstr "システムユーザーに一致できます"
@ -1641,6 +1680,7 @@ msgstr "クラウド サービス"
#: assets/models/asset/common.py:92 assets/models/platform.py:16
#: settings/serializers/auth/radius.py:17 settings/serializers/auth/sms.py:72
#: terminal/serializers/storage.py:133
#: xpack/plugins/cloud/serializers/account_attrs.py:73
msgid "Port"
msgstr "ポート"
@ -2969,7 +3009,7 @@ msgid "IP group"
msgstr "IP グループ"
#: authentication/models/connection_token.py:38
#: terminal/serializers/storage.py:113
#: terminal/serializers/storage.py:114
msgid "Account name"
msgstr "アカウント名"
@ -3105,24 +3145,12 @@ msgstr "アクション"
msgid "Is expired"
msgstr "期限切れです"
#: authentication/serializers/password_mfa.py:16
#: authentication/serializers/password_mfa.py:24
#: notifications/backends/__init__.py:10 settings/serializers/msg.py:22
#: settings/serializers/msg.py:57 users/forms/profile.py:102
#: users/forms/profile.py:109 users/models/user.py:794
#: users/templates/users/forgot_password.html:117
#: users/views/profile/reset.py:92
msgid "Email"
msgstr "メール"
#: authentication/serializers/password_mfa.py:29
#: users/templates/users/forgot_password.html:108
msgid "The {} cannot be empty"
msgstr "{} 空にしてはならない"
#: authentication/serializers/token.py:22
#, fuzzy
#| msgid "Access key"
msgid "Access IP"
msgstr "IPホワイトリスト"
@ -3526,7 +3554,7 @@ msgstr "タイミングトリガー"
msgid "Ready"
msgstr "の準備を"
#: common/const/choices.py:16 terminal/const.py:75 tickets/const.py:29
#: common/const/choices.py:16 terminal/const.py:76 tickets/const.py:29
#: tickets/const.py:39
msgid "Pending"
msgstr "未定"
@ -3783,14 +3811,18 @@ msgstr "間違ったデータ タイプです。リストにする必要があ
msgid "Invalid choice: {}"
msgstr "無効なオプション: {}"
#: common/tasks.py:20 common/utils/verify_code.py:16
#: common/tasks.py:21 common/utils/verify_code.py:16
msgid "Send email"
msgstr "メールを送る"
#: common/tasks.py:47
#: common/tasks.py:48
msgid "Send email attachment"
msgstr "メールの添付ファイルを送信"
#: common/tasks.py:69 terminal/tasks.py:62
msgid "Upload session replay to external storage"
msgstr "セッションの記録を外部ストレージにアップロードする"
#: common/utils/ip/geoip/utils.py:26
msgid "Invalid ip"
msgstr "無効な IP"
@ -4520,8 +4552,6 @@ msgid "Can view file manager"
msgstr "ファイルマネージャを表示できます"
#: rbac/models/menu.py:20
#, fuzzy
#| msgid "Can view my assets"
msgid "Can view System Tools"
msgstr "私の資産を見ることができます"
@ -6257,64 +6287,60 @@ msgstr "確認して同意する"
msgid "Review & Cancel"
msgstr "確認してキャンセル"
#: terminal/const.py:44
#: terminal/const.py:45
msgid "Critical"
msgstr "クリティカル"
#: terminal/const.py:45
#: terminal/const.py:46
msgid "High"
msgstr "高い"
#: terminal/const.py:46 terminal/const.py:82
#: terminal/const.py:47 terminal/const.py:83
#: users/templates/users/reset_password.html:50
msgid "Normal"
msgstr "正常"
#: terminal/const.py:47
#: terminal/const.py:48
msgid "Offline"
msgstr "オフライン"
#: terminal/const.py:78
#: terminal/const.py:79
msgid "Mismatch"
msgstr "一致しない"
#: terminal/const.py:83
#: terminal/const.py:84
msgid "Tunnel"
msgstr "ちかチャネル"
#: terminal/const.py:85
msgid "SFTP"
msgstr "SFTP"
#: terminal/const.py:89
#: terminal/const.py:90
msgid "Read only"
msgstr "読み取り専用"
#: terminal/const.py:90
#: terminal/const.py:91
msgid "Writable"
msgstr "書き込み可能"
#: terminal/const.py:94
#: terminal/const.py:95
msgid "Kill session"
msgstr "セッションを終了する"
#: terminal/const.py:95
#: terminal/const.py:96
msgid "Lock session"
msgstr "セッションをロックする"
#: terminal/const.py:96
#: terminal/const.py:97
msgid "Unlock session"
msgstr "セッションのロックを解除する"
#: terminal/const.py:101
#: terminal/const.py:102
msgid "Replay create failed"
msgstr "ビデオの作成に失敗しました"
#: terminal/const.py:102
#: terminal/const.py:103
msgid "Replay upload failed"
msgstr "動画のアップロードに失敗しました"
#: terminal/const.py:103
#: terminal/const.py:104
msgid "Replay convert failed"
msgstr "ビデオのトランスコーディングに失敗しました"
@ -6350,7 +6376,7 @@ msgstr "同時実行可能"
msgid "Tags"
msgstr "ラベル"
#: terminal/models/applet/applet.py:48 terminal/serializers/storage.py:161
#: terminal/models/applet/applet.py:48 terminal/serializers/storage.py:197
msgid "Hosts"
msgstr "ホスト"
@ -6443,9 +6469,9 @@ msgstr "Redis ポート"
#: terminal/models/component/endpoint.py:29
#: terminal/models/component/endpoint.py:102
#: terminal/serializers/endpoint.py:73 terminal/serializers/storage.py:40
#: terminal/serializers/storage.py:52 terminal/serializers/storage.py:82
#: terminal/serializers/storage.py:92 terminal/serializers/storage.py:100
#: terminal/serializers/endpoint.py:73 terminal/serializers/storage.py:41
#: terminal/serializers/storage.py:53 terminal/serializers/storage.py:83
#: terminal/serializers/storage.py:93 terminal/serializers/storage.py:101
msgid "Endpoint"
msgstr "エンドポイント"
@ -6697,7 +6723,7 @@ msgstr ""
"URL を入力します。<br>例: https://172.16.10.110 または https://dev."
"jumpserver.com"
#: terminal/serializers/applet_host.py:46 terminal/serializers/storage.py:172
#: terminal/serializers/applet_host.py:46 terminal/serializers/storage.py:208
msgid "Ignore Certificate Verification"
msgstr "証明書の検証を無視する"
@ -6860,69 +6886,78 @@ msgstr "表示からのログイン"
msgid "Terminal display"
msgstr "ターミナルディスプレイ"
#: terminal/serializers/storage.py:22
#: terminal/serializers/storage.py:23
msgid "Endpoint invalid: remove path `{}`"
msgstr "エンドポイントが無効: パス '{}' を削除"
#: terminal/serializers/storage.py:28
#: terminal/serializers/storage.py:29
msgid "Bucket"
msgstr "バケット"
#: terminal/serializers/storage.py:32
#: terminal/serializers/storage.py:33
#: xpack/plugins/cloud/serializers/account_attrs.py:17
msgid "Access key id"
msgstr "アクセスキー"
#: terminal/serializers/storage.py:36
#: terminal/serializers/storage.py:37
#: xpack/plugins/cloud/serializers/account_attrs.py:20
msgid "Access key secret"
msgstr "アクセスキーシークレット"
#: terminal/serializers/storage.py:67 xpack/plugins/cloud/models.py:250
#: terminal/serializers/storage.py:68 xpack/plugins/cloud/models.py:250
msgid "Region"
msgstr "リージョン"
#: terminal/serializers/storage.py:111
#: terminal/serializers/storage.py:112
msgid "Container name"
msgstr "コンテナー名"
#: terminal/serializers/storage.py:114
#: terminal/serializers/storage.py:115
msgid "Account key"
msgstr "アカウントキー"
#: terminal/serializers/storage.py:117
#: terminal/serializers/storage.py:118
msgid "Endpoint suffix"
msgstr "エンドポイントサフィックス"
#: terminal/serializers/storage.py:137
#: terminal/serializers/storage.py:129
msgid "HOST"
msgstr ""
#: terminal/serializers/storage.py:146 users/models/user.py:822
#: xpack/plugins/cloud/serializers/account_attrs.py:206
msgid "Private key"
msgstr "ssh秘密鍵"
#: terminal/serializers/storage.py:173
msgid "The address cannot contain the special character `#`"
msgstr "アドレスには特殊文字「#」を含めることはできません"
#: terminal/serializers/storage.py:139
#: terminal/serializers/storage.py:175
msgid "The address format is incorrect"
msgstr "アドレス形式が正しくありません"
#: terminal/serializers/storage.py:146
#: terminal/serializers/storage.py:182
msgid "Host invalid"
msgstr "ホスト無効"
#: terminal/serializers/storage.py:149
#: terminal/serializers/storage.py:185
msgid "Port invalid"
msgstr "ポートが無効"
#: terminal/serializers/storage.py:164
#: terminal/serializers/storage.py:200
msgid "Index by date"
msgstr "日付による索引付け"
#: terminal/serializers/storage.py:165
#: terminal/serializers/storage.py:201
msgid "Whether to create an index by date"
msgstr "現在の日付に基づいてインデックスを動的に作成するかどうか"
#: terminal/serializers/storage.py:168
#: terminal/serializers/storage.py:204
msgid "Index"
msgstr "インデックス"
#: terminal/serializers/storage.py:170
#: terminal/serializers/storage.py:206
msgid "Doc type"
msgstr "Docタイプ"
@ -6942,10 +6977,6 @@ msgstr "端末の状態を定期的にクリーンアップする"
msgid "Clean orphan session"
msgstr "オフライン セッションをクリアする"
#: terminal/tasks.py:62
msgid "Upload session replay to external storage"
msgstr "セッションの記録を外部ストレージにアップロードする"
#: terminal/tasks.py:91
msgid "Run applet host deployment"
msgstr "アプリケーション マシンの展開を実行する"
@ -7500,11 +7531,6 @@ msgstr "電話"
msgid "OTP secret key"
msgstr "OTP 秘密"
#: users/models/user.py:822
#: xpack/plugins/cloud/serializers/account_attrs.py:206
msgid "Private key"
msgstr "ssh秘密鍵"
#: users/models/user.py:830 users/serializers/profile.py:128
#: users/serializers/user.py:166
msgid "Is first login"
@ -8664,3 +8690,6 @@ msgstr "エンタープライズプロフェッショナル版"
#: xpack/plugins/license/models.py:86
msgid "Ultimate edition"
msgstr "エンタープライズ・フラッグシップ・エディション"
#~ msgid "Object Storage"
#~ msgstr "オブジェクトストレージ"

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:73e074ad0c1d8bfec0c2df6e2c9e29a230a3acc0e8ee1c0820910e8ce769fd52
size 134072
oid sha256:b9a380c7adbd9fad7af4257cb72742c0e68b50846591cc5b0124a0df539ec285
size 134380

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: JumpServer 0.3.3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-03 16:52+0800\n"
"POT-Creation-Date: 2023-11-03 18:29+0800\n"
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
"Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: JumpServer team<ibuler@qq.com>\n"
@ -23,11 +23,12 @@ msgstr "参数 'action' 必须是 [{}]"
#: accounts/const/account.py:6
#: accounts/serializers/automations/change_secret.py:32
#: assets/models/_user.py:24 audits/signal_handlers/login_log.py:34
#: assets/models/_user.py:23 audits/signal_handlers/login_log.py:34
#: authentication/confirm/password.py:9 authentication/confirm/password.py:24
#: authentication/confirm/password.py:26 authentication/forms.py:32
#: authentication/templates/authentication/login.html:330
#: settings/serializers/auth/ldap.py:25 settings/serializers/auth/ldap.py:47
#: terminal/serializers/storage.py:123 terminal/serializers/storage.py:142
#: users/forms/profile.py:22 users/serializers/user.py:104
#: users/templates/users/_msg_user_created.html:13
#: users/templates/users/user_password_verify.html:18
@ -37,6 +38,7 @@ msgstr "密码"
#: accounts/const/account.py:7
#: accounts/serializers/automations/change_secret.py:33
#: terminal/serializers/storage.py:124
msgid "SSH key"
msgstr "SSH 密钥"
@ -44,7 +46,7 @@ msgstr "SSH 密钥"
msgid "Access key"
msgstr "Access key"
#: accounts/const/account.py:9 assets/models/_user.py:48
#: accounts/const/account.py:9 assets/models/_user.py:47
#: authentication/backends/passkey/models.py:16
#: authentication/models/sso_token.py:14 settings/serializers/feature.py:50
msgid "Token"
@ -96,7 +98,7 @@ msgstr "更新"
#: accounts/const/account.py:33
#: accounts/serializers/automations/change_secret.py:150 audits/const.py:62
#: audits/signal_handlers/activity_log.py:33 common/const/choices.py:19
#: ops/const.py:74 terminal/const.py:77 xpack/plugins/cloud/const.py:43
#: ops/const.py:74 terminal/const.py:78 xpack/plugins/cloud/const.py:43
msgid "Failed"
msgstr "失败"
@ -188,6 +190,21 @@ msgstr "创建并推送"
msgid "Only create"
msgstr "仅创建"
#: accounts/const/automation.py:102
#: authentication/serializers/password_mfa.py:16
#: authentication/serializers/password_mfa.py:24
#: notifications/backends/__init__.py:10 settings/serializers/msg.py:22
#: settings/serializers/msg.py:57 users/forms/profile.py:102
#: users/forms/profile.py:109 users/models/user.py:794
#: users/templates/users/forgot_password.html:117
#: users/views/profile/reset.py:92
msgid "Email"
msgstr "邮箱"
#: accounts/const/automation.py:104 terminal/const.py:86
msgid "SFTP"
msgstr "SFTP"
#: accounts/const/vault.py:8 assets/const/category.py:12
#: assets/models/asset/database.py:9 assets/models/asset/database.py:24
msgid "Database"
@ -294,20 +311,42 @@ msgstr "可以验证账号"
msgid "Can push account"
msgstr "可以推送账号"
#: accounts/models/automations/backup_account.py:27
#: accounts/models/automations/backup_account.py:28
msgid "Backup Type"
msgstr "备份类型"
#: accounts/models/automations/backup_account.py:29
#: accounts/models/automations/backup_account.py:30
msgid "Is Password Divided"
msgstr "密钥是否拆分成前后两部分"
#: accounts/models/automations/backup_account.py:33
msgid "Recipient part one"
msgstr "收件人部分一"
#: accounts/models/automations/backup_account.py:31
#: accounts/models/automations/backup_account.py:37
msgid "Recipient part two"
msgstr "收件人部分二"
#: accounts/models/automations/backup_account.py:40
#: accounts/models/automations/backup_account.py:110
#: accounts/models/automations/backup_account.py:41
msgid "Object Storage Recipient part one"
msgstr "接收服务器一"
#: accounts/models/automations/backup_account.py:45
msgid "Object Storage Recipient part two"
msgstr "接收服务器二"
#: accounts/models/automations/backup_account.py:48
#: accounts/serializers/account/backup.py:20
msgid "Zip Encrypt Password"
msgstr "文件加密密码"
#: accounts/models/automations/backup_account.py:56
#: accounts/models/automations/backup_account.py:139
msgid "Account backup plan"
msgstr "账号备份计划"
#: accounts/models/automations/backup_account.py:91
#: accounts/models/automations/backup_account.py:120
#: assets/models/automations/base.py:115 audits/models.py:64
#: ops/models/base.py:55 ops/models/celery.py:63 ops/models/job.py:228
#: ops/templates/ops/celery_task_log.html:75
@ -318,37 +357,37 @@ msgstr "账号备份计划"
msgid "Date start"
msgstr "开始日期"
#: accounts/models/automations/backup_account.py:94
#: accounts/models/automations/backup_account.py:123
#: authentication/templates/authentication/_msg_oauth_bind.html:11
#: notifications/notifications.py:186
msgid "Time"
msgstr "时间"
#: accounts/models/automations/backup_account.py:98
#: accounts/models/automations/backup_account.py:127
msgid "Account backup snapshot"
msgstr "账号备份快照"
#: accounts/models/automations/backup_account.py:102
#: accounts/serializers/account/backup.py:42
#: accounts/models/automations/backup_account.py:131
#: accounts/serializers/account/backup.py:49
#: accounts/serializers/automations/base.py:55
#: assets/models/automations/base.py:122
#: assets/serializers/automations/base.py:40
msgid "Trigger mode"
msgstr "触发模式"
#: accounts/models/automations/backup_account.py:105 audits/models.py:202
#: accounts/models/automations/backup_account.py:134 audits/models.py:202
#: terminal/models/session/sharing.py:125 xpack/plugins/cloud/models.py:205
msgid "Reason"
msgstr "原因"
#: accounts/models/automations/backup_account.py:107
#: accounts/models/automations/backup_account.py:136
#: accounts/serializers/automations/change_secret.py:105
#: accounts/serializers/automations/change_secret.py:128
#: ops/serializers/job.py:56 terminal/serializers/session.py:49
msgid "Is success"
msgstr "是否成功"
#: accounts/models/automations/backup_account.py:115
#: accounts/models/automations/backup_account.py:144
msgid "Account backup execution"
msgstr "账号备份执行"
@ -393,7 +432,7 @@ msgid "SSH key change strategy"
msgstr "SSH 密钥推送方式"
#: accounts/models/automations/change_secret.py:15
#: accounts/serializers/account/backup.py:34
#: accounts/serializers/account/backup.py:41
#: accounts/serializers/automations/change_secret.py:56
msgid "Recipient"
msgstr "收件人"
@ -457,13 +496,14 @@ msgstr "最后登录日期"
#: accounts/models/automations/push_account.py:15 accounts/models/base.py:65
#: accounts/serializers/account/virtual.py:21 acls/serializers/base.py:19
#: acls/serializers/base.py:50 acls/templates/acls/asset_login_reminder.html:5
#: acls/templates/acls/user_login_reminder.html:5 assets/models/_user.py:23
#: acls/templates/acls/user_login_reminder.html:5 assets/models/_user.py:22
#: audits/models.py:187 authentication/forms.py:25 authentication/forms.py:27
#: authentication/models/temp_token.py:9
#: authentication/templates/authentication/_msg_different_city.html:9
#: authentication/templates/authentication/_msg_oauth_bind.html:9
#: users/forms/profile.py:32 users/forms/profile.py:115
#: users/models/user.py:790 users/templates/users/_msg_user_created.html:12
#: terminal/serializers/storage.py:136 users/forms/profile.py:32
#: users/forms/profile.py:115 users/models/user.py:790
#: users/templates/users/_msg_user_created.html:12
#: xpack/plugins/cloud/serializers/account_attrs.py:26
msgid "Username"
msgstr "用户名"
@ -511,6 +551,7 @@ msgstr "账号验证"
#: accounts/serializers/automations/change_secret.py:45
#: authentication/serializers/connect_token_secret.py:41
#: authentication/serializers/connect_token_secret.py:50
#: terminal/serializers/storage.py:140
msgid "Secret type"
msgstr "密文类型"
@ -535,7 +576,7 @@ msgstr "密码规则"
#: accounts/models/base.py:64 accounts/serializers/account/virtual.py:20
#: acls/models/base.py:35 acls/models/base.py:96 acls/models/command_acl.py:21
#: acls/serializers/base.py:35 applications/models.py:9
#: assets/models/_user.py:22 assets/models/asset/common.py:91
#: assets/models/_user.py:21 assets/models/asset/common.py:91
#: assets/models/asset/common.py:149 assets/models/cmd_filter.py:21
#: assets/models/domain.py:18 assets/models/group.py:17
#: assets/models/label.py:18 assets/models/platform.py:15
@ -571,7 +612,7 @@ msgstr "特权账号"
msgid "Is active"
msgstr "激活"
#: accounts/models/template.py:17 assets/models/_user.py:53
#: accounts/models/template.py:17 assets/models/_user.py:54
msgid "Auto push"
msgstr "自动推送"
@ -626,17 +667,17 @@ msgid ""
msgstr ""
"连接资产时不使用用户名和密码的账号,仅支持 web类型 和 自定义类型 的资产"
#: accounts/notifications.py:8
#: accounts/notifications.py:9 accounts/notifications.py:34
msgid "Notification of account backup route task results"
msgstr "账号备份任务结果通知"
#: accounts/notifications.py:18
#: accounts/notifications.py:19 accounts/notifications.py:43
msgid ""
"{} - The account backup passage task has been completed. See the attachment "
"for details"
msgstr "{} - 账号备份任务已完成, 详情见附件"
#: accounts/notifications.py:21
#: accounts/notifications.py:22
msgid ""
"{} - The account backup passage task has been completed: the encryption "
"password has not been set - please go to personal information -> file "
@ -645,17 +686,17 @@ msgstr ""
"{} - 账号备份任务已完成: 未设置加密密码 - 请前往个人信息 -> 文件加密密码中设"
"置加密密码"
#: accounts/notifications.py:33
#: accounts/notifications.py:53
msgid "Notification of implementation result of encryption change plan"
msgstr "改密计划任务结果通知"
#: accounts/notifications.py:43
#: accounts/notifications.py:63
msgid ""
"{} - The encryption change task has been completed. See the attachment for "
"details"
msgstr "{} - 改密任务已完成, 详情见附件"
#: accounts/notifications.py:46
#: accounts/notifications.py:66
msgid ""
"{} - The encryption change task has been completed: the encryption password "
"has not been set - please go to personal information -> file encryption "
@ -684,7 +725,7 @@ msgstr "类别"
#: accounts/serializers/account/account.py:191
#: accounts/serializers/automations/base.py:54 acls/models/command_acl.py:24
#: acls/serializers/command_acl.py:19 applications/models.py:14
#: assets/models/_user.py:50 assets/models/automations/base.py:20
#: assets/models/_user.py:49 assets/models/automations/base.py:20
#: assets/models/cmd_filter.py:74 assets/models/platform.py:90
#: assets/serializers/asset/common.py:122 assets/serializers/platform.py:113
#: assets/serializers/platform.py:132 audits/serializers.py:50
@ -693,8 +734,8 @@ msgstr "类别"
#: perms/serializers/user_permission.py:26 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:228
#: terminal/serializers/storage.py:240 tickets/models/comment.py:26
#: terminal/serializers/session.py:21 terminal/serializers/storage.py:264
#: terminal/serializers/storage.py:276 tickets/models/comment.py:26
#: tickets/models/flow.py:56 tickets/models/ticket/apply_application.py:16
#: tickets/models/ticket/general.py:275 tickets/serializers/flow.py:53
#: tickets/serializers/ticket/ticket.py:19
@ -776,28 +817,28 @@ msgstr "用户"
msgid "Date"
msgstr "日期"
#: accounts/serializers/account/backup.py:31
#: accounts/serializers/account/backup.py:38
#: accounts/serializers/automations/base.py:36
#: assets/serializers/automations/base.py:34 ops/mixin.py:23 ops/mixin.py:104
#: settings/serializers/auth/ldap.py:66
msgid "Periodic perform"
msgstr "定时执行"
#: accounts/serializers/account/backup.py:32
#: accounts/serializers/account/backup.py:39
#: accounts/serializers/automations/base.py:37
msgid "Executed amount"
msgstr "执行次数"
#: accounts/serializers/account/backup.py:35
#: accounts/serializers/account/backup.py:42
#: accounts/serializers/automations/change_secret.py:57
msgid "Currently only mail sending is supported"
msgstr "当前只支持邮件发送"
#: accounts/serializers/account/backup.py:37
#: accounts/serializers/account/backup.py:44
msgid "Asset type"
msgstr "资产类型"
#: accounts/serializers/account/base.py:24
#: accounts/serializers/account/base.py:24 terminal/serializers/storage.py:149
msgid "Key password"
msgstr "密钥密码"
@ -848,7 +889,7 @@ msgid ""
"default parameters will be used"
msgstr "关联平台,可配置推送参数,如果不关联,将使用默认参数"
#: accounts/serializers/account/virtual.py:19 assets/models/_user.py:27
#: accounts/serializers/account/virtual.py:19 assets/models/_user.py:26
#: 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
@ -909,7 +950,7 @@ msgstr "自动化任务执行历史"
#: accounts/serializers/automations/change_secret.py:149 audits/const.py:61
#: audits/models.py:63 audits/signal_handlers/activity_log.py:33
#: common/const/choices.py:18 ops/const.py:72 ops/serializers/celery.py:40
#: terminal/const.py:76 terminal/models/session/sharing.py:121
#: terminal/const.py:77 terminal/models/session/sharing.py:121
#: tickets/views/approve.py:117
msgid "Success"
msgstr "成功"
@ -1012,7 +1053,7 @@ msgstr "告警"
msgid "Notifications"
msgstr "通知"
#: acls/models/base.py:37 assets/models/_user.py:51
#: acls/models/base.py:37 assets/models/_user.py:50
#: assets/models/cmd_filter.py:76 terminal/models/component/endpoint.py:97
#: xpack/plugins/cloud/models.py:275
msgid "Priority"
@ -1048,7 +1089,7 @@ msgid "Accounts"
msgstr "账号管理"
#: acls/models/command_acl.py:16 assets/models/cmd_filter.py:60
#: ops/serializers/job.py:55 terminal/const.py:84
#: ops/serializers/job.py:55 terminal/const.py:85
#: terminal/models/session/session.py:42 terminal/serializers/command.py:18
#: terminal/templates/terminal/_msg_command_alert.html:12
#: terminal/templates/terminal/_msg_command_execute_alert.html:10
@ -1298,7 +1339,7 @@ msgid "Authentication failed"
msgstr "认证失败"
#: assets/automations/ping_gateway/manager.py:60
#: assets/automations/ping_gateway/manager.py:86 terminal/const.py:100
#: assets/automations/ping_gateway/manager.py:86 terminal/const.py:101
msgid "Connect failed"
msgstr "连接失败"
@ -1532,99 +1573,99 @@ msgstr "网站"
msgid "This function is not supported temporarily"
msgstr "暂时不支持此功能"
#: assets/models/_user.py:25
#: assets/models/_user.py:24
msgid "SSH private key"
msgstr "SSH密钥"
#: assets/models/_user.py:26
#: assets/models/_user.py:25
msgid "SSH public key"
msgstr "SSH公钥"
# msgid "Comment"
# msgstr "备注"
#: assets/models/_user.py:28 assets/models/automations/base.py:114
#: assets/models/_user.py:27 assets/models/automations/base.py:114
#: assets/models/cmd_filter.py:41 assets/models/group.py:19
#: audits/models.py:266 common/db/models.py:34 ops/models/base.py:54
#: ops/models/job.py:227 users/models/user.py:1024
msgid "Date created"
msgstr "创建日期"
#: assets/models/_user.py:29 assets/models/cmd_filter.py:42
#: assets/models/_user.py:28 assets/models/cmd_filter.py:42
#: common/db/models.py:35 users/models/user.py:846
msgid "Date updated"
msgstr "更新日期"
#: assets/models/_user.py:30 assets/models/cmd_filter.py:44
#: assets/models/_user.py:29 assets/models/cmd_filter.py:44
#: assets/models/cmd_filter.py:91 assets/models/group.py:18
#: common/db/models.py:32 users/models/user.py:835
#: users/serializers/group.py:29
msgid "Created by"
msgstr "创建者"
#: assets/models/_user.py:40
#: assets/models/_user.py:39
msgid "Automatic managed"
msgstr "托管密码"
#: assets/models/_user.py:41
#: assets/models/_user.py:40
msgid "Manually input"
msgstr "手动输入"
#: assets/models/_user.py:45
#: assets/models/_user.py:44
msgid "Common user"
msgstr "普通用户"
#: assets/models/_user.py:46 assets/models/_user.py:95
#: assets/models/_user.py:45 assets/models/_user.py:98
msgid "Admin user"
msgstr "特权用户"
#: assets/models/_user.py:49
#: assets/models/_user.py:48
msgid "Username same with user"
msgstr "用户名与用户相同"
#: assets/models/_user.py:52 authentication/models/connection_token.py:41
#: assets/models/_user.py:53 authentication/models/connection_token.py:41
#: authentication/serializers/connect_token_secret.py:111
#: terminal/models/applet/applet.py:42 terminal/serializers/session.py:19
#: terminal/serializers/session.py:45 terminal/serializers/storage.py:70
#: terminal/serializers/session.py:45 terminal/serializers/storage.py:71
msgid "Protocol"
msgstr "协议"
#: assets/models/_user.py:54
#: assets/models/_user.py:55
msgid "Sudo"
msgstr "Sudo"
#: assets/models/_user.py:55 ops/const.py:49 ops/const.py:59
#: assets/models/_user.py:56 ops/const.py:49 ops/const.py:59
msgid "Shell"
msgstr "Shell"
#: assets/models/_user.py:56
#: assets/models/_user.py:58
msgid "Login mode"
msgstr "认证方式"
#: assets/models/_user.py:57
#: assets/models/_user.py:59 terminal/serializers/storage.py:152
msgid "SFTP Root"
msgstr "SFTP根路径"
#: assets/models/_user.py:58
#: assets/models/_user.py:60
msgid "Home"
msgstr "家目录"
#: assets/models/_user.py:59
#: assets/models/_user.py:61
msgid "System groups"
msgstr "用户组"
#: assets/models/_user.py:62
#: assets/models/_user.py:64
msgid "User switch"
msgstr "用户切换"
#: assets/models/_user.py:63
#: assets/models/_user.py:66
msgid "Switch from"
msgstr "切换自"
#: assets/models/_user.py:69
#: assets/models/_user.py:72
msgid "System user"
msgstr "系统用户"
#: assets/models/_user.py:71
#: assets/models/_user.py:74
msgid "Can match system user"
msgstr "可以匹配系统用户"
@ -1634,6 +1675,7 @@ msgstr "云服务"
#: assets/models/asset/common.py:92 assets/models/platform.py:16
#: settings/serializers/auth/radius.py:17 settings/serializers/auth/sms.py:72
#: terminal/serializers/storage.py:133
#: xpack/plugins/cloud/serializers/account_attrs.py:73
msgid "Port"
msgstr "端口"
@ -2938,7 +2980,7 @@ msgid "IP group"
msgstr "IPグループ"
#: authentication/models/connection_token.py:38
#: terminal/serializers/storage.py:113
#: terminal/serializers/storage.py:114
msgid "Account name"
msgstr "账号名称"
@ -3074,16 +3116,6 @@ msgstr "动作"
msgid "Is expired"
msgstr "已过期"
#: authentication/serializers/password_mfa.py:16
#: authentication/serializers/password_mfa.py:24
#: notifications/backends/__init__.py:10 settings/serializers/msg.py:22
#: settings/serializers/msg.py:57 users/forms/profile.py:102
#: users/forms/profile.py:109 users/models/user.py:794
#: users/templates/users/forgot_password.html:117
#: users/views/profile/reset.py:92
msgid "Email"
msgstr "邮箱"
#: authentication/serializers/password_mfa.py:29
#: users/templates/users/forgot_password.html:108
msgid "The {} cannot be empty"
@ -3481,7 +3513,7 @@ msgstr "定时触发"
msgid "Ready"
msgstr "准备"
#: common/const/choices.py:16 terminal/const.py:75 tickets/const.py:29
#: common/const/choices.py:16 terminal/const.py:76 tickets/const.py:29
#: tickets/const.py:39
msgid "Pending"
msgstr "待定的"
@ -3736,14 +3768,18 @@ msgstr "错误的数据类型,应该是列表"
msgid "Invalid choice: {}"
msgstr "无效选项: {}"
#: common/tasks.py:20 common/utils/verify_code.py:16
#: common/tasks.py:21 common/utils/verify_code.py:16
msgid "Send email"
msgstr "发件邮件"
#: common/tasks.py:47
#: common/tasks.py:48
msgid "Send email attachment"
msgstr "发送邮件附件"
#: common/tasks.py:69 terminal/tasks.py:62
msgid "Upload session replay to external storage"
msgstr "上传会话录像到外部存储"
#: common/utils/ip/geoip/utils.py:26
msgid "Invalid ip"
msgstr "无效 IP"
@ -6165,64 +6201,60 @@ msgstr "审批 & 接受"
msgid "Review & Cancel"
msgstr "审批 & 取消"
#: terminal/const.py:44
#: terminal/const.py:45
msgid "Critical"
msgstr "严重"
#: terminal/const.py:45
#: terminal/const.py:46
msgid "High"
msgstr "较高"
#: terminal/const.py:46 terminal/const.py:82
#: terminal/const.py:47 terminal/const.py:83
#: users/templates/users/reset_password.html:50
msgid "Normal"
msgstr "正常"
#: terminal/const.py:47
#: terminal/const.py:48
msgid "Offline"
msgstr "离线"
#: terminal/const.py:78
#: terminal/const.py:79
msgid "Mismatch"
msgstr "未匹配"
#: terminal/const.py:83
#: terminal/const.py:84
msgid "Tunnel"
msgstr "隧道"
#: terminal/const.py:85
msgid "SFTP"
msgstr "SFTP"
#: terminal/const.py:89
#: terminal/const.py:90
msgid "Read only"
msgstr "只读"
#: terminal/const.py:90
#: terminal/const.py:91
msgid "Writable"
msgstr "读写"
#: terminal/const.py:94
#: terminal/const.py:95
msgid "Kill session"
msgstr "终断会话"
#: terminal/const.py:95
#: terminal/const.py:96
msgid "Lock session"
msgstr "锁定会话"
#: terminal/const.py:96
#: terminal/const.py:97
msgid "Unlock session"
msgstr "解锁会话"
#: terminal/const.py:101
#: terminal/const.py:102
msgid "Replay create failed"
msgstr "录像创建失败"
#: terminal/const.py:102
#: terminal/const.py:103
msgid "Replay upload failed"
msgstr "录像上传失败"
#: terminal/const.py:103
#: terminal/const.py:104
msgid "Replay convert failed"
msgstr "录像转码失败"
@ -6258,7 +6290,7 @@ msgstr "可以并发"
msgid "Tags"
msgstr "标签"
#: terminal/models/applet/applet.py:48 terminal/serializers/storage.py:161
#: terminal/models/applet/applet.py:48 terminal/serializers/storage.py:197
msgid "Hosts"
msgstr "主机"
@ -6349,9 +6381,9 @@ msgstr "Redis 端口"
#: terminal/models/component/endpoint.py:29
#: terminal/models/component/endpoint.py:102
#: terminal/serializers/endpoint.py:73 terminal/serializers/storage.py:40
#: terminal/serializers/storage.py:52 terminal/serializers/storage.py:82
#: terminal/serializers/storage.py:92 terminal/serializers/storage.py:100
#: terminal/serializers/endpoint.py:73 terminal/serializers/storage.py:41
#: terminal/serializers/storage.py:53 terminal/serializers/storage.py:83
#: terminal/serializers/storage.py:93 terminal/serializers/storage.py:101
msgid "Endpoint"
msgstr "端点"
@ -6601,7 +6633,7 @@ msgstr ""
"建议填写内网地址,否则填写当前站点 URL<br>例如https://172.16.10.110 or "
"https://dev.jumpserver.com"
#: terminal/serializers/applet_host.py:46 terminal/serializers/storage.py:172
#: terminal/serializers/applet_host.py:46 terminal/serializers/storage.py:208
msgid "Ignore Certificate Verification"
msgstr "忽略证书认证"
@ -6759,69 +6791,78 @@ msgstr "登录来源名称"
msgid "Terminal display"
msgstr "终端显示"
#: terminal/serializers/storage.py:22
#: terminal/serializers/storage.py:23
msgid "Endpoint invalid: remove path `{}`"
msgstr "端点无效: 移除路径 `{}`"
#: terminal/serializers/storage.py:28
#: terminal/serializers/storage.py:29
msgid "Bucket"
msgstr "桶名称"
#: terminal/serializers/storage.py:32
#: terminal/serializers/storage.py:33
#: xpack/plugins/cloud/serializers/account_attrs.py:17
msgid "Access key id"
msgstr "Access key ID(AK)"
#: terminal/serializers/storage.py:36
#: terminal/serializers/storage.py:37
#: xpack/plugins/cloud/serializers/account_attrs.py:20
msgid "Access key secret"
msgstr "Access key secret(SK)"
#: terminal/serializers/storage.py:67 xpack/plugins/cloud/models.py:250
#: terminal/serializers/storage.py:68 xpack/plugins/cloud/models.py:250
msgid "Region"
msgstr "地域"
#: terminal/serializers/storage.py:111
#: terminal/serializers/storage.py:112
msgid "Container name"
msgstr "容器名称"
#: terminal/serializers/storage.py:114
#: terminal/serializers/storage.py:115
msgid "Account key"
msgstr "账号密钥"
#: terminal/serializers/storage.py:117
#: terminal/serializers/storage.py:118
msgid "Endpoint suffix"
msgstr "端点后缀"
#: terminal/serializers/storage.py:137
#: terminal/serializers/storage.py:129
msgid "HOST"
msgstr ""
#: terminal/serializers/storage.py:146 users/models/user.py:822
#: xpack/plugins/cloud/serializers/account_attrs.py:206
msgid "Private key"
msgstr "ssh私钥"
#: terminal/serializers/storage.py:173
msgid "The address cannot contain the special character `#`"
msgstr "地址中不能包含特殊字符 `#`"
#: terminal/serializers/storage.py:139
#: terminal/serializers/storage.py:175
msgid "The address format is incorrect"
msgstr "地址格式不正确"
#: terminal/serializers/storage.py:146
#: terminal/serializers/storage.py:182
msgid "Host invalid"
msgstr "主机无效"
#: terminal/serializers/storage.py:149
#: terminal/serializers/storage.py:185
msgid "Port invalid"
msgstr "端口无效"
#: terminal/serializers/storage.py:164
#: terminal/serializers/storage.py:200
msgid "Index by date"
msgstr "按日期建索引"
#: terminal/serializers/storage.py:165
#: terminal/serializers/storage.py:201
msgid "Whether to create an index by date"
msgstr "是否根据日期动态建立索引"
#: terminal/serializers/storage.py:168
#: terminal/serializers/storage.py:204
msgid "Index"
msgstr "索引"
#: terminal/serializers/storage.py:170
#: terminal/serializers/storage.py:206
msgid "Doc type"
msgstr "文档类型"
@ -6841,10 +6882,6 @@ msgstr "周期清理终端状态"
msgid "Clean orphan session"
msgstr "清除离线会话"
#: terminal/tasks.py:62
msgid "Upload session replay to external storage"
msgstr "上传会话录像到外部存储"
#: terminal/tasks.py:91
msgid "Run applet host deployment"
msgstr "运行应用机部署"
@ -7393,11 +7430,6 @@ msgstr "手机"
msgid "OTP secret key"
msgstr "OTP 密钥"
#: users/models/user.py:822
#: xpack/plugins/cloud/serializers/account_attrs.py:206
msgid "Private key"
msgstr "ssh私钥"
#: users/models/user.py:830 users/serializers/profile.py:128
#: users/serializers/user.py:166
msgid "Is first login"
@ -8541,3 +8573,6 @@ msgstr "企业专业版"
#: xpack/plugins/license/models.py:86
msgid "Ultimate edition"
msgstr "企业旗舰版"
#~ msgid "Object Storage"
#~ msgstr "对象存储"

View File

@ -29,6 +29,7 @@ class ReplayStorageType(TextChoices):
azure = 'azure', 'Azure'
obs = 'obs', 'OBS'
cos = 'cos', 'COS'
sftp = 'sftp', 'SFTP'
class CommandStorageType(TextChoices):

View File

@ -0,0 +1,18 @@
# Generated by Django 4.1.10 on 2023-11-02 10:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('terminal', '0066_applethost_using_same_account'),
]
operations = [
migrations.AlterField(
model_name='replaystorage',
name='type',
field=models.CharField(choices=[('null', 'Null'), ('server', 'Server'), ('s3', 'S3'), ('ceph', 'Ceph'), ('swift', 'Swift'), ('oss', 'OSS'), ('azure', 'Azure'), ('obs', 'OBS'), ('cos', 'COS'), ('sftp', 'SFTP')], default='server', max_length=16, verbose_name='Type'),
),
]

View File

@ -3,6 +3,7 @@
from urllib.parse import urlparse
from django.db.models import TextChoices
from django.core.validators import MaxValueValidator, MinValueValidator, validate_ipv46_address
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from rest_framework.validators import UniqueValidator
@ -118,6 +119,40 @@ class ReplayStorageTypeAzureSerializer(serializers.Serializer):
)
class SftpSecretType(TextChoices):
PASSWORD = 'password', _('Password')
SSH_KEY = 'ssh_key', _('SSH key')
class ReplayStorageTypeSFTPSerializer(serializers.Serializer):
SFTP_HOST = serializers.CharField(
required=True, max_length=1024, label=_('HOST'), validators=[validate_ipv46_address]
)
SFTP_PORT = serializers.IntegerField(
required=False, default=22, validators=[MaxValueValidator(65535), MinValueValidator(0)],
label=_('Port')
)
SFTP_USERNAME = serializers.CharField(
required=True, max_length=1024, label=_('Username')
)
STP_SECRET_TYPE = serializers.ChoiceField(choices=SftpSecretType.choices,
default=SftpSecretType.PASSWORD,
label=_('Secret type'))
SFTP_PASSWORD = EncryptedField(
allow_blank=True, allow_null=True, required=False, max_length=1024, label=_('Password')
)
STP_PRIVATE_KEY = serializers.CharField(
allow_blank=True, allow_null=True, required=False, max_length=4096,
write_only=True, label=_('Private key')
)
STP_PASSPHRASE = EncryptedField(
allow_blank=True, allow_null=True, required=False, max_length=1024, label=_('Key password')
)
SFTP_ROOT_PATH = serializers.CharField(
required=True, max_length=1024, label=_('SFTP Root')
)
# mapping
replay_storage_type_serializer_classes_mapping = {
const.ReplayStorageType.s3.value: ReplayStorageTypeS3Serializer,
@ -126,7 +161,8 @@ replay_storage_type_serializer_classes_mapping = {
const.ReplayStorageType.oss.value: ReplayStorageTypeOSSSerializer,
const.ReplayStorageType.azure.value: ReplayStorageTypeAzureSerializer,
const.ReplayStorageType.obs.value: ReplayStorageTypeOBSSerializer,
const.ReplayStorageType.cos.value: ReplayStorageTypeCOSSerializer
const.ReplayStorageType.cos.value: ReplayStorageTypeCOSSerializer,
const.ReplayStorageType.sftp.value: ReplayStorageTypeSFTPSerializer
}