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.
- EGG-INFO/PKG-INFO +176 -0
- EGG-INFO/SOURCES.txt +91 -0
- EGG-INFO/dependency_links.txt +1 -0
- EGG-INFO/not-zip-safe +1 -0
- EGG-INFO/requires.txt +17 -0
- EGG-INFO/top_level.txt +2 -0
- pyramid_fullauth/__init__.py +105 -0
- pyramid_fullauth/__init__.pyc +0 -0
- pyramid_fullauth/auth.py +66 -0
- pyramid_fullauth/auth.pyc +0 -0
- pyramid_fullauth/events.py +267 -0
- pyramid_fullauth/events.pyc +0 -0
- pyramid_fullauth/exceptions.py +47 -0
- pyramid_fullauth/exceptions.pyc +0 -0
- pyramid_fullauth/models/__init__.py +189 -0
- pyramid_fullauth/models/__init__.pyc +0 -0
- pyramid_fullauth/models/mixins/__init__.py +9 -0
- pyramid_fullauth/models/mixins/__init__.pyc +0 -0
- pyramid_fullauth/models/mixins/email.py +81 -0
- pyramid_fullauth/models/mixins/email.pyc +0 -0
- pyramid_fullauth/models/mixins/password.py +141 -0
- pyramid_fullauth/models/mixins/password.pyc +0 -0
- pyramid_fullauth/request.py +69 -0
- pyramid_fullauth/request.pyc +0 -0
- pyramid_fullauth/resources/helpers/social.mako +17 -0
- pyramid_fullauth/resources/locale/pyramid_fullauth.pot +216 -0
- pyramid_fullauth/resources/templates/403.mako +11 -0
- pyramid_fullauth/resources/templates/_form.login.mako +44 -0
- pyramid_fullauth/resources/templates/_form.register.mako +47 -0
- pyramid_fullauth/resources/templates/_social.login.mako +17 -0
- pyramid_fullauth/resources/templates/activate.mako +14 -0
- pyramid_fullauth/resources/templates/email_change.mako +33 -0
- pyramid_fullauth/resources/templates/layout.mako +13 -0
- pyramid_fullauth/resources/templates/login.mako +14 -0
- pyramid_fullauth/resources/templates/register.mako +22 -0
- pyramid_fullauth/resources/templates/reset.mako +34 -0
- pyramid_fullauth/resources/templates/reset.proceed.mako +41 -0
- pyramid_fullauth/routing/__init__.py +5 -0
- pyramid_fullauth/routing/__init__.pyc +0 -0
- pyramid_fullauth/routing/predicates.py +86 -0
- pyramid_fullauth/routing/predicates.pyc +0 -0
- pyramid_fullauth/tools.py +66 -0
- pyramid_fullauth/tools.pyc +0 -0
- pyramid_fullauth/views/__init__.py +15 -0
- pyramid_fullauth/views/__init__.pyc +0 -0
- pyramid_fullauth/views/basic/__init__.py +5 -0
- pyramid_fullauth/views/basic/__init__.pyc +0 -0
- pyramid_fullauth/views/basic/activate.py +44 -0
- pyramid_fullauth/views/basic/activate.pyc +0 -0
- pyramid_fullauth/views/basic/forbidden.py +47 -0
- pyramid_fullauth/views/basic/forbidden.pyc +0 -0
- pyramid_fullauth/views/basic/login.py +128 -0
- pyramid_fullauth/views/basic/login.pyc +0 -0
- pyramid_fullauth/views/basic/logout.py +28 -0
- pyramid_fullauth/views/basic/logout.pyc +0 -0
- pyramid_fullauth/views/basic/profile/__init__.py +5 -0
- pyramid_fullauth/views/basic/profile/__init__.pyc +0 -0
- pyramid_fullauth/views/basic/profile/email.py +107 -0
- pyramid_fullauth/views/basic/profile/email.pyc +0 -0
- pyramid_fullauth/views/basic/profile/password.py +128 -0
- pyramid_fullauth/views/basic/profile/password.pyc +0 -0
- pyramid_fullauth/views/basic/register.py +110 -0
- pyramid_fullauth/views/basic/register.pyc +0 -0
- pyramid_fullauth/views/social.py +218 -0
- pyramid_fullauth/views/social.pyc +0 -0
- tests/__init__.py +1 -0
- tests/__init__.pyc +0 -0
- tests/conftest.py +190 -0
- tests/conftest.pyc +0 -0
- tests/tools.py +54 -0
- tests/tools.pyc +0 -0
- tests/unit/test_default_settings.py +15 -0
- tests/unit/test_default_settings.pyc +0 -0
- tests/unit/test_groupfinder.py +20 -0
- tests/unit/test_groupfinder.pyc +0 -0
- tests/unit/test_social_view.py +65 -0
- tests/unit/test_social_view.pyc +0 -0
- tests/unit/test_tools.py +24 -0
- tests/unit/test_tools.pyc +0 -0
- tests/unit/test_user_active.py +31 -0
- tests/unit/test_user_active.pyc +0 -0
- tests/unit/test_user_admin.py +61 -0
- tests/unit/test_user_admin.pyc +0 -0
- tests/unit/test_user_email.py +37 -0
- tests/unit/test_user_email.pyc +0 -0
- tests/unit/test_user_password.py +52 -0
- tests/unit/test_user_password.pyc +0 -0
- tests/unit/test_user_providers.py +24 -0
- tests/unit/test_user_providers.pyc +0 -0
- tests/unit/test_user_repr.py +29 -0
- tests/unit/test_user_repr.pyc +0 -0
- tests/unit/test_validators.py +44 -0
- tests/unit/test_validators.pyc +0 -0
- tests/views/__init__.py +1 -0
- tests/views/__init__.pyc +0 -0
- tests/views/conftest.py +15 -0
- tests/views/conftest.pyc +0 -0
- tests/views/test_activation.py +83 -0
- tests/views/test_activation.pyc +0 -0
- tests/views/test_email.py +175 -0
- tests/views/test_email.pyc +0 -0
- tests/views/test_events.py +546 -0
- tests/views/test_events.pyc +0 -0
- tests/views/test_login.py +151 -0
- tests/views/test_login.pyc +0 -0
- tests/views/test_login_social.py +254 -0
- tests/views/test_login_social.pyc +0 -0
- tests/views/test_logout.py +42 -0
- tests/views/test_logout.pyc +0 -0
- tests/views/test_register.py +134 -0
- tests/views/test_register.pyc +0 -0
- tests/views/test_reset.py +100 -0
- 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
|
tests/unit/test_tools.py
ADDED
|
@@ -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
|
tests/views/__init__.py
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Makes easier keeping some tests config with tests."""
|
tests/views/__init__.pyc
ADDED
|
Binary file
|
tests/views/conftest.py
ADDED
|
@@ -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)
|
tests/views/conftest.pyc
ADDED
|
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
|