perf: 优化登录,cas, openid 自动登录

pull/6101/head
ibuler 2021-04-29 17:15:46 +08:00 committed by 老广
parent 7294f6e5e0
commit 4d6d4cbc22
14 changed files with 217 additions and 153 deletions

View File

@ -7,13 +7,14 @@ import time
from django.conf import settings from django.conf import settings
from django.contrib import auth from django.contrib import auth
from django.utils.translation import ugettext as _
from django.contrib.auth import ( from django.contrib.auth import (
BACKEND_SESSION_KEY, _get_backends, BACKEND_SESSION_KEY, _get_backends,
PermissionDenied, user_login_failed, _clean_credentials PermissionDenied, user_login_failed, _clean_credentials
) )
from django.shortcuts import reverse from django.shortcuts import reverse
from common.utils import get_object_or_none, get_request_ip, get_logger, bulk_get from common.utils import get_object_or_none, get_request_ip, get_logger, bulk_get, FlashMessageUtil
from users.models import User from users.models import User
from users.utils import LoginBlockUtil, MFABlockUtils from users.utils import LoginBlockUtil, MFABlockUtils
from . import errors from . import errors
@ -204,41 +205,40 @@ class AuthMixin:
return user return user
@classmethod @classmethod
def generate_reset_password_url_with_flash_msg(cls, user: User, flash_view_name): def generate_reset_password_url_with_flash_msg(cls, user, message):
reset_passwd_url = reverse('authentication:reset-password') reset_passwd_url = reverse('authentication:reset-password')
query_str = urlencode({ query_str = urlencode({
'token': user.generate_reset_token() 'token': user.generate_reset_token()
}) })
reset_passwd_url = f'{reset_passwd_url}?{query_str}' reset_passwd_url = f'{reset_passwd_url}?{query_str}'
flash_page_url = reverse(flash_view_name) message_data = {
query_str = urlencode({ 'title': _('Please change your password'),
'redirect_url': reset_passwd_url 'message': message,
}) 'interval': 3,
return f'{flash_page_url}?{query_str}' 'redirect_url': reset_passwd_url,
}
return FlashMessageUtil.gen_message_url(message_data)
@classmethod @classmethod
def _check_passwd_is_too_simple(cls, user: User, password): def _check_passwd_is_too_simple(cls, user: User, password):
if user.is_superuser and password == 'admin': if user.is_superuser and password == 'admin':
url = cls.generate_reset_password_url_with_flash_msg( message = _('Your password is too simple, please change it for security')
user, 'authentication:passwd-too-simple-flash-msg' url = cls.generate_reset_password_url_with_flash_msg(user, message=message)
)
raise errors.PasswdTooSimple(url) raise errors.PasswdTooSimple(url)
@classmethod @classmethod
def _check_passwd_need_update(cls, user: User): def _check_passwd_need_update(cls, user: User):
if user.need_update_password: if user.need_update_password:
url = cls.generate_reset_password_url_with_flash_msg( message = _('You should to change your password before login')
user, 'authentication:passwd-need-update-flash-msg' url = cls.generate_reset_password_url_with_flash_msg(user, message)
)
raise errors.PasswdNeedUpdate(url) raise errors.PasswdNeedUpdate(url)
@classmethod @classmethod
def _check_password_require_reset_or_not(cls, user: User): def _check_password_require_reset_or_not(cls, user: User):
if user.password_has_expired: if user.password_has_expired:
url = cls.generate_reset_password_url_with_flash_msg( message = _('Your password has expired, please reset before logging in')
user, 'authentication:passwd-has-expired-flash-msg' url = cls.generate_reset_password_url_with_flash_msg(user, message)
)
raise errors.PasswordRequireResetError(url) raise errors.PasswordRequireResetError(url)
def check_user_auth_if_need(self, decrypt_passwd=False): def check_user_auth_if_need(self, decrypt_passwd=False):

View File

