Merge lp:~matiasb/canonical-identity-provider/validate-returns-is-verified into lp:canonical-identity-provider/release
- validate-returns-is-verified
- Merge into trunk
Proposed by
Matias Bordese
Status: | Merged |
---|---|
Approved by: | Ricardo Kirkner |
Approved revision: | no longer in the source branch. |
Merged at revision: | 1144 |
Proposed branch: | lp:~matiasb/canonical-identity-provider/validate-returns-is-verified |
Merge into: | lp:canonical-identity-provider/release |
Diff against target: |
271 lines (+66/-29) 2 files modified
src/api/v20/handlers.py (+6/-5) src/api/v20/tests/test_handlers.py (+60/-24) |
To merge this branch: | bzr merge lp:~matiasb/canonical-identity-provider/validate-returns-is-verified |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ricardo Kirkner (community) | Approve | ||
Review via email: mp+226035@code.launchpad.net |
Commit message
Added account_verified details to validate_request API endpoint.
Description of the change
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/api/v20/handlers.py' | |||
2 | --- src/api/v20/handlers.py 2013-11-28 14:25:58 +0000 | |||
3 | +++ src/api/v20/handlers.py 2014-07-08 20:32:06 +0000 | |||
4 | @@ -458,7 +458,7 @@ | |||
5 | 458 | if authorization is not None: | 458 | if authorization is not None: |
6 | 459 | headers = {'Authorization': authorization} | 459 | headers = {'Authorization': authorization} |
7 | 460 | 460 | ||
9 | 461 | result = {'is_valid': False} | 461 | result = dict(is_valid=False, account_verified=False) |
10 | 462 | 462 | ||
11 | 463 | if not http_url or not http_method: | 463 | if not http_url or not http_method: |
12 | 464 | return result | 464 | return result |
13 | @@ -489,18 +489,19 @@ | |||
14 | 489 | consumer, _, _ = oauth_server.verify_request(oauth_request) | 489 | consumer, _, _ = oauth_server.verify_request(oauth_request) |
15 | 490 | except oauth.OAuthError: | 490 | except oauth.OAuthError: |
16 | 491 | # do nothing special, signature was invalid | 491 | # do nothing special, signature was invalid |
18 | 492 | valid = False | 492 | pass |
19 | 493 | except Exception as e: | 493 | except Exception as e: |
20 | 494 | result['error'] = self.serialize_error(e) | 494 | result['error'] = self.serialize_error(e) |
21 | 495 | logger.exception( | 495 | logger.exception( |
22 | 496 | 'RequestsHandler.create: could not verify request:') | 496 | 'RequestsHandler.create: could not verify request:') |
23 | 497 | valid = False | ||
24 | 498 | else: | 497 | else: |
25 | 499 | # signature is valid, need to also check the account exists | 498 | # signature is valid, need to also check the account exists |
26 | 500 | # and is active | 499 | # and is active |
28 | 501 | valid = Account.objects.active_by_openid(consumer.key) is not None | 500 | account = Account.objects.active_by_openid(consumer.key) |
29 | 501 | result['is_valid'] = account is not None | ||
30 | 502 | result['account_verified'] = ( | ||
31 | 503 | account is not None and account.is_verified) | ||
32 | 502 | 504 | ||
33 | 503 | result['is_valid'] = valid | ||
34 | 504 | return result | 505 | return result |
35 | 505 | 506 | ||
36 | 506 | 507 | ||
37 | 507 | 508 | ||
38 | === modified file 'src/api/v20/tests/test_handlers.py' | |||
39 | --- src/api/v20/tests/test_handlers.py 2014-01-27 19:18:59 +0000 | |||
40 | +++ src/api/v20/tests/test_handlers.py 2014-07-08 20:32:06 +0000 | |||
41 | @@ -333,7 +333,8 @@ | |||
42 | 333 | ) | 333 | ) |
43 | 334 | return data | 334 | return data |
44 | 335 | 335 | ||
46 | 336 | def assert_request_response(self, response, expected, error=None): | 336 | def assert_request_response(self, response, is_valid, account_verified, |
47 | 337 | error=None): | ||
48 | 337 | self.assertEqual(response.status_code, 200) | 338 | self.assertEqual(response.status_code, 200) |
49 | 338 | try: | 339 | try: |
50 | 339 | response = json.loads(response.content) | 340 | response = json.loads(response.content) |
51 | @@ -341,7 +342,8 @@ | |||
52 | 341 | self.fail('Could not JSON-decode response, content is %r.' % | 342 | self.fail('Could not JSON-decode response, content is %r.' % |
53 | 342 | response.content) | 343 | response.content) |
54 | 343 | else: | 344 | else: |
56 | 344 | expected = dict(is_valid=expected) | 345 | expected = dict(is_valid=is_valid, |
57 | 346 | account_verified=account_verified) | ||
58 | 345 | if error: | 347 | if error: |
59 | 346 | expected['error'] = error | 348 | expected['error'] = error |
60 | 347 | self.assertEqual(response, expected) | 349 | self.assertEqual(response, expected) |
61 | @@ -349,32 +351,37 @@ | |||
62 | 349 | def test_invalid_if_not_method_given(self): | 351 | def test_invalid_if_not_method_given(self): |
63 | 350 | self.data.pop('http_method') | 352 | self.data.pop('http_method') |
64 | 351 | response = self.do_post() | 353 | response = self.do_post() |
66 | 352 | self.assert_request_response(response, False) | 354 | self.assert_request_response( |
67 | 355 | response, is_valid=False, account_verified=False) | ||
68 | 353 | self.assertFalse(self.mock_logger.exception.called) | 356 | self.assertFalse(self.mock_logger.exception.called) |
69 | 354 | 357 | ||
70 | 355 | def test_invalid_if_method_none(self): | 358 | def test_invalid_if_method_none(self): |
71 | 356 | self.data['http_method'] = None | 359 | self.data['http_method'] = None |
72 | 357 | response = self.do_post() | 360 | response = self.do_post() |
74 | 358 | self.assert_request_response(response, False) | 361 | self.assert_request_response( |
75 | 362 | response, is_valid=False, account_verified=False) | ||
76 | 359 | self.assertFalse(self.mock_logger.exception.called) | 363 | self.assertFalse(self.mock_logger.exception.called) |
77 | 360 | 364 | ||
78 | 361 | def test_invalid_if_not_url_given(self): | 365 | def test_invalid_if_not_url_given(self): |
79 | 362 | self.data.pop('http_url') | 366 | self.data.pop('http_url') |
80 | 363 | response = self.do_post() | 367 | response = self.do_post() |
82 | 364 | self.assert_request_response(response, False) | 368 | self.assert_request_response( |
83 | 369 | response, is_valid=False, account_verified=False) | ||
84 | 365 | self.assertFalse(self.mock_logger.exception.called) | 370 | self.assertFalse(self.mock_logger.exception.called) |
85 | 366 | 371 | ||
86 | 367 | def test_invalid_if_url_none(self): | 372 | def test_invalid_if_url_none(self): |
87 | 368 | self.data['http_url'] = None | 373 | self.data['http_url'] = None |
88 | 369 | response = self.do_post() | 374 | response = self.do_post() |
90 | 370 | self.assert_request_response(response, False) | 375 | self.assert_request_response( |
91 | 376 | response, is_valid=False, account_verified=False) | ||
92 | 371 | self.assertFalse(self.mock_logger.exception.called) | 377 | self.assertFalse(self.mock_logger.exception.called) |
93 | 372 | 378 | ||
94 | 373 | def test_url_encoded(self): | 379 | def test_url_encoded(self): |
95 | 374 | self.data = self.build_data(external_url=u'http://foo/ñoño ñandú/') | 380 | self.data = self.build_data(external_url=u'http://foo/ñoño ñandú/') |
96 | 375 | response = self.do_post() | 381 | response = self.do_post() |
97 | 376 | 382 | ||
99 | 377 | self.assert_request_response(response, True) | 383 | self.assert_request_response( |
100 | 384 | response, is_valid=True, account_verified=True) | ||
101 | 378 | self.assertFalse(self.mock_logger.exception.called) | 385 | self.assertFalse(self.mock_logger.exception.called) |
102 | 379 | 386 | ||
103 | 380 | def test_error_in_response_is_robust_to_encodings(self): | 387 | def test_error_in_response_is_robust_to_encodings(self): |
104 | @@ -388,7 +395,8 @@ | |||
105 | 388 | 395 | ||
106 | 389 | msg = ', '.join(repr(i) for i in exc.args) | 396 | msg = ', '.join(repr(i) for i in exc.args) |
107 | 390 | self.assert_request_response( | 397 | self.assert_request_response( |
109 | 391 | response, False, error="TypeError: %s" % msg) | 398 | response, is_valid=False, account_verified=False, |
110 | 399 | error="TypeError: %s" % msg) | ||
111 | 392 | 400 | ||
112 | 393 | def test_invalid_if_from_request_fails(self): | 401 | def test_invalid_if_from_request_fails(self): |
113 | 394 | self._apply_patch( | 402 | self._apply_patch( |
114 | @@ -397,7 +405,8 @@ | |||
115 | 397 | 405 | ||
116 | 398 | response = self.do_post() | 406 | response = self.do_post() |
117 | 399 | self.assert_request_response( | 407 | self.assert_request_response( |
119 | 400 | response, False, error="ValueError: 'foo \\xf1o\\xf1o'") | 408 | response, is_valid=False, account_verified=False, |
120 | 409 | error="ValueError: 'foo \\xf1o\\xf1o'") | ||
121 | 401 | self.mock_logger.exception.assert_called_once_with( | 410 | self.mock_logger.exception.assert_called_once_with( |
122 | 402 | 'RequestsHandler.create: could not build OAuthRequest with the ' | 411 | 'RequestsHandler.create: could not build OAuthRequest with the ' |
123 | 403 | 'given parameters %r:', self.data) | 412 | 'given parameters %r:', self.data) |
124 | @@ -409,26 +418,30 @@ | |||
125 | 409 | 418 | ||
126 | 410 | response = self.do_post() | 419 | response = self.do_post() |
127 | 411 | self.assert_request_response( | 420 | self.assert_request_response( |
129 | 412 | response, False, error="KeyError: u'\\xf1'") | 421 | response, is_valid=False, account_verified=False, |
130 | 422 | error="KeyError: u'\\xf1'") | ||
131 | 413 | self.mock_logger.exception.assert_called_once_with( | 423 | self.mock_logger.exception.assert_called_once_with( |
132 | 414 | 'RequestsHandler.create: could not verify request:') | 424 | 'RequestsHandler.create: could not verify request:') |
133 | 415 | 425 | ||
134 | 416 | def test_invalid_if_header_none(self): | 426 | def test_invalid_if_header_none(self): |
135 | 417 | self.data['authorization'] = None | 427 | self.data['authorization'] = None |
136 | 418 | response = self.do_post() | 428 | response = self.do_post() |
138 | 419 | self.assert_request_response(response, False) | 429 | self.assert_request_response( |
139 | 430 | response, is_valid=False, account_verified=False) | ||
140 | 420 | self.assertFalse(self.mock_logger.exception.called) | 431 | self.assertFalse(self.mock_logger.exception.called) |
141 | 421 | 432 | ||
142 | 422 | def test_invalid_if_not_header_given(self): | 433 | def test_invalid_if_not_header_given(self): |
143 | 423 | self.data.pop('authorization') | 434 | self.data.pop('authorization') |
144 | 424 | response = self.do_post() | 435 | response = self.do_post() |
146 | 425 | self.assert_request_response(response, False) | 436 | self.assert_request_response( |
147 | 437 | response, is_valid=False, account_verified=False) | ||
148 | 426 | self.assertFalse(self.mock_logger.exception.called) | 438 | self.assertFalse(self.mock_logger.exception.called) |
149 | 427 | 439 | ||
150 | 428 | def test_invalid_if_no_header_or_query_string(self): | 440 | def test_invalid_if_no_header_or_query_string(self): |
151 | 429 | del self.data['authorization'] | 441 | del self.data['authorization'] |
152 | 430 | response = self.do_post() | 442 | response = self.do_post() |
154 | 431 | self.assert_request_response(response, False) | 443 | self.assert_request_response( |
155 | 444 | response, is_valid=False, account_verified=False) | ||
156 | 432 | self.assertFalse(self.mock_logger.exception.called) | 445 | self.assertFalse(self.mock_logger.exception.called) |
157 | 433 | 446 | ||
158 | 434 | def test_invalid_if_bad_query_string(self): | 447 | def test_invalid_if_bad_query_string(self): |
159 | @@ -436,7 +449,8 @@ | |||
160 | 436 | # make sure there is no authorization header | 449 | # make sure there is no authorization header |
161 | 437 | del self.data['authorization'] | 450 | del self.data['authorization'] |
162 | 438 | response = self.do_post() | 451 | response = self.do_post() |
164 | 439 | self.assert_request_response(response, False) | 452 | self.assert_request_response( |
165 | 453 | response, is_valid=False, account_verified=False) | ||
166 | 440 | self.assertFalse(self.mock_logger.exception.called) | 454 | self.assertFalse(self.mock_logger.exception.called) |
167 | 441 | 455 | ||
168 | 442 | def test_invalid_if_query_string_invalid(self): | 456 | def test_invalid_if_query_string_invalid(self): |
169 | @@ -451,7 +465,8 @@ | |||
170 | 451 | 465 | ||
171 | 452 | # do a post with correct params | 466 | # do a post with correct params |
172 | 453 | response = self.do_post() | 467 | response = self.do_post() |
174 | 454 | self.assert_request_response(response, False) | 468 | self.assert_request_response( |
175 | 469 | response, is_valid=False, account_verified=False) | ||
176 | 455 | self.assertFalse(self.mock_logger.exception.called) | 470 | self.assertFalse(self.mock_logger.exception.called) |
177 | 456 | 471 | ||
178 | 457 | def test_url_mismatch(self): | 472 | def test_url_mismatch(self): |
179 | @@ -460,14 +475,16 @@ | |||
180 | 460 | self.data['http_url'] = new_url | 475 | self.data['http_url'] = new_url |
181 | 461 | response = self.do_post() | 476 | response = self.do_post() |
182 | 462 | 477 | ||
184 | 463 | self.assert_request_response(response, False) | 478 | self.assert_request_response( |
185 | 479 | response, is_valid=False, account_verified=False) | ||
186 | 464 | self.assertFalse(self.mock_logger.exception.called) | 480 | self.assertFalse(self.mock_logger.exception.called) |
187 | 465 | 481 | ||
188 | 466 | def test_method_mismatch(self): | 482 | def test_method_mismatch(self): |
189 | 467 | self.data['http_method'] = self.default_http_method * 2 | 483 | self.data['http_method'] = self.default_http_method * 2 |
190 | 468 | response = self.do_post() | 484 | response = self.do_post() |
191 | 469 | 485 | ||
193 | 470 | self.assert_request_response(response, False) | 486 | self.assert_request_response( |
194 | 487 | response, is_valid=False, account_verified=False) | ||
195 | 471 | self.assertFalse(self.mock_logger.exception.called) | 488 | self.assertFalse(self.mock_logger.exception.called) |
196 | 472 | 489 | ||
197 | 473 | def test_valid_request(self): | 490 | def test_valid_request(self): |
198 | @@ -475,7 +492,20 @@ | |||
199 | 475 | response = self.do_post() | 492 | response = self.do_post() |
200 | 476 | 493 | ||
201 | 477 | self.assertEqual(response.status_code, 200) | 494 | self.assertEqual(response.status_code, 200) |
203 | 478 | self.assert_request_response(response, True) | 495 | self.assert_request_response( |
204 | 496 | response, is_valid=True, account_verified=True) | ||
205 | 497 | self.assertFalse(self.mock_logger.exception.called) | ||
206 | 498 | |||
207 | 499 | def test_valid_request_unverified_user(self): | ||
208 | 500 | self.account.verified_emails().delete() | ||
209 | 501 | assert not self.account.is_verified | ||
210 | 502 | |||
211 | 503 | # do a post with correct params | ||
212 | 504 | response = self.do_post() | ||
213 | 505 | |||
214 | 506 | self.assertEqual(response.status_code, 200) | ||
215 | 507 | self.assert_request_response( | ||
216 | 508 | response, is_valid=True, account_verified=False) | ||
217 | 479 | self.assertFalse(self.mock_logger.exception.called) | 509 | self.assertFalse(self.mock_logger.exception.called) |
218 | 480 | 510 | ||
219 | 481 | def test_valid_request_for_non_existent_account(self): | 511 | def test_valid_request_for_non_existent_account(self): |
220 | @@ -483,7 +513,8 @@ | |||
221 | 483 | # do a post with correct params for a non existent account | 513 | # do a post with correct params for a non existent account |
222 | 484 | response = self.do_post() | 514 | response = self.do_post() |
223 | 485 | 515 | ||
225 | 486 | self.assert_request_response(response, False) | 516 | self.assert_request_response( |
226 | 517 | response, is_valid=False, account_verified=False) | ||
227 | 487 | 518 | ||
228 | 488 | def test_valid_request_for_inactive_account(self): | 519 | def test_valid_request_for_inactive_account(self): |
229 | 489 | for status, name in AccountStatus._get_choices(): | 520 | for status, name in AccountStatus._get_choices(): |
230 | @@ -499,7 +530,8 @@ | |||
231 | 499 | # do a post with correct params for an inactive account | 530 | # do a post with correct params for an inactive account |
232 | 500 | response = self.do_post() | 531 | response = self.do_post() |
233 | 501 | 532 | ||
235 | 502 | self.assert_request_response(response, False) | 533 | self.assert_request_response( |
236 | 534 | response, is_valid=False, account_verified=False) | ||
237 | 503 | self.assertFalse(self.mock_logger.exception.called) | 535 | self.assertFalse(self.mock_logger.exception.called) |
238 | 504 | 536 | ||
239 | 505 | def test_valid_request_with_only_query_string(self): | 537 | def test_valid_request_with_only_query_string(self): |
240 | @@ -511,7 +543,8 @@ | |||
241 | 511 | response = self.do_post() | 543 | response = self.do_post() |
242 | 512 | 544 | ||
243 | 513 | self.assertEqual(response.status_code, 200) | 545 | self.assertEqual(response.status_code, 200) |
245 | 514 | self.assert_request_response(response, True) | 546 | self.assert_request_response( |
246 | 547 | response, is_valid=True, account_verified=True) | ||
247 | 515 | self.assertFalse(self.mock_logger.exception.called) | 548 | self.assertFalse(self.mock_logger.exception.called) |
248 | 516 | 549 | ||
249 | 517 | def test_query_string_ignored_if_authorization_header_found(self): | 550 | def test_query_string_ignored_if_authorization_header_found(self): |
250 | @@ -521,15 +554,18 @@ | |||
251 | 521 | response = self.do_post() | 554 | response = self.do_post() |
252 | 522 | 555 | ||
253 | 523 | self.assertEqual(response.status_code, 200) | 556 | self.assertEqual(response.status_code, 200) |
255 | 524 | self.assert_request_response(response, True) | 557 | self.assert_request_response( |
256 | 558 | response, is_valid=True, account_verified=True) | ||
257 | 525 | self.assertFalse(self.mock_logger.exception.called) | 559 | self.assertFalse(self.mock_logger.exception.called) |
258 | 526 | 560 | ||
259 | 527 | def test_replay_attack(self): | 561 | def test_replay_attack(self): |
260 | 528 | response = self.do_post() | 562 | response = self.do_post() |
262 | 529 | self.assert_request_response(response, True) | 563 | self.assert_request_response( |
263 | 564 | response, is_valid=True, account_verified=True) | ||
264 | 530 | 565 | ||
265 | 531 | response = self.do_post() | 566 | response = self.do_post() |
267 | 532 | self.assert_request_response(response, False) | 567 | self.assert_request_response( |
268 | 568 | response, is_valid=False, account_verified=False) | ||
269 | 533 | 569 | ||
270 | 534 | 570 | ||
271 | 535 | class RequestsWithHEADTestCase(RequestsTestCase): | 571 | class RequestsWithHEADTestCase(RequestsTestCase): |
LGTM