pyramid-fullauth 0.3.0__py2.7.egg

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. EGG-INFO/PKG-INFO +176 -0
  2. EGG-INFO/SOURCES.txt +91 -0
  3. EGG-INFO/dependency_links.txt +1 -0
  4. EGG-INFO/not-zip-safe +1 -0
  5. EGG-INFO/requires.txt +17 -0
  6. EGG-INFO/top_level.txt +2 -0
  7. pyramid_fullauth/__init__.py +105 -0
  8. pyramid_fullauth/__init__.pyc +0 -0
  9. pyramid_fullauth/auth.py +66 -0
  10. pyramid_fullauth/auth.pyc +0 -0
  11. pyramid_fullauth/events.py +267 -0
  12. pyramid_fullauth/events.pyc +0 -0
  13. pyramid_fullauth/exceptions.py +47 -0
  14. pyramid_fullauth/exceptions.pyc +0 -0
  15. pyramid_fullauth/models/__init__.py +189 -0
  16. pyramid_fullauth/models/__init__.pyc +0 -0
  17. pyramid_fullauth/models/mixins/__init__.py +9 -0
  18. pyramid_fullauth/models/mixins/__init__.pyc +0 -0
  19. pyramid_fullauth/models/mixins/email.py +81 -0
  20. pyramid_fullauth/models/mixins/email.pyc +0 -0
  21. pyramid_fullauth/models/mixins/password.py +141 -0
  22. pyramid_fullauth/models/mixins/password.pyc +0 -0
  23. pyramid_fullauth/request.py +69 -0
  24. pyramid_fullauth/request.pyc +0 -0
  25. pyramid_fullauth/resources/helpers/social.mako +17 -0
  26. pyramid_fullauth/resources/locale/pyramid_fullauth.pot +216 -0
  27. pyramid_fullauth/resources/templates/403.mako +11 -0
  28. pyramid_fullauth/resources/templates/_form.login.mako +44 -0
  29. pyramid_fullauth/resources/templates/_form.register.mako +47 -0
  30. pyramid_fullauth/resources/templates/_social.login.mako +17 -0
  31. pyramid_fullauth/resources/templates/activate.mako +14 -0
  32. pyramid_fullauth/resources/templates/email_change.mako +33 -0
  33. pyramid_fullauth/resources/templates/layout.mako +13 -0
  34. pyramid_fullauth/resources/templates/login.mako +14 -0
  35. pyramid_fullauth/resources/templates/register.mako +22 -0
  36. pyramid_fullauth/resources/templates/reset.mako +34 -0
  37. pyramid_fullauth/resources/templates/reset.proceed.mako +41 -0
  38. pyramid_fullauth/routing/__init__.py +5 -0
  39. pyramid_fullauth/routing/__init__.pyc +0 -0
  40. pyramid_fullauth/routing/predicates.py +86 -0
  41. pyramid_fullauth/routing/predicates.pyc +0 -0
  42. pyramid_fullauth/tools.py +66 -0
  43. pyramid_fullauth/tools.pyc +0 -0
  44. pyramid_fullauth/views/__init__.py +15 -0
  45. pyramid_fullauth/views/__init__.pyc +0 -0
  46. pyramid_fullauth/views/basic/__init__.py +5 -0
  47. pyramid_fullauth/views/basic/__init__.pyc +0 -0
  48. pyramid_fullauth/views/basic/activate.py +44 -0
  49. pyramid_fullauth/views/basic/activate.pyc +0 -0
  50. pyramid_fullauth/views/basic/forbidden.py +47 -0
  51. pyramid_fullauth/views/basic/forbidden.pyc +0 -0
  52. pyramid_fullauth/views/basic/login.py +128 -0
  53. pyramid_fullauth/views/basic/login.pyc +0 -0
  54. pyramid_fullauth/views/basic/logout.py +28 -0
  55. pyramid_fullauth/views/basic/logout.pyc +0 -0
  56. pyramid_fullauth/views/basic/profile/__init__.py +5 -0
  57. pyramid_fullauth/views/basic/profile/__init__.pyc +0 -0
  58. pyramid_fullauth/views/basic/profile/email.py +107 -0
  59. pyramid_fullauth/views/basic/profile/email.pyc +0 -0
  60. pyramid_fullauth/views/basic/profile/password.py +128 -0
  61. pyramid_fullauth/views/basic/profile/password.pyc +0 -0
  62. pyramid_fullauth/views/basic/register.py +110 -0
  63. pyramid_fullauth/views/basic/register.pyc +0 -0
  64. pyramid_fullauth/views/social.py +218 -0
  65. pyramid_fullauth/views/social.pyc +0 -0
  66. tests/__init__.py +1 -0
  67. tests/__init__.pyc +0 -0
  68. tests/conftest.py +190 -0
  69. tests/conftest.pyc +0 -0
  70. tests/tools.py +54 -0
  71. tests/tools.pyc +0 -0
  72. tests/unit/test_default_settings.py +15 -0
  73. tests/unit/test_default_settings.pyc +0 -0
  74. tests/unit/test_groupfinder.py +20 -0
  75. tests/unit/test_groupfinder.pyc +0 -0
  76. tests/unit/test_social_view.py +65 -0
  77. tests/unit/test_social_view.pyc +0 -0
  78. tests/unit/test_tools.py +24 -0
  79. tests/unit/test_tools.pyc +0 -0
  80. tests/unit/test_user_active.py +31 -0
  81. tests/unit/test_user_active.pyc +0 -0
  82. tests/unit/test_user_admin.py +61 -0
  83. tests/unit/test_user_admin.pyc +0 -0
  84. tests/unit/test_user_email.py +37 -0
  85. tests/unit/test_user_email.pyc +0 -0
  86. tests/unit/test_user_password.py +52 -0
  87. tests/unit/test_user_password.pyc +0 -0
  88. tests/unit/test_user_providers.py +24 -0
  89. tests/unit/test_user_providers.pyc +0 -0
  90. tests/unit/test_user_repr.py +29 -0
  91. tests/unit/test_user_repr.pyc +0 -0
  92. tests/unit/test_validators.py +44 -0
  93. tests/unit/test_validators.pyc +0 -0
  94. tests/views/__init__.py +1 -0
  95. tests/views/__init__.pyc +0 -0
  96. tests/views/conftest.py +15 -0
  97. tests/views/conftest.pyc +0 -0
  98. tests/views/test_activation.py +83 -0
  99. tests/views/test_activation.pyc +0 -0
  100. tests/views/test_email.py +175 -0
  101. tests/views/test_email.pyc +0 -0
  102. tests/views/test_events.py +546 -0
  103. tests/views/test_events.pyc +0 -0
  104. tests/views/test_login.py +151 -0
  105. tests/views/test_login.pyc +0 -0
  106. tests/views/test_login_social.py +254 -0
  107. tests/views/test_login_social.pyc +0 -0
  108. tests/views/test_logout.py +42 -0
  109. tests/views/test_logout.pyc +0 -0
  110. tests/views/test_register.py +134 -0
  111. tests/views/test_register.pyc +0 -0
  112. tests/views/test_reset.py +100 -0
  113. tests/views/test_reset.pyc +0 -0
tests/tools.py ADDED
@@ -0,0 +1,54 @@
1
+ """Tools used for fullauth tests."""
2
+ from pyramid.view import view_config
3
+ from pyramid.compat import text_type
4
+
5
+ DEFAULT_USER = {
6
+ 'username': text_type('u1'),
7
+ 'password': text_type('password1'),
8
+ 'email': text_type('email@example.com'),
9
+ 'address_ip': text_type('127.0.0.1')
10
+ }
11
+
12
+
13
+ def authenticate(app, email=DEFAULT_USER['email'],
14
+ password=DEFAULT_USER['password'],
15
+ remember=False,
16
+ response_code=302):
17
+ """Authenticate user."""
18
+ res = app.get('/login')
19
+ form = res.form
20
+
21
+ form['email'] = email
22
+ form['password'] = password
23
+ if remember:
24
+ form['remember'] = 1
25
+
26
+ res = form.submit()
27
+
28
+ # We've been redirected after log in
29
+ assert res.status_code == response_code
30
+
31
+ return res
32
+
33
+
34
+ def is_user_logged(app):
35
+ """Check for auth_tkt cookies beeing set to see if user is logged in."""
36
+ cookies = app.cookies
37
+ if 'auth_tkt' in cookies and cookies['auth_tkt']:
38
+
39
+ return True
40
+ return False
41
+
42
+ # this below are additional views crafted for tests.
43
+
44
+
45
+ def include_views(config):
46
+ """Dummy pyramid 'plugin' adding dummy secret view."""
47
+ config.add_route('secret', '/secret')
48
+ config.scan('tests.tools')
49
+
50
+
51
+ @view_config(route_name="secret", permission="super_high", renderer='json')
52
+ def secret_view(request):
53
+ """Dummy view with redirect to login."""
54
+ return {}
tests/tools.pyc ADDED
Binary file
@@ -0,0 +1,15 @@
1
+ """
2
+ Test for recognizing default settings.
3
+
4
+ Also helps to keeping them in line.
5
+ """
6
+
7
+
8
+ def test_defaults(default_config):
9
+ """Load defaults config for fullauth."""
10
+ # Config should get created based on fullauth defaults
11
+ assert 'fullauth' in default_config.registry['config']
12
+ # csrf should be turned on by default
13
+ assert default_config.registry['config']['fullauth']['check_csrf'] is True
14
+ # also hashalg should be anything but not md5 by default.
15
+ assert default_config.registry['config']['fullauth']['AuthTkt']['hashalg'] is not 'md5'
Binary file
@@ -0,0 +1,20 @@
1
+ """Test groupfinder."""
2
+ import pytest
3
+
4
+ from pyramid_fullauth.auth import groupfinder
5
+
6
+
7
+ @pytest.mark.parametrize(['is_admin', 'is_active', 'groups'],
8
+ [(True, True, ['s:superadmin', 's:user']),
9
+ (True, False, ['s:superadmin', 's:inactive']),
10
+ (False, True, ['s:user']),
11
+ (False, False, ['s:inactive'])])
12
+ def test_groupfinder(web_request, db_session, user, is_admin, is_active, groups):
13
+ """Return special group assigned for user."""
14
+ user = db_session.merge(user)
15
+ user.is_admin = is_admin
16
+ user.is_active = is_active
17
+
18
+ web_request.user = user
19
+ assigned_groups = groupfinder(user.id, web_request)
20
+ assert groups == assigned_groups
Binary file
@@ -0,0 +1,65 @@
1
+ """Unittest for social login view."""
2
+ import pytest
3
+ import mock
4
+ from velruse import AuthenticationComplete
5
+
6
+ from pyramid_fullauth.views.social import SocialLoginViews
7
+
8
+
9
+ @pytest.mark.parametrize('profile, email', [
10
+ (
11
+ {
12
+ 'accounts': [{'domain': u'facebook.com', 'userid': u'2343'}],
13
+ 'displayName': u'teddy',
14
+ 'verifiedEmail': 'verified@email.co.uk',
15
+ 'preferredUsername': u'teddy',
16
+ 'emails': [{'value': u'aasd@bwwqwe.pl'}],
17
+ 'name': u'ted'
18
+ },
19
+ 'verified@email.co.uk'
20
+ ), (
21
+ {
22
+ 'accounts': [{'domain': u'facebook.com', 'userid': u'2343'}],
23
+ 'displayName': u'teddy',
24
+ 'preferredUsername': u'teddy',
25
+ 'emails': [{'value': u'aasd@bwwqwe.pl'}],
26
+ 'name': u'ted'
27
+ },
28
+ 'aasd@bwwqwe.pl'
29
+ ), (
30
+ {
31
+ 'accounts': [{'domain': u'facebook.com', 'userid': u'2343'}],
32
+ 'displayName': u'teddy',
33
+ 'preferredUsername': u'teddy',
34
+ 'emails': [{}],
35
+ 'name': u'ted'
36
+ },
37
+ '2343@facebook.com'
38
+ ), (
39
+ {
40
+ 'accounts': [{'domain': u'facebook.com', 'userid': u'2343'}],
41
+ 'displayName': u'teddy',
42
+ 'preferredUsername': u'teddy',
43
+ 'emails': [],
44
+ 'name': u'ted'
45
+ },
46
+ '2343@facebook.com'
47
+ ), (
48
+ {
49
+ 'accounts': [{'domain': u'facebook.com', 'userid': u'2343'}],
50
+ 'displayName': u'teddy',
51
+ 'preferredUsername': u'teddy',
52
+ 'name': u'ted'
53
+ },
54
+ '2343@facebook.com'
55
+ ),
56
+ ])
57
+ def test_email_from_context(profile, email):
58
+ """Test email_from_context email getting method."""
59
+ context = AuthenticationComplete(
60
+ profile,
61
+ {'oauthAccessToken': '7897048593434'},
62
+ u'facebook',
63
+ u'facebook')
64
+ view = SocialLoginViews(mock.MagicMock())
65
+ assert view._email_from_context(context) == email
Binary file
@@ -0,0 +1,24 @@
1
+ """Test fullauth's tools."""
2
+ import pytest
3
+
4
+ from pyramid_fullauth.tools import validate_passsword, password_generator
5
+ from pyramid_fullauth.exceptions import (
6
+ EmptyError, ShortPasswordError, PasswordConfirmMismatchError
7
+ )
8
+
9
+
10
+ @pytest.mark.parametrize(('password', 'exception'),
11
+ [('', EmptyError),
12
+ ('1234', ShortPasswordError),
13
+ ('123456789', PasswordConfirmMismatchError)
14
+ ])
15
+ def test_raises_errors(web_request, password, exception):
16
+ """Test validate_passsword possible exceptions."""
17
+ with pytest.raises(exception):
18
+ validate_passsword(web_request, password)
19
+
20
+
21
+ @pytest.mark.parametrize('length', [5, 6])
22
+ def test_password_generator(length):
23
+ """Test password_generator generating proper length of a random password."""
24
+ assert len(password_generator(length)) == length
Binary file
@@ -0,0 +1,31 @@
1
+ """User active method tests."""
2
+ import pytest
3
+
4
+ from pyramid_fullauth.models import User
5
+
6
+
7
+ def test_is_active_error():
8
+ """is_active can only be modified on object in session."""
9
+ with pytest.raises(AttributeError):
10
+ user = User()
11
+ user.is_active = True
12
+
13
+
14
+ def test_is_active(db_session, user):
15
+ """
16
+ Test is_active attribute.
17
+
18
+ Setting is_active to True, should result in change of activated_at date being set
19
+ Setting to false, should set deactivated_at.
20
+ """
21
+ user = db_session.merge(user)
22
+
23
+ assert not user.is_active
24
+ assert not user.activated_at
25
+ user.is_active = True
26
+ assert user.is_active
27
+ assert user.activated_at
28
+ assert not user.deactivated_at
29
+ user.is_active = False
30
+ assert not user.is_active
31
+ assert user.deactivated_at
Binary file
@@ -0,0 +1,61 @@
1
+ """Test admin related behaviour on user model."""
2
+ import pytest
3
+ import transaction
4
+ from pyramid.compat import text_type
5
+
6
+ from pyramid_fullauth.models import User
7
+ from pyramid_fullauth.exceptions import DeleteException
8
+
9
+
10
+ def test_regular_user_not_admin(db_session, user):
11
+ """Regular user is_admin flag test."""
12
+ user = db_session.merge(user)
13
+
14
+ # Default user should not be an admin
15
+ assert not user.is_admin
16
+
17
+
18
+ def test_remove_last_admin(db_session, user):
19
+ """
20
+ Admin user is_admin flag test.
21
+
22
+ At least one admin needed.
23
+ """
24
+ user = db_session.merge(user)
25
+ user.is_admin = True
26
+ transaction.commit()
27
+ user = db_session.merge(user)
28
+
29
+ with pytest.raises(AttributeError):
30
+ user.is_admin = False
31
+
32
+
33
+ def test_delete_admin(db_session, user):
34
+ """Admin user soft delete behaviour - more than one admins present."""
35
+ user = db_session.merge(user)
36
+ user2 = User(
37
+ email=text_type('test2@example.com'),
38
+ address_ip='127.0.0.1',
39
+ password='pass',
40
+ is_admin=True
41
+ )
42
+ db_session.add(user2)
43
+ user.is_admin = True
44
+ transaction.commit()
45
+ user = db_session.merge(user)
46
+
47
+ user.delete()
48
+
49
+ assert user.deleted_at
50
+
51
+
52
+ def test_delete_last_admin(db_session, user):
53
+ """Admin user soft delete - only one admin, no deleting possible."""
54
+ user = db_session.merge(user)
55
+
56
+ user.is_admin = True
57
+ transaction.commit()
58
+ user = db_session.merge(user)
59
+
60
+ with pytest.raises(DeleteException):
61
+ user.delete()
Binary file
@@ -0,0 +1,37 @@
1
+ """Test email related User methods."""
2
+ from pyramid.compat import text_type
3
+ from pyramid_fullauth.models import User
4
+
5
+ NEW_EMAIL = text_type('new@example.com')
6
+
7
+
8
+ def test_set_new_email():
9
+ """
10
+ Test User.set_new_email method.
11
+
12
+ setting new email should result in setting new_email field,
13
+ and key used to activate the change.
14
+ """
15
+ user = User()
16
+ assert user.email_change_key is None
17
+ assert user.new_email is None
18
+ user.set_new_email(NEW_EMAIL)
19
+
20
+ assert user.new_email == NEW_EMAIL
21
+ assert user.email_change_key
22
+
23
+
24
+ def test_change_email():
25
+ """
26
+ Test User.change_email method.
27
+
28
+ Calling it should copy new email set by set_new_email method
29
+ into regular email field.
30
+ """
31
+ user = User()
32
+ assert not user.email
33
+ user.set_new_email(NEW_EMAIL)
34
+ user.change_email()
35
+
36
+ assert not user.email_change_key
37
+ assert user.email == NEW_EMAIL
Binary file
@@ -0,0 +1,52 @@
1
+ """Password related user model behaviour."""
2
+ import pytest
3
+ from pyramid.compat import text_type
4
+ import transaction
5
+
6
+ from pyramid_fullauth.models import User
7
+ from pyramid_fullauth.exceptions import EmptyError
8
+
9
+
10
+ def test_hash_checkout(db_session, user):
11
+ """User.check_password correct one."""
12
+ user = db_session.merge(user)
13
+ assert user.check_password(text_type('password1')) is True
14
+
15
+
16
+ def test_hash_checkout_bad(db_session, user):
17
+ """User.check_password() wrong password."""
18
+ user = db_session.merge(user)
19
+ assert user.check_password(text_type('password2')) is False
20
+
21
+
22
+ @pytest.mark.parametrize('password', ['haselko', 'haselko' * 1000])
23
+ def test_password_change(db_session, user, password):
24
+ """User password change."""
25
+ new_password = text_type(password)
26
+
27
+ user = db_session.merge(user)
28
+ old_password = user.password
29
+ old_salt = user._salt
30
+ user.password = new_password
31
+ transaction.commit()
32
+
33
+ user = db_session.query(User).filter(User.username == text_type('u1')).one()
34
+ assert not user.password == old_password
35
+ assert not user._salt == old_salt
36
+ assert user.check_password(new_password)
37
+
38
+
39
+ def test_password_empty(db_session, user):
40
+ """User try to set empty password."""
41
+ user = db_session.merge(user)
42
+
43
+ with pytest.raises(EmptyError):
44
+ user.password = text_type('')
45
+
46
+
47
+ def test_set_reset(db_session, user):
48
+ """User.set_reset - generates reset key for those who forgot their password. """
49
+ user = db_session.merge(user)
50
+ assert not user.reset_key
51
+ user.set_reset()
52
+ assert user.reset_key
Binary file
@@ -0,0 +1,24 @@
1
+ """Test provider related user methods."""
2
+ from pyramid.compat import text_type
3
+ import transaction
4
+
5
+ from pyramid_fullauth.models import User
6
+ from pyramid_fullauth.models import AuthenticationProvider
7
+
8
+
9
+ def test_user_provider_id(db_session, user):
10
+ """User provider_id returns proper provider identification."""
11
+ user = db_session.merge(user)
12
+ email = user.email
13
+ # Provider does not exists yet
14
+ assert not user.provider_id('email')
15
+
16
+ provider = AuthenticationProvider()
17
+ provider.provider = text_type('email')
18
+ provider.provider_id = email
19
+ user.providers.append(provider)
20
+ transaction.commit()
21
+
22
+ user = db_session.query(User).filter(User.email == email).one()
23
+ # Provider exists
24
+ assert user.provider_id('email') == email
Binary file
@@ -0,0 +1,29 @@
1
+ """Test user representation."""
2
+ from pyramid.compat import text_type
3
+
4
+ from pyramid_fullauth.models import User
5
+
6
+
7
+ def test_introduce_email():
8
+ """user gets introduced by e-mail only."""
9
+ user = User()
10
+ user.email = text_type('test@test.pl')
11
+ # To string should return concatenated email
12
+ assert str(user) == 'test@...'
13
+
14
+
15
+ def test_introduce_username():
16
+ """user gets introduced by username."""
17
+ user = User()
18
+ # 'User not saved should be represented by \'None\'')
19
+ assert str(user) == 'None'
20
+ user.id = 1
21
+ # if id is set, user should be presented with it
22
+ assert str(user) == '1'
23
+
24
+ user.email = text_type('test@test.pl')
25
+ user.username = text_type('testowy')
26
+ # To string should return username
27
+ assert str(user) == 'testowy'
28
+ # User should be represented by "<User (\'1\', \'testowy\')>"
29
+ assert user.__repr__() == "<User ('1', 'testowy')>"
Binary file
@@ -0,0 +1,44 @@
1
+ """Test various validators present on User class."""
2
+ import pytest
3
+ import transaction
4
+ from pyramid.compat import text_type
5
+
6
+ from pyramid_fullauth.models import User
7
+ from pyramid_fullauth.exceptions import EmptyError, EmailValidationError
8
+
9
+
10
+ @pytest.mark.parametrize('email', [
11
+ text_type('very.common@example.com'),
12
+ text_type('a.little.lengthy.but.fine@dept.example.com'),
13
+ text_type('disposable.style.email.with+symbol@example.com'),
14
+ text_type('"very.unusual.@.unusual.com"@example.com'),
15
+ text_type('!#$%&\'*+-/=?^_`{}|~@example.org'),
16
+ text_type('""@example.org'),
17
+ text_type('"much.more unusual"@example.com'),
18
+ text_type('"()<>[]:,;@\\\"!#$%&\'*+-/=?^_`{}| ~ ? ^_`{}|~.a"@example.org'),
19
+ ])
20
+ def test_email_valid_formats(db_session, user, email):
21
+ """Check all valid formats of Email (RFC 5321) can be set by user."""
22
+ user = db_session.merge(user)
23
+
24
+ user.email = email
25
+ transaction.commit()
26
+
27
+ user = db_session.query(User).filter(
28
+ User.username == text_type('u1')).one()
29
+ assert user.email == email
30
+
31
+
32
+ def test_email_empty(user):
33
+ """Test reaction of email validator for empty email."""
34
+ with pytest.raises(EmptyError):
35
+ user.email = text_type('')
36
+
37
+
38
+ def test_email_invalid_formats(db_session, user, invalid_email):
39
+ """Check all invalid formats of Email (RFC 5321) can not be set by user."""
40
+ user = db_session.merge(user)
41
+
42
+ with pytest.raises(EmailValidationError):
43
+ user.email = invalid_email
44
+ db_session.commit()
Binary file
@@ -0,0 +1 @@
1
+ """Makes easier keeping some tests config with tests."""
Binary file
@@ -0,0 +1,15 @@
1
+ """General view fixtures."""
2
+ import pytest
3
+ import transaction
4
+
5
+ from pyramid_fullauth.models import AuthenticationProvider
6
+
7
+
8
+ @pytest.fixture
9
+ def facebook_user(active_user, db_session):
10
+ """Facebook user."""
11
+ active_user = db_session.merge(active_user)
12
+ active_user.providers.append(
13
+ AuthenticationProvider(provider='facebook', provider_id='1234'))
14
+ transaction.commit()
15
+ return db_session.merge(active_user)
Binary file
@@ -0,0 +1,83 @@
1
+ # -*- coding: utf-8 -*-
2
+ """Account activation related tests."""
3
+ from urllib import quote
4
+
5
+ import pytest
6
+ import transaction
7
+
8
+ from pyramid_fullauth.models import User
9
+ from tests.tools import authenticate, is_user_logged
10
+
11
+
12
+ def test_account_activation(user, db_session, default_app):
13
+ """Activate user."""
14
+ user = db_session.merge(user)
15
+
16
+ default_app.get('/register/activate/' + user.activate_key)
17
+ transaction.commit()
18
+ user = db_session.query(User).filter(User.email == user.email).one()
19
+
20
+ assert not user.activate_key
21
+ assert user.is_active
22
+ assert user.activated_at
23
+
24
+ authenticate(default_app)
25
+ assert is_user_logged(default_app) is True
26
+
27
+
28
+ def test_account_activation_wrong_key(user, db_session, default_app):
29
+ """Activate user with wrong key."""
30
+ user = db_session.merge(user)
31
+ activate_key = user.activate_key
32
+ res = default_app.get('/register/activate/' + activate_key[:-5], status=200)
33
+ transaction.commit()
34
+
35
+ assert 'Invalid activation code' in res.body
36
+
37
+ user = db_session.query(User).filter(User.email == user.email).one()
38
+ assert user.activate_key == activate_key
39
+ assert user.activate_key is not None
40
+ assert not user.activated_at
41
+ # User should not have active account at this moment
42
+ assert not user.is_active
43
+
44
+
45
+ def test_account_activation_key_with_trash_chars(user, db_session, default_app):
46
+ """Strange characters in activation key."""
47
+ if db_session.connection().dialect.name == 'mysql':
48
+ pytest.xfail("failing due mysql default character set being latin1 and collation latin1_swedish_ci")
49
+
50
+ user = db_session.merge(user)
51
+
52
+ activate_key = user.activate_key
53
+ res = default_app.get('/register/activate/' + quote(
54
+ u'ąśðłĸęł¶→łęóħó³→←śðđ[]}³½ĸżćŋðń→↓ŧ¶ħ→ĸł¼²³↓←ħ@ĸđśðĸ@ł¼ęłśħđó[³²½łðśđħ'.encode('utf-8')),
55
+ status=200
56
+ )
57
+ transaction.commit()
58
+
59
+ assert 'Invalid activation code' in res.body
60
+ user = db_session.query(User).filter(User.email == user.email).one()
61
+
62
+ assert user.activate_key == activate_key
63
+ assert user.activate_key is not None
64
+ assert not user.activated_at
65
+ # User should not have active account at this moment
66
+ assert not user.is_active
67
+
68
+
69
+ def test_account_activation_twice(user, db_session, default_app):
70
+ """Click activation link twice."""
71
+ user = db_session.merge(user)
72
+
73
+ activate_key = user.activate_key
74
+ res = default_app.get('/register/activate/' + activate_key)
75
+ transaction.commit()
76
+ user = db_session.query(User).filter(User.email == user.email).one()
77
+
78
+ assert not user.activate_key
79
+ assert user.is_active
80
+ assert user.activated_at
81
+
82
+ res = default_app.get('/register/activate/' + activate_key, status=200)
83
+ assert 'Invalid activation code' in res.body
Binary file