feat: 页面配置serializer版 (#6750)

* feat: 页面配置serializer版

* perf: 优化配置

* perf: 优化设置

* perf: 优化设置

* perf: 优化配置页面

* perf: 基本完成设置优化

Co-authored-by: feng626 <1304903146@qq.com>
Co-authored-by: ibuler <ibuler@qq.com>
pull/6783/head
fit2bot 2021-09-09 14:00:50 +08:00 committed by GitHub
parent 7a2e93c087
commit 07179a4d22
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 1620 additions and 890 deletions

View File

@ -131,8 +131,8 @@ def on_system_user_groups_change(instance, action, pk_set, reverse, **kwargs):
@on_transaction_commit
def on_system_user_update(instance: SystemUser, created, **kwargs):
"""
当系统用户更新时可能更新了用户名等这时要自动推送系统用户到资产上,
其实应该当 用户名密码sudo等更新时再推送这里偷个懒,
当系统用户更新时可能更新了用户名等这时要自动推送系统用户到资产上,
其实应该当 用户名密码sudo等更新时再推送这里偷个懒,
这里直接取了 instance.assets 因为nodes和系统用户发生变化时会自动将nodes下的资产
关联到上面
"""

View File

@ -5,14 +5,12 @@ from django.utils import timezone
from celery import shared_task
from ops.celery.decorator import (
register_as_period_task, after_app_shutdown_clean_periodic
register_as_period_task
)
from .models import UserLoginLog, OperateLog
from common.utils import get_log_keep_day
@shared_task
@after_app_shutdown_clean_periodic
def clean_login_log_period():
now = timezone.now()
days = get_log_keep_day('LOGIN_LOG_KEEP_DAYS')
@ -20,8 +18,6 @@ def clean_login_log_period():
UserLoginLog.objects.filter(datetime__lt=expired_day).delete()
@shared_task
@after_app_shutdown_clean_periodic
def clean_operation_log_period():
now = timezone.now()
days = get_log_keep_day('OPERATE_LOG_KEEP_DAYS')
@ -29,7 +25,6 @@ def clean_operation_log_period():
OperateLog.objects.filter(datetime__lt=expired_day).delete()
@shared_task
def clean_ftp_log_period():
now = timezone.now()
days = get_log_keep_day('FTP_LOG_KEEP_DAYS')

View File

@ -51,7 +51,8 @@ class UserLoginView(mixins.AuthMixin, FormView):
if settings.AUTH_OPENID:
auth_type = 'OIDC'
openid_auth_url = reverse(settings.AUTH_OPENID_AUTH_LOGIN_URL_NAME) + f'?next={next_url}'
openid_auth_url = reverse(settings.AUTH_OPENID_AUTH_LOGIN_URL_NAME)
openid_auth_url = openid_auth_url + f'?next={next_url}'
else:
openid_auth_url = None
@ -64,16 +65,13 @@ class UserLoginView(mixins.AuthMixin, FormView):
if not any([openid_auth_url, cas_auth_url]):
return None
if settings.LOGIN_REDIRECT_TO_BACKEND == 'OPENID' and openid_auth_url:
login_redirect = settings.LOGIN_REDIRECT_TO_BACKEND.lower()
if login_redirect == ['CAS', 'cas'] and cas_auth_url:
auth_url = cas_auth_url
else:
auth_url = openid_auth_url
elif settings.LOGIN_REDIRECT_TO_BACKEND == 'CAS' and cas_auth_url:
auth_url = cas_auth_url
else:
auth_url = openid_auth_url or cas_auth_url
if settings.LOGIN_REDIRECT_TO_BACKEND:
if settings.LOGIN_REDIRECT_TO_BACKEND or not settings.LOGIN_REDIRECT_MSG_ENABLED:
redirect_url = auth_url
else:
message_data = {

View File

@ -179,13 +179,14 @@ class Config(dict):
'AUTH_OPENID_CLIENT_SECRET': 'client-secret',
'AUTH_OPENID_SHARE_SESSION': True,
'AUTH_OPENID_IGNORE_SSL_VERIFICATION': True,
# OpenID 新配置参数 (version >= 1.5.9)
'AUTH_OPENID_PROVIDER_ENDPOINT': 'https://op-example.com/',
'AUTH_OPENID_PROVIDER_AUTHORIZATION_ENDPOINT': 'https://op-example.com/authorize',
'AUTH_OPENID_PROVIDER_TOKEN_ENDPOINT': 'https://op-example.com/token',
'AUTH_OPENID_PROVIDER_JWKS_ENDPOINT': 'https://op-example.com/jwks',
'AUTH_OPENID_PROVIDER_USERINFO_ENDPOINT': 'https://op-example.com/userinfo',
'AUTH_OPENID_PROVIDER_END_SESSION_ENDPOINT': 'https://op-example.com/logout',
'AUTH_OPENID_PROVIDER_ENDPOINT': 'https://oidc.example.com/',
'AUTH_OPENID_PROVIDER_AUTHORIZATION_ENDPOINT': 'https://oidc.example.com/authorize',
'AUTH_OPENID_PROVIDER_TOKEN_ENDPOINT': 'https://oidc.example.com/token',
'AUTH_OPENID_PROVIDER_JWKS_ENDPOINT': 'https://oidc.example.com/jwks',
'AUTH_OPENID_PROVIDER_USERINFO_ENDPOINT': 'https://oidc.example.com/userinfo',
'AUTH_OPENID_PROVIDER_END_SESSION_ENDPOINT': 'https://oidc.example.com/logout',
'AUTH_OPENID_PROVIDER_SIGNATURE_ALG': 'HS256',
'AUTH_OPENID_PROVIDER_SIGNATURE_KEY': None,
'AUTH_OPENID_SCOPES': 'openid profile email',
@ -194,10 +195,13 @@ class Config(dict):
'AUTH_OPENID_USE_STATE': True,
'AUTH_OPENID_USE_NONCE': True,
'AUTH_OPENID_ALWAYS_UPDATE_USER': True,
# OpenID 旧配置参数 (version <= 1.5.8 (discarded))
'AUTH_OPENID_SERVER_URL': 'http://openid',
# Keycloak 旧配置参数 (version <= 1.5.8 (discarded))
'AUTH_OPENID_KEYCLOAK': True,
'AUTH_OPENID_SERVER_URL': 'https://keycloak.example.com',
'AUTH_OPENID_REALM_NAME': None,
# Raidus 认证
'AUTH_RADIUS': False,
'RADIUS_SERVER': 'localhost',
'RADIUS_PORT': 1812,
@ -205,8 +209,9 @@ class Config(dict):
'RADIUS_ENCRYPT_PASSWORD': True,
'OTP_IN_RADIUS': False,
# Cas 认证
'AUTH_CAS': False,
'CAS_SERVER_URL': "http://host/cas/",
'CAS_SERVER_URL': "https://example.com/cas/",
'CAS_ROOT_PROXIED_AS': '',
'CAS_LOGOUT_COMPLETELY': True,
'CAS_VERSION': 3,
@ -218,24 +223,31 @@ class Config(dict):
'AUTH_SSO': False,
'AUTH_SSO_AUTHKEY_TTL': 60 * 15,
# 企业微信
'AUTH_WECOM': False,
'WECOM_CORPID': '',
'WECOM_AGENTID': '',
'WECOM_SECRET': '',
# 钉钉
'AUTH_DINGTALK': False,
'DINGTALK_AGENTID': '',
'DINGTALK_APPKEY': '',
'DINGTALK_APPSECRET': '',
# 飞书
'AUTH_FEISHU': False,
'FEISHU_APP_ID': '',
'FEISHU_APP_SECRET': '',
'LOGIN_REDIRECT_TO_BACKEND': '', # 'OPENID / CAS
'LOGIN_REDIRECT_MSG_ENABLED': True,
'OTP_VALID_WINDOW': 2,
'OTP_ISSUER_NAME': 'JumpServer',
'EMAIL_SUFFIX': 'jumpserver.org',
'EMAIL_SUFFIX': 'example.com',
# Terminal配置
'TERMINAL_PASSWORD_AUTH': True,
'TERMINAL_PUBLIC_KEY_AUTH': True,
'TERMINAL_HEARTBEAT_INTERVAL': 20,
@ -245,7 +257,9 @@ class Config(dict):
'TERMINAL_HOST_KEY': '',
'TERMINAL_TELNET_REGEX': '',
'TERMINAL_COMMAND_STORAGE': {},
'TERMINAL_RDP_ADDR': '',
# 安全配置
'SECURITY_MFA_AUTH': 0, # 0 不开启 1 全局开启 2 管理员开启
'SECURITY_COMMAND_EXECUTION': True,
'SECURITY_SERVICE_ACCOUNT_REGISTRATION': True,
@ -262,58 +276,60 @@ class Config(dict):
'SECURITY_PASSWORD_SPECIAL_CHAR': False,
'SECURITY_LOGIN_CHALLENGE_ENABLED': False,
'SECURITY_LOGIN_CAPTCHA_ENABLED': True,
'SECURITY_DATA_CRYPTO_ALGO': 'aes',
'SECURITY_INSECURE_COMMAND': False,
'SECURITY_INSECURE_COMMAND_LEVEL': 5,
'SECURITY_INSECURE_COMMAND_EMAIL_RECEIVER': '',
'SECURITY_LUNA_REMEMBER_AUTH': True,
'SECURITY_WATERMARK_ENABLED': True,
'SECURITY_MFA_VERIFY_TTL': 3600,
'SECURITY_SESSION_SHARE': True,
'OLD_PASSWORD_HISTORY_LIMIT_COUNT': 5,
'LOGIN_CONFIRM_ENABLE': False, # 准备废弃,放到 acl 中
'CHANGE_AUTH_PLAN_SECURE_MODE_ENABLED': True,
'USER_LOGIN_SINGLE_MACHINE_ENABLED': False,
'ONLY_ALLOW_EXIST_USER_AUTH': False,
'ONLY_ALLOW_AUTH_FROM_SOURCE': False,
# 启动前
'HTTP_BIND_HOST': '0.0.0.0',
'HTTP_LISTEN_PORT': 8080,
'WS_LISTEN_PORT': 8070,
'SYSLOG_ADDR': '', # '192.168.0.1:514'
'SYSLOG_FACILITY': 'user',
'SYSLOG_SOCKTYPE': 2,
'PERM_EXPIRED_CHECK_PERIODIC': 60 * 60,
'FLOWER_URL': "127.0.0.1:5555",
'LANGUAGE_CODE': 'zh',
'TIME_ZONE': 'Asia/Shanghai',
'FORCE_SCRIPT_NAME': '',
'SESSION_COOKIE_SECURE': False,
'CSRF_COOKIE_SECURE': False,
'REFERER_CHECK_ENABLED': False,
'SESSION_SAVE_EVERY_REQUEST': True,
'SESSION_EXPIRE_AT_BROWSER_CLOSE_FORCE': False,
'SERVER_REPLAY_STORAGE': {},
'SECURITY_DATA_CRYPTO_ALGO': 'aes',
# 记录清理清理
'LOGIN_LOG_KEEP_DAYS': 200,
'TASK_LOG_KEEP_DAYS': 90,
'OPERATE_LOG_KEEP_DAYS': 200,
'FTP_LOG_KEEP_DAYS': 200,
'ASSETS_PERM_CACHE_TIME': 3600 * 24,
'SECURITY_MFA_VERIFY_TTL': 3600,
'OLD_PASSWORD_HISTORY_LIMIT_COUNT': 5,
'ASSETS_PERM_CACHE_ENABLE': HAS_XPACK,
'SYSLOG_ADDR': '', # '192.168.0.1:514'
'SYSLOG_FACILITY': 'user',
'SYSLOG_SOCKTYPE': 2,
'PERM_SINGLE_ASSET_TO_UNGROUP_NODE': False,
'PERM_EXPIRED_CHECK_PERIODIC': 60 * 60,
'WINDOWS_SSH_DEFAULT_SHELL': 'cmd',
'FLOWER_URL': "127.0.0.1:5555",
'DEFAULT_ORG_SHOW_ALL_USERS': True,
'PERIOD_TASK_ENABLED': True,
'FORCE_SCRIPT_NAME': '',
'LOGIN_CONFIRM_ENABLE': False,
'WINDOWS_SKIP_ALL_MANUAL_PASSWORD': False,
'ORG_CHANGE_TO_URL': '',
'LANGUAGE_CODE': 'zh',
'TIME_ZONE': 'Asia/Shanghai',
'CHANGE_AUTH_PLAN_SECURE_MODE_ENABLED': True,
'USER_LOGIN_SINGLE_MACHINE_ENABLED': False,
'TICKETS_ENABLED': True,
'SESSION_COOKIE_SECURE': False,
'CSRF_COOKIE_SECURE': False,
'REFERER_CHECK_ENABLED': False,
'SERVER_REPLAY_STORAGE': {},
'CONNECTION_TOKEN_ENABLED': False,
'ONLY_ALLOW_EXIST_USER_AUTH': False,
'ONLY_ALLOW_AUTH_FROM_SOURCE': False,
'SESSION_SAVE_EVERY_REQUEST': True,
'SESSION_EXPIRE_AT_BROWSER_CLOSE_FORCE': False,
'FORGOT_PASSWORD_URL': '',
'HEALTH_CHECK_TOKEN': '',
'LOGIN_REDIRECT_TO_BACKEND': None, # 'OPENID / CAS
'CLOUD_SYNC_TASK_EXECUTION_KEEP_DAYS': 30,
'TERMINAL_RDP_ADDR': ''
# 废弃的
'DEFAULT_ORG_SHOW_ALL_USERS': True,
'ORG_CHANGE_TO_URL': '',
'WINDOWS_SKIP_ALL_MANUAL_PASSWORD': False,
'CONNECTION_TOKEN_ENABLED': False,
'PERM_SINGLE_ASSET_TO_UNGROUP_NODE': False,
'WINDOWS_SSH_DEFAULT_SHELL': 'cmd',
'PERIOD_TASK_ENABLED': True,
'TICKETS_ENABLED': True,
'FORGOT_PASSWORD_URL': '',
'HEALTH_CHECK_TOKEN': '',
}
def compatible_auth_openid_of_key(self):
@ -324,6 +340,9 @@ class Config(dict):
构造出新配置中标准OpenID协议中所需的Endpoint即可
(Keycloak说明文档参考: https://www.keycloak.org/docs/latest/securing_apps/)
"""
if self.AUTH_OPENID and not self.AUTH_OPENID_REALM_NAME:
self['AUTH_OPENID_KEYCLOAK'] = False
if not self.AUTH_OPENID:
return

View File

@ -72,14 +72,9 @@ 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
ASSETS_PERM_CACHE_TIME = CONFIG.ASSETS_PERM_CACHE_TIME
# Asset user auth external backend, default AuthBook backend
BACKEND_ASSET_USER_AUTH_VAULT = False
DEFAULT_ORG_SHOW_ALL_USERS = CONFIG.DEFAULT_ORG_SHOW_ALL_USERS
PERM_SINGLE_ASSET_TO_UNGROUP_NODE = CONFIG.PERM_SINGLE_ASSET_TO_UNGROUP_NODE
PERM_EXPIRED_CHECK_PERIODIC = CONFIG.PERM_EXPIRED_CHECK_PERIODIC
WINDOWS_SSH_DEFAULT_SHELL = CONFIG.WINDOWS_SSH_DEFAULT_SHELL
@ -132,5 +127,6 @@ SECURITY_WATERMARK_ENABLED = CONFIG.SECURITY_WATERMARK_ENABLED
SECURITY_SESSION_SHARE = CONFIG.SECURITY_SESSION_SHARE
LOGIN_REDIRECT_TO_BACKEND = CONFIG.LOGIN_REDIRECT_TO_BACKEND
LOGIN_REDIRECT_MSG_ENABLED = CONFIG.LOGIN_REDIRECT_MSG_ENABLED
CLOUD_SYNC_TASK_EXECUTION_KEEP_DAYS = CONFIG.CLOUD_SYNC_TASK_EXECUTION_KEEP_DAYS

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,6 @@ from redis.exceptions import ConnectionError
from channels.generic.websocket import JsonWebsocketConsumer
from common.utils import get_logger
from .models import SiteMessage
from .site_msg import SiteMessageUtil
from .signals_handler import new_site_msg_chan

View File

@ -46,7 +46,7 @@ class BaseHost(Host):
if host_data.get('username'):
self.set_variable('ansible_user', host_data['username'])
# 添加密码和
# 添加密码和
if host_data.get('password'):
self.set_variable('ansible_ssh_pass', host_data['password'])
if host_data.get('private_key'):

View File

@ -159,7 +159,7 @@ class PeriodTaskFormMixin(forms.Form):
)
interval = forms.IntegerField(
required=False, initial=24,
help_text=_('Tips: (Units: hour)'), label=_("Cycle perform"),
help_text=_('Unit: hour'), label=_("Cycle perform"),
)
def get_initial_for_field(self, field, field_name):

View File

@ -1,5 +1,7 @@
from .common import *
from .settings import *
from .ldap import *
from .wecom import *
from .dingtalk import *
from .feishu import *
from .public import *
from .email import *

View File

@ -1,193 +0,0 @@
# -*- 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 jumpserver.utils import has_valid_xpack_license
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.jpg'),
'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_login_title():
default_title = _('Welcome to the JumpServer open source Bastion Host')
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,
"OLD_PASSWORD_HISTORY_LIMIT_COUNT": settings.OLD_PASSWORD_HISTORY_LIMIT_COUNT,
"SECURITY_COMMAND_EXECUTION": settings.SECURITY_COMMAND_EXECUTION,
"SECURITY_PASSWORD_EXPIRATION_TIME": settings.SECURITY_PASSWORD_EXPIRATION_TIME,
"SECURITY_LUNA_REMEMBER_AUTH": settings.SECURITY_LUNA_REMEMBER_AUTH,
"XPACK_LICENSE_IS_VALID": has_valid_xpack_license(),
"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_ADMIN_USER_PASSWORD_MIN_LENGTH': settings.SECURITY_ADMIN_USER_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,
},
"AUTH_WECOM": settings.AUTH_WECOM,
"AUTH_DINGTALK": settings.AUTH_DINGTALK,
"AUTH_FEISHU": settings.AUTH_FEISHU,
'SECURITY_WATERMARK_ENABLED': settings.SECURITY_WATERMARK_ENABLED,
'SECURITY_SESSION_SHARE': settings.SECURITY_SESSION_SHARE
}
}
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,
'wecom': serializers.WeComSettingSerializer,
'dingtalk': serializers.DingTalkSettingSerializer,
'feishu': serializers.FeiShuSettingSerializer,
}
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()
obj = {item: getattr(settings, item) for item in items}
return obj
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
if encrypted and value in ['', None]:
continue
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)

View File

@ -0,0 +1,68 @@
# -*- coding: utf-8 -*-
#
from smtplib import SMTPSenderRefused
from rest_framework.views import Response, APIView
from django.core.mail import send_mail, get_connection
from django.utils.translation import ugettext_lazy as _
from common.permissions import IsSuperUser
from common.utils import get_logger
from .. import serializers
logger = get_logger(__file__)
__all__ = ['MailTestingAPI']
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)})

View File

@ -0,0 +1,79 @@
from rest_framework import generics
from rest_framework.permissions import AllowAny
from django.conf import settings
from django.utils.translation import ugettext_lazy as _
from django.templatetags.static import static
from jumpserver.utils import has_valid_xpack_license
from common.utils import get_logger
from .. import serializers
logger = get_logger(__name__)
__all__ = ['PublicSettingApi']
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.jpg'),
'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_login_title():
default_title = _('Welcome to the JumpServer open source Bastion Host')
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,
"OLD_PASSWORD_HISTORY_LIMIT_COUNT": settings.OLD_PASSWORD_HISTORY_LIMIT_COUNT,
"SECURITY_COMMAND_EXECUTION": settings.SECURITY_COMMAND_EXECUTION,
"SECURITY_PASSWORD_EXPIRATION_TIME": settings.SECURITY_PASSWORD_EXPIRATION_TIME,
"SECURITY_LUNA_REMEMBER_AUTH": settings.SECURITY_LUNA_REMEMBER_AUTH,
"XPACK_LICENSE_IS_VALID": has_valid_xpack_license(),
"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_ADMIN_USER_PASSWORD_MIN_LENGTH': settings.SECURITY_ADMIN_USER_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,
},
"AUTH_WECOM": settings.AUTH_WECOM,
"AUTH_DINGTALK": settings.AUTH_DINGTALK,
"AUTH_FEISHU": settings.AUTH_FEISHU,
'SECURITY_WATERMARK_ENABLED': settings.SECURITY_WATERMARK_ENABLED,
'SECURITY_SESSION_SHARE': settings.SECURITY_SESSION_SHARE,
}
}
return instance

View File

@ -0,0 +1,85 @@
# -*- coding: utf-8 -*-
#
from rest_framework import generics
from django.conf import settings
from jumpserver.conf import Config
from common.permissions import IsSuperUser
from common.utils import get_logger
from .. import serializers
from ..models import Setting
logger = get_logger(__file__)
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,
'wecom': serializers.WeComSettingSerializer,
'dingtalk': serializers.DingTalkSettingSerializer,
'feishu': serializers.FeiShuSettingSerializer,
'auth': serializers.AuthSettingSerializer,
'oidc': serializers.OIDCSettingSerializer,
'keycloak': serializers.KeycloakSettingSerializer,
'radius': serializers.RadiusSettingSerializer,
'cas': serializers.CASSettingSerializer,
'sso': serializers.SSOSettingSerializer,
'clean': serializers.CleaningSerializer,
'other': serializers.OtherSettingSerializer,
}
def get_serializer_class(self):
category = self.request.query_params.get('category', 'basic')
default = serializers.BasicSettingSerializer
cls = self.serializer_class_mapper.get(category, default)
return cls
def get_fields(self):
serializer = self.get_serializer_class()()
fields = serializer.get_fields()
return fields
def get_object(self):
items = self.get_fields().keys()
obj = {}
for item in items:
if hasattr(settings, item):
obj[item] = getattr(settings, item)
else:
obj[item] = Config.defaults[item]
return obj
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
if encrypted and value in ['', None]:
continue
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)
if hasattr(serializer, 'post_save'):
serializer.post_save()

View File

@ -0,0 +1,18 @@
# Generated by Django 3.1.12 on 2021-09-01 02:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('settings', '0002_auto_20210729_1546'),
]
operations = [
migrations.AlterField(
model_name='setting',
name='value',
field=models.TextField(blank=True, null=True, verbose_name='Value'),
),
]

View File

@ -27,7 +27,7 @@ class SettingManager(models.Manager):
class Setting(models.Model):
name = models.CharField(max_length=128, unique=True, verbose_name=_("Name"))
value = models.TextField(verbose_name=_("Value"))
value = models.TextField(verbose_name=_("Value"), null=True, blank=True)
category = models.CharField(max_length=128, default="default")
encrypted = models.BooleanField(default=False)
enabled = models.BooleanField(verbose_name=_("Enabled"), default=True)

View File

@ -1,7 +1,13 @@
# coding: utf-8
#
from .basic import *
from .auth import *
from .email import *
from .ldap import *
from .public import *
from .settings import *
from .security import *
from .terminal import *
from .cleaning import *
from .other import *

View File

@ -0,0 +1,9 @@
from .cas import *
from .ldap import *
from .oidc import *
from .radius import *
from .dingtalk import *
from .feishu import *
from .wecom import *
from .sso import *
from .base import *

View File

@ -0,0 +1,25 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
__all__ = [
'AuthSettingSerializer',
]
class AuthSettingSerializer(serializers.Serializer):
AUTH_CAS = serializers.BooleanField(required=False, label=_('CAS Auth'))
AUTH_OPENID = serializers.BooleanField(required=False, label=_('OPENID Auth'))
AUTH_RADIUS = serializers.BooleanField(required=False, label=_('RADIUS Auth'))
AUTH_DINGTALK = serializers.BooleanField(default=False, label=_('DingTalk Auth'))
AUTH_FEISHU = serializers.BooleanField(default=False, label=_('FeiShu Auth'))
AUTH_WECOM = serializers.BooleanField(default=False, label=_('WeCom Auth'))
AUTH_SSO = serializers.BooleanField(default=False, label=_("SSO Auth"))
FORGOT_PASSWORD_URL = serializers.CharField(
required=False, max_length=1024, label=_("Forgot password url")
)
HEALTH_CHECK_TOKEN = serializers.CharField(
required=False, max_length=1024, label=_("Health check token")
)
LOGIN_REDIRECT_MSG_ENABLED = serializers.BooleanField(
required=False, label=_("Enable login redirect msg")
)

View File

@ -0,0 +1,18 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
__all__ = [
'CASSettingSerializer',
]
class CASSettingSerializer(serializers.Serializer):
AUTH_CAS = serializers.BooleanField(required=False, label=_('Enable CAS Auth'))
CAS_SERVER_URL = serializers.CharField(required=False, max_length=1024, label=_('Server url'))
CAS_LOGOUT_COMPLETELY = serializers.BooleanField(required=False, label=_('Logout completely'))
CAS_VERSION = serializers.IntegerField(required=False, label=_('Version'))
CAS_USERNAME_ATTRIBUTE = serializers.CharField(required=False, max_length=1024, label=_('Username attr'))
CAS_APPLY_ATTRIBUTES_TO_USER = serializers.BooleanField(required=False, label=_('Enable attributes map'))
CAS_RENAME_ATTRIBUTES = serializers.DictField(required=False, label=_('Rename attr'))
CAS_CREATE_USER = serializers.BooleanField(required=False, label=_('Create user if not'))

View File

@ -0,0 +1,11 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
__all__ = ['DingTalkSettingSerializer']
class DingTalkSettingSerializer(serializers.Serializer):
DINGTALK_AGENTID = serializers.CharField(max_length=256, required=True, label='AgentId')
DINGTALK_APPKEY = serializers.CharField(max_length=256, required=True, label='AppKey')
DINGTALK_APPSECRET = serializers.CharField(max_length=256, required=False, label='AppSecret', write_only=True)
AUTH_DINGTALK = serializers.BooleanField(default=False, label=_('Enable DingTalk Auth'))

View File

@ -0,0 +1,11 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
__all__ = ['FeiShuSettingSerializer']
class FeiShuSettingSerializer(serializers.Serializer):
FEISHU_APP_ID = serializers.CharField(max_length=256, required=True, label='App ID')
FEISHU_APP_SECRET = serializers.CharField(max_length=256, required=False, label='App Secret', write_only=True)
AUTH_FEISHU = serializers.BooleanField(default=False, label=_('Enable FeiShu Auth'))

View File

@ -0,0 +1,74 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
__all__ = [
'LDAPTestConfigSerializer', 'LDAPUserSerializer', 'LDAPTestLoginSerializer',
'LDAPSettingSerializer',
]
class LDAPTestConfigSerializer(serializers.Serializer):
AUTH_LDAP_SERVER_URI = serializers.CharField(max_length=1024)
AUTH_LDAP_BIND_DN = serializers.CharField(max_length=1024, required=False, allow_blank=True)
AUTH_LDAP_BIND_PASSWORD = serializers.CharField(required=False, allow_blank=True)
AUTH_LDAP_SEARCH_OU = serializers.CharField()
AUTH_LDAP_SEARCH_FILTER = serializers.CharField()
AUTH_LDAP_USER_ATTR_MAP = serializers.CharField()
AUTH_LDAP_START_TLS = serializers.BooleanField(required=False)
AUTH_LDAP = serializers.BooleanField(required=False)
class LDAPTestLoginSerializer(serializers.Serializer):
username = serializers.CharField(max_length=1024, required=True)
password = serializers.CharField(max_length=2014, required=True)
class LDAPUserSerializer(serializers.Serializer):
id = serializers.CharField()
username = serializers.CharField()
name = serializers.CharField()
email = serializers.CharField()
existing = serializers.BooleanField(read_only=True)
class LDAPSettingSerializer(serializers.Serializer):
# encrypt_fields 现在使用 write_only 来判断了
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_SYNC_IS_PERIODIC = serializers.BooleanField(required=False, label=_('Periodic display'))
AUTH_LDAP_SYNC_INTERVAL = serializers.CharField(
required=False, max_length=1024, allow_null=True,
label=_('Interval'), help_text=_('Unit: hour')
)
AUTH_LDAP_SYNC_CRONTAB = serializers.CharField(
required=False, max_length=1024, allow_null=True, label=_('Regularly perform')
)
AUTH_LDAP_CONNECT_TIMEOUT = serializers.IntegerField(required=False, label=_('Connect timeout'))
AUTH_LDAP_SEARCH_PAGED_SIZE = serializers.IntegerField(required=False, label=_('Search paged size'))
AUTH_LDAP = serializers.BooleanField(required=False, label=_('Enable LDAP auth'))
@staticmethod
def post_save():
from users.tasks import import_ldap_user_periodic
import_ldap_user_periodic()

View File

@ -0,0 +1,78 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
__all__ = [
'OIDCSettingSerializer', 'KeycloakSettingSerializer',
]
class CommonSettingSerializer(serializers.Serializer):
# OpenID 公有配置参数 (version <= 1.5.8 或 version >= 1.5.8)
BASE_SITE_URL = serializers.CharField(
required=False, allow_null=True, max_length=1024, label=_('Base site url')
)
AUTH_OPENID_CLIENT_ID = serializers.CharField(
required=False, max_length=1024, label=_('Client Id')
)
AUTH_OPENID_CLIENT_SECRET = serializers.CharField(
required=False, max_length=1024, write_only=True, label=_('Client Secret')
)
AUTH_OPENID_SHARE_SESSION = serializers.BooleanField(required=False, label=_('Share session'))
AUTH_OPENID_IGNORE_SSL_VERIFICATION = serializers.BooleanField(
required=False, label=_('Ignore ssl verification')
)
class KeycloakSettingSerializer(CommonSettingSerializer):
# OpenID 旧配置参数 (version <= 1.5.8 (discarded))
AUTH_OPENID_KEYCLOAK = serializers.BooleanField(
label=_("Use Keycloak"), required=False, default=False
)
AUTH_OPENID_SERVER_URL = serializers.CharField(
required=False, max_length=1024, label=_('Server url')
)
AUTH_OPENID_REALM_NAME = serializers.CharField(
required=False, max_length=1024, allow_null=True, label=_('Realm name')
)
class OIDCSettingSerializer(KeycloakSettingSerializer):
# OpenID 新配置参数 (version >= 1.5.9)
AUTH_OPENID = serializers.BooleanField(required=False, label=_('Enable OPENID Auth'))
AUTH_OPENID_PROVIDER_ENDPOINT = serializers.CharField(
required=False, max_length=1024, label=_('Provider endpoint')
)
AUTH_OPENID_PROVIDER_AUTHORIZATION_ENDPOINT = serializers.CharField(
required=False, max_length=1024, label=_('Provider auth endpoint')
)
AUTH_OPENID_PROVIDER_TOKEN_ENDPOINT = serializers.CharField(
required=False, max_length=1024, label=_('Provider token endpoint')
)
AUTH_OPENID_PROVIDER_JWKS_ENDPOINT = serializers.CharField(
required=False, max_length=1024, label=_('Provider jwks endpoint')
)
AUTH_OPENID_PROVIDER_USERINFO_ENDPOINT = serializers.CharField(
required=False, max_length=1024, label=_('Provider userinfo endpoint')
)
AUTH_OPENID_PROVIDER_END_SESSION_ENDPOINT = serializers.CharField(
required=False, max_length=1024, label=_('Provider end session endpoint')
)
AUTH_OPENID_PROVIDER_SIGNATURE_ALG = serializers.CharField(
required=False, max_length=1024, label=_('Provider sign alg')
)
AUTH_OPENID_PROVIDER_SIGNATURE_KEY = serializers.CharField(
required=False, max_length=1024, allow_null=True, label=_('Provider sign key')
)
AUTH_OPENID_SCOPES = serializers.CharField(required=False, max_length=1024, label=_('Scopes'))
AUTH_OPENID_ID_TOKEN_MAX_AGE = serializers.IntegerField(
required=False, label=_('Id token max age')
)
AUTH_OPENID_ID_TOKEN_INCLUDE_CLAIMS = serializers.BooleanField(
required=False, label=_('Id token include claims')
)
AUTH_OPENID_USE_STATE = serializers.BooleanField(required=False, label=_('Use state'))
AUTH_OPENID_USE_NONCE = serializers.BooleanField(required=False, label=_('Use nonce'))
AUTH_OPENID_ALWAYS_UPDATE_USER = serializers.BooleanField(
required=False, label=_('Always update user')
)

View File

@ -0,0 +1,19 @@
# coding: utf-8
#
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
__all__ = [
'RadiusSettingSerializer',
]
class RadiusSettingSerializer(serializers.Serializer):
AUTH_RADIUS = serializers.BooleanField(required=False, label=_('Enable RADIUS Auth'))
RADIUS_SERVER = serializers.CharField(required=False, max_length=1024, label=_('Host'))
RADIUS_PORT = serializers.IntegerField(required=False, label=_('Port'))
RADIUS_SECRET = serializers.CharField(
required=False, max_length=1024, allow_null=True, label=_('Secret'), write_only=True
)
OTP_IN_RADIUS = serializers.BooleanField(required=False, label=_('OTP in radius'))

View File

@ -0,0 +1,17 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
__all__ = [
'SSOSettingSerializer',
]
class SSOSettingSerializer(serializers.Serializer):
AUTH_SSO = serializers.BooleanField(
required=False, label=_('Enable SSO auth'),
help_text=_("Other service can using SSO token login to JumpServer without password")
)
AUTH_SSO_AUTHKEY_TTL = serializers.IntegerField(
required=False, label=_('SSO auth key TTL'), help_text=_("Unit: second")
)

View File

@ -0,0 +1,11 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
__all__ = ['WeComSettingSerializer']
class WeComSettingSerializer(serializers.Serializer):
WECOM_CORPID = serializers.CharField(max_length=256, required=True, label='corpid')
WECOM_AGENTID = serializers.CharField(max_length=256, required=True, label='agentid')
WECOM_SECRET = serializers.CharField(max_length=256, required=False, label='secret', write_only=True)
AUTH_WECOM = serializers.BooleanField(default=False, label=_('Enable WeCom Auth'))

View File

@ -0,0 +1,22 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
class BasicSettingSerializer(serializers.Serializer):
SITE_URL = serializers.URLField(
required=True, label=_("Site url"),
help_text=_('eg: http://dev.jumpserver.org:8080')
)
USER_GUIDE_URL = serializers.URLField(
required=False, allow_blank=True, allow_null=True, label=_("User guide url"),
help_text=_('User first login update profile done redirect to it')
)
FORGOT_PASSWORD_URL = serializers.URLField(
required=False, allow_blank=True, allow_null=True, label=_("Forgot password url"),
help_text=_('The forgot password url on login page, If you use '
'ldap or cas external authentication, you can set it')
)
GLOBAL_ORG_DISPLAY_NAME = serializers.CharField(
required=False, max_length=1024, allow_blank=True, allow_null=True, label=_("Global organization name"),
help_text=_('The name of global organization to display')
)

View File

@ -0,0 +1,22 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
__all__ = ['CleaningSerializer']
class CleaningSerializer(serializers.Serializer):
LOGIN_LOG_KEEP_DAYS = serializers.IntegerField(
label=_("Login log keep days"), help_text=_("Unit: day")
)
TASK_LOG_KEEP_DAYS = serializers.IntegerField(
label=_("Task log keep days"), help_text=_("Unit: day")
)
OPERATE_LOG_KEEP_DAYS = serializers.IntegerField(
label=_("Operate log keep days"), help_text=_("Unit: day")
)
FTP_LOG_KEEP_DAYS = serializers.IntegerField(
label=_("FTP log keep days"), help_text=_("Unit: day")
)
CLOUD_SYNC_TASK_EXECUTION_KEEP_DAYS = serializers.IntegerField(
label=_("Cloud sync record keep days"), help_text=_("Unit: day")
)

View File

@ -1,9 +1,10 @@
# coding: utf-8
#
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
__all__ = ['MailTestSerializer']
__all__ = ['MailTestSerializer', 'EmailSettingSerializer', 'EmailContentSettingSerializer']
class MailTestSerializer(serializers.Serializer):
@ -15,3 +16,56 @@ class MailTestSerializer(serializers.Serializer):
EMAIL_RECIPIENT = serializers.CharField(required=False, allow_blank=True)
EMAIL_USE_SSL = serializers.BooleanField(default=False)
EMAIL_USE_TLS = serializers.BooleanField(default=False)
class EmailSettingSerializer(serializers.Serializer):
# encrypt_fields 现在使用 write_only 来判断了
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,
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)')
)

View File

@ -1,34 +0,0 @@
# coding: utf-8
#
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
__all__ = [
'LDAPTestConfigSerializer', 'LDAPUserSerializer', 'LDAPTestLoginSerializer'
]
class LDAPTestConfigSerializer(serializers.Serializer):
AUTH_LDAP_SERVER_URI = serializers.CharField(max_length=1024)
AUTH_LDAP_BIND_DN = serializers.CharField(max_length=1024, required=False, allow_blank=True)
AUTH_LDAP_BIND_PASSWORD = serializers.CharField(required=False, allow_blank=True)
AUTH_LDAP_SEARCH_OU = serializers.CharField()
AUTH_LDAP_SEARCH_FILTER = serializers.CharField()
AUTH_LDAP_USER_ATTR_MAP = serializers.CharField()
AUTH_LDAP_START_TLS = serializers.BooleanField(required=False)
AUTH_LDAP = serializers.BooleanField(required=False)
class LDAPTestLoginSerializer(serializers.Serializer):
username = serializers.CharField(max_length=1024, required=True)
password = serializers.CharField(max_length=2014, required=True)
class LDAPUserSerializer(serializers.Serializer):
id = serializers.CharField()
username = serializers.CharField()
name = serializers.CharField()
email = serializers.CharField()
existing = serializers.BooleanField(read_only=True)

View File

@ -0,0 +1,28 @@
from abc import ABCMeta
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
class OtherSettingSerializer(serializers.Serializer):
EMAIL_SUFFIX = serializers.CharField(
required=False, max_length=1024, label=_("Email suffix"),
help_text=_('This is used by default if no email is returned during SSO authentication')
)
TICKETS_ENABLED = serializers.BooleanField(required=False, default=True, label=_("Enable tickets"))
OTP_ISSUER_NAME = serializers.CharField(
required=False, max_length=1024, label=_('OTP issuer name'),
)
OTP_VALID_WINDOW = serializers.IntegerField(label=_("OTP valid window"))
PERIOD_TASK_ENABLED = serializers.BooleanField(required=False, label=_("Enable period task"))
WINDOWS_SSH_DEFAULT_SHELL = serializers.CharField(
required=False, max_length=1024, label=_('Ansible windows default shell')
)
PERM_SINGLE_ASSET_TO_UNGROUP_NODE = serializers.BooleanField(
required=False, label=_("Perm single to ungroup node")
)

View File

@ -0,0 +1,115 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
class SecurityPasswordRuleSerializer(serializers.Serializer):
SECURITY_PASSWORD_MIN_LENGTH = serializers.IntegerField(
min_value=6, max_value=30, required=True,
label=_('Password minimum length')
)
SECURITY_ADMIN_USER_PASSWORD_MIN_LENGTH = serializers.IntegerField(
min_value=6, max_value=30, required=True,
label=_('Admin user 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'))
class SecurityAuthSerializer(serializers.Serializer):
SECURITY_MFA_AUTH = serializers.ChoiceField(
choices=(
[0, _('Disable')],
[1, _('All users')],
[2, _('Only admin users')],
),
required=False, label=_("Global MFA auth")
)
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=_(
'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_PASSWORD_EXPIRATION_TIME = serializers.IntegerField(
min_value=1, max_value=99999, required=True,
label=_('User password expiration'),
help_text=_(
'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'
)
)
OLD_PASSWORD_HISTORY_LIMIT_COUNT = serializers.IntegerField(
min_value=0, max_value=99999, required=True,
label=_('Number of repeated historical passwords'),
help_text=_(
'Tip: When the user resets the password, it cannot be '
'the previous n historical passwords of the user'
)
)
USER_LOGIN_SINGLE_MACHINE_ENABLED = serializers.BooleanField(
required=False, default=False, label=_("Only single device login"),
help_text=_("Next device login, pre login will be logout")
)
ONLY_ALLOW_EXIST_USER_AUTH = serializers.BooleanField(
required=False, default=False, label=_("Only exist user login"),
help_text=_("If enable, CAS、OIDC auth will be failed, if user not exist yet")
)
ONLY_ALLOW_AUTH_FROM_SOURCE = serializers.BooleanField(
required=False, default=False, label=_("Only from source login"),
help_text=_("If enable, CAS、OIDC auth will be failed, if user not exist yet")
)
SECURITY_MFA_VERIFY_TTL = serializers.IntegerField(label=_("MFA verify TTL"), help_text=_("Unit: second"))
SECURITY_LOGIN_CAPTCHA_ENABLED = serializers.BooleanField(
required=False, default=True,
label=_("Enable Login captcha")
)
class SecuritySettingSerializer(SecurityPasswordRuleSerializer, SecurityAuthSerializer):
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_WATERMARK_ENABLED = serializers.BooleanField(
required=True, label=_('Replay watermark'),
help_text=_('Enabled, the session replay contains watermark information')
)
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_LUNA_REMEMBER_AUTH = serializers.BooleanField(
label=_("Remember manual auth")
)
CHANGE_AUTH_PLAN_SECURE_MODE_ENABLED = serializers.BooleanField(
label=_("Enable change auth secure mode")
)
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')
)
SECURITY_COMMAND_EXECUTION = serializers.BooleanField(
required=False, label=_('Batch command execution'),
help_text=_('Allow user run batch command or not using ansible')
)
SECURITY_SESSION_SHARE = serializers.BooleanField(
required=True, label=_('Session share'),
help_text=_("Enabled, Allows user active session to be shared with other users")
)

View File

@ -1,250 +1,38 @@
# coding: utf-8
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from .basic import BasicSettingSerializer
from .other import OtherSettingSerializer
from .email import EmailSettingSerializer, EmailContentSettingSerializer
from .auth import (
LDAPSettingSerializer, OIDCSettingSerializer, KeycloakSettingSerializer,
CASSettingSerializer, RadiusSettingSerializer, FeiShuSettingSerializer,
WeComSettingSerializer, DingTalkSettingSerializer
)
from .terminal import TerminalSettingSerializer
from .security import SecuritySettingSerializer
from .cleaning import CleaningSerializer
__all__ = [
'BasicSettingSerializer', 'EmailSettingSerializer', 'EmailContentSettingSerializer',
'LDAPSettingSerializer', 'TerminalSettingSerializer', 'SecuritySettingSerializer',
'SettingsSerializer', 'WeComSettingSerializer', 'DingTalkSettingSerializer',
'FeiShuSettingSerializer',
'SettingsSerializer',
]
class BasicSettingSerializer(serializers.Serializer):
SITE_URL = serializers.URLField(
required=True, label=_("Site url"),
help_text=_('eg: http://dev.jumpserver.org:8080')
)
USER_GUIDE_URL = serializers.URLField(
required=False, allow_blank=True, allow_null=True, label=_("User guide url"),
help_text=_('User first login update profile done redirect to it')
)
FORGOT_PASSWORD_URL = serializers.URLField(
required=False, allow_blank=True, allow_null=True, label=_("Forgot password url"),
help_text=_('The forgot password url on login page, If you use '
'ldap or cas external authentication, you can set it')
)
GLOBAL_ORG_DISPLAY_NAME = serializers.CharField(
required=False, max_length=1024, allow_blank=True, allow_null=True, label=_("Global organization name"),
help_text=_('The name of global organization to display')
)
class EmailSettingSerializer(serializers.Serializer):
# encrypt_fields 现在使用 write_only 来判断了
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,
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 现在使用 write_only 来判断了
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):
SORT_BY_CHOICES = (
('hostname', _('Hostname')),
('ip', _('IP'))
)
PAGE_SIZE_CHOICES = (
('all', _('All')),
('auto', _('Auto')),
('10', '10'),
('15', '15'),
('25', '25'),
('50', '50'),
)
TERMINAL_PASSWORD_AUTH = serializers.BooleanField(required=False, label=_('Password auth'))
TERMINAL_PUBLIC_KEY_AUTH = serializers.BooleanField(
required=False, label=_('Public key auth'),
help_text=_('Tips: If use other auth method, like AD/LDAP, you should disable this to '
'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_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'))
TERMINAL_RDP_ADDR = serializers.CharField(
required=False, label=_("RDP address"),
max_length=1024,
allow_blank=True,
help_text=_('RDP visit address, eg: dev.jumpserver.org:3389')
)
class SecuritySettingSerializer(serializers.Serializer):
SECURITY_MFA_AUTH = serializers.ChoiceField(
choices=(
[0, _('Disable')],
[1, _('All users')],
[2, _('Only admin users')],
),
required=False, label=_("Global MFA auth")
)
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_WATERMARK_ENABLED = serializers.BooleanField(
required=True, label=_('Replay watermark'),
help_text=_('Enabled, the session replay contains watermark information')
)
SECURITY_SESSION_SHARE = serializers.BooleanField(
required=True, label=_('Session share'),
help_text=_("Enabled, Allows user active session to be shared with other users")
)
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')
)
OLD_PASSWORD_HISTORY_LIMIT_COUNT = serializers.IntegerField(
min_value=0, max_value=99999, required=True,
label=_('Number of repeated historical passwords'),
help_text=_('Tip: When the user resets the password, it cannot be the previous n historical passwords of the user')
)
SECURITY_PASSWORD_MIN_LENGTH = serializers.IntegerField(
min_value=6, max_value=30, required=True,
label=_('Password minimum length')
)
SECURITY_ADMIN_USER_PASSWORD_MIN_LENGTH = serializers.IntegerField(
min_value=6, max_value=30, required=True,
label=_('Admin user 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 WeComSettingSerializer(serializers.Serializer):
WECOM_CORPID = serializers.CharField(max_length=256, required=True, label='corpid')
WECOM_AGENTID = serializers.CharField(max_length=256, required=True, label='agentid')
WECOM_SECRET = serializers.CharField(max_length=256, required=False, label='secret', write_only=True)
AUTH_WECOM = serializers.BooleanField(default=False, label=_('Enable WeCom Auth'))
class DingTalkSettingSerializer(serializers.Serializer):
DINGTALK_AGENTID = serializers.CharField(max_length=256, required=True, label='AgentId')
DINGTALK_APPKEY = serializers.CharField(max_length=256, required=True, label='AppKey')
DINGTALK_APPSECRET = serializers.CharField(max_length=256, required=False, label='AppSecret', write_only=True)
AUTH_DINGTALK = serializers.BooleanField(default=False, label=_('Enable DingTalk Auth'))
class FeiShuSettingSerializer(serializers.Serializer):
FEISHU_APP_ID = serializers.CharField(max_length=256, required=True, label='App ID')
FEISHU_APP_SECRET = serializers.CharField(max_length=256, required=False, label='App Secret', write_only=True)
AUTH_FEISHU = serializers.BooleanField(default=False, label=_('Enable FeiShu Auth'))
class SettingsSerializer(
BasicSettingSerializer,
EmailSettingSerializer,
EmailContentSettingSerializer,
LDAPSettingSerializer,
TerminalSettingSerializer,
SecuritySettingSerializer,
WeComSettingSerializer,
DingTalkSettingSerializer,
FeiShuSettingSerializer,
EmailSettingSerializer,
EmailContentSettingSerializer,
OtherSettingSerializer,
OIDCSettingSerializer,
KeycloakSettingSerializer,
CASSettingSerializer,
RadiusSettingSerializer,
CleaningSerializer
):
# encrypt_fields 现在使用 write_only 来判断了
pass

View File

@ -0,0 +1,42 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
class TerminalSettingSerializer(serializers.Serializer):
SORT_BY_CHOICES = (
('hostname', _('Hostname')),
('ip', _('IP'))
)
PAGE_SIZE_CHOICES = (
('all', _('All')),
('auto', _('Auto')),
('10', '10'),
('15', '15'),
('25', '25'),
('50', '50'),
)
TERMINAL_PASSWORD_AUTH = serializers.BooleanField(required=False, label=_('Password auth'))
TERMINAL_PUBLIC_KEY_AUTH = serializers.BooleanField(
required=False, label=_('Public key auth'),
help_text=_('Tips: If use other auth method, like AD/LDAP, you should disable this to '
'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_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=_('Unit: 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'),
help_text=_("The login success message varies with devices. "
"if you cannot log in to the device through Telnet, set this parameter")
)
TERMINAL_RDP_ADDR = serializers.CharField(
required=False, label=_("RDP address"),
max_length=1024,
allow_blank=True,
help_text=_('RDP visit address, eg: dev.jumpserver.org:3389')
)

View File

@ -92,8 +92,8 @@ def import_ldap_user():
def import_ldap_user_periodic():
if not settings.AUTH_LDAP:
return
task_name = 'import_ldap_user_periodic'
if not settings.AUTH_LDAP_SYNC_IS_PERIODIC:
task_name = sys._getframe().f_code.co_name
disable_celery_periodic_task(task_name)
return
@ -104,7 +104,7 @@ def import_ldap_user_periodic():
interval = None
crontab = settings.AUTH_LDAP_SYNC_CRONTAB
tasks = {
'import_ldap_user_periodic': {
task_name: {
'task': import_ldap_user.name,
'interval': interval,
'crontab': crontab,

View File

@ -1,5 +1,5 @@
# SECURITY WARNING: keep the secret key used in production secret!
# 加密钥 生产环境中请修改为随机字符串,请勿外泄, 可使用命令生成
# 加密钥 生产环境中请修改为随机字符串,请勿外泄, 可使用命令生成
# $ cat /dev/urandom | tr -dc A-Za-z0-9 | head -c 49;echo
SECRET_KEY: