@ -1,21 +1,279 @@
@@ -1,21 +1,279 @@
''' views for user accounts
This includes login , logout , registration , forgotten passwords , changing
settings and passwords
'''
import deform
from pyramid . httpexceptions import HTTPFound
from pyramid . security import remember , forget
from pyramid . view import view_config
from sqlalchemy import func , or_
from ordr . events import (
ChangeEmailNotification ,
PasswordResetNotification ,
RegistrationNotification
)
from ordr . models . account import Role , TokenSubject , User
from ordr . events import ChangeEmailNotification
from ordr . models . account import TokenSubject
# account resource root
@view_config (
context = ' ordr.resources.account.AccountResource ' ,
permission = ' edit '
permission = ' view '
)
def account ( context , request ) :
''' redirect if ' /account ' was requested directly '''
return HTTPFound ( request . resource_url ( request . root ) )
# login and logout
@view_config (
context = ' ordr.resources.account.AccountResource ' ,
name = ' login ' ,
request_method = ' GET ' ,
permission = ' login ' ,
renderer = ' ordr:templates/account/login.jinja2 ' ,
)
def login ( context , request ) :
''' shows the login page '''
context . nav_active = ' welcome '
return { ' loginerror ' : False }
@view_config (
context = ' ordr.resources.account.AccountResource ' ,
name = ' login ' ,
request_method = ' POST ' ,
permission = ' login ' ,
renderer = ' ordr:templates/account/login.jinja2 ' ,
)
def check_login ( context , request ) :
''' check user credentials '''
username = request . POST . get ( ' username ' )
password = request . POST . get ( ' password ' )
user = (
request . dbsession
. query ( User )
. filter_by ( username = username )
. first ( )
)
if user and user . is_active and user . check_password ( password ) :
headers = remember ( request , user . id )
return HTTPFound ( request . resource_url ( request . root ) , headers = headers )
context . nav_active = ' welcome '
return { ' loginerror ' : True }
@view_config (
context = ' ordr.resources.account.AccountResource ' ,
name = ' logout ' ,
permission = ' logout '
)
def logout ( context , request ) :
''' log out of an user '''
headers = forget ( request )
return HTTPFound ( request . resource_url ( request . root ) , headers = headers )
# registration process
@view_config (
context = ' ordr.resources.account.RegistrationResource ' ,
permission = ' register ' ,
request_method = ' GET ' ,
renderer = ' ordr:templates/account/registration_form.jinja2 '
)
def registration_form ( context , request ) :
''' show registration form '''
form = context . get_registration_form ( )
return { ' form ' : form }
@view_config (
context = ' ordr.resources.account.RegistrationResource ' ,
permission = ' register ' ,
request_method = ' POST ' ,
renderer = ' ordr:templates/account/registration_form.jinja2 '
)
def registration_form_processing ( context , request ) :
''' process registration form '''
if ' create ' not in request . POST :
return HTTPFound ( request . resource_url ( request . root ) )
form = context . get_registration_form ( )
data = request . POST . items ( )
try :
appstruct = form . validate ( data )
except deform . ValidationFailure as e :
return { ' form ' : form }
# form validation successfull, create user
account = User (
username = appstruct [ ' username ' ] ,
first_name = appstruct [ ' first_name ' ] ,
last_name = appstruct [ ' last_name ' ] ,
email = appstruct [ ' email ' ] ,
role = Role . UNVALIDATED
)
account . set_password ( appstruct [ ' password ' ] )
request . dbsession . add ( account )
# create a verify-new-account token and send email
token = account . issue_token ( request , TokenSubject . REGISTRATION )
notification = RegistrationNotification ( request , account , { ' token ' : token } )
request . registry . notify ( notification )
return HTTPFound ( request . resource_url ( context , ' verify ' ) )
@view_config (
context = ' ordr.resources.account.RegistrationResource ' ,
name = ' verify ' ,
permission = ' register ' ,
request_method = ' GET ' ,
renderer = ' ordr:templates/account/registration_verify.jinja2 '
)
def registration_verify_email ( context , request ) :
''' show email verification text '''
return { }
@view_config (
context = ' ordr.resources.account.RegistrationTokenResource ' ,
permission = ' register ' ,
request_method = ' GET ' ,
renderer = ' ordr:templates/account/registration_completed.jinja2 '
)
def registration_completed ( context , request ) :
''' registration is completed, awaiting activation by admin '''
token = context . model
account = token . owner
account . role = Role . NEW
request . dbsession . delete ( token )
return { }
# forgotten password process
@view_config (
context = ' ordr.resources.account.PasswordResetResource ' ,
permission = ' reset ' ,
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 = ' reset ' ,
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 = ' reset ' ,
request_method = ' GET ' ,
renderer = ' ordr:templates/account/forgotten_password_verify.jinja2 '
)
def forgotten_password_verify_email ( context , request ) :
''' show email verification text '''
return { }
@view_config (
context = ' ordr.resources.account.PasswordResetResource ' ,
name = ' completed ' ,
permission = ' reset ' ,
request_method = ' GET ' ,
renderer = ' ordr:templates/account/forgotten_password_completed.jinja2 '
)
def forgotten_password_completed ( context , request ) :
''' user is verified, process reset password form '''
return { }
@view_config (
context = ' ordr.resources.account.PasswordResetTokenResource ' ,
permission = ' reset ' ,
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 = ' reset ' ,
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 ' ) )
# account settings
@view_config (
context = ' ordr.resources.account.AccountResource ' ,
permission = ' edit ' ,
@ -85,7 +343,7 @@ def settings_form_processing(context, request):
@@ -85,7 +343,7 @@ def settings_form_processing(context, request):
request_method = ' GET ' ,
renderer = ' ordr:templates/account/settings_mail_changed.jinja2 '
)
def verify_email ( context , request ) :
def verify_email_change ( context , request ) :
''' show email verification text '''
payload = context . model . payload
request . user . email = payload [ ' email ' ]
@ -93,6 +351,8 @@ def verify_email(context, request):
@@ -93,6 +351,8 @@ def verify_email(context, request):
return { }
# change password
@view_config (
context = ' ordr.resources.account.AccountResource ' ,
permission = ' edit ' ,