@ -18,13 +18,7 @@ urlpatterns = [
# 原来在users中的 # 原来在users中的
path('password/forgot/', users_view.UserForgotPasswordView.as_view(), name='forgot-password'), path('password/forgot/', users_view.UserForgotPasswordView.as_view(), name='forgot-password'),
path('password/forgot/sendmail-success/', users_view.UserForgotPasswordSendmailSuccessView.as_view(),
name='forgot-password-sendmail-success'),
path('password/reset/', users_view.UserResetPasswordView.as_view(), name='reset-password'), path('password/reset/', users_view.UserResetPasswordView.as_view(), name='reset-password'),
path('password/too-simple-flash-msg/', views.FlashPasswdTooSimpleMsgView.as_view(), name='passwd-too-simple-flash-msg'),
path('password/need-update-flash-msg/', views.FlashPasswdNeedUpdateMsgView.as_view(), name='passwd-need-update-flash-msg'),
path('password/has-expired-msg/', views.FlashPasswdHasExpiredMsgView.as_view(), name='passwd-has-expired-flash-msg'),
path('password/reset/success/', users_view.UserResetPasswordSuccessView.as_view(), name='reset-password-success'),
path('password/verify/', users_view.UserVerifyPasswordView.as_view(), name='user-verify-password'), path('password/verify/', users_view.UserVerifyPasswordView.as_view(), name='user-verify-password'),
# Profile # Profile

View File

@ -19,7 +19,7 @@ from django.conf import settings
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.contrib.auth import BACKEND_SESSION_KEY from django.contrib.auth import BACKEND_SESSION_KEY
from common.utils import get_request_ip, get_object_or_none from common.utils import get_request_ip, FlashMessageUtil
from users.utils import ( from users.utils import (
redirect_user_first_login_or_index redirect_user_first_login_or_index
) )
@ -31,8 +31,6 @@ from ..forms import get_user_login_form_cls
__all__ = [ __all__ = [
'UserLoginView', 'UserLogoutView', 'UserLoginView', 'UserLogoutView',
'UserLoginGuardView', 'UserLoginWaitConfirmView', 'UserLoginGuardView', 'UserLoginWaitConfirmView',
'FlashPasswdTooSimpleMsgView', 'FlashPasswdHasExpiredMsgView',
'FlashPasswdNeedUpdateMsgView'
] ]
@ -44,12 +42,42 @@ class UserLoginView(mixins.AuthMixin, FormView):
redirect_field_name = 'next' redirect_field_name = 'next'
template_name = 'authentication/login.html' template_name = 'authentication/login.html'
def redirect_third_party_auth_if_need(self, request):
# show jumpserver login page if request http://{JUMP-SERVER}/?admin=1
if self.request.GET.get("admin", 0):
return None
auth_type = ''
auth_url = ''
if settings.AUTH_OPENID:
auth_type = 'OIDC'
auth_url = reverse(settings.AUTH_OPENID_AUTH_LOGIN_URL_NAME)
elif settings.AUTH_CAS:
auth_type = 'CAS'
auth_url = reverse(settings.CAS_LOGIN_URL_NAME)
if not auth_url:
return None
message_data = {
'title': _('Redirecting'),
'message': _("Redirecting to {} authentication").format(auth_type),
'redirect_url': auth_url,
'has_cancel': True,
'cancel_url': reverse('authentication:login') + '?admin=1'
}
redirect_url = FlashMessageUtil.gen_message_url(message_data)
query_string = request.GET.urlencode()
redirect_url = "{}&{}".format(redirect_url, query_string)
return redirect_url
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
if request.user.is_staff: if request.user.is_staff:
first_login_url = redirect_user_first_login_or_index( first_login_url = redirect_user_first_login_or_index(
request, self.redirect_field_name request, self.redirect_field_name
) )
return redirect(first_login_url) return redirect(first_login_url)
redirect_url = self.redirect_third_party_auth_if_need(request)
if redirect_url:
return redirect(redirect_url)
request.session.set_test_cookie() request.session.set_test_cookie()
return super().get(request, *args, **kwargs) return super().get(request, *args, **kwargs)
@ -225,50 +253,3 @@ class UserLogoutView(TemplateView):
} }
kwargs.update(context) kwargs.update(context)
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
@method_decorator(never_cache, name='dispatch')
class FlashPasswdTooSimpleMsgView(TemplateView):
template_name = 'flash_message_standalone.html'
def get(self, request, *args, **kwargs):
context = {
'title': _('Please change your password'),
'messages': _('Your password is too simple, please change it for security'),
'interval': 3,
'redirect_url': request.GET.get('redirect_url'),
'auto_redirect': True,
}
return self.render_to_response(context)
@method_decorator(never_cache, name='dispatch')
class FlashPasswdNeedUpdateMsgView(TemplateView):
template_name = 'flash_message_standalone.html'
def get(self, request, *args, **kwargs):
context = {
'title': _('Please change your password'),
'messages': _('You should to change your password before login'),
'interval': 3,
'redirect_url': request.GET.get('redirect_url'),
'auto_redirect': True,
'confirm_button': _('Confirm')
}
return self.render_to_response(context)
@method_decorator(never_cache, name='dispatch')
class FlashPasswdHasExpiredMsgView(TemplateView):
template_name = 'flash_message_standalone.html'
def get(self, request, *args, **kwargs):
context = {
'title': _('Please change your password'),
'messages': _('Your password has expired, please reset before logging in'),
'interval': 3,
'redirect_url': request.GET.get('redirect_url'),
'auto_redirect': True,
'confirm_button': _('Confirm')
}
return self.render_to_response(context)

