Browse Source

registration process working

master
Holger Frey 7 years ago
parent
commit
8d4df465c2
  1. 39
      mail/20171023104036_7z0s.eml
  2. 39
      mail/20171023104054_c95d.eml
  3. 39
      mail/20171023104107_zi5j.eml
  4. 39
      mail/20171023104203_jphu.eml
  5. 39
      mail/20171023104247_zj8w.eml
  6. 39
      mail/20171023104351_istb.eml
  7. 39
      mail/20171023104501_9pm0.eml
  8. 8
      ordr2/events.py
  9. 1
      ordr2/schemas/__init__.py
  10. 3
      ordr2/schemas/account.py
  11. 1
      ordr2/schemas/helpers.py
  12. 17
      ordr2/templates/account/registration_completed.jinja2
  13. 16
      ordr2/templates/account/registration_confirmation.jinja2
  14. 23
      ordr2/views/account.py
  15. 14
      tests/_functional/__init__.py
  16. 28
      tests/_functional/registration.py
  17. 36
      tests/views/account.py

39
mail/20171023104036_7z0s.eml

@ -0,0 +1,39 @@
Content-Type: text/html; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
From: ordr@example.com
Subject: [ordr] Please verify your email address
To: amy@example.com
Content-Disposition: inline
<!DOCTYPE=20html>
<html>
<head>
=09<meta=20http-equiv=3D"Content-Type"=20content=3D"text/html;=20charset=3D=
utf-8">
=20=20=09<title>[ordr]=20verify=20your=20email=20address</title>
=20=20=09<link=20href=3D'http://fonts.googleapis.com/css?family=3DAnton&sub=
set=3Dlatin,latin-ext'=20rel=3D'stylesheet'=20type=3D'text/css'>
</head>
<body>
=20=20=09<h1>Hi=20there!</h1>
=20=20=09<p>
=20=20=09=09Please=20verify=20your=20email=20address=20for=20the=20account=
=20""=20by=20following=20this=20link
=20=20=09=09<a=20href=3D"http://localhost/account/68297eb302224e77b3dfe7264=
c328ed2">http://localhost/account/68297eb302224e77b3dfe7264c328ed2</a>
=09</p>
=09<p=20class=3D"signature">
=09=09Regards,
=09=09<br/>
=09=09<span=20class=3D"brand">ordr</span>
=09</p>
=09<p=20class=3D"footprint">
=09=09<small>Please=20don't=20respont=20to=20this=20email!=20This=20is=20an=
=20automatically=20generated=20notification=20by=20the=20system.</small>
=09=09<a=20href=3D"http://distractedbysquirrels.com/"=20target=3D"_blank"=
=20title=3D"This=20software=20was=20originally=20written=20by=20Sebastian=
=20Sebald."=20class=3D"icon-dbs"></a>
=09</p>
</body>
</html>

39
mail/20171023104054_c95d.eml

@ -0,0 +1,39 @@
Content-Type: text/html; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
From: ordr@example.com
Subject: [ordr] Please verify your email address
To: amy@example.com
Content-Disposition: inline
<!DOCTYPE=20html>
<html>
<head>
=09<meta=20http-equiv=3D"Content-Type"=20content=3D"text/html;=20charset=3D=
utf-8">
=20=20=09<title>[ordr]=20verify=20your=20email=20address</title>
=20=20=09<link=20href=3D'http://fonts.googleapis.com/css?family=3DAnton&sub=
set=3Dlatin,latin-ext'=20rel=3D'stylesheet'=20type=3D'text/css'>
</head>
<body>
=20=20=09<h1>Hi=20there!</h1>
=20=20=09<p>
=20=20=09=09Please=20verify=20your=20email=20address=20for=20the=20account=
=20""=20by=20following=20this=20link
=20=20=09=09<a=20href=3D"http://localhost/account/7f9ec1dedca1402cbf9d38ee3=
709efdd">http://localhost/account/7f9ec1dedca1402cbf9d38ee3709efdd</a>
=09</p>
=09<p=20class=3D"signature">
=09=09Regards,
=09=09<br/>
=09=09<span=20class=3D"brand">ordr</span>
=09</p>
=09<p=20class=3D"footprint">
=09=09<small>Please=20don't=20respont=20to=20this=20email!=20This=20is=20an=
=20automatically=20generated=20notification=20by=20the=20system.</small>
=09=09<a=20href=3D"http://distractedbysquirrels.com/"=20target=3D"_blank"=
=20title=3D"This=20software=20was=20originally=20written=20by=20Sebastian=
=20Sebald."=20class=3D"icon-dbs"></a>
=09</p>
</body>
</html>

