[Update] users认证逻辑迁移到authentication中

pull/2461/head
BaiJiangJie 2019-02-27 20:55:28 +08:00
parent 21714cc411
commit 6700dc969f
16 changed files with 263 additions and 239 deletions

View File

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
#
from .auth import *

View File

@ -0,0 +1,200 @@
# -*- coding: utf-8 -*-
#
import uuid
from django.core.cache import cache
from django.urls import reverse
from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext as _
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.views import APIView
from common.utils import get_logger, get_request_ip
from common.permissions import IsOrgAdminOrAppUser
from orgs.mixins import RootOrgViewMixin
from authentication.signals import post_auth_success, post_auth_failed
from users.serializers import UserSerializer
from users.models import User, LoginLog
from users.utils import (
check_user_valid, check_otp_code, increase_login_failed_count,
is_block_login, clean_failed_count
)
from users.hands import Asset, SystemUser
logger = get_logger(__name__)
class UserAuthApi(RootOrgViewMixin, APIView):
permission_classes = (AllowAny,)
serializer_class = UserSerializer
def post(self, request):
# limit login
username = request.data.get('username')
ip = request.data.get('remote_addr', None)
ip = ip or get_request_ip(request)
if is_block_login(username, ip):
msg = _("Log in frequently and try again later")
logger.warn(msg + ': ' + username + ':' + ip)
return Response({'msg': msg}, status=401)
user, msg = self.check_user_valid(request)
if not user:
username = request.data.get('username', '')
exist = User.objects.filter(username=username).first()
reason = LoginLog.REASON_PASSWORD if exist else LoginLog.REASON_NOT_EXIST
self.send_auth_signal(success=False, username=username, reason=reason)
increase_login_failed_count(username, ip)
return Response({'msg': msg}, status=401)
if user.password_has_expired:
self.send_auth_signal(
success=False, username=username,
reason=LoginLog.REASON_PASSWORD_EXPIRED
)
msg = _("The user {} password has expired, please update.".format(
user.username))
logger.info(msg)
return Response({'msg': msg}, status=401)
if not user.otp_enabled:
self.send_auth_signal(success=True, user=user)
# 登陆成功,清除原来的缓存计数
clean_failed_count(username, ip)
token = user.create_bearer_token(request)
return Response(
{'token': token, 'user': self.serializer_class(user).data}
)
seed = uuid.uuid4().hex
cache.set(seed, user, 300)
return Response(
{
'code': 101,
'msg': _('Please carry seed value and '
'conduct MFA secondary certification'),
'otp_url': reverse('api-auth:user-otp-auth'),
'seed': seed,
'user': self.serializer_class(user).data
}, status=300
)
@staticmethod
def check_user_valid(request):
username = request.data.get('username', '')
password = request.data.get('password', '')
public_key = request.data.get('public_key', '')
user, msg = check_user_valid(
username=username, password=password,
public_key=public_key
)
return user, msg
def send_auth_signal(self, success=True, user=None, username='', reason=''):
if success:
post_auth_success.send(sender=self.__class__, user=user, request=self.request)
else:
post_auth_failed.send(
sender=self.__class__, username=username,
request=self.request, reason=reason
)
class UserConnectionTokenApi(RootOrgViewMixin, APIView):
permission_classes = (IsOrgAdminOrAppUser,)
def post(self, request):
user_id = request.data.get('user', '')
asset_id = request.data.get('asset', '')
system_user_id = request.data.get('system_user', '')
token = str(uuid.uuid4())
user = get_object_or_404(User, id=user_id)
asset = get_object_or_404(Asset, id=asset_id)
system_user = get_object_or_404(SystemUser, id=system_user_id)
value = {
'user': user_id,
'username': user.username,
'asset': asset_id,
'hostname': asset.hostname,
'system_user': system_user_id,
'system_user_name': system_user.name
}
cache.set(token, value, timeout=20)
return Response({"token": token}, status=201)
def get(self, request):
token = request.query_params.get('token')
user_only = request.query_params.get('user-only', None)
value = cache.get(token, None)
if not value:
return Response('', status=404)
if not user_only:
return Response(value)
else:
return Response({'user': value['user']})
def get_permissions(self):
if self.request.query_params.get('user-only', None):
self.permission_classes = (AllowAny,)
return super().get_permissions()
class UserToken(APIView):
permission_classes = (AllowAny,)
def post(self, request):
if not request.user.is_authenticated:
username = request.data.get('username', '')
email = request.data.get('email', '')
password = request.data.get('password', '')
public_key = request.data.get('public_key', '')
user, msg = check_user_valid(
username=username, email=email,
password=password, public_key=public_key)
else:
user = request.user
msg = None
if user:
token = user.create_bearer_token(request)
return Response({'Token': token, 'Keyword': 'Bearer'}, status=200)
else:
return Response({'error': msg}, status=406)
class UserOtpAuthApi(RootOrgViewMixin, APIView):
permission_classes = (AllowAny,)
serializer_class = UserSerializer
def post(self, request):
otp_code = request.data.get('otp_code', '')
seed = request.data.get('seed', '')
user = cache.get(seed, None)
if not user:
return Response(
{'msg': _('Please verify the user name and password first')},
status=401
)
if not check_otp_code(user.otp_secret_key, otp_code):
self.send_auth_signal(success=False, username=user.username, reason=LoginLog.REASON_MFA)
return Response({'msg': _('MFA certification failed')}, status=401)
self.send_auth_signal(success=True, user=user)
token = user.create_bearer_token(request)
data = {'token': token, 'user': self.serializer_class(user).data}
return Response(data)
def send_auth_signal(self, success=True, user=None, username='', reason=''):
if success:
post_auth_success.send(sender=self.__class__, user=user, request=self.request)
else:
post_auth_failed.send(
sender=self.__class__, username=username,
request=self.request, reason=reason
)

View File

@ -14,7 +14,7 @@ from rest_framework import authentication, exceptions
from rest_framework.authentication import CSRFCheck from rest_framework.authentication import CSRFCheck
from common.utils import get_object_or_none, make_signature, http_to_unixtime from common.utils import get_object_or_none, make_signature, http_to_unixtime
from .models import User, AccessKey, PrivateToken from users.models import User, AccessKey, PrivateToken
def get_request_date_header(request): def get_request_date_header(request):

View File

@ -1 +1,19 @@
# coding:utf-8
#
from __future__ import absolute_import
from django.urls import path
from .. import api
app_name = 'authentication'
urlpatterns = [
# path('token/', api.UserToken.as_view(), name='user-token'),
path('auth/', api.UserAuthApi.as_view(), name='user-auth'),
path('connection-token/',
api.UserConnectionTokenApi.as_view(), name='connection-token'),
path('otp/auth/', api.UserOtpAuthApi.as_view(), name='user-otp-auth'),
]

View File

@ -2,6 +2,7 @@
# #
from django.urls import path from django.urls import path
from .. import views from .. import views
app_name = 'authentication' app_name = 'authentication'
@ -9,6 +10,11 @@ app_name = 'authentication'
urlpatterns = [ urlpatterns = [
# openid # openid
path('openid/login/', views.OpenIDLoginView.as_view(), name='openid-login'), path('openid/login/', views.OpenIDLoginView.as_view(), name='openid-login'),
path('openid/login/complete/', views.OpenIDLoginCompleteView.as_view(), path('openid/login/complete/',
name='openid-login-complete'), views.OpenIDLoginCompleteView.as_view(), name='openid-login-complete'),
# login
path('login/', views.UserLoginView.as_view(), name='login'),
path('login/otp/', views.UserLoginOtpView.as_view(), name='login-otp'),
path('logout/', views.UserLogoutView.as_view(), name='logout'),
] ]