View File

@ -5,7 +5,7 @@ from django.contrib.auth.mixins import UserPassesTestMixin
from django.utils import timezone from django.utils import timezone
__all__ = ["DatetimeSearchMixin"] __all__ = ["DatetimeSearchMixin", "PermissionsMixin"]
from rest_framework import permissions from rest_framework import permissions

View File

@ -0,0 +1,10 @@
from django.urls import path
from .. import views
app_name = 'common'
urlpatterns = [
# login
path('flash-message/', views.FlashMessageMsgView.as_view(), name='flash-message'),
]

View File

@ -8,3 +8,4 @@ from .http import *
from .ipip import * from .ipip import *
from .crypto import * from .crypto import *
from .random import * from .random import *
from .jumpserver import *

View File

@ -0,0 +1,31 @@
from django.core.cache import cache
from django.shortcuts import reverse
from .random import random_string
__all__ = ['FlashMessageUtil']
class FlashMessageUtil:
@staticmethod
def get_key(code):
key = 'MESSAGE_{}'.format(code)
return key
@classmethod
def get_message_code(cls, message_data):
code = random_string(12)
key = cls.get_key(code)
cache.set(key, message_data, 60)
return code
@classmethod
def get_message_by_code(cls, code):
key = cls.get_key(code)
return cache.get(key)
@classmethod
def gen_message_url(cls, message_data):
code = cls.get_message_code(message_data)
return reverse('common:flash-message') + f'?code={code}'

40
apps/common/views.py Normal file
View File

@ -0,0 +1,40 @@
#
from django.utils.decorators import method_decorator
from django.views.decorators.cache import never_cache
from django.http import HttpResponse
from django.views.generic.base import TemplateView
from common.utils import bulk_get, FlashMessageUtil
@method_decorator(never_cache, name='dispatch')
class FlashMessageMsgView(TemplateView):
template_name = 'flash_message_standalone.html'
def get(self, request, *args, **kwargs):
code = request.GET.get('code')
if not code:
return HttpResponse('Not found the code')
message_data = FlashMessageUtil.get_message_by_code(code)
if not message_data:
return HttpResponse('Message code error')
title, message, redirect_url, confirm_button, cancel_url = bulk_get(
message_data, 'title', 'message', 'redirect_url', 'confirm_button', 'cancel_url'
)
interval = message_data.get('interval', 3)
auto_redirect = message_data.get('auto_redirect', True)
has_cancel = message_data.get('has_cancel', False)
context = {
'title': title,
'messages': message,
'interval': interval,
'redirect_url': redirect_url,
'auto_redirect': auto_redirect,
'confirm_button': confirm_button,
'has_cancel': has_cancel,
'cancel_url': cancel_url,
}
return self.render_to_response(context)

View File