39
mail/20171023104107_zi5j.eml

@ -0,0 +1,39 @@
Content-Type: text/html; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
From: ordr@example.com
Subject: [ordr] Please verify your email address
To: amy@example.com
Content-Disposition: inline
<!DOCTYPE=20html>
<html>
<head>
=09<meta=20http-equiv=3D"Content-Type"=20content=3D"text/html;=20charset=3D=
utf-8">
=20=20=09<title>[ordr]=20verify=20your=20email=20address</title>
=20=20=09<link=20href=3D'http://fonts.googleapis.com/css?family=3DAnton&sub=
set=3Dlatin,latin-ext'=20rel=3D'stylesheet'=20type=3D'text/css'>
</head>
<body>
=20=20=09<h1>Hi=20there!</h1>
=20=20=09<p>
=20=20=09=09Please=20verify=20your=20email=20address=20for=20the=20account=
=20""=20by=20following=20this=20link
=20=20=09=09<a=20href=3D"http://localhost/account/a7967f6249a545afbd5903ff1=
eb07381">http://localhost/account/a7967f6249a545afbd5903ff1eb07381</a>
=09</p>
=09<p=20class=3D"signature">
=09=09Regards,
=09=09<br/>
=09=09<span=20class=3D"brand">ordr</span>
=09</p>
=09<p=20class=3D"footprint">
=09=09<small>Please=20don't=20respont=20to=20this=20email!=20This=20is=20an=
=20automatically=20generated=20notification=20by=20the=20system.</small>
=09=09<a=20href=3D"http://distractedbysquirrels.com/"=20target=3D"_blank"=
=20title=3D"This=20software=20was=20originally=20written=20by=20Sebastian=
=20Sebald."=20class=3D"icon-dbs"></a>
=09</p>
</body>
</html>

39
mail/20171023104203_jphu.eml

@ -0,0 +1,39 @@
Content-Type: text/html; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
From: ordr@example.com
Subject: [ordr] Please verify your email address
To: amy@example.com
Content-Disposition: inline
<!DOCTYPE=20html>
<html>
<head>
=09<meta=20http-equiv=3D"Content-Type"=20content=3D"text/html;=20charset=3D=
utf-8">
=20=20=09<title>[ordr]=20verify=20your=20email=20address</title>
=20=20=09<link=20href=3D'http://fonts.googleapis.com/css?family=3DAnton&sub=
set=3Dlatin,latin-ext'=20rel=3D'stylesheet'=20type=3D'text/css'>
</head>
<body>
=20=20=09<h1>Hi=20there!</h1>
=20=20=09<p>
=20=20=09=09Please=20verify=20your=20email=20address=20for=20the=20account=
=20""=20by=20following=20this=20link
=20=20=09=09<a=20href=3D"http://localhost/account/b2c98fbf355147ac96ffa6eac=
9ca9079">http://localhost/account/b2c98fbf355147ac96ffa6eac9ca9079</a>
=09</p>
=09<p=20class=3D"signature">
=09=09Regards,
=09=09<br/>
=09=09<span=20class=3D"brand">ordr</span>
=09</p>
=09<p=20class=3D"footprint">
=09=09<small>Please=20don't=20respont=20to=20this=20email!=20This=20is=20an=
=20automatically=20generated=20notification=20by=20the=20system.</small>
=09=09<a=20href=3D"http://distractedbysquirrels.com/"=20target=3D"_blank"=
=20title=3D"This=20software=20was=20originally=20written=20by=20Sebastian=
=20Sebald."=20class=3D"icon-dbs"></a>
=09</p>
</body>
</html>

39
mail/20171023104247_zj8w.eml

@ -0,0 +1,39 @@
Content-Type: text/html; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
From: ordr@example.com
Subject: [ordr] Please verify your email address
To: amy@example.com
Content-Disposition: inline
<!DOCTYPE=20html>
<html>
<head>
=09<meta=20http-equiv=3D"Content-Type"=20content=3D"text/html;=20charset=3D=
utf-8">
=20=20=09<title>[ordr]=20verify=20your=20email=20address</title>
=20=20=09<link=20href=3D'http://fonts.googleapis.com/css?family=3DAnton&sub=
set=3Dlatin,latin-ext'=20rel=3D'stylesheet'=20type=3D'text/css'>
</head>
<body>
=20=20=09<h1>Hi=20there!</h1>
=20=20=09<p>
=20=20=09=09Please=20verify=20your=20email=20address=20for=20the=20account=
=20""=20by=20following=20this=20link
=20=20=09=09<a=20href=3D"http://localhost/account/c730af7ecfde42899c1d6c5f5=
e488d62">http://localhost/account/c730af7ecfde42899c1d6c5f5e488d62</a>
=09</p>
=09<p=20class=3D"signature">
=09=09Regards,
=09=09<br/>
=09=09<span=20class=3D"brand">ordr</span>
=09</p>
=09<p=20class=3D"footprint">
=09=09<small>Please=20don't=20respont=20to=20this=20email!=20This=20is=20an=
=20automatically=20generated=20notification=20by=20the=20system.</small>
=09=09<a=20href=3D"http://distractedbysquirrels.com/"=20target=3D"_blank"=
=20title=3D"This=20software=20was=20originally=20written=20by=20Sebastian=
=20Sebald."=20class=3D"icon-dbs"></a>
=09</p>
</body>
</html>

