feat: 支持 magnus (#7965)

* feat: 支持 magnus

* perf: 添加 setting 到 api

* perf: 放出 mongodb

Co-authored-by: ibuler <ibuler@qq.com>
pull/7976/head^2
fit2bot 2022-03-25 14:45:08 +08:00 committed by GitHub
parent 8718dc6751
commit e0fdfa52b9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 273 additions and 202 deletions

View File

@ -41,7 +41,7 @@ class AppType(models.TextChoices):
def category_types_mapper(cls): def category_types_mapper(cls):
return { return {
AppCategory.db: [ AppCategory.db: [
cls.mysql, cls.oracle, cls.pgsql, cls.mariadb, cls.mysql, cls.mariadb, cls.oracle, cls.pgsql,
cls.sqlserver, cls.redis, cls.mongodb cls.sqlserver, cls.redis, cls.mongodb
], ],
AppCategory.remote_app: [ AppCategory.remote_app: [

View File

@ -100,10 +100,8 @@ class ApplicationTreeNodeMixin:
temp_pid = pid temp_pid = pid
type_category_mapper = const.AppType.type_category_mapper() type_category_mapper = const.AppType.type_category_mapper()
types = const.AppType.type_category_mapper().keys() types = const.AppType.type_category_mapper().keys()
for tp in types: for tp in types:
# TODO: Temporary exclude mongodb
if tp == const.AppType.mongodb:
continue
if not settings.XPACK_ENABLED and const.AppType.is_xpack(tp): if not settings.XPACK_ENABLED and const.AppType.is_xpack(tp):
continue continue
category = type_category_mapper.get(tp) category = type_category_mapper.get(tp)

View File

@ -1,9 +1,12 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import re import re
from django.shortcuts import reverse as dj_reverse from django.shortcuts import reverse as dj_reverse
from django.conf import settings from django.conf import settings
from django.utils import timezone from django.utils import timezone
from django.db import models
from django.db.models.signals import post_save, pre_save
UUID_PATTERN = re.compile(r'[0-9a-zA-Z\-]{36}') UUID_PATTERN = re.compile(r'[0-9a-zA-Z\-]{36}')
@ -58,3 +61,12 @@ def get_log_keep_day(s, defaults=200):
except ValueError: except ValueError:
days = defaults days = defaults
return days return days
def bulk_create_with_signal(cls: models.Model, items, **kwargs):
for i in items:
pre_save.send(sender=cls, instance=i)
result = cls.objects.bulk_create(items, **kwargs)
for i in items:
post_save.send(sender=cls, instance=i, created=True)
return result

View File

@ -300,32 +300,6 @@ class IndexApi(DatesLoginMetricMixin, APIView):
class HealthApiMixin(APIView): class HealthApiMixin(APIView):
pass pass
# 先去掉 Health Api 的权限校验,方便各组件直接调用
# def is_token_right(self):
# token = self.request.query_params.get('token')
# ok_token = settings.HEALTH_CHECK_TOKEN
# if ok_token and token != ok_token:
# return False
# return True
# def is_localhost(self):
# ip = get_request_ip(self.request)
# return ip in ['localhost', '127.0.0.1']
# def check_permissions(self, request):
# if self.is_token_right():
# return
# if self.is_localhost():
# return
# msg = '''
# Health check token error,
# Please set query param in url and
# same with setting HEALTH_CHECK_TOKEN.
# eg: $PATH/?token=$HEALTH_CHECK_TOKEN
# '''
# self.permission_denied(request, message={'error': msg}, code=403)
class HealthCheckView(HealthApiMixin): class HealthCheckView(HealthApiMixin):
permission_classes = (AllowAny,) permission_classes = (AllowAny,)

View File

@ -16,8 +16,10 @@ import json
import yaml import yaml
import copy import copy
from importlib import import_module from importlib import import_module
from django.urls import reverse_lazy
from urllib.parse import urljoin, urlparse from urllib.parse import urljoin, urlparse
from django.urls import reverse_lazy
from django.conf import settings
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@ -307,9 +309,14 @@ class Config(dict):
'TERMINAL_HOST_KEY': '', 'TERMINAL_HOST_KEY': '',
'TERMINAL_TELNET_REGEX': '', 'TERMINAL_TELNET_REGEX': '',
'TERMINAL_COMMAND_STORAGE': {}, 'TERMINAL_COMMAND_STORAGE': {},
'TERMINAL_RDP_ADDR': '', 'TERMINAL_RDP_ADDR': lambda: urlparse(settings.SITE_URL).hostname + ':3389',
'XRDP_ENABLED': True, 'XRDP_ENABLED': True,
'TERMINAL_MAGNUS_ENABLED': True,
'TERMINAL_MAGNUS_HOST': lambda: urlparse(settings.SITE_URL).hostname,
'TERMINAL_MAGNUS_MYSQL_PORT': 33060,
'TERMINAL_MAGNUS_POSTGRE_PORT': 54320,
# 安全配置 # 安全配置
'SECURITY_MFA_AUTH': 0, # 0 不开启 1 全局开启 2 管理员开启 'SECURITY_MFA_AUTH': 0, # 0 不开启 1 全局开启 2 管理员开启
'SECURITY_MFA_AUTH_ENABLED_FOR_THIRD_PARTY': True, 'SECURITY_MFA_AUTH_ENABLED_FOR_THIRD_PARTY': True,
@ -392,6 +399,7 @@ class Config(dict):
'FORGOT_PASSWORD_URL': '', 'FORGOT_PASSWORD_URL': '',
'HEALTH_CHECK_TOKEN': '', 'HEALTH_CHECK_TOKEN': '',
} }
@staticmethod @staticmethod
@ -540,7 +548,8 @@ class Config(dict):
value = self.get_from_env(item) value = self.get_from_env(item)
if value is not None: if value is not None:
return value return value
return self.defaults.get(item) value = self.defaults.get(item)
return value
def __getitem__(self, item): def __getitem__(self, item):
return self.get(item) return self.get(item)

View File

@ -167,3 +167,9 @@ ANNOUNCEMENT = CONFIG.ANNOUNCEMENT
# help # help
HELP_DOCUMENT_URL = CONFIG.HELP_DOCUMENT_URL HELP_DOCUMENT_URL = CONFIG.HELP_DOCUMENT_URL
HELP_SUPPORT_URL = CONFIG.HELP_SUPPORT_URL HELP_SUPPORT_URL = CONFIG.HELP_SUPPORT_URL
# Magnus
MAGNUS_ENABLED = CONFIG.MAGNUS_ENABLED
TERMINAL_MAGNUS_HOST = CONFIG.TERMINAL_MAGNUS_HOST
TERMINAL_MAGNUS_MYSQL_PORT = CONFIG.TERMINAL_MAGNUS_MYSQL_PORT
TERMINAL_MAGNUS_POSTGRE_PORT = CONFIG.TERMINAL_MAGNUS_POSTGRE_PORT

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:b1c6c0f9212f9d154a432d93785677ebc206eed4fd4338d3fe11b4b528d65c11 oid sha256:d545e79536feb40608d809a54b8b2140e235373acf331202131882e7af002dfb
size 104323 size 105242

View File

@ -7,7 +7,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: 2022-03-21 10:37+0800\n" "POT-Creation-Date: 2022-03-23 15:35+0800\n"
"PO-Revision-Date: 2021-05-20 10:54+0800\n" "PO-Revision-Date: 2021-05-20 10:54+0800\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"
@ -22,7 +22,7 @@ msgid "Acls"
msgstr "访问控制" msgstr "访问控制"
#: acls/models/base.py:25 acls/serializers/login_asset_acl.py:47 #: acls/models/base.py:25 acls/serializers/login_asset_acl.py:47
#: applications/models/application.py:212 assets/models/asset.py:138 #: applications/models/application.py:213 assets/models/asset.py:138
#: assets/models/base.py:175 assets/models/cluster.py:18 #: assets/models/base.py:175 assets/models/cluster.py:18
#: assets/models/cmd_filter.py:27 assets/models/domain.py:23 #: assets/models/cmd_filter.py:27 assets/models/domain.py:23
#: assets/models/group.py:20 assets/models/label.py:18 ops/mixin.py:24 #: assets/models/group.py:20 assets/models/label.py:18 ops/mixin.py:24
@ -30,7 +30,7 @@ msgstr "访问控制"
#: settings/models.py:29 settings/serializers/sms.py:6 #: settings/models.py:29 settings/serializers/sms.py:6
#: terminal/models/storage.py:23 terminal/models/task.py:16 #: terminal/models/storage.py:23 terminal/models/task.py:16
#: terminal/models/terminal.py:100 users/forms/profile.py:32 #: terminal/models/terminal.py:100 users/forms/profile.py:32
#: users/models/group.py:15 users/models/user.py:584 #: users/models/group.py:15 users/models/user.py:655
#: users/templates/users/_select_user_modal.html:13 #: users/templates/users/_select_user_modal.html:13
#: users/templates/users/user_asset_permission.html:37 #: users/templates/users/user_asset_permission.html:37
#: users/templates/users/user_asset_permission.html:154 #: users/templates/users/user_asset_permission.html:154
@ -40,12 +40,12 @@ msgid "Name"
msgstr "名称" msgstr "名称"
#: acls/models/base.py:27 assets/models/cmd_filter.py:84 #: acls/models/base.py:27 assets/models/cmd_filter.py:84
#: assets/models/user.py:234 #: assets/models/user.py:247
msgid "Priority" msgid "Priority"
msgstr "优先级" msgstr "优先级"
#: acls/models/base.py:28 assets/models/cmd_filter.py:84 #: acls/models/base.py:28 assets/models/cmd_filter.py:84
#: assets/models/user.py:234 #: assets/models/user.py:247
msgid "1-100, the lower the value will be match first" msgid "1-100, the lower the value will be match first"
msgstr "优先级可选范围为 1-100 (数值越小越优先)" msgstr "优先级可选范围为 1-100 (数值越小越优先)"
@ -56,7 +56,7 @@ msgstr "优先级可选范围为 1-100 (数值越小越优先)"
msgid "Active" msgid "Active"
msgstr "激活中" msgstr "激活中"
#: acls/models/base.py:32 applications/models/application.py:225 #: acls/models/base.py:32 applications/models/application.py:226
#: assets/models/asset.py:143 assets/models/asset.py:231 #: assets/models/asset.py:143 assets/models/asset.py:231
#: assets/models/backup.py:54 assets/models/base.py:180 #: assets/models/backup.py:54 assets/models/base.py:180
#: assets/models/cluster.py:29 assets/models/cmd_filter.py:48 #: assets/models/cluster.py:29 assets/models/cmd_filter.py:48
@ -66,7 +66,7 @@ msgstr "激活中"
#: perms/models/base.py:93 rbac/models/role.py:37 settings/models.py:34 #: perms/models/base.py:93 rbac/models/role.py:37 settings/models.py:34
#: terminal/models/storage.py:26 terminal/models/terminal.py:114 #: terminal/models/storage.py:26 terminal/models/terminal.py:114
#: tickets/models/comment.py:24 tickets/models/ticket.py:154 #: tickets/models/comment.py:24 tickets/models/ticket.py:154
#: users/models/group.py:16 users/models/user.py:621 #: users/models/group.py:16 users/models/user.py:692
#: xpack/plugins/change_auth_plan/models/base.py:44 #: xpack/plugins/change_auth_plan/models/base.py:44
#: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:116 #: xpack/plugins/cloud/models.py:35 xpack/plugins/cloud/models.py:116
#: xpack/plugins/gathered_user/models.py:26 #: xpack/plugins/gathered_user/models.py:26
@ -90,12 +90,12 @@ msgstr "登录复核"
#: assets/models/cmd_filter.py:30 assets/models/label.py:15 audits/models.py:37 #: assets/models/cmd_filter.py:30 assets/models/label.py:15 audits/models.py:37
#: audits/models.py:60 audits/models.py:85 audits/serializers.py:100 #: audits/models.py:60 audits/models.py:85 audits/serializers.py:100
#: authentication/models.py:50 orgs/models.py:214 perms/models/base.py:84 #: authentication/models.py:50 orgs/models.py:214 perms/models/base.py:84
#: rbac/builtin.py:101 rbac/models/rolebinding.py:39 templates/index.html:78 #: rbac/builtin.py:101 rbac/models/rolebinding.py:40 templates/index.html:78
#: terminal/backends/command/models.py:19 #: terminal/backends/command/models.py:19
#: terminal/backends/command/serializers.py:12 terminal/models/session.py:42 #: terminal/backends/command/serializers.py:12 terminal/models/session.py:42
#: terminal/notifications.py:91 terminal/notifications.py:139 #: terminal/notifications.py:91 terminal/notifications.py:139
#: tickets/models/comment.py:17 users/const.py:14 users/models/user.py:809 #: tickets/models/comment.py:17 users/const.py:14 users/models/user.py:880
#: users/models/user.py:840 users/serializers/group.py:19 #: users/models/user.py:911 users/serializers/group.py:19
#: 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
#: users/templates/users/user_database_app_permission.html:37 #: users/templates/users/user_database_app_permission.html:37
@ -169,7 +169,7 @@ msgstr "格式为逗号分隔的字符串, * 表示匹配所有. "
#: authentication/forms.py:15 authentication/forms.py:17 #: authentication/forms.py:15 authentication/forms.py:17
#: authentication/templates/authentication/_msg_different_city.html:9 #: authentication/templates/authentication/_msg_different_city.html:9
#: authentication/templates/authentication/_msg_oauth_bind.html:9 #: authentication/templates/authentication/_msg_oauth_bind.html:9
#: ops/models/adhoc.py:159 users/forms/profile.py:31 users/models/user.py:582 #: ops/models/adhoc.py:159 users/forms/profile.py:31 users/models/user.py:653
#: users/templates/users/_msg_user_created.html:12 #: users/templates/users/_msg_user_created.html:12
#: users/templates/users/_select_user_modal.html:14 #: users/templates/users/_select_user_modal.html:14
#: xpack/plugins/change_auth_plan/models/asset.py:34 #: xpack/plugins/change_auth_plan/models/asset.py:34
@ -215,7 +215,7 @@ msgid ""
msgstr "格式为逗号分隔的字符串, * 表示匹配所有. 可选的协议有: {}" msgstr "格式为逗号分隔的字符串, * 表示匹配所有. 可选的协议有: {}"
#: acls/serializers/login_asset_acl.py:55 assets/models/asset.py:213 #: acls/serializers/login_asset_acl.py:55 assets/models/asset.py:213
#: assets/models/domain.py:62 assets/models/user.py:235 #: assets/models/domain.py:62 assets/models/user.py:248
#: terminal/serializers/session.py:30 terminal/serializers/storage.py:69 #: terminal/serializers/session.py:30 terminal/serializers/storage.py:69
msgid "Protocol" msgid "Protocol"
msgstr "协议" msgstr "协议"
@ -255,7 +255,7 @@ msgstr "时段"
msgid "My applications" msgid "My applications"
msgstr "我的应用" msgstr "我的应用"
#: applications/apps.py:9 applications/models/application.py:61 #: applications/apps.py:9 applications/models/application.py:62
msgid "Applications" msgid "Applications"
msgstr "应用管理" msgstr "应用管理"
@ -274,14 +274,14 @@ msgstr "远程应用"
msgid "Custom" msgid "Custom"
msgstr "自定义" msgstr "自定义"
#: applications/models/account.py:12 applications/models/application.py:229 #: applications/models/account.py:12 applications/models/application.py:230
#: assets/models/backup.py:32 assets/models/cmd_filter.py:45 #: assets/models/backup.py:32 assets/models/cmd_filter.py:45
#: perms/models/application_permission.py:28 #: perms/models/application_permission.py:28
msgid "Application" msgid "Application"
msgstr "应用程序" msgstr "应用程序"
#: applications/models/account.py:15 assets/models/authbook.py:20 #: applications/models/account.py:15 assets/models/authbook.py:20
#: assets/models/cmd_filter.py:42 assets/models/user.py:325 audits/models.py:40 #: assets/models/cmd_filter.py:42 assets/models/user.py:338 audits/models.py:40
#: perms/models/application_permission.py:33 #: perms/models/application_permission.py:33
#: perms/models/asset_permission.py:25 terminal/backends/command/models.py:21 #: perms/models/asset_permission.py:25 terminal/backends/command/models.py:21
#: terminal/backends/command/serializers.py:14 terminal/models/session.py:46 #: terminal/backends/command/serializers.py:14 terminal/models/session.py:46
@ -314,7 +314,7 @@ msgstr "可以查看应用账号密码"
msgid "Can change application account secret" msgid "Can change application account secret"
msgstr "可以查看应用账号密码" msgstr "可以查看应用账号密码"
#: applications/models/application.py:214 #: applications/models/application.py:215
#: applications/serializers/application.py:99 assets/models/label.py:21 #: applications/serializers/application.py:99 assets/models/label.py:21
#: perms/models/application_permission.py:21 #: perms/models/application_permission.py:21
#: perms/serializers/application/user_permission.py:33 #: perms/serializers/application/user_permission.py:33
@ -323,9 +323,9 @@ msgstr "可以查看应用账号密码"
msgid "Category" msgid "Category"
msgstr "类别" msgstr "类别"
#: applications/models/application.py:217 #: applications/models/application.py:218
#: applications/serializers/application.py:101 assets/models/backup.py:49 #: applications/serializers/application.py:101 assets/models/backup.py:49
#: assets/models/cmd_filter.py:82 assets/models/user.py:233 #: assets/models/cmd_filter.py:82 assets/models/user.py:246
#: perms/models/application_permission.py:24 #: perms/models/application_permission.py:24
#: perms/serializers/application/user_permission.py:34 #: perms/serializers/application/user_permission.py:34
#: terminal/models/storage.py:55 terminal/models/storage.py:119 #: terminal/models/storage.py:55 terminal/models/storage.py:119
@ -336,21 +336,21 @@ msgstr "类别"
msgid "Type" msgid "Type"
msgstr "类型" msgstr "类型"
#: applications/models/application.py:221 assets/models/asset.py:217 #: applications/models/application.py:222 assets/models/asset.py:217
#: assets/models/domain.py:29 assets/models/domain.py:63 #: assets/models/domain.py:29 assets/models/domain.py:63
msgid "Domain" msgid "Domain"
msgstr "网域" msgstr "网域"
#: applications/models/application.py:223 xpack/plugins/cloud/models.py:33 #: applications/models/application.py:224 xpack/plugins/cloud/models.py:33
#: xpack/plugins/cloud/serializers/account.py:58 #: xpack/plugins/cloud/serializers/account.py:58
msgid "Attrs" msgid "Attrs"
msgstr "属性" msgstr "属性"
#: applications/models/application.py:233 #: applications/models/application.py:234
msgid "Can match application" msgid "Can match application"
msgstr "匹配应用" msgstr "匹配应用"
#: applications/models/application.py:281 #: applications/models/application.py:282
msgid "Application user" msgid "Application user"
msgstr "应用用户" msgstr "应用用户"
@ -379,7 +379,7 @@ msgstr "类型名称"
#: assets/serializers/cmd_filter.py:49 common/db/models.py:113 #: assets/serializers/cmd_filter.py:49 common/db/models.py:113
#: common/mixins/models.py:50 ops/models/adhoc.py:39 ops/models/command.py:30 #: common/mixins/models.py:50 ops/models/adhoc.py:39 ops/models/command.py:30
#: orgs/models.py:67 orgs/models.py:217 perms/models/base.py:92 #: orgs/models.py:67 orgs/models.py:217 perms/models/base.py:92
#: users/models/group.py:18 users/models/user.py:841 #: users/models/group.py:18 users/models/user.py:912
#: xpack/plugins/cloud/models.py:125 #: xpack/plugins/cloud/models.py:125
msgid "Date created" msgid "Date created"
msgstr "创建日期" msgstr "创建日期"
@ -598,7 +598,7 @@ msgstr "主机名原始"
msgid "Protocols" msgid "Protocols"
msgstr "协议组" msgstr "协议组"
#: assets/models/asset.py:218 assets/models/user.py:225 #: assets/models/asset.py:218 assets/models/user.py:238
#: perms/models/asset_permission.py:24 #: perms/models/asset_permission.py:24
#: xpack/plugins/change_auth_plan/models/asset.py:43 #: xpack/plugins/change_auth_plan/models/asset.py:43
#: xpack/plugins/gathered_user/models.py:24 #: xpack/plugins/gathered_user/models.py:24
@ -611,7 +611,7 @@ msgid "Is active"
msgstr "激活" msgstr "激活"
#: assets/models/asset.py:222 assets/models/cluster.py:19 #: assets/models/asset.py:222 assets/models/cluster.py:19
#: assets/models/user.py:222 assets/models/user.py:377 #: assets/models/user.py:235 assets/models/user.py:390
msgid "Admin user" msgid "Admin user"
msgstr "特权用户" msgstr "特权用户"
@ -631,7 +631,7 @@ msgstr "标签管理"
#: assets/models/cluster.py:28 assets/models/cmd_filter.py:52 #: assets/models/cluster.py:28 assets/models/cmd_filter.py:52
#: assets/models/cmd_filter.py:99 assets/models/group.py:21 #: assets/models/cmd_filter.py:99 assets/models/group.py:21
#: common/db/models.py:111 common/mixins/models.py:49 orgs/models.py:66 #: common/db/models.py:111 common/mixins/models.py:49 orgs/models.py:66
#: orgs/models.py:219 perms/models/base.py:91 users/models/user.py:629 #: orgs/models.py:219 perms/models/base.py:91 users/models/user.py:700
#: users/serializers/group.py:33 #: users/serializers/group.py:33
#: xpack/plugins/change_auth_plan/models/base.py:48 #: xpack/plugins/change_auth_plan/models/base.py:48
#: xpack/plugins/cloud/models.py:122 xpack/plugins/gathered_user/models.py:30 #: xpack/plugins/cloud/models.py:122 xpack/plugins/gathered_user/models.py:30
@ -812,7 +812,7 @@ msgstr "带宽"
msgid "Contact" msgid "Contact"
msgstr "联系人" msgstr "联系人"
#: assets/models/cluster.py:22 users/models/user.py:604 #: assets/models/cluster.py:22 users/models/user.py:675
msgid "Phone" msgid "Phone"
msgstr "手机" msgstr "手机"
@ -838,7 +838,7 @@ msgid "Default"
msgstr "默认" msgstr "默认"
#: assets/models/cluster.py:36 assets/models/label.py:14 rbac/const.py:6 #: assets/models/cluster.py:36 assets/models/label.py:14 rbac/const.py:6
#: users/models/user.py:826 #: users/models/user.py:897
msgid "System" msgid "System"
msgstr "系统" msgstr "系统"
@ -847,7 +847,7 @@ msgid "Default Cluster"
msgstr "默认Cluster" msgstr "默认Cluster"
#: assets/models/cmd_filter.py:34 perms/models/base.py:86 #: assets/models/cmd_filter.py:34 perms/models/base.py:86
#: users/models/group.py:31 users/models/user.py:590 #: users/models/group.py:31 users/models/user.py:661
#: users/templates/users/_select_user_modal.html:16 #: users/templates/users/_select_user_modal.html:16
#: users/templates/users/user_asset_permission.html:39 #: users/templates/users/user_asset_permission.html:39
#: users/templates/users/user_asset_permission.html:67 #: users/templates/users/user_asset_permission.html:67
@ -993,77 +993,77 @@ msgstr "节点"
msgid "Can match node" msgid "Can match node"
msgstr "可以匹配节点" msgstr "可以匹配节点"
#: assets/models/user.py:216 #: assets/models/user.py:229
msgid "Automatic managed" msgid "Automatic managed"
msgstr "托管密码" msgstr "托管密码"
#: assets/models/user.py:217 #: assets/models/user.py:230
msgid "Manually input" msgid "Manually input"
msgstr "手动输入" msgstr "手动输入"
#: assets/models/user.py:221 #: assets/models/user.py:234
msgid "Common user" msgid "Common user"
msgstr "普通用户" msgstr "普通用户"
#: assets/models/user.py:224 #: assets/models/user.py:237
msgid "Username same with user" msgid "Username same with user"
msgstr "用户名与用户相同" msgstr "用户名与用户相同"
#: assets/models/user.py:227 assets/serializers/domain.py:29 #: assets/models/user.py:240 assets/serializers/domain.py:29
#: terminal/templates/terminal/_msg_command_execute_alert.html:16 #: terminal/templates/terminal/_msg_command_execute_alert.html:16
#: xpack/plugins/change_auth_plan/models/asset.py:39 #: xpack/plugins/change_auth_plan/models/asset.py:39
msgid "Assets" msgid "Assets"
msgstr "资产" msgstr "资产"
#: assets/models/user.py:231 users/apps.py:9 #: assets/models/user.py:244 users/apps.py:9
msgid "Users" msgid "Users"
msgstr "用户管理" msgstr "用户管理"
#: assets/models/user.py:232 #: assets/models/user.py:245
msgid "User groups" msgid "User groups"
msgstr "用户组" msgstr "用户组"
#: assets/models/user.py:236 #: assets/models/user.py:249
msgid "Auto push" msgid "Auto push"
msgstr "自动推送" msgstr "自动推送"
#: assets/models/user.py:237 #: assets/models/user.py:250
msgid "Sudo" msgid "Sudo"
msgstr "Sudo" msgstr "Sudo"
#: assets/models/user.py:238 #: assets/models/user.py:251
msgid "Shell" msgid "Shell"
msgstr "Shell" msgstr "Shell"
#: assets/models/user.py:239 #: assets/models/user.py:252
msgid "Login mode" msgid "Login mode"
msgstr "认证方式" msgstr "认证方式"
#: assets/models/user.py:240 #: assets/models/user.py:253
msgid "SFTP Root" msgid "SFTP Root"
msgstr "SFTP根路径" msgstr "SFTP根路径"
#: assets/models/user.py:241 authentication/models.py:48 #: assets/models/user.py:254 authentication/models.py:48
msgid "Token" msgid "Token"
msgstr "" msgstr ""
#: assets/models/user.py:242 #: assets/models/user.py:255
msgid "Home" msgid "Home"
msgstr "家目录" msgstr "家目录"
#: assets/models/user.py:243 #: assets/models/user.py:256
msgid "System groups" msgid "System groups"
msgstr "用户组" msgstr "用户组"
#: assets/models/user.py:246 #: assets/models/user.py:259
msgid "User switch" msgid "User switch"
msgstr "用户切换" msgstr "用户切换"
#: assets/models/user.py:247 #: assets/models/user.py:260
msgid "Switch from" msgid "Switch from"
msgstr "切换自" msgstr "切换自"
#: assets/models/user.py:327 #: assets/models/user.py:340
msgid "Can match system user" msgid "Can match system user"
msgstr "可以匹配系统用户" msgstr "可以匹配系统用户"
@ -1502,7 +1502,7 @@ msgstr "用户代理"
#: audits/models.py:124 #: audits/models.py:124
#: authentication/templates/authentication/_mfa_confirm_modal.html:14 #: authentication/templates/authentication/_mfa_confirm_modal.html:14
#: users/forms/profile.py:64 users/models/user.py:607 #: users/forms/profile.py:64 users/models/user.py:678
#: users/serializers/profile.py:121 #: users/serializers/profile.py:121
msgid "MFA" msgid "MFA"
msgstr "MFA" msgstr "MFA"
@ -1580,13 +1580,13 @@ msgstr "认证令牌"
#: audits/signal_handlers.py:71 authentication/notifications.py:73 #: audits/signal_handlers.py:71 authentication/notifications.py:73
#: authentication/views/login.py:164 authentication/views/wecom.py:158 #: authentication/views/login.py:164 authentication/views/wecom.py:158
#: notifications/backends/__init__.py:11 users/models/user.py:643 #: notifications/backends/__init__.py:11 users/models/user.py:714
msgid "WeCom" msgid "WeCom"
msgstr "企业微信" msgstr "企业微信"
#: audits/signal_handlers.py:72 authentication/views/dingtalk.py:160 #: audits/signal_handlers.py:72 authentication/views/dingtalk.py:160
#: authentication/views/login.py:170 notifications/backends/__init__.py:12 #: authentication/views/login.py:170 notifications/backends/__init__.py:12
#: users/models/user.py:644 #: users/models/user.py:715
msgid "DingTalk" msgid "DingTalk"
msgstr "钉钉" msgstr "钉钉"
@ -2117,14 +2117,14 @@ msgid "Show"
msgstr "显示" msgstr "显示"
#: authentication/templates/authentication/_access_key_modal.html:66 #: authentication/templates/authentication/_access_key_modal.html:66
#: settings/serializers/security.py:39 users/models/user.py:479 #: settings/serializers/security.py:39 users/models/user.py:550
#: users/serializers/profile.py:111 users/templates/users/mfa_setting.html:61 #: users/serializers/profile.py:111 users/templates/users/mfa_setting.html:61
#: users/templates/users/user_verify_mfa.html:36 #: users/templates/users/user_verify_mfa.html:36
msgid "Disable" msgid "Disable"
msgstr "禁用" msgstr "禁用"
#: authentication/templates/authentication/_access_key_modal.html:67 #: authentication/templates/authentication/_access_key_modal.html:67
#: users/models/user.py:480 users/serializers/profile.py:112 #: users/models/user.py:551 users/serializers/profile.py:112
#: users/templates/users/mfa_setting.html:26 #: users/templates/users/mfa_setting.html:26
#: users/templates/users/mfa_setting.html:68 #: users/templates/users/mfa_setting.html:68
msgid "Enable" msgid "Enable"
@ -2373,7 +2373,7 @@ msgid "The FeiShu is already bound to another user"
msgstr "该飞书已经绑定其他用户" msgstr "该飞书已经绑定其他用户"
#: authentication/views/feishu.py:148 authentication/views/login.py:176 #: authentication/views/feishu.py:148 authentication/views/login.py:176
#: notifications/backends/__init__.py:14 users/models/user.py:645 #: notifications/backends/__init__.py:14 users/models/user.py:716
msgid "FeiShu" msgid "FeiShu"
msgstr "飞书" msgstr "飞书"
@ -2668,7 +2668,7 @@ msgid "Notifications"
msgstr "通知" msgstr "通知"
#: notifications/backends/__init__.py:10 users/forms/profile.py:101 #: notifications/backends/__init__.py:10 users/forms/profile.py:101
#: users/models/user.py:586 #: users/models/user.py:657
msgid "Email" msgid "Email"
msgstr "邮件" msgstr "邮件"
@ -2880,7 +2880,7 @@ msgid "App organizations"
msgstr "组织管理" msgstr "组织管理"
#: orgs/mixins/models.py:46 orgs/mixins/serializers.py:25 orgs/models.py:80 #: orgs/mixins/models.py:46 orgs/mixins/serializers.py:25 orgs/models.py:80
#: orgs/models.py:211 rbac/const.py:7 rbac/models/rolebinding.py:46 #: orgs/models.py:211 rbac/const.py:7 rbac/models/rolebinding.py:47
#: rbac/serializers/rolebinding.py:40 tickets/serializers/ticket/ticket.py:77 #: rbac/serializers/rolebinding.py:40 tickets/serializers/ticket/ticket.py:77
msgid "Organization" msgid "Organization"
msgstr "组织" msgstr "组织"
@ -2893,8 +2893,8 @@ msgstr "全局组织"
msgid "Can view root org" msgid "Can view root org"
msgstr "可以查看全局组织" msgstr "可以查看全局组织"
#: orgs/models.py:216 rbac/models/role.py:46 rbac/models/rolebinding.py:42 #: orgs/models.py:216 rbac/models/role.py:46 rbac/models/rolebinding.py:43
#: users/models/user.py:594 users/templates/users/_select_user_modal.html:15 #: users/models/user.py:665 users/templates/users/_select_user_modal.html:15
msgid "Role" msgid "Role"
msgstr "角色" msgstr "角色"
@ -2981,7 +2981,7 @@ msgstr "剪贴板复制粘贴"
#: perms/models/base.py:90 #: perms/models/base.py:90
#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:58 #: tickets/serializers/ticket/meta/ticket_type/apply_application.py:58
#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:60 #: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:60
#: users/models/user.py:626 #: users/models/user.py:697
msgid "Date expired" msgid "Date expired"
msgstr "失效日期" msgstr "失效日期"
@ -3024,15 +3024,15 @@ msgstr "组织 ({}) 的应用授权"
#: perms/serializers/application/permission.py:20 #: perms/serializers/application/permission.py:20
#: perms/serializers/application/permission.py:41 #: perms/serializers/application/permission.py:41
#: perms/serializers/asset/permission.py:19 #: perms/serializers/asset/permission.py:19
#: perms/serializers/asset/permission.py:45 users/serializers/user.py:137 #: perms/serializers/asset/permission.py:45 users/serializers/user.py:139
msgid "Is valid" msgid "Is valid"
msgstr "账号是否有效" msgstr "账号是否有效"
#: perms/serializers/application/permission.py:21 #: perms/serializers/application/permission.py:21
#: perms/serializers/application/permission.py:40 #: perms/serializers/application/permission.py:40
#: perms/serializers/asset/permission.py:20 #: perms/serializers/asset/permission.py:20
#: perms/serializers/asset/permission.py:44 users/serializers/user.py:83 #: perms/serializers/asset/permission.py:44 users/serializers/user.py:85
#: users/serializers/user.py:139 #: users/serializers/user.py:141
msgid "Is expired" msgid "Is expired"
msgstr "已过期" msgstr "已过期"
@ -3166,7 +3166,7 @@ msgstr "文件管理"
msgid "Permission" msgid "Permission"
msgstr "权限" msgstr "权限"
#: rbac/models/role.py:31 rbac/models/rolebinding.py:36 #: rbac/models/role.py:31 rbac/models/rolebinding.py:37
msgid "Scope" msgid "Scope"
msgstr "范围" msgstr "范围"
@ -3178,29 +3178,29 @@ msgstr "授权"
msgid "Built-in" msgid "Built-in"
msgstr "内置" msgstr "内置"
#: rbac/models/role.py:127 #: rbac/models/role.py:130
msgid "System role" msgid "System role"
msgstr "系统角色" msgstr "系统角色"
#: rbac/models/role.py:135 #: rbac/models/role.py:138
msgid "Organization role" msgid "Organization role"
msgstr "组织角色" msgstr "组织角色"
#: rbac/models/rolebinding.py:51 #: rbac/models/rolebinding.py:52
msgid "Role binding" msgid "Role binding"
msgstr "角色绑定" msgstr "角色绑定"
#: rbac/models/rolebinding.py:123 #: rbac/models/rolebinding.py:128
msgid "" msgid ""
"User last role in org, can not be delete, you can remove user from org " "User last role in org, can not be delete, you can remove user from org "
"instead" "instead"
msgstr "用户最后一个角色,不能删除,你可以将用户从组织移除" msgstr "用户最后一个角色,不能删除,你可以将用户从组织移除"
#: rbac/models/rolebinding.py:130 #: rbac/models/rolebinding.py:135
msgid "Organization role binding" msgid "Organization role binding"
msgstr "组织角色绑定" msgstr "组织角色绑定"
#: rbac/models/rolebinding.py:145 #: rbac/models/rolebinding.py:150
msgid "System role binding" msgid "System role binding"
msgstr "系统角色绑定" msgstr "系统角色绑定"
@ -4176,36 +4176,64 @@ msgstr ""
"提示:如果你使用其它认证方式,如 AD/LDAP你应该禁用此项以避免第三方系统删" "提示:如果你使用其它认证方式,如 AD/LDAP你应该禁用此项以避免第三方系统删"
"除后,还可以登录" "除后,还可以登录"
#: settings/serializers/terminal.py:25 #: settings/serializers/terminal.py:26
msgid "List sort by" msgid "List sort by"
msgstr "资产列表排序" msgstr "资产列表排序"
#: settings/serializers/terminal.py:27 #: settings/serializers/terminal.py:29
msgid "List page size" msgid "List page size"
msgstr "资产列表每页数量" msgstr "资产列表每页数量"
#: settings/serializers/terminal.py:29 #: settings/serializers/terminal.py:32
msgid "Telnet login regex" msgid "Telnet login regex"
msgstr "Telnet 成功正则表达式" msgstr "Telnet 成功正则表达式"
#: settings/serializers/terminal.py:30 #: settings/serializers/terminal.py:33
msgid "" msgid ""
"The login success message varies with devices. if you cannot log in to the " "The login success message varies with devices. if you cannot log in to the "
"device through Telnet, set this parameter" "device through Telnet, set this parameter"
msgstr "不同设备登录成功提示不一样,所以如果 telnet 不能正常登录,可以这里设置" msgstr "不同设备登录成功提示不一样,所以如果 telnet 不能正常登录,可以这里设置"
#: settings/serializers/terminal.py:34 #: settings/serializers/terminal.py:37
msgid "RDP address" msgid "RDP address"
msgstr "RDP 地址" msgstr "RDP 地址"
#: settings/serializers/terminal.py:35 #: settings/serializers/terminal.py:38
msgid "RDP visit address, eg: dev.jumpserver.org:3389" msgid "RDP visit address, eg: dev.jumpserver.org:3389"
msgstr "RDP 访问地址, 如: dev.jumpserver.org:3389" msgstr "RDP 访问地址, 如: dev.jumpserver.org:3389"
#: settings/serializers/terminal.py:38 #: settings/serializers/terminal.py:40
msgid "Enable XRDP" msgid "Enable XRDP"
msgstr "启用 XRDP 服务" msgstr "启用 XRDP 服务"
#: settings/serializers/terminal.py:42
msgid "Enable database proxy"
msgstr "启用数据库组件"
#: settings/serializers/terminal.py:44
msgid "Database proxy host"
msgstr "数据库主机地址"
#: settings/serializers/terminal.py:45
msgid "Database proxy host, eg: dev.jumpserver.org"
msgstr "数据库组件地址, 如: dev.jumpserver.org (没有端口, 不同协议端口不同)"
#: settings/serializers/terminal.py:48
msgid "MySQL port"
msgstr "MySQL 协议端口"
#: settings/serializers/terminal.py:49
msgid "Database proxy MySQL protocol port"
msgstr "数据库组件 MySQL 协议监听的端口"
#: settings/serializers/terminal.py:52
msgid "PostgreSQL port"
msgstr "PostgreSQL 端口"
#: settings/serializers/terminal.py:53
msgid "Database proxy PostgreSQL port"
msgstr "数据库组件 PostgreSQL 协议监听的端口"
#: settings/utils/ldap.py:417 #: settings/utils/ldap.py:417
msgid "ldap:// or ldaps:// protocol is used." msgid "ldap:// or ldaps:// protocol is used."
msgstr "使用 ldap:// 或 ldaps:// 协议" msgstr "使用 ldap:// 或 ldaps:// 协议"
@ -5023,7 +5051,7 @@ msgstr "端点无效: 移除路径 `{}`"
msgid "Bucket" msgid "Bucket"
msgstr "桶名称" msgstr "桶名称"
#: terminal/serializers/storage.py:34 users/models/user.py:618 #: terminal/serializers/storage.py:34 users/models/user.py:689
msgid "Secret key" msgid "Secret key"
msgstr "密钥" msgstr "密钥"
@ -5081,7 +5109,7 @@ msgstr "忽略证书认证"
msgid "Load status" msgid "Load status"
msgstr "负载状态" msgstr "负载状态"
#: terminal/serializers/terminal.py:83 terminal/serializers/terminal.py:91 #: terminal/serializers/terminal.py:81 terminal/serializers/terminal.py:89
msgid "Not found" msgid "Not found"
msgstr "没有发现" msgstr "没有发现"
@ -5519,7 +5547,7 @@ msgstr "当前组织已存在该类型"
msgid "Click here to review" msgid "Click here to review"
msgstr "点击查看" msgstr "点击查看"
#: users/api/user.py:180 #: users/api/user.py:183
msgid "Could not reset self otp, use profile reset instead" msgid "Could not reset self otp, use profile reset instead"
msgstr "不能在该页面重置 MFA 多因子认证, 请去个人信息页面重置" msgstr "不能在该页面重置 MFA 多因子认证, 请去个人信息页面重置"
@ -5626,68 +5654,68 @@ msgstr "不能和原来的密钥相同"
msgid "Not a valid ssh public key" msgid "Not a valid ssh public key"
msgstr "SSH密钥不合法" msgstr "SSH密钥不合法"
#: users/forms/profile.py:160 users/models/user.py:615 #: users/forms/profile.py:160 users/models/user.py:686
#: users/templates/users/user_password_update.html:48 #: users/templates/users/user_password_update.html:48
msgid "Public key" msgid "Public key"
msgstr "SSH公钥" msgstr "SSH公钥"
#: users/models/user.py:481 #: users/models/user.py:552
msgid "Force enable" msgid "Force enable"
msgstr "强制启用" msgstr "强制启用"
#: users/models/user.py:548 #: users/models/user.py:619
msgid "Local" msgid "Local"
msgstr "数据库" msgstr "数据库"
#: users/models/user.py:596 users/serializers/user.py:138 #: users/models/user.py:667 users/serializers/user.py:140
msgid "Is service account" msgid "Is service account"
msgstr "服务账号" msgstr "服务账号"
#: users/models/user.py:598 #: users/models/user.py:669
msgid "Avatar" msgid "Avatar"
msgstr "头像" msgstr "头像"
#: users/models/user.py:601 #: users/models/user.py:672
msgid "Wechat" msgid "Wechat"
msgstr "微信" msgstr "微信"
#: users/models/user.py:612 #: users/models/user.py:683
msgid "Private key" msgid "Private key"
msgstr "ssh私钥" msgstr "ssh私钥"
#: users/models/user.py:634 #: users/models/user.py:705
msgid "Source" msgid "Source"
msgstr "来源" msgstr "来源"
#: users/models/user.py:638 #: users/models/user.py:709
msgid "Date password last updated" msgid "Date password last updated"
msgstr "最后更新密码日期" msgstr "最后更新密码日期"
#: users/models/user.py:641 #: users/models/user.py:712
msgid "Need update password" msgid "Need update password"
msgstr "需要更新密码" msgstr "需要更新密码"
#: users/models/user.py:811 #: users/models/user.py:882
msgid "Can invite user" msgid "Can invite user"
msgstr "可以邀请用户" msgstr "可以邀请用户"
#: users/models/user.py:812 #: users/models/user.py:883
msgid "Can remove user" msgid "Can remove user"
msgstr "可以移除用户" msgstr "可以移除用户"
#: users/models/user.py:813 #: users/models/user.py:884
msgid "Can match user" msgid "Can match user"
msgstr "可以匹配用户" msgstr "可以匹配用户"
#: users/models/user.py:822 #: users/models/user.py:893
msgid "Administrator" msgid "Administrator"
msgstr "管理员" msgstr "管理员"
#: users/models/user.py:825 #: users/models/user.py:896
msgid "Administrator is the super user of system" msgid "Administrator is the super user of system"
msgstr "Administrator是初始的超级管理员" msgstr "Administrator是初始的超级管理员"
#: users/models/user.py:850 #: users/models/user.py:921
msgid "User password history" msgid "User password history"
msgstr "用户密码历史" msgstr "用户密码历史"
@ -5738,7 +5766,7 @@ msgstr "新密码不能是最近 {} 次的密码"
msgid "The newly set password is inconsistent" msgid "The newly set password is inconsistent"
msgstr "两次密码不一致" msgstr "两次密码不一致"
#: users/serializers/profile.py:142 users/serializers/user.py:136 #: users/serializers/profile.py:142 users/serializers/user.py:138
msgid "Is first login" msgid "Is first login"
msgstr "首次登录" msgstr "首次登录"
@ -5750,85 +5778,85 @@ msgstr "系统角色"
msgid "Org roles" msgid "Org roles"
msgstr "组织角色" msgstr "组织角色"
#: users/serializers/user.py:75 #: users/serializers/user.py:77
#: xpack/plugins/change_auth_plan/models/base.py:35 #: xpack/plugins/change_auth_plan/models/base.py:35
#: xpack/plugins/change_auth_plan/serializers/base.py:22 #: xpack/plugins/change_auth_plan/serializers/base.py:22
msgid "Password strategy" msgid "Password strategy"
msgstr "密码策略" msgstr "密码策略"
#: users/serializers/user.py:77 #: users/serializers/user.py:79
msgid "MFA enabled" msgid "MFA enabled"
msgstr "MFA" msgstr "MFA"
#: users/serializers/user.py:78 #: users/serializers/user.py:80
msgid "MFA force enabled" msgid "MFA force enabled"
msgstr "强制 MFA" msgstr "强制 MFA"
#: users/serializers/user.py:80 #: users/serializers/user.py:82
msgid "MFA level display" msgid "MFA level display"
msgstr "MFA 等级名称" msgstr "MFA 等级名称"
#: users/serializers/user.py:82 #: users/serializers/user.py:84
msgid "Login blocked" msgid "Login blocked"
msgstr "登录被阻塞" msgstr "登录被阻塞"
#: users/serializers/user.py:85 #: users/serializers/user.py:87
msgid "Can public key authentication" msgid "Can public key authentication"
msgstr "能否公钥认证" msgstr "能否公钥认证"
#: users/serializers/user.py:140 #: users/serializers/user.py:142
msgid "Avatar url" msgid "Avatar url"
msgstr "头像路径" msgstr "头像路径"
#: users/serializers/user.py:142 #: users/serializers/user.py:144
msgid "Groups name" msgid "Groups name"
msgstr "用户组名" msgstr "用户组名"
#: users/serializers/user.py:143 #: users/serializers/user.py:145
msgid "Source name" msgid "Source name"
msgstr "用户来源名" msgstr "用户来源名"
#: users/serializers/user.py:144 #: users/serializers/user.py:146
msgid "Organization role name" msgid "Organization role name"
msgstr "组织角色名称" msgstr "组织角色名称"
#: users/serializers/user.py:145 #: users/serializers/user.py:147
msgid "Super role name" msgid "Super role name"
msgstr "超级角色名称" msgstr "超级角色名称"
#: users/serializers/user.py:146 #: users/serializers/user.py:148
msgid "Total role name" msgid "Total role name"
msgstr "汇总角色名称" msgstr "汇总角色名称"
#: users/serializers/user.py:148 #: users/serializers/user.py:150
msgid "Is wecom bound" msgid "Is wecom bound"
msgstr "是否绑定了企业微信" msgstr "是否绑定了企业微信"
#: users/serializers/user.py:149 #: users/serializers/user.py:151
msgid "Is dingtalk bound" msgid "Is dingtalk bound"
msgstr "是否绑定了钉钉" msgstr "是否绑定了钉钉"
#: users/serializers/user.py:150 #: users/serializers/user.py:152
msgid "Is feishu bound" msgid "Is feishu bound"
msgstr "是否绑定了飞书" msgstr "是否绑定了飞书"
#: users/serializers/user.py:151 #: users/serializers/user.py:153
msgid "Is OTP bound" msgid "Is OTP bound"
msgstr "是否绑定了虚拟 MFA" msgstr "是否绑定了虚拟 MFA"
#: users/serializers/user.py:153 #: users/serializers/user.py:155
msgid "System role name" msgid "System role name"
msgstr "系统角色名称" msgstr "系统角色名称"
#: users/serializers/user.py:245 #: users/serializers/user.py:247
msgid "Select users" msgid "Select users"
msgstr "选择用户" msgstr "选择用户"
#: users/serializers/user.py:246 #: users/serializers/user.py:248
msgid "For security, only list several users" msgid "For security, only list several users"
msgstr "为了安全,仅列出几个用户" msgstr "为了安全,仅列出几个用户"
#: users/serializers/user.py:279 #: users/serializers/user.py:281
msgid "name not unique" msgid "name not unique"
msgstr "名称重复" msgstr "名称重复"

View File

@ -30,19 +30,15 @@ class PublicSettingApi(generics.RetrieveAPIView):
def get_object(self): def get_object(self):
instance = { instance = {
"data": { "data": {
# Security
"WINDOWS_SKIP_ALL_MANUAL_PASSWORD": settings.WINDOWS_SKIP_ALL_MANUAL_PASSWORD, "WINDOWS_SKIP_ALL_MANUAL_PASSWORD": settings.WINDOWS_SKIP_ALL_MANUAL_PASSWORD,
"OLD_PASSWORD_HISTORY_LIMIT_COUNT": settings.OLD_PASSWORD_HISTORY_LIMIT_COUNT,
"SECURITY_MAX_IDLE_TIME": settings.SECURITY_MAX_IDLE_TIME, "SECURITY_MAX_IDLE_TIME": settings.SECURITY_MAX_IDLE_TIME,
"XPACK_ENABLED": settings.XPACK_ENABLED,
"SECURITY_VIEW_AUTH_NEED_MFA": settings.SECURITY_VIEW_AUTH_NEED_MFA, "SECURITY_VIEW_AUTH_NEED_MFA": settings.SECURITY_VIEW_AUTH_NEED_MFA,
"SECURITY_MFA_VERIFY_TTL": settings.SECURITY_MFA_VERIFY_TTL, "SECURITY_MFA_VERIFY_TTL": settings.SECURITY_MFA_VERIFY_TTL,
"OLD_PASSWORD_HISTORY_LIMIT_COUNT": settings.OLD_PASSWORD_HISTORY_LIMIT_COUNT,
"SECURITY_COMMAND_EXECUTION": settings.SECURITY_COMMAND_EXECUTION, "SECURITY_COMMAND_EXECUTION": settings.SECURITY_COMMAND_EXECUTION,
"SECURITY_PASSWORD_EXPIRATION_TIME": settings.SECURITY_PASSWORD_EXPIRATION_TIME, "SECURITY_PASSWORD_EXPIRATION_TIME": settings.SECURITY_PASSWORD_EXPIRATION_TIME,
"SECURITY_LUNA_REMEMBER_AUTH": settings.SECURITY_LUNA_REMEMBER_AUTH, "SECURITY_LUNA_REMEMBER_AUTH": settings.SECURITY_LUNA_REMEMBER_AUTH,
"XPACK_LICENSE_IS_VALID": has_valid_xpack_license(),
"XPACK_LICENSE_INFO": get_xpack_license_info(),
"LOGIN_TITLE": self.get_login_title(),
"LOGO_URLS": self.get_logo_urls(),
"PASSWORD_RULE": { "PASSWORD_RULE": {
'SECURITY_PASSWORD_MIN_LENGTH': settings.SECURITY_PASSWORD_MIN_LENGTH, 'SECURITY_PASSWORD_MIN_LENGTH': settings.SECURITY_PASSWORD_MIN_LENGTH,
'SECURITY_ADMIN_USER_PASSWORD_MIN_LENGTH': settings.SECURITY_ADMIN_USER_PASSWORD_MIN_LENGTH, 'SECURITY_ADMIN_USER_PASSWORD_MIN_LENGTH': settings.SECURITY_ADMIN_USER_PASSWORD_MIN_LENGTH,
@ -51,16 +47,30 @@ class PublicSettingApi(generics.RetrieveAPIView):
'SECURITY_PASSWORD_NUMBER': settings.SECURITY_PASSWORD_NUMBER, 'SECURITY_PASSWORD_NUMBER': settings.SECURITY_PASSWORD_NUMBER,
'SECURITY_PASSWORD_SPECIAL_CHAR': settings.SECURITY_PASSWORD_SPECIAL_CHAR, 'SECURITY_PASSWORD_SPECIAL_CHAR': settings.SECURITY_PASSWORD_SPECIAL_CHAR,
}, },
'SECURITY_WATERMARK_ENABLED': settings.SECURITY_WATERMARK_ENABLED,
'SECURITY_SESSION_SHARE': settings.SECURITY_SESSION_SHARE,
# XPACK
"XPACK_ENABLED": settings.XPACK_ENABLED,
"XPACK_LICENSE_IS_VALID": has_valid_xpack_license(),
"XPACK_LICENSE_INFO": get_xpack_license_info(),
# Performance
"LOGIN_TITLE": self.get_login_title(),
"LOGO_URLS": self.get_logo_urls(),
"HELP_DOCUMENT_URL": settings.HELP_DOCUMENT_URL,
"HELP_SUPPORT_URL": settings.HELP_SUPPORT_URL,
# Auth
"AUTH_WECOM": settings.AUTH_WECOM, "AUTH_WECOM": settings.AUTH_WECOM,
"AUTH_DINGTALK": settings.AUTH_DINGTALK, "AUTH_DINGTALK": settings.AUTH_DINGTALK,
"AUTH_FEISHU": settings.AUTH_FEISHU, "AUTH_FEISHU": settings.AUTH_FEISHU,
'SECURITY_WATERMARK_ENABLED': settings.SECURITY_WATERMARK_ENABLED, # Terminal
'SECURITY_SESSION_SHARE': settings.SECURITY_SESSION_SHARE,
"XRDP_ENABLED": settings.XRDP_ENABLED, "XRDP_ENABLED": settings.XRDP_ENABLED,
"TERMINAL_MAGNUS_ENABLED": settings.TERMINAL_MAGNUS_ENABLED,
"TERMINAL_MAGNUS_HOST": settings.TERMINAL_MAGNUS_HOST,
"TERMINAL_MAGNUS_MYSQL_PORT": settings.TERMINAL_MAGNUS_MYSQL_PORT,
"TERMINAL_MAGNUS_POSTGRE_PORT": settings.TERMINAL_MAGNUS_POSTGRE_PORT,
# Announcement
"ANNOUNCEMENT_ENABLED": settings.ANNOUNCEMENT_ENABLED, "ANNOUNCEMENT_ENABLED": settings.ANNOUNCEMENT_ENABLED,
"ANNOUNCEMENT": settings.ANNOUNCEMENT, "ANNOUNCEMENT": settings.ANNOUNCEMENT,
"HELP_DOCUMENT_URL": settings.HELP_DOCUMENT_URL,
"HELP_SUPPORT_URL": settings.HELP_SUPPORT_URL,
} }
} }
return instance return instance

View File

@ -22,9 +22,12 @@ class TerminalSettingSerializer(serializers.Serializer):
help_text=_('Tips: If use other auth method, like AD/LDAP, you should disable this to ' help_text=_('Tips: If use other auth method, like AD/LDAP, you should disable this to '
'avoid being able to log in after deleting') 'avoid being able to log in after deleting')
) )
TERMINAL_ASSET_LIST_SORT_BY = serializers.ChoiceField(SORT_BY_CHOICES, required=False, label=_('List sort by')) TERMINAL_ASSET_LIST_SORT_BY = serializers.ChoiceField(
TERMINAL_ASSET_LIST_PAGE_SIZE = serializers.ChoiceField(PAGE_SIZE_CHOICES, required=False, SORT_BY_CHOICES, required=False, label=_('List sort by')
label=_('List page size')) )
TERMINAL_ASSET_LIST_PAGE_SIZE = serializers.ChoiceField(
PAGE_SIZE_CHOICES, required=False, label=_('List page size')
)
TERMINAL_TELNET_REGEX = serializers.CharField( TERMINAL_TELNET_REGEX = serializers.CharField(
allow_blank=True, max_length=1024, required=False, label=_('Telnet login regex'), allow_blank=True, max_length=1024, required=False, label=_('Telnet login regex'),
help_text=_("The login success message varies with devices. " help_text=_("The login success message varies with devices. "
@ -34,5 +37,19 @@ class TerminalSettingSerializer(serializers.Serializer):
required=False, label=_("RDP address"), max_length=1024, allow_blank=True, required=False, label=_("RDP address"), max_length=1024, allow_blank=True,
help_text=_('RDP visit address, eg: dev.jumpserver.org:3389') help_text=_('RDP visit address, eg: dev.jumpserver.org:3389')
) )
XRDP_ENABLED = serializers.BooleanField(label=_("Enable XRDP")) XRDP_ENABLED = serializers.BooleanField(label=_("Enable XRDP"))
TERMINAL_MAGNUS_ENABLED = serializers.BooleanField(label=_("Enable database proxy"))
TERMINAL_MAGNUS_HOST = serializers.CharField(
required=False, label=_("Database proxy host"), max_length=1024, allow_blank=True,
help_text=_('Database proxy host, eg: dev.jumpserver.org')
)
TERMINAL_MAGNUS_MYSQL_PORT = serializers.IntegerField(
required=False, label=_("MySQL port"), default=33060,
help_text=_('Database proxy MySQL protocol port')
)
TERMINAL_MAGNUS_POSTGRE_PORT = serializers.IntegerField(
required=False, label=_("PostgreSQL port"), default=54320,
help_text=_('Database proxy PostgreSQL port')
)

View File

@ -3,6 +3,8 @@
import json import json
import threading import threading
from django.conf import LazySettings
from django.db.utils import ProgrammingError, OperationalError
from django.dispatch import receiver from django.dispatch import receiver
from django.db.models.signals import post_save, pre_save from django.db.models.signals import post_save, pre_save
from django.utils.functional import LazyObject from django.utils.functional import LazyObject
@ -85,3 +87,17 @@ def subscribe_settings_change(sender, **kwargs):
t = threading.Thread(target=keep_subscribe_settings_change) t = threading.Thread(target=keep_subscribe_settings_change)
t.daemon = True t.daemon = True
t.start() t.start()
@receiver(django_ready)
def monkey_patch_settings(sender, **kwargs):
def monkey_patch_getattr(self, name):
val = getattr(self._wrapped, name)
if callable(val):
val = val()
return val
try:
LazySettings.__getattr__ = monkey_patch_getattr
except (ProgrammingError, OperationalError):
pass

View File

@ -8,7 +8,7 @@ from common.utils import get_request_ip
from .. import const from .. import const
from ..models import ( from ..models import (
Terminal, Status, Session, Task, CommandStorage, ReplayStorage Terminal, Status, Task, CommandStorage, ReplayStorage
) )
@ -53,13 +53,11 @@ class TerminalSerializer(BulkModelSerializer):
'type', 'remote_addr', 'http_port', 'ssh_port', 'type', 'remote_addr', 'http_port', 'ssh_port',
'session_online', 'command_storage', 'replay_storage', 'session_online', 'command_storage', 'replay_storage',
'is_accepted', "is_active", 'is_alive', 'is_accepted', "is_active", 'is_alive',
'date_created', 'date_created', 'comment',
'comment',
] ]
fields_fk = ['status', 'status_display', 'stat'] fields_fk = ['status', 'status_display', 'stat']
fields = fields_small + fields_fk fields = fields_small + fields_fk
read_only_fields = ['type', 'date_created'] read_only_fields = ['type', 'date_created']
extra_kwargs = { extra_kwargs = {
'command_storage': {'required': True, }, 'command_storage': {'required': True, },
'replay_storage': {'required': True, }, 'replay_storage': {'required': True, },
@ -134,7 +132,7 @@ class TerminalRegistrationSerializer(serializers.ModelSerializer):
if request: if request:
instance.remote_addr = get_request_ip(request) instance.remote_addr = get_request_ip(request)
sa = self.service_account.create(validated_data) sa = self.service_account.create(validated_data)
sa.set_component_role() sa.system_roles.add_role_system_component()
instance.user = sa instance.user = sa
instance.command_storage = CommandStorage.default().name instance.command_storage = CommandStorage.default().name
instance.replay_storage = ReplayStorage.default().name instance.replay_storage = ReplayStorage.default().name

View File

@ -12,17 +12,18 @@ from django.db import models
from django.conf import settings from django.conf import settings
from django.utils import timezone from django.utils import timezone
from django.core.cache import cache from django.core.cache import cache
from django.shortcuts import reverse
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser
from django.contrib.auth.hashers import check_password from django.contrib.auth.hashers import check_password
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django.shortcuts import reverse
from orgs.utils import current_org from orgs.utils import current_org
from orgs.models import Organization from orgs.models import Organization
from rbac.const import Scope from rbac.const import Scope
from common import fields from common import fields
from common.utils import date_expired_default, get_logger, lazyproperty, random_string from common.utils import (
date_expired_default, get_logger, lazyproperty, random_string, bulk_create_with_signal
)
from ..signals import post_user_change_password, post_user_leave_org, pre_user_leave_org from ..signals import post_user_change_password, post_user_leave_org, pre_user_leave_org
__all__ = ['User', 'UserPasswordHistory'] __all__ = ['User', 'UserPasswordHistory']
@ -173,17 +174,17 @@ class RoleManager(models.Manager):
def __init__(self, user, *args, **kwargs): def __init__(self, user, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.user = user self.user = user
self.role_binding_cls = self.get_role_binding_cls()
self.role_cls = self.get_role_cls()
def get_role_binding_cls(self): @lazyproperty
def role_binding_cls(self):
from rbac.models import SystemRoleBinding, OrgRoleBinding from rbac.models import SystemRoleBinding, OrgRoleBinding
if self.scope == Scope.org: if self.scope == Scope.org:
return OrgRoleBinding return OrgRoleBinding
else: else:
return SystemRoleBinding return SystemRoleBinding
def get_role_cls(self): @lazyproperty
def role_cls(self):
from rbac.models import SystemRole, OrgRole from rbac.models import SystemRole, OrgRole
if self.scope == Scope.org: if self.scope == Scope.org:
return OrgRole return OrgRole
@ -240,17 +241,18 @@ class RoleManager(models.Manager):
items = [] items = []
for role in need_adds: for role in need_adds:
kwargs = { kwargs = {'role': role, 'user': self.user, 'scope': self.scope}
'role': role, if self.scope == Scope.org:
'user': self.user, if current_org.is_root():
'scope': self.scope continue
} else:
if self.scope == Scope.org and not current_org.is_root():
kwargs['org_id'] = current_org.id kwargs['org_id'] = current_org.id
items.append(self.role_binding_cls(**kwargs)) items.append(self.role_binding_cls(**kwargs))
try: try:
self.role_binding_cls.objects.bulk_create(items, ignore_conflicts=True) result = bulk_create_with_signal(self.role_binding_cls, items, ignore_conflicts=True)
self.user.expire_users_rbac_perms_cache()
return result
except Exception as e: except Exception as e:
logger.error('Create role binding error: {}'.format(e)) logger.error('Create role binding error: {}'.format(e))
@ -273,25 +275,15 @@ class RoleManager(models.Manager):
if not roles: if not roles:
return return
roles = self._clean_roles(roles) roles = self._clean_roles(roles)
return self.role_bindings.filter(role__in=roles).delete() deleted = self.role_bindings.filter(role__in=roles).delete()
self.user.expire_users_rbac_perms_cache()
return deleted
def cache_set(self, roles): def cache_set(self, roles):
query = self._get_queryset() query = self._get_queryset()
query._result_cache = roles query._result_cache = roles
self._cache = query self._cache = query
def remove_role_system_admin(self):
role = self.builtin_role.system_admin.get_role()
return self.remove(role)
def add_role_system_admin(self):
role = self.builtin_role.system_admin.get_role()
return self.add(role)
def add_role_system_user(self):
role = self.builtin_role.system_user.get_role()
return self.add(role)
@property @property
def builtin_role(self): def builtin_role(self):
from rbac.builtin import BuiltinRole from rbac.builtin import BuiltinRole
@ -311,6 +303,22 @@ class SystemRoleManager(RoleManager):
self.scope = Scope.system self.scope = Scope.system
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
def remove_role_system_admin(self):
role = self.builtin_role.system_admin.get_role()
return self.remove(role)
def add_role_system_admin(self):
role = self.builtin_role.system_admin.get_role()
return self.add(role)
def add_role_system_user(self):
role = self.builtin_role.system_user.get_role()
return self.add(role)
def add_role_system_component(self):
role = self.builtin_role.system_component.get_role()
self.add(role)
class RoleMixin: class RoleMixin:
objects: models.Manager objects: models.Manager
@ -403,11 +411,6 @@ class RoleMixin:
access_key = app.create_access_key() access_key = app.create_access_key()
return app, access_key return app, access_key
def set_component_role(self):
from rbac.models import Role
role = Role.BuiltinRole.system_component.get_role()
self.system_roles.add(role)
def remove(self): def remove(self):
if current_org.is_root(): if current_org.is_root():
return return