Refactor user login, change password to use colander/deform
This commit is contained in:
parent
cff757fe9e
commit
ec438ead51
|
@ -1,24 +1,24 @@
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
|
|
||||||
$('#username').keydown(function(event) {
|
$('input[name="username"]').keydown(function(event) {
|
||||||
if (event.which == 13) {
|
if (event.which == 13) {
|
||||||
$('#password').focus().select();
|
$('input[name="password"]').focus().select();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
$('form').submit(function() {
|
$('form').submit(function() {
|
||||||
if (! $('#username').val()) {
|
if (! $('input[name="username"]').val()) {
|
||||||
with ($('#username').get(0)) {
|
with ($('input[name="username"]').get(0)) {
|
||||||
select();
|
select();
|
||||||
focus();
|
focus();
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (! $('#password').val()) {
|
if (! $('input[name="password"]').val()) {
|
||||||
with ($('#password').get(0)) {
|
with ($('input[name="password"]').get(0)) {
|
||||||
select();
|
select();
|
||||||
focus();
|
focus();
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,6 @@ $(function() {
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#username').focus();
|
$('input[name="username"]').focus();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,17 +1,8 @@
|
||||||
## -*- coding: utf-8 -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/base.mako" />
|
<%inherit file="/base.mako" />
|
||||||
|
|
||||||
<%def name="title()">Change Password</%def>
|
<%def name="title()">Change Password</%def>
|
||||||
|
|
||||||
<div class="form">
|
<div class="form">
|
||||||
${h.form(url('change_password'))}
|
${form.render_deform()|n}
|
||||||
${form.csrf_token()}
|
|
||||||
${form.referrer_field()}
|
|
||||||
${form.field_div('current_password', form.password('current_password'))}
|
|
||||||
${form.field_div('new_password', form.password('new_password'))}
|
|
||||||
${form.field_div('confirm_password', form.password('confirm_password'))}
|
|
||||||
<div class="buttons">
|
|
||||||
${h.submit('submit', "Change Password")}
|
|
||||||
</div>
|
|
||||||
${h.end_form()}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -76,6 +76,9 @@ ${h.csrf_token(request)}
|
||||||
## % if form.creating and form.allow_successive_creates:
|
## % if form.creating and form.allow_successive_creates:
|
||||||
## ${h.submit('create_and_continue', form.successive_create_label)}
|
## ${h.submit('create_and_continue', form.successive_create_label)}
|
||||||
## % endif
|
## % endif
|
||||||
|
% if getattr(form, 'show_reset', False):
|
||||||
|
<input type="reset" value="Reset" />
|
||||||
|
% endif
|
||||||
% if getattr(form, 'show_cancel', True):
|
% if getattr(form, 'show_cancel', True):
|
||||||
${h.link_to("Cancel", form.cancel_url, class_='cancel button{}'.format(' autodisable' if form.auto_disable_cancel else ''))}
|
${h.link_to("Cancel", form.cancel_url, class_='cancel button{}'.format(' autodisable' if form.auto_disable_cancel else ''))}
|
||||||
% endif
|
% endif
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
## -*- coding: utf-8 -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/base.mako" />
|
<%inherit file="/base.mako" />
|
||||||
|
|
||||||
<%def name="title()">Login</%def>
|
<%def name="title()">Login</%def>
|
||||||
|
@ -19,19 +19,7 @@
|
||||||
|
|
||||||
<%def name="login_form()">
|
<%def name="login_form()">
|
||||||
<div class="form">
|
<div class="form">
|
||||||
${form.begin(**{'data-ajax': 'false'})}
|
${form.render_deform(form_kwargs={'data-ajax': 'false'})|n}
|
||||||
${form.hidden('referrer', value=referrer)}
|
|
||||||
${form.csrf_token()}
|
|
||||||
|
|
||||||
${form.field_div('username', form.text('username'))}
|
|
||||||
${form.field_div('password', form.password('password'))}
|
|
||||||
|
|
||||||
<div class="buttons">
|
|
||||||
${form.submit('submit', "Login")}
|
|
||||||
<input type="reset" value="Reset" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
${form.end()}
|
|
||||||
</div>
|
</div>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2017 Lance Edgar
|
# Copyright © 2010-2018 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -28,47 +28,42 @@ from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
from rattail.db.auth import authenticate_user, set_user_password
|
from rattail.db.auth import authenticate_user, set_user_password
|
||||||
|
|
||||||
import formencode as fe
|
import colander
|
||||||
|
from deform import widget as dfwidget
|
||||||
from pyramid.httpexceptions import HTTPForbidden
|
from pyramid.httpexceptions import HTTPForbidden
|
||||||
from pyramid_simpleform import Form
|
|
||||||
from webhelpers2.html import tags, literal
|
from webhelpers2.html import tags, literal
|
||||||
|
|
||||||
from tailbone import forms
|
from tailbone import forms2 as forms
|
||||||
from tailbone.db import Session
|
from tailbone.db import Session
|
||||||
from tailbone.views import View
|
from tailbone.views import View
|
||||||
from tailbone.auth import login_user, logout_user
|
from tailbone.auth import login_user, logout_user
|
||||||
|
|
||||||
|
|
||||||
class UserLogin(fe.Schema):
|
class UserLogin(colander.MappingSchema):
|
||||||
allow_extra_fields = True
|
|
||||||
filter_extra_fields = True
|
username = colander.SchemaNode(colander.String())
|
||||||
username = fe.validators.NotEmpty()
|
|
||||||
password = fe.validators.NotEmpty()
|
password = colander.SchemaNode(colander.String(),
|
||||||
|
widget=dfwidget.PasswordWidget())
|
||||||
|
|
||||||
|
|
||||||
class CurrentPasswordCorrect(fe.validators.FancyValidator):
|
@colander.deferred
|
||||||
|
def current_password_correct(node, kw):
|
||||||
def _to_python(self, value, state):
|
user = kw['user']
|
||||||
user = state
|
def validate(node, value):
|
||||||
if not authenticate_user(Session, user.username, value):
|
if not authenticate_user(Session(), user.username, value):
|
||||||
raise fe.Invalid("The password is incorrect.", value, state)
|
raise colander.Invalid(node, "The password is incorrect")
|
||||||
return value
|
return validate
|
||||||
|
|
||||||
|
|
||||||
class ChangePassword(fe.Schema):
|
class ChangePassword(colander.MappingSchema):
|
||||||
|
|
||||||
allow_extra_fields = True
|
current_password = colander.SchemaNode(colander.String(),
|
||||||
filter_extra_fields = True
|
widget=dfwidget.PasswordWidget(),
|
||||||
|
validator=current_password_correct)
|
||||||
|
|
||||||
current_password = fe.All(
|
new_password = colander.SchemaNode(colander.String(),
|
||||||
fe.validators.NotEmpty(),
|
widget=dfwidget.CheckedPasswordWidget())
|
||||||
CurrentPasswordCorrect())
|
|
||||||
|
|
||||||
new_password = fe.validators.NotEmpty()
|
|
||||||
confirm_password = fe.validators.NotEmpty()
|
|
||||||
|
|
||||||
chained_validators = [fe.validators.FieldsMatch(
|
|
||||||
'new_password', 'confirm_password')]
|
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationView(View):
|
class AuthenticationView(View):
|
||||||
|
@ -103,10 +98,15 @@ class AuthenticationView(View):
|
||||||
self.request.session.flash("{} is already logged in".format(self.request.user), 'error')
|
self.request.session.flash("{} is already logged in".format(self.request.user), 'error')
|
||||||
return self.redirect(referrer)
|
return self.redirect(referrer)
|
||||||
|
|
||||||
form = forms.SimpleForm(self.request, UserLogin)
|
form = forms.Form(schema=UserLogin(), request=self.request)
|
||||||
if form.validate():
|
form.save_label = "Login"
|
||||||
user = self.authenticate_user(form.data['username'],
|
form.auto_disable_save = False
|
||||||
form.data['password'])
|
form.auto_disable = False # TODO: deprecate / remove this
|
||||||
|
form.show_reset = True
|
||||||
|
form.show_cancel = False
|
||||||
|
if form.validate(newstyle=True):
|
||||||
|
user = self.authenticate_user(form.validated['username'],
|
||||||
|
form.validated['password'])
|
||||||
if user:
|
if user:
|
||||||
# okay now they're truly logged in
|
# okay now they're truly logged in
|
||||||
headers = login_user(self.request, user)
|
headers = login_user(self.request, user)
|
||||||
|
@ -122,7 +122,7 @@ class AuthenticationView(View):
|
||||||
default=self.request.static_url('tailbone:static/img/home_logo.png'))
|
default=self.request.static_url('tailbone:static/img/home_logo.png'))
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'form': forms.FormRenderer(form),
|
'form': form,
|
||||||
'referrer': referrer,
|
'referrer': referrer,
|
||||||
'image_url': image_url,
|
'image_url': image_url,
|
||||||
'dialog': mobile,
|
'dialog': mobile,
|
||||||
|
@ -169,12 +169,14 @@ class AuthenticationView(View):
|
||||||
self.request.session.flash("Cannot change password for 'chuck' in demo mode", 'error')
|
self.request.session.flash("Cannot change password for 'chuck' in demo mode", 'error')
|
||||||
return self.redirect(self.request.get_referrer())
|
return self.redirect(self.request.get_referrer())
|
||||||
|
|
||||||
form = Form(self.request, schema=ChangePassword, state=self.request.user)
|
schema = ChangePassword().bind(user=self.request.user)
|
||||||
if form.validate():
|
form = forms.Form(schema=schema, request=self.request)
|
||||||
set_user_password(self.request.user, form.data['new_password'])
|
if form.validate(newstyle=True):
|
||||||
|
set_user_password(self.request.user, form.validated['new_password'])
|
||||||
|
self.request.session.flash("Your password has been changed.")
|
||||||
return self.redirect(self.request.get_referrer())
|
return self.redirect(self.request.get_referrer())
|
||||||
|
|
||||||
return {'form': forms.FormRenderer(form)}
|
return {'form': form}
|
||||||
|
|
||||||
def become_root(self):
|
def become_root(self):
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in a new issue