mirror of https://github.com/jumpserver/jumpserver
commit
151d897746
|
@ -138,7 +138,8 @@ class SystemUserAppAuthInfoApi(generics.RetrieveAPIView):
|
|||
instance = super().get_object()
|
||||
app_id = self.kwargs.get('app_id')
|
||||
user_id = self.request.query_params.get("user_id")
|
||||
instance.load_app_more_auth(app_id, user_id)
|
||||
username = self.request.query_params.get("username")
|
||||
instance.load_app_more_auth(app_id, username, user_id)
|
||||
return instance
|
||||
|
||||
|
||||
|
|
|
@ -129,12 +129,21 @@ class AuthMixin:
|
|||
if password:
|
||||
self.password = password
|
||||
|
||||
def load_app_more_auth(self, app_id=None, user_id=None):
|
||||
def load_app_more_auth(self, app_id=None, username=None, user_id=None):
|
||||
self._clean_auth_info_if_manual_login_mode()
|
||||
# 加载临时认证信息
|
||||
if self.login_mode == self.LOGIN_MANUAL:
|
||||
self._load_tmp_auth_if_has(app_id, user_id)
|
||||
return
|
||||
# 更新用户名
|
||||
from users.models import User
|
||||
user = get_object_or_none(User, pk=user_id) if user_id else None
|
||||
if self.username_same_with_user:
|
||||
if user and not username:
|
||||
_username = user.username
|
||||
else:
|
||||
_username = username
|
||||
self.username = _username
|
||||
|
||||
def load_asset_special_auth(self, asset, username=''):
|
||||
"""
|
||||
|
|
|
@ -40,10 +40,6 @@ def expire_node_assets_mapping_for_memory(org_id):
|
|||
root_org_id = Organization.ROOT_ID
|
||||
|
||||
# 当前进程清除(cache 数据)
|
||||
logger.debug(
|
||||
"Expire node assets id mapping from cache of org={}, pid={}"
|
||||
"".format(org_id, os.getpid())
|
||||
)
|
||||
Node.expire_node_all_asset_ids_mapping_from_cache(org_id)
|
||||
Node.expire_node_all_asset_ids_mapping_from_cache(root_org_id)
|
||||
|
||||
|
@ -81,10 +77,6 @@ def subscribe_node_assets_mapping_expire(sender, **kwargs):
|
|||
root_org_id = Organization.ROOT_ID
|
||||
Node.expire_node_all_asset_ids_mapping_from_memory(org_id)
|
||||
Node.expire_node_all_asset_ids_mapping_from_memory(root_org_id)
|
||||
logger.debug(
|
||||
"Expire node assets id mapping from memory of org={}, pid={}"
|
||||
"".format(str(org_id), os.getpid())
|
||||
)
|
||||
|
||||
def keep_subscribe_node_assets_relation():
|
||||
node_assets_mapping_for_memory_pub_sub.keep_handle_msg(handle_node_relation_change)
|
||||
|
|
|
@ -13,16 +13,24 @@ __all__ = ['add_nodes_assets_to_system_users']
|
|||
@tmp_to_root_org()
|
||||
def add_nodes_assets_to_system_users(nodes_keys, system_users):
|
||||
from ..models import Node
|
||||
from assets.tasks import push_system_user_to_assets
|
||||
|
||||
nodes = Node.objects.filter(key__in=nodes_keys)
|
||||
assets = Node.get_nodes_all_assets(*nodes)
|
||||
for system_user in system_users:
|
||||
""" 解决资产和节点进行关联时,已经关联过的节点不会触发 authbook post_save 信号,
|
||||
无法更新节点下所有资产的管理用户的问题 """
|
||||
need_push_asset_ids = []
|
||||
for asset in assets:
|
||||
defaults = {'asset': asset, 'systemuser': system_user, 'org_id': asset.org_id}
|
||||
instance, created = AuthBook.objects.update_or_create(
|
||||
defaults=defaults, asset=asset, systemuser=system_user
|
||||
)
|
||||
if created:
|
||||
need_push_asset_ids.append(asset.id)
|
||||
# # 不再自动更新资产管理用户,只允许用户手动指定。
|
||||
# 只要关联都需要更新资产的管理用户
|
||||
# instance.update_asset_admin_user_if_need()
|
||||
|
||||
if need_push_asset_ids:
|
||||
push_system_user_to_assets.delay(system_user.id, need_push_asset_ids)
|
||||
|
|
|
@ -138,7 +138,7 @@ def get_push_unixlike_system_user_tasks(system_user, username=None):
|
|||
return tasks
|
||||
|
||||
|
||||
def get_push_windows_system_user_tasks(system_user, username=None):
|
||||
def get_push_windows_system_user_tasks(system_user: SystemUser, username=None):
|
||||
if username is None:
|
||||
username = system_user.username
|
||||
password = system_user.password
|
||||
|
@ -151,6 +151,11 @@ def get_push_windows_system_user_tasks(system_user, username=None):
|
|||
if not password:
|
||||
logger.error("Error: no password found")
|
||||
return tasks
|
||||
|
||||
if system_user.ad_domain:
|
||||
logger.error('System user with AD domain do not support push.')
|
||||
return tasks
|
||||
|
||||
task = {
|
||||
'name': 'Add user {}'.format(username),
|
||||
'action': {
|
||||
|
|
|
@ -294,7 +294,7 @@ class SecretDetailMixin:
|
|||
data.update(asset_detail)
|
||||
else:
|
||||
app_detail = self._get_application_secret_detail(app)
|
||||
system_user.load_app_more_auth(app.id, user.id)
|
||||
system_user.load_app_more_auth(app.id, user.username, user.id)
|
||||
data['type'] = 'application'
|
||||
data.update(app_detail)
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import copy
|
||||
|
||||
from urllib import parse
|
||||
|
||||
from django.views import View
|
||||
from django.contrib import auth as auth
|
||||
from django.urls import reverse
|
||||
|
@ -23,9 +25,13 @@ logger = get_logger(__file__)
|
|||
|
||||
class PrepareRequestMixin:
|
||||
@staticmethod
|
||||
def prepare_django_request(request):
|
||||
def is_secure():
|
||||
url_result = parse.urlparse(settings.SITE_URL)
|
||||
return 'on' if url_result.scheme == 'https' else 'off'
|
||||
|
||||
def prepare_django_request(self, request):
|
||||
result = {
|
||||
'https': 'on' if request.is_secure() else 'off',
|
||||
'https': self.is_secure(),
|
||||
'http_host': request.META['HTTP_HOST'],
|
||||
'script_name': request.META['PATH_INFO'],
|
||||
'get_data': request.GET.copy(),
|
||||
|
|
|
@ -173,7 +173,6 @@ class Cache(metaclass=CacheType):
|
|||
def expire(self, *fields):
|
||||
self._data = None
|
||||
if not fields:
|
||||
logger.debug(f'Delete cached key: key={self.key}')
|
||||
self.redis.delete(self.key)
|
||||
else:
|
||||
self.redis.hdel(self.key, *fields)
|
||||
|
|
|
@ -170,7 +170,7 @@ class BaseService(object):
|
|||
|
||||
def _restart(self):
|
||||
if self.retry > self.max_retry:
|
||||
logging.info("Service start failed, exit: ", self.name)
|
||||
logging.info("Service start failed, exit: {}".format(self.name))
|
||||
self.EXIT_EVENT.set()
|
||||
return
|
||||
self.retry += 1
|
||||
|
|
|
@ -7,7 +7,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: JumpServer 0.3.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-12-09 20:32+0800\n"
|
||||
"POT-Creation-Date: 2021-12-14 17:54+0800\n"
|
||||
"PO-Revision-Date: 2021-05-20 10:54+0800\n"
|
||||
"Last-Translator: ibuler <ibuler@qq.com>\n"
|
||||
"Language-Team: JumpServer team<ibuler@qq.com>\n"
|
||||
|
@ -343,7 +343,7 @@ msgstr "类别名称"
|
|||
#: perms/serializers/application/permission.py:17
|
||||
#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:33
|
||||
#: tickets/serializers/ticket/ticket.py:22
|
||||
#: tickets/serializers/ticket/ticket.py:168
|
||||
#: tickets/serializers/ticket/ticket.py:169
|
||||
msgid "Type display"
|
||||
msgstr "类型名称"
|
||||
|
||||
|
@ -384,10 +384,10 @@ msgstr "应用路径"
|
|||
|
||||
#: applications/serializers/attrs/application_category/remote_app.py:45
|
||||
#: assets/serializers/system_user.py:159
|
||||
#: xpack/plugins/change_auth_plan/serializers/asset.py:65
|
||||
#: xpack/plugins/change_auth_plan/serializers/asset.py:68
|
||||
#: xpack/plugins/change_auth_plan/serializers/asset.py:71
|
||||
#: xpack/plugins/change_auth_plan/serializers/asset.py:87
|
||||
#: xpack/plugins/change_auth_plan/serializers/asset.py:64
|
||||
#: xpack/plugins/change_auth_plan/serializers/asset.py:67
|
||||
#: xpack/plugins/change_auth_plan/serializers/asset.py:70
|
||||
#: xpack/plugins/change_auth_plan/serializers/asset.py:101
|
||||
#: xpack/plugins/cloud/serializers/account_attrs.py:52
|
||||
msgid "This field is required."
|
||||
msgstr "该字段是必填项。"
|
||||
|
@ -586,6 +586,7 @@ msgid "Ok"
|
|||
msgstr "成功"
|
||||
|
||||
#: assets/models/base.py:32 audits/models.py:102
|
||||
#: xpack/plugins/change_auth_plan/task_handlers/base/manager.py:121
|
||||
#: xpack/plugins/cloud/const.py:29
|
||||
msgid "Failed"
|
||||
msgstr "失败"
|
||||
|
@ -1169,6 +1170,7 @@ msgid "Filename"
|
|||
msgstr "文件名"
|
||||
|
||||
#: audits/models.py:42 audits/models.py:101 terminal/models/sharing.py:84
|
||||
#: xpack/plugins/change_auth_plan/task_handlers/base/manager.py:119
|
||||
msgid "Success"
|
||||
msgstr "成功"
|
||||
|
||||
|
@ -1326,12 +1328,12 @@ msgstr ""
|
|||
msgid "Auth Token"
|
||||
msgstr "认证令牌"
|
||||
|
||||
#: audits/signals_handler.py:68 authentication/views/login.py:183
|
||||
#: audits/signals_handler.py:68 authentication/views/login.py:164
|
||||
#: notifications/backends/__init__.py:11 users/models/user.py:607
|
||||
msgid "WeCom"
|
||||
msgstr "企业微信"
|
||||
|
||||
#: audits/signals_handler.py:69 authentication/views/login.py:189
|
||||
#: audits/signals_handler.py:69 authentication/views/login.py:170
|
||||
#: notifications/backends/__init__.py:12 users/models/user.py:608
|
||||
msgid "DingTalk"
|
||||
msgstr "钉钉"
|
||||
|
@ -1899,7 +1901,7 @@ msgstr "代码错误"
|
|||
#: authentication/templates/authentication/_msg_reset_password.html:3
|
||||
#: authentication/templates/authentication/_msg_rest_password_success.html:2
|
||||
#: authentication/templates/authentication/_msg_rest_public_key_success.html:2
|
||||
#: jumpserver/conf.py:282
|
||||
#: jumpserver/conf.py:293
|
||||
#: perms/templates/perms/_msg_item_permissions_expire.html:3
|
||||
#: perms/templates/perms/_msg_permed_items_expire.html:3
|
||||
#: users/templates/users/_msg_account_expire_reminder.html:4
|
||||
|
@ -2107,24 +2109,24 @@ msgstr "没有绑定飞书"
|
|||
msgid "Please login with a password and then bind the FeiShu"
|
||||
msgstr "请使用密码登录,然后绑定飞书"
|
||||
|
||||
#: authentication/views/login.py:89
|
||||
#: authentication/views/login.py:70
|
||||
msgid "Redirecting"
|
||||
msgstr "跳转中"
|
||||
|
||||
#: authentication/views/login.py:90
|
||||
#: authentication/views/login.py:71
|
||||
msgid "Redirecting to {} authentication"
|
||||
msgstr "正在跳转到 {} 认证"
|
||||
|
||||
#: authentication/views/login.py:116
|
||||
#: authentication/views/login.py:94
|
||||
msgid "Please enable cookies and try again."
|
||||
msgstr "设置你的浏览器支持cookie"
|
||||
|
||||
#: authentication/views/login.py:195 notifications/backends/__init__.py:14
|
||||
#: authentication/views/login.py:176 notifications/backends/__init__.py:14
|
||||
#: users/models/user.py:609
|
||||
msgid "FeiShu"
|
||||
msgstr "飞书"
|
||||
|
||||
#: authentication/views/login.py:284
|
||||
#: authentication/views/login.py:265
|
||||
msgid ""
|
||||
"Wait for <b>{}</b> confirm, You also can copy link to her/him <br/>\n"
|
||||
" Don't close this page"
|
||||
|
@ -2132,15 +2134,15 @@ msgstr ""
|
|||
"等待 <b>{}</b> 确认, 你也可以复制链接发给他/她 <br/>\n"
|
||||
" 不要关闭本页面"
|
||||
|
||||
#: authentication/views/login.py:289
|
||||
#: authentication/views/login.py:270
|
||||
msgid "No ticket found"
|
||||
msgstr "没有发现工单"
|
||||
|
||||
#: authentication/views/login.py:323
|
||||
#: authentication/views/login.py:304
|
||||
msgid "Logout success"
|
||||
msgstr "退出登录成功"
|
||||
|
||||
#: authentication/views/login.py:324
|
||||
#: authentication/views/login.py:305
|
||||
msgid "Logout success, return login page"
|
||||
msgstr "退出登录成功,返回到登录页面"
|
||||
|
||||
|
@ -2339,11 +2341,11 @@ msgstr "不能包含特殊字符"
|
|||
msgid "The mobile phone number format is incorrect"
|
||||
msgstr "手机号格式不正确"
|
||||
|
||||
#: jumpserver/conf.py:281
|
||||
#: jumpserver/conf.py:292
|
||||
msgid "Create account successfully"
|
||||
msgstr "创建账户成功"
|
||||
|
||||
#: jumpserver/conf.py:283
|
||||
#: jumpserver/conf.py:294
|
||||
msgid "Your account has been created successfully"
|
||||
msgstr "你的账户已创建成功"
|
||||
|
||||
|
@ -2859,7 +2861,7 @@ msgstr "服务端地址"
|
|||
msgid "Proxy server url"
|
||||
msgstr "回调地址"
|
||||
|
||||
#: settings/serializers/auth/cas.py:14 settings/serializers/auth/saml2.py:29
|
||||
#: settings/serializers/auth/cas.py:14 settings/serializers/auth/saml2.py:32
|
||||
msgid "Logout completely"
|
||||
msgstr "同步注销"
|
||||
|
||||
|
@ -2871,7 +2873,7 @@ msgstr "用户名属性"
|
|||
msgid "Enable attributes map"
|
||||
msgstr "启用属性映射"
|
||||
|
||||
#: settings/serializers/auth/cas.py:18 settings/serializers/auth/saml2.py:28
|
||||
#: settings/serializers/auth/cas.py:18 settings/serializers/auth/saml2.py:31
|
||||
msgid "Rename attr"
|
||||
msgstr "映射属性"
|
||||
|
||||
|
@ -3031,7 +3033,7 @@ msgstr "使用状态"
|
|||
msgid "Use nonce"
|
||||
msgstr "临时使用"
|
||||
|
||||
#: settings/serializers/auth/oidc.py:76 settings/serializers/auth/saml2.py:30
|
||||
#: settings/serializers/auth/oidc.py:76 settings/serializers/auth/saml2.py:33
|
||||
msgid "Always update user"
|
||||
msgstr "总是更新用户信息"
|
||||
|
||||
|
@ -3048,20 +3050,24 @@ msgid "Enable SAML2 Auth"
|
|||
msgstr "启用 SAML2 认证"
|
||||
|
||||
#: settings/serializers/auth/saml2.py:15
|
||||
msgid "IDP Metadata URL"
|
||||
msgid "IDP metadata URL"
|
||||
msgstr ""
|
||||
|
||||
#: settings/serializers/auth/saml2.py:18
|
||||
msgid "IDP Metadata XML"
|
||||
msgid "IDP metadata XML"
|
||||
msgstr ""
|
||||
|
||||
#: settings/serializers/auth/saml2.py:22
|
||||
msgid "SP Private Key"
|
||||
msgstr ""
|
||||
#: settings/serializers/auth/saml2.py:21
|
||||
msgid "SP advanced settings"
|
||||
msgstr "高级设置"
|
||||
|
||||
#: settings/serializers/auth/saml2.py:26
|
||||
msgid "SP Public Cert"
|
||||
msgstr ""
|
||||
#: settings/serializers/auth/saml2.py:25
|
||||
msgid "SP private key"
|
||||
msgstr "SP 密钥"
|
||||
|
||||
#: settings/serializers/auth/saml2.py:29
|
||||
msgid "SP cert"
|
||||
msgstr "SP 证书"
|
||||
|
||||
#: settings/serializers/auth/sms.py:10
|
||||
msgid "Enable SMS"
|
||||
|
@ -4784,11 +4790,11 @@ msgstr "内容"
|
|||
msgid "Approve level"
|
||||
msgstr "审批级别"
|
||||
|
||||
#: tickets/models/flow.py:25 tickets/serializers/ticket/ticket.py:140
|
||||
#: tickets/models/flow.py:25 tickets/serializers/ticket/ticket.py:141
|
||||
msgid "Approve strategy"
|
||||
msgstr "审批策略"
|
||||
|
||||
#: tickets/models/flow.py:30 tickets/serializers/ticket/ticket.py:141
|
||||
#: tickets/models/flow.py:30 tickets/serializers/ticket/ticket.py:142
|
||||
msgid "Assignees"
|
||||
msgstr "受理人"
|
||||
|
||||
|
@ -4876,7 +4882,7 @@ msgstr "申请的系统用户名称"
|
|||
|
||||
#: tickets/serializers/ticket/meta/ticket_type/apply_application.py:71
|
||||
#: tickets/serializers/ticket/meta/ticket_type/apply_asset.py:73
|
||||
#: tickets/serializers/ticket/ticket.py:127
|
||||
#: tickets/serializers/ticket/ticket.py:128
|
||||
msgid "Permission named `{}` already exists"
|
||||
msgstr "授权名称 `{}` 已存在"
|
||||
|
||||
|
@ -4936,7 +4942,7 @@ msgid "From cmd filter"
|
|||
msgstr "来自命令过滤规则"
|
||||
|
||||
#: tickets/serializers/ticket/meta/ticket_type/common.py:11
|
||||
#: tickets/serializers/ticket/ticket.py:122
|
||||
#: tickets/serializers/ticket/ticket.py:123
|
||||
msgid "Created by ticket ({}-{})"
|
||||
msgstr "通过工单创建 ({}-{})"
|
||||
|
||||
|
@ -4962,15 +4968,15 @@ msgid ""
|
|||
"request url (`{}`)"
|
||||
msgstr "提交数据中的类型 (`{}`) 与请求URL地址中的类型 (`{}`) 不一致"
|
||||
|
||||
#: tickets/serializers/ticket/ticket.py:115
|
||||
#: tickets/serializers/ticket/ticket.py:116
|
||||
msgid "The ticket flow `{}` does not exist"
|
||||
msgstr "工单流程 `{}` 不存在"
|
||||
|
||||
#: tickets/serializers/ticket/ticket.py:162
|
||||
#: tickets/serializers/ticket/ticket.py:163
|
||||
msgid "Please select the Assignees"
|
||||
msgstr "请选择受理人"
|
||||
|
||||
#: tickets/serializers/ticket/ticket.py:188
|
||||
#: tickets/serializers/ticket/ticket.py:189
|
||||
msgid "The current organization type already exists"
|
||||
msgstr "当前组织已存在该类型"
|
||||
|
||||
|
@ -5633,7 +5639,7 @@ msgid "Replace (The key generated by JumpServer) "
|
|||
msgstr "替换 (由 JumpServer 生成的密钥)"
|
||||
|
||||
#: xpack/plugins/change_auth_plan/models/asset.py:50
|
||||
#: xpack/plugins/change_auth_plan/serializers/asset.py:34
|
||||
#: xpack/plugins/change_auth_plan/serializers/asset.py:33
|
||||
msgid "SSH Key strategy"
|
||||
msgstr "SSH 密钥策略"
|
||||
|
||||
|
@ -5722,11 +5728,11 @@ msgstr ""
|
|||
"{} - 改密任务已完成: 未设置加密密码 - 请前往个人信息 -> 文件加密密码中设置加"
|
||||
"密密码"
|
||||
|
||||
#: xpack/plugins/change_auth_plan/serializers/asset.py:31
|
||||
#: xpack/plugins/change_auth_plan/serializers/asset.py:30
|
||||
msgid "Change Password"
|
||||
msgstr "更改密码"
|
||||
|
||||
#: xpack/plugins/change_auth_plan/serializers/asset.py:32
|
||||
#: xpack/plugins/change_auth_plan/serializers/asset.py:31
|
||||
msgid "Change SSH Key"
|
||||
msgstr "修改 SSH Key"
|
||||
|
||||
|
@ -5811,8 +5817,8 @@ msgid "Qingyun Private Cloud"
|
|||
msgstr "青云私有云"
|
||||
|
||||
#: xpack/plugins/cloud/const.py:19
|
||||
msgid "OpenStack Cloud"
|
||||
msgstr "OpenStack Cloud"
|
||||
msgid "OpenStack"
|
||||
msgstr "OpenStack"
|
||||
|
||||
#: xpack/plugins/cloud/const.py:20
|
||||
msgid "Google Cloud Platform"
|
||||
|
|
|
@ -6,6 +6,7 @@ from rest_framework import generics
|
|||
from rest_framework.views import Response, APIView
|
||||
from orgs.models import Organization
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.conf import settings
|
||||
|
||||
from ..utils import (
|
||||
LDAPServerUtil, LDAPCacheUtil, LDAPImportUtil, LDAPSyncUtil,
|
||||
|
@ -47,6 +48,10 @@ class LDAPTestingConfigAPI(APIView):
|
|||
search_filter = serializer.validated_data["AUTH_LDAP_SEARCH_FILTER"]
|
||||
attr_map = serializer.validated_data["AUTH_LDAP_USER_ATTR_MAP"]
|
||||
auth_ldap = serializer.validated_data.get('AUTH_LDAP', False)
|
||||
|
||||
if not password:
|
||||
password = settings.AUTH_LDAP_BIND_PASSWORD
|
||||
|
||||
config = {
|
||||
'server_uri': server_uri,
|
||||
'bind_dn': bind_dn,
|
||||
|
|
|
@ -12,21 +12,21 @@ class SAML2SettingSerializer(serializers.Serializer):
|
|||
default=False, required=False, label=_('Enable SAML2 Auth')
|
||||
)
|
||||
SAML2_IDP_METADATA_URL = serializers.URLField(
|
||||
allow_blank=True, required=False, label=_('IDP Metadata URL')
|
||||
allow_blank=True, required=False, label=_('IDP metadata URL')
|
||||
)
|
||||
SAML2_IDP_METADATA_XML = serializers.CharField(
|
||||
allow_blank=True, required=False, label=_('IDP Metadata XML')
|
||||
allow_blank=True, required=False, label=_('IDP metadata XML')
|
||||
)
|
||||
SAML2_SP_ADVANCED_SETTINGS = serializers.JSONField(
|
||||
required=False, label=_('SP ADVANCED SETTINGS')
|
||||
required=False, label=_('SP advanced settings')
|
||||
)
|
||||
SAML2_SP_KEY_CONTENT = serializers.CharField(
|
||||
allow_blank=True, required=False,
|
||||
write_only=True, label=_('SP Private Key')
|
||||
write_only=True, label=_('SP private key')
|
||||
)
|
||||
SAML2_SP_CERT_CONTENT = serializers.CharField(
|
||||
allow_blank=True, required=False,
|
||||
write_only=True, label=_('SP Public Cert')
|
||||
write_only=True, label=_('SP cert')
|
||||
)
|
||||
SAML2_RENAME_ATTRIBUTES = serializers.DictField(required=False, label=_('Rename attr'))
|
||||
SAML2_LOGOUT_COMPLETELY = serializers.BooleanField(required=False, label=_('Logout completely'))
|
||||
|
|
|
@ -39,7 +39,8 @@ class UserOtpEnableStartView(AuthMixin, TemplateView):
|
|||
try:
|
||||
self.get_user_from_session()
|
||||
except SessionEmptyError:
|
||||
return redirect('authentication:login') + '?_=otp_enable_start'
|
||||
url = reverse('authentication:login') + '?_=otp_enable_start'
|
||||
return redirect(url)
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
|
||||
|
@ -72,8 +73,8 @@ class UserOtpEnableBindView(AuthMixin, TemplateView, FormView):
|
|||
def _pre_check_can_bind(self):
|
||||
try:
|
||||
user = self.get_user_from_session()
|
||||
except:
|
||||
verify_url = reverse('authentication:user-otp-enable-start')
|
||||
except Exception as e:
|
||||
verify_url = reverse('authentication:user-otp-enable-start') + f'?e={e}'
|
||||
return HttpResponseRedirect(verify_url)
|
||||
|
||||
if user.otp_secret_key:
|
||||
|
|
117
jms
117
jms
|
@ -2,20 +2,27 @@
|
|||
# coding: utf-8
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import logging
|
||||
import logging.handlers
|
||||
import time
|
||||
import argparse
|
||||
import sys
|
||||
import django
|
||||
from django.core import management
|
||||
from django.db.utils import OperationalError
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.insert(0, BASE_DIR)
|
||||
APP_DIR = os.path.join(BASE_DIR, 'apps')
|
||||
|
||||
os.chdir(APP_DIR)
|
||||
sys.path.insert(0, APP_DIR)
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "jumpserver.settings")
|
||||
django.setup()
|
||||
|
||||
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
|
||||
try:
|
||||
from apps.jumpserver import const
|
||||
from jumpserver import const
|
||||
__version__ = const.VERSION
|
||||
except ImportError as e:
|
||||
print("Not found __version__: {}".format(e))
|
||||
|
@ -25,7 +32,7 @@ except ImportError as e:
|
|||
sys.exit(1)
|
||||
|
||||
try:
|
||||
from apps.jumpserver.const import CONFIG
|
||||
from jumpserver.const import CONFIG
|
||||
except ImportError as e:
|
||||
print("Import error: {}".format(e))
|
||||
print("Could not find config file, `cp config_example.yml config.yml`")
|
||||
|
@ -48,56 +55,45 @@ except:
|
|||
|
||||
|
||||
def check_database_connection():
|
||||
os.chdir(os.path.join(BASE_DIR, 'apps'))
|
||||
for i in range(60):
|
||||
logging.info("Check database connection ...")
|
||||
_code = subprocess.call("python manage.py showmigrations users ", shell=True)
|
||||
if _code == 0:
|
||||
logging.info(f"Check database connection: {i}")
|
||||
try:
|
||||
management.call_command('check', '--database', 'default')
|
||||
logging.info("Database connect success")
|
||||
return
|
||||
except OperationalError:
|
||||
logging.info('Database not setup, retry')
|
||||
except Exception as e:
|
||||
logging.error('Unexpect error occur: {}'.format(str(e)))
|
||||
time.sleep(1)
|
||||
logging.error("Connection database failed, exit")
|
||||
sys.exit(10)
|
||||
|
||||
|
||||
def check_migrations():
|
||||
_apps_dir = os.path.join(BASE_DIR, 'apps')
|
||||
_cmd = "python manage.py showmigrations | grep '\[.\]' | grep -v '\[X\]'"
|
||||
_code = subprocess.call(_cmd, shell=True, cwd=_apps_dir)
|
||||
|
||||
if _code == 1:
|
||||
return
|
||||
# for i in range(3):
|
||||
# print("!!! Warning: Has SQL migrations not perform, 有 SQL 变更没有执行")
|
||||
# print("You should run `./PROC upgrade_db` first, 请先运行 ./PROC upgrade_db, 进行表结构变更")
|
||||
# sys.exit(1)
|
||||
|
||||
|
||||
def expire_caches():
|
||||
_apps_dir = os.path.join(BASE_DIR, 'apps')
|
||||
_code = subprocess.call("python manage.py expire_caches", shell=True, cwd=_apps_dir)
|
||||
|
||||
if _code == 1:
|
||||
return
|
||||
try:
|
||||
management.call_command('expire_caches')
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def perform_db_migrate():
|
||||
logging.info("Check database structure change ...")
|
||||
os.chdir(os.path.join(BASE_DIR, 'apps'))
|
||||
logging.info("Migrate model change to database ...")
|
||||
_code = subprocess.call('python3 manage.py migrate', shell=True)
|
||||
if _code == 0:
|
||||
return
|
||||
logging.error('Perform migrate failed, exit')
|
||||
sys.exit(11)
|
||||
try:
|
||||
management.call_command('migrate')
|
||||
except Exception:
|
||||
logging.error('Perform migrate failed, exit')
|
||||
sys.exit(11)
|
||||
|
||||
|
||||
def collect_static():
|
||||
logging.info("Collect static files")
|
||||
os.chdir(os.path.join(BASE_DIR, 'apps'))
|
||||
_cmd = 'python3 manage.py collectstatic --no-input -c &> /dev/null '
|
||||
subprocess.call(_cmd, shell=True)
|
||||
logging.info("Collect static files done")
|
||||
try:
|
||||
management.call_command('collectstatic', '--no-input', '-c', verbosity=0, interactive=False)
|
||||
logging.info("Collect static files done")
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
def compile_i81n_file():
|
||||
|
@ -105,8 +101,7 @@ def compile_i81n_file():
|
|||
if os.path.exists(django_mo_file):
|
||||
return
|
||||
os.chdir(os.path.join(BASE_DIR, 'apps'))
|
||||
_cmd = 'python3 manage.py compilemessages --no-input -c &> /dev/null '
|
||||
subprocess.call(_cmd, shell=True)
|
||||
management.call_command('compilemessages', verbosity=0, interactive=False)
|
||||
logging.info("Compile i18n files done")
|
||||
|
||||
|
||||
|
@ -116,13 +111,34 @@ def upgrade_db():
|
|||
|
||||
|
||||
def prepare():
|
||||
# installer(check) & k8s(no check)
|
||||
check_database_connection()
|
||||
check_migrations()
|
||||
upgrade_db()
|
||||
expire_caches()
|
||||
|
||||
|
||||
def start_services():
|
||||
services = args.services if isinstance(args.services, list) else [args.services]
|
||||
if action == 'start' and {'all', 'web'} & set(services):
|
||||
prepare()
|
||||
|
||||
start_args = []
|
||||
if args.daemon:
|
||||
start_args.append('--daemon')
|
||||
if args.worker:
|
||||
start_args.extend(['--worker', str(args.worker)])
|
||||
if args.force:
|
||||
start_args.append('--force')
|
||||
|
||||
try:
|
||||
management.call_command(action, *services, *start_args)
|
||||
except KeyboardInterrupt:
|
||||
logging.info('Cancel ...')
|
||||
time.sleep(2)
|
||||
except Exception as e:
|
||||
logging.error("Start service error {}: {}".format(services, e))
|
||||
time.sleep(2)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(
|
||||
description="""
|
||||
|
@ -155,23 +171,4 @@ if __name__ == '__main__':
|
|||
elif action == "collect_static":
|
||||
collect_static()
|
||||
else:
|
||||
services = args.services if isinstance(args.services, list) else [args.services]
|
||||
if action == 'start' and {'all', 'web'} & set(services):
|
||||
prepare()
|
||||
|
||||
services_string = ' '.join(services)
|
||||
cmd = f'python manage.py {args.action} {services_string}'
|
||||
if args.daemon:
|
||||
cmd += ' --daemon'
|
||||
if args.worker:
|
||||
cmd += f' --worker {args.worker}'
|
||||
if args.force:
|
||||
cmd += ' --force'
|
||||
apps_dir = os.path.join(BASE_DIR, 'apps')
|
||||
|
||||
try:
|
||||
# processes: main(3s) -> call(0.25s) -> service -> sub-process
|
||||
code = subprocess.call(cmd, shell=True, cwd=apps_dir)
|
||||
except KeyboardInterrupt:
|
||||
time.sleep(2)
|
||||
pass
|
||||
start_services()
|
||||
|
|
Loading…
Reference in New Issue