Commit 517c6822 authored by ibuler's avatar ibuler

[Update] 修改登录路基

parent 458bee9a
import uuid
from django.db import models
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from rest_framework.authtoken.models import Token
from django.conf import settings
from common.mixins.models import CommonModelMixin
from common.utils import get_object_or_none, get_request_ip, get_ip_city
class AccessKey(models.Model):
......@@ -42,3 +44,32 @@ class LoginConfirmSetting(CommonModelMixin):
reviewers = models.ManyToManyField('users.User', verbose_name=_("Reviewers"), related_name=_("review_login_confirmation_settings"))
is_active = models.BooleanField(default=True, verbose_name=_("Is active"))
@classmethod
def get_user_confirm_setting(cls, user):
return get_object_or_none(cls, user=user)
def create_confirm_order(self, request=None):
from orders.models import Order
title = _('User login request confirm: {}'.format(self.user))
if request:
remote_addr = get_request_ip(request)
city = get_ip_city(remote_addr)
body = _("User: {}\nIP: {}\nCity: {}\nDate: {}\n").format(
self.user, remote_addr, city, timezone.now()
)
else:
body = ''
reviewer = self.reviewers.all()
reviewer_names = ','.join([u.name for u in reviewer])
order = Order.objects.create(
user=self.user, user_display=str(self.user),
title=title, body=body,
assignees_display=reviewer_names,
type=Order.TYPE_LOGIN_REQUEST,
)
order.assignees.set(reviewer)
return order
def __str__(self):
return '{} confirm'.format(self.user.username)
{% load i18n %}
{% load static %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ title }}</title>
{% include '_head_css_js.html' %}
<link href="{% static "css/jumpserver.css" %}" rel="stylesheet">
<script type="text/javascript"
src="{% url 'javascript-catalog' %}"></script>
<script src="{% static "js/jumpserver.js" %}"></script>
</head>
<body class="gray-bg">
<div class="passwordBox2 animated fadeInDown">
<div class="row">
<div class="col-md-12">
<div class="ibox-content">
<div>
<img src="{{ LOGO_URL }}" style="margin: auto" width="82" height="82">
<h2 style="display: inline">
{{ JMS_TITLE }}
</h2>
</div>
<p></p>
<div class="alert alert-success" id="messages">
Wait for Guanghongwei confirm, You also can copy link to her/his <br/>
Don't close ....
</div>
<div class="progress progress-bar-default">
<div style="width: 43%" aria-valuemax="100" aria-valuemin="0" aria-valuenow="43" role="progressbar" class="progress-bar">
</div>
</div>
<div class="row">
<div class="col-lg-3">
<a href="{{ redirect_url }}" class="btn btn-primary block full-width m-b">
{% trans 'Refresh' %}
</a>
</div>
<div class="col-lg-3">
<a href="{{ redirect_url }}" class="btn btn-primary block full-width m-b">
{% trans 'Copy link' %}
</a>
</div>
</div>
</div>
</div>
</div>
<hr/>
<div class="row">
<div class="col-md-6">
{% include '_copyright.html' %}
</div>
<div class="col-md-6 text-right">
<small>2014-2019</small>
</div>
</div>
</div>
</body>
<script>
var time = '{{ interval }}';
if (!time) {
time = 5;
} else {
time = parseInt(time);
}
function redirect_page() {
if (time >= 0) {
var messages = '{{ messages|safe }}, <b>' + time + '</b> ...';
$('#messages').html(messages);
time--;
setTimeout(redirect_page, 1000);
} else {
window.location.href = "{{ redirect_url }}";
}
}
{% if auto_redirect %}
window.onload = redirect_page;
{% endif %}
</script>
</html>
......@@ -16,5 +16,7 @@ urlpatterns = [
# login
path('login/', views.UserLoginView.as_view(), name='login'),
path('login/otp/', views.UserLoginOtpView.as_view(), name='login-otp'),
path('login/continue/', views.UserLoginContinueView.as_view(), name='login-continue'),
path('login/wait/', views.UserLoginWaitConfirmView.as_view(), name='login-wait'),
path('logout/', views.UserLogoutView.as_view(), name='logout'),
]
......@@ -12,13 +12,12 @@ from django.utils.translation import ugettext as _
from django.views.decorators.cache import never_cache
from django.views.decorators.csrf import csrf_protect
from django.views.decorators.debug import sensitive_post_parameters
from django.views.generic.base import TemplateView
from django.views.generic.base import TemplateView, View, RedirectView
from django.views.generic.edit import FormView
from django.conf import settings
from common.utils import get_request_ip
from users.models import User
from audits.models import UserLoginLog as 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,
......@@ -31,6 +30,7 @@ from .. import const
__all__ = [
'UserLoginView', 'UserLoginOtpView', 'UserLogoutView',
'UserLoginContinueView', 'UserLoginWaitConfirmView',
]
......@@ -40,7 +40,6 @@ __all__ = [
class UserLoginView(FormView):
form_class = forms.UserLoginForm
form_class_captcha = forms.UserLoginCaptchaForm
redirect_field_name = 'next'
key_prefix_captcha = "_LOGIN_INVALID_{}"
def get_template_names(self):
......@@ -52,7 +51,7 @@ class UserLoginView(FormView):
if not License.has_valid_license():
return template_name
template_name = 'authentication/new_login.html'
template_name = 'authentication/xpack_login.html'
return template_name
def get(self, request, *args, **kwargs):
......@@ -91,7 +90,8 @@ class UserLoginView(FormView):
ip = get_request_ip(self.request)
# 登陆成功,清除缓存计数
clean_failed_count(username, ip)
return redirect(self.get_success_url())
self.request.session['auth_password'] = '1'
return self.redirect_to_continue_view()
def form_invalid(self, form):
# write login failed log
......@@ -111,6 +111,11 @@ class UserLoginView(FormView):
form._errors = old_form.errors
return super().form_invalid(form)
@staticmethod
def redirect_to_continue_view():
continue_url = reverse('authentication:login-continue')
return redirect(continue_url)
def get_form_class(self):
ip = get_request_ip(self.request)
if cache.get(self.key_prefix_captcha.format(ip)):
......@@ -118,21 +123,6 @@ class UserLoginView(FormView):
else:
return self.form_class
def get_success_url(self):
user = get_user_or_tmp_user(self.request)
if user.otp_enabled and user.otp_secret_key:
# 1,2,mfa_setting & T
return reverse('authentication:login-otp')
elif user.otp_enabled and not user.otp_secret_key:
# 1,2,mfa_setting & F
return reverse('users:user-otp-enable-authentication')
elif not user.otp_enabled:
# 0 & T,F
auth_login(self.request, user)
self.send_auth_signal(success=True, user=user)
return redirect_user_first_login_or_index(self.request, self.redirect_field_name)
def get_context_data(self, **kwargs):
context = {
'demo_mode': os.environ.get("DEMO_MODE"),
......@@ -141,15 +131,6 @@ class UserLoginView(FormView):
kwargs.update(context)
return super().get_context_data(**kwargs)
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 UserLoginOtpView(FormView):
template_name = 'authentication/login_otp.html'
......@@ -162,9 +143,8 @@ class UserLoginOtpView(FormView):
otp_secret_key = user.otp_secret_key
if check_otp_code(otp_secret_key, otp_code):
auth_login(self.request, user)
self.send_auth_signal(success=True, user=user)
return redirect(self.get_success_url())
self.request.session['auth_otp'] = '1'
return UserLoginView.redirect_to_continue_view()
else:
self.send_auth_signal(
success=False, username=user.username,
......@@ -175,8 +155,40 @@ class UserLoginOtpView(FormView):
)
return super().form_invalid(form)
def get_success_url(self):
return redirect_user_first_login_or_index(self.request, self.redirect_field_name)
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 UserLoginContinueView(RedirectView):
redirect_field_name = 'next'
def get_redirect_url(self, *args, **kwargs):
if not self.request.session.get('auth_password'):
return reverse('authentication:login')
user = get_user_or_tmp_user(self.request)
if user.otp_enabled and user.otp_secret_key and \
not self.request.session.get('auth_otp'):
return reverse('authentication:login-otp')
self.login_success(user)
if user.otp_enabled and not user.otp_secret_key:
# 1,2,mfa_setting & F
return reverse('users:user-otp-enable-authentication')
url = redirect_user_first_login_or_index(
self.request, self.redirect_field_name
)
return url
def login_success(self, user):
auth_login(self.request, user)
self.send_auth_signal(success=True, user=user)
def send_auth_signal(self, success=True, user=None, username='', reason=''):
if success:
......@@ -188,6 +200,13 @@ class UserLoginOtpView(FormView):
)
class UserLoginWaitConfirmView(TemplateView):
template_name = 'authentication/login_wait_confirm.html'
def get_context_data(self, **kwargs):
return super().get_context_data(**kwargs)
@method_decorator(never_cache, name='dispatch')
class UserLogoutView(TemplateView):
template_name = 'flash_message_standalone.html'
......
......@@ -10,8 +10,9 @@ class Order(CommonModelMixin):
('rejected', _("Rejected")),
('pending', _("Pending"))
)
TYPE_LOGIN_REQUEST = 'login_request'
TYPE_CHOICES = (
('login_request', _("Login request")),
(TYPE_LOGIN_REQUEST, _("Login request")),
)
user = models.ForeignKey('users.User', on_delete=models.SET_NULL, null=True, related_name='orders', verbose_name=_("User"))
user_display = models.CharField(max_length=128, verbose_name=_("User display name"))
......@@ -22,7 +23,10 @@ class Order(CommonModelMixin):
assignees_display = models.CharField(max_length=128, verbose_name=_("Assignees display name"), blank=True)
type = models.CharField(choices=TYPE_CHOICES, max_length=64)
status = models.CharField(choices=STATUS_CHOICES, max_length=16)
status = models.CharField(choices=STATUS_CHOICES, max_length=16, default='pending')
def __str__(self):
return '{}: {}'.format(self.user_display, self.title)
class Meta:
ordering = ('date_created',)
......
......@@ -10,7 +10,9 @@ from django.conf import settings
from django.contrib.auth.hashers import make_password
from django.contrib.auth.models import AbstractUser
from django.core.cache import cache
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.utils import timezone
from django.shortcuts import reverse
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment