|
|
|
import deform
|
|
|
|
|
|
|
|
from pyramid.httpexceptions import HTTPFound
|
|
|
|
from pyramid.view import view_config
|
|
|
|
from sqlalchemy import func, or_
|
|
|
|
|
|
|
|
from ordr.models.account import User, TokenSubject
|
|
|
|
from ordr.events import PasswordResetNotification
|
|
|
|
|
|
|
|
# below this password length a warning is displayed
|
|
|
|
MIN_PW_LENGTH = 12
|
|
|
|
|
|
|
|
|
|
|
|
@view_config(
|
|
|
|
context='ordr.resources.account.PasswordResetResource',
|
|
|
|
permission='view',
|
|
|
|
request_method='GET',
|
|
|
|
renderer='ordr:templates/account/forgotten_password_form.jinja2'
|
|
|
|
)
|
|
|
|
def forgotten_password_form(context, request):
|
|
|
|
''' show forgotten password form '''
|
|
|
|
return {'formerror': False}
|
|
|
|
|
|
|
|
|
|
|
|
@view_config(
|
|
|
|
context='ordr.resources.account.PasswordResetResource',
|
|
|
|
permission='view',
|
|
|
|
request_method='POST',
|
|
|
|
renderer='ordr:templates/account/forgotten_password_form.jinja2'
|
|
|
|
)
|
|
|
|
def forgotten_password_form_processing(context, request):
|
|
|
|
''' process forgotten password form '''
|
|
|
|
if 'cancel' in request.POST:
|
|
|
|
return HTTPFound(request.resource_url(request.root))
|
|
|
|
identifier = request.POST.get('identifier', '')
|
|
|
|
account = (
|
|
|
|
request.dbsession
|
|
|
|
.query(User)
|
|
|
|
.filter(or_(
|
|
|
|
func.lower(User.username) == identifier.lower(),
|
|
|
|
func.lower(User.email) == identifier.lower()
|
|
|
|
))
|
|
|
|
.first()
|
|
|
|
)
|
|
|
|
if account is None or not account.is_active:
|
|
|
|
return {'formerror': True}
|
|
|
|
|
|
|
|
# create a verify-new-account token and send email
|
|
|
|
token = account.issue_token(request, TokenSubject.RESET_PASSWORD)
|
|
|
|
notification = PasswordResetNotification(
|
|
|
|
request,
|
|
|
|
account,
|
|
|
|
{'token': token}
|
|
|
|
)
|
|
|
|
request.registry.notify(notification)
|
|
|
|
|
|
|
|
return HTTPFound(request.resource_url(context, 'verify'))
|
|
|
|
|
|
|
|
|
|
|
|
@view_config(
|
|
|
|
context='ordr.resources.account.PasswordResetResource',
|
|
|
|
name='verify',
|
|
|
|
permission='view',
|
|
|
|
request_method='GET',
|
|
|
|
renderer='ordr:templates/account/forgotten_password_verify.jinja2'
|
|
|
|
)
|
|
|
|
def verify(context, request):
|
|
|
|
''' show email verification text '''
|
|
|
|
return {}
|
|
|
|
|
|
|
|
|
|
|
|
@view_config(
|
|
|
|
context='ordr.resources.account.PasswordResetResource',
|
|
|
|
name='completed',
|
|
|
|
permission='view',
|
|
|
|
request_method='GET',
|
|
|
|
renderer='ordr:templates/account/forgotten_password_completed.jinja2'
|
|
|
|
)
|
|
|
|
def completed(context, request):
|
|
|
|
''' user is verified, process reset password form '''
|
|
|
|
return {}
|
|
|
|
|
|
|
|
|
|
|
|
@view_config(
|
|
|
|
context='ordr.resources.account.PasswordResetTokenResource',
|
|
|
|
permission='view',
|
|
|
|
request_method='GET',
|
|
|
|
renderer='ordr:templates/account/forgotten_password_reset.jinja2'
|
|
|
|
)
|
|
|
|
def reset_password_form(context, request):
|
|
|
|
''' user is verified, show reset password form '''
|
|
|
|
form = context.get_reset_form()
|
|
|
|
return {'form': form}
|
|
|
|
|
|
|
|
|
|
|
|
@view_config(
|
|
|
|
context='ordr.resources.account.PasswordResetTokenResource',
|
|
|
|
permission='view',
|
|
|
|
request_method='POST',
|
|
|
|
renderer='ordr:templates/account/forgotten_password_reset.jinja2'
|
|
|
|
)
|
|
|
|
def reset_password_form_processing(context, request):
|
|
|
|
''' process the password reset form '''
|
|
|
|
if 'change' not in request.POST:
|
|
|
|
return HTTPFound(request.resource_url(request.root))
|
|
|
|
|
|
|
|
form = context.get_reset_form()
|
|
|
|
data = request.POST.items()
|
|
|
|
try:
|
|
|
|
appstruct = form.validate(data)
|
|
|
|
except deform.ValidationFailure as e:
|
|
|
|
return {'form': form}
|
|
|
|
|
|
|
|
# set new password
|
|
|
|
token = context.model
|
|
|
|
account = token.owner
|
|
|
|
account.set_password(appstruct['password'])
|
|
|
|
request.dbsession.delete(token)
|
|
|
|
|
|
|
|
return HTTPFound(request.resource_url(context.__parent__, 'completed'))
|