@ -29,6 +29,7 @@ api_v1 = [
app_view_patterns = [ app_view_patterns = [
path('auth/', include('authentication.urls.view_urls'), name='auth'), path('auth/', include('authentication.urls.view_urls'), name='auth'),
path('ops/', include('ops.urls.view_urls'), name='ops'), path('ops/', include('ops.urls.view_urls'), name='ops'),
path('common/', include('common.urls.view_urls'), name='common'),
re_path(r'flower/(?P<path>.*)', views.celery_flower_view, name='flower-view'), re_path(r'flower/(?P<path>.*)', views.celery_flower_view, name='flower-view'),
] ]

View File

@ -1,17 +1,15 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import re import re
import time
from django.http import HttpResponseRedirect, JsonResponse, Http404 from django.http import HttpResponseRedirect, JsonResponse, Http404
from django.conf import settings from django.conf import settings
from django.views.generic import View from django.views.generic import View
from django.shortcuts import redirect from django.shortcuts import redirect
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from rest_framework.views import APIView
from rest_framework.permissions import AllowAny
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse from django.http import HttpResponse
from rest_framework.views import APIView
from common.http import HttpResponseTemporaryRedirect from common.http import HttpResponseTemporaryRedirect
@ -85,3 +83,4 @@ class KokoView(View):
"<div>Koko is a separately deployed program, you need to deploy Koko, configure nginx for url distribution,</div> " "<div>Koko is a separately deployed program, you need to deploy Koko, configure nginx for url distribution,</div> "
"</div>If you see this page, prove that you are not accessing the nginx listening port. Good luck.</div>") "</div>If you see this page, prove that you are not accessing the nginx listening port. Good luck.</div>")
return HttpResponse(msg) return HttpResponse(msg)

Binary file not shown.

View File

