mirror of https://github.com/jumpserver/jumpserver
fix captcha not valid bug of login view; use django's default login and logout view to enhance robustness
parent
6fc3bbb97d
commit
e75d33439a
|
@ -19,9 +19,15 @@
|
|||
</a>
|
||||
</li>
|
||||
<li>
|
||||
{% if user.is_authenticated %}
|
||||
<a href="{% url 'users:logout' %}">
|
||||
<i class="fa fa-sign-out"></i> Log out
|
||||
<i class="fa fa-sign-out"></i>{% trans 'Log out' %}
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{% url 'users:login' %}">
|
||||
<i class="fa fa-sign-in"></i>{% trans 'Log in' %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
<a data-toggle="dropdown" class="dropdown-toggle" href="#">
|
||||
<span class="clear">
|
||||
<span class="block m-t-xs">
|
||||
<strong class="font-bold"> {{ request.user.name }}<span style="color: #8095a8"></span></strong>
|
||||
<strong class="font-bold"> {{ user.name }}<span style="color: #8095a8"></span></strong>
|
||||
</span>
|
||||
<span class="text-muted text-xs block">
|
||||
{{ request.user.get_role_display | default:"{% trans 'User' %}" }}<b class="caret"></b>
|
||||
{{ user.get_role_display | default:_('User') }}<b class="caret"></b>
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
|
|
|
@ -1,20 +1,24 @@
|
|||
# ~*~ coding: utf-8 ~*~
|
||||
|
||||
from django.forms import ModelForm
|
||||
from django import forms
|
||||
from captcha.fields import CaptchaField
|
||||
from django.contrib.auth.forms import AuthenticationForm
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from captcha.fields import CaptchaField
|
||||
|
||||
from .models import User, UserGroup
|
||||
|
||||
|
||||
class UserLoginForm(forms.Form):
|
||||
class UserLoginForm(AuthenticationForm):
|
||||
username = forms.CharField(label=_('Username'), max_length=100)
|
||||
password = forms.CharField(label=_('Password'), widget=forms.PasswordInput, max_length=100)
|
||||
password = forms.CharField(
|
||||
label=_('Password'), widget=forms.PasswordInput, max_length=100,
|
||||
strip=False)
|
||||
captcha = CaptchaField()
|
||||
|
||||
|
||||
class UserAddForm(ModelForm):
|
||||
class UserAddForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = [
|
||||
|
@ -32,7 +36,8 @@ class UserAddForm(ModelForm):
|
|||
}
|
||||
|
||||
|
||||
class UserUpdateForm(ModelForm):
|
||||
class UserUpdateForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = [
|
||||
|
@ -51,7 +56,8 @@ class UserUpdateForm(ModelForm):
|
|||
}
|
||||
|
||||
|
||||
class UserGroupForm(ModelForm):
|
||||
class UserGroupForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = UserGroup
|
||||
|
||||
|
|
|
@ -40,11 +40,10 @@
|
|||
{% if form.errors %}
|
||||
{% if 'captcha' in form.errors %}
|
||||
<p class="red-fonts">{% trans 'Captcha invalid' %}</p>
|
||||
{% else %}
|
||||
<p class="red-fonts">{{ form.non_field_errors.as_text }}</p>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if errors %}
|
||||
<p class="red-fonts">{{ errors }}</p>
|
||||
{% endif %}
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="{{ form.username.html_name }}" placeholder="{% trans 'Username' %}" required="">
|
||||
</div>
|
||||
|
@ -57,7 +56,7 @@
|
|||
<button type="submit" class="btn btn-primary block full-width m-b">{% trans 'Login' %}</button>
|
||||
|
||||
<a href="{% url 'users:forget-password' %}">
|
||||
<small>Forgot password?</small>
|
||||
<small>{% trans 'Forgot password' %}?</small>
|
||||
</a>
|
||||
|
||||
<p class="text-muted text-center">
|
||||
|
@ -79,7 +78,4 @@
|
|||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
|
||||
|
|
|
@ -1,37 +1,61 @@
|
|||
from django.conf.urls import url, include
|
||||
from django.conf.urls import url
|
||||
from django.contrib.auth import views as auth_views
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
import views
|
||||
import api
|
||||
|
||||
from users.forms import UserLoginForm
|
||||
|
||||
app_name = 'users'
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^login$', views.UserLoginView.as_view(), name='login'),
|
||||
url(r'^logout$', views.UserLogoutView.as_view(), name='logout'),
|
||||
url(r'^login$',
|
||||
auth_views.login,
|
||||
{'template_name': "users/login.html",
|
||||
'authentication_form': UserLoginForm,
|
||||
'redirect_authenticated_user': True},
|
||||
name='login'),
|
||||
url(r'^logout$',
|
||||
auth_views.logout,
|
||||
{
|
||||
"template_name": "common/flash_message_standalone.html",
|
||||
"extra_context": {
|
||||
'title': _('Logout success'),
|
||||
'messages': _('Logout success, return login page'),
|
||||
'redirect_url': '/users/login',
|
||||
'auto_redirect': True,
|
||||
}
|
||||
},
|
||||
name='logout'),
|
||||
url(r'^password/forget$', views.UserForgetPasswordView.as_view(), name='forget-password'),
|
||||
url(r'^password/forget/sendmail-success$',
|
||||
views.UserForgetPasswordSendmailSuccessView.as_view(), name='forget-password-sendmail-success'),
|
||||
url(r'^password/reset$', views.UserResetPasswordView.as_view(), name='reset-password'),
|
||||
url(r'^password/reset/success$', views.UserResetPasswordSuccessView.as_view(), name='reset-password-success'),
|
||||
url(r'^password/reset/success$', views.UserResetPasswordSuccessView.as_view(),
|
||||
name='reset-password-success'),
|
||||
url(r'^user$', views.UserListView.as_view(), name='user-list'),
|
||||
url(r'^user/(?P<pk>[0-9]+)$', views.UserDetailView.as_view(), name='user-detail'),
|
||||
url(r'^user/add$', views.UserAddView.as_view(), name='user-add'),
|
||||
url(r'^user/(?P<pk>[0-9]+)/edit$', views.UserUpdateView.as_view(), name='user-edit'),
|
||||
url(r'^user/(?P<pk>[0-9]+)/delete$', views.UserDeleteView.as_view(), name='user-delete'),
|
||||
url(r'^usergroup$', views.UserGroupListView.as_view(), name='usergroup-list'),
|
||||
url(r'^usergroup/(?P<pk>[0-9]+)$', views.UserGroupDetailView.as_view(), name='usergroup-detail'),
|
||||
url(r'^usergroup/(?P<pk>[0-9]+)$',
|
||||
views.UserGroupDetailView.as_view(), name='usergroup-detail'),
|
||||
url(r'^usergroup/add/$', views.UserGroupAddView.as_view(), name='usergroup-add'),
|
||||
url(r'^usergroup/(?P<pk>[0-9]+)/edit$', views.UserGroupUpdateView.as_view(), name='usergroup-edit'),
|
||||
url(r'^usergroup/(?P<pk>[0-9]+)/delete$', views.UserGroupDeleteView.as_view(), name='usergroup-delete'),
|
||||
url(r'^usergroup/(?P<pk>[0-9]+)/edit$',
|
||||
views.UserGroupUpdateView.as_view(), name='usergroup-edit'),
|
||||
url(r'^usergroup/(?P<pk>[0-9]+)/delete$',
|
||||
views.UserGroupDeleteView.as_view(), name='usergroup-delete'),
|
||||
]
|
||||
|
||||
|
||||
urlpatterns += [
|
||||
url(r'^v1/users$', api.UserListAddApi.as_view(), name='user-list-api'),
|
||||
url(r'^v1/users/(?P<pk>[0-9]+)$', api.UserDetailDeleteUpdateApi.as_view(), name='user-detail-api'),
|
||||
url(r'^v1/users/(?P<pk>[0-9]+)$',
|
||||
api.UserDetailDeleteUpdateApi.as_view(), name='user-detail-api'),
|
||||
url(r'^v1/users/(?P<pk>[0-9]+)/active$', api.UserActiveApi.as_view(), name='user-active-api'),
|
||||
url(r'^v1/usergroups$', api.UserGroupListAddApi.as_view(), name='usergroup-list-api'),
|
||||
url(r'^v1/usergroups/(?P<pk>[0-9]+)$', api.UserGroupDetailDeleteUpdateApi.as_view(), name='usergroup-detail-api'),
|
||||
url(r'^v1/usergroups/(?P<pk>[0-9]+)$',
|
||||
api.UserGroupDetailDeleteUpdateApi.as_view(), name='usergroup-detail-api'),
|
||||
]
|
||||
|
|
|
@ -4,78 +4,28 @@ from __future__ import unicode_literals
|
|||
|
||||
import logging
|
||||
|
||||
from django.shortcuts import get_object_or_404, reverse, render, Http404, redirect
|
||||
from django.conf import settings
|
||||
from django.contrib.messages.views import SuccessMessageMixin
|
||||
from django.db.models import Q
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, reverse
|
||||
from django.urls import reverse_lazy
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.db.models import Q
|
||||
from django.views.generic.base import View, TemplateView
|
||||
from django.views.generic.base import TemplateView
|
||||
from django.views.generic.list import ListView
|
||||
from django.views.generic.edit import CreateView, DeleteView, UpdateView, ProcessFormView, FormView
|
||||
from django.views.generic.edit import CreateView, DeleteView, UpdateView
|
||||
from django.views.generic.detail import DetailView
|
||||
from django.contrib.messages.views import SuccessMessageMixin
|
||||
from django.conf import settings
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.contrib.auth import views as auth_view, authenticate, login, logout
|
||||
|
||||
from common.utils import get_object_or_none
|
||||
|
||||
from .models import User, UserGroup
|
||||
from .forms import UserAddForm, UserUpdateForm, UserGroupForm, UserLoginForm
|
||||
from .utils import AdminUserRequiredMixin, ssh_key_gen, user_add_success_next, send_reset_password_mail
|
||||
from .forms import UserAddForm, UserUpdateForm, UserGroupForm
|
||||
from .utils import AdminUserRequiredMixin, user_add_success_next, send_reset_password_mail
|
||||
|
||||
|
||||
logger = logging.getLogger('jumpserver.users.views')
|
||||
|
||||
|
||||
class UserLoginView(FormView):
|
||||
template_name = 'users/login.html'
|
||||
form_class = UserLoginForm
|
||||
redirect_field_name = 'next'
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if self.request.user.is_staff:
|
||||
return redirect(request.POST.get(self.redirect_field_name, reverse('index')))
|
||||
# Todo: Django have bug, lose context issue: https://github.com/django/django/pull/7202
|
||||
# so we jump it and use origin method render_to_response
|
||||
# return super(UserLoginView, self).get(request, *args, **kwargs)
|
||||
return self.render_to_response(self.get_context_data(**kwargs))
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
form = self.get_form()
|
||||
if not form.is_valid():
|
||||
return self.form_invalid(form)
|
||||
|
||||
username = form['username'].value()
|
||||
password = form['password'].value()
|
||||
|
||||
user = authenticate(username=username, password=password)
|
||||
if user is None:
|
||||
kwargs.update({'errors': _('Username or password invalid')})
|
||||
return self.get(request, *args, **kwargs)
|
||||
|
||||
login(request, user)
|
||||
return redirect(request.GET.get(self.redirect_field_name, reverse('index')))
|
||||
|
||||
|
||||
class UserLogoutView(TemplateView):
|
||||
template_name = 'common/flash_message_standalone.html'
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
logout(request)
|
||||
|
||||
return super(UserLogoutView, self).get(request)
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = {
|
||||
'title': _('Logout success'),
|
||||
'messages': _('Logout success, return login page'),
|
||||
'redirect_url': reverse('users:login'),
|
||||
'auto_redirect': True,
|
||||
}
|
||||
kwargs.update(context)
|
||||
return super(UserLogoutView, self).get_context_data(**kwargs)
|
||||
|
||||
|
||||
class UserListView(AdminUserRequiredMixin, ListView):
|
||||
model = User
|
||||
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
|
||||
|
@ -166,7 +116,8 @@ class UserDetailView(AdminUserRequiredMixin, DetailView):
|
|||
context_object_name = "user"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
groups = [group for group in UserGroup.objects.iterator() if group not in self.object.groups.iterator()]
|
||||
groups = [
|
||||
group for group in UserGroup.objects.iterator() if group not in self.object.groups.iterator()]
|
||||
context = {'app': _('Users'), 'action': _('User detail'), 'groups': groups}
|
||||
kwargs.update(context)
|
||||
return super(UserDetailView, self).get_context_data(**kwargs)
|
||||
|
|
Loading…
Reference in New Issue