pyramid-fullauth 0.4.0__py3.4.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 (116) hide show
  1. EGG-INFO/PKG-INFO +184 -0
  2. EGG-INFO/SOURCES.txt +93 -0
  3. EGG-INFO/dependency_links.txt +1 -0
  4. EGG-INFO/not-zip-safe +1 -0
  5. EGG-INFO/requires.txt +13 -0
  6. EGG-INFO/top_level.txt +2 -0
  7. pyramid_fullauth/__init__.py +106 -0
  8. pyramid_fullauth/__pycache__/__init__.cpython-34.pyc +0 -0
  9. pyramid_fullauth/__pycache__/auth.cpython-34.pyc +0 -0
  10. pyramid_fullauth/__pycache__/events.cpython-34.pyc +0 -0
  11. pyramid_fullauth/__pycache__/exceptions.cpython-34.pyc +0 -0
  12. pyramid_fullauth/__pycache__/request.cpython-34.pyc +0 -0
  13. pyramid_fullauth/__pycache__/tools.cpython-34.pyc +0 -0
  14. pyramid_fullauth/auth.py +67 -0
  15. pyramid_fullauth/config/default.yaml +26 -0
  16. pyramid_fullauth/events.py +281 -0
  17. pyramid_fullauth/exceptions.py +47 -0
  18. pyramid_fullauth/models/__init__.py +190 -0
  19. pyramid_fullauth/models/__pycache__/__init__.cpython-34.pyc +0 -0
  20. pyramid_fullauth/models/extensions/__init__.py +39 -0
  21. pyramid_fullauth/models/extensions/__pycache__/__init__.cpython-34.pyc +0 -0
  22. pyramid_fullauth/models/mixins/__init__.py +9 -0
  23. pyramid_fullauth/models/mixins/__pycache__/__init__.cpython-34.pyc +0 -0
  24. pyramid_fullauth/models/mixins/__pycache__/email.cpython-34.pyc +0 -0
  25. pyramid_fullauth/models/mixins/__pycache__/password.cpython-34.pyc +0 -0
  26. pyramid_fullauth/models/mixins/email.py +128 -0
  27. pyramid_fullauth/models/mixins/password.py +141 -0
  28. pyramid_fullauth/request.py +70 -0
  29. pyramid_fullauth/resources/helpers/social.mako +17 -0
  30. pyramid_fullauth/resources/locale/pyramid_fullauth.pot +216 -0
  31. pyramid_fullauth/resources/templates/403.mako +11 -0
  32. pyramid_fullauth/resources/templates/_form.login.mako +44 -0
  33. pyramid_fullauth/resources/templates/_form.register.mako +47 -0
  34. pyramid_fullauth/resources/templates/_social.login.mako +17 -0
  35. pyramid_fullauth/resources/templates/activate.mako +14 -0
  36. pyramid_fullauth/resources/templates/email_change.mako +33 -0
  37. pyramid_fullauth/resources/templates/layout.mako +13 -0
  38. pyramid_fullauth/resources/templates/login.mako +17 -0
  39. pyramid_fullauth/resources/templates/register.mako +22 -0
  40. pyramid_fullauth/resources/templates/reset.mako +34 -0
  41. pyramid_fullauth/resources/templates/reset.proceed.mako +41 -0
  42. pyramid_fullauth/routing/__init__.py +5 -0
  43. pyramid_fullauth/routing/__pycache__/__init__.cpython-34.pyc +0 -0
  44. pyramid_fullauth/routing/__pycache__/predicates.cpython-34.pyc +0 -0
  45. pyramid_fullauth/routing/predicates.py +86 -0
  46. pyramid_fullauth/tools.py +69 -0
  47. pyramid_fullauth/views/__init__.py +15 -0
  48. pyramid_fullauth/views/__pycache__/__init__.cpython-34.pyc +0 -0
  49. pyramid_fullauth/views/__pycache__/social.cpython-34.pyc +0 -0
  50. pyramid_fullauth/views/basic/__init__.py +5 -0
  51. pyramid_fullauth/views/basic/__pycache__/__init__.cpython-34.pyc +0 -0
  52. pyramid_fullauth/views/basic/__pycache__/activate.cpython-34.pyc +0 -0
  53. pyramid_fullauth/views/basic/__pycache__/forbidden.cpython-34.pyc +0 -0
  54. pyramid_fullauth/views/basic/__pycache__/login.cpython-34.pyc +0 -0
  55. pyramid_fullauth/views/basic/__pycache__/logout.cpython-34.pyc +0 -0
  56. pyramid_fullauth/views/basic/__pycache__/register.cpython-34.pyc +0 -0
  57. pyramid_fullauth/views/basic/activate.py +44 -0
  58. pyramid_fullauth/views/basic/forbidden.py +46 -0
  59. pyramid_fullauth/views/basic/login.py +128 -0
  60. pyramid_fullauth/views/basic/logout.py +28 -0
  61. pyramid_fullauth/views/basic/profile/__init__.py +5 -0
  62. pyramid_fullauth/views/basic/profile/__pycache__/__init__.cpython-34.pyc +0 -0
  63. pyramid_fullauth/views/basic/profile/__pycache__/email.cpython-34.pyc +0 -0
  64. pyramid_fullauth/views/basic/profile/__pycache__/password.cpython-34.pyc +0 -0
  65. pyramid_fullauth/views/basic/profile/email.py +108 -0
  66. pyramid_fullauth/views/basic/profile/password.py +129 -0
  67. pyramid_fullauth/views/basic/register.py +111 -0
  68. pyramid_fullauth/views/social.py +221 -0
  69. tests/__init__.py +1 -0
  70. tests/__pycache__/__init__.cpython-34.pyc +0 -0
  71. tests/__pycache__/conftest.cpython-34.pyc +0 -0
  72. tests/__pycache__/tools.cpython-34.pyc +0 -0
  73. tests/conftest.py +201 -0
  74. tests/tools.py +54 -0
  75. tests/unit/__pycache__/test_default_settings.cpython-34.pyc +0 -0
  76. tests/unit/__pycache__/test_groupfinder.cpython-34.pyc +0 -0
  77. tests/unit/__pycache__/test_social_view.cpython-34.pyc +0 -0
  78. tests/unit/__pycache__/test_tools.cpython-34.pyc +0 -0
  79. tests/unit/__pycache__/test_user_active.cpython-34.pyc +0 -0
  80. tests/unit/__pycache__/test_user_admin.cpython-34.pyc +0 -0
  81. tests/unit/__pycache__/test_user_email.cpython-34.pyc +0 -0
  82. tests/unit/__pycache__/test_user_password.cpython-34.pyc +0 -0
  83. tests/unit/__pycache__/test_user_providers.cpython-34.pyc +0 -0
  84. tests/unit/__pycache__/test_user_repr.cpython-34.pyc +0 -0
  85. tests/unit/__pycache__/test_validators.cpython-34.pyc +0 -0
  86. tests/unit/test_default_settings.py +15 -0
  87. tests/unit/test_groupfinder.py +20 -0
  88. tests/unit/test_social_view.py +69 -0
  89. tests/unit/test_tools.py +24 -0
  90. tests/unit/test_user_active.py +31 -0
  91. tests/unit/test_user_admin.py +61 -0
  92. tests/unit/test_user_email.py +37 -0
  93. tests/unit/test_user_password.py +52 -0
  94. tests/unit/test_user_providers.py +24 -0
  95. tests/unit/test_user_repr.py +29 -0
  96. tests/unit/test_validators.py +44 -0
  97. tests/views/__init__.py +1 -0
  98. tests/views/__pycache__/__init__.cpython-34.pyc +0 -0
  99. tests/views/__pycache__/conftest.cpython-34.pyc +0 -0
  100. tests/views/__pycache__/test_activation.cpython-34.pyc +0 -0
  101. tests/views/__pycache__/test_email.cpython-34.pyc +0 -0
  102. tests/views/__pycache__/test_events.cpython-34.pyc +0 -0
  103. tests/views/__pycache__/test_login.cpython-34.pyc +0 -0
  104. tests/views/__pycache__/test_login_social.cpython-34.pyc +0 -0
  105. tests/views/__pycache__/test_logout.cpython-34.pyc +0 -0
  106. tests/views/__pycache__/test_register.cpython-34.pyc +0 -0
  107. tests/views/__pycache__/test_reset.cpython-34.pyc +0 -0
  108. tests/views/conftest.py +20 -0
  109. tests/views/test_activation.py +86 -0
  110. tests/views/test_email.py +175 -0
  111. tests/views/test_events.py +558 -0
  112. tests/views/test_login.py +172 -0
  113. tests/views/test_login_social.py +289 -0
  114. tests/views/test_logout.py +42 -0
  115. tests/views/test_register.py +138 -0
  116. 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)