39
mail/20171023104351_istb.eml

@ -0,0 +1,39 @@
Content-Type: text/html; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
From: ordr@example.com
Subject: [ordr] Please verify your email address
To: amy@example.com
Content-Disposition: inline
<!DOCTYPE=20html>
<html>
<head>
=09<meta=20http-equiv=3D"Content-Type"=20content=3D"text/html;=20charset=3D=
utf-8">
=20=20=09<title>[ordr]=20verify=20your=20email=20address</title>
=20=20=09<link=20href=3D'http://fonts.googleapis.com/css?family=3DAnton&sub=
set=3Dlatin,latin-ext'=20rel=3D'stylesheet'=20type=3D'text/css'>
</head>
<body>
=20=20=09<h1>Hi=20there!</h1>
=20=20=09<p>
=20=20=09=09Please=20verify=20your=20email=20address=20for=20the=20account=
=20""=20by=20following=20this=20link
=20=20=09=09<a=20href=3D"http://localhost/account/010d7d85a9fa415ca88d0a0bf=
ce3fe8e">http://localhost/account/010d7d85a9fa415ca88d0a0bfce3fe8e</a>
=09</p>
=09<p=20class=3D"signature">
=09=09Regards,
=09=09<br/>
=09=09<span=20class=3D"brand">ordr</span>
=09</p>
=09<p=20class=3D"footprint">
=09=09<small>Please=20don't=20respont=20to=20this=20email!=20This=20is=20an=
=20automatically=20generated=20notification=20by=20the=20system.</small>
=09=09<a=20href=3D"http://distractedbysquirrels.com/"=20target=3D"_blank"=
=20title=3D"This=20software=20was=20originally=20written=20by=20Sebastian=
=20Sebald."=20class=3D"icon-dbs"></a>
=09</p>
</body>
</html>

39
mail/20171023104501_9pm0.eml

@ -0,0 +1,39 @@
Content-Type: text/html; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
From: ordr@example.com
Subject: [ordr] Please verify your email address
To: amy@example.com
Content-Disposition: inline
<!DOCTYPE=20html>
<html>
<head>
=09<meta=20http-equiv=3D"Content-Type"=20content=3D"text/html;=20charset=3D=
utf-8">
=20=20=09<title>[ordr]=20verify=20your=20email=20address</title>
=20=20=09<link=20href=3D'http://fonts.googleapis.com/css?family=3DAnton&sub=
set=3Dlatin,latin-ext'=20rel=3D'stylesheet'=20type=3D'text/css'>
</head>
<body>
=20=20=09<h1>Hi=20there!</h1>
=20=20=09<p>
=20=20=09=09Please=20verify=20your=20email=20address=20for=20the=20account=
=20""=20by=20following=20this=20link
=20=20=09=09<a=20href=3D"http://localhost/account/b1e2b70fad024881ab5f5d421=
eea371a">http://localhost/account/b1e2b70fad024881ab5f5d421eea371a</a>
=09</p>
=09<p=20class=3D"signature">
=09=09Regards,
=09=09<br/>
=09=09<span=20class=3D"brand">ordr</span>
=09</p>
=09<p=20class=3D"footprint">
=09=09<small>Please=20don't=20respont=20to=20this=20email!=20This=20is=20an=
=20automatically=20generated=20notification=20by=20the=20system.</small>
=09=09<a=20href=3D"http://distractedbysquirrels.com/"=20target=3D"_blank"=
=20title=3D"This=20software=20was=20originally=20written=20by=20Sebastian=
=20Sebald."=20class=3D"icon-dbs"></a>
=09</p>
</body>
</html>

8
ordr2/events.py

