mirror of https://github.com/jumpserver/jumpserver
Merge pull request #8457 from jumpserver/pr@dev@perf_redis
perf: redis AND login pagepull/8465/head
commit
2471787277
|
@ -40,3 +40,4 @@ logs/*
|
|||
release/*
|
||||
releashe
|
||||
/apps/script.py
|
||||
data/certs
|
||||
|
|
|
@ -32,12 +32,29 @@
|
|||
font-weight: normal;
|
||||
}
|
||||
|
||||
.hr-line-dashed {
|
||||
border-top: 1px dashed #e7eaec;
|
||||
color: #ffffff;
|
||||
background-color: #ffffff;
|
||||
height: 1px;
|
||||
margin: 20px 0;
|
||||
.form-group {
|
||||
margin-bottom: 40px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.addition .form-group, .has-error .form-group {
|
||||
margin-bottom: 20px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.auth-methods.has-error .form-group, .auth-methods.addition .form-group {
|
||||
margin-bottom: 15px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.has-error.addition .form-group {
|
||||
margin-bottom: 20px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.auth-methods.addition.has-error .form-group {
|
||||
margin-bottom: 10px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.login-content {
|
||||
|
@ -78,34 +95,25 @@
|
|||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.captch-field .has-error .help-block {
|
||||
.captcha-field .has-error .help-block {
|
||||
margin-top: -8px !important;
|
||||
}
|
||||
|
||||
.no-captcha-challenge .form-group {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.jms-title {
|
||||
padding: 40px 10px 10px;
|
||||
}
|
||||
|
||||
.no-captcha-challenge .jms-title {
|
||||
padding: 60px 10px 10px;
|
||||
}
|
||||
|
||||
.no-captcha-challenge .welcome-message {
|
||||
padding-top: 10px;
|
||||
.more-login-items {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.more-login-item {
|
||||
border-right: 1px dashed #dedede;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
.more-login-item:last-child {
|
||||
border: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.select-con {
|
||||
|
@ -117,6 +125,7 @@
|
|||
}
|
||||
|
||||
.login-page-language {
|
||||
font-size: 12px!important;
|
||||
margin-right: -11px !important;
|
||||
padding-top: 12px !important;
|
||||
padding-left: 0 !important;
|
||||
|
@ -125,15 +134,65 @@
|
|||
font-weight: 350 !important;
|
||||
min-height: auto !important;
|
||||
}
|
||||
|
||||
.right-image {
|
||||
height: 100%;
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.jms-title {
|
||||
font-size: 21px;
|
||||
font-weight:400;
|
||||
color: #151515;
|
||||
letter-spacing: 0;
|
||||
}
|
||||
.more-methods-title {
|
||||
position: relative;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.more-methods-title:before, .more-methods-title:after {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
content: '';
|
||||
border: 1px dashed #e7eaec;
|
||||
width: 35%;
|
||||
}
|
||||
.more-methods-title:before {
|
||||
left: 0;
|
||||
}
|
||||
.more-methods-title:after {
|
||||
right: 0;
|
||||
}
|
||||
.more-methods-title.ja:before, .more-methods-title.ja:after{
|
||||
width: 26%;
|
||||
}
|
||||
.captcha-field .form-group {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.auto-login.form-group .checkbox {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.more-login {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.has-error .more-login {
|
||||
margin-top: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div class="login-content">
|
||||
<div class="login-content
|
||||
{% if form.errors or form.non_field_error %} has-error {% endif %}
|
||||
{% if auth_methods %} auth-methods {% endif %}
|
||||
{% if form.captcha or form.mfa_type or form.challenge %} addition {% endif %}
|
||||
">
|
||||
<div class="right-image-box">
|
||||
<a href="{% if not XPACK_ENABLED %}https://github.com/jumpserver/jumpserver{% endif %}">
|
||||
<img src="{{ LOGIN_IMAGE_URL }}" style="height: 100%; width: 100%"/>
|
||||
<a href="{% if not XPACK_ENABLED %}https://github.com/jumpserver/jumpserver.git{% endif %}">
|
||||
<img src="{{ LOGIN_IMAGE_URL }}" class="right-image" alt="screen-image"/>
|
||||
</a>
|
||||
</div>
|
||||
<div class="left-form-box {% if not form.challenge and not form.captcha %} no-captcha-challenge {% endif %}">
|
||||
|
@ -142,26 +201,23 @@
|
|||
<li class="dropdown">
|
||||
<a class="dropdown-toggle login-page-language" data-toggle="dropdown" href="#" target="_blank">
|
||||
<i class="fa fa-globe fa-lg" style="margin-right: 2px"></i>
|
||||
{% if request.COOKIES.django_language == 'en' %}
|
||||
<span>English<b class="caret"></b></span>
|
||||
{% elif request.COOKIES.django_language == 'ja' %}
|
||||
<span>日本語<b class="caret"></b></span>
|
||||
{% else %}
|
||||
<span>中文(简体)<b class="caret"></b></span>
|
||||
{% endif %}
|
||||
<span>{{ current_lang.title }}<b class="caret"></b></span>
|
||||
</a>
|
||||
<ul class="dropdown-menu profile-dropdown dropdown-menu-right">
|
||||
<li> <a id="switch_cn" href="{% url 'i18n-switch' lang='zh-hans' %}"> <span>中文(简体)</span> </a> </li>
|
||||
<li> <a id="switch_en" href="{% url 'i18n-switch' lang='en' %}"> <span>English</span> </a> </li>
|
||||
<li> <a id="switch_ja" href="{% url 'i18n-switch' lang='ja' %}"> <span>日本語</span> </a> </li>
|
||||
{% for lang in langs %}
|
||||
<li>
|
||||
<a href="{% url 'i18n-switch' lang=lang.code %}">
|
||||
<span>{{ lang.title }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="jms-title">
|
||||
<span style="font-size: 21px;font-weight:400;color: #151515;letter-spacing: 0;">{{ JMS_TITLE }}</span>
|
||||
<span style="">{{ JMS_TITLE }}</span>
|
||||
</div>
|
||||
<div class="contact-form col-md-10 col-md-offset-1">
|
||||
|
||||
<form id="login-form" action="" method="post" role="form" novalidate="novalidate">
|
||||
{% csrf_token %}
|
||||
<div style="line-height: 17px;margin-bottom: 20px;color: #999999;">
|
||||
|
@ -177,7 +233,6 @@
|
|||
</div>
|
||||
|
||||
{% bootstrap_field form.username show_label=False %}
|
||||
|
||||
<div class="form-group {% if form.password.errors %} has-error {% endif %}">
|
||||
<input type="password" class="form-control" id="password" placeholder="{% trans 'Password' %}" required>
|
||||
<input id="password-hidden" type="text" style="display:none" name="{{ form.password.html_name }}">
|
||||
|
@ -194,18 +249,18 @@
|
|||
{% include '_mfa_login_field.html' %}
|
||||
</div>
|
||||
{% elif form.captcha %}
|
||||
<div class="captch-field">
|
||||
<div class="captcha-field">
|
||||
{% bootstrap_field form.captcha show_label=False %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="form-group" style="padding-top: 5px; margin-bottom: 10px">
|
||||
<div class="form-group auto-login" style="margin-bottom: 10px">
|
||||
<div class="row">
|
||||
<div class="col-md-6" style="text-align: left">
|
||||
{% if form.auto_login %}
|
||||
{% bootstrap_field form.auto_login form_group_class='' %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-6" style="line-height: 25px">
|
||||
<a id="forgot_password" href="{{ forgot_password_url }}" style="float: right">
|
||||
<small>{% trans 'Forgot password' %}?</small>
|
||||
</a>
|
||||
|
@ -213,18 +268,21 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" style="">
|
||||
<button type="submit" class="btn btn-transparent" onclick="doLogin();return false;">{% trans 'Login' %}</button>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-transparent" onclick="doLogin();return false;">
|
||||
{% trans 'Login' %}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="more-login">
|
||||
{% if auth_methods %}
|
||||
<div class="hr-line-dashed"></div>
|
||||
<div style="display: inline-block; float: left">
|
||||
<b class="text-muted text-left" >{% trans "More login options" %}</b>
|
||||
<div class="more-methods-title {{ current_lang.code }}">
|
||||
{% trans "More login options" %}
|
||||
</div>
|
||||
<div class="more-login-items">
|
||||
{% for method in auth_methods %}
|
||||
<a href="{{ method.url }}" class="more-login-item">
|
||||
<i class="fa"><img src="{{ method.logo }}" height="13" width="13"></i> {{ method.name }}
|
||||
<i class="fa"><img src="{{ method.logo }}" height="15" width="15"></i> {{ method.name }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
|
|
@ -10,8 +10,7 @@ from django.contrib.auth import login as auth_login, logout as auth_logout
|
|||
from django.http import HttpResponse
|
||||
from django.shortcuts import reverse, redirect
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.db import transaction
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.utils.translation import ugettext as _, get_language
|
||||
from django.views.decorators.cache import never_cache
|
||||
from django.views.decorators.csrf import csrf_protect
|
||||
from django.views.decorators.debug import sensitive_post_parameters
|
||||
|
@ -181,6 +180,29 @@ class UserLoginView(mixins.AuthMixin, FormView):
|
|||
]
|
||||
return [method for method in auth_methods if method['enabled']]
|
||||
|
||||
@staticmethod
|
||||
def get_support_langs():
|
||||
langs = [
|
||||
{
|
||||
'title': '中文(简体)',
|
||||
'code': 'zh-hans'
|
||||
},
|
||||
{
|
||||
'title': 'English',
|
||||
'code': 'en'
|
||||
},
|
||||
{
|
||||
'title': '日本語',
|
||||
'code': 'ja'
|
||||
}
|
||||
]
|
||||
return langs
|
||||
|
||||
def get_current_lang(self):
|
||||
langs = self.get_support_langs()
|
||||
matched_lang = filter(lambda x: x['code'] == get_language(), langs)
|
||||
return next(matched_lang, langs[0])
|
||||
|
||||
@staticmethod
|
||||
def get_forgot_password_url():
|
||||
forgot_password_url = reverse('authentication:forgot-password')
|
||||
|
@ -188,14 +210,16 @@ class UserLoginView(mixins.AuthMixin, FormView):
|
|||
return forgot_password_url
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
context = super().get_context_data(**kwargs)
|
||||
context.update({
|
||||
'demo_mode': os.environ.get("DEMO_MODE"),
|
||||
'auth_methods': self.get_support_auth_methods(),
|
||||
'langs': self.get_support_langs(),
|
||||
'current_lang': self.get_current_lang(),
|
||||
'forgot_password_url': self.get_forgot_password_url(),
|
||||
**self.get_user_mfa_context(self.request.user)
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super().get_context_data(**kwargs)
|
||||
})
|
||||
return context
|
||||
|
||||
|
||||
class UserLoginGuardView(mixins.AuthMixin, RedirectView):
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from channels.auth import AuthMiddlewareStack
|
||||
from channels.routing import ProtocolTypeRouter, URLRouter
|
||||
from django.core.asgi import get_asgi_application
|
||||
|
||||
from ops.urls.ws_urls import urlpatterns as ops_urlpatterns
|
||||
from notifications.urls.ws_urls import urlpatterns as notifications_urlpatterns
|
||||
|
@ -12,4 +13,5 @@ application = ProtocolTypeRouter({
|
|||
'websocket': AuthMiddlewareStack(
|
||||
URLRouter(urlpatterns)
|
||||
),
|
||||
"http": get_asgi_application(),
|
||||
})
|
||||
|
|
|
@ -11,10 +11,19 @@ from django.urls import reverse_lazy
|
|||
from .. import const
|
||||
from ..const import CONFIG
|
||||
|
||||
|
||||
def exist_or_default(path, default):
|
||||
if not os.path.exists(path):
|
||||
path = default
|
||||
return path
|
||||
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
VERSION = const.VERSION
|
||||
BASE_DIR = const.BASE_DIR
|
||||
PROJECT_DIR = const.PROJECT_DIR
|
||||
DATA_DIR = os.path.join(PROJECT_DIR, 'data')
|
||||
CERTS_DIR = os.path.join(DATA_DIR, 'certs')
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/
|
||||
|
@ -148,19 +157,7 @@ SESSION_EXPIRE_AT_BROWSER_CLOSE = True
|
|||
# 自定义的配置,SESSION_EXPIRE_AT_BROWSER_CLOSE 始终为 True, 下面这个来控制是否强制关闭后过期 cookie
|
||||
SESSION_EXPIRE_AT_BROWSER_CLOSE_FORCE = CONFIG.SESSION_EXPIRE_AT_BROWSER_CLOSE_FORCE
|
||||
SESSION_SAVE_EVERY_REQUEST = CONFIG.SESSION_SAVE_EVERY_REQUEST
|
||||
SESSION_ENGINE = 'jumpserver.rewriting.session'
|
||||
SESSION_REDIS = {
|
||||
'url': '%(protocol)s://:%(password)s@%(host)s:%(port)s/%(db)s' % {
|
||||
'protocol': 'rediss' if CONFIG.REDIS_USE_SSL else 'redis',
|
||||
'password': CONFIG.REDIS_PASSWORD,
|
||||
'host': CONFIG.REDIS_HOST,
|
||||
'port': CONFIG.REDIS_PORT,
|
||||
'db': CONFIG.REDIS_DB_CACHE,
|
||||
},
|
||||
'prefix': 'auth_session',
|
||||
'socket_timeout': 1,
|
||||
'retry_on_timeout': False
|
||||
}
|
||||
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
|
||||
|
||||
MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'
|
||||
# Database
|
||||
|
@ -180,7 +177,6 @@ DATABASES = {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
DB_CA_PATH = os.path.join(PROJECT_DIR, 'data', 'certs', 'db_ca.pem')
|
||||
if CONFIG.DB_ENGINE.lower() == 'mysql':
|
||||
DB_OPTIONS['init_command'] = "SET sql_mode='STRICT_TRANS_TABLES'"
|
||||
|
@ -264,45 +260,40 @@ FILE_UPLOAD_PERMISSIONS = 0o644
|
|||
FILE_UPLOAD_DIRECTORY_PERMISSIONS = 0o755
|
||||
|
||||
# Cache use redis
|
||||
REDIS_SSL_KEYFILE = os.path.join(PROJECT_DIR, 'data', 'certs', 'redis_client.key')
|
||||
if not os.path.exists(REDIS_SSL_KEYFILE):
|
||||
REDIS_SSL_KEYFILE = None
|
||||
|
||||
REDIS_SSL_CERTFILE = os.path.join(PROJECT_DIR, 'data', 'certs', 'redis_client.crt')
|
||||
if not os.path.exists(REDIS_SSL_CERTFILE):
|
||||
REDIS_SSL_CERTFILE = None
|
||||
|
||||
REDIS_SSL_CA_CERTS = os.path.join(PROJECT_DIR, 'data', 'certs', 'redis_ca.crt')
|
||||
if not os.path.exists(REDIS_SSL_CA_CERTS):
|
||||
REDIS_SSL_CA_CERTS = os.path.join(PROJECT_DIR, 'data', 'certs', 'redis_ca.pem')
|
||||
|
||||
if not os.path.exists(REDIS_SSL_CA_CERTS):
|
||||
REDIS_SSL_CA_CERTS = None
|
||||
|
||||
REDIS_SSL_KEYFILE = exist_or_default(os.path.join(CERTS_DIR, 'redis_client.key'), None)
|
||||
REDIS_SSL_CERTFILE = exist_or_default(os.path.join(CERTS_DIR, 'redis_client.crt'), None)
|
||||
REDIS_SSL_CA_CERTS = exist_or_default(os.path.join(CERTS_DIR, 'redis_ca.pem'), None)
|
||||
REDIS_SSL_CA_CERTS = exist_or_default(os.path.join(CERTS_DIR, 'redis_ca.crt'), REDIS_SSL_CA_CERTS)
|
||||
REDIS_SSL_REQUIRED = CONFIG.REDIS_SSL_REQUIRED or 'none'
|
||||
REDIS_LOCATION_NO_DB = '%(protocol)s://:%(password)s@%(host)s:%(port)s/{}' % {
|
||||
'protocol': 'rediss' if CONFIG.REDIS_USE_SSL else 'redis',
|
||||
'password': CONFIG.REDIS_PASSWORD,
|
||||
'host': CONFIG.REDIS_HOST,
|
||||
'port': CONFIG.REDIS_PORT,
|
||||
}
|
||||
|
||||
CACHES = {
|
||||
'default': {
|
||||
# 'BACKEND': 'redis_cache.RedisCache',
|
||||
'BACKEND': 'redis_lock.django_cache.RedisCache',
|
||||
'LOCATION': '%(protocol)s://:%(password)s@%(host)s:%(port)s/%(db)s' % {
|
||||
'protocol': 'rediss' if CONFIG.REDIS_USE_SSL else 'redis',
|
||||
'password': CONFIG.REDIS_PASSWORD,
|
||||
'host': CONFIG.REDIS_HOST,
|
||||
'port': CONFIG.REDIS_PORT,
|
||||
'db': CONFIG.REDIS_DB_CACHE,
|
||||
},
|
||||
'OPTIONS': {
|
||||
"REDIS_CLIENT_KWARGS": {"health_check_interval": 30},
|
||||
"CONNECTION_POOL_KWARGS": {
|
||||
'ssl_cert_reqs': REDIS_SSL_REQUIRED,
|
||||
"ssl_keyfile": REDIS_SSL_KEYFILE,
|
||||
"ssl_certfile": REDIS_SSL_CERTFILE,
|
||||
"ssl_ca_certs": REDIS_SSL_CA_CERTS
|
||||
} if CONFIG.REDIS_USE_SSL else {}
|
||||
}
|
||||
REDIS_CACHE_DEFAULT = {
|
||||
'BACKEND': 'redis_lock.django_cache.RedisCache',
|
||||
'LOCATION': REDIS_LOCATION_NO_DB.format(CONFIG.REDIS_DB_CACHE),
|
||||
'OPTIONS': {
|
||||
"REDIS_CLIENT_KWARGS": {"health_check_interval": 30},
|
||||
"CONNECTION_POOL_KWARGS": {
|
||||
'ssl_cert_reqs': REDIS_SSL_REQUIRED,
|
||||
"ssl_keyfile": REDIS_SSL_KEYFILE,
|
||||
"ssl_certfile": REDIS_SSL_CERTFILE,
|
||||
"ssl_ca_certs": REDIS_SSL_CA_CERTS
|
||||
} if CONFIG.REDIS_USE_SSL else {}
|
||||
}
|
||||
}
|
||||
REDIS_CACHE_SESSION = dict(REDIS_CACHE_DEFAULT)
|
||||
REDIS_CACHE_SESSION['LOCATION'] = REDIS_LOCATION_NO_DB.format(CONFIG.REDIS_DB_SESSION)
|
||||
|
||||
CACHES = {
|
||||
'default': REDIS_CACHE_DEFAULT,
|
||||
'session': REDIS_CACHE_SESSION
|
||||
}
|
||||
|
||||
SESSION_CACHE_ALIAS = "session"
|
||||
|
||||
FORCE_SCRIPT_NAME = CONFIG.FORCE_SCRIPT_NAME
|
||||
SESSION_COOKIE_SECURE = CONFIG.SESSION_COOKIE_SECURE
|
||||
|
|
|
@ -6,6 +6,7 @@ import ssl
|
|||
from .base import REDIS_SSL_CA_CERTS, REDIS_SSL_CERTFILE, REDIS_SSL_KEYFILE, REDIS_SSL_REQUIRED
|
||||
from ..const import CONFIG, PROJECT_DIR
|
||||
|
||||
|
||||
REST_FRAMEWORK = {
|
||||
# Use Django's standard `django.contrib.auth` permissions,
|
||||
# or allow read-only access for unauthenticated users.
|
||||
|
@ -14,7 +15,6 @@ REST_FRAMEWORK = {
|
|||
),
|
||||
'DEFAULT_RENDERER_CLASSES': (
|
||||
'rest_framework.renderers.JSONRenderer',
|
||||
# 'rest_framework.renderers.BrowsableAPIRenderer',
|
||||
'common.drf.renders.CSVFileRenderer',
|
||||
'common.drf.renders.ExcelFileRenderer',
|
||||
|
||||
|
@ -47,9 +47,6 @@ REST_FRAMEWORK = {
|
|||
'DATETIME_INPUT_FORMATS': ['%Y/%m/%d %H:%M:%S %z', 'iso-8601', '%Y-%m-%d %H:%M:%S %z'],
|
||||
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
|
||||
'EXCEPTION_HANDLER': 'common.drf.exc_handlers.common_exception_handler',
|
||||
# 'PAGE_SIZE': 100,
|
||||
# 'MAX_PAGE_SIZE': 5000
|
||||
|
||||
}
|
||||
|
||||
SWAGGER_SETTINGS = {
|
||||
|
@ -67,7 +64,7 @@ SWAGGER_SETTINGS = {
|
|||
|
||||
|
||||
# Captcha settings, more see https://django-simple-captcha.readthedocs.io/en/latest/advanced.html
|
||||
CAPTCHA_IMAGE_SIZE = (140, 34)
|
||||
CAPTCHA_IMAGE_SIZE = (180, 38)
|
||||
CAPTCHA_FOREGROUND_COLOR = '#001100'
|
||||
CAPTCHA_NOISE_FUNCTIONS = ('captcha.helpers.noise_dots',)
|
||||
CAPTCHA_CHALLENGE_FUNCT = 'captcha.helpers.math_challenge'
|
||||
|
@ -127,18 +124,13 @@ CELERY_RESULT_SERIALIZER = 'pickle'
|
|||
CELERY_RESULT_BACKEND = CELERY_BROKER_URL
|
||||
CELERY_ACCEPT_CONTENT = ['json', 'pickle']
|
||||
CELERY_RESULT_EXPIRES = 600
|
||||
# CELERY_WORKER_LOG_FORMAT = '%(asctime)s [%(module)s %(levelname)s] %(message)s'
|
||||
# CELERY_WORKER_LOG_FORMAT = '%(message)s'
|
||||
# CELERY_WORKER_TASK_LOG_FORMAT = '%(task_id)s %(task_name)s %(message)s'
|
||||
CELERY_WORKER_TASK_LOG_FORMAT = '%(message)s'
|
||||
# CELERY_WORKER_LOG_FORMAT = '%(asctime)s [%(module)s %(levelname)s] %(message)s'
|
||||
CELERY_WORKER_LOG_FORMAT = '%(message)s'
|
||||
CELERY_TASK_EAGER_PROPAGATES = True
|
||||
CELERY_WORKER_REDIRECT_STDOUTS = True
|
||||
CELERY_WORKER_REDIRECT_STDOUTS_LEVEL = "INFO"
|
||||
# CELERY_WORKER_HIJACK_ROOT_LOGGER = True
|
||||
# CELERY_WORKER_MAX_TASKS_PER_CHILD = 40
|
||||
CELERY_TASK_SOFT_TIME_LIMIT = 3600
|
||||
|
||||
if CONFIG.REDIS_USE_SSL:
|
||||
CELERY_BROKER_USE_SSL = CELERY_REDIS_BACKEND_USE_SSL = {
|
||||
'ssl_cert_reqs': REDIS_SSL_REQUIRED,
|
||||
|
|
|
@ -2298,7 +2298,7 @@ msgstr "登录"
|
|||
|
||||
#: authentication/templates/authentication/login.html:224
|
||||
msgid "More login options"
|
||||
msgstr "更多登录方式"
|
||||
msgstr "其他方式登录"
|
||||
|
||||
#: authentication/templates/authentication/login_mfa.html:6
|
||||
msgid "MFA Auth"
|
||||
|
|
|
@ -5,5 +5,5 @@ from .. import ws
|
|||
app_name = 'notifications'
|
||||
|
||||
urlpatterns = [
|
||||
path('ws/notifications/site-msg/', ws.SiteMsgWebsocket, name='site-msg-ws'),
|
||||
]
|
||||
path('ws/notifications/site-msg/', ws.SiteMsgWebsocket.as_asgi(), name='site-msg-ws'),
|
||||
]
|
||||
|
|
|
@ -5,5 +5,5 @@ from .. import ws
|
|||
app_name = 'ops'
|
||||
|
||||
urlpatterns = [
|
||||
path('ws/ops/tasks/log/', ws.TaskLogWebsocket, name='task-log-ws'),
|
||||
path('ws/ops/tasks/log/', ws.TaskLogWebsocket.as_asgi(), name='task-log-ws'),
|
||||
]
|
||||
|
|
|
@ -3,9 +3,9 @@ ansible==2.10.7
|
|||
asn1crypto==0.24.0
|
||||
bcrypt==3.1.4
|
||||
billiard==3.6.4.0
|
||||
boto3==1.18.11
|
||||
botocore==1.21.11
|
||||
celery==5.2.2
|
||||
boto3==1.24.12
|
||||
botocore==1.27.12
|
||||
celery==5.2.7
|
||||
certifi==2018.1.18
|
||||
cffi==1.13.2
|
||||
chardet==3.0.4
|
||||
|
@ -17,117 +17,118 @@ decorator==4.1.2
|
|||
Django==3.1.14
|
||||
django-auth-ldap==2.2.0
|
||||
django-bootstrap3==14.2.0
|
||||
django-celery-beat==2.2.1
|
||||
django-celery-beat==2.3.0
|
||||
django-filter==2.4.0
|
||||
django-formtools==2.2
|
||||
django-ranged-response==0.2.0
|
||||
django-rest-swagger==2.2.0
|
||||
django-simple-captcha==0.5.13
|
||||
django-timezone-field==4.1.0
|
||||
djangorestframework==3.12.2
|
||||
django-simple-captcha==0.5.17
|
||||
django-timezone-field==5.0
|
||||
djangorestframework==3.13.1
|
||||
djangorestframework-bulk==0.2.1
|
||||
docutils==0.14
|
||||
ecdsa==0.13.3
|
||||
enum-compat==0.0.2
|
||||
ephem==3.7.6.0
|
||||
eventlet==0.31.1
|
||||
eventlet==0.33.1
|
||||
future==0.16.0
|
||||
ForgeryPy3==0.3.1
|
||||
greenlet==0.4.14
|
||||
gunicorn==19.9.0
|
||||
greenlet==1.1.2
|
||||
gunicorn==20.1.0
|
||||
idna==2.6
|
||||
itsdangerous==0.24
|
||||
itypes==1.1.0
|
||||
Jinja2==2.11.3
|
||||
jmespath==0.9.3
|
||||
kombu==5.2.2
|
||||
ldap3==2.4
|
||||
MarkupSafe==1.1.1
|
||||
mysqlclient==2.0.1
|
||||
olefile==0.44
|
||||
itsdangerous==1.1.0
|
||||
itypes==1.2.0
|
||||
Jinja2==3.1.2
|
||||
jmespath==1.0.1
|
||||
kombu==5.2.4
|
||||
ldap3==2.9.1
|
||||
MarkupSafe==2.1.1
|
||||
mysqlclient==2.1.0
|
||||
olefile==0.46
|
||||
openapi-codec==1.3.2
|
||||
paramiko==2.10.1
|
||||
passlib==1.7.1
|
||||
Pillow==9.0.1
|
||||
paramiko==2.11.0
|
||||
passlib==1.7.4
|
||||
Pillow==9.1.1
|
||||
pyasn1==0.4.8
|
||||
pycparser==2.19
|
||||
pycryptodome==3.12.0
|
||||
pycryptodomex==3.12.0
|
||||
pyotp==2.2.6
|
||||
pycparser==2.21
|
||||
pycryptodome==3.14.1
|
||||
pycryptodomex==3.14.1
|
||||
pyotp==2.6.0
|
||||
PyNaCl==1.5.0
|
||||
python-dateutil==2.8.2
|
||||
pytz==2018.3
|
||||
pytz==2022.1
|
||||
PyYAML==6.0
|
||||
redis==4.3.1
|
||||
requests==2.25.1
|
||||
jms-storage==0.0.42
|
||||
s3transfer==0.5.0
|
||||
simplejson==3.13.2
|
||||
six==1.11.0
|
||||
sshpubkeys==3.1.0
|
||||
uritemplate==3.0.0
|
||||
urllib3==1.26.5
|
||||
redis==4.3.3
|
||||
requests==2.28.0
|
||||
jms-storage==0.0.43
|
||||
s3transfer==0.6.0
|
||||
simplejson==3.17.6
|
||||
six==1.16.0
|
||||
sshpubkeys==3.3.1
|
||||
uritemplate==4.1.1
|
||||
urllib3==1.26.9
|
||||
vine==5.0.0
|
||||
drf-yasg==1.20.0
|
||||
Werkzeug==0.15.3
|
||||
drf-nested-routers==0.91
|
||||
aliyun-python-sdk-core-v3==2.9.1
|
||||
aliyun-python-sdk-ecs==4.10.1
|
||||
Werkzeug==2.1.2
|
||||
drf-nested-routers==0.93.4
|
||||
rest_condition==1.0.3
|
||||
python-ldap==3.4.0
|
||||
tencentcloud-sdk-python==3.0.477
|
||||
django-radius==1.4.0
|
||||
django-redis-sessions==0.6.1
|
||||
django-radius==1.5.0
|
||||
unicodecsv==0.14.1
|
||||
python-daemon==2.2.3
|
||||
python-daemon==2.3.0
|
||||
httpsig==1.3.0
|
||||
treelib==1.5.3
|
||||
treelib==1.6.1
|
||||
django-proxy==1.2.1
|
||||
flower==1.0.0
|
||||
channels-redis==3.2.0
|
||||
channels==2.4.0
|
||||
daphne==2.4.1
|
||||
psutil==5.6.6
|
||||
channels-redis==3.4.0
|
||||
channels==3.0.4
|
||||
daphne==3.0.2
|
||||
psutil==5.9.1
|
||||
django-cas-ng==4.0.1
|
||||
python-cas==1.5.0
|
||||
ipython
|
||||
huaweicloud-sdk-python==1.0.21
|
||||
django-redis==4.11.0
|
||||
django-redis==5.2.0
|
||||
python-redis-lock==3.7.0
|
||||
jumpserver-django-oidc-rp==0.3.7.8
|
||||
django-mysql==3.9.0
|
||||
gmssl==3.2.1
|
||||
azure-mgmt-compute==4.6.2
|
||||
azure-mgmt-network==2.7.0
|
||||
msrestazure==0.6.4
|
||||
adal==1.2.5
|
||||
openpyxl==3.0.5
|
||||
pyexcel==0.6.6
|
||||
openpyxl==3.0.10
|
||||
pyexcel==0.7.0
|
||||
pyexcel-xlsx==0.6.0
|
||||
data-tree==0.0.1
|
||||
pyvmomi==7.0.1
|
||||
termcolor==1.1.0
|
||||
azure-identity==1.5.0
|
||||
azure-mgmt-subscription==1.0.0
|
||||
qingcloud-sdk==1.2.12
|
||||
django-simple-history==3.0.0
|
||||
google-cloud-compute==0.5.0
|
||||
PyMySQL==1.0.2
|
||||
cx-Oracle==8.2.1
|
||||
psycopg2-binary==2.9.1
|
||||
alibabacloud_dysmsapi20170525==2.0.2
|
||||
geoip2==4.4.0
|
||||
django-simple-history==3.1.1
|
||||
geoip2==4.5.0
|
||||
html2text==2020.1.16
|
||||
python-novaclient==11.0.1
|
||||
pyzipper==0.3.5
|
||||
python3-saml==1.12.0
|
||||
python-keystoneclient==4.3.0
|
||||
pymssql==2.1.5
|
||||
kubernetes==21.7.0
|
||||
websocket-client==1.2.3
|
||||
numpy==1.22.0
|
||||
pandas==1.3.5
|
||||
pyjwkest==1.4.2
|
||||
jsonfield2==4.0.0.post0
|
||||
bce-python-sdk==0.8.64
|
||||
ipip-ipdb==1.6.1
|
||||
# Cloud req
|
||||
qingcloud-sdk==1.2.12
|
||||
azure-mgmt-subscription==1.0.0
|
||||
azure-identity==1.5.0
|
||||
azure-mgmt-compute==4.6.2
|
||||
azure-mgmt-network==2.7.0
|
||||
google-cloud-compute==0.5.0
|
||||
alibabacloud_dysmsapi20170525==2.0.2
|
||||
python-novaclient==11.0.1
|
||||
python-keystoneclient==4.3.0
|
||||
bce-python-sdk==0.8.64
|
||||
tencentcloud-sdk-python==3.0.477
|
||||
aliyun-python-sdk-core-v3==2.9.1
|
||||
aliyun-python-sdk-ecs==4.10.1
|
||||
huaweicloud-sdk-python==1.0.21
|
||||
# DB requirements
|
||||
PyMySQL==1.0.2
|
||||
cx-Oracle==8.2.1
|
||||
psycopg2-binary==2.9.1
|
||||
pymssql==2.1.5
|
||||
|
|
Loading…
Reference in New Issue