View File

@ -2,3 +2,4 @@
# #
from .openid import * from .openid import *
from .login import *

View File

@ -1,15 +1,11 @@
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
#
from __future__ import unicode_literals from __future__ import unicode_literals
import os import os
from django.core.cache import cache from django.core.cache import cache
from django.shortcuts import render
from django.utils import timezone
from django.contrib.auth import login as auth_login, logout as auth_logout from django.contrib.auth import login as auth_login, logout as auth_logout
from django.contrib.auth.mixins import LoginRequiredMixin from django.http import HttpResponse
from django.views.generic import ListView
from django.core.files.storage import default_storage
from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import reverse, redirect from django.shortcuts import reverse, redirect
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
@ -19,23 +15,20 @@ from django.views.decorators.debug import sensitive_post_parameters
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
from django.views.generic.edit import FormView from django.views.generic.edit import FormView
from django.conf import settings from django.conf import settings
from formtools.wizard.views import SessionWizardView
from common.utils import get_object_or_none, get_request_ip from common.utils import get_request_ip
from authentication.signals import post_auth_success, post_auth_failed from authentication.signals import post_auth_success, post_auth_failed
from users.models import User, LoginLog
from users.utils import send_reset_password_mail, check_otp_code, \
redirect_user_first_login_or_index, get_user_or_tmp_user, \
set_tmp_user_to_cache, get_password_check_rules, check_password_rules, \
is_block_login, increase_login_failed_count, clean_failed_count
from users import forms from users import forms
from users.models import User, LoginLog
from users.utils import (
check_otp_code, is_block_login, clean_failed_count, get_user_or_tmp_user,
set_tmp_user_to_cache, increase_login_failed_count,
redirect_user_first_login_or_index,
)
__all__ = [ __all__ = [
'UserLoginView', 'UserLoginOtpView', 'UserLogoutView', 'UserLoginView', 'UserLoginOtpView', 'UserLogoutView',
'UserForgotPasswordView', 'UserForgotPasswordSendmailSuccessView',
'UserResetPasswordView', 'UserResetPasswordSuccessView',
'UserFirstLoginView', 'LoginLogListView'
] ]
@ -122,7 +115,7 @@ class UserLoginView(FormView):
if user.otp_enabled and user.otp_secret_key: if user.otp_enabled and user.otp_secret_key:
# 1,2,mfa_setting & T # 1,2,mfa_setting & T
return reverse('users:login-otp') return reverse('authentication:login-otp')
elif user.otp_enabled and not user.otp_secret_key: elif user.otp_enabled and not user.otp_secret_key:
# 1,2,mfa_setting & F # 1,2,mfa_setting & F
return reverse('users:user-otp-enable-authentication') return reverse('users:user-otp-enable-authentication')
@ -169,7 +162,9 @@ class UserLoginOtpView(FormView):
success=False, username=user.username, success=False, username=user.username,
reason=LoginLog.REASON_MFA reason=LoginLog.REASON_MFA
) )
form.add_error('otp_code', _('MFA code invalid, or ntp sync server time')) form.add_error(
'otp_code', _('MFA code invalid, or ntp sync server time')
)
return super().form_invalid(form) return super().form_invalid(form)
def get_success_url(self): def get_success_url(self):
@ -202,7 +197,7 @@ class UserLogoutView(TemplateView):
'title': _('Logout success'), 'title': _('Logout success'),
'messages': _('Logout success, return login page'), 'messages': _('Logout success, return login page'),
'interval': 1, 'interval': 1,
'redirect_url': reverse('users:login'), 'redirect_url': reverse('authentication:login'),
'auto_redirect': True, 'auto_redirect': True,
} }
kwargs.update(context) kwargs.update(context)

View File

