mirror of https://github.com/jumpserver/jumpserver
perf(settings): 优化settings配置 (#5515)
* stash * perf: 优化 动态seting * perf(settings): 优化settings配置 * perf: 完成终端和安全setting * perf: 修改翻译 * perf: 去掉其他位置的DYNAMIC * perf: 还原回来原来的一些代码 * perf: 优化ldap * perf: 移除dynmic config * perf: 去掉debug消息 * perf: 优化 refresh 命名 Co-authored-by: ibuler <ibuler@qq.com>pull/5541/head
parent
351d4d8123
commit
d363118911
|
@ -1,40 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from jumpserver.const import DYNAMIC
|
||||
from werkzeug.local import Local, LocalProxy
|
||||
from werkzeug.local import Local
|
||||
|
||||
thread_local = Local()
|
||||
|
||||
|
||||
def _find(attr):
|
||||
return getattr(thread_local, attr, None)
|
||||
|
||||
|
||||
class _Settings:
|
||||
pass
|
||||
|
||||
|
||||
def get_dynamic_cfg_from_thread_local():
|
||||
KEY = 'dynamic_config'
|
||||
|
||||
try:
|
||||
cfg = getattr(thread_local, KEY)
|
||||
except AttributeError:
|
||||
cfg = _Settings()
|
||||
setattr(thread_local, KEY, cfg)
|
||||
|
||||
return cfg
|
||||
|
||||
|
||||
class DynamicDefaultLocalProxy(LocalProxy):
|
||||
def __getattr__(self, item):
|
||||
try:
|
||||
value = super().__getattr__(item)
|
||||
except AttributeError:
|
||||
value = getattr(DYNAMIC, item)()
|
||||
setattr(self, item, value)
|
||||
|
||||
return value
|
||||
|
||||
|
||||
LOCAL_DYNAMIC_SETTINGS = DynamicDefaultLocalProxy(get_dynamic_cfg_from_thread_local)
|
||||
|
|
|
@ -5,16 +5,12 @@ import os
|
|||
import logging
|
||||
from collections import defaultdict
|
||||
from django.conf import settings
|
||||
from django.dispatch import receiver
|
||||
from django.core.signals import request_finished
|
||||
from django.db import connection
|
||||
from django.conf import LazySettings
|
||||
from django.db.utils import ProgrammingError, OperationalError
|
||||
|
||||
from jumpserver.utils import get_current_request
|
||||
|
||||
from .local import thread_local
|
||||
from .signals import django_ready
|
||||
|
||||
pattern = re.compile(r'FROM `(\w+)`')
|
||||
logger = logging.getLogger("jumpserver.common")
|
||||
|
@ -74,17 +70,3 @@ if settings.DEBUG and DEBUG_DB:
|
|||
request_finished.connect(on_request_finished_logging_db_query)
|
||||
else:
|
||||
request_finished.connect(on_request_finished_release_local)
|
||||
|
||||
|
||||
@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
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import redis
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
def get_redis_client(db):
|
||||
rc = redis.StrictRedis(
|
||||
host=settings.REDIS_HOST,
|
||||
port=settings.REDIS_PORT,
|
||||
password=settings.REDIS_PASSWORD,
|
||||
db=db
|
||||
)
|
||||
return rc
|
||||
|
||||
|
||||
class RedisPubSub:
|
||||
def __init__(self, ch, db=10):
|
||||
self.ch = ch
|
||||
self.redis = get_redis_client(db)
|
||||
|
||||
def subscribe(self):
|
||||
ps = self.redis.pubsub()
|
||||
ps.subscribe(self.ch)
|
||||
return ps
|
||||
|
||||
def publish(self, data):
|
||||
self.redis.publish(self.ch, data)
|
||||
return True
|
|
@ -426,98 +426,6 @@ class Config(dict):
|
|||
return self.get(item)
|
||||
|
||||
|
||||
class DynamicConfig:
|
||||
def __init__(self, static_config):
|
||||
self.static_config = static_config
|
||||
self.db_setting = None
|
||||
|
||||
def __getitem__(self, item):
|
||||
return self.dynamic(item)
|
||||
|
||||
def __getattr__(self, item):
|
||||
return self.dynamic(item)
|
||||
|
||||
def dynamic(self, item):
|
||||
return lambda: self.get(item)
|
||||
|
||||
def LOGIN_URL(self):
|
||||
return self.get('LOGIN_URL')
|
||||
|
||||
def AUTHENTICATION_BACKENDS(self):
|
||||
backends = [
|
||||
'authentication.backends.pubkey.PublicKeyAuthBackend',
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
]
|
||||
if self.get('AUTH_LDAP'):
|
||||
backends.insert(0, 'authentication.backends.ldap.LDAPAuthorizationBackend')
|
||||
if self.static_config.get('AUTH_CAS'):
|
||||
backends.insert(0, 'authentication.backends.cas.CASBackend')
|
||||
if self.static_config.get('AUTH_OPENID'):
|
||||
backends.insert(0, 'jms_oidc_rp.backends.OIDCAuthPasswordBackend')
|
||||
backends.insert(0, 'jms_oidc_rp.backends.OIDCAuthCodeBackend')
|
||||
if self.static_config.get('AUTH_RADIUS'):
|
||||
backends.insert(0, 'authentication.backends.radius.RadiusBackend')
|
||||
if self.static_config.get('AUTH_SSO'):
|
||||
backends.insert(0, 'authentication.backends.api.SSOAuthentication')
|
||||
return backends
|
||||
|
||||
def XPACK_LICENSE_IS_VALID(self):
|
||||
if not HAS_XPACK:
|
||||
return False
|
||||
try:
|
||||
from xpack.plugins.license.models import License
|
||||
return License.has_valid_license()
|
||||
except:
|
||||
return False
|
||||
|
||||
def XPACK_INTERFACE_LOGIN_TITLE(self):
|
||||
default_title = _('Welcome to the JumpServer open source fortress')
|
||||
if not HAS_XPACK:
|
||||
return default_title
|
||||
try:
|
||||
from xpack.plugins.interface.models import Interface
|
||||
return Interface.get_login_title()
|
||||
except:
|
||||
return default_title
|
||||
|
||||
def LOGO_URLS(self):
|
||||
logo_urls = {'logo_logout': static('img/logo.png'),
|
||||
'logo_index': static('img/logo_text.png'),
|
||||
'login_image': static('img/login_image.png'),
|
||||
'favicon': static('img/facio.ico')}
|
||||
if not HAS_XPACK:
|
||||
return logo_urls
|
||||
try:
|
||||
from xpack.plugins.interface.models import Interface
|
||||
obj = Interface.interface()
|
||||
if obj:
|
||||
if obj.logo_logout:
|
||||
logo_urls.update({'logo_logout': obj.logo_logout.url})
|
||||
if obj.logo_index:
|
||||
logo_urls.update({'logo_index': obj.logo_index.url})
|
||||
if obj.login_image:
|
||||
logo_urls.update({'login_image': obj.login_image.url})
|
||||
if obj.favicon:
|
||||
logo_urls.update({'favicon': obj.favicon.url})
|
||||
except:
|
||||
pass
|
||||
return logo_urls
|
||||
|
||||
def get_from_db(self, item):
|
||||
if self.db_setting is not None:
|
||||
value = self.db_setting.get(item)
|
||||
if value is not None:
|
||||
return value
|
||||
return None
|
||||
|
||||
def get(self, item):
|
||||
# 先从数据库中获取
|
||||
value = self.get_from_db(item)
|
||||
if value is not None:
|
||||
return value
|
||||
return self.static_config.get(item)
|
||||
|
||||
|
||||
class ConfigManager:
|
||||
config_class = Config
|
||||
|
||||
|
@ -694,7 +602,3 @@ class ConfigManager:
|
|||
# 对config进行兼容处理
|
||||
config.compatible()
|
||||
return config
|
||||
|
||||
@classmethod
|
||||
def get_dynamic_config(cls, config):
|
||||
return DynamicConfig(config)
|
||||
|
|
|
@ -4,12 +4,11 @@ import os
|
|||
|
||||
from .conf import ConfigManager
|
||||
|
||||
__all__ = ['BASE_DIR', 'PROJECT_DIR', 'VERSION', 'CONFIG', 'DYNAMIC']
|
||||
__all__ = ['BASE_DIR', 'PROJECT_DIR', 'VERSION', 'CONFIG']
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
PROJECT_DIR = os.path.dirname(BASE_DIR)
|
||||
VERSION = '2.0.0'
|
||||
CONFIG = ConfigManager.load_user_config()
|
||||
DYNAMIC = ConfigManager.get_dynamic_config(CONFIG)
|
||||
|
||||
|
||||
|
|
|
@ -3,21 +3,21 @@
|
|||
import os
|
||||
import ldap
|
||||
|
||||
from ..const import CONFIG, DYNAMIC, PROJECT_DIR
|
||||
from ..const import CONFIG, PROJECT_DIR
|
||||
|
||||
# OTP settings
|
||||
OTP_ISSUER_NAME = CONFIG.OTP_ISSUER_NAME
|
||||
OTP_VALID_WINDOW = CONFIG.OTP_VALID_WINDOW
|
||||
|
||||
# Auth LDAP settings
|
||||
AUTH_LDAP = DYNAMIC.AUTH_LDAP
|
||||
AUTH_LDAP_SERVER_URI = DYNAMIC.AUTH_LDAP_SERVER_URI
|
||||
AUTH_LDAP_BIND_DN = DYNAMIC.AUTH_LDAP_BIND_DN
|
||||
AUTH_LDAP_BIND_PASSWORD = DYNAMIC.AUTH_LDAP_BIND_PASSWORD
|
||||
AUTH_LDAP_SEARCH_OU = DYNAMIC.AUTH_LDAP_SEARCH_OU
|
||||
AUTH_LDAP_SEARCH_FILTER = DYNAMIC.AUTH_LDAP_SEARCH_FILTER
|
||||
AUTH_LDAP_START_TLS = DYNAMIC.AUTH_LDAP_START_TLS
|
||||
AUTH_LDAP_USER_ATTR_MAP = DYNAMIC.AUTH_LDAP_USER_ATTR_MAP
|
||||
AUTH_LDAP = CONFIG.AUTH_LDAP
|
||||
AUTH_LDAP_SERVER_URI = CONFIG.AUTH_LDAP_SERVER_URI
|
||||
AUTH_LDAP_BIND_DN = CONFIG.AUTH_LDAP_BIND_DN
|
||||
AUTH_LDAP_BIND_PASSWORD = CONFIG.AUTH_LDAP_BIND_PASSWORD
|
||||
AUTH_LDAP_SEARCH_OU = CONFIG.AUTH_LDAP_SEARCH_OU
|
||||
AUTH_LDAP_SEARCH_FILTER = CONFIG.AUTH_LDAP_SEARCH_FILTER
|
||||
AUTH_LDAP_START_TLS = CONFIG.AUTH_LDAP_START_TLS
|
||||
AUTH_LDAP_USER_ATTR_MAP = CONFIG.AUTH_LDAP_USER_ATTR_MAP
|
||||
AUTH_LDAP_USER_QUERY_FIELD = 'username'
|
||||
AUTH_LDAP_GLOBAL_OPTIONS = {
|
||||
ldap.OPT_X_TLS_REQUIRE_CERT: ldap.OPT_X_TLS_NEVER,
|
||||
|
@ -105,4 +105,17 @@ TOKEN_EXPIRATION = CONFIG.TOKEN_EXPIRATION
|
|||
LOGIN_CONFIRM_ENABLE = CONFIG.LOGIN_CONFIRM_ENABLE
|
||||
OTP_IN_RADIUS = CONFIG.OTP_IN_RADIUS
|
||||
|
||||
AUTHENTICATION_BACKENDS = DYNAMIC.AUTHENTICATION_BACKENDS
|
||||
AUTHENTICATION_BACKENDS = [
|
||||
'authentication.backends.pubkey.PublicKeyAuthBackend',
|
||||
'django.contrib.auth.backends.ModelBackend',
|
||||
]
|
||||
|
||||
if AUTH_CAS:
|
||||
AUTHENTICATION_BACKENDS.insert(0, 'authentication.backends.cas.CASBackend')
|
||||
if AUTH_OPENID:
|
||||
AUTHENTICATION_BACKENDS.insert(0, 'jms_oidc_rp.backends.OIDCAuthPasswordBackend')
|
||||
AUTHENTICATION_BACKENDS.insert(0, 'jms_oidc_rp.backends.OIDCAuthCodeBackend')
|
||||
if AUTH_RADIUS:
|
||||
AUTHENTICATION_BACKENDS.insert(0, 'authentication.backends.radius.RadiusBackend')
|
||||
if AUTH_SSO:
|
||||
AUTHENTICATION_BACKENDS.insert(0, 'authentication.backends.api.SSOAuthentication')
|
||||
|
|
|
@ -3,7 +3,7 @@ import os
|
|||
from django.urls import reverse_lazy
|
||||
|
||||
from .. import const
|
||||
from ..const import CONFIG, DYNAMIC
|
||||
from ..const import CONFIG
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
VERSION = const.VERSION
|
||||
|
@ -23,7 +23,7 @@ BOOTSTRAP_TOKEN = CONFIG.BOOTSTRAP_TOKEN
|
|||
DEBUG = CONFIG.DEBUG
|
||||
|
||||
# Absolute url for some case, for example email link
|
||||
SITE_URL = DYNAMIC.SITE_URL
|
||||
SITE_URL = CONFIG.SITE_URL
|
||||
|
||||
# LOG LEVEL
|
||||
LOG_LEVEL = CONFIG.LOG_LEVEL
|
||||
|
@ -216,14 +216,14 @@ MEDIA_ROOT = os.path.join(PROJECT_DIR, 'data', 'media').replace('\\', '/') + '/'
|
|||
FIXTURE_DIRS = [os.path.join(BASE_DIR, 'fixtures'), ]
|
||||
|
||||
# Email config
|
||||
EMAIL_HOST = DYNAMIC.EMAIL_HOST
|
||||
EMAIL_PORT = DYNAMIC.EMAIL_PORT
|
||||
EMAIL_HOST_USER = DYNAMIC.EMAIL_HOST_USER
|
||||
EMAIL_HOST_PASSWORD = DYNAMIC.EMAIL_HOST_PASSWORD
|
||||
EMAIL_FROM = DYNAMIC.EMAIL_FROM
|
||||
EMAIL_RECIPIENT = DYNAMIC.EMAIL_RECIPIENT
|
||||
EMAIL_USE_SSL = DYNAMIC.EMAIL_USE_SSL
|
||||
EMAIL_USE_TLS = DYNAMIC.EMAIL_USE_TLS
|
||||
EMAIL_HOST = CONFIG.EMAIL_HOST
|
||||
EMAIL_PORT = CONFIG.EMAIL_PORT
|
||||
EMAIL_HOST_USER = CONFIG.EMAIL_HOST_USER
|
||||
EMAIL_HOST_PASSWORD = CONFIG.EMAIL_HOST_PASSWORD
|
||||
EMAIL_FROM = CONFIG.EMAIL_FROM
|
||||
EMAIL_RECIPIENT = CONFIG.EMAIL_RECIPIENT
|
||||
EMAIL_USE_SSL = CONFIG.EMAIL_USE_SSL
|
||||
EMAIL_USE_TLS = CONFIG.EMAIL_USE_TLS
|
||||
|
||||
|
||||
# Custom User Auth model
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
from ..const import CONFIG, DYNAMIC
|
||||
from ..const import CONFIG
|
||||
|
||||
# Storage settings
|
||||
COMMAND_STORAGE = {
|
||||
|
@ -11,7 +11,7 @@ DEFAULT_TERMINAL_COMMAND_STORAGE = {
|
|||
"TYPE": "server",
|
||||
},
|
||||
}
|
||||
TERMINAL_COMMAND_STORAGE = DYNAMIC.TERMINAL_COMMAND_STORAGE or {}
|
||||
TERMINAL_COMMAND_STORAGE = CONFIG.TERMINAL_COMMAND_STORAGE or {}
|
||||
|
||||
# Server 类型的录像存储
|
||||
SERVER_REPLAY_STORAGE = CONFIG.SERVER_REPLAY_STORAGE
|
||||
|
@ -28,20 +28,20 @@ DEFAULT_TERMINAL_REPLAY_STORAGE = {
|
|||
"TYPE": "server",
|
||||
},
|
||||
}
|
||||
TERMINAL_REPLAY_STORAGE = DYNAMIC.TERMINAL_REPLAY_STORAGE
|
||||
TERMINAL_REPLAY_STORAGE = CONFIG.TERMINAL_REPLAY_STORAGE
|
||||
|
||||
# Security settings
|
||||
SECURITY_MFA_AUTH = DYNAMIC.SECURITY_MFA_AUTH
|
||||
SECURITY_COMMAND_EXECUTION = DYNAMIC.SECURITY_COMMAND_EXECUTION
|
||||
SECURITY_LOGIN_LIMIT_COUNT = DYNAMIC.SECURITY_LOGIN_LIMIT_COUNT
|
||||
SECURITY_LOGIN_LIMIT_TIME = DYNAMIC.SECURITY_LOGIN_LIMIT_TIME # Unit: minute
|
||||
SECURITY_MAX_IDLE_TIME = DYNAMIC.SECURITY_MAX_IDLE_TIME # Unit: minute
|
||||
SECURITY_PASSWORD_EXPIRATION_TIME = DYNAMIC.SECURITY_PASSWORD_EXPIRATION_TIME # Unit: day
|
||||
SECURITY_PASSWORD_MIN_LENGTH = DYNAMIC.SECURITY_PASSWORD_MIN_LENGTH # Unit: bit
|
||||
SECURITY_PASSWORD_UPPER_CASE = DYNAMIC.SECURITY_PASSWORD_UPPER_CASE
|
||||
SECURITY_PASSWORD_LOWER_CASE = DYNAMIC.SECURITY_PASSWORD_LOWER_CASE
|
||||
SECURITY_PASSWORD_NUMBER = DYNAMIC.SECURITY_PASSWORD_NUMBER
|
||||
SECURITY_PASSWORD_SPECIAL_CHAR = DYNAMIC.SECURITY_PASSWORD_SPECIAL_CHAR
|
||||
SECURITY_MFA_AUTH = CONFIG.SECURITY_MFA_AUTH
|
||||
SECURITY_COMMAND_EXECUTION = CONFIG.SECURITY_COMMAND_EXECUTION
|
||||
SECURITY_LOGIN_LIMIT_COUNT = CONFIG.SECURITY_LOGIN_LIMIT_COUNT
|
||||
SECURITY_LOGIN_LIMIT_TIME = CONFIG.SECURITY_LOGIN_LIMIT_TIME # Unit: minute
|
||||
SECURITY_MAX_IDLE_TIME = CONFIG.SECURITY_MAX_IDLE_TIME # Unit: minute
|
||||
SECURITY_PASSWORD_EXPIRATION_TIME = CONFIG.SECURITY_PASSWORD_EXPIRATION_TIME # Unit: day
|
||||
SECURITY_PASSWORD_MIN_LENGTH = CONFIG.SECURITY_PASSWORD_MIN_LENGTH # Unit: bit
|
||||
SECURITY_PASSWORD_UPPER_CASE = CONFIG.SECURITY_PASSWORD_UPPER_CASE
|
||||
SECURITY_PASSWORD_LOWER_CASE = CONFIG.SECURITY_PASSWORD_LOWER_CASE
|
||||
SECURITY_PASSWORD_NUMBER = CONFIG.SECURITY_PASSWORD_NUMBER
|
||||
SECURITY_PASSWORD_SPECIAL_CHAR = CONFIG.SECURITY_PASSWORD_SPECIAL_CHAR
|
||||
SECURITY_PASSWORD_RULES = [
|
||||
'SECURITY_PASSWORD_MIN_LENGTH',
|
||||
'SECURITY_PASSWORD_UPPER_CASE',
|
||||
|
@ -51,24 +51,24 @@ SECURITY_PASSWORD_RULES = [
|
|||
]
|
||||
SECURITY_MFA_VERIFY_TTL = CONFIG.SECURITY_MFA_VERIFY_TTL
|
||||
SECURITY_VIEW_AUTH_NEED_MFA = CONFIG.SECURITY_VIEW_AUTH_NEED_MFA
|
||||
SECURITY_SERVICE_ACCOUNT_REGISTRATION = DYNAMIC.SECURITY_SERVICE_ACCOUNT_REGISTRATION
|
||||
SECURITY_SERVICE_ACCOUNT_REGISTRATION = CONFIG.SECURITY_SERVICE_ACCOUNT_REGISTRATION
|
||||
SECURITY_LOGIN_CAPTCHA_ENABLED = CONFIG.SECURITY_LOGIN_CAPTCHA_ENABLED
|
||||
SECURITY_LOGIN_CHALLENGE_ENABLED = CONFIG.SECURITY_LOGIN_CHALLENGE_ENABLED
|
||||
SECURITY_DATA_CRYPTO_ALGO = CONFIG.SECURITY_DATA_CRYPTO_ALGO
|
||||
SECURITY_INSECURE_COMMAND = DYNAMIC.SECURITY_INSECURE_COMMAND
|
||||
SECURITY_INSECURE_COMMAND = CONFIG.SECURITY_INSECURE_COMMAND
|
||||
SECURITY_INSECURE_COMMAND_LEVEL = CONFIG.SECURITY_INSECURE_COMMAND_LEVEL
|
||||
SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER = DYNAMIC.SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER
|
||||
SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER = CONFIG.SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER
|
||||
|
||||
# Terminal other setting
|
||||
TERMINAL_PASSWORD_AUTH = DYNAMIC.TERMINAL_PASSWORD_AUTH
|
||||
TERMINAL_PUBLIC_KEY_AUTH = DYNAMIC.TERMINAL_PUBLIC_KEY_AUTH
|
||||
TERMINAL_HEARTBEAT_INTERVAL = DYNAMIC.TERMINAL_HEARTBEAT_INTERVAL
|
||||
TERMINAL_ASSET_LIST_SORT_BY = DYNAMIC.TERMINAL_ASSET_LIST_SORT_BY
|
||||
TERMINAL_ASSET_LIST_PAGE_SIZE = DYNAMIC.TERMINAL_ASSET_LIST_PAGE_SIZE
|
||||
TERMINAL_SESSION_KEEP_DURATION = DYNAMIC.TERMINAL_SESSION_KEEP_DURATION
|
||||
TERMINAL_HOST_KEY = DYNAMIC.TERMINAL_HOST_KEY
|
||||
TERMINAL_HEADER_TITLE = DYNAMIC.TERMINAL_HEADER_TITLE
|
||||
TERMINAL_TELNET_REGEX = DYNAMIC.TERMINAL_TELNET_REGEX
|
||||
TERMINAL_PASSWORD_AUTH = CONFIG.TERMINAL_PASSWORD_AUTH
|
||||
TERMINAL_PUBLIC_KEY_AUTH = CONFIG.TERMINAL_PUBLIC_KEY_AUTH
|
||||
TERMINAL_HEARTBEAT_INTERVAL = CONFIG.TERMINAL_HEARTBEAT_INTERVAL
|
||||
TERMINAL_ASSET_LIST_SORT_BY = CONFIG.TERMINAL_ASSET_LIST_SORT_BY
|
||||
TERMINAL_ASSET_LIST_PAGE_SIZE = CONFIG.TERMINAL_ASSET_LIST_PAGE_SIZE
|
||||
TERMINAL_SESSION_KEEP_DURATION = CONFIG.TERMINAL_SESSION_KEEP_DURATION
|
||||
TERMINAL_HOST_KEY = CONFIG.TERMINAL_HOST_KEY
|
||||
TERMINAL_HEADER_TITLE = CONFIG.TERMINAL_HEADER_TITLE
|
||||
TERMINAL_TELNET_REGEX = CONFIG.TERMINAL_TELNET_REGEX
|
||||
|
||||
# User or user group permission cache time, default 3600 seconds
|
||||
ASSETS_PERM_CACHE_ENABLE = CONFIG.ASSETS_PERM_CACHE_ENABLE
|
||||
|
@ -90,32 +90,25 @@ PERIOD_TASK_ENABLED = CONFIG.PERIOD_TASK_ENABLED
|
|||
USER_LOGIN_SINGLE_MACHINE_ENABLED = CONFIG.USER_LOGIN_SINGLE_MACHINE_ENABLED
|
||||
|
||||
# Email custom content
|
||||
EMAIL_SUBJECT_PREFIX = DYNAMIC.EMAIL_SUBJECT_PREFIX
|
||||
EMAIL_SUFFIX = DYNAMIC.EMAIL_SUFFIX
|
||||
EMAIL_CUSTOM_USER_CREATED_SUBJECT = DYNAMIC.EMAIL_CUSTOM_USER_CREATED_SUBJECT
|
||||
EMAIL_CUSTOM_USER_CREATED_HONORIFIC = DYNAMIC.EMAIL_CUSTOM_USER_CREATED_HONORIFIC
|
||||
EMAIL_CUSTOM_USER_CREATED_BODY = DYNAMIC.EMAIL_CUSTOM_USER_CREATED_BODY
|
||||
EMAIL_CUSTOM_USER_CREATED_SIGNATURE = DYNAMIC.EMAIL_CUSTOM_USER_CREATED_SIGNATURE
|
||||
EMAIL_SUBJECT_PREFIX = CONFIG.EMAIL_SUBJECT_PREFIX
|
||||
EMAIL_SUFFIX = CONFIG.EMAIL_SUFFIX
|
||||
EMAIL_CUSTOM_USER_CREATED_SUBJECT = CONFIG.EMAIL_CUSTOM_USER_CREATED_SUBJECT
|
||||
EMAIL_CUSTOM_USER_CREATED_HONORIFIC = CONFIG.EMAIL_CUSTOM_USER_CREATED_HONORIFIC
|
||||
EMAIL_CUSTOM_USER_CREATED_BODY = CONFIG.EMAIL_CUSTOM_USER_CREATED_BODY
|
||||
EMAIL_CUSTOM_USER_CREATED_SIGNATURE = CONFIG.EMAIL_CUSTOM_USER_CREATED_SIGNATURE
|
||||
|
||||
DISPLAY_PER_PAGE = CONFIG.DISPLAY_PER_PAGE
|
||||
DEFAULT_EXPIRED_YEARS = 70
|
||||
USER_GUIDE_URL = DYNAMIC.USER_GUIDE_URL
|
||||
USER_GUIDE_URL = CONFIG.USER_GUIDE_URL
|
||||
HTTP_LISTEN_PORT = CONFIG.HTTP_LISTEN_PORT
|
||||
WS_LISTEN_PORT = CONFIG.WS_LISTEN_PORT
|
||||
LOGIN_LOG_KEEP_DAYS = DYNAMIC.LOGIN_LOG_KEEP_DAYS
|
||||
LOGIN_LOG_KEEP_DAYS = CONFIG.LOGIN_LOG_KEEP_DAYS
|
||||
TASK_LOG_KEEP_DAYS = CONFIG.TASK_LOG_KEEP_DAYS
|
||||
ORG_CHANGE_TO_URL = CONFIG.ORG_CHANGE_TO_URL
|
||||
WINDOWS_SKIP_ALL_MANUAL_PASSWORD = CONFIG.WINDOWS_SKIP_ALL_MANUAL_PASSWORD
|
||||
|
||||
AUTH_EXPIRED_SECONDS = 60 * 5
|
||||
|
||||
# XPACK
|
||||
XPACK_LICENSE_IS_VALID = DYNAMIC.XPACK_LICENSE_IS_VALID
|
||||
|
||||
XPACK_INTERFACE_LOGIN_TITLE = DYNAMIC.XPACK_INTERFACE_LOGIN_TITLE
|
||||
|
||||
LOGO_URLS = DYNAMIC.LOGO_URLS
|
||||
|
||||
CHANGE_AUTH_PLAN_SECURE_MODE_ENABLED = CONFIG.CHANGE_AUTH_PLAN_SECURE_MODE_ENABLED
|
||||
|
||||
DATETIME_DISPLAY_FORMAT = '%Y-%m-%d %H:%M:%S'
|
||||
|
|
|
@ -127,3 +127,8 @@ CELERY_WORKER_REDIRECT_STDOUTS_LEVEL = "INFO"
|
|||
CELERY_TASK_SOFT_TIME_LIMIT = 3600
|
||||
|
||||
ANSIBLE_LOG_DIR = os.path.join(PROJECT_DIR, 'data', 'ansible')
|
||||
|
||||
#
|
||||
REDIS_HOST = CONFIG.REDIS_HOST
|
||||
REDIS_PORT = CONFIG.REDIS_PORT
|
||||
REDIS_PASSWORD = CONFIG.REDIS_PASSWORD
|
||||
|
|
Binary file not shown.
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: JumpServer 0.3.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-01-21 15:49+0800\n"
|
||||
"POT-Creation-Date: 2021-01-26 17:25+0800\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
||||
"Language-Team: JumpServer team<ibuler@qq.com>\n"
|
||||
|
@ -36,10 +36,10 @@ msgstr "自定义"
|
|||
#: assets/models/base.py:234 assets/models/cluster.py:18
|
||||
#: assets/models/cmd_filter.py:21 assets/models/domain.py:21
|
||||
#: assets/models/group.py:20 assets/models/label.py:18 ops/mixin.py:24
|
||||
#: orgs/models.py:23 perms/models/base.py:48 settings/models.py:27
|
||||
#: orgs/models.py:23 perms/models/base.py:48 settings/models.py:29
|
||||
#: terminal/models/storage.py:15 terminal/models/storage.py:55
|
||||
#: terminal/models/task.py:16 terminal/models/terminal.py:131
|
||||
#: users/forms/profile.py:20 users/models/group.py:15 users/models/user.py:518
|
||||
#: users/forms/profile.py:20 users/models/group.py:15 users/models/user.py:517
|
||||
#: users/templates/users/_select_user_modal.html:13
|
||||
#: users/templates/users/user_asset_permission.html:37
|
||||
#: users/templates/users/user_asset_permission.html:154
|
||||
|
@ -95,10 +95,10 @@ msgstr ""
|
|||
#: assets/models/cmd_filter.py:57 assets/models/domain.py:22
|
||||
#: assets/models/domain.py:56 assets/models/group.py:23
|
||||
#: assets/models/label.py:23 ops/models/adhoc.py:37 orgs/models.py:26
|
||||
#: perms/models/base.py:56 settings/models.py:32 terminal/models/storage.py:21
|
||||
#: perms/models/base.py:56 settings/models.py:34 terminal/models/storage.py:21
|
||||
#: terminal/models/storage.py:61 terminal/models/terminal.py:145
|
||||
#: tickets/models/ticket.py:73 users/models/group.py:16
|
||||
#: users/models/user.py:551 users/templates/users/user_detail.html:115
|
||||
#: users/models/user.py:550 users/templates/users/user_detail.html:115
|
||||
#: users/templates/users/user_granted_database_app.html:38
|
||||
#: users/templates/users/user_granted_remote_app.html:37
|
||||
#: users/templates/users/user_group_detail.html:62
|
||||
|
@ -164,7 +164,7 @@ msgstr "目标URL"
|
|||
#: assets/models/base.py:235 assets/models/gathered_user.py:15
|
||||
#: audits/models.py:99 authentication/forms.py:11
|
||||
#: authentication/templates/authentication/login.html:101
|
||||
#: ops/models/adhoc.py:148 users/forms/profile.py:19 users/models/user.py:516
|
||||
#: ops/models/adhoc.py:148 users/forms/profile.py:19 users/models/user.py:515
|
||||
#: users/templates/users/_select_user_modal.html:14
|
||||
#: users/templates/users/user_detail.html:53
|
||||
#: users/templates/users/user_list.html:15
|
||||
|
@ -181,7 +181,8 @@ msgstr "用户名"
|
|||
#: assets/models/base.py:236 assets/serializers/asset_user.py:71
|
||||
#: audits/signals_handler.py:42 authentication/forms.py:13
|
||||
#: authentication/templates/authentication/login.html:109
|
||||
#: users/forms/user.py:22 users/forms/user.py:193
|
||||
#: settings/serializers/settings.py:84 users/forms/user.py:22
|
||||
#: users/forms/user.py:193
|
||||
#: users/templates/users/user_otp_check_password.html:13
|
||||
#: users/templates/users/user_password_update.html:43
|
||||
#: users/templates/users/user_password_verify.html:18
|
||||
|
@ -204,7 +205,7 @@ msgstr "目标URL"
|
|||
|
||||
#: applications/serializers/attrs/application_type/mysql_workbench.py:18
|
||||
#: assets/models/asset.py:190 assets/models/domain.py:52
|
||||
#: assets/serializers/asset_user.py:46 settings/serializers/settings.py:52
|
||||
#: assets/serializers/asset_user.py:46 settings/serializers/settings.py:103
|
||||
#: users/templates/users/_granted_assets.html:26
|
||||
#: users/templates/users/user_asset_permission.html:156
|
||||
msgid "IP"
|
||||
|
@ -260,7 +261,7 @@ msgid "Platform"
|
|||
msgstr "系统平台"
|
||||
|
||||
#: assets/models/asset.py:191 assets/serializers/asset_user.py:45
|
||||
#: assets/serializers/gathered_user.py:20 settings/serializers/settings.py:51
|
||||
#: assets/serializers/gathered_user.py:20 settings/serializers/settings.py:102
|
||||
#: users/templates/users/_granted_assets.html:25
|
||||
#: users/templates/users/user_asset_permission.html:157
|
||||
msgid "Hostname"
|
||||
|
@ -368,7 +369,7 @@ msgstr "标签管理"
|
|||
#: assets/models/cluster.py:28 assets/models/cmd_filter.py:26
|
||||
#: assets/models/cmd_filter.py:60 assets/models/group.py:21
|
||||
#: common/db/models.py:67 common/mixins/models.py:49 orgs/models.py:24
|
||||
#: orgs/models.py:427 perms/models/base.py:54 users/models/user.py:559
|
||||
#: orgs/models.py:427 perms/models/base.py:54 users/models/user.py:558
|
||||
#: users/serializers/group.py:35 users/templates/users/user_detail.html:97
|
||||
#: xpack/plugins/change_auth_plan/models.py:81 xpack/plugins/cloud/models.py:58
|
||||
#: xpack/plugins/cloud/models.py:156 xpack/plugins/gathered_user/models.py:30
|
||||
|
@ -430,7 +431,7 @@ msgstr "带宽"
|
|||
msgid "Contact"
|
||||
msgstr "联系人"
|
||||
|
||||
#: assets/models/cluster.py:22 users/models/user.py:537
|
||||
#: assets/models/cluster.py:22 users/models/user.py:536
|
||||
#: users/templates/users/user_detail.html:62
|
||||
msgid "Phone"
|
||||
msgstr "手机"
|
||||
|
@ -456,7 +457,7 @@ msgid "Default"
|
|||
msgstr "默认"
|
||||
|
||||
#: assets/models/cluster.py:36 assets/models/label.py:14
|
||||
#: users/models/user.py:678
|
||||
#: users/models/user.py:677
|
||||
msgid "System"
|
||||
msgstr "系统"
|
||||
|
||||
|
@ -560,7 +561,7 @@ msgstr "默认资产组"
|
|||
#: templates/index.html:78 terminal/backends/command/models.py:18
|
||||
#: terminal/backends/command/serializers.py:12 terminal/models/session.py:37
|
||||
#: tickets/models/comment.py:17 users/forms/group.py:15
|
||||
#: users/models/user.py:159 users/models/user.py:666
|
||||
#: users/models/user.py:158 users/models/user.py:665
|
||||
#: users/serializers/group.py:20
|
||||
#: users/templates/users/user_asset_permission.html:38
|
||||
#: users/templates/users/user_asset_permission.html:64
|
||||
|
@ -574,7 +575,7 @@ msgstr "默认资产组"
|
|||
msgid "User"
|
||||
msgstr "用户"
|
||||
|
||||
#: assets/models/label.py:19 assets/models/node.py:413 settings/models.py:28
|
||||
#: assets/models/label.py:19 assets/models/node.py:413 settings/models.py:30
|
||||
msgid "Value"
|
||||
msgstr "值"
|
||||
|
||||
|
@ -741,14 +742,14 @@ msgid "Backend"
|
|||
msgstr "后端"
|
||||
|
||||
#: assets/serializers/asset_user.py:75 users/forms/profile.py:148
|
||||
#: users/models/user.py:548 users/templates/users/user_password_update.html:48
|
||||
#: users/models/user.py:547 users/templates/users/user_password_update.html:48
|
||||
#: users/templates/users/user_profile.html:69
|
||||
#: users/templates/users/user_profile_update.html:46
|
||||
#: users/templates/users/user_pubkey_update.html:46
|
||||
msgid "Public key"
|
||||
msgstr "SSH公钥"
|
||||
|
||||
#: assets/serializers/asset_user.py:79 users/models/user.py:545
|
||||
#: assets/serializers/asset_user.py:79 users/models/user.py:544
|
||||
msgid "Private key"
|
||||
msgstr "ssh私钥"
|
||||
|
||||
|
@ -1045,7 +1046,7 @@ msgstr "修改者"
|
|||
msgid "Disabled"
|
||||
msgstr "禁用"
|
||||
|
||||
#: audits/models.py:90 settings/models.py:31
|
||||
#: audits/models.py:90 settings/models.py:33
|
||||
#: users/templates/users/user_detail.html:82
|
||||
msgid "Enabled"
|
||||
msgstr "启用"
|
||||
|
@ -1079,7 +1080,7 @@ msgstr "用户代理"
|
|||
#: audits/models.py:104
|
||||
#: authentication/templates/authentication/_mfa_confirm_modal.html:14
|
||||
#: authentication/templates/authentication/login_otp.html:6
|
||||
#: users/forms/profile.py:52 users/models/user.py:540
|
||||
#: users/forms/profile.py:52 users/models/user.py:539
|
||||
#: users/serializers/user.py:232 users/templates/users/user_detail.html:77
|
||||
#: users/templates/users/user_profile.html:87
|
||||
msgid "MFA"
|
||||
|
@ -1354,7 +1355,7 @@ msgid "Show"
|
|||
msgstr "显示"
|
||||
|
||||
#: authentication/templates/authentication/_access_key_modal.html:66
|
||||
#: users/models/user.py:444 users/serializers/user.py:229
|
||||
#: users/models/user.py:443 users/serializers/user.py:229
|
||||
#: users/templates/users/user_profile.html:94
|
||||
#: users/templates/users/user_profile.html:163
|
||||
#: users/templates/users/user_profile.html:166
|
||||
|
@ -1363,7 +1364,7 @@ msgid "Disable"
|
|||
msgstr "禁用"
|
||||
|
||||
#: authentication/templates/authentication/_access_key_modal.html:67
|
||||
#: users/models/user.py:445 users/serializers/user.py:230
|
||||
#: users/models/user.py:444 users/serializers/user.py:230
|
||||
#: users/templates/users/user_profile.html:92
|
||||
#: users/templates/users/user_profile.html:170
|
||||
msgid "Enable"
|
||||
|
@ -1600,11 +1601,6 @@ msgstr "字段必须唯一"
|
|||
msgid "Should not contains special characters"
|
||||
msgstr "不能包含特殊字符"
|
||||
|
||||
#: jumpserver/conf.py:474 xpack/plugins/interface/api.py:18
|
||||
#: xpack/plugins/interface/models.py:36
|
||||
msgid "Welcome to the JumpServer open source fortress"
|
||||
msgstr "欢迎使用JumpServer开源堡垒机"
|
||||
|
||||
#: jumpserver/views/celery_flower.py:23
|
||||
msgid "<h1>Flow service unavailable, check it</h1>"
|
||||
msgstr ""
|
||||
|
@ -1813,7 +1809,7 @@ msgstr "组织管理员"
|
|||
msgid "Organization auditor"
|
||||
msgstr "组织审计员"
|
||||
|
||||
#: orgs/models.py:424 users/forms/user.py:27 users/models/user.py:528
|
||||
#: orgs/models.py:424 users/forms/user.py:27 users/models/user.py:527
|
||||
#: users/templates/users/_select_user_modal.html:15
|
||||
#: users/templates/users/user_detail.html:73
|
||||
#: users/templates/users/user_list.html:16
|
||||
|
@ -1837,7 +1833,7 @@ msgstr "管理员正在修改授权,请稍等"
|
|||
msgid "The authorization cannot be revoked for the time being"
|
||||
msgstr "该授权暂时不能撤销"
|
||||
|
||||
#: perms/models/application_permission.py:27 users/models/user.py:160
|
||||
#: perms/models/application_permission.py:27 users/models/user.py:159
|
||||
msgid "Application"
|
||||
msgstr "应用程序"
|
||||
|
||||
|
@ -1845,7 +1841,7 @@ msgstr "应用程序"
|
|||
msgid "Application permission"
|
||||
msgstr "应用管理"
|
||||
|
||||
#: perms/models/asset_permission.py:34 settings/serializers/settings.py:56
|
||||
#: perms/models/asset_permission.py:34 settings/serializers/settings.py:107
|
||||
msgid "All"
|
||||
msgstr "全部"
|
||||
|
||||
|
@ -1887,7 +1883,7 @@ msgid "Asset permission"
|
|||
msgstr "资产授权"
|
||||
|
||||
#: perms/models/base.py:50 templates/_nav.html:21 users/forms/user.py:168
|
||||
#: users/models/group.py:31 users/models/user.py:524
|
||||
#: users/models/group.py:31 users/models/user.py:523
|
||||
#: users/templates/users/_select_user_modal.html:16
|
||||
#: users/templates/users/user_asset_permission.html:39
|
||||
#: users/templates/users/user_asset_permission.html:67
|
||||
|
@ -1905,7 +1901,7 @@ msgstr "用户组"
|
|||
#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:77
|
||||
#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:43
|
||||
#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:81
|
||||
#: users/models/user.py:556 users/templates/users/user_detail.html:93
|
||||
#: users/models/user.py:555 users/templates/users/user_detail.html:93
|
||||
#: users/templates/users/user_profile.html:120
|
||||
msgid "Date expired"
|
||||
msgstr "失效日期"
|
||||
|
@ -1944,27 +1940,310 @@ msgstr "收藏夹"
|
|||
msgid "Please wait while your data is being initialized"
|
||||
msgstr "数据正在初始化,请稍等"
|
||||
|
||||
#: settings/api.py:34
|
||||
#: settings/api/common.py:24
|
||||
msgid "Test mail sent to {}, please check"
|
||||
msgstr "邮件已经发送{}, 请检查"
|
||||
|
||||
#: settings/api.py:244
|
||||
#: settings/api/common.py:110 xpack/plugins/interface/api.py:18
|
||||
#: xpack/plugins/interface/models.py:36
|
||||
msgid "Welcome to the JumpServer open source fortress"
|
||||
msgstr "欢迎使用JumpServer开源堡垒机"
|
||||
|
||||
#: settings/api/ldap.py:189
|
||||
msgid "Get ldap users is None"
|
||||
msgstr "获取 LDAP 用户为 None"
|
||||
|
||||
#: settings/api.py:251
|
||||
#: settings/api/ldap.py:196
|
||||
msgid "Imported {} users successfully"
|
||||
msgstr "导入 {} 个用户成功"
|
||||
|
||||
#: settings/models.py:96 users/templates/users/reset_password.html:29
|
||||
#: settings/models.py:123 users/templates/users/reset_password.html:29
|
||||
#: users/templates/users/user_profile.html:20
|
||||
msgid "Setting"
|
||||
msgstr "设置"
|
||||
|
||||
#: settings/serializers/settings.py:57
|
||||
#: settings/serializers/settings.py:15
|
||||
msgid "Site url"
|
||||
msgstr "当前站点URL"
|
||||
|
||||
#: settings/serializers/settings.py:16
|
||||
msgid "eg: http://demo.jumpserver.org:8080"
|
||||
msgstr "如: http://demo.jumpserver.org:8080"
|
||||
|
||||
#: settings/serializers/settings.py:19
|
||||
msgid "User guide url"
|
||||
msgstr "用户向导URL"
|
||||
|
||||
#: settings/serializers/settings.py:20
|
||||
msgid "User first login update profile done redirect to it"
|
||||
msgstr "用户第一次登录,修改profile后重定向到地址, 可以是 wiki 或 其他说明文档"
|
||||
|
||||
#: settings/serializers/settings.py:27
|
||||
msgid "SMTP host"
|
||||
msgstr "SMTP 主机"
|
||||
|
||||
#: settings/serializers/settings.py:28
|
||||
msgid "SMTP port"
|
||||
msgstr "SMTP 端口"
|
||||
|
||||
#: settings/serializers/settings.py:29
|
||||
msgid "SMTP account"
|
||||
msgstr "SMTP 账号"
|
||||
|
||||
#: settings/serializers/settings.py:31
|
||||
msgid "SMTP password"
|
||||
msgstr "SMTP 密码"
|
||||
|
||||
#: settings/serializers/settings.py:32
|
||||
msgid "Tips: Some provider use token except password"
|
||||
msgstr "提示:一些邮件提供商需要输入的是授权码"
|
||||
|
||||
#: settings/serializers/settings.py:35
|
||||
msgid "Send user"
|
||||
msgstr "发件人"
|
||||
|
||||
#: settings/serializers/settings.py:36
|
||||
msgid "Tips: Send mail account, default SMTP account as the send account"
|
||||
msgstr "提示:发送邮件账号,默认使用 SMTP 账号作为发送账号"
|
||||
|
||||
#: settings/serializers/settings.py:39
|
||||
msgid "Test recipient"
|
||||
msgstr "测试收件人"
|
||||
|
||||
#: settings/serializers/settings.py:40
|
||||
msgid "Tips: Used only as a test mail recipient"
|
||||
msgstr "提示:仅用来作为测试邮件收件人"
|
||||
|
||||
#: settings/serializers/settings.py:43
|
||||
msgid "Use SSL"
|
||||
msgstr "使用 SSL"
|
||||
|
||||
#: settings/serializers/settings.py:44
|
||||
msgid "If SMTP port is 465, may be select"
|
||||
msgstr "如果SMTP端口是465,通常需要启用 SSL"
|
||||
|
||||
#: settings/serializers/settings.py:47
|
||||
msgid "Use TLS"
|
||||
msgstr "使用 TLS"
|
||||
|
||||
#: settings/serializers/settings.py:48
|
||||
msgid "If SMTP port is 587, may be select"
|
||||
msgstr "如果SMTP端口是587,通常需要启用 TLS"
|
||||
|
||||
#: settings/serializers/settings.py:51
|
||||
msgid "Subject prefix"
|
||||
msgstr "主题前缀"
|
||||
|
||||
#: settings/serializers/settings.py:58
|
||||
msgid "Create user email subject"
|
||||
msgstr "邮件主题"
|
||||
|
||||
#: settings/serializers/settings.py:59
|
||||
msgid ""
|
||||
"Tips: When creating a user, send the subject of the email (eg:Create account "
|
||||
"successfully)"
|
||||
msgstr "提示: 创建用户时,发送设置密码邮件的主题 (例如: 创建用户成功)"
|
||||
|
||||
#: settings/serializers/settings.py:63
|
||||
msgid "Create user honorific"
|
||||
msgstr "邮件的敬语"
|
||||
|
||||
#: settings/serializers/settings.py:64
|
||||
msgid "Tips: When creating a user, send the honorific of the email (eg:Hello)"
|
||||
msgstr "提示: 创建用户时,发送设置密码邮件的敬语 (例如: 您好)"
|
||||
|
||||
#: settings/serializers/settings.py:68
|
||||
msgid "Create user email content"
|
||||
msgstr "邮件的内容"
|
||||
|
||||
#: settings/serializers/settings.py:69
|
||||
msgid "Tips:When creating a user, send the content of the email"
|
||||
msgstr "提示: 创建用户时,发送设置密码邮件的内容"
|
||||
|
||||
#: settings/serializers/settings.py:72
|
||||
msgid "Signature"
|
||||
msgstr "署名"
|
||||
|
||||
#: settings/serializers/settings.py:73
|
||||
msgid "Tips: Email signature (eg:jumpserver)"
|
||||
msgstr "邮件署名 (如:jumpserver)"
|
||||
|
||||
#: settings/serializers/settings.py:81
|
||||
msgid "LDAP server"
|
||||
msgstr "LDAP 地址"
|
||||
|
||||
#: settings/serializers/settings.py:81
|
||||
msgid "eg: ldap://localhost:389"
|
||||
msgstr ""
|
||||
|
||||
#: settings/serializers/settings.py:83
|
||||
msgid "Bind DN"
|
||||
msgstr "绑定 DN"
|
||||
|
||||
#: settings/serializers/settings.py:86
|
||||
msgid "User OU"
|
||||
msgstr "用户 OU"
|
||||
|
||||
#: settings/serializers/settings.py:87
|
||||
msgid "Use | split multi OUs"
|
||||
msgstr "多个 OU 使用 | 分割"
|
||||
|
||||
#: settings/serializers/settings.py:90
|
||||
msgid "User search filter"
|
||||
msgstr "用户过滤器"
|
||||
|
||||
#: settings/serializers/settings.py:91
|
||||
#, python-format
|
||||
msgid "Choice may be (cn|uid|sAMAccountName)=%(user)s)"
|
||||
msgstr "可能的选项是(cn或uid或sAMAccountName=%(user)s)"
|
||||
|
||||
#: settings/serializers/settings.py:94
|
||||
msgid "User attr map"
|
||||
msgstr "用户属性映射"
|
||||
|
||||
#: settings/serializers/settings.py:95
|
||||
msgid ""
|
||||
"User attr map present how to map LDAP user attr to jumpserver, username,name,"
|
||||
"email is jumpserver attr"
|
||||
msgstr ""
|
||||
"用户属性映射代表怎样将LDAP中用户属性映射到jumpserver用户上,username, name,"
|
||||
"email 是jumpserver的用户需要属性"
|
||||
|
||||
#: settings/serializers/settings.py:97
|
||||
msgid "Enable LDAP auth"
|
||||
msgstr "启用 LDAP 认证"
|
||||
|
||||
#: settings/serializers/settings.py:108
|
||||
msgid "Auto"
|
||||
msgstr "自动"
|
||||
|
||||
#: settings/serializers/settings.py:114
|
||||
msgid "Password auth"
|
||||
msgstr "密码认证"
|
||||
|
||||
#: settings/serializers/settings.py:115
|
||||
msgid "Public key auth"
|
||||
msgstr "密钥认证"
|
||||
|
||||
#: settings/serializers/settings.py:116
|
||||
msgid "List sort by"
|
||||
msgstr "资产列表排序"
|
||||
|
||||
#: settings/serializers/settings.py:117
|
||||
msgid "List page size"
|
||||
msgstr "资产列表每页数量"
|
||||
|
||||
#: settings/serializers/settings.py:119
|
||||
msgid "Session keep duration"
|
||||
msgstr "会话日志保存时间"
|
||||
|
||||
#: settings/serializers/settings.py:120
|
||||
msgid ""
|
||||
"Units: days, Session, record, command will be delete if more than duration, "
|
||||
"only in database"
|
||||
msgstr ""
|
||||
"单位:天。 会话、录像、命令记录超过该时长将会被删除(仅影响数据库存储, oss等不"
|
||||
"受影响)"
|
||||
|
||||
#: settings/serializers/settings.py:122
|
||||
msgid "Telnet login regex"
|
||||
msgstr "Telnet 成功正则表达式"
|
||||
|
||||
#: settings/serializers/settings.py:127
|
||||
msgid "Global MFA auth"
|
||||
msgstr "全局启用 MFA 认证"
|
||||
|
||||
#: settings/serializers/settings.py:128
|
||||
msgid "All user enable MFA"
|
||||
msgstr "强制每个启用多因子认证"
|
||||
|
||||
#: settings/serializers/settings.py:131
|
||||
msgid "Batch command execution"
|
||||
msgstr "批量命令执行"
|
||||
|
||||
#: settings/serializers/settings.py:132
|
||||
msgid "Allow user run batch command or not using ansible"
|
||||
msgstr "是否允许用户使用 ansible 执行批量命令"
|
||||
|
||||
#: settings/serializers/settings.py:135
|
||||
msgid "Enable terminal register"
|
||||
msgstr "终端注册"
|
||||
|
||||
#: settings/serializers/settings.py:136
|
||||
msgid ""
|
||||
"Allow terminal register, after all terminal setup, you should disable this "
|
||||
"for security"
|
||||
msgstr "是否允许终端注册,当所有终端启动后,为了安全应该关闭"
|
||||
|
||||
#: settings/serializers/settings.py:140
|
||||
msgid "Limit the number of login failures"
|
||||
msgstr "限制登录失败次数"
|
||||
|
||||
#: settings/serializers/settings.py:144
|
||||
msgid "Block logon interval"
|
||||
msgstr "禁止登录时间间隔"
|
||||
|
||||
#: settings/serializers/settings.py:145
|
||||
msgid ""
|
||||
"Tip: (unit/minute) if the user has failed to log in for a limited number of "
|
||||
"times, no login is allowed during this time interval."
|
||||
msgstr ""
|
||||
"提示:(单位:分)当用户登录失败次数达到限制后,那么在此时间间隔内禁止登录"
|
||||
|
||||
#: settings/serializers/settings.py:149
|
||||
msgid "Connection max idle time"
|
||||
msgstr "连接最大空闲时间"
|
||||
|
||||
#: settings/serializers/settings.py:150
|
||||
msgid "If idle time more than it, disconnect connection Unit: minute"
|
||||
msgstr "提示:如果超过该配置没有操作,连接会被断开 (单位:分)"
|
||||
|
||||
#: settings/serializers/settings.py:154
|
||||
msgid "User password expiration"
|
||||
msgstr "用户密码过期时间"
|
||||
|
||||
#: settings/serializers/settings.py:155
|
||||
msgid ""
|
||||
"Tip: (unit: day) If the user does not update the password during the time, "
|
||||
"the user password will expire failure;The password expiration reminder mail "
|
||||
"will be automatic sent to the user by system within 5 days (daily) before "
|
||||
"the password expires"
|
||||
msgstr ""
|
||||
"提示:(单位:天)如果用户在此期间没有更新密码,用户密码将过期失效; 密码过期"
|
||||
"提醒邮件将在密码过期前5天内由系统(每天)自动发送给用户"
|
||||
|
||||
#: settings/serializers/settings.py:159
|
||||
msgid "Password minimum length"
|
||||
msgstr "密码最小长度"
|
||||
|
||||
#: settings/serializers/settings.py:162
|
||||
msgid "Must contain capital"
|
||||
msgstr "必须包含大写字符"
|
||||
|
||||
#: settings/serializers/settings.py:164
|
||||
msgid "Must contain lowercase"
|
||||
msgstr "必须包含小写字符"
|
||||
|
||||
#: settings/serializers/settings.py:165
|
||||
msgid "Must contain numeric"
|
||||
msgstr "必须包含数字"
|
||||
|
||||
#: settings/serializers/settings.py:166
|
||||
msgid "Must contain special"
|
||||
msgstr "必须包含特殊字符"
|
||||
|
||||
#: settings/serializers/settings.py:167
|
||||
msgid "Insecure command alert"
|
||||
msgstr "危险命令告警"
|
||||
|
||||
#: settings/serializers/settings.py:169
|
||||
msgid "Email recipient"
|
||||
msgstr "邮件收件人"
|
||||
|
||||
#: settings/serializers/settings.py:170
|
||||
msgid "Multiple user using , split"
|
||||
msgstr "多个用户,使用 , 分割"
|
||||
|
||||
#: settings/utils/ldap.py:411
|
||||
msgid "Host or port is disconnected: {}"
|
||||
msgstr "主机或端口不可连接: {}"
|
||||
|
@ -3215,7 +3494,7 @@ msgstr "确认密码"
|
|||
msgid "Password does not match"
|
||||
msgstr "密码不一致"
|
||||
|
||||
#: users/forms/profile.py:89 users/models/user.py:520
|
||||
#: users/forms/profile.py:89 users/models/user.py:519
|
||||
#: users/templates/users/user_detail.html:57
|
||||
#: users/templates/users/user_profile.html:59
|
||||
msgid "Email"
|
||||
|
@ -3256,7 +3535,7 @@ msgstr "不能和原来的密钥相同"
|
|||
msgid "Not a valid ssh public key"
|
||||
msgstr "SSH密钥不合法"
|
||||
|
||||
#: users/forms/user.py:31 users/models/user.py:563
|
||||
#: users/forms/user.py:31 users/models/user.py:562
|
||||
#: users/templates/users/user_detail.html:89
|
||||
#: users/templates/users/user_list.html:18
|
||||
#: users/templates/users/user_profile.html:102
|
||||
|
@ -3290,39 +3569,39 @@ msgstr "设置密码"
|
|||
msgid "Password strategy"
|
||||
msgstr "密码策略"
|
||||
|
||||
#: users/models/user.py:157
|
||||
#: users/models/user.py:156
|
||||
msgid "System administrator"
|
||||
msgstr "系统管理员"
|
||||
|
||||
#: users/models/user.py:158
|
||||
#: users/models/user.py:157
|
||||
msgid "System auditor"
|
||||
msgstr "系统审计员"
|
||||
|
||||
#: users/models/user.py:446 users/templates/users/user_profile.html:90
|
||||
#: users/models/user.py:445 users/templates/users/user_profile.html:90
|
||||
msgid "Force enable"
|
||||
msgstr "强制启用"
|
||||
|
||||
#: users/models/user.py:508
|
||||
#: users/models/user.py:507
|
||||
msgid "Local"
|
||||
msgstr "数据库"
|
||||
|
||||
#: users/models/user.py:531
|
||||
#: users/models/user.py:530
|
||||
msgid "Avatar"
|
||||
msgstr "头像"
|
||||
|
||||
#: users/models/user.py:534 users/templates/users/user_detail.html:68
|
||||
#: users/models/user.py:533 users/templates/users/user_detail.html:68
|
||||
msgid "Wechat"
|
||||
msgstr "微信"
|
||||
|
||||
#: users/models/user.py:567
|
||||
#: users/models/user.py:566
|
||||
msgid "Date password last updated"
|
||||
msgstr "最后更新密码日期"
|
||||
|
||||
#: users/models/user.py:674
|
||||
#: users/models/user.py:673
|
||||
msgid "Administrator"
|
||||
msgstr "管理员"
|
||||
|
||||
#: users/models/user.py:677
|
||||
#: users/models/user.py:676
|
||||
msgid "Administrator is the super user of system"
|
||||
msgstr "Administrator是初始的超级管理员"
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
from .common import *
|
||||
from .ldap import *
|
|
@ -0,0 +1,189 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
from smtplib import SMTPSenderRefused
|
||||
from rest_framework import generics
|
||||
from rest_framework.views import Response, APIView
|
||||
from rest_framework.permissions import AllowAny
|
||||
from django.conf import settings
|
||||
from django.core.mail import send_mail, get_connection
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.templatetags.static import static
|
||||
|
||||
from common.permissions import IsSuperUser
|
||||
from common.utils import get_logger
|
||||
from .. import serializers
|
||||
from ..models import Setting
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
class MailTestingAPI(APIView):
|
||||
permission_classes = (IsSuperUser,)
|
||||
serializer_class = serializers.MailTestSerializer
|
||||
success_message = _("Test mail sent to {}, please check")
|
||||
|
||||
def post(self, request):
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
serializer.is_valid(raise_exception=True)
|
||||
|
||||
email_host = serializer.validated_data['EMAIL_HOST']
|
||||
email_port = serializer.validated_data['EMAIL_PORT']
|
||||
email_host_user = serializer.validated_data["EMAIL_HOST_USER"]
|
||||
email_host_password = serializer.validated_data['EMAIL_HOST_PASSWORD']
|
||||
email_from = serializer.validated_data["EMAIL_FROM"]
|
||||
email_recipient = serializer.validated_data["EMAIL_RECIPIENT"]
|
||||
email_use_ssl = serializer.validated_data['EMAIL_USE_SSL']
|
||||
email_use_tls = serializer.validated_data['EMAIL_USE_TLS']
|
||||
|
||||
# 设置 settings 的值,会导致动态配置在当前进程失效
|
||||
# for k, v in serializer.validated_data.items():
|
||||
# if k.startswith('EMAIL'):
|
||||
# setattr(settings, k, v)
|
||||
try:
|
||||
subject = "Test"
|
||||
message = "Test smtp setting"
|
||||
email_from = email_from or email_host_user
|
||||
email_recipient = email_recipient or email_from
|
||||
connection = get_connection(
|
||||
host=email_host, port=email_port,
|
||||
username=email_host_user, password=email_host_password,
|
||||
use_tls=email_use_tls, use_ssl=email_use_ssl,
|
||||
)
|
||||
send_mail(
|
||||
subject, message, email_from, [email_recipient],
|
||||
connection=connection
|
||||
)
|
||||
except SMTPSenderRefused as e:
|
||||
error = e.smtp_error
|
||||
if isinstance(error, bytes):
|
||||
for coding in ('gbk', 'utf8'):
|
||||
try:
|
||||
error = error.decode(coding)
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
else:
|
||||
break
|
||||
return Response({"error": str(error)}, status=400)
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
return Response({"error": str(e)}, status=400)
|
||||
return Response({"msg": self.success_message.format(email_recipient)})
|
||||
|
||||
|
||||
class PublicSettingApi(generics.RetrieveAPIView):
|
||||
permission_classes = (AllowAny,)
|
||||
serializer_class = serializers.PublicSettingSerializer
|
||||
|
||||
@staticmethod
|
||||
def get_logo_urls():
|
||||
logo_urls = {
|
||||
'logo_logout': static('img/logo.png'),
|
||||
'logo_index': static('img/logo_text.png'),
|
||||
'login_image': static('img/login_image.png'),
|
||||
'favicon': static('img/facio.ico')
|
||||
}
|
||||
if not settings.XPACK_ENABLED:
|
||||
return logo_urls
|
||||
from xpack.plugins.interface.models import Interface
|
||||
obj = Interface.interface()
|
||||
if not obj:
|
||||
return logo_urls
|
||||
for attr in ['logo_logout', 'logo_index', 'login_image', 'favicon']:
|
||||
if getattr(obj, attr, '') and getattr(obj, attr).url:
|
||||
logo_urls.update({attr: getattr(obj, attr).url})
|
||||
return logo_urls
|
||||
|
||||
@staticmethod
|
||||
def get_xpack_license_is_valid():
|
||||
if not settings.XPACK_ENABLED:
|
||||
return False
|
||||
try:
|
||||
from xpack.plugins.license.models import License
|
||||
return License.has_valid_license()
|
||||
except Exception as e:
|
||||
logger.error(e)
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def get_login_title():
|
||||
default_title = _('Welcome to the JumpServer open source fortress')
|
||||
if not settings.XPACK_ENABLED:
|
||||
return default_title
|
||||
from xpack.plugins.interface.models import Interface
|
||||
return Interface.get_login_title()
|
||||
|
||||
def get_object(self):
|
||||
instance = {
|
||||
"data": {
|
||||
"WINDOWS_SKIP_ALL_MANUAL_PASSWORD": settings.WINDOWS_SKIP_ALL_MANUAL_PASSWORD,
|
||||
"SECURITY_MAX_IDLE_TIME": settings.SECURITY_MAX_IDLE_TIME,
|
||||
"XPACK_ENABLED": settings.XPACK_ENABLED,
|
||||
"LOGIN_CONFIRM_ENABLE": settings.LOGIN_CONFIRM_ENABLE,
|
||||
"SECURITY_VIEW_AUTH_NEED_MFA": settings.SECURITY_VIEW_AUTH_NEED_MFA,
|
||||
"SECURITY_MFA_VERIFY_TTL": settings.SECURITY_MFA_VERIFY_TTL,
|
||||
"SECURITY_COMMAND_EXECUTION": settings.SECURITY_COMMAND_EXECUTION,
|
||||
"SECURITY_PASSWORD_EXPIRATION_TIME": settings.SECURITY_PASSWORD_EXPIRATION_TIME,
|
||||
"XPACK_LICENSE_IS_VALID": self.get_xpack_license_is_valid(),
|
||||
"LOGIN_TITLE": self.get_login_title(),
|
||||
"LOGO_URLS": self.get_logo_urls(),
|
||||
"TICKETS_ENABLED": settings.TICKETS_ENABLED,
|
||||
"PASSWORD_RULE": {
|
||||
'SECURITY_PASSWORD_MIN_LENGTH': settings.SECURITY_PASSWORD_MIN_LENGTH,
|
||||
'SECURITY_PASSWORD_UPPER_CASE': settings.SECURITY_PASSWORD_UPPER_CASE,
|
||||
'SECURITY_PASSWORD_LOWER_CASE': settings.SECURITY_PASSWORD_LOWER_CASE,
|
||||
'SECURITY_PASSWORD_NUMBER': settings.SECURITY_PASSWORD_NUMBER,
|
||||
'SECURITY_PASSWORD_SPECIAL_CHAR': settings.SECURITY_PASSWORD_SPECIAL_CHAR,
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance
|
||||
|
||||
|
||||
class SettingsApi(generics.RetrieveUpdateAPIView):
|
||||
permission_classes = (IsSuperUser,)
|
||||
serializer_class_mapper = {
|
||||
'all': serializers.SettingsSerializer,
|
||||
'basic': serializers.BasicSettingSerializer,
|
||||
'terminal': serializers.TerminalSettingSerializer,
|
||||
'security': serializers.SecuritySettingSerializer,
|
||||
'ldap': serializers.LDAPSettingSerializer,
|
||||
'email': serializers.EmailSettingSerializer,
|
||||
'email_content': serializers.EmailContentSettingSerializer,
|
||||
}
|
||||
|
||||
def get_serializer_class(self):
|
||||
category = self.request.query_params.get('category', serializers.BasicSettingSerializer)
|
||||
return self.serializer_class_mapper.get(category, serializers.BasicSettingSerializer)
|
||||
|
||||
def get_fields(self):
|
||||
serializer = self.get_serializer_class()()
|
||||
fields = serializer.get_fields()
|
||||
return fields
|
||||
|
||||
def get_object(self):
|
||||
items = self.get_fields().keys()
|
||||
return {item: getattr(settings, item) for item in items}
|
||||
|
||||
def parse_serializer_data(self, serializer):
|
||||
data = []
|
||||
fields = self.get_fields()
|
||||
encrypted_items = [name for name, field in fields.items() if field.write_only]
|
||||
category = self.request.query_params.get('category', '')
|
||||
for name, value in serializer.validated_data.items():
|
||||
encrypted = name in encrypted_items
|
||||
data.append({
|
||||
'name': name, 'value': value,
|
||||
'encrypted': encrypted, 'category': category
|
||||
})
|
||||
return data
|
||||
|
||||
def perform_update(self, serializer):
|
||||
settings_items = self.parse_serializer_data(serializer)
|
||||
serializer_data = getattr(serializer, 'data', {})
|
||||
for item in settings_items:
|
||||
changed, setting = Setting.update_or_create(**item)
|
||||
if not changed:
|
||||
continue
|
||||
serializer_data[setting.name] = setting.cleaned_value
|
||||
setattr(serializer, '_data', serializer_data)
|
|
@ -10,16 +10,15 @@ from rest_framework.views import Response, APIView
|
|||
from django.conf import settings
|
||||
from django.core.mail import send_mail, get_connection
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
|
||||
from .utils import (
|
||||
from ..utils import (
|
||||
LDAPServerUtil, LDAPCacheUtil, LDAPImportUtil, LDAPSyncUtil,
|
||||
LDAP_USE_CACHE_FLAGS, LDAPTestUtil, ObjectDict
|
||||
)
|
||||
from .tasks import sync_ldap_user
|
||||
from ..tasks import sync_ldap_user
|
||||
from common.permissions import IsOrgAdmin, IsSuperUser
|
||||
from common.utils import get_logger
|
||||
from .serializers import (
|
||||
from ..serializers import (
|
||||
MailTestSerializer, LDAPTestConfigSerializer, LDAPUserSerializer,
|
||||
PublicSettingSerializer, LDAPTestLoginSerializer, SettingsSerializer
|
||||
)
|
||||
|
@ -28,60 +27,6 @@ from users.models import User
|
|||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
class MailTestingAPI(APIView):
|
||||
permission_classes = (IsSuperUser,)
|
||||
serializer_class = MailTestSerializer
|
||||
success_message = _("Test mail sent to {}, please check")
|
||||
|
||||
def post(self, request):
|
||||
serializer = self.serializer_class(data=request.data)
|
||||
if serializer.is_valid():
|
||||
email_host = serializer.validated_data['EMAIL_HOST']
|
||||
email_port = serializer.validated_data['EMAIL_PORT']
|
||||
email_host_user = serializer.validated_data["EMAIL_HOST_USER"]
|
||||
email_host_password = serializer.validated_data['EMAIL_HOST_PASSWORD']
|
||||
email_from = serializer.validated_data["EMAIL_FROM"]
|
||||
email_recipient = serializer.validated_data["EMAIL_RECIPIENT"]
|
||||
email_use_ssl = serializer.validated_data['EMAIL_USE_SSL']
|
||||
email_use_tls = serializer.validated_data['EMAIL_USE_TLS']
|
||||
|
||||
# 设置 settings 的值,会导致动态配置在当前进程失效
|
||||
# for k, v in serializer.validated_data.items():
|
||||
# if k.startswith('EMAIL'):
|
||||
# setattr(settings, k, v)
|
||||
try:
|
||||
subject = "Test"
|
||||
message = "Test smtp setting"
|
||||
email_from = email_from or email_host_user
|
||||
email_recipient = email_recipient or email_from
|
||||
connection = get_connection(
|
||||
host=email_host, port=email_port,
|
||||
username=email_host_user, password=email_host_password,
|
||||
use_tls=email_use_tls, use_ssl=email_use_ssl,
|
||||
)
|
||||
send_mail(
|
||||
subject, message, email_from, [email_recipient],
|
||||
connection=connection
|
||||
)
|
||||
except SMTPSenderRefused as e:
|
||||
resp = e.smtp_error
|
||||
if isinstance(resp, bytes):
|
||||
for coding in ('gbk', 'utf8'):
|
||||
try:
|
||||
resp = resp.decode(coding)
|
||||
except UnicodeDecodeError:
|
||||
continue
|
||||
else:
|
||||
break
|
||||
return Response({"error": str(resp)}, status=400)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
return Response({"error": str(e)}, status=400)
|
||||
return Response({"msg": self.success_message.format(email_recipient)})
|
||||
else:
|
||||
return Response({"error": str(serializer.errors)}, status=400)
|
||||
|
||||
|
||||
class LDAPTestingConfigAPI(APIView):
|
||||
permission_classes = (IsSuperUser,)
|
||||
serializer_class = LDAPTestConfigSerializer
|
||||
|
@ -262,59 +207,3 @@ class LDAPCacheRefreshAPI(generics.RetrieveAPIView):
|
|||
return Response(data={'msg': str(e)}, status=400)
|
||||
return Response(data={'msg': 'success'})
|
||||
|
||||
|
||||
class PublicSettingApi(generics.RetrieveAPIView):
|
||||
permission_classes = ()
|
||||
serializer_class = PublicSettingSerializer
|
||||
|
||||
def get_object(self):
|
||||
instance = {
|
||||
"data": {
|
||||
"WINDOWS_SKIP_ALL_MANUAL_PASSWORD": settings.WINDOWS_SKIP_ALL_MANUAL_PASSWORD,
|
||||
"SECURITY_MAX_IDLE_TIME": settings.SECURITY_MAX_IDLE_TIME,
|
||||
"XPACK_ENABLED": settings.XPACK_ENABLED,
|
||||
"XPACK_LICENSE_IS_VALID": settings.XPACK_LICENSE_IS_VALID,
|
||||
"LOGIN_CONFIRM_ENABLE": settings.LOGIN_CONFIRM_ENABLE,
|
||||
"SECURITY_VIEW_AUTH_NEED_MFA": settings.SECURITY_VIEW_AUTH_NEED_MFA,
|
||||
"SECURITY_MFA_VERIFY_TTL": settings.SECURITY_MFA_VERIFY_TTL,
|
||||
"SECURITY_COMMAND_EXECUTION": settings.SECURITY_COMMAND_EXECUTION,
|
||||
"LOGIN_TITLE": settings.XPACK_INTERFACE_LOGIN_TITLE,
|
||||
"SECURITY_PASSWORD_EXPIRATION_TIME": settings.SECURITY_PASSWORD_EXPIRATION_TIME,
|
||||
"LOGO_URLS": settings.LOGO_URLS,
|
||||
"TICKETS_ENABLED": settings.TICKETS_ENABLED,
|
||||
"PASSWORD_RULE": {
|
||||
'SECURITY_PASSWORD_MIN_LENGTH': settings.SECURITY_PASSWORD_MIN_LENGTH,
|
||||
'SECURITY_PASSWORD_UPPER_CASE': settings.SECURITY_PASSWORD_UPPER_CASE,
|
||||
'SECURITY_PASSWORD_LOWER_CASE': settings.SECURITY_PASSWORD_LOWER_CASE,
|
||||
'SECURITY_PASSWORD_NUMBER': settings.SECURITY_PASSWORD_NUMBER,
|
||||
'SECURITY_PASSWORD_SPECIAL_CHAR': settings.SECURITY_PASSWORD_SPECIAL_CHAR,
|
||||
}
|
||||
}
|
||||
}
|
||||
return instance
|
||||
|
||||
|
||||
class SettingsApi(generics.RetrieveUpdateAPIView):
|
||||
permission_classes = (IsSuperUser,)
|
||||
serializer_class = SettingsSerializer
|
||||
|
||||
def get_object(self):
|
||||
instance = {category: self._get_setting_fields_obj(list(category_serializer.get_fields()))
|
||||
for category, category_serializer in self.serializer_class().get_fields().items()
|
||||
if isinstance(category_serializer, serializers.Serializer)}
|
||||
return ObjectDict(instance)
|
||||
|
||||
def perform_update(self, serializer):
|
||||
serializer.save()
|
||||
|
||||
def _get_setting_fields_obj(self, category_fields):
|
||||
if isinstance(category_fields, Iterable):
|
||||
fields_data = {field_name: getattr(settings, field_name)
|
||||
for field_name in category_fields}
|
||||
return ObjectDict(fields_data)
|
||||
|
||||
if isinstance(category_fields, str):
|
||||
fields_data = {category_fields: getattr(settings, category_fields)}
|
||||
return ObjectDict(fields_data)
|
||||
|
||||
return ObjectDict()
|
|
@ -3,9 +3,11 @@ import json
|
|||
from django.db import models
|
||||
from django.db.utils import ProgrammingError, OperationalError
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.core.cache import cache
|
||||
from django.conf import settings
|
||||
|
||||
from common.utils import signer
|
||||
from common.utils import signer, get_logger
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
class SettingQuerySet(models.QuerySet):
|
||||
|
@ -37,24 +39,6 @@ class Setting(models.Model):
|
|||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
@classmethod
|
||||
def get(cls, item):
|
||||
cached = cls.get_from_cache(item)
|
||||
if cached is not None:
|
||||
return cached
|
||||
instances = cls.objects.filter(name=item)
|
||||
if len(instances) == 1:
|
||||
s = instances[0]
|
||||
s.refresh_setting()
|
||||
return s.cleaned_value
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def get_from_cache(cls, item):
|
||||
key = cls.cache_key_prefix + item
|
||||
cached = cache.get(key)
|
||||
return cached
|
||||
|
||||
@property
|
||||
def cleaned_value(self):
|
||||
try:
|
||||
|
@ -87,9 +71,52 @@ class Setting(models.Model):
|
|||
except (ProgrammingError, OperationalError):
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
def refresh_item(cls, name):
|
||||
item = cls.objects.filter(name=name).first()
|
||||
if not item:
|
||||
return
|
||||
item.refresh_setting()
|
||||
|
||||
def refresh_setting(self):
|
||||
key = self.cache_key_prefix + self.name
|
||||
cache.set(key, self.cleaned_value, None)
|
||||
logger.debug(f"Refresh setting: {self.name}")
|
||||
if hasattr(self.__class__, f'refresh_{self.name}'):
|
||||
getattr(self.__class__, f'refresh_{self.name}')()
|
||||
else:
|
||||
setattr(settings, self.name, self.cleaned_value)
|
||||
|
||||
@classmethod
|
||||
def refresh_AUTH_LDAP(cls):
|
||||
setting = cls.objects.filter(name='AUTH_LDAP').first()
|
||||
if not setting:
|
||||
return
|
||||
ldap_backend = 'authentication.backends.ldap.LDAPAuthorizationBackend'
|
||||
backends = settings.AUTHENTICATION_BACKENDS
|
||||
has = ldap_backend in backends
|
||||
if setting.cleaned_value and not has:
|
||||
settings.AUTHENTICATION_BACKENDS.insert(0, ldap_backend)
|
||||
|
||||
if not setting.cleaned_value and has:
|
||||
index = backends.index(ldap_backend)
|
||||
backends.pop(index)
|
||||
settings.AUTH_LDAP = setting.cleaned_value
|
||||
|
||||
@classmethod
|
||||
def update_or_create(cls, name='', value='', encrypted=False, category=''):
|
||||
"""
|
||||
不能使用 Model 提供的,update_or_create 因为这里有 encrypted 和 cleaned_value
|
||||
:return: (changed, instance)
|
||||
"""
|
||||
setting = cls.objects.filter(name=name).first()
|
||||
changed = False
|
||||
if not setting:
|
||||
setting = Setting(name=name, encrypted=encrypted, category=category)
|
||||
if setting.cleaned_value != value:
|
||||
setting.encrypted = encrypted
|
||||
setting.cleaned_value = value
|
||||
setting.save()
|
||||
changed = True
|
||||
return changed, setting
|
||||
|
||||
class Meta:
|
||||
db_table = "settings_setting"
|
||||
|
|
|
@ -1,49 +1,100 @@
|
|||
# coding: utf-8
|
||||
|
||||
from django.db import transaction
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from rest_framework import serializers
|
||||
from ..models import Setting
|
||||
|
||||
__all__ = ['SettingsSerializer']
|
||||
__all__ = [
|
||||
'BasicSettingSerializer', 'EmailSettingSerializer', 'EmailContentSettingSerializer',
|
||||
'LDAPSettingSerializer', 'TerminalSettingSerializer', 'SecuritySettingSerializer',
|
||||
'SettingsSerializer'
|
||||
]
|
||||
|
||||
|
||||
class BasicSettingSerializer(serializers.Serializer):
|
||||
SITE_URL = serializers.URLField(required=True)
|
||||
USER_GUIDE_URL = serializers.URLField(required=False, allow_blank=True, )
|
||||
EMAIL_SUBJECT_PREFIX = serializers.CharField(max_length=1024, required=True)
|
||||
SITE_URL = serializers.URLField(
|
||||
required=True, label=_("Site url"),
|
||||
help_text=_('eg: http://demo.jumpserver.org:8080')
|
||||
)
|
||||
USER_GUIDE_URL = serializers.URLField(
|
||||
required=False, allow_blank=True, label=_("User guide url"),
|
||||
help_text=_('User first login update profile done redirect to it')
|
||||
)
|
||||
|
||||
|
||||
class EmailSettingSerializer(serializers.Serializer):
|
||||
encrypt_fields = ["EMAIL_HOST_PASSWORD", ]
|
||||
# encrypt_fields 现在使用 write_only 来判断了
|
||||
|
||||
EMAIL_HOST = serializers.CharField(max_length=1024, required=True)
|
||||
EMAIL_PORT = serializers.CharField(max_length=5, required=True)
|
||||
EMAIL_HOST_USER = serializers.CharField(max_length=128, required=True)
|
||||
EMAIL_HOST_PASSWORD = serializers.CharField(max_length=1024, write_only=True, required=False, )
|
||||
EMAIL_FROM = serializers.CharField(max_length=128, allow_blank=True, required=False)
|
||||
EMAIL_RECIPIENT = serializers.CharField(max_length=128, allow_blank=True, required=False)
|
||||
EMAIL_USE_SSL = serializers.BooleanField(required=False)
|
||||
EMAIL_USE_TLS = serializers.BooleanField(required=False)
|
||||
EMAIL_HOST = serializers.CharField(max_length=1024, required=True, label=_("SMTP host"))
|
||||
EMAIL_PORT = serializers.CharField(max_length=5, required=True, label=_("SMTP port"))
|
||||
EMAIL_HOST_USER = serializers.CharField(max_length=128, required=True, label=_("SMTP account"))
|
||||
EMAIL_HOST_PASSWORD = serializers.CharField(
|
||||
max_length=1024, write_only=True, required=False, label=_("SMTP password"),
|
||||
help_text=_("Tips: Some provider use token except password")
|
||||
)
|
||||
EMAIL_FROM = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Send user'),
|
||||
help_text=_('Tips: Send mail account, default SMTP account as the send account')
|
||||
)
|
||||
EMAIL_RECIPIENT = serializers.CharField(
|
||||
max_length=128, allow_blank=True, required=False, label=_('Test recipient'),
|
||||
help_text=_('Tips: Used only as a test mail recipient')
|
||||
)
|
||||
EMAIL_USE_SSL = serializers.BooleanField(
|
||||
required=False, label=_('Use SSL'),
|
||||
help_text=_('If SMTP port is 465, may be select')
|
||||
)
|
||||
EMAIL_USE_TLS = serializers.BooleanField(
|
||||
required=False, label=_("Use TLS"),
|
||||
help_text=_('If SMTP port is 587, may be select')
|
||||
)
|
||||
EMAIL_SUBJECT_PREFIX = serializers.CharField(
|
||||
max_length=1024, required=True, label=_('Subject prefix')
|
||||
)
|
||||
|
||||
|
||||
class EmailContentSettingSerializer(serializers.Serializer):
|
||||
EMAIL_CUSTOM_USER_CREATED_SUBJECT = serializers.CharField(max_length=1024, allow_blank=True, required=False, )
|
||||
EMAIL_CUSTOM_USER_CREATED_HONORIFIC = serializers.CharField(max_length=1024, allow_blank=True, required=False, )
|
||||
EMAIL_CUSTOM_USER_CREATED_BODY = serializers.CharField(max_length=4096, allow_blank=True, required=False)
|
||||
EMAIL_CUSTOM_USER_CREATED_SIGNATURE = serializers.CharField(max_length=512, allow_blank=True, required=False)
|
||||
EMAIL_CUSTOM_USER_CREATED_SUBJECT = serializers.CharField(
|
||||
max_length=1024, allow_blank=True, required=False,
|
||||
label=_('Create user email subject'),
|
||||
help_text=_('Tips: When creating a user, send the subject of the email (eg:Create account successfully)')
|
||||
)
|
||||
EMAIL_CUSTOM_USER_CREATED_HONORIFIC = serializers.CharField(
|
||||
max_length=1024, allow_blank=True, required=False,
|
||||
label=_('Create user honorific'),
|
||||
help_text=_('Tips: When creating a user, send the honorific of the email (eg:Hello)')
|
||||
)
|
||||
EMAIL_CUSTOM_USER_CREATED_BODY = serializers.CharField(
|
||||
max_length=4096, allow_blank=True, required=False,
|
||||
label=_('Create user email content'),
|
||||
help_text=_('Tips:When creating a user, send the content of the email')
|
||||
)
|
||||
EMAIL_CUSTOM_USER_CREATED_SIGNATURE = serializers.CharField(
|
||||
max_length=512, allow_blank=True, required=False, label=_('Signature'),
|
||||
help_text=_('Tips: Email signature (eg:jumpserver)')
|
||||
)
|
||||
|
||||
|
||||
class LdapSettingSerializer(serializers.Serializer):
|
||||
encrypt_fields = ["AUTH_LDAP_BIND_PASSWORD", ]
|
||||
class LDAPSettingSerializer(serializers.Serializer):
|
||||
# encrypt_fields 现在使用 write_only 来判断了
|
||||
|
||||
AUTH_LDAP_SERVER_URI = serializers.CharField(required=True)
|
||||
AUTH_LDAP_BIND_DN = serializers.CharField(required=False)
|
||||
AUTH_LDAP_BIND_PASSWORD = serializers.CharField(max_length=1024, write_only=True, required=False)
|
||||
AUTH_LDAP_SEARCH_OU = serializers.CharField(max_length=1024, allow_blank=True, required=False)
|
||||
AUTH_LDAP_SEARCH_FILTER = serializers.CharField(max_length=1024, required=True)
|
||||
AUTH_LDAP_USER_ATTR_MAP = serializers.DictField(required=True)
|
||||
AUTH_LDAP = serializers.BooleanField(required=False)
|
||||
AUTH_LDAP_SERVER_URI = serializers.CharField(
|
||||
required=True, max_length=1024, label=_('LDAP server'), help_text=_('eg: ldap://localhost:389')
|
||||
)
|
||||
AUTH_LDAP_BIND_DN = serializers.CharField(required=False, max_length=1024, label=_('Bind DN'))
|
||||
AUTH_LDAP_BIND_PASSWORD = serializers.CharField(max_length=1024, write_only=True, required=False, label=_('Password'))
|
||||
AUTH_LDAP_SEARCH_OU = serializers.CharField(
|
||||
max_length=1024, allow_blank=True, required=False, label=_('User OU'),
|
||||
help_text=_('Use | split multi OUs')
|
||||
)
|
||||
AUTH_LDAP_SEARCH_FILTER = serializers.CharField(
|
||||
max_length=1024, required=True, label=_('User search filter'),
|
||||
help_text=_('Choice may be (cn|uid|sAMAccountName)=%(user)s)')
|
||||
)
|
||||
AUTH_LDAP_USER_ATTR_MAP = serializers.DictField(
|
||||
required=True, label=_('User attr map'),
|
||||
help_text=_('User attr map present how to map LDAP user attr to jumpserver, username,name,email is jumpserver attr')
|
||||
)
|
||||
AUTH_LDAP = serializers.BooleanField(required=False, label=_('Enable LDAP auth'))
|
||||
|
||||
|
||||
class TerminalSettingSerializer(serializers.Serializer):
|
||||
|
@ -60,67 +111,75 @@ class TerminalSettingSerializer(serializers.Serializer):
|
|||
('25', '25'),
|
||||
('50', '50'),
|
||||
)
|
||||
TERMINAL_PASSWORD_AUTH = serializers.BooleanField(required=False)
|
||||
TERMINAL_PUBLIC_KEY_AUTH = serializers.BooleanField(required=False)
|
||||
TERMINAL_HEARTBEAT_INTERVAL = serializers.IntegerField(min_value=5, max_value=99999, required=False)
|
||||
TERMINAL_ASSET_LIST_SORT_BY = serializers.ChoiceField(SORT_BY_CHOICES, required=False)
|
||||
TERMINAL_ASSET_LIST_PAGE_SIZE = serializers.ChoiceField(PAGE_SIZE_CHOICES, required=False)
|
||||
TERMINAL_SESSION_KEEP_DURATION = serializers.IntegerField(min_value=1, max_value=99999, required=True)
|
||||
TERMINAL_TELNET_REGEX = serializers.CharField(allow_blank=True, required=False)
|
||||
TERMINAL_PASSWORD_AUTH = serializers.BooleanField(required=False, label=_('Password auth'))
|
||||
TERMINAL_PUBLIC_KEY_AUTH = serializers.BooleanField(required=False, label=_('Public key auth'))
|
||||
TERMINAL_ASSET_LIST_SORT_BY = serializers.ChoiceField(SORT_BY_CHOICES, required=False, label=_('List sort by'))
|
||||
TERMINAL_ASSET_LIST_PAGE_SIZE = serializers.ChoiceField(PAGE_SIZE_CHOICES, required=False, label=_('List page size'))
|
||||
TERMINAL_SESSION_KEEP_DURATION = serializers.IntegerField(
|
||||
min_value=1, max_value=99999, required=True, label=_('Session keep duration'),
|
||||
help_text=_('Units: days, Session, record, command will be delete if more than duration, only in database')
|
||||
)
|
||||
TERMINAL_TELNET_REGEX = serializers.CharField(allow_blank=True, max_length=1024, required=False, label=_('Telnet login regex'))
|
||||
|
||||
|
||||
class SecuritySettingSerializer(serializers.Serializer):
|
||||
SECURITY_MFA_AUTH = serializers.BooleanField(required=False)
|
||||
SECURITY_COMMAND_EXECUTION = serializers.BooleanField(required=False)
|
||||
SECURITY_SERVICE_ACCOUNT_REGISTRATION = serializers.BooleanField(required=True)
|
||||
SECURITY_LOGIN_LIMIT_COUNT = serializers.IntegerField(min_value=3, max_value=99999, required=True)
|
||||
SECURITY_LOGIN_LIMIT_TIME = serializers.IntegerField(min_value=5, max_value=99999, required=True)
|
||||
SECURITY_MAX_IDLE_TIME = serializers.IntegerField(min_value=1, max_value=99999, required=False)
|
||||
SECURITY_PASSWORD_EXPIRATION_TIME = serializers.IntegerField(min_value=1, max_value=99999, required=True)
|
||||
SECURITY_PASSWORD_MIN_LENGTH = serializers.IntegerField(min_value=6, max_value=30, required=True)
|
||||
SECURITY_PASSWORD_UPPER_CASE = serializers.BooleanField(required=False)
|
||||
SECURITY_PASSWORD_LOWER_CASE = serializers.BooleanField(required=False)
|
||||
SECURITY_PASSWORD_NUMBER = serializers.BooleanField(required=False)
|
||||
SECURITY_PASSWORD_SPECIAL_CHAR = serializers.BooleanField(required=False)
|
||||
SECURITY_INSECURE_COMMAND = serializers.BooleanField(required=False)
|
||||
SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER = serializers.CharField(max_length=8192, required=False, allow_blank=True)
|
||||
SECURITY_MFA_AUTH = serializers.BooleanField(
|
||||
required=False, label=_("Global MFA auth"),
|
||||
help_text=_('All user enable MFA')
|
||||
)
|
||||
SECURITY_COMMAND_EXECUTION = serializers.BooleanField(
|
||||
required=False, label=_('Batch command execution'),
|
||||
help_text=_('Allow user run batch command or not using ansible')
|
||||
)
|
||||
SECURITY_SERVICE_ACCOUNT_REGISTRATION = serializers.BooleanField(
|
||||
required=True, label=_('Enable terminal register'),
|
||||
help_text=_("Allow terminal register, after all terminal setup, you should disable this for security")
|
||||
)
|
||||
SECURITY_LOGIN_LIMIT_COUNT = serializers.IntegerField(
|
||||
min_value=3, max_value=99999,
|
||||
label=_('Limit the number of login failures')
|
||||
)
|
||||
SECURITY_LOGIN_LIMIT_TIME = serializers.IntegerField(
|
||||
min_value=5, max_value=99999, required=True,
|
||||
label=_('Block logon interval'),
|
||||
help_text=_('Tip: (unit/minute) if the user has failed to log in for a limited number of times, no login is allowed during this time interval.')
|
||||
)
|
||||
SECURITY_MAX_IDLE_TIME = serializers.IntegerField(
|
||||
min_value=1, max_value=99999, required=False,
|
||||
label=_('Connection max idle time'),
|
||||
help_text=_('If idle time more than it, disconnect connection Unit: minute')
|
||||
)
|
||||
SECURITY_PASSWORD_EXPIRATION_TIME = serializers.IntegerField(
|
||||
min_value=1, max_value=99999, required=True,
|
||||
label=_('User password expiration'),
|
||||
help_text=_('Tip: (unit: day) If the user does not update the password during the time, the user password will expire failure;The password expiration reminder mail will be automatic sent to the user by system within 5 days (daily) before the password expires')
|
||||
)
|
||||
SECURITY_PASSWORD_MIN_LENGTH = serializers.IntegerField(
|
||||
min_value=6, max_value=30, required=True,
|
||||
label=_('Password minimum length')
|
||||
)
|
||||
SECURITY_PASSWORD_UPPER_CASE = serializers.BooleanField(
|
||||
required=False, label=_('Must contain capital')
|
||||
)
|
||||
SECURITY_PASSWORD_LOWER_CASE = serializers.BooleanField(required=False, label=_('Must contain lowercase'))
|
||||
SECURITY_PASSWORD_NUMBER = serializers.BooleanField(required=False, label=_('Must contain numeric'))
|
||||
SECURITY_PASSWORD_SPECIAL_CHAR = serializers.BooleanField(required=False, label=_('Must contain special'))
|
||||
SECURITY_INSECURE_COMMAND = serializers.BooleanField(required=False, label=_('Insecure command alert'))
|
||||
SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER = serializers.CharField(
|
||||
max_length=8192, required=False, allow_blank=True, label=_('Email recipient'),
|
||||
help_text=_('Multiple user using , split')
|
||||
)
|
||||
|
||||
|
||||
class SettingsSerializer(serializers.Serializer):
|
||||
basic = BasicSettingSerializer(required=False)
|
||||
email = EmailSettingSerializer(required=False)
|
||||
email_content = EmailContentSettingSerializer(required=False)
|
||||
ldap = LdapSettingSerializer(required=False)
|
||||
terminal = TerminalSettingSerializer(required=False)
|
||||
security = SecuritySettingSerializer(required=False)
|
||||
class SettingsSerializer(
|
||||
BasicSettingSerializer,
|
||||
EmailSettingSerializer,
|
||||
EmailContentSettingSerializer,
|
||||
LDAPSettingSerializer,
|
||||
TerminalSettingSerializer,
|
||||
SecuritySettingSerializer
|
||||
):
|
||||
|
||||
encrypt_fields = ["EMAIL_HOST_PASSWORD", "AUTH_LDAP_BIND_PASSWORD"]
|
||||
# encrypt_fields 现在使用 write_only 来判断了
|
||||
pass
|
||||
|
||||
def create(self, validated_data):
|
||||
pass
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
for category, category_data in validated_data.items():
|
||||
if not category_data:
|
||||
continue
|
||||
self.update_validated_settings(category_data)
|
||||
for field_name, field_value in category_data.items():
|
||||
setattr(getattr(instance, category), field_name, field_value)
|
||||
|
||||
return instance
|
||||
|
||||
def update_validated_settings(self, validated_data, category='default'):
|
||||
if not validated_data:
|
||||
return
|
||||
with transaction.atomic():
|
||||
for field_name, field_value in validated_data.items():
|
||||
try:
|
||||
setting = Setting.objects.get(name=field_name)
|
||||
except Setting.DoesNotExist:
|
||||
setting = Setting()
|
||||
encrypted = True if field_name in self.encrypt_fields else False
|
||||
setting.name = field_name
|
||||
setting.category = category
|
||||
setting.encrypted = encrypted
|
||||
setting.cleaned_value = field_value
|
||||
setting.save()
|
||||
|
|
|
@ -1,28 +1,44 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
import json
|
||||
import threading
|
||||
|
||||
from django.dispatch import receiver
|
||||
from django.db.models.signals import post_save, pre_save
|
||||
from django.utils.functional import LazyObject
|
||||
|
||||
from jumpserver.utils import current_request
|
||||
from common.decorator import on_transaction_commit
|
||||
from common.utils import get_logger, ssh_key_gen
|
||||
from common.utils.connection import RedisPubSub
|
||||
from common.signals import django_ready
|
||||
from .models import Setting
|
||||
|
||||
logger = get_logger(__file__)
|
||||
|
||||
|
||||
@receiver(post_save, sender=Setting, dispatch_uid="my_unique_identifier")
|
||||
def get_settings_pub_sub():
|
||||
return RedisPubSub('settings')
|
||||
|
||||
|
||||
class SettingSubPub(LazyObject):
|
||||
def _setup(self):
|
||||
self._wrapped = get_settings_pub_sub()
|
||||
|
||||
|
||||
setting_pub_sub = SettingSubPub()
|
||||
|
||||
|
||||
@receiver(post_save, sender=Setting)
|
||||
@on_transaction_commit
|
||||
def refresh_settings_on_changed(sender, instance=None, **kwargs):
|
||||
if instance:
|
||||
instance.refresh_setting()
|
||||
setting_pub_sub.publish(instance.name)
|
||||
|
||||
|
||||
@receiver(django_ready)
|
||||
def on_django_ready_add_db_config(sender, **kwargs):
|
||||
from django.conf import settings
|
||||
settings.DYNAMIC.db_setting = Setting
|
||||
Setting.refresh_all_settings()
|
||||
|
||||
|
||||
@receiver(django_ready)
|
||||
|
@ -41,9 +57,27 @@ def auto_generate_terminal_host_key(sender, **kwargs):
|
|||
def on_create_set_created_by(sender, instance=None, **kwargs):
|
||||
if getattr(instance, '_ignore_auto_created_by', False) is True:
|
||||
return
|
||||
if hasattr(instance, 'created_by') and not instance.created_by:
|
||||
if current_request and current_request.user.is_authenticated:
|
||||
user_name = current_request.user.name
|
||||
if isinstance(user_name, str):
|
||||
user_name = user_name[:30]
|
||||
instance.created_by = user_name
|
||||
if not hasattr(instance, 'created_by') or instance.created_by:
|
||||
return
|
||||
if current_request and current_request.user.is_authenticated:
|
||||
user_name = current_request.user.name
|
||||
if isinstance(user_name, str):
|
||||
user_name = user_name[:30]
|
||||
instance.created_by = user_name
|
||||
|
||||
|
||||
@receiver(django_ready)
|
||||
def subscribe_settings_change(sender, **kwargs):
|
||||
logger.debug("Start subscribe setting change")
|
||||
|
||||
def keep_subscribe():
|
||||
sub = setting_pub_sub.subscribe()
|
||||
for msg in sub.listen():
|
||||
if msg["type"] != "message":
|
||||
continue
|
||||
item = msg['data'].decode()
|
||||
logger.debug("Found setting change: {}".format(str(item)))
|
||||
Setting.refresh_item(item)
|
||||
t = threading.Thread(target=keep_subscribe)
|
||||
t.daemon = True
|
||||
t.start()
|
||||
|
|
|
@ -16,7 +16,6 @@ from django.utils.translation import ugettext_lazy as _
|
|||
from django.utils import timezone
|
||||
from django.shortcuts import reverse
|
||||
|
||||
from common.local import LOCAL_DYNAMIC_SETTINGS
|
||||
from orgs.utils import current_org
|
||||
from orgs.models import OrganizationMember, Organization
|
||||
from common.utils import date_expired_default, get_logger, lazyproperty
|
||||
|
@ -452,7 +451,7 @@ class MFAMixin:
|
|||
|
||||
@property
|
||||
def mfa_force_enabled(self):
|
||||
if LOCAL_DYNAMIC_SETTINGS.SECURITY_MFA_AUTH:
|
||||
if settings.SECURITY_MFA_AUTH:
|
||||
return True
|
||||
return self.mfa_level == 2
|
||||
|
||||
|
|
Loading…
Reference in New Issue