Compare commits

...

13 Commits

Author SHA1 Message Date
wangruidong
6686afcec1 fix: Password reset is only required for AUTH_BACKEND_MODEL 2024-10-23 11:04:15 +08:00
wangruidong
0918f5c6f6 perf: Translate 2024-10-22 17:49:22 +08:00
wangruidong
891e3d5609 perf: Storage update comment failed 2024-10-22 17:28:47 +08:00
wangruidong
9fad591545 fix: Historical sessions download failed 2024-10-22 16:34:46 +08:00
fit2bot
1ed1c3a536 perf: optimize the connection of operation logs to ES to prevent ES downtime from causing the core component to become unhealthy. (#14283)
* perf: optimize the connection of operation logs to ES to prevent ES downtime from causing the core component to become unhealthy.

* perf: sync publish message

---------

Co-authored-by: jiangweidong <1053570670@qq.com>
2024-10-12 16:18:18 +08:00
wangruidong
63824d3491 fix: adhoc execute alert msg 2024-10-12 16:15:48 +08:00
wangruidong
96eadf060c perf: site msg content optimize 2024-10-11 11:30:59 +08:00
Bai
2c9128b0e7 perf: DEFAULT_PAGE_SIZE same as MAX_LIMIT_PER_PAGE 2024-10-10 18:00:26 +08:00
Bai
7d6fd0f881 fix: Fixed the issue that the workbench user login log only displays failed logs 2024-09-29 14:45:59 +08:00
jiangweidong
4e996afd5e perf: Cloud Sync IP Policy Updated to Preferred Option i18n 2024-09-27 14:29:08 +08:00
feng
1ed745d042 perf: Login encryption key cache added 2024-09-26 15:11:56 +08:00
feng
39ebbfcf10 perf: The locked ip shows the username 2024-09-06 11:00:39 +08:00
wangruidong
d0ec4f798b perf: Optimize asset connection speed with es command storage 2024-08-30 10:53:03 +08:00
34 changed files with 368 additions and 230 deletions

View File

@@ -28,7 +28,7 @@ from orgs.utils import current_org, tmp_to_root_org
from rbac.permissions import RBACPermission
from terminal.models import default_storage
from users.models import User
from .backends import TYPE_ENGINE_MAPPING
from .backends import get_operate_log_storage
from .const import ActivityChoices
from .filters import UserSessionFilterSet, OperateLogFilterSet
from .models import (
@@ -146,7 +146,9 @@ class MyLoginLogViewSet(UserLoginCommonMixin, OrgReadonlyModelViewSet):
def get_queryset(self):
qs = super().get_queryset()
qs = qs.filter(username=self.request.user.username)
username = self.request.user.username
q = Q(username=username) | Q(username__icontains=f'({username})')
qs = qs.filter(q)
return qs
@@ -222,13 +224,11 @@ class OperateLogViewSet(OrgReadonlyModelViewSet):
if self.is_action_detail:
with tmp_to_root_org():
qs |= OperateLog.objects.filter(org_id=Organization.SYSTEM_ID)
es_config = settings.OPERATE_LOG_ELASTICSEARCH_CONFIG
if es_config:
engine_mod = import_module(TYPE_ENGINE_MAPPING['es'])
store = engine_mod.OperateLogStore(es_config)
if store.ping(timeout=2):
qs = ESQuerySet(store)
qs.model = OperateLog
storage = get_operate_log_storage()
if storage.get_type() == 'es':
qs = ESQuerySet(storage)
qs.model = OperateLog
return qs

View File

@@ -1,18 +1,62 @@
from importlib import import_module
from django.conf import settings
from django.core.cache import cache
from django.utils.translation import gettext_lazy as _
from common.utils import get_logger
from .base import BaseOperateStorage
from .es import OperateLogStore as ESOperateLogStore
from .db import OperateLogStore as DBOperateLogStore
TYPE_ENGINE_MAPPING = {
'db': 'audits.backends.db',
'es': 'audits.backends.es',
logger = get_logger(__file__)
_global_op_log_storage: None | ESOperateLogStore | DBOperateLogStore = None
op_log_type_mapping = {
'server': DBOperateLogStore, 'es': ESOperateLogStore
}
def get_operate_log_storage(default=False):
engine_mod = import_module(TYPE_ENGINE_MAPPING['db'])
es_config = settings.OPERATE_LOG_ELASTICSEARCH_CONFIG
if not default and es_config:
engine_mod = import_module(TYPE_ENGINE_MAPPING['es'])
storage = engine_mod.OperateLogStore(es_config)
return storage
def _send_es_unavailable_alarm_msg():
from terminal.notifications import StorageConnectivityMessage
from terminal.const import CommandStorageType
key = 'OPERATE_LOG_ES_UNAVAILABLE_KEY'
if cache.get(key):
return
cache.set(key, 1, 60)
errors = [{
'msg': _("Connect failed"), 'name': f"{_('Operate log')}",
'type': CommandStorageType.es.label
}]
StorageConnectivityMessage(errors).publish_async()
def refresh_log_storage():
global _global_op_log_storage
_global_op_log_storage = None
if settings.OPERATE_LOG_ELASTICSEARCH_CONFIG.get('HOSTS'):
try:
config = settings.OPERATE_LOG_ELASTICSEARCH_CONFIG
log_storage = op_log_type_mapping['es'](config)
_global_op_log_storage = log_storage
except Exception as e:
_send_es_unavailable_alarm_msg()
logger.warning('Invalid logs storage type: es, error: %s' % str(e))
if not _global_op_log_storage:
_global_op_log_storage = op_log_type_mapping['server']()
def get_operate_log_storage():
if _global_op_log_storage is None:
refresh_log_storage()
log_storage = _global_op_log_storage
if not log_storage.ping(timeout=3):
if log_storage.get_type() == 'es':
_send_es_unavailable_alarm_msg()
logger.warning('Switch default operate log storage.')
log_storage = op_log_type_mapping['server']()
return log_storage

View File

@@ -0,0 +1,15 @@
from perms.const import ActionChoices
class BaseOperateStorage(object):
@staticmethod
def get_type():
return 'base'
@staticmethod
def _get_special_handler(resource_type):
# 根据资源类型,处理特殊字段
resource_map = {
'Asset permission': lambda k, v: ActionChoices.display(int(v)) if k == 'Actions' else v
}
return resource_map.get(resource_type, lambda k, v: v)

View File

@@ -2,14 +2,14 @@
from django.utils.translation import gettext_lazy as _
from audits.models import OperateLog
from perms.const import ActionChoices
from .base import BaseOperateStorage
class OperateLogStore(object):
class OperateLogStore(BaseOperateStorage):
# 用不可见字符分割前后数据,节省存储-> diff: {'key': 'before\0after'}
SEP = '\0'
def __init__(self, config):
def __init__(self, *args, **kwargs):
self.model = OperateLog
self.max_length = 2048
self.max_length_tip_msg = _(
@@ -17,9 +17,13 @@ class OperateLogStore(object):
)
@staticmethod
def ping(timeout=None):
def ping(*args, **kwargs):
return True
@staticmethod
def get_type():
return 'db'
@classmethod
def convert_before_after_to_diff(cls, before, after):
if not isinstance(before, dict):
@@ -46,21 +50,13 @@ class OperateLogStore(object):
before[k], after[k] = before_value, after_value
return before, after
@staticmethod
def _get_special_handler(resource_type):
# 根据资源类型,处理特殊字段
resource_map = {
'Asset permission': lambda k, v: ActionChoices.display(int(v)) if k == 'Actions' else v
}
return resource_map.get(resource_type, lambda k, v: _(v))
@classmethod
def convert_diff_friendly(cls, op_log):
diff_list = list()
handler = cls._get_special_handler(op_log.resource_type)
# 标记翻译字符串
labels = _("labels")
operate_log_id = _("operate_log_id")
handler = cls._get_special_handler(op_log.resource_type)
for k, v in op_log.diff.items():
before, after = v.split(cls.SEP, 1)
diff_list.append({

View File

@@ -2,16 +2,17 @@
#
import uuid
from django.utils.translation import gettext_lazy as _
from common.utils.timezone import local_now_display
from common.utils import get_logger
from common.utils.encode import Singleton
from common.plugins.es import ES
from .base import BaseOperateStorage
logger = get_logger(__file__)
class OperateLogStore(ES, metaclass=Singleton):
class OperateLogStore(BaseOperateStorage, ES):
def __init__(self, config):
properties = {
"id": {
@@ -48,7 +49,26 @@ class OperateLogStore(ES, metaclass=Singleton):
self.pre_use_check()
@staticmethod
def make_data(data):
def get_type():
return 'es'
@classmethod
def convert_diff_friendly(cls, op_log):
diff_list = []
handler = cls._get_special_handler(op_log.get('resource_type'))
before = op_log.get('before') or {}
after = op_log.get('after') or {}
keys = set(before.keys()) | set(after.keys())
for key in keys:
before_v, after_v = before.get(key), after.get(key)
diff_list.append({
'field': _(key),
'before': handler(key, before_v) if before_v else _('empty'),
'after': handler(key, after_v) if after_v else _('empty'),
})
return diff_list
def make_data(self, data):
op_id = data.get('id', str(uuid.uuid4()))
datetime_param = data.get('datetime', local_now_display())
data = {

View File

@@ -7,7 +7,6 @@ from django.utils.translation import gettext_lazy as _
from common.local import encrypted_field_set
from common.utils import get_request_ip, get_logger
from common.utils.encode import Singleton
from common.utils.timezone import as_current_tz
from jumpserver.utils import current_request
from orgs.models import Organization
@@ -21,17 +20,9 @@ from .backends import get_operate_log_storage
logger = get_logger(__name__)
class OperatorLogHandler(metaclass=Singleton):
class OperatorLogHandler(object):
CACHE_KEY = 'OPERATOR_LOG_CACHE_KEY'
def __init__(self):
self.log_client = self.get_storage_client()
@staticmethod
def get_storage_client():
client = get_operate_log_storage()
return client
@staticmethod
def _consistent_type_to_str(value1, value2):
if isinstance(value1, datetime):
@@ -164,13 +155,8 @@ class OperatorLogHandler(metaclass=Singleton):
'remote_addr': remote_addr, 'before': before, 'after': after,
}
with transaction.atomic():
if self.log_client.ping(timeout=1):
client = self.log_client
else:
logger.info('Switch default operate log storage save.')
client = get_operate_log_storage(default=True)
try:
client = get_operate_log_storage()
client.save(**data)
except Exception as e:
error_msg = 'An error occurred saving OperateLog.' \

View File

@@ -3,7 +3,7 @@
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from audits.backends.db import OperateLogStore
from audits.backends import get_operate_log_storage
from common.serializers.fields import LabeledChoiceField, ObjectRelatedField
from common.utils import reverse, i18n_trans
from common.utils.timezone import as_current_tz
@@ -77,7 +77,7 @@ class OperateLogActionDetailSerializer(serializers.ModelSerializer):
fields = ('diff',)
def to_representation(self, instance):
return {'diff': OperateLogStore.convert_diff_friendly(instance)}
return {'diff': get_operate_log_storage().convert_diff_friendly(instance)}
class OperateLogSerializer(BulkOrgResourceModelSerializer):

View File

@@ -189,7 +189,7 @@ def on_django_start_set_operate_log_monitor_models(sender, **kwargs):
'ApplyCommandTicket', 'ApplyLoginAssetTicket',
'FavoriteAsset', 'ChangeSecretRecord'
}
include_models = {'UserSession'}
include_models = set()
for i, app in enumerate(apps.get_models(), 1):
app_name = app._meta.app_label
model_name = app._meta.object_name

View File

@@ -2,6 +2,7 @@ import base64
from django.conf import settings
from django.contrib.auth import logout as auth_logout
from django.core.cache import cache
from django.http import HttpResponse
from django.shortcuts import redirect, reverse, render
from django.utils.deprecation import MiddlewareMixin
@@ -116,23 +117,43 @@ class ThirdPartyLoginMiddleware(mixins.AuthMixin):
class SessionCookieMiddleware(MiddlewareMixin):
USER_LOGIN_ENCRYPTION_KEY_PAIR = 'user_login_encryption_key_pair'
@staticmethod
def set_cookie_public_key(request, response):
def set_cookie_public_key(self, request, response):
if request.path.startswith('/api'):
return
pub_key_name = settings.SESSION_RSA_PUBLIC_KEY_NAME
public_key = request.session.get(pub_key_name)
cookie_key = request.COOKIES.get(pub_key_name)
if public_key and public_key == cookie_key:
session_public_key_name = settings.SESSION_RSA_PUBLIC_KEY_NAME
session_private_key_name = settings.SESSION_RSA_PRIVATE_KEY_NAME
session_public_key = request.session.get(session_public_key_name)
cookie_public_key = request.COOKIES.get(session_public_key_name)
if session_public_key and session_public_key == cookie_public_key:
return
pri_key_name = settings.SESSION_RSA_PRIVATE_KEY_NAME
private_key, public_key = gen_key_pair()
private_key, public_key = self.get_key_pair()
public_key_decode = base64.b64encode(public_key.encode()).decode()
request.session[pub_key_name] = public_key_decode
request.session[pri_key_name] = private_key
response.set_cookie(pub_key_name, public_key_decode)
request.session[session_public_key_name] = public_key_decode
request.session[session_private_key_name] = private_key
response.set_cookie(session_public_key_name, public_key_decode)
def get_key_pair(self):
key_pair = cache.get(self.USER_LOGIN_ENCRYPTION_KEY_PAIR)
if key_pair:
return key_pair['private_key'], key_pair['public_key']
private_key, public_key = gen_key_pair()
key_pair = {
'private_key': private_key,
'public_key': public_key
}
cache.set(self.USER_LOGIN_ENCRYPTION_KEY_PAIR, key_pair, None)
return private_key, public_key
@staticmethod
def set_cookie_session_prefix(request, response):

View File

@@ -319,20 +319,26 @@ class AuthPostCheckMixin:
@classmethod
def _check_passwd_is_too_simple(cls, user: User, password):
if user.is_superuser and password == 'admin':
if not user.is_auth_backend_model():
return
if user.check_passwd_too_simple(password):
message = _('Your password is too simple, please change it for security')
url = cls.generate_reset_password_url_with_flash_msg(user, message=message)
raise errors.PasswordTooSimple(url)
@classmethod
def _check_passwd_need_update(cls, user: User):
if user.need_update_password:
if not user.is_auth_backend_model():
return
if user.check_need_update_password():
message = _('You should to change your password before login')
url = cls.generate_reset_password_url_with_flash_msg(user, message)
raise errors.PasswordNeedUpdate(url)
@classmethod
def _check_password_require_reset_or_not(cls, user: User):
if not user.is_auth_backend_model():
return
if user.password_has_expired:
message = _('Your password has expired, please reset before logging in')
url = cls.generate_reset_password_url_with_flash_msg(user, message)

View File

@@ -8,10 +8,8 @@
<p>
<b>{% trans 'Username' %}:</b> {{ username }}<br>
<b>{% trans 'Login time' %}:</b> {{ time }}<br>
<b>{% trans 'Login city' %}:</b> {{ city }}({{ ip }})
<b>{% trans 'Login city' %}:</b> {{ city }}({{ ip }})<br>
</p>
-
<p>
{% trans 'If you suspect that the login behavior is abnormal, please modify the account password in time.' %}
</p>

View File

@@ -10,8 +10,7 @@
{% trans 'Click here reset password' %}
</a>
</p>
-
<br>
<p>
{% trans 'This link is valid for 1 hour. After it expires' %}
<a href="{{ forget_password_url }}?email={{ user.email }}">{% trans 'request new one' %}</a>

View File

@@ -5,11 +5,10 @@
{% trans 'Your password has just been successfully updated' %}
</p>
<p>
<b>{% trans 'IP' %}:</b> {{ ip_address }} <br />
<b>{% trans 'Browser' %}:</b> {{ browser }}
<b>{% trans 'IP' %}:</b> {{ ip_address }} <br/>
<b>{% trans 'Browser' %}:</b> {{ browser }} <br>
</p>
-
<p>
{% trans 'If the password update was not initiated by you, your account may have security issues' %} <br />
{% trans 'If the password update was not initiated by you, your account may have security issues' %} <br/>
{% trans 'If you have any questions, you can contact the administrator' %}
</p>

View File

@@ -5,11 +5,10 @@
{% trans 'Your public key has just been successfully updated' %}
</p>
<p>
<b>{% trans 'IP' %}:</b> {{ ip_address }} <br />
<b>{% trans 'Browser' %}:</b> {{ browser }}
<b>{% trans 'IP' %}:</b> {{ ip_address }} <br>
<b>{% trans 'Browser' %}:</b> {{ browser }}<br>
</p>
-
<p>
{% trans 'If the public key update was not initiated by you, your account may have security issues' %} <br />
{% trans 'If the public key update was not initiated by you, your account may have security issues' %} <br/>
{% trans 'If you have any questions, you can contact the administrator' %}
</p>

View File

@@ -1,4 +1,4 @@
from .utils import gen_key_pair, rsa_decrypt, rsa_encrypt
from common.utils import gen_key_pair, rsa_decrypt, rsa_encrypt
def test_rsa_encrypt_decrypt(message='test-password-$%^&*'):

View File

@@ -600,7 +600,6 @@ class Config(dict):
# API 分页
'MAX_LIMIT_PER_PAGE': 10000,
'DEFAULT_PAGE_SIZE': None,
'LIMIT_SUPER_PRIV': False,

View File

@@ -208,7 +208,7 @@ SESSION_RSA_PUBLIC_KEY_NAME = 'jms_public_key'
OPERATE_LOG_ELASTICSEARCH_CONFIG = CONFIG.OPERATE_LOG_ELASTICSEARCH_CONFIG
MAX_LIMIT_PER_PAGE = CONFIG.MAX_LIMIT_PER_PAGE
DEFAULT_PAGE_SIZE = CONFIG.DEFAULT_PAGE_SIZE
DEFAULT_PAGE_SIZE = CONFIG.MAX_LIMIT_PER_PAGE
PERM_TREE_REGEN_INTERVAL = CONFIG.PERM_TREE_REGEN_INTERVAL
# Magnus DB Port

View File

@@ -8610,7 +8610,7 @@ msgstr ""
#: xpack/plugins/cloud/models.py:100
#: xpack/plugins/cloud/serializers/task.py:167
msgid "Sync IP type"
msgid "Preferred IP type"
msgstr ""
#: xpack/plugins/cloud/models.py:103

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:607f8df8c6cea454283e0bc371db3be0c81f7cfa981a5f00c20b5be139e16aac
size 178618
oid sha256:2dd9ffcfe15b130a5b3d7b4fcfe806eaae979973e8bd29ad9a473b9215424c57
size 178725

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-08-20 14:54+0800\n"
"POT-Creation-Date: 2024-10-22 17:33+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -798,8 +798,8 @@ msgstr "カテゴリ"
#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:40
#: terminal/models/component/storage.py:57
#: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29
#: terminal/serializers/session.py:23 terminal/serializers/storage.py:271
#: terminal/serializers/storage.py:283 tickets/models/comment.py:26
#: terminal/serializers/session.py:23 terminal/serializers/storage.py:274
#: terminal/serializers/storage.py:286 tickets/models/comment.py:26
#: tickets/models/flow.py:56 tickets/models/ticket/apply_application.py:16
#: tickets/models/ticket/general.py:276 tickets/serializers/flow.py:53
#: tickets/serializers/ticket/ticket.py:19
@@ -1425,12 +1425,13 @@ msgid "Unable to connect to port {port} on {address}"
msgstr "{port} のポート {address} に接続できません"
#: assets/automations/ping_gateway/manager.py:58
#: authentication/middleware.py:93 xpack/plugins/cloud/providers/fc.py:47
#: authentication/middleware.py:94 xpack/plugins/cloud/providers/fc.py:47
msgid "Authentication failed"
msgstr "認証に失敗しました"
#: assets/automations/ping_gateway/manager.py:60
#: assets/automations/ping_gateway/manager.py:86 terminal/const.py:102
#: assets/automations/ping_gateway/manager.py:86 audits/backends/__init__.py:29
#: terminal/const.py:102
msgid "Connect failed"
msgstr "接続に失敗しました"
@@ -1978,7 +1979,8 @@ msgstr "ラベル"
msgid "New node"
msgstr "新しいノード"
#: assets/models/node.py:467 audits/backends/db.py:68 audits/backends/db.py:69
#: assets/models/node.py:467 audits/backends/db.py:64 audits/backends/db.py:65
#: audits/backends/es.py:66 audits/backends/es.py:67
msgid "empty"
msgstr "空"
@@ -2407,15 +2409,15 @@ msgstr "監査"
msgid "The text content is too long. Use Elasticsearch to store operation logs"
msgstr "文章の内容が長すぎる。Elasticsearchで操作履歴を保存する"
#: audits/backends/db.py:61
#: audits/backends/db.py:58
msgid "labels"
msgstr "ラベル"
msgstr "タグ"
#: audits/backends/db.py:62
#: audits/backends/db.py:59
msgid "operate_log_id"
msgstr "操作ログID"
#: audits/backends/db.py:94
#: audits/backends/db.py:90
msgid "Tips"
msgstr "謎々"
@@ -2498,7 +2500,7 @@ msgstr "終了"
#: audits/const.py:46 settings/serializers/terminal.py:6
#: terminal/models/applet/host.py:26 terminal/models/component/terminal.py:175
#: terminal/models/virtualapp/provider.py:14 terminal/serializers/session.py:55
#: terminal/serializers/session.py:69
#: terminal/serializers/session.py:79
msgid "Terminal"
msgstr "ターミナル"
@@ -2523,11 +2525,11 @@ msgstr "タスク"
msgid "-"
msgstr "-"
#: audits/handler.py:116
#: audits/handler.py:107
msgid "Yes"
msgstr "是"
#: audits/handler.py:116
#: audits/handler.py:107
msgid "No"
msgstr "否"
@@ -3140,7 +3142,7 @@ msgstr "電話番号を設定して有効にする"
msgid "Clear phone number to disable"
msgstr "無効にする電話番号をクリアする"
#: authentication/middleware.py:94 settings/utils/ldap.py:679
#: authentication/middleware.py:95 settings/utils/ldap.py:679
msgid "Authentication failed (before login check failed): {}"
msgstr "認証に失敗しました (ログインチェックが失敗する前): {}"
@@ -3421,7 +3423,7 @@ msgstr "アカウントにリモートログイン動作があります。注意
msgid "Login time"
msgstr "ログイン時間"
#: authentication/templates/authentication/_msg_different_city.html:16
#: authentication/templates/authentication/_msg_different_city.html:14
msgid ""
"If you suspect that the login behavior is abnormal, please modify the "
"account password in time."
@@ -3449,13 +3451,13 @@ msgstr ""
msgid "Click here reset password"
msgstr "ここをクリックしてパスワードをリセット"
#: authentication/templates/authentication/_msg_reset_password.html:16
#: users/templates/users/_msg_user_created.html:22
#: authentication/templates/authentication/_msg_reset_password.html:15
#: users/templates/users/_msg_user_created.html:20
msgid "This link is valid for 1 hour. After it expires"
msgstr "このリンクは1時間有効です。有効期限が切れた後"
#: authentication/templates/authentication/_msg_reset_password.html:17
#: users/templates/users/_msg_user_created.html:23
#: authentication/templates/authentication/_msg_reset_password.html:16
#: users/templates/users/_msg_user_created.html:21
msgid "request new one"
msgstr "新しいものを要求する"
@@ -3484,7 +3486,7 @@ msgstr "パスワードが正常に更新されました"
msgid "Browser"
msgstr "ブラウザ"
#: authentication/templates/authentication/_msg_rest_password_success.html:13
#: authentication/templates/authentication/_msg_rest_password_success.html:12
msgid ""
"If the password update was not initiated by you, your account may have "
"security issues"
@@ -3492,8 +3494,8 @@ msgstr ""
"パスワードの更新が開始されなかった場合、アカウントにセキュリティ上の問題があ"
"る可能性があります"
#: authentication/templates/authentication/_msg_rest_password_success.html:14
#: authentication/templates/authentication/_msg_rest_public_key_success.html:14
#: authentication/templates/authentication/_msg_rest_password_success.html:13
#: authentication/templates/authentication/_msg_rest_public_key_success.html:13
msgid "If you have any questions, you can contact the administrator"
msgstr "質問があれば、管理者に連絡できます"
@@ -3501,7 +3503,7 @@ msgstr "質問があれば、管理者に連絡できます"
msgid "Your public key has just been successfully updated"
msgstr "公開鍵が正常に更新されました"
#: authentication/templates/authentication/_msg_rest_public_key_success.html:13
#: authentication/templates/authentication/_msg_rest_public_key_success.html:12
msgid ""
"If the public key update was not initiated by you, your account may have "
"security issues"
@@ -3580,7 +3582,7 @@ msgid "LAN"
msgstr "ローカルエリアネットワーク"
#: authentication/views/base.py:70
#: perms/templates/perms/_msg_permed_items_expire.html:21
#: perms/templates/perms/_msg_permed_items_expire.html:20
msgid "If you have any question, please contact the administrator"
msgstr "質問があったら、管理者に連絡して下さい"
@@ -4467,7 +4469,7 @@ msgstr "Material"
msgid "Material Type"
msgstr "Material を選択してオプションを設定します。"
#: ops/models/job.py:545
#: ops/models/job.py:555
msgid "Job Execution"
msgstr "ジョブ実行"
@@ -6617,7 +6619,7 @@ msgstr "使用中のストレージを削除できません"
msgid "Command storages"
msgstr "コマンドストア"
#: terminal/api/component/storage.py:82
#: terminal/api/component/storage.py:82 xpack/plugins/cloud/manager.py:83
msgid "Invalid"
msgstr "無効"
@@ -7011,7 +7013,7 @@ msgstr "ログイン元"
msgid "Replay"
msgstr "リプレイ"
#: terminal/models/session/session.py:48 terminal/serializers/session.py:68
#: terminal/models/session/session.py:48 terminal/serializers/session.py:78
msgid "Command amount"
msgstr "コマンド量"
@@ -7396,7 +7398,8 @@ msgstr "アクセスキー"
msgid "Access key secret"
msgstr "アクセスキーシークレット"
#: terminal/serializers/storage.py:68 xpack/plugins/cloud/models.py:258
#: terminal/serializers/storage.py:68 xpack/plugins/cloud/manager.py:83
#: xpack/plugins/cloud/models.py:258
msgid "Region"
msgstr "リージョン"
@@ -7453,6 +7456,14 @@ msgstr "インデックス"
msgid "Doc type"
msgstr "Docタイプ"
#: terminal/serializers/storage.py:258
msgid "Store locally"
msgstr "ローカルに保存する"
#: terminal/serializers/storage.py:259
msgid "Do not save"
msgstr "保存しない"
#: terminal/serializers/task.py:9
msgid "Session id"
msgstr "セッション"
@@ -8216,7 +8227,7 @@ msgid "User password history"
msgstr "ユーザーパスワード履歴"
#: users/notifications.py:55
#: users/templates/users/_msg_password_expire_reminder.html:17
#: users/templates/users/_msg_password_expire_reminder.html:16
#: users/templates/users/reset_password.html:5
#: users/templates/users/reset_password.html:6
msgid "Reset password"
@@ -8477,7 +8488,7 @@ msgstr ""
msgid "Click here update password"
msgstr "ここをクリック更新パスワード"
#: users/templates/users/_msg_password_expire_reminder.html:16
#: users/templates/users/_msg_password_expire_reminder.html:15
msgid "If your password has expired, please click the link below to"
msgstr ""
"パスワードの有効期限が切れている場合は、以下のリンクをクリックしてください"
@@ -8861,11 +8872,6 @@ msgstr "そして"
msgid "Or"
msgstr "または"
#: xpack/plugins/cloud/manager.py:55 xpack/plugins/cloud/providers/gcp.py:64
#: xpack/plugins/cloud/providers/huaweicloud.py:34
msgid "Account unavailable"
msgstr "利用できないアカウント"
#: xpack/plugins/cloud/meta.py:9
msgid "Cloud center"
msgstr "クラウドセンター"
@@ -9161,6 +9167,11 @@ msgstr "華東-上海"
msgid "AP-Singapore"
msgstr "アジア太平洋-シンガポール"
#: xpack/plugins/cloud/providers/gcp.py:64
#: xpack/plugins/cloud/providers/huaweicloud.py:34
msgid "Account unavailable"
msgstr "利用できないアカウント"
#: xpack/plugins/cloud/providers/huaweicloud.py:44
msgid "CN North-Beijing1"
msgstr "華北-北京1"
@@ -9412,11 +9423,3 @@ msgstr "エンタープライズプロフェッショナル版"
#: xpack/plugins/license/models.py:86
msgid "Ultimate edition"
msgstr "エンタープライズ・フラッグシップ・エディション"
#~ msgid "Account history"
#~ msgstr "アカウント履歴"
#, fuzzy
#~| msgid "Operate log"
#~ msgid "Operate log id"
#~ msgstr "ログの操作"

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fb60a2ebb525e5aaa2d2c64fb4956fcc56f1b608a6dfb186513e743e226af261
size 146172
oid sha256:4517c6a7464c68f949912b97c8a9abcc766ca19e32267a1d1da3f0e012471c1a
size 146255

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: JumpServer 0.3.3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-08-20 14:54+0800\n"
"POT-Creation-Date: 2024-10-22 17:33+0800\n"
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
"Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: JumpServer team<ibuler@qq.com>\n"
@@ -796,8 +796,8 @@ msgstr "类别"
#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:40
#: terminal/models/component/storage.py:57
#: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29
#: terminal/serializers/session.py:23 terminal/serializers/storage.py:271
#: terminal/serializers/storage.py:283 tickets/models/comment.py:26
#: terminal/serializers/session.py:23 terminal/serializers/storage.py:274
#: terminal/serializers/storage.py:286 tickets/models/comment.py:26
#: tickets/models/flow.py:56 tickets/models/ticket/apply_application.py:16
#: tickets/models/ticket/general.py:276 tickets/serializers/flow.py:53
#: tickets/serializers/ticket/ticket.py:19
@@ -1415,12 +1415,13 @@ msgid "Unable to connect to port {port} on {address}"
msgstr "无法连接到 {port} 上的端口 {address}"
#: assets/automations/ping_gateway/manager.py:58
#: authentication/middleware.py:93 xpack/plugins/cloud/providers/fc.py:47
#: authentication/middleware.py:94 xpack/plugins/cloud/providers/fc.py:47
msgid "Authentication failed"
msgstr "认证失败"
#: assets/automations/ping_gateway/manager.py:60
#: assets/automations/ping_gateway/manager.py:86 terminal/const.py:102
#: assets/automations/ping_gateway/manager.py:86 audits/backends/__init__.py:29
#: terminal/const.py:102
msgid "Connect failed"
msgstr "连接失败"
@@ -1968,7 +1969,8 @@ msgstr "标签"
msgid "New node"
msgstr "新节点"
#: assets/models/node.py:467 audits/backends/db.py:68 audits/backends/db.py:69
#: assets/models/node.py:467 audits/backends/db.py:64 audits/backends/db.py:65
#: audits/backends/es.py:66 audits/backends/es.py:67
msgid "empty"
msgstr "空"
@@ -2388,15 +2390,15 @@ msgstr "日志审计"
msgid "The text content is too long. Use Elasticsearch to store operation logs"
msgstr "文字内容太长。请使用 Elasticsearch 存储操作日志"
#: audits/backends/db.py:61
#: audits/backends/db.py:58
msgid "labels"
msgstr "标签"
#: audits/backends/db.py:62
#: audits/backends/db.py:59
msgid "operate_log_id"
msgstr "操作日志ID"
#: audits/backends/db.py:94
#: audits/backends/db.py:90
msgid "Tips"
msgstr "提示"
@@ -2479,7 +2481,7 @@ msgstr "结束"
#: audits/const.py:46 settings/serializers/terminal.py:6
#: terminal/models/applet/host.py:26 terminal/models/component/terminal.py:175
#: terminal/models/virtualapp/provider.py:14 terminal/serializers/session.py:55
#: terminal/serializers/session.py:69
#: terminal/serializers/session.py:79
msgid "Terminal"
msgstr "终端"
@@ -2504,11 +2506,11 @@ msgstr "任务"
msgid "-"
msgstr "-"
#: audits/handler.py:116
#: audits/handler.py:107
msgid "Yes"
msgstr "是"
#: audits/handler.py:116
#: audits/handler.py:107
msgid "No"
msgstr "否"
@@ -3108,7 +3110,7 @@ msgstr "设置手机号码启用"
msgid "Clear phone number to disable"
msgstr "清空手机号码禁用"
#: authentication/middleware.py:94 settings/utils/ldap.py:679
#: authentication/middleware.py:95 settings/utils/ldap.py:679
msgid "Authentication failed (before login check failed): {}"
msgstr "认证失败 (登录前检查失败): {}"
@@ -3387,7 +3389,7 @@ msgstr "你的账号存在异地登录行为,请关注。"
msgid "Login time"
msgstr "登录日期"
#: authentication/templates/authentication/_msg_different_city.html:16
#: authentication/templates/authentication/_msg_different_city.html:14
msgid ""
"If you suspect that the login behavior is abnormal, please modify the "
"account password in time."
@@ -3411,13 +3413,13 @@ msgstr "请点击下面链接重置密码, 如果不是您申请的,请关
msgid "Click here reset password"
msgstr "点击这里重置密码"
#: authentication/templates/authentication/_msg_reset_password.html:16
#: users/templates/users/_msg_user_created.html:22
#: authentication/templates/authentication/_msg_reset_password.html:15
#: users/templates/users/_msg_user_created.html:20
msgid "This link is valid for 1 hour. After it expires"
msgstr "这个链接有效期1小时, 超过时间您可以"
#: authentication/templates/authentication/_msg_reset_password.html:17
#: users/templates/users/_msg_user_created.html:23
#: authentication/templates/authentication/_msg_reset_password.html:16
#: users/templates/users/_msg_user_created.html:21
msgid "request new one"
msgstr "重新申请"
@@ -3446,14 +3448,14 @@ msgstr "你的密码刚刚成功更新"
msgid "Browser"
msgstr "浏览器"
#: authentication/templates/authentication/_msg_rest_password_success.html:13
#: authentication/templates/authentication/_msg_rest_password_success.html:12
msgid ""
"If the password update was not initiated by you, your account may have "
"security issues"
msgstr "如果这次密码更新不是由你发起的,那么你的账号可能存在安全问题"
#: authentication/templates/authentication/_msg_rest_password_success.html:14
#: authentication/templates/authentication/_msg_rest_public_key_success.html:14
#: authentication/templates/authentication/_msg_rest_password_success.html:13
#: authentication/templates/authentication/_msg_rest_public_key_success.html:13
msgid "If you have any questions, you can contact the administrator"
msgstr "如果有疑问或需求,请联系系统管理员"
@@ -3461,7 +3463,7 @@ msgstr "如果有疑问或需求,请联系系统管理员"
msgid "Your public key has just been successfully updated"
msgstr "你的公钥刚刚成功更新"
#: authentication/templates/authentication/_msg_rest_public_key_success.html:13
#: authentication/templates/authentication/_msg_rest_public_key_success.html:12
msgid ""
"If the public key update was not initiated by you, your account may have "
"security issues"
@@ -3534,7 +3536,7 @@ msgid "LAN"
msgstr "局域网"
#: authentication/views/base.py:70
#: perms/templates/perms/_msg_permed_items_expire.html:21
#: perms/templates/perms/_msg_permed_items_expire.html:20
msgid "If you have any question, please contact the administrator"
msgstr "如果有疑问或需求,请联系系统管理员"
@@ -4408,7 +4410,7 @@ msgstr "Material"
msgid "Material Type"
msgstr "Material 类型"
#: ops/models/job.py:545
#: ops/models/job.py:555
msgid "Job Execution"
msgstr "作业执行"
@@ -6514,7 +6516,7 @@ msgstr "不允许删除正在使用的存储配置"
msgid "Command storages"
msgstr "命令存储"
#: terminal/api/component/storage.py:82
#: terminal/api/component/storage.py:82 xpack/plugins/cloud/manager.py:83
msgid "Invalid"
msgstr "无效"
@@ -6908,7 +6910,7 @@ msgstr "登录来源"
msgid "Replay"
msgstr "回放"
#: terminal/models/session/session.py:48 terminal/serializers/session.py:68
#: terminal/models/session/session.py:48 terminal/serializers/session.py:78
msgid "Command amount"
msgstr "命令数量"
@@ -7286,7 +7288,8 @@ msgstr "Access key ID(AK)"
msgid "Access key secret"
msgstr "Access key secret(SK)"
#: terminal/serializers/storage.py:68 xpack/plugins/cloud/models.py:258
#: terminal/serializers/storage.py:68 xpack/plugins/cloud/manager.py:83
#: xpack/plugins/cloud/models.py:258
msgid "Region"
msgstr "地域"
@@ -7343,6 +7346,14 @@ msgstr "索引"
msgid "Doc type"
msgstr "文档类型"
#: terminal/serializers/storage.py:258
msgid "Store locally"
msgstr "本地存储"
#: terminal/serializers/storage.py:259
msgid "Do not save"
msgstr "不保存"
#: terminal/serializers/task.py:9
msgid "Session id"
msgstr "会话 ID"
@@ -8100,7 +8111,7 @@ msgid "User password history"
msgstr "用户密码历史"
#: users/notifications.py:55
#: users/templates/users/_msg_password_expire_reminder.html:17
#: users/templates/users/_msg_password_expire_reminder.html:16
#: users/templates/users/reset_password.html:5
#: users/templates/users/reset_password.html:6
msgid "Reset password"
@@ -8355,7 +8366,7 @@ msgstr "为了您的账号安全,请点击下面的链接及时更新密码"
msgid "Click here update password"
msgstr "点击这里更新密码"
#: users/templates/users/_msg_password_expire_reminder.html:16
#: users/templates/users/_msg_password_expire_reminder.html:15
msgid "If your password has expired, please click the link below to"
msgstr "如果你的密码已过期,请点击"
@@ -8728,11 +8739,6 @@ msgstr "与"
msgid "Or"
msgstr "或"
#: xpack/plugins/cloud/manager.py:55 xpack/plugins/cloud/providers/gcp.py:64
#: xpack/plugins/cloud/providers/huaweicloud.py:34
msgid "Account unavailable"
msgstr "账号无效"
#: xpack/plugins/cloud/meta.py:9
msgid "Cloud center"
msgstr "云管中心"
@@ -8768,7 +8774,7 @@ msgstr "IP网段组"
#: xpack/plugins/cloud/models.py:100
#: xpack/plugins/cloud/serializers/task.py:167
msgid "Sync IP type"
msgstr "同步IP类型"
msgstr "同步 IP 类型"
#: xpack/plugins/cloud/models.py:103
#: xpack/plugins/cloud/serializers/task.py:185
@@ -9028,6 +9034,11 @@ msgstr "华东-上海"
msgid "AP-Singapore"
msgstr "亚太-新加坡"
#: xpack/plugins/cloud/providers/gcp.py:64
#: xpack/plugins/cloud/providers/huaweicloud.py:34
msgid "Account unavailable"
msgstr "账号无效"
#: xpack/plugins/cloud/providers/huaweicloud.py:44
msgid "CN North-Beijing1"
msgstr "华北-北京1"
@@ -9276,6 +9287,3 @@ msgstr "企业专业版"
#: xpack/plugins/license/models.py:86
msgid "Ultimate edition"
msgstr "企业旗舰版"
#~ msgid "Account history"
#~ msgstr "账号历史"

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4aaedb4c31b1d11ddf63e5d0a27958ee5d42e78e2ce255746b8134d18ffc990f
size 146283
oid sha256:7d4d2709e597e055072474f08be2f363d43df239240051024a77213ba48ecfac
size 146366

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: JumpServer 0.3.3\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-08-20 14:54+0800\n"
"POT-Creation-Date: 2024-10-22 17:33+0800\n"
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
"Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: JumpServer team<ibuler@qq.com>\n"
@@ -798,8 +798,8 @@ msgstr "類別"
#: perms/serializers/user_permission.py:27 terminal/models/applet/applet.py:40
#: terminal/models/component/storage.py:57
#: terminal/models/component/storage.py:146 terminal/serializers/applet.py:29
#: terminal/serializers/session.py:23 terminal/serializers/storage.py:271
#: terminal/serializers/storage.py:283 tickets/models/comment.py:26
#: terminal/serializers/session.py:23 terminal/serializers/storage.py:274
#: terminal/serializers/storage.py:286 tickets/models/comment.py:26
#: tickets/models/flow.py:56 tickets/models/ticket/apply_application.py:16
#: tickets/models/ticket/general.py:276 tickets/serializers/flow.py:53
#: tickets/serializers/ticket/ticket.py:19
@@ -1417,12 +1417,13 @@ msgid "Unable to connect to port {port} on {address}"
msgstr "無法連接到 {port} 上的埠 {address}"
#: assets/automations/ping_gateway/manager.py:58
#: authentication/middleware.py:93 xpack/plugins/cloud/providers/fc.py:47
#: authentication/middleware.py:94 xpack/plugins/cloud/providers/fc.py:47
msgid "Authentication failed"
msgstr "認證失敗"
#: assets/automations/ping_gateway/manager.py:60
#: assets/automations/ping_gateway/manager.py:86 terminal/const.py:102
#: assets/automations/ping_gateway/manager.py:86 audits/backends/__init__.py:29
#: terminal/const.py:102
msgid "Connect failed"
msgstr "連接失敗"
@@ -1970,7 +1971,8 @@ msgstr "標籤"
msgid "New node"
msgstr "新節點"
#: assets/models/node.py:467 audits/backends/db.py:68 audits/backends/db.py:69
#: assets/models/node.py:467 audits/backends/db.py:64 audits/backends/db.py:65
#: audits/backends/es.py:66 audits/backends/es.py:67
msgid "empty"
msgstr "空"
@@ -2390,15 +2392,15 @@ msgstr "日誌審計"
msgid "The text content is too long. Use Elasticsearch to store operation logs"
msgstr "文字內容太長。請使用 Elasticsearch 儲存操作日誌"
#: audits/backends/db.py:61
#: audits/backends/db.py:58
msgid "labels"
msgstr "標籤"
#: audits/backends/db.py:62
#: audits/backends/db.py:59
msgid "operate_log_id"
msgstr "操作日誌ID"
#: audits/backends/db.py:94
#: audits/backends/db.py:90
msgid "Tips"
msgstr "提示"
@@ -2481,7 +2483,7 @@ msgstr "結束"
#: audits/const.py:46 settings/serializers/terminal.py:6
#: terminal/models/applet/host.py:26 terminal/models/component/terminal.py:175
#: terminal/models/virtualapp/provider.py:14 terminal/serializers/session.py:55
#: terminal/serializers/session.py:69
#: terminal/serializers/session.py:79
msgid "Terminal"
msgstr "終端"
@@ -2506,11 +2508,11 @@ msgstr "任務"
msgid "-"
msgstr "-"
#: audits/handler.py:116
#: audits/handler.py:107
msgid "Yes"
msgstr "是"
#: audits/handler.py:116
#: audits/handler.py:107
msgid "No"
msgstr "否"
@@ -3110,7 +3112,7 @@ msgstr "設置手機號碼啟用"
msgid "Clear phone number to disable"
msgstr "清空手機號碼禁用"
#: authentication/middleware.py:94 settings/utils/ldap.py:679
#: authentication/middleware.py:95 settings/utils/ldap.py:679
msgid "Authentication failed (before login check failed): {}"
msgstr "認證失敗 (登錄前檢查失敗): {}"
@@ -3389,7 +3391,7 @@ msgstr "你的帳號存在異地登入行為,請關注。"
msgid "Login time"
msgstr "登錄日期"
#: authentication/templates/authentication/_msg_different_city.html:16
#: authentication/templates/authentication/_msg_different_city.html:14
msgid ""
"If you suspect that the login behavior is abnormal, please modify the "
"account password in time."
@@ -3413,13 +3415,13 @@ msgstr "請點擊下面連結重設密碼, 如果不是您申請的,請關
msgid "Click here reset password"
msgstr "點擊這裡重設密碼"
#: authentication/templates/authentication/_msg_reset_password.html:16
#: users/templates/users/_msg_user_created.html:22
#: authentication/templates/authentication/_msg_reset_password.html:15
#: users/templates/users/_msg_user_created.html:20
msgid "This link is valid for 1 hour. After it expires"
msgstr "這個連結有效期1小時, 超過時間您可以"
#: authentication/templates/authentication/_msg_reset_password.html:17
#: users/templates/users/_msg_user_created.html:23
#: authentication/templates/authentication/_msg_reset_password.html:16
#: users/templates/users/_msg_user_created.html:21
msgid "request new one"
msgstr "重新申請"
@@ -3448,14 +3450,14 @@ msgstr "你的密碼剛剛成功更新"
msgid "Browser"
msgstr "瀏覽器"
#: authentication/templates/authentication/_msg_rest_password_success.html:13
#: authentication/templates/authentication/_msg_rest_password_success.html:12
msgid ""
"If the password update was not initiated by you, your account may have "
"security issues"
msgstr "如果這次密碼更新不是由你發起的,那麼你的帳號可能存在安全問題"
#: authentication/templates/authentication/_msg_rest_password_success.html:14
#: authentication/templates/authentication/_msg_rest_public_key_success.html:14
#: authentication/templates/authentication/_msg_rest_password_success.html:13
#: authentication/templates/authentication/_msg_rest_public_key_success.html:13
msgid "If you have any questions, you can contact the administrator"
msgstr "如果有疑問或需求,請聯絡系統管理員"
@@ -3463,7 +3465,7 @@ msgstr "如果有疑問或需求,請聯絡系統管理員"
msgid "Your public key has just been successfully updated"
msgstr "你的公鑰剛剛成功更新"
#: authentication/templates/authentication/_msg_rest_public_key_success.html:13
#: authentication/templates/authentication/_msg_rest_public_key_success.html:12
msgid ""
"If the public key update was not initiated by you, your account may have "
"security issues"
@@ -3536,7 +3538,7 @@ msgid "LAN"
msgstr "區域網路"
#: authentication/views/base.py:70
#: perms/templates/perms/_msg_permed_items_expire.html:21
#: perms/templates/perms/_msg_permed_items_expire.html:20
msgid "If you have any question, please contact the administrator"
msgstr "如果有疑問或需求,請聯絡系統管理員"
@@ -4409,7 +4411,7 @@ msgstr "Material"
msgid "Material Type"
msgstr "Material 類型"
#: ops/models/job.py:545
#: ops/models/job.py:555
msgid "Job Execution"
msgstr "作業執行"
@@ -6515,7 +6517,7 @@ msgstr "不允許刪除正在使用的儲存配置"
msgid "Command storages"
msgstr "命令儲存"
#: terminal/api/component/storage.py:82
#: terminal/api/component/storage.py:82 xpack/plugins/cloud/manager.py:83
msgid "Invalid"
msgstr "無效"
@@ -6909,7 +6911,7 @@ msgstr "登錄來源"
msgid "Replay"
msgstr "重播"
#: terminal/models/session/session.py:48 terminal/serializers/session.py:68
#: terminal/models/session/session.py:48 terminal/serializers/session.py:78
msgid "Command amount"
msgstr "命令數量"
@@ -7287,7 +7289,8 @@ msgstr "Access key ID(AK)"
msgid "Access key secret"
msgstr "Access key secret(SK)"
#: terminal/serializers/storage.py:68 xpack/plugins/cloud/models.py:258
#: terminal/serializers/storage.py:68 xpack/plugins/cloud/manager.py:83
#: xpack/plugins/cloud/models.py:258
msgid "Region"
msgstr "地域"
@@ -7344,6 +7347,14 @@ msgstr "索引"
msgid "Doc type"
msgstr "文件類型"
#: terminal/serializers/storage.py:258
msgid "Store locally"
msgstr "本地儲存"
#: terminal/serializers/storage.py:259
msgid "Do not save"
msgstr "不儲存"
#: terminal/serializers/task.py:9
msgid "Session id"
msgstr "會話 ID"
@@ -8101,7 +8112,7 @@ msgid "User password history"
msgstr "用戶密碼歷史"
#: users/notifications.py:55
#: users/templates/users/_msg_password_expire_reminder.html:17
#: users/templates/users/_msg_password_expire_reminder.html:16
#: users/templates/users/reset_password.html:5
#: users/templates/users/reset_password.html:6
msgid "Reset password"
@@ -8356,7 +8367,7 @@ msgstr "為了您的帳號安全,請點擊下面的連結及時更新密碼"
msgid "Click here update password"
msgstr "點擊這裡更新密碼"
#: users/templates/users/_msg_password_expire_reminder.html:16
#: users/templates/users/_msg_password_expire_reminder.html:15
msgid "If your password has expired, please click the link below to"
msgstr "如果你的密碼已過期,請點擊"
@@ -8729,11 +8740,6 @@ msgstr "與"
msgid "Or"
msgstr "或"
#: xpack/plugins/cloud/manager.py:55 xpack/plugins/cloud/providers/gcp.py:64
#: xpack/plugins/cloud/providers/huaweicloud.py:34
msgid "Account unavailable"
msgstr "帳號無效"
#: xpack/plugins/cloud/meta.py:9
msgid "Cloud center"
msgstr "雲管中心"
@@ -8769,7 +8775,7 @@ msgstr "IP網段組"
#: xpack/plugins/cloud/models.py:100
#: xpack/plugins/cloud/serializers/task.py:167
msgid "Sync IP type"
msgstr "同步IP類型"
msgstr "同步 IP 類型"
#: xpack/plugins/cloud/models.py:103
#: xpack/plugins/cloud/serializers/task.py:185
@@ -9029,6 +9035,11 @@ msgstr "華東-上海"
msgid "AP-Singapore"
msgstr "亞太-新加坡"
#: xpack/plugins/cloud/providers/gcp.py:64
#: xpack/plugins/cloud/providers/huaweicloud.py:34
msgid "Account unavailable"
msgstr "帳號無效"
#: xpack/plugins/cloud/providers/huaweicloud.py:44
msgid "CN North-Beijing1"
msgstr "華北-北京1"
@@ -9277,6 +9288,3 @@ msgstr "企業專業版"
#: xpack/plugins/license/models.py:86
msgid "Ultimate edition"
msgstr "企業旗艦版"
#~ msgid "Account history"
#~ msgstr "帳號歷史"

View File

@@ -14,7 +14,8 @@ class SiteMessageUtil:
def send_msg(cls, subject, message, user_ids=(), group_ids=(),
sender=None, is_broadcast=False):
if not any((user_ids, group_ids, is_broadcast)):
raise ValueError('No recipient is specified')
logger.warning(f'No recipient is specified, message subject: {subject}')
return
with transaction.atomic():
site_msg = SiteMessageModel.objects.create(

View File

@@ -39,9 +39,10 @@ class AdHocRunner:
def check_module(self):
if self.module not in self.cmd_modules_choices:
return
if self.module_args and self.module_args.split()[0] in settings.SECURITY_COMMAND_BLACKLIST:
command = self.module_args
if command and set(command.split()).intersection(set(settings.SECURITY_COMMAND_BLACKLIST)):
raise CommandInBlackListException(
"Command is rejected by black list: {}".format(self.module_args.split()[0]))
"Command is rejected by black list: {}".format(self.module_args))
def set_local_connection(self):
if self.job_module in self.need_local_connection_modules_choices:

View File

@@ -478,6 +478,16 @@ class JobExecution(JMSOrgBaseModel):
for acl in acls:
if self.match_command_group(acl, asset):
break
command = self.current_job.args
if command and set(command.split()).intersection(set(settings.SECURITY_COMMAND_BLACKLIST)):
CommandExecutionAlert({
"assets": self.current_job.assets.all(),
"input": self.material,
"risk_level": RiskLevelChoices.reject,
"user": self.creator,
}).publish_async()
raise CommandInBlackListException(
"Command is rejected by black list: {}".format(self.current_job.args))
def check_danger_keywords(self):
lines = self.job.playbook.check_dangerous_keywords()

View File

@@ -15,8 +15,7 @@
{% endfor %}
</ul>
<br/>
-
<br>
<p>
{% trans 'If you have any question, please contact the administrator' %}
</p>

View File

@@ -58,6 +58,16 @@ class SessionSerializer(BulkOrgResourceModelSerializer):
'terminal_display': {'label': _('Terminal display')},
}
def get_fields(self):
fields = super().get_fields()
self.pop_fields_if_need(fields)
return fields
def pop_fields_if_need(self, fields):
request = self.context.get('request')
if request and request.method != 'GET':
fields.pop("command_amount", None)
def validate_asset(self, value):
max_length = self.Meta.model.asset.field.max_length
value = pretty_string(value, max_length=max_length)

View File

@@ -220,7 +220,6 @@ command_storage_type_serializer_classes_mapping = {
class BaseStorageSerializer(serializers.ModelSerializer):
storage_type_serializer_classes_mapping = {}
meta = MethodSerializer()
comment = serializers.SerializerMethodField()
class Meta:
model = None
@@ -253,11 +252,15 @@ class BaseStorageSerializer(serializers.ModelSerializer):
serializer = serializer_class
return serializer
@staticmethod
def get_comment(obj):
need_translate_comments = ['Store locally', 'Do not save']
comment = obj.comment
return _(comment) if comment in need_translate_comments else comment
def to_representation(self, instance):
data = super().to_representation(instance)
need_translate_comments = {
'Store locally': _('Store locally'),
'Do not save': _('Do not save')
}
comment = instance.comment
data['comment'] = need_translate_comments.get(comment, comment)
return data
def save(self, **kwargs):
instance = super().save(**kwargs)

View File

@@ -69,7 +69,7 @@ class AuthMixin:
if self.username:
self.date_password_last_updated = timezone.now()
post_user_change_password.send(self.__class__, user=self)
super().set_password(raw_password) # noqa
super().set_password(raw_password) # noqa
def set_public_key(self, public_key):
if self.can_update_ssh_key():
@@ -160,6 +160,22 @@ class AuthMixin:
return True
return False
def check_need_update_password(self):
if self.is_local and self.need_update_password:
return True
return False
@staticmethod
def check_passwd_too_simple(password):
simple_passwords = ['admin', 'ChangeMe']
if password in simple_passwords:
return True
return False
def is_auth_backend_model(self):
backend = getattr(self, 'backend', None)
return backend == settings.AUTH_BACKEND_MODEL
@staticmethod
def get_public_key_md5(key):
try:

View File

@@ -9,9 +9,8 @@
<br />
<br />
<a href="{{ update_password_url }}">{% trans 'Click here update password' %}</a>
<br />
<br/>
</p>
-
<p>
{% trans 'If your password has expired, please click the link below to' %}
<a href="{{ forget_password_url }}?email={{ email }}">{% trans 'Reset password' %}</a>

View File

@@ -15,9 +15,7 @@
{% trans 'click here to set your password' %}
</a>
</p>
-
<br>
<p>
{% trans 'This link is valid for 1 hour. After it expires' %}
<a href="{{ forget_password_url }}?email={{ user.email }}">{% trans 'request new one' %}</a>

View File

@@ -227,7 +227,7 @@ class MFABlockUtils(BlockUtilBase):
class LoginIpBlockUtil(BlockGlobalIpUtilBase):
LIMIT_KEY_TMPL = "_LOGIN_LIMIT_{}"
BLOCK_KEY_TMPL = "_LOGIN_BLOCK_{}"
BLOCK_KEY_TMPL = "_LOGIN_BLOCK_IP_{}"
def validate_emails(emails):