@ -8,7 +8,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-04-29 12:17+0800\n" "POT-Creation-Date: 2021-04-29 16:20+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\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"
@ -354,7 +354,9 @@ msgid "You can't delete the root node ({})"
msgstr "不能删除根节点 ({})" msgstr "不能删除根节点 ({})"
#: assets/api/node.py:75 #: assets/api/node.py:75
msgid "Deletion failed and the node contains children or assets" #, fuzzy
#| msgid "Deletion failed and the node contains children or assets"
msgid "Deletion failed and the node contains assets"
msgstr "删除失败,节点包含子节点或资产" msgstr "删除失败,节点包含子节点或资产"
#: assets/backends/db.py:244 #: assets/backends/db.py:244
@ -650,31 +652,31 @@ msgstr "资产组"
msgid "Default asset group" msgid "Default asset group"
msgstr "默认资产组" msgstr "默认资产组"
#: assets/models/label.py:19 assets/models/node.py:547 settings/models.py:30 #: assets/models/label.py:19 assets/models/node.py:546 settings/models.py:30
msgid "Value" msgid "Value"
msgstr "值" msgstr "值"
#: assets/models/node.py:152 #: assets/models/node.py:151
msgid "New node" msgid "New node"
msgstr "新节点" msgstr "新节点"
#: assets/models/node.py:475 users/templates/users/_granted_assets.html:130 #: assets/models/node.py:474 users/templates/users/_granted_assets.html:130
msgid "empty" msgid "empty"
msgstr "空" msgstr "空"
#: assets/models/node.py:546 perms/models/asset_permission.py:176 #: assets/models/node.py:545 perms/models/asset_permission.py:176
msgid "Key" msgid "Key"
msgstr "键" msgstr "键"
#: assets/models/node.py:548 #: assets/models/node.py:547
msgid "Full value" msgid "Full value"
msgstr "全称" msgstr "全称"
#: assets/models/node.py:551 perms/models/asset_permission.py:177 #: assets/models/node.py:550 perms/models/asset_permission.py:177
msgid "Parent key" msgid "Parent key"
msgstr "ssh私钥" msgstr "ssh私钥"
#: assets/models/node.py:560 assets/serializers/system_user.py:191 #: assets/models/node.py:559 assets/serializers/system_user.py:191
#: users/templates/users/user_asset_permission.html:41 #: users/templates/users/user_asset_permission.html:41
#: users/templates/users/user_asset_permission.html:73 #: users/templates/users/user_asset_permission.html:73
#: users/templates/users/user_asset_permission.html:158 #: users/templates/users/user_asset_permission.html:158
@ -1360,15 +1362,15 @@ msgstr "来源 IP 不被允许登录"
msgid "SSO auth closed" msgid "SSO auth closed"
msgstr "SSO 认证关闭了" msgstr "SSO 认证关闭了"
#: authentication/errors.py:271 authentication/views/login.py:237 #: authentication/errors.py:271 authentication/views/login.py:267
msgid "Your password is too simple, please change it for security" msgid "Your password is too simple, please change it for security"
msgstr "你的密码过于简单,为了安全,请修改" msgstr "你的密码过于简单,为了安全,请修改"
#: authentication/errors.py:280 authentication/views/login.py:252 #: authentication/errors.py:280 authentication/views/login.py:282
msgid "You should to change your password before login" msgid "You should to change your password before login"
msgstr "登录完成前,请先修改密码" msgstr "登录完成前,请先修改密码"
#: authentication/errors.py:289 authentication/views/login.py:268 #: authentication/errors.py:289 authentication/views/login.py:298
msgid "Your password has expired, please reset before logging in" msgid "Your password has expired, please reset before logging in"
msgstr "您的密码已过期,先修改再登录" msgstr "您的密码已过期,先修改再登录"
@ -1453,8 +1455,9 @@ msgid "Need MFA for view auth"
msgstr "需要多因子认证来查看账号信息" msgstr "需要多因子认证来查看账号信息"
#: authentication/templates/authentication/_mfa_confirm_modal.html:20 #: authentication/templates/authentication/_mfa_confirm_modal.html:20
#: authentication/views/login.py:256 authentication/views/login.py:272 #: authentication/views/login.py:286 authentication/views/login.py:302
#: templates/_modal.html:23 users/templates/users/user_password_verify.html:20 #: authentication/views/login.py:318 templates/_modal.html:23
#: users/templates/users/user_password_verify.html:20
msgid "Confirm" msgid "Confirm"
msgstr "确认" msgstr "确认"
@ -1519,7 +1522,6 @@ msgid "Copy link"
msgstr "复制链接" msgstr "复制链接"
#: authentication/templates/authentication/login_wait_confirm.html:51 #: authentication/templates/authentication/login_wait_confirm.html:51
#: templates/flash_message_standalone.html:38
msgid "Return" msgid "Return"
msgstr "返回" msgstr "返回"
@ -1527,11 +1529,19 @@ msgstr "返回"
msgid "Copy success" msgid "Copy success"
msgstr "复制成功" msgstr "复制成功"
#: authentication/views/login.py:58 #: authentication/views/login.py:63 authentication/views/login.py:313
msgid "Redirecting"
msgstr "跳转中"
#: authentication/views/login.py:64
msgid "Redirecting to {} authentication"
msgstr "正在跳转到 {} 认证"
#: authentication/views/login.py:88
msgid "Please enable cookies and try again." msgid "Please enable cookies and try again."
msgstr "设置你的浏览器支持cookie" msgstr "设置你的浏览器支持cookie"
#: authentication/views/login.py:183 #: authentication/views/login.py:213
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"
@ -1539,23 +1549,27 @@ msgstr ""
"等待 <b>{}</b> 确认, 你也可以复制链接发给他/她 <br/>\n" "等待 <b>{}</b> 确认, 你也可以复制链接发给他/她 <br/>\n"
" 不要关闭本页面" " 不要关闭本页面"
#: authentication/views/login.py:188 #: authentication/views/login.py:218
msgid "No ticket found" msgid "No ticket found"
msgstr "没有发现工单" msgstr "没有发现工单"
#: authentication/views/login.py:220 #: authentication/views/login.py:250
msgid "Logout success" msgid "Logout success"
msgstr "退出登录成功" msgstr "退出登录成功"
#: authentication/views/login.py:221 #: authentication/views/login.py:251
msgid "Logout success, return login page" msgid "Logout success, return login page"
msgstr "退出登录成功,返回到登录页面" msgstr "退出登录成功,返回到登录页面"
#: authentication/views/login.py:236 authentication/views/login.py:251 #: authentication/views/login.py:266 authentication/views/login.py:281
#: authentication/views/login.py:267 #: authentication/views/login.py:297
msgid "Please change your password" msgid "Please change your password"
msgstr "请修改密码" msgstr "请修改密码"
#: authentication/views/login.py:314
msgid "Redirect to third party auth"
msgstr ""
#: common/const/__init__.py:6 #: common/const/__init__.py:6
#, python-format #, python-format
msgid "%(name)s was created successfully" msgid "%(name)s was created successfully"
@ -1671,7 +1685,7 @@ msgstr "JumpServer 开源堡垒机"
msgid "<h1>Flow service unavailable, check it</h1>" msgid "<h1>Flow service unavailable, check it</h1>"
msgstr "" msgstr ""
#: jumpserver/views/other.py:27 #: jumpserver/views/other.py:25
msgid "" msgid ""
"<div>Luna is a separately deployed program, you need to deploy Luna, koko, " "<div>Luna is a separately deployed program, you need to deploy Luna, koko, "
"configure nginx for url distribution,</div> </div>If you see this page, " "configure nginx for url distribution,</div> </div>If you see this page, "
@ -1680,11 +1694,11 @@ msgstr ""
"<div>Luna是单独部署的一个程序你需要部署lunakoko, </div><div>如果你看到了" "<div>Luna是单独部署的一个程序你需要部署lunakoko, </div><div>如果你看到了"
"这个页面证明你访问的不是nginx监听的端口祝你好运</div>" "这个页面证明你访问的不是nginx监听的端口祝你好运</div>"
#: jumpserver/views/other.py:71 #: jumpserver/views/other.py:69
msgid "Websocket server run on port: {}, you should proxy it on nginx" msgid "Websocket server run on port: {}, you should proxy it on nginx"
msgstr "Websocket 服务运行在端口: {}, 请检查nginx是否代理是否设置" msgstr "Websocket 服务运行在端口: {}, 请检查nginx是否代理是否设置"
#: jumpserver/views/other.py:85 #: jumpserver/views/other.py:83
msgid "" msgid ""
"<div>Koko is a separately deployed program, you need to deploy Koko, " "<div>Koko is a separately deployed program, you need to deploy Koko, "
"configure nginx for url distribution,</div> </div>If you see this page, " "configure nginx for url distribution,</div> </div>If you see this page, "
@ -2760,6 +2774,14 @@ msgstr "确认删除"
msgid "Are you sure delete" msgid "Are you sure delete"
msgstr "您确定删除吗?" msgstr "您确定删除吗?"
#: templates/flash_message_standalone.html:28
msgid "Cancel"
msgstr "取消"
#: templates/flash_message_standalone.html:37
msgid "Go"
msgstr "跳转"
#: templates/index.html:11 #: templates/index.html:11
msgid "Total users" msgid "Total users"
msgstr "用户总数" msgstr "用户总数"
@ -4978,9 +5000,6 @@ msgstr "社区版"
#~ msgid "This will reset the user password and send a reset mail" #~ msgid "This will reset the user password and send a reset mail"
#~ msgstr "将失效用户当前密码,并发送重设密码邮件到用户邮箱" #~ msgstr "将失效用户当前密码,并发送重设密码邮件到用户邮箱"
#~ msgid "Cancel"
#~ msgstr "取消"
#~ msgid "" #~ msgid ""
#~ "The reset-ssh-public-key E-mail has been sent successfully. Please inform " #~ "The reset-ssh-public-key E-mail has been sent successfully. Please inform "
#~ "the user to update his new ssh public key." #~ "the user to update his new ssh public key."

