Package repoze :: Package who :: Package plugins :: Package tests :: Module test_form
[hide private]

Source Code for Module repoze.who.plugins.tests.test_form

  1  import unittest 
  2   
3 -class TestFormPlugin(unittest.TestCase):
4
5 - def _getTargetClass(self):
6 from repoze.who.plugins.form import FormPlugin 7 return FormPlugin
8
9 - def _makeOne(self, 10 login_form_qs='__do_login', 11 rememberer_name='cookie', 12 formbody=None, 13 formcallable=None, 14 ):
15 plugin = self._getTargetClass()(login_form_qs, rememberer_name, 16 formbody, formcallable) 17 return plugin
18
19 - def _makeEnviron(self, login=None, password=None, do_login=False, 20 max_age=None):
21 from StringIO import StringIO 22 fields = [] 23 if login: 24 fields.append(('login', login)) 25 if password: 26 fields.append(('password', password)) 27 if max_age: 28 fields.append(('max_age', max_age)) 29 content_type, body = encode_multipart_formdata(fields) 30 credentials = {'login':'chris', 'password':'password'} 31 identifier = DummyIdentifier(credentials) 32 33 environ = {'wsgi.version': (1,0), 34 'wsgi.input': StringIO(body), 35 'wsgi.url_scheme': 'http', 36 'SERVER_NAME': 'localhost', 37 'SERVER_PORT': '8080', 38 'CONTENT_TYPE': content_type, 39 'CONTENT_LENGTH': len(body), 40 'REQUEST_METHOD': 'POST', 41 'repoze.who.plugins': {'cookie':identifier}, 42 'PATH_INFO': '/protected', 43 'QUERY_STRING': '', 44 } 45 if do_login: 46 environ['QUERY_STRING'] = '__do_login=true' 47 return environ
48
49 - def test_implements(self):
50 from zope.interface.verify import verifyClass 51 from repoze.who.interfaces import IIdentifier 52 from repoze.who.interfaces import IChallenger 53 klass = self._getTargetClass() 54 verifyClass(IIdentifier, klass) 55 verifyClass(IChallenger, klass)
56
57 - def test_identify_noqs(self):
58 plugin = self._makeOne() 59 environ = self._makeEnviron() 60 result = plugin.identify(environ) 61 self.assertEqual(result, None)
62
64 plugin = self._makeOne() 65 environ = self._makeEnviron(do_login=True) 66 result = plugin.identify(environ) 67 self.assertEqual(result, None)
68
69 - def test_identify_nologin(self):
70 plugin = self._makeOne() 71 environ = self._makeEnviron(do_login=True, login='chris') 72 result = plugin.identify(environ) 73 self.assertEqual(result, None)
74
75 - def test_identify_nopassword(self):
76 plugin = self._makeOne() 77 environ = self._makeEnviron(do_login=True, password='password') 78 result = plugin.identify(environ) 79 self.assertEqual(result, None)
80
81 - def test_identify_success(self):
82 from paste.httpexceptions import HTTPFound 83 plugin = self._makeOne() 84 environ = self._makeEnviron(do_login=True, login='chris', 85 password='password') 86 result = plugin.identify(environ) 87 self.assertEqual(result, {'login':'chris', 'password':'password'}) 88 app = environ['repoze.who.application'] 89 self.failUnless(isinstance(app, HTTPFound)) 90 self.assertEqual(app.location(), 'http://localhost:8080/protected')
91
93 from paste.httpexceptions import HTTPFound 94 plugin = self._makeOne() 95 environ = self._makeEnviron(do_login=True, login='chris', 96 password='password', max_age='500') 97 result = plugin.identify(environ) 98 self.assertEqual(result, {'login':'chris', 'password':'password', 99 'max_age':'500'}) 100 app = environ['repoze.who.application'] 101 self.failUnless(isinstance(app, HTTPFound)) 102 self.assertEqual(app.location(), 'http://localhost:8080/protected')
103
104 - def test_remember(self):
105 plugin = self._makeOne() 106 environ = self._makeEnviron() 107 identity = {} 108 result = plugin.remember(environ, identity) 109 self.assertEqual(result, None) 110 self.assertEqual(environ['repoze.who.plugins']['cookie'].remembered, 111 identity)
112
113 - def test_forget(self):
114 plugin = self._makeOne() 115 environ = self._makeEnviron() 116 identity = {} 117 result = plugin.forget(environ, identity) 118 self.assertEqual(result, None) 119 self.assertEqual(environ['repoze.who.plugins']['cookie'].forgotten, 120 identity 121 )
122
124 from repoze.who.plugins.form import _DEFAULT_FORM 125 plugin = self._makeOne() 126 environ = self._makeEnviron() 127 app = plugin.challenge(environ, '401 Unauthorized', [], []) 128 sr = DummyStartResponse() 129 result = app(environ, sr) 130 self.assertEqual(''.join(result), _DEFAULT_FORM) 131 self.assertEqual(len(sr.headers), 2) 132 cl = str(len(_DEFAULT_FORM)) 133 self.assertEqual(sr.headers[0], ('Content-Length', cl)) 134 self.assertEqual(sr.headers[1], ('Content-Type', 'text/html')) 135 self.assertEqual(sr.status, '200 OK')
136
138 import os 139 here = os.path.dirname(__file__) 140 fixtures = os.path.join(here, 'fixtures') 141 form = os.path.join(fixtures, 'form.html') 142 formbody = open(form).read() 143 plugin = self._makeOne(formbody=formbody) 144 environ = self._makeEnviron() 145 app = plugin.challenge(environ, '401 Unauthorized', [], []) 146 sr = DummyStartResponse() 147 result = app(environ, sr) 148 self.assertEqual(''.join(result), formbody) 149 self.assertEqual(len(sr.headers), 2) 150 cl = str(len(formbody)) 151 self.assertEqual(sr.headers[0], ('Content-Length', cl)) 152 self.assertEqual(sr.headers[1], ('Content-Type', 'text/html')) 153 self.assertEqual(sr.status, '200 OK')
154
156 def _formcallable(environ): 157 return 'formcallable'
158 plugin = self._makeOne(formcallable=_formcallable) 159 environ = self._makeEnviron() 160 app = plugin.challenge(environ, '401 Unauthorized', [], []) 161 sr = DummyStartResponse() 162 result = app(environ, sr) 163 self.assertEqual(result, ['formcallable'])
164
165 - def test_challenge_with_location(self):
166 plugin = self._makeOne() 167 environ = self._makeEnviron() 168 app = plugin.challenge(environ, '401 Unauthorized', 169 [('Location', 'http://foo/bar')], 170 [('Set-Cookie', 'a=123')]) 171 sr = DummyStartResponse() 172 app(environ, sr) 173 headers = sorted(sr.headers) 174 self.assertEqual(len(headers), 3) 175 self.assertEqual(headers[0], ('Location', 'http://foo/bar')) 176 self.assertEqual(headers[1], 177 ('Set-Cookie', 'a=123')) 178 self.assertEqual(headers[2], 179 ('content-type', 'text/plain; charset=utf8')) 180 self.assertEqual(sr.status, '302 Found')
181
182 -class Test_make_plugin(unittest.TestCase):
183
184 - def _callFUT(self, *args, **kw):
185 from repoze.who.plugins.form import make_plugin 186 return make_plugin(*args, **kw)
187
189 self.assertRaises(ValueError, self._callFUT)
190
191 - def test_with_form(self):
192 import os 193 here = os.path.dirname(__file__) 194 fixtures = os.path.join(here, 'fixtures') 195 form = os.path.join(fixtures, 'form.html') 196 formbody = open(form).read() 197 plugin = self._callFUT('__login', 'cookie', form) 198 self.assertEqual(plugin.login_form_qs, '__login') 199 self.assertEqual(plugin.rememberer_name, 'cookie') 200 self.assertEqual(plugin.formbody, formbody) 201 self.assertEqual(plugin.formcallable, None)
202
203 - def test_default_form(self):
204 plugin = self._callFUT('__login', 'cookie') 205 self.assertEqual(plugin.login_form_qs, '__login') 206 self.assertEqual(plugin.rememberer_name, 'cookie') 207 self.assertEqual(plugin.formbody, None) 208 self.assertEqual(plugin.formcallable, None)
209
210 - def test_with_formcallable(self):
211 dotted='repoze.who.plugins.tests.test_form:sample_formcallable' 212 plugin = self._callFUT('__login', 'cookie', 213 formcallable=dotted 214 ) 215 self.assertEqual(plugin.formcallable, sample_formcallable)
216
217 -def sample_formcallable(environ):
218 return {'foo': 'bar'}
219 220
221 -class TestRedirectingFormPlugin(unittest.TestCase):
222
223 - def _getTargetClass(self):
226
227 - def _makeOne(self, login_form_url='http://example.com/login.html', 228 login_handler_path = '/login_handler', 229 logout_handler_path = '/logout_handler', 230 rememberer_name='cookie', 231 reason_param='reason'):
232 plugin = self._getTargetClass()(login_form_url, login_handler_path, 233 logout_handler_path, 234 rememberer_name, reason_param) 235 return plugin
236
237 - def _makeEnviron(self, login=None, password=None, came_from=None, 238 path_info='/', identifier=None, max_age=None):
239 from StringIO import StringIO 240 fields = [] 241 if login: 242 fields.append(('login', login)) 243 if password: 244 fields.append(('password', password)) 245 if came_from: 246 fields.append(('came_from', came_from)) 247 if max_age: 248 fields.append(('max_age', max_age)) 249 if identifier is None: 250 credentials = {'login':'chris', 'password':'password'} 251 identifier = DummyIdentifier(credentials) 252 content_type, body = encode_multipart_formdata(fields) 253 environ = {'wsgi.version': (1,0), 254 'wsgi.input': StringIO(body), 255 'wsgi.url_scheme':'http', 256 'SERVER_NAME': 'www.example.com', 257 'SERVER_PORT': '80', 258 'CONTENT_TYPE': content_type, 259 'CONTENT_LENGTH': len(body), 260 'REQUEST_METHOD': 'POST', 261 'repoze.who.plugins': {'cookie':identifier}, 262 'QUERY_STRING': 'default=1', 263 'PATH_INFO': path_info, 264 } 265 return environ
266
267 - def test_implements(self):
268 from zope.interface.verify import verifyClass 269 from repoze.who.interfaces import IIdentifier 270 from repoze.who.interfaces import IChallenger 271 klass = self._getTargetClass() 272 verifyClass(IIdentifier, klass) 273 verifyClass(IChallenger, klass)
274
276 plugin = self._makeOne() 277 environ = self._makeEnviron(path_info='/not_login_handler') 278 result = plugin.identify(environ) 279 self.assertEqual(result, None) 280 self.failIf(environ.get('repoze.who.application'))
281
283 plugin = self._makeOne() 284 environ = self._makeEnviron(path_info='/login_handler', 285 login='chris', 286 password='password', 287 came_from='http://example.com') 288 result = plugin.identify(environ) 289 self.assertEqual(result, {'login':'chris', 'password':'password'}) 290 app = environ['repoze.who.application'] 291 self.assertEqual(len(app.headers), 1) 292 name, value = app.headers[0] 293 self.assertEqual(name, 'location') 294 self.assertEqual(value, 'http://example.com') 295 self.assertEqual(app.code, 302)
296
298 plugin = self._makeOne() 299 environ = self._makeEnviron(path_info='/login_handler', 300 login='chris', 301 password='password', 302 came_from='http://example.com', 303 max_age='500') 304 result = plugin.identify(environ) 305 self.assertEqual(result, {'login':'chris', 'password':'password', 306 'max_age':'500'}) 307 app = environ['repoze.who.application'] 308 self.assertEqual(len(app.headers), 1) 309 name, value = app.headers[0] 310 self.assertEqual(name, 'location') 311 self.assertEqual(value, 'http://example.com') 312 self.assertEqual(app.code, 302)
313
315 plugin = self._makeOne() 316 environ = self._makeEnviron(path_info='/login_handler') 317 result = plugin.identify(environ) 318 self.assertEqual(result, None) 319 app = environ['repoze.who.application'] 320 self.assertEqual(len(app.headers), 1) 321 name, value = app.headers[0] 322 self.assertEqual(name, 'location') 323 self.assertEqual(value, '/') 324 self.assertEqual(app.code, 302)
325
327 plugin = self._makeOne() 328 environ = self._makeEnviron(path_info='/login_handler', 329 login='chris', 330 password='password') 331 result = plugin.identify(environ) 332 self.assertEqual(result, {'login':'chris', 'password':'password'}) 333 app = environ['repoze.who.application'] 334 self.assertEqual(len(app.headers), 1) 335 name, value = app.headers[0] 336 self.assertEqual(name, 'location') 337 self.assertEqual(value, '/') 338 self.assertEqual(app.code, 302)
339
341 plugin = self._makeOne() 342 environ = self._makeEnviron(path_info='/login_handler', 343 login='chris', 344 password='password') 345 environ['HTTP_REFERER'] = 'http://foo.bar' 346 result = plugin.identify(environ) 347 self.assertEqual(result, {'login':'chris', 'password':'password'}) 348 app = environ['repoze.who.application'] 349 self.assertEqual(len(app.headers), 1) 350 name, value = app.headers[0] 351 self.assertEqual(name, 'location') 352 self.assertEqual(value, 'http://foo.bar') 353 self.assertEqual(app.code, 302)
354
356 plugin = self._makeOne() 357 environ = self._makeEnviron(path_info='/logout_handler', 358 login='chris', 359 password='password', 360 came_from='http://example.com') 361 result = plugin.identify(environ) 362 self.assertEqual(result, None) 363 app = environ['repoze.who.application'] 364 self.assertEqual(len(app.headers), 0) 365 self.assertEqual(app.code, 401) 366 self.assertEqual(environ['came_from'], 'http://example.com')
367
369 plugin = self._makeOne() 370 environ = self._makeEnviron(path_info='/logout_handler', 371 login='chris', 372 password='password') 373 result = plugin.identify(environ) 374 self.assertEqual(result, None) 375 app = environ['repoze.who.application'] 376 self.assertEqual(len(app.headers), 0) 377 self.assertEqual(app.code, 401) 378 self.assertEqual(environ['came_from'], '/')
379
381 plugin = self._makeOne() 382 environ = self._makeEnviron(path_info='/logout_handler', 383 login='chris', 384 password='password') 385 environ['HTTP_REFERER'] = 'http://example.com/referer' 386 result = plugin.identify(environ) 387 self.assertEqual(result, None) 388 app = environ['repoze.who.application'] 389 self.assertEqual(len(app.headers), 0) 390 self.assertEqual(app.code, 401) 391 self.assertEqual(environ['came_from'], 'http://example.com/referer')
392
393 - def test_remember(self):
394 plugin = self._makeOne() 395 environ = self._makeEnviron() 396 identity = {} 397 result = plugin.remember(environ, identity) 398 self.assertEqual(result, None) 399 self.assertEqual(environ['repoze.who.plugins']['cookie'].remembered, 400 identity)
401
402 - def test_forget(self):
403 plugin = self._makeOne() 404 environ = self._makeEnviron() 405 identity = {} 406 result = plugin.forget(environ, identity) 407 self.assertEqual(result, None) 408 self.assertEqual(environ['repoze.who.plugins']['cookie'].forgotten, 409 identity 410 )
411
412 - def test_challenge(self):
413 plugin = self._makeOne() 414 environ = self._makeEnviron() 415 app = plugin.challenge(environ, '401 Unauthorized', [('app', '1')], 416 [('forget', '1')]) 417 sr = DummyStartResponse() 418 result = ''.join(app(environ, sr)) 419 self.failUnless(result.startswith('302 Found')) 420 self.assertEqual(len(sr.headers), 3) 421 self.assertEqual(sr.headers[0][0], 'Location') 422 url = sr.headers[0][1] 423 import urlparse 424 import cgi 425 parts = urlparse.urlparse(url) 426 parts_qsl = cgi.parse_qsl(parts[4]) 427 self.assertEqual(len(parts_qsl), 1) 428 came_from_key, came_from_value = parts_qsl[0] 429 self.assertEqual(parts[0], 'http') 430 self.assertEqual(parts[1], 'example.com') 431 self.assertEqual(parts[2], '/login.html') 432 self.assertEqual(parts[3], '') 433 self.assertEqual(came_from_key, 'came_from') 434 self.assertEqual(came_from_value, 'http://www.example.com/?default=1') 435 headers = sr.headers 436 self.assertEqual(len(headers), 3) 437 self.assertEqual(sr.headers[1][0], 'forget') 438 self.assertEqual(sr.headers[1][1], '1') 439 self.assertEqual(sr.headers[2][0], 'content-type') 440 self.assertEqual(sr.headers[2][1], 'text/plain; charset=utf8') 441 self.assertEqual(sr.status, '302 Found')
442
444 plugin = self._makeOne() 445 environ = self._makeEnviron() 446 environ['came_from'] = 'http://example.com/came_from' 447 app = plugin.challenge(environ, '401 Unauthorized', [('app', '1')], 448 [('forget', '1')]) 449 sr = DummyStartResponse() 450 result = ''.join(app(environ, sr)) 451 self.failUnless(result.startswith('302 Found')) 452 self.assertEqual(len(sr.headers), 3) 453 self.assertEqual(sr.headers[0][0], 'Location') 454 url = sr.headers[0][1] 455 import urlparse 456 import cgi 457 parts = urlparse.urlparse(url) 458 parts_qsl = cgi.parse_qsl(parts[4]) 459 self.assertEqual(len(parts_qsl), 1) 460 came_from_key, came_from_value = parts_qsl[0] 461 self.assertEqual(parts[0], 'http') 462 self.assertEqual(parts[1], 'example.com') 463 self.assertEqual(parts[2], '/login.html') 464 self.assertEqual(parts[3], '') 465 self.assertEqual(came_from_key, 'came_from') 466 self.assertEqual(came_from_value, 'http://example.com/came_from')
467
469 plugin = self._makeOne() 470 environ = self._makeEnviron() 471 environ['came_from'] = 'http://example.com/came_from' 472 app = plugin.challenge( 473 environ, '401 Unauthorized', 474 [('X-Authorization-Failure-Reason', 'you are ugly')], 475 [('forget', '1')]) 476 sr = DummyStartResponse() 477 result = ''.join(app(environ, sr)) 478 self.failUnless(result.startswith('302 Found')) 479 self.assertEqual(len(sr.headers), 3) 480 self.assertEqual(sr.headers[0][0], 'Location') 481 url = sr.headers[0][1] 482 import urlparse 483 import cgi 484 parts = urlparse.urlparse(url) 485 parts_qsl = cgi.parse_qsl(parts[4]) 486 self.assertEqual(len(parts_qsl), 2) 487 parts_qsl.sort() 488 came_from_key, came_from_value = parts_qsl[0] 489 reason_key, reason_value = parts_qsl[1] 490 self.assertEqual(parts[0], 'http') 491 self.assertEqual(parts[1], 'example.com') 492 self.assertEqual(parts[2], '/login.html') 493 self.assertEqual(parts[3], '') 494 self.assertEqual(came_from_key, 'came_from') 495 self.assertEqual(came_from_value, 'http://example.com/came_from') 496 self.assertEqual(reason_key, 'reason') 497 self.assertEqual(reason_value, 'you are ugly')
498
500 plugin = self._makeOne(reason_param='auth_failure') 501 environ = self._makeEnviron() 502 environ['came_from'] = 'http://example.com/came_from' 503 app = plugin.challenge( 504 environ, '401 Unauthorized', 505 [('X-Authorization-Failure-Reason', 'you are ugly')], 506 [('forget', '1')]) 507 sr = DummyStartResponse() 508 result = ''.join(app(environ, sr)) 509 self.failUnless(result.startswith('302 Found')) 510 self.assertEqual(len(sr.headers), 3) 511 self.assertEqual(sr.headers[0][0], 'Location') 512 url = sr.headers[0][1] 513 import urlparse 514 import cgi 515 parts = urlparse.urlparse(url) 516 parts_qsl = cgi.parse_qsl(parts[4]) 517 self.assertEqual(len(parts_qsl), 2) 518 parts_qsl.sort() 519 reason_key, reason_value = parts_qsl[0] 520 came_from_key, came_from_value = parts_qsl[1] 521 self.assertEqual(parts[0], 'http') 522 self.assertEqual(parts[1], 'example.com') 523 self.assertEqual(parts[2], '/login.html') 524 self.assertEqual(parts[3], '') 525 self.assertEqual(came_from_key, 'came_from') 526 self.assertEqual(came_from_value, 'http://example.com/came_from') 527 self.assertEqual(reason_key, 'auth_failure') 528 self.assertEqual(reason_value, 'you are ugly')
529
531 plugin = self._makeOne() 532 environ = self._makeEnviron() 533 app = plugin.challenge( 534 environ, 535 '401 Unauthorized', 536 [('app', '1'), ('set-cookie','a'), ('set-cookie','b')], 537 []) 538 sr = DummyStartResponse() 539 result = ''.join(app(environ, sr)) 540 self.failUnless(result.startswith('302 Found')) 541 self.assertEqual(sr.headers[1][0], 'set-cookie') 542 self.assertEqual(sr.headers[1][1], 'a') 543 self.assertEqual(sr.headers[2][0], 'set-cookie') 544 self.assertEqual(sr.headers[2][1], 'b')
545
546 -class Test_make_redirecting_plugin(unittest.TestCase):
547
548 - def _callFUT(self, *args, **kw):
549 from repoze.who.plugins.form import make_redirecting_plugin 550 return make_redirecting_plugin(*args, **kw)
551
553 self.assertRaises(ValueError, self._callFUT, None)
554
556 self.assertRaises(ValueError, self._callFUT, '/go_there', None)
557
559 self.assertRaises(ValueError, self._callFUT, 560 '/go_there', '/logged_in', None)
561
563 self.assertRaises(ValueError, self._callFUT, 564 '/go_there', '/logged_in', '/logged_out', None)
565
566 - def test_factory_ok(self):
567 plugin = self._callFUT('/go_there', 568 '/logged_in', 569 '/logged_out', 570 'rememberer') 571 self.assertEqual(plugin.login_form_url, '/go_there') 572 self.assertEqual(plugin.login_handler_path, '/logged_in') 573 self.assertEqual(plugin.logout_handler_path, '/logged_out') 574 self.assertEqual(plugin.rememberer_name, 'rememberer')
575
576 -class DummyIdentifier:
577 forgotten = False 578 remembered = False 579
580 - def __init__(self, credentials=None, remember_headers=None, 581 forget_headers=None, replace_app=None):
582 self.credentials = credentials 583 self.remember_headers = remember_headers 584 self.forget_headers = forget_headers 585 self.replace_app = replace_app
586
587 - def identify(self, environ):
588 if self.replace_app: 589 environ['repoze.who.application'] = self.replace_app 590 return self.credentials
591
592 - def forget(self, environ, identity):
593 self.forgotten = identity 594 return self.forget_headers
595
596 - def remember(self, environ, identity):
597 self.remembered = identity 598 return self.remember_headers
599
600 -class DummyStartResponse:
601 - def __call__(self, status, headers, exc_info=None):
602 self.status = status 603 self.headers = headers 604 self.exc_info = exc_info 605 return []
606
607 -def encode_multipart_formdata(fields):
608 BOUNDARY = '----------ThIs_Is_tHe_bouNdaRY_$' 609 CRLF = '\r\n' 610 L = [] 611 for (key, value) in fields: 612 L.append('--' + BOUNDARY) 613 L.append('Content-Disposition: form-data; name="%s"' % key) 614 L.append('') 615 L.append(value) 616 L.append('--' + BOUNDARY + '--') 617 L.append('') 618 body = CRLF.join(L) 619 content_type = 'multipart/form-data; boundary=%s' % BOUNDARY 620 return content_type, body
621