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
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"""Social network login test."""
|
|
2
|
+
import transaction
|
|
3
|
+
from pyramid import testing
|
|
4
|
+
from velruse import AuthenticationComplete
|
|
5
|
+
from mock import MagicMock
|
|
6
|
+
|
|
7
|
+
from pyramid_fullauth.views.social import SocialLoginViews
|
|
8
|
+
from pyramid_fullauth.models import User
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def test_social_login_link(social_app):
|
|
12
|
+
"""Login:Form displayed social form."""
|
|
13
|
+
res = social_app.get('/login')
|
|
14
|
+
assert ('Connect with facebook</a>' in res.body)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_social_click_link(social_app):
|
|
18
|
+
"""Click social login link."""
|
|
19
|
+
res = social_app.get('/login/facebook?scope=email%2Coffline_access', status=302)
|
|
20
|
+
assert (res.headers['Location'].startswith(
|
|
21
|
+
'https://www.facebook.com/dialog/oauth/?scope=email%2Coffline_access&state='))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def test_social_login_register(social_config, db_session):
|
|
25
|
+
"""Register fresh user and logs him in."""
|
|
26
|
+
profile = {
|
|
27
|
+
'accounts': [{'domain': u'facebook.com', 'userid': u'2343'}],
|
|
28
|
+
'displayName': u'teddy',
|
|
29
|
+
'verifiedEmail': u'we@po.pl',
|
|
30
|
+
'preferredUsername': u'teddy',
|
|
31
|
+
'emails': [{'value': u'aasd@bwwqwe.pl'}],
|
|
32
|
+
'name': u'ted'
|
|
33
|
+
}
|
|
34
|
+
credentials = {'oauthAccessToken': '7897048593434'}
|
|
35
|
+
provider_name = u'facebook'
|
|
36
|
+
provider_type = u'facebook'
|
|
37
|
+
request = testing.DummyRequest()
|
|
38
|
+
request.user = None
|
|
39
|
+
request.registry = social_config.registry
|
|
40
|
+
request.remote_addr = u'127.0.0.123'
|
|
41
|
+
request.context = AuthenticationComplete(profile, credentials, provider_name, provider_type)
|
|
42
|
+
|
|
43
|
+
request.login_perform = MagicMock(name='login_perform')
|
|
44
|
+
request.login_perform.return_value = {'status': True}
|
|
45
|
+
view = SocialLoginViews(request)
|
|
46
|
+
out = view()
|
|
47
|
+
assert out == {'status': True}
|
|
48
|
+
transaction.commit()
|
|
49
|
+
|
|
50
|
+
# read first new account
|
|
51
|
+
user = db_session.query(User).one()
|
|
52
|
+
assert user.is_active
|
|
53
|
+
assert user.provider_id('facebook') == profile['accounts'][0]['userid']
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_login_different_social_account(social_config, db_session, facebook_user):
|
|
57
|
+
"""
|
|
58
|
+
Login with different social account than connected from same provider.
|
|
59
|
+
|
|
60
|
+
System should let user in, but not change connection.
|
|
61
|
+
"""
|
|
62
|
+
# profile mock response
|
|
63
|
+
profile = {
|
|
64
|
+
# facebook user id is different than user's
|
|
65
|
+
'accounts': [{'domain': u'facebook.com', 'userid': u'2343'}],
|
|
66
|
+
'displayName': u'teddy',
|
|
67
|
+
'verifiedEmail': facebook_user.email,
|
|
68
|
+
'preferredUsername': u'teddy',
|
|
69
|
+
'emails': [{'value': u'aasd@bwwqwe.pl'}],
|
|
70
|
+
'name': u'ted'
|
|
71
|
+
}
|
|
72
|
+
request = testing.DummyRequest()
|
|
73
|
+
request.user = None
|
|
74
|
+
request.registry = social_config.registry
|
|
75
|
+
request.remote_addr = u'127.0.0.123'
|
|
76
|
+
request.context = AuthenticationComplete(
|
|
77
|
+
profile,
|
|
78
|
+
{'oauthAccessToken': '7897048593434'},
|
|
79
|
+
u'facebook',
|
|
80
|
+
u'facebook')
|
|
81
|
+
|
|
82
|
+
request.login_perform = MagicMock(name='login_perform')
|
|
83
|
+
request.login_perform.return_value = {'status': True}
|
|
84
|
+
view = SocialLoginViews(request)
|
|
85
|
+
out = view()
|
|
86
|
+
# user should be authenticated recognized by email!
|
|
87
|
+
assert out['status'] is True
|
|
88
|
+
assert facebook_user.provider_id('facebook') is not profile['accounts'][0]['userid']
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def test_login_social_connect(social_config, active_user, db_session):
|
|
92
|
+
"""Connect and logs user in."""
|
|
93
|
+
user = db_session.merge(active_user)
|
|
94
|
+
|
|
95
|
+
profile = {
|
|
96
|
+
'accounts': [{'domain': u'facebook.com', 'userid': u'2343'}],
|
|
97
|
+
'displayName': u'teddy',
|
|
98
|
+
'preferredUsername': u'teddy',
|
|
99
|
+
'emails': [{'value': user.email}],
|
|
100
|
+
'name': u'ted'
|
|
101
|
+
}
|
|
102
|
+
credentials = {'oauthAccessToken': '7897048593434'}
|
|
103
|
+
provider_name = u'facebook'
|
|
104
|
+
provider_type = u'facebook'
|
|
105
|
+
user = None
|
|
106
|
+
request = testing.DummyRequest()
|
|
107
|
+
request.user = user
|
|
108
|
+
request.registry = social_config.registry
|
|
109
|
+
request.remote_addr = u'127.0.0.123'
|
|
110
|
+
request.context = AuthenticationComplete(profile, credentials, provider_name, provider_type)
|
|
111
|
+
|
|
112
|
+
request.login_perform = MagicMock(name='login_perform')
|
|
113
|
+
request.login_perform.return_value = {'status': True}
|
|
114
|
+
view = SocialLoginViews(request)
|
|
115
|
+
out = view()
|
|
116
|
+
assert out == {'status': True}
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def test_logged_social_connect_account(social_config, active_user, db_session):
|
|
120
|
+
"""Connect facebook account to logged in user."""
|
|
121
|
+
user = db_session.merge(active_user)
|
|
122
|
+
|
|
123
|
+
profile = {
|
|
124
|
+
'accounts': [{'domain': u'facebook.com', 'userid': u'2343'}],
|
|
125
|
+
'displayName': u'teddy',
|
|
126
|
+
'preferredUsername': u'teddy',
|
|
127
|
+
'emails': [{'value': u'aasd@basd.pl'}],
|
|
128
|
+
'name': u'ted'
|
|
129
|
+
}
|
|
130
|
+
credentials = {'oauthAccessToken': '7897048593434'}
|
|
131
|
+
provider_name = u'facebook'
|
|
132
|
+
provider_type = u'facebook'
|
|
133
|
+
request = testing.DummyRequest()
|
|
134
|
+
request.user = user
|
|
135
|
+
request.registry = social_config.registry
|
|
136
|
+
request.remote_addr = u'127.0.0.123'
|
|
137
|
+
request.context = AuthenticationComplete(profile, credentials, provider_name, provider_type)
|
|
138
|
+
request._ = lambda msg, *args, **kwargs: msg
|
|
139
|
+
|
|
140
|
+
request.login_perform = MagicMock(name='login_perform')
|
|
141
|
+
request.login_perform.return_value = {'status': True}
|
|
142
|
+
view = SocialLoginViews(request)
|
|
143
|
+
out = view()
|
|
144
|
+
assert out['status'] is True
|
|
145
|
+
|
|
146
|
+
transaction.commit()
|
|
147
|
+
user = db_session.merge(user)
|
|
148
|
+
assert user.provider_id('facebook') == profile['accounts'][0]['userid']
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def test_logged_social_connect_self(social_config, facebook_user, db_session):
|
|
152
|
+
"""Connect self."""
|
|
153
|
+
user = db_session.merge(facebook_user)
|
|
154
|
+
|
|
155
|
+
profile = {
|
|
156
|
+
'accounts': [{'domain': u'facebook.com', 'userid': user.provider_id('facebook')}],
|
|
157
|
+
'displayName': u'teddy',
|
|
158
|
+
'preferredUsername': u'teddy',
|
|
159
|
+
'emails': [{'value': user.email}],
|
|
160
|
+
'name': u'ted'
|
|
161
|
+
}
|
|
162
|
+
credentials = {'oauthAccessToken': '7897048593434'}
|
|
163
|
+
provider_name = u'facebook'
|
|
164
|
+
provider_type = u'facebook'
|
|
165
|
+
request = testing.DummyRequest()
|
|
166
|
+
request.user = user
|
|
167
|
+
request.registry = social_config.registry
|
|
168
|
+
request.remote_addr = u'127.0.0.123'
|
|
169
|
+
request.context = AuthenticationComplete(profile, credentials, provider_name, provider_type)
|
|
170
|
+
request._ = lambda msg, *args, **kwargs: msg
|
|
171
|
+
|
|
172
|
+
request.login_perform = MagicMock(name='login_perform')
|
|
173
|
+
request.login_perform.return_value = {'status': True}
|
|
174
|
+
view = SocialLoginViews(request)
|
|
175
|
+
out = view()
|
|
176
|
+
assert out['status'] is True
|
|
177
|
+
|
|
178
|
+
user = db_session.merge(facebook_user)
|
|
179
|
+
assert user.provider_id('facebook') == profile['accounts'][0]['userid']
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def test_logged_social_connect_second_account(social_config, facebook_user, db_session):
|
|
183
|
+
"""Connect second facebook account to logged in user."""
|
|
184
|
+
user = db_session.merge(facebook_user)
|
|
185
|
+
|
|
186
|
+
# mock request
|
|
187
|
+
profile = {
|
|
188
|
+
'accounts': [{'domain': u'facebook.com', 'userid': u'2343'}],
|
|
189
|
+
'displayName': u'teddy',
|
|
190
|
+
'preferredUsername': u'teddy',
|
|
191
|
+
'emails': [{'value': u'aasd@basd.pl'}],
|
|
192
|
+
'name': u'ted'
|
|
193
|
+
}
|
|
194
|
+
credentials = {'oauthAccessToken': '7897048593434'}
|
|
195
|
+
provider_name = u'facebook'
|
|
196
|
+
provider_type = u'facebook'
|
|
197
|
+
request = testing.DummyRequest()
|
|
198
|
+
request.user = user
|
|
199
|
+
request.registry = social_config.registry
|
|
200
|
+
request.remote_addr = u'127.0.0.123'
|
|
201
|
+
request.context = AuthenticationComplete(profile, credentials, provider_name, provider_type)
|
|
202
|
+
request._ = lambda msg, *args, **kwargs: msg
|
|
203
|
+
|
|
204
|
+
request.login_perform = MagicMock(name='login_perform')
|
|
205
|
+
request.login_perform.return_value = {'status': True}
|
|
206
|
+
view = SocialLoginViews(request)
|
|
207
|
+
out = view()
|
|
208
|
+
# status should be false
|
|
209
|
+
assert out['status'] is False
|
|
210
|
+
assert out['msg'] == 'Your account is already connected to other ${provider} account.'
|
|
211
|
+
assert user.provider_id('facebook') is not profile['accounts'][0]['userid']
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
def test_logged_social_connect_used_account(social_config, facebook_user, db_session):
|
|
215
|
+
"""Try to connect facebook account to logged in user used by other user."""
|
|
216
|
+
# this user will be logged and trying to connect facebook's user account.
|
|
217
|
+
fresh_user = User(
|
|
218
|
+
email='new@user.pl',
|
|
219
|
+
password='somepassword',
|
|
220
|
+
address_ip='127.0.0.1')
|
|
221
|
+
db_session.add(fresh_user)
|
|
222
|
+
transaction.commit()
|
|
223
|
+
user = db_session.merge(facebook_user)
|
|
224
|
+
fresh_user = db_session.merge(fresh_user)
|
|
225
|
+
|
|
226
|
+
# mock request
|
|
227
|
+
profile = {
|
|
228
|
+
'accounts': [{'domain': u'facebook.com', 'userid': user.provider_id('facebook')}],
|
|
229
|
+
'displayName': u'teddy',
|
|
230
|
+
'preferredUsername': u'teddy',
|
|
231
|
+
'emails': [{'value': u'aasd@basd.pl'}],
|
|
232
|
+
'name': u'ted'
|
|
233
|
+
}
|
|
234
|
+
credentials = {'oauthAccessToken': '7897048593434'}
|
|
235
|
+
provider_name = u'facebook'
|
|
236
|
+
provider_type = u'facebook'
|
|
237
|
+
request = testing.DummyRequest()
|
|
238
|
+
request.user = fresh_user
|
|
239
|
+
request.registry = social_config.registry
|
|
240
|
+
request.remote_addr = u'127.0.0.123'
|
|
241
|
+
request.context = AuthenticationComplete(profile, credentials, provider_name, provider_type)
|
|
242
|
+
request._ = lambda msg, *args, **kwargs: msg
|
|
243
|
+
|
|
244
|
+
request.login_perform = MagicMock(name='login_perform')
|
|
245
|
+
request.login_perform.return_value = {'status': True}
|
|
246
|
+
# call!
|
|
247
|
+
view = SocialLoginViews(request)
|
|
248
|
+
out = view()
|
|
249
|
+
# status should be false
|
|
250
|
+
assert out['status'] is False
|
|
251
|
+
assert out['msg'] == 'This ${provider} account is already connected with other account.'
|
|
252
|
+
transaction.begin()
|
|
253
|
+
fresh_user = db_session.merge(fresh_user)
|
|
254
|
+
assert fresh_user.provider_id('facebook') is None
|
|
Binary file
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Logout related tests."""
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
from tests.tools import authenticate, is_user_logged
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_logout(active_user, extended_app):
|
|
8
|
+
"""Check logout action."""
|
|
9
|
+
authenticate(extended_app)
|
|
10
|
+
assert is_user_logged(extended_app) is True
|
|
11
|
+
|
|
12
|
+
extended_app.get('/logout', status=302)
|
|
13
|
+
assert is_user_logged(extended_app) is False
|
|
14
|
+
res = extended_app.get('/secret', status=302)
|
|
15
|
+
assert res.status_code == 302
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_logout_login(active_user, extended_config, extended_app):
|
|
19
|
+
"""Check logout action with configured logout redirection."""
|
|
20
|
+
extended_config.registry['config'].fullauth.redirects.logout = 'login'
|
|
21
|
+
authenticate(extended_app)
|
|
22
|
+
assert is_user_logged(extended_app) is True
|
|
23
|
+
|
|
24
|
+
res = extended_app.get('/logout', status=302)
|
|
25
|
+
assert is_user_logged(extended_app) is False
|
|
26
|
+
# redirection should be done to login page.
|
|
27
|
+
assert '/login' in res.location
|
|
28
|
+
res = extended_app.get('/secret', status=302)
|
|
29
|
+
assert res.status_code == 302
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_automatic_logout(active_user, short_config, short_app):
|
|
33
|
+
"""Test automatic logout."""
|
|
34
|
+
timeout = short_config.registry['config']['fullauth']['AuthTkt']['timeout'] + 1
|
|
35
|
+
|
|
36
|
+
authenticate(short_app)
|
|
37
|
+
# Simulating inactivity
|
|
38
|
+
time.sleep(timeout)
|
|
39
|
+
res = short_app.get('/email/change')
|
|
40
|
+
assert res.headers['Location'] == 'http://localhost/login?after=%2Femail%2Fchange'
|
|
41
|
+
res = res.follow()
|
|
42
|
+
assert res.form
|
|
Binary file
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"""Registration related tests."""
|
|
2
|
+
from HTMLParser import HTMLParser
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
import transaction
|
|
6
|
+
from sqlalchemy.orm.exc import NoResultFound
|
|
7
|
+
|
|
8
|
+
from pyramid_fullauth.models import User
|
|
9
|
+
from tests.tools import DEFAULT_USER
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def test_register_view(default_app):
|
|
13
|
+
"""Display register form."""
|
|
14
|
+
res = default_app.get('/register')
|
|
15
|
+
assert res.form
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.mark.parametrize('email, password', (
|
|
19
|
+
# casual
|
|
20
|
+
(DEFAULT_USER['email'], DEFAULT_USER['password']),
|
|
21
|
+
# loooong password
|
|
22
|
+
(DEFAULT_USER['email'], DEFAULT_USER['password'] * 10000),
|
|
23
|
+
))
|
|
24
|
+
def test_register_success(db_session, default_app, email, password):
|
|
25
|
+
"""Register user successfully."""
|
|
26
|
+
assert db_session.query(User).count() == 0
|
|
27
|
+
|
|
28
|
+
res = default_app.get('/register')
|
|
29
|
+
res.form['email'] = email
|
|
30
|
+
res.form['password'] = password
|
|
31
|
+
res.form['confirm_password'] = password
|
|
32
|
+
res = res.form.submit(extra_environ={'REMOTE_ADDR': '0.0.0.0'})
|
|
33
|
+
transaction.commit()
|
|
34
|
+
|
|
35
|
+
user = db_session.query(User).filter(User.email == email).one()
|
|
36
|
+
|
|
37
|
+
# User should not have active account at this moment
|
|
38
|
+
assert user.is_active is not None
|
|
39
|
+
assert user.check_password(password)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_register_user_exists(db_session, user, default_app):
|
|
43
|
+
"""Trying to register existing user."""
|
|
44
|
+
res = default_app.get('/register')
|
|
45
|
+
res.form['email'] = DEFAULT_USER['email']
|
|
46
|
+
res.form['password'] = DEFAULT_USER['password']
|
|
47
|
+
res.form['confirm_password'] = DEFAULT_USER['password']
|
|
48
|
+
res = res.form.submit(extra_environ={'REMOTE_ADDR': '0.0.0.0'})
|
|
49
|
+
transaction.commit()
|
|
50
|
+
|
|
51
|
+
assert 'User with given e-mail already exists' in res.body
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@pytest.mark.parametrize('email, password, confirm_password, error', (
|
|
55
|
+
# no email
|
|
56
|
+
(None, DEFAULT_USER['password'], DEFAULT_USER['password'],
|
|
57
|
+
'E-mail is empty'),
|
|
58
|
+
# empty email
|
|
59
|
+
('', DEFAULT_USER['password'], DEFAULT_USER['password'],
|
|
60
|
+
'E-mail is empty'),
|
|
61
|
+
# not matching passwords
|
|
62
|
+
(DEFAULT_USER['email'], DEFAULT_USER['password'], DEFAULT_USER['password'] + 'Typo',
|
|
63
|
+
'Passwords don\'t match'),
|
|
64
|
+
# long, incorect email
|
|
65
|
+
(u'email' * 100 + '@wap.pl', DEFAULT_USER['password'], DEFAULT_USER['password'],
|
|
66
|
+
'Incorrect e-mail format'),
|
|
67
|
+
# too short password
|
|
68
|
+
(DEFAULT_USER['email'], '12', '12',
|
|
69
|
+
'Password is too short'),
|
|
70
|
+
# empty password
|
|
71
|
+
(DEFAULT_USER['email'], '', '', 'Please enter your password'),
|
|
72
|
+
))
|
|
73
|
+
def test_register_error(db_session, default_app, email, password, confirm_password, error):
|
|
74
|
+
"""Error in registration process."""
|
|
75
|
+
assert db_session.query(User).count() == 0
|
|
76
|
+
|
|
77
|
+
res = default_app.get('/register')
|
|
78
|
+
if email is not None:
|
|
79
|
+
res.form['email'] = email
|
|
80
|
+
res.form['password'] = password
|
|
81
|
+
res.form['confirm_password'] = confirm_password
|
|
82
|
+
res = res.form.submit(extra_environ={'REMOTE_ADDR': '0.0.0.0'})
|
|
83
|
+
transaction.commit()
|
|
84
|
+
|
|
85
|
+
assert error in HTMLParser().unescape(res.body)
|
|
86
|
+
assert db_session.query(User).count() == 0
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def test_register_wrong_csrf(db_session, default_app):
|
|
90
|
+
"""CSRF error during registration."""
|
|
91
|
+
assert db_session.query(User).count() == 0
|
|
92
|
+
|
|
93
|
+
res = default_app.get('/register')
|
|
94
|
+
res.form['email'] = DEFAULT_USER['email']
|
|
95
|
+
res.form['password'] = DEFAULT_USER['password']
|
|
96
|
+
res.form['confirm_password'] = DEFAULT_USER['password']
|
|
97
|
+
res.form['csrf_token'] = 'wrong_token'
|
|
98
|
+
res = res.form.submit(extra_environ={'REMOTE_ADDR': '0.0.0.0'},
|
|
99
|
+
status=401)
|
|
100
|
+
transaction.commit()
|
|
101
|
+
|
|
102
|
+
assert db_session.query(User).count() == 0
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def test_no_pass_confirm(db_session, nopassconfirm_app):
|
|
106
|
+
"""Register without password confirm option."""
|
|
107
|
+
assert db_session.query(User).count() == 0
|
|
108
|
+
|
|
109
|
+
res = nopassconfirm_app.get('/register')
|
|
110
|
+
res.form['email'] = DEFAULT_USER['email']
|
|
111
|
+
res.form['password'] = DEFAULT_USER['password']
|
|
112
|
+
res = res.form.submit(extra_environ={'REMOTE_ADDR': '0.0.0.0'})
|
|
113
|
+
|
|
114
|
+
assert 'Passwords don\'t match!' not in HTMLParser().unescape(res.body)
|
|
115
|
+
transaction.commit()
|
|
116
|
+
|
|
117
|
+
user = db_session.query(User).filter(User.email == DEFAULT_USER['email']).one()
|
|
118
|
+
|
|
119
|
+
# User should not have active account at this moment
|
|
120
|
+
assert user.is_active is not None
|
|
121
|
+
assert user.check_password(DEFAULT_USER['password'])
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def test_register_action_no_password_required(db_session, nopassregister_app):
|
|
125
|
+
"""Register without password required."""
|
|
126
|
+
with pytest.raises(NoResultFound):
|
|
127
|
+
db_session.query(User).filter(User.email == DEFAULT_USER['email']).one()
|
|
128
|
+
|
|
129
|
+
res = nopassregister_app.get('/register')
|
|
130
|
+
res.form['email'] = DEFAULT_USER['email']
|
|
131
|
+
res = res.form.submit(extra_environ={'REMOTE_ADDR': '0.0.0.0'})
|
|
132
|
+
transaction.commit()
|
|
133
|
+
|
|
134
|
+
db_session.query(User).filter(User.email == DEFAULT_USER['email']).one()
|
|
Binary file
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"""Reset password views."""
|
|
2
|
+
from HTMLParser import HTMLParser
|
|
3
|
+
import transaction
|
|
4
|
+
|
|
5
|
+
from pyramid_fullauth.models import User
|
|
6
|
+
|
|
7
|
+
NEW_PASSWORD = 'YouShallPass'
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def test_reset_view(default_app):
|
|
11
|
+
"""Simple get test."""
|
|
12
|
+
res = default_app.get('/password/reset')
|
|
13
|
+
assert res.form
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_reset_action(user, db_session, default_app):
|
|
17
|
+
"""Successful password reset request."""
|
|
18
|
+
user = db_session.merge(user)
|
|
19
|
+
assert user.reset_key is None
|
|
20
|
+
|
|
21
|
+
res = default_app.get('/password/reset')
|
|
22
|
+
res.form['email'] = user.email
|
|
23
|
+
res = res.form.submit()
|
|
24
|
+
|
|
25
|
+
transaction.commit()
|
|
26
|
+
|
|
27
|
+
user = db_session.query(User).filter(User.email == user.email).one()
|
|
28
|
+
assert user.reset_key is not None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def test_reset_email_not_exists(user, db_session, default_app):
|
|
32
|
+
"""Reset password request with wrong email (not in database)."""
|
|
33
|
+
user = db_session.merge(user)
|
|
34
|
+
|
|
35
|
+
res = default_app.get('/password/reset')
|
|
36
|
+
res.form['email'] = u'wrong@example.com'
|
|
37
|
+
res = res.form.submit()
|
|
38
|
+
assert 'Error! User does not exists' in res
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def test_reset_proceed(user, db_session, default_app):
|
|
42
|
+
"""Actually change password."""
|
|
43
|
+
user = db_session.merge(user)
|
|
44
|
+
user.set_reset()
|
|
45
|
+
transaction.commit()
|
|
46
|
+
|
|
47
|
+
user = db_session.merge(user)
|
|
48
|
+
res = default_app.get('/password/reset/' + user.reset_key)
|
|
49
|
+
assert 'Recover your password - choose new password' in res
|
|
50
|
+
|
|
51
|
+
res.form['password'] = NEW_PASSWORD
|
|
52
|
+
res.form['confirm_password'] = NEW_PASSWORD
|
|
53
|
+
res = res.form.submit()
|
|
54
|
+
|
|
55
|
+
user = db_session.query(User).filter(User.email == user.email).one()
|
|
56
|
+
assert user.reset_key is None
|
|
57
|
+
assert user.check_password(NEW_PASSWORD) is True
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_reset_proceed_wrong_reset_key(user, db_session, default_app):
|
|
61
|
+
"""Try changing password with wrong reset_key."""
|
|
62
|
+
user = db_session.merge(user)
|
|
63
|
+
user.set_reset()
|
|
64
|
+
transaction.commit()
|
|
65
|
+
|
|
66
|
+
user = db_session.merge(user)
|
|
67
|
+
res = default_app.get(
|
|
68
|
+
'/password/reset/' + user.reset_key + 'randomchars', status=404)
|
|
69
|
+
assert res.status_code == 404
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_reset_proceed_wrong_confirm(user, db_session, default_app):
|
|
73
|
+
"""Reset test for reseting pasword with notmatched passwords."""
|
|
74
|
+
user = db_session.merge(user)
|
|
75
|
+
user.set_reset()
|
|
76
|
+
transaction.commit()
|
|
77
|
+
|
|
78
|
+
user = db_session.merge(user)
|
|
79
|
+
res = default_app.get('/password/reset/' + user.reset_key)
|
|
80
|
+
|
|
81
|
+
res.form['password'] = NEW_PASSWORD
|
|
82
|
+
res.form['confirm_password'] = NEW_PASSWORD + 'Typo'
|
|
83
|
+
res = res.form.submit()
|
|
84
|
+
|
|
85
|
+
assert 'Error! Password doesn\'t match' in HTMLParser().unescape(res.body)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def test_reset_proceed_wrong_csrf(user, db_session, default_app):
|
|
89
|
+
"""Reset test for reseting pasword with notmatched csrf."""
|
|
90
|
+
user = db_session.merge(user)
|
|
91
|
+
user.set_reset()
|
|
92
|
+
transaction.commit()
|
|
93
|
+
|
|
94
|
+
user = db_session.merge(user)
|
|
95
|
+
res = default_app.get('/password/reset/' + user.reset_key)
|
|
96
|
+
|
|
97
|
+
res.form['password'] = NEW_PASSWORD
|
|
98
|
+
res.form['confirm_password'] = NEW_PASSWORD
|
|
99
|
+
res.form['csrf_token'] = 'sadasere723612dassdgaSDs7a'
|
|
100
|
+
res.form.submit(status=401)
|
|
Binary file
|