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