View File

@ -4,14 +4,6 @@
{% block html_title %} {{ title }} {% endblock %} {% block html_title %} {{ title }} {% endblock %}
{% block title %} {{ title }}{% endblock %} {% block title %} {{ title }}{% endblock %}
{% block custom_head_css_js %}
<style>
.passwordBox {
max-width: 660px;
}
</style>
{% endblock %}
{% block content %} {% block content %}
<div> <div>
{% if errors %} {% if errors %}
@ -30,12 +22,19 @@
</p> </p>
{% endif %} {% endif %}
<div class="row"> <div class="row">
<div class="col-lg-3"> {% if has_cancel %}
<div class="col-lg-2">
<a href="{{ cancel_url }}" class="btn btn-default block full-width m-b">
{% trans 'Cancel' %}
</a>
</div>
{% endif %}
<div class="col-lg-2">
<a href="{{ redirect_url }}" class="btn btn-primary block full-width m-b"> <a href="{{ redirect_url }}" class="btn btn-primary block full-width m-b">
{% if confirm_button %} {% if confirm_button %}
{{ confirm_button }} {{ confirm_button }}
{% else %} {% else %}
{% trans 'Return' %} {% trans 'Go' %}
{% endif %} {% endif %}
</a> </a>
</div> </div>

View File

