diff --git a/Dockerfile-ee b/Dockerfile-ee index c59ab222d..1809e321a 100644 --- a/Dockerfile-ee +++ b/Dockerfile-ee @@ -21,6 +21,17 @@ WORKDIR /opt/jumpserver ARG PIP_MIRROR=https://pypi.org/simple +ARG GMSSL_VERSION=3.1.1 + RUN set -ex \ && uv pip install -i${PIP_MIRROR} --group xpack \ - && rm -rf /root/.cache/ \ No newline at end of file + && rm -rf /root/.cache/ + +RUN set -ex \ + && wget -q -O /tmp/gmssl-install.sh \ + "https://github.com/guanzhi/GmSSL/releases/download/v${GMSSL_VERSION}/GmSSL-${GMSSL_VERSION}-Linux.sh" \ + && chmod +x /tmp/gmssl-install.sh \ + && /tmp/gmssl-install.sh --prefix=/usr/local \ + && echo "/usr/local/GmSSL-${GMSSL_VERSION}-Linux/lib" > /etc/ld.so.conf.d/gmssl.conf \ + && ldconfig \ + && rm -f /tmp/gmssl-install.sh \ No newline at end of file diff --git a/apps/authentication/backends/cert/__init__.py b/apps/authentication/backends/cert/__init__.py new file mode 100644 index 000000000..72f1ead27 --- /dev/null +++ b/apps/authentication/backends/cert/__init__.py @@ -0,0 +1 @@ +from .backends import * \ No newline at end of file diff --git a/apps/authentication/backends/cert/api.py b/apps/authentication/backends/cert/api.py new file mode 100644 index 000000000..7e46a9ec5 --- /dev/null +++ b/apps/authentication/backends/cert/api.py @@ -0,0 +1,193 @@ + +import base64 +import os +import subprocess +import tempfile +from django.utils.translation import gettext_lazy as _ + +import yaml +from django.conf import settings +from django.http import FileResponse, Http404 +from django.utils.decorators import method_decorator +from django.views.decorators.cache import cache_control +from rest_framework.response import Response +from rest_framework.views import APIView +from rest_framework.permissions import AllowAny +from common.permissions import OnlySuperUser +from common.utils import get_logger +from .driver import cert_vd_cfg + + +__all__ = ['VendorDriverFileAPIView', 'CertVendorDriverConfigAPIView'] + +logger = get_logger(__name__) + + +class VendorDriverFileAPIView(APIView): + permission_classes = (AllowAny,) + + @method_decorator(cache_control(public=True, max_age=3600)) + def get(self, request): + js_file = cert_vd_cfg.driver_js_file + if not js_file or not os.path.isfile(js_file): + raise Http404 + response = FileResponse(open(js_file, 'rb'), content_type='application/javascript') + response['Cache-Control'] = 'public, max-age=3600' + return response + + +class CertVendorDriverConfigAPIView(APIView): + permission_classes = (AllowAny,) + + def get(self, request): + lang = request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME) or settings.LANGUAGE_CODE + data = cert_vd_cfg.get_vendor_sdk_data(lang=lang) + return Response(data) + + +class CertEnrollAPIView(APIView): + permission_classes = (OnlySuperUser,) + + # SM2 曲线 OID:1.2.156.10197.1.301 + # DER 编码:06 08 2a 81 1c cf 55 01 82 2d + _SM2_OID_DER = bytes([0x06, 0x08, 0x2a, 0x81, 0x1c, 0xcf, 0x55, 0x01, 0x82, 0x2d]) + + def post(self, request): + if not cert_vd_cfg.enroll_enabled: + data = {'error': _('Certificate enrollment is not enabled')} + return Response(data=data, status=400) + + csr_raw = request.data.get('csr') + if not csr_raw: + data = {'error': _('CSR is required')} + return Response(data=data, status=400) + + try: + singed_cert = self.sign_cert(csr_raw) + except Exception as e: + error = '{}: {}'.format(_('Certificate signing failed'), str(e)) + logger.error(error, exc_info=True) + return Response(data={'error': error}, status=400) + + data = {'signed_cert': singed_cert} + return Response(data=data, status=200) + + def sign_cert(self, csr_raw): + # 记录输入是否含 PEM 头,用于决定输出格式 + if isinstance(csr_raw, bytes): + has_pem_header = csr_raw.lstrip().startswith(b'-----BEGIN') + else: + has_pem_header = csr_raw.strip().startswith('-----BEGIN') + + csr_pem = self._normalize_csr_to_pem(csr_raw) + if self._is_sm2_csr(csr_pem): + singed_cert = self.sign_cert_by_gmssl(csr_pem) + else: + singed_cert = self.sign_cert_by_other(csr_pem) + + # 输入不含 PEM 头时,返回裸 base64(去掉首尾标识行) + if not has_pem_header: + lines = singed_cert.strip().splitlines() + singed_cert = ''.join( + ln for ln in lines if not ln.startswith('-----') + ) + return singed_cert + + def _normalize_csr_to_pem(self, csr_data): + """ + 将 SDK 返回的 CSR 统一转换成标准 PEM 字符串。 + 支持三种输入格式: + 1. 已经是标准 PEM(含 -----BEGIN CERTIFICATE REQUEST----- 头) + 2. 裸 base64 字符串(无 PEM 头,国密 USB Key SDK 常见) + 3. 原始 DER 二进制 bytes + """ + if isinstance(csr_data, bytes): + if csr_data.lstrip().startswith(b'-----BEGIN'): + return csr_data.decode('utf-8') + b64 = base64.b64encode(csr_data).decode('ascii') + else: + csr_data = csr_data.strip() + if csr_data.startswith('-----BEGIN'): + return csr_data + # 裸 base64:去除空白后校验并重新分行 + b64 = ''.join(csr_data.split()) + base64.b64decode(b64, validate=True) + + lines = [b64[i:i + 64] for i in range(0, len(b64), 64)] + return ( + '-----BEGIN CERTIFICATE REQUEST-----\n' + + '\n'.join(lines) + + '\n-----END CERTIFICATE REQUEST-----\n' + ) + + def _is_sm2_csr(self, csr_pem): + """ + 通过查找 SM2 曲线 OID 字节序列判断 CSR 是否使用 SM2 算法, + 无需调用外部工具。 + """ + pem_lines = csr_pem.strip().splitlines() + b64 = ''.join(ln for ln in pem_lines if not ln.startswith('-----')) + der = base64.b64decode(b64) + return self._SM2_OID_DER in der + + def sign_cert_by_other(self, csr_pem): + pass + + def sign_cert_by_gmssl(self, csr_pem): + """ + 使用 gmssl reqsign 签发 SM2 证书。 + 命令示例: + gmssl reqsign -in user.csr -days 365 -cacert root.crt -key root.key -pass 123456 -out user.crt + """ + gmssl_bin = cert_vd_cfg.gmssl_bin + ca_key_path = cert_vd_cfg.ca_key_file + ca_cert_path = cert_vd_cfg.ca_cert_file + ca_key_pass = str(cert_vd_cfg.ca_key_pass) + if not ca_key_path or not os.path.isfile(ca_key_path): + raise FileNotFoundError('CA_KEY_FILE not configured or not found') + if not ca_cert_path or not os.path.isfile(ca_cert_path): + raise FileNotFoundError('CA_CERT_FILE not configured or not found') + + validity_days = str(cert_vd_cfg.enroll_validity_days) + + csr_file = cert_file = None + try: + with tempfile.NamedTemporaryFile( + suffix='.csr', mode='w', delete=False, encoding='utf-8' + ) as f: + f.write(csr_pem) + csr_file = f.name + + fd, cert_file = tempfile.mkstemp(suffix='.crt') + os.close(fd) + + # https://github.com/GmSSL/GmSSL-Python#sm2数字证书 + # gmssl_python 只支持SM2证书的解析和验证等功能,不支持SM2证书的签发和生成, + # 所以还是需要使用 gmssl bin 来执行 reqsign 命令行工具进行签发。虽然增加了对外部命令的依赖, + # 但这是目前最简单可靠的方案。 + cmd = [ + gmssl_bin, 'reqsign', + '-in', csr_file, + '-days', validity_days, + '-cacert', ca_cert_path, + '-key', ca_key_path, + '-out', cert_file, + ] + if ca_key_pass: + cmd += ['-pass', ca_key_pass] + + result = subprocess.run( + cmd, + capture_output=True, + text=True, + timeout=30 + ) + if result.returncode != 0: + raise RuntimeError('gmssl reqsign failed: {}'.format(result.stderr.strip())) + + with open(cert_file, 'r', encoding='utf-8') as f: + return f.read() + finally: + for path in (csr_file, cert_file): + if path and os.path.exists(path): + os.unlink(path) diff --git a/apps/authentication/backends/cert/api_urls.py b/apps/authentication/backends/cert/api_urls.py new file mode 100644 index 000000000..2a7e11cbd --- /dev/null +++ b/apps/authentication/backends/cert/api_urls.py @@ -0,0 +1,10 @@ + +from django.urls import path +from . import api + +urlpatterns = [ + # api + path('cert/vendor-driver.js/', api.VendorDriverFileAPIView.as_view(), name='cert-vendor-driver-js-file'), + path('cert/vendor-driver-config/', api.CertVendorDriverConfigAPIView.as_view(), name='cert-vendor-driver-config'), + path('cert/enroll/', api.CertEnrollAPIView.as_view(), name='cert-enroll'), +] diff --git a/apps/authentication/backends/cert/backends.py b/apps/authentication/backends/cert/backends.py new file mode 100644 index 000000000..d203120c1 --- /dev/null +++ b/apps/authentication/backends/cert/backends.py @@ -0,0 +1,193 @@ +# -*- coding: utf-8 -*- +# + +import base64 +import os +import tempfile + +from django.conf import settings + +from users.models import User +from common.utils import get_logger +from ..base import JMSBaseAuthBackend + + +__all__ = ['CertBackend'] + +logger = get_logger(__name__) + +# SM2 曲线 OID DER 字节序列,用于判断证书算法(与 api.py 保持一致) +_SM2_OID_DER = bytes([0x06, 0x08, 0x2a, 0x81, 0x1c, 0xcf, 0x55, 0x01, 0x82, 0x2d]) + + +class CertBackend(JMSBaseAuthBackend): + backend = settings.AUTH_BACKEND_CERT + + @staticmethod + def is_enabled(): + return settings.AUTH_CERT + + def authenticate(self, request, username, cert, signature, challenge): + try: + cert_pem = self._normalize_cert_to_pem(cert) + except Exception as e: + logger.warning('CertBackend: cert normalization failed: %s', e) + return None + + if self._is_sm2_cert(cert_pem): + return self._authenticate_sm2(cert_pem, username, signature, challenge) + else: + return self._authenticate_other(cert_pem, username, signature, challenge) + + # ── SM2 四步校验 ───────────────────────────────────────────────────────── + + def _authenticate_sm2(self, cert_pem, username, signature, challenge): + # 加载证书(写临时文件 → Sm2Certificate) + try: + sm2_cert = self._load_sm2_cert(cert_pem) + except Exception as e: + logger.warning('CertBackend: failed to load SM2 cert: %s', e) + return None + + # Step 1: 校验证书链,是否由 CA 根证书签发 + try: + self._verify_sm2_cert_chain(sm2_cert) + except Exception as e: + logger.warning('CertBackend: SM2 cert chain verification failed: %s', e) + return None + + # Step 2: 从证书 subject 提取 CN,与传入 username 比对 + cert_cn = sm2_cert.get_subject().get('commonName') + if cert_cn != username: + logger.warning( + 'CertBackend: cert CN %r does not match username %r', cert_cn, username + ) + return None + + # Step 3: 用证书公钥验证签名 + public_key = sm2_cert.get_subject_public_key() + try: + sig_ok = self._verify_sm2_signature(public_key, signature, challenge) + except Exception as e: + logger.warning('CertBackend: SM2 signature verification failed: %s', e) + return None + if not sig_ok: + logger.warning('CertBackend: SM2 signature mismatch') + return None + + # Step 4: 查询并返回用户 + return User.objects.filter(username=username).first() + + @staticmethod + def _load_sm2_cert(cert_pem): + """将 PEM 字符串写入临时文件,加载为 Sm2Certificate 对象后立即删除临时文件。""" + from common.utils.gmssl_python import Sm2Certificate + + fd, cert_file = tempfile.mkstemp(suffix='.crt') + try: + os.close(fd) + with open(cert_file, 'w', encoding='utf-8') as f: + f.write(cert_pem) + sm2_cert = Sm2Certificate() + sm2_cert.import_pem(cert_file) + finally: + if os.path.exists(cert_file): + os.unlink(cert_file) + return sm2_cert + + def _verify_sm2_cert_chain(self, sm2_cert): + """调用 Sm2Certificate.verify_by_ca_certificate 验证证书链。""" + from common.utils.gmssl_python import SM2_DEFAULT_ID + + ca_cert_path = getattr(settings, 'CA_CERT_FILE', '') + if not ca_cert_path or not os.path.isfile(ca_cert_path): + raise FileNotFoundError('CA_CERT_FILE not configured or not found') + + from common.utils.gmssl_python import Sm2Certificate + ca_cert = Sm2Certificate() + ca_cert.import_pem(ca_cert_path) + + if not sm2_cert.verify_by_ca_certificate(ca_cert, SM2_DEFAULT_ID): + raise ValueError('SM2 cert chain verification failed') + + @staticmethod + def _verify_sm2_signature(sm2_key, signature, challenge): + """ + 使用 gmssl_python 的 Sm2Signature 做 SM2withSM3 验签。 + + sm2_key : Sm2Certificate.get_subject_public_key() 返回的 Sm2Key 对象。 + signature : USB Key 返回的签名(bytes / hex 字符串 / base64 字符串,DER 格式)。 + challenge : 服务端下发的挑战码字符串;JS 端对 btoa(challenge) 做签名。 + """ + from common.utils.gmssl_python import Sm2Signature, DO_VERIFY, SM2_DEFAULT_ID + + sig_bytes = CertBackend._decode_signature(signature) + + # JS 端直接对 challenge 字符串签名,无需 base64 编码 + if isinstance(challenge, bytes): + signed_data = challenge + else: + signed_data = challenge.encode('utf-8') + + verifier = Sm2Signature(sm2_key, SM2_DEFAULT_ID, DO_VERIFY) + verifier.update(signed_data) + return bool(verifier.verify(sig_bytes)) + + # ── 工具方法 ───────────────────────────────────────────────────────────── + + @staticmethod + def _is_sm2_cert(cert_pem): + """通过 OID 字节序列判断证书是否使用 SM2 算法。""" + pem_lines = cert_pem.strip().splitlines() + b64 = ''.join(ln for ln in pem_lines if not ln.startswith('-----')) + der = base64.b64decode(b64) + return _SM2_OID_DER in der + + @staticmethod + def _normalize_cert_to_pem(cert_data): + """ + 将证书统一转换为标准 PEM 格式。 + 支持:已含头尾的 PEM、裸 base64 字符串、DER bytes。 + """ + if isinstance(cert_data, bytes): + if cert_data.lstrip().startswith(b'-----BEGIN'): + return cert_data.decode('utf-8') + b64 = base64.b64encode(cert_data).decode('ascii') + else: + cert_data = cert_data.strip() + if cert_data.startswith('-----BEGIN'): + return cert_data + b64 = ''.join(cert_data.split()) + base64.b64decode(b64, validate=True) # 验证是合法 base64 + + lines = [b64[i:i + 64] for i in range(0, len(b64), 64)] + return ( + '-----BEGIN CERTIFICATE-----\n' + + '\n'.join(lines) + + '\n-----END CERTIFICATE-----\n' + ) + + @staticmethod + def _decode_signature(signature): + """ + 将签名值转为 bytes。 + 依次尝试:已是 bytes → 十六进制字符串 → base64 字符串。 + """ + if isinstance(signature, bytes): + return signature + sig = signature.strip() + try: + return bytes.fromhex(sig) + except ValueError: + pass + try: + return base64.b64decode(sig) + except Exception: + pass + raise ValueError('Cannot decode signature: unknown format') + + # ── 其他算法(预留)──────────────────────────────────────────────────────── + + def _authenticate_other(self, cert_pem, username, signature, challenge): + logger.warning('CertBackend: non-SM2 cert verification is not yet implemented') + return None \ No newline at end of file diff --git a/apps/authentication/backends/cert/driver.py b/apps/authentication/backends/cert/driver.py new file mode 100644 index 000000000..a3f39b103 --- /dev/null +++ b/apps/authentication/backends/cert/driver.py @@ -0,0 +1,182 @@ +import os +import yaml +import json +from django.conf import settings +from common.utils import get_logger +from common.decorators import Singleton +from common.const import Language + + +logger = get_logger(__name__) + +class Setting: + VENDOR = getattr(settings, 'VENDOR', '') + + +@Singleton +class CertVendorDriverConfig: + """ + 从 YAML 配置文件读取所有证书相关配置。 + + CA 相关路径/密码(ca_cert_file / ca_key_file / ca_key_pass)属于系统敏感配置, + 只能在系统设置(config.yml / Django settings)中配置,不允许写入此 YAML。 + + YAML 结构约定: + cert: # 系统级配置段 + gmssl_bin: gmssl # gmssl 二进制路径 + challenge_ttl: 300 # Challenge 码 Redis 存活秒数 + enroll: + enabled: true # 是否开启证书签发 + key_algo: SM2 # 签发密钥算法:SM2 或 RSA + subject_cn: username # 用户证书 Subject CN 取自用户的哪个字段 + subject_o: JumpServer # 用户证书 Subject O(组织名) + # 其余 key 为厂商 SDK 方法映射(供前端 API 层使用) + newUKeyAPI: ... + checkInstall: ... + getCertCN: ... + ... + """ + + def __init__(self): + if not settings.AUTH_CERT: + logger.debug('CertVendorDriverConfig: authentication backend not enabled, skipping config load') + return + config_file = getattr(settings, 'AUTH_CERT_VENDOR_DRIVER_CONFIG_FILE', None) + self._raw = self._load_yaml(config_file) + self._cert = self._raw.get('cert') or {} + self._enroll = self._cert.get('enroll') or {} + + # ── YAML 加载 ──────────────────────────────────────────────────────────── + + @staticmethod + def _load_yaml(config_file): + if not config_file or not os.path.isfile(config_file): + logger.warning('CertVendorDriverConfig: config file not found: %s', config_file) + return {} + with open(config_file, 'r', encoding='utf-8') as f: + return yaml.safe_load(f) or {} + + # ── CA / 证书链(只读系统设置,不允许在 YAML 中配置)──────────────────────── + + @property + def ca_cert_file(self): + """CA 根证书路径,只从系统设置读取。""" + return getattr(settings, 'CA_CERT_FILE', None) + + @property + def ca_key_file(self): + """CA 私钥路径,只从系统设置读取。""" + return getattr(settings, 'CA_KEY_FILE', None) + + @property + def ca_key_pass(self): + """CA 私钥密码,只从系统设置读取。""" + return getattr(settings, 'CA_KEY_PASS', '') + + @property + def driver_js_file(self): + """返回厂商 SDK 驱动文件的 FileResponse,供 API 层使用。""" + return getattr(settings, 'AUTH_CERT_VENDOR_DRIVER_JS_FILE', None) + + # ── 工具 ───────────────────────────────────────────────────────────────── + + @property + def gmssl_bin(self): + """gmssl 二进制路径,默认 'gmssl'(系统 PATH 中查找)。""" + return 'gmssl' + + # ── 认证流程 ────────────────────────────────────────────────────────────── + + @property + def challenge_ttl(self): + """Challenge 码在 Redis 中的存活时间(秒),默认 300。""" + v = self._cert.get('challenge_ttl', 300) + return int(v) + + # ── 证书签发 ────────────────────────────────────────────────────────────── + + @property + def enroll_enabled(self): + """是否开启用户证书签发功能。""" + v = self._enroll.get('enabled', True) + return bool(v) + + @property + def enroll_key_algo(self): + """签发证书时生成密钥对的算法,SM2 或 RSA。""" + return self._enroll.get('key_algo', 'SM2') + + @property + def enroll_subject_cn(self): + """用户证书 Subject CN 取自用户模型的哪个字段,默认 'username'。""" + return self._enroll.get('subject_cn', 'username') + + @property + def enroll_subject_o(self): + """用户证书 Subject O(组织名)。""" + return self._enroll.get('subject_o', Setting.VENDOR) + + @property + def enroll_validity_days(self): + """签发证书的有效期(天),默认 365。""" + v = self._enroll.get('validity_days', 365) + return int(v) + + # ── 厂商 SDK 映射(原始数据,供 API 层序列化给前端)─────────────────────── + + @staticmethod + def _render(data, trans_filter=None): + """ + 渲染 YAML 数据中的 Jinja2 模板表达式。 + - {{ settings.xxx }} → 系统设置值(任何时候都生效) + - {{ user.xxx }} → 原样保留,留给前端 JS 运行时解析 + - {{ 'text' | trans }} → 按 trans_filter 翻译;不传则原文返回(初始化阶段) + """ + from jinja2 import Undefined, Environment + + class KeepUndefined(Undefined): + """未定义变量原样保留占位符,支持任意深度的属性链。""" + def __str__(self): + return '{{ ' + self._undefined_name + ' }}' + def __getattr__(self, name): + return KeepUndefined(name=f'{self._undefined_name}.{name}') + + template_str = json.dumps(data, ensure_ascii=False) + env = Environment(undefined=KeepUndefined) + env.filters['trans'] = trans_filter or (lambda s: s) + rendered = env.from_string(template_str).render(settings=Setting) + return json.loads(rendered) + + def _build_trans_filter(self, lang): + """构建 Jinja2 | trans filter 函数,按 lang 从 YAML i18n 表查找翻译。 + 未找到翻译时原文返回;语言键自动归一化(zh_hant → zh-hant)。 + """ + i18n_raw = self._raw.get('i18n') or {} + i18n = { + text: { + Language.to_internal_code(lk.replace('_', '-')): lv + for lk, lv in entries.items() + } + for text, entries in i18n_raw.items() + if isinstance(entries, dict) + } + + def trans_filter(s): + translations = i18n.get(str(s)) + if not translations: + return s + return translations.get(lang) or translations.get('en') or s + + return trans_filter + + def get_vendor_sdk_data(self, lang='en'): + """返回去掉 'cert'/'i18n' 顶层 key 后的厂商 SDK 方法映射。 + YAML 中任意字符串值均可用 {{ 'text' | trans }} 语法标记为可翻译。 + """ + lang = Language.to_internal_code(lang) + trans_filter = self._build_trans_filter(lang) + data = self._render(self._raw, trans_filter) + return {k: v for k, v in data.items() if k not in ('i18n',)} + + +cert_vd_cfg = CertVendorDriverConfig() diff --git a/apps/authentication/backends/cert/driver_config_demo/cert_driver_config.yaml b/apps/authentication/backends/cert/driver_config_demo/cert_driver_config.yaml new file mode 100644 index 000000000..001182e57 --- /dev/null +++ b/apps/authentication/backends/cert/driver_config_demo/cert_driver_config.yaml @@ -0,0 +1,343 @@ +# ── 系统级证书配置 ───────────────────────────────────────────────────────────── +# 所有与证书认证相关的系统配置均放在 cert: 段,其余 key 为厂商 SDK 方法映射。 +cert: + # Challenge 码在 Redis 中的存活时间(秒) + challenge_ttl: 300 + # 证书签发配置 + enroll: + enabled: true + key_algo: SM2 # 签发密钥算法:SM2 或 RSA + validity_days: 365 # 签发证书的有效期(天) + pin: + default: "88888888" + +showBasicInfo: + # 基础加密操作 + - version: + label: "{{ 'Version' | trans }}" + method: + call: UKey_GetVersion + description: "{{ 'Get USB Key driver version' | trans }}" + - devSN: + label: "{{ 'Device serial number' | trans }}" + method: + call: UKey_GetDevSN + description: "{{ 'Get device serial number' | trans }}" + - enrollEnabled: + label: "{{ 'Certificate enrollment' | trans }}" + value: "{{ 'Enabled' | trans }}" + description: "{{ 'Whether certificate enrollment is enabled' | trans }}" + only: admin + - enrollKeyAlgo: + label: "{{ 'Enrollment algorithm' | trans }}" + value: "{{ 'SM2' | trans }}" + description: "{{ 'Key algorithm used for enrollment' | trans }}" + only: admin + - enrollValidityDays: + label: "{{ 'Certificate validity' | trans }}" + value: "{{ '365 days' | trans }}" + description: "{{ 'Certificate validity period used for enrollment' | trans }}" + only: admin + +# ── 厂商 USB Key SDK 方法映射 ────────────────────────────────────────────────── +# USB Key 厂商 SDK 方法名映射 + +# Driver 初始化 +newUKeyAPI: + description: "{{ 'Initialize USB Key SDK and get SDK instance' | trans }}" + method: + call: UKeyAPI + +# 基本操作 +checkInstall: + description: "{{ 'Check if USB Key driver is installed' | trans }}" + method: + call: UKey_CheckInstall + +# 获取用户名 +getCertCN: + description: "{{ 'Get built-in username from USB Key' | trans }}" + method: + call: UKey_GetCertInfo + params: + - key: CERT_TYPE_SIGN + value: 1 + - key: CERT_SUBJECT_CN + value: 9 + +# 管理员重置 PIN +adminResetPIN: + description: "{{ 'Reset PIN' | trans }}" + method: + call: UKey_UnblockPIN + params: + - key: admin_pin + value: '{{ input.admin_pin }}' + - key: usb_key_pin + value: '{{ output.default_pin }}' + +# 用户修改 PIN +userChangePIN: + description: "{{ 'User change PIN' | trans }}" + method: + call: UKey_ChangePIN + params: + - key: old_pin + value: '{{ input.old_pin }}' + - key: new_pin1 + value: '{{ input.new_pin1 }}' + result: + success: 0 + +# 清除证书 +deleteCert: + description: "{{ 'Delete existing certificate' | trans }}" + method: + call: UKey_DeleteCons + +# 校验 PIN +checkPIN: + description: "{{ 'Verify PIN' | trans }}" + method: + call: UKey_VerifyPIN + params: + - key: pin + value: '{{ input.login_pin }}' + result: + success: 0 + +# 获取公钥 +getCert: + description: "{{ 'Get certificate' | trans }}" + method: + call: UKey_GetCert + params: + - key: CERT_TYPE_SIGN + value: 1 + +# 签名数据 +signData: + description: "{{ 'Sign data using the private key in USB Key' | trans }}" + method: + call: UKey_SignData + params: + - key: SM3 + value: 1 + - key: challenge_code + value: '{{ output.challenge_code }}' + +getCertInfo: + description: "{{ 'Get certificate list (including certificate information)' | trans }}" + method: + call: UKey_GetCertInfoList + fields: + - ID: + key: ID + label: "{{ 'Certificate ID' | trans }}" + - CN: + key: CN + label: "{{ 'CN (ID)' | trans }}" + - DN: + key: DN + label: "{{ 'DN' | trans }}" + - SN: + key: SN + label: "{{ 'SN' | trans }}" + - bef: + key: bef + label: "{{ 'bef' | trans }}" + - aft: + key: aft + label: "{{ 'aft' | trans }}" + - isSM: + key: isSM + label: "{{ 'SM2 certificate' | trans }}" + - DEVSN: + key: DEVSN + label: "{{ 'Device serial number' | trans }}" + showFields: [ID, CN, DN, SN, bef, aft, isSM, DEVSN] + +# 制证流程(Enrollment) +# 步骤顺序:1 → 2 → 3 → 4(服务端签发)→ 5 +enrollSteps: + # 制证前清除旧证书,避免容器满 + - deleteCert: + description: "{{ 'Delete existing certificate' | trans }}" + method: + call: UKey_DeleteCons + + # 在 USB Key 硬件内生成密钥对(私钥永不离开设备) + - genKeyPair: + description: "{{ 'Generate key pair' | trans }}" + method: + call: UKey_GenKeyPair + params: + - key: asymAlg + label: "{{ 'Asymmetric algorithm' | trans }}" + type: int + value: 1 # SM2 + + # 用 USB Key 内的私钥生成 CSR(包含公钥 + Subject 信息) + - genCSR: + description: "{{ 'Generate certificate signing request (CSR)' | trans }}" + method: + call: UKey_GenCSR + params: + - key: dn + label: "{{ 'Certificate subject (Subject DN)' | trans }}" + type: string + items: + - key: CN + label: "{{ 'Name (CN)' | trans }}" + value: '{{ user.username }}' # 从配置读取 Subject CN 字段 + - key: OU + label: "{{ 'Other information' | trans }}" + value: '{{ settings.VENDOR }}' # 从配置读取 Subject O 字段 + + - signCert: + description: "{{ 'Certificate issuance' | trans }}" + + # 服务端 CA 签发证书后,将证书写入 USB Key + - writeCert: + description: "{{ 'Write the certificate' | trans }}" + method: + call: UKey_ImportCertAndKeyPair + params: + - key: SignCert + type: string + value: '{{ output.signed_cert }}' # 从服务端签发结果读取签名证书 + - key: EncCert + value: '' + - key: EncKeyPair + value: '' + +i18n: + Version: + en: Version + zh-hans: 版本 + zh-hant: 版本 + Get USB Key driver version: + en: Get USB Key driver version + zh-hans: 获取 USB Key 驱动版本 + zh-hant: 取得 USB Key 驅動版本 + Device serial number: + en: Device serial number + zh-hans: 设备序列号 + zh-hant: 裝置序號 + Get device serial number: + en: Get device serial number + zh-hans: 获取设备序列号 + zh-hant: 取得裝置序號 + Certificate enrollment: + en: Certificate enrollment + zh-hans: 制证功能 + zh-hant: 制證功能 + Enabled: + en: Enabled + zh-hans: 启用 + zh-hant: 啟用 + Whether certificate enrollment is enabled: + en: Whether certificate enrollment is enabled + zh-hans: 是否启用制证功能 + zh-hant: 是否啟用制證功能 + Enrollment algorithm: + en: Enrollment algorithm + zh-hans: 制证算法 + zh-hant: 制證演算法 + Key algorithm used for enrollment: + en: Key algorithm used for enrollment + zh-hans: 制证使用的密钥算法 + zh-hant: 制證使用的金鑰演算法 + Certificate validity: + en: Certificate validity + zh-hans: 证书期限 + zh-hant: 證書有效期 + 365 days: + en: 365 days + zh-hans: 365 天 + zh-hant: 365 天 + Certificate validity period used for enrollment: + en: Certificate validity period used for enrollment + zh-hans: 制证使用的证书有效期 + zh-hant: 制證使用的證書有效期 + Initialize USB Key SDK and get SDK instance: + en: Initialize USB Key SDK and get SDK instance + zh-hans: 初始化 USB Key SDK,获取 SDK 对象实例 + zh-hant: 初始化 USB Key SDK 並取得 SDK 物件實例 + Check if USB Key driver is installed: + en: Check if USB Key driver is installed + zh-hans: 检查 USB Key 驱动是否安装 + zh-hant: 檢查 USB Key 驅動是否已安裝 + Get built-in username from USB Key: + en: Get built-in username from USB Key + zh-hans: 获取 USB Key 内置用户名 + zh-hant: 取得 USB Key 內建使用者名稱 + Reset PIN: + en: Reset PIN + zh-hans: 重置 PIN + zh-hant: 重置 PIN + User change PIN: + en: User change PIN + zh-hans: 用户修改 PIN + zh-hant: 使用者修改 PIN + Delete existing certificate: + en: Delete existing certificate + zh-hans: 删除已有证书 + zh-hant: 刪除已有證書 + Verify PIN: + en: Verify PIN + zh-hans: 校验 PIN 是否正确 + zh-hant: 驗證 PIN 是否正確 + Get certificate: + en: Get certificate + zh-hans: 获取证书 + zh-hant: 取得證書 + Sign data using the private key in USB Key: + en: Sign data using the private key in USB Key + zh-hans: 使用 USB Key 内的私钥对数据进行签名 + zh-hant: 使用 USB Key 內的私鑰對資料進行簽名 + Get certificate list (including certificate information): + en: Get certificate list (including certificate information) + zh-hans: 获取证书列表(包含证书信息) + zh-hant: 取得證書清單(包含證書資訊) + Certificate ID: + en: Certificate ID + zh-hans: 证书 ID + zh-hant: 證書 ID + SM2 certificate: + en: SM2 certificate + zh-hans: 国密证书 + zh-hant: 國密證書 + Generate key pair: + en: Generate key pair + zh-hans: 生成密钥对 + zh-hant: 產生金鑰對 + Asymmetric algorithm: + en: Asymmetric algorithm + zh-hans: 非对称算法 + zh-hant: 非對稱演算法 + Generate certificate signing request (CSR): + en: Generate certificate signing request (CSR) + zh-hans: 生成证书签名请求 (CSR) + zh-hant: 產生憑證簽名請求 (CSR) + Certificate subject (Subject DN): + en: Certificate subject (Subject DN) + zh-hans: 证书主题 (Subject DN) + zh-hant: 憑證主題 (Subject DN) + Name (CN): + en: Name (CN) + zh-hans: 名称 (CN) + zh-hant: 名稱 (CN) + Other information: + en: Other information + zh-hans: 其他信息 + zh-hant: 其他資訊 + Certificate issuance: + en: Certificate issuance + zh-hans: 证书签发 + zh-hant: 證書簽發 + Write the certificate: + en: Write the certificate + zh-hans: 写入证书 + zh-hant: 寫入證書 + diff --git a/apps/authentication/backends/cert/forms.py b/apps/authentication/backends/cert/forms.py new file mode 100644 index 000000000..277d919f2 --- /dev/null +++ b/apps/authentication/backends/cert/forms.py @@ -0,0 +1,18 @@ +from django import forms +from django.utils.translation import gettext_lazy as _ + + +class CertLoginForm(forms.Form): + username = forms.CharField( + label=_('Username'), max_length=100, required=True, + widget=forms.HiddenInput(), + ) + cert = forms.CharField( + required=True, + widget=forms.HiddenInput(), + ) + signature = forms.CharField( + required=True, + widget=forms.HiddenInput(), + ) + diff --git a/apps/authentication/backends/cert/view_urls.py b/apps/authentication/backends/cert/view_urls.py new file mode 100644 index 000000000..2faaadf47 --- /dev/null +++ b/apps/authentication/backends/cert/view_urls.py @@ -0,0 +1,7 @@ +from . import views + +from django.urls import path + +urlpatterns = [ + path('cert/login/', views.CertLoginView.as_view(), name='cert-login') +] diff --git a/apps/authentication/backends/cert/views.py b/apps/authentication/backends/cert/views.py new file mode 100644 index 000000000..1b3b6d64d --- /dev/null +++ b/apps/authentication/backends/cert/views.py @@ -0,0 +1,129 @@ +# -*- coding: utf-8 -*- +# +import secrets + +from django.conf import settings +from django.contrib.auth import authenticate, login as auth_login +from django.core.cache import cache +from django.utils.decorators import method_decorator +from django.utils.translation import gettext as _ +from django.views.decorators.cache import never_cache +from django.views.decorators.csrf import csrf_protect +from django.views.decorators.debug import sensitive_post_parameters +from django.views.generic.edit import FormView +from django.shortcuts import redirect +from django.http.response import HttpResponseRedirect + +from common.utils import reverse, safe_next_url +from users.utils import redirect_user_first_login_or_index +from authentication.mixins import AuthMixin +from authentication.errors import ACLError +from authentication.errors import ( + AuthFailedError, LoginConfirmBaseError, NeedRedirectError +) +from .forms import CertLoginForm +from users.utils import LoginBlockUtil, LoginIpBlockUtil + + +__all__ = ['CertLoginView'] + +_CHALLENGE_CACHE_KEY_PREFIX = 'cert_login_challenge' +NEXT_URL = 'next' + +@method_decorator(sensitive_post_parameters(), name='dispatch') +@method_decorator(csrf_protect, name='dispatch') +@method_decorator(never_cache, name='dispatch') +class CertLoginView(AuthMixin, FormView): + template_name = 'authentication/cert_login.html' + form_class = CertLoginForm + redirect_field_name = 'next' + + # ------------------------------------------------------------------ + # Challenge helpers + # ------------------------------------------------------------------ + + def _ensure_session(self): + if not self.request.session.session_key: + self.request.session.create() + + def _challenge_cache_key(self): + self._ensure_session() + return f'{_CHALLENGE_CACHE_KEY_PREFIX}_{self.request.session.session_key}' + + def _generate_and_store_challenge(self): + challenge = secrets.token_hex(16) + ttl = getattr(settings, 'AUTH_CERT_CHALLENGE_TTL', 300) + cache.set(self._challenge_cache_key(), challenge, ttl) + return challenge + + def _get_stored_challenge(self): + return cache.get(self._challenge_cache_key(), '') + + def _delete_stored_challenge(self): + cache.delete(self._challenge_cache_key()) + + # ------------------------------------------------------------------ + # Views + # ------------------------------------------------------------------ + + def get(self, request, *args, **kwargs): + challenge = self._generate_and_store_challenge() + context = self.get_context_data(form=self.get_form(), challenge=challenge) + return self.render_to_response(context) + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + if 'challenge' not in context: + context['challenge'] = self._get_stored_challenge() + return context + + def form_valid(self, form): + username = form.cleaned_data['username'] + cert = form.cleaned_data['cert'] + signature = form.cleaned_data['signature'] + challenge = self._get_stored_challenge() + + error_msg = None + ip = self.get_request_ip() + + try: + self._check_is_block(username, True) + self._check_only_allow_exists_user_auth(username) + + user = authenticate( + self.request, username=username, cert=cert, signature=signature, challenge=challenge + ) + if user is None: + error_msg = _('Invalid credentials') + return self.get_failed_response(form, username, error_msg) + + username = user.username + self._check_login_acl(user, ip) + + LoginIpBlockUtil(ip).clean_block_if_need() + LoginBlockUtil(username, ip).clean_failed_count() + except AuthFailedError as e: + error_msg = e.msg + except NeedRedirectError as e: + return redirect(e.url) + except Exception as e: + error_msg = str(e) + finally: + self._delete_stored_challenge() + + if error_msg: + return self.get_failed_response(form, username, error_msg) + else: + return self.get_success_response(self.request, user) + + def get_failed_response(self, form, username, error_msg): + form.add_error(None, error_msg) + # Refresh the challenge so it cannot be replayed + challenge = self._generate_and_store_challenge() + context = self.get_context_data(form=form, challenge=challenge) + self.send_auth_signal(success=False, reason=error_msg, username=username) + return self.render_to_response(context) + + def get_success_response(self, request, user): + self.mark_cert_ok(user, auth_backend=settings.AUTH_BACKEND_CERT) + return self.redirect_to_guard_view() diff --git a/apps/authentication/mixins.py b/apps/authentication/mixins.py index b201a1cf8..16599bc48 100644 --- a/apps/authentication/mixins.py +++ b/apps/authentication/mixins.py @@ -245,6 +245,12 @@ class CommonMixin: return user user_id = self.request.session.get('user_id') + auth_cert_ok = self.request.session.get('auth_cert') + if auth_cert_ok: + user = get_object_or_404(User, pk=user_id) + user.backend = self.request.session.get("auth_backend") + return user + auth_ok = self.request.session.get('auth_password') auth_expired_at = self.request.session.get('auth_password_expired_at') auth_expired = auth_expired_at < time.time() if auth_expired_at else False @@ -669,7 +675,7 @@ class AuthMixin(CommonMixin, AuthPreCheckMixin, AuthACLMixin, AuthFaceMixin, MFA LoginBlockUtil(user.username, ip).clean_failed_count() LoginIpBlockUtil(ip).clean_block_if_need() return user - + def mark_password_ok(self, user, auto_login=False, auth_backend=None): request = self.request request.session['auth_password'] = 1 @@ -681,6 +687,12 @@ class AuthMixin(CommonMixin, AuthPreCheckMixin, AuthACLMixin, AuthFaceMixin, MFA request.session['auth_backend'] = auth_backend + def mark_cert_ok(self, user, auth_backend): + request = self.request + request.session['auth_cert'] = 1 + request.session['user_id'] = str(user.id) + request.session['auth_backend'] = auth_backend + def check_oauth2_auth(self, user: User, auth_backend): ip = self.get_request_ip() request = self.request @@ -713,7 +725,8 @@ class AuthMixin(CommonMixin, AuthPreCheckMixin, AuthACLMixin, AuthFaceMixin, MFA keys = [ 'auth_password', 'user_id', 'auth_confirm_required', 'auth_notice_required', 'auth_ticket_id', 'auth_acl_id', - 'user_session_id', 'user_log_id', 'can_send_notifications' + 'user_session_id', 'user_log_id', 'can_send_notifications', + 'auth_cert' ] for k in keys: self.request.session.pop(k, '') diff --git a/apps/authentication/templates/authentication/cert_login.html b/apps/authentication/templates/authentication/cert_login.html new file mode 100644 index 000000000..20627e1fa --- /dev/null +++ b/apps/authentication/templates/authentication/cert_login.html @@ -0,0 +1,492 @@ +{% load i18n %} +{% load bootstrap3 %} +{% load static %} + + + + + + {{ INTERFACE.login_title }} + + {% include '_head_css_js.html' %} + + + + + + + +
+
+ Logo +
+

{% trans "Certificate Authentication" %}

+ + +
+ + {% trans "Loading USB Key driver..." %} +
+ +
+ {% csrf_token %} + + {% if form.non_field_errors %} +
+

{{ form.non_field_errors.as_text }}

+
+ {% endif %} + + {# username is auto-filled from USB Key cert, display input is readonly, actual value submitted via hidden field #} +
+ + {{ form.username }} + {% if form.username.errors %} +

{{ form.username.errors.as_text }}

+ {% endif %} +
+ {# PIN is only used for client-side USB Key verification, not submitted to backend #} +
+ +
+ {# cert is fetched and filled by JS after PIN verification, not shown to user #} + {{ form.cert }} + {# signature is filled by JS after signing challenge code, not shown to user #} + {{ form.signature }} + + + +
+ +
+
+ +
+ {% trans "More login methods" %} +
+
+ +{% include '_foot_js.html' %} + + + diff --git a/apps/authentication/urls/api_urls.py b/apps/authentication/urls/api_urls.py index 1072f4a41..2b7f7b3a3 100644 --- a/apps/authentication/urls/api_urls.py +++ b/apps/authentication/urls/api_urls.py @@ -6,6 +6,7 @@ from rest_framework.routers import DefaultRouter from .. import api from ..backends.passkey.urls import urlpatterns as passkey_urlpatterns +from ..backends.cert.api_urls import urlpatterns as cert_api_urlpatterns app_name = 'authentication' router = DefaultRouter() @@ -53,6 +54,7 @@ if settings.AUTH_CUSTOM_SSO: path('custom-sso/login/', api.CustomSSOLoginAPIView.as_view(), name='custom-sso-login'), ] - +if settings.AUTH_CERT: + urlpatterns += cert_api_urlpatterns urlpatterns += router.urls + passkey_urlpatterns diff --git a/apps/authentication/urls/view_urls.py b/apps/authentication/urls/view_urls.py index 0ed6621f9..337805acb 100644 --- a/apps/authentication/urls/view_urls.py +++ b/apps/authentication/urls/view_urls.py @@ -4,6 +4,7 @@ from django.db.transaction import non_atomic_requests from django.urls import path, include + from users import views as users_view from .. import views @@ -81,10 +82,12 @@ urlpatterns = [ path('openid/', include(('authentication.backends.oidc.urls', 'authentication'), namespace='openid')), path('saml2/', include(('authentication.backends.saml2.urls', 'authentication'), namespace='saml2')), path('oauth2/', include(('authentication.backends.oauth2.urls', 'authentication'), namespace='oauth2')), + path('cert/', include(('authentication.backends.cert.view_urls', 'authentication'), namespace='cert')), path('captcha/', include('captcha.urls')), path('oauth2-provider/', include(('authentication.backends.oauth2_provider.urls', 'authentication'), namespace='oauth2-provider')), path('user-agreement/', views.UserAgreementView.as_view(), name='user-agreement'), path('privacy-policy/', views.PrivacyPolicyView.as_view(), name='privacy-policy'), + ] diff --git a/apps/authentication/utils.py b/apps/authentication/utils.py index 731cc4493..61d88b2d6 100644 --- a/apps/authentication/utils.py +++ b/apps/authentication/utils.py @@ -145,5 +145,11 @@ def get_auth_methods(): 'enabled': settings.AUTH_PASSKEY, 'url': reverse('api-auth:passkey-login'), 'logo': static('img/login_passkey.png') + }, + { + 'name': _('CERT'), + 'enabled': settings.AUTH_CERT, + 'url': reverse('authentication:cert:cert-login'), + 'logo': static('img/login_cert.png') } ] diff --git a/apps/common/utils/gmssl_python.py b/apps/common/utils/gmssl_python.py new file mode 100644 index 000000000..056d64d83 --- /dev/null +++ b/apps/common/utils/gmssl_python.py @@ -0,0 +1,1040 @@ +# Copyright 2023 The GmSSL Project. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the License); you may +# not use this file except in compliance with the License. +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# GmSSL-Python - Python binding of the GmSSL library with `ctypes` + + +from ctypes import * +from ctypes.util import find_library +import datetime +import sys + +if find_library('gmssl') == None: + raise ValueError('Install GmSSL dynamic library from https://github.com/guanzhi/GmSSL') +gmssl = cdll.LoadLibrary(find_library("gmssl")) +if gmssl.gmssl_version_num() < 30101: + raise ValueError('GmSSL version < 3.1.1') + +if sys.platform == 'win32': + libc = cdll.LoadLibrary(find_library('msvcrt')) +else: + libc = cdll.LoadLibrary(find_library('c')) + + +class NativeError(Exception): + ''' + GmSSL libraray inner error + ''' + +class StateError(Exception): + ''' + Crypto state error + ''' + +GMSSL_PYTHON_VERSION = "2.2.2" + +def gmssl_library_version_num(): + return gmssl.gmssl_version_num() + +def gmssl_library_version_str(): + gmssl.gmssl_version_str.restype = c_char_p + return gmssl.gmssl_version_str().decode('ascii') + +GMSSL_LIBRARY_VERSION = gmssl_library_version_str() + + +def rand_bytes(size): + buf = create_string_buffer(size) + gmssl.rand_bytes(buf, c_size_t(size)) + return buf.raw + + + +SM3_DIGEST_SIZE = 32 +_SM3_STATE_WORDS = 8 +_SM3_BLOCK_SIZE = 64 + +class Sm3(Structure): + + _fields_ = [ + ("dgst", c_uint32 * _SM3_STATE_WORDS), + ("nblocks", c_uint64), + ("block", c_uint8 * _SM3_BLOCK_SIZE), + ("num", c_size_t) + ] + + def __init__(self): + gmssl.sm3_init(byref(self)) + + def reset(self): + gmssl.sm3_init(byref(self)) + + def update(self, data): + gmssl.sm3_update(byref(self), data, c_size_t(len(data))) + + def digest(self): + dgst = create_string_buffer(SM3_DIGEST_SIZE) + gmssl.sm3_finish(byref(self), dgst) + return dgst.raw + + +SM3_HMAC_MIN_KEY_SIZE = 16 +SM3_HMAC_MAX_KEY_SIZE = 64 +SM3_HMAC_SIZE = SM3_DIGEST_SIZE + +class Sm3Hmac(Structure): + + _fields_ = [ + ("sm3_ctx", Sm3), + ("key", c_uint8 * _SM3_BLOCK_SIZE) + ] + + def __init__(self, key): + if len(key) < SM3_HMAC_MIN_KEY_SIZE or len(key) > SM3_HMAC_MAX_KEY_SIZE: + raise ValueError('Invalid SM3 HMAC key length') + gmssl.sm3_hmac_init(byref(self), key, c_size_t(len(key))) + + def reset(self, key): + if len(key) < SM3_HMAC_MIN_KEY_SIZE or len(key) > SM3_HMAC_MAX_KEY_SIZE: + raise ValueError('Invalid SM3 HMAC key length') + gmssl.sm3_hmac_init(byref(self), key, c_size_t(len(key))) + + def update(self, data): + gmssl.sm3_hmac_update(byref(self), data, c_size_t(len(data))) + + def generate_mac(self): + hmac = create_string_buffer(SM3_HMAC_SIZE) + gmssl.sm3_hmac_finish(byref(self), hmac) + return hmac.raw + + + +SM3_PBKDF2_MIN_ITER = 10000 # from +SM3_PBKDF2_MAX_ITER = 16777216 # 2^24 +SM3_PBKDF2_MAX_SALT_SIZE = 64 # from +SM3_PBKDF2_DEFAULT_SALT_SIZE = 8 # from +SM3_PBKDF2_MAX_KEY_SIZE = 256 # from gmssljni.c:sm3_pbkdf2():sizeof(keybuf) + +def sm3_pbkdf2(passwd, salt, iterator, keylen): + + if len(salt) > SM3_PBKDF2_MAX_SALT_SIZE: + raise ValueError('Invalid salt length') + + if iterator < SM3_PBKDF2_MIN_ITER or iterator > SM3_PBKDF2_MAX_ITER: + raise ValueError('Invalid iterator value') + + if keylen > SM3_PBKDF2_MAX_KEY_SIZE: + raise ValueError('Invalid key length') + + passwd = passwd.encode('utf-8') + key = create_string_buffer(keylen) + + if gmssl.pbkdf2_hmac_sm3_genkey(c_char_p(passwd), c_size_t(len(passwd)), + salt, c_size_t(len(salt)), c_size_t(iterator), c_size_t(keylen), key) != 1: + raise NativeError('libgmssl inner error') + + return key.raw + + + +SM4_KEY_SIZE = 16 +SM4_BLOCK_SIZE = 16 +_SM4_NUM_ROUNDS = 32 + +class Sm4(Structure): + + _fields_ = [ + ("rk", c_uint32 * _SM4_NUM_ROUNDS) + ] + + def __init__(self, key, encrypt): + if len(key) != SM4_KEY_SIZE: + raise ValueError('Invalid key length') + if encrypt: + gmssl.sm4_set_encrypt_key(byref(self), key) + else: + gmssl.sm4_set_decrypt_key(byref(self), key) + + def encrypt(self, block): + if len(block) != SM4_BLOCK_SIZE: + raise ValueError('Invalid block size') + outbuf = create_string_buffer(SM4_BLOCK_SIZE) + gmssl.sm4_encrypt(byref(self), block, outbuf) + return outbuf.raw + + +SM4_CBC_IV_SIZE = SM4_BLOCK_SIZE + + +class Sm4Cbc(Structure): + + _fields_ = [ + ("sm4_key", Sm4), + ("iv", c_uint8 * SM4_BLOCK_SIZE), + ("block", c_uint8 * SM4_BLOCK_SIZE), + ("block_nbytes", c_size_t) + ] + + def __init__(self, key, iv, encrypt): + if len(key) != SM4_KEY_SIZE: + raise ValueError('Invalid key length') + if len(iv) != SM4_BLOCK_SIZE: + raise ValueError('Invalid IV size') + if encrypt == DO_ENCRYPT: + if gmssl.sm4_cbc_encrypt_init(byref(self), key, iv) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm4_cbc_decrypt_init(byref(self), key, iv) != 1: + raise NativeError('libgmssl inner error') + self._encrypt = encrypt + + def update(self, data): + outbuf = create_string_buffer(len(data) + SM4_BLOCK_SIZE) + outlen = c_size_t() + if self._encrypt == DO_ENCRYPT: + if gmssl.sm4_cbc_encrypt_update(byref(self), data, c_size_t(len(data)), + outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm4_cbc_decrypt_update(byref(self), data, c_size_t(len(data)), + outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[0:outlen.value] + + def finish(self): + outbuf = create_string_buffer(SM4_BLOCK_SIZE) + outlen = c_size_t() + if self._encrypt == True: + if gmssl.sm4_cbc_encrypt_finish(byref(self), outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm4_cbc_decrypt_finish(byref(self), outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[:outlen.value] + + + +SM4_CTR_IV_SIZE = 16 + + +class Sm4Ctr(Structure): + + _fields_ = [ + ("sm4_key", Sm4), + ("ctr", c_uint8 * SM4_BLOCK_SIZE), + ("block", c_uint8 * SM4_BLOCK_SIZE), + ("block_nbytes", c_size_t) + ] + + def __init__(self, key, iv): + if len(key) != SM4_KEY_SIZE: + raise ValueError('Invalid key length') + if len(iv) != SM4_BLOCK_SIZE: + raise ValueError('Invalid IV size') + if gmssl.sm4_ctr_encrypt_init(byref(self), key, iv) != 1: + raise NativeError('libgmssl inner error') + + def update(self, data): + outbuf = create_string_buffer(len(data) + SM4_BLOCK_SIZE) + outlen = c_size_t() + if gmssl.sm4_ctr_encrypt_update(byref(self), data, c_size_t(len(data)), + outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[0:outlen.value] + + def finish(self): + outbuf = create_string_buffer(SM4_BLOCK_SIZE) + outlen = c_size_t() + if gmssl.sm4_ctr_encrypt_finish(byref(self), outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[:outlen.value] + + +ZUC_KEY_SIZE = 16 +ZUC_IV_SIZE = 16 + +class ZucState(Structure): + _fields_ = [ + ("LFSR", c_uint32 * 16), + ("R1", c_uint32), + ("R2", c_uint32) + ] + +class Zuc(Structure): + + _fields_ = [ + ("zuc_state", ZucState), + ("block", c_uint8 * 4), + ("block_nbytes", c_size_t) + ] + + def __init__(self, key, iv): + if len(key) != ZUC_KEY_SIZE: + raise ValueError('Invalid key length') + if len(iv) != ZUC_IV_SIZE: + raise ValueError('Invalid IV size') + if gmssl.zuc_encrypt_init(byref(self), key, iv) != 1: + raise NativeError('libgmssl inner error') + + def update(self, data): + outbuf = create_string_buffer(len(data) + SM4_BLOCK_SIZE) + outlen = c_size_t() + if gmssl.zuc_encrypt_update(byref(self), data, c_size_t(len(data)), + outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[0:outlen.value] + + def finish(self): + outbuf = create_string_buffer(SM4_BLOCK_SIZE) + outlen = c_size_t() + if gmssl.zuc_encrypt_finish(byref(self), outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[:outlen.value] + + +class gf128_t(Structure): + _fields_ = [ + ("hi", c_uint64), + ("lo", c_uint64) + ] + + +class Ghash(Structure): + _fields_ = [ + ("H", gf128_t), + ("X", gf128_t), + ("aadlen", c_size_t), + ("clen", c_size_t), + ("block", c_uint8 * 16), + ("num", c_size_t) + ] + + +SM4_GCM_MIN_IV_SIZE = 1 +SM4_GCM_MAX_IV_SIZE = 64 +SM4_GCM_DEFAULT_IV_SIZE = 12 +SM4_GCM_DEFAULT_TAG_SIZE = 16 +SM4_GCM_MAX_TAG_SIZE = 16 + +class Sm4Gcm(Structure): + + _fields_ = [ + ("sm4_ctr_ctx", Sm4Ctr), + ("mac_ctx", Ghash), + ("Y", c_uint8 * 16), + ("taglen", c_size_t), + ("mac", c_uint8 * 16), + ("maclen", c_size_t) + ] + + def __init__(self, key, iv, aad, taglen = SM4_GCM_DEFAULT_TAG_SIZE, encrypt = True): + if len(key) != SM4_KEY_SIZE: + raise ValueError('Invalid key length') + if len(iv) < SM4_GCM_MIN_IV_SIZE or len(iv) > SM4_GCM_MAX_IV_SIZE: + raise ValueError('Invalid IV size') + if taglen < 1 or taglen > SM4_GCM_MAX_TAG_SIZE: + raise ValueError('Invalid Tag length') + if encrypt == DO_ENCRYPT: + if gmssl.sm4_gcm_encrypt_init(byref(self), key, c_size_t(len(key)), + iv, c_size_t(len(iv)), aad, c_size_t(len(aad)), + c_size_t(taglen)) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm4_gcm_decrypt_init(byref(self), key, c_size_t(len(key)), + iv, c_size_t(len(iv)), aad, c_size_t(len(aad)), + c_size_t(taglen)) != 1: + raise NativeError('libgmssl inner error') + self._encrypt = encrypt + + def update(self, data): + outbuf = create_string_buffer(len(data) + SM4_BLOCK_SIZE) + outlen = c_size_t() + if self._encrypt == DO_ENCRYPT: + if gmssl.sm4_gcm_encrypt_update(byref(self), data, c_size_t(len(data)), + outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm4_gcm_decrypt_update(byref(self), data, c_size_t(len(data)), + outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[0:outlen.value] + + def finish(self): + outbuf = create_string_buffer(SM4_BLOCK_SIZE + SM4_GCM_MAX_TAG_SIZE) + outlen = c_size_t() + if self._encrypt == DO_ENCRYPT: + if gmssl.sm4_gcm_encrypt_finish(byref(self), outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm4_gcm_decrypt_finish(byref(self), outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[:outlen.value] + + +SM2_DEFAULT_ID = '1234567812345678' + +SM2_MAX_SIGNATURE_SIZE = 72 + +SM2_MIN_PLAINTEXT_SIZE = 1 +SM2_MAX_PLAINTEXT_SIZE = 255 +SM2_MIN_CIPHERTEXT_SIZE = 45 +SM2_MAX_CIPHERTEXT_SIZE = 366 + + +class Sm2Point(Structure): + _fields_ = [ + ("x", c_uint8 * 32), + ("y", c_uint8 * 32) + ] + + +class Sm2Key(Structure): + + _fields_ = [ + ("public_key", Sm2Point), + ("private_key", c_uint8 * 32) + ] + + def __init__(self): + self._has_public_key = False + self._has_private_key = False + + def generate_key(self): + if gmssl.sm2_key_generate(byref(self)) != 1: + raise NativeError('libgmssl inner error') + self._has_public_key = True + self._has_private_key = True + + def has_private_key(self): + return self._has_private_key + + def has_public_key(self): + return self._has_public_key + + def compute_z(self, signer_id = SM2_DEFAULT_ID): + if self._has_public_key == False: + raise TypeError('has no public key') + signer_id = signer_id.encode('utf-8') + z = create_string_buffer(SM3_DIGEST_SIZE) + gmssl.sm2_compute_z(z, byref(self), c_char_p(signer_id), c_size_t(len(signer_id))) + return z.raw + + def export_encrypted_private_key_info_pem(self, path, passwd): + if self._has_private_key == False: + raise TypeError('has no private key') + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + passwd = passwd.encode('utf-8') + if gmssl.sm2_private_key_info_encrypt_to_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + + def import_encrypted_private_key_info_pem(self, path, passwd): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'rb') + passwd = passwd.encode('utf-8') + if gmssl.sm2_private_key_info_decrypt_from_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + self._has_public_key = True + self._has_private_key = True + + def export_public_key_info_pem(self, path): + if self._has_public_key == False: + raise TypeError('has no public key') + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + if gmssl.sm2_public_key_info_to_pem(byref(self), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + + def import_public_key_info_pem(self, path): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'rb') + if gmssl.sm2_public_key_info_from_pem(byref(self), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + self._has_public_key = True + self._has_private_key = False + + def sign(self, dgst): + if self._has_private_key == False: + raise TypeError('has no private key') + if len(dgst) != SM3_DIGEST_SIZE: + raise ValueError('Invalid SM3 digest size') + sig = create_string_buffer(SM2_MAX_SIGNATURE_SIZE) + siglen = c_size_t() + if gmssl.sm2_sign(byref(self), dgst, sig, byref(siglen)) != 1: + raise NativeError('libgmssl inner error') + return sig[:siglen.value] + + def verify(self, dgst, signature): + if self._has_public_key == False: + raise TypeError('has no public key') + if len(dgst) != SM3_DIGEST_SIZE: + raise ValueError('Invalid SM3 digest size') + if gmssl.sm2_verify(byref(self), dgst, signature, c_size_t(len(signature))) != 1: + return False + return True + + def encrypt(self, data): + if self._has_public_key == False: + raise TypeError('has no public key') + if len(data) > SM2_MAX_PLAINTEXT_SIZE: + raise NativeError('libgmssl inner error') + outbuf = create_string_buffer(SM2_MAX_CIPHERTEXT_SIZE) + outlen = c_size_t() + if gmssl.sm2_encrypt(byref(self), data, c_size_t(len(data)), + outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[:outlen.value] + + def decrypt(self, ciphertext): + if self._has_private_key == False: + raise TypeError('has no private key') + outbuf = create_string_buffer(SM2_MAX_PLAINTEXT_SIZE) + outlen = c_size_t() + if gmssl.sm2_decrypt(byref(self), ciphertext, c_size_t(len(ciphertext)) + , outbuf, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return outbuf[:outlen.value] + + +DO_ENCRYPT = True +DO_DECRYPT = False +DO_SIGN = True +DO_VERIFY = False + +class Sm2Signature(Structure): + + _fields_ = [ + ("sm3_ctx", Sm3), + ("key", Sm2Key) + ] + + def __init__(self, sm2_key, signer_id = SM2_DEFAULT_ID, sign = DO_SIGN): + signer_id = signer_id.encode('utf-8') + if sign == DO_SIGN: + if sm2_key.has_private_key() != True: + raise NativeError('libgmssl inner error') + if gmssl.sm2_sign_init(byref(self), byref(sm2_key), + c_char_p(signer_id), c_size_t(len(signer_id))) != 1: + raise NativeError('libgmssl inner error') + else: + if sm2_key.has_public_key() != True: + raise NativeError('libgmssl inner error') + if gmssl.sm2_verify_init(byref(self), byref(sm2_key), + c_char_p(signer_id), c_size_t(len(signer_id))) != 1: + raise NativeError('libgmssl inner error') + self._sign = sign + + def update(self, data): + if self._sign == DO_SIGN: + if gmssl.sm2_sign_update(byref(self), data, c_size_t(len(data))) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm2_verify_update(byref(self), data, c_size_t(len(data))) != 1: + raise NativeError('libgmssl inner error') + + def sign(self): + if self._sign != DO_SIGN: + raise StateError('not sign state') + sig = create_string_buffer(SM2_MAX_SIGNATURE_SIZE) + siglen = c_size_t() + if gmssl.sm2_sign_finish(byref(self), sig, byref(siglen)) != 1: + raise NativeError('libgmssl inner error') + return sig[:siglen.value] + + def verify(self, signature): + if self._sign != DO_VERIFY: + raise StateError('not verify state') + if gmssl.sm2_verify_finish(byref(self), signature, c_size_t(len(signature))) != 1: + return False + return True + + +class sm9_bn_t(Structure): + _fields_ = [ + ("d", c_uint64 * 8) + ] + +class sm9_fp2_t(Structure): + _fields_ = [ + ("d", sm9_bn_t * 2) + ] + +class Sm9Point(Structure): + _fields_ = [ + ("X", sm9_bn_t), + ("Y", sm9_bn_t), + ("Z", sm9_bn_t) + ] + +class Sm9TwistPoint(Structure): + _fields_ = [ + ("X", sm9_fp2_t), + ("Y", sm9_fp2_t), + ("Z", sm9_fp2_t) + ] + + +SM9_MAX_ID_SIZE = 63 +SM9_MAX_PLAINTEXT_SIZE = 255 +SM9_MAX_CIPHERTEXT_SIZE = 367 + +class Sm9EncKey(Structure): + _fields_ = [ + ("Ppube", Sm9Point), + ("de", Sm9TwistPoint) + ] + + def __init__(self, owner_id): + self._id = owner_id.encode('utf-8') + self._has_private_key = False + + def get_id(self): + return self._id; + + def has_private_key(self): + return self._has_private_key + + def import_encrypted_private_key_info_pem(self, path, passwd): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'rb') + passwd = passwd.encode('utf-8') + if gmssl.sm9_enc_key_info_decrypt_from_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + self._has_private_key = True + + def export_encrypted_private_key_info_pem(self, path, passwd): + if self._has_private_key != True: + raise TypeError('has no private key') + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + passwd = passwd.encode('utf-8') + if gmssl.sm9_enc_key_info_encrypt_to_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + + def decrypt(self, ciphertext): + if self._has_private_key != True: + raise TypeError('has no private key') + plaintext = create_string_buffer(SM9_MAX_PLAINTEXT_SIZE) + outlen = c_size_t() + if gmssl.sm9_decrypt(byref(self), c_char_p(self._id), c_size_t(len(self._id)), + ciphertext, c_size_t(len(ciphertext)), plaintext, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return plaintext[0:outlen.value] + + +class Sm9EncMasterKey(Structure): + _fields_ = [ + ("Ppube", Sm9Point), + ("ke", sm9_bn_t) + ] + + def __init__(self): + self._has_public_key = False + self._has_private_key = False + + def generate_master_key(self): + if gmssl.sm9_enc_master_key_generate(byref(self)) != 1: + raise NativeError('libgmssl inner error') + self._has_public_key = True + self._has_private_key = True + + def extract_key(self, identity): + if self._has_private_key != True: + raise TypeError('has no master key') + key = Sm9EncKey(identity) + identity = identity.encode('utf-8') + if gmssl.sm9_enc_master_key_extract_key(byref(self), + c_char_p(identity), c_size_t(len(identity)), byref(key)) != 1: + raise NativeError('libgmssl inner error') + key._has_public_key = True + key._has_private_key = True + return key + + def import_encrypted_master_key_info_pem(self, path, passwd): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'rb') + passwd = passwd.encode('utf-8') + if gmssl.sm9_enc_master_key_info_decrypt_from_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + self._has_public_key = True + self._has_private_key = True + + def export_encrypted_master_key_info_pem(self, path, passwd): + if self._has_private_key != True: + raise TypeError('has no master key') + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + passwd = passwd.encode('utf-8') + if gmssl.sm9_enc_master_key_info_encrypt_to_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + + def export_public_master_key_pem(self, path): + if self._has_public_key != True: + raise TypeError('has no public master key') + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + if gmssl.sm9_enc_master_public_key_to_pem(byref(self), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + + def import_public_master_key_pem(self, path): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'rb') + if gmssl.sm9_enc_master_public_key_from_pem(byref(self), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + self._has_public_key = True + self._has_private_key = False + + def encrypt(self, plaintext, to): + if self._has_public_key != True: + raise TypeError('has no public master key') + to = to.encode('utf-8') + ciphertext = create_string_buffer(SM9_MAX_CIPHERTEXT_SIZE) + outlen = c_size_t() + if gmssl.sm9_encrypt(byref(self), c_char_p(to), c_size_t(len(to)), + plaintext, c_size_t(len(plaintext)), ciphertext, byref(outlen)) != 1: + raise NativeError('libgmssl inner error') + return ciphertext[0:outlen.value] + + +class Sm9SignKey(Structure): + _fields_ = [ + ("Ppubs", Sm9TwistPoint), + ("ds", Sm9Point) + ] + + def __init__(self, owner_id): + self._id = owner_id.encode('utf-8') + self._has_private_key = False + + def get_id(self): + return self._id; + + def has_private_key(self): + return self._has_private_key + + def import_encrypted_private_key_info_pem(self, path, passwd): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'rb') + passwd = passwd.encode('utf-8') + if gmssl.sm9_sign_key_info_decrypt_from_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + self._has_private_key = True + + def export_encrypted_private_key_info_pem(self, path, passwd): + if self._has_private_key == False: + raise TypeError('has no master key') + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + passwd = passwd.encode('utf-8') + if gmssl.sm9_sign_key_info_encrypt_to_pem(byref(self), c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + + +class Sm9SignMasterKey(Structure): + _fields_ = [ + ("Ppubs", Sm9TwistPoint), + ("ks", sm9_bn_t) + ] + + def __init__(self): + self._has_public_key = False + self._has_private_key = False + + def generate_master_key(self): + if gmssl.sm9_sign_master_key_generate(byref(self)) != 1: + raise NativeError('libgmssl inner error') + self._has_public_key = True + self._has_private_key = True + + def extract_key(self, identity): + if self._has_private_key != True: + raise TypeError('has no master key') + key = Sm9SignKey(identity) + identity = identity.encode('utf-8') + if gmssl.sm9_sign_master_key_extract_key(byref(self), + c_char_p(identity), c_size_t(len(identity)), byref(key)) != 1: + raise NativeError('libgmssl inner error') + key._has_public_key = True + key._has_private_key = True + return key + + def import_encrypted_master_key_info_pem(self, path, passwd): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'rb') + passwd = passwd.encode('utf-8') + if gmssl.sm9_sign_master_key_info_decrypt_from_pem(byref(self), + c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + self._has_public_key = True + self._has_private_key = True + + def export_encrypted_master_key_info_pem(self, path, passwd): + if self._has_private_key != True: + raise TypeError('has no master key') + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + passwd = passwd.encode('utf-8') + if gmssl.sm9_sign_master_key_info_encrypt_to_pem(byref(self), + c_char_p(passwd), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + + def export_public_master_key_pem(self, path): + if self._has_public_key != True: + raise TypeError('has no public master key') + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + if gmssl.sm9_sign_master_public_key_to_pem(byref(self), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + + def import_public_master_key_pem(self, path): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'rb') + if gmssl.sm9_sign_master_public_key_from_pem(byref(self), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + libc.fclose(c_void_p(fp)) + self._has_public_key = True + self._has_private_key = False + + +SM9_SIGNATURE_SIZE = 104 + +class Sm9Signature(Structure): + + _fields_ = [ + ("sm3", Sm3) + ] + + def __init__(self, sign = DO_SIGN): + if sign == DO_SIGN: + if gmssl.sm9_sign_init(byref(self)) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm9_verify_init(byref(self)) != 1: + raise NativeError('libgmssl inner error') + self._sign = sign + self._inited = True + + + def reset(self): + if self._inited != True: + raise StateError('not initialized') + + if self._sign == DO_SIGN: + if gmssl.sm9_sign_init(byref(self)) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm9_verify_init(byref(self)) != 1: + raise NativeError('libgmssl inner error') + + def update(self, data): + + if self._inited != True: + raise StateError('not initialized') + + if self._sign == DO_SIGN: + if gmssl.sm9_sign_update(byref(self), data, c_size_t(len(data))) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.sm9_verify_update(byref(self), data, c_size_t(len(data))) != 1: + raise NativeError('libgmssl inner error') + + + def sign(self, sign_key): + if self._inited != True: + raise StateError('not initialized') + if self._sign != DO_SIGN: + raise StateError('not sign state') + + sig = create_string_buffer(SM9_SIGNATURE_SIZE) + siglen = c_size_t() + if gmssl.sm9_sign_finish(byref(self), byref(sign_key), sig, byref(siglen)) != 1: + raise NativeError('libgmssl inner error') + return sig[:siglen.value] + + def verify(self, signature, public_master_key, signer_id): + if self._inited != True: + raise StateError('not initialized') + if self._sign != DO_VERIFY: + raise StateError('not verify state') + + signer_id = signer_id.encode('utf-8') + + if gmssl.sm9_verify_finish(byref(self), signature, c_size_t(len(signature)), + byref(public_master_key), c_char_p(signer_id), c_size_t(len(signer_id))) != 1: + return False + return True + + + +_ASN1_TAG_IA5String = 22 +_ASN1_TAG_SEQUENCE = 0x30 +_ASN1_TAG_SET = 0x31 + + + +def gmssl_parse_attr_type_and_value(name, d, dlen): + oid = c_int() + tag = c_int() + val = c_void_p() + vlen = c_size_t() + + if gmssl.x509_name_type_from_der(byref(oid), byref(d), byref(dlen)) != 1: + raise NativeError('libgmssl inner error') + gmssl.x509_name_type_name.restype = c_char_p + oid_name = gmssl.x509_name_type_name(oid).decode('ascii') + + if oid_name == 'emailAddress': + if gmssl.asn1_ia5_string_from_der_ex(_ASN1_TAG_IA5String, byref(val), byref(vlen), byref(d), byref(dlen)) != 1: + raise NativeError('libgmssl inner error') + else: + if gmssl.x509_directory_name_from_der(byref(tag), byref(val), byref(vlen), byref(d), byref(dlen)) != 1: + raise NativeError('libgmssl inner error') + + if dlen.value != 0: + raise ValueError('invalid der encoding') + + value = create_string_buffer(vlen.value) + libc.memcpy(value, val, vlen) + + name[oid_name] = value.raw.decode('utf-8') + return True + +def gmssl_parse_rdn(name, d, dlen): + v = c_void_p() + vlen = c_size_t() + + while dlen.value > 0: + if gmssl.asn1_type_from_der(_ASN1_TAG_SEQUENCE, byref(v), byref(vlen), byref(d), byref(dlen)) != 1: + raise NativeError('libgmssl inner error') + + if gmssl_parse_attr_type_and_value(name, v, vlen) != 1: + raise NativeError('libgmssl inner error') + + return True + +# https://stacktuts.com/how-to-correctly-pass-pointer-to-pointer-into-dll-in-python-and-ctypes# +def gmssl_parse_name(name, d, dlen): + v = c_void_p() + vlen = c_size_t() + + while dlen.value > 0: + if gmssl.asn1_nonempty_type_from_der(c_int(_ASN1_TAG_SET), byref(v), byref(vlen), byref(d), byref(dlen)) != 1: + raise NativeError('libgmssl inner error') + gmssl_parse_rdn(name, v, vlen) + return True + + +class Validity: + + def __init__(self, not_before, not_after): + self.not_before = datetime.datetime.fromtimestamp(not_before) + self.not_after = datetime.datetime.fromtimestamp(not_after) + + +class Sm2Certificate: + + def import_pem(self, path): + + cert = c_void_p() + certlen = c_size_t() + if gmssl.x509_cert_new_from_file(byref(cert), byref(certlen), path.encode('utf-8')) != 1: + raise NativeError('libgmssl inner error') + + self._cert = create_string_buffer(certlen.value) + libc.memcpy(self._cert, cert, certlen) + libc.free(cert) + + def get_raw(self): + return self._cert; + + def export_pem(self, path): + libc.fopen.restype = c_void_p + fp = libc.fopen(path.encode('utf-8'), 'wb') + if gmssl.x509_cert_to_pem(self._cert, c_size_t(len(self._cert)), c_void_p(fp)) != 1: + raise NativeError('libgmssl inner error') + + def get_serial_number(self): + + serial_ptr = c_void_p() + serial_len = c_size_t() + + if gmssl.x509_cert_get_issuer_and_serial_number(self._cert, c_size_t(len(self._cert)), + None, None, byref(serial_ptr), byref(serial_len)) != 1: + raise NativeError('libgmssl inner error') + + serial = create_string_buffer(serial_len.value) + libc.memcpy(serial, serial_ptr, serial_len) + return serial.raw + + def get_issuer(self): + issuer_ptr = c_void_p() + issuer_len = c_size_t() + if gmssl.x509_cert_get_issuer(self._cert, c_size_t(len(self._cert)), + byref(issuer_ptr), byref(issuer_len)) != 1: + raise NativeError('libgmssl inner error') + issuer_raw = create_string_buffer(issuer_len.value) + libc.memcpy(issuer_raw, issuer_ptr, issuer_len) + + issuer = { "raw_data" : issuer_raw.raw } + gmssl_parse_name(issuer, issuer_ptr, issuer_len) + return issuer + + def get_subject(self): + subject_ptr = c_void_p() + subject_len = c_size_t() + if gmssl.x509_cert_get_subject(self._cert, c_size_t(len(self._cert)), + byref(subject_ptr), byref(subject_len)) != 1: + raise NativeError('libgmssl inner error') + subject_raw = create_string_buffer(subject_len.value) + libc.memcpy(subject_raw, subject_ptr, subject_len) + + subject = { "raw_data" : subject_raw.raw } + gmssl_parse_name(subject, subject_ptr, subject_len) + return subject + + def get_subject_public_key(self): + public_key = Sm2Key() + gmssl.x509_cert_get_subject_public_key(self._cert, c_size_t(len(self._cert)), byref(public_key)) + public_key._has_private_key = False + public_key._has_public_key = True + return public_key + + def get_validity(self): + not_before = c_ulong() + not_after = c_ulong() + if gmssl.x509_cert_get_details(self._cert, c_size_t(len(self._cert)), + None, None, None, None, None, None, + byref(not_before), byref(not_after), + None, None, None, None, None, None, None, None, None, None, None, None) != 1: + raise NativeError('libgmssl inner error') + return Validity(not_before.value, not_after.value) + + def verify_by_ca_certificate(self, cacert, sm2_id): + + cacert_raw = cacert.get_raw() + sm2_id = sm2_id.encode('utf-8') + + if gmssl.x509_cert_verify_by_ca_cert(self._cert, c_size_t(len(self._cert)), + cacert_raw, c_size_t(len(cacert_raw)), c_char_p(sm2_id), c_size_t(len(sm2_id))) != 1: + return False + return True + diff --git a/apps/i18n/core/en/LC_MESSAGES/django.po b/apps/i18n/core/en/LC_MESSAGES/django.po index 902521979..d685b8712 100644 --- a/apps/i18n/core/en/LC_MESSAGES/django.po +++ b/apps/i18n/core/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-04-21 17:03+0800\n" +"POT-Creation-Date: 2026-05-25 14:02+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -28,7 +28,7 @@ msgstr "" msgid "No valid assets found for account creation." msgstr "" -#: accounts/api/account/application.py:77 +#: accounts/api/account/application.py:87 #: authentication/api/connection_token.py:463 msgid "Account not found" msgstr "" @@ -42,15 +42,15 @@ msgstr "" msgid "The account key will be split into two parts and sent" msgstr "" -#: accounts/automations/backup_account/handlers.py:131 +#: accounts/automations/backup_account/handlers.py:132 msgid "Number of backup accounts" msgstr "" -#: accounts/automations/backup_account/handlers.py:152 +#: accounts/automations/backup_account/handlers.py:153 msgid "Generating asset related backup information files" msgstr "" -#: accounts/automations/backup_account/handlers.py:177 +#: accounts/automations/backup_account/handlers.py:178 #: accounts/automations/backup_account/manager.py:26 #: accounts/automations/change_secret/manager.py:81 #: accounts/automations/push_account/manager.py:62 @@ -61,31 +61,31 @@ msgstr "" msgid "Duration" msgstr "" -#: accounts/automations/backup_account/handlers.py:178 +#: accounts/automations/backup_account/handlers.py:179 msgid "Backup file creation completed" msgstr "" -#: accounts/automations/backup_account/handlers.py:186 +#: accounts/automations/backup_account/handlers.py:187 msgid "Start sending backup emails" msgstr "" -#: accounts/automations/backup_account/handlers.py:213 +#: accounts/automations/backup_account/handlers.py:214 msgid "Encrypting files using encryption password" msgstr "" -#: accounts/automations/backup_account/handlers.py:223 +#: accounts/automations/backup_account/handlers.py:224 msgid "The backup file will be sent to" msgstr "" -#: accounts/automations/backup_account/handlers.py:246 +#: accounts/automations/backup_account/handlers.py:247 msgid "The backup task has no assigned sftp server" msgstr "" -#: accounts/automations/backup_account/handlers.py:267 +#: accounts/automations/backup_account/handlers.py:268 msgid "The backup task has no assigned recipient" msgstr "" -#: accounts/automations/backup_account/handlers.py:290 +#: accounts/automations/backup_account/handlers.py:291 msgid "Plan start" msgstr "" @@ -149,7 +149,7 @@ msgstr "" #: settings/serializers/auth/ldap.py:53 settings/serializers/auth/ldap_ha.py:35 #: settings/serializers/msg.py:37 settings/serializers/terminal.py:32 #: terminal/serializers/storage.py:123 terminal/serializers/storage.py:142 -#: users/forms/profile.py:22 users/serializers/user.py:148 +#: users/forms/profile.py:22 users/serializers/user.py:153 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/cloud/serializers/account_attrs.py:43 @@ -223,7 +223,7 @@ msgstr "" #: accounts/const/account.py:34 accounts/const/automation.py:115 #: accounts/serializers/automations/change_secret.py:171 audits/const.py:66 -#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:66 +#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:67 #: ops/const.py:77 terminal/const.py:81 xpack/plugins/cloud/const.py:55 msgid "Failed" msgstr "" @@ -345,14 +345,14 @@ msgstr "" #: accounts/const/automation.py:116 #: accounts/serializers/automations/change_secret.py:170 audits/const.py:65 #: audits/models.py:65 audits/signal_handlers/activity_log.py:34 -#: common/const/choices.py:65 ops/const.py:75 ops/serializers/celery.py:48 +#: common/const/choices.py:66 ops/const.py:75 ops/serializers/celery.py:48 #: terminal/const.py:80 terminal/models/session/sharing.py:119 #: tickets/views/approve.py:128 msgid "Success" msgstr "Success" -#: accounts/const/automation.py:117 common/const/choices.py:63 -#: common/const/choices.py:114 terminal/const.py:79 +#: accounts/const/automation.py:117 common/const/choices.py:64 +#: common/const/choices.py:127 terminal/const.py:79 msgid "Pending" msgstr "" @@ -360,7 +360,7 @@ msgstr "" msgid "Queued" msgstr "" -#: accounts/const/automation.py:122 common/const/choices.py:62 +#: accounts/const/automation.py:122 common/const/choices.py:63 msgid "Ready" msgstr "" @@ -372,7 +372,7 @@ msgstr "" msgid "Can login" msgstr "" -#: accounts/const/automation.py:128 users/serializers/user.py:254 +#: accounts/const/automation.py:128 users/serializers/user.py:259 msgid "Superuser" msgstr "" @@ -401,7 +401,7 @@ msgid "Default tablespace" msgstr "" #: accounts/const/automation.py:135 rbac/models/role.py:46 -#: rbac/models/rolebinding.py:52 users/models/user/__init__.py:79 +#: rbac/models/rolebinding.py:53 users/models/user/__init__.py:79 msgid "Role" msgstr "" @@ -410,7 +410,7 @@ msgid "Perms" msgstr "" #: accounts/const/automation.py:137 perms/serializers/permission.py:56 -#: users/serializers/user.py:245 +#: users/serializers/user.py:250 msgid "Groups" msgstr "" @@ -783,7 +783,7 @@ msgstr "" #: assets/models/automations/base.py:137 #: assets/serializers/automations/base.py:47 audits/models.py:224 #: audits/reporting.py:607 audits/serializers.py:77 ops/models/base.py:49 -#: ops/models/job.py:233 terminal/models/applet/applet.py:382 +#: ops/models/job.py:233 terminal/models/applet/applet.py:390 #: terminal/models/applet/host.py:140 terminal/models/component/status.py:30 #: terminal/models/virtualapp/virtualapp.py:99 #: terminal/serializers/applet.py:19 terminal/serializers/applet_host.py:163 @@ -798,7 +798,7 @@ msgstr "" #: accounts/serializers/account/account.py:297 assets/const/automation.py:9 #: authentication/templates/authentication/passkey.html:177 #: authentication/views/base.py:43 authentication/views/base.py:44 -#: authentication/views/base.py:45 common/const/choices.py:67 +#: authentication/views/base.py:45 common/const/choices.py:68 #: settings/templates/ldap/_msg_import_ldap_user.html:26 msgid "Error" msgstr "" @@ -893,8 +893,9 @@ msgstr "" #: accounts/templates/accounts/push_account_report.html:79 #: accounts/templates/accounts/push_account_report.html:119 #: acls/serializers/base.py:19 acls/serializers/base.py:50 audits/models.py:204 -#: audits/reporting.py:241 authentication/forms.py:21 -#: authentication/forms.py:23 authentication/models/temp_token.py:10 +#: audits/reporting.py:241 authentication/backends/cert/forms.py:7 +#: authentication/forms.py:21 authentication/forms.py:23 +#: authentication/models/temp_token.py:10 #: authentication/serializers/connect_token_secret.py:43 #: authentication/serializers/connect_token_secret.py:53 #: authentication/templates/authentication/_msg_different_city.html:9 @@ -1048,7 +1049,7 @@ msgstr "" #: assets/models/cmd_filter.py:39 assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:129 reports/models.py:18 #: terminal/models/applet/applet.py:41 -#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:257 +#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:262 msgid "Is active" msgstr "Active" @@ -1064,7 +1065,7 @@ msgstr "" msgid "Push params" msgstr "" -#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:403 +#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:404 msgid "Account template" msgstr "" @@ -1148,7 +1149,7 @@ msgstr "" msgid "Change secret or push account failed information" msgstr "" -#: accounts/risk_handlers.py:17 common/const/choices.py:116 +#: accounts/risk_handlers.py:17 common/const/choices.py:129 msgid "Ignored" msgstr "" @@ -1304,7 +1305,7 @@ msgstr "" #: authentication/notifications.py:16 authentication/notifications.py:55 #: notifications/models/notification.py:12 #: perms/api/user_permission/mixin.py:58 perms/models/asset_permission.py:63 -#: rbac/builtin.py:134 rbac/models/rolebinding.py:49 +#: rbac/builtin.py:134 rbac/models/rolebinding.py:50 #: rbac/serializers/rolebinding.py:17 terminal/backends/command/models.py:16 #: terminal/models/session/session.py:27 terminal/models/session/sharing.py:34 #: terminal/notifications.py:168 terminal/notifications.py:235 @@ -1312,8 +1313,8 @@ msgstr "" #: terminal/templates/terminal/_msg_command_warning.html:9 #: terminal/templates/terminal/_msg_session_sharing.html:6 #: tickets/models/comment.py:21 tickets/serializers/flow.py:15 -#: users/const.py:14 users/models/user/__init__.py:298 -#: users/models/user/__init__.py:325 +#: users/const.py:14 users/models/user/__init__.py:303 +#: users/models/user/__init__.py:330 msgid "User" msgstr "" @@ -1346,7 +1347,7 @@ msgstr "" #: assets/models/cmd_filter.py:88 common/db/models.py:36 ops/models/adhoc.py:25 #: ops/models/job.py:165 ops/models/playbook.py:31 rbac/models/role.py:37 #: settings/models.py:43 terminal/models/applet/applet.py:46 -#: terminal/models/applet/applet.py:383 terminal/models/applet/host.py:143 +#: terminal/models/applet/applet.py:391 terminal/models/applet/host.py:143 #: terminal/models/component/endpoint.py:29 #: terminal/models/component/endpoint.py:117 #: terminal/models/session/session.py:44 @@ -1605,7 +1606,7 @@ msgid "" " Account storage - Record limit" msgstr "" -#: accounts/tasks/remove_account.py:89 +#: accounts/tasks/remove_account.py:91 msgid "Remove historical accounts that are out of range." msgstr "" @@ -1672,7 +1673,7 @@ msgstr "" #: accounts/templates/accounts/push_account_report.html:22 #: assets/models/automations/base.py:143 audits/models.py:66 #: ops/models/base.py:55 ops/models/celery.py:89 ops/models/job.py:241 -#: ops/templates/ops/celery_task_log.html:101 +#: ops/templates/ops/celery_task_log.html:154 #: perms/models/asset_permission.py:78 settings/serializers/feature.py:29 #: settings/templates/ldap/_msg_import_ldap_user.html:5 #: terminal/models/applet/host.py:141 terminal/models/session/session.py:42 @@ -1856,7 +1857,7 @@ msgstr "" #: acls/models/base.py:81 perms/serializers/permission.py:54 #: tickets/models/flow.py:23 users/models/preference.py:16 -#: users/serializers/group.py:21 users/serializers/user.py:424 +#: users/serializers/group.py:21 users/serializers/user.py:429 msgid "Users" msgstr "" @@ -1882,7 +1883,7 @@ msgid "Command" msgstr "" #: acls/models/command_acl.py:17 assets/models/cmd_filter.py:59 -#: xpack/plugins/cloud/models.py:369 +#: xpack/plugins/cloud/models.py:370 msgid "Regex" msgstr "" @@ -1971,7 +1972,7 @@ msgstr "" msgid "Login acl" msgstr "" -#: acls/models/login_acl.py:27 tickets/const.py:11 +#: acls/models/login_acl.py:30 tickets/const.py:11 msgid "Login confirm" msgstr "" @@ -2089,7 +2090,7 @@ msgstr "" #: authentication/templates/authentication/_msg_oauth_bind.html:12 #: authentication/templates/authentication/_msg_rest_password_success.html:8 #: authentication/templates/authentication/_msg_rest_public_key_success.html:8 -#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:405 +#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:406 msgid "IP" msgstr "" @@ -2148,15 +2149,15 @@ msgstr "" msgid "User details" msgstr "" -#: assets/api/asset/asset.py:166 +#: assets/api/asset/asset.py:168 msgid "Cannot create asset directly, you should create a host or other" msgstr "" -#: assets/api/asset/asset.py:173 +#: assets/api/asset/asset.py:175 msgid "The number of assets exceeds the limit of 5000" msgstr "" -#: assets/api/asset/asset.py:179 +#: assets/api/asset/asset.py:181 msgid "The number of assets exceeds the license limit" msgstr "" @@ -2173,6 +2174,11 @@ msgstr "" msgid "Deletion failed and the node contains assets" msgstr "" +#: assets/api/node.py:99 +#, python-brace-format +msgid "Node {} is an ancestor of node {}, can't be added as its child" +msgstr "" + #: assets/api/tree.py:48 assets/serializers/node.py:42 msgid "The same level node name cannot be the same" msgstr "" @@ -2190,29 +2196,29 @@ msgstr "Assets" msgid "Task: {} finished" msgstr "" -#: assets/automations/base/manager.py:340 +#: assets/automations/base/manager.py:341 #, python-brace-format msgid " - Platform {} ansible disabled" msgstr "" -#: assets/automations/base/manager.py:555 +#: assets/automations/base/manager.py:556 msgid ">>> Task preparation phase" msgstr "" -#: assets/automations/base/manager.py:559 +#: assets/automations/base/manager.py:560 #, python-brace-format msgid ">>> Executing tasks in batches, total {runner_count}" msgstr "" -#: assets/automations/base/manager.py:564 +#: assets/automations/base/manager.py:565 msgid ">>> Start executing tasks" msgstr "" -#: assets/automations/base/manager.py:566 +#: assets/automations/base/manager.py:567 msgid ">>> No tasks need to be executed" msgstr "" -#: assets/automations/base/manager.py:570 +#: assets/automations/base/manager.py:571 #, python-brace-format msgid ">>> Begin executing batch {index} of tasks" msgstr "" @@ -2602,7 +2608,7 @@ msgid "Port" msgstr "" #: assets/models/asset/common.py:167 assets/serializers/asset/common.py:175 -#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:59 +#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:69 msgid "Address" msgstr "" @@ -2610,12 +2616,12 @@ msgstr "" #: assets/serializers/asset/common.py:151 #: authentication/backends/passkey/models.py:12 #: authentication/serializers/connect_token_secret.py:130 -#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:399 +#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:400 msgid "Platform" msgstr "" #: assets/models/asset/common.py:173 assets/models/zone.py:22 -#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:401 +#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:402 msgid "Zone" msgstr "" @@ -2684,9 +2690,9 @@ msgid "Proxy" msgstr "" #: assets/models/automations/base.py:23 assets/models/cmd_filter.py:32 -#: assets/models/node.py:553 ops/models/job.py:158 +#: assets/models/node.py:560 ops/models/job.py:158 #: perms/models/asset_permission.py:72 tickets/models/ticket/apply_asset.py:15 -#: xpack/plugins/cloud/models.py:400 +#: xpack/plugins/cloud/models.py:401 msgid "Node" msgstr "" @@ -2710,7 +2716,7 @@ msgstr "" #: assets/models/automations/base.py:140 assets/models/cmd_filter.py:41 #: authentication/serializers/token.py:134 common/db/models.py:34 #: ops/models/base.py:54 ops/models/job.py:240 -#: users/models/user/__init__.py:328 +#: users/models/user/__init__.py:333 msgid "Date created" msgstr "" @@ -2799,7 +2805,7 @@ msgstr "" msgid "System" msgstr "" -#: assets/models/label.py:19 assets/models/node.py:539 +#: assets/models/label.py:19 assets/models/node.py:546 #: assets/serializers/cagegory.py:11 assets/serializers/cagegory.py:18 #: assets/serializers/cagegory.py:24 #: authentication/models/connection_token.py:35 @@ -2814,7 +2820,7 @@ msgstr "" #: assets/serializers/platform.py:160 #: authentication/serializers/connect_token_secret.py:136 #: common/serializers/common.py:85 labels/serializers.py:45 -#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:404 +#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:405 msgid "Label" msgstr "" @@ -2830,27 +2836,27 @@ msgstr "" msgid "My assets" msgstr "" -#: assets/models/node.py:168 +#: assets/models/node.py:172 msgid "New node" msgstr "" -#: assets/models/node.py:467 audits/backends/db.py:85 audits/backends/db.py:86 +#: assets/models/node.py:474 audits/backends/db.py:85 audits/backends/db.py:86 msgid "empty" msgstr "" -#: assets/models/node.py:538 perms/models/perm_node.py:28 +#: assets/models/node.py:545 perms/models/perm_node.py:28 msgid "Key" msgstr "" -#: assets/models/node.py:540 assets/serializers/node.py:20 +#: assets/models/node.py:547 assets/serializers/node.py:20 msgid "Full value" msgstr "" -#: assets/models/node.py:544 perms/models/perm_node.py:30 +#: assets/models/node.py:551 perms/models/perm_node.py:30 msgid "Parent key" msgstr "" -#: assets/models/node.py:556 +#: assets/models/node.py:563 msgid "Can match node" msgstr "" @@ -3024,7 +3030,7 @@ msgstr "" #: authentication/serializers/connect_token_secret.py:30 #: authentication/serializers/connect_token_secret.py:77 #: perms/models/asset_permission.py:76 perms/serializers/permission.py:68 -#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:402 +#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:403 #: xpack/plugins/cloud/serializers/task.py:36 msgid "Protocols" msgstr "" @@ -3436,7 +3442,7 @@ msgid "Symlink" msgstr "" #: audits/const.py:18 audits/const.py:29 -#: ops/templates/ops/celery_task_log.html:86 +#: ops/templates/ops/celery_task_log.html:139 #: terminal/api/session/session.py:159 msgid "Download" msgstr "" @@ -3465,7 +3471,9 @@ msgstr "" msgid "Connect" msgstr "" -#: audits/const.py:31 authentication/templates/authentication/login.html:334 +#: audits/const.py:31 +#: authentication/templates/authentication/cert_login.html:232 +#: authentication/templates/authentication/login.html:334 #: authentication/templates/authentication/login.html:408 #: templates/_header_bar.html:101 #: xpack/plugins/interface/templates/login_i18n.html:21 @@ -4170,24 +4178,24 @@ msgstr "" msgid "Current user not support mfa type: {}" msgstr "" -#: authentication/api/password.py:34 terminal/api/session/session.py:347 +#: authentication/api/password.py:37 terminal/api/session/session.py:347 #: users/views/profile/reset.py:63 #, python-brace-format msgid "User does not exist: {}" msgstr "" -#: authentication/api/password.py:34 users/views/profile/reset.py:166 +#: authentication/api/password.py:37 users/views/profile/reset.py:166 msgid "No user matched" msgstr "" -#: authentication/api/password.py:38 +#: authentication/api/password.py:41 #, python-brace-format msgid "" "The user is from {}, please go to the corresponding system to change the " "password" msgstr "" -#: authentication/api/password.py:69 +#: authentication/api/password.py:72 #: authentication/templates/authentication/login.html:400 #: users/templates/users/forgot_password.html:41 #: users/templates/users/forgot_password.html:42 @@ -4197,7 +4205,7 @@ msgstr "" msgid "Forgot password" msgstr "" -#: authentication/api/password.py:70 authentication/mfa/email.py:42 +#: authentication/api/password.py:73 authentication/mfa/email.py:42 #, python-brace-format msgid "The validity period of the verification code is {} minute" msgstr "" @@ -4210,9 +4218,20 @@ msgstr "Authentication" msgid "CAS Error" msgstr "" -#: authentication/backends/custom.py:60 -#: authentication/backends/oauth2/backends.py:158 -msgid "User invalid, disabled or expired" +#: authentication/backends/cert/api.py:57 +msgid "Certificate enrollment is not enabled" +msgstr "" + +#: authentication/backends/cert/api.py:62 +msgid "CSR is required" +msgstr "" + +#: authentication/backends/cert/api.py:68 +msgid "Certificate signing failed" +msgstr "" + +#: authentication/backends/cert/views.py:97 +msgid "Invalid credentials" msgstr "" #: authentication/backends/drf.py:61 @@ -4455,16 +4474,16 @@ msgstr "" msgid "Please wait for %s seconds before retry" msgstr "" -#: authentication/errors/redirect.py:85 authentication/mixins.py:436 +#: authentication/errors/redirect.py:85 authentication/mixins.py:445 #: users/views/profile/reset.py:224 msgid "Your password is too simple, please change it for security" msgstr "" -#: authentication/errors/redirect.py:93 authentication/mixins.py:445 +#: authentication/errors/redirect.py:93 authentication/mixins.py:454 msgid "You should to change your password before login" msgstr "" -#: authentication/errors/redirect.py:101 authentication/mixins.py:454 +#: authentication/errors/redirect.py:101 authentication/mixins.py:463 msgid "Your password has expired, please reset before logging in" msgstr "" @@ -4589,11 +4608,11 @@ msgid "" "contact the administrator." msgstr "" -#: authentication/mixins.py:184 +#: authentication/mixins.py:187 msgid "User is invalid" msgstr "" -#: authentication/mixins.py:201 +#: authentication/mixins.py:204 #, python-brace-format msgid "" " The administrator has enabled 'Only allow login from user source'. \n" @@ -4601,12 +4620,12 @@ msgid "" "administrator. " msgstr "" -#: authentication/mixins.py:382 +#: authentication/mixins.py:391 #, python-brace-format msgid "The MFA type ({}) is not enabled" msgstr "" -#: authentication/mixins.py:424 +#: authentication/mixins.py:433 msgid "Please change your password" msgstr "" @@ -4798,7 +4817,7 @@ msgstr "" #: authentication/serializers/connection_token.py:46 #: perms/serializers/permission.py:66 perms/serializers/permission.py:87 -#: users/serializers/user.py:127 users/serializers/user.py:261 +#: users/serializers/user.py:127 users/serializers/user.py:266 msgid "Is expired" msgstr "Expired" @@ -4838,13 +4857,13 @@ msgstr "" #: authentication/serializers/token.py:93 perms/serializers/permission.py:65 #: perms/serializers/permission.py:88 users/serializers/user.py:128 -#: users/serializers/user.py:258 +#: users/serializers/user.py:263 msgid "Is valid" msgstr "Is Valid" #: authentication/serializers/token.py:131 ops/models/adhoc.py:26 #: ops/models/playbook.py:34 ops/serializers/mixin.py:10 rbac/models/role.py:31 -#: rbac/models/rolebinding.py:46 rbac/serializers/role.py:12 +#: rbac/models/rolebinding.py:47 rbac/serializers/role.py:12 #: settings/serializers/auth/oauth2.py:37 msgid "Scope" msgstr "" @@ -4936,7 +4955,7 @@ msgstr "" #: authentication/templates/authentication/_msg_oauth_bind.html:3 #: authentication/templates/authentication/_msg_reset_password.html:3 #: authentication/templates/authentication/_msg_reset_password_code.html:9 -#: jumpserver/conf.py:555 +#: jumpserver/conf.py:558 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:32 #: users/templates/users/_msg_account_expire_reminder.html:4 @@ -5032,6 +5051,73 @@ msgstr "" msgid "Cancel" msgstr "" +#: authentication/templates/authentication/cert_login.html:190 +#, fuzzy +#| msgid "App Authentication" +msgid "Certificate Authentication" +msgstr "Authentication" + +#: authentication/templates/authentication/cert_login.html:195 +#: authentication/templates/authentication/cert_login.html:250 +msgid "Loading USB Key driver..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:210 +msgid "Insert USB Key to auto-fetch" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:238 +msgid "Other login methods" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:251 +msgid "Detecting USB Key..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:252 +msgid "USB Key connected" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:253 +msgid "Please insert USB Key" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:254 +msgid "Driver unavailable" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:255 +msgid "USB Key SDK initialization failed" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:256 +msgid "Verifying PIN..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:257 +msgid "PIN verified" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:258 +msgid "PIN verification failed" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:259 +msgid "Signing challenge code..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:260 +msgid "Signing failed" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:261 +msgid "Failed to retrieve certificate" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:262 +msgid "No certificate detected, please contact administrator" +msgstr "" + #: authentication/templates/authentication/face_capture.html:14 msgid "Retry" msgstr "" @@ -5099,6 +5185,10 @@ msgstr "" msgid "LAN" msgstr "" +#: authentication/utils.py:150 +msgid "CERT" +msgstr "" + #: authentication/views/base.py:71 #: perms/templates/perms/_msg_permed_items_expire.html:18 msgid "If you have any question, please contact the administrator" @@ -5258,47 +5348,47 @@ msgstr "" msgid "Request file format may be wrong" msgstr "" -#: common/const/choices.py:40 +#: common/const/choices.py:41 msgid "China" msgstr "" -#: common/const/choices.py:57 +#: common/const/choices.py:58 msgid "Manual" msgstr "" -#: common/const/choices.py:58 +#: common/const/choices.py:59 msgid "Timing" msgstr "" -#: common/const/choices.py:64 ops/const.py:74 +#: common/const/choices.py:65 ops/const.py:74 msgid "Running" msgstr "" -#: common/const/choices.py:68 +#: common/const/choices.py:69 msgid "Canceled" msgstr "" -#: common/const/choices.py:115 +#: common/const/choices.py:128 msgid "Confirmed" msgstr "" -#: common/const/choices.py:123 terminal/models/applet/applet.py:31 +#: common/const/choices.py:136 terminal/models/applet/applet.py:31 msgid "Community edition" msgstr "" -#: common/const/choices.py:124 +#: common/const/choices.py:137 msgid "Basic edition" msgstr "" -#: common/const/choices.py:125 +#: common/const/choices.py:138 msgid "Standard edition" msgstr "" -#: common/const/choices.py:126 +#: common/const/choices.py:139 msgid "Professional edition" msgstr "" -#: common/const/choices.py:127 +#: common/const/choices.py:140 msgid "Ultimate edition" msgstr "" @@ -5776,24 +5866,24 @@ msgstr "" msgid "The message code provided is invalid or has expired" msgstr "" -#: jumpserver/conf.py:549 +#: jumpserver/conf.py:552 #, python-brace-format msgid "The verification code is: {code}" msgstr "" -#: jumpserver/conf.py:554 +#: jumpserver/conf.py:557 msgid "Create account successfully" msgstr "" -#: jumpserver/conf.py:556 +#: jumpserver/conf.py:559 msgid "Your account has been created successfully" msgstr "" -#: jumpserver/context_processor.py:17 +#: jumpserver/context_processor.py:16 msgid "JumpServer - An open-source PAM" msgstr "JumpServer" -#: jumpserver/context_processor.py:37 +#: jumpserver/context_processor.py:31 msgid "FIT2CLOUD" msgstr "" @@ -6477,7 +6567,7 @@ msgid "Please save in a org" msgstr "" #: orgs/mixins/models.py:58 orgs/mixins/serializers.py:25 orgs/models.py:91 -#: rbac/const.py:7 rbac/models/rolebinding.py:56 +#: rbac/const.py:7 rbac/models/rolebinding.py:57 #: rbac/serializers/rolebinding.py:44 settings/serializers/auth/base.py:53 #: terminal/notifications.py:309 #: terminal/templates/terminal/_msg_command_warning.html:27 @@ -6868,25 +6958,25 @@ msgstr "" msgid "Organization role" msgstr "" -#: rbac/models/rolebinding.py:62 +#: rbac/models/rolebinding.py:63 msgid "Role binding" msgstr "" -#: rbac/models/rolebinding.py:168 +#: rbac/models/rolebinding.py:169 msgid "All organizations" msgstr "" -#: rbac/models/rolebinding.py:200 +#: rbac/models/rolebinding.py:201 msgid "" "User last role in org, can not be delete, you can remove user from org " "instead" msgstr "" -#: rbac/models/rolebinding.py:207 +#: rbac/models/rolebinding.py:208 msgid "Organization role binding" msgstr "" -#: rbac/models/rolebinding.py:222 +#: rbac/models/rolebinding.py:223 msgid "System role binding" msgstr "" @@ -6951,7 +7041,7 @@ msgid "Storage" msgstr "" #: rbac/tree.py:64 terminal/models/applet/applet.py:53 -#: terminal/models/applet/applet.py:379 terminal/models/applet/host.py:30 +#: terminal/models/applet/applet.py:387 terminal/models/applet/host.py:30 #: terminal/serializers/applet.py:16 msgid "Applet" msgstr "" @@ -7010,51 +7100,51 @@ msgstr "Access key id" msgid "Range days" msgstr "" -#: reports/views.py:20 +#: reports/views.py:19 msgid "User login report" msgstr "" -#: reports/views.py:24 +#: reports/views.py:23 msgid "User change password report" msgstr "" -#: reports/views.py:28 +#: reports/views.py:27 msgid "Asset statistics report" msgstr "" -#: reports/views.py:32 +#: reports/views.py:31 msgid "Asset activity report" msgstr "" -#: reports/views.py:36 +#: reports/views.py:35 msgid "Account statistics report" msgstr "" -#: reports/views.py:40 +#: reports/views.py:39 msgid "Account automation report" msgstr "" -#: reports/views.py:44 +#: reports/views.py:43 msgid "ConsoleDashboard" msgstr "" -#: reports/views.py:48 +#: reports/views.py:47 msgid "AuditsDashboard" msgstr "" -#: reports/views.py:52 +#: reports/views.py:51 msgid "PamDashboard" msgstr "" -#: reports/views.py:56 +#: reports/views.py:55 msgid "ChangeSecretDashboard" msgstr "" -#: reports/views.py:191 +#: reports/views.py:190 msgid "Failed to send email: " msgstr "" -#: reports/views.py:192 +#: reports/views.py:191 msgid "Email sent successfully to " msgstr "" @@ -7326,14 +7416,14 @@ msgstr "" #: settings/serializers/auth/dingtalk.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the DingTalk service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the DingTalk service user attribute name" msgstr "" #: settings/serializers/auth/feishu.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the FeiShu service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the FeiShu service user attribute name" msgstr "" #: settings/serializers/auth/lark.py:13 users/models/user/_source.py:24 @@ -7342,8 +7432,8 @@ msgstr "" #: settings/serializers/auth/lark.py:19 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Lark service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Lark service user attribute name" msgstr "" #: settings/serializers/auth/ldap.py:42 settings/serializers/auth/ldap.py:108 @@ -7387,8 +7477,8 @@ msgstr "" #: settings/serializers/auth/ldap.py:69 settings/serializers/auth/ldap_ha.py:51 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the LDAP service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the LDAP service user attribute name" msgstr "" #: settings/serializers/auth/ldap.py:85 settings/serializers/auth/ldap_ha.py:67 @@ -7486,8 +7576,8 @@ msgstr "" #: settings/serializers/auth/oauth2.py:62 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OAuth2 service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OAuth2 service user attribute name" msgstr "" #: settings/serializers/auth/oauth2.py:67 settings/serializers/auth/oidc.py:117 @@ -7521,8 +7611,8 @@ msgstr "" #: settings/serializers/auth/oidc.py:41 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OIDC service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OIDC service user attribute name" msgstr "" #: settings/serializers/auth/oidc.py:45 @@ -7655,8 +7745,8 @@ msgstr "" #: settings/serializers/auth/slack.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Slack service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Slack service user attribute name" msgstr "" #: settings/serializers/auth/sms.py:18 @@ -7691,7 +7781,7 @@ msgid "Template code" msgstr "" #: settings/serializers/auth/sms.py:40 users/models/user/__init__.py:89 -#: users/serializers/user.py:159 +#: users/serializers/user.py:164 msgid "Phone" msgstr "" @@ -7745,7 +7835,7 @@ msgid "Enable SSO auth" msgstr "" #: settings/serializers/auth/sso.py:17 -msgid "Other service can using SSO token login to JumpServer without password" +msgid "Other service can using SSO token login to system without password" msgstr "" #: settings/serializers/auth/sso.py:20 @@ -7759,8 +7849,8 @@ msgstr "" #: settings/serializers/auth/wecom.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the WeCom service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the WeCom service user attribute name" msgstr "" #: settings/serializers/basic.py:11 @@ -8806,7 +8896,7 @@ msgstr "" msgid "The verification code has been sent" msgstr "" -#: templates/_without_nav_base.html:46 +#: templates/_without_nav_base.html:51 msgid "Home page" msgstr "Home" @@ -9067,31 +9157,31 @@ msgstr "" msgid "Hosts" msgstr "" -#: terminal/models/applet/applet.py:94 +#: terminal/models/applet/applet.py:102 #: terminal/models/virtualapp/virtualapp.py:66 #, python-brace-format msgid "Applet pkg not valid, Missing file {}" msgstr "" -#: terminal/models/applet/applet.py:113 +#: terminal/models/applet/applet.py:121 #, python-brace-format msgid "Load platform.yml failed: {}" msgstr "" -#: terminal/models/applet/applet.py:116 +#: terminal/models/applet/applet.py:124 msgid "Only support custom platform" msgstr "" -#: terminal/models/applet/applet.py:121 +#: terminal/models/applet/applet.py:129 msgid "Missing type in platform.yml" msgstr "" -#: terminal/models/applet/applet.py:381 terminal/models/applet/host.py:36 +#: terminal/models/applet/applet.py:389 terminal/models/applet/host.py:36 #: terminal/models/applet/host.py:138 msgid "Hosting" msgstr "" -#: terminal/models/applet/applet.py:387 +#: terminal/models/applet/applet.py:395 msgid "Applet Publication" msgstr "" @@ -9181,7 +9271,7 @@ msgstr "" #: terminal/models/component/endpoint.py:35 #: terminal/models/component/endpoint.py:115 -#: terminal/serializers/endpoint.py:63 terminal/serializers/storage.py:41 +#: 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" @@ -9395,8 +9485,8 @@ msgstr "Storage" #: terminal/notifications.py:279 terminal/tasks.py:212 #: xpack/plugins/cloud/api.py:182 -#: xpack/plugins/cloud/serializers/account.py:143 -#: xpack/plugins/cloud/serializers/account.py:146 +#: xpack/plugins/cloud/serializers/account.py:148 +#: xpack/plugins/cloud/serializers/account.py:151 msgid "Test failure: Account invalid" msgstr "" @@ -9499,7 +9589,8 @@ msgstr "" msgid "" "If not exist, the RDS will be in trial mode, and the trial period is 120 " "days. Detail" +"remote-desktop-services/rds-client-access-license\" " +"target=\"_blank\">Detail" msgstr "" #: terminal/serializers/applet_host.py:55 @@ -9606,20 +9697,20 @@ msgstr "" msgid "Timestamp" msgstr "" -#: terminal/serializers/endpoint.py:27 +#: terminal/serializers/endpoint.py:28 msgid "" "The host address accessed when connecting to assets, if it is empty, the " "access address of the current browser will be used (the default endpoint " "does not allow modification of the host)" msgstr "" -#: terminal/serializers/endpoint.py:54 +#: terminal/serializers/endpoint.py:64 msgid "" "The assets within this IP range or Host, the following endpoint will be used " "for the connection" msgstr "" -#: terminal/serializers/endpoint.py:55 +#: terminal/serializers/endpoint.py:65 msgid "" "If asset IP addresses under different endpoints conflict, use asset labels" msgstr "" @@ -9753,7 +9844,7 @@ msgstr "Is alive" msgid "Stat" msgstr "" -#: terminal/serializers/terminal.py:83 terminal/serializers/terminal.py:91 +#: terminal/serializers/terminal.py:79 terminal/serializers/terminal.py:87 msgid "Not found" msgstr "" @@ -10315,7 +10406,7 @@ msgstr "" msgid "Approval Step Distribution" msgstr "" -#: tickets/serializers/flow.py:45 +#: tickets/serializers/flow.py:42 msgid "The current organization type already exists" msgstr "" @@ -10376,7 +10467,7 @@ msgid "Ticket information" msgstr "" #: tickets/templates/tickets/approve_check_password.html:28 -#: tickets/views/approve.py:43 tickets/views/approve.py:80 +#: tickets/views/approve.py:42 tickets/views/approve.py:80 msgid "Ticket approval" msgstr "" @@ -10384,12 +10475,12 @@ msgstr "" msgid "Approval" msgstr "" -#: tickets/views/approve.py:44 +#: tickets/views/approve.py:43 msgid "" "This ticket does not exist, the process has ended, or this link has expired" msgstr "" -#: tickets/views/approve.py:72 +#: tickets/views/approve.py:71 msgid "Click the button below to approve or reject" msgstr "" @@ -10593,7 +10684,7 @@ msgstr "" msgid "Email lookup" msgstr "" -#: users/models/user/__init__.py:82 users/serializers/user.py:259 +#: users/models/user/__init__.py:82 users/serializers/user.py:264 msgid "Is service account" msgstr "Is service account" @@ -10610,7 +10701,7 @@ msgid "OTP secret key" msgstr "" #: users/models/user/__init__.py:105 users/serializers/profile.py:86 -#: users/serializers/user.py:256 +#: users/serializers/user.py:261 msgid "Is first login" msgstr "First login" @@ -10630,23 +10721,23 @@ msgstr "" msgid "Date api key used" msgstr "" -#: users/models/user/__init__.py:293 +#: users/models/user/__init__.py:298 msgid "Can not delete admin user" msgstr "" -#: users/models/user/__init__.py:307 +#: users/models/user/__init__.py:312 msgid "Can invite user" msgstr "" -#: users/models/user/__init__.py:308 +#: users/models/user/__init__.py:313 msgid "Can remove user" msgstr "" -#: users/models/user/__init__.py:309 +#: users/models/user/__init__.py:314 msgid "Can match user" msgstr "" -#: users/models/user/__init__.py:338 +#: users/models/user/__init__.py:343 msgid "User password history" msgstr "" @@ -10654,6 +10745,10 @@ msgstr "" msgid "Force enabled" msgstr "" +#: users/models/user/_source.py:27 +msgid "Certificate" +msgstr "" + #: users/notifications.py:23 users/notifications.py:68 msgid "Reset password url" msgstr "" @@ -10763,7 +10858,7 @@ msgstr "" msgid "Connect default open method" msgstr "" -#: users/serializers/preference/luna.py:34 xpack/plugins/interface/models.py:42 +#: users/serializers/preference/luna.py:34 xpack/plugins/interface/models.py:44 #: xpack/plugins/interface/serializers/interface.py:35 msgid "Theme" msgstr "" @@ -10872,7 +10967,7 @@ msgstr "" msgid "Login blocked" msgstr "" -#: users/serializers/user.py:130 users/serializers/user.py:265 +#: users/serializers/user.py:130 users/serializers/user.py:270 msgid "Is OTP bound" msgstr "OTP bound" @@ -10888,59 +10983,65 @@ msgstr "" msgid "Can public key authentication" msgstr "Can public key authentication" -#: users/serializers/user.py:144 +#: users/serializers/user.py:145 +#, fuzzy +#| msgid "Can public key authentication" +msgid "Can certificate authentication" +msgstr "Can public key authentication" + +#: users/serializers/user.py:149 msgid "Is face code set" msgstr "" -#: users/serializers/user.py:230 +#: users/serializers/user.py:235 msgid "Full name" msgstr "" -#: users/serializers/user.py:233 +#: users/serializers/user.py:238 msgid "Login username" msgstr "" -#: users/serializers/user.py:236 +#: users/serializers/user.py:241 msgid "Email address" msgstr "" -#: users/serializers/user.py:246 +#: users/serializers/user.py:251 msgid "User groups to join" msgstr "" -#: users/serializers/user.py:250 +#: users/serializers/user.py:255 msgid "" "User source identifies where the user was created, which could be AD or " "other sources.There are security settings that can restrict users to log in " "to the system only from the sources." msgstr "" -#: users/serializers/user.py:260 +#: users/serializers/user.py:265 msgid "Is org admin" msgstr "Org admin" -#: users/serializers/user.py:262 +#: users/serializers/user.py:267 msgid "Avatar url" msgstr "" -#: users/serializers/user.py:267 +#: users/serializers/user.py:272 msgid "MFA level" msgstr "MFA" -#: users/serializers/user.py:268 +#: users/serializers/user.py:273 msgid "Multi-Factor Authentication" msgstr "" -#: users/serializers/user.py:398 +#: users/serializers/user.py:403 msgid "Has public keys" msgstr "" -#: users/serializers/user.py:426 +#: users/serializers/user.py:431 msgid "" "* For security, only a partial of users is displayed. You can search for more" msgstr "" -#: users/serializers/user.py:462 +#: users/serializers/user.py:467 msgid "name not unique" msgstr "" @@ -11411,7 +11512,7 @@ msgstr "" msgid "Public IP" msgstr "" -#: xpack/plugins/cloud/const.py:50 xpack/plugins/cloud/models.py:373 +#: xpack/plugins/cloud/const.py:50 xpack/plugins/cloud/models.py:374 msgid "Instance name" msgstr "" @@ -11610,8 +11711,8 @@ msgstr "" msgid "Date last sync" msgstr "" -#: xpack/plugins/cloud/models.py:135 xpack/plugins/cloud/models.py:391 -#: xpack/plugins/cloud/models.py:418 +#: xpack/plugins/cloud/models.py:135 xpack/plugins/cloud/models.py:392 +#: xpack/plugins/cloud/models.py:419 msgid "Strategy" msgstr "" @@ -11651,71 +11752,71 @@ msgstr "" msgid "Task strategy" msgstr "" -#: xpack/plugins/cloud/models.py:362 +#: xpack/plugins/cloud/models.py:363 msgid "Equal" msgstr "" -#: xpack/plugins/cloud/models.py:363 +#: xpack/plugins/cloud/models.py:364 msgid "Not Equal" msgstr "" -#: xpack/plugins/cloud/models.py:364 +#: xpack/plugins/cloud/models.py:365 msgid "In" msgstr "" -#: xpack/plugins/cloud/models.py:365 +#: xpack/plugins/cloud/models.py:366 msgid "Contains" msgstr "" -#: xpack/plugins/cloud/models.py:366 +#: xpack/plugins/cloud/models.py:367 msgid "Exclude" msgstr "" -#: xpack/plugins/cloud/models.py:367 +#: xpack/plugins/cloud/models.py:368 msgid "Startswith" msgstr "" -#: xpack/plugins/cloud/models.py:368 +#: xpack/plugins/cloud/models.py:369 msgid "Endswith" msgstr "" -#: xpack/plugins/cloud/models.py:374 +#: xpack/plugins/cloud/models.py:375 msgid "Instance platform" msgstr "" -#: xpack/plugins/cloud/models.py:375 +#: xpack/plugins/cloud/models.py:376 msgid "Instance address" msgstr "" -#: xpack/plugins/cloud/models.py:382 +#: xpack/plugins/cloud/models.py:383 msgid "Rule attr" msgstr "" -#: xpack/plugins/cloud/models.py:386 +#: xpack/plugins/cloud/models.py:387 msgid "Rule match" msgstr "" -#: xpack/plugins/cloud/models.py:388 +#: xpack/plugins/cloud/models.py:389 msgid "Rule value" msgstr "" -#: xpack/plugins/cloud/models.py:395 xpack/plugins/cloud/serializers/task.py:82 +#: xpack/plugins/cloud/models.py:396 xpack/plugins/cloud/serializers/task.py:82 msgid "Strategy rule" msgstr "" -#: xpack/plugins/cloud/models.py:406 +#: xpack/plugins/cloud/models.py:407 msgid "Name strategy" msgstr "" -#: xpack/plugins/cloud/models.py:413 +#: xpack/plugins/cloud/models.py:414 msgid "Action attr" msgstr "" -#: xpack/plugins/cloud/models.py:415 +#: xpack/plugins/cloud/models.py:416 msgid "Action value" msgstr "" -#: xpack/plugins/cloud/models.py:422 xpack/plugins/cloud/serializers/task.py:85 +#: xpack/plugins/cloud/models.py:423 xpack/plugins/cloud/serializers/task.py:85 msgid "Strategy action" msgstr "" @@ -12066,38 +12167,38 @@ msgstr "" msgid "Restore default successfully." msgstr "" -#: xpack/plugins/interface/meta.py:9 xpack/plugins/interface/models.py:47 -#: xpack/plugins/interface/models.py:91 +#: xpack/plugins/interface/meta.py:9 xpack/plugins/interface/models.py:49 +#: xpack/plugins/interface/models.py:104 msgid "Interface settings" msgstr "" -#: xpack/plugins/interface/models.py:24 +#: xpack/plugins/interface/models.py:26 msgid "Login title" msgstr "" -#: xpack/plugins/interface/models.py:28 +#: xpack/plugins/interface/models.py:30 msgid "Login image" msgstr "" -#: xpack/plugins/interface/models.py:32 +#: xpack/plugins/interface/models.py:34 msgid "Website icon" msgstr "" -#: xpack/plugins/interface/models.py:36 +#: xpack/plugins/interface/models.py:38 msgid "Index logo" msgstr "" -#: xpack/plugins/interface/models.py:40 +#: xpack/plugins/interface/models.py:42 msgid "Logout logo" msgstr "" -#: xpack/plugins/interface/models.py:43 +#: xpack/plugins/interface/models.py:45 msgid "Footer content" msgstr "" -#: xpack/plugins/interface/models.py:44 +#: xpack/plugins/interface/models.py:46 #: xpack/plugins/interface/serializers/interface.py:73 -msgid "Extended fields" +msgid "Extend" msgstr "" #: xpack/plugins/interface/serializers/interface.py:48 @@ -12140,7 +12241,7 @@ msgstr "" #: xpack/plugins/interface/templates/login_i18n.html:22 msgid "More login methods" -msgstr "Or" +msgstr "" #: xpack/plugins/jdmc/i18n.py:4 msgid "AuditAdmin" diff --git a/apps/i18n/core/es/LC_MESSAGES/django.po b/apps/i18n/core/es/LC_MESSAGES/django.po index e40f01150..7daa979f2 100644 --- a/apps/i18n/core/es/LC_MESSAGES/django.po +++ b/apps/i18n/core/es/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-04-21 17:03+0800\n" +"POT-Creation-Date: 2026-05-25 14:02+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -28,7 +28,7 @@ msgstr "La cuenta ya existe" msgid "No valid assets found for account creation." msgstr "No se encontraron activos válidos disponibles para crear una cuenta." -#: accounts/api/account/application.py:77 +#: accounts/api/account/application.py:87 #: authentication/api/connection_token.py:463 msgid "Account not found" msgstr "Cuenta no encontrada" @@ -43,15 +43,15 @@ msgid "The account key will be split into two parts and sent" msgstr "" "La clave de la cuenta se enviará en dos partes, la anterior y la posterior" -#: accounts/automations/backup_account/handlers.py:131 +#: accounts/automations/backup_account/handlers.py:132 msgid "Number of backup accounts" msgstr "Cantidad de cuentas de respaldo" -#: accounts/automations/backup_account/handlers.py:152 +#: accounts/automations/backup_account/handlers.py:153 msgid "Generating asset related backup information files" msgstr "Generar archivo de información de respaldo relacionado con activos" -#: accounts/automations/backup_account/handlers.py:177 +#: accounts/automations/backup_account/handlers.py:178 #: accounts/automations/backup_account/manager.py:26 #: accounts/automations/change_secret/manager.py:81 #: accounts/automations/push_account/manager.py:62 @@ -62,31 +62,31 @@ msgstr "Generar archivo de información de respaldo relacionado con activos" msgid "Duration" msgstr "Tiempo transcurrido" -#: accounts/automations/backup_account/handlers.py:178 +#: accounts/automations/backup_account/handlers.py:179 msgid "Backup file creation completed" msgstr "Creación del archivo de respaldo completada" -#: accounts/automations/backup_account/handlers.py:186 +#: accounts/automations/backup_account/handlers.py:187 msgid "Start sending backup emails" msgstr "Comenzando el envío del correo electrónico de respaldo" -#: accounts/automations/backup_account/handlers.py:213 +#: accounts/automations/backup_account/handlers.py:214 msgid "Encrypting files using encryption password" msgstr "Cifrando el archivo con contraseña encriptada" -#: accounts/automations/backup_account/handlers.py:223 +#: accounts/automations/backup_account/handlers.py:224 msgid "The backup file will be sent to" msgstr "El archivo de respaldo será enviado a" -#: accounts/automations/backup_account/handlers.py:246 +#: accounts/automations/backup_account/handlers.py:247 msgid "The backup task has no assigned sftp server" msgstr "Esta tarea de respaldo no tiene servidor SFTP asignado" -#: accounts/automations/backup_account/handlers.py:267 +#: accounts/automations/backup_account/handlers.py:268 msgid "The backup task has no assigned recipient" msgstr "La tarea de respaldo no tiene destinatario especificado" -#: accounts/automations/backup_account/handlers.py:290 +#: accounts/automations/backup_account/handlers.py:291 msgid "Plan start" msgstr "Tarea iniciada" @@ -179,7 +179,7 @@ msgstr "" #: settings/serializers/auth/ldap.py:53 settings/serializers/auth/ldap_ha.py:35 #: settings/serializers/msg.py:37 settings/serializers/terminal.py:32 #: terminal/serializers/storage.py:123 terminal/serializers/storage.py:142 -#: users/forms/profile.py:22 users/serializers/user.py:148 +#: users/forms/profile.py:22 users/serializers/user.py:153 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/cloud/serializers/account_attrs.py:43 @@ -253,7 +253,7 @@ msgstr "Actualizar" #: accounts/const/account.py:34 accounts/const/automation.py:115 #: accounts/serializers/automations/change_secret.py:171 audits/const.py:66 -#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:66 +#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:67 #: ops/const.py:77 terminal/const.py:81 xpack/plugins/cloud/const.py:55 msgid "Failed" msgstr "Fallido" @@ -375,14 +375,14 @@ msgstr "SFTP" #: accounts/const/automation.py:116 #: accounts/serializers/automations/change_secret.py:170 audits/const.py:65 #: audits/models.py:65 audits/signal_handlers/activity_log.py:34 -#: common/const/choices.py:65 ops/const.py:75 ops/serializers/celery.py:48 +#: common/const/choices.py:66 ops/const.py:75 ops/serializers/celery.py:48 #: terminal/const.py:80 terminal/models/session/sharing.py:119 #: tickets/views/approve.py:128 msgid "Success" msgstr "éxito" -#: accounts/const/automation.py:117 common/const/choices.py:63 -#: common/const/choices.py:114 terminal/const.py:79 +#: accounts/const/automation.py:117 common/const/choices.py:64 +#: common/const/choices.py:127 terminal/const.py:79 msgid "Pending" msgstr "pendiente" @@ -390,7 +390,7 @@ msgstr "pendiente" msgid "Queued" msgstr "En cola" -#: accounts/const/automation.py:122 common/const/choices.py:62 +#: accounts/const/automation.py:122 common/const/choices.py:63 msgid "Ready" msgstr "Preparar" @@ -402,7 +402,7 @@ msgstr "En proceso" msgid "Can login" msgstr "se puede iniciar sesión" -#: accounts/const/automation.py:128 users/serializers/user.py:254 +#: accounts/const/automation.py:128 users/serializers/user.py:259 msgid "Superuser" msgstr "superusuario" @@ -431,7 +431,7 @@ msgid "Default tablespace" msgstr "espacio de tablas predeterminado" #: accounts/const/automation.py:135 rbac/models/role.py:46 -#: rbac/models/rolebinding.py:52 users/models/user/__init__.py:79 +#: rbac/models/rolebinding.py:53 users/models/user/__init__.py:79 msgid "Role" msgstr "rol" @@ -440,7 +440,7 @@ msgid "Perms" msgstr "Permisos" #: accounts/const/automation.py:137 perms/serializers/permission.py:56 -#: users/serializers/user.py:245 +#: users/serializers/user.py:250 msgid "Groups" msgstr "Grupo de usuarios" @@ -815,7 +815,7 @@ msgstr "Fecha de finalización" #: assets/models/automations/base.py:137 #: assets/serializers/automations/base.py:47 audits/models.py:224 #: audits/reporting.py:607 audits/serializers.py:77 ops/models/base.py:49 -#: ops/models/job.py:233 terminal/models/applet/applet.py:382 +#: ops/models/job.py:233 terminal/models/applet/applet.py:390 #: terminal/models/applet/host.py:140 terminal/models/component/status.py:30 #: terminal/models/virtualapp/virtualapp.py:99 #: terminal/serializers/applet.py:19 terminal/serializers/applet_host.py:163 @@ -830,7 +830,7 @@ msgstr "Estado" #: accounts/serializers/account/account.py:297 assets/const/automation.py:9 #: authentication/templates/authentication/passkey.html:177 #: authentication/views/base.py:43 authentication/views/base.py:44 -#: authentication/views/base.py:45 common/const/choices.py:67 +#: authentication/views/base.py:45 common/const/choices.py:68 #: settings/templates/ldap/_msg_import_ldap_user.html:26 msgid "Error" msgstr "Error" @@ -925,8 +925,9 @@ msgstr "Contraseña duplicada" #: accounts/templates/accounts/push_account_report.html:79 #: accounts/templates/accounts/push_account_report.html:119 #: acls/serializers/base.py:19 acls/serializers/base.py:50 audits/models.py:204 -#: audits/reporting.py:241 authentication/forms.py:21 -#: authentication/forms.py:23 authentication/models/temp_token.py:10 +#: audits/reporting.py:241 authentication/backends/cert/forms.py:7 +#: authentication/forms.py:21 authentication/forms.py:23 +#: authentication/models/temp_token.py:10 #: authentication/serializers/connect_token_secret.py:43 #: authentication/serializers/connect_token_secret.py:53 #: authentication/templates/authentication/_msg_different_city.html:9 @@ -1086,7 +1087,7 @@ msgstr "cuenta privilegiada." #: assets/models/cmd_filter.py:39 assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:129 reports/models.py:18 #: terminal/models/applet/applet.py:41 -#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:257 +#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:262 msgid "Is active" msgstr "Activación" @@ -1102,7 +1103,7 @@ msgstr "Plataforma" msgid "Push params" msgstr "Parámetros de envío de cuentas" -#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:403 +#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:404 msgid "Account template" msgstr "Plantilla de cuentas" @@ -1203,7 +1204,7 @@ msgid "Change secret or push account failed information" msgstr "" "información sobre fallos en el cambio de contraseña o en la cuenta de envío" -#: accounts/risk_handlers.py:17 common/const/choices.py:116 +#: accounts/risk_handlers.py:17 common/const/choices.py:129 msgid "Ignored" msgstr "Ignorar" @@ -1359,7 +1360,7 @@ msgstr "ID" #: authentication/notifications.py:16 authentication/notifications.py:55 #: notifications/models/notification.py:12 #: perms/api/user_permission/mixin.py:58 perms/models/asset_permission.py:63 -#: rbac/builtin.py:134 rbac/models/rolebinding.py:49 +#: rbac/builtin.py:134 rbac/models/rolebinding.py:50 #: rbac/serializers/rolebinding.py:17 terminal/backends/command/models.py:16 #: terminal/models/session/session.py:27 terminal/models/session/sharing.py:34 #: terminal/notifications.py:168 terminal/notifications.py:235 @@ -1367,8 +1368,8 @@ msgstr "ID" #: terminal/templates/terminal/_msg_command_warning.html:9 #: terminal/templates/terminal/_msg_session_sharing.html:6 #: tickets/models/comment.py:21 tickets/serializers/flow.py:15 -#: users/const.py:14 users/models/user/__init__.py:298 -#: users/models/user/__init__.py:325 +#: users/const.py:14 users/models/user/__init__.py:303 +#: users/models/user/__init__.py:330 msgid "User" msgstr "Usuario" @@ -1403,7 +1404,7 @@ msgstr "Lista blanca de IP" #: assets/models/cmd_filter.py:88 common/db/models.py:36 ops/models/adhoc.py:25 #: ops/models/job.py:165 ops/models/playbook.py:31 rbac/models/role.py:37 #: settings/models.py:43 terminal/models/applet/applet.py:46 -#: terminal/models/applet/applet.py:383 terminal/models/applet/host.py:143 +#: terminal/models/applet/applet.py:391 terminal/models/applet/host.py:143 #: terminal/models/component/endpoint.py:29 #: terminal/models/component/endpoint.py:117 #: terminal/models/session/session.py:44 @@ -1713,7 +1714,7 @@ msgstr "" "límites establecidos en la configuración del almacenamiento de cuentas a las " "2 de la mañana todos los días" -#: accounts/tasks/remove_account.py:89 +#: accounts/tasks/remove_account.py:91 msgid "Remove historical accounts that are out of range." msgstr "Eliminar cuentas históricas que estén fuera de rango." @@ -1798,7 +1799,7 @@ msgstr "Nombre de la tarea" #: accounts/templates/accounts/push_account_report.html:22 #: assets/models/automations/base.py:143 audits/models.py:66 #: ops/models/base.py:55 ops/models/celery.py:89 ops/models/job.py:241 -#: ops/templates/ops/celery_task_log.html:101 +#: ops/templates/ops/celery_task_log.html:154 #: perms/models/asset_permission.py:78 settings/serializers/feature.py:29 #: settings/templates/ldap/_msg_import_ldap_user.html:5 #: terminal/models/applet/host.py:141 terminal/models/session/session.py:42 @@ -1986,7 +1987,7 @@ msgstr "Persona aprobadora" #: acls/models/base.py:81 perms/serializers/permission.py:54 #: tickets/models/flow.py:23 users/models/preference.py:16 -#: users/serializers/group.py:21 users/serializers/user.py:424 +#: users/serializers/group.py:21 users/serializers/user.py:429 msgid "Users" msgstr "Usuario" @@ -2012,7 +2013,7 @@ msgid "Command" msgstr "Comando" #: acls/models/command_acl.py:17 assets/models/cmd_filter.py:59 -#: xpack/plugins/cloud/models.py:369 +#: xpack/plugins/cloud/models.py:370 msgid "Regex" msgstr "Expresión regular" @@ -2101,7 +2102,7 @@ msgstr "Reglas" msgid "Login acl" msgstr "Control de acceso al inicio de sesión" -#: acls/models/login_acl.py:27 tickets/const.py:11 +#: acls/models/login_acl.py:30 tickets/const.py:11 msgid "Login confirm" msgstr "Revisión de inicio de sesión" @@ -2224,7 +2225,7 @@ msgstr "" #: authentication/templates/authentication/_msg_oauth_bind.html:12 #: authentication/templates/authentication/_msg_rest_password_success.html:8 #: authentication/templates/authentication/_msg_rest_public_key_success.html:8 -#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:405 +#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:406 msgid "IP" msgstr "IP" @@ -2291,16 +2292,16 @@ msgstr "" msgid "User details" msgstr "Detalles del usuario" -#: assets/api/asset/asset.py:166 +#: assets/api/asset/asset.py:168 msgid "Cannot create asset directly, you should create a host or other" msgstr "" "No se puede crear activos directamente, debes crear un host u otro activo" -#: assets/api/asset/asset.py:173 +#: assets/api/asset/asset.py:175 msgid "The number of assets exceeds the limit of 5000" msgstr "La cantidad de activos ha superado el límite de 5000" -#: assets/api/asset/asset.py:179 +#: assets/api/asset/asset.py:181 #, fuzzy #| msgid "The number of assets exceeds the limit of 5000" msgid "The number of assets exceeds the license limit" @@ -2319,6 +2320,11 @@ msgstr "No se puede eliminar el nodo raíz ({})" msgid "Deletion failed and the node contains assets" msgstr "Eliminación fallida, el nodo contiene activos" +#: assets/api/node.py:99 +#, python-brace-format +msgid "Node {} is an ancestor of node {}, can't be added as its child" +msgstr "" + #: assets/api/tree.py:48 assets/serializers/node.py:42 msgid "The same level node name cannot be the same" msgstr "Los nombres de los nodos de igual nivel no pueden repetirse" @@ -2336,30 +2342,30 @@ msgstr "Gestión de activos" msgid "Task: {} finished" msgstr "Tarea: {} Completado" -#: assets/automations/base/manager.py:340 +#: assets/automations/base/manager.py:341 #, python-brace-format msgid " - Platform {} ansible disabled" msgstr "" "- Plataforma {} Ansible está deshabilitada, no se pueden ejecutar tareas" -#: assets/automations/base/manager.py:555 +#: assets/automations/base/manager.py:556 msgid ">>> Task preparation phase" msgstr ">>> Etapa de preparación de tareas" -#: assets/automations/base/manager.py:559 +#: assets/automations/base/manager.py:560 #, python-brace-format msgid ">>> Executing tasks in batches, total {runner_count}" msgstr ">>> Ejecución de tareas por fases, un total de {runner_count}" -#: assets/automations/base/manager.py:564 +#: assets/automations/base/manager.py:565 msgid ">>> Start executing tasks" msgstr ">>> Comenzando la ejecución de tareas" -#: assets/automations/base/manager.py:566 +#: assets/automations/base/manager.py:567 msgid ">>> No tasks need to be executed" msgstr ">>> No hay tareas que ejecutar" -#: assets/automations/base/manager.py:570 +#: assets/automations/base/manager.py:571 #, python-brace-format msgid ">>> Begin executing batch {index} of tasks" msgstr ">>> Comenzando a ejecutar el lote de tareas número {index}" @@ -2771,7 +2777,7 @@ msgid "Port" msgstr "Puerto" #: assets/models/asset/common.py:167 assets/serializers/asset/common.py:175 -#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:59 +#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:69 msgid "Address" msgstr "Dirección" @@ -2779,12 +2785,12 @@ msgstr "Dirección" #: assets/serializers/asset/common.py:151 #: authentication/backends/passkey/models.py:12 #: authentication/serializers/connect_token_secret.py:130 -#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:399 +#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:400 msgid "Platform" msgstr "Plataforma" #: assets/models/asset/common.py:173 assets/models/zone.py:22 -#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:401 +#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:402 msgid "Zone" msgstr "Dominio" @@ -2853,9 +2859,9 @@ msgid "Proxy" msgstr "Proxy" #: assets/models/automations/base.py:23 assets/models/cmd_filter.py:32 -#: assets/models/node.py:553 ops/models/job.py:158 +#: assets/models/node.py:560 ops/models/job.py:158 #: perms/models/asset_permission.py:72 tickets/models/ticket/apply_asset.py:15 -#: xpack/plugins/cloud/models.py:400 +#: xpack/plugins/cloud/models.py:401 msgid "Node" msgstr "Nodo" @@ -2879,7 +2885,7 @@ msgstr "Tareas de automatización de activos" #: assets/models/automations/base.py:140 assets/models/cmd_filter.py:41 #: authentication/serializers/token.py:134 common/db/models.py:34 #: ops/models/base.py:54 ops/models/job.py:240 -#: users/models/user/__init__.py:328 +#: users/models/user/__init__.py:333 msgid "Date created" msgstr "Fecha de creación" @@ -2968,7 +2974,7 @@ msgstr "Puerta de enlace" msgid "System" msgstr "Sistema" -#: assets/models/label.py:19 assets/models/node.py:539 +#: assets/models/label.py:19 assets/models/node.py:546 #: assets/serializers/cagegory.py:11 assets/serializers/cagegory.py:18 #: assets/serializers/cagegory.py:24 #: authentication/models/connection_token.py:35 @@ -2983,7 +2989,7 @@ msgstr "Valor" #: assets/serializers/platform.py:160 #: authentication/serializers/connect_token_secret.py:136 #: common/serializers/common.py:85 labels/serializers.py:45 -#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:404 +#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:405 msgid "Label" msgstr "Etiqueta" @@ -2999,27 +3005,27 @@ msgstr "Nota personalizada" msgid "My assets" msgstr "Mis activos" -#: assets/models/node.py:168 +#: assets/models/node.py:172 msgid "New node" msgstr "Nodo nuevo" -#: assets/models/node.py:467 audits/backends/db.py:85 audits/backends/db.py:86 +#: assets/models/node.py:474 audits/backends/db.py:85 audits/backends/db.py:86 msgid "empty" msgstr "Vacío" -#: assets/models/node.py:538 perms/models/perm_node.py:28 +#: assets/models/node.py:545 perms/models/perm_node.py:28 msgid "Key" msgstr "Clave" -#: assets/models/node.py:540 assets/serializers/node.py:20 +#: assets/models/node.py:547 assets/serializers/node.py:20 msgid "Full value" msgstr "Nombre completo" -#: assets/models/node.py:544 perms/models/perm_node.py:30 +#: assets/models/node.py:551 perms/models/perm_node.py:30 msgid "Parent key" msgstr "ssh clave privada" -#: assets/models/node.py:556 +#: assets/models/node.py:563 msgid "Can match node" msgstr "puede coincidir con nodo" @@ -3199,7 +3205,7 @@ msgstr "" #: authentication/serializers/connect_token_secret.py:30 #: authentication/serializers/connect_token_secret.py:77 #: perms/models/asset_permission.py:76 perms/serializers/permission.py:68 -#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:402 +#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:403 #: xpack/plugins/cloud/serializers/task.py:36 msgid "Protocols" msgstr "Grupo de protocolos" @@ -3664,7 +3670,7 @@ msgid "Symlink" msgstr "Establecer enlace simbólico" #: audits/const.py:18 audits/const.py:29 -#: ops/templates/ops/celery_task_log.html:86 +#: ops/templates/ops/celery_task_log.html:139 #: terminal/api/session/session.py:159 msgid "Download" msgstr "Descargar" @@ -3693,7 +3699,9 @@ msgstr "Exportar" msgid "Connect" msgstr "Conectar" -#: audits/const.py:31 authentication/templates/authentication/login.html:334 +#: audits/const.py:31 +#: authentication/templates/authentication/cert_login.html:232 +#: authentication/templates/authentication/login.html:334 #: authentication/templates/authentication/login.html:408 #: templates/_header_bar.html:101 #: xpack/plugins/interface/templates/login_i18n.html:21 @@ -4502,17 +4510,17 @@ msgstr "El emparejamiento facial ha fallado." msgid "Current user not support mfa type: {}" msgstr "El usuario actual no es compatible con el tipo de MFA: {}" -#: authentication/api/password.py:34 terminal/api/session/session.py:347 +#: authentication/api/password.py:37 terminal/api/session/session.py:347 #: users/views/profile/reset.py:63 #, python-brace-format msgid "User does not exist: {}" msgstr "El usuario no existe: {}" -#: authentication/api/password.py:34 users/views/profile/reset.py:166 +#: authentication/api/password.py:37 users/views/profile/reset.py:166 msgid "No user matched" msgstr "No se encontró coincidencia con el usuario" -#: authentication/api/password.py:38 +#: authentication/api/password.py:41 #, python-brace-format msgid "" "The user is from {}, please go to the corresponding system to change the " @@ -4521,7 +4529,7 @@ msgstr "" "El usuario proviene de {} por favor, modifica la contraseña en el sistema " "correspondiente" -#: authentication/api/password.py:69 +#: authentication/api/password.py:72 #: authentication/templates/authentication/login.html:400 #: users/templates/users/forgot_password.html:41 #: users/templates/users/forgot_password.html:42 @@ -4531,7 +4539,7 @@ msgstr "" msgid "Forgot password" msgstr "Olvidé la contraseña" -#: authentication/api/password.py:70 authentication/mfa/email.py:42 +#: authentication/api/password.py:73 authentication/mfa/email.py:42 #, python-brace-format msgid "The validity period of the verification code is {} minute" msgstr "El código de verificación tiene una validez de {} minuto." @@ -4544,10 +4552,29 @@ msgstr "Gestión de autenticación" msgid "CAS Error" msgstr "Error CAS" -#: authentication/backends/custom.py:60 -#: authentication/backends/oauth2/backends.py:158 -msgid "User invalid, disabled or expired" -msgstr "Usuario no válido, ha sido desactivado o ha expirado" +#: authentication/backends/cert/api.py:57 +#, fuzzy +#| msgid "LDAP authentication is not enabled" +msgid "Certificate enrollment is not enabled" +msgstr "La autenticación LDAP no está habilitada" + +#: authentication/backends/cert/api.py:62 +#, fuzzy +#| msgid "type is required" +msgid "CSR is required" +msgstr "Tipo Este campo es obligatorio." + +#: authentication/backends/cert/api.py:68 +#, fuzzy +#| msgid "Authentication failed" +msgid "Certificate signing failed" +msgstr "Autenticación fallida" + +#: authentication/backends/cert/views.py:97 +#, fuzzy +#| msgid "Invalid data" +msgid "Invalid credentials" +msgstr "Datos no válidos" #: authentication/backends/drf.py:61 msgid "Invalid token header. No credentials provided." @@ -4802,18 +4829,18 @@ msgstr "Tu contraseña es inválida" msgid "Please wait for %s seconds before retry" msgstr "Por favor, inténtalo de nuevo en %s segundos" -#: authentication/errors/redirect.py:85 authentication/mixins.py:436 +#: authentication/errors/redirect.py:85 authentication/mixins.py:445 #: users/views/profile/reset.py:224 msgid "Your password is too simple, please change it for security" msgstr "" "Tu contraseña es demasiado simple, por razones de seguridad, modifícala" -#: authentication/errors/redirect.py:93 authentication/mixins.py:445 +#: authentication/errors/redirect.py:93 authentication/mixins.py:454 msgid "You should to change your password before login" msgstr "" "Antes de completar el inicio de sesión, por favor, modifique su contraseña." -#: authentication/errors/redirect.py:101 authentication/mixins.py:454 +#: authentication/errors/redirect.py:101 authentication/mixins.py:463 msgid "Your password has expired, please reset before logging in" msgstr "Su contraseña ha expirado; modifíquela antes de iniciar sesión." @@ -4950,11 +4977,11 @@ msgstr "" "existentes', el usuario actual no está en la lista de usuarios, por favor " "contacta al administrador." -#: authentication/mixins.py:184 +#: authentication/mixins.py:187 msgid "User is invalid" msgstr "Usuario no válido" -#: authentication/mixins.py:201 +#: authentication/mixins.py:204 #, python-brace-format msgid "" " The administrator has enabled 'Only allow login from user source'. \n" @@ -4965,12 +4992,12 @@ msgstr "" "fuente de usuarios', la fuente del usuario actual es {}, por favor contacta " "al administrador." -#: authentication/mixins.py:382 +#: authentication/mixins.py:391 #, python-brace-format msgid "The MFA type ({}) is not enabled" msgstr "El método MFA ({}) no está habilitado" -#: authentication/mixins.py:424 +#: authentication/mixins.py:433 msgid "Please change your password" msgstr "Por favor, modifica la contraseña" @@ -5162,7 +5189,7 @@ msgstr "Action" #: authentication/serializers/connection_token.py:46 #: perms/serializers/permission.py:66 perms/serializers/permission.py:87 -#: users/serializers/user.py:127 users/serializers/user.py:261 +#: users/serializers/user.py:127 users/serializers/user.py:266 msgid "Is expired" msgstr "Expirado" @@ -5204,13 +5231,13 @@ msgstr "Clave SSH no válida" #: authentication/serializers/token.py:93 perms/serializers/permission.py:65 #: perms/serializers/permission.py:88 users/serializers/user.py:128 -#: users/serializers/user.py:258 +#: users/serializers/user.py:263 msgid "Is valid" msgstr "¿Es válida?" #: authentication/serializers/token.py:131 ops/models/adhoc.py:26 #: ops/models/playbook.py:34 ops/serializers/mixin.py:10 rbac/models/role.py:31 -#: rbac/models/rolebinding.py:46 rbac/serializers/role.py:12 +#: rbac/models/rolebinding.py:47 rbac/serializers/role.py:12 #: settings/serializers/auth/oauth2.py:37 msgid "Scope" msgstr "Rango" @@ -5313,7 +5340,7 @@ msgstr "Código de error" #: authentication/templates/authentication/_msg_oauth_bind.html:3 #: authentication/templates/authentication/_msg_reset_password.html:3 #: authentication/templates/authentication/_msg_reset_password_code.html:9 -#: jumpserver/conf.py:555 +#: jumpserver/conf.py:558 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:32 #: users/templates/users/_msg_account_expire_reminder.html:4 @@ -5425,6 +5452,87 @@ msgstr "" msgid "Cancel" msgstr "Cancelar" +#: authentication/templates/authentication/cert_login.html:190 +#, fuzzy +#| msgid "Multi-Factor Authentication" +msgid "Certificate Authentication" +msgstr "Autenticación" + +#: authentication/templates/authentication/cert_login.html:195 +#: authentication/templates/authentication/cert_login.html:250 +msgid "Loading USB Key driver..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:210 +msgid "Insert USB Key to auto-fetch" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:238 +#, fuzzy +#| msgid "More login options" +msgid "Other login methods" +msgstr "Otras formas de iniciar sesión" + +#: authentication/templates/authentication/cert_login.html:251 +msgid "Detecting USB Key..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:252 +msgid "USB Key connected" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:253 +#, fuzzy +#| msgid "Please enter SMS code" +msgid "Please insert USB Key" +msgstr "Introduce el código de verificación por SMS" + +#: authentication/templates/authentication/cert_login.html:254 +#, fuzzy +#| msgid "Account unavailable" +msgid "Driver unavailable" +msgstr "Cuenta no válida" + +#: authentication/templates/authentication/cert_login.html:255 +msgid "USB Key SDK initialization failed" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:256 +msgid "Verifying PIN..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:257 +#, fuzzy +#| msgid "Date verified" +msgid "PIN verified" +msgstr "Fecha de verificación" + +#: authentication/templates/authentication/cert_login.html:258 +#, fuzzy +#| msgid "OTP verification code" +msgid "PIN verification failed" +msgstr "Código de verificación MFA virtual" + +#: authentication/templates/authentication/cert_login.html:259 +msgid "Signing challenge code..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:260 +#, fuzzy +#| msgid "Signing key" +msgid "Signing failed" +msgstr "Firma clave" + +#: authentication/templates/authentication/cert_login.html:261 +msgid "Failed to retrieve certificate" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:262 +#, fuzzy +#| msgid "Your account has expired, please contact the administrator." +msgid "No certificate detected, please contact administrator" +msgstr "Su cuenta ha expirado, por favor contacte al administrador." + #: authentication/templates/authentication/face_capture.html:14 msgid "Retry" msgstr "Reintentar" @@ -5500,6 +5608,10 @@ msgstr "¿Reintentar?" msgid "LAN" msgstr "Red local" +#: authentication/utils.py:150 +msgid "CERT" +msgstr "" + #: authentication/views/base.py:71 #: perms/templates/perms/_msg_permed_items_expire.html:18 msgid "If you have any question, please contact the administrator" @@ -5668,47 +5780,47 @@ msgstr "" msgid "Request file format may be wrong" msgstr "Formato de archivo subido incorrecto o archivo de otro tipo de recurso" -#: common/const/choices.py:40 +#: common/const/choices.py:41 msgid "China" msgstr "China" -#: common/const/choices.py:57 +#: common/const/choices.py:58 msgid "Manual" msgstr "Acción manual" -#: common/const/choices.py:58 +#: common/const/choices.py:59 msgid "Timing" msgstr "Acción programada" -#: common/const/choices.py:64 ops/const.py:74 +#: common/const/choices.py:65 ops/const.py:74 msgid "Running" msgstr "En ejecución" -#: common/const/choices.py:68 +#: common/const/choices.py:69 msgid "Canceled" msgstr "Cancelar" -#: common/const/choices.py:115 +#: common/const/choices.py:128 msgid "Confirmed" msgstr "Confirmar" -#: common/const/choices.py:123 terminal/models/applet/applet.py:31 +#: common/const/choices.py:136 terminal/models/applet/applet.py:31 msgid "Community edition" msgstr "Versión comunitaria" -#: common/const/choices.py:124 +#: common/const/choices.py:137 msgid "Basic edition" msgstr "Versión básica empresarial" -#: common/const/choices.py:125 +#: common/const/choices.py:138 msgid "Standard edition" msgstr "Versión estándar empresarial" -#: common/const/choices.py:126 +#: common/const/choices.py:139 msgid "Professional edition" msgstr "Versión profesional empresarial" -#: common/const/choices.py:127 +#: common/const/choices.py:140 msgid "Ultimate edition" msgstr "Versión insignia empresarial" @@ -6229,24 +6341,24 @@ msgstr "No se encontró el Código" msgid "The message code provided is invalid or has expired" msgstr "El código de mensaje proporcionado es inválido o ha expirado" -#: jumpserver/conf.py:549 +#: jumpserver/conf.py:552 #, python-brace-format msgid "The verification code is: {code}" msgstr "El código de verificación es: {code}" -#: jumpserver/conf.py:554 +#: jumpserver/conf.py:557 msgid "Create account successfully" msgstr "Creación de cuenta exitosa" -#: jumpserver/conf.py:556 +#: jumpserver/conf.py:559 msgid "Your account has been created successfully" msgstr "Tu cuenta ha sido creada con éxito" -#: jumpserver/context_processor.py:17 +#: jumpserver/context_processor.py:16 msgid "JumpServer - An open-source PAM" msgstr "JumpServer, bastión de código abierto." -#: jumpserver/context_processor.py:37 +#: jumpserver/context_processor.py:31 msgid "FIT2CLOUD" msgstr "" @@ -7033,7 +7145,7 @@ msgid "Please save in a org" msgstr "Por favor, seleccione una organización antes de guardar." #: orgs/mixins/models.py:58 orgs/mixins/serializers.py:25 orgs/models.py:91 -#: rbac/const.py:7 rbac/models/rolebinding.py:56 +#: rbac/const.py:7 rbac/models/rolebinding.py:57 #: rbac/serializers/rolebinding.py:44 settings/serializers/auth/base.py:53 #: terminal/notifications.py:309 #: terminal/templates/terminal/_msg_command_warning.html:27 @@ -7461,15 +7573,15 @@ msgstr "Rol del sistema" msgid "Organization role" msgstr "Rol de la organización" -#: rbac/models/rolebinding.py:62 +#: rbac/models/rolebinding.py:63 msgid "Role binding" msgstr "Vinculación de roles" -#: rbac/models/rolebinding.py:168 +#: rbac/models/rolebinding.py:169 msgid "All organizations" msgstr "Todas las organizaciones" -#: rbac/models/rolebinding.py:200 +#: rbac/models/rolebinding.py:201 msgid "" "User last role in org, can not be delete, you can remove user from org " "instead" @@ -7477,11 +7589,11 @@ msgstr "" "El último rol del usuario no se puede eliminar, pero puedes quitar al " "usuario de la organización" -#: rbac/models/rolebinding.py:207 +#: rbac/models/rolebinding.py:208 msgid "Organization role binding" msgstr "Rol de organización vinculado" -#: rbac/models/rolebinding.py:222 +#: rbac/models/rolebinding.py:223 msgid "System role binding" msgstr "Rol del sistema vinculado" @@ -7546,7 +7658,7 @@ msgid "Storage" msgstr "Almacenamiento" #: rbac/tree.py:64 terminal/models/applet/applet.py:53 -#: terminal/models/applet/applet.py:379 terminal/models/applet/host.py:30 +#: terminal/models/applet/applet.py:387 terminal/models/applet/host.py:30 #: terminal/serializers/applet.py:16 msgid "Applet" msgstr "Aplicación remota" @@ -7609,51 +7721,51 @@ msgstr "Revocar token de acceso" msgid "Range days" msgstr "Modificador" -#: reports/views.py:20 +#: reports/views.py:19 msgid "User login report" msgstr "Informe de inicio de sesión de usuarios" -#: reports/views.py:24 +#: reports/views.py:23 msgid "User change password report" msgstr "Informe de cambio de contraseña de usuarios" -#: reports/views.py:28 +#: reports/views.py:27 msgid "Asset statistics report" msgstr "Informe de estadísticas de activos" -#: reports/views.py:32 +#: reports/views.py:31 msgid "Asset activity report" msgstr "Informe de actividades de activos" -#: reports/views.py:36 +#: reports/views.py:35 msgid "Account statistics report" msgstr "Informe de estadísticas de cuentas" -#: reports/views.py:40 +#: reports/views.py:39 msgid "Account automation report" msgstr "Informe de automatización de cuentas" -#: reports/views.py:44 +#: reports/views.py:43 msgid "ConsoleDashboard" msgstr "Tablero de consola" -#: reports/views.py:48 +#: reports/views.py:47 msgid "AuditsDashboard" msgstr "Tablero de auditoría" -#: reports/views.py:52 +#: reports/views.py:51 msgid "PamDashboard" msgstr "Tablero PAM" -#: reports/views.py:56 +#: reports/views.py:55 msgid "ChangeSecretDashboard" msgstr "Tablero de cambio de contraseña de cuenta" -#: reports/views.py:191 +#: reports/views.py:190 msgid "Failed to send email: " msgstr "Error al enviar el correo electrónico" -#: reports/views.py:192 +#: reports/views.py:191 msgid "Email sent successfully to " msgstr "Envío de correo electrónico exitoso" @@ -7962,8 +8074,8 @@ msgstr "Habilitar autenticación de DingTalk" #: settings/serializers/auth/dingtalk.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the DingTalk service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the DingTalk service user attribute name" msgstr "" "Mapeo de atributos de usuario, donde `key` es el nombre del atributo de " "usuario del sistema, y `value` es el nombre del atributo de usuario del " @@ -7971,8 +8083,8 @@ msgstr "" #: settings/serializers/auth/feishu.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the FeiShu service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the FeiShu service user attribute name" msgstr "" "Mapeo de atributos de usuario, donde `key` es el nombre del atributo de " "usuario del sistema, y `value` es el nombre del atributo de usuario del " @@ -7984,8 +8096,8 @@ msgstr "Lark" #: settings/serializers/auth/lark.py:19 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Lark service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Lark service user attribute name" msgstr "" "Mapeo de atributos de usuario, donde `key` es el nombre del atributo de " "usuario del sistema y `value` es el nombre del atributo de usuario del " @@ -8055,8 +8167,8 @@ msgstr "Las posibles opciones son (cn o uid o sAMAccountName=%(user)s)" #: settings/serializers/auth/ldap.py:69 settings/serializers/auth/ldap_ha.py:51 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the LDAP service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the LDAP service user attribute name" msgstr "" "Mapeo de atributos de usuario, donde `key` es el nombre del atributo del " "usuario del sistema, y `value` es el nombre del atributo del usuario en el " @@ -8169,8 +8281,8 @@ msgstr "" #: settings/serializers/auth/oauth2.py:62 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OAuth2 service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OAuth2 service user attribute name" msgstr "" "Mapeo de atributos del usuario, donde `key` es el nombre del atributo de " "usuario del sistema y `value` es el nombre del atributo de usuario del " @@ -8208,8 +8320,8 @@ msgstr "Ignorar la verificación del certificado SSL" #: settings/serializers/auth/oidc.py:41 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OIDC service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OIDC service user attribute name" msgstr "" "Mapeo de atributos de usuario, donde `key` es el nombre del atributo de " "usuario del sistema y `value` es el nombre del atributo de usuario del " @@ -8359,8 +8471,8 @@ msgstr "Al salir, los usuarios también se desconectarán del servidor SAML2" #: settings/serializers/auth/slack.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Slack service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Slack service user attribute name" msgstr "" "Mapeo de atributos de usuario, donde `key` es el nombre del atributo de " "usuario del sistema y `value` es el nombre del atributo de usuario del " @@ -8398,7 +8510,7 @@ msgid "Template code" msgstr "Plantilla" #: settings/serializers/auth/sms.py:40 users/models/user/__init__.py:89 -#: users/serializers/user.py:159 +#: users/serializers/user.py:164 msgid "Phone" msgstr "Teléfono móvil" @@ -8456,7 +8568,10 @@ msgid "Enable SSO auth" msgstr "Habilitar autenticación con token SSO" #: settings/serializers/auth/sso.py:17 -msgid "Other service can using SSO token login to JumpServer without password" +#, fuzzy +#| msgid "" +#| "Other service can using SSO token login to JumpServer without password" +msgid "Other service can using SSO token login to system without password" msgstr "" "Otros sistemas pueden integrarse con JumpServer utilizando el Token SSO, " "eliminando el proceso de inicio de sesión" @@ -8472,8 +8587,8 @@ msgstr "Unidad: segundos" #: settings/serializers/auth/wecom.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the WeCom service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the WeCom service user attribute name" msgstr "" "Mapeo de atributos de usuario, donde `key` es el nombre del atributo del " "usuario del sistema y `value` es el nombre del atributo del usuario del " @@ -9731,7 +9846,7 @@ msgstr "El código de verificación ha sido enviado" msgid "The verification code has been sent" msgstr "Página principal" -#: templates/_without_nav_base.html:46 +#: templates/_without_nav_base.html:51 msgid "Home page" msgstr "Cliente" @@ -10000,31 +10115,31 @@ msgstr "puede ejecutarse en paralelo" msgid "Hosts" msgstr "host" -#: terminal/models/applet/applet.py:94 +#: terminal/models/applet/applet.py:102 #: terminal/models/virtualapp/virtualapp.py:66 #, python-brace-format msgid "Applet pkg not valid, Missing file {}" msgstr "Paquete Applet inválido, falta el archivo {}" -#: terminal/models/applet/applet.py:113 +#: terminal/models/applet/applet.py:121 #, python-brace-format msgid "Load platform.yml failed: {}" msgstr "Error al cargar platform.yml: {}" -#: terminal/models/applet/applet.py:116 +#: terminal/models/applet/applet.py:124 msgid "Only support custom platform" msgstr "Solo se admite plataforma personalizada" -#: terminal/models/applet/applet.py:121 +#: terminal/models/applet/applet.py:129 msgid "Missing type in platform.yml" msgstr "Falta tipo en el platform.yml" -#: terminal/models/applet/applet.py:381 terminal/models/applet/host.py:36 +#: terminal/models/applet/applet.py:389 terminal/models/applet/host.py:36 #: terminal/models/applet/host.py:138 msgid "Hosting" msgstr "Máquina anfitriona" -#: terminal/models/applet/applet.py:387 +#: terminal/models/applet/applet.py:395 msgid "Applet Publication" msgstr "Lanzamiento de la aplicación" @@ -10128,7 +10243,7 @@ msgstr "Puerto de VNC" #: terminal/models/component/endpoint.py:35 #: terminal/models/component/endpoint.py:115 -#: terminal/serializers/endpoint.py:63 terminal/serializers/storage.py:41 +#: 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" @@ -10342,8 +10457,8 @@ msgstr "Almacenamiento de comandos y grabaciones" #: terminal/notifications.py:279 terminal/tasks.py:212 #: xpack/plugins/cloud/api.py:182 -#: xpack/plugins/cloud/serializers/account.py:143 -#: xpack/plugins/cloud/serializers/account.py:146 +#: xpack/plugins/cloud/serializers/account.py:148 +#: xpack/plugins/cloud/serializers/account.py:151 msgid "Test failure: Account invalid" msgstr "Prueba fallida: cuenta no válida" @@ -10465,11 +10580,13 @@ msgstr "Licencia RDS ya existente" msgid "" "If not exist, the RDS will be in trial mode, and the trial period is 120 " "days. Detail" +"remote-desktop-services/rds-client-access-license\" " +"target=\"_blank\">Detail" msgstr "" "Si no existe, RDS estará en modo de prueba, con un período de prueba de 120 " "días. Más detalles" +"remote-desktop-services/rds-client-access-license' target='_blank'>Más " +"detalles" #: terminal/serializers/applet_host.py:55 msgid "RDS License Server" @@ -10598,7 +10715,7 @@ msgstr "ID de sesión no válido" msgid "Timestamp" msgstr "Marca de tiempo" -#: terminal/serializers/endpoint.py:27 +#: terminal/serializers/endpoint.py:28 msgid "" "The host address accessed when connecting to assets, if it is empty, the " "access address of the current browser will be used (the default endpoint " @@ -10608,7 +10725,7 @@ msgstr "" "utilizará la dirección de acceso del navegador actual (el punto final por " "defecto no permite modificar el host)" -#: terminal/serializers/endpoint.py:54 +#: terminal/serializers/endpoint.py:64 msgid "" "The assets within this IP range or Host, the following endpoint will be used " "for the connection" @@ -10616,7 +10733,7 @@ msgstr "" "Los activos dentro de este rango de IP o de este host se conectarán " "utilizando el siguiente punto final." -#: terminal/serializers/endpoint.py:55 +#: terminal/serializers/endpoint.py:65 msgid "" "If asset IP addresses under different endpoints conflict, use asset labels" msgstr "" @@ -10757,7 +10874,7 @@ msgstr "En línea" msgid "Stat" msgstr "Estado" -#: terminal/serializers/terminal.py:83 terminal/serializers/terminal.py:91 +#: terminal/serializers/terminal.py:79 terminal/serializers/terminal.py:87 msgid "Not found" msgstr "No se encontró" @@ -11360,7 +11477,7 @@ msgstr "Solicitante" msgid "Approval Step Distribution" msgstr "Aprobación sin inicio de sesión" -#: tickets/serializers/flow.py:45 +#: tickets/serializers/flow.py:42 msgid "The current organization type already exists" msgstr "El tipo ya existe en la organización actual" @@ -11421,7 +11538,7 @@ msgid "Ticket information" msgstr "Información de la orden de trabajo" #: tickets/templates/tickets/approve_check_password.html:28 -#: tickets/views/approve.py:43 tickets/views/approve.py:80 +#: tickets/views/approve.py:42 tickets/views/approve.py:80 msgid "Ticket approval" msgstr "Aprobación de la orden de trabajo" @@ -11429,14 +11546,14 @@ msgstr "Aprobación de la orden de trabajo" msgid "Approval" msgstr "Aceptar" -#: tickets/views/approve.py:44 +#: tickets/views/approve.py:43 msgid "" "This ticket does not exist, the process has ended, or this link has expired" msgstr "" "La orden de trabajo no existe, o el proceso de la orden de trabajo ha " "finalizado, o este enlace ha expirado" -#: tickets/views/approve.py:72 +#: tickets/views/approve.py:71 msgid "Click the button below to approve or reject" msgstr "Haga clic en el botón de abajo para aceptar o rechazar" @@ -11657,7 +11774,7 @@ msgstr "Configuración del usuario" msgid "Email lookup" msgstr "Cuenta de correo electrónico" -#: users/models/user/__init__.py:82 users/serializers/user.py:259 +#: users/models/user/__init__.py:82 users/serializers/user.py:264 msgid "Is service account" msgstr "Cuenta de servicio" @@ -11674,7 +11791,7 @@ msgid "OTP secret key" msgstr "Clave OTP" #: users/models/user/__init__.py:105 users/serializers/profile.py:86 -#: users/serializers/user.py:256 +#: users/serializers/user.py:261 msgid "Is first login" msgstr "Primer inicio de sesión" @@ -11694,23 +11811,23 @@ msgstr "Vector facial" msgid "Date api key used" msgstr "Fecha de último uso de la API key" -#: users/models/user/__init__.py:293 +#: users/models/user/__init__.py:298 msgid "Can not delete admin user" msgstr "No se puede eliminar al usuario administrador" -#: users/models/user/__init__.py:307 +#: users/models/user/__init__.py:312 msgid "Can invite user" msgstr "Se puede invitar a usuarios" -#: users/models/user/__init__.py:308 +#: users/models/user/__init__.py:313 msgid "Can remove user" msgstr "Se puede eliminar a usuarios" -#: users/models/user/__init__.py:309 +#: users/models/user/__init__.py:314 msgid "Can match user" msgstr "Se puede hacer coincidir a usuarios" -#: users/models/user/__init__.py:338 +#: users/models/user/__init__.py:343 msgid "User password history" msgstr "Historial de contraseñas de usuarios" @@ -11718,6 +11835,12 @@ msgstr "Historial de contraseñas de usuarios" msgid "Force enabled" msgstr "Activación forzada" +#: users/models/user/_source.py:27 +#, fuzzy +#| msgid "Authenticate" +msgid "Certificate" +msgstr "Verificar identidad" + #: users/notifications.py:23 users/notifications.py:68 msgid "Reset password url" msgstr "URL de reinicio de contraseña" @@ -11831,7 +11954,7 @@ msgstr "Carga asíncrona del árbol de activos" msgid "Connect default open method" msgstr "Forma predeterminada de apertura de conexión" -#: users/serializers/preference/luna.py:34 xpack/plugins/interface/models.py:42 +#: users/serializers/preference/luna.py:34 xpack/plugins/interface/models.py:44 #: xpack/plugins/interface/serializers/interface.py:35 msgid "Theme" msgstr "Tema" @@ -11947,7 +12070,7 @@ msgstr "Forzar MFA" msgid "Login blocked" msgstr "Inicio de sesión bloqueado" -#: users/serializers/user.py:130 users/serializers/user.py:265 +#: users/serializers/user.py:130 users/serializers/user.py:270 msgid "Is OTP bound" msgstr "¿Está vinculado a un MFA virtual?" @@ -11963,27 +12086,33 @@ msgstr "Administrador de la organización" msgid "Can public key authentication" msgstr "Pueden usar autenticación de clave pública" -#: users/serializers/user.py:144 +#: users/serializers/user.py:145 +#, fuzzy +#| msgid "Can public key authentication" +msgid "Can certificate authentication" +msgstr "Pueden usar autenticación de clave pública" + +#: users/serializers/user.py:149 msgid "Is face code set" msgstr "¿Existen características faciales?" -#: users/serializers/user.py:230 +#: users/serializers/user.py:235 msgid "Full name" msgstr "Nombre completo" -#: users/serializers/user.py:233 +#: users/serializers/user.py:238 msgid "Login username" msgstr "Usuario que inicia sesión" -#: users/serializers/user.py:236 +#: users/serializers/user.py:241 msgid "Email address" msgstr "Dirección de correo electrónico" -#: users/serializers/user.py:246 +#: users/serializers/user.py:251 msgid "User groups to join" msgstr "Cantidad de grupos de usuarios" -#: users/serializers/user.py:250 +#: users/serializers/user.py:255 msgid "" "User source identifies where the user was created, which could be AD or " "other sources.There are security settings that can restrict users to log in " @@ -11994,34 +12123,34 @@ msgstr "" "usuarios para que solo inicien sesión en el sistema desde fuentes " "específicas." -#: users/serializers/user.py:260 +#: users/serializers/user.py:265 msgid "Is org admin" msgstr "Administrador de la organización" -#: users/serializers/user.py:262 +#: users/serializers/user.py:267 msgid "Avatar url" msgstr "Ruta del avatar" -#: users/serializers/user.py:267 +#: users/serializers/user.py:272 msgid "MFA level" msgstr "MFA" -#: users/serializers/user.py:268 +#: users/serializers/user.py:273 msgid "Multi-Factor Authentication" msgstr "Autenticación" -#: users/serializers/user.py:398 +#: users/serializers/user.py:403 msgid "Has public keys" msgstr "Hay clave pública" -#: users/serializers/user.py:426 +#: users/serializers/user.py:431 msgid "" "* For security, only a partial of users is displayed. You can search for more" msgstr "" "* Por razones de seguridad, solo se muestran algunos usuarios. Puedes buscar " "más" -#: users/serializers/user.py:462 +#: users/serializers/user.py:467 msgid "name not unique" msgstr "Nombres duplicados" @@ -12545,7 +12674,7 @@ msgstr "IP Privada" msgid "Public IP" msgstr "IP público" -#: xpack/plugins/cloud/const.py:50 xpack/plugins/cloud/models.py:373 +#: xpack/plugins/cloud/const.py:50 xpack/plugins/cloud/models.py:374 msgid "Instance name" msgstr "Nombre de la instancia" @@ -12746,8 +12875,8 @@ msgstr "Publicar activo" msgid "Date last sync" msgstr "Fecha de Última Sincronización" -#: xpack/plugins/cloud/models.py:135 xpack/plugins/cloud/models.py:391 -#: xpack/plugins/cloud/models.py:418 +#: xpack/plugins/cloud/models.py:135 xpack/plugins/cloud/models.py:392 +#: xpack/plugins/cloud/models.py:419 msgid "Strategy" msgstr "Estrategia" @@ -12787,71 +12916,71 @@ msgstr "Relación de condiciones" msgid "Task strategy" msgstr "Estrategia de tareas" -#: xpack/plugins/cloud/models.py:362 +#: xpack/plugins/cloud/models.py:363 msgid "Equal" msgstr "Igual a" -#: xpack/plugins/cloud/models.py:363 +#: xpack/plugins/cloud/models.py:364 msgid "Not Equal" msgstr "No igual a" -#: xpack/plugins/cloud/models.py:364 +#: xpack/plugins/cloud/models.py:365 msgid "In" msgstr "En..." -#: xpack/plugins/cloud/models.py:365 +#: xpack/plugins/cloud/models.py:366 msgid "Contains" msgstr "Contener" -#: xpack/plugins/cloud/models.py:366 +#: xpack/plugins/cloud/models.py:367 msgid "Exclude" msgstr "Excluir" -#: xpack/plugins/cloud/models.py:367 +#: xpack/plugins/cloud/models.py:368 msgid "Startswith" msgstr "Comenzar con..." -#: xpack/plugins/cloud/models.py:368 +#: xpack/plugins/cloud/models.py:369 msgid "Endswith" msgstr "Terminar con..." -#: xpack/plugins/cloud/models.py:374 +#: xpack/plugins/cloud/models.py:375 msgid "Instance platform" msgstr "Plataforma de instancia" -#: xpack/plugins/cloud/models.py:375 +#: xpack/plugins/cloud/models.py:376 msgid "Instance address" msgstr "Dirección de instancia" -#: xpack/plugins/cloud/models.py:382 +#: xpack/plugins/cloud/models.py:383 msgid "Rule attr" msgstr "Atributos de regla" -#: xpack/plugins/cloud/models.py:386 +#: xpack/plugins/cloud/models.py:387 msgid "Rule match" msgstr "Coincidencia de regla" -#: xpack/plugins/cloud/models.py:388 +#: xpack/plugins/cloud/models.py:389 msgid "Rule value" msgstr "Valor de regla" -#: xpack/plugins/cloud/models.py:395 xpack/plugins/cloud/serializers/task.py:82 +#: xpack/plugins/cloud/models.py:396 xpack/plugins/cloud/serializers/task.py:82 msgid "Strategy rule" msgstr "Condición" -#: xpack/plugins/cloud/models.py:406 +#: xpack/plugins/cloud/models.py:407 msgid "Name strategy" msgstr "Estrategia de nombre de host" -#: xpack/plugins/cloud/models.py:413 +#: xpack/plugins/cloud/models.py:414 msgid "Action attr" msgstr "Atributos de acción" -#: xpack/plugins/cloud/models.py:415 +#: xpack/plugins/cloud/models.py:416 msgid "Action value" msgstr "Valor de acción" -#: xpack/plugins/cloud/models.py:422 xpack/plugins/cloud/serializers/task.py:85 +#: xpack/plugins/cloud/models.py:423 xpack/plugins/cloud/serializers/task.py:85 msgid "Strategy action" msgstr "Acción" @@ -13231,38 +13360,38 @@ msgstr "La misión aún no ha comenzado." msgid "Restore default successfully." msgstr "¡Restauración predeterminada exitosa!" -#: xpack/plugins/interface/meta.py:9 xpack/plugins/interface/models.py:47 -#: xpack/plugins/interface/models.py:91 +#: xpack/plugins/interface/meta.py:9 xpack/plugins/interface/models.py:49 +#: xpack/plugins/interface/models.py:104 msgid "Interface settings" msgstr "Configuración de la interfaz" -#: xpack/plugins/interface/models.py:24 +#: xpack/plugins/interface/models.py:26 msgid "Login title" msgstr "Título de la página de inicio de sesión" -#: xpack/plugins/interface/models.py:28 +#: xpack/plugins/interface/models.py:30 msgid "Login image" msgstr "Imagen de la página de inicio de sesión" -#: xpack/plugins/interface/models.py:32 +#: xpack/plugins/interface/models.py:34 msgid "Website icon" msgstr "Ícono del sitio web" -#: xpack/plugins/interface/models.py:36 +#: xpack/plugins/interface/models.py:38 msgid "Index logo" msgstr "Logo de la página de gestión" -#: xpack/plugins/interface/models.py:40 +#: xpack/plugins/interface/models.py:42 msgid "Logout logo" msgstr "Cerrar sesión" -#: xpack/plugins/interface/models.py:43 +#: xpack/plugins/interface/models.py:45 msgid "Footer content" msgstr "Contenido del pie de página" -#: xpack/plugins/interface/models.py:44 +#: xpack/plugins/interface/models.py:46 #: xpack/plugins/interface/serializers/interface.py:73 -msgid "Extended fields" +msgid "Extend" msgstr "" #: xpack/plugins/interface/serializers/interface.py:48 @@ -13317,6 +13446,18 @@ msgstr "" msgid "More login methods" msgstr "Otras formas de iniciar sesión" +#: xpack/plugins/jdmc/i18n.py:4 +#, fuzzy +#| msgid "Audit view" +msgid "AuditAdmin" +msgstr "Registro de auditoría" + +#: xpack/plugins/jdmc/i18n.py:5 +#, fuzzy +#| msgid "SystemAdmin" +msgid "SecAdmin" +msgstr "Administrador del sistema" + #: xpack/plugins/jdmc/meta.py:9 msgid "JDMC" msgstr "" @@ -13329,6 +13470,9 @@ msgstr "Importación de licencia exitosa" msgid "Invalid license" msgstr "Licencia no válida" +#~ msgid "User invalid, disabled or expired" +#~ msgstr "Usuario no válido, ha sido desactivado o ha expirado" + #~ msgid "Microsoft" #~ msgstr "Microsoft" diff --git a/apps/i18n/core/ja/LC_MESSAGES/django.po b/apps/i18n/core/ja/LC_MESSAGES/django.po index 3519b9357..968f81b91 100644 --- a/apps/i18n/core/ja/LC_MESSAGES/django.po +++ b/apps/i18n/core/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: 2026-04-21 17:03+0800\n" +"POT-Creation-Date: 2026-05-25 14:02+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -28,7 +28,7 @@ msgstr "アカウントはすでに存在しています" msgid "No valid assets found for account creation." msgstr "アカウント作成に使用できる有効な資産が見つかりませんでした。" -#: accounts/api/account/application.py:77 +#: accounts/api/account/application.py:87 #: authentication/api/connection_token.py:463 msgid "Account not found" msgstr "アカウントが見つかりません" @@ -42,15 +42,15 @@ msgstr "パラメータ 'action' は [{}] でなければなりません。" msgid "The account key will be split into two parts and sent" msgstr "アカウントの秘密鍵は、前後二部に分けられて送信されます" -#: accounts/automations/backup_account/handlers.py:131 +#: accounts/automations/backup_account/handlers.py:132 msgid "Number of backup accounts" msgstr "バックアップアカウントの数" -#: accounts/automations/backup_account/handlers.py:152 +#: accounts/automations/backup_account/handlers.py:153 msgid "Generating asset related backup information files" msgstr "資産関連のバックアップ情報ファイルを生成" -#: accounts/automations/backup_account/handlers.py:177 +#: accounts/automations/backup_account/handlers.py:178 #: accounts/automations/backup_account/manager.py:26 #: accounts/automations/change_secret/manager.py:81 #: accounts/automations/push_account/manager.py:62 @@ -61,31 +61,31 @@ msgstr "資産関連のバックアップ情報ファイルを生成" msgid "Duration" msgstr "時を過ごす" -#: accounts/automations/backup_account/handlers.py:178 +#: accounts/automations/backup_account/handlers.py:179 msgid "Backup file creation completed" msgstr "バックアップファイルの作成が完了しました" -#: accounts/automations/backup_account/handlers.py:186 +#: accounts/automations/backup_account/handlers.py:187 msgid "Start sending backup emails" msgstr "バックアップメールの送信を開始する" -#: accounts/automations/backup_account/handlers.py:213 +#: accounts/automations/backup_account/handlers.py:214 msgid "Encrypting files using encryption password" msgstr "暗号化パスワードを使用してファイルを暗号化中" -#: accounts/automations/backup_account/handlers.py:223 +#: accounts/automations/backup_account/handlers.py:224 msgid "The backup file will be sent to" msgstr "バックアップファイルは送信されます" -#: accounts/automations/backup_account/handlers.py:246 +#: accounts/automations/backup_account/handlers.py:247 msgid "The backup task has no assigned sftp server" msgstr "このバックアップタスクはsftpサーバーに割り当てられていません" -#: accounts/automations/backup_account/handlers.py:267 +#: accounts/automations/backup_account/handlers.py:268 msgid "The backup task has no assigned recipient" msgstr "バックアップタスクは受取人を指定していません" -#: accounts/automations/backup_account/handlers.py:290 +#: accounts/automations/backup_account/handlers.py:291 msgid "Plan start" msgstr "計画開始" @@ -153,7 +153,7 @@ msgstr ">>> ゲートウェイ接続のテストタスクを開始する" #: settings/serializers/auth/ldap.py:53 settings/serializers/auth/ldap_ha.py:35 #: settings/serializers/msg.py:37 settings/serializers/terminal.py:32 #: terminal/serializers/storage.py:123 terminal/serializers/storage.py:142 -#: users/forms/profile.py:22 users/serializers/user.py:148 +#: users/forms/profile.py:22 users/serializers/user.py:153 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/cloud/serializers/account_attrs.py:43 @@ -227,7 +227,7 @@ msgstr "更新" #: accounts/const/account.py:34 accounts/const/automation.py:115 #: accounts/serializers/automations/change_secret.py:171 audits/const.py:66 -#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:66 +#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:67 #: ops/const.py:77 terminal/const.py:81 xpack/plugins/cloud/const.py:55 msgid "Failed" msgstr "失敗しました" @@ -349,14 +349,14 @@ msgstr "SFTP" #: accounts/const/automation.py:116 #: accounts/serializers/automations/change_secret.py:170 audits/const.py:65 #: audits/models.py:65 audits/signal_handlers/activity_log.py:34 -#: common/const/choices.py:65 ops/const.py:75 ops/serializers/celery.py:48 +#: common/const/choices.py:66 ops/const.py:75 ops/serializers/celery.py:48 #: terminal/const.py:80 terminal/models/session/sharing.py:119 #: tickets/views/approve.py:128 msgid "Success" msgstr "成功" -#: accounts/const/automation.py:117 common/const/choices.py:63 -#: common/const/choices.py:114 terminal/const.py:79 +#: accounts/const/automation.py:117 common/const/choices.py:64 +#: common/const/choices.py:127 terminal/const.py:79 msgid "Pending" msgstr "未定" @@ -364,7 +364,7 @@ msgstr "未定" msgid "Queued" msgstr "順番待ち" -#: accounts/const/automation.py:122 common/const/choices.py:62 +#: accounts/const/automation.py:122 common/const/choices.py:63 msgid "Ready" msgstr "の準備を" @@ -376,7 +376,7 @@ msgstr "処理中" msgid "Can login" msgstr "ログイン可能" -#: accounts/const/automation.py:128 users/serializers/user.py:254 +#: accounts/const/automation.py:128 users/serializers/user.py:259 msgid "Superuser" msgstr "システムユーザー" @@ -405,7 +405,7 @@ msgid "Default tablespace" msgstr "デフォルト表領域" #: accounts/const/automation.py:135 rbac/models/role.py:46 -#: rbac/models/rolebinding.py:52 users/models/user/__init__.py:79 +#: rbac/models/rolebinding.py:53 users/models/user/__init__.py:79 msgid "Role" msgstr "ロール" @@ -414,7 +414,7 @@ msgid "Perms" msgstr "パーマ" #: accounts/const/automation.py:137 perms/serializers/permission.py:56 -#: users/serializers/user.py:245 +#: users/serializers/user.py:250 msgid "Groups" msgstr "ユーザーグループ" @@ -804,7 +804,7 @@ msgstr "終了日" #: assets/models/automations/base.py:137 #: assets/serializers/automations/base.py:47 audits/models.py:224 #: audits/reporting.py:607 audits/serializers.py:77 ops/models/base.py:49 -#: ops/models/job.py:233 terminal/models/applet/applet.py:382 +#: ops/models/job.py:233 terminal/models/applet/applet.py:390 #: terminal/models/applet/host.py:140 terminal/models/component/status.py:30 #: terminal/models/virtualapp/virtualapp.py:99 #: terminal/serializers/applet.py:19 terminal/serializers/applet_host.py:163 @@ -819,7 +819,7 @@ msgstr "ステータス" #: accounts/serializers/account/account.py:297 assets/const/automation.py:9 #: authentication/templates/authentication/passkey.html:177 #: authentication/views/base.py:43 authentication/views/base.py:44 -#: authentication/views/base.py:45 common/const/choices.py:67 +#: authentication/views/base.py:45 common/const/choices.py:68 #: settings/templates/ldap/_msg_import_ldap_user.html:26 msgid "Error" msgstr "間違い" @@ -914,8 +914,9 @@ msgstr "パスワードの重複" #: accounts/templates/accounts/push_account_report.html:79 #: accounts/templates/accounts/push_account_report.html:119 #: acls/serializers/base.py:19 acls/serializers/base.py:50 audits/models.py:204 -#: audits/reporting.py:241 authentication/forms.py:21 -#: authentication/forms.py:23 authentication/models/temp_token.py:10 +#: audits/reporting.py:241 authentication/backends/cert/forms.py:7 +#: authentication/forms.py:21 authentication/forms.py:23 +#: authentication/models/temp_token.py:10 #: authentication/serializers/connect_token_secret.py:43 #: authentication/serializers/connect_token_secret.py:53 #: authentication/templates/authentication/_msg_different_city.html:9 @@ -1074,7 +1075,7 @@ msgstr "特権アカウント" #: assets/models/cmd_filter.py:39 assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:129 reports/models.py:18 #: terminal/models/applet/applet.py:41 -#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:257 +#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:262 msgid "Is active" msgstr "アクティブです。" @@ -1090,7 +1091,7 @@ msgstr "プラットフォーム" msgid "Push params" msgstr "パラメータをプッシュする" -#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:403 +#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:404 msgid "Account template" msgstr "アカウント テンプレート" @@ -1184,7 +1185,7 @@ msgstr "アカウント変更情報" msgid "Change secret or push account failed information" msgstr "パスワード変更またはアカウントプッシュ失敗情報" -#: accounts/risk_handlers.py:17 common/const/choices.py:116 +#: accounts/risk_handlers.py:17 common/const/choices.py:129 msgid "Ignored" msgstr "無視する" @@ -1341,7 +1342,7 @@ msgstr "ID" #: authentication/notifications.py:16 authentication/notifications.py:55 #: notifications/models/notification.py:12 #: perms/api/user_permission/mixin.py:58 perms/models/asset_permission.py:63 -#: rbac/builtin.py:134 rbac/models/rolebinding.py:49 +#: rbac/builtin.py:134 rbac/models/rolebinding.py:50 #: rbac/serializers/rolebinding.py:17 terminal/backends/command/models.py:16 #: terminal/models/session/session.py:27 terminal/models/session/sharing.py:34 #: terminal/notifications.py:168 terminal/notifications.py:235 @@ -1349,8 +1350,8 @@ msgstr "ID" #: terminal/templates/terminal/_msg_command_warning.html:9 #: terminal/templates/terminal/_msg_session_sharing.html:6 #: tickets/models/comment.py:21 tickets/serializers/flow.py:15 -#: users/const.py:14 users/models/user/__init__.py:298 -#: users/models/user/__init__.py:325 +#: users/const.py:14 users/models/user/__init__.py:303 +#: users/models/user/__init__.py:330 msgid "User" msgstr "ユーザー" @@ -1385,7 +1386,7 @@ msgstr "Access IP" #: assets/models/cmd_filter.py:88 common/db/models.py:36 ops/models/adhoc.py:25 #: ops/models/job.py:165 ops/models/playbook.py:31 rbac/models/role.py:37 #: settings/models.py:43 terminal/models/applet/applet.py:46 -#: terminal/models/applet/applet.py:383 terminal/models/applet/host.py:143 +#: terminal/models/applet/applet.py:391 terminal/models/applet/host.py:143 #: terminal/models/component/endpoint.py:29 #: terminal/models/component/endpoint.py:117 #: terminal/models/session/session.py:44 @@ -1673,7 +1674,7 @@ msgstr "" "ジ-レコード制限の設定に基づき、毎日午前2時に超過した数量のアカウントレコード" "をクリーニングします" -#: accounts/tasks/remove_account.py:89 +#: accounts/tasks/remove_account.py:91 msgid "Remove historical accounts that are out of range." msgstr "範囲外の履歴アカウントを削除する" @@ -1746,7 +1747,7 @@ msgstr "タスク名" #: accounts/templates/accounts/push_account_report.html:22 #: assets/models/automations/base.py:143 audits/models.py:66 #: ops/models/base.py:55 ops/models/celery.py:89 ops/models/job.py:241 -#: ops/templates/ops/celery_task_log.html:101 +#: ops/templates/ops/celery_task_log.html:154 #: perms/models/asset_permission.py:78 settings/serializers/feature.py:29 #: settings/templates/ldap/_msg_import_ldap_user.html:5 #: terminal/models/applet/host.py:141 terminal/models/session/session.py:42 @@ -1931,7 +1932,7 @@ msgstr "レビュー担当者" #: acls/models/base.py:81 perms/serializers/permission.py:54 #: tickets/models/flow.py:23 users/models/preference.py:16 -#: users/serializers/group.py:21 users/serializers/user.py:424 +#: users/serializers/group.py:21 users/serializers/user.py:429 msgid "Users" msgstr "ユーザー" @@ -1957,7 +1958,7 @@ msgid "Command" msgstr "コマンド" #: acls/models/command_acl.py:17 assets/models/cmd_filter.py:59 -#: xpack/plugins/cloud/models.py:369 +#: xpack/plugins/cloud/models.py:370 msgid "Regex" msgstr "正規情報" @@ -2046,7 +2047,7 @@ msgstr "ルール" msgid "Login acl" msgstr "ログインacl" -#: acls/models/login_acl.py:27 tickets/const.py:11 +#: acls/models/login_acl.py:30 tickets/const.py:11 msgid "Login confirm" msgstr "ログイン確認" @@ -2169,7 +2170,7 @@ msgstr "" #: authentication/templates/authentication/_msg_oauth_bind.html:12 #: authentication/templates/authentication/_msg_rest_password_success.html:8 #: authentication/templates/authentication/_msg_rest_public_key_success.html:8 -#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:405 +#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:406 msgid "IP" msgstr "IP" @@ -2231,17 +2232,17 @@ msgstr "ユーザーが最近ログインしたことをお知らせいたしま msgid "User details" msgstr "ユーザー詳細" -#: assets/api/asset/asset.py:166 +#: assets/api/asset/asset.py:168 msgid "Cannot create asset directly, you should create a host or other" msgstr "" "資産を直接作成することはできません。ホストまたはその他を作成する必要がありま" "す" -#: assets/api/asset/asset.py:173 +#: assets/api/asset/asset.py:175 msgid "The number of assets exceeds the limit of 5000" msgstr "資産の数が5000の制限を超えています" -#: assets/api/asset/asset.py:179 +#: assets/api/asset/asset.py:181 #, fuzzy #| msgid "The number of assets exceeds the limit of 5000" msgid "The number of assets exceeds the license limit" @@ -2260,6 +2261,11 @@ msgstr "ルートノード ({}) を削除できません。" msgid "Deletion failed and the node contains assets" msgstr "削除に失敗し、ノードにアセットが含まれています。" +#: assets/api/node.py:99 +#, python-brace-format +msgid "Node {} is an ancestor of node {}, can't be added as its child" +msgstr "" + #: assets/api/tree.py:48 assets/serializers/node.py:42 msgid "The same level node name cannot be the same" msgstr "同じレベルのノード名を同じにすることはできません。" @@ -2277,29 +2283,29 @@ msgstr "アプリ資産" msgid "Task: {} finished" msgstr "タスク:{} 完了" -#: assets/automations/base/manager.py:340 +#: assets/automations/base/manager.py:341 #, python-brace-format msgid " - Platform {} ansible disabled" msgstr " - プラットフォーム {} ansible 無効" -#: assets/automations/base/manager.py:555 +#: assets/automations/base/manager.py:556 msgid ">>> Task preparation phase" msgstr "タスク準備段階" -#: assets/automations/base/manager.py:559 +#: assets/automations/base/manager.py:560 #, python-brace-format msgid ">>> Executing tasks in batches, total {runner_count}" msgstr ">>> バッチでタスクを実行、合計 {runner_count}" -#: assets/automations/base/manager.py:564 +#: assets/automations/base/manager.py:565 msgid ">>> Start executing tasks" msgstr ">>> タスクの実行を開始" -#: assets/automations/base/manager.py:566 +#: assets/automations/base/manager.py:567 msgid ">>> No tasks need to be executed" msgstr ">>> 実行する必要があるタスクはありません" -#: assets/automations/base/manager.py:570 +#: assets/automations/base/manager.py:571 #, python-brace-format msgid ">>> Begin executing batch {index} of tasks" msgstr ">>> 第 {index} バッチのタスクの実行を開始" @@ -2701,7 +2707,7 @@ msgid "Port" msgstr "ポート" #: assets/models/asset/common.py:167 assets/serializers/asset/common.py:175 -#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:59 +#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:69 msgid "Address" msgstr "アドレス" @@ -2709,12 +2715,12 @@ msgstr "アドレス" #: assets/serializers/asset/common.py:151 #: authentication/backends/passkey/models.py:12 #: authentication/serializers/connect_token_secret.py:130 -#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:399 +#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:400 msgid "Platform" msgstr "プラットフォーム" #: assets/models/asset/common.py:173 assets/models/zone.py:22 -#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:401 +#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:402 msgid "Zone" msgstr "ゾーン" @@ -2783,9 +2789,9 @@ msgid "Proxy" msgstr "プロキシー" #: assets/models/automations/base.py:23 assets/models/cmd_filter.py:32 -#: assets/models/node.py:553 ops/models/job.py:158 +#: assets/models/node.py:560 ops/models/job.py:158 #: perms/models/asset_permission.py:72 tickets/models/ticket/apply_asset.py:15 -#: xpack/plugins/cloud/models.py:400 +#: xpack/plugins/cloud/models.py:401 msgid "Node" msgstr "ノード" @@ -2809,7 +2815,7 @@ msgstr "アセットの自動化タスク" #: assets/models/automations/base.py:140 assets/models/cmd_filter.py:41 #: authentication/serializers/token.py:134 common/db/models.py:34 #: ops/models/base.py:54 ops/models/job.py:240 -#: users/models/user/__init__.py:328 +#: users/models/user/__init__.py:333 msgid "Date created" msgstr "作成された日付" @@ -2898,7 +2904,7 @@ msgstr "ゲートウェイ" msgid "System" msgstr "システム" -#: assets/models/label.py:19 assets/models/node.py:539 +#: assets/models/label.py:19 assets/models/node.py:546 #: assets/serializers/cagegory.py:11 assets/serializers/cagegory.py:18 #: assets/serializers/cagegory.py:24 #: authentication/models/connection_token.py:35 @@ -2913,7 +2919,7 @@ msgstr "値" #: assets/serializers/platform.py:160 #: authentication/serializers/connect_token_secret.py:136 #: common/serializers/common.py:85 labels/serializers.py:45 -#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:404 +#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:405 msgid "Label" msgstr "ラベル" @@ -2929,27 +2935,27 @@ msgstr "カスタムメモ" msgid "My assets" msgstr "私の資産" -#: assets/models/node.py:168 +#: assets/models/node.py:172 msgid "New node" msgstr "新しいノード" -#: assets/models/node.py:467 audits/backends/db.py:85 audits/backends/db.py:86 +#: assets/models/node.py:474 audits/backends/db.py:85 audits/backends/db.py:86 msgid "empty" msgstr "空" -#: assets/models/node.py:538 perms/models/perm_node.py:28 +#: assets/models/node.py:545 perms/models/perm_node.py:28 msgid "Key" msgstr "キー" -#: assets/models/node.py:540 assets/serializers/node.py:20 +#: assets/models/node.py:547 assets/serializers/node.py:20 msgid "Full value" msgstr "フルバリュー" -#: assets/models/node.py:544 perms/models/perm_node.py:30 +#: assets/models/node.py:551 perms/models/perm_node.py:30 msgid "Parent key" msgstr "親キー" -#: assets/models/node.py:556 +#: assets/models/node.py:563 msgid "Can match node" msgstr "ノードを一致させることができます" @@ -3129,7 +3135,7 @@ msgstr "" #: authentication/serializers/connect_token_secret.py:30 #: authentication/serializers/connect_token_secret.py:77 #: perms/models/asset_permission.py:76 perms/serializers/permission.py:68 -#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:402 +#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:403 #: xpack/plugins/cloud/serializers/task.py:36 msgid "Protocols" msgstr "プロトコル" @@ -3586,7 +3592,7 @@ msgid "Symlink" msgstr "Symlink" #: audits/const.py:18 audits/const.py:29 -#: ops/templates/ops/celery_task_log.html:86 +#: ops/templates/ops/celery_task_log.html:139 #: terminal/api/session/session.py:159 msgid "Download" msgstr "ダウンロード" @@ -3615,7 +3621,9 @@ msgstr "エクスポート" msgid "Connect" msgstr "接続" -#: audits/const.py:31 authentication/templates/authentication/login.html:334 +#: audits/const.py:31 +#: authentication/templates/authentication/cert_login.html:232 +#: authentication/templates/authentication/login.html:334 #: authentication/templates/authentication/login.html:408 #: templates/_header_bar.html:101 #: xpack/plugins/interface/templates/login_i18n.html:21 @@ -4408,17 +4416,17 @@ msgstr "顔認証の照合に失敗" msgid "Current user not support mfa type: {}" msgstr "現在のユーザーはmfaタイプをサポートしていません: {}" -#: authentication/api/password.py:34 terminal/api/session/session.py:347 +#: authentication/api/password.py:37 terminal/api/session/session.py:347 #: users/views/profile/reset.py:63 #, python-brace-format msgid "User does not exist: {}" msgstr "ユーザーが存在しない: {}" -#: authentication/api/password.py:34 users/views/profile/reset.py:166 +#: authentication/api/password.py:37 users/views/profile/reset.py:166 msgid "No user matched" msgstr "ユーザーにマッチしなかった" -#: authentication/api/password.py:38 +#: authentication/api/password.py:41 #, python-brace-format msgid "" "The user is from {}, please go to the corresponding system to change the " @@ -4427,7 +4435,7 @@ msgstr "" "ユーザーは {}からです。対応するシステムにアクセスしてパスワードを変更してくだ" "さい。" -#: authentication/api/password.py:69 +#: authentication/api/password.py:72 #: authentication/templates/authentication/login.html:400 #: users/templates/users/forgot_password.html:41 #: users/templates/users/forgot_password.html:42 @@ -4437,7 +4445,7 @@ msgstr "" msgid "Forgot password" msgstr "パスワードを忘れた" -#: authentication/api/password.py:70 authentication/mfa/email.py:42 +#: authentication/api/password.py:73 authentication/mfa/email.py:42 #, python-brace-format msgid "The validity period of the verification code is {} minute" msgstr "認証コードの有効時間は {} 分" @@ -4450,10 +4458,29 @@ msgstr "認証" msgid "CAS Error" msgstr "CAS エラー" -#: authentication/backends/custom.py:60 -#: authentication/backends/oauth2/backends.py:158 -msgid "User invalid, disabled or expired" -msgstr "ユーザーが無効、無効、または期限切れです" +#: authentication/backends/cert/api.py:57 +#, fuzzy +#| msgid "LDAP authentication is not enabled" +msgid "Certificate enrollment is not enabled" +msgstr "LDAP 認証が有効になっていない" + +#: authentication/backends/cert/api.py:62 +#, fuzzy +#| msgid "type is required" +msgid "CSR is required" +msgstr "タイプ このフィールドは必須です." + +#: authentication/backends/cert/api.py:68 +#, fuzzy +#| msgid "Authentication failed" +msgid "Certificate signing failed" +msgstr "認証に失敗しました" + +#: authentication/backends/cert/views.py:97 +#, fuzzy +#| msgid "Invalid data" +msgid "Invalid credentials" +msgstr "無効なデータ" #: authentication/backends/drf.py:61 msgid "Invalid token header. No credentials provided." @@ -4705,16 +4732,16 @@ msgstr "パスワードが無効です" msgid "Please wait for %s seconds before retry" msgstr "%s 秒後に再試行してください" -#: authentication/errors/redirect.py:85 authentication/mixins.py:436 +#: authentication/errors/redirect.py:85 authentication/mixins.py:445 #: users/views/profile/reset.py:224 msgid "Your password is too simple, please change it for security" msgstr "パスワードがシンプルすぎるので、セキュリティのために変更してください" -#: authentication/errors/redirect.py:93 authentication/mixins.py:445 +#: authentication/errors/redirect.py:93 authentication/mixins.py:454 msgid "You should to change your password before login" msgstr "ログインする前にパスワードを変更する必要があります" -#: authentication/errors/redirect.py:101 authentication/mixins.py:454 +#: authentication/errors/redirect.py:101 authentication/mixins.py:463 msgid "Your password has expired, please reset before logging in" msgstr "" "パスワードの有効期限が切れました。ログインする前にリセットしてください。" @@ -4845,11 +4872,11 @@ msgstr "" "管理者は「既存のユーザーのみログインを許可」に設定しています。現在のユーザー" "はユーザーリストに含まれていません。管理者に連絡してください。" -#: authentication/mixins.py:184 +#: authentication/mixins.py:187 msgid "User is invalid" msgstr "無効なユーザーです" -#: authentication/mixins.py:201 +#: authentication/mixins.py:204 #, python-brace-format msgid "" " The administrator has enabled 'Only allow login from user source'. \n" @@ -4859,12 +4886,12 @@ msgstr "" "管理者は「ユーザーソースからのみログインを許可」に設定しています。現在のユー" "ザーのソースは {} です。管理者に連絡してください。" -#: authentication/mixins.py:382 +#: authentication/mixins.py:391 #, python-brace-format msgid "The MFA type ({}) is not enabled" msgstr "MFAタイプ ({}) が有効になっていない" -#: authentication/mixins.py:424 +#: authentication/mixins.py:433 msgid "Please change your password" msgstr "パスワードを変更してください" @@ -5056,7 +5083,7 @@ msgstr "アクション" #: authentication/serializers/connection_token.py:46 #: perms/serializers/permission.py:66 perms/serializers/permission.py:87 -#: users/serializers/user.py:127 users/serializers/user.py:261 +#: users/serializers/user.py:127 users/serializers/user.py:266 msgid "Is expired" msgstr "期限切れです" @@ -5098,13 +5125,13 @@ msgstr "有効なssh公開鍵ではありません" #: authentication/serializers/token.py:93 perms/serializers/permission.py:65 #: perms/serializers/permission.py:88 users/serializers/user.py:128 -#: users/serializers/user.py:258 +#: users/serializers/user.py:263 msgid "Is valid" msgstr "有効です" #: authentication/serializers/token.py:131 ops/models/adhoc.py:26 #: ops/models/playbook.py:34 ops/serializers/mixin.py:10 rbac/models/role.py:31 -#: rbac/models/rolebinding.py:46 rbac/serializers/role.py:12 +#: rbac/models/rolebinding.py:47 rbac/serializers/role.py:12 #: settings/serializers/auth/oauth2.py:37 msgid "Scope" msgstr "スコープ" @@ -5203,7 +5230,7 @@ msgstr "コードエラー" #: authentication/templates/authentication/_msg_oauth_bind.html:3 #: authentication/templates/authentication/_msg_reset_password.html:3 #: authentication/templates/authentication/_msg_reset_password_code.html:9 -#: jumpserver/conf.py:555 +#: jumpserver/conf.py:558 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:32 #: users/templates/users/_msg_account_expire_reminder.html:4 @@ -5307,6 +5334,87 @@ msgstr "" msgid "Cancel" msgstr "キャンセル" +#: authentication/templates/authentication/cert_login.html:190 +#, fuzzy +#| msgid "Multi-Factor Authentication" +msgid "Certificate Authentication" +msgstr "認証" + +#: authentication/templates/authentication/cert_login.html:195 +#: authentication/templates/authentication/cert_login.html:250 +msgid "Loading USB Key driver..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:210 +msgid "Insert USB Key to auto-fetch" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:238 +#, fuzzy +#| msgid "More login options" +msgid "Other login methods" +msgstr "その他のログインオプション" + +#: authentication/templates/authentication/cert_login.html:251 +msgid "Detecting USB Key..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:252 +msgid "USB Key connected" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:253 +#, fuzzy +#| msgid "Please enter SMS code" +msgid "Please insert USB Key" +msgstr "SMSコードを入力してください" + +#: authentication/templates/authentication/cert_login.html:254 +#, fuzzy +#| msgid "Account unavailable" +msgid "Driver unavailable" +msgstr "利用できないアカウント" + +#: authentication/templates/authentication/cert_login.html:255 +msgid "USB Key SDK initialization failed" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:256 +msgid "Verifying PIN..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:257 +#, fuzzy +#| msgid "Date verified" +msgid "PIN verified" +msgstr "確認済みの日付" + +#: authentication/templates/authentication/cert_login.html:258 +#, fuzzy +#| msgid "OTP verification code" +msgid "PIN verification failed" +msgstr "OTP検証コード" + +#: authentication/templates/authentication/cert_login.html:259 +msgid "Signing challenge code..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:260 +#, fuzzy +#| msgid "Signing key" +msgid "Signing failed" +msgstr "プロバイダ署名キー" + +#: authentication/templates/authentication/cert_login.html:261 +msgid "Failed to retrieve certificate" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:262 +#, fuzzy +#| msgid "Your account has expired, please contact the administrator." +msgid "No certificate detected, please contact administrator" +msgstr "あなたのアカウントは既に期限切れです。管理者にご連絡ください。" + #: authentication/templates/authentication/face_capture.html:14 msgid "Retry" msgstr "再試行" @@ -5378,6 +5486,10 @@ msgstr "再試行しますか?" msgid "LAN" msgstr "ローカルエリアネットワーク" +#: authentication/utils.py:150 +msgid "CERT" +msgstr "" + #: authentication/views/base.py:71 #: perms/templates/perms/_msg_permed_items_expire.html:18 msgid "If you have any question, please contact the administrator" @@ -5541,47 +5653,47 @@ msgstr "パスワードでログインしてからWeComをバインドしてく msgid "Request file format may be wrong" msgstr "リクエストファイルの形式が間違っている可能性があります" -#: common/const/choices.py:40 +#: common/const/choices.py:41 msgid "China" msgstr "中国" -#: common/const/choices.py:57 +#: common/const/choices.py:58 msgid "Manual" msgstr "手動トリガー" -#: common/const/choices.py:58 +#: common/const/choices.py:59 msgid "Timing" msgstr "定期トリガー" -#: common/const/choices.py:64 ops/const.py:74 +#: common/const/choices.py:65 ops/const.py:74 msgid "Running" msgstr "ランニング" -#: common/const/choices.py:68 +#: common/const/choices.py:69 msgid "Canceled" msgstr "キャンセル" -#: common/const/choices.py:115 +#: common/const/choices.py:128 msgid "Confirmed" msgstr "確認" -#: common/const/choices.py:123 terminal/models/applet/applet.py:31 +#: common/const/choices.py:136 terminal/models/applet/applet.py:31 msgid "Community edition" msgstr "コミュニティ版" -#: common/const/choices.py:124 +#: common/const/choices.py:137 msgid "Basic edition" msgstr "エンタープライズ基本版" -#: common/const/choices.py:125 +#: common/const/choices.py:138 msgid "Standard edition" msgstr "エンタープライズ標準版" -#: common/const/choices.py:126 +#: common/const/choices.py:139 msgid "Professional edition" msgstr "エンタープライズプロフェッショナル版" -#: common/const/choices.py:127 +#: common/const/choices.py:140 msgid "Ultimate edition" msgstr "エンタープライズ・フラッグシップ・エディション" @@ -6097,24 +6209,24 @@ msgstr "コードが見つかりません" msgid "The message code provided is invalid or has expired" msgstr "提供されたメッセージコードは無効か期限切れです" -#: jumpserver/conf.py:549 +#: jumpserver/conf.py:552 #, python-brace-format msgid "The verification code is: {code}" msgstr "認証コードは: {code}" -#: jumpserver/conf.py:554 +#: jumpserver/conf.py:557 msgid "Create account successfully" msgstr "アカウントを正常に作成" -#: jumpserver/conf.py:556 +#: jumpserver/conf.py:559 msgid "Your account has been created successfully" msgstr "アカウントが正常に作成されました" -#: jumpserver/context_processor.py:17 +#: jumpserver/context_processor.py:16 msgid "JumpServer - An open-source PAM" msgstr "JumpServer オープンソースの要塞ホスト" -#: jumpserver/context_processor.py:37 +#: jumpserver/context_processor.py:31 msgid "FIT2CLOUD" msgstr "" @@ -6836,7 +6948,7 @@ msgid "Please save in a org" msgstr "組織を選択してから保存してください" #: orgs/mixins/models.py:58 orgs/mixins/serializers.py:25 orgs/models.py:91 -#: rbac/const.py:7 rbac/models/rolebinding.py:56 +#: rbac/const.py:7 rbac/models/rolebinding.py:57 #: rbac/serializers/rolebinding.py:44 settings/serializers/auth/base.py:53 #: terminal/notifications.py:309 #: terminal/templates/terminal/_msg_command_warning.html:27 @@ -7261,26 +7373,26 @@ msgstr "システムの役割" msgid "Organization role" msgstr "組織の役割" -#: rbac/models/rolebinding.py:62 +#: rbac/models/rolebinding.py:63 msgid "Role binding" msgstr "ロールバインディング" -#: rbac/models/rolebinding.py:168 +#: rbac/models/rolebinding.py:169 msgid "All organizations" msgstr "全ての組織" -#: rbac/models/rolebinding.py:200 +#: rbac/models/rolebinding.py:201 msgid "" "User last role in org, can not be delete, you can remove user from org " "instead" msgstr "" "ユーザーの最後のロールは削除できません。ユーザーを組織から削除できます。" -#: rbac/models/rolebinding.py:207 +#: rbac/models/rolebinding.py:208 msgid "Organization role binding" msgstr "組織の役割バインディング" -#: rbac/models/rolebinding.py:222 +#: rbac/models/rolebinding.py:223 msgid "System role binding" msgstr "システムロールバインディング" @@ -7345,7 +7457,7 @@ msgid "Storage" msgstr "ストレージ" #: rbac/tree.py:64 terminal/models/applet/applet.py:53 -#: terminal/models/applet/applet.py:379 terminal/models/applet/host.py:30 +#: terminal/models/applet/applet.py:387 terminal/models/applet/host.py:30 #: terminal/serializers/applet.py:16 msgid "Applet" msgstr "リモートアプリケーション" @@ -7408,51 +7520,51 @@ msgstr "アクセストークンを取り消す" msgid "Range days" msgstr "による変更" -#: reports/views.py:20 +#: reports/views.py:19 msgid "User login report" msgstr "ユーザーログイン報告" -#: reports/views.py:24 +#: reports/views.py:23 msgid "User change password report" msgstr "ユーザー変更パスワード報告" -#: reports/views.py:28 +#: reports/views.py:27 msgid "Asset statistics report" msgstr "資産統計報告" -#: reports/views.py:32 +#: reports/views.py:31 msgid "Asset activity report" msgstr "資産活動報告" -#: reports/views.py:36 +#: reports/views.py:35 msgid "Account statistics report" msgstr "アカウント統計報告" -#: reports/views.py:40 +#: reports/views.py:39 msgid "Account automation report" msgstr "アカウント自動化報告" -#: reports/views.py:44 +#: reports/views.py:43 msgid "ConsoleDashboard" msgstr "コンソールダッシュボード" -#: reports/views.py:48 +#: reports/views.py:47 msgid "AuditsDashboard" msgstr "監査台ダッシュボード" -#: reports/views.py:52 +#: reports/views.py:51 msgid "PamDashboard" msgstr "PAMダッシュボード" -#: reports/views.py:56 +#: reports/views.py:55 msgid "ChangeSecretDashboard" msgstr "アカウントパスワード変更ダッシュボード" -#: reports/views.py:191 +#: reports/views.py:190 msgid "Failed to send email: " msgstr "メール送信失敗" -#: reports/views.py:192 +#: reports/views.py:191 msgid "Email sent successfully to " msgstr "メール送信成功" @@ -7735,16 +7847,16 @@ msgstr "ピン認証の有効化" #: settings/serializers/auth/dingtalk.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the DingTalk service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the DingTalk service user attribute name" msgstr "" "ユーザー属性のマッピング、ここで `key` はこのシステムのユーザー属性名で、" "`value` は ディントーク サービスのユーザー属性名です" #: settings/serializers/auth/feishu.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the FeiShu service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the FeiShu service user attribute name" msgstr "" "ユーザー属性のマッピング、ここで `key` はこのシステムのユーザー属性名で、" "`value` は フェイシュ サービスのユーザー属性名です" @@ -7755,8 +7867,8 @@ msgstr "Lark" #: settings/serializers/auth/lark.py:19 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Lark service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Lark service user attribute name" msgstr "" "ユーザー属性のマッピング、ここで `key` はこのシステムのユーザー属性名で、" "`value` は Lark サービスのユーザー属性名です" @@ -7803,8 +7915,8 @@ msgstr "選択は (cnまたはuidまたはsAMAccountName)=%(user)s)" #: settings/serializers/auth/ldap.py:69 settings/serializers/auth/ldap_ha.py:51 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the LDAP service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the LDAP service user attribute name" msgstr "" "ユーザー属性のマッピング、ここで `key` はこのシステムのユーザー属性名で、" "`value` は LDAP サービスのユーザー属性名です" @@ -7912,8 +8024,8 @@ msgstr "ユーザーがログアウトすると、OAuth2 サーバからもロ #: settings/serializers/auth/oauth2.py:62 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OAuth2 service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OAuth2 service user attribute name" msgstr "" "ユーザー属性のマッピング、ここで `key` はこのシステムのユーザー属性名で、" "`value` は OAuth2 サービスのユーザー属性名です" @@ -7949,8 +8061,8 @@ msgstr "Ssl検証を無視する" #: settings/serializers/auth/oidc.py:41 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OIDC service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OIDC service user attribute name" msgstr "" "ユーザー属性のマッピング、ここで `key` はこのシステムのユーザー属性名で、" "`value` は OIDC サービスのユーザー属性名です" @@ -8087,8 +8199,8 @@ msgid "" "User attribute mapping, where the `key` is the SAML2 service user attribute " "name and the `value` is this system user attribute name" msgstr "" -"ユーザー属性マッピング(`key`はSAML2サービスのユーザー属性名、`value`は" -"このシステムのユーザー属性名)" +"ユーザー属性マッピング(`key`はSAML2サービスのユーザー属性名、`value`はこのシ" +"ステムのユーザー属性名)" #: settings/serializers/auth/saml2.py:43 msgid "When the user signs out, they also be logged out from the SAML2 server" @@ -8096,8 +8208,8 @@ msgstr "ユーザーがログアウトすると、SAML2サーバーからもロ #: settings/serializers/auth/slack.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Slack service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Slack service user attribute name" msgstr "" "ユーザー属性のマッピング、ここで `key` はこのシステムのユーザー属性名で、" "`value` は Slack サービスのユーザー属性名です" @@ -8134,7 +8246,7 @@ msgid "Template code" msgstr "テンプレートコード" #: settings/serializers/auth/sms.py:40 users/models/user/__init__.py:89 -#: users/serializers/user.py:159 +#: users/serializers/user.py:164 msgid "Phone" msgstr "電話" @@ -8191,7 +8303,10 @@ msgid "Enable SSO auth" msgstr "SSO Token認証の有効化" #: settings/serializers/auth/sso.py:17 -msgid "Other service can using SSO token login to JumpServer without password" +#, fuzzy +#| msgid "" +#| "Other service can using SSO token login to JumpServer without password" +msgid "Other service can using SSO token login to system without password" msgstr "" "他のサービスはパスワードなしでJumpServerへのSSOトークンログインを使用できます" @@ -8206,8 +8321,8 @@ msgstr "単位: 秒" #: settings/serializers/auth/wecom.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the WeCom service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the WeCom service user attribute name" msgstr "" "ユーザー属性のマッピング、ここで `key` はこのシステムのユーザー属性名で、" "`value` は エンタープライズ WeChat サービスのユーザー属性名です" @@ -9368,7 +9483,7 @@ msgstr "待つ:" msgid "The verification code has been sent" msgstr "確認コードが送信されました" -#: templates/_without_nav_base.html:46 +#: templates/_without_nav_base.html:51 msgid "Home page" msgstr "ホームページ" @@ -9631,31 +9746,31 @@ msgstr "同時実行可能" msgid "Hosts" msgstr "ホスト" -#: terminal/models/applet/applet.py:94 +#: terminal/models/applet/applet.py:102 #: terminal/models/virtualapp/virtualapp.py:66 #, python-brace-format msgid "Applet pkg not valid, Missing file {}" msgstr "無効なアプレット パッケージ、ファイル {} がありません" -#: terminal/models/applet/applet.py:113 +#: terminal/models/applet/applet.py:121 #, python-brace-format msgid "Load platform.yml failed: {}" msgstr "platform.ymlのロードに失敗しました:{}" -#: terminal/models/applet/applet.py:116 +#: terminal/models/applet/applet.py:124 msgid "Only support custom platform" msgstr "カスタムプラットフォームのみをサポート" -#: terminal/models/applet/applet.py:121 +#: terminal/models/applet/applet.py:129 msgid "Missing type in platform.yml" msgstr "platform.ymlにタイプがありません" -#: terminal/models/applet/applet.py:381 terminal/models/applet/host.py:36 +#: terminal/models/applet/applet.py:389 terminal/models/applet/host.py:36 #: terminal/models/applet/host.py:138 msgid "Hosting" msgstr "ホスト マシン" -#: terminal/models/applet/applet.py:387 +#: terminal/models/applet/applet.py:395 msgid "Applet Publication" msgstr "アプリケーションのリリース" @@ -9745,7 +9860,7 @@ msgstr "VNC ポート" #: terminal/models/component/endpoint.py:35 #: terminal/models/component/endpoint.py:115 -#: terminal/serializers/endpoint.py:63 terminal/serializers/storage.py:41 +#: 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" @@ -9959,8 +10074,8 @@ msgstr "コマンド及び録画記憶" #: terminal/notifications.py:279 terminal/tasks.py:212 #: xpack/plugins/cloud/api.py:182 -#: xpack/plugins/cloud/serializers/account.py:143 -#: xpack/plugins/cloud/serializers/account.py:146 +#: xpack/plugins/cloud/serializers/account.py:148 +#: xpack/plugins/cloud/serializers/account.py:151 msgid "Test failure: Account invalid" msgstr "テスト失敗: アカウントが無効" @@ -10082,7 +10197,8 @@ msgstr "既存の RDS 証明書" msgid "" "If not exist, the RDS will be in trial mode, and the trial period is 120 " "days. Detail" +"remote-desktop-services/rds-client-access-license\" " +"target=\"_blank\">Detail" msgstr "" "存在しない場合、RDSは試用モードで、試用期間は120日間です。>> 테스트 게이트웨이 계정 연결성 작업 시작" #: settings/serializers/auth/ldap.py:53 settings/serializers/auth/ldap_ha.py:35 #: settings/serializers/msg.py:37 settings/serializers/terminal.py:32 #: terminal/serializers/storage.py:123 terminal/serializers/storage.py:142 -#: users/forms/profile.py:22 users/serializers/user.py:148 +#: users/forms/profile.py:22 users/serializers/user.py:153 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/cloud/serializers/account_attrs.py:43 @@ -227,7 +227,7 @@ msgstr "업데이트" #: accounts/const/account.py:34 accounts/const/automation.py:115 #: accounts/serializers/automations/change_secret.py:171 audits/const.py:66 -#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:66 +#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:67 #: ops/const.py:77 terminal/const.py:81 xpack/plugins/cloud/const.py:55 msgid "Failed" msgstr "실패" @@ -349,14 +349,14 @@ msgstr "SFTP" #: accounts/const/automation.py:116 #: accounts/serializers/automations/change_secret.py:170 audits/const.py:65 #: audits/models.py:65 audits/signal_handlers/activity_log.py:34 -#: common/const/choices.py:65 ops/const.py:75 ops/serializers/celery.py:48 +#: common/const/choices.py:66 ops/const.py:75 ops/serializers/celery.py:48 #: terminal/const.py:80 terminal/models/session/sharing.py:119 #: tickets/views/approve.py:128 msgid "Success" msgstr "성공" -#: accounts/const/automation.py:117 common/const/choices.py:63 -#: common/const/choices.py:114 terminal/const.py:79 +#: accounts/const/automation.py:117 common/const/choices.py:64 +#: common/const/choices.py:127 terminal/const.py:79 msgid "Pending" msgstr "대기 중" @@ -364,7 +364,7 @@ msgstr "대기 중" msgid "Queued" msgstr "대기 중" -#: accounts/const/automation.py:122 common/const/choices.py:62 +#: accounts/const/automation.py:122 common/const/choices.py:63 msgid "Ready" msgstr "준비 중" @@ -376,7 +376,7 @@ msgstr "처리 중" msgid "Can login" msgstr "로그인 가능" -#: accounts/const/automation.py:128 users/serializers/user.py:254 +#: accounts/const/automation.py:128 users/serializers/user.py:259 msgid "Superuser" msgstr "슈퍼 사용자" @@ -405,7 +405,7 @@ msgid "Default tablespace" msgstr "기본 테이블 공간" #: accounts/const/automation.py:135 rbac/models/role.py:46 -#: rbac/models/rolebinding.py:52 users/models/user/__init__.py:79 +#: rbac/models/rolebinding.py:53 users/models/user/__init__.py:79 msgid "Role" msgstr "역할" @@ -414,7 +414,7 @@ msgid "Perms" msgstr "권한" #: accounts/const/automation.py:137 perms/serializers/permission.py:56 -#: users/serializers/user.py:245 +#: users/serializers/user.py:250 msgid "Groups" msgstr "사용자 그룹" @@ -788,7 +788,7 @@ msgstr "종료 날짜" #: assets/models/automations/base.py:137 #: assets/serializers/automations/base.py:47 audits/models.py:224 #: audits/reporting.py:607 audits/serializers.py:77 ops/models/base.py:49 -#: ops/models/job.py:233 terminal/models/applet/applet.py:382 +#: ops/models/job.py:233 terminal/models/applet/applet.py:390 #: terminal/models/applet/host.py:140 terminal/models/component/status.py:30 #: terminal/models/virtualapp/virtualapp.py:99 #: terminal/serializers/applet.py:19 terminal/serializers/applet_host.py:163 @@ -803,7 +803,7 @@ msgstr "상태" #: accounts/serializers/account/account.py:297 assets/const/automation.py:9 #: authentication/templates/authentication/passkey.html:177 #: authentication/views/base.py:43 authentication/views/base.py:44 -#: authentication/views/base.py:45 common/const/choices.py:67 +#: authentication/views/base.py:45 common/const/choices.py:68 #: settings/templates/ldap/_msg_import_ldap_user.html:26 msgid "Error" msgstr "오류" @@ -898,8 +898,9 @@ msgstr "중복 비밀번호" #: accounts/templates/accounts/push_account_report.html:79 #: accounts/templates/accounts/push_account_report.html:119 #: acls/serializers/base.py:19 acls/serializers/base.py:50 audits/models.py:204 -#: audits/reporting.py:241 authentication/forms.py:21 -#: authentication/forms.py:23 authentication/models/temp_token.py:10 +#: audits/reporting.py:241 authentication/backends/cert/forms.py:7 +#: authentication/forms.py:21 authentication/forms.py:23 +#: authentication/models/temp_token.py:10 #: authentication/serializers/connect_token_secret.py:43 #: authentication/serializers/connect_token_secret.py:53 #: authentication/templates/authentication/_msg_different_city.html:9 @@ -1056,7 +1057,7 @@ msgstr "권한 계정" #: assets/models/cmd_filter.py:39 assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:129 reports/models.py:18 #: terminal/models/applet/applet.py:41 -#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:257 +#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:262 msgid "Is active" msgstr "활성화" @@ -1072,7 +1073,7 @@ msgstr "플랫폼" msgid "Push params" msgstr "계정 푸시 매개변수" -#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:403 +#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:404 msgid "Account template" msgstr "계정 템플릿" @@ -1165,7 +1166,7 @@ msgstr "계정 변경 정보" msgid "Change secret or push account failed information" msgstr "비밀번호 변경 또는 계정 푸시 실패 정보" -#: accounts/risk_handlers.py:17 common/const/choices.py:116 +#: accounts/risk_handlers.py:17 common/const/choices.py:129 msgid "Ignored" msgstr "무시" @@ -1321,7 +1322,7 @@ msgstr "ID" #: authentication/notifications.py:16 authentication/notifications.py:55 #: notifications/models/notification.py:12 #: perms/api/user_permission/mixin.py:58 perms/models/asset_permission.py:63 -#: rbac/builtin.py:134 rbac/models/rolebinding.py:49 +#: rbac/builtin.py:134 rbac/models/rolebinding.py:50 #: rbac/serializers/rolebinding.py:17 terminal/backends/command/models.py:16 #: terminal/models/session/session.py:27 terminal/models/session/sharing.py:34 #: terminal/notifications.py:168 terminal/notifications.py:235 @@ -1329,8 +1330,8 @@ msgstr "ID" #: terminal/templates/terminal/_msg_command_warning.html:9 #: terminal/templates/terminal/_msg_session_sharing.html:6 #: tickets/models/comment.py:21 tickets/serializers/flow.py:15 -#: users/const.py:14 users/models/user/__init__.py:298 -#: users/models/user/__init__.py:325 +#: users/const.py:14 users/models/user/__init__.py:303 +#: users/models/user/__init__.py:330 msgid "User" msgstr "사용자" @@ -1365,7 +1366,7 @@ msgstr "IP 화이트리스트" #: assets/models/cmd_filter.py:88 common/db/models.py:36 ops/models/adhoc.py:25 #: ops/models/job.py:165 ops/models/playbook.py:31 rbac/models/role.py:37 #: settings/models.py:43 terminal/models/applet/applet.py:46 -#: terminal/models/applet/applet.py:383 terminal/models/applet/host.py:143 +#: terminal/models/applet/applet.py:391 terminal/models/applet/host.py:143 #: terminal/models/component/endpoint.py:29 #: terminal/models/component/endpoint.py:117 #: terminal/models/session/session.py:44 @@ -1653,7 +1654,7 @@ msgstr "" "해야 합니다. 시스템은 계정 저장소 - 기록 제한 설정에 따라 매일 새벽 2시에 초" "과된 수량의 계정 기록을 정리합니다." -#: accounts/tasks/remove_account.py:89 +#: accounts/tasks/remove_account.py:91 msgid "Remove historical accounts that are out of range." msgstr "범위를 초과한 역사적인 계정을 삭제합니다." @@ -1725,7 +1726,7 @@ msgstr "작업 이름" #: accounts/templates/accounts/push_account_report.html:22 #: assets/models/automations/base.py:143 audits/models.py:66 #: ops/models/base.py:55 ops/models/celery.py:89 ops/models/job.py:241 -#: ops/templates/ops/celery_task_log.html:101 +#: ops/templates/ops/celery_task_log.html:154 #: perms/models/asset_permission.py:78 settings/serializers/feature.py:29 #: settings/templates/ldap/_msg_import_ldap_user.html:5 #: terminal/models/applet/host.py:141 terminal/models/session/session.py:42 @@ -1911,7 +1912,7 @@ msgstr "승인자" #: acls/models/base.py:81 perms/serializers/permission.py:54 #: tickets/models/flow.py:23 users/models/preference.py:16 -#: users/serializers/group.py:21 users/serializers/user.py:424 +#: users/serializers/group.py:21 users/serializers/user.py:429 msgid "Users" msgstr "사용자" @@ -1937,7 +1938,7 @@ msgid "Command" msgstr "명령" #: acls/models/command_acl.py:17 assets/models/cmd_filter.py:59 -#: xpack/plugins/cloud/models.py:369 +#: xpack/plugins/cloud/models.py:370 msgid "Regex" msgstr "정규 표현식" @@ -2026,7 +2027,7 @@ msgstr "규칙" msgid "Login acl" msgstr "로그인 접근 제어" -#: acls/models/login_acl.py:27 tickets/const.py:11 +#: acls/models/login_acl.py:30 tickets/const.py:11 msgid "Login confirm" msgstr "로그인 재검토" @@ -2148,7 +2149,7 @@ msgstr "" #: authentication/templates/authentication/_msg_oauth_bind.html:12 #: authentication/templates/authentication/_msg_rest_password_success.html:8 #: authentication/templates/authentication/_msg_rest_public_key_success.html:8 -#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:405 +#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:406 msgid "IP" msgstr "IP" @@ -2210,15 +2211,15 @@ msgstr "최근에 사용자가 로그인했음을 알려드립니다:" msgid "User details" msgstr "사용자 세부정보" -#: assets/api/asset/asset.py:166 +#: assets/api/asset/asset.py:168 msgid "Cannot create asset directly, you should create a host or other" msgstr "직접 자산을 생성할 수 없습니다. 호스트나 다른 자산을 생성해야 합니다." -#: assets/api/asset/asset.py:173 +#: assets/api/asset/asset.py:175 msgid "The number of assets exceeds the limit of 5000" msgstr "자산 수가 5000을 초과했습니다." -#: assets/api/asset/asset.py:179 +#: assets/api/asset/asset.py:181 #, fuzzy #| msgid "The number of assets exceeds the limit of 5000" msgid "The number of assets exceeds the license limit" @@ -2237,6 +2238,11 @@ msgstr "루트 노드를 삭제할 수 없습니다 ({})" msgid "Deletion failed and the node contains assets" msgstr "삭제 실패, 노드에 자산이 포함되어 있습니다." +#: assets/api/node.py:99 +#, python-brace-format +msgid "Node {} is an ancestor of node {}, can't be added as its child" +msgstr "" + #: assets/api/tree.py:48 assets/serializers/node.py:42 msgid "The same level node name cannot be the same" msgstr "동급 노드 이름은 중복될 수 없습니다." @@ -2254,29 +2260,29 @@ msgstr "자산 관리" msgid "Task: {} finished" msgstr "작업: {} 완료" -#: assets/automations/base/manager.py:340 +#: assets/automations/base/manager.py:341 #, python-brace-format msgid " - Platform {} ansible disabled" msgstr "- 플랫폼 {} Ansible이 비활성화되어 있어 작업을 실행할 수 없습니다." -#: assets/automations/base/manager.py:555 +#: assets/automations/base/manager.py:556 msgid ">>> Task preparation phase" msgstr ">>> 작업 준비 단계" -#: assets/automations/base/manager.py:559 +#: assets/automations/base/manager.py:560 #, python-brace-format msgid ">>> Executing tasks in batches, total {runner_count}" msgstr ">>> 작업을 분할 실행합니다. 총 {runner_count}" -#: assets/automations/base/manager.py:564 +#: assets/automations/base/manager.py:565 msgid ">>> Start executing tasks" msgstr ">>> 작업 실행 시작" -#: assets/automations/base/manager.py:566 +#: assets/automations/base/manager.py:567 msgid ">>> No tasks need to be executed" msgstr ">>> 실행할 작업이 없습니다." -#: assets/automations/base/manager.py:570 +#: assets/automations/base/manager.py:571 #, python-brace-format msgid ">>> Begin executing batch {index} of tasks" msgstr ">>> {index}번째 배치 작업 실행 시작" @@ -2676,7 +2682,7 @@ msgid "Port" msgstr "포트" #: assets/models/asset/common.py:167 assets/serializers/asset/common.py:175 -#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:59 +#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:69 msgid "Address" msgstr "주소" @@ -2684,12 +2690,12 @@ msgstr "주소" #: assets/serializers/asset/common.py:151 #: authentication/backends/passkey/models.py:12 #: authentication/serializers/connect_token_secret.py:130 -#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:399 +#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:400 msgid "Platform" msgstr "플랫폼" #: assets/models/asset/common.py:173 assets/models/zone.py:22 -#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:401 +#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:402 msgid "Zone" msgstr "도메인" @@ -2758,9 +2764,9 @@ msgid "Proxy" msgstr "프록시." #: assets/models/automations/base.py:23 assets/models/cmd_filter.py:32 -#: assets/models/node.py:553 ops/models/job.py:158 +#: assets/models/node.py:560 ops/models/job.py:158 #: perms/models/asset_permission.py:72 tickets/models/ticket/apply_asset.py:15 -#: xpack/plugins/cloud/models.py:400 +#: xpack/plugins/cloud/models.py:401 msgid "Node" msgstr "노드." @@ -2784,7 +2790,7 @@ msgstr "자산 자동화 작업" #: assets/models/automations/base.py:140 assets/models/cmd_filter.py:41 #: authentication/serializers/token.py:134 common/db/models.py:34 #: ops/models/base.py:54 ops/models/job.py:240 -#: users/models/user/__init__.py:328 +#: users/models/user/__init__.py:333 msgid "Date created" msgstr "생성 날짜" @@ -2873,7 +2879,7 @@ msgstr "게이트웨이" msgid "System" msgstr "시스템" -#: assets/models/label.py:19 assets/models/node.py:539 +#: assets/models/label.py:19 assets/models/node.py:546 #: assets/serializers/cagegory.py:11 assets/serializers/cagegory.py:18 #: assets/serializers/cagegory.py:24 #: authentication/models/connection_token.py:35 @@ -2888,7 +2894,7 @@ msgstr "값" #: assets/serializers/platform.py:160 #: authentication/serializers/connect_token_secret.py:136 #: common/serializers/common.py:85 labels/serializers.py:45 -#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:404 +#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:405 msgid "Label" msgstr "태그" @@ -2904,27 +2910,27 @@ msgstr "사용자 정의 메모" msgid "My assets" msgstr "내 자산" -#: assets/models/node.py:168 +#: assets/models/node.py:172 msgid "New node" msgstr "새 노드" -#: assets/models/node.py:467 audits/backends/db.py:85 audits/backends/db.py:86 +#: assets/models/node.py:474 audits/backends/db.py:85 audits/backends/db.py:86 msgid "empty" msgstr "비어 있음" -#: assets/models/node.py:538 perms/models/perm_node.py:28 +#: assets/models/node.py:545 perms/models/perm_node.py:28 msgid "Key" msgstr "키" -#: assets/models/node.py:540 assets/serializers/node.py:20 +#: assets/models/node.py:547 assets/serializers/node.py:20 msgid "Full value" msgstr "전체 이름" -#: assets/models/node.py:544 perms/models/perm_node.py:30 +#: assets/models/node.py:551 perms/models/perm_node.py:30 msgid "Parent key" msgstr "ssh 개인 키" -#: assets/models/node.py:556 +#: assets/models/node.py:563 msgid "Can match node" msgstr "개별 노드와 일치" @@ -3102,7 +3108,7 @@ msgstr "" #: authentication/serializers/connect_token_secret.py:30 #: authentication/serializers/connect_token_secret.py:77 #: perms/models/asset_permission.py:76 perms/serializers/permission.py:68 -#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:402 +#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:403 #: xpack/plugins/cloud/serializers/task.py:36 msgid "Protocols" msgstr "프로토콜 그룹" @@ -3548,7 +3554,7 @@ msgid "Symlink" msgstr "심볼릭 링크 생성" #: audits/const.py:18 audits/const.py:29 -#: ops/templates/ops/celery_task_log.html:86 +#: ops/templates/ops/celery_task_log.html:139 #: terminal/api/session/session.py:159 msgid "Download" msgstr "다운로드" @@ -3577,7 +3583,9 @@ msgstr "내보내기" msgid "Connect" msgstr "연결" -#: audits/const.py:31 authentication/templates/authentication/login.html:334 +#: audits/const.py:31 +#: authentication/templates/authentication/cert_login.html:232 +#: authentication/templates/authentication/login.html:334 #: authentication/templates/authentication/login.html:408 #: templates/_header_bar.html:101 #: xpack/plugins/interface/templates/login_i18n.html:21 @@ -4371,24 +4379,24 @@ msgstr "얼굴 인식 실패" msgid "Current user not support mfa type: {}" msgstr "현재 사용자는 MFA 유형을 지원하지 않습니다: {}" -#: authentication/api/password.py:34 terminal/api/session/session.py:347 +#: authentication/api/password.py:37 terminal/api/session/session.py:347 #: users/views/profile/reset.py:63 #, python-brace-format msgid "User does not exist: {}" msgstr "사용자가 존재하지 않습니다: {}" -#: authentication/api/password.py:34 users/views/profile/reset.py:166 +#: authentication/api/password.py:37 users/views/profile/reset.py:166 msgid "No user matched" msgstr "사용자와 일치하지 않음" -#: authentication/api/password.py:38 +#: authentication/api/password.py:41 #, python-brace-format msgid "" "The user is from {}, please go to the corresponding system to change the " "password" msgstr "사용자가 {}에서 옵니다. 해당 시스템에서 비밀번호를 변경하세요" -#: authentication/api/password.py:69 +#: authentication/api/password.py:72 #: authentication/templates/authentication/login.html:400 #: users/templates/users/forgot_password.html:41 #: users/templates/users/forgot_password.html:42 @@ -4398,7 +4406,7 @@ msgstr "사용자가 {}에서 옵니다. 해당 시스템에서 비밀번호를 msgid "Forgot password" msgstr "비밀번호를 잊으셨나요" -#: authentication/api/password.py:70 authentication/mfa/email.py:42 +#: authentication/api/password.py:73 authentication/mfa/email.py:42 #, python-brace-format msgid "The validity period of the verification code is {} minute" msgstr "인증 코드의 유효 기간은 {} 분입니다." @@ -4411,10 +4419,29 @@ msgstr "인증 관리" msgid "CAS Error" msgstr "CAS 오류" -#: authentication/backends/custom.py:60 -#: authentication/backends/oauth2/backends.py:158 -msgid "User invalid, disabled or expired" -msgstr "사용자가 유효하지 않거나 비활성 상태이거나 만료되었습니다" +#: authentication/backends/cert/api.py:57 +#, fuzzy +#| msgid "LDAP authentication is not enabled" +msgid "Certificate enrollment is not enabled" +msgstr "LDAP 인증이 활성화되지 않았습니다" + +#: authentication/backends/cert/api.py:62 +#, fuzzy +#| msgid "type is required" +msgid "CSR is required" +msgstr "유형: 이 필드는 필수입니다." + +#: authentication/backends/cert/api.py:68 +#, fuzzy +#| msgid "Authentication failed" +msgid "Certificate signing failed" +msgstr "인증 실패" + +#: authentication/backends/cert/views.py:97 +#, fuzzy +#| msgid "Invalid data" +msgid "Invalid credentials" +msgstr "유효하지 않은 데이터" #: authentication/backends/drf.py:61 msgid "Invalid token header. No credentials provided." @@ -4667,16 +4694,16 @@ msgstr "귀하의 비밀번호가 유효하지 않습니다" msgid "Please wait for %s seconds before retry" msgstr "%s 초 후에 다시 시도해주세요." -#: authentication/errors/redirect.py:85 authentication/mixins.py:436 +#: authentication/errors/redirect.py:85 authentication/mixins.py:445 #: users/views/profile/reset.py:224 msgid "Your password is too simple, please change it for security" msgstr "비밀번호가 너무 간단합니다. 보안을 위해 수정해주세요." -#: authentication/errors/redirect.py:93 authentication/mixins.py:445 +#: authentication/errors/redirect.py:93 authentication/mixins.py:454 msgid "You should to change your password before login" msgstr "로그인 완료 전에 비밀번호를 먼저 수정해주세요." -#: authentication/errors/redirect.py:101 authentication/mixins.py:454 +#: authentication/errors/redirect.py:101 authentication/mixins.py:463 msgid "Your password has expired, please reset before logging in" msgstr "당신의 비밀번호가 만료되었습니다. 수정 후 로그인해주세요." @@ -4805,11 +4832,11 @@ msgstr "" "관리자가 '존재하는 사용자만 로그인 허용'을 활성화했습니다. 현재 사용자가 사용" "자 목록에 없습니다. 관리자에게 문의하십시오." -#: authentication/mixins.py:184 +#: authentication/mixins.py:187 msgid "User is invalid" msgstr "무효한 사용자" -#: authentication/mixins.py:201 +#: authentication/mixins.py:204 #, python-brace-format msgid "" " The administrator has enabled 'Only allow login from user source'. \n" @@ -4819,12 +4846,12 @@ msgstr "" "관리자가 '사용자 출처에서만 로그인 허용'을 활성화했습니다. 현재 사용자 출처" "는 {}입니다. 관리자에게 문의하십시오." -#: authentication/mixins.py:382 +#: authentication/mixins.py:391 #, python-brace-format msgid "The MFA type ({}) is not enabled" msgstr "해당 MFA ({}) 방식이 활성화되지 않았습니다." -#: authentication/mixins.py:424 +#: authentication/mixins.py:433 msgid "Please change your password" msgstr "비밀번호를 수정하십시오." @@ -5016,7 +5043,7 @@ msgstr "Action" #: authentication/serializers/connection_token.py:46 #: perms/serializers/permission.py:66 perms/serializers/permission.py:87 -#: users/serializers/user.py:127 users/serializers/user.py:261 +#: users/serializers/user.py:127 users/serializers/user.py:266 msgid "Is expired" msgstr "이미 만료" @@ -5058,13 +5085,13 @@ msgstr "SSH 키가 유효하지 않습니다" #: authentication/serializers/token.py:93 perms/serializers/permission.py:65 #: perms/serializers/permission.py:88 users/serializers/user.py:128 -#: users/serializers/user.py:258 +#: users/serializers/user.py:263 msgid "Is valid" msgstr "유효한가요" #: authentication/serializers/token.py:131 ops/models/adhoc.py:26 #: ops/models/playbook.py:34 ops/serializers/mixin.py:10 rbac/models/role.py:31 -#: rbac/models/rolebinding.py:46 rbac/serializers/role.py:12 +#: rbac/models/rolebinding.py:47 rbac/serializers/role.py:12 #: settings/serializers/auth/oauth2.py:37 msgid "Scope" msgstr "범위" @@ -5163,7 +5190,7 @@ msgstr "코드 오류" #: authentication/templates/authentication/_msg_oauth_bind.html:3 #: authentication/templates/authentication/_msg_reset_password.html:3 #: authentication/templates/authentication/_msg_reset_password_code.html:9 -#: jumpserver/conf.py:555 +#: jumpserver/conf.py:558 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:32 #: users/templates/users/_msg_account_expire_reminder.html:4 @@ -5273,6 +5300,87 @@ msgstr "취소" msgid "Cancel" msgstr "재시도" +#: authentication/templates/authentication/cert_login.html:190 +#, fuzzy +#| msgid "Multi-Factor Authentication" +msgid "Certificate Authentication" +msgstr "인증" + +#: authentication/templates/authentication/cert_login.html:195 +#: authentication/templates/authentication/cert_login.html:250 +msgid "Loading USB Key driver..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:210 +msgid "Insert USB Key to auto-fetch" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:238 +#, fuzzy +#| msgid "More login options" +msgid "Other login methods" +msgstr "기타 로그인 방법" + +#: authentication/templates/authentication/cert_login.html:251 +msgid "Detecting USB Key..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:252 +msgid "USB Key connected" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:253 +#, fuzzy +#| msgid "Please enter SMS code" +msgid "Please insert USB Key" +msgstr "문자 메시지 인증 코드를 입력해 주세요" + +#: authentication/templates/authentication/cert_login.html:254 +#, fuzzy +#| msgid "Account unavailable" +msgid "Driver unavailable" +msgstr "계정 무효" + +#: authentication/templates/authentication/cert_login.html:255 +msgid "USB Key SDK initialization failed" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:256 +msgid "Verifying PIN..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:257 +#, fuzzy +#| msgid "Date verified" +msgid "PIN verified" +msgstr "검증 날짜" + +#: authentication/templates/authentication/cert_login.html:258 +#, fuzzy +#| msgid "OTP verification code" +msgid "PIN verification failed" +msgstr "가상 MFA 인증 코드" + +#: authentication/templates/authentication/cert_login.html:259 +msgid "Signing challenge code..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:260 +#, fuzzy +#| msgid "Signing key" +msgid "Signing failed" +msgstr "서명 키" + +#: authentication/templates/authentication/cert_login.html:261 +msgid "Failed to retrieve certificate" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:262 +#, fuzzy +#| msgid "Your account has expired, please contact the administrator." +msgid "No certificate detected, please contact administrator" +msgstr "귀하의 계정이 만료되었습니다. 관리자에게 문의하시기 바랍니다." + #: authentication/templates/authentication/face_capture.html:14 msgid "Retry" msgstr "" @@ -5344,6 +5452,10 @@ msgstr "재시도 하시겠습니까?" msgid "LAN" msgstr "지역 네트워크" +#: authentication/utils.py:150 +msgid "CERT" +msgstr "" + #: authentication/views/base.py:71 #: perms/templates/perms/_msg_permed_items_expire.html:18 msgid "If you have any question, please contact the administrator" @@ -5508,47 +5620,47 @@ msgstr "密码로 로그인한 후 기업 WeChat을 연결해 주시기 바랍 msgid "Request file format may be wrong" msgstr "업로드한 파일 형식이 잘못되었거나 다른 유형의 리소스 파일입니다." -#: common/const/choices.py:40 +#: common/const/choices.py:41 msgid "China" msgstr "중국" -#: common/const/choices.py:57 +#: common/const/choices.py:58 msgid "Manual" msgstr "수동으로 트리거" -#: common/const/choices.py:58 +#: common/const/choices.py:59 msgid "Timing" msgstr "예약 트리거" -#: common/const/choices.py:64 ops/const.py:74 +#: common/const/choices.py:65 ops/const.py:74 msgid "Running" msgstr "실행 중" -#: common/const/choices.py:68 +#: common/const/choices.py:69 msgid "Canceled" msgstr "취소" -#: common/const/choices.py:115 +#: common/const/choices.py:128 msgid "Confirmed" msgstr "확인" -#: common/const/choices.py:123 terminal/models/applet/applet.py:31 +#: common/const/choices.py:136 terminal/models/applet/applet.py:31 msgid "Community edition" msgstr "커뮤니티 버전" -#: common/const/choices.py:124 +#: common/const/choices.py:137 msgid "Basic edition" msgstr "기업 기본 버전" -#: common/const/choices.py:125 +#: common/const/choices.py:138 msgid "Standard edition" msgstr "기업 표준 버전" -#: common/const/choices.py:126 +#: common/const/choices.py:139 msgid "Professional edition" msgstr "기업 전문 버전" -#: common/const/choices.py:127 +#: common/const/choices.py:140 msgid "Ultimate edition" msgstr "기업 플래그십 버전" @@ -6060,24 +6172,24 @@ msgstr "제공된 메시지 코드가 유효하지 않거나 만료되었습니 msgid "The message code provided is invalid or has expired" msgstr "인증 코드는: {code}" -#: jumpserver/conf.py:549 +#: jumpserver/conf.py:552 #, python-brace-format msgid "The verification code is: {code}" msgstr "인증 코드: {code}" -#: jumpserver/conf.py:554 +#: jumpserver/conf.py:557 msgid "Create account successfully" msgstr "귀하의 계정이 성공적으로 생성되었습니다" -#: jumpserver/conf.py:556 +#: jumpserver/conf.py:559 msgid "Your account has been created successfully" msgstr "JumpServer 오픈소스 방화벽" -#: jumpserver/context_processor.py:17 +#: jumpserver/context_processor.py:16 msgid "JumpServer - An open-source PAM" msgstr "Flower 서비스가 사용 불가능합니다, 확인하십시오" -#: jumpserver/context_processor.py:37 +#: jumpserver/context_processor.py:31 msgid "FIT2CLOUD" msgstr "" @@ -6811,7 +6923,7 @@ msgid "Please save in a org" msgstr "저장하기 전에 조직을 선택해 주십시오" #: orgs/mixins/models.py:58 orgs/mixins/serializers.py:25 orgs/models.py:91 -#: rbac/const.py:7 rbac/models/rolebinding.py:56 +#: rbac/const.py:7 rbac/models/rolebinding.py:57 #: rbac/serializers/rolebinding.py:44 settings/serializers/auth/base.py:53 #: terminal/notifications.py:309 #: terminal/templates/terminal/_msg_command_warning.html:27 @@ -7252,26 +7364,26 @@ msgstr "시스템 역할" msgid "Organization role" msgstr "조직 역할" -#: rbac/models/rolebinding.py:62 +#: rbac/models/rolebinding.py:63 msgid "Role binding" msgstr "역할 바인딩" -#: rbac/models/rolebinding.py:168 +#: rbac/models/rolebinding.py:169 msgid "All organizations" msgstr "모든 조직" -#: rbac/models/rolebinding.py:200 +#: rbac/models/rolebinding.py:201 msgid "" "User last role in org, can not be delete, you can remove user from org " "instead" msgstr "" "사용자의 마지막 역할은 삭제할 수 없으며, 사용자를 조직에서 제거할 수 있습니다" -#: rbac/models/rolebinding.py:207 +#: rbac/models/rolebinding.py:208 msgid "Organization role binding" msgstr "조직 역할 바인딩" -#: rbac/models/rolebinding.py:222 +#: rbac/models/rolebinding.py:223 msgid "System role binding" msgstr "시스템 역할 바인딩" @@ -7336,7 +7448,7 @@ msgid "Storage" msgstr "저장소" #: rbac/tree.py:64 terminal/models/applet/applet.py:53 -#: terminal/models/applet/applet.py:379 terminal/models/applet/host.py:30 +#: terminal/models/applet/applet.py:387 terminal/models/applet/host.py:30 #: terminal/serializers/applet.py:16 msgid "Applet" msgstr "원격 애플리케이션" @@ -7399,51 +7511,51 @@ msgstr "접근 토큰 철회" msgid "Range days" msgstr "수정자" -#: reports/views.py:20 +#: reports/views.py:19 msgid "User login report" msgstr "사용자 로그인 보고서" -#: reports/views.py:24 +#: reports/views.py:23 msgid "User change password report" msgstr "사용자 비밀번호 변경 보고서" -#: reports/views.py:28 +#: reports/views.py:27 msgid "Asset statistics report" msgstr "자산 통계 보고서" -#: reports/views.py:32 +#: reports/views.py:31 msgid "Asset activity report" msgstr "자산 활동 보고서" -#: reports/views.py:36 +#: reports/views.py:35 msgid "Account statistics report" msgstr "계정 통계 보고서" -#: reports/views.py:40 +#: reports/views.py:39 msgid "Account automation report" msgstr "계정 자동화 보고서" -#: reports/views.py:44 +#: reports/views.py:43 msgid "ConsoleDashboard" msgstr "콘솔 대시보드" -#: reports/views.py:48 +#: reports/views.py:47 msgid "AuditsDashboard" msgstr "감사 대시보드" -#: reports/views.py:52 +#: reports/views.py:51 msgid "PamDashboard" msgstr "PAM 대시보드" -#: reports/views.py:56 +#: reports/views.py:55 msgid "ChangeSecretDashboard" msgstr "계정 비밀번호 변경 대시보드" -#: reports/views.py:191 +#: reports/views.py:190 msgid "Failed to send email: " msgstr "메일 전송 실패" -#: reports/views.py:192 +#: reports/views.py:191 msgid "Email sent successfully to " msgstr "메일 전송 성공" @@ -7715,8 +7827,8 @@ msgid "" "User attribute mapping, where the `key` is the CAS service user attribute " "name and the `value` is this system user attribute name" msgstr "" -"사용자 속성 매핑에서 `key`는 CAS 서비스의 사용자 속성 이름이고, `value`는 " -"이 시스템 사용자 속성 이름입니다." +"사용자 속성 매핑에서 `key`는 CAS 서비스의 사용자 속성 이름이고, `value`는 이 " +"시스템 사용자 속성 이름입니다." #: settings/serializers/auth/dingtalk.py:16 msgid "Dingtalk" @@ -7724,16 +7836,16 @@ msgstr "딩딩 인증 활성화" #: settings/serializers/auth/dingtalk.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the DingTalk service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the DingTalk service user attribute name" msgstr "" "사용자 속성 매핑에서 `key`는 이 시스템 사용자 속성 이름이고, `value`는 딩딩 " "서비스의 사용자 속성 이름입니다." #: settings/serializers/auth/feishu.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the FeiShu service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the FeiShu service user attribute name" msgstr "" "사용자 속성 매핑에서 `key`는 이 시스템 사용자 속성 이름이고, `value`는 페이" "서 서비스의 사용자 속성 이름입니다." @@ -7744,8 +7856,8 @@ msgstr "Lark" #: settings/serializers/auth/lark.py:19 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Lark service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Lark service user attribute name" msgstr "" "사용자 속성 매핑에서 `key`는 이 시스템 사용자 속성 이름이고, `value`는 Lark " "서비스의 사용자 속성 이름입니다." @@ -7792,8 +7904,8 @@ msgstr "가능한 옵션은 (cn 또는 uid 또는 sAMAccountName=%(user)s)입니 #: settings/serializers/auth/ldap.py:69 settings/serializers/auth/ldap_ha.py:51 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the LDAP service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the LDAP service user attribute name" msgstr "" "사용자 속성 매핑에서 `key`는 이 시스템 사용자 속성 이름이고, `value`는 LDAP " "서비스 사용자 속성 이름입니다." @@ -7901,8 +8013,8 @@ msgstr "사용자가 로그아웃할 때, 그들은 OAuth2 서버에서도 로 #: settings/serializers/auth/oauth2.py:62 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OAuth2 service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OAuth2 service user attribute name" msgstr "" "사용자 속성 매핑, 여기서 `key`는 이 시스템 사용자 속성 이름이고, `value`는 " "OAuth2 서비스 사용자 속성 이름입니다" @@ -7938,8 +8050,8 @@ msgstr "SSL 인증서 검증 무시" #: settings/serializers/auth/oidc.py:41 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OIDC service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OIDC service user attribute name" msgstr "" "사용자 속성 매핑, 여기서 `key`는 이 시스템 사용자 속성 이름이고, `value`는 " "OIDC 서비스 사용자 속성 이름입니다" @@ -8084,8 +8196,8 @@ msgstr "사용자가 로그아웃하면 SAML2 서버에서도 로그아웃됩니 #: settings/serializers/auth/slack.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Slack service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Slack service user attribute name" msgstr "" "사용자 속성 매핑, 여기서 `key`는 이 시스템 사용자 속성 이름이고, `value`는 " "Slack 서비스 사용자 속성 이름입니다." @@ -8122,7 +8234,7 @@ msgid "Template code" msgstr "템플릿" #: settings/serializers/auth/sms.py:40 users/models/user/__init__.py:89 -#: users/serializers/user.py:159 +#: users/serializers/user.py:164 msgid "Phone" msgstr "휴대폰" @@ -8179,7 +8291,10 @@ msgid "Enable SSO auth" msgstr "SSO 토큰 인증 활성화" #: settings/serializers/auth/sso.py:17 -msgid "Other service can using SSO token login to JumpServer without password" +#, fuzzy +#| msgid "" +#| "Other service can using SSO token login to JumpServer without password" +msgid "Other service can using SSO token login to system without password" msgstr "" "기타 시스템은 SSO 토큰을 통해 JumpServer에 연동하여 로그인 과정을 생략할 수 " "있습니다." @@ -8195,11 +8310,11 @@ msgstr "단위: 초" #: settings/serializers/auth/wecom.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the WeCom service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the WeCom service user attribute name" msgstr "" -"사용자 속성 매핑, 여기서 `key`는 이 시스템 사용자 속성 이름이고, `value`는 " -"기업 WeChat 서비스 사용자 속성 이름입니다." +"사용자 속성 매핑, 여기서 `key`는 이 시스템 사용자 속성 이름이고, `value`는 기" +"업 WeChat 서비스 사용자 속성 이름입니다." #: settings/serializers/basic.py:11 msgid "Site URL" @@ -9363,7 +9478,7 @@ msgstr "대기 중:" msgid "The verification code has been sent" msgstr "인증 코드가 전송되었습니다." -#: templates/_without_nav_base.html:46 +#: templates/_without_nav_base.html:51 msgid "Home page" msgstr "홈페이지" @@ -9625,31 +9740,31 @@ msgstr "동시 가능" msgid "Hosts" msgstr "주최자" -#: terminal/models/applet/applet.py:94 +#: terminal/models/applet/applet.py:102 #: terminal/models/virtualapp/virtualapp.py:66 #, python-brace-format msgid "Applet pkg not valid, Missing file {}" msgstr "Applet pkg 유효하지 않음, 파일 {}가 없습니다" -#: terminal/models/applet/applet.py:113 +#: terminal/models/applet/applet.py:121 #, python-brace-format msgid "Load platform.yml failed: {}" msgstr "platform.yml 로드 실패: {}" -#: terminal/models/applet/applet.py:116 +#: terminal/models/applet/applet.py:124 msgid "Only support custom platform" msgstr "사용자 정의 플랫폼만 지원합니다" -#: terminal/models/applet/applet.py:121 +#: terminal/models/applet/applet.py:129 msgid "Missing type in platform.yml" msgstr "platform.yml에 유형이 누락되었습니다" -#: terminal/models/applet/applet.py:381 terminal/models/applet/host.py:36 +#: terminal/models/applet/applet.py:389 terminal/models/applet/host.py:36 #: terminal/models/applet/host.py:138 msgid "Hosting" msgstr "호스트 머신" -#: terminal/models/applet/applet.py:387 +#: terminal/models/applet/applet.py:395 msgid "Applet Publication" msgstr "애플리케이션 배포" @@ -9739,7 +9854,7 @@ msgstr "VNC 포트" #: terminal/models/component/endpoint.py:35 #: terminal/models/component/endpoint.py:115 -#: terminal/serializers/endpoint.py:63 terminal/serializers/storage.py:41 +#: 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" @@ -9953,8 +10068,8 @@ msgstr "명령 및 녹화 저장" #: terminal/notifications.py:279 terminal/tasks.py:212 #: xpack/plugins/cloud/api.py:182 -#: xpack/plugins/cloud/serializers/account.py:143 -#: xpack/plugins/cloud/serializers/account.py:146 +#: xpack/plugins/cloud/serializers/account.py:148 +#: xpack/plugins/cloud/serializers/account.py:151 msgid "Test failure: Account invalid" msgstr "테스트 실패: 계정이 유효하지 않음" @@ -10075,7 +10190,8 @@ msgstr "이미 RDS 라이센스 보유" msgid "" "If not exist, the RDS will be in trial mode, and the trial period is 120 " "days. Detail" +"remote-desktop-services/rds-client-access-license\" " +"target=\"_blank\">Detail" msgstr "" "존재하지 않을 경우, RDS는 시험 모드에 있으며, 시험 기간은 120일입니다.>> Iniciando teste de conectividade da conta do gateway" #: settings/serializers/auth/ldap.py:53 settings/serializers/auth/ldap_ha.py:35 #: settings/serializers/msg.py:37 settings/serializers/terminal.py:32 #: terminal/serializers/storage.py:123 terminal/serializers/storage.py:142 -#: users/forms/profile.py:22 users/serializers/user.py:148 +#: users/forms/profile.py:22 users/serializers/user.py:153 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/cloud/serializers/account_attrs.py:43 @@ -227,7 +227,7 @@ msgstr "Atualizar" #: accounts/const/account.py:34 accounts/const/automation.py:115 #: accounts/serializers/automations/change_secret.py:171 audits/const.py:66 -#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:66 +#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:67 #: ops/const.py:77 terminal/const.py:81 xpack/plugins/cloud/const.py:55 msgid "Failed" msgstr "Falha" @@ -276,8 +276,7 @@ msgstr "Gerar Aleatoriamente" #: accounts/const/automation.py:59 ops/const.py:17 msgid "Replace (Replace only keys pushed by system) " -msgstr "" -"Substituir (Substituir apenas as chaves impulsionadas pelo sistema) " +msgstr "Substituir (Substituir apenas as chaves impulsionadas pelo sistema) " #: accounts/const/automation.py:60 ops/const.py:16 msgid "Empty and append SSH KEY" @@ -350,14 +349,14 @@ msgstr "SFTP" #: accounts/const/automation.py:116 #: accounts/serializers/automations/change_secret.py:170 audits/const.py:65 #: audits/models.py:65 audits/signal_handlers/activity_log.py:34 -#: common/const/choices.py:65 ops/const.py:75 ops/serializers/celery.py:48 +#: common/const/choices.py:66 ops/const.py:75 ops/serializers/celery.py:48 #: terminal/const.py:80 terminal/models/session/sharing.py:119 #: tickets/views/approve.py:128 msgid "Success" msgstr "Successo" -#: accounts/const/automation.py:117 common/const/choices.py:63 -#: common/const/choices.py:114 terminal/const.py:79 +#: accounts/const/automation.py:117 common/const/choices.py:64 +#: common/const/choices.py:127 terminal/const.py:79 msgid "Pending" msgstr "Pendente" @@ -365,7 +364,7 @@ msgstr "Pendente" msgid "Queued" msgstr "Em fila de espera" -#: accounts/const/automation.py:122 common/const/choices.py:62 +#: accounts/const/automation.py:122 common/const/choices.py:63 msgid "Ready" msgstr "Preparar" @@ -377,7 +376,7 @@ msgstr "Em processamento" msgid "Can login" msgstr "Login Permitido" -#: accounts/const/automation.py:128 users/serializers/user.py:254 +#: accounts/const/automation.py:128 users/serializers/user.py:259 msgid "Superuser" msgstr "Superusuário" @@ -406,7 +405,7 @@ msgid "Default tablespace" msgstr "Espaço de Tabela Padrão" #: accounts/const/automation.py:135 rbac/models/role.py:46 -#: rbac/models/rolebinding.py:52 users/models/user/__init__.py:79 +#: rbac/models/rolebinding.py:53 users/models/user/__init__.py:79 msgid "Role" msgstr "Papel" @@ -415,7 +414,7 @@ msgid "Perms" msgstr "Permissões" #: accounts/const/automation.py:137 perms/serializers/permission.py:56 -#: users/serializers/user.py:245 +#: users/serializers/user.py:250 msgid "Groups" msgstr "Grupos de usuários" @@ -790,7 +789,7 @@ msgstr "Data de fim" #: assets/models/automations/base.py:137 #: assets/serializers/automations/base.py:47 audits/models.py:224 #: audits/reporting.py:607 audits/serializers.py:77 ops/models/base.py:49 -#: ops/models/job.py:233 terminal/models/applet/applet.py:382 +#: ops/models/job.py:233 terminal/models/applet/applet.py:390 #: terminal/models/applet/host.py:140 terminal/models/component/status.py:30 #: terminal/models/virtualapp/virtualapp.py:99 #: terminal/serializers/applet.py:19 terminal/serializers/applet_host.py:163 @@ -805,7 +804,7 @@ msgstr "Status" #: accounts/serializers/account/account.py:297 assets/const/automation.py:9 #: authentication/templates/authentication/passkey.html:177 #: authentication/views/base.py:43 authentication/views/base.py:44 -#: authentication/views/base.py:45 common/const/choices.py:67 +#: authentication/views/base.py:45 common/const/choices.py:68 #: settings/templates/ldap/_msg_import_ldap_user.html:26 msgid "Error" msgstr "Erro" @@ -915,8 +914,9 @@ msgstr "Senha repetida" #: accounts/templates/accounts/push_account_report.html:79 #: accounts/templates/accounts/push_account_report.html:119 #: acls/serializers/base.py:19 acls/serializers/base.py:50 audits/models.py:204 -#: audits/reporting.py:241 authentication/forms.py:21 -#: authentication/forms.py:23 authentication/models/temp_token.py:10 +#: audits/reporting.py:241 authentication/backends/cert/forms.py:7 +#: authentication/forms.py:21 authentication/forms.py:23 +#: authentication/models/temp_token.py:10 #: authentication/serializers/connect_token_secret.py:43 #: authentication/serializers/connect_token_secret.py:53 #: authentication/templates/authentication/_msg_different_city.html:9 @@ -1075,7 +1075,7 @@ msgstr "Conta privilegiada" #: assets/models/cmd_filter.py:39 assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:129 reports/models.py:18 #: terminal/models/applet/applet.py:41 -#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:257 +#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:262 msgid "Is active" msgstr "Ativação" @@ -1091,7 +1091,7 @@ msgstr "Plataforma" msgid "Push params" msgstr "Parâmetros de Push de Conta" -#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:403 +#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:404 msgid "Account template" msgstr "Template de Conta" @@ -1189,7 +1189,7 @@ msgstr "Informações de alterações de conta" msgid "Change secret or push account failed information" msgstr "Informações de falha na alteração de senha ou conta de push" -#: accounts/risk_handlers.py:17 common/const/choices.py:116 +#: accounts/risk_handlers.py:17 common/const/choices.py:129 msgid "Ignored" msgstr "Ignorar" @@ -1345,7 +1345,7 @@ msgstr "ID" #: authentication/notifications.py:16 authentication/notifications.py:55 #: notifications/models/notification.py:12 #: perms/api/user_permission/mixin.py:58 perms/models/asset_permission.py:63 -#: rbac/builtin.py:134 rbac/models/rolebinding.py:49 +#: rbac/builtin.py:134 rbac/models/rolebinding.py:50 #: rbac/serializers/rolebinding.py:17 terminal/backends/command/models.py:16 #: terminal/models/session/session.py:27 terminal/models/session/sharing.py:34 #: terminal/notifications.py:168 terminal/notifications.py:235 @@ -1353,8 +1353,8 @@ msgstr "ID" #: terminal/templates/terminal/_msg_command_warning.html:9 #: terminal/templates/terminal/_msg_session_sharing.html:6 #: tickets/models/comment.py:21 tickets/serializers/flow.py:15 -#: users/const.py:14 users/models/user/__init__.py:298 -#: users/models/user/__init__.py:325 +#: users/const.py:14 users/models/user/__init__.py:303 +#: users/models/user/__init__.py:330 msgid "User" msgstr "Usuário" @@ -1389,7 +1389,7 @@ msgstr "Lista branca de IP" #: assets/models/cmd_filter.py:88 common/db/models.py:36 ops/models/adhoc.py:25 #: ops/models/job.py:165 ops/models/playbook.py:31 rbac/models/role.py:37 #: settings/models.py:43 terminal/models/applet/applet.py:46 -#: terminal/models/applet/applet.py:383 terminal/models/applet/host.py:143 +#: terminal/models/applet/applet.py:391 terminal/models/applet/host.py:143 #: terminal/models/component/endpoint.py:29 #: terminal/models/component/endpoint.py:117 #: terminal/models/session/session.py:44 @@ -1694,7 +1694,7 @@ msgstr "" "limpar os registros de conta excedentes às 2 da manhã de acordo com a " "configuração de limite de registro em Armazenamento de Conta " -#: accounts/tasks/remove_account.py:89 +#: accounts/tasks/remove_account.py:91 msgid "Remove historical accounts that are out of range." msgstr "Deletar contas históricas fora do alcance" @@ -1767,7 +1767,7 @@ msgstr "Nome da tarefa" #: accounts/templates/accounts/push_account_report.html:22 #: assets/models/automations/base.py:143 audits/models.py:66 #: ops/models/base.py:55 ops/models/celery.py:89 ops/models/job.py:241 -#: ops/templates/ops/celery_task_log.html:101 +#: ops/templates/ops/celery_task_log.html:154 #: perms/models/asset_permission.py:78 settings/serializers/feature.py:29 #: settings/templates/ldap/_msg_import_ldap_user.html:5 #: terminal/models/applet/host.py:141 terminal/models/session/session.py:42 @@ -1954,7 +1954,7 @@ msgstr "Aprovador" #: acls/models/base.py:81 perms/serializers/permission.py:54 #: tickets/models/flow.py:23 users/models/preference.py:16 -#: users/serializers/group.py:21 users/serializers/user.py:424 +#: users/serializers/group.py:21 users/serializers/user.py:429 msgid "Users" msgstr "Usuário" @@ -1980,7 +1980,7 @@ msgid "Command" msgstr "Comando" #: acls/models/command_acl.py:17 assets/models/cmd_filter.py:59 -#: xpack/plugins/cloud/models.py:369 +#: xpack/plugins/cloud/models.py:370 msgid "Regex" msgstr "Expressão Regular" @@ -2069,7 +2069,7 @@ msgstr "Regras" msgid "Login acl" msgstr "Controle de acesso de login" -#: acls/models/login_acl.py:27 tickets/const.py:11 +#: acls/models/login_acl.py:30 tickets/const.py:11 msgid "Login confirm" msgstr "Revisão de login" @@ -2192,7 +2192,7 @@ msgstr "" #: authentication/templates/authentication/_msg_oauth_bind.html:12 #: authentication/templates/authentication/_msg_rest_password_success.html:8 #: authentication/templates/authentication/_msg_rest_public_key_success.html:8 -#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:405 +#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:406 msgid "IP" msgstr "IP" @@ -2256,17 +2256,17 @@ msgstr "Queremos informá-lo de que recentemente houve logins de usuários:" msgid "User details" msgstr "Detalhes do usuário" -#: assets/api/asset/asset.py:166 +#: assets/api/asset/asset.py:168 msgid "Cannot create asset directly, you should create a host or other" msgstr "" "Não é possível criar ativos diretamente, você deve criar um host ou outros " "ativos." -#: assets/api/asset/asset.py:173 +#: assets/api/asset/asset.py:175 msgid "The number of assets exceeds the limit of 5000" msgstr "A quantidade de ativos excedeu o limite de 5000" -#: assets/api/asset/asset.py:179 +#: assets/api/asset/asset.py:181 #, fuzzy #| msgid "The number of assets exceeds the limit of 5000" msgid "The number of assets exceeds the license limit" @@ -2285,6 +2285,11 @@ msgstr "Não é possível excluir o nó raiz ({})" msgid "Deletion failed and the node contains assets" msgstr "Falha ao excluir, o nó contém ativos" +#: assets/api/node.py:99 +#, python-brace-format +msgid "Node {} is an ancestor of node {}, can't be added as its child" +msgstr "" + #: assets/api/tree.py:48 assets/serializers/node.py:42 msgid "The same level node name cannot be the same" msgstr "O nome do nó no mesmo nível não pode ser repetido" @@ -2302,29 +2307,29 @@ msgstr "Gestão de ativos" msgid "Task: {} finished" msgstr "Tarefa: {} concluída" -#: assets/automations/base/manager.py:340 +#: assets/automations/base/manager.py:341 #, python-brace-format msgid " - Platform {} ansible disabled" msgstr " - Plataforma {} Ansible foi desabilitada, impossível executar tarefas" -#: assets/automations/base/manager.py:555 +#: assets/automations/base/manager.py:556 msgid ">>> Task preparation phase" msgstr ">>> Preparando para executar tarefas" -#: assets/automations/base/manager.py:559 +#: assets/automations/base/manager.py:560 #, python-brace-format msgid ">>> Executing tasks in batches, total {runner_count}" msgstr ">>> Executando tarefas em partes, total de {runner_count}" -#: assets/automations/base/manager.py:564 +#: assets/automations/base/manager.py:565 msgid ">>> Start executing tasks" msgstr ">>> Começando a executar tarefas" -#: assets/automations/base/manager.py:566 +#: assets/automations/base/manager.py:567 msgid ">>> No tasks need to be executed" msgstr ">>> Não há tarefas para executar" -#: assets/automations/base/manager.py:570 +#: assets/automations/base/manager.py:571 #, python-brace-format msgid ">>> Begin executing batch {index} of tasks" msgstr ">>> Começando a executar o lote {index} de tarefas" @@ -2729,7 +2734,7 @@ msgid "Port" msgstr "Porta" #: assets/models/asset/common.py:167 assets/serializers/asset/common.py:175 -#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:59 +#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:69 msgid "Address" msgstr "Endereço" @@ -2737,12 +2742,12 @@ msgstr "Endereço" #: assets/serializers/asset/common.py:151 #: authentication/backends/passkey/models.py:12 #: authentication/serializers/connect_token_secret.py:130 -#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:399 +#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:400 msgid "Platform" msgstr "Plataforma" #: assets/models/asset/common.py:173 assets/models/zone.py:22 -#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:401 +#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:402 msgid "Zone" msgstr "Domínio" @@ -2811,9 +2816,9 @@ msgid "Proxy" msgstr "Proxy" #: assets/models/automations/base.py:23 assets/models/cmd_filter.py:32 -#: assets/models/node.py:553 ops/models/job.py:158 +#: assets/models/node.py:560 ops/models/job.py:158 #: perms/models/asset_permission.py:72 tickets/models/ticket/apply_asset.py:15 -#: xpack/plugins/cloud/models.py:400 +#: xpack/plugins/cloud/models.py:401 msgid "Node" msgstr "Nó" @@ -2837,7 +2842,7 @@ msgstr "Tarefas de Automação de Ativos" #: assets/models/automations/base.py:140 assets/models/cmd_filter.py:41 #: authentication/serializers/token.py:134 common/db/models.py:34 #: ops/models/base.py:54 ops/models/job.py:240 -#: users/models/user/__init__.py:328 +#: users/models/user/__init__.py:333 msgid "Date created" msgstr "Data de criação" @@ -2926,7 +2931,7 @@ msgstr "Gateway" msgid "System" msgstr "Sistema" -#: assets/models/label.py:19 assets/models/node.py:539 +#: assets/models/label.py:19 assets/models/node.py:546 #: assets/serializers/cagegory.py:11 assets/serializers/cagegory.py:18 #: assets/serializers/cagegory.py:24 #: authentication/models/connection_token.py:35 @@ -2941,7 +2946,7 @@ msgstr "Valor" #: assets/serializers/platform.py:160 #: authentication/serializers/connect_token_secret.py:136 #: common/serializers/common.py:85 labels/serializers.py:45 -#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:404 +#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:405 msgid "Label" msgstr "Etiqueta" @@ -2957,27 +2962,27 @@ msgstr "Nota personalizada" msgid "My assets" msgstr "Meus ativos" -#: assets/models/node.py:168 +#: assets/models/node.py:172 msgid "New node" msgstr "Novo nó" -#: assets/models/node.py:467 audits/backends/db.py:85 audits/backends/db.py:86 +#: assets/models/node.py:474 audits/backends/db.py:85 audits/backends/db.py:86 msgid "empty" msgstr "Vazio" -#: assets/models/node.py:538 perms/models/perm_node.py:28 +#: assets/models/node.py:545 perms/models/perm_node.py:28 msgid "Key" msgstr "Chave" -#: assets/models/node.py:540 assets/serializers/node.py:20 +#: assets/models/node.py:547 assets/serializers/node.py:20 msgid "Full value" msgstr "Nome completo" -#: assets/models/node.py:544 perms/models/perm_node.py:30 +#: assets/models/node.py:551 perms/models/perm_node.py:30 msgid "Parent key" msgstr "Chave privada ssh" -#: assets/models/node.py:556 +#: assets/models/node.py:563 msgid "Can match node" msgstr "Pode corresponder ao nó" @@ -3157,7 +3162,7 @@ msgstr "" #: authentication/serializers/connect_token_secret.py:30 #: authentication/serializers/connect_token_secret.py:77 #: perms/models/asset_permission.py:76 perms/serializers/permission.py:68 -#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:402 +#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:403 #: xpack/plugins/cloud/serializers/task.py:36 msgid "Protocols" msgstr "Grupo de Protocolo" @@ -3611,7 +3616,7 @@ msgid "Symlink" msgstr "Criar link simbólico" #: audits/const.py:18 audits/const.py:29 -#: ops/templates/ops/celery_task_log.html:86 +#: ops/templates/ops/celery_task_log.html:139 #: terminal/api/session/session.py:159 msgid "Download" msgstr "Baixar" @@ -3640,7 +3645,9 @@ msgstr "Exportar" msgid "Connect" msgstr "Conectar" -#: audits/const.py:31 authentication/templates/authentication/login.html:334 +#: audits/const.py:31 +#: authentication/templates/authentication/cert_login.html:232 +#: authentication/templates/authentication/login.html:334 #: authentication/templates/authentication/login.html:408 #: templates/_header_bar.html:101 #: xpack/plugins/interface/templates/login_i18n.html:21 @@ -4437,17 +4444,17 @@ msgstr "Falha na comparação facial" msgid "Current user not support mfa type: {}" msgstr "O usuário atual não suporta o tipo de MFA: {}" -#: authentication/api/password.py:34 terminal/api/session/session.py:347 +#: authentication/api/password.py:37 terminal/api/session/session.py:347 #: users/views/profile/reset.py:63 #, python-brace-format msgid "User does not exist: {}" msgstr "Usuário não encontrado: {}" -#: authentication/api/password.py:34 users/views/profile/reset.py:166 +#: authentication/api/password.py:37 users/views/profile/reset.py:166 msgid "No user matched" msgstr "Nenhum usuário correspondente encontrado" -#: authentication/api/password.py:38 +#: authentication/api/password.py:41 #, python-brace-format msgid "" "The user is from {}, please go to the corresponding system to change the " @@ -4455,7 +4462,7 @@ msgid "" msgstr "" "O usuário vem de {} Por favor, altere a senha no sistema correspondente" -#: authentication/api/password.py:69 +#: authentication/api/password.py:72 #: authentication/templates/authentication/login.html:400 #: users/templates/users/forgot_password.html:41 #: users/templates/users/forgot_password.html:42 @@ -4465,7 +4472,7 @@ msgstr "" msgid "Forgot password" msgstr "Esqueceu a senha" -#: authentication/api/password.py:70 authentication/mfa/email.py:42 +#: authentication/api/password.py:73 authentication/mfa/email.py:42 #, python-brace-format msgid "The validity period of the verification code is {} minute" msgstr "O código de verificação é válido por {} minuto" @@ -4478,10 +4485,29 @@ msgstr "gerenciamento de autenticação" msgid "CAS Error" msgstr "Erro CAS" -#: authentication/backends/custom.py:60 -#: authentication/backends/oauth2/backends.py:158 -msgid "User invalid, disabled or expired" -msgstr "O usuário é inválido, desativado ou expirado" +#: authentication/backends/cert/api.py:57 +#, fuzzy +#| msgid "LDAP authentication is not enabled" +msgid "Certificate enrollment is not enabled" +msgstr "A autenticação LDAP não está ativada" + +#: authentication/backends/cert/api.py:62 +#, fuzzy +#| msgid "type is required" +msgid "CSR is required" +msgstr "Tipo Esse campo é obrigatório." + +#: authentication/backends/cert/api.py:68 +#, fuzzy +#| msgid "Authentication failed" +msgid "Certificate signing failed" +msgstr "Falha na autenticação" + +#: authentication/backends/cert/views.py:97 +#, fuzzy +#| msgid "Invalid data" +msgid "Invalid credentials" +msgstr "Dados inválidos" #: authentication/backends/drf.py:61 msgid "Invalid token header. No credentials provided." @@ -4735,16 +4761,16 @@ msgstr "Sua senha é inválida" msgid "Please wait for %s seconds before retry" msgstr "Por favor, tente novamente após %s segundos" -#: authentication/errors/redirect.py:85 authentication/mixins.py:436 +#: authentication/errors/redirect.py:85 authentication/mixins.py:445 #: users/views/profile/reset.py:224 msgid "Your password is too simple, please change it for security" msgstr "Sua senha é muito simples, por segurança, favor alterar" -#: authentication/errors/redirect.py:93 authentication/mixins.py:445 +#: authentication/errors/redirect.py:93 authentication/mixins.py:454 msgid "You should to change your password before login" msgstr "Antes de finalizar o login, favor alterar a senha" -#: authentication/errors/redirect.py:101 authentication/mixins.py:454 +#: authentication/errors/redirect.py:101 authentication/mixins.py:463 msgid "Your password has expired, please reset before logging in" msgstr "Sua senha expirou, modifique antes de fazer login" @@ -4876,11 +4902,11 @@ msgstr "" "usuário atual não está na lista de usuários; por favor, entre em contato com " "o administrador." -#: authentication/mixins.py:184 +#: authentication/mixins.py:187 msgid "User is invalid" msgstr "Usuário inválido" -#: authentication/mixins.py:201 +#: authentication/mixins.py:204 #, python-brace-format msgid "" " The administrator has enabled 'Only allow login from user source'. \n" @@ -4890,12 +4916,12 @@ msgstr "" "O administrador ativou 'permitir login apenas de fontes de usuário', a fonte " "atual do usuário é {}, entre em contato com o administrador." -#: authentication/mixins.py:382 +#: authentication/mixins.py:391 #, python-brace-format msgid "The MFA type ({}) is not enabled" msgstr "Este método MFA ({}) não está ativado" -#: authentication/mixins.py:424 +#: authentication/mixins.py:433 msgid "Please change your password" msgstr "Por favor, altere sua senha." @@ -5087,7 +5113,7 @@ msgstr "Action" #: authentication/serializers/connection_token.py:46 #: perms/serializers/permission.py:66 perms/serializers/permission.py:87 -#: users/serializers/user.py:127 users/serializers/user.py:261 +#: users/serializers/user.py:127 users/serializers/user.py:266 msgid "Is expired" msgstr "Expirado" @@ -5129,13 +5155,13 @@ msgstr "Chave SSH inválida" #: authentication/serializers/token.py:93 perms/serializers/permission.py:65 #: perms/serializers/permission.py:88 users/serializers/user.py:128 -#: users/serializers/user.py:258 +#: users/serializers/user.py:263 msgid "Is valid" msgstr "Está válido?" #: authentication/serializers/token.py:131 ops/models/adhoc.py:26 #: ops/models/playbook.py:34 ops/serializers/mixin.py:10 rbac/models/role.py:31 -#: rbac/models/rolebinding.py:46 rbac/serializers/role.py:12 +#: rbac/models/rolebinding.py:47 rbac/serializers/role.py:12 #: settings/serializers/auth/oauth2.py:37 msgid "Scope" msgstr "Alcance" @@ -5238,7 +5264,7 @@ msgstr "Erro de código" #: authentication/templates/authentication/_msg_oauth_bind.html:3 #: authentication/templates/authentication/_msg_reset_password.html:3 #: authentication/templates/authentication/_msg_reset_password_code.html:9 -#: jumpserver/conf.py:555 +#: jumpserver/conf.py:558 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:32 #: users/templates/users/_msg_account_expire_reminder.html:4 @@ -5348,6 +5374,87 @@ msgstr "" msgid "Cancel" msgstr "Cancelar" +#: authentication/templates/authentication/cert_login.html:190 +#, fuzzy +#| msgid "Multi-Factor Authentication" +msgid "Certificate Authentication" +msgstr "Autenticação" + +#: authentication/templates/authentication/cert_login.html:195 +#: authentication/templates/authentication/cert_login.html:250 +msgid "Loading USB Key driver..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:210 +msgid "Insert USB Key to auto-fetch" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:238 +#, fuzzy +#| msgid "More login options" +msgid "Other login methods" +msgstr "Login por outros métodos" + +#: authentication/templates/authentication/cert_login.html:251 +msgid "Detecting USB Key..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:252 +msgid "USB Key connected" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:253 +#, fuzzy +#| msgid "Please enter SMS code" +msgid "Please insert USB Key" +msgstr "Por favor insira o código de verificação por SMS" + +#: authentication/templates/authentication/cert_login.html:254 +#, fuzzy +#| msgid "Account unavailable" +msgid "Driver unavailable" +msgstr "Conta inválida" + +#: authentication/templates/authentication/cert_login.html:255 +msgid "USB Key SDK initialization failed" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:256 +msgid "Verifying PIN..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:257 +#, fuzzy +#| msgid "Date verified" +msgid "PIN verified" +msgstr "Data de validação" + +#: authentication/templates/authentication/cert_login.html:258 +#, fuzzy +#| msgid "OTP verification code" +msgid "PIN verification failed" +msgstr "Código de verificação MFA virtual" + +#: authentication/templates/authentication/cert_login.html:259 +msgid "Signing challenge code..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:260 +#, fuzzy +#| msgid "Signing key" +msgid "Signing failed" +msgstr "Chave de assinatura" + +#: authentication/templates/authentication/cert_login.html:261 +msgid "Failed to retrieve certificate" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:262 +#, fuzzy +#| msgid "Your account has expired, please contact the administrator." +msgid "No certificate detected, please contact administrator" +msgstr "Sua conta já expirou, por favor, entre em contato com o administrador." + #: authentication/templates/authentication/face_capture.html:14 msgid "Retry" msgstr "Tentar novamente" @@ -5423,6 +5530,10 @@ msgstr "Deseja tentar novamente?" msgid "LAN" msgstr "Rede Local" +#: authentication/utils.py:150 +msgid "CERT" +msgstr "" + #: authentication/views/base.py:71 #: perms/templates/perms/_msg_permed_items_expire.html:18 msgid "If you have any question, please contact the administrator" @@ -5591,47 +5702,47 @@ msgstr "Faça login com a senha, e então vincule ao WeChat Corporativo" msgid "Request file format may be wrong" msgstr "Formato de arquivo enviado errado ou outro tipo de recurso do arquivo" -#: common/const/choices.py:40 +#: common/const/choices.py:41 msgid "China" msgstr "China" -#: common/const/choices.py:57 +#: common/const/choices.py:58 msgid "Manual" msgstr "AçãoManual" -#: common/const/choices.py:58 +#: common/const/choices.py:59 msgid "Timing" msgstr "AçãoProgramada" -#: common/const/choices.py:64 ops/const.py:74 +#: common/const/choices.py:65 ops/const.py:74 msgid "Running" msgstr "Em execução" -#: common/const/choices.py:68 +#: common/const/choices.py:69 msgid "Canceled" msgstr "Cancelar" -#: common/const/choices.py:115 +#: common/const/choices.py:128 msgid "Confirmed" msgstr "Confirmar" -#: common/const/choices.py:123 terminal/models/applet/applet.py:31 +#: common/const/choices.py:136 terminal/models/applet/applet.py:31 msgid "Community edition" msgstr "Versão Comunitária" -#: common/const/choices.py:124 +#: common/const/choices.py:137 msgid "Basic edition" msgstr "Versão Básica Empresarial" -#: common/const/choices.py:125 +#: common/const/choices.py:138 msgid "Standard edition" msgstr "Versão Padrão Empresarial" -#: common/const/choices.py:126 +#: common/const/choices.py:139 msgid "Professional edition" msgstr "Versão Profissional Empresarial" -#: common/const/choices.py:127 +#: common/const/choices.py:140 msgid "Ultimate edition" msgstr "Versão Premium Empresarial" @@ -6148,24 +6259,24 @@ msgstr "Código não encontrado" msgid "The message code provided is invalid or has expired" msgstr "O código da mensagem fornecido é inválido ou expirou" -#: jumpserver/conf.py:549 +#: jumpserver/conf.py:552 #, python-brace-format msgid "The verification code is: {code}" msgstr "O código de verificação é: {code}" -#: jumpserver/conf.py:554 +#: jumpserver/conf.py:557 msgid "Create account successfully" msgstr "Criação de conta bem sucedida" -#: jumpserver/conf.py:556 +#: jumpserver/conf.py:559 msgid "Your account has been created successfully" msgstr "Sua conta foi criada com sucesso" -#: jumpserver/context_processor.py:17 +#: jumpserver/context_processor.py:16 msgid "JumpServer - An open-source PAM" msgstr "JumpServer Open Fortress Machine" -#: jumpserver/context_processor.py:37 +#: jumpserver/context_processor.py:31 msgid "FIT2CLOUD" msgstr "" @@ -6898,7 +7009,7 @@ msgid "Please save in a org" msgstr "Por favor, selecione uma organização antes de salvar" #: orgs/mixins/models.py:58 orgs/mixins/serializers.py:25 orgs/models.py:91 -#: rbac/const.py:7 rbac/models/rolebinding.py:56 +#: rbac/const.py:7 rbac/models/rolebinding.py:57 #: rbac/serializers/rolebinding.py:44 settings/serializers/auth/base.py:53 #: terminal/notifications.py:309 #: terminal/templates/terminal/_msg_command_warning.html:27 @@ -7325,15 +7436,15 @@ msgstr "Papel do sistema" msgid "Organization role" msgstr "Papel da organização" -#: rbac/models/rolebinding.py:62 +#: rbac/models/rolebinding.py:63 msgid "Role binding" msgstr "Vinculação de papel" -#: rbac/models/rolebinding.py:168 +#: rbac/models/rolebinding.py:169 msgid "All organizations" msgstr "Todas as organizações" -#: rbac/models/rolebinding.py:200 +#: rbac/models/rolebinding.py:201 msgid "" "User last role in org, can not be delete, you can remove user from org " "instead" @@ -7341,11 +7452,11 @@ msgstr "" "O último papel do usuário não pode ser excluído, você pode remover o usuário " "da organização" -#: rbac/models/rolebinding.py:207 +#: rbac/models/rolebinding.py:208 msgid "Organization role binding" msgstr "Associação de papéis da organização" -#: rbac/models/rolebinding.py:222 +#: rbac/models/rolebinding.py:223 msgid "System role binding" msgstr "Associação de papéis do sistema" @@ -7410,7 +7521,7 @@ msgid "Storage" msgstr "Armazenamento" #: rbac/tree.py:64 terminal/models/applet/applet.py:53 -#: terminal/models/applet/applet.py:379 terminal/models/applet/host.py:30 +#: terminal/models/applet/applet.py:387 terminal/models/applet/host.py:30 #: terminal/serializers/applet.py:16 msgid "Applet" msgstr "Aplicativo Remoto" @@ -7473,51 +7584,51 @@ msgstr "Revogar token de acesso" msgid "Range days" msgstr "Modificador" -#: reports/views.py:20 +#: reports/views.py:19 msgid "User login report" msgstr "Relatório de Login de Usuário" -#: reports/views.py:24 +#: reports/views.py:23 msgid "User change password report" msgstr "Relatório de Mudança de Senha do Usuário" -#: reports/views.py:28 +#: reports/views.py:27 msgid "Asset statistics report" msgstr "Relatório de Estatísticas de Ativos" -#: reports/views.py:32 +#: reports/views.py:31 msgid "Asset activity report" msgstr "Relatório de Atividades de Ativos" -#: reports/views.py:36 +#: reports/views.py:35 msgid "Account statistics report" msgstr "Relatório de Estatísticas de Contas" -#: reports/views.py:40 +#: reports/views.py:39 msgid "Account automation report" msgstr "Relatório de Automação de Contas" -#: reports/views.py:44 +#: reports/views.py:43 msgid "ConsoleDashboard" msgstr "Painel de Console" -#: reports/views.py:48 +#: reports/views.py:47 msgid "AuditsDashboard" msgstr "Painel de Auditoria" -#: reports/views.py:52 +#: reports/views.py:51 msgid "PamDashboard" msgstr "Painel PAM" -#: reports/views.py:56 +#: reports/views.py:55 msgid "ChangeSecretDashboard" msgstr "Painel de Alteração de Senha da Conta" -#: reports/views.py:191 +#: reports/views.py:190 msgid "Failed to send email: " msgstr "Envio de e-mail falhou" -#: reports/views.py:192 +#: reports/views.py:191 msgid "Email sent successfully to " msgstr "Envio de e-mail bem-sucedido" @@ -7800,8 +7911,8 @@ msgstr "Habilitar autenticação DingTalk" #: settings/serializers/auth/dingtalk.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the DingTalk service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the DingTalk service user attribute name" msgstr "" "Mapeamento de atributos do usuário, onde `key` é o nome do atributo do " "usuário do sistema, e `value` é o nome do atributo do usuário do serviço " @@ -7809,8 +7920,8 @@ msgstr "" #: settings/serializers/auth/feishu.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the FeiShu service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the FeiShu service user attribute name" msgstr "" "Mapeamento de atributos do usuário, onde `key` é o nome do atributo do " "usuário do sistema, e `value` é o nome do atributo do usuário do serviço " @@ -7822,8 +7933,8 @@ msgstr "Lark" #: settings/serializers/auth/lark.py:19 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Lark service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Lark service user attribute name" msgstr "" "Mapeamento de atributos do usuário, onde `key` é o nome do atributo do " "usuário do sistema e `value` é o nome do atributo do usuário do serviço Lark" @@ -7871,8 +7982,8 @@ msgstr "As opções possíveis são (cn ou uid ou sAMAccountName=%(user)s)" #: settings/serializers/auth/ldap.py:69 settings/serializers/auth/ldap_ha.py:51 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the LDAP service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the LDAP service user attribute name" msgstr "" "Mapeamento de atributos do usuário, onde `key` é o nome do atributo do " "usuário do sistema e `value` é o nome do atributo do usuário do serviço LDAP" @@ -7982,8 +8093,8 @@ msgstr "Quando os usuários saem, eles também sairão do servidor OAuth2" #: settings/serializers/auth/oauth2.py:62 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OAuth2 service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OAuth2 service user attribute name" msgstr "" "Mapeamento de atributos do usuário, onde `key` é o nome do atributo do " "usuário do sistema, e `value` é o nome do atributo do usuário do serviço " @@ -8020,8 +8131,8 @@ msgstr "Ignorar validação do certificado SSL" #: settings/serializers/auth/oidc.py:41 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OIDC service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OIDC service user attribute name" msgstr "" "Mapeamento de atributos do usuário, onde `key` é o nome do atributo do " "usuário do sistema e `value` é o nome do atributo do usuário do serviço OIDC" @@ -8170,12 +8281,11 @@ msgstr "" #: settings/serializers/auth/slack.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Slack service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Slack service user attribute name" msgstr "" "Mapeamento de atributos do usuário, onde `key` é o nome do atributo do " -"usuário do sistema, `value` é o nome do atributo do usuário do serviço " -"Slack" +"usuário do sistema, `value` é o nome do atributo do usuário do serviço Slack" #: settings/serializers/auth/sms.py:18 msgid "Enable Short Message Service (SMS)" @@ -8209,7 +8319,7 @@ msgid "Template code" msgstr "Modelo" #: settings/serializers/auth/sms.py:40 users/models/user/__init__.py:89 -#: users/serializers/user.py:159 +#: users/serializers/user.py:164 msgid "Phone" msgstr "Celular" @@ -8267,7 +8377,10 @@ msgid "Enable SSO auth" msgstr "Ativar autenticação com token SSO" #: settings/serializers/auth/sso.py:17 -msgid "Other service can using SSO token login to JumpServer without password" +#, fuzzy +#| msgid "" +#| "Other service can using SSO token login to JumpServer without password" +msgid "Other service can using SSO token login to system without password" msgstr "" "Outros sistemas podem se integrar ao JumpServer usando Token SSO, eliminando " "o processo de login." @@ -8283,8 +8396,8 @@ msgstr "Unidade: segundos" #: settings/serializers/auth/wecom.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the WeCom service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the WeCom service user attribute name" msgstr "" "Mapeamento de atributos do usuário, onde `key` é o nome do atributo do " "usuário do sistema e `value` é o nome do atributo do usuário do serviço " @@ -9476,7 +9589,7 @@ msgstr "Aguardando:" msgid "The verification code has been sent" msgstr "O código de verificação foi enviado" -#: templates/_without_nav_base.html:46 +#: templates/_without_nav_base.html:51 msgid "Home page" msgstr "Página Inicial" @@ -9741,31 +9854,31 @@ msgstr "Pode ser Executado Simultaneamente" msgid "Hosts" msgstr "Host" -#: terminal/models/applet/applet.py:94 +#: terminal/models/applet/applet.py:102 #: terminal/models/virtualapp/virtualapp.py:66 #, python-brace-format msgid "Applet pkg not valid, Missing file {}" msgstr "Applet pkg inválido, arquivo ausente {}" -#: terminal/models/applet/applet.py:113 +#: terminal/models/applet/applet.py:121 #, python-brace-format msgid "Load platform.yml failed: {}" msgstr "Falha ao carregar platform.yml: {}" -#: terminal/models/applet/applet.py:116 +#: terminal/models/applet/applet.py:124 msgid "Only support custom platform" msgstr "Somente suporte para plataformas personalizadas" -#: terminal/models/applet/applet.py:121 +#: terminal/models/applet/applet.py:129 msgid "Missing type in platform.yml" msgstr "Tipo ausente em platform.yml" -#: terminal/models/applet/applet.py:381 terminal/models/applet/host.py:36 +#: terminal/models/applet/applet.py:389 terminal/models/applet/host.py:36 #: terminal/models/applet/host.py:138 msgid "Hosting" msgstr "Máquina Hospedeira" -#: terminal/models/applet/applet.py:387 +#: terminal/models/applet/applet.py:395 msgid "Applet Publication" msgstr "Publicação de Aplicativo" @@ -9855,7 +9968,7 @@ msgstr "Porta VNC" #: terminal/models/component/endpoint.py:35 #: terminal/models/component/endpoint.py:115 -#: terminal/serializers/endpoint.py:63 terminal/serializers/storage.py:41 +#: 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" @@ -10069,8 +10182,8 @@ msgstr "Armazenamento de comandos e gravações" #: terminal/notifications.py:279 terminal/tasks.py:212 #: xpack/plugins/cloud/api.py:182 -#: xpack/plugins/cloud/serializers/account.py:143 -#: xpack/plugins/cloud/serializers/account.py:146 +#: xpack/plugins/cloud/serializers/account.py:148 +#: xpack/plugins/cloud/serializers/account.py:151 msgid "Test failure: Account invalid" msgstr "Teste falhou: Conta inválida" @@ -10192,11 +10305,13 @@ msgstr "Já existem licenças RDS" msgid "" "If not exist, the RDS will be in trial mode, and the trial period is 120 " "days. Detail" +"remote-desktop-services/rds-client-access-license\" " +"target=\"_blank\">Detail" msgstr "" "Se não existir, o RDS estará em modo de teste, com um período de teste de " "120 dias. Detalhes" +"remote-desktop-services/rds-client-access-license' target='_blank'>Detalhes" #: terminal/serializers/applet_host.py:55 msgid "RDS License Server" @@ -10320,7 +10435,7 @@ msgstr "ID de sessão inválida" msgid "Timestamp" msgstr "Timestamp" -#: terminal/serializers/endpoint.py:27 +#: terminal/serializers/endpoint.py:28 msgid "" "The host address accessed when connecting to assets, if it is empty, the " "access address of the current browser will be used (the default endpoint " @@ -10329,7 +10444,7 @@ msgstr "" "Endereço do host acessado ao conectar ao ativo, se estiver vazio, use o " "endereço de acesso do navegador atual (o host padrão não permite modificação)" -#: terminal/serializers/endpoint.py:54 +#: terminal/serializers/endpoint.py:64 msgid "" "The assets within this IP range or Host, the following endpoint will be used " "for the connection" @@ -10337,7 +10452,7 @@ msgstr "" "Os ativos dentro deste intervalo de IP ou host serão conectados utilizando o " "seguinte endpoint." -#: terminal/serializers/endpoint.py:55 +#: terminal/serializers/endpoint.py:65 msgid "" "If asset IP addresses under different endpoints conflict, use asset labels" msgstr "" @@ -10477,7 +10592,7 @@ msgstr "Online" msgid "Stat" msgstr "Status" -#: terminal/serializers/terminal.py:83 terminal/serializers/terminal.py:91 +#: terminal/serializers/terminal.py:79 terminal/serializers/terminal.py:87 msgid "Not found" msgstr "Não encontrado" @@ -11078,7 +11193,7 @@ msgstr "Solicitante" msgid "Approval Step Distribution" msgstr "Aprovação sem Login" -#: tickets/serializers/flow.py:45 +#: tickets/serializers/flow.py:42 msgid "The current organization type already exists" msgstr "A organização atual já possui este tipo." @@ -11139,7 +11254,7 @@ msgid "Ticket information" msgstr " Informações de ordem de serviço" #: tickets/templates/tickets/approve_check_password.html:28 -#: tickets/views/approve.py:43 tickets/views/approve.py:80 +#: tickets/views/approve.py:42 tickets/views/approve.py:80 msgid "Ticket approval" msgstr " Aprovação de ordem de serviço" @@ -11147,14 +11262,14 @@ msgstr " Aprovação de ordem de serviço" msgid "Approval" msgstr " Acordo" -#: tickets/views/approve.py:44 +#: tickets/views/approve.py:43 msgid "" "This ticket does not exist, the process has ended, or this link has expired" msgstr "" " A ordem de serviço não existe, o processo da ordem de serviço já terminou, " "ou este link já expirou" -#: tickets/views/approve.py:72 +#: tickets/views/approve.py:71 msgid "Click the button below to approve or reject" msgstr "Clique no botão abaixo para aceitar ou recusar" @@ -11373,7 +11488,7 @@ msgstr "Configurações do usuário" msgid "Email lookup" msgstr "Conta de e-mail" -#: users/models/user/__init__.py:82 users/serializers/user.py:259 +#: users/models/user/__init__.py:82 users/serializers/user.py:264 msgid "Is service account" msgstr "Conta de serviço" @@ -11390,7 +11505,7 @@ msgid "OTP secret key" msgstr "OTP chave" #: users/models/user/__init__.py:105 users/serializers/profile.py:86 -#: users/serializers/user.py:256 +#: users/serializers/user.py:261 msgid "Is first login" msgstr "Primeiro login" @@ -11410,23 +11525,23 @@ msgstr "Vetor facial" msgid "Date api key used" msgstr "Data do último uso da API key" -#: users/models/user/__init__.py:293 +#: users/models/user/__init__.py:298 msgid "Can not delete admin user" msgstr "Não é possível excluir o usuário administrador" -#: users/models/user/__init__.py:307 +#: users/models/user/__init__.py:312 msgid "Can invite user" msgstr "Pode convidar usuários" -#: users/models/user/__init__.py:308 +#: users/models/user/__init__.py:313 msgid "Can remove user" msgstr "Pode remover usuários" -#: users/models/user/__init__.py:309 +#: users/models/user/__init__.py:314 msgid "Can match user" msgstr "Pode combinar usuários" -#: users/models/user/__init__.py:338 +#: users/models/user/__init__.py:343 msgid "User password history" msgstr "Histórico de senhas do usuário" @@ -11434,6 +11549,12 @@ msgstr "Histórico de senhas do usuário" msgid "Force enabled" msgstr "Forçar ativação" +#: users/models/user/_source.py:27 +#, fuzzy +#| msgid "Authenticate" +msgid "Certificate" +msgstr "Verificar identidade" + #: users/notifications.py:23 users/notifications.py:68 msgid "Reset password url" msgstr "URL para redefinir a senha" @@ -11547,7 +11668,7 @@ msgstr "Carregamento assíncrono da árvore de ativos" msgid "Connect default open method" msgstr "Forma padrão de abertura de conexão" -#: users/serializers/preference/luna.py:34 xpack/plugins/interface/models.py:42 +#: users/serializers/preference/luna.py:34 xpack/plugins/interface/models.py:44 #: xpack/plugins/interface/serializers/interface.py:35 msgid "Theme" msgstr "Tema" @@ -11663,7 +11784,7 @@ msgstr " MFA Obrigatório " msgid "Login blocked" msgstr " Login Bloqueado " -#: users/serializers/user.py:130 users/serializers/user.py:265 +#: users/serializers/user.py:130 users/serializers/user.py:270 msgid "Is OTP bound" msgstr " MFA Virtual Vinculado " @@ -11679,27 +11800,33 @@ msgstr " Admin da Organização " msgid "Can public key authentication" msgstr " Autenticação por Chave Pública Permitida " -#: users/serializers/user.py:144 +#: users/serializers/user.py:145 +#, fuzzy +#| msgid "Can public key authentication" +msgid "Can certificate authentication" +msgstr " Autenticação por Chave Pública Permitida " + +#: users/serializers/user.py:149 msgid "Is face code set" msgstr "Existem características faciais?" -#: users/serializers/user.py:230 +#: users/serializers/user.py:235 msgid "Full name" msgstr " Nome Completo " -#: users/serializers/user.py:233 +#: users/serializers/user.py:238 msgid "Login username" msgstr " Usuário de Login " -#: users/serializers/user.py:236 +#: users/serializers/user.py:241 msgid "Email address" msgstr " Endereço de Email " -#: users/serializers/user.py:246 +#: users/serializers/user.py:251 msgid "User groups to join" msgstr " Quantidade de Grupos de Usuários " -#: users/serializers/user.py:250 +#: users/serializers/user.py:255 msgid "" "User source identifies where the user was created, which could be AD or " "other sources.There are security settings that can restrict users to log in " @@ -11709,34 +11836,34 @@ msgstr "" "pode ser AD ou outra fonte. As configurações de segurança podem limitar os " "usuários a fazer login somente a partir de uma fonte especificada." -#: users/serializers/user.py:260 +#: users/serializers/user.py:265 msgid "Is org admin" msgstr "Administrador da organização" -#: users/serializers/user.py:262 +#: users/serializers/user.py:267 msgid "Avatar url" msgstr "Caminho do avatar" -#: users/serializers/user.py:267 +#: users/serializers/user.py:272 msgid "MFA level" msgstr "MFA" -#: users/serializers/user.py:268 +#: users/serializers/user.py:273 msgid "Multi-Factor Authentication" msgstr "Autenticação" -#: users/serializers/user.py:398 +#: users/serializers/user.py:403 msgid "Has public keys" msgstr "Possui chave pública" -#: users/serializers/user.py:426 +#: users/serializers/user.py:431 msgid "" "* For security, only a partial of users is displayed. You can search for more" msgstr "" "* Para sua segurança, apenas alguns usuários são mostrados. Você pode " "procurar por mais" -#: users/serializers/user.py:462 +#: users/serializers/user.py:467 msgid "name not unique" msgstr "Nome duplicado" @@ -12254,7 +12381,7 @@ msgstr "IP privado" msgid "Public IP" msgstr "IP público" -#: xpack/plugins/cloud/const.py:50 xpack/plugins/cloud/models.py:373 +#: xpack/plugins/cloud/const.py:50 xpack/plugins/cloud/models.py:374 msgid "Instance name" msgstr "Nome da instância" @@ -12455,8 +12582,8 @@ msgstr "Liberar recursos" msgid "Date last sync" msgstr "Última data de sincronização" -#: xpack/plugins/cloud/models.py:135 xpack/plugins/cloud/models.py:391 -#: xpack/plugins/cloud/models.py:418 +#: xpack/plugins/cloud/models.py:135 xpack/plugins/cloud/models.py:392 +#: xpack/plugins/cloud/models.py:419 msgid "Strategy" msgstr "Estratégia" @@ -12496,71 +12623,71 @@ msgstr "Relação Condicional" msgid "Task strategy" msgstr "Estratégia de Tarefa" -#: xpack/plugins/cloud/models.py:362 +#: xpack/plugins/cloud/models.py:363 msgid "Equal" msgstr "Igual a" -#: xpack/plugins/cloud/models.py:363 +#: xpack/plugins/cloud/models.py:364 msgid "Not Equal" msgstr "Não é igual a" -#: xpack/plugins/cloud/models.py:364 +#: xpack/plugins/cloud/models.py:365 msgid "In" msgstr "Em..." -#: xpack/plugins/cloud/models.py:365 +#: xpack/plugins/cloud/models.py:366 msgid "Contains" msgstr "Contém" -#: xpack/plugins/cloud/models.py:366 +#: xpack/plugins/cloud/models.py:367 msgid "Exclude" msgstr "Excluir" -#: xpack/plugins/cloud/models.py:367 +#: xpack/plugins/cloud/models.py:368 msgid "Startswith" msgstr "Iniciar com..." -#: xpack/plugins/cloud/models.py:368 +#: xpack/plugins/cloud/models.py:369 msgid "Endswith" msgstr "Terminar com..." -#: xpack/plugins/cloud/models.py:374 +#: xpack/plugins/cloud/models.py:375 msgid "Instance platform" msgstr "Plataforma de instância" -#: xpack/plugins/cloud/models.py:375 +#: xpack/plugins/cloud/models.py:376 msgid "Instance address" msgstr "Endereço da instância" -#: xpack/plugins/cloud/models.py:382 +#: xpack/plugins/cloud/models.py:383 msgid "Rule attr" msgstr "Atributos de regra" -#: xpack/plugins/cloud/models.py:386 +#: xpack/plugins/cloud/models.py:387 msgid "Rule match" msgstr "Correspondência de regra" -#: xpack/plugins/cloud/models.py:388 +#: xpack/plugins/cloud/models.py:389 msgid "Rule value" msgstr "Valor da regra" -#: xpack/plugins/cloud/models.py:395 xpack/plugins/cloud/serializers/task.py:82 +#: xpack/plugins/cloud/models.py:396 xpack/plugins/cloud/serializers/task.py:82 msgid "Strategy rule" msgstr "Condição" -#: xpack/plugins/cloud/models.py:406 +#: xpack/plugins/cloud/models.py:407 msgid "Name strategy" msgstr "Política de nome de host" -#: xpack/plugins/cloud/models.py:413 +#: xpack/plugins/cloud/models.py:414 msgid "Action attr" msgstr "Atributos de ação" -#: xpack/plugins/cloud/models.py:415 +#: xpack/plugins/cloud/models.py:416 msgid "Action value" msgstr "Valor de ação" -#: xpack/plugins/cloud/models.py:422 xpack/plugins/cloud/serializers/task.py:85 +#: xpack/plugins/cloud/models.py:423 xpack/plugins/cloud/serializers/task.py:85 msgid "Strategy action" msgstr "Action" @@ -12925,38 +13052,38 @@ msgstr "A missão ainda não começou" msgid "Restore default successfully." msgstr "Restauração para as configurações padrão bem sucedida!" -#: xpack/plugins/interface/meta.py:9 xpack/plugins/interface/models.py:47 -#: xpack/plugins/interface/models.py:91 +#: xpack/plugins/interface/meta.py:9 xpack/plugins/interface/models.py:49 +#: xpack/plugins/interface/models.py:104 msgid "Interface settings" msgstr "Configurações da interface" -#: xpack/plugins/interface/models.py:24 +#: xpack/plugins/interface/models.py:26 msgid "Login title" msgstr "Título da página de login" -#: xpack/plugins/interface/models.py:28 +#: xpack/plugins/interface/models.py:30 msgid "Login image" msgstr "Imagem da página de login" -#: xpack/plugins/interface/models.py:32 +#: xpack/plugins/interface/models.py:34 msgid "Website icon" msgstr "Ícone do site" -#: xpack/plugins/interface/models.py:36 +#: xpack/plugins/interface/models.py:38 msgid "Index logo" msgstr "Gerenciar página de logo" -#: xpack/plugins/interface/models.py:40 +#: xpack/plugins/interface/models.py:42 msgid "Logout logo" msgstr "Fazer Logout" -#: xpack/plugins/interface/models.py:43 +#: xpack/plugins/interface/models.py:45 msgid "Footer content" msgstr "Conteúdo do rodapé" -#: xpack/plugins/interface/models.py:44 +#: xpack/plugins/interface/models.py:46 #: xpack/plugins/interface/serializers/interface.py:73 -msgid "Extended fields" +msgid "Extend" msgstr "" #: xpack/plugins/interface/serializers/interface.py:48 @@ -13011,6 +13138,12 @@ msgstr "" msgid "More login methods" msgstr "Login por outros métodos" +#: xpack/plugins/jdmc/i18n.py:4 +#, fuzzy +#| msgid "Audit view" +msgid "AuditAdmin" +msgstr "Painel de auditoria" + #: xpack/plugins/jdmc/i18n.py:5 #, fuzzy #| msgid "SystemAdmin" @@ -13029,6 +13162,9 @@ msgstr "Importação de licença bem-sucedida" msgid "Invalid license" msgstr "Licença inválida" +#~ msgid "User invalid, disabled or expired" +#~ msgstr "O usuário é inválido, desativado ou expirado" + #~ msgid "Microsoft" #~ msgstr "Microsoft" diff --git a/apps/i18n/core/ru/LC_MESSAGES/django.po b/apps/i18n/core/ru/LC_MESSAGES/django.po index fb4b273f9..3d227c7a2 100644 --- a/apps/i18n/core/ru/LC_MESSAGES/django.po +++ b/apps/i18n/core/ru/LC_MESSAGES/django.po @@ -3,7 +3,7 @@ msgid "" msgstr "" "Project-Id-Version: jumpserver\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-04-21 17:03+0800\n" +"POT-Creation-Date: 2026-05-25 14:02+0800\n" "PO-Revision-Date: 2025-11-13 12:26\n" "Last-Translator: ibuler \n" "Language-Team: Russian\n" @@ -31,7 +31,7 @@ msgstr "Учетная запись уже существует." msgid "No valid assets found for account creation." msgstr "Не удалось найти действительные активы для создания учетной записи." -#: accounts/api/account/application.py:77 +#: accounts/api/account/application.py:87 #: authentication/api/connection_token.py:463 msgid "Account not found" msgstr "Учетная запись не найдена" @@ -45,15 +45,15 @@ msgstr "Параметр 'Действие' должен быть [{}]" msgid "The account key will be split into two parts and sent" msgstr "Ключ учетной записи будет разделен на две части и отправлен" -#: accounts/automations/backup_account/handlers.py:131 +#: accounts/automations/backup_account/handlers.py:132 msgid "Number of backup accounts" msgstr "Количество резервируемых учётных записей" -#: accounts/automations/backup_account/handlers.py:152 +#: accounts/automations/backup_account/handlers.py:153 msgid "Generating asset related backup information files" msgstr "Создание файлов резервной копии данных, связанных с активами" -#: accounts/automations/backup_account/handlers.py:177 +#: accounts/automations/backup_account/handlers.py:178 #: accounts/automations/backup_account/manager.py:26 #: accounts/automations/change_secret/manager.py:81 #: accounts/automations/push_account/manager.py:62 @@ -64,31 +64,31 @@ msgstr "Создание файлов резервной копии данных msgid "Duration" msgstr "Продолжительность" -#: accounts/automations/backup_account/handlers.py:178 +#: accounts/automations/backup_account/handlers.py:179 msgid "Backup file creation completed" msgstr "Создание файла резервной копии завершено" -#: accounts/automations/backup_account/handlers.py:186 +#: accounts/automations/backup_account/handlers.py:187 msgid "Start sending backup emails" msgstr "Начинается отправка резервной копии на почту" -#: accounts/automations/backup_account/handlers.py:213 +#: accounts/automations/backup_account/handlers.py:214 msgid "Encrypting files using encryption password" msgstr "Шифрование файлов с использованием пароля шифрования" -#: accounts/automations/backup_account/handlers.py:223 +#: accounts/automations/backup_account/handlers.py:224 msgid "The backup file will be sent to" msgstr "Резервный файл будет отправлен" -#: accounts/automations/backup_account/handlers.py:246 +#: accounts/automations/backup_account/handlers.py:247 msgid "The backup task has no assigned sftp server" msgstr "В задаче резервирования не указан сервер SFTP" -#: accounts/automations/backup_account/handlers.py:267 +#: accounts/automations/backup_account/handlers.py:268 msgid "The backup task has no assigned recipient" msgstr "В задаче резервирования не указан получатель" -#: accounts/automations/backup_account/handlers.py:290 +#: accounts/automations/backup_account/handlers.py:291 msgid "Plan start" msgstr "Запуск задачи" @@ -157,7 +157,7 @@ msgstr "" #: settings/serializers/auth/ldap.py:53 settings/serializers/auth/ldap_ha.py:35 #: settings/serializers/msg.py:37 settings/serializers/terminal.py:32 #: terminal/serializers/storage.py:123 terminal/serializers/storage.py:142 -#: users/forms/profile.py:22 users/serializers/user.py:148 +#: users/forms/profile.py:22 users/serializers/user.py:153 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/cloud/serializers/account_attrs.py:43 @@ -231,7 +231,7 @@ msgstr "Обновить" #: accounts/const/account.py:34 accounts/const/automation.py:115 #: accounts/serializers/automations/change_secret.py:171 audits/const.py:66 -#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:66 +#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:67 #: ops/const.py:77 terminal/const.py:81 xpack/plugins/cloud/const.py:55 msgid "Failed" msgstr "Не удалось" @@ -353,14 +353,14 @@ msgstr "SFTP" #: accounts/const/automation.py:116 #: accounts/serializers/automations/change_secret.py:170 audits/const.py:65 #: audits/models.py:65 audits/signal_handlers/activity_log.py:34 -#: common/const/choices.py:65 ops/const.py:75 ops/serializers/celery.py:48 +#: common/const/choices.py:66 ops/const.py:75 ops/serializers/celery.py:48 #: terminal/const.py:80 terminal/models/session/sharing.py:119 #: tickets/views/approve.py:128 msgid "Success" msgstr "Успех" -#: accounts/const/automation.py:117 common/const/choices.py:63 -#: common/const/choices.py:114 terminal/const.py:79 +#: accounts/const/automation.py:117 common/const/choices.py:64 +#: common/const/choices.py:127 terminal/const.py:79 msgid "Pending" msgstr "В ожидании" @@ -368,7 +368,7 @@ msgstr "В ожидании" msgid "Queued" msgstr "В очереди" -#: accounts/const/automation.py:122 common/const/choices.py:62 +#: accounts/const/automation.py:122 common/const/choices.py:63 msgid "Ready" msgstr "Готово" @@ -380,7 +380,7 @@ msgstr "Обработка" msgid "Can login" msgstr "Доступен вход" -#: accounts/const/automation.py:128 users/serializers/user.py:254 +#: accounts/const/automation.py:128 users/serializers/user.py:259 msgid "Superuser" msgstr "Суперпользователь" @@ -409,7 +409,7 @@ msgid "Default tablespace" msgstr "Табличное пространство по умолчанию" #: accounts/const/automation.py:135 rbac/models/role.py:46 -#: rbac/models/rolebinding.py:52 users/models/user/__init__.py:79 +#: rbac/models/rolebinding.py:53 users/models/user/__init__.py:79 msgid "Role" msgstr "Роль" @@ -418,7 +418,7 @@ msgid "Perms" msgstr "Права" #: accounts/const/automation.py:137 perms/serializers/permission.py:56 -#: users/serializers/user.py:245 +#: users/serializers/user.py:250 msgid "Groups" msgstr "Группы" @@ -793,7 +793,7 @@ msgstr "Дата окончания" #: assets/models/automations/base.py:137 #: assets/serializers/automations/base.py:47 audits/models.py:224 #: audits/reporting.py:607 audits/serializers.py:77 ops/models/base.py:49 -#: ops/models/job.py:233 terminal/models/applet/applet.py:382 +#: ops/models/job.py:233 terminal/models/applet/applet.py:390 #: terminal/models/applet/host.py:140 terminal/models/component/status.py:30 #: terminal/models/virtualapp/virtualapp.py:99 #: terminal/serializers/applet.py:19 terminal/serializers/applet_host.py:163 @@ -808,7 +808,7 @@ msgstr "Статус" #: accounts/serializers/account/account.py:297 assets/const/automation.py:9 #: authentication/templates/authentication/passkey.html:177 #: authentication/views/base.py:43 authentication/views/base.py:44 -#: authentication/views/base.py:45 common/const/choices.py:67 +#: authentication/views/base.py:45 common/const/choices.py:68 #: settings/templates/ldap/_msg_import_ldap_user.html:26 msgid "Error" msgstr "Ошибка" @@ -903,8 +903,9 @@ msgstr "Повторяющийся пароль" #: accounts/templates/accounts/push_account_report.html:79 #: accounts/templates/accounts/push_account_report.html:119 #: acls/serializers/base.py:19 acls/serializers/base.py:50 audits/models.py:204 -#: audits/reporting.py:241 authentication/forms.py:21 -#: authentication/forms.py:23 authentication/models/temp_token.py:10 +#: audits/reporting.py:241 authentication/backends/cert/forms.py:7 +#: authentication/forms.py:21 authentication/forms.py:23 +#: authentication/models/temp_token.py:10 #: authentication/serializers/connect_token_secret.py:43 #: authentication/serializers/connect_token_secret.py:53 #: authentication/templates/authentication/_msg_different_city.html:9 @@ -1063,7 +1064,7 @@ msgstr "Привилегированный" #: assets/models/cmd_filter.py:39 assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:129 reports/models.py:18 #: terminal/models/applet/applet.py:41 -#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:257 +#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:262 msgid "Is active" msgstr "Активно" @@ -1079,7 +1080,7 @@ msgstr "Платформа" msgid "Push params" msgstr "Параметры публикации аккаунта" -#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:403 +#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:404 msgid "Account template" msgstr "Шаблон УЗ" @@ -1181,7 +1182,7 @@ msgstr "Сбор информации об изменении УЗ" msgid "Change secret or push account failed information" msgstr "Информация о неудачных сменах секретов и публикациях УЗ" -#: accounts/risk_handlers.py:17 common/const/choices.py:116 +#: accounts/risk_handlers.py:17 common/const/choices.py:129 msgid "Ignored" msgstr "Игнорируется" @@ -1337,7 +1338,7 @@ msgstr "ID" #: authentication/notifications.py:16 authentication/notifications.py:55 #: notifications/models/notification.py:12 #: perms/api/user_permission/mixin.py:58 perms/models/asset_permission.py:63 -#: rbac/builtin.py:134 rbac/models/rolebinding.py:49 +#: rbac/builtin.py:134 rbac/models/rolebinding.py:50 #: rbac/serializers/rolebinding.py:17 terminal/backends/command/models.py:16 #: terminal/models/session/session.py:27 terminal/models/session/sharing.py:34 #: terminal/notifications.py:168 terminal/notifications.py:235 @@ -1345,8 +1346,8 @@ msgstr "ID" #: terminal/templates/terminal/_msg_command_warning.html:9 #: terminal/templates/terminal/_msg_session_sharing.html:6 #: tickets/models/comment.py:21 tickets/serializers/flow.py:15 -#: users/const.py:14 users/models/user/__init__.py:298 -#: users/models/user/__init__.py:325 +#: users/const.py:14 users/models/user/__init__.py:303 +#: users/models/user/__init__.py:330 msgid "User" msgstr "Пользователь" @@ -1381,7 +1382,7 @@ msgstr "Белый список IP" #: assets/models/cmd_filter.py:88 common/db/models.py:36 ops/models/adhoc.py:25 #: ops/models/job.py:165 ops/models/playbook.py:31 rbac/models/role.py:37 #: settings/models.py:43 terminal/models/applet/applet.py:46 -#: terminal/models/applet/applet.py:383 terminal/models/applet/host.py:143 +#: terminal/models/applet/applet.py:391 terminal/models/applet/host.py:143 #: terminal/models/component/endpoint.py:29 #: terminal/models/component/endpoint.py:117 #: terminal/models/session/session.py:44 @@ -1696,7 +1697,7 @@ msgstr "" " в разделе \"Системные настройки - Функции\" - Хранилище учетной " "записи - Ограничение записей" -#: accounts/tasks/remove_account.py:89 +#: accounts/tasks/remove_account.py:91 msgid "Remove historical accounts that are out of range." msgstr "Удаление исторических учетных записей, которые превышают лимит." @@ -1769,7 +1770,7 @@ msgstr "Название задачи" #: accounts/templates/accounts/push_account_report.html:22 #: assets/models/automations/base.py:143 audits/models.py:66 #: ops/models/base.py:55 ops/models/celery.py:89 ops/models/job.py:241 -#: ops/templates/ops/celery_task_log.html:101 +#: ops/templates/ops/celery_task_log.html:154 #: perms/models/asset_permission.py:78 settings/serializers/feature.py:29 #: settings/templates/ldap/_msg_import_ldap_user.html:5 #: terminal/models/applet/host.py:141 terminal/models/session/session.py:42 @@ -1954,7 +1955,7 @@ msgstr "Утверждающий" #: acls/models/base.py:81 perms/serializers/permission.py:54 #: tickets/models/flow.py:23 users/models/preference.py:16 -#: users/serializers/group.py:21 users/serializers/user.py:424 +#: users/serializers/group.py:21 users/serializers/user.py:429 msgid "Users" msgstr "Пользователь" @@ -1980,7 +1981,7 @@ msgid "Command" msgstr "Команда" #: acls/models/command_acl.py:17 assets/models/cmd_filter.py:59 -#: xpack/plugins/cloud/models.py:369 +#: xpack/plugins/cloud/models.py:370 msgid "Regex" msgstr "Регулярное выражение" @@ -2069,7 +2070,7 @@ msgstr "Правило" msgid "Login acl" msgstr "Правила входа пользователей" -#: acls/models/login_acl.py:27 tickets/const.py:11 +#: acls/models/login_acl.py:30 tickets/const.py:11 msgid "Login confirm" msgstr "Проверка входа" @@ -2193,7 +2194,7 @@ msgstr "" #: authentication/templates/authentication/_msg_oauth_bind.html:12 #: authentication/templates/authentication/_msg_rest_password_success.html:8 #: authentication/templates/authentication/_msg_rest_public_key_success.html:8 -#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:405 +#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:406 msgid "IP" msgstr "IP" @@ -2256,16 +2257,16 @@ msgstr "Мы хотим сообщить вам, что недавно воше msgid "User details" msgstr "Данные пользователя" -#: assets/api/asset/asset.py:166 +#: assets/api/asset/asset.py:168 msgid "Cannot create asset directly, you should create a host or other" msgstr "" "Невозможно создать актив напрямую, вам следует создать хост или другой тип" -#: assets/api/asset/asset.py:173 +#: assets/api/asset/asset.py:175 msgid "The number of assets exceeds the limit of 5000" msgstr "Количество активов превышает лимит в 5000" -#: assets/api/asset/asset.py:179 +#: assets/api/asset/asset.py:181 #, fuzzy #| msgid "The number of assets exceeds the limit of 5000" msgid "The number of assets exceeds the license limit" @@ -2284,6 +2285,11 @@ msgstr "Нельзя удалить корневую папку ({})" msgid "Deletion failed and the node contains assets" msgstr "Удаление не удалось, папка содержит активы" +#: assets/api/node.py:99 +#, python-brace-format +msgid "Node {} is an ancestor of node {}, can't be added as its child" +msgstr "" + #: assets/api/tree.py:48 assets/serializers/node.py:42 msgid "The same level node name cannot be the same" msgstr "Имена папок одного уровня не могут повторяться" @@ -2301,29 +2307,29 @@ msgstr "Управление активами" msgid "Task: {} finished" msgstr "Задача: {} Выполнена" -#: assets/automations/base/manager.py:340 +#: assets/automations/base/manager.py:341 #, python-brace-format msgid " - Platform {} ansible disabled" msgstr " - Ansible отключена на платформе {}, выполнение задачи невозможно" -#: assets/automations/base/manager.py:555 +#: assets/automations/base/manager.py:556 msgid ">>> Task preparation phase" msgstr ">>> Подготовка к выполнению" -#: assets/automations/base/manager.py:559 +#: assets/automations/base/manager.py:560 #, python-brace-format msgid ">>> Executing tasks in batches, total {runner_count}" msgstr ">>> Пакетное выполнение задач, всего {runner_count}" -#: assets/automations/base/manager.py:564 +#: assets/automations/base/manager.py:565 msgid ">>> Start executing tasks" msgstr ">>> Начинаем выполнение задач" -#: assets/automations/base/manager.py:566 +#: assets/automations/base/manager.py:567 msgid ">>> No tasks need to be executed" msgstr ">>> Нет задач для выполнения" -#: assets/automations/base/manager.py:570 +#: assets/automations/base/manager.py:571 #, python-brace-format msgid ">>> Begin executing batch {index} of tasks" msgstr ">>> Начинаем выполнение пакета из {index} задач" @@ -2729,7 +2735,7 @@ msgid "Port" msgstr "Порт" #: assets/models/asset/common.py:167 assets/serializers/asset/common.py:175 -#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:59 +#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:69 msgid "Address" msgstr "Адрес" @@ -2737,12 +2743,12 @@ msgstr "Адрес" #: assets/serializers/asset/common.py:151 #: authentication/backends/passkey/models.py:12 #: authentication/serializers/connect_token_secret.py:130 -#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:399 +#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:400 msgid "Platform" msgstr "Платформа" #: assets/models/asset/common.py:173 assets/models/zone.py:22 -#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:401 +#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:402 msgid "Zone" msgstr "Зона" @@ -2811,9 +2817,9 @@ msgid "Proxy" msgstr "Прокси" #: assets/models/automations/base.py:23 assets/models/cmd_filter.py:32 -#: assets/models/node.py:553 ops/models/job.py:158 +#: assets/models/node.py:560 ops/models/job.py:158 #: perms/models/asset_permission.py:72 tickets/models/ticket/apply_asset.py:15 -#: xpack/plugins/cloud/models.py:400 +#: xpack/plugins/cloud/models.py:401 msgid "Node" msgstr "Папка" @@ -2839,7 +2845,7 @@ msgstr "Автоматизация активов" #: assets/models/automations/base.py:140 assets/models/cmd_filter.py:41 #: authentication/serializers/token.py:134 common/db/models.py:34 #: ops/models/base.py:54 ops/models/job.py:240 -#: users/models/user/__init__.py:328 +#: users/models/user/__init__.py:333 msgid "Date created" msgstr "Дата создания" @@ -2928,7 +2934,7 @@ msgstr "Шлюз" msgid "System" msgstr "Система" -#: assets/models/label.py:19 assets/models/node.py:539 +#: assets/models/label.py:19 assets/models/node.py:546 #: assets/serializers/cagegory.py:11 assets/serializers/cagegory.py:18 #: assets/serializers/cagegory.py:24 #: authentication/models/connection_token.py:35 @@ -2943,7 +2949,7 @@ msgstr "Значение" #: assets/serializers/platform.py:160 #: authentication/serializers/connect_token_secret.py:136 #: common/serializers/common.py:85 labels/serializers.py:45 -#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:404 +#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:405 msgid "Label" msgstr "Тег" @@ -2959,27 +2965,27 @@ msgstr "Пользовательская заметка" msgid "My assets" msgstr "Мои активы" -#: assets/models/node.py:168 +#: assets/models/node.py:172 msgid "New node" msgstr "Новая папка" -#: assets/models/node.py:467 audits/backends/db.py:85 audits/backends/db.py:86 +#: assets/models/node.py:474 audits/backends/db.py:85 audits/backends/db.py:86 msgid "empty" msgstr "пусто" -#: assets/models/node.py:538 perms/models/perm_node.py:28 +#: assets/models/node.py:545 perms/models/perm_node.py:28 msgid "Key" msgstr "Ключ" -#: assets/models/node.py:540 assets/serializers/node.py:20 +#: assets/models/node.py:547 assets/serializers/node.py:20 msgid "Full value" msgstr "Полное значение" -#: assets/models/node.py:544 perms/models/perm_node.py:30 +#: assets/models/node.py:551 perms/models/perm_node.py:30 msgid "Parent key" msgstr "Ключ SSH" -#: assets/models/node.py:556 +#: assets/models/node.py:563 msgid "Can match node" msgstr "Сопоставление с папкой" @@ -3159,7 +3165,7 @@ msgstr "" #: authentication/serializers/connect_token_secret.py:30 #: authentication/serializers/connect_token_secret.py:77 #: perms/models/asset_permission.py:76 perms/serializers/permission.py:68 -#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:402 +#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:403 #: xpack/plugins/cloud/serializers/task.py:36 msgid "Protocols" msgstr "Протоколы" @@ -3619,7 +3625,7 @@ msgid "Symlink" msgstr "Создать символическую ссылку" #: audits/const.py:18 audits/const.py:29 -#: ops/templates/ops/celery_task_log.html:86 +#: ops/templates/ops/celery_task_log.html:139 #: terminal/api/session/session.py:159 msgid "Download" msgstr "Скачать" @@ -3648,7 +3654,9 @@ msgstr "Экспорт" msgid "Connect" msgstr "Подключить" -#: audits/const.py:31 authentication/templates/authentication/login.html:334 +#: audits/const.py:31 +#: authentication/templates/authentication/cert_login.html:232 +#: authentication/templates/authentication/login.html:334 #: authentication/templates/authentication/login.html:408 #: templates/_header_bar.html:101 #: xpack/plugins/interface/templates/login_i18n.html:21 @@ -4448,17 +4456,17 @@ msgstr "Не удалось сравнить лица" msgid "Current user not support mfa type: {}" msgstr "Текущий пользователь не поддерживает тип МФА: {}." -#: authentication/api/password.py:34 terminal/api/session/session.py:347 +#: authentication/api/password.py:37 terminal/api/session/session.py:347 #: users/views/profile/reset.py:63 #, python-brace-format msgid "User does not exist: {}" msgstr "Пользователь не существует: {}" -#: authentication/api/password.py:34 users/views/profile/reset.py:166 +#: authentication/api/password.py:37 users/views/profile/reset.py:166 msgid "No user matched" msgstr "Нет подходящего пользователя" -#: authentication/api/password.py:38 +#: authentication/api/password.py:41 #, python-brace-format msgid "" "The user is from {}, please go to the corresponding system to change the " @@ -4466,7 +4474,7 @@ msgid "" msgstr "" "Пользователь из {}, пожалуйста, измените пароль в соответствующей системе" -#: authentication/api/password.py:69 +#: authentication/api/password.py:72 #: authentication/templates/authentication/login.html:400 #: users/templates/users/forgot_password.html:41 #: users/templates/users/forgot_password.html:42 @@ -4476,7 +4484,7 @@ msgstr "" msgid "Forgot password" msgstr "Забыли пароль" -#: authentication/api/password.py:70 authentication/mfa/email.py:42 +#: authentication/api/password.py:73 authentication/mfa/email.py:42 #, python-brace-format msgid "The validity period of the verification code is {} minute" msgstr "Срок действия кода проверки: {} мин" @@ -4489,10 +4497,29 @@ msgstr "Управление аутентификацией" msgid "CAS Error" msgstr "Ошибка CAS" -#: authentication/backends/custom.py:60 -#: authentication/backends/oauth2/backends.py:158 -msgid "User invalid, disabled or expired" -msgstr "Пользователь недействителен, отключен или просрочен" +#: authentication/backends/cert/api.py:57 +#, fuzzy +#| msgid "LDAP authentication is not enabled" +msgid "Certificate enrollment is not enabled" +msgstr "LDAP аутентификация не включена" + +#: authentication/backends/cert/api.py:62 +#, fuzzy +#| msgid "type is required" +msgid "CSR is required" +msgstr "тип обязателен" + +#: authentication/backends/cert/api.py:68 +#, fuzzy +#| msgid "Authentication failed" +msgid "Certificate signing failed" +msgstr "Ошибка аутентификации" + +#: authentication/backends/cert/views.py:97 +#, fuzzy +#| msgid "Invalid data" +msgid "Invalid credentials" +msgstr "Недопустимые данные" #: authentication/backends/drf.py:61 msgid "Invalid token header. No credentials provided." @@ -4746,16 +4773,16 @@ msgstr "Ваш пароль недействителен" msgid "Please wait for %s seconds before retry" msgstr "Пожалуйста, подождите %s секунд перед повторной попыткой" -#: authentication/errors/redirect.py:85 authentication/mixins.py:436 +#: authentication/errors/redirect.py:85 authentication/mixins.py:445 #: users/views/profile/reset.py:224 msgid "Your password is too simple, please change it for security" msgstr "Ваш пароль слишком простой, измените его в целях безопасности" -#: authentication/errors/redirect.py:93 authentication/mixins.py:445 +#: authentication/errors/redirect.py:93 authentication/mixins.py:454 msgid "You should to change your password before login" msgstr "Вам необходимо сменить пароль перед входом в систему" -#: authentication/errors/redirect.py:101 authentication/mixins.py:454 +#: authentication/errors/redirect.py:101 authentication/mixins.py:463 msgid "Your password has expired, please reset before logging in" msgstr "" "Срок действия вашего пароля истек, пожалуйста, сбросьте его перед входом в " @@ -4887,11 +4914,11 @@ msgstr "" "пользователей', текущий пользователь отсутствует в списке пользователей, " "пожалуйста, свяжитесь с администратором." -#: authentication/mixins.py:184 +#: authentication/mixins.py:187 msgid "User is invalid" msgstr "Недействительный пользователь" -#: authentication/mixins.py:201 +#: authentication/mixins.py:204 #, python-brace-format msgid "" " The administrator has enabled 'Only allow login from user source'. \n" @@ -4901,12 +4928,12 @@ msgstr "" "Администратор включил 'разрешить вход только из источника пользователей', " "текущий источник пользователя - {}, пожалуйста, свяжитесь с администратором." -#: authentication/mixins.py:382 +#: authentication/mixins.py:391 #, python-brace-format msgid "The MFA type ({}) is not enabled" msgstr "Способ МФА ({}) не включен" -#: authentication/mixins.py:424 +#: authentication/mixins.py:433 msgid "Please change your password" msgstr "Пожалуйста, измените свой пароль" @@ -5098,7 +5125,7 @@ msgstr "Действия" #: authentication/serializers/connection_token.py:46 #: perms/serializers/permission.py:66 perms/serializers/permission.py:87 -#: users/serializers/user.py:127 users/serializers/user.py:261 +#: users/serializers/user.py:127 users/serializers/user.py:266 msgid "Is expired" msgstr "Истекший?" @@ -5140,13 +5167,13 @@ msgstr "Недействительный ключ SSH" #: authentication/serializers/token.py:93 perms/serializers/permission.py:65 #: perms/serializers/permission.py:88 users/serializers/user.py:128 -#: users/serializers/user.py:258 +#: users/serializers/user.py:263 msgid "Is valid" msgstr "Действует?" #: authentication/serializers/token.py:131 ops/models/adhoc.py:26 #: ops/models/playbook.py:34 ops/serializers/mixin.py:10 rbac/models/role.py:31 -#: rbac/models/rolebinding.py:46 rbac/serializers/role.py:12 +#: rbac/models/rolebinding.py:47 rbac/serializers/role.py:12 #: settings/serializers/auth/oauth2.py:37 msgid "Scope" msgstr "Область" @@ -5249,7 +5276,7 @@ msgstr "Ошибка кода" #: authentication/templates/authentication/_msg_oauth_bind.html:3 #: authentication/templates/authentication/_msg_reset_password.html:3 #: authentication/templates/authentication/_msg_reset_password_code.html:9 -#: jumpserver/conf.py:555 +#: jumpserver/conf.py:558 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:32 #: users/templates/users/_msg_account_expire_reminder.html:4 @@ -5362,6 +5389,87 @@ msgstr "" msgid "Cancel" msgstr "Отмена" +#: authentication/templates/authentication/cert_login.html:190 +#, fuzzy +#| msgid "Multi-Factor Authentication" +msgid "Certificate Authentication" +msgstr "Многофакторная аутентификация" + +#: authentication/templates/authentication/cert_login.html:195 +#: authentication/templates/authentication/cert_login.html:250 +msgid "Loading USB Key driver..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:210 +msgid "Insert USB Key to auto-fetch" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:238 +#, fuzzy +#| msgid "More login options" +msgid "Other login methods" +msgstr "Другие способы входа" + +#: authentication/templates/authentication/cert_login.html:251 +msgid "Detecting USB Key..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:252 +msgid "USB Key connected" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:253 +#, fuzzy +#| msgid "Please enter SMS code" +msgid "Please insert USB Key" +msgstr "Пожалуйста, введите код из SMS" + +#: authentication/templates/authentication/cert_login.html:254 +#, fuzzy +#| msgid "Account unavailable" +msgid "Driver unavailable" +msgstr "Учетная запись недоступна" + +#: authentication/templates/authentication/cert_login.html:255 +msgid "USB Key SDK initialization failed" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:256 +msgid "Verifying PIN..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:257 +#, fuzzy +#| msgid "Date verified" +msgid "PIN verified" +msgstr "Дата проверки" + +#: authentication/templates/authentication/cert_login.html:258 +#, fuzzy +#| msgid "OTP verification code" +msgid "PIN verification failed" +msgstr "Код подтверждения OTP" + +#: authentication/templates/authentication/cert_login.html:259 +msgid "Signing challenge code..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:260 +#, fuzzy +#| msgid "Signing key" +msgid "Signing failed" +msgstr "Подпись ключа" + +#: authentication/templates/authentication/cert_login.html:261 +msgid "Failed to retrieve certificate" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:262 +#, fuzzy +#| msgid "Your account has expired, please contact the administrator." +msgid "No certificate detected, please contact administrator" +msgstr "Ваш аккаунт истек, пожалуйста, свяжитесь с администратором" + #: authentication/templates/authentication/face_capture.html:14 msgid "Retry" msgstr "Повторить" @@ -5437,6 +5545,10 @@ msgstr "Хотите попробовать снова?" msgid "LAN" msgstr "Локальная сеть" +#: authentication/utils.py:150 +msgid "CERT" +msgstr "" + #: authentication/views/base.py:71 #: perms/templates/perms/_msg_permed_items_expire.html:18 msgid "If you have any question, please contact the administrator" @@ -5602,47 +5714,47 @@ msgstr "Пожалуйста, войдите с паролем, а затем п msgid "Request file format may be wrong" msgstr "Неверный формат загружаемого файла или файл другого типа ресурсов" -#: common/const/choices.py:40 +#: common/const/choices.py:41 msgid "China" msgstr "Китай" -#: common/const/choices.py:57 +#: common/const/choices.py:58 msgid "Manual" msgstr "Ручной триггер" -#: common/const/choices.py:58 +#: common/const/choices.py:59 msgid "Timing" msgstr "Триггер по времени" -#: common/const/choices.py:64 ops/const.py:74 +#: common/const/choices.py:65 ops/const.py:74 msgid "Running" msgstr "В процессе" -#: common/const/choices.py:68 +#: common/const/choices.py:69 msgid "Canceled" msgstr "Отмена" -#: common/const/choices.py:115 +#: common/const/choices.py:128 msgid "Confirmed" msgstr "Подтвержденный" -#: common/const/choices.py:123 terminal/models/applet/applet.py:31 +#: common/const/choices.py:136 terminal/models/applet/applet.py:31 msgid "Community edition" msgstr "Редакция Community" -#: common/const/choices.py:124 +#: common/const/choices.py:137 msgid "Basic edition" msgstr "Редакция Basic" -#: common/const/choices.py:125 +#: common/const/choices.py:138 msgid "Standard edition" msgstr "Редакция Standard" -#: common/const/choices.py:126 +#: common/const/choices.py:139 msgid "Professional edition" msgstr "Редакция Professional" -#: common/const/choices.py:127 +#: common/const/choices.py:140 msgid "Ultimate edition" msgstr "Редакция Ultimate" @@ -6162,24 +6274,24 @@ msgstr "Код не найден" msgid "The message code provided is invalid or has expired" msgstr "Предоставленный код сообщения недействительный или истек" -#: jumpserver/conf.py:549 +#: jumpserver/conf.py:552 #, python-brace-format msgid "The verification code is: {code}" msgstr "Код подтверждения: {code}" -#: jumpserver/conf.py:554 +#: jumpserver/conf.py:557 msgid "Create account successfully" msgstr "Успешное создание учетной записи" -#: jumpserver/conf.py:556 +#: jumpserver/conf.py:559 msgid "Your account has been created successfully" msgstr "Ваша учетная запись была успешно создана" -#: jumpserver/context_processor.py:17 +#: jumpserver/context_processor.py:16 msgid "JumpServer - An open-source PAM" msgstr "JumpServer открытая система управления доступом" -#: jumpserver/context_processor.py:37 +#: jumpserver/context_processor.py:31 msgid "FIT2CLOUD" msgstr "" @@ -6917,7 +7029,7 @@ msgid "Please save in a org" msgstr "Пожалуйста, выберите организацию перед сохранением" #: orgs/mixins/models.py:58 orgs/mixins/serializers.py:25 orgs/models.py:91 -#: rbac/const.py:7 rbac/models/rolebinding.py:56 +#: rbac/const.py:7 rbac/models/rolebinding.py:57 #: rbac/serializers/rolebinding.py:44 settings/serializers/auth/base.py:53 #: terminal/notifications.py:309 #: terminal/templates/terminal/_msg_command_warning.html:27 @@ -7347,15 +7459,15 @@ msgstr "Системная роль" msgid "Organization role" msgstr "Организационная роль" -#: rbac/models/rolebinding.py:62 +#: rbac/models/rolebinding.py:63 msgid "Role binding" msgstr "Привязка ролей" -#: rbac/models/rolebinding.py:168 +#: rbac/models/rolebinding.py:169 msgid "All organizations" msgstr "Все организации" -#: rbac/models/rolebinding.py:200 +#: rbac/models/rolebinding.py:201 msgid "" "User last role in org, can not be delete, you can remove user from org " "instead" @@ -7363,11 +7475,11 @@ msgstr "" "Последняя роль пользователя не может быть удалена. Вы можете удалить " "пользователя из организации." -#: rbac/models/rolebinding.py:207 +#: rbac/models/rolebinding.py:208 msgid "Organization role binding" msgstr "Привязка организационной роли" -#: rbac/models/rolebinding.py:222 +#: rbac/models/rolebinding.py:223 msgid "System role binding" msgstr "Привязка системной роли" @@ -7432,7 +7544,7 @@ msgid "Storage" msgstr "Хранилище" #: rbac/tree.py:64 terminal/models/applet/applet.py:53 -#: terminal/models/applet/applet.py:379 terminal/models/applet/host.py:30 +#: terminal/models/applet/applet.py:387 terminal/models/applet/host.py:30 #: terminal/serializers/applet.py:16 msgid "Applet" msgstr "Приложения" @@ -7495,51 +7607,51 @@ msgstr "Отменить токен доступа" msgid "Range days" msgstr "Изменивший" -#: reports/views.py:20 +#: reports/views.py:19 msgid "User login report" msgstr "Отчет о входах пользователей" -#: reports/views.py:24 +#: reports/views.py:23 msgid "User change password report" msgstr "Отчет о смене пароля пользователя" -#: reports/views.py:28 +#: reports/views.py:27 msgid "Asset statistics report" msgstr "Отчет по статистике активов" -#: reports/views.py:32 +#: reports/views.py:31 msgid "Asset activity report" msgstr "Отчет по действиям с активами" -#: reports/views.py:36 +#: reports/views.py:35 msgid "Account statistics report" msgstr "Отчет по статистике учётных записей" -#: reports/views.py:40 +#: reports/views.py:39 msgid "Account automation report" msgstr "Отчет по автоматизации учётных записей" -#: reports/views.py:44 +#: reports/views.py:43 msgid "ConsoleDashboard" msgstr "Панель управления" -#: reports/views.py:48 +#: reports/views.py:47 msgid "AuditsDashboard" msgstr "Панель аудита" -#: reports/views.py:52 +#: reports/views.py:51 msgid "PamDashboard" msgstr "Панель PAM" -#: reports/views.py:56 +#: reports/views.py:55 msgid "ChangeSecretDashboard" msgstr "Панель смены пароля УЗ" -#: reports/views.py:191 +#: reports/views.py:190 msgid "Failed to send email: " msgstr "Не удалось отправить письмо " -#: reports/views.py:192 +#: reports/views.py:191 msgid "Email sent successfully to " msgstr "Письмо успешно отправлено " @@ -7823,21 +7935,21 @@ msgstr "Dingtalk" #: settings/serializers/auth/dingtalk.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the DingTalk service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the DingTalk service user attribute name" msgstr "" "Сопоставление атрибутов пользователя, где \"ключ\" — это название атрибута " -"пользователя системы, а \"значение\" — название атрибута пользователя " -"службы DingTalk" +"пользователя системы, а \"значение\" — название атрибута пользователя службы " +"DingTalk" #: settings/serializers/auth/feishu.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the FeiShu service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the FeiShu service user attribute name" msgstr "" "Сопоставление атрибутов пользователя, где \"ключ\" — это название атрибута " -"пользователя системы, а \"значение\" — название атрибута пользователя " -"службы Feishu" +"пользователя системы, а \"значение\" — название атрибута пользователя службы " +"Feishu" #: settings/serializers/auth/lark.py:13 users/models/user/_source.py:24 msgid "Lark" @@ -7845,12 +7957,12 @@ msgstr "Lark" #: settings/serializers/auth/lark.py:19 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Lark service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Lark service user attribute name" msgstr "" "Сопоставление атрибутов пользователя, где \"ключ\" — это имя атрибута " -"пользователя системы, а \"значение\" — это имя атрибута пользователя " -"службы Lark" +"пользователя системы, а \"значение\" — это имя атрибута пользователя службы " +"Lark" #: settings/serializers/auth/ldap.py:42 settings/serializers/auth/ldap.py:108 msgid "LDAP" @@ -7896,12 +8008,12 @@ msgstr "Возможные варианты: (cn или uid или sAMAccountNam #: settings/serializers/auth/ldap.py:69 settings/serializers/auth/ldap_ha.py:51 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the LDAP service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the LDAP service user attribute name" msgstr "" "Сопоставление атрибутов пользователя, где \"ключ\" — это имя атрибута " -"пользователя системы, а \"значение\" — это имя атрибута пользователя " -"службы LDAP" +"пользователя системы, а \"значение\" — это имя атрибута пользователя службы " +"LDAP" #: settings/serializers/auth/ldap.py:85 settings/serializers/auth/ldap_ha.py:67 msgid "Connect timeout (s)" @@ -8008,8 +8120,8 @@ msgstr "При выходе пользователя из системы он т #: settings/serializers/auth/oauth2.py:62 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OAuth2 service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OAuth2 service user attribute name" msgstr "" "Сопоставление атрибутов пользователя, где \"ключ\" - это название атрибута " "пользователя системы, а \"значение\" - название атрибута пользователя " @@ -8046,8 +8158,8 @@ msgstr "Игнорировать проверку SSL" #: settings/serializers/auth/oidc.py:41 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OIDC service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OIDC service user attribute name" msgstr "" "Сопоставление атрибутов пользователя, где \"ключ\" - это имя атрибута " "пользователя системы, а \"значение\" - это имя атрибута пользователя OIDC " @@ -8194,8 +8306,8 @@ msgstr "При выходе пользователя из системы он т #: settings/serializers/auth/slack.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Slack service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Slack service user attribute name" msgstr "" "Сопоставление атрибутов пользователя, где \"ключ\" — это имя атрибута " "пользователя системы, а \"значение\" — имя атрибута пользователя Slack " @@ -8233,7 +8345,7 @@ msgid "Template code" msgstr "Шаблон" #: settings/serializers/auth/sms.py:40 users/models/user/__init__.py:89 -#: users/serializers/user.py:159 +#: users/serializers/user.py:164 msgid "Phone" msgstr "Телефон" @@ -8290,7 +8402,10 @@ msgid "Enable SSO auth" msgstr "Включить аутентификацию по SSO-токену" #: settings/serializers/auth/sso.py:17 -msgid "Other service can using SSO token login to JumpServer without password" +#, fuzzy +#| msgid "" +#| "Other service can using SSO token login to JumpServer without password" +msgid "Other service can using SSO token login to system without password" msgstr "" "Другие системы могут использовать токен SSO для интеграции с JumpServer, " "исключая процесс входа в систему" @@ -8306,8 +8421,8 @@ msgstr "Единицы: секунды" #: settings/serializers/auth/wecom.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the WeCom service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the WeCom service user attribute name" msgstr "" "Сопоставление атрибутов пользователя, где \"ключ\" — это название атрибута " "пользователя системы, а \"значение\" — это название атрибута пользователя " @@ -9487,7 +9602,7 @@ msgstr "Ожидание: " msgid "The verification code has been sent" msgstr "Код подтверждения был отправлен" -#: templates/_without_nav_base.html:46 +#: templates/_without_nav_base.html:51 msgid "Home page" msgstr "Главная страница" @@ -9752,31 +9867,31 @@ msgstr "Возможен параллельный запуск" msgid "Hosts" msgstr "Хосты" -#: terminal/models/applet/applet.py:94 +#: terminal/models/applet/applet.py:102 #: terminal/models/virtualapp/virtualapp.py:66 #, python-brace-format msgid "Applet pkg not valid, Missing file {}" msgstr "Недопустимый пакет Applet: отсутствует файл {}" -#: terminal/models/applet/applet.py:113 +#: terminal/models/applet/applet.py:121 #, python-brace-format msgid "Load platform.yml failed: {}" msgstr "Не удалось загрузить platform.yml: {}" -#: terminal/models/applet/applet.py:116 +#: terminal/models/applet/applet.py:124 msgid "Only support custom platform" msgstr "Поддерживается только пользовательская платформа" -#: terminal/models/applet/applet.py:121 +#: terminal/models/applet/applet.py:129 msgid "Missing type in platform.yml" msgstr "Отсутствует тип в platform.yml" -#: terminal/models/applet/applet.py:381 terminal/models/applet/host.py:36 +#: terminal/models/applet/applet.py:389 terminal/models/applet/host.py:36 #: terminal/models/applet/host.py:138 msgid "Hosting" msgstr "Хост-машина" -#: terminal/models/applet/applet.py:387 +#: terminal/models/applet/applet.py:395 msgid "Applet Publication" msgstr "Публикация приложения" @@ -9866,7 +9981,7 @@ msgstr "VNC порт" #: terminal/models/component/endpoint.py:35 #: terminal/models/component/endpoint.py:115 -#: terminal/serializers/endpoint.py:63 terminal/serializers/storage.py:41 +#: 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" @@ -10080,8 +10195,8 @@ msgstr "Хранение команд и записей сессий" #: terminal/notifications.py:279 terminal/tasks.py:212 #: xpack/plugins/cloud/api.py:182 -#: xpack/plugins/cloud/serializers/account.py:143 -#: xpack/plugins/cloud/serializers/account.py:146 +#: xpack/plugins/cloud/serializers/account.py:148 +#: xpack/plugins/cloud/serializers/account.py:151 msgid "Test failure: Account invalid" msgstr "Тест не пройден: учетная запись недействительна" @@ -10203,11 +10318,13 @@ msgstr "Существующая лицензия RDS" msgid "" "If not exist, the RDS will be in trial mode, and the trial period is 120 " "days. Detail" +"remote-desktop-services/rds-client-access-license\" " +"target=\"_blank\">Detail" msgstr "" "Если лицензия отсутствует, RDS будет работать в пробном режиме в течение 120 " "дней. Подробнее" +"remote-desktop-services/rds-client-access-license' " +"target='_blank'>Подробнее" #: terminal/serializers/applet_host.py:55 msgid "RDS License Server" @@ -10336,7 +10453,7 @@ msgstr "Неверный id сессии" msgid "Timestamp" msgstr "Метка времени" -#: terminal/serializers/endpoint.py:27 +#: terminal/serializers/endpoint.py:28 msgid "" "The host address accessed when connecting to assets, if it is empty, the " "access address of the current browser will be used (the default endpoint " @@ -10346,7 +10463,7 @@ msgstr "" "Если он пустой, используется адрес доступа текущего браузера (в конечной " "точке по умолчанию нельзя изменить хост)" -#: terminal/serializers/endpoint.py:54 +#: terminal/serializers/endpoint.py:64 msgid "" "The assets within this IP range or Host, the following endpoint will be used " "for the connection" @@ -10354,7 +10471,7 @@ msgstr "" "Активы в пределах данного диапазона IP или хоста будут подключены с " "использованием следующей конечной точки." -#: terminal/serializers/endpoint.py:55 +#: terminal/serializers/endpoint.py:65 msgid "" "If asset IP addresses under different endpoints conflict, use asset labels" msgstr "" @@ -10495,7 +10612,7 @@ msgstr "Онлайн" msgid "Stat" msgstr "Статус" -#: terminal/serializers/terminal.py:83 terminal/serializers/terminal.py:91 +#: terminal/serializers/terminal.py:79 terminal/serializers/terminal.py:87 msgid "Not found" msgstr "Отсутствует" @@ -11099,7 +11216,7 @@ msgstr "Запрашивающий" msgid "Approval Step Distribution" msgstr "Одобрение без входа" -#: tickets/serializers/flow.py:45 +#: tickets/serializers/flow.py:42 msgid "The current organization type already exists" msgstr "В текущей организации уже существует данный тип" @@ -11160,7 +11277,7 @@ msgid "Ticket information" msgstr "Информация о заявке" #: tickets/templates/tickets/approve_check_password.html:28 -#: tickets/views/approve.py:43 tickets/views/approve.py:80 +#: tickets/views/approve.py:42 tickets/views/approve.py:80 msgid "Ticket approval" msgstr "Одобрение заявки" @@ -11168,14 +11285,14 @@ msgstr "Одобрение заявки" msgid "Approval" msgstr "Согласен" -#: tickets/views/approve.py:44 +#: tickets/views/approve.py:43 msgid "" "This ticket does not exist, the process has ended, or this link has expired" msgstr "" "Эта заявка не существует, процесс завершен или срок действия этой ссылки " "истек" -#: tickets/views/approve.py:72 +#: tickets/views/approve.py:71 msgid "Click the button below to approve or reject" msgstr "Нажмите кнопку ниже, чтобы одобрить или отклонить" @@ -11391,7 +11508,7 @@ msgstr "Настройки пользователя" msgid "Email lookup" msgstr "Адрес электронной почты" -#: users/models/user/__init__.py:82 users/serializers/user.py:259 +#: users/models/user/__init__.py:82 users/serializers/user.py:264 msgid "Is service account" msgstr "Служебная УЗ" @@ -11410,7 +11527,7 @@ msgstr "Секретный ключ OTP" # msgid "Private key" # msgstr "ssh私钥" #: users/models/user/__init__.py:105 users/serializers/profile.py:86 -#: users/serializers/user.py:256 +#: users/serializers/user.py:261 msgid "Is first login" msgstr "Первый вход" @@ -11430,23 +11547,23 @@ msgstr "Вектор лица" msgid "Date api key used" msgstr "Дата использования ключа API" -#: users/models/user/__init__.py:293 +#: users/models/user/__init__.py:298 msgid "Can not delete admin user" msgstr "Невозможно удалить администратора" -#: users/models/user/__init__.py:307 +#: users/models/user/__init__.py:312 msgid "Can invite user" msgstr "Приглашать пользователя" -#: users/models/user/__init__.py:308 +#: users/models/user/__init__.py:313 msgid "Can remove user" msgstr "Удаление пользователя" -#: users/models/user/__init__.py:309 +#: users/models/user/__init__.py:314 msgid "Can match user" msgstr "Сопоставление пользователей" -#: users/models/user/__init__.py:338 +#: users/models/user/__init__.py:343 msgid "User password history" msgstr "История паролей пользователя" @@ -11454,6 +11571,12 @@ msgstr "История паролей пользователя" msgid "Force enabled" msgstr "Принудительное включение" +#: users/models/user/_source.py:27 +#, fuzzy +#| msgid "Authenticate" +msgid "Certificate" +msgstr "Аутентификация" + #: users/notifications.py:23 users/notifications.py:68 msgid "Reset password url" msgstr "Ссылка для сброса пароля" @@ -11567,7 +11690,7 @@ msgstr "Асинхронная загрузка дерева активов" msgid "Connect default open method" msgstr "Подключить с настройками по умолчанию" -#: users/serializers/preference/luna.py:34 xpack/plugins/interface/models.py:42 +#: users/serializers/preference/luna.py:34 xpack/plugins/interface/models.py:44 #: xpack/plugins/interface/serializers/interface.py:35 msgid "Theme" msgstr "Тема" @@ -11685,7 +11808,7 @@ msgstr "Обязательная МФА" msgid "Login blocked" msgstr "Вход заблокирован" -#: users/serializers/user.py:130 users/serializers/user.py:265 +#: users/serializers/user.py:130 users/serializers/user.py:270 msgid "Is OTP bound" msgstr "OTP привязан" @@ -11701,27 +11824,33 @@ msgstr "Администратор организации" msgid "Can public key authentication" msgstr "Может войти с открытым ключем" -#: users/serializers/user.py:144 +#: users/serializers/user.py:145 +#, fuzzy +#| msgid "Can public key authentication" +msgid "Can certificate authentication" +msgstr "Может войти с открытым ключем" + +#: users/serializers/user.py:149 msgid "Is face code set" msgstr "Есть настройки биометрии" -#: users/serializers/user.py:230 +#: users/serializers/user.py:235 msgid "Full name" msgstr "Полное имя" -#: users/serializers/user.py:233 +#: users/serializers/user.py:238 msgid "Login username" msgstr "Имя пользователя для входа" -#: users/serializers/user.py:236 +#: users/serializers/user.py:241 msgid "Email address" msgstr "Адрес электронной почты" -#: users/serializers/user.py:246 +#: users/serializers/user.py:251 msgid "User groups to join" msgstr "Группы пользователей для добавления" -#: users/serializers/user.py:250 +#: users/serializers/user.py:255 msgid "" "User source identifies where the user was created, which could be AD or " "other sources.There are security settings that can restrict users to log in " @@ -11732,34 +11861,34 @@ msgstr "" "ограничивать пользователей, чтобы они входили в систему только из указанных " "источников." -#: users/serializers/user.py:260 +#: users/serializers/user.py:265 msgid "Is org admin" msgstr "Администратор организации" -#: users/serializers/user.py:262 +#: users/serializers/user.py:267 msgid "Avatar url" msgstr "URL аватара" -#: users/serializers/user.py:267 +#: users/serializers/user.py:272 msgid "MFA level" msgstr "Уровень МФА" -#: users/serializers/user.py:268 +#: users/serializers/user.py:273 msgid "Multi-Factor Authentication" msgstr "Многофакторная аутентификация" -#: users/serializers/user.py:398 +#: users/serializers/user.py:403 msgid "Has public keys" msgstr "Есть открытый ключ" -#: users/serializers/user.py:426 +#: users/serializers/user.py:431 msgid "" "* For security, only a partial of users is displayed. You can search for more" msgstr "" "* В целях безопасности отображаются только некоторые пользователи. Вы можете " "выполнить поиск по другим" -#: users/serializers/user.py:462 +#: users/serializers/user.py:467 msgid "name not unique" msgstr "имя не уникально" @@ -12281,7 +12410,7 @@ msgstr "Частный IP" msgid "Public IP" msgstr "Публичный IP" -#: xpack/plugins/cloud/const.py:50 xpack/plugins/cloud/models.py:373 +#: xpack/plugins/cloud/const.py:50 xpack/plugins/cloud/models.py:374 msgid "Instance name" msgstr "Имя экземпляра" @@ -12482,8 +12611,8 @@ msgstr "Опубликовать активы" msgid "Date last sync" msgstr "Дата последней синхронизации" -#: xpack/plugins/cloud/models.py:135 xpack/plugins/cloud/models.py:391 -#: xpack/plugins/cloud/models.py:418 +#: xpack/plugins/cloud/models.py:135 xpack/plugins/cloud/models.py:392 +#: xpack/plugins/cloud/models.py:419 msgid "Strategy" msgstr "Стратегия" @@ -12523,71 +12652,71 @@ msgstr "Логика правил" msgid "Task strategy" msgstr "Стратегия задачи" -#: xpack/plugins/cloud/models.py:362 +#: xpack/plugins/cloud/models.py:363 msgid "Equal" msgstr "Равно" -#: xpack/plugins/cloud/models.py:363 +#: xpack/plugins/cloud/models.py:364 msgid "Not Equal" msgstr "Не равно" -#: xpack/plugins/cloud/models.py:364 +#: xpack/plugins/cloud/models.py:365 msgid "In" msgstr "в" -#: xpack/plugins/cloud/models.py:365 +#: xpack/plugins/cloud/models.py:366 msgid "Contains" msgstr "Содержит" -#: xpack/plugins/cloud/models.py:366 +#: xpack/plugins/cloud/models.py:367 msgid "Exclude" msgstr "Исключить" -#: xpack/plugins/cloud/models.py:367 +#: xpack/plugins/cloud/models.py:368 msgid "Startswith" msgstr "Начинается с" -#: xpack/plugins/cloud/models.py:368 +#: xpack/plugins/cloud/models.py:369 msgid "Endswith" msgstr "Заканчивается на" -#: xpack/plugins/cloud/models.py:374 +#: xpack/plugins/cloud/models.py:375 msgid "Instance platform" msgstr "Платформа экземпляра" -#: xpack/plugins/cloud/models.py:375 +#: xpack/plugins/cloud/models.py:376 msgid "Instance address" msgstr "Адрес экземпляра" -#: xpack/plugins/cloud/models.py:382 +#: xpack/plugins/cloud/models.py:383 msgid "Rule attr" msgstr "Атрибуты правила" -#: xpack/plugins/cloud/models.py:386 +#: xpack/plugins/cloud/models.py:387 msgid "Rule match" msgstr "Сопоставление правила" -#: xpack/plugins/cloud/models.py:388 +#: xpack/plugins/cloud/models.py:389 msgid "Rule value" msgstr "Значение правила" -#: xpack/plugins/cloud/models.py:395 xpack/plugins/cloud/serializers/task.py:82 +#: xpack/plugins/cloud/models.py:396 xpack/plugins/cloud/serializers/task.py:82 msgid "Strategy rule" msgstr "Правило стратегии" -#: xpack/plugins/cloud/models.py:406 +#: xpack/plugins/cloud/models.py:407 msgid "Name strategy" msgstr "Стратегия имени" -#: xpack/plugins/cloud/models.py:413 +#: xpack/plugins/cloud/models.py:414 msgid "Action attr" msgstr "Атрибуты действия" -#: xpack/plugins/cloud/models.py:415 +#: xpack/plugins/cloud/models.py:416 msgid "Action value" msgstr "Значение действия" -#: xpack/plugins/cloud/models.py:422 xpack/plugins/cloud/serializers/task.py:85 +#: xpack/plugins/cloud/models.py:423 xpack/plugins/cloud/serializers/task.py:85 msgid "Strategy action" msgstr "Действия стратегии" @@ -12950,38 +13079,38 @@ msgstr "Миссия еще не началась" msgid "Restore default successfully." msgstr "Настройки по умолчанию успешно восстановлены." -#: xpack/plugins/interface/meta.py:9 xpack/plugins/interface/models.py:47 -#: xpack/plugins/interface/models.py:91 +#: xpack/plugins/interface/meta.py:9 xpack/plugins/interface/models.py:49 +#: xpack/plugins/interface/models.py:104 msgid "Interface settings" msgstr "Настройки интерфейса" -#: xpack/plugins/interface/models.py:24 +#: xpack/plugins/interface/models.py:26 msgid "Login title" msgstr "Заголовок страницы входа" -#: xpack/plugins/interface/models.py:28 +#: xpack/plugins/interface/models.py:30 msgid "Login image" msgstr "Изображение на странице входа" -#: xpack/plugins/interface/models.py:32 +#: xpack/plugins/interface/models.py:34 msgid "Website icon" msgstr "Иконка сайта" -#: xpack/plugins/interface/models.py:36 +#: xpack/plugins/interface/models.py:38 msgid "Index logo" msgstr "Логотип страницы" -#: xpack/plugins/interface/models.py:40 +#: xpack/plugins/interface/models.py:42 msgid "Logout logo" msgstr "Иконка выхода" -#: xpack/plugins/interface/models.py:43 +#: xpack/plugins/interface/models.py:45 msgid "Footer content" msgstr "Содержимое нижнего колонтитула" -#: xpack/plugins/interface/models.py:44 +#: xpack/plugins/interface/models.py:46 #: xpack/plugins/interface/serializers/interface.py:73 -msgid "Extended fields" +msgid "Extend" msgstr "" #: xpack/plugins/interface/serializers/interface.py:48 @@ -13036,6 +13165,12 @@ msgstr "" msgid "More login methods" msgstr "Другие способы входа" +#: xpack/plugins/jdmc/i18n.py:4 +#, fuzzy +#| msgid "Audit view" +msgid "AuditAdmin" +msgstr "Панель Аудита" + #: xpack/plugins/jdmc/i18n.py:5 #, fuzzy #| msgid "SystemAdmin" @@ -13054,6 +13189,9 @@ msgstr "Лицензия успешно импортирована" msgid "Invalid license" msgstr "Лицензия недействительна" +#~ msgid "User invalid, disabled or expired" +#~ msgstr "Пользователь недействителен, отключен или просрочен" + #~ msgid "Microsoft" #~ msgstr "Microsoft" diff --git a/apps/i18n/core/vi/LC_MESSAGES/django.po b/apps/i18n/core/vi/LC_MESSAGES/django.po index cd05229d1..872b05540 100644 --- a/apps/i18n/core/vi/LC_MESSAGES/django.po +++ b/apps/i18n/core/vi/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-04-21 17:03+0800\n" +"POT-Creation-Date: 2026-05-25 14:02+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -28,7 +28,7 @@ msgstr "Tài khoản đã tồn tại" msgid "No valid assets found for account creation." msgstr "Không tìm thấy tài sản hợp lệ để tạo tài khoản." -#: accounts/api/account/application.py:77 +#: accounts/api/account/application.py:87 #: authentication/api/connection_token.py:463 msgid "Account not found" msgstr "Tài khoản không tìm thấy" @@ -42,15 +42,15 @@ msgstr "Tham số 'action' phải là [{}]" msgid "The account key will be split into two parts and sent" msgstr "Khóa tài khoản sẽ được chia thành hai phần gửi đi" -#: accounts/automations/backup_account/handlers.py:131 +#: accounts/automations/backup_account/handlers.py:132 msgid "Number of backup accounts" msgstr "Số lượng tài khoản sao lưu" -#: accounts/automations/backup_account/handlers.py:152 +#: accounts/automations/backup_account/handlers.py:153 msgid "Generating asset related backup information files" msgstr "Tạo tệp thông tin sao lưu liên quan đến tài sản" -#: accounts/automations/backup_account/handlers.py:177 +#: accounts/automations/backup_account/handlers.py:178 #: accounts/automations/backup_account/manager.py:26 #: accounts/automations/change_secret/manager.py:81 #: accounts/automations/push_account/manager.py:62 @@ -61,31 +61,31 @@ msgstr "Tạo tệp thông tin sao lưu liên quan đến tài sản" msgid "Duration" msgstr "Thời gian tiêu tốn" -#: accounts/automations/backup_account/handlers.py:178 +#: accounts/automations/backup_account/handlers.py:179 msgid "Backup file creation completed" msgstr "Hoàn thành việc tạo tệp sao lưu" -#: accounts/automations/backup_account/handlers.py:186 +#: accounts/automations/backup_account/handlers.py:187 msgid "Start sending backup emails" msgstr "Bắt đầu gửi email sao lưu" -#: accounts/automations/backup_account/handlers.py:213 +#: accounts/automations/backup_account/handlers.py:214 msgid "Encrypting files using encryption password" msgstr "Đang mã hóa tệp bằng mật khẩu mã hóa" -#: accounts/automations/backup_account/handlers.py:223 +#: accounts/automations/backup_account/handlers.py:224 msgid "The backup file will be sent to" msgstr "Tệp sao lưu sẽ được gửi đến" -#: accounts/automations/backup_account/handlers.py:246 +#: accounts/automations/backup_account/handlers.py:247 msgid "The backup task has no assigned sftp server" msgstr "Nhiệm vụ sao lưu này chưa được phân bổ máy chủ sftp" -#: accounts/automations/backup_account/handlers.py:267 +#: accounts/automations/backup_account/handlers.py:268 msgid "The backup task has no assigned recipient" msgstr "Nhiệm vụ sao lưu không chỉ định người nhận" -#: accounts/automations/backup_account/handlers.py:290 +#: accounts/automations/backup_account/handlers.py:291 msgid "Plan start" msgstr "Nhiệm vụ bắt đầu" @@ -154,7 +154,7 @@ msgstr "" #: settings/serializers/auth/ldap.py:53 settings/serializers/auth/ldap_ha.py:35 #: settings/serializers/msg.py:37 settings/serializers/terminal.py:32 #: terminal/serializers/storage.py:123 terminal/serializers/storage.py:142 -#: users/forms/profile.py:22 users/serializers/user.py:148 +#: users/forms/profile.py:22 users/serializers/user.py:153 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/cloud/serializers/account_attrs.py:43 @@ -228,7 +228,7 @@ msgstr "Cập nhật" #: accounts/const/account.py:34 accounts/const/automation.py:115 #: accounts/serializers/automations/change_secret.py:171 audits/const.py:66 -#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:66 +#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:67 #: ops/const.py:77 terminal/const.py:81 xpack/plugins/cloud/const.py:55 msgid "Failed" msgstr "Thất bại" @@ -350,14 +350,14 @@ msgstr "SFTP" #: accounts/const/automation.py:116 #: accounts/serializers/automations/change_secret.py:170 audits/const.py:65 #: audits/models.py:65 audits/signal_handlers/activity_log.py:34 -#: common/const/choices.py:65 ops/const.py:75 ops/serializers/celery.py:48 +#: common/const/choices.py:66 ops/const.py:75 ops/serializers/celery.py:48 #: terminal/const.py:80 terminal/models/session/sharing.py:119 #: tickets/views/approve.py:128 msgid "Success" msgstr "Success" -#: accounts/const/automation.py:117 common/const/choices.py:63 -#: common/const/choices.py:114 terminal/const.py:79 +#: accounts/const/automation.py:117 common/const/choices.py:64 +#: common/const/choices.py:127 terminal/const.py:79 msgid "Pending" msgstr "Đang chờ xử lý" @@ -365,7 +365,7 @@ msgstr "Đang chờ xử lý" msgid "Queued" msgstr "Sẵn sàng" -#: accounts/const/automation.py:122 common/const/choices.py:62 +#: accounts/const/automation.py:122 common/const/choices.py:63 msgid "Ready" msgstr "Đang xử lý" @@ -377,7 +377,7 @@ msgstr "Có thể đăng nhập" msgid "Can login" msgstr "Siêu người dùng" -#: accounts/const/automation.py:128 users/serializers/user.py:254 +#: accounts/const/automation.py:128 users/serializers/user.py:259 msgid "Superuser" msgstr "Ngày tạo" @@ -406,7 +406,7 @@ msgid "Default tablespace" msgstr "Không gian bảng mặc định" #: accounts/const/automation.py:135 rbac/models/role.py:46 -#: rbac/models/rolebinding.py:52 users/models/user/__init__.py:79 +#: rbac/models/rolebinding.py:53 users/models/user/__init__.py:79 msgid "Role" msgstr "Vai trò" @@ -415,7 +415,7 @@ msgid "Perms" msgstr "Quyền hạn" #: accounts/const/automation.py:137 perms/serializers/permission.py:56 -#: users/serializers/user.py:245 +#: users/serializers/user.py:250 msgid "Groups" msgstr "Nhóm người dùng" @@ -790,7 +790,7 @@ msgstr "Ngày kết thúc" #: assets/models/automations/base.py:137 #: assets/serializers/automations/base.py:47 audits/models.py:224 #: audits/reporting.py:607 audits/serializers.py:77 ops/models/base.py:49 -#: ops/models/job.py:233 terminal/models/applet/applet.py:382 +#: ops/models/job.py:233 terminal/models/applet/applet.py:390 #: terminal/models/applet/host.py:140 terminal/models/component/status.py:30 #: terminal/models/virtualapp/virtualapp.py:99 #: terminal/serializers/applet.py:19 terminal/serializers/applet_host.py:163 @@ -805,7 +805,7 @@ msgstr "Trạng thái" #: accounts/serializers/account/account.py:297 assets/const/automation.py:9 #: authentication/templates/authentication/passkey.html:177 #: authentication/views/base.py:43 authentication/views/base.py:44 -#: authentication/views/base.py:45 common/const/choices.py:67 +#: authentication/views/base.py:45 common/const/choices.py:68 #: settings/templates/ldap/_msg_import_ldap_user.html:26 msgid "Error" msgstr "Lỗi" @@ -900,8 +900,9 @@ msgstr "Mật khẩu trùng lặp" #: accounts/templates/accounts/push_account_report.html:79 #: accounts/templates/accounts/push_account_report.html:119 #: acls/serializers/base.py:19 acls/serializers/base.py:50 audits/models.py:204 -#: audits/reporting.py:241 authentication/forms.py:21 -#: authentication/forms.py:23 authentication/models/temp_token.py:10 +#: audits/reporting.py:241 authentication/backends/cert/forms.py:7 +#: authentication/forms.py:21 authentication/forms.py:23 +#: authentication/models/temp_token.py:10 #: authentication/serializers/connect_token_secret.py:43 #: authentication/serializers/connect_token_secret.py:53 #: authentication/templates/authentication/_msg_different_city.html:9 @@ -1072,7 +1073,7 @@ msgstr "Tài khoản đặc quyền" #: assets/models/cmd_filter.py:39 assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:129 reports/models.py:18 #: terminal/models/applet/applet.py:41 -#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:257 +#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:262 msgid "Is active" msgstr "Active" @@ -1088,7 +1089,7 @@ msgstr "Nền tảng" msgid "Push params" msgstr "Tham số đẩy tài khoản" -#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:403 +#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:404 msgid "Account template" msgstr "Mẫu tài khoản" @@ -1185,7 +1186,7 @@ msgstr "Thông tin thay đổi tài khoản." msgid "Change secret or push account failed information" msgstr "Thông báo lỗi khi thay đổi mật khẩu hoặc đẩy tài khoản." -#: accounts/risk_handlers.py:17 common/const/choices.py:116 +#: accounts/risk_handlers.py:17 common/const/choices.py:129 msgid "Ignored" msgstr "Bỏ qua." @@ -1341,7 +1342,7 @@ msgstr "ID" #: authentication/notifications.py:16 authentication/notifications.py:55 #: notifications/models/notification.py:12 #: perms/api/user_permission/mixin.py:58 perms/models/asset_permission.py:63 -#: rbac/builtin.py:134 rbac/models/rolebinding.py:49 +#: rbac/builtin.py:134 rbac/models/rolebinding.py:50 #: rbac/serializers/rolebinding.py:17 terminal/backends/command/models.py:16 #: terminal/models/session/session.py:27 terminal/models/session/sharing.py:34 #: terminal/notifications.py:168 terminal/notifications.py:235 @@ -1349,8 +1350,8 @@ msgstr "ID" #: terminal/templates/terminal/_msg_command_warning.html:9 #: terminal/templates/terminal/_msg_session_sharing.html:6 #: tickets/models/comment.py:21 tickets/serializers/flow.py:15 -#: users/const.py:14 users/models/user/__init__.py:298 -#: users/models/user/__init__.py:325 +#: users/const.py:14 users/models/user/__init__.py:303 +#: users/models/user/__init__.py:330 msgid "User" msgstr "Người dùng" @@ -1385,7 +1386,7 @@ msgstr "Danh sách trắng IP" #: assets/models/cmd_filter.py:88 common/db/models.py:36 ops/models/adhoc.py:25 #: ops/models/job.py:165 ops/models/playbook.py:31 rbac/models/role.py:37 #: settings/models.py:43 terminal/models/applet/applet.py:46 -#: terminal/models/applet/applet.py:383 terminal/models/applet/host.py:143 +#: terminal/models/applet/applet.py:391 terminal/models/applet/host.py:143 #: terminal/models/component/endpoint.py:29 #: terminal/models/component/endpoint.py:117 #: terminal/models/session/session.py:44 @@ -1684,7 +1685,7 @@ msgstr "" "hạn ghi chép lưu trữ tài khoản - mỗi ngày vào lúc 2 giờ sáng sẽ dọn dẹp các " "bản ghi tài khoản vượt quá số lượng quy định" -#: accounts/tasks/remove_account.py:89 +#: accounts/tasks/remove_account.py:91 msgid "Remove historical accounts that are out of range." msgstr "Xóa các tài khoản lịch sử vượt quá giới hạn." @@ -1757,7 +1758,7 @@ msgstr "Tên nhiệm vụ" #: accounts/templates/accounts/push_account_report.html:22 #: assets/models/automations/base.py:143 audits/models.py:66 #: ops/models/base.py:55 ops/models/celery.py:89 ops/models/job.py:241 -#: ops/templates/ops/celery_task_log.html:101 +#: ops/templates/ops/celery_task_log.html:154 #: perms/models/asset_permission.py:78 settings/serializers/feature.py:29 #: settings/templates/ldap/_msg_import_ldap_user.html:5 #: terminal/models/applet/host.py:141 terminal/models/session/session.py:42 @@ -1945,7 +1946,7 @@ msgstr "Người phê duyệt" #: acls/models/base.py:81 perms/serializers/permission.py:54 #: tickets/models/flow.py:23 users/models/preference.py:16 -#: users/serializers/group.py:21 users/serializers/user.py:424 +#: users/serializers/group.py:21 users/serializers/user.py:429 msgid "Users" msgstr "Người dùng" @@ -1971,7 +1972,7 @@ msgid "Command" msgstr "Lệnh" #: acls/models/command_acl.py:17 assets/models/cmd_filter.py:59 -#: xpack/plugins/cloud/models.py:369 +#: xpack/plugins/cloud/models.py:370 msgid "Regex" msgstr "Biểu thức chính quy" @@ -2060,7 +2061,7 @@ msgstr "Quy tắc" msgid "Login acl" msgstr "Kiểm soát truy cập đăng nhập" -#: acls/models/login_acl.py:27 tickets/const.py:11 +#: acls/models/login_acl.py:30 tickets/const.py:11 msgid "Login confirm" msgstr "Kiểm tra đăng nhập" @@ -2182,7 +2183,7 @@ msgstr "" #: authentication/templates/authentication/_msg_oauth_bind.html:12 #: authentication/templates/authentication/_msg_rest_password_success.html:8 #: authentication/templates/authentication/_msg_rest_public_key_success.html:8 -#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:405 +#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:406 msgid "IP" msgstr "IP" @@ -2247,7 +2248,7 @@ msgstr "Chúng tôi xin thông báo rằng, gần đây có người dùng đã msgid "User details" msgstr "Thông tin người dùng" -#: assets/api/asset/asset.py:166 +#: assets/api/asset/asset.py:168 msgid "Cannot create asset directly, you should create a host or other" msgstr "" "Không thể tạo tài sản trực tiếp, bạn nên tạo máy chủ hoặc các tài sản khác. " @@ -2261,11 +2262,11 @@ msgstr "" ">>> Không có nhiệm vụ nào cần thực hiện. <–SEP–> >>> Bắt đầu thực hiện đợt " "nhiệm vụ thứ {index}. <–SEP–> Không có tài khoản." -#: assets/api/asset/asset.py:173 +#: assets/api/asset/asset.py:175 msgid "The number of assets exceeds the limit of 5000" msgstr "Số lượng tài sản vượt quá giới hạn 5000" -#: assets/api/asset/asset.py:179 +#: assets/api/asset/asset.py:181 #, fuzzy #| msgid "The number of assets exceeds the limit of 5000" msgid "The number of assets exceeds the license limit" @@ -2284,6 +2285,11 @@ msgstr "Không thể xóa nút gốc ({})" msgid "Deletion failed and the node contains assets" msgstr "Xóa không thành công, nút chứa tài sản" +#: assets/api/node.py:99 +#, python-brace-format +msgid "Node {} is an ancestor of node {}, can't be added as its child" +msgstr "" + #: assets/api/tree.py:48 assets/serializers/node.py:42 msgid "The same level node name cannot be the same" msgstr "Tên nút cùng cấp không được trùng lặp" @@ -2301,29 +2307,29 @@ msgstr "Assets" msgid "Task: {} finished" msgstr "Nhiệm vụ: {} Hoàn thành" -#: assets/automations/base/manager.py:340 +#: assets/automations/base/manager.py:341 #, python-brace-format msgid " - Platform {} ansible disabled" msgstr "- Nền tảng {} Ansible đã bị vô hiệu hóa, không thể thực hiện nhiệm vụ" -#: assets/automations/base/manager.py:555 +#: assets/automations/base/manager.py:556 msgid ">>> Task preparation phase" msgstr ">>> Giai đoạn chuẩn bị nhiệm vụ" -#: assets/automations/base/manager.py:559 +#: assets/automations/base/manager.py:560 #, python-brace-format msgid ">>> Executing tasks in batches, total {runner_count}" msgstr ">>> Thực hiện nhiệm vụ theo từng đợt, tổng cộng {runner_count}" -#: assets/automations/base/manager.py:564 +#: assets/automations/base/manager.py:565 msgid ">>> Start executing tasks" msgstr ">>> Bắt đầu thực hiện nhiệm vụ" -#: assets/automations/base/manager.py:566 +#: assets/automations/base/manager.py:567 msgid ">>> No tasks need to be executed" msgstr ">>> Không có nhiệm vụ nào cần thực hiện" -#: assets/automations/base/manager.py:570 +#: assets/automations/base/manager.py:571 #, python-brace-format msgid ">>> Begin executing batch {index} of tasks" msgstr ">>> Bắt đầu thực hiện đợt nhiệm vụ thứ {index}" @@ -2728,7 +2734,7 @@ msgid "Port" msgstr "Cổng" #: assets/models/asset/common.py:167 assets/serializers/asset/common.py:175 -#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:59 +#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:69 msgid "Address" msgstr "Địa chỉ" @@ -2736,12 +2742,12 @@ msgstr "Địa chỉ" #: assets/serializers/asset/common.py:151 #: authentication/backends/passkey/models.py:12 #: authentication/serializers/connect_token_secret.py:130 -#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:399 +#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:400 msgid "Platform" msgstr "Nền tảng" #: assets/models/asset/common.py:173 assets/models/zone.py:22 -#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:401 +#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:402 msgid "Zone" msgstr "Tên miền" @@ -2810,9 +2816,9 @@ msgid "Proxy" msgstr "Đại lý" #: assets/models/automations/base.py:23 assets/models/cmd_filter.py:32 -#: assets/models/node.py:553 ops/models/job.py:158 +#: assets/models/node.py:560 ops/models/job.py:158 #: perms/models/asset_permission.py:72 tickets/models/ticket/apply_asset.py:15 -#: xpack/plugins/cloud/models.py:400 +#: xpack/plugins/cloud/models.py:401 msgid "Node" msgstr "Nút" @@ -2836,7 +2842,7 @@ msgstr "Nhiệm vụ tự động hóa tài sản" #: assets/models/automations/base.py:140 assets/models/cmd_filter.py:41 #: authentication/serializers/token.py:134 common/db/models.py:34 #: ops/models/base.py:54 ops/models/job.py:240 -#: users/models/user/__init__.py:328 +#: users/models/user/__init__.py:333 msgid "Date created" msgstr "Ngày tạo" @@ -2925,7 +2931,7 @@ msgstr "Cổng" msgid "System" msgstr "Hệ thống" -#: assets/models/label.py:19 assets/models/node.py:539 +#: assets/models/label.py:19 assets/models/node.py:546 #: assets/serializers/cagegory.py:11 assets/serializers/cagegory.py:18 #: assets/serializers/cagegory.py:24 #: authentication/models/connection_token.py:35 @@ -2940,7 +2946,7 @@ msgstr "Giá trị" #: assets/serializers/platform.py:160 #: authentication/serializers/connect_token_secret.py:136 #: common/serializers/common.py:85 labels/serializers.py:45 -#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:404 +#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:405 msgid "Label" msgstr "Nhãn" @@ -2956,27 +2962,27 @@ msgstr "Ghi chú tùy chỉnh" msgid "My assets" msgstr "Tài sản của tôi" -#: assets/models/node.py:168 +#: assets/models/node.py:172 msgid "New node" msgstr "Nút mới" -#: assets/models/node.py:467 audits/backends/db.py:85 audits/backends/db.py:86 +#: assets/models/node.py:474 audits/backends/db.py:85 audits/backends/db.py:86 msgid "empty" msgstr "Trống" -#: assets/models/node.py:538 perms/models/perm_node.py:28 +#: assets/models/node.py:545 perms/models/perm_node.py:28 msgid "Key" msgstr "Phím" -#: assets/models/node.py:540 assets/serializers/node.py:20 +#: assets/models/node.py:547 assets/serializers/node.py:20 msgid "Full value" msgstr "Tên đầy đủ" -#: assets/models/node.py:544 perms/models/perm_node.py:30 +#: assets/models/node.py:551 perms/models/perm_node.py:30 msgid "Parent key" msgstr "Khóa SSH riêng" -#: assets/models/node.py:556 +#: assets/models/node.py:563 msgid "Can match node" msgstr "Có thể khớp với nút" @@ -3156,7 +3162,7 @@ msgstr "" #: authentication/serializers/connect_token_secret.py:30 #: authentication/serializers/connect_token_secret.py:77 #: perms/models/asset_permission.py:76 perms/serializers/permission.py:68 -#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:402 +#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:403 #: xpack/plugins/cloud/serializers/task.py:36 msgid "Protocols" msgstr "Nhóm giao thức" @@ -3640,7 +3646,7 @@ msgid "Symlink" msgstr "Tạo liên kết mềm" #: audits/const.py:18 audits/const.py:29 -#: ops/templates/ops/celery_task_log.html:86 +#: ops/templates/ops/celery_task_log.html:139 #: terminal/api/session/session.py:159 msgid "Download" msgstr "Tải xuống" @@ -3669,7 +3675,9 @@ msgstr "Xuất" msgid "Connect" msgstr "Kết nối" -#: audits/const.py:31 authentication/templates/authentication/login.html:334 +#: audits/const.py:31 +#: authentication/templates/authentication/cert_login.html:232 +#: authentication/templates/authentication/login.html:334 #: authentication/templates/authentication/login.html:408 #: templates/_header_bar.html:101 #: xpack/plugins/interface/templates/login_i18n.html:21 @@ -4464,17 +4472,17 @@ msgstr "So sánh khuôn mặt thất bại" msgid "Current user not support mfa type: {}" msgstr "Người dùng hiện tại không hỗ trợ loại MFA: {}" -#: authentication/api/password.py:34 terminal/api/session/session.py:347 +#: authentication/api/password.py:37 terminal/api/session/session.py:347 #: users/views/profile/reset.py:63 #, python-brace-format msgid "User does not exist: {}" msgstr "Người dùng không tồn tại: {}" -#: authentication/api/password.py:34 users/views/profile/reset.py:166 +#: authentication/api/password.py:37 users/views/profile/reset.py:166 msgid "No user matched" msgstr "Không tìm thấy người dùng khớp" -#: authentication/api/password.py:38 +#: authentication/api/password.py:41 #, python-brace-format msgid "" "The user is from {}, please go to the corresponding system to change the " @@ -4482,7 +4490,7 @@ msgid "" msgstr "" "Người dùng đến từ {} hãy đi tới hệ thống tương ứng để thay đổi mật khẩu" -#: authentication/api/password.py:69 +#: authentication/api/password.py:72 #: authentication/templates/authentication/login.html:400 #: users/templates/users/forgot_password.html:41 #: users/templates/users/forgot_password.html:42 @@ -4492,7 +4500,7 @@ msgstr "" msgid "Forgot password" msgstr "Quên mật khẩu" -#: authentication/api/password.py:70 authentication/mfa/email.py:42 +#: authentication/api/password.py:73 authentication/mfa/email.py:42 #, python-brace-format msgid "The validity period of the verification code is {} minute" msgstr "Mã xác minh có hiệu lực trong {} phút" @@ -4505,10 +4513,29 @@ msgstr "Authentication" msgid "CAS Error" msgstr "Lỗi CAS" -#: authentication/backends/custom.py:60 -#: authentication/backends/oauth2/backends.py:158 -msgid "User invalid, disabled or expired" -msgstr "Người dùng không hợp lệ, đã bị vô hiệu hóa hoặc đã hết hạn" +#: authentication/backends/cert/api.py:57 +#, fuzzy +#| msgid "LDAP authentication is not enabled" +msgid "Certificate enrollment is not enabled" +msgstr "Xác thực LDAP chưa được kích hoạt" + +#: authentication/backends/cert/api.py:62 +#, fuzzy +#| msgid "type is required" +msgid "CSR is required" +msgstr "Loại: trường này là bắt buộc." + +#: authentication/backends/cert/api.py:68 +#, fuzzy +#| msgid "Authentication failed" +msgid "Certificate signing failed" +msgstr "Xác thực thất bại" + +#: authentication/backends/cert/views.py:97 +#, fuzzy +#| msgid "Invalid data" +msgid "Invalid credentials" +msgstr "Dữ liệu không hợp lệ" #: authentication/backends/drf.py:61 msgid "Invalid token header. No credentials provided." @@ -4761,16 +4788,16 @@ msgstr "Mật khẩu của bạn không hợp lệ" msgid "Please wait for %s seconds before retry" msgstr "Vui lòng thử lại sau %s giây" -#: authentication/errors/redirect.py:85 authentication/mixins.py:436 +#: authentication/errors/redirect.py:85 authentication/mixins.py:445 #: users/views/profile/reset.py:224 msgid "Your password is too simple, please change it for security" msgstr "Mật khẩu của bạn quá đơn giản, để đảm bảo an toàn, vui lòng thay đổi" -#: authentication/errors/redirect.py:93 authentication/mixins.py:445 +#: authentication/errors/redirect.py:93 authentication/mixins.py:454 msgid "You should to change your password before login" msgstr "Trước khi hoàn tất đăng nhập, vui lòng thay đổi mật khẩu" -#: authentication/errors/redirect.py:101 authentication/mixins.py:454 +#: authentication/errors/redirect.py:101 authentication/mixins.py:463 msgid "Your password has expired, please reset before logging in" msgstr "Mật khẩu của bạn đã hết hạn, hãy thay đổi rồi mới đăng nhập" @@ -4901,11 +4928,11 @@ msgstr "" "dùng hiện tại không có trong danh sách người dùng, vui lòng liên hệ với quản " "trị viên." -#: authentication/mixins.py:184 +#: authentication/mixins.py:187 msgid "User is invalid" msgstr "Người dùng không hợp lệ" -#: authentication/mixins.py:201 +#: authentication/mixins.py:204 #, python-brace-format msgid "" " The administrator has enabled 'Only allow login from user source'. \n" @@ -4915,12 +4942,12 @@ msgstr "" "Quản trị viên đã bật 'chỉ cho phép đăng nhập từ nguồn người dùng', nguồn " "người dùng hiện tại là {}, vui lòng liên hệ với quản trị viên." -#: authentication/mixins.py:382 +#: authentication/mixins.py:391 #, python-brace-format msgid "The MFA type ({}) is not enabled" msgstr "Phương thức MFA ({}) này chưa được kích hoạt" -#: authentication/mixins.py:424 +#: authentication/mixins.py:433 msgid "Please change your password" msgstr "Vui lòng thay đổi mật khẩu" @@ -5114,7 +5141,7 @@ msgstr "Action" #: authentication/serializers/connection_token.py:46 #: perms/serializers/permission.py:66 perms/serializers/permission.py:87 -#: users/serializers/user.py:127 users/serializers/user.py:261 +#: users/serializers/user.py:127 users/serializers/user.py:266 msgid "Is expired" msgstr "Expired" @@ -5156,13 +5183,13 @@ msgstr "SSH khóa không hợp lệ" #: authentication/serializers/token.py:93 perms/serializers/permission.py:65 #: perms/serializers/permission.py:88 users/serializers/user.py:128 -#: users/serializers/user.py:258 +#: users/serializers/user.py:263 msgid "Is valid" msgstr "Is Valid" #: authentication/serializers/token.py:131 ops/models/adhoc.py:26 #: ops/models/playbook.py:34 ops/serializers/mixin.py:10 rbac/models/role.py:31 -#: rbac/models/rolebinding.py:46 rbac/serializers/role.py:12 +#: rbac/models/rolebinding.py:47 rbac/serializers/role.py:12 #: settings/serializers/auth/oauth2.py:37 msgid "Scope" msgstr "Phạm vi" @@ -5264,7 +5291,7 @@ msgstr "Mã không chính xác" #: authentication/templates/authentication/_msg_oauth_bind.html:3 #: authentication/templates/authentication/_msg_reset_password.html:3 #: authentication/templates/authentication/_msg_reset_password_code.html:9 -#: jumpserver/conf.py:555 +#: jumpserver/conf.py:558 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:32 #: users/templates/users/_msg_account_expire_reminder.html:4 @@ -5371,6 +5398,87 @@ msgstr "" msgid "Cancel" msgstr "Hủy bỏ" +#: authentication/templates/authentication/cert_login.html:190 +#, fuzzy +#| msgid "Multi-Factor Authentication" +msgid "Certificate Authentication" +msgstr "Xác thực" + +#: authentication/templates/authentication/cert_login.html:195 +#: authentication/templates/authentication/cert_login.html:250 +msgid "Loading USB Key driver..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:210 +msgid "Insert USB Key to auto-fetch" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:238 +#, fuzzy +#| msgid "More login options" +msgid "Other login methods" +msgstr "Or" + +#: authentication/templates/authentication/cert_login.html:251 +msgid "Detecting USB Key..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:252 +msgid "USB Key connected" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:253 +#, fuzzy +#| msgid "Please enter SMS code" +msgid "Please insert USB Key" +msgstr "Vui lòng nhập mã xác minh qua tin nhắn" + +#: authentication/templates/authentication/cert_login.html:254 +#, fuzzy +#| msgid "Account unavailable" +msgid "Driver unavailable" +msgstr "Tài khoản không hợp lệ" + +#: authentication/templates/authentication/cert_login.html:255 +msgid "USB Key SDK initialization failed" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:256 +msgid "Verifying PIN..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:257 +#, fuzzy +#| msgid "Date verified" +msgid "PIN verified" +msgstr "Ngày xác nhận" + +#: authentication/templates/authentication/cert_login.html:258 +#, fuzzy +#| msgid "OTP verification code" +msgid "PIN verification failed" +msgstr "Mã xác minh MFA ảo" + +#: authentication/templates/authentication/cert_login.html:259 +msgid "Signing challenge code..." +msgstr "" + +#: authentication/templates/authentication/cert_login.html:260 +#, fuzzy +#| msgid "Signing key" +msgid "Signing failed" +msgstr "Khóa ký" + +#: authentication/templates/authentication/cert_login.html:261 +msgid "Failed to retrieve certificate" +msgstr "" + +#: authentication/templates/authentication/cert_login.html:262 +#, fuzzy +#| msgid "Your account has expired, please contact the administrator." +msgid "No certificate detected, please contact administrator" +msgstr "Tài khoản của bạn đã hết hạn, vui lòng liên hệ với quản lý." + #: authentication/templates/authentication/face_capture.html:14 msgid "Retry" msgstr "Thử lại" @@ -5446,6 +5554,10 @@ msgstr "Có muốn thử lại không?" msgid "LAN" msgstr "Mạng nội bộ" +#: authentication/utils.py:150 +msgid "CERT" +msgstr "" + #: authentication/views/base.py:71 #: perms/templates/perms/_msg_permed_items_expire.html:18 msgid "If you have any question, please contact the administrator" @@ -5613,47 +5725,47 @@ msgstr "" msgid "Request file format may be wrong" msgstr "Định dạng tệp tải lên sai hoặc tệp thuộc loại tài nguyên khác." -#: common/const/choices.py:40 +#: common/const/choices.py:41 msgid "China" msgstr "Trung Quốc" -#: common/const/choices.py:57 +#: common/const/choices.py:58 msgid "Manual" msgstr "Kích hoạt thủ công" -#: common/const/choices.py:58 +#: common/const/choices.py:59 msgid "Timing" msgstr "Kích hoạt theo thời gian" -#: common/const/choices.py:64 ops/const.py:74 +#: common/const/choices.py:65 ops/const.py:74 msgid "Running" msgstr "Đang chạy" -#: common/const/choices.py:68 +#: common/const/choices.py:69 msgid "Canceled" msgstr "Hủy bỏ" -#: common/const/choices.py:115 +#: common/const/choices.py:128 msgid "Confirmed" msgstr "Xác nhận" -#: common/const/choices.py:123 terminal/models/applet/applet.py:31 +#: common/const/choices.py:136 terminal/models/applet/applet.py:31 msgid "Community edition" msgstr "Phiên bản cộng đồng" -#: common/const/choices.py:124 +#: common/const/choices.py:137 msgid "Basic edition" msgstr "Phiên bản cơ bản doanh nghiệp" -#: common/const/choices.py:125 +#: common/const/choices.py:138 msgid "Standard edition" msgstr "Phiên bản tiêu chuẩn doanh nghiệp" -#: common/const/choices.py:126 +#: common/const/choices.py:139 msgid "Professional edition" msgstr "Phiên bản chuyên nghiệp doanh nghiệp" -#: common/const/choices.py:127 +#: common/const/choices.py:140 msgid "Ultimate edition" msgstr "Phiên bản cao cấp doanh nghiệp" @@ -6178,24 +6290,24 @@ msgstr "Không tìm thấy mã" msgid "The message code provided is invalid or has expired" msgstr "Mã tin nhắn cung cấp không hợp lệ hoặc đã hết hạn" -#: jumpserver/conf.py:549 +#: jumpserver/conf.py:552 #, python-brace-format msgid "The verification code is: {code}" msgstr "Mã xác nhận là: {code}" -#: jumpserver/conf.py:554 +#: jumpserver/conf.py:557 msgid "Create account successfully" msgstr "Tạo tài khoản thành công" -#: jumpserver/conf.py:556 +#: jumpserver/conf.py:559 msgid "Your account has been created successfully" msgstr "Tài khoản của bạn đã được tạo thành công" -#: jumpserver/context_processor.py:17 +#: jumpserver/context_processor.py:16 msgid "JumpServer - An open-source PAM" msgstr "JumpServer" -#: jumpserver/context_processor.py:37 +#: jumpserver/context_processor.py:31 msgid "FIT2CLOUD" msgstr "" @@ -6919,7 +7031,7 @@ msgid "Please save in a org" msgstr "Vui lòng chọn một tổ chức trước khi lưu" #: orgs/mixins/models.py:58 orgs/mixins/serializers.py:25 orgs/models.py:91 -#: rbac/const.py:7 rbac/models/rolebinding.py:56 +#: rbac/const.py:7 rbac/models/rolebinding.py:57 #: rbac/serializers/rolebinding.py:44 settings/serializers/auth/base.py:53 #: terminal/notifications.py:309 #: terminal/templates/terminal/_msg_command_warning.html:27 @@ -7345,15 +7457,15 @@ msgstr "Vai trò hệ thống" msgid "Organization role" msgstr "Vai trò tổ chức" -#: rbac/models/rolebinding.py:62 +#: rbac/models/rolebinding.py:63 msgid "Role binding" msgstr "Liên kết vai trò" -#: rbac/models/rolebinding.py:168 +#: rbac/models/rolebinding.py:169 msgid "All organizations" msgstr "Tất cả tổ chức" -#: rbac/models/rolebinding.py:200 +#: rbac/models/rolebinding.py:201 msgid "" "User last role in org, can not be delete, you can remove user from org " "instead" @@ -7361,11 +7473,11 @@ msgstr "" "Vai trò cuối cùng của người dùng, không thể xóa, bạn có thể loại bỏ người " "dùng khỏi tổ chức" -#: rbac/models/rolebinding.py:207 +#: rbac/models/rolebinding.py:208 msgid "Organization role binding" msgstr "Liên kết vai trò tổ chức" -#: rbac/models/rolebinding.py:222 +#: rbac/models/rolebinding.py:223 msgid "System role binding" msgstr "Liên kết vai trò hệ thống" @@ -7430,7 +7542,7 @@ msgid "Storage" msgstr "Lưu trữ" #: rbac/tree.py:64 terminal/models/applet/applet.py:53 -#: terminal/models/applet/applet.py:379 terminal/models/applet/host.py:30 +#: terminal/models/applet/applet.py:387 terminal/models/applet/host.py:30 #: terminal/serializers/applet.py:16 msgid "Applet" msgstr "Ứng dụng từ xa" @@ -7493,51 +7605,51 @@ msgstr "Thu hồi mã thông báo truy cập" msgid "Range days" msgstr "Người chỉnh sửa" -#: reports/views.py:20 +#: reports/views.py:19 msgid "User login report" msgstr "Báo cáo đăng nhập người dùng" -#: reports/views.py:24 +#: reports/views.py:23 msgid "User change password report" msgstr "Báo cáo thay đổi mật khẩu người dùng" -#: reports/views.py:28 +#: reports/views.py:27 msgid "Asset statistics report" msgstr "Báo cáo thống kê tài sản" -#: reports/views.py:32 +#: reports/views.py:31 msgid "Asset activity report" msgstr "Báo cáo hoạt động tài sản" -#: reports/views.py:36 +#: reports/views.py:35 msgid "Account statistics report" msgstr "Báo cáo thống kê tài khoản" -#: reports/views.py:40 +#: reports/views.py:39 msgid "Account automation report" msgstr "Báo cáo tự động hóa tài khoản" -#: reports/views.py:44 +#: reports/views.py:43 msgid "ConsoleDashboard" msgstr "Bảng điều khiển Console" -#: reports/views.py:48 +#: reports/views.py:47 msgid "AuditsDashboard" msgstr "Bảng điều khiển Audit" -#: reports/views.py:52 +#: reports/views.py:51 msgid "PamDashboard" msgstr "Bảng điều khiển PAM" -#: reports/views.py:56 +#: reports/views.py:55 msgid "ChangeSecretDashboard" msgstr "Bảng điều khiển thay đổi mật khẩu tài khoản" -#: reports/views.py:191 +#: reports/views.py:190 msgid "Failed to send email: " msgstr "Gửi thư không thành công" -#: reports/views.py:192 +#: reports/views.py:191 msgid "Email sent successfully to " msgstr "Gửi thư thành công" @@ -7819,19 +7931,19 @@ msgstr "Kích hoạt xác thực DingTalk" #: settings/serializers/auth/dingtalk.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the DingTalk service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the DingTalk service user attribute name" msgstr "" -"Bản đồ thuộc tính người dùng, trong đó `key` là tên thuộc tính người dùng " -"hệ thống, `value` là tên thuộc tính người dùng dịch vụ DingTalk" +"Bản đồ thuộc tính người dùng, trong đó `key` là tên thuộc tính người dùng hệ " +"thống, `value` là tên thuộc tính người dùng dịch vụ DingTalk" #: settings/serializers/auth/feishu.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the FeiShu service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the FeiShu service user attribute name" msgstr "" -"Bản đồ thuộc tính người dùng, trong đó `key` là tên thuộc tính người dùng " -"hệ thống, `value` là tên thuộc tính người dùng dịch vụ FeiShu" +"Bản đồ thuộc tính người dùng, trong đó `key` là tên thuộc tính người dùng hệ " +"thống, `value` là tên thuộc tính người dùng dịch vụ FeiShu" #: settings/serializers/auth/lark.py:13 users/models/user/_source.py:24 msgid "Lark" @@ -7839,11 +7951,11 @@ msgstr "Lark" #: settings/serializers/auth/lark.py:19 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Lark service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Lark service user attribute name" msgstr "" -"Bản đồ thuộc tính người dùng, trong đó `key` là tên thuộc tính người dùng " -"hệ thống, `value` là tên thuộc tính người dùng dịch vụ Lark" +"Bản đồ thuộc tính người dùng, trong đó `key` là tên thuộc tính người dùng hệ " +"thống, `value` là tên thuộc tính người dùng dịch vụ Lark" #: settings/serializers/auth/ldap.py:42 settings/serializers/auth/ldap.py:108 msgid "LDAP" @@ -7903,8 +8015,8 @@ msgstr "" #: settings/serializers/auth/ldap.py:69 settings/serializers/auth/ldap_ha.py:51 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the LDAP service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the LDAP service user attribute name" msgstr "" "Ánh xạ thuộc tính của người dùng, trong đó `key` là tên thuộc tính người " "dùng hệ thống, `value` là tên thuộc tính người dùng dịch vụ LDAP" @@ -8014,8 +8126,8 @@ msgstr "Khi người dùng đăng xuất, họ cũng sẽ thoát khỏi máy ch #: settings/serializers/auth/oauth2.py:62 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OAuth2 service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OAuth2 service user attribute name" msgstr "" "Ánh xạ thuộc tính người dùng, trong đó `key` là tên thuộc tính người dùng " "của hệ thống, `value` là tên thuộc tính người dùng của dịch vụ OAuth2" @@ -8051,8 +8163,8 @@ msgstr "Bỏ qua xác thực chứng chỉ SSL" #: settings/serializers/auth/oidc.py:41 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OIDC service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OIDC service user attribute name" msgstr "" "Ánh xạ thuộc tính người dùng, trong đó `key` là tên thuộc tính người dùng " "của hệ thống, `value` là tên thuộc tính người dùng của dịch vụ OIDC" @@ -8200,11 +8312,11 @@ msgstr "Khi người dùng đăng xuất, họ cũng sẽ bị đăng xuất kh #: settings/serializers/auth/slack.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Slack service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Slack service user attribute name" msgstr "" -"Ánh xạ thuộc tính người dùng, trong đó `key` là tên thuộc tính người dùng " -"hệ thống, `value` là tên thuộc tính người dùng dịch vụ Slack" +"Ánh xạ thuộc tính người dùng, trong đó `key` là tên thuộc tính người dùng hệ " +"thống, `value` là tên thuộc tính người dùng dịch vụ Slack" #: settings/serializers/auth/sms.py:18 msgid "Enable Short Message Service (SMS)" @@ -8238,7 +8350,7 @@ msgid "Template code" msgstr "Mẫu tin nhắn" #: settings/serializers/auth/sms.py:40 users/models/user/__init__.py:89 -#: users/serializers/user.py:159 +#: users/serializers/user.py:164 msgid "Phone" msgstr "Số điện thoại di động" @@ -8295,7 +8407,10 @@ msgid "Enable SSO auth" msgstr "Kích hoạt xác thực token SSO" #: settings/serializers/auth/sso.py:17 -msgid "Other service can using SSO token login to JumpServer without password" +#, fuzzy +#| msgid "" +#| "Other service can using SSO token login to JumpServer without password" +msgid "Other service can using SSO token login to system without password" msgstr "" "Các hệ thống khác có thể sử dụng SSO Token để kết nối với JumpServer, miễn " "quá trình đăng nhập" @@ -8311,11 +8426,11 @@ msgstr "Đơn vị: giây" #: settings/serializers/auth/wecom.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the WeCom service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the WeCom service user attribute name" msgstr "" -"Ánh xạ thuộc tính người dùng, trong đó `key` là tên thuộc tính người dùng " -"hệ thống, `value` là tên thuộc tính người dùng dịch vụ WeChat doanh nghiệp" +"Ánh xạ thuộc tính người dùng, trong đó `key` là tên thuộc tính người dùng hệ " +"thống, `value` là tên thuộc tính người dùng dịch vụ WeChat doanh nghiệp" #: settings/serializers/basic.py:11 msgid "Site URL" @@ -9479,7 +9594,7 @@ msgstr "Đang chờ:" msgid "The verification code has been sent" msgstr "Mã xác thực đã được gửi" -#: templates/_without_nav_base.html:46 +#: templates/_without_nav_base.html:51 msgid "Home page" msgstr "Home" @@ -9744,31 +9859,31 @@ msgstr "Có thể đồng thời" msgid "Hosts" msgstr "Máy chủ" -#: terminal/models/applet/applet.py:94 +#: terminal/models/applet/applet.py:102 #: terminal/models/virtualapp/virtualapp.py:66 #, python-brace-format msgid "Applet pkg not valid, Missing file {}" msgstr "Gói Applet không hợp lệ, thiếu tệp {}" -#: terminal/models/applet/applet.py:113 +#: terminal/models/applet/applet.py:121 #, python-brace-format msgid "Load platform.yml failed: {}" msgstr "Tải platform.yml thất bại: {}" -#: terminal/models/applet/applet.py:116 +#: terminal/models/applet/applet.py:124 msgid "Only support custom platform" msgstr "Chỉ hỗ trợ nền tảng tùy chỉnh" -#: terminal/models/applet/applet.py:121 +#: terminal/models/applet/applet.py:129 msgid "Missing type in platform.yml" msgstr "Thiếu loại trong platform.yml" -#: terminal/models/applet/applet.py:381 terminal/models/applet/host.py:36 +#: terminal/models/applet/applet.py:389 terminal/models/applet/host.py:36 #: terminal/models/applet/host.py:138 msgid "Hosting" msgstr "Máy chủ chủ" -#: terminal/models/applet/applet.py:387 +#: terminal/models/applet/applet.py:395 msgid "Applet Publication" msgstr "Phát hành ứng dụng" @@ -9858,7 +9973,7 @@ msgstr "Cổng VNC" #: terminal/models/component/endpoint.py:35 #: terminal/models/component/endpoint.py:115 -#: terminal/serializers/endpoint.py:63 terminal/serializers/storage.py:41 +#: 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" @@ -10072,8 +10187,8 @@ msgstr "Storage" #: terminal/notifications.py:279 terminal/tasks.py:212 #: xpack/plugins/cloud/api.py:182 -#: xpack/plugins/cloud/serializers/account.py:143 -#: xpack/plugins/cloud/serializers/account.py:146 +#: xpack/plugins/cloud/serializers/account.py:148 +#: xpack/plugins/cloud/serializers/account.py:151 msgid "Test failure: Account invalid" msgstr "Kiểm tra thất bại: Tài khoản không hợp lệ" @@ -10194,7 +10309,8 @@ msgstr "Đã có giấy phép RDS" msgid "" "If not exist, the RDS will be in trial mode, and the trial period is 120 " "days. Detail" +"remote-desktop-services/rds-client-access-license\" " +"target=\"_blank\">Detail" msgstr "" "Nếu không có, RDS sẽ ở chế độ dùng thử, thời gian thử nghiệm là 120 ngày. >> 开始执行测试网关账号可连接性任务" #: settings/serializers/auth/ldap.py:53 settings/serializers/auth/ldap_ha.py:35 #: settings/serializers/msg.py:37 settings/serializers/terminal.py:32 #: terminal/serializers/storage.py:123 terminal/serializers/storage.py:142 -#: users/forms/profile.py:22 users/serializers/user.py:148 +#: users/forms/profile.py:22 users/serializers/user.py:153 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/cloud/serializers/account_attrs.py:43 @@ -225,7 +225,7 @@ msgstr "更新" #: accounts/const/account.py:34 accounts/const/automation.py:115 #: accounts/serializers/automations/change_secret.py:171 audits/const.py:66 -#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:66 +#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:67 #: ops/const.py:77 terminal/const.py:81 xpack/plugins/cloud/const.py:55 msgid "Failed" msgstr "失败" @@ -347,14 +347,14 @@ msgstr "SFTP" #: accounts/const/automation.py:116 #: accounts/serializers/automations/change_secret.py:170 audits/const.py:65 #: audits/models.py:65 audits/signal_handlers/activity_log.py:34 -#: common/const/choices.py:65 ops/const.py:75 ops/serializers/celery.py:48 +#: common/const/choices.py:66 ops/const.py:75 ops/serializers/celery.py:48 #: terminal/const.py:80 terminal/models/session/sharing.py:119 #: tickets/views/approve.py:128 msgid "Success" msgstr "成功" -#: accounts/const/automation.py:117 common/const/choices.py:63 -#: common/const/choices.py:114 terminal/const.py:79 +#: accounts/const/automation.py:117 common/const/choices.py:64 +#: common/const/choices.py:127 terminal/const.py:79 msgid "Pending" msgstr "待定的" @@ -362,7 +362,7 @@ msgstr "待定的" msgid "Queued" msgstr "排队中" -#: accounts/const/automation.py:122 common/const/choices.py:62 +#: accounts/const/automation.py:122 common/const/choices.py:63 msgid "Ready" msgstr "准备就绪" @@ -374,7 +374,7 @@ msgstr "处理中" msgid "Can login" msgstr "可登录" -#: accounts/const/automation.py:128 users/serializers/user.py:254 +#: accounts/const/automation.py:128 users/serializers/user.py:259 msgid "Superuser" msgstr "超级用户" @@ -403,7 +403,7 @@ msgid "Default tablespace" msgstr "默认表空间" #: accounts/const/automation.py:135 rbac/models/role.py:46 -#: rbac/models/rolebinding.py:52 users/models/user/__init__.py:79 +#: rbac/models/rolebinding.py:53 users/models/user/__init__.py:79 msgid "Role" msgstr "角色" @@ -412,7 +412,7 @@ msgid "Perms" msgstr "权限" #: accounts/const/automation.py:137 perms/serializers/permission.py:56 -#: users/serializers/user.py:245 +#: users/serializers/user.py:250 msgid "Groups" msgstr "用户组" @@ -785,7 +785,7 @@ msgstr "结束日期" #: assets/models/automations/base.py:137 #: assets/serializers/automations/base.py:47 audits/models.py:224 #: audits/reporting.py:607 audits/serializers.py:77 ops/models/base.py:49 -#: ops/models/job.py:233 terminal/models/applet/applet.py:382 +#: ops/models/job.py:233 terminal/models/applet/applet.py:390 #: terminal/models/applet/host.py:140 terminal/models/component/status.py:30 #: terminal/models/virtualapp/virtualapp.py:99 #: terminal/serializers/applet.py:19 terminal/serializers/applet_host.py:163 @@ -800,7 +800,7 @@ msgstr "状态" #: accounts/serializers/account/account.py:297 assets/const/automation.py:9 #: authentication/templates/authentication/passkey.html:177 #: authentication/views/base.py:43 authentication/views/base.py:44 -#: authentication/views/base.py:45 common/const/choices.py:67 +#: authentication/views/base.py:45 common/const/choices.py:68 #: settings/templates/ldap/_msg_import_ldap_user.html:26 msgid "Error" msgstr "错误" @@ -895,8 +895,9 @@ msgstr "重复密码" #: accounts/templates/accounts/push_account_report.html:79 #: accounts/templates/accounts/push_account_report.html:119 #: acls/serializers/base.py:19 acls/serializers/base.py:50 audits/models.py:204 -#: audits/reporting.py:241 authentication/forms.py:21 -#: authentication/forms.py:23 authentication/models/temp_token.py:10 +#: audits/reporting.py:241 authentication/backends/cert/forms.py:7 +#: authentication/forms.py:21 authentication/forms.py:23 +#: authentication/models/temp_token.py:10 #: authentication/serializers/connect_token_secret.py:43 #: authentication/serializers/connect_token_secret.py:53 #: authentication/templates/authentication/_msg_different_city.html:9 @@ -1050,7 +1051,7 @@ msgstr "特权账号" #: assets/models/cmd_filter.py:39 assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:129 reports/models.py:18 #: terminal/models/applet/applet.py:41 -#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:257 +#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:262 msgid "Is active" msgstr "激活" @@ -1066,7 +1067,7 @@ msgstr "平台" msgid "Push params" msgstr "账号推送参数" -#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:403 +#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:404 msgid "Account template" msgstr "账号模板" @@ -1159,7 +1160,7 @@ msgstr "账号变更信息" msgid "Change secret or push account failed information" msgstr "改密或推送账号失败信息" -#: accounts/risk_handlers.py:17 common/const/choices.py:116 +#: accounts/risk_handlers.py:17 common/const/choices.py:129 msgid "Ignored" msgstr "忽略" @@ -1315,7 +1316,7 @@ msgstr "ID" #: authentication/notifications.py:16 authentication/notifications.py:55 #: notifications/models/notification.py:12 #: perms/api/user_permission/mixin.py:58 perms/models/asset_permission.py:63 -#: rbac/builtin.py:134 rbac/models/rolebinding.py:49 +#: rbac/builtin.py:134 rbac/models/rolebinding.py:50 #: rbac/serializers/rolebinding.py:17 terminal/backends/command/models.py:16 #: terminal/models/session/session.py:27 terminal/models/session/sharing.py:34 #: terminal/notifications.py:168 terminal/notifications.py:235 @@ -1323,8 +1324,8 @@ msgstr "ID" #: terminal/templates/terminal/_msg_command_warning.html:9 #: terminal/templates/terminal/_msg_session_sharing.html:6 #: tickets/models/comment.py:21 tickets/serializers/flow.py:15 -#: users/const.py:14 users/models/user/__init__.py:298 -#: users/models/user/__init__.py:325 +#: users/const.py:14 users/models/user/__init__.py:303 +#: users/models/user/__init__.py:330 msgid "User" msgstr "用户" @@ -1359,7 +1360,7 @@ msgstr "IP 白名单" #: assets/models/cmd_filter.py:88 common/db/models.py:36 ops/models/adhoc.py:25 #: ops/models/job.py:165 ops/models/playbook.py:31 rbac/models/role.py:37 #: settings/models.py:43 terminal/models/applet/applet.py:46 -#: terminal/models/applet/applet.py:383 terminal/models/applet/host.py:143 +#: terminal/models/applet/applet.py:391 terminal/models/applet/host.py:143 #: terminal/models/component/endpoint.py:29 #: terminal/models/component/endpoint.py:117 #: terminal/models/session/session.py:44 @@ -1634,7 +1635,7 @@ msgstr "" "由于每次更新资产账号,都会生成历史账号,所以需要清理资产账号的历史。系统会根" "据账号存储-记录限制的配置,每天凌晨2点对于超出的数量的账号记录进行清理" -#: accounts/tasks/remove_account.py:89 +#: accounts/tasks/remove_account.py:91 msgid "Remove historical accounts that are out of range." msgstr "删除超出范围的历史帐户。" @@ -1701,7 +1702,7 @@ msgstr "任务名称" #: accounts/templates/accounts/push_account_report.html:22 #: assets/models/automations/base.py:143 audits/models.py:66 #: ops/models/base.py:55 ops/models/celery.py:89 ops/models/job.py:241 -#: ops/templates/ops/celery_task_log.html:101 +#: ops/templates/ops/celery_task_log.html:154 #: perms/models/asset_permission.py:78 settings/serializers/feature.py:29 #: settings/templates/ldap/_msg_import_ldap_user.html:5 #: terminal/models/applet/host.py:141 terminal/models/session/session.py:42 @@ -1885,7 +1886,7 @@ msgstr "审批人" #: acls/models/base.py:81 perms/serializers/permission.py:54 #: tickets/models/flow.py:23 users/models/preference.py:16 -#: users/serializers/group.py:21 users/serializers/user.py:424 +#: users/serializers/group.py:21 users/serializers/user.py:429 msgid "Users" msgstr "用户" @@ -1911,7 +1912,7 @@ msgid "Command" msgstr "命令" #: acls/models/command_acl.py:17 assets/models/cmd_filter.py:59 -#: xpack/plugins/cloud/models.py:369 +#: xpack/plugins/cloud/models.py:370 msgid "Regex" msgstr "正则表达式" @@ -2000,7 +2001,7 @@ msgstr "规则" msgid "Login acl" msgstr "登录访问控制" -#: acls/models/login_acl.py:27 tickets/const.py:11 +#: acls/models/login_acl.py:30 tickets/const.py:11 msgid "Login confirm" msgstr "登录复核" @@ -2122,7 +2123,7 @@ msgstr "" #: authentication/templates/authentication/_msg_oauth_bind.html:12 #: authentication/templates/authentication/_msg_rest_password_success.html:8 #: authentication/templates/authentication/_msg_rest_public_key_success.html:8 -#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:405 +#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:406 msgid "IP" msgstr "IP" @@ -2183,15 +2184,15 @@ msgstr "我们想通知您,最近有用户登录:" msgid "User details" msgstr "用户详情" -#: assets/api/asset/asset.py:166 +#: assets/api/asset/asset.py:168 msgid "Cannot create asset directly, you should create a host or other" msgstr "不能直接创建资产, 你应该创建主机或其他资产" -#: assets/api/asset/asset.py:173 +#: assets/api/asset/asset.py:175 msgid "The number of assets exceeds the limit of 5000" msgstr "资产数量超过了 5000 的限制" -#: assets/api/asset/asset.py:179 +#: assets/api/asset/asset.py:181 msgid "The number of assets exceeds the license limit" msgstr "资产数量超过许可证限制" @@ -2208,6 +2209,11 @@ msgstr "不能删除根节点 ({})" msgid "Deletion failed and the node contains assets" msgstr "删除失败,节点包含资产" +#: assets/api/node.py:99 +#, python-brace-format +msgid "Node {} is an ancestor of node {}, can't be added as its child" +msgstr "" + #: assets/api/tree.py:48 assets/serializers/node.py:42 msgid "The same level node name cannot be the same" msgstr "同级别节点名字不能重复" @@ -2225,29 +2231,29 @@ msgstr "资产管理" msgid "Task: {} finished" msgstr "任务:{} 完成" -#: assets/automations/base/manager.py:340 +#: assets/automations/base/manager.py:341 #, python-brace-format msgid " - Platform {} ansible disabled" msgstr " - 平台 {} Ansible 已禁用, 无法执行任务" -#: assets/automations/base/manager.py:555 +#: assets/automations/base/manager.py:556 msgid ">>> Task preparation phase" msgstr ">>> 任务准备阶段" -#: assets/automations/base/manager.py:559 +#: assets/automations/base/manager.py:560 #, python-brace-format msgid ">>> Executing tasks in batches, total {runner_count}" msgstr ">>> 分次执行任务,总共 {runner_count}" -#: assets/automations/base/manager.py:564 +#: assets/automations/base/manager.py:565 msgid ">>> Start executing tasks" msgstr ">>> 开始执行任务" -#: assets/automations/base/manager.py:566 +#: assets/automations/base/manager.py:567 msgid ">>> No tasks need to be executed" msgstr ">>> 没有需要执行的任务" -#: assets/automations/base/manager.py:570 +#: assets/automations/base/manager.py:571 #, python-brace-format msgid ">>> Begin executing batch {index} of tasks" msgstr ">>> 开始执行第 {index} 批任务" @@ -2642,7 +2648,7 @@ msgid "Port" msgstr "端口" #: assets/models/asset/common.py:167 assets/serializers/asset/common.py:175 -#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:59 +#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:69 msgid "Address" msgstr "地址" @@ -2650,12 +2656,12 @@ msgstr "地址" #: assets/serializers/asset/common.py:151 #: authentication/backends/passkey/models.py:12 #: authentication/serializers/connect_token_secret.py:130 -#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:399 +#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:400 msgid "Platform" msgstr "平台" #: assets/models/asset/common.py:173 assets/models/zone.py:22 -#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:401 +#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:402 msgid "Zone" msgstr "网域" @@ -2724,9 +2730,9 @@ msgid "Proxy" msgstr "代理" #: assets/models/automations/base.py:23 assets/models/cmd_filter.py:32 -#: assets/models/node.py:553 ops/models/job.py:158 +#: assets/models/node.py:560 ops/models/job.py:158 #: perms/models/asset_permission.py:72 tickets/models/ticket/apply_asset.py:15 -#: xpack/plugins/cloud/models.py:400 +#: xpack/plugins/cloud/models.py:401 msgid "Node" msgstr "节点" @@ -2752,7 +2758,7 @@ msgstr "资产自动化任务" #: assets/models/automations/base.py:140 assets/models/cmd_filter.py:41 #: authentication/serializers/token.py:134 common/db/models.py:34 #: ops/models/base.py:54 ops/models/job.py:240 -#: users/models/user/__init__.py:328 +#: users/models/user/__init__.py:333 msgid "Date created" msgstr "创建日期" @@ -2841,7 +2847,7 @@ msgstr "网关" msgid "System" msgstr "系统" -#: assets/models/label.py:19 assets/models/node.py:539 +#: assets/models/label.py:19 assets/models/node.py:546 #: assets/serializers/cagegory.py:11 assets/serializers/cagegory.py:18 #: assets/serializers/cagegory.py:24 #: authentication/models/connection_token.py:35 @@ -2856,7 +2862,7 @@ msgstr "值" #: assets/serializers/platform.py:160 #: authentication/serializers/connect_token_secret.py:136 #: common/serializers/common.py:85 labels/serializers.py:45 -#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:404 +#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:405 msgid "Label" msgstr "标签" @@ -2872,27 +2878,27 @@ msgstr "自定义备注" msgid "My assets" msgstr "我的资产" -#: assets/models/node.py:168 +#: assets/models/node.py:172 msgid "New node" msgstr "新节点" -#: assets/models/node.py:467 audits/backends/db.py:85 audits/backends/db.py:86 +#: assets/models/node.py:474 audits/backends/db.py:85 audits/backends/db.py:86 msgid "empty" msgstr "空" -#: assets/models/node.py:538 perms/models/perm_node.py:28 +#: assets/models/node.py:545 perms/models/perm_node.py:28 msgid "Key" msgstr "键" -#: assets/models/node.py:540 assets/serializers/node.py:20 +#: assets/models/node.py:547 assets/serializers/node.py:20 msgid "Full value" msgstr "全称" -#: assets/models/node.py:544 perms/models/perm_node.py:30 +#: assets/models/node.py:551 perms/models/perm_node.py:30 msgid "Parent key" msgstr "ssh私钥" -#: assets/models/node.py:556 +#: assets/models/node.py:563 msgid "Can match node" msgstr "可以匹配节点" @@ -3068,7 +3074,7 @@ msgstr "节点路径,格式为 [\"/组织/节点名\"], 如果节点不存在 #: authentication/serializers/connect_token_secret.py:30 #: authentication/serializers/connect_token_secret.py:77 #: perms/models/asset_permission.py:76 perms/serializers/permission.py:68 -#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:402 +#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:403 #: xpack/plugins/cloud/serializers/task.py:36 msgid "Protocols" msgstr "协议组" @@ -3498,7 +3504,7 @@ msgid "Symlink" msgstr "建立软链接" #: audits/const.py:18 audits/const.py:29 -#: ops/templates/ops/celery_task_log.html:86 +#: ops/templates/ops/celery_task_log.html:139 #: terminal/api/session/session.py:159 msgid "Download" msgstr "下载" @@ -3527,7 +3533,9 @@ msgstr "导出" msgid "Connect" msgstr "连接" -#: audits/const.py:31 authentication/templates/authentication/login.html:334 +#: audits/const.py:31 +#: authentication/templates/authentication/cert_login.html:232 +#: authentication/templates/authentication/login.html:334 #: authentication/templates/authentication/login.html:408 #: templates/_header_bar.html:101 #: xpack/plugins/interface/templates/login_i18n.html:21 @@ -4222,24 +4230,24 @@ msgstr "人脸比对失败" msgid "Current user not support mfa type: {}" msgstr "当前用户不支持 MFA 类型: {}" -#: authentication/api/password.py:34 terminal/api/session/session.py:347 +#: authentication/api/password.py:37 terminal/api/session/session.py:347 #: users/views/profile/reset.py:63 #, python-brace-format msgid "User does not exist: {}" msgstr "用户不存在: {}" -#: authentication/api/password.py:34 users/views/profile/reset.py:166 +#: authentication/api/password.py:37 users/views/profile/reset.py:166 msgid "No user matched" msgstr "没有匹配到用户" -#: authentication/api/password.py:38 +#: authentication/api/password.py:41 #, python-brace-format msgid "" "The user is from {}, please go to the corresponding system to change the " "password" msgstr "用户来自 {} 请去相应系统修改密码" -#: authentication/api/password.py:69 +#: authentication/api/password.py:72 #: authentication/templates/authentication/login.html:400 #: users/templates/users/forgot_password.html:41 #: users/templates/users/forgot_password.html:42 @@ -4249,7 +4257,7 @@ msgstr "用户来自 {} 请去相应系统修改密码" msgid "Forgot password" msgstr "忘记密码" -#: authentication/api/password.py:70 authentication/mfa/email.py:42 +#: authentication/api/password.py:73 authentication/mfa/email.py:42 #, python-brace-format msgid "The validity period of the verification code is {} minute" msgstr "验证码有效期为 {} 分钟" @@ -4262,10 +4270,21 @@ msgstr "认证管理" msgid "CAS Error" msgstr "CAS 错误" -#: authentication/backends/custom.py:60 -#: authentication/backends/oauth2/backends.py:158 -msgid "User invalid, disabled or expired" -msgstr "用户无效,已禁用或已过期" +#: authentication/backends/cert/api.py:57 +msgid "Certificate enrollment is not enabled" +msgstr "证书签发未开启" + +#: authentication/backends/cert/api.py:62 +msgid "CSR is required" +msgstr "CSR 是必须的。" + +#: authentication/backends/cert/api.py:68 +msgid "Certificate signing failed" +msgstr "证书签发失败" + +#: authentication/backends/cert/views.py:97 +msgid "Invalid credentials" +msgstr "无效的证书" #: authentication/backends/drf.py:61 msgid "Invalid token header. No credentials provided." @@ -4508,16 +4527,16 @@ msgstr "您的密码无效" msgid "Please wait for %s seconds before retry" msgstr "请在 %s 秒后重试" -#: authentication/errors/redirect.py:85 authentication/mixins.py:436 +#: authentication/errors/redirect.py:85 authentication/mixins.py:445 #: users/views/profile/reset.py:224 msgid "Your password is too simple, please change it for security" msgstr "你的密码过于简单,为了安全,请修改" -#: authentication/errors/redirect.py:93 authentication/mixins.py:445 +#: authentication/errors/redirect.py:93 authentication/mixins.py:454 msgid "You should to change your password before login" msgstr "登录完成前,请先修改密码" -#: authentication/errors/redirect.py:101 authentication/mixins.py:454 +#: authentication/errors/redirect.py:101 authentication/mixins.py:463 msgid "Your password has expired, please reset before logging in" msgstr "您的密码已过期,先修改再登录" @@ -4643,11 +4662,11 @@ msgid "" msgstr "" "管理员已开启'仅允许已存在用户登录',当前用户不在用户列表中,请联系管理员。" -#: authentication/mixins.py:184 +#: authentication/mixins.py:187 msgid "User is invalid" msgstr "无效的用户" -#: authentication/mixins.py:201 +#: authentication/mixins.py:204 #, python-brace-format msgid "" " The administrator has enabled 'Only allow login from user source'. \n" @@ -4655,12 +4674,12 @@ msgid "" "administrator. " msgstr "管理员已开启'仅允许从用户来源登录',当前用户来源为 {},请联系管理员。" -#: authentication/mixins.py:382 +#: authentication/mixins.py:391 #, python-brace-format msgid "The MFA type ({}) is not enabled" msgstr "该 MFA ({}) 方式没有启用" -#: authentication/mixins.py:424 +#: authentication/mixins.py:433 msgid "Please change your password" msgstr "请修改密码" @@ -4852,7 +4871,7 @@ msgstr "动作" #: authentication/serializers/connection_token.py:46 #: perms/serializers/permission.py:66 perms/serializers/permission.py:87 -#: users/serializers/user.py:127 users/serializers/user.py:261 +#: users/serializers/user.py:127 users/serializers/user.py:266 msgid "Is expired" msgstr "已过期" @@ -4892,13 +4911,13 @@ msgstr "SSH密钥不合法" #: authentication/serializers/token.py:93 perms/serializers/permission.py:65 #: perms/serializers/permission.py:88 users/serializers/user.py:128 -#: users/serializers/user.py:258 +#: users/serializers/user.py:263 msgid "Is valid" msgstr "是否有效" #: authentication/serializers/token.py:131 ops/models/adhoc.py:26 #: ops/models/playbook.py:34 ops/serializers/mixin.py:10 rbac/models/role.py:31 -#: rbac/models/rolebinding.py:46 rbac/serializers/role.py:12 +#: rbac/models/rolebinding.py:47 rbac/serializers/role.py:12 #: settings/serializers/auth/oauth2.py:37 msgid "Scope" msgstr "范围" @@ -4993,7 +5012,7 @@ msgstr "代码错误" #: authentication/templates/authentication/_msg_oauth_bind.html:3 #: authentication/templates/authentication/_msg_reset_password.html:3 #: authentication/templates/authentication/_msg_reset_password_code.html:9 -#: jumpserver/conf.py:555 +#: jumpserver/conf.py:558 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:32 #: users/templates/users/_msg_account_expire_reminder.html:4 @@ -5089,6 +5108,67 @@ msgstr "如果这次公钥更新不是由你发起的,那么你的账号可能 msgid "Cancel" msgstr "取消" +#: authentication/templates/authentication/cert_login.html:190 +msgid "Certificate Authentication" +msgstr "证书认证" + +#: authentication/templates/authentication/cert_login.html:195 +#: authentication/templates/authentication/cert_login.html:250 +msgid "Loading USB Key driver..." +msgstr "正在加载 USB Key 驱动..." + +#: authentication/templates/authentication/cert_login.html:210 +msgid "Insert USB Key to auto-fetch" +msgstr "请插入 USB Key 自动获取" + +#: authentication/templates/authentication/cert_login.html:251 +msgid "Detecting USB Key..." +msgstr "正在检测 USB Key..." + +#: authentication/templates/authentication/cert_login.html:252 +msgid "USB Key connected" +msgstr "USB Key 已连接" + +#: authentication/templates/authentication/cert_login.html:253 +msgid "Please insert USB Key" +msgstr "请插入 USB Key" + +#: authentication/templates/authentication/cert_login.html:254 +msgid "Driver unavailable" +msgstr "驱动不可用" + +#: authentication/templates/authentication/cert_login.html:255 +msgid "USB Key SDK initialization failed" +msgstr "USB Key SDK 初始化失败" + +#: authentication/templates/authentication/cert_login.html:256 +msgid "Verifying PIN..." +msgstr "PIN 校验中..." + +#: authentication/templates/authentication/cert_login.html:257 +msgid "PIN verified" +msgstr "PIN 校验通过" + +#: authentication/templates/authentication/cert_login.html:258 +msgid "PIN verification failed" +msgstr "校验 PIN 失败" + +#: authentication/templates/authentication/cert_login.html:259 +msgid "Signing challenge code..." +msgstr "正在对挑战码签名..." + +#: authentication/templates/authentication/cert_login.html:260 +msgid "Signing failed" +msgstr "签名失败" + +#: authentication/templates/authentication/cert_login.html:261 +msgid "Failed to retrieve certificate" +msgstr "获取证书失败" + +#: authentication/templates/authentication/cert_login.html:262 +msgid "No certificate detected, please contact administrator" +msgstr "未检测到证书,请联系管理员制证" + #: authentication/templates/authentication/face_capture.html:14 msgid "Retry" msgstr "重试" @@ -5156,6 +5236,10 @@ msgstr "是否重试 ?" msgid "LAN" msgstr "局域网" +#: authentication/utils.py:150 +msgid "CERT" +msgstr "" + #: authentication/views/base.py:71 #: perms/templates/perms/_msg_permed_items_expire.html:18 msgid "If you have any question, please contact the administrator" @@ -5318,47 +5402,47 @@ msgstr "请使用密码登录,然后绑定企业微信" msgid "Request file format may be wrong" msgstr "上传的文件格式错误 或 其它类型资源的文件" -#: common/const/choices.py:40 +#: common/const/choices.py:41 msgid "China" msgstr "中国" -#: common/const/choices.py:57 +#: common/const/choices.py:58 msgid "Manual" msgstr "手动触发" -#: common/const/choices.py:58 +#: common/const/choices.py:59 msgid "Timing" msgstr "定时触发" -#: common/const/choices.py:64 ops/const.py:74 +#: common/const/choices.py:65 ops/const.py:74 msgid "Running" msgstr "运行中" -#: common/const/choices.py:68 +#: common/const/choices.py:69 msgid "Canceled" msgstr "取消" -#: common/const/choices.py:115 +#: common/const/choices.py:128 msgid "Confirmed" msgstr "确认" -#: common/const/choices.py:123 terminal/models/applet/applet.py:31 +#: common/const/choices.py:136 terminal/models/applet/applet.py:31 msgid "Community edition" msgstr "社区版" -#: common/const/choices.py:124 +#: common/const/choices.py:137 msgid "Basic edition" msgstr "企业基础版" -#: common/const/choices.py:125 +#: common/const/choices.py:138 msgid "Standard edition" msgstr "企业标准版" -#: common/const/choices.py:126 +#: common/const/choices.py:139 msgid "Professional edition" msgstr "企业专业版" -#: common/const/choices.py:127 +#: common/const/choices.py:140 msgid "Ultimate edition" msgstr "企业旗舰版" @@ -5841,24 +5925,24 @@ msgstr "未找到 Code" msgid "The message code provided is invalid or has expired" msgstr "提供的消息代码无效或已过期" -#: jumpserver/conf.py:549 +#: jumpserver/conf.py:552 #, python-brace-format msgid "The verification code is: {code}" msgstr "验证码为: {code}" -#: jumpserver/conf.py:554 +#: jumpserver/conf.py:557 msgid "Create account successfully" msgstr "创建账号成功" -#: jumpserver/conf.py:556 +#: jumpserver/conf.py:559 msgid "Your account has been created successfully" msgstr "你的账号已创建成功" -#: jumpserver/context_processor.py:17 +#: jumpserver/context_processor.py:16 msgid "JumpServer - An open-source PAM" msgstr "JumpServer 开源堡垒机" -#: jumpserver/context_processor.py:37 +#: jumpserver/context_processor.py:31 msgid "FIT2CLOUD" msgstr "" @@ -6557,7 +6641,7 @@ msgid "Please save in a org" msgstr "请选择一个组织后再保存" #: orgs/mixins/models.py:58 orgs/mixins/serializers.py:25 orgs/models.py:91 -#: rbac/const.py:7 rbac/models/rolebinding.py:56 +#: rbac/const.py:7 rbac/models/rolebinding.py:57 #: rbac/serializers/rolebinding.py:44 settings/serializers/auth/base.py:53 #: terminal/notifications.py:309 #: terminal/templates/terminal/_msg_command_warning.html:27 @@ -6860,10 +6944,8 @@ msgid "Can view file manager" msgstr "可以查看文件管理" #: rbac/models/menu.py:21 -#, fuzzy -#| msgid "Can view console view" msgid "Can view jdmc console" -msgstr "可以显示控制台" +msgstr "可以显示 JDMC 控制台" #: rbac/models/menu.py:22 msgid "Can view System Tools" @@ -6957,25 +7039,25 @@ msgstr "系统角色" msgid "Organization role" msgstr "组织角色" -#: rbac/models/rolebinding.py:62 +#: rbac/models/rolebinding.py:63 msgid "Role binding" msgstr "角色绑定" -#: rbac/models/rolebinding.py:168 +#: rbac/models/rolebinding.py:169 msgid "All organizations" msgstr "所有组织" -#: rbac/models/rolebinding.py:200 +#: rbac/models/rolebinding.py:201 msgid "" "User last role in org, can not be delete, you can remove user from org " "instead" msgstr "用户最后一个角色,不能删除,你可以将用户从组织移除" -#: rbac/models/rolebinding.py:207 +#: rbac/models/rolebinding.py:208 msgid "Organization role binding" msgstr "组织角色绑定" -#: rbac/models/rolebinding.py:222 +#: rbac/models/rolebinding.py:223 msgid "System role binding" msgstr "系统角色绑定" @@ -7040,7 +7122,7 @@ msgid "Storage" msgstr "存储" #: rbac/tree.py:64 terminal/models/applet/applet.py:53 -#: terminal/models/applet/applet.py:379 terminal/models/applet/host.py:30 +#: terminal/models/applet/applet.py:387 terminal/models/applet/host.py:30 #: terminal/serializers/applet.py:16 msgid "Applet" msgstr "远程应用" @@ -7059,10 +7141,8 @@ msgid "Job audit" msgstr "作业审计" #: rbac/tree.py:137 -#, fuzzy -#| msgid "Console" msgid "JDMC console" -msgstr "控制台" +msgstr "JDMC 控制台" #: rbac/tree.py:201 msgid "App organizations" @@ -7101,51 +7181,51 @@ msgstr "撤销访问令牌" msgid "Range days" msgstr "范围天数" -#: reports/views.py:20 +#: reports/views.py:19 msgid "User login report" msgstr "用户登录报告" -#: reports/views.py:24 +#: reports/views.py:23 msgid "User change password report" msgstr "用户改密报告" -#: reports/views.py:28 +#: reports/views.py:27 msgid "Asset statistics report" msgstr "资产统计报告" -#: reports/views.py:32 +#: reports/views.py:31 msgid "Asset activity report" msgstr "资产活动报告" -#: reports/views.py:36 +#: reports/views.py:35 msgid "Account statistics report" msgstr "账号统计报告" -#: reports/views.py:40 +#: reports/views.py:39 msgid "Account automation report" msgstr "账号自动化报告" -#: reports/views.py:44 +#: reports/views.py:43 msgid "ConsoleDashboard" msgstr "控制台仪表板" -#: reports/views.py:48 +#: reports/views.py:47 msgid "AuditsDashboard" msgstr "审计台仪表板" -#: reports/views.py:52 +#: reports/views.py:51 msgid "PamDashboard" msgstr "PAM 仪表板" -#: reports/views.py:56 +#: reports/views.py:55 msgid "ChangeSecretDashboard" msgstr "账号改密仪表盘" -#: reports/views.py:191 +#: reports/views.py:190 msgid "Failed to send email: " msgstr "发送邮件失败" -#: reports/views.py:192 +#: reports/views.py:191 msgid "Email sent successfully to " msgstr "发送邮件成功" @@ -7415,8 +7495,8 @@ msgid "" "User attribute mapping, where the `key` is the CAS service user attribute " "name and the `value` is this system user attribute name" msgstr "" -"用户属性映射,其中 `key` 是 CAS 服务用户属性名称,`value` 是本系统用户" -"属性名称" +"用户属性映射,其中 `key` 是 CAS 服务用户属性名称,`value` 是本系统用户属性名" +"称" #: settings/serializers/auth/dingtalk.py:16 msgid "Dingtalk" @@ -7424,19 +7504,17 @@ msgstr "启用钉钉认证" #: settings/serializers/auth/dingtalk.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the DingTalk service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the DingTalk service user attribute name" msgstr "" -"用户属性映射,其中 `key` 是本系统用户属性名称,`value` 是钉钉服务用户属" -"性名称" +"用户属性映射,其中 `key` 是本系统用户属性名称,`value` 是钉钉服务用户属性名称" #: settings/serializers/auth/feishu.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the FeiShu service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the FeiShu service user attribute name" msgstr "" -"用户属性映射,其中 `key` 是本系统用户属性名称,`value` 是飞书服务用户属" -"性名称" +"用户属性映射,其中 `key` 是本系统用户属性名称,`value` 是飞书服务用户属性名称" #: settings/serializers/auth/lark.py:13 users/models/user/_source.py:24 msgid "Lark" @@ -7444,11 +7522,11 @@ msgstr "Lark" #: settings/serializers/auth/lark.py:19 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Lark service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Lark service user attribute name" msgstr "" -"用户属性映射,其中 `key` 是本系统用户属性名称,`value` 是 Lark 服务用户" -"属性名称" +"用户属性映射,其中 `key` 是本系统用户属性名称,`value` 是 Lark 服务用户属性名" +"称" #: settings/serializers/auth/ldap.py:42 settings/serializers/auth/ldap.py:108 msgid "LDAP" @@ -7491,11 +7569,11 @@ msgstr "可能的选项是(cn或uid或sAMAccountName=%(user)s)" #: settings/serializers/auth/ldap.py:69 settings/serializers/auth/ldap_ha.py:51 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the LDAP service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the LDAP service user attribute name" msgstr "" -"用户属性映射,其中 `key` 是本系统用户属性名称,`value` 是 LDAP 服务用户" -"属性名称" +"用户属性映射,其中 `key` 是本系统用户属性名称,`value` 是 LDAP 服务用户属性名" +"称" #: settings/serializers/auth/ldap.py:85 settings/serializers/auth/ldap_ha.py:67 msgid "Connect timeout (s)" @@ -7596,11 +7674,11 @@ msgstr "当用户退出时,他们也会从 OAuth2 服务器退出" #: settings/serializers/auth/oauth2.py:62 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OAuth2 service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OAuth2 service user attribute name" msgstr "" -"用户属性映射,其中 `key` 是本系统用户属性名称,`value` 是 OAuth2 服务用" -"户属性名称" +"用户属性映射,其中 `key` 是本系统用户属性名称,`value` 是 OAuth2 服务用户属性" +"名称" #: settings/serializers/auth/oauth2.py:67 settings/serializers/auth/oidc.py:117 #: settings/serializers/auth/saml2.py:45 @@ -7633,11 +7711,11 @@ msgstr "忽略 SSL 证书验证" #: settings/serializers/auth/oidc.py:41 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OIDC service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OIDC service user attribute name" msgstr "" -"用户属性映射,其中 `key` 是本系统用户属性名称,`value` 是 OIDC 服务用户" -"属性名称" +"用户属性映射,其中 `key` 是本系统用户属性名称,`value` 是 OIDC 服务用户属性名" +"称" #: settings/serializers/auth/oidc.py:45 msgid "Enable PKCE" @@ -7767,8 +7845,8 @@ msgid "" "User attribute mapping, where the `key` is the SAML2 service user attribute " "name and the `value` is this system user attribute name" msgstr "" -"用户属性映射,其中 `key` 是 SAML2 服务用户属性名称,`value` 是本系统用" -"户属性名称" +"用户属性映射,其中 `key` 是 SAML2 服务用户属性名称,`value` 是本系统用户属性" +"名称" #: settings/serializers/auth/saml2.py:43 msgid "When the user signs out, they also be logged out from the SAML2 server" @@ -7776,11 +7854,11 @@ msgstr "当用户退出时,他们也会从 SAML2 服务器注销" #: settings/serializers/auth/slack.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Slack service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Slack service user attribute name" msgstr "" -"用户属性映射,其中 `key` 是本系统用户属性名称,`value` 是 Slack 服务用" -"户属性名称" +"用户属性映射,其中 `key` 是本系统用户属性名称,`value` 是 Slack 服务用户属性" +"名称" #: settings/serializers/auth/sms.py:18 msgid "Enable Short Message Service (SMS)" @@ -7814,7 +7892,7 @@ msgid "Template code" msgstr "模板" #: settings/serializers/auth/sms.py:40 users/models/user/__init__.py:89 -#: users/serializers/user.py:159 +#: users/serializers/user.py:164 msgid "Phone" msgstr "手机" @@ -7870,8 +7948,8 @@ msgid "Enable SSO auth" msgstr "启用 SSO 令牌认证" #: settings/serializers/auth/sso.py:17 -msgid "Other service can using SSO token login to JumpServer without password" -msgstr "其它系统可以使用 SSO Token 对接 JumpServer, 免去登录的过程" +msgid "Other service can using SSO token login to system without password" +msgstr "其它系统可以使用 SSO Token 对接系统,免去登录的过程" #: settings/serializers/auth/sso.py:20 msgid "SSO auth key TTL" @@ -7884,11 +7962,11 @@ msgstr "单位: 秒" #: settings/serializers/auth/wecom.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the WeCom service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the WeCom service user attribute name" msgstr "" -"用户属性映射,其中 `key` 是本系统用户属性名称,`value` 是企业微信服务用" -"户属性名称" +"用户属性映射,其中 `key` 是本系统用户属性名称,`value` 是企业微信服务用户属性" +"名称" #: settings/serializers/basic.py:11 msgid "Site URL" @@ -8976,7 +9054,7 @@ msgstr "等待:" msgid "The verification code has been sent" msgstr "验证码已发送" -#: templates/_without_nav_base.html:46 +#: templates/_without_nav_base.html:51 msgid "Home page" msgstr "首页" @@ -9237,31 +9315,31 @@ msgstr "可以并发" msgid "Hosts" msgstr "主机" -#: terminal/models/applet/applet.py:94 +#: terminal/models/applet/applet.py:102 #: terminal/models/virtualapp/virtualapp.py:66 #, python-brace-format msgid "Applet pkg not valid, Missing file {}" msgstr "Applet pkg 无效,缺少文件 {}" -#: terminal/models/applet/applet.py:113 +#: terminal/models/applet/applet.py:121 #, python-brace-format msgid "Load platform.yml failed: {}" msgstr "加载 platform.yml 失败: {}" -#: terminal/models/applet/applet.py:116 +#: terminal/models/applet/applet.py:124 msgid "Only support custom platform" msgstr "只支持自定义平台" -#: terminal/models/applet/applet.py:121 +#: terminal/models/applet/applet.py:129 msgid "Missing type in platform.yml" msgstr "在 platform.yml 中缺少类型" -#: terminal/models/applet/applet.py:381 terminal/models/applet/host.py:36 +#: terminal/models/applet/applet.py:389 terminal/models/applet/host.py:36 #: terminal/models/applet/host.py:138 msgid "Hosting" msgstr "宿主机" -#: terminal/models/applet/applet.py:387 +#: terminal/models/applet/applet.py:395 msgid "Applet Publication" msgstr "应用发布" @@ -9351,7 +9429,7 @@ msgstr "VNC 端口" #: terminal/models/component/endpoint.py:35 #: terminal/models/component/endpoint.py:115 -#: terminal/serializers/endpoint.py:63 terminal/serializers/storage.py:41 +#: 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" @@ -9556,10 +9634,8 @@ msgid "Level" msgstr "级别" #: terminal/notifications.py:172 terminal/notifications.py:239 -#, fuzzy -#| msgid "Privacy Policy" msgid "Policy" -msgstr "隐私协议" +msgstr "策略" #: terminal/notifications.py:263 msgid "Command and replay storage" @@ -9567,8 +9643,8 @@ msgstr "命令及录像存储" #: terminal/notifications.py:279 terminal/tasks.py:212 #: xpack/plugins/cloud/api.py:182 -#: xpack/plugins/cloud/serializers/account.py:143 -#: xpack/plugins/cloud/serializers/account.py:146 +#: xpack/plugins/cloud/serializers/account.py:148 +#: xpack/plugins/cloud/serializers/account.py:151 msgid "Test failure: Account invalid" msgstr "测试失败: 账号无效" @@ -9667,7 +9743,8 @@ msgstr "已有 RDS 许可证" msgid "" "If not exist, the RDS will be in trial mode, and the trial period is 120 " "days. Detail" +"remote-desktop-services/rds-client-access-license\" " +"target=\"_blank\">Detail" msgstr "" "如果不存在,RDS 将处于试用模式,试用期为 120 天。>> 開始執行測試閘道器帳號可連結性的任務" #: settings/serializers/auth/ldap.py:53 settings/serializers/auth/ldap_ha.py:35 #: settings/serializers/msg.py:37 settings/serializers/terminal.py:32 #: terminal/serializers/storage.py:123 terminal/serializers/storage.py:142 -#: users/forms/profile.py:22 users/serializers/user.py:148 +#: users/forms/profile.py:22 users/serializers/user.py:153 #: users/templates/users/_msg_user_created.html:13 #: users/templates/users/user_password_verify.html:18 #: xpack/plugins/cloud/serializers/account_attrs.py:43 @@ -227,7 +227,7 @@ msgstr "更新" #: accounts/const/account.py:34 accounts/const/automation.py:115 #: accounts/serializers/automations/change_secret.py:171 audits/const.py:66 -#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:66 +#: audits/signal_handlers/activity_log.py:34 common/const/choices.py:67 #: ops/const.py:77 terminal/const.py:81 xpack/plugins/cloud/const.py:55 msgid "Failed" msgstr "失敗" @@ -349,14 +349,14 @@ msgstr "SFTP" #: accounts/const/automation.py:116 #: accounts/serializers/automations/change_secret.py:170 audits/const.py:65 #: audits/models.py:65 audits/signal_handlers/activity_log.py:34 -#: common/const/choices.py:65 ops/const.py:75 ops/serializers/celery.py:48 +#: common/const/choices.py:66 ops/const.py:75 ops/serializers/celery.py:48 #: terminal/const.py:80 terminal/models/session/sharing.py:119 #: tickets/views/approve.py:128 msgid "Success" msgstr "成功" -#: accounts/const/automation.py:117 common/const/choices.py:63 -#: common/const/choices.py:114 terminal/const.py:79 +#: accounts/const/automation.py:117 common/const/choices.py:64 +#: common/const/choices.py:127 terminal/const.py:79 msgid "Pending" msgstr "待定的" @@ -364,7 +364,7 @@ msgstr "待定的" msgid "Queued" msgstr "排隊中" -#: accounts/const/automation.py:122 common/const/choices.py:62 +#: accounts/const/automation.py:122 common/const/choices.py:63 msgid "Ready" msgstr "準備" @@ -376,7 +376,7 @@ msgstr "處理中" msgid "Can login" msgstr "可登入" -#: accounts/const/automation.py:128 users/serializers/user.py:254 +#: accounts/const/automation.py:128 users/serializers/user.py:259 msgid "Superuser" msgstr "超級使用者" @@ -405,7 +405,7 @@ msgid "Default tablespace" msgstr "默認表空間" #: accounts/const/automation.py:135 rbac/models/role.py:46 -#: rbac/models/rolebinding.py:52 users/models/user/__init__.py:79 +#: rbac/models/rolebinding.py:53 users/models/user/__init__.py:79 msgid "Role" msgstr "角色" @@ -414,7 +414,7 @@ msgid "Perms" msgstr "權限" #: accounts/const/automation.py:137 perms/serializers/permission.py:56 -#: users/serializers/user.py:245 +#: users/serializers/user.py:250 msgid "Groups" msgstr "使用者群組" @@ -787,7 +787,7 @@ msgstr "結束日期" #: assets/models/automations/base.py:137 #: assets/serializers/automations/base.py:47 audits/models.py:224 #: audits/reporting.py:607 audits/serializers.py:77 ops/models/base.py:49 -#: ops/models/job.py:233 terminal/models/applet/applet.py:382 +#: ops/models/job.py:233 terminal/models/applet/applet.py:390 #: terminal/models/applet/host.py:140 terminal/models/component/status.py:30 #: terminal/models/virtualapp/virtualapp.py:99 #: terminal/serializers/applet.py:19 terminal/serializers/applet_host.py:163 @@ -802,7 +802,7 @@ msgstr "狀態" #: accounts/serializers/account/account.py:297 assets/const/automation.py:9 #: authentication/templates/authentication/passkey.html:177 #: authentication/views/base.py:43 authentication/views/base.py:44 -#: authentication/views/base.py:45 common/const/choices.py:67 +#: authentication/views/base.py:45 common/const/choices.py:68 #: settings/templates/ldap/_msg_import_ldap_user.html:26 msgid "Error" msgstr "錯誤" @@ -897,8 +897,9 @@ msgstr "重複密碼" #: accounts/templates/accounts/push_account_report.html:79 #: accounts/templates/accounts/push_account_report.html:119 #: acls/serializers/base.py:19 acls/serializers/base.py:50 audits/models.py:204 -#: audits/reporting.py:241 authentication/forms.py:21 -#: authentication/forms.py:23 authentication/models/temp_token.py:10 +#: audits/reporting.py:241 authentication/backends/cert/forms.py:7 +#: authentication/forms.py:21 authentication/forms.py:23 +#: authentication/models/temp_token.py:10 #: authentication/serializers/connect_token_secret.py:43 #: authentication/serializers/connect_token_secret.py:53 #: authentication/templates/authentication/_msg_different_city.html:9 @@ -1052,7 +1053,7 @@ msgstr "特權帳號" #: assets/models/cmd_filter.py:39 assets/models/label.py:22 #: authentication/serializers/connect_token_secret.py:129 reports/models.py:18 #: terminal/models/applet/applet.py:41 -#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:257 +#: terminal/models/virtualapp/virtualapp.py:23 users/serializers/user.py:262 msgid "Is active" msgstr "啟用" @@ -1068,7 +1069,7 @@ msgstr "系統平台" msgid "Push params" msgstr "帳號推送參數" -#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:403 +#: accounts/models/template.py:26 xpack/plugins/cloud/models.py:404 msgid "Account template" msgstr "帳號模板" @@ -1161,7 +1162,7 @@ msgstr "帳號變更資訊" msgid "Change secret or push account failed information" msgstr "改密或推送帳號失敗資訊" -#: accounts/risk_handlers.py:17 common/const/choices.py:116 +#: accounts/risk_handlers.py:17 common/const/choices.py:129 msgid "Ignored" msgstr "忽略" @@ -1317,7 +1318,7 @@ msgstr "ID" #: authentication/notifications.py:16 authentication/notifications.py:55 #: notifications/models/notification.py:12 #: perms/api/user_permission/mixin.py:58 perms/models/asset_permission.py:63 -#: rbac/builtin.py:134 rbac/models/rolebinding.py:49 +#: rbac/builtin.py:134 rbac/models/rolebinding.py:50 #: rbac/serializers/rolebinding.py:17 terminal/backends/command/models.py:16 #: terminal/models/session/session.py:27 terminal/models/session/sharing.py:34 #: terminal/notifications.py:168 terminal/notifications.py:235 @@ -1325,8 +1326,8 @@ msgstr "ID" #: terminal/templates/terminal/_msg_command_warning.html:9 #: terminal/templates/terminal/_msg_session_sharing.html:6 #: tickets/models/comment.py:21 tickets/serializers/flow.py:15 -#: users/const.py:14 users/models/user/__init__.py:298 -#: users/models/user/__init__.py:325 +#: users/const.py:14 users/models/user/__init__.py:303 +#: users/models/user/__init__.py:330 msgid "User" msgstr "用戶" @@ -1361,7 +1362,7 @@ msgstr "IP 白名單" #: assets/models/cmd_filter.py:88 common/db/models.py:36 ops/models/adhoc.py:25 #: ops/models/job.py:165 ops/models/playbook.py:31 rbac/models/role.py:37 #: settings/models.py:43 terminal/models/applet/applet.py:46 -#: terminal/models/applet/applet.py:383 terminal/models/applet/host.py:143 +#: terminal/models/applet/applet.py:391 terminal/models/applet/host.py:143 #: terminal/models/component/endpoint.py:29 #: terminal/models/component/endpoint.py:117 #: terminal/models/session/session.py:44 @@ -1637,7 +1638,7 @@ msgstr "" "由於每次更新資產帳號,均會生成歷史帳號,因此需要清理資產帳號的歷史。系統會根" "據帳號存儲-記錄限制的配置,每天凌晨2點對於超出的數量的帳號記錄進行清理" -#: accounts/tasks/remove_account.py:89 +#: accounts/tasks/remove_account.py:91 msgid "Remove historical accounts that are out of range." msgstr "刪除超出範圍的歷史帳戶。" @@ -1704,7 +1705,7 @@ msgstr "任務名稱" #: accounts/templates/accounts/push_account_report.html:22 #: assets/models/automations/base.py:143 audits/models.py:66 #: ops/models/base.py:55 ops/models/celery.py:89 ops/models/job.py:241 -#: ops/templates/ops/celery_task_log.html:101 +#: ops/templates/ops/celery_task_log.html:154 #: perms/models/asset_permission.py:78 settings/serializers/feature.py:29 #: settings/templates/ldap/_msg_import_ldap_user.html:5 #: terminal/models/applet/host.py:141 terminal/models/session/session.py:42 @@ -1888,7 +1889,7 @@ msgstr "審批人" #: acls/models/base.py:81 perms/serializers/permission.py:54 #: tickets/models/flow.py:23 users/models/preference.py:16 -#: users/serializers/group.py:21 users/serializers/user.py:424 +#: users/serializers/group.py:21 users/serializers/user.py:429 msgid "Users" msgstr "用戶管理" @@ -1914,7 +1915,7 @@ msgid "Command" msgstr "命令" #: acls/models/command_acl.py:17 assets/models/cmd_filter.py:59 -#: xpack/plugins/cloud/models.py:369 +#: xpack/plugins/cloud/models.py:370 msgid "Regex" msgstr "正則表達式" @@ -2003,7 +2004,7 @@ msgstr "規則" msgid "Login acl" msgstr "登錄訪問控制" -#: acls/models/login_acl.py:27 tickets/const.py:11 +#: acls/models/login_acl.py:30 tickets/const.py:11 msgid "Login confirm" msgstr "登錄覆核" @@ -2125,7 +2126,7 @@ msgstr "" #: authentication/templates/authentication/_msg_oauth_bind.html:12 #: authentication/templates/authentication/_msg_rest_password_success.html:8 #: authentication/templates/authentication/_msg_rest_public_key_success.html:8 -#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:405 +#: common/drf/renders/base.py:165 xpack/plugins/cloud/models.py:406 msgid "IP" msgstr "IP" @@ -2186,15 +2187,15 @@ msgstr "我們想通知您,最近有用戶登入:" msgid "User details" msgstr "使用者詳情" -#: assets/api/asset/asset.py:166 +#: assets/api/asset/asset.py:168 msgid "Cannot create asset directly, you should create a host or other" msgstr "不能直接創建資產, 你應該創建主機或其他資產" -#: assets/api/asset/asset.py:173 +#: assets/api/asset/asset.py:175 msgid "The number of assets exceeds the limit of 5000" msgstr "資產數量超過 5000 的限制" -#: assets/api/asset/asset.py:179 +#: assets/api/asset/asset.py:181 #, fuzzy #| msgid "The number of assets exceeds the limit of 5000" msgid "The number of assets exceeds the license limit" @@ -2213,6 +2214,11 @@ msgstr "不能刪除根節點 ({})" msgid "Deletion failed and the node contains assets" msgstr "刪除失敗,節點包含資產" +#: assets/api/node.py:99 +#, python-brace-format +msgid "Node {} is an ancestor of node {}, can't be added as its child" +msgstr "" + #: assets/api/tree.py:48 assets/serializers/node.py:42 msgid "The same level node name cannot be the same" msgstr "同級別節點名字不能重複" @@ -2230,29 +2236,29 @@ msgstr "資產管理" msgid "Task: {} finished" msgstr "任務:{} 完成" -#: assets/automations/base/manager.py:340 +#: assets/automations/base/manager.py:341 #, python-brace-format msgid " - Platform {} ansible disabled" msgstr " - 平台 {} Ansible 已禁用, 無法執行任務" -#: assets/automations/base/manager.py:555 +#: assets/automations/base/manager.py:556 msgid ">>> Task preparation phase" msgstr ">>> 任務準備階段" -#: assets/automations/base/manager.py:559 +#: assets/automations/base/manager.py:560 #, python-brace-format msgid ">>> Executing tasks in batches, total {runner_count}" msgstr ">>> 分次執行任務,總共 {runner_count}" -#: assets/automations/base/manager.py:564 +#: assets/automations/base/manager.py:565 msgid ">>> Start executing tasks" msgstr ">>> 開始執行任務" -#: assets/automations/base/manager.py:566 +#: assets/automations/base/manager.py:567 msgid ">>> No tasks need to be executed" msgstr ">>> 沒有需要執行的任務" -#: assets/automations/base/manager.py:570 +#: assets/automations/base/manager.py:571 #, python-brace-format msgid ">>> Begin executing batch {index} of tasks" msgstr ">>> 開始執行第 {index} 批任務" @@ -2647,7 +2653,7 @@ msgid "Port" msgstr "埠" #: assets/models/asset/common.py:167 assets/serializers/asset/common.py:175 -#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:59 +#: settings/serializers/terminal.py:10 terminal/serializers/endpoint.py:69 msgid "Address" msgstr "地址" @@ -2655,12 +2661,12 @@ msgstr "地址" #: assets/serializers/asset/common.py:151 #: authentication/backends/passkey/models.py:12 #: authentication/serializers/connect_token_secret.py:130 -#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:399 +#: perms/serializers/user_permission.py:26 xpack/plugins/cloud/models.py:400 msgid "Platform" msgstr "系統平台" #: assets/models/asset/common.py:173 assets/models/zone.py:22 -#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:401 +#: perms/serializers/user_permission.py:29 xpack/plugins/cloud/models.py:402 msgid "Zone" msgstr "網域" @@ -2729,9 +2735,9 @@ msgid "Proxy" msgstr "代理" #: assets/models/automations/base.py:23 assets/models/cmd_filter.py:32 -#: assets/models/node.py:553 ops/models/job.py:158 +#: assets/models/node.py:560 ops/models/job.py:158 #: perms/models/asset_permission.py:72 tickets/models/ticket/apply_asset.py:15 -#: xpack/plugins/cloud/models.py:400 +#: xpack/plugins/cloud/models.py:401 msgid "Node" msgstr "節點" @@ -2757,7 +2763,7 @@ msgstr "資產自動化任務" #: assets/models/automations/base.py:140 assets/models/cmd_filter.py:41 #: authentication/serializers/token.py:134 common/db/models.py:34 #: ops/models/base.py:54 ops/models/job.py:240 -#: users/models/user/__init__.py:328 +#: users/models/user/__init__.py:333 msgid "Date created" msgstr "創建日期" @@ -2846,7 +2852,7 @@ msgstr "網關" msgid "System" msgstr "系統" -#: assets/models/label.py:19 assets/models/node.py:539 +#: assets/models/label.py:19 assets/models/node.py:546 #: assets/serializers/cagegory.py:11 assets/serializers/cagegory.py:18 #: assets/serializers/cagegory.py:24 #: authentication/models/connection_token.py:35 @@ -2861,7 +2867,7 @@ msgstr "值" #: assets/serializers/platform.py:160 #: authentication/serializers/connect_token_secret.py:136 #: common/serializers/common.py:85 labels/serializers.py:45 -#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:404 +#: settings/serializers/msg.py:91 xpack/plugins/cloud/models.py:405 msgid "Label" msgstr "標籤" @@ -2877,27 +2883,27 @@ msgstr "自訂備註" msgid "My assets" msgstr "我的資產" -#: assets/models/node.py:168 +#: assets/models/node.py:172 msgid "New node" msgstr "新節點" -#: assets/models/node.py:467 audits/backends/db.py:85 audits/backends/db.py:86 +#: assets/models/node.py:474 audits/backends/db.py:85 audits/backends/db.py:86 msgid "empty" msgstr "空" -#: assets/models/node.py:538 perms/models/perm_node.py:28 +#: assets/models/node.py:545 perms/models/perm_node.py:28 msgid "Key" msgstr "鍵" -#: assets/models/node.py:540 assets/serializers/node.py:20 +#: assets/models/node.py:547 assets/serializers/node.py:20 msgid "Full value" msgstr "全稱" -#: assets/models/node.py:544 perms/models/perm_node.py:30 +#: assets/models/node.py:551 perms/models/perm_node.py:30 msgid "Parent key" msgstr "ssh私鑰" -#: assets/models/node.py:556 +#: assets/models/node.py:563 msgid "Can match node" msgstr "可以匹配節點" @@ -3073,7 +3079,7 @@ msgstr "節點路徑,格式為 [\"/組織/節點名稱\"], 如果節點不存 #: authentication/serializers/connect_token_secret.py:30 #: authentication/serializers/connect_token_secret.py:77 #: perms/models/asset_permission.py:76 perms/serializers/permission.py:68 -#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:402 +#: perms/serializers/user_permission.py:86 xpack/plugins/cloud/models.py:403 #: xpack/plugins/cloud/serializers/task.py:36 msgid "Protocols" msgstr "協議組" @@ -3507,7 +3513,7 @@ msgid "Symlink" msgstr "建立軟連結" #: audits/const.py:18 audits/const.py:29 -#: ops/templates/ops/celery_task_log.html:86 +#: ops/templates/ops/celery_task_log.html:139 #: terminal/api/session/session.py:159 msgid "Download" msgstr "下載" @@ -3536,7 +3542,9 @@ msgstr "匯出" msgid "Connect" msgstr "連接" -#: audits/const.py:31 authentication/templates/authentication/login.html:334 +#: audits/const.py:31 +#: authentication/templates/authentication/cert_login.html:232 +#: authentication/templates/authentication/login.html:334 #: authentication/templates/authentication/login.html:408 #: templates/_header_bar.html:101 #: xpack/plugins/interface/templates/login_i18n.html:21 @@ -4185,10 +4193,8 @@ msgid "SSO" msgstr "SSO" #: audits/signal_handlers/login_log.py:36 -#, fuzzy -#| msgid "Custom" msgid "Custom SSO" -msgstr "自定義" +msgstr "自定義 SSO" #: audits/signal_handlers/login_log.py:37 msgid "Auth Token" @@ -4325,24 +4331,24 @@ msgstr "臉部比對失敗" msgid "Current user not support mfa type: {}" msgstr "當前用戶不支持 MFA 類型: {}" -#: authentication/api/password.py:34 terminal/api/session/session.py:347 +#: authentication/api/password.py:37 terminal/api/session/session.py:347 #: users/views/profile/reset.py:63 #, python-brace-format msgid "User does not exist: {}" msgstr "用戶不存在: {}" -#: authentication/api/password.py:34 users/views/profile/reset.py:166 +#: authentication/api/password.py:37 users/views/profile/reset.py:166 msgid "No user matched" msgstr "沒有匹配到用戶" -#: authentication/api/password.py:38 +#: authentication/api/password.py:41 #, python-brace-format msgid "" "The user is from {}, please go to the corresponding system to change the " "password" msgstr "用戶來自 {} 請去相應系統修改密碼" -#: authentication/api/password.py:69 +#: authentication/api/password.py:72 #: authentication/templates/authentication/login.html:400 #: users/templates/users/forgot_password.html:41 #: users/templates/users/forgot_password.html:42 @@ -4352,7 +4358,7 @@ msgstr "用戶來自 {} 請去相應系統修改密碼" msgid "Forgot password" msgstr "忘記密碼" -#: authentication/api/password.py:70 authentication/mfa/email.py:42 +#: authentication/api/password.py:73 authentication/mfa/email.py:42 #, python-brace-format msgid "The validity period of the verification code is {} minute" msgstr "驗證碼有效期為 {} 分鐘" @@ -4365,10 +4371,21 @@ msgstr "身份验证管理" msgid "CAS Error" msgstr "CAS 錯誤" -#: authentication/backends/custom.py:60 -#: authentication/backends/oauth2/backends.py:158 -msgid "User invalid, disabled or expired" -msgstr "用戶無效,已禁用或已過期" +#: authentication/backends/cert/api.py:57 +msgid "Certificate enrollment is not enabled" +msgstr "憑證簽發未啟用" + +#: authentication/backends/cert/api.py:62 +msgid "CSR is required" +msgstr "CSR 為必填項。" + +#: authentication/backends/cert/api.py:68 +msgid "Certificate signing failed" +msgstr "憑證簽發失敗" + +#: authentication/backends/cert/views.py:97 +msgid "Invalid credentials" +msgstr "無效的憑證" #: authentication/backends/drf.py:61 msgid "Invalid token header. No credentials provided." @@ -4611,16 +4628,16 @@ msgstr "您的密碼無效" msgid "Please wait for %s seconds before retry" msgstr "請在 %s 秒後重試" -#: authentication/errors/redirect.py:85 authentication/mixins.py:436 +#: authentication/errors/redirect.py:85 authentication/mixins.py:445 #: users/views/profile/reset.py:224 msgid "Your password is too simple, please change it for security" msgstr "你的密碼過於簡單,為了安全,請修改" -#: authentication/errors/redirect.py:93 authentication/mixins.py:445 +#: authentication/errors/redirect.py:93 authentication/mixins.py:454 msgid "You should to change your password before login" msgstr "登錄完成前,請先修改密碼" -#: authentication/errors/redirect.py:101 authentication/mixins.py:454 +#: authentication/errors/redirect.py:101 authentication/mixins.py:463 msgid "Your password has expired, please reset before logging in" msgstr "您的密碼已過期,先修改再登錄" @@ -4746,11 +4763,11 @@ msgid "" msgstr "" "管理員已開啟 '僅允許已存在用戶登入',當前用戶不在用戶列表中,請聯繫管理員。" -#: authentication/mixins.py:184 +#: authentication/mixins.py:187 msgid "User is invalid" msgstr "無效的用戶" -#: authentication/mixins.py:201 +#: authentication/mixins.py:204 #, python-brace-format msgid "" " The administrator has enabled 'Only allow login from user source'. \n" @@ -4758,12 +4775,12 @@ msgid "" "administrator. " msgstr "管理員已開啟 '僅允許從用戶來源登入',當前用戶來源為 {},請聯繫管理員。" -#: authentication/mixins.py:382 +#: authentication/mixins.py:391 #, python-brace-format msgid "The MFA type ({}) is not enabled" msgstr "該 MFA ({}) 方式沒有啟用" -#: authentication/mixins.py:424 +#: authentication/mixins.py:433 msgid "Please change your password" msgstr "請修改密碼" @@ -4955,7 +4972,7 @@ msgstr "動作" #: authentication/serializers/connection_token.py:46 #: perms/serializers/permission.py:66 perms/serializers/permission.py:87 -#: users/serializers/user.py:127 users/serializers/user.py:261 +#: users/serializers/user.py:127 users/serializers/user.py:266 msgid "Is expired" msgstr "已過期" @@ -4995,13 +5012,13 @@ msgstr "SSH金鑰不合法" #: authentication/serializers/token.py:93 perms/serializers/permission.py:65 #: perms/serializers/permission.py:88 users/serializers/user.py:128 -#: users/serializers/user.py:258 +#: users/serializers/user.py:263 msgid "Is valid" msgstr "是否有效" #: authentication/serializers/token.py:131 ops/models/adhoc.py:26 #: ops/models/playbook.py:34 ops/serializers/mixin.py:10 rbac/models/role.py:31 -#: rbac/models/rolebinding.py:46 rbac/serializers/role.py:12 +#: rbac/models/rolebinding.py:47 rbac/serializers/role.py:12 #: settings/serializers/auth/oauth2.py:37 msgid "Scope" msgstr "範圍" @@ -5096,7 +5113,7 @@ msgstr "代碼錯誤" #: authentication/templates/authentication/_msg_oauth_bind.html:3 #: authentication/templates/authentication/_msg_reset_password.html:3 #: authentication/templates/authentication/_msg_reset_password_code.html:9 -#: jumpserver/conf.py:555 +#: jumpserver/conf.py:558 #: perms/templates/perms/_msg_item_permissions_expire.html:3 #: tickets/templates/tickets/approve_check_password.html:32 #: users/templates/users/_msg_account_expire_reminder.html:4 @@ -5192,6 +5209,67 @@ msgstr "如果這次公鑰更新不是由你發起的,那麼你的帳號可能 msgid "Cancel" msgstr "取消" +#: authentication/templates/authentication/cert_login.html:190 +msgid "Certificate Authentication" +msgstr "憑證認證" + +#: authentication/templates/authentication/cert_login.html:195 +#: authentication/templates/authentication/cert_login.html:250 +msgid "Loading USB Key driver..." +msgstr "正在載入 USB Key 驅動程式..." + +#: authentication/templates/authentication/cert_login.html:210 +msgid "Insert USB Key to auto-fetch" +msgstr "請插入 USB Key 自動取得" + +#: authentication/templates/authentication/cert_login.html:251 +msgid "Detecting USB Key..." +msgstr "正在偵測 USB Key..." + +#: authentication/templates/authentication/cert_login.html:252 +msgid "USB Key connected" +msgstr "USB Key 已連接" + +#: authentication/templates/authentication/cert_login.html:253 +msgid "Please insert USB Key" +msgstr "請插入 USB Key" + +#: authentication/templates/authentication/cert_login.html:254 +msgid "Driver unavailable" +msgstr "驅動程式不可用" + +#: authentication/templates/authentication/cert_login.html:255 +msgid "USB Key SDK initialization failed" +msgstr "USB Key SDK 初始化失敗" + +#: authentication/templates/authentication/cert_login.html:256 +msgid "Verifying PIN..." +msgstr "PIN 驗證中..." + +#: authentication/templates/authentication/cert_login.html:257 +msgid "PIN verified" +msgstr "PIN 驗證通過" + +#: authentication/templates/authentication/cert_login.html:258 +msgid "PIN verification failed" +msgstr "驗證 PIN 失敗" + +#: authentication/templates/authentication/cert_login.html:259 +msgid "Signing challenge code..." +msgstr "正在對挑戰碼簽名..." + +#: authentication/templates/authentication/cert_login.html:260 +msgid "Signing failed" +msgstr "簽名失敗" + +#: authentication/templates/authentication/cert_login.html:261 +msgid "Failed to retrieve certificate" +msgstr "取得憑證失敗" + +#: authentication/templates/authentication/cert_login.html:262 +msgid "No certificate detected, please contact administrator" +msgstr "未偵測到憑證,請聯繫管理員製證" + #: authentication/templates/authentication/face_capture.html:14 msgid "Retry" msgstr "重試" @@ -5259,6 +5337,10 @@ msgstr "是否重試 ?" msgid "LAN" msgstr "區域網路" +#: authentication/utils.py:150 +msgid "CERT" +msgstr "" + #: authentication/views/base.py:71 #: perms/templates/perms/_msg_permed_items_expire.html:18 msgid "If you have any question, please contact the administrator" @@ -5421,47 +5503,47 @@ msgstr "請使用密碼登錄,然後綁定企業微信" msgid "Request file format may be wrong" msgstr "上傳的檔案格式錯誤 或 其它類型資源的文件" -#: common/const/choices.py:40 +#: common/const/choices.py:41 msgid "China" msgstr "中國" -#: common/const/choices.py:57 +#: common/const/choices.py:58 msgid "Manual" msgstr "手動觸發" -#: common/const/choices.py:58 +#: common/const/choices.py:59 msgid "Timing" msgstr "定時觸發" -#: common/const/choices.py:64 ops/const.py:74 +#: common/const/choices.py:65 ops/const.py:74 msgid "Running" msgstr "運行中" -#: common/const/choices.py:68 +#: common/const/choices.py:69 msgid "Canceled" msgstr "取消" -#: common/const/choices.py:115 +#: common/const/choices.py:128 msgid "Confirmed" msgstr "確認" -#: common/const/choices.py:123 terminal/models/applet/applet.py:31 +#: common/const/choices.py:136 terminal/models/applet/applet.py:31 msgid "Community edition" msgstr "社區版" -#: common/const/choices.py:124 +#: common/const/choices.py:137 msgid "Basic edition" msgstr "企業基礎版" -#: common/const/choices.py:125 +#: common/const/choices.py:138 msgid "Standard edition" msgstr "企業標準版" -#: common/const/choices.py:126 +#: common/const/choices.py:139 msgid "Professional edition" msgstr "企業專業版" -#: common/const/choices.py:127 +#: common/const/choices.py:140 msgid "Ultimate edition" msgstr "企業旗艦版" @@ -5962,24 +6044,24 @@ msgstr "未找到 Code" msgid "The message code provided is invalid or has expired" msgstr "提供的消息代碼無效或已過期" -#: jumpserver/conf.py:549 +#: jumpserver/conf.py:552 #, python-brace-format msgid "The verification code is: {code}" msgstr "驗證碼為: {code}" -#: jumpserver/conf.py:554 +#: jumpserver/conf.py:557 msgid "Create account successfully" msgstr "創建帳號成功" -#: jumpserver/conf.py:556 +#: jumpserver/conf.py:559 msgid "Your account has been created successfully" msgstr "你的帳號已創建成功" -#: jumpserver/context_processor.py:17 +#: jumpserver/context_processor.py:16 msgid "JumpServer - An open-source PAM" msgstr "JumpServer 開源堡壘機" -#: jumpserver/context_processor.py:37 +#: jumpserver/context_processor.py:31 msgid "FIT2CLOUD" msgstr "" @@ -6680,7 +6762,7 @@ msgid "Please save in a org" msgstr "請選擇一個組織後再保存" #: orgs/mixins/models.py:58 orgs/mixins/serializers.py:25 orgs/models.py:91 -#: rbac/const.py:7 rbac/models/rolebinding.py:56 +#: rbac/const.py:7 rbac/models/rolebinding.py:57 #: rbac/serializers/rolebinding.py:44 settings/serializers/auth/base.py:53 #: terminal/notifications.py:309 #: terminal/templates/terminal/_msg_command_warning.html:27 @@ -7104,25 +7186,25 @@ msgstr "系統角色" msgid "Organization role" msgstr "組織角色" -#: rbac/models/rolebinding.py:62 +#: rbac/models/rolebinding.py:63 msgid "Role binding" msgstr "角色綁定" -#: rbac/models/rolebinding.py:168 +#: rbac/models/rolebinding.py:169 msgid "All organizations" msgstr "所有組織" -#: rbac/models/rolebinding.py:200 +#: rbac/models/rolebinding.py:201 msgid "" "User last role in org, can not be delete, you can remove user from org " "instead" msgstr "用戶最後一個角色,不能刪除,你可以將用戶從組織移除" -#: rbac/models/rolebinding.py:207 +#: rbac/models/rolebinding.py:208 msgid "Organization role binding" msgstr "組織角色綁定" -#: rbac/models/rolebinding.py:222 +#: rbac/models/rolebinding.py:223 msgid "System role binding" msgstr "系統角色綁定" @@ -7187,7 +7269,7 @@ msgid "Storage" msgstr "儲存" #: rbac/tree.py:64 terminal/models/applet/applet.py:53 -#: terminal/models/applet/applet.py:379 terminal/models/applet/host.py:30 +#: terminal/models/applet/applet.py:387 terminal/models/applet/host.py:30 #: terminal/serializers/applet.py:16 msgid "Applet" msgstr "遠程應用" @@ -7250,51 +7332,51 @@ msgstr "撤銷訪問令牌" msgid "Range days" msgstr "修改者" -#: reports/views.py:20 +#: reports/views.py:19 msgid "User login report" msgstr "用戶登錄報告" -#: reports/views.py:24 +#: reports/views.py:23 msgid "User change password report" msgstr "用戶修改密碼報告" -#: reports/views.py:28 +#: reports/views.py:27 msgid "Asset statistics report" msgstr "資產統計報告" -#: reports/views.py:32 +#: reports/views.py:31 msgid "Asset activity report" msgstr "資產活動報告" -#: reports/views.py:36 +#: reports/views.py:35 msgid "Account statistics report" msgstr "賬號統計報告" -#: reports/views.py:40 +#: reports/views.py:39 msgid "Account automation report" msgstr "賬號自動化報告" -#: reports/views.py:44 +#: reports/views.py:43 msgid "ConsoleDashboard" msgstr "控制台儀表板" -#: reports/views.py:48 +#: reports/views.py:47 msgid "AuditsDashboard" msgstr "審計台儀表板" -#: reports/views.py:52 +#: reports/views.py:51 msgid "PamDashboard" msgstr "PAM 儀表板" -#: reports/views.py:56 +#: reports/views.py:55 msgid "ChangeSecretDashboard" msgstr "帳號改密儀表盤" -#: reports/views.py:191 +#: reports/views.py:190 msgid "Failed to send email: " msgstr "發送郵件失敗" -#: reports/views.py:192 +#: reports/views.py:191 msgid "Email sent successfully to " msgstr "發送郵件成功" @@ -7573,19 +7655,19 @@ msgstr "啟用釘釘認證" #: settings/serializers/auth/dingtalk.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the DingTalk service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the DingTalk service user attribute name" msgstr "" -"使用者屬性對照,其中 `key` 是本系統使用者屬性名稱,`value` 是釘釘服務使" -"用者屬性名稱" +"使用者屬性對照,其中 `key` 是本系統使用者屬性名稱,`value` 是釘釘服務使用者屬" +"性名稱" #: settings/serializers/auth/feishu.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the FeiShu service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the FeiShu service user attribute name" msgstr "" -"使用者屬性對照,其中 `key` 是本系統使用者屬性名稱,`value` 是飛書服務使" -"用者屬性名稱" +"使用者屬性對照,其中 `key` 是本系統使用者屬性名稱,`value` 是飛書服務使用者屬" +"性名稱" #: settings/serializers/auth/lark.py:13 users/models/user/_source.py:24 msgid "Lark" @@ -7593,11 +7675,11 @@ msgstr "Lark" #: settings/serializers/auth/lark.py:19 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Lark service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Lark service user attribute name" msgstr "" -"使用者屬性對照,其中 `key` 是本系統使用者屬性名稱,`value` 是 Lark 服務" -"使用者屬性名稱" +"使用者屬性對照,其中 `key` 是本系統使用者屬性名稱,`value` 是 Lark 服務使用者" +"屬性名稱" #: settings/serializers/auth/ldap.py:42 settings/serializers/auth/ldap.py:108 msgid "LDAP" @@ -7640,11 +7722,11 @@ msgstr "可能的選項是(cn或uid或sAMAccountName=%(user)s)" #: settings/serializers/auth/ldap.py:69 settings/serializers/auth/ldap_ha.py:51 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the LDAP service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the LDAP service user attribute name" msgstr "" -"使用者屬性對照,其中 `key` 是本系統使用者屬性名稱,`value` 是 LDAP 服務" -"使用者屬性名稱" +"使用者屬性對照,其中 `key` 是本系統使用者屬性名稱,`value` 是 LDAP 服務使用者" +"屬性名稱" #: settings/serializers/auth/ldap.py:85 settings/serializers/auth/ldap_ha.py:67 msgid "Connect timeout (s)" @@ -7745,11 +7827,11 @@ msgstr "當使用者退出時,他們也會從 OAuth2 伺服器退出" #: settings/serializers/auth/oauth2.py:62 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OAuth2 service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OAuth2 service user attribute name" msgstr "" -"使用者屬性對照,其中 `key` 是本系統使用者屬性名稱,`value` 是 OAuth2 服" -"務使用者屬性名稱" +"使用者屬性對照,其中 `key` 是本系統使用者屬性名稱,`value` 是 OAuth2 服務使用" +"者屬性名稱" #: settings/serializers/auth/oauth2.py:67 settings/serializers/auth/oidc.py:117 #: settings/serializers/auth/saml2.py:45 @@ -7782,11 +7864,11 @@ msgstr "Ignore SSL certificate verification" #: settings/serializers/auth/oidc.py:41 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the OIDC service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the OIDC service user attribute name" msgstr "" -"使用者屬性映射,其中 `key` 是本系統使用者屬性名稱,`value` 是 OIDC 服務" -"使用者屬性名稱" +"使用者屬性映射,其中 `key` 是本系統使用者屬性名稱,`value` 是 OIDC 服務使用者" +"屬性名稱" #: settings/serializers/auth/oidc.py:45 msgid "Enable PKCE" @@ -7916,8 +7998,8 @@ msgid "" "User attribute mapping, where the `key` is the SAML2 service user attribute " "name and the `value` is this system user attribute name" msgstr "" -" 使用者屬性映射,其中 `key` 是 SAML2 服務使用者屬性名稱,`value` 是 " -"本系統使用者屬性名稱" +" 使用者屬性映射,其中 `key` 是 SAML2 服務使用者屬性名稱,`value` 是 本系統使" +"用者屬性名稱" #: settings/serializers/auth/saml2.py:43 msgid "When the user signs out, they also be logged out from the SAML2 server" @@ -7925,11 +8007,11 @@ msgstr "當使用者登出時,他們也會從 SAML2 伺服器登出" #: settings/serializers/auth/slack.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the Slack service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the Slack service user attribute name" msgstr "" -"使用者屬性對照,其中 `key` 是本系統使用者屬性名稱,`value` 是 Slack 服" -"務使用者屬性名稱" +"使用者屬性對照,其中 `key` 是本系統使用者屬性名稱,`value` 是 Slack 服務使用" +"者屬性名稱" #: settings/serializers/auth/sms.py:18 msgid "Enable Short Message Service (SMS)" @@ -7963,7 +8045,7 @@ msgid "Template code" msgstr "模板" #: settings/serializers/auth/sms.py:40 users/models/user/__init__.py:89 -#: users/serializers/user.py:159 +#: users/serializers/user.py:164 msgid "Phone" msgstr "手機" @@ -8019,8 +8101,8 @@ msgid "Enable SSO auth" msgstr "啟用 SSO 令牌認證" #: settings/serializers/auth/sso.py:17 -msgid "Other service can using SSO token login to JumpServer without password" -msgstr "其它系統可以使用 SSO Token 對接 JumpServer, 免去登錄的過程" +msgid "Other service can using SSO token login to system without password" +msgstr "其它系統可以使用 SSO Token 對接系统, 免去登錄的過程" #: settings/serializers/auth/sso.py:20 msgid "SSO auth key TTL" @@ -8033,11 +8115,11 @@ msgstr "單位: 秒" #: settings/serializers/auth/wecom.py:20 msgid "" -"User attribute mapping, where the `key` is this system user attribute " -"name and the `value` is the WeCom service user attribute name" +"User attribute mapping, where the `key` is this system user attribute name " +"and the `value` is the WeCom service user attribute name" msgstr "" -"使用者屬性映射,其中 `key` 是本系統使用者屬性名稱,`value` 是企業微信服" -"務使用者屬性名稱" +"使用者屬性映射,其中 `key` 是本系統使用者屬性名稱,`value` 是企業微信服務使用" +"者屬性名稱" #: settings/serializers/basic.py:11 msgid "Site URL" @@ -9134,7 +9216,7 @@ msgstr "等待:" msgid "The verification code has been sent" msgstr "驗證碼已發送" -#: templates/_without_nav_base.html:46 +#: templates/_without_nav_base.html:51 msgid "Home page" msgstr "首頁" @@ -9395,31 +9477,31 @@ msgstr "可以並發" msgid "Hosts" msgstr "主機" -#: terminal/models/applet/applet.py:94 +#: terminal/models/applet/applet.py:102 #: terminal/models/virtualapp/virtualapp.py:66 #, python-brace-format msgid "Applet pkg not valid, Missing file {}" msgstr "Applet pkg 無效,缺少文件 {}" -#: terminal/models/applet/applet.py:113 +#: terminal/models/applet/applet.py:121 #, python-brace-format msgid "Load platform.yml failed: {}" msgstr "載入 platform.yml 失敗: {}" -#: terminal/models/applet/applet.py:116 +#: terminal/models/applet/applet.py:124 msgid "Only support custom platform" msgstr "只支持自訂平台" -#: terminal/models/applet/applet.py:121 +#: terminal/models/applet/applet.py:129 msgid "Missing type in platform.yml" msgstr "在 platform.yml 中缺少類型" -#: terminal/models/applet/applet.py:381 terminal/models/applet/host.py:36 +#: terminal/models/applet/applet.py:389 terminal/models/applet/host.py:36 #: terminal/models/applet/host.py:138 msgid "Hosting" msgstr "宿主機" -#: terminal/models/applet/applet.py:387 +#: terminal/models/applet/applet.py:395 msgid "Applet Publication" msgstr "應用發布" @@ -9509,7 +9591,7 @@ msgstr "VNC 端口" #: terminal/models/component/endpoint.py:35 #: terminal/models/component/endpoint.py:115 -#: terminal/serializers/endpoint.py:63 terminal/serializers/storage.py:41 +#: 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" @@ -9723,8 +9805,8 @@ msgstr "命令及錄影儲存" #: terminal/notifications.py:279 terminal/tasks.py:212 #: xpack/plugins/cloud/api.py:182 -#: xpack/plugins/cloud/serializers/account.py:143 -#: xpack/plugins/cloud/serializers/account.py:146 +#: xpack/plugins/cloud/serializers/account.py:148 +#: xpack/plugins/cloud/serializers/account.py:151 msgid "Test failure: Account invalid" msgstr "測試失敗: 帳號無效" @@ -9844,7 +9926,8 @@ msgstr "已有 RDS 許可證" msgid "" "If not exist, the RDS will be in trial mode, and the trial period is 120 " "days. Detail" +"remote-desktop-services/rds-client-access-license\" " +"target=\"_blank\">Detail" msgstr "" "如果不存在,RDS將處於試用模式,試用期為 120 天。