From 8d4df465c26b0df8af5d8373a2f9bd7c91d55bcf Mon Sep 17 00:00:00 2001 From: Holger Frey Date: Mon, 23 Oct 2017 10:49:49 +0200 Subject: [PATCH] registration process working --- mail/20171023104036_7z0s.eml | 39 +++++++++++++++++++ mail/20171023104054_c95d.eml | 39 +++++++++++++++++++ mail/20171023104107_zi5j.eml | 39 +++++++++++++++++++ mail/20171023104203_jphu.eml | 39 +++++++++++++++++++ mail/20171023104247_zj8w.eml | 39 +++++++++++++++++++ mail/20171023104351_istb.eml | 39 +++++++++++++++++++ mail/20171023104501_9pm0.eml | 39 +++++++++++++++++++ ordr2/events.py | 8 ++-- ordr2/schemas/__init__.py | 1 + ordr2/schemas/account.py | 3 +- ordr2/schemas/helpers.py | 1 - .../account/registration_completed.jinja2 | 17 ++++++++ .../account/registration_confirmation.jinja2 | 16 ++++++++ ordr2/views/account.py | 23 ++++++++++- tests/_functional/__init__.py | 14 ++++++- tests/_functional/registration.py | 28 +++++++------ tests/views/account.py | 36 ++++++++++++++--- 17 files changed, 395 insertions(+), 25 deletions(-) create mode 100644 mail/20171023104036_7z0s.eml create mode 100644 mail/20171023104054_c95d.eml create mode 100644 mail/20171023104107_zi5j.eml create mode 100644 mail/20171023104203_jphu.eml create mode 100644 mail/20171023104247_zj8w.eml create mode 100644 mail/20171023104351_istb.eml create mode 100644 mail/20171023104501_9pm0.eml create mode 100644 ordr2/templates/account/registration_completed.jinja2 create mode 100644 ordr2/templates/account/registration_confirmation.jinja2 diff --git a/mail/20171023104036_7z0s.eml b/mail/20171023104036_7z0s.eml new file mode 100644 index 0000000..85cd7a4 --- /dev/null +++ b/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 + + + + +=09 +=20=20=09[ordr]=20verify=20your=20email=20address +=20=20=09 + + +=20=20=09

Hi=20there!

+=20=20=09

+=20=20=09=09Please=20verify=20your=20email=20address=20for=20the=20account= +=20""=20by=20following=20this=20link +=20=20=09=09http://localhost/account/68297eb302224e77b3dfe7264c328ed2 +=09

+=09 +=09=09Regards, +=09=09
+=09=09ordr +=09

+=09 +=09=09Please=20don't=20respont=20to=20this=20email!=20This=20is=20an= +=20automatically=20generated=20notification=20by=20the=20system. +=09=09 +=09

+ + \ No newline at end of file diff --git a/mail/20171023104054_c95d.eml b/mail/20171023104054_c95d.eml new file mode 100644 index 0000000..57d9de6 --- /dev/null +++ b/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 + + + + +=09 +=20=20=09[ordr]=20verify=20your=20email=20address +=20=20=09 + + +=20=20=09

Hi=20there!

+=20=20=09

+=20=20=09=09Please=20verify=20your=20email=20address=20for=20the=20account= +=20""=20by=20following=20this=20link +=20=20=09=09http://localhost/account/7f9ec1dedca1402cbf9d38ee3709efdd +=09

+=09 +=09=09Regards, +=09=09
+=09=09ordr +=09

+=09 +=09=09Please=20don't=20respont=20to=20this=20email!=20This=20is=20an= +=20automatically=20generated=20notification=20by=20the=20system. +=09=09 +=09

+ + \ No newline at end of file diff --git a/mail/20171023104107_zi5j.eml b/mail/20171023104107_zi5j.eml new file mode 100644 index 0000000..52d1f26 --- /dev/null +++ b/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 + + + + +=09 +=20=20=09[ordr]=20verify=20your=20email=20address +=20=20=09 + + +=20=20=09

Hi=20there!

+=20=20=09

+=20=20=09=09Please=20verify=20your=20email=20address=20for=20the=20account= +=20""=20by=20following=20this=20link +=20=20=09=09http://localhost/account/a7967f6249a545afbd5903ff1eb07381 +=09

+=09 +=09=09Regards, +=09=09
+=09=09ordr +=09

+=09 +=09=09Please=20don't=20respont=20to=20this=20email!=20This=20is=20an= +=20automatically=20generated=20notification=20by=20the=20system. +=09=09 +=09

+ + \ No newline at end of file diff --git a/mail/20171023104203_jphu.eml b/mail/20171023104203_jphu.eml new file mode 100644 index 0000000..f4f527d --- /dev/null +++ b/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 + + + + +=09 +=20=20=09[ordr]=20verify=20your=20email=20address +=20=20=09 + + +=20=20=09

Hi=20there!

