pyramid-fullauth 0.3.0__py2.7.egg

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. EGG-INFO/PKG-INFO +176 -0
  2. EGG-INFO/SOURCES.txt +91 -0
  3. EGG-INFO/dependency_links.txt +1 -0
  4. EGG-INFO/not-zip-safe +1 -0
  5. EGG-INFO/requires.txt +17 -0
  6. EGG-INFO/top_level.txt +2 -0
  7. pyramid_fullauth/__init__.py +105 -0
  8. pyramid_fullauth/__init__.pyc +0 -0
  9. pyramid_fullauth/auth.py +66 -0
  10. pyramid_fullauth/auth.pyc +0 -0
  11. pyramid_fullauth/events.py +267 -0
  12. pyramid_fullauth/events.pyc +0 -0
  13. pyramid_fullauth/exceptions.py +47 -0
  14. pyramid_fullauth/exceptions.pyc +0 -0
  15. pyramid_fullauth/models/__init__.py +189 -0
  16. pyramid_fullauth/models/__init__.pyc +0 -0
  17. pyramid_fullauth/models/mixins/__init__.py +9 -0
  18. pyramid_fullauth/models/mixins/__init__.pyc +0 -0
  19. pyramid_fullauth/models/mixins/email.py +81 -0
  20. pyramid_fullauth/models/mixins/email.pyc +0 -0
  21. pyramid_fullauth/models/mixins/password.py +141 -0
  22. pyramid_fullauth/models/mixins/password.pyc +0 -0
  23. pyramid_fullauth/request.py +69 -0
  24. pyramid_fullauth/request.pyc +0 -0
  25. pyramid_fullauth/resources/helpers/social.mako +17 -0
  26. pyramid_fullauth/resources/locale/pyramid_fullauth.pot +216 -0
  27. pyramid_fullauth/resources/templates/403.mako +11 -0
  28. pyramid_fullauth/resources/templates/_form.login.mako +44 -0
  29. pyramid_fullauth/resources/templates/_form.register.mako +47 -0
  30. pyramid_fullauth/resources/templates/_social.login.mako +17 -0
  31. pyramid_fullauth/resources/templates/activate.mako +14 -0
  32. pyramid_fullauth/resources/templates/email_change.mako +33 -0
  33. pyramid_fullauth/resources/templates/layout.mako +13 -0
  34. pyramid_fullauth/resources/templates/login.mako +14 -0
  35. pyramid_fullauth/resources/templates/register.mako +22 -0
  36. pyramid_fullauth/resources/templates/reset.mako +34 -0
  37. pyramid_fullauth/resources/templates/reset.proceed.mako +41 -0
  38. pyramid_fullauth/routing/__init__.py +5 -0
  39. pyramid_fullauth/routing/__init__.pyc +0 -0
  40. pyramid_fullauth/routing/predicates.py +86 -0
  41. pyramid_fullauth/routing/predicates.pyc +0 -0
  42. pyramid_fullauth/tools.py +66 -0
  43. pyramid_fullauth/tools.pyc +0 -0
  44. pyramid_fullauth/views/__init__.py +15 -0
  45. pyramid_fullauth/views/__init__.pyc +0 -0
  46. pyramid_fullauth/views/basic/__init__.py +5 -0
  47. pyramid_fullauth/views/basic/__init__.pyc +0 -0
  48. pyramid_fullauth/views/basic/activate.py +44 -0
  49. pyramid_fullauth/views/basic/activate.pyc +0 -0
  50. pyramid_fullauth/views/basic/forbidden.py +47 -0
  51. pyramid_fullauth/views/basic/forbidden.pyc +0 -0
  52. pyramid_fullauth/views/basic/login.py +128 -0
  53. pyramid_fullauth/views/basic/login.pyc +0 -0
  54. pyramid_fullauth/views/basic/logout.py +28 -0
  55. pyramid_fullauth/views/basic/logout.pyc +0 -0
  56. pyramid_fullauth/views/basic/profile/__init__.py +5 -0
  57. pyramid_fullauth/views/basic/profile/__init__.pyc +0 -0
  58. pyramid_fullauth/views/basic/profile/email.py +107 -0
  59. pyramid_fullauth/views/basic/profile/email.pyc +0 -0
  60. pyramid_fullauth/views/basic/profile/password.py +128 -0
  61. pyramid_fullauth/views/basic/profile/password.pyc +0 -0
  62. pyramid_fullauth/views/basic/register.py +110 -0
  63. pyramid_fullauth/views/basic/register.pyc +0 -0
  64. pyramid_fullauth/views/social.py +218 -0
  65. pyramid_fullauth/views/social.pyc +0 -0
  66. tests/__init__.py +1 -0
  67. tests/__init__.pyc +0 -0
  68. tests/conftest.py +190 -0
  69. tests/conftest.pyc +0 -0
  70. tests/tools.py +54 -0
  71. tests/tools.pyc +0 -0
  72. tests/unit/test_default_settings.py +15 -0
  73. tests/unit/test_default_settings.pyc +0 -0
  74. tests/unit/test_groupfinder.py +20 -0
  75. tests/unit/test_groupfinder.pyc +0 -0
  76. tests/unit/test_social_view.py +65 -0
  77. tests/unit/test_social_view.pyc +0 -0
  78. tests/unit/test_tools.py +24 -0
  79. tests/unit/test_tools.pyc +0 -0
  80. tests/unit/test_user_active.py +31 -0
  81. tests/unit/test_user_active.pyc +0 -0
  82. tests/unit/test_user_admin.py +61 -0
  83. tests/unit/test_user_admin.pyc +0 -0
  84. tests/unit/test_user_email.py +37 -0
  85. tests/unit/test_user_email.pyc +0 -0
  86. tests/unit/test_user_password.py +52 -0
  87. tests/unit/test_user_password.pyc +0 -0
  88. tests/unit/test_user_providers.py +24 -0
  89. tests/unit/test_user_providers.pyc +0 -0
  90. tests/unit/test_user_repr.py +29 -0
  91. tests/unit/test_user_repr.pyc +0 -0
  92. tests/unit/test_validators.py +44 -0
  93. tests/unit/test_validators.pyc +0 -0
  94. tests/views/__init__.py +1 -0
  95. tests/views/__init__.pyc +0 -0
  96. tests/views/conftest.py +15 -0
  97. tests/views/conftest.pyc +0 -0
  98. tests/views/test_activation.py +83 -0
  99. tests/views/test_activation.pyc +0 -0
  100. tests/views/test_email.py +175 -0
  101. tests/views/test_email.pyc +0 -0
  102. tests/views/test_events.py +546 -0
  103. tests/views/test_events.pyc +0 -0
  104. tests/views/test_login.py +151 -0
  105. tests/views/test_login.pyc +0 -0
  106. tests/views/test_login_social.py +254 -0
  107. tests/views/test_login_social.pyc +0 -0
  108. tests/views/test_logout.py +42 -0
  109. tests/views/test_logout.pyc +0 -0
  110. tests/views/test_register.py +134 -0
  111. tests/views/test_register.pyc +0 -0
  112. tests/views/test_reset.py +100 -0
  113. tests/views/test_reset.pyc +0 -0
@@ -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