Merge pull request #3871 from jumpserver/lina_dev

Lina dev
This commit is contained in:
BaiJiangJie 2020-04-10 14:50:05 +08:00 committed by GitHub
commit 42c5c02709
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 370 additions and 223 deletions

View File

@ -19,7 +19,7 @@ JumpServer 采纳分布式架构,支持多机房跨区域部署,支持横向
<table> <table>
<tr> <tr>
<td rowspan="7">身份认证<br>Authentication</td> <td rowspan="8">身份认证<br>Authentication</td>
<td rowspan="5">登录认证</td> <td rowspan="5">登录认证</td>
<td>资源统一登录与认证</td> <td>资源统一登录与认证</td>
</tr> </tr>

View File

@ -154,8 +154,8 @@ class AssetUserManager:
@staticmethod @staticmethod
def create(**kwargs): def create(**kwargs):
authbook = AuthBook(**kwargs) # 使用create方法创建AuthBook对象解决并发创建问题添加锁机制
authbook.save() authbook = AuthBook.create(**kwargs)
return authbook return authbook
def __getattr__(self, item): def __getattr__(self, item):

View File

@ -1,7 +1,9 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from django.db import models from django.db import models, transaction
from django.db.models import Max
from django.core.cache import cache
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from orgs.mixins.models import OrgManager from orgs.mixins.models import OrgManager
@ -11,8 +13,10 @@ __all__ = ['AuthBook']
class AuthBookQuerySet(models.QuerySet): class AuthBookQuerySet(models.QuerySet):
def latest_version(self): def delete(self):
return self.filter(is_latest=True) if self.count() > 1:
raise PermissionError(_("Bulk delete deny"))
return super().delete()
class AuthBookManager(OrgManager): class AuthBookManager(OrgManager):
@ -33,37 +37,42 @@ class AuthBook(BaseUser):
class Meta: class Meta:
verbose_name = _('AuthBook') verbose_name = _('AuthBook')
def set_to_latest(self):
self.remove_pre_latest()
self.is_latest = True
self.save()
def get_pre_latest(self):
pre_obj = self.__class__.objects.filter(
username=self.username, asset=self.asset
).latest_version().first()
return pre_obj
def remove_pre_latest(self):
pre_obj = self.get_pre_latest()
if pre_obj:
pre_obj.is_latest = False
pre_obj.save()
def set_version(self):
pre_obj = self.get_pre_latest()
if pre_obj:
self.version = pre_obj.version + 1
else:
self.version = 1
self.save()
def get_related_assets(self): def get_related_assets(self):
return [self.asset] return [self.asset]
def generate_id_with_asset(self, asset): def generate_id_with_asset(self, asset):
return self.id return self.id
@classmethod
def get_max_version(cls, username, asset):
version_max = cls.objects.filter(username=username, asset=asset) \
.aggregate(Max('version'))
version_max = version_max['version__max'] or 0
return version_max
@classmethod
def create(cls, **kwargs):
"""
使用并发锁机制创建AuthBook对象, (主要针对并发创建 username, asset 相同的对象时)
并更新其他对象的 is_latest=False (其他对象: 与当前对象的 username, asset 相同)
同时设置自己的 is_latest=True, version=max_version + 1
"""
username = kwargs['username']
asset = kwargs['asset']
key_lock = 'KEY_LOCK_CREATE_AUTH_BOOK_{}_{}'.format(username, asset.id)
with cache.lock(key_lock):
with transaction.atomic():
cls.objects.filter(
username=username, asset=asset, is_latest=True
).update(is_latest=False)
max_version = cls.get_max_version(username, asset)
kwargs.update({
'version': max_version + 1,
'is_latest': True
})
obj = cls.objects.create(**kwargs)
return obj
@property @property
def connectivity(self): def connectivity(self):
return self.get_asset_connectivity(self.asset) return self.get_asset_connectivity(self.asset)

View File