@ -1,18 +1,15 @@
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
from __future__ import unicode_literals from __future__ import unicode_literals
from django.shortcuts import render
from django.views.generic import RedirectView from django.views.generic import RedirectView
from django.core.files.storage import default_storage
from django.shortcuts import reverse, redirect from django.shortcuts import reverse, redirect
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
from django.conf import settings from django.conf import settings
from django.urls import reverse_lazy from django.urls import reverse_lazy
from formtools.wizard.views import SessionWizardView
from django.views.generic import FormView from django.views.generic import FormView
from common.utils import get_object_or_none from common.utils import get_object_or_none, FlashMessageUtil
from common.permissions import IsValidUser from common.permissions import IsValidUser
from common.mixins.views import PermissionsMixin from common.mixins.views import PermissionsMixin
from ...models import User from ...models import User
@ -24,9 +21,7 @@ from ... import forms
__all__ = [ __all__ = [
'UserLoginView', 'UserForgotPasswordSendmailSuccessView', 'UserLoginView', 'UserResetPasswordView', 'UserForgotPasswordView', 'UserFirstLoginView',
'UserResetPasswordSuccessView', 'UserResetPasswordSuccessView',
'UserResetPasswordView', 'UserForgotPasswordView', 'UserFirstLoginView',
] ]
@ -39,6 +34,17 @@ class UserForgotPasswordView(FormView):
template_name = 'users/forgot_password.html' template_name = 'users/forgot_password.html'
form_class = forms.UserForgotPasswordForm form_class = forms.UserForgotPasswordForm
@staticmethod
def get_redirect_message_url():
message_data = {
'title': _('Send reset password message'),
'message': _('Send reset password mail success, '
'login your mail box and follow it '),
'redirect_url': reverse('authentication:login'),
}
url = FlashMessageUtil.gen_message_url(message_data)
return url
def form_valid(self, form): def form_valid(self, form):
email = form.cleaned_data['email'] email = form.cleaned_data['email']
user = get_object_or_none(User, email=email) user = get_object_or_none(User, email=email)
@ -53,37 +59,9 @@ class UserForgotPasswordView(FormView):
).format(user.get_source_display()) ).format(user.get_source_display())
form.add_error('email', error) form.add_error('email', error)
return self.form_invalid(form) return self.form_invalid(form)
send_reset_password_mail(user) send_reset_password_mail(user)
return redirect('authentication:forgot-password-sendmail-success') url = self.get_redirect_message_url()
return redirect(url)
class UserForgotPasswordSendmailSuccessView(TemplateView):
template_name = 'flash_message_standalone.html'
def get_context_data(self, **kwargs):
context = {
'title': _('Send reset password message'),
'messages': _('Send reset password mail success, '
'login your mail box and follow it '),
'redirect_url': reverse('authentication:login'),
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class UserResetPasswordSuccessView(TemplateView):
template_name = 'flash_message_standalone.html'
def get_context_data(self, **kwargs):
context = {
'title': _('Reset password success'),
'messages': _('Reset password success, return to login page'),
'redirect_url': reverse('authentication:login'),
'auto_redirect': True,
}
kwargs.update(context)
return super().get_context_data(**kwargs)
class UserResetPasswordView(FormView): class UserResetPasswordView(FormView):
@ -139,7 +117,18 @@ class UserResetPasswordView(FormView):
user.reset_password(password) user.reset_password(password)
User.expired_reset_password_token(token) User.expired_reset_password_token(token)
send_reset_password_success_mail(self.request, user) send_reset_password_success_mail(self.request, user)
return redirect('authentication:reset-password-success') url = self.get_redirect_url()
return redirect(url)
@staticmethod
def get_redirect_url():
message_data = {
'title': _('Reset password success'),
'message': _('Reset password success, return to login page'),
'redirect_url': reverse('authentication:login'),
'auto_redirect': True,
}
return FlashMessageUtil.gen_message_url(message_data)
class UserFirstLoginView(PermissionsMixin, TemplateView): class UserFirstLoginView(PermissionsMixin, TemplateView):