+=20=20=09

+=20=20=09=09Please=20verify=20your=20email=20address=20for=20the=20account= +=20""=20by=20following=20this=20link +=20=20=09=09http://localhost/account/b2c98fbf355147ac96ffa6eac9ca9079 +=09

+=09 +=09=09Regards, +=09=09
+=09=09ordr +=09

+=09 +=09=09Please=20don't=20respont=20to=20this=20email!=20This=20is=20an= +=20automatically=20generated=20notification=20by=20the=20system. +=09=09 +=09

+ + \ No newline at end of file diff --git a/mail/20171023104247_zj8w.eml b/mail/20171023104247_zj8w.eml new file mode 100644 index 0000000..869d729 --- /dev/null +++ b/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 + + + + +=09 +=20=20=09[ordr]=20verify=20your=20email=20address +=20=20=09 + + +=20=20=09

Hi=20there!

+=20=20=09

+=20=20=09=09Please=20verify=20your=20email=20address=20for=20the=20account= +=20""=20by=20following=20this=20link +=20=20=09=09http://localhost/account/c730af7ecfde42899c1d6c5f5e488d62 +=09

+=09 +=09=09Regards, +=09=09
+=09=09ordr +=09

+=09 +=09=09Please=20don't=20respont=20to=20this=20email!=20This=20is=20an= +=20automatically=20generated=20notification=20by=20the=20system. +=09=09 +=09

+ + \ No newline at end of file diff --git a/mail/20171023104351_istb.eml b/mail/20171023104351_istb.eml new file mode 100644 index 0000000..d411867 --- /dev/null +++ b/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 + + + + +=09 +=20=20=09[ordr]=20verify=20your=20email=20address +=20=20=09 + + +=20=20=09

Hi=20there!

+=20=20=09

+=20=20=09=09Please=20verify=20your=20email=20address=20for=20the=20account= +=20""=20by=20following=20this=20link +=20=20=09=09http://localhost/account/010d7d85a9fa415ca88d0a0bfce3fe8e +=09

+=09 +=09=09Regards, +=09=09
+=09=09ordr +=09

+=09 +=09=09Please=20don't=20respont=20to=20this=20email!=20This=20is=20an= +=20automatically=20generated=20notification=20by=20the=20system. +=09=09 +=09

+ + \ No newline at end of file diff --git a/mail/20171023104501_9pm0.eml b/mail/20171023104501_9pm0.eml new file mode 100644 index 0000000..c13d4d1 --- /dev/null +++ b/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 + + + + +=09 +=20=20=09[ordr]=20verify=20your=20email=20address +=20=20=09 + + +=20=20=09

Hi=20there!

+=20=20=09

+=20=20=09=09Please=20verify=20your=20email=20address=20for=20the=20account= +=20""=20by=20following=20this=20link +=20=20=09=09http://localhost/account/b1e2b70fad024881ab5f5d421eea371a +=09

+=09 +=09=09Regards, +=09=09
+=09=09ordr +=09

+=09 +=09=09Please=20don't=20respont=20to=20this=20email!=20This=20is=20an= +=20automatically=20generated=20notification=20by=20the=20system. +=09=09 +=09