@ -574,8 +574,6 @@ class Node(OrgModelMixin, SomeNodesMixin, TreeMixin, FamilyMixin, FullValueMixin
org = get_current_org() org = get_current_org()
if not org or not org.is_real(): if not org or not org.is_real():
Organization.default().change_to() Organization.default().change_to()
i = 0
while i < count:
nodes = list(cls.objects.all()) nodes = list(cls.objects.all())
if count > 100: if count > 100:
length = 100 length = 100
@ -584,4 +582,5 @@ class Node(OrgModelMixin, SomeNodesMixin, TreeMixin, FamilyMixin, FullValueMixin
for i in range(length): for i in range(length):
node = random.choice(nodes) node = random.choice(nodes)
node.create_child('Node {}'.format(i)) child = node.create_child('Node {}'.format(i))
print("{}. {}".format(i, child))

View File

@ -37,7 +37,6 @@ class AssetUserWriteSerializer(AuthSerializerMixin, BulkOrgResourceModelSerializ
if not validated_data.get("name") and validated_data.get("username"): if not validated_data.get("name") and validated_data.get("username"):
validated_data["name"] = validated_data["username"] validated_data["name"] = validated_data["username"]
instance = AssetUserManager.create(**validated_data) instance = AssetUserManager.create(**validated_data)
instance.set_to_latest()
return instance return instance

View File

@ -15,7 +15,6 @@ from .utils import TreeService
from .tasks import ( from .tasks import (
update_assets_hardware_info_util, update_assets_hardware_info_util,
test_asset_connectivity_util, test_asset_connectivity_util,
push_system_user_to_assets,
push_system_user_to_assets_manual, push_system_user_to_assets_manual,
push_system_user_to_assets, push_system_user_to_assets,
add_nodes_assets_to_system_users add_nodes_assets_to_system_users
@ -235,9 +234,3 @@ def on_node_update_or_created(sender, **kwargs):
Node.refresh_nodes() Node.refresh_nodes()
with tmp_to_root_org(): with tmp_to_root_org():
Node.refresh_nodes() Node.refresh_nodes()
@receiver(post_save, sender=AuthBook)
def on_authbook_created(sender, instance=None, created=True, **kwargs):
if created and instance:
instance.set_version()

View File

@ -5,6 +5,7 @@ from django.db import transaction
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from keycloak.realm import KeycloakRealm from keycloak.realm import KeycloakRealm
from keycloak.keycloak_openid import KeycloakOpenID from keycloak.keycloak_openid import KeycloakOpenID
from users.utils import construct_user_email
from .signals import post_create_or_update_openid_user from .signals import post_create_or_update_openid_user
from .decorator import ssl_verification from .decorator import ssl_verification
@ -155,13 +156,17 @@ class Client(object):
""" """
userinfo = self.get_userinfo(token=token_response['access_token']) userinfo = self.get_userinfo(token=token_response['access_token'])
with transaction.atomic(): with transaction.atomic():
name = userinfo.get('name', '')
username = userinfo.get('preferred_username', ''),
email = userinfo.get('email', '')
email = construct_user_email(username, email)
user, created = get_user_model().objects.update_or_create( user, created = get_user_model().objects.update_or_create(
username=userinfo.get('preferred_username', ''), username=username,
defaults={ defaults={
'email': userinfo.get('email', ''), 'name': name, 'email': email,
'first_name': userinfo.get('given_name', ''), 'first_name': userinfo.get('given_name', ''),
'last_name': userinfo.get('family_name', ''), 'last_name': userinfo.get('family_name', ''),
'name': userinfo.get('name', '')
} }
) )
oidt_profile = OpenIDTokenProfile( oidt_profile = OpenIDTokenProfile(

View File

@ -84,7 +84,8 @@ class SimpleMetadataWithFilters(SimpleMetadata):
def get_filters_fields(self, request, view): def get_filters_fields(self, request, view):
fields = [] fields = []
if hasattr(view, 'get_filter_fields'): if hasattr(view, 'get_filter_fields'):
fields = view.get_filter_fields(request) # fields = view.get_filter_fields(request)
fields = view.get_filter_fields()
elif hasattr(view, 'filter_fields'): elif hasattr(view, 'filter_fields'):
fields = view.filter_fields fields = view.filter_fields
return fields return fields

View File

@ -101,6 +101,15 @@ class CustomMetaDictField(serializers.DictField):
filter_value = {k: v for k, v in value.items() if k in fields_names} filter_value = {k: v for k, v in value.items() if k in fields_names}
return filter_value return filter_value
@staticmethod
def strip_value(value):
new_value = {}
for k, v in value.items():
if isinstance(v, str):
v = v.strip()
new_value[k] = v
return new_value
def get_value(self, dictionary): def get_value(self, dictionary):
""" """
反序列化时调用 反序列化时调用
@ -108,4 +117,5 @@ class CustomMetaDictField(serializers.DictField):
value = super().get_value(dictionary) value = super().get_value(dictionary)
value = self.convert_value_key(dictionary, value) value = self.convert_value_key(dictionary, value)
value = self.filter_value_key(dictionary, value) value = self.filter_value_key(dictionary, value)
value = self.strip_value(value)
return value return value

View File

@ -142,7 +142,6 @@ class Config(dict):
'AUTH_OPENID_CLIENT_SECRET': '', 'AUTH_OPENID_CLIENT_SECRET': '',
'AUTH_OPENID_IGNORE_SSL_VERIFICATION': True, 'AUTH_OPENID_IGNORE_SSL_VERIFICATION': True,
'AUTH_OPENID_SHARE_SESSION': True, 'AUTH_OPENID_SHARE_SESSION': True,
'CAS_ROOT_PROXIED_AS': '',
'AUTH_RADIUS': False, 'AUTH_RADIUS': False,
'RADIUS_SERVER': 'localhost', 'RADIUS_SERVER': 'localhost',
@ -153,6 +152,7 @@ class Config(dict):
'AUTH_CAS': False, 'AUTH_CAS': False,
'CAS_SERVER_URL': "http://host/cas/", 'CAS_SERVER_URL': "http://host/cas/",
'CAS_ROOT_PROXIED_AS': '',
'CAS_LOGOUT_COMPLETELY': True, 'CAS_LOGOUT_COMPLETELY': True,
'CAS_VERSION': 3, 'CAS_VERSION': 3,

View File

@ -7,6 +7,6 @@ __all__ = ['BASE_DIR', 'PROJECT_DIR', 'VERSION', 'CONFIG', 'DYNAMIC']
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
PROJECT_DIR = os.path.dirname(BASE_DIR) PROJECT_DIR = os.path.dirname(BASE_DIR)
VERSION = '1.5.7' VERSION = '1.5.8'
CONFIG = ConfigManager.load_user_config() CONFIG = ConfigManager.load_user_config()
DYNAMIC = ConfigManager.get_dynamic_config(CONFIG) DYNAMIC = ConfigManager.get_dynamic_config(CONFIG)

View File

@ -232,7 +232,8 @@ FILE_UPLOAD_DIRECTORY_PERMISSIONS = 0o755
# Cache use redis # Cache use redis
CACHES = { CACHES = {
'default': { 'default': {
'BACKEND': 'redis_cache.RedisCache', # 'BACKEND': 'redis_cache.RedisCache',
'BACKEND': 'redis_lock.django_cache.RedisCache',
'LOCATION': 'redis://:%(password)s@%(host)s:%(port)s/%(db)s' % { 'LOCATION': 'redis://:%(password)s@%(host)s:%(port)s/%(db)s' % {
'password': CONFIG.REDIS_PASSWORD, 'password': CONFIG.REDIS_PASSWORD,
'host': CONFIG.REDIS_HOST, 'host': CONFIG.REDIS_HOST,

View File

@ -24,7 +24,8 @@ class MonthLoginMetricMixin:
@lazyproperty @lazyproperty
def session_month_dates(self): def session_month_dates(self):
return self.session_month.dates('date_start', 'day') dates = self.session_month.dates('date_start', 'day')
return dates
def get_month_day_metrics(self): def get_month_day_metrics(self):
month_str = [ month_str = [
@ -57,12 +58,22 @@ class MonthLoginMetricMixin:
def asset_disabled_total(self): def asset_disabled_total(self):
return Asset.objects.filter(is_active=False).count() return Asset.objects.filter(is_active=False).count()
@staticmethod
def get_date_start_2_end(d):
time_min = timezone.datetime.min.time()
time_max = timezone.datetime.max.time()
tz = timezone.get_current_timezone()
ds = timezone.datetime.combine(d, time_min).replace(tzinfo=tz)
de = timezone.datetime.combine(d, time_max).replace(tzinfo=tz)
return ds, de
def get_date_login_count(self, date): def get_date_login_count(self, date):
tp = "LOGIN" tp = "LOGIN"
count = self.__get_data_from_cache(date, tp) count = self.__get_data_from_cache(date, tp)
if count is not None: if count is not None:
return count return count
count = Session.objects.filter(date_start__date=date).count() ds, de = self.get_date_start_2_end(date)
count = Session.objects.filter(date_start__range=(ds, de)).count()
self.__set_data_to_cache(date, tp, count) self.__set_data_to_cache(date, tp, count)
return count return count
@ -80,7 +91,8 @@ class MonthLoginMetricMixin:
count = self.__get_data_from_cache(date, tp) count = self.__get_data_from_cache(date, tp)
if count is not None: if count is not None:
return count return count
count = Session.objects.filter(date_start__date=date)\ ds, de = self.get_date_start_2_end(date)
count = Session.objects.filter(date_start__range=(ds, de))\
.values('user').distinct().count() .values('user').distinct().count()
self.__set_data_to_cache(date, tp, count) self.__set_data_to_cache(date, tp, count)
return count return count
@ -97,7 +109,8 @@ class MonthLoginMetricMixin:
count = self.__get_data_from_cache(date, tp) count = self.__get_data_from_cache(date, tp)
if count is not None: if count is not None:
return count return count
count = Session.objects.filter(date_start__date=date) \ ds, de = self.get_date_start_2_end(date)
count = Session.objects.filter(date_start__range=(ds, de)) \
.values('asset').distinct().count() .values('asset').distinct().count()
self.__set_data_to_cache(date, tp, count) self.__set_data_to_cache(date, tp, count)
return count return count

Binary file not shown.

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: JumpServer 0.3.3\n" "Project-Id-Version: JumpServer 0.3.3\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-03-18 17:58+0800\n" "POT-Creation-Date: 2020-04-09 23:31+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: ibuler <ibuler@qq.com>\n" "Last-Translator: ibuler <ibuler@qq.com>\n"
"Language-Team: JumpServer team<ibuler@qq.com>\n" "Language-Team: JumpServer team<ibuler@qq.com>\n"
@ -26,9 +26,9 @@ msgstr "自定义"
#: applications/templates/applications/remote_app_list.html:27 #: applications/templates/applications/remote_app_list.html:27
#: applications/templates/applications/user_remote_app_list.html:18 #: applications/templates/applications/user_remote_app_list.html:18
#: assets/forms/domain.py:15 assets/forms/label.py:13 #: assets/forms/domain.py:15 assets/forms/label.py:13
#: assets/models/asset.py:353 assets/models/authbook.py:23 #: assets/models/asset.py:353 assets/models/authbook.py:27
#: assets/models/gathered_user.py:14 assets/serializers/admin_user.py:32 #: assets/models/gathered_user.py:14 assets/serializers/admin_user.py:32
#: assets/serializers/asset_user.py:48 assets/serializers/asset_user.py:85 #: assets/serializers/asset_user.py:47 assets/serializers/asset_user.py:84
#: assets/serializers/system_user.py:44 assets/serializers/system_user.py:176 #: assets/serializers/system_user.py:44 assets/serializers/system_user.py:176
#: assets/templates/assets/admin_user_list.html:23 #: assets/templates/assets/admin_user_list.html:23
#: assets/templates/assets/asset_list.html:170 #: assets/templates/assets/asset_list.html:170
@ -53,12 +53,13 @@ msgstr "自定义"
#: users/templates/users/user_asset_permission.html:70 #: users/templates/users/user_asset_permission.html:70
#: users/templates/users/user_granted_remote_app.html:36 #: users/templates/users/user_granted_remote_app.html:36
#: xpack/plugins/change_auth_plan/forms.py:74 #: xpack/plugins/change_auth_plan/forms.py:74
#: xpack/plugins/change_auth_plan/models.py:267 #: xpack/plugins/change_auth_plan/models.py:265
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:40 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:40
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:54 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:54
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:13 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:13
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:14 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:14
#: xpack/plugins/cloud/models.py:266 #: xpack/plugins/cloud/models.py:269
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:37
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:47 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:47
#: xpack/plugins/orgs/templates/orgs/org_list.html:17 #: xpack/plugins/orgs/templates/orgs/org_list.html:17
#: xpack/plugins/vault/forms.py:13 xpack/plugins/vault/forms.py:15 #: xpack/plugins/vault/forms.py:13 xpack/plugins/vault/forms.py:15
@ -142,8 +143,8 @@ msgstr "运行参数"
#: perms/templates/perms/remote_app_permission_user.html:49 #: perms/templates/perms/remote_app_permission_user.html:49
#: settings/models.py:26 #: settings/models.py:26
#: settings/templates/settings/_ldap_list_users_modal.html:32 #: settings/templates/settings/_ldap_list_users_modal.html:32
#: terminal/models.py:26 terminal/models.py:334 terminal/models.py:366 #: terminal/models.py:26 terminal/models.py:341 terminal/models.py:373
#: terminal/models.py:403 terminal/templates/terminal/base_storage_list.html:31 #: terminal/models.py:410 terminal/templates/terminal/base_storage_list.html:31
#: terminal/templates/terminal/terminal_detail.html:43 #: terminal/templates/terminal/terminal_detail.html:43
#: terminal/templates/terminal/terminal_list.html:30 users/forms/profile.py:20 #: terminal/templates/terminal/terminal_list.html:30 users/forms/profile.py:20
#: users/models/group.py:15 users/models/user.py:440 #: users/models/group.py:15 users/models/user.py:440
@ -182,7 +183,7 @@ msgstr "名称"
#: assets/templates/assets/cmd_filter_rule_list.html:53 #: assets/templates/assets/cmd_filter_rule_list.html:53
#: audits/templates/audits/login_log_list.html:58 #: audits/templates/audits/login_log_list.html:58
#: perms/templates/perms/remote_app_permission_remote_app.html:50 #: perms/templates/perms/remote_app_permission_remote_app.html:50
#: terminal/models.py:368 terminal/models.py:405 #: terminal/models.py:375 terminal/models.py:412
#: terminal/templates/terminal/base_storage_list.html:32 #: terminal/templates/terminal/base_storage_list.html:32
#: tickets/models/ticket.py:43 tickets/templates/tickets/ticket_detail.html:33 #: tickets/models/ticket.py:43 tickets/templates/tickets/ticket_detail.html:33
#: tickets/templates/tickets/ticket_list.html:35 #: tickets/templates/tickets/ticket_list.html:35
@ -247,8 +248,8 @@ msgstr "数据库"
#: perms/templates/perms/asset_permission_detail.html:97 #: perms/templates/perms/asset_permission_detail.html:97
#: perms/templates/perms/database_app_permission_detail.html:93 #: perms/templates/perms/database_app_permission_detail.html:93
#: perms/templates/perms/remote_app_permission_detail.html:89 #: perms/templates/perms/remote_app_permission_detail.html:89
#: settings/models.py:31 terminal/models.py:36 terminal/models.py:373 #: settings/models.py:31 terminal/models.py:36 terminal/models.py:380
#: terminal/models.py:410 terminal/templates/terminal/base_storage_list.html:33 #: terminal/models.py:417 terminal/templates/terminal/base_storage_list.html:33
#: terminal/templates/terminal/terminal_detail.html:63 #: terminal/templates/terminal/terminal_detail.html:63
#: tickets/templates/tickets/ticket_detail.html:104 users/models/group.py:16 #: tickets/templates/tickets/ticket_detail.html:104 users/models/group.py:16
#: users/models/user.py:473 users/templates/users/user_detail.html:115 #: users/models/user.py:473 users/templates/users/user_detail.html:115
@ -257,13 +258,13 @@ msgstr "数据库"
#: users/templates/users/user_group_detail.html:62 #: users/templates/users/user_group_detail.html:62
#: users/templates/users/user_group_list.html:16 #: users/templates/users/user_group_list.html:16
#: users/templates/users/user_profile.html:138 #: users/templates/users/user_profile.html:138
#: xpack/plugins/change_auth_plan/models.py:77 #: xpack/plugins/change_auth_plan/models.py:75
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:115 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:115
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:19 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:19
#: xpack/plugins/cloud/models.py:53 xpack/plugins/cloud/models.py:136 #: xpack/plugins/cloud/models.py:53 xpack/plugins/cloud/models.py:139
#: xpack/plugins/cloud/templates/cloud/account_detail.html:67 #: xpack/plugins/cloud/templates/cloud/account_detail.html:67
#: xpack/plugins/cloud/templates/cloud/account_list.html:15 #: xpack/plugins/cloud/templates/cloud/account_list.html:15
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:102 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:128
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:18 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:18
#: xpack/plugins/gathered_user/models.py:26 #: xpack/plugins/gathered_user/models.py:26
#: xpack/plugins/orgs/templates/orgs/org_detail.html:59 #: xpack/plugins/orgs/templates/orgs/org_detail.html:59
@ -321,9 +322,9 @@ msgstr "参数"
#: perms/templates/perms/remote_app_permission_detail.html:85 #: perms/templates/perms/remote_app_permission_detail.html:85
#: users/models/user.py:481 users/serializers/group.py:32 #: users/models/user.py:481 users/serializers/group.py:32
#: users/templates/users/user_detail.html:97 #: users/templates/users/user_detail.html:97
#: xpack/plugins/change_auth_plan/models.py:81 #: xpack/plugins/change_auth_plan/models.py:79
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:111 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:111
#: xpack/plugins/cloud/models.py:56 xpack/plugins/cloud/models.py:142 #: xpack/plugins/cloud/models.py:56 xpack/plugins/cloud/models.py:145
#: xpack/plugins/gathered_user/models.py:30 #: xpack/plugins/gathered_user/models.py:30
msgid "Created by" msgid "Created by"
msgstr "创建者" msgstr "创建者"
@ -350,9 +351,9 @@ msgstr "创建者"
#: tickets/templates/tickets/ticket_detail.html:52 users/models/group.py:18 #: tickets/templates/tickets/ticket_detail.html:52 users/models/group.py:18
#: users/templates/users/user_group_detail.html:58 #: users/templates/users/user_group_detail.html:58
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:103 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:103
#: xpack/plugins/cloud/models.py:59 xpack/plugins/cloud/models.py:145 #: xpack/plugins/cloud/models.py:59 xpack/plugins/cloud/models.py:148
#: xpack/plugins/cloud/templates/cloud/account_detail.html:63 #: xpack/plugins/cloud/templates/cloud/account_detail.html:63
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:98 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:108
#: xpack/plugins/orgs/templates/orgs/org_detail.html:55 #: xpack/plugins/orgs/templates/orgs/org_detail.html:55
msgid "Date created" msgid "Date created"
msgstr "创建日期" msgstr "创建日期"
@ -405,7 +406,7 @@ msgstr "远程应用"
#: users/templates/users/user_pubkey_update.html:80 #: users/templates/users/user_pubkey_update.html:80
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:65 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:65
#: xpack/plugins/cloud/templates/cloud/account_create_update.html:29 #: xpack/plugins/cloud/templates/cloud/account_create_update.html:29
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:49 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:52
#: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:40 #: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:40
#: xpack/plugins/interface/templates/interface/interface.html:72 #: xpack/plugins/interface/templates/interface/interface.html:72
#: xpack/plugins/orgs/templates/orgs/org_create_update.html:29 #: xpack/plugins/orgs/templates/orgs/org_create_update.html:29
@ -739,7 +740,7 @@ msgstr "最新版本的不能被删除"
#: assets/templates/assets/asset_detail.html:194 #: assets/templates/assets/asset_detail.html:194
#: assets/templates/assets/system_user_assets.html:118 #: assets/templates/assets/system_user_assets.html:118
#: perms/models/asset_permission.py:81 #: perms/models/asset_permission.py:81
#: xpack/plugins/change_auth_plan/models.py:56 #: xpack/plugins/change_auth_plan/models.py:54
#: xpack/plugins/gathered_user/models.py:24 #: xpack/plugins/gathered_user/models.py:24
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:17 #: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:17
msgid "Nodes" msgid "Nodes"
@ -857,8 +858,8 @@ msgstr "SSH网关支持代理SSH,RDP和VNC"
#: users/templates/users/user_list.html:15 #: users/templates/users/user_list.html:15
#: users/templates/users/user_profile.html:47 #: users/templates/users/user_profile.html:47
#: xpack/plugins/change_auth_plan/forms.py:59 #: xpack/plugins/change_auth_plan/forms.py:59
#: xpack/plugins/change_auth_plan/models.py:47 #: xpack/plugins/change_auth_plan/models.py:45
#: xpack/plugins/change_auth_plan/models.py:263 #: xpack/plugins/change_auth_plan/models.py:261
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:63 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:63
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:53 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:53
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:12 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:12
@ -871,6 +872,7 @@ msgstr "用户名"
#: ops/templates/ops/task_detail.html:95 #: ops/templates/ops/task_detail.html:95
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:82 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:82
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:72 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:72
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:82
msgid "Yes" msgid "Yes"
msgstr "是" msgstr "是"
@ -878,6 +880,7 @@ msgstr "是"
#: ops/templates/ops/task_detail.html:97 #: ops/templates/ops/task_detail.html:97
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:84 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:84
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:74 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:74
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:84
msgid "No" msgid "No"
msgstr "否" msgstr "否"
@ -899,7 +902,7 @@ msgid "Password or private key passphrase"
msgstr "密码或密钥密码" msgstr "密码或密钥密码"
#: assets/forms/user.py:26 assets/models/base.py:234 #: assets/forms/user.py:26 assets/models/base.py:234
#: assets/serializers/asset_user.py:72 #: assets/serializers/asset_user.py:71
#: assets/templates/assets/_asset_user_auth_update_modal.html:21 #: assets/templates/assets/_asset_user_auth_update_modal.html:21
#: assets/templates/assets/_asset_user_auth_view_modal.html:27 #: assets/templates/assets/_asset_user_auth_view_modal.html:27
#: authentication/forms.py:12 #: authentication/forms.py:12
@ -914,13 +917,13 @@ msgstr "密码或密钥密码"
#: users/templates/users/user_profile_update.html:41 #: users/templates/users/user_profile_update.html:41
#: users/templates/users/user_pubkey_update.html:41 #: users/templates/users/user_pubkey_update.html:41
#: users/templates/users/user_update.html:20 #: users/templates/users/user_update.html:20
#: xpack/plugins/change_auth_plan/models.py:68 #: xpack/plugins/change_auth_plan/models.py:66
#: xpack/plugins/change_auth_plan/models.py:183 #: xpack/plugins/change_auth_plan/models.py:181
#: xpack/plugins/change_auth_plan/models.py:270 #: xpack/plugins/change_auth_plan/models.py:268
msgid "Password" msgid "Password"
msgstr "密码" msgstr "密码"
#: assets/forms/user.py:29 assets/serializers/asset_user.py:80 #: assets/forms/user.py:29 assets/serializers/asset_user.py:79
#: assets/templates/assets/_asset_user_auth_update_modal.html:27 #: assets/templates/assets/_asset_user_auth_update_modal.html:27
#: users/models/user.py:467 #: users/models/user.py:467
msgid "Private key" msgid "Private key"
@ -993,7 +996,7 @@ msgid "Internal"
msgstr "内部的" msgstr "内部的"
#: assets/models/asset.py:187 assets/models/domain.py:49 #: assets/models/asset.py:187 assets/models/domain.py:49
#: assets/serializers/asset_user.py:47 #: assets/serializers/asset_user.py:46
#: assets/templates/assets/_asset_list_modal.html:47 #: assets/templates/assets/_asset_list_modal.html:47
#: assets/templates/assets/_asset_user_list.html:20 #: assets/templates/assets/_asset_user_list.html:20
#: assets/templates/assets/asset_detail.html:60 #: assets/templates/assets/asset_detail.html:60
@ -1009,7 +1012,7 @@ msgstr "内部的"
msgid "IP" msgid "IP"
msgstr "IP" msgstr "IP"
#: assets/models/asset.py:188 assets/serializers/asset_user.py:46 #: assets/models/asset.py:188 assets/serializers/asset_user.py:45
#: assets/serializers/gathered_user.py:20 #: assets/serializers/gathered_user.py:20
#: assets/templates/assets/_asset_list_modal.html:46 #: assets/templates/assets/_asset_list_modal.html:46
#: assets/templates/assets/_asset_user_auth_update_modal.html:9 #: assets/templates/assets/_asset_user_auth_update_modal.html:9
@ -1120,11 +1123,15 @@ msgstr "主机名原始"
msgid "Labels" msgid "Labels"
msgstr "标签管理" msgstr "标签管理"
#: assets/models/authbook.py:24 ops/templates/ops/task_detail.html:70 #: assets/models/authbook.py:18
msgid "Bulk delete deny"
msgstr "拒绝批量删除"
#: assets/models/authbook.py:28 ops/templates/ops/task_detail.html:70
msgid "Latest version" msgid "Latest version"
msgstr "最新版本" msgstr "最新版本"
#: assets/models/authbook.py:25 #: assets/models/authbook.py:29
#: assets/templates/assets/_asset_user_list.html:22 #: assets/templates/assets/_asset_user_list.html:22
#: ops/templates/ops/adhoc_history.html:56 #: ops/templates/ops/adhoc_history.html:56
#: ops/templates/ops/adhoc_history_detail.html:55 #: ops/templates/ops/adhoc_history_detail.html:55
@ -1132,19 +1139,19 @@ msgstr "最新版本"
msgid "Version" msgid "Version"
msgstr "版本" msgstr "版本"
#: assets/models/authbook.py:34 #: assets/models/authbook.py:38
msgid "AuthBook" msgid "AuthBook"
msgstr "" msgstr ""
#: assets/models/base.py:235 xpack/plugins/change_auth_plan/models.py:72 #: assets/models/base.py:235 xpack/plugins/change_auth_plan/models.py:70
#: xpack/plugins/change_auth_plan/models.py:190 #: xpack/plugins/change_auth_plan/models.py:188
#: xpack/plugins/change_auth_plan/models.py:277 #: xpack/plugins/change_auth_plan/models.py:275
msgid "SSH private key" msgid "SSH private key"
msgstr "ssh密钥" msgstr "ssh密钥"
#: assets/models/base.py:236 xpack/plugins/change_auth_plan/models.py:75 #: assets/models/base.py:236 xpack/plugins/change_auth_plan/models.py:73
#: xpack/plugins/change_auth_plan/models.py:186 #: xpack/plugins/change_auth_plan/models.py:184
#: xpack/plugins/change_auth_plan/models.py:273 #: xpack/plugins/change_auth_plan/models.py:271
msgid "SSH public key" msgid "SSH public key"
msgstr "ssh公钥" msgstr "ssh公钥"
@ -1190,7 +1197,7 @@ msgid "Default"
msgstr "默认" msgstr "默认"
#: assets/models/cluster.py:36 assets/models/label.py:14 #: assets/models/cluster.py:36 assets/models/label.py:14
#: users/models/user.py:595 #: users/models/user.py:600
msgid "System" msgid "System"
msgstr "系统" msgstr "系统"
@ -1323,7 +1330,7 @@ msgstr "默认资产组"
#: tickets/models/ticket.py:128 tickets/templates/tickets/ticket_detail.html:32 #: tickets/models/ticket.py:128 tickets/templates/tickets/ticket_detail.html:32
#: tickets/templates/tickets/ticket_list.html:34 #: tickets/templates/tickets/ticket_list.html:34
#: tickets/templates/tickets/ticket_list.html:103 users/forms/group.py:15 #: tickets/templates/tickets/ticket_list.html:103 users/forms/group.py:15
#: users/models/user.py:143 users/models/user.py:159 users/models/user.py:583 #: users/models/user.py:143 users/models/user.py:159 users/models/user.py:588
#: users/serializers/group.py:20 #: users/serializers/group.py:20
#: users/templates/users/user_asset_permission.html:38 #: users/templates/users/user_asset_permission.html:38
#: users/templates/users/user_asset_permission.html:64 #: users/templates/users/user_asset_permission.html:64
@ -1396,7 +1403,7 @@ msgstr "手动登录"
#: assets/views/platform.py:58 assets/views/platform.py:74 #: assets/views/platform.py:58 assets/views/platform.py:74
#: assets/views/system_user.py:30 assets/views/system_user.py:47 #: assets/views/system_user.py:30 assets/views/system_user.py:47
#: assets/views/system_user.py:64 assets/views/system_user.py:80 #: assets/views/system_user.py:64 assets/views/system_user.py:80
#: templates/_nav.html:39 xpack/plugins/change_auth_plan/models.py:52 #: templates/_nav.html:39 xpack/plugins/change_auth_plan/models.py:50
msgid "Assets" msgid "Assets"
msgstr "资产管理" msgstr "资产管理"
@ -1512,7 +1519,7 @@ msgstr "组织名称"
msgid "Connectivity" msgid "Connectivity"
msgstr "连接" msgstr "连接"
#: assets/serializers/asset_user.py:45 #: assets/serializers/asset_user.py:44
#: assets/templates/assets/_node_detail_modal.html:18 #: assets/templates/assets/_node_detail_modal.html:18
#: audits/templates/audits/login_log_list.html:56 #: audits/templates/audits/login_log_list.html:56
#: authentication/templates/authentication/_access_key_modal.html:30 #: authentication/templates/authentication/_access_key_modal.html:30
@ -1525,11 +1532,11 @@ msgstr "连接"
msgid "ID" msgid "ID"
msgstr "ID" msgstr "ID"
#: assets/serializers/asset_user.py:49 #: assets/serializers/asset_user.py:48
msgid "Backend" msgid "Backend"
msgstr "后端" msgstr "后端"
#: assets/serializers/asset_user.py:76 users/forms/profile.py:148 #: assets/serializers/asset_user.py:75 users/forms/profile.py:148
#: users/models/user.py:470 users/templates/users/first_login.html:42 #: users/models/user.py:470 users/templates/users/first_login.html:42
#: users/templates/users/user_password_update.html:49 #: users/templates/users/user_password_update.html:49
#: users/templates/users/user_profile.html:69 #: users/templates/users/user_profile.html:69
@ -1724,7 +1731,7 @@ msgstr "资产列表"
#: ops/templates/ops/command_execution_create.html:112 #: ops/templates/ops/command_execution_create.html:112
#: settings/templates/settings/_ldap_list_users_modal.html:41 #: settings/templates/settings/_ldap_list_users_modal.html:41
#: users/templates/users/_granted_assets.html:7 #: users/templates/users/_granted_assets.html:7
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:62 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:65
msgid "Loading" msgid "Loading"
msgstr "加载中" msgstr "加载中"
@ -1884,7 +1891,7 @@ msgstr "自动生成密钥"
#: perms/templates/perms/remote_app_permission_create_update.html:51 #: perms/templates/perms/remote_app_permission_create_update.html:51
#: terminal/templates/terminal/terminal_update.html:38 #: terminal/templates/terminal/terminal_update.html:38
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:61 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:61
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:44 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:47
#: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:35 #: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:35
msgid "Other" msgid "Other"
msgstr "其它" msgstr "其它"
@ -1953,7 +1960,7 @@ msgstr "选择节点"
#: users/templates/users/user_list.html:184 #: users/templates/users/user_list.html:184
#: users/templates/users/user_password_verify.html:20 #: users/templates/users/user_password_verify.html:20
#: xpack/plugins/cloud/templates/cloud/account_create_update.html:30 #: xpack/plugins/cloud/templates/cloud/account_create_update.html:30
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:50 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:53
#: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:41 #: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:41
#: xpack/plugins/interface/templates/interface/interface.html:103 #: xpack/plugins/interface/templates/interface/interface.html:103
#: xpack/plugins/orgs/templates/orgs/org_create_update.html:30 #: xpack/plugins/orgs/templates/orgs/org_create_update.html:30
@ -1993,7 +2000,7 @@ msgstr "资产用户"
#: users/templates/users/user_detail.html:126 #: users/templates/users/user_detail.html:126
#: users/templates/users/user_profile.html:150 #: users/templates/users/user_profile.html:150
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:126 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:126
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:129 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:139
#: xpack/plugins/license/templates/license/license_detail.html:80 #: xpack/plugins/license/templates/license/license_detail.html:80
msgid "Quick modify" msgid "Quick modify"
msgstr "快速修改" msgstr "快速修改"
@ -2526,7 +2533,7 @@ msgstr "启用"
msgid "-" msgid "-"
msgstr "" msgstr ""
#: audits/models.py:78 xpack/plugins/cloud/models.py:201 #: audits/models.py:78 xpack/plugins/cloud/models.py:204
msgid "Failed" msgid "Failed"
msgstr "失败" msgstr "失败"
@ -2557,9 +2564,9 @@ msgid "MFA"
msgstr "多因子认证" msgstr "多因子认证"
#: audits/models.py:87 audits/templates/audits/login_log_list.html:63 #: audits/models.py:87 audits/templates/audits/login_log_list.html:63
#: xpack/plugins/change_auth_plan/models.py:287 #: xpack/plugins/change_auth_plan/models.py:286
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:15 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:15
#: xpack/plugins/cloud/models.py:214 #: xpack/plugins/cloud/models.py:217
msgid "Reason" msgid "Reason"
msgstr "原因" msgstr "原因"
@ -2567,7 +2574,7 @@ msgstr "原因"
#: tickets/templates/tickets/ticket_detail.html:34 #: tickets/templates/tickets/ticket_detail.html:34
#: tickets/templates/tickets/ticket_list.html:36 #: tickets/templates/tickets/ticket_list.html:36
#: tickets/templates/tickets/ticket_list.html:104 #: tickets/templates/tickets/ticket_list.html:104
#: xpack/plugins/cloud/models.py:211 xpack/plugins/cloud/models.py:269 #: xpack/plugins/cloud/models.py:214 xpack/plugins/cloud/models.py:272
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:50 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:50
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:48 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:48
msgid "Status" msgid "Status"
@ -2587,8 +2594,8 @@ msgstr "登录日期"
#: perms/templates/perms/remote_app_permission_detail.html:73 #: perms/templates/perms/remote_app_permission_detail.html:73
#: terminal/models.py:199 terminal/templates/terminal/session_detail.html:72 #: terminal/models.py:199 terminal/templates/terminal/session_detail.html:72
#: terminal/templates/terminal/session_list.html:32 #: terminal/templates/terminal/session_list.html:32
#: xpack/plugins/change_auth_plan/models.py:169 #: xpack/plugins/change_auth_plan/models.py:167
#: xpack/plugins/change_auth_plan/models.py:291 #: xpack/plugins/change_auth_plan/models.py:290
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:59 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:59
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:17 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:17
#: xpack/plugins/gathered_user/models.py:76 #: xpack/plugins/gathered_user/models.py:76
@ -3003,7 +3010,7 @@ msgstr "字段必须唯一"
msgid "<h1>Flow service unavailable, check it</h1>" msgid "<h1>Flow service unavailable, check it</h1>"
msgstr "" msgstr ""
#: jumpserver/views/index.py:244 templates/_nav.html:7 #: jumpserver/views/index.py:257 templates/_nav.html:7
msgid "Dashboard" msgid "Dashboard"
msgstr "仪表盘" msgstr "仪表盘"
@ -3040,13 +3047,13 @@ msgstr "没有该主机 {} 权限"
#: ops/mixin.py:29 ops/mixin.py:92 ops/mixin.py:162 #: ops/mixin.py:29 ops/mixin.py:92 ops/mixin.py:162
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:98 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:98
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:88 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:98
msgid "Cycle perform" msgid "Cycle perform"
msgstr "周期执行" msgstr "周期执行"
#: ops/mixin.py:33 ops/mixin.py:90 ops/mixin.py:111 ops/mixin.py:150 #: ops/mixin.py:33 ops/mixin.py:90 ops/mixin.py:111 ops/mixin.py:150
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:90 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:90
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:80 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:90
msgid "Regularly perform" msgid "Regularly perform"
msgstr "定期执行" msgstr "定期执行"
@ -3054,8 +3061,8 @@ msgstr "定期执行"
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:54 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:54
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:79 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:79
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:17 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:17
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:37 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:40
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:69 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:79
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:16 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:16
#: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:28 #: xpack/plugins/gathered_user/templates/gathered_user/task_create_update.html:28
msgid "Periodic perform" msgid "Periodic perform"
@ -3120,63 +3127,63 @@ msgstr "Become"
msgid "Create by" msgid "Create by"
msgstr "创建者" msgstr "创建者"
#: ops/models/adhoc.py:232 #: ops/models/adhoc.py:233
msgid "Task display" msgid "Task display"
msgstr "任务展示" msgstr "任务展示"
#: ops/models/adhoc.py:233 #: ops/models/adhoc.py:234
msgid "Host amount" msgid "Host amount"
msgstr "主机数量" msgstr "主机数量"
#: ops/models/adhoc.py:235 #: ops/models/adhoc.py:236
msgid "Start time" msgid "Start time"
msgstr "开始时间" msgstr "开始时间"
#: ops/models/adhoc.py:236 #: ops/models/adhoc.py:237
msgid "End time" msgid "End time"
msgstr "完成时间" msgstr "完成时间"
#: ops/models/adhoc.py:237 ops/templates/ops/adhoc_history.html:55 #: ops/models/adhoc.py:238 ops/templates/ops/adhoc_history.html:55
#: ops/templates/ops/task_history.html:61 ops/templates/ops/task_list.html:16 #: ops/templates/ops/task_history.html:61 ops/templates/ops/task_list.html:16
#: xpack/plugins/change_auth_plan/models.py:172 #: xpack/plugins/change_auth_plan/models.py:170
#: xpack/plugins/change_auth_plan/models.py:294 #: xpack/plugins/change_auth_plan/models.py:293
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:58 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:58
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:16 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_subtask_list.html:16
#: xpack/plugins/gathered_user/models.py:79 #: xpack/plugins/gathered_user/models.py:79
msgid "Time" msgid "Time"
msgstr "时间" msgstr "时间"
#: ops/models/adhoc.py:238 ops/templates/ops/adhoc_detail.html:104 #: ops/models/adhoc.py:239 ops/templates/ops/adhoc_detail.html:104
#: ops/templates/ops/adhoc_history.html:53 #: ops/templates/ops/adhoc_history.html:53
#: ops/templates/ops/adhoc_history_detail.html:67 #: ops/templates/ops/adhoc_history_detail.html:67
#: ops/templates/ops/task_detail.html:82 ops/templates/ops/task_history.html:59 #: ops/templates/ops/task_detail.html:82 ops/templates/ops/task_history.html:59
msgid "Is finished" msgid "Is finished"
msgstr "是否完成" msgstr "是否完成"
#: ops/models/adhoc.py:239 ops/templates/ops/adhoc_history.html:54 #: ops/models/adhoc.py:240 ops/templates/ops/adhoc_history.html:54
#: ops/templates/ops/task_history.html:60 #: ops/templates/ops/task_history.html:60
msgid "Is success" msgid "Is success"
msgstr "是否成功" msgstr "是否成功"
#: ops/models/adhoc.py:240 #: ops/models/adhoc.py:241
msgid "Adhoc raw result" msgid "Adhoc raw result"
msgstr "结果" msgstr "结果"
#: ops/models/adhoc.py:241 #: ops/models/adhoc.py:242
msgid "Adhoc result summary" msgid "Adhoc result summary"
msgstr "汇总" msgstr "汇总"
#: ops/models/adhoc.py:281 xpack/plugins/change_auth_plan/utils.py:86 #: ops/models/adhoc.py:282 xpack/plugins/change_auth_plan/utils.py:137
msgid "{} Start task: {}" msgid "{} Start task: {}"
msgstr "{} 任务开始: {}" msgstr "{} 任务开始: {}"
#: ops/models/adhoc.py:290 xpack/plugins/change_auth_plan/utils.py:98 #: ops/models/adhoc.py:291 xpack/plugins/change_auth_plan/utils.py:149
msgid "{} Task finish" msgid "{} Task finish"
msgstr "{} 任务结束" msgstr "{} 任务结束"
#: ops/models/command.py:24 #: ops/models/command.py:24
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:56 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:56
#: xpack/plugins/cloud/models.py:209 #: xpack/plugins/cloud/models.py:212
msgid "Result" msgid "Result"
msgstr "结果" msgstr "结果"
@ -3354,7 +3361,7 @@ msgid "Pending"
msgstr "等待" msgstr "等待"
#: ops/templates/ops/command_execution_list.html:70 #: ops/templates/ops/command_execution_list.html:70
#: xpack/plugins/change_auth_plan/models.py:259 #: xpack/plugins/change_auth_plan/models.py:257
msgid "Finished" msgid "Finished"
msgstr "结束" msgstr "结束"
@ -3394,7 +3401,7 @@ msgstr "内容"
#: ops/templates/ops/task_list.html:73 #: ops/templates/ops/task_list.html:73
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:135 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:135
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:54 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_list.html:54
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:138 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:148
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:58 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:58
#: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:44 #: xpack/plugins/gathered_user/templates/gathered_user/task_list.html:44
msgid "Run" msgid "Run"
@ -3579,6 +3586,7 @@ msgid "Add node to this permission"
msgstr "添加节点" msgstr "添加节点"
#: perms/templates/perms/asset_permission_asset.html:105 #: perms/templates/perms/asset_permission_asset.html:105
#: terminal/templates/terminal/session_list.html:149
#: users/templates/users/user_detail.html:226 #: users/templates/users/user_detail.html:226
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:101 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_asset_list.html:101
msgid "Join" msgid "Join"
@ -4252,8 +4260,8 @@ msgid "The port is not the port of the LDAP service: {}"
msgstr "端口不是LDAP服务端口: {}" msgstr "端口不是LDAP服务端口: {}"
#: settings/utils/ldap.py:393 #: settings/utils/ldap.py:393
msgid "Please enter the certificate: {}" msgid "Please add certificate: {}"
msgstr "" msgstr "请添加证书"
#: settings/utils/ldap.py:395 settings/utils/ldap.py:422 #: settings/utils/ldap.py:395 settings/utils/ldap.py:422
#: settings/utils/ldap.py:452 settings/utils/ldap.py:480 #: settings/utils/ldap.py:452 settings/utils/ldap.py:480
@ -4761,6 +4769,22 @@ msgstr "月未登录主机"
msgid "Filters" msgid "Filters"
msgstr "过滤" msgstr "过滤"
#: terminal/api/session.py:142
msgid "Session does not exist: {}"
msgstr "会话不存在: {}"
#: terminal/api/session.py:145
msgid "Session is finished or the protocol not supported"
msgstr "会话已经完成或协议不支持"
#: terminal/api/session.py:150
msgid "User does not exist: {}"
msgstr "用户不存在: {}"
#: terminal/api/session.py:154
msgid "User does not have permission"
msgstr "用户没有权限"
#: terminal/api/storage.py:24 #: terminal/api/storage.py:24
msgid "Deleting the default storage is not allowed" msgid "Deleting the default storage is not allowed"
msgstr "不允许删除默认存储配置" msgstr "不允许删除默认存储配置"
@ -4779,13 +4803,13 @@ msgstr "测试失败: 账户无效"
#: terminal/backends/command/models.py:14 #: terminal/backends/command/models.py:14
#: terminal/templates/terminal/command_list.html:110 #: terminal/templates/terminal/command_list.html:110
#: terminal/templates/terminal/command_list.html:194 #: terminal/templates/terminal/command_list.html:205
msgid "Ordinary" msgid "Ordinary"
msgstr "普通" msgstr "普通"
#: terminal/backends/command/models.py:15 #: terminal/backends/command/models.py:15
#: terminal/templates/terminal/command_list.html:111 #: terminal/templates/terminal/command_list.html:111
#: terminal/templates/terminal/command_list.html:191 #: terminal/templates/terminal/command_list.html:202
msgid "Dangerous" msgid "Dangerous"
msgstr "危险" msgstr "危险"
@ -4860,9 +4884,9 @@ msgid ""
" " " "
msgstr "" msgstr ""
#: terminal/forms/storage.py:136 xpack/plugins/cloud/models.py:263 #: terminal/forms/storage.py:136 xpack/plugins/cloud/models.py:266
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:29 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:29
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:106 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:112
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:46 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:46
msgid "Region" msgid "Region"
msgstr "地域" msgstr "地域"
@ -4953,7 +4977,7 @@ msgstr "回放"
msgid "Date end" msgid "Date end"
msgstr "结束日期" msgstr "结束日期"
#: terminal/models.py:335 #: terminal/models.py:342
msgid "Args" msgid "Args"
msgstr "参数" msgstr "参数"
@ -4961,7 +4985,7 @@ msgstr "参数"
msgid "Export command" msgid "Export command"
msgstr "导出命令" msgstr "导出命令"
#: terminal/templates/terminal/command_list.html:199 #: terminal/templates/terminal/command_list.html:210
msgid "Goto" msgid "Goto"
msgstr "转到" msgstr "转到"
@ -5040,11 +5064,11 @@ msgstr "终断任务已发送,请等待"
msgid "Terminate" msgid "Terminate"
msgstr "终断" msgstr "终断"
#: terminal/templates/terminal/session_list.html:174 #: terminal/templates/terminal/session_list.html:179
msgid "Finish session success" msgid "Finish session success"
msgstr "标记会话完成成功" msgstr "标记会话完成成功"
#: terminal/templates/terminal/session_list.html:242 #: terminal/templates/terminal/session_list.html:247
msgid "Visit doc for replay play offline: " msgid "Visit doc for replay play offline: "
msgstr "访问文档查看如何离线播放: " msgstr "访问文档查看如何离线播放: "
@ -5276,7 +5300,7 @@ msgstr "工单列表"
msgid "Ticket detail" msgid "Ticket detail"
msgstr "工单详情" msgstr "工单详情"
#: users/api/user.py:177 #: users/api/user.py:116
msgid "Could not reset self otp, use profile reset instead" msgid "Could not reset self otp, use profile reset instead"
msgstr "不能在该页面重置多因子认证, 请去个人信息页面重置" msgstr "不能在该页面重置多因子认证, 请去个人信息页面重置"
@ -5350,7 +5374,7 @@ msgid "Public key should not be the same as your old one."
msgstr "不能和原来的密钥相同" msgstr "不能和原来的密钥相同"
#: users/forms/profile.py:137 users/forms/user.py:90 #: users/forms/profile.py:137 users/forms/user.py:90
#: users/serializers/user.py:131 #: users/serializers/user.py:138
msgid "Not a valid ssh public key" msgid "Not a valid ssh public key"
msgstr "ssh密钥不合法" msgstr "ssh密钥不合法"
@ -5390,7 +5414,7 @@ msgstr "生成重置密码链接,通过邮件发送给用户"
msgid "Set password" msgid "Set password"
msgstr "设置密码" msgstr "设置密码"
#: users/forms/user.py:132 xpack/plugins/change_auth_plan/models.py:61 #: users/forms/user.py:132 xpack/plugins/change_auth_plan/models.py:59
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:45 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_create_update.html:45
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:67 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:67
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:57 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_execution_list.html:57
@ -5398,7 +5422,7 @@ msgstr "设置密码"
msgid "Password strategy" msgid "Password strategy"
msgstr "密码策略" msgstr "密码策略"
#: users/models/user.py:142 users/models/user.py:591 #: users/models/user.py:142 users/models/user.py:596
msgid "Administrator" msgid "Administrator"
msgstr "管理员" msgstr "管理员"
@ -5435,7 +5459,7 @@ msgstr "微信"
msgid "Date password last updated" msgid "Date password last updated"
msgstr "最后更新密码日期" msgstr "最后更新密码日期"
#: users/models/user.py:594 #: users/models/user.py:599
msgid "Administrator is the super user of system" msgid "Administrator is the super user of system"
msgstr "Administrator是初始的超级管理员" msgstr "Administrator是初始的超级管理员"
@ -5443,39 +5467,39 @@ msgstr "Administrator是初始的超级管理员"
msgid "Auditors cannot be join in the user group" msgid "Auditors cannot be join in the user group"
msgstr "审计员不能被加入到用户组" msgstr "审计员不能被加入到用户组"
#: users/serializers/user.py:35 #: users/serializers/user.py:42
msgid "Is first login" msgid "Is first login"
msgstr "首次登录" msgstr "首次登录"
#: users/serializers/user.py:36 #: users/serializers/user.py:43
msgid "Is valid" msgid "Is valid"
msgstr "账户是否有效" msgstr "账户是否有效"
#: users/serializers/user.py:37 #: users/serializers/user.py:44
msgid "Is expired" msgid "Is expired"
msgstr " 是否过期" msgstr " 是否过期"
#: users/serializers/user.py:38 #: users/serializers/user.py:45
msgid "Avatar url" msgid "Avatar url"
msgstr "头像路径" msgstr "头像路径"
#: users/serializers/user.py:46 #: users/serializers/user.py:53
msgid "Role limit to {}" msgid "Role limit to {}"
msgstr "角色只能为 {}" msgstr "角色只能为 {}"
#: users/serializers/user.py:58 #: users/serializers/user.py:65
msgid "Password does not match security rules" msgid "Password does not match security rules"
msgstr "密码不满足安全规则" msgstr "密码不满足安全规则"
#: users/serializers/user.py:116 #: users/serializers/user.py:123
msgid "Groups name" msgid "Groups name"
msgstr "用户组名" msgstr "用户组名"
#: users/serializers/user.py:117 #: users/serializers/user.py:124
msgid "Source name" msgid "Source name"
msgstr "用户来源名" msgstr "用户来源名"
#: users/serializers/user.py:118 #: users/serializers/user.py:125
msgid "Role name" msgid "Role name"
msgstr "角色名" msgstr "角色名"
@ -6209,8 +6233,8 @@ msgstr ""
"用户不存在,则创建用户。" "用户不存在,则创建用户。"
#: xpack/plugins/change_auth_plan/meta.py:9 #: xpack/plugins/change_auth_plan/meta.py:9
#: xpack/plugins/change_auth_plan/models.py:89 #: xpack/plugins/change_auth_plan/models.py:87
#: xpack/plugins/change_auth_plan/models.py:176 #: xpack/plugins/change_auth_plan/models.py:174
#: xpack/plugins/change_auth_plan/views.py:33 #: xpack/plugins/change_auth_plan/views.py:33
#: xpack/plugins/change_auth_plan/views.py:50 #: xpack/plugins/change_auth_plan/views.py:50
#: xpack/plugins/change_auth_plan/views.py:74 #: xpack/plugins/change_auth_plan/views.py:74
@ -6221,57 +6245,57 @@ msgstr ""
msgid "Change auth plan" msgid "Change auth plan"
msgstr "改密计划" msgstr "改密计划"
#: xpack/plugins/change_auth_plan/models.py:41 #: xpack/plugins/change_auth_plan/models.py:39
msgid "Custom password" msgid "Custom password"
msgstr "自定义密码" msgstr "自定义密码"
#: xpack/plugins/change_auth_plan/models.py:42 #: xpack/plugins/change_auth_plan/models.py:40
msgid "All assets use the same random password" msgid "All assets use the same random password"
msgstr "所有资产使用相同的随机密码" msgstr "所有资产使用相同的随机密码"
#: xpack/plugins/change_auth_plan/models.py:43 #: xpack/plugins/change_auth_plan/models.py:41
msgid "All assets use different random password" msgid "All assets use different random password"
msgstr "所有资产使用不同的随机密码" msgstr "所有资产使用不同的随机密码"
#: xpack/plugins/change_auth_plan/models.py:65 #: xpack/plugins/change_auth_plan/models.py:63
#: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:72 #: xpack/plugins/change_auth_plan/templates/change_auth_plan/plan_detail.html:72
msgid "Password rules" msgid "Password rules"
msgstr "密码规则" msgstr "密码规则"
#: xpack/plugins/change_auth_plan/models.py:180 #: xpack/plugins/change_auth_plan/models.py:178
msgid "Change auth plan snapshot" msgid "Change auth plan snapshot"
msgstr "改密计划快照" msgstr "改密计划快照"
#: xpack/plugins/change_auth_plan/models.py:195 #: xpack/plugins/change_auth_plan/models.py:193
#: xpack/plugins/change_auth_plan/models.py:281 #: xpack/plugins/change_auth_plan/models.py:279
msgid "Change auth plan execution" msgid "Change auth plan execution"
msgstr "改密计划执行" msgstr "改密计划执行"
#: xpack/plugins/change_auth_plan/models.py:254 #: xpack/plugins/change_auth_plan/models.py:252
msgid "Ready" msgid "Ready"
msgstr "" msgstr ""
#: xpack/plugins/change_auth_plan/models.py:255 #: xpack/plugins/change_auth_plan/models.py:253
msgid "check_condition" msgid "Preflight check"
msgstr "" msgstr ""
#: xpack/plugins/change_auth_plan/models.py:256 #: xpack/plugins/change_auth_plan/models.py:254
msgid "Change auth" msgid "Change auth"
msgstr "" msgstr ""
#: xpack/plugins/change_auth_plan/models.py:257 #: xpack/plugins/change_auth_plan/models.py:255
msgid "Verify auth" msgid "Verify auth"
msgstr "" msgstr ""
#: xpack/plugins/change_auth_plan/models.py:258 #: xpack/plugins/change_auth_plan/models.py:256
msgid "Save auth" msgid "Keep auth"
msgstr "" msgstr ""
#: xpack/plugins/change_auth_plan/models.py:284 #: xpack/plugins/change_auth_plan/models.py:283
msgid "Step" msgid "Step"
msgstr "步骤" msgstr "步骤"
#: xpack/plugins/change_auth_plan/models.py:301 #: xpack/plugins/change_auth_plan/models.py:300
msgid "Change auth plan task" msgid "Change auth plan task"
msgstr "改密计划任务" msgstr "改密计划任务"
@ -6344,13 +6368,17 @@ msgstr "执行失败"
msgid "Create plan" msgid "Create plan"
msgstr "创建计划" msgstr "创建计划"
#: xpack/plugins/change_auth_plan/utils.py:237 #: xpack/plugins/change_auth_plan/utils.py:437
msgid "Failed to connect asset" msgid "Invalid/incorrect password"
msgstr "连接资产失败" msgstr "无效/错误 密码"
#: xpack/plugins/change_auth_plan/utils.py:239 #: xpack/plugins/change_auth_plan/utils.py:439
msgid "Incorrect password" msgid "Failed to connect to the host"
msgstr "密码错误" msgstr "连接主机失败"
#: xpack/plugins/change_auth_plan/utils.py:441
msgid "Data could not be sent to remote"
msgstr "无法将数据发送到远程"
#: xpack/plugins/change_auth_plan/views.py:34 #: xpack/plugins/change_auth_plan/views.py:34
msgid "Plan list" msgid "Plan list"
@ -6392,6 +6420,10 @@ msgstr "选择节点"
msgid "Select admins" msgid "Select admins"
msgstr "选择管理员" msgstr "选择管理员"
#: xpack/plugins/cloud/forms.py:85
msgid "Tips: The asset information is always covered"
msgstr ""
#: xpack/plugins/cloud/meta.py:9 xpack/plugins/cloud/views.py:27 #: xpack/plugins/cloud/meta.py:9 xpack/plugins/cloud/views.py:27
#: xpack/plugins/cloud/views.py:44 xpack/plugins/cloud/views.py:62 #: xpack/plugins/cloud/views.py:44 xpack/plugins/cloud/views.py:62
#: xpack/plugins/cloud/views.py:78 xpack/plugins/cloud/views.py:92 #: xpack/plugins/cloud/views.py:78 xpack/plugins/cloud/views.py:92
@ -6436,48 +6468,52 @@ msgstr "地域"
msgid "Instances" msgid "Instances"
msgstr "实例" msgstr "实例"
#: xpack/plugins/cloud/models.py:139 #: xpack/plugins/cloud/models.py:136
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:94 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:69
msgid "Covered always"
msgstr "总是覆盖"
#: xpack/plugins/cloud/models.py:142
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:104
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:17 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:17
msgid "Date last sync" msgid "Date last sync"
msgstr "最后同步日期" msgstr "最后同步日期"
#: xpack/plugins/cloud/models.py:150 xpack/plugins/cloud/models.py:207 #: xpack/plugins/cloud/models.py:153 xpack/plugins/cloud/models.py:210
msgid "Sync instance task" msgid "Sync instance task"
msgstr "同步实例任务" msgstr "同步实例任务"
#: xpack/plugins/cloud/models.py:202 #: xpack/plugins/cloud/models.py:205
msgid "Succeed" msgid "Succeed"
msgstr "成功" msgstr "成功"
#: xpack/plugins/cloud/models.py:217 xpack/plugins/cloud/models.py:272 #: xpack/plugins/cloud/models.py:220 xpack/plugins/cloud/models.py:275
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:51 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_history.html:51
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:49 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:49
msgid "Date sync" msgid "Date sync"
msgstr "同步日期" msgstr "同步日期"
#: xpack/plugins/cloud/models.py:245 #: xpack/plugins/cloud/models.py:248
msgid "Unsync" msgid "Unsync"
msgstr "未同步" msgstr "未同步"
#: xpack/plugins/cloud/models.py:246 xpack/plugins/cloud/models.py:247 #: xpack/plugins/cloud/models.py:249 xpack/plugins/cloud/models.py:250
msgid "Synced" msgid "Synced"
msgstr "已同步" msgstr "已同步"
#: xpack/plugins/cloud/models.py:248 #: xpack/plugins/cloud/models.py:251
msgid "Released" msgid "Released"
msgstr "已释放" msgstr "已释放"
#: xpack/plugins/cloud/models.py:253 #: xpack/plugins/cloud/models.py:256
msgid "Sync task" msgid "Sync task"
msgstr "同步任务" msgstr "同步任务"
#: xpack/plugins/cloud/models.py:257 #: xpack/plugins/cloud/models.py:260
msgid "Sync instance task history" msgid "Sync instance task history"
msgstr "同步实例任务历史" msgstr "同步实例任务历史"
#: xpack/plugins/cloud/models.py:260 #: xpack/plugins/cloud/models.py:263
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:114
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:45 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_instance.html:45
msgid "Instance" msgid "Instance"
msgstr "实例" msgstr "实例"
@ -6556,7 +6592,7 @@ msgstr "创建账户"
msgid "Node & AdminUser" msgid "Node & AdminUser"
msgstr "节点 & 管理用户" msgstr "节点 & 管理用户"
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:63 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_create_update.html:66
msgid "Load failed" msgid "Load failed"
msgstr "加载失败" msgstr "加载失败"
@ -6581,11 +6617,11 @@ msgstr "同步历史列表"
msgid "Sync instance list" msgid "Sync instance list"
msgstr "同步实例列表" msgstr "同步实例列表"
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:135 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:145
msgid "Run task manually" msgid "Run task manually"
msgstr "手动执行任务" msgstr "手动执行任务"
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:178 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_detail.html:188
#: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:102 #: xpack/plugins/cloud/templates/cloud/sync_instance_task_list.html:102
msgid "Sync success" msgid "Sync success"
msgstr "同步成功" msgstr "同步成功"
@ -6622,7 +6658,7 @@ msgstr "执行次数"
msgid "Instance count" msgid "Instance count"
msgstr "实例个数" msgstr "实例个数"
#: xpack/plugins/cloud/utils.py:37 #: xpack/plugins/cloud/utils.py:38
msgid "Account unavailable" msgid "Account unavailable"
msgstr "账户无效" msgstr "账户无效"
@ -6916,6 +6952,9 @@ msgstr "密码匣子"
msgid "vault create" msgid "vault create"
msgstr "创建" msgstr "创建"
#~ msgid "* For security, do not change {}'s password"
#~ msgstr "* 为了安全,不能修改 {} 的密码"
#~ msgid "Assets is empty, please add the asset" #~ msgid "Assets is empty, please add the asset"
#~ msgstr "资产为空,请添加资产" #~ msgstr "资产为空,请添加资产"
@ -7290,9 +7329,6 @@ msgstr "创建"
#~ msgid "Loading..." #~ msgid "Loading..."
#~ msgstr "加载中..." #~ msgstr "加载中..."
#~ msgid "You do not have permission."
#~ msgstr "你没有权限"
#~ msgid "Interface" #~ msgid "Interface"
#~ msgstr "界面" #~ msgstr "界面"
@ -7317,9 +7353,6 @@ msgstr "创建"
#~ msgid "Reachable assets" #~ msgid "Reachable assets"
#~ msgstr "可连接资产" #~ msgstr "可连接资产"
#~ msgid "User does not exist"
#~ msgstr "用户不存在"
#~ msgid "Restore default successfully" #~ msgid "Restore default successfully"
#~ msgstr "恢复默认成功!" #~ msgstr "恢复默认成功!"

View File

@ -132,6 +132,9 @@ class AdHocResultCallback(CallbackMixin, CallbackModule, CMDCallBackModule):
def display_failed_stderr(self): def display_failed_stderr(self):
pass pass
def set_play_context(self, context):
context.ssh_args = '-C -o ControlMaster=no'
class CommandResultCallback(AdHocResultCallback): class CommandResultCallback(AdHocResultCallback):
""" """

View File

@ -278,7 +278,7 @@ class AdHocExecution(OrgModelMixin):
raw = '' raw = ''
try: try:
date_start_s = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') date_start_s = timezone.now().now().strftime('%Y-%m-%d %H:%M:%S')
print(_("{} Start task: {}").format(date_start_s, self.task.name)) print(_("{} Start task: {}").format(date_start_s, self.task.name))
raw, summary = self.start_runner() raw, summary = self.start_runner()
except Exception as e: except Exception as e:
@ -286,7 +286,7 @@ class AdHocExecution(OrgModelMixin):
raw = {"dark": {"all": str(e)}, "contacted": []} raw = {"dark": {"all": str(e)}, "contacted": []}
finally: finally:
self.clean_up(summary, time_start) self.clean_up(summary, time_start)
date_end = timezone.now() date_end = timezone.now().now()
date_end_s = date_end.strftime('%Y-%m-%d %H:%M:%S') date_end_s = date_end.strftime('%Y-%m-%d %H:%M:%S')
print(_("{} Task finish").format(date_end_s)) print(_("{} Task finish").format(date_end_s))
print('.\n\n.') print('.\n\n.')

View File

@ -390,7 +390,7 @@ class LDAPTestUtil(object):
except LDAPSessionTerminatedByServerError as e: except LDAPSessionTerminatedByServerError as e:
error = _('The port is not the port of the LDAP service: {}'.format(e)) error = _('The port is not the port of the LDAP service: {}'.format(e))
except LDAPSocketReceiveError as e: except LDAPSocketReceiveError as e:
error = _('Please enter the certificate: {}'.format(e)) error = _('Please add certificate: {}'.format(e))
except Exception as e: except Exception as e:
error = _('Unknown error: {}'.format(e)) error = _('Unknown error: {}'.format(e))
else: else:

View File

@ -1256,7 +1256,8 @@ function toSafeDateISOStr(s) {
function toSafeLocalDateStr(d) { function toSafeLocalDateStr(d) {
var date = safeDate(d); var date = safeDate(d);
var date_s = date.toLocaleString(getUserLang(), {hour12: false}); // var date_s = date.toLocaleString(getUserLang(), {hour12: false});
var date_s = date.toLocaleString(getUserLang(), {hourCycle: "h23"});
return date_s.split("/").join('-') return date_s.split("/").join('-')
} }

View File

@ -7,7 +7,7 @@
<script src="{% static "js/plugins/toastr/toastr.min.js" %}"></script> <script src="{% static "js/plugins/toastr/toastr.min.js" %}"></script>
<script src="{% static "js/inspinia.js" %}"></script> <script src="{% static "js/inspinia.js" %}"></script>
<script type="text/javascript" src="{% url 'javascript-catalog' %}"></script> <script type="text/javascript" src="{% url 'javascript-catalog' %}"></script>
<script src="{% static "js/jumpserver.js" %}?v=7"></script> <script src="{% static "js/jumpserver.js" %}?v=8"></script>
<script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script> <script src="{% static 'js/plugins/select2/select2.full.min.js' %}"></script>
<script src="{% static 'js/plugins/select2/i18n/zh-CN.js' %}"></script> <script src="{% static 'js/plugins/select2/i18n/zh-CN.js' %}"></script>
<script> <script>

View File

@ -1,22 +1,27 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from django.utils.translation import ugettext as _
from django.shortcuts import get_object_or_404, reverse from django.shortcuts import get_object_or_404, reverse
from django.core.files.storage import default_storage from django.core.files.storage import default_storage
from rest_framework import viewsets from rest_framework import viewsets, views
from rest_framework.response import Response from rest_framework.response import Response
from common.utils import is_uuid, get_logger from common.utils import is_uuid, get_logger, get_object_or_none
from common.mixins.api import AsyncApiMixin from common.mixins.api import AsyncApiMixin
from common.permissions import IsOrgAdminOrAppUser, IsOrgAuditor from common.permissions import IsOrgAdminOrAppUser, IsOrgAuditor, IsAppUser
from common.drf.filters import DatetimeRangeFilter from common.drf.filters import DatetimeRangeFilter
from orgs.mixins.api import OrgBulkModelViewSet from orgs.mixins.api import OrgBulkModelViewSet
from orgs.utils import tmp_to_root_org, tmp_to_org
from users.models import User
from ..utils import find_session_replay_local, download_session_replay from ..utils import find_session_replay_local, download_session_replay
from ..hands import SystemUser from ..hands import SystemUser
from ..models import Session from ..models import Session
from .. import serializers from .. import serializers
__all__ = ['SessionViewSet', 'SessionReplayViewSet',] __all__ = [
'SessionViewSet', 'SessionReplayViewSet', 'SessionJoinValidateAPI'
]
logger = get_logger(__name__) logger = get_logger(__name__)
@ -117,3 +122,36 @@ class SessionReplayViewSet(AsyncApiMixin, viewsets.ViewSet):
return Response({"error": url}) return Response({"error": url})
data = self.get_replay_data(session, url) data = self.get_replay_data(session, url)
return Response(data) return Response(data)
class SessionJoinValidateAPI(views.APIView):
permission_classes = (IsAppUser, )
serializer_class = serializers.SessionJoinValidateSerializer
def post(self, request, *args, **kwargs):
serializer = self.serializer_class(data=request.data)
if not serializer.is_valid():
msg = str(serializer.errors)
return Response({'ok': False, 'msg': msg}, status=401)
user_id = serializer.validated_data['user_id']
session_id = serializer.validated_data['session_id']
with tmp_to_root_org():
session = get_object_or_none(Session, pk=session_id)
if not session:
msg = _('Session does not exist: {}'.format(session_id))
return Response({'ok': False, 'msg': msg}, status=401)
if not session.can_join():
msg = _('Session is finished or the protocol not supported')
return Response({'ok': False, 'msg': msg}, status=401)
user = get_object_or_none(User, pk=user_id)
if not user:
msg = _('User does not exist: {}'.format(user_id))
return Response({'ok': False, 'msg': msg}, status=401)
with tmp_to_org(session.org):
if not user.admin_or_audit_orgs:
msg = _('User does not have permission')
return Response({'ok': False, 'msg': msg}, status=401)
return Response({'ok': True, 'msg': ''}, status=200)

View File

@ -243,6 +243,13 @@ class Session(OrgModelMixin):
return True return True
return False return False
def can_join(self):
if self.is_finished:
return False
if self.protocol not in ['ssh', 'telnet', 'mysql']:
return False
return True
def save_to_storage(self, f): def save_to_storage(self, f):
local_path = self.get_local_path() local_path = self.get_local_path()
try: try:

View File

@ -6,7 +6,7 @@ from ..models import Session
__all__ = [ __all__ = [
'SessionSerializer', 'SessionDisplaySerializer', 'SessionSerializer', 'SessionDisplaySerializer',
'ReplaySerializer', 'ReplaySerializer', 'SessionJoinValidateSerializer',
] ]
@ -21,7 +21,7 @@ class SessionSerializer(BulkOrgResourceModelSerializer):
"user_id", "asset_id", "system_user_id", "user_id", "asset_id", "system_user_id",
"login_from", "login_from_display", "remote_addr", "login_from", "login_from_display", "remote_addr",
"is_success", "is_finished", "has_replay", "can_replay", "is_success", "is_finished", "has_replay", "can_replay",
"protocol", "date_start", "date_end", "can_join", "protocol", "date_start", "date_end",
"terminal", "terminal",
] ]
@ -35,3 +35,8 @@ class SessionDisplaySerializer(SessionSerializer):
class ReplaySerializer(serializers.Serializer): class ReplaySerializer(serializers.Serializer):
file = serializers.FileField(allow_empty_file=True) file = serializers.FileField(allow_empty_file=True)
class SessionJoinValidateSerializer(serializers.Serializer):
user_id = serializers.UUIDField()
session_id = serializers.UUIDField()

View File

@ -117,6 +117,17 @@ $(document).ready(function () {
.on('click', '#btn_bulk_update', function(){ .on('click', '#btn_bulk_update', function(){
// var action = $('#slct_bulk_update').val(); // var action = $('#slct_bulk_update').val();
var params = getUrlParams(table.ajax.url()); var params = getUrlParams(table.ajax.url());
var searchParams = '';
var searchValue = $('input[type=search]').val();
var searchMap = parseTableFilter(searchValue);
if (Object.keys(searchMap).length === 0) {
searchParams = searchValue;
} else {
$.each(searchMap, function (k, v) {
searchParams += k + '=' + v + '&'
})
}
params += '&' + searchParams;
var exportPath = "{% url 'api-terminal:command-export' %}"; var exportPath = "{% url 'api-terminal:command-export' %}";
var url = exportPath + "?" + params; var url = exportPath + "?" + params;

View File

@ -146,10 +146,15 @@ function initTable() {
.replace("sessionID", cellData) .replace("sessionID", cellData)
.replace("terminalID", rowData.terminal) .replace("terminalID", rowData.terminal)
} }
var joinBtn = ' <a disabled data-session="sessionID" class="btn btn-xs btn-info btn-join" >{% trans "Join" %}</a>';
joinBtn = joinBtn.replace("sessionID", rowData.id);
if (rowData.can_join){
joinBtn = joinBtn.replace("disabled", "")
}
if (rowData.is_finished) { if (rowData.is_finished) {
btnGroup += replayBtn + downloadBtn btnGroup += replayBtn + downloadBtn
} else { } else {
btnGroup += termBtn; btnGroup += termBtn + joinBtn;
} }
$(td).html(btnGroup); $(td).html(btnGroup);
}}, }},
@ -240,12 +245,17 @@ $(document).ready(function() {
var hasConfirm = getCookie('replayConfirm'); var hasConfirm = getCookie('replayConfirm');
if (!hasConfirm) { if (!hasConfirm) {
var help_text = "{% trans "Visit doc for replay play offline: " %}"; var help_text = "{% trans "Visit doc for replay play offline: " %}";
help_text += "http://docs.jumpserver.org"; help_text += "https://github.com/jumpserver/videoplayer";
var r = confirm(help_text); var r = confirm(help_text);
setCookie("replayConfirm", "1") setCookie("replayConfirm", "1")
} }
window.open(downloadUrl) window.open(downloadUrl)
}) })
.on('click', '.btn-join', function () {
var sessionID = $(this).data("session");
var joinUrl = "/luna/join/?shareroom=" + sessionID;
window.open(joinUrl, "height=600, width=800, top=400, left=400, toolbar=no, menubar=no, scrollbars=no, location=no, status=no");
})
.on("click", '#session_table_filter input', function (e) { .on("click", '#session_table_filter input', function (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();

View File

@ -22,6 +22,7 @@ router.register(r'replay-storages', api.ReplayStorageViewSet, 'replay-storage')
router.register(r'command-storages', api.CommandStorageViewSet, 'command-storage') router.register(r'command-storages', api.CommandStorageViewSet, 'command-storage')
urlpatterns = [ urlpatterns = [
path('sessions/join/validate/', api.SessionJoinValidateAPI.as_view(), name='join-session-validate'),
path('sessions/<uuid:pk>/replay/', path('sessions/<uuid:pk>/replay/',
api.SessionReplayViewSet.as_view({'get': 'retrieve', 'post': 'create'}), api.SessionReplayViewSet.as_view({'get': 'retrieve', 'post': 'create'}),
name='session-replay'), name='session-replay'),

View File

@ -42,8 +42,7 @@ class UserSerializer(BulkSerializerMixin, serializers.ModelSerializer):
'groups', 'role', 'wechat', 'phone', 'mfa_level', 'groups', 'role', 'wechat', 'phone', 'mfa_level',
'comment', 'source', 'is_valid', 'is_expired', 'comment', 'source', 'is_valid', 'is_expired',
'is_active', 'created_by', 'is_first_login', 'is_active', 'created_by', 'is_first_login',
'password_strategy', 'password_strategy', 'date_password_last_updated', 'date_expired',
'date_password_last_updated', 'date_expired',
'avatar_url', 'avatar_url',
] ]
extra_kwargs = { extra_kwargs = {

View File

@ -64,7 +64,7 @@ REDIS_PORT: 6379
# AUTH_OPENID_CLIENT_SECRET: client-secret # AUTH_OPENID_CLIENT_SECRET: client-secret
# AUTH_OPENID_IGNORE_SSL_VERIFICATION: True # AUTH_OPENID_IGNORE_SSL_VERIFICATION: True
# AUTH_OPENID_SHARE_SESSION: True # AUTH_OPENID_SHARE_SESSION: True
#
# Use Radius authorization # Use Radius authorization
# 使用Radius来认证 # 使用Radius来认证
# AUTH_RADIUS: false # AUTH_RADIUS: false
@ -72,6 +72,13 @@ REDIS_PORT: 6379
# RADIUS_PORT: 1812 # RADIUS_PORT: 1812
# RADIUS_SECRET: # RADIUS_SECRET:
# CAS 配置
# AUTH_CAS': False,
# CAS_SERVER_URL': "http://host/cas/",
# CAS_ROOT_PROXIED_AS': 'http://jumpserver-host:port',
# CAS_LOGOUT_COMPLETELY': True,
# CAS_VERSION': 3,
# LDAP/AD settings # LDAP/AD settings
# LDAP 搜索分页数量 # LDAP 搜索分页数量
# AUTH_LDAP_SEARCH_PAGED_SIZE: 1000 # AUTH_LDAP_SEARCH_PAGED_SIZE: 1000

View File

@ -4,7 +4,7 @@ asn1crypto==0.24.0
bcrypt==3.1.4 bcrypt==3.1.4
billiard==3.5.0.3 billiard==3.5.0.3
boto3==1.12.14 boto3==1.12.14
botocore==1.9.5 botocore==1.15.26
celery==4.1.1 celery==4.1.1
certifi==2018.1.18 certifi==2018.1.18
cffi==1.13.2 cffi==1.13.2
@ -61,8 +61,8 @@ pytz==2018.3
PyYAML==5.1 PyYAML==5.1
redis==2.10.6 redis==2.10.6
requests==2.22.0 requests==2.22.0
jms-storage==0.0.27 jms-storage==0.0.28
s3transfer==0.1.13 s3transfer==0.3.3
simplejson==3.13.2 simplejson==3.13.2
six==1.11.0 six==1.11.0
sshpubkeys==3.1.0 sshpubkeys==3.1.0
@ -96,3 +96,5 @@ django-cas-ng==4.0.1
python-cas==1.5.0 python-cas==1.5.0
ipython ipython
huaweicloud-sdk-python==1.0.21 huaweicloud-sdk-python==1.0.21
django-redis==4.11.0
python-redis-lock==3.5.0