@ -135,7 +135,7 @@ TEMPLATES = [
# WSGI_APPLICATION = 'jumpserver.wsgi.applications' # WSGI_APPLICATION = 'jumpserver.wsgi.applications'
LOGIN_REDIRECT_URL = reverse_lazy('index') LOGIN_REDIRECT_URL = reverse_lazy('index')
LOGIN_URL = reverse_lazy('users:login') LOGIN_URL = reverse_lazy('authentication:login')
SESSION_COOKIE_DOMAIN = CONFIG.SESSION_COOKIE_DOMAIN SESSION_COOKIE_DOMAIN = CONFIG.SESSION_COOKIE_DOMAIN
CSRF_COOKIE_DOMAIN = CONFIG.CSRF_COOKIE_DOMAIN CSRF_COOKIE_DOMAIN = CONFIG.CSRF_COOKIE_DOMAIN
@ -343,10 +343,10 @@ REST_FRAMEWORK = {
), ),
'DEFAULT_AUTHENTICATION_CLASSES': ( 'DEFAULT_AUTHENTICATION_CLASSES': (
# 'rest_framework.authentication.BasicAuthentication', # 'rest_framework.authentication.BasicAuthentication',
'users.authentication.AccessKeyAuthentication', 'authentication.authentication.AccessKeyAuthentication',
'users.authentication.AccessTokenAuthentication', 'authentication.authentication.AccessTokenAuthentication',
'users.authentication.PrivateTokenAuthentication', 'authentication.authentication.PrivateTokenAuthentication',
'users.authentication.SessionAuthentication', 'authentication.authentication.SessionAuthentication',
), ),
'DEFAULT_FILTER_BACKENDS': ( 'DEFAULT_FILTER_BACKENDS': (
'django_filters.rest_framework.DjangoFilterBackend', 'django_filters.rest_framework.DjangoFilterBackend',

View File

@ -21,6 +21,7 @@ api_v1_patterns = [
path('audits/v1/', include('audits.urls.api_urls', namespace='api-audits')), path('audits/v1/', include('audits.urls.api_urls', namespace='api-audits')),
path('orgs/v1/', include('orgs.urls.api_urls', namespace='api-orgs')), path('orgs/v1/', include('orgs.urls.api_urls', namespace='api-orgs')),
path('settings/v1/', include('settings.urls.api_urls', namespace='api-settings')), path('settings/v1/', include('settings.urls.api_urls', namespace='api-settings')),
path('authentication/v1/', include('authentication.urls.api_urls', namespace='api-auth')),
])) ]))
] ]

View File

@ -94,10 +94,10 @@
<li><a id="switch_user"><i class="fa fa-exchange"></i><span> {% trans 'User page' %}</span></a></li> <li><a id="switch_user"><i class="fa fa-exchange"></i><span> {% trans 'User page' %}</span></a></li>
{% endif %} {% endif %}
{% endif %} {% endif %}
<li><a href="{% url 'users:logout' %}"><i class="fa fa-sign-out"></i> {% trans 'Logout' %}</a></li> <li><a href="{% url 'authentication:logout' %}"><i class="fa fa-sign-out"></i> {% trans 'Logout' %}</a></li>
</ul> </ul>
{% else %} {% else %}
<a href="{% url 'users:login' %}"> <a href="{% url 'authentication:login' %}">
<i class="fa fa-sign-in"></i>{% trans 'Login' %} <i class="fa fa-sign-in"></i>{% trans 'Login' %}
</a> </a>
{% endif %} {% endif %}

View File

