diff --git a/ordr2/resources/__init__.py b/ordr2/resources/__init__.py index 00bf576..8a3fd06 100644 --- a/ordr2/resources/__init__.py +++ b/ordr2/resources/__init__.py @@ -1,6 +1,6 @@ from pyramid.security import Allow, Everyone -from .account import Account +from .account import Account, PasswordResetAccount from .admin import Admin, UserList, UserAccount from .base import BaseResource diff --git a/ordr2/resources/account.py b/ordr2/resources/account.py index ced05c0..718d6e4 100644 --- a/ordr2/resources/account.py +++ b/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 + +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): + nodes = {'reset': PasswordReset} + def __init__(self, name, parent): super().__init__(name, parent) self.model = self.request.user @@ -17,4 +51,6 @@ class Account(BaseResource): (Deny, Authenticated, 'register'), (Allow, Everyone, 'register'), (Allow, Authenticated, 'settings'), + (Allow, Everyone, 'reset'), + DENY_ALL ] diff --git a/ordr2/schemas/account.py b/ordr2/schemas/account.py index 0f06534..818552a 100644 --- a/ordr2/schemas/account.py +++ b/ordr2/schemas/account.py @@ -105,15 +105,6 @@ class ChangePasswordSchema(CSRFSchema): 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): ''' confirm changes with current password ''' @@ -148,3 +139,21 @@ class SettingsSchema(CSRFSchema): template='textinput_disabled.pt' ) 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) diff --git a/ordr2/templates/account/password_reset.jinja2 b/ordr2/templates/account/password_reset.jinja2 new file mode 100644 index 0000000..694874d --- /dev/null +++ b/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 %} +