@ -37,25 +37,25 @@ class UserNotification(object):
class CompleteRegistration(UserNotification): class CompleteRegistration(UserNotification):
''' user notification for account activation ''' ''' user notification for account activation '''
subject='[ordr] Please verify your email address' subject = '[ordr] Please verify your email address'
template = 'ordr2:templates/emails/registration.jinja2' template = 'ordr2:templates/emails/registration.jinja2'
class AccountActivation(UserNotification): class AccountActivation(UserNotification):
''' user notification for account activation ''' ''' user notification for account activation '''
subject='[ordr] Your account was activated' subject = '[ordr] Your account was activated'
template = 'ordr2:templates/emails/activation.jinja2' template = 'ordr2:templates/emails/activation.jinja2'
class PasswordReset(UserNotification): class PasswordReset(UserNotification):
''' user notification for password reset link ''' ''' user notification for password reset link '''
subject='[ordr] Password Reset' subject = '[ordr] Password Reset'
template = 'ordr2:templates/emails/password_reset.jinja2' template = 'ordr2:templates/emails/password_reset.jinja2'
class OrderStatusChange(UserNotification): class OrderStatusChange(UserNotification):
''' user notification for order status change ''' ''' user notification for order status change '''
subject='[ordr] Order Status Change' subject = '[ordr] Order Status Change'
template = 'ordr2:templates/emails/order.jinja2' template = 'ordr2:templates/emails/order.jinja2'

1
ordr2/schemas/__init__.py

@ -10,6 +10,7 @@ from .helpers import (
deferred_csrf_validator deferred_csrf_validator
) )
# Base Schema # Base Schema
class CSRFSchema(colander.Schema): class CSRFSchema(colander.Schema):

3
ordr2/schemas/account.py

@ -22,7 +22,7 @@ class RegistrationSchema(CSRFSchema):
readonly=True readonly=True
), ),
description='automagically generated for you', description='automagically generated for you',
validator = deferred_unique_username_validator, validator=deferred_unique_username_validator,
) )
first_name = colander.SchemaNode( first_name = colander.SchemaNode(
colander.String() colander.String()
@ -47,4 +47,3 @@ class RegistrationSchema(CSRFSchema):
} }
settings.update(override) settings.update(override)
return super().as_form(request, **settings) return super().as_form(request, **settings)

1
ordr2/schemas/helpers.py

@ -1,7 +1,6 @@
''' helper functions for schemas ''' ''' helper functions for schemas '''
import colander import colander
import deform
from pyramid.csrf import get_csrf_token, check_csrf_token from pyramid.csrf import get_csrf_token, check_csrf_token

17
ordr2/templates/account/registration_completed.jinja2

@ -0,0 +1,17 @@
{% extends "ordr2:templates/layout.jinja2" %}
{% block title %} Ordr | Account Registration {% endblock title %}
{% block content %}
<div class="row">
<div class="col-2"></div>
<div class="col-5">
<h1>Account Registration Completed</h1>
<p>Thank you for verifying your email address.</p>
<p>Before you can start ordering, an administrator must activate your account</p>
<p>You'll receive an email when your account is activated</p>
</div>
</div>
{% endblock content %}

16
ordr2/templates/account/registration_confirmation.jinja2

@ -0,0 +1,16 @@
{% extends "ordr2:templates/layout.jinja2" %}
{% block title %} Ordr | Account Registration {% endblock title %}
{% block content %}
<div class="row">
<div class="col-2"></div>
<div class="col-5">
<h1>Verify Your Email Address</h1>
<p>To complete the registration process an email has been sent to you.</p>
<p>Please follow the link in the email to verify your address and complete the registration process</p>
</div>
</div>
{% endblock content %}

23
ordr2/views/account.py

@ -60,7 +60,7 @@ def logout(context, request):
def registration_form(context, request): def registration_form(context, request):
''' the new user registraion page ''' ''' the new user registraion page '''
form = RegistrationSchema.as_form(request) form = RegistrationSchema.as_form(request)
return {'form':form} return {'form': form}
@view_config( @view_config(
@ -107,3 +107,24 @@ def registration_form_processing(context, request):
) )
return HTTPFound(request.resource_url(context, 'registered')) return HTTPFound(request.resource_url(context, 'registered'))
@view_config(
context='ordr2:resources.account.AccountResource',
name='registered',
permission='register',
renderer='ordr2:templates/account/registration_confirmation.jinja2'
)
def registration_confirmation(context, request):
return {}
@view_config(
context='ordr2:resources.account.RegistrationToken',
permission='register',
renderer='ordr2:templates/account/registration_completed.jinja2'
)
def registration_completed(context, request):
context.model.owner.role = Role.NEW
request.dbsession.delete(context.model)
return {}

