Browse Source

passwort reset links are working

php2python
Holger Frey 7 years ago
parent
commit
30df8627db
  1. 2
      ordr2/resources/__init__.py
  2. 38
      ordr2/resources/account.py
  3. 27
      ordr2/schemas/account.py
  4. 24
      ordr2/templates/account/password_reset.jinja2
  5. 55
      ordr2/views/account.py

2
ordr2/resources/__init__.py

@ -1,6 +1,6 @@
from pyramid.security import Allow, Everyone from pyramid.security import Allow, Everyone
from .account import Account from .account import Account, PasswordResetAccount
from .admin import Admin, UserList, UserAccount from .admin import Admin, UserList, UserAccount
from .base import BaseResource from .base import BaseResource

38
ordr2/resources/account.py

@ -1,10 +1,44 @@
from pyramid.security import Allow, Authenticated, Deny, Everyone from pyramid.security import Allow, Authenticated, Deny, DENY_ALL, Everyone
from ordr2.models import User
from .base import BaseResource from .base import BaseResource
class PasswordResetAccount(BaseResource):
def __acl__(self):
return [
(Allow, Everyone, 'reset'),
DENY_ALL
]
class PasswordReset(BaseResource):
def __acl__(self):
return [
(Allow, Everyone, 'reset'),
DENY_ALL
]
def __getitem__(self, key):
key = key.strip()
if key:
account = self.request.dbsession.\
query(User).\
filter_by(password_reset=key).\
first()
if account:
return PasswordResetAccount(key, self, account)
raise KeyError
class Account(BaseResource): class Account(BaseResource):
nodes = {'reset': PasswordReset}
def __init__(self, name, parent): def __init__(self, name, parent):
super().__init__(name, parent) super().__init__(name, parent)
self.model = self.request.user self.model = self.request.user
@ -17,4 +51,6 @@ class Account(BaseResource):
(Deny, Authenticated, 'register'), (Deny, Authenticated, 'register'),
(Allow, Everyone, 'register'), (Allow, Everyone, 'register'),
(Allow, Authenticated, 'settings'), (Allow, Authenticated, 'settings'),
(Allow, Everyone, 'reset'),
DENY_ALL
] ]

27
ordr2/schemas/account.py

@ -105,15 +105,6 @@ class ChangePasswordSchema(CSRFSchema):
missing='' missing=''
) )
@classmethod
def as_form(cls, request, **override):
settings = {
'buttons': ('Change Password', 'Cancel'),
'css_class': 'form-horizontal'
}
settings.update(override)
return super().as_form(request, **settings)
class ConfirmSettingsSchema(CSRFSchema): class ConfirmSettingsSchema(CSRFSchema):
''' confirm changes with current password ''' ''' confirm changes with current password '''
@ -148,3 +139,21 @@ class SettingsSchema(CSRFSchema):
template='textinput_disabled.pt' template='textinput_disabled.pt'
) )
return form return form
class ResetPasswordSchema(CSRFSchema):
''' reset password of an account '''
new_password = colander.SchemaNode(
colander.String(),
widget=deform.widget.CheckedPasswordWidget()
)
@classmethod
def as_form(cls, request, **override):
settings = {
'buttons': ('Change Password', 'Cancel'),
'css_class': 'form-horizontal'
}
settings.update(override)
return super().as_form(request, **settings)

24
ordr2/templates/account/password_reset.jinja2

@ -0,0 +1,24 @@
{% extends "ordr2:templates/layout.jinja2" %}
{% import 'ordr2:templates/macros.jinja2' as macros with context %}
{% block subtitle %} Account | Reset Password {% endblock subtitle %}
{% block content %}
<div class="content controls">
<div class="container-fluid">
<div class="row-fluid">
<div class="page-controls">
<h1>Reset your Password</h1>
</div>
</div>
<div class="row">
<div class="span8">
{{ macros.flash_messages() }}
{{form.render()|safe}}
</div>
</div>
</div>
</div>
{% endblock content %}

55
ordr2/views/account.py

@ -7,7 +7,11 @@ from pyramid.view import view_config
from ordr2.events import UserLogIn from ordr2.events import UserLogIn
from ordr2.models import User, Role from ordr2.models import User, Role
from ordr2.schemas.account import RegistrationSchema, SettingsSchema from ordr2.schemas.account import (
ResetPasswordSchema,
RegistrationSchema,
SettingsSchema
)
# user log in and log out # user log in and log out
@ -185,6 +189,9 @@ def settings_form(context, request):
def settings_form_processing(context, request): def settings_form_processing(context, request):
''' display the user settings form ''' ''' display the user settings form '''
if 'Cancel' in request.POST:
return HTTPFound(request.resource_url(request.root))
form = SettingsSchema.as_form(request) form = SettingsSchema.as_form(request)
data = request.POST.items() data = request.POST.items()
try: try:
@ -207,3 +214,49 @@ def settings_form_processing(context, request):
request.flash('success', 'Your account information has been updated.') request.flash('success', 'Your account information has been updated.')
return {'form': form} return {'form': form}
# passwort reset links
@view_config(
context='ordr2:resources.PasswordResetAccount',
permission='reset',
request_method='GET',
renderer='ordr2:templates/account/password_reset.jinja2'
)
def reset_password_form(context, request):
''' display the password reset form '''
form = ResetPasswordSchema.as_form(request)
return {'form': form}
@view_config(
context='ordr2:resources.PasswordResetAccount',
permission='reset',
request_method='POST',
renderer='ordr2:templates/account/password_reset.jinja2'
)
def reset_password_form_processing(context, request):
''' process the password reset form '''
if 'Cancel' in request.POST:
return HTTPFound(request.resource_url(request.root))
form = ResetPasswordSchema.as_form(request)
data = request.POST.items()
try:
appstruct = form.validate(data)
except deform.ValidationFailure as e:
return {'form': form}
context.model.set_password(appstruct['new_password'])
context.model.password_reset = ''
request.flash(
'success',
'Password reset successful',
'Please Log In with your new password',
)
return HTTPFound(request.resource_url(request.root, 'account', 'login'))