+ + \ No newline at end of file diff --git a/ordr2/events.py b/ordr2/events.py index 3fb29c1..df0a97b 100644 --- a/ordr2/events.py +++ b/ordr2/events.py @@ -37,25 +37,25 @@ class UserNotification(object): class CompleteRegistration(UserNotification): ''' 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' class AccountActivation(UserNotification): ''' user notification for account activation ''' - subject='[ordr] Your account was activated' + subject = '[ordr] Your account was activated' template = 'ordr2:templates/emails/activation.jinja2' class PasswordReset(UserNotification): ''' user notification for password reset link ''' - subject='[ordr] Password Reset' + subject = '[ordr] Password Reset' template = 'ordr2:templates/emails/password_reset.jinja2' class OrderStatusChange(UserNotification): ''' user notification for order status change ''' - subject='[ordr] Order Status Change' + subject = '[ordr] Order Status Change' template = 'ordr2:templates/emails/order.jinja2' diff --git a/ordr2/schemas/__init__.py b/ordr2/schemas/__init__.py index 01ad178..9ab51cd 100644 --- a/ordr2/schemas/__init__.py +++ b/ordr2/schemas/__init__.py @@ -10,6 +10,7 @@ from .helpers import ( deferred_csrf_validator ) + # Base Schema class CSRFSchema(colander.Schema): diff --git a/ordr2/schemas/account.py b/ordr2/schemas/account.py index 48db69d..51f5987 100644 --- a/ordr2/schemas/account.py +++ b/ordr2/schemas/account.py @@ -22,7 +22,7 @@ class RegistrationSchema(CSRFSchema): readonly=True ), description='automagically generated for you', - validator = deferred_unique_username_validator, + validator=deferred_unique_username_validator, ) first_name = colander.SchemaNode( colander.String() @@ -47,4 +47,3 @@ class RegistrationSchema(CSRFSchema): } settings.update(override) return super().as_form(request, **settings) - diff --git a/ordr2/schemas/helpers.py b/ordr2/schemas/helpers.py index e22a43f..fa50a5f 100644 --- a/ordr2/schemas/helpers.py +++ b/ordr2/schemas/helpers.py @@ -1,7 +1,6 @@ ''' helper functions for schemas ''' import colander -import deform from pyramid.csrf import get_csrf_token, check_csrf_token diff --git a/ordr2/templates/account/registration_completed.jinja2 b/ordr2/templates/account/registration_completed.jinja2 new file mode 100644 index 0000000..4115e42 --- /dev/null +++ b/ordr2/templates/account/registration_completed.jinja2 @@ -0,0 +1,17 @@ +{% extends "ordr2:templates/layout.jinja2" %} + +{% block title %} Ordr | Account Registration {% endblock title %} + +{% block content %} +
+
+
+ +

Account Registration Completed

+

Thank you for verifying your email address.

+

Before you can start ordering, an administrator must activate your account

+

You'll receive an email when your account is activated

+ +
+
+{% endblock content %} diff --git a/ordr2/templates/account/registration_confirmation.jinja2 b/ordr2/templates/account/registration_confirmation.jinja2 new file mode 100644 index 0000000..81a047b --- /dev/null +++ b/ordr2/templates/account/registration_confirmation.jinja2 @@ -0,0 +1,16 @@ +{% extends "ordr2:templates/layout.jinja2" %} + +{% block title %} Ordr | Account Registration {% endblock title %} + +{% block content %} +
+
+
+ +

Verify Your Email Address

+

To complete the registration process an email has been sent to you.

+

Please follow the link in the email to verify your address and complete the registration process

+ +
+
+{% endblock content %} diff --git a/ordr2/views/account.py b/ordr2/views/account.py index fcadb9f..220c4c2 100644 --- a/ordr2/views/account.py +++ b/ordr2/views/account.py @@ -60,7 +60,7 @@ def logout(context, request): def registration_form(context, request): ''' the new user registraion page ''' form = RegistrationSchema.as_form(request) - return {'form':form} + return {'form': form} @view_config( @@ -107,3 +107,24 @@ def registration_form_processing(context, request): ) 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 {} diff --git a/tests/_functional/__init__.py b/tests/_functional/__init__.py index 3234789..980535c 100644 --- a/tests/_functional/__init__.py +++ b/tests/_functional/__init__.py @@ -2,14 +2,26 @@ import os.path import pytest +import re import transaction import webtest +from bs4 import BeautifulSoup + from .. import APP_SETTINGS, create_users, get_user 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): diff --git a/tests/_functional/registration.py b/tests/_functional/registration.py index 847ee28..4d6afcf 100644 --- a/tests/_functional/registration.py +++ b/tests/_functional/registration.py @@ -2,7 +2,9 @@ import pytest -from . import testapp +from pyramid_mailer import get_mailer + +from . import testapp, get_token_url from .. import get_user @@ -39,25 +41,29 @@ def test_account_registeration_flow(testapp): ''' test the complete registration process ''' # submit the registration form - form = resonse.forms[1] + response = testapp.get('/account/register') + form = response.forms[1] form['username'] = 'AmyMcDonald' form['first_name'] = 'Amy' form['last_name'] = 'McDonald' form['email'] = 'amy@example.com' form['password'] = 'Amy' - form['password_confirm'] = 'Amy' - response = form.submitt() + form['password-confirm'] = 'Amy' + response = form.submit() - assert response.location == '/account/verify' + assert response.location == 'http://localhost/account/registered' 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 - email = '' - token = email - response = testapp.get('/account/' + token) - assert 'consider a longer password' in response - assert 'activated by an administrator' in response + mailer = get_mailer(testapp.app.registry) + email = mailer.outbox[-1] + assert email.subject == '[ordr] Please verify your email address' + token_link = get_token_url(email) + + response = testapp.get(token_link) + assert 'Account Registration Completed' in response # logging in should not work form = response.forms[0] diff --git a/tests/views/account.py b/tests/views/account.py index 8e5d238..6cd0273 100644 --- a/tests/views/account.py +++ b/tests/views/account.py @@ -139,10 +139,8 @@ def test_registration_form_processing_ok(dbsession): assert token.subject == TokenSubject.USER_REGISTRATION # and a verification email should be sent - # mailer = get_mailer(request.registry) - # last_mail = mailer.outbox[-1] - # assert 'Please verify your email address ' in last_mail.html - # assert 'http://example.com/' + token.hash in last_mail.html + # this is tested in the functional test since request.registry.notify + # doesn't know about event subscribers in the unittest 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}) result = registration_form_processing(context, request) - # return value of function call 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