fix captcha not valid bug of login view; use django's default login and logout view to enhance robustness

pull/530/head
xiaokong1937@gmail.com 2016-09-05 21:38:21 +08:00
parent 6fc3bbb97d
commit e75d33439a
6 changed files with 70 additions and 87 deletions

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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>

View File

@ -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'),
]

View File

@ -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)