pyramid-fullauth 0.4.0__py3.3.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 +184 -0
- EGG-INFO/SOURCES.txt +93 -0
- EGG-INFO/dependency_links.txt +1 -0
- EGG-INFO/not-zip-safe +1 -0
- EGG-INFO/requires.txt +13 -0
- EGG-INFO/top_level.txt +2 -0
- pyramid_fullauth/__init__.py +106 -0
- pyramid_fullauth/__pycache__/__init__.cpython-33.pyc +0 -0
- pyramid_fullauth/__pycache__/auth.cpython-33.pyc +0 -0
- pyramid_fullauth/__pycache__/events.cpython-33.pyc +0 -0
- pyramid_fullauth/__pycache__/exceptions.cpython-33.pyc +0 -0
- pyramid_fullauth/__pycache__/request.cpython-33.pyc +0 -0
- pyramid_fullauth/__pycache__/tools.cpython-33.pyc +0 -0
- pyramid_fullauth/auth.py +67 -0
- pyramid_fullauth/config/default.yaml +26 -0
- pyramid_fullauth/events.py +281 -0
- pyramid_fullauth/exceptions.py +47 -0
- pyramid_fullauth/models/__init__.py +190 -0
- pyramid_fullauth/models/__pycache__/__init__.cpython-33.pyc +0 -0
- pyramid_fullauth/models/extensions/__init__.py +39 -0
- pyramid_fullauth/models/extensions/__pycache__/__init__.cpython-33.pyc +0 -0
- pyramid_fullauth/models/mixins/__init__.py +9 -0
- pyramid_fullauth/models/mixins/__pycache__/__init__.cpython-33.pyc +0 -0
- pyramid_fullauth/models/mixins/__pycache__/email.cpython-33.pyc +0 -0
- pyramid_fullauth/models/mixins/__pycache__/password.cpython-33.pyc +0 -0
- pyramid_fullauth/models/mixins/email.py +128 -0
- pyramid_fullauth/models/mixins/password.py +141 -0
- pyramid_fullauth/request.py +70 -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 +17 -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/__pycache__/__init__.cpython-33.pyc +0 -0
- pyramid_fullauth/routing/__pycache__/predicates.cpython-33.pyc +0 -0
- pyramid_fullauth/routing/predicates.py +86 -0
- pyramid_fullauth/tools.py +69 -0
- pyramid_fullauth/views/__init__.py +15 -0
- pyramid_fullauth/views/__pycache__/__init__.cpython-33.pyc +0 -0
- pyramid_fullauth/views/__pycache__/social.cpython-33.pyc +0 -0
- pyramid_fullauth/views/basic/__init__.py +5 -0
- pyramid_fullauth/views/basic/__pycache__/__init__.cpython-33.pyc +0 -0
- pyramid_fullauth/views/basic/__pycache__/activate.cpython-33.pyc +0 -0
- pyramid_fullauth/views/basic/__pycache__/forbidden.cpython-33.pyc +0 -0
- pyramid_fullauth/views/basic/__pycache__/login.cpython-33.pyc +0 -0
- pyramid_fullauth/views/basic/__pycache__/logout.cpython-33.pyc +0 -0
- pyramid_fullauth/views/basic/__pycache__/register.cpython-33.pyc +0 -0
- pyramid_fullauth/views/basic/activate.py +44 -0
- pyramid_fullauth/views/basic/forbidden.py +46 -0
- pyramid_fullauth/views/basic/login.py +128 -0
- pyramid_fullauth/views/basic/logout.py +28 -0
- pyramid_fullauth/views/basic/profile/__init__.py +5 -0
- pyramid_fullauth/views/basic/profile/__pycache__/__init__.cpython-33.pyc +0 -0
- pyramid_fullauth/views/basic/profile/__pycache__/email.cpython-33.pyc +0 -0
- pyramid_fullauth/views/basic/profile/__pycache__/password.cpython-33.pyc +0 -0
- pyramid_fullauth/views/basic/profile/email.py +108 -0
- pyramid_fullauth/views/basic/profile/password.py +129 -0
- pyramid_fullauth/views/basic/register.py +111 -0
- pyramid_fullauth/views/social.py +221 -0
- tests/__init__.py +1 -0
- tests/__pycache__/__init__.cpython-33.pyc +0 -0
- tests/__pycache__/conftest.cpython-33.pyc +0 -0
- tests/__pycache__/tools.cpython-33.pyc +0 -0
- tests/conftest.py +201 -0
- tests/tools.py +54 -0
- tests/unit/__pycache__/test_default_settings.cpython-33.pyc +0 -0
- tests/unit/__pycache__/test_groupfinder.cpython-33.pyc +0 -0
- tests/unit/__pycache__/test_social_view.cpython-33.pyc +0 -0
- tests/unit/__pycache__/test_tools.cpython-33.pyc +0 -0
- tests/unit/__pycache__/test_user_active.cpython-33.pyc +0 -0
- tests/unit/__pycache__/test_user_admin.cpython-33.pyc +0 -0
- tests/unit/__pycache__/test_user_email.cpython-33.pyc +0 -0
- tests/unit/__pycache__/test_user_password.cpython-33.pyc +0 -0
- tests/unit/__pycache__/test_user_providers.cpython-33.pyc +0 -0
- tests/unit/__pycache__/test_user_repr.cpython-33.pyc +0 -0
- tests/unit/__pycache__/test_validators.cpython-33.pyc +0 -0
- tests/unit/test_default_settings.py +15 -0
- tests/unit/test_groupfinder.py +20 -0
- tests/unit/test_social_view.py +69 -0
- tests/unit/test_tools.py +24 -0
- tests/unit/test_user_active.py +31 -0
- tests/unit/test_user_admin.py +61 -0
- tests/unit/test_user_email.py +37 -0
- tests/unit/test_user_password.py +52 -0
- tests/unit/test_user_providers.py +24 -0
- tests/unit/test_user_repr.py +29 -0
- tests/unit/test_validators.py +44 -0
- tests/views/__init__.py +1 -0
- tests/views/__pycache__/__init__.cpython-33.pyc +0 -0
- tests/views/__pycache__/conftest.cpython-33.pyc +0 -0
- tests/views/__pycache__/test_activation.cpython-33.pyc +0 -0
- tests/views/__pycache__/test_email.cpython-33.pyc +0 -0
- tests/views/__pycache__/test_events.cpython-33.pyc +0 -0
- tests/views/__pycache__/test_login.cpython-33.pyc +0 -0
- tests/views/__pycache__/test_login_social.cpython-33.pyc +0 -0
- tests/views/__pycache__/test_logout.cpython-33.pyc +0 -0
- tests/views/__pycache__/test_register.cpython-33.pyc +0 -0
- tests/views/__pycache__/test_reset.cpython-33.pyc +0 -0
- tests/views/conftest.py +20 -0
- tests/views/test_activation.py +86 -0
- tests/views/test_email.py +175 -0
- tests/views/test_events.py +558 -0
- tests/views/test_login.py +172 -0
- tests/views/test_login_social.py +289 -0
- tests/views/test_logout.py +42 -0
- tests/views/test_register.py +138 -0
- tests/views/test_reset.py +105 -0
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
"""All events related tests."""
|
|
2
|
+
import pytest
|
|
3
|
+
import transaction
|
|
4
|
+
from mock import MagicMock
|
|
5
|
+
from pyramid import testing
|
|
6
|
+
from pyramid.compat import text_type
|
|
7
|
+
from pyramid.view import view_config
|
|
8
|
+
from pyramid.httpexceptions import HTTPFound
|
|
9
|
+
from sqlalchemy.orm.exc import NoResultFound
|
|
10
|
+
from pytest_pyramid import factories
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from velruse import AuthenticationComplete
|
|
14
|
+
except ImportError:
|
|
15
|
+
# py3 version doesn't have social auth
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
from pyramid_fullauth.models import User
|
|
20
|
+
from pyramid_fullauth.views.social import SocialLoginViews
|
|
21
|
+
from pyramid_fullauth.events import (
|
|
22
|
+
BeforeLogIn, AfterLogIn, AlreadyLoggedIn,
|
|
23
|
+
BeforeEmailChange, AfterEmailChange, AfterEmailChangeActivation,
|
|
24
|
+
BeforeReset, AfterResetRequest, AfterReset,
|
|
25
|
+
AfterSocialRegister, AfterSocialLogIn, SocialAccountAlreadyConnected,
|
|
26
|
+
AfterActivate,
|
|
27
|
+
BeforeRegister, AfterRegister
|
|
28
|
+
)
|
|
29
|
+
from tests.tools import authenticate, is_user_logged, DEFAULT_USER
|
|
30
|
+
from tests.conftest import py2only
|
|
31
|
+
from tests.views.conftest import mock_translate
|
|
32
|
+
|
|
33
|
+
EVENT_PATH = '/event?event={0.__name__}'
|
|
34
|
+
EVENT_URL = 'http://localhost' + EVENT_PATH
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
evented_config = factories.pyramid_config({
|
|
38
|
+
'yml.location': 'tests:config',
|
|
39
|
+
'env': 'login',
|
|
40
|
+
'pyramid.includes': [
|
|
41
|
+
'pyramid_tm',
|
|
42
|
+
'pyramid_fullauth',
|
|
43
|
+
'tests.tools.include_views',
|
|
44
|
+
'tests.views.test_events.include_views'
|
|
45
|
+
]
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def include_views(config):
|
|
50
|
+
"""Dummy pyramid plugin including events."""
|
|
51
|
+
config.add_route('event', '/event')
|
|
52
|
+
config.scan('tests.views.test_events')
|
|
53
|
+
# config.add_subscriber(raise_attribute_error, BeforeLogIn)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@view_config(route_name="event", renderer='json')
|
|
57
|
+
def event_view(request):
|
|
58
|
+
"""Dummy view."""
|
|
59
|
+
return {'event', request.GET.get('event')}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def redirect_to_secret(event):
|
|
63
|
+
"""Redirect to event page with event name set as query event attribute."""
|
|
64
|
+
raise HTTPFound(
|
|
65
|
+
event.request.route_path(
|
|
66
|
+
'event', _query=(('event', event.__class__.__name__),)
|
|
67
|
+
))
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def raise_attribute_error(event):
|
|
71
|
+
"""Raise attribute error with message being the event class name."""
|
|
72
|
+
if event.user:
|
|
73
|
+
raise AttributeError(event.__class__.__name__)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@pytest.fixture
|
|
77
|
+
def alreadyloggedin_config(evented_config):
|
|
78
|
+
"""Add AlreadyLoggedIn event subscriber that redirects to event page."""
|
|
79
|
+
evented_config.add_subscriber(redirect_to_secret, AlreadyLoggedIn)
|
|
80
|
+
return evented_config
|
|
81
|
+
|
|
82
|
+
alreadyloggedin_app = factories.pyramid_app('alreadyloggedin_config')
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_default_login_redirect_from_event(active_user, alreadyloggedin_app):
|
|
86
|
+
"""After successful login, access to login page should result in redirect."""
|
|
87
|
+
authenticate(alreadyloggedin_app)
|
|
88
|
+
res = alreadyloggedin_app.get('/login', status=302)
|
|
89
|
+
assert res.location == EVENT_URL.format(AlreadyLoggedIn)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@pytest.fixture
|
|
93
|
+
def beforelogin_config(evented_config):
|
|
94
|
+
"""Add BeforeLogIn event that raises AttributeError with event class name."""
|
|
95
|
+
evented_config.add_subscriber(raise_attribute_error, BeforeLogIn)
|
|
96
|
+
return evented_config
|
|
97
|
+
|
|
98
|
+
beforelogin_app = factories.pyramid_app('beforelogin_config')
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def test_error_beforelogin(active_user, beforelogin_app):
|
|
102
|
+
"""Test errors from BeforeLogIn event."""
|
|
103
|
+
res = beforelogin_app.get('/login')
|
|
104
|
+
post_data = {
|
|
105
|
+
'email': DEFAULT_USER['email'],
|
|
106
|
+
'password': DEFAULT_USER['password'],
|
|
107
|
+
'csrf_token': res.form['csrf_token'].value
|
|
108
|
+
}
|
|
109
|
+
res = beforelogin_app.post('/login', post_data, xhr=True)
|
|
110
|
+
assert res.json['status'] is False
|
|
111
|
+
assert res.json['msg'] == 'BeforeLogIn'
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@pytest.fixture
|
|
115
|
+
def afterlogin_config(evented_config):
|
|
116
|
+
"""Add AfterLogIn event subscriber that redirects to event page."""
|
|
117
|
+
evented_config.add_subscriber(redirect_to_secret, AfterLogIn)
|
|
118
|
+
return evented_config
|
|
119
|
+
|
|
120
|
+
afterlogin_app = factories.pyramid_app('afterlogin_config')
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def test_login_redirect(active_user, afterlogin_app):
|
|
124
|
+
"""Log in and test redirect from AfterLogIn."""
|
|
125
|
+
assert is_user_logged(afterlogin_app) is False
|
|
126
|
+
|
|
127
|
+
res = authenticate(afterlogin_app)
|
|
128
|
+
assert res.location == EVENT_URL.format(AfterLogIn)
|
|
129
|
+
|
|
130
|
+
assert is_user_logged(afterlogin_app) is True
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@pytest.fixture
|
|
134
|
+
def afterloginerror_config(evented_config):
|
|
135
|
+
"""Add AfterLogIn event subscriber that raises AttributeError."""
|
|
136
|
+
evented_config.add_subscriber(raise_attribute_error, AfterLogIn)
|
|
137
|
+
return evented_config
|
|
138
|
+
|
|
139
|
+
afterloginerror_app = factories.pyramid_app('afterloginerror_config')
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
def test_error_afterlogin(active_user, afterloginerror_app):
|
|
143
|
+
"""Test errors from BeforeLogIn event."""
|
|
144
|
+
res = afterloginerror_app.get('/login')
|
|
145
|
+
post_data = {
|
|
146
|
+
'email': DEFAULT_USER['email'],
|
|
147
|
+
'password': DEFAULT_USER['password'],
|
|
148
|
+
'csrf_token': res.form['csrf_token'].value
|
|
149
|
+
}
|
|
150
|
+
res = afterloginerror_app.post('/login', post_data, xhr=True)
|
|
151
|
+
assert res.json['status'] is False
|
|
152
|
+
assert res.json['msg'] == 'AfterLogIn'
|
|
153
|
+
|
|
154
|
+
assert is_user_logged(afterloginerror_app) is False
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
@pytest.fixture
|
|
158
|
+
def beforeemailchange_config(evented_config):
|
|
159
|
+
"""Add BeforeEmailChange event subscriber that raises AttributeError."""
|
|
160
|
+
evented_config.add_subscriber(raise_attribute_error, BeforeEmailChange)
|
|
161
|
+
return evented_config
|
|
162
|
+
|
|
163
|
+
beforeemailchange_app = factories.pyramid_app('beforeemailchange_config')
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def test_beforeemailchange_error(active_user, beforeemailchange_app):
|
|
167
|
+
"""Raise AttributeError from BeforeEmailChange event."""
|
|
168
|
+
app = beforeemailchange_app
|
|
169
|
+
|
|
170
|
+
authenticate(app)
|
|
171
|
+
new_email = 'email@email.com'
|
|
172
|
+
|
|
173
|
+
res = app.get('/email/change')
|
|
174
|
+
res = app.post(
|
|
175
|
+
'/email/change',
|
|
176
|
+
{
|
|
177
|
+
'csrf_token': res.form['csrf_token'].value,
|
|
178
|
+
'email': new_email},
|
|
179
|
+
xhr=True)
|
|
180
|
+
assert res.json['status'] is False
|
|
181
|
+
assert res.json['msg'] == 'BeforeEmailChange'
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
@pytest.fixture
|
|
185
|
+
def afteremailchange_config(evented_config):
|
|
186
|
+
"""Add AfterEmailChange, AfterEmailChangeActivation event subscriber that redirects to event page."""
|
|
187
|
+
evented_config.add_subscriber(redirect_to_secret, AfterEmailChange)
|
|
188
|
+
evented_config.add_subscriber(redirect_to_secret, AfterEmailChangeActivation)
|
|
189
|
+
return evented_config
|
|
190
|
+
|
|
191
|
+
afteremailchange_app = factories.pyramid_app('afteremailchange_config')
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def test_afteremailchange(db_session, active_user, afteremailchange_app):
|
|
195
|
+
"""Redirect after successful email change request."""
|
|
196
|
+
app = afteremailchange_app
|
|
197
|
+
|
|
198
|
+
authenticate(app)
|
|
199
|
+
email = DEFAULT_USER['email']
|
|
200
|
+
new_email = 'email@email.com'
|
|
201
|
+
|
|
202
|
+
user = db_session.query(User).filter(User.email == email).one()
|
|
203
|
+
|
|
204
|
+
res = app.get('/email/change')
|
|
205
|
+
form = res.form
|
|
206
|
+
form['email'] = new_email
|
|
207
|
+
res = form.submit()
|
|
208
|
+
assert res.location == EVENT_URL.format(AfterEmailChange)
|
|
209
|
+
|
|
210
|
+
transaction.commit()
|
|
211
|
+
|
|
212
|
+
user = db_session.query(User).filter(User.email == email).one()
|
|
213
|
+
assert user.new_email == new_email
|
|
214
|
+
assert user.email == email
|
|
215
|
+
assert user.email_change_key is not None
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def test_afteremailchange_xhr(db_session, active_user, afteremailchange_app):
|
|
219
|
+
"""Change email with valid data."""
|
|
220
|
+
app = afteremailchange_app
|
|
221
|
+
|
|
222
|
+
authenticate(app)
|
|
223
|
+
email = DEFAULT_USER['email']
|
|
224
|
+
new_email = 'email@email.com'
|
|
225
|
+
|
|
226
|
+
user = db_session.query(User).filter(User.email == email).one()
|
|
227
|
+
|
|
228
|
+
res = app.get('/email/change')
|
|
229
|
+
res = app.post(
|
|
230
|
+
'/email/change',
|
|
231
|
+
{
|
|
232
|
+
'csrf_token': res.form['csrf_token'].value,
|
|
233
|
+
'email': new_email},
|
|
234
|
+
xhr=True)
|
|
235
|
+
assert res.json['status'] is True
|
|
236
|
+
assert res.json['url'] == EVENT_PATH.format(AfterEmailChange)
|
|
237
|
+
|
|
238
|
+
transaction.commit()
|
|
239
|
+
|
|
240
|
+
user = db_session.query(User).filter(User.email == email).one()
|
|
241
|
+
assert user.new_email == new_email
|
|
242
|
+
assert user.email == email
|
|
243
|
+
assert user.email_change_key is not None
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def test_afteremailchangeactivation(db_session, active_user, afteremailchange_app):
|
|
247
|
+
"""Confirm email change view with redirect from AfterEmailChangeActivation."""
|
|
248
|
+
app = afteremailchange_app
|
|
249
|
+
# login user
|
|
250
|
+
authenticate(app)
|
|
251
|
+
|
|
252
|
+
email = DEFAULT_USER['email']
|
|
253
|
+
user = db_session.query(User).filter(User.email == email).one()
|
|
254
|
+
|
|
255
|
+
new_email = text_type('email2@email.com')
|
|
256
|
+
user.set_new_email(new_email)
|
|
257
|
+
transaction.commit()
|
|
258
|
+
|
|
259
|
+
user = db_session.merge(user)
|
|
260
|
+
res = app.get('/email/change/' + user.email_change_key)
|
|
261
|
+
assert res.status_code == 302
|
|
262
|
+
assert res.location == EVENT_URL.format(AfterEmailChangeActivation)
|
|
263
|
+
|
|
264
|
+
with pytest.raises(NoResultFound):
|
|
265
|
+
# there is no user with old email
|
|
266
|
+
db_session.query(User).filter(User.email == email).one()
|
|
267
|
+
|
|
268
|
+
user = db_session.query(User).filter(User.email == new_email).one()
|
|
269
|
+
assert not user.email_change_key
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
@pytest.fixture
|
|
273
|
+
def afterreset_config(evented_config):
|
|
274
|
+
"""Add AfterReset, AfterResetRequest event subscriber that redirects to event page."""
|
|
275
|
+
evented_config.add_subscriber(redirect_to_secret, AfterResetRequest)
|
|
276
|
+
evented_config.add_subscriber(redirect_to_secret, AfterReset)
|
|
277
|
+
return evented_config
|
|
278
|
+
|
|
279
|
+
afterreset_app = factories.pyramid_app('afterreset_config')
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def test_afterresetrequest(user, db_session, afterreset_app):
|
|
283
|
+
"""Successful password reset request with redirect from AfterResetRequest."""
|
|
284
|
+
user = db_session.merge(user)
|
|
285
|
+
assert user.reset_key is None
|
|
286
|
+
|
|
287
|
+
res = afterreset_app.get('/password/reset')
|
|
288
|
+
res.form['email'] = user.email
|
|
289
|
+
res = res.form.submit()
|
|
290
|
+
assert res.location == EVENT_URL.format(AfterResetRequest)
|
|
291
|
+
|
|
292
|
+
transaction.commit()
|
|
293
|
+
|
|
294
|
+
user = db_session.query(User).filter(User.email == user.email).one()
|
|
295
|
+
assert user.reset_key is not None
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
def test_afterreset(user, db_session, afterreset_app):
|
|
299
|
+
"""Actually change password with redirect from AfterReset."""
|
|
300
|
+
user = db_session.merge(user)
|
|
301
|
+
user.set_reset()
|
|
302
|
+
transaction.commit()
|
|
303
|
+
|
|
304
|
+
user = db_session.merge(user)
|
|
305
|
+
res = afterreset_app.get('/password/reset/' + user.reset_key)
|
|
306
|
+
|
|
307
|
+
res.form['password'] = 'YouShallPass'
|
|
308
|
+
res.form['confirm_password'] = 'YouShallPass'
|
|
309
|
+
res = res.form.submit()
|
|
310
|
+
assert res.location == EVENT_URL.format(AfterReset)
|
|
311
|
+
|
|
312
|
+
user = db_session.query(User).filter(User.email == user.email).one()
|
|
313
|
+
assert user.reset_key is None
|
|
314
|
+
assert user.check_password('YouShallPass') is True
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
@pytest.fixture
|
|
318
|
+
def beforereset_config(evented_config):
|
|
319
|
+
"""Add BeforeReset event subscriber that raises AttributeError."""
|
|
320
|
+
evented_config.add_subscriber(raise_attribute_error, BeforeReset)
|
|
321
|
+
return evented_config
|
|
322
|
+
|
|
323
|
+
beforereset_app = factories.pyramid_app('beforereset_config')
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def test_beforereset(user, db_session, beforereset_app):
|
|
327
|
+
"""Error thrown from BeforeReset event."""
|
|
328
|
+
user = db_session.merge(user)
|
|
329
|
+
user.set_reset()
|
|
330
|
+
transaction.commit()
|
|
331
|
+
|
|
332
|
+
user = db_session.merge(user)
|
|
333
|
+
res = beforereset_app.get('/password/reset/' + user.reset_key)
|
|
334
|
+
|
|
335
|
+
res.form['password'] = 'YouShallPass'
|
|
336
|
+
res.form['confirm_password'] = 'YouShallPass'
|
|
337
|
+
res = res.form.submit()
|
|
338
|
+
assert 'Error! BeforeReset' in res.body.decode('unicode_escape')
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
@pytest.fixture
|
|
342
|
+
def aftersocialregister_config(evented_config):
|
|
343
|
+
"""Add AfterSocialRegister event subscriber that redirects to event page."""
|
|
344
|
+
evented_config.add_subscriber(redirect_to_secret, AfterSocialRegister)
|
|
345
|
+
return evented_config
|
|
346
|
+
|
|
347
|
+
aftersocialregister_app = factories.pyramid_app('aftersocialregister_config')
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
@py2only
|
|
351
|
+
def test_aftersocialregister(aftersocialregister_config, aftersocialregister_app, db_session):
|
|
352
|
+
"""Register fresh user and logs him in and check response if redirect from AfterSocialRegister."""
|
|
353
|
+
profile = {
|
|
354
|
+
'accounts': [{'domain': text_type('facebook.com'), 'userid': text_type('2343')}],
|
|
355
|
+
'displayName': text_type('teddy'),
|
|
356
|
+
'verifiedEmail': text_type('we@po.pl'),
|
|
357
|
+
'preferredUsername': text_type('teddy'),
|
|
358
|
+
'emails': [{'value': text_type('aasd@bwwqwe.pl')}],
|
|
359
|
+
'name': text_type('ted')
|
|
360
|
+
}
|
|
361
|
+
credentials = {'oauthAccessToken': '7897048593434'}
|
|
362
|
+
provider_name = text_type('facebook')
|
|
363
|
+
provider_type = text_type('facebook')
|
|
364
|
+
request = testing.DummyRequest()
|
|
365
|
+
request.user = None
|
|
366
|
+
request.registry = aftersocialregister_config.registry
|
|
367
|
+
request.remote_addr = text_type('127.0.0.123')
|
|
368
|
+
request.context = AuthenticationComplete(profile, credentials, provider_name, provider_type)
|
|
369
|
+
|
|
370
|
+
request.login_perform = MagicMock(name='login_perform')
|
|
371
|
+
request.login_perform.return_value = {'status': True}
|
|
372
|
+
view = SocialLoginViews(request)
|
|
373
|
+
out = view()
|
|
374
|
+
assert out.location == EVENT_PATH.format(AfterSocialRegister)
|
|
375
|
+
transaction.commit()
|
|
376
|
+
|
|
377
|
+
# read first new account
|
|
378
|
+
user = db_session.query(User).one()
|
|
379
|
+
assert user.is_active
|
|
380
|
+
assert user.provider_id('facebook') == profile['accounts'][0]['userid']
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
@pytest.fixture
|
|
384
|
+
def aftersociallogin_config(evented_config):
|
|
385
|
+
"""Add AfterSocialLogIn event subscriber that redirects to event page."""
|
|
386
|
+
evented_config.add_subscriber(redirect_to_secret, AfterSocialLogIn)
|
|
387
|
+
return evented_config
|
|
388
|
+
|
|
389
|
+
aftersociallogin_app = factories.pyramid_app('aftersociallogin_config')
|
|
390
|
+
|
|
391
|
+
|
|
392
|
+
@py2only
|
|
393
|
+
def test_aftersociallogin(aftersociallogin_config, aftersociallogin_app, db_session):
|
|
394
|
+
"""Register fresh user and logs him in and check response if redirect from AfterSocialLogIn."""
|
|
395
|
+
profile = {
|
|
396
|
+
'accounts': [{'domain': text_type('facebook.com'), 'userid': text_type('2343')}],
|
|
397
|
+
'displayName': text_type('teddy'),
|
|
398
|
+
'verifiedEmail': text_type('we@po.pl'),
|
|
399
|
+
'preferredUsername': text_type('teddy'),
|
|
400
|
+
'emails': [{'value': text_type('aasd@bwwqwe.pl')}],
|
|
401
|
+
'name': text_type('ted')
|
|
402
|
+
}
|
|
403
|
+
credentials = {'oauthAccessToken': '7897048593434'}
|
|
404
|
+
provider_name = text_type('facebook')
|
|
405
|
+
provider_type = text_type('facebook')
|
|
406
|
+
request = testing.DummyRequest()
|
|
407
|
+
request.user = None
|
|
408
|
+
request.registry = aftersociallogin_config.registry
|
|
409
|
+
request.remote_addr = text_type('127.0.0.123')
|
|
410
|
+
request.context = AuthenticationComplete(profile, credentials, provider_name, provider_type)
|
|
411
|
+
|
|
412
|
+
def login_perform(*args, **kwargs):
|
|
413
|
+
return HTTPFound(location=kwargs['location'])
|
|
414
|
+
request.login_perform = login_perform
|
|
415
|
+
view = SocialLoginViews(request)
|
|
416
|
+
out = view()
|
|
417
|
+
assert out.location == EVENT_PATH.format(AfterSocialLogIn)
|
|
418
|
+
transaction.commit()
|
|
419
|
+
|
|
420
|
+
# read first new account
|
|
421
|
+
user = db_session.query(User).one()
|
|
422
|
+
assert user.is_active
|
|
423
|
+
assert user.provider_id('facebook') == profile['accounts'][0]['userid']
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
@pytest.fixture
|
|
427
|
+
def alreadyconnected_config(evented_config):
|
|
428
|
+
"""Add SocialAccountAlreadyConnected event subscriber that redirects to event page."""
|
|
429
|
+
evented_config.add_subscriber(redirect_to_secret, SocialAccountAlreadyConnected)
|
|
430
|
+
return evented_config
|
|
431
|
+
|
|
432
|
+
alreadyconnected_app = factories.pyramid_app('alreadyconnected_config')
|
|
433
|
+
|
|
434
|
+
|
|
435
|
+
@py2only
|
|
436
|
+
def test_alreadyconnected(alreadyconnected_config, alreadyconnected_app, facebook_user, db_session):
|
|
437
|
+
"""Try to connect facebook account to logged in user used by other user check redirect from SocialAccountAlreadyConnected."""
|
|
438
|
+
# this user will be logged and trying to connect facebook's user account.
|
|
439
|
+
fresh_user = User(
|
|
440
|
+
email=text_type('new@user.pl'),
|
|
441
|
+
password=text_type('somepassword'),
|
|
442
|
+
address_ip=text_type('127.0.0.1')
|
|
443
|
+
)
|
|
444
|
+
db_session.add(fresh_user)
|
|
445
|
+
transaction.commit()
|
|
446
|
+
user = db_session.merge(facebook_user)
|
|
447
|
+
fresh_user = db_session.merge(fresh_user)
|
|
448
|
+
|
|
449
|
+
# mock request
|
|
450
|
+
profile = {
|
|
451
|
+
'accounts': [{'domain': text_type('facebook.com'), 'userid': user.provider_id('facebook')}],
|
|
452
|
+
'displayName': text_type('teddy'),
|
|
453
|
+
'preferredUsername': text_type('teddy'),
|
|
454
|
+
'emails': [{'value': text_type('aasd@basd.pl')}],
|
|
455
|
+
'name': text_type('ted')
|
|
456
|
+
}
|
|
457
|
+
credentials = {'oauthAccessToken': '7897048593434'}
|
|
458
|
+
provider_name = text_type('facebook')
|
|
459
|
+
provider_type = text_type('facebook')
|
|
460
|
+
request = testing.DummyRequest()
|
|
461
|
+
request.user = fresh_user
|
|
462
|
+
request.registry = alreadyconnected_config.registry
|
|
463
|
+
request.remote_addr = text_type('127.0.0.123')
|
|
464
|
+
request.context = AuthenticationComplete(profile, credentials, provider_name, provider_type)
|
|
465
|
+
request._ = mock_translate
|
|
466
|
+
|
|
467
|
+
request.login_perform = MagicMock(name='login_perform')
|
|
468
|
+
request.login_perform.return_value = {'status': True}
|
|
469
|
+
# call!
|
|
470
|
+
view = SocialLoginViews(request)
|
|
471
|
+
out = view()
|
|
472
|
+
assert out.location == EVENT_PATH.format(SocialAccountAlreadyConnected)
|
|
473
|
+
transaction.begin()
|
|
474
|
+
fresh_user = db_session.merge(fresh_user)
|
|
475
|
+
assert fresh_user.provider_id('facebook') is None
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
@pytest.fixture
|
|
479
|
+
def afteractivate_config(evented_config):
|
|
480
|
+
"""Add AfterActivate event subscriber that redirects to event page."""
|
|
481
|
+
evented_config.add_subscriber(redirect_to_secret, AfterActivate)
|
|
482
|
+
return evented_config
|
|
483
|
+
|
|
484
|
+
afteractivate_app = factories.pyramid_app('afteractivate_config')
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
def test_afteractivate(user, db_session, afteractivate_app):
|
|
488
|
+
"""Activate user adn check redirect through AfterActivate."""
|
|
489
|
+
user = db_session.merge(user)
|
|
490
|
+
|
|
491
|
+
res = afteractivate_app.get('/register/activate/' + user.activate_key)
|
|
492
|
+
assert res.location == EVENT_URL.format(AfterActivate)
|
|
493
|
+
transaction.commit()
|
|
494
|
+
user = db_session.query(User).filter(User.email == user.email).one()
|
|
495
|
+
|
|
496
|
+
assert not user.activate_key
|
|
497
|
+
assert user.is_active
|
|
498
|
+
assert user.activated_at
|
|
499
|
+
|
|
500
|
+
authenticate(afteractivate_app)
|
|
501
|
+
assert is_user_logged(afteractivate_app) is True
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
@pytest.fixture
|
|
505
|
+
def beforeregister_config(evented_config):
|
|
506
|
+
"""Add BeforeRegister event subscriber that raises AttributeError."""
|
|
507
|
+
evented_config.add_subscriber(raise_attribute_error, BeforeRegister)
|
|
508
|
+
return evented_config
|
|
509
|
+
|
|
510
|
+
beforeregister_app = factories.pyramid_app('beforeregister_config')
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
def test_beforeregister(db_session, beforeregister_app):
|
|
514
|
+
"""Register user check eror catching from BeforeRegister event."""
|
|
515
|
+
assert db_session.query(User).count() == 0
|
|
516
|
+
|
|
517
|
+
res = beforeregister_app.get('/register')
|
|
518
|
+
res = beforeregister_app.post(
|
|
519
|
+
'/register',
|
|
520
|
+
{
|
|
521
|
+
'csrf_token': res.form['csrf_token'].value,
|
|
522
|
+
'email': 'test@test.co.uk',
|
|
523
|
+
'password': 'passmeplease',
|
|
524
|
+
'confirm_password': 'passmeplease'
|
|
525
|
+
},
|
|
526
|
+
extra_environ={'REMOTE_ADDR': '0.0.0.0'},
|
|
527
|
+
xhr=True)
|
|
528
|
+
assert res.json['errors']['msg'] == 'BeforeRegister'
|
|
529
|
+
|
|
530
|
+
|
|
531
|
+
@pytest.fixture
|
|
532
|
+
def afterregister_config(evented_config):
|
|
533
|
+
"""Add AfterRegister event subscriber that redirects to event page."""
|
|
534
|
+
evented_config.add_subscriber(redirect_to_secret, AfterRegister)
|
|
535
|
+
return evented_config
|
|
536
|
+
|
|
537
|
+
afteraregister_app = factories.pyramid_app('afterregister_config')
|
|
538
|
+
|
|
539
|
+
|
|
540
|
+
def test_afterregister(db_session, afteraregister_app):
|
|
541
|
+
"""Register user check eror catching from BeforeRegister event."""
|
|
542
|
+
assert db_session.query(User).count() == 0
|
|
543
|
+
email = 'test@test.co.uk'
|
|
544
|
+
password = 'passmeplease'
|
|
545
|
+
|
|
546
|
+
res = afteraregister_app.get('/register')
|
|
547
|
+
res.form['email'] = email
|
|
548
|
+
res.form['password'] = password
|
|
549
|
+
res.form['confirm_password'] = password
|
|
550
|
+
res = res.form.submit(extra_environ={'REMOTE_ADDR': '0.0.0.0'})
|
|
551
|
+
assert res.location == EVENT_URL.format(AfterRegister)
|
|
552
|
+
transaction.commit()
|
|
553
|
+
|
|
554
|
+
user = db_session.query(User).filter(User.email == email).one()
|
|
555
|
+
|
|
556
|
+
# User should not have active account at this moment
|
|
557
|
+
assert user.is_active is not None
|
|
558
|
+
assert user.check_password(password)
|