14
tests/_functional/__init__.py

@ -2,14 +2,26 @@
import os.path import os.path
import pytest import pytest
import re
import transaction import transaction
import webtest import webtest
from bs4 import BeautifulSoup
from .. import APP_SETTINGS, create_users, get_user from .. import APP_SETTINGS, create_users, get_user
WEBTEST_SETTINGS = APP_SETTINGS.copy() WEBTEST_SETTINGS = APP_SETTINGS.copy()
# WEBTEST_SETTINGS.update({ }) WEBTEST_SETTINGS['pyramid.includes'].append('pyramid_mailer.testing')
def get_token_url(email):
''' extracts an account token url from an email '''
soup = BeautifulSoup(email.html, 'html.parser')
for link in soup.find_all('a'):
if re.search('/account/[a-f0-9]{32}', link['href']):
return link['href']
class CustomTestApp(webtest.TestApp): class CustomTestApp(webtest.TestApp):

28
tests/_functional/registration.py

@ -2,7 +2,9 @@
import pytest import pytest
from . import testapp from pyramid_mailer import get_mailer
from . import testapp, get_token_url
from .. import get_user from .. import get_user
@ -39,25 +41,29 @@ def test_account_registeration_flow(testapp):
''' test the complete registration process ''' ''' test the complete registration process '''
# submit the registration form # submit the registration form
form = resonse.forms[1] response = testapp.get('/account/register')
form = response.forms[1]
form['username'] = 'AmyMcDonald' form['username'] = 'AmyMcDonald'
form['first_name'] = 'Amy' form['first_name'] = 'Amy'
form['last_name'] = 'McDonald' form['last_name'] = 'McDonald'
form['email'] = 'amy@example.com' form['email'] = 'amy@example.com'
form['password'] = 'Amy' form['password'] = 'Amy'
form['password_confirm'] = 'Amy' form['password-confirm'] = 'Amy'
response = form.submitt() response = form.submit()
assert response.location == '/account/verify' assert response.location == 'http://localhost/account/registered'
response = response.follow() response = response.follow()
assert 'email sent' in response assert 'Verify Your Email Address' in response
assert 'consider a longer password' in response
# click the email verification token # click the email verification token
email = '' mailer = get_mailer(testapp.app.registry)
token = email email = mailer.outbox[-1]
response = testapp.get('/account/' + token) assert email.subject == '[ordr] Please verify your email address'
assert 'consider a longer password' in response token_link = get_token_url(email)
assert 'activated by an administrator' in response
response = testapp.get(token_link)
assert 'Account Registration Completed' in response
# logging in should not work # logging in should not work
form = response.forms[0] form = response.forms[0]

36
tests/views/account.py

@ -139,10 +139,8 @@ def test_registration_form_processing_ok(dbsession):
assert token.subject == TokenSubject.USER_REGISTRATION assert token.subject == TokenSubject.USER_REGISTRATION
# and a verification email should be sent # and a verification email should be sent
# mailer = get_mailer(request.registry) # this is tested in the functional test since request.registry.notify
# last_mail = mailer.outbox[-1] # doesn't know about event subscribers in the unittest
# assert 'Please verify your email address ' in last_mail.html
# assert 'http://example.com/' + token.hash in last_mail.html
def test_registration_form_processing_cancel(app_config): def test_registration_form_processing_cancel(app_config):
@ -186,5 +184,33 @@ def test_registration_form_processing_validation_error(dbsession, key, value):
set_deform_data(request, REGISTRATION_FORM_DATA, {key: value}) set_deform_data(request, REGISTRATION_FORM_DATA, {key: value})
result = registration_form_processing(context, request) result = registration_form_processing(context, request)
# return value of function call
assert isinstance(result['form'], deform.Form) assert isinstance(result['form'], deform.Form)
def test_registration_confirmation():
''' registration, awaiting confirmation of email address '''
from ordr2.views.account import registration_confirmation
result = registration_confirmation(None, None)
assert result == {}
def test_registration_completed(dbsession):
''' registration, confirmation of email address successful '''
from ordr2.models.account import User, Role, Token, TokenSubject
from ordr2.views.account import registration_completed
request = DummyRequest(dbsession=dbsession)
user = get_user('unvalidated')
user.issue_token(request, TokenSubject.USER_REGISTRATION)
dbsession.add(user)
dbsession.flush()
token = user.tokens[0]
context = DummyResource(model=token)
result = registration_completed(context, request)
assert result == {}
assert user.role == Role.NEW
assert dbsession.query(Token).count() == 0
assert dbsession.query(User).count() == 1