@ -1,198 +1,3 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
import uuid
from django.core.cache import cache
from django.urls import reverse
from django.shortcuts import get_object_or_404
from django.utils.translation import ugettext as _
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.views import APIView
from common.utils import get_logger, get_request_ip
from common.permissions import IsOrgAdminOrAppUser
from orgs.mixins import RootOrgViewMixin
from authentication.signals import post_auth_success, post_auth_failed
from ..serializers import UserSerializer
from ..models import User, LoginLog
from ..utils import check_user_valid, check_otp_code, \
increase_login_failed_count, is_block_login, \
clean_failed_count
from ..hands import Asset, SystemUser
logger = get_logger(__name__)
class UserAuthApi(RootOrgViewMixin, APIView):
permission_classes = (AllowAny,)
serializer_class = UserSerializer
def post(self, request):
# limit login
username = request.data.get('username')
ip = request.data.get('remote_addr', None)
ip = ip or get_request_ip(request)
if is_block_login(username, ip):
msg = _("Log in frequently and try again later")
logger.warn(msg + ': ' + username + ':' + ip)
return Response({'msg': msg}, status=401)
user, msg = self.check_user_valid(request)
if not user:
username = request.data.get('username', '')
exist = User.objects.filter(username=username).first()
reason = LoginLog.REASON_PASSWORD if exist else LoginLog.REASON_NOT_EXIST
self.send_auth_signal(success=False, username=username, reason=reason)
increase_login_failed_count(username, ip)
return Response({'msg': msg}, status=401)
if user.password_has_expired:
self.send_auth_signal(
success=False, username=username,
reason=LoginLog.REASON_PASSWORD_EXPIRED
)
msg = _("The user {} password has expired, please update.".format(
user.username))
logger.info(msg)
return Response({'msg': msg}, status=401)
if not user.otp_enabled:
self.send_auth_signal(success=True, user=user)
# 登陆成功,清除原来的缓存计数
clean_failed_count(username, ip)
token = user.create_bearer_token(request)
return Response(
{'token': token, 'user': self.serializer_class(user).data}
)
seed = uuid.uuid4().hex
cache.set(seed, user, 300)
return Response(
{
'code': 101,
'msg': _('Please carry seed value and '
'conduct MFA secondary certification'),
'otp_url': reverse('api-users:user-otp-auth'),
'seed': seed,
'user': self.serializer_class(user).data
}, status=300
)
@staticmethod
def check_user_valid(request):
username = request.data.get('username', '')
password = request.data.get('password', '')
public_key = request.data.get('public_key', '')
user, msg = check_user_valid(
username=username, password=password,
public_key=public_key
)
return user, msg
def send_auth_signal(self, success=True, user=None, username='', reason=''):
if success:
post_auth_success.send(sender=self.__class__, user=user, request=self.request)
else:
post_auth_failed.send(
sender=self.__class__, username=username,
request=self.request, reason=reason
)
class UserConnectionTokenApi(RootOrgViewMixin, APIView):
permission_classes = (IsOrgAdminOrAppUser,)
def post(self, request):
user_id = request.data.get('user', '')
asset_id = request.data.get('asset', '')
system_user_id = request.data.get('system_user', '')
token = str(uuid.uuid4())
user = get_object_or_404(User, id=user_id)
asset = get_object_or_404(Asset, id=asset_id)
system_user = get_object_or_404(SystemUser, id=system_user_id)
value = {
'user': user_id,
'username': user.username,
'asset': asset_id,
'hostname': asset.hostname,
'system_user': system_user_id,
'system_user_name': system_user.name
}
cache.set(token, value, timeout=20)
return Response({"token": token}, status=201)
def get(self, request):
token = request.query_params.get('token')
user_only = request.query_params.get('user-only', None)
value = cache.get(token, None)
if not value:
return Response('', status=404)
if not user_only:
return Response(value)
else:
return Response({'user': value['user']})
def get_permissions(self):
if self.request.query_params.get('user-only', None):
self.permission_classes = (AllowAny,)
return super().get_permissions()
class UserToken(APIView):
permission_classes = (AllowAny,)
def post(self, request):
if not request.user.is_authenticated:
username = request.data.get('username', '')
email = request.data.get('email', '')
password = request.data.get('password', '')
public_key = request.data.get('public_key', '')
user, msg = check_user_valid(
username=username, email=email,
password=password, public_key=public_key)
else:
user = request.user
msg = None
if user:
token = user.create_bearer_token(request)
return Response({'Token': token, 'Keyword': 'Bearer'}, status=200)
else:
return Response({'error': msg}, status=406)
class UserOtpAuthApi(RootOrgViewMixin, APIView):
permission_classes = (AllowAny,)
serializer_class = UserSerializer
def post(self, request):
otp_code = request.data.get('otp_code', '')
seed = request.data.get('seed', '')
user = cache.get(seed, None)
if not user:
return Response(
{'msg': _('Please verify the user name and password first')},
status=401
)
if not check_otp_code(user.otp_secret_key, otp_code):
self.send_auth_signal(success=False, username=user.username, reason=LoginLog.REASON_MFA)
return Response({'msg': _('MFA certification failed')}, status=401)
self.send_auth_signal(success=True, user=user)
token = user.create_bearer_token(request)
data = {'token': token, 'user': self.serializer_class(user).data}
return Response(data)
def send_auth_signal(self, success=True, user=None, username='', reason=''):
if success:
post_auth_success.send(sender=self.__class__, user=user, request=self.request)
else:
post_auth_failed.send(
sender=self.__class__, username=username,
request=self.request, reason=reason
)

View File

@ -15,11 +15,7 @@ router.register(r'groups', api.UserGroupViewSet, 'user-group')
urlpatterns = [ urlpatterns = [
# path('token/', api.UserToken.as_view(), name='user-token'),
path('connection-token/', api.UserConnectionTokenApi.as_view(), name='connection-token'),
path('profile/', api.UserProfileApi.as_view(), name='user-profile'), path('profile/', api.UserProfileApi.as_view(), name='user-profile'),
path('auth/', api.UserAuthApi.as_view(), name='user-auth'),
path('otp/auth/', api.UserOtpAuthApi.as_view(), name='user-otp-auth'),
path('otp/reset/', api.UserResetOTPApi.as_view(), name='my-otp-reset'), path('otp/reset/', api.UserResetOTPApi.as_view(), name='my-otp-reset'),
path('users/<uuid:pk>/otp/reset/', api.UserResetOTPApi.as_view(), name='user-reset-otp'), path('users/<uuid:pk>/otp/reset/', api.UserResetOTPApi.as_view(), name='user-reset-otp'),
path('users/<uuid:pk>/password/', api.UserChangePasswordApi.as_view(), name='change-user-password'), path('users/<uuid:pk>/password/', api.UserChangePasswordApi.as_view(), name='change-user-password'),

View File

@ -9,8 +9,6 @@ app_name = 'users'
urlpatterns = [ urlpatterns = [
# Login view # Login view
path('login/', views.UserLoginView.as_view(), name='login'), path('login/', views.UserLoginView.as_view(), name='login'),
path('logout/', views.UserLogoutView.as_view(), name='logout'),
path('login/otp/', views.UserLoginOtpView.as_view(), name='login-otp'),
path('password/forgot/', views.UserForgotPasswordView.as_view(), name='forgot-password'), path('password/forgot/', views.UserForgotPasswordView.as_view(), name='forgot-password'),
path('password/forgot/sendmail-success/', views.UserForgotPasswordSendmailSuccessView.as_view(), name='forgot-password-sendmail-success'), path('password/forgot/sendmail-success/', views.UserForgotPasswordSendmailSuccessView.as_view(), name='forgot-password-sendmail-success'),
path('password/reset/', views.UserResetPasswordView.as_view(), name='reset-password'), path('password/reset/', views.UserResetPasswordView.as_view(), name='reset-password'),
@ -50,5 +48,5 @@ urlpatterns = [
# Login log # Login log
# Abandon # Abandon
path('login-log/', views.LoginLogListView.as_view(), name='login-log-list'), # path('login-log/', views.LoginLogListView.as_view(), name='login-log-list'),
] ]

View File

@ -62,7 +62,7 @@ def send_user_created_mail(user):
'rest_password_token': user.generate_reset_token(), 'rest_password_token': user.generate_reset_token(),
'forget_password_url': reverse('users:forgot-password', external=True), 'forget_password_url': reverse('users:forgot-password', external=True),
'email': user.email, 'email': user.email,
'login_url': reverse('users:login', external=True), 'login_url': reverse('authentication:login', external=True),
} }
if settings.DEBUG: if settings.DEBUG:
try: try:
@ -98,7 +98,7 @@ def send_reset_password_mail(user):
'rest_password_token': user.generate_reset_token(), 'rest_password_token': user.generate_reset_token(),
'forget_password_url': reverse('users:forgot-password', external=True), 'forget_password_url': reverse('users:forgot-password', external=True),
'email': user.email, 'email': user.email,
'login_url': reverse('users:login', external=True), 'login_url': reverse('authentication:login', external=True),
} }
if settings.DEBUG: if settings.DEBUG:
logger.debug(message) logger.debug(message)
@ -136,7 +136,7 @@ def send_password_expiration_reminder_mail(user):
'update_password_url': reverse('users:user-password-update', external=True), 'update_password_url': reverse('users:user-password-update', external=True),
'forget_password_url': reverse('users:forgot-password', external=True), 'forget_password_url': reverse('users:forgot-password', external=True),
'email': user.email, 'email': user.email,
'login_url': reverse('users:login', external=True), 'login_url': reverse('authentication:login', external=True),
} }
if settings.DEBUG: if settings.DEBUG:
logger.debug(message) logger.debug(message)
@ -158,7 +158,7 @@ def send_reset_ssh_key_mail(user):
</br> </br>
""") % { """) % {
'name': user.name, 'name': user.name,
'login_url': reverse('users:login', external=True), 'login_url': reverse('authentication:login', external=True),
} }
if settings.DEBUG: if settings.DEBUG:
logger.debug(message) logger.debug(message)

View File

@ -24,7 +24,7 @@ from .. import forms
__all__ = [ __all__ = [
'UserLoginView', 'UserForgotPasswordSendmailSuccessView', 'UserLoginView', 'UserForgotPasswordSendmailSuccessView',
'UserResetPasswordSuccessView', 'UserResetPasswordSuccessView', 'UserResetPasswordSuccessView', 'UserResetPasswordSuccessView',
'UserResetPasswordView', 'UserForgotPasswordView', 'UserResetPasswordView', 'UserForgotPasswordView', 'UserFirstLoginView',
] ]
@ -58,7 +58,7 @@ class UserForgotPasswordSendmailSuccessView(TemplateView):
'title': _('Send reset password message'), 'title': _('Send reset password message'),
'messages': _('Send reset password mail success, ' 'messages': _('Send reset password mail success, '
'login your mail box and follow it '), 'login your mail box and follow it '),
'redirect_url': reverse('users:login'), 'redirect_url': reverse('authentication:login'),
} }
kwargs.update(context) kwargs.update(context)
return super().get_context_data(**kwargs) return super().get_context_data(**kwargs)
@ -71,7 +71,7 @@ class UserResetPasswordSuccessView(TemplateView):
context = { context = {
'title': _('Reset password success'), 'title': _('Reset password success'),
'messages': _('Reset password success, return to login page'), 'messages': _('Reset password success, return to login page'),
'redirect_url': reverse('users:login'), 'redirect_url': reverse('authentication:login'),
'auto_redirect': True, 'auto_redirect': True,
} }
kwargs.update(context) kwargs.update(context)

View File

@ -574,7 +574,7 @@ class UserOtpSettingsSuccessView(TemplateView):
'title': title, 'title': title,
'messages': describe, 'messages': describe,
'interval': 1, 'interval': 1,
'redirect_url': reverse('users:login'), 'redirect_url': reverse('authentication:login'),
'auto_redirect': True, 'auto_redirect': True,
} }
kwargs.update(context) kwargs.update(context)