Tres Seaver
2012-03-19 9c1e6f85bee360d4e53bff46f6df5be5fdc254b7
commit | author | age
993216 1 import unittest
TS 2
9c1e6f 3 class _Base(unittest.TestCase):
TS 4
5     def failUnless(self, predicate, message=''):
6         self.assertTrue(predicate, message) # Nannies go home!
7
8     def failIf(self, predicate, message=''):
9         self.assertFalse(predicate, message) # Nannies go home!
10
11 class Test_get_api(_Base):
993216 12
TS 13     def _callFUT(self, environ):
14         from repoze.who.api import get_api
15         return get_api(environ)
16
17     def test___call___empty_environ(self):
18         environ = {}
19         api = self._callFUT(environ)
20         self.failUnless(api is None)
21
22     def test___call___w_api_in_environ(self):
23         expected = object()
24         environ = {'repoze.who.api': expected}
25         api = self._callFUT(environ)
26         self.failUnless(api is expected)
27
9c1e6f 28 class APIFactoryTests(_Base):
993216 29
TS 30     def _getTargetClass(self):
31         from repoze.who.api import APIFactory
32         return APIFactory
33
34     def _makeOne(self,
35                  plugins=None,
36                  identifiers=None,
37                  authenticators=None,
38                  challengers=None,
39                  mdproviders=None,
40                  request_classifier=None,
41                  challenge_decider=None,
b482a1 42                  remote_user_key=None,
993216 43                  logger=None,
TS 44                 ):
45         if plugins is None:
46             plugins = {}
47         if identifiers is None:
48             identifiers = ()
49         if authenticators is None:
50             authenticators = ()
51         if challengers is None:
52             challengers = ()
53         if mdproviders is None:
54             mdproviders = ()
55         return self._getTargetClass()(identifiers,
56                                       authenticators,
57                                       challengers,
58                                       mdproviders,
59                                       request_classifier,
60                                       challenge_decider,
b482a1 61                                       remote_user_key,
993216 62                                       logger,
TS 63                                      )
64
65     def test_class_conforms_to_IAPIFactory(self):
66         from zope.interface.verify import verifyClass
67         from repoze.who.interfaces import IAPIFactory
68         verifyClass(IAPIFactory, self._getTargetClass())
69
70     def test_instance_conforms_to_IAPIFactory(self):
71         from zope.interface.verify import verifyObject
72         from repoze.who.interfaces import IAPIFactory
73         verifyObject(IAPIFactory, self._makeOne())
74
75     def test_ctor_defaults(self):
76         factory = self._makeOne()
77         self.assertEqual(len(factory.identifiers), 0)
78         self.assertEqual(len(factory.authenticators), 0)
79         self.assertEqual(len(factory.challengers), 0)
80         self.assertEqual(len(factory.mdproviders), 0)
81         self.assertEqual(factory.request_classifier, None)
82         self.assertEqual(factory.challenge_decider, None)
83         self.assertEqual(factory.logger, None)
84
85     def test___call___empty_environ(self):
86         from repoze.who.api import API
87         environ = {}
88         factory = self._makeOne()
89         api = factory(environ)
90         self.failUnless(isinstance(api, API))
91         self.failUnless(environ['repoze.who.api'] is api)
92
93     def test___call___w_api_in_environ(self):
94         expected = object()
95         environ = {'repoze.who.api': expected}
96         factory = self._makeOne()
97         api = factory(environ)
98         self.failUnless(api is expected)
99
100
9c1e6f 101 class TestMakeRegistries(_Base):
993216 102
TS 103     def _callFUT(self, identifiers, authenticators, challengers, mdproviders):
104         from repoze.who.api import make_registries
105         return make_registries(identifiers, authenticators,
106                                challengers, mdproviders)
107
108     def test_empty(self):
109         iface_reg, name_reg = self._callFUT([], [], [], [])
110         self.assertEqual(iface_reg, {})
111         self.assertEqual(name_reg, {})
112
113     def test_brokenimpl(self):
114         self.assertRaises(ValueError, self._callFUT,
115                           [(None, object())], [], [], [])
116
117     def test_ok(self):
118         from repoze.who.interfaces import IIdentifier
119         from repoze.who.interfaces import IAuthenticator
120         from repoze.who.interfaces import IChallenger
121         from repoze.who.interfaces import IMetadataProvider
122         credentials1 = {'login':'chris', 'password':'password'}
123         dummy_id1 = DummyIdentifier(credentials1)
124         credentials2 = {'login':'chris', 'password':'password'}
125         dummy_id2 = DummyIdentifier(credentials2)
126         identifiers = [ ('id1', dummy_id1), ('id2', dummy_id2) ]
127         dummy_auth = DummyAuthenticator(None)
128         authenticators = [ ('auth', dummy_auth) ]
129         dummy_challenger = DummyChallenger(None)
130         challengers = [ ('challenger', dummy_challenger) ]
131         dummy_mdprovider = DummyMDProvider()
132         mdproviders = [ ('mdprovider', dummy_mdprovider) ]
133         iface_reg, name_reg = self._callFUT(identifiers, authenticators,
134                                             challengers, mdproviders)
135         self.assertEqual(iface_reg[IIdentifier], [dummy_id1, dummy_id2])
136         self.assertEqual(iface_reg[IAuthenticator], [dummy_auth])
137         self.assertEqual(iface_reg[IChallenger], [dummy_challenger])
138         self.assertEqual(iface_reg[IMetadataProvider], [dummy_mdprovider])
139         self.assertEqual(name_reg['id1'], dummy_id1)
140         self.assertEqual(name_reg['id2'], dummy_id2)
141         self.assertEqual(name_reg['auth'], dummy_auth)
142         self.assertEqual(name_reg['challenger'], dummy_challenger)
143         self.assertEqual(name_reg['mdprovider'], dummy_mdprovider)
144
9c1e6f 145 class TestMatchClassification(_Base):
993216 146
TS 147     def _getFUT(self):
148         from repoze.who.api import match_classification
149         return match_classification
150
151     def test_match_classification(self):
152         f = self._getFUT()
153         from repoze.who.interfaces import IIdentifier
154         from repoze.who.interfaces import IChallenger
155         from repoze.who.interfaces import IAuthenticator
156         multi1 = DummyMultiPlugin()
157         multi2 = DummyMultiPlugin()
158         multi1.classifications = {IIdentifier:('foo', 'bar'),
159                                   IChallenger:('buz',),
160                                   IAuthenticator:None}
161         multi2.classifications = {IIdentifier:('foo', 'baz', 'biz')}
162         plugins = (multi1, multi2)
163         # specific
164         self.assertEqual(f(IIdentifier, plugins, 'foo'), [multi1, multi2])
165         self.assertEqual(f(IIdentifier, plugins, 'bar'), [multi1])
166         self.assertEqual(f(IIdentifier, plugins, 'biz'), [multi2])
167         # any for multi2
168         self.assertEqual(f(IChallenger, plugins, 'buz'), [multi1, multi2])
169         # any for either
170         self.assertEqual(f(IAuthenticator, plugins, 'buz'), [multi1, multi2])
171
9c1e6f 172 class APITests(_Base):
993216 173
TS 174     def _getTargetClass(self):
175         from repoze.who.api import API
176         return API
177
178     def _makeOne(self,
b482a1 179                  environ=None,
993216 180                  identifiers=None,
TS 181                  authenticators=None,
182                  challengers=None,
b482a1 183                  request_classifier=None,
993216 184                  mdproviders=None,
TS 185                  challenge_decider=None,
b482a1 186                  remote_user_key=None,
993216 187                  logger=None
TS 188                  ):
b482a1 189         if environ is None:
TS 190             environ = {}
993216 191         if identifiers is None:
TS 192             identifiers = []
193         if authenticators is None:
194             authenticators = []
195         if challengers is None:
196             challengers = []
b482a1 197         if request_classifier is None:
TS 198             request_classifier = DummyRequestClassifier()
993216 199         if mdproviders is None:
TS 200             mdproviders = []
201         if challenge_decider is None:
202             challenge_decider = DummyChallengeDecider()
b482a1 203         api = self._getTargetClass()(environ,
TS 204                                      identifiers,
993216 205                                      authenticators,
TS 206                                      challengers,
207                                      mdproviders,
b482a1 208                                      request_classifier,
993216 209                                      challenge_decider,
b482a1 210                                      remote_user_key,
993216 211                                      logger,
TS 212                                     )
213         return api
214
215     def _makeEnviron(self):
02a504 216         from wsgiref.util import setup_testing_defaults
AO 217         environ = {}
218         setup_testing_defaults(environ)
219         return environ
b482a1 220
TS 221     def test_class_conforms_to_IAPI(self):
222         from zope.interface.verify import verifyClass
223         from repoze.who.interfaces import IAPI
224         verifyClass(IAPI, self._getTargetClass())
993216 225
52bc23 226     def test_ctor_accepts_logger_instance(self):
TS 227         logger = DummyLogger()
228         api = self._makeOne(logger=logger)
229         self.assertEqual(len(logger._info), 1)
230         self.assertEqual(logger._info[0], 'request classification: browser')
231         self.assertEqual(len(logger._debug), 0)
232
233     def test_authenticate_no_identities(self):
234         logger = DummyLogger()
235         environ = self._makeEnviron()
236         plugin = DummyNoResultsIdentifier()
237         plugins = [ ('dummy', plugin) ]
238         api = self._makeOne(environ=environ,
239                             identifiers=plugins,
240                             logger=logger)
241         identity = api.authenticate()
242         self.assertEqual(identity, None)
243         self.assertEqual(len(logger._info), 2)
244         self.assertEqual(logger._info[0], 'request classification: browser')
245         self.assertEqual(logger._info[1], 'no identities found, '
246                                           'not authenticating')
247
248     def test_authenticate_w_identities_no_authenticators(self):
249         logger = DummyLogger()
250         environ = self._makeEnviron()
251         credentials = {'login':'chris', 'password':'password'}
252         identifier = DummyIdentifier(credentials)
253         identifiers = [ ('i', identifier) ]
254         api = self._makeOne(environ=environ,
255                             identifiers=identifiers, logger=logger)
256         identity = api.authenticate()
257         self.assertEqual(identity, None)
258         self.assertEqual(len(logger._info), 2)
259         self.assertEqual(logger._info[0], 'request classification: browser')
260         # Hmm, should this message distinguish "none found" from
261         # "none authenticated"?
262         self.assertEqual(logger._info[1], 'no identities found, '
263                                           'not authenticating')
264
265     #def test_authenticate_w_identities_w_authenticators_miss(self):
266     def test_authenticate_w_identities_w_authenticators_hit(self):
267         logger = DummyLogger()
268         environ = self._makeEnviron()
269         credentials = {'login':'chris', 'password':'password'}
270         identifier = DummyIdentifier(credentials)
271         identifiers = [ ('i', identifier) ]
272         authenticator = DummyAuthenticator('chrisid')
273         authenticators = [ ('a', authenticator) ]
274         api = self._makeOne(environ=environ,
275                             identifiers=identifiers,
276                             authenticators=authenticators,
277                             logger=logger)
278         identity = api.authenticate()
279         self.assertEqual(identity['repoze.who.userid'], 'chrisid')
280         self.failUnless(identity['identifier'] is identifier)
281         self.failUnless(identity['authenticator'] is authenticator)
282
283         self.assertEqual(len(logger._info), 1)
284         self.assertEqual(logger._info[0], 'request classification: browser')
285
286     def test_challenge_noidentifier_noapp(self):
287         logger = DummyLogger()
288         identity = {'login':'chris', 'password':'password'}
289         environ = self._makeEnviron()
290         environ['repoze.who.identity'] = identity
291         challenger = DummyChallenger()
292         plugins = [ ('challenge', challenger) ]
293         api = self._makeOne(environ=environ,
294                             challengers=plugins,
295                             request_classifier=lambda environ: 'match',
296                             logger=logger,
297                            )
298         app = api.challenge('401 Unauthorized', [])
299         self.assertEqual(app, None)
300         self.assertEqual(environ['challenged'], None)
301         self.assertEqual(len(logger._info), 2)
302         self.assertEqual(logger._info[0], 'request classification: match')
303         self.assertEqual(logger._info[1], 'no challenge app returned')
304         self.assertEqual(len(logger._debug), 2)
305         self.failUnless(logger._debug[0].startswith(
306                                         'challengers registered: ['))
307         self.failUnless(logger._debug[1].startswith(
308                                         'challengers matched for '
309                                         'classification "match": ['))
310
311     def test_challenge_noidentifier_with_app(self):
312         logger = DummyLogger()
313         identity = {'login':'chris', 'password':'password'}
314         environ = self._makeEnviron()
315         environ['repoze.who.identity'] = identity
316         app = DummyApp()
317         challenger = DummyChallenger(app)
318         plugins = [ ('challenge', challenger) ]
319         api = self._makeOne(environ=environ,
320                             challengers=plugins,
321                             request_classifier=lambda environ: 'match',
322                             logger=logger,
323                            )
324         result = api.challenge('401 Unauthorized', [])
325         self.assertEqual(result, app)
326         self.assertEqual(environ['challenged'], app)
327         self.assertEqual(len(logger._info), 2)
328         self.assertEqual(logger._info[0], 'request classification: match')
329         self.failUnless(logger._info[1].startswith('challenger plugin '))
330         self.failUnless(logger._info[1].endswith(
331                          '"challenge" returned an app'))
332         self.assertEqual(len(logger._debug), 2)
333         self.failUnless(logger._debug[0].startswith(
334                                         'challengers registered: ['))
335         self.failUnless(logger._debug[1].startswith(
336                                         'challengers matched for '
337                                         'classification "match": ['))
338
339     def test_challenge_identifier_no_app_no_forget_headers(self):
340         logger = DummyLogger()
341         credentials = {'login':'chris', 'password':'password'}
342         identifier = DummyIdentifier(credentials)
343         identity = {'login':'chris',
344                     'password':'password',
345                     'identifier': identifier}
346         environ = self._makeEnviron()
347         environ['repoze.who.identity'] = identity
348         challenger = DummyChallenger()
349         plugins = [ ('challenge', challenger) ]
350         api = self._makeOne(environ=environ,
351                             challengers=plugins,
352                             request_classifier=lambda environ: 'match',
353                             logger=logger,
354                            )
355         result = api.challenge('401 Unauthorized', [])
356         self.assertEqual(result, None)
357         self.assertEqual(environ['challenged'], None)
358         self.assertEqual(identifier.forgotten, identity)
359         self.assertEqual(len(logger._info), 2)
360         self.assertEqual(logger._info[0], 'request classification: match')
361         self.assertEqual(logger._info[1], 'no challenge app returned')
362         self.assertEqual(len(logger._debug), 2)
363         self.failUnless(logger._debug[0].startswith(
364                                         'challengers registered: ['))
365         self.failUnless(logger._debug[1].startswith(
366                                         'challengers matched for '
367                                         'classification "match": ['))
368
369     def test_challenge_identifier_app_no_forget_headers(self):
370         logger = DummyLogger()
371         credentials = {'login':'chris', 'password':'password'}
372         identifier = DummyIdentifier(credentials)
373         identity = {'login':'chris',
374                     'password':'password',
375                     'identifier': identifier}
376         environ = self._makeEnviron()
377         environ['repoze.who.identity'] = identity
378         app = DummyApp()
379         challenger = DummyChallenger(app)
380         plugins = [ ('challenge', challenger) ]
381         api = self._makeOne(environ=environ,
382                             challengers=plugins,
383                             request_classifier=lambda environ: 'match',
384                             logger=logger,
385                            )
386         result = api.challenge('401 Unauthorized', [])
387         self.assertEqual(result, app)
388         self.assertEqual(environ['challenged'], app)
389         self.assertEqual(identifier.forgotten, identity)
390         self.assertEqual(len(logger._info), 2)
391         self.assertEqual(logger._info[0], 'request classification: match')
392         self.failUnless(logger._info[1].startswith('challenger plugin '))
393         self.failUnless(logger._info[1].endswith(
394                          '"challenge" returned an app'))
395         self.assertEqual(len(logger._debug), 2)
396         self.failUnless(logger._debug[0].startswith(
397                                         'challengers registered: ['))
398         self.failUnless(logger._debug[1].startswith(
399                                         'challengers matched for '
400                                         'classification "match": ['))
401
402     def test_challenge_identifier_no_app_forget_headers(self):
403         FORGET_HEADERS = [('X-testing-forget', 'Oubliez!')]
404         logger = DummyLogger()
405         credentials = {'login':'chris', 'password':'password'}
406         identifier = DummyIdentifier(credentials,
407                                      forget_headers=FORGET_HEADERS)
408         identity = {'login':'chris',
409                     'password':'password',
410                     'identifier': identifier}
411         environ = self._makeEnviron()
412         environ['repoze.who.identity'] = identity
413         app = DummyApp()
414         challenger = DummyChallenger(app)
415         plugins = [ ('challenge', challenger) ]
416         api = self._makeOne(environ=environ,
417                             challengers=plugins,
418                             request_classifier=lambda environ: 'match',
419                             logger=logger,
420                            )
421         result = api.challenge('401 Unauthorized', [])
422         self.assertEqual(result, app)
423         self.assertEqual(environ['challenged'], app)
424         self.assertEqual(challenger._challenged_with[3], FORGET_HEADERS)
425         self.assertEqual(len(logger._info), 3)
426         self.assertEqual(logger._info[0], 'request classification: match')
427         self.failUnless(logger._info[1].startswith(
428                                         'forgetting via headers from'))
429         self.failUnless(logger._info[1].endswith(repr(FORGET_HEADERS)))
430         self.failUnless(logger._info[2].startswith('challenger plugin '))
431         self.failUnless(logger._info[2].endswith(
432                          '"challenge" returned an app'))
433         self.assertEqual(len(logger._debug), 2)
434         self.failUnless(logger._debug[0].startswith(
435                                         'challengers registered: ['))
436         self.failUnless(logger._debug[1].startswith(
437                                         'challengers matched for '
438                                         'classification "match": ['))
439
440     def test_multi_challenge_firstwins(self):
441         credentials = {'login':'chris', 'password':'password'}
442         identifier = DummyIdentifier(credentials)
443         identity = {'login':'chris',
444                     'password':'password',
445                     'identifier': identifier}
446         environ = self._makeEnviron()
447         environ['repoze.who.identity'] = identity
448         app1 = DummyApp()
449         app2 = DummyApp()
450         challenger1 = DummyChallenger(app1)
451         challenger2 = DummyChallenger(app2)
452         plugins = [ ('challenge1', challenger1), ('challenge2', challenger2) ]
453         api = self._makeOne(environ=environ, challengers=plugins,
454                             request_classifier=lambda environ: 'match')
455         result = api.challenge('401 Unauthorized', [])
456         self.assertEqual(result, app1)
457         self.assertEqual(environ['challenged'], app1)
458         self.assertEqual(identifier.forgotten, identity)
459
460     def test_multi_challenge_skipnomatch_findimplicit(self):
461         from repoze.who.interfaces import IChallenger
462         credentials = {'login':'chris', 'password':'password'}
463         identifier = DummyIdentifier(credentials)
464         identity = {'login':'chris',
465                     'password':'password',
466                     'identifier': identifier}
467         environ = self._makeEnviron()
468         environ['repoze.who.identity'] = identity
469         app1 = DummyApp()
470         app2 = DummyApp()
471         challenger1 = DummyChallenger(app1)
472         challenger1.classifications = {IChallenger:['nomatch']}
473         challenger2 = DummyChallenger(app2)
474         challenger2.classifications = {IChallenger:None}
475         plugins = [ ('challenge1', challenger1), ('challenge2', challenger2) ]
476         api = self._makeOne(environ=environ, challengers=plugins,
477                             request_classifier=lambda environ: 'match')
478         result = api.challenge('401 Unauthorized', [])
479         self.assertEqual(result, app2)
480         self.assertEqual(environ['challenged'], app2)
481         self.assertEqual(identifier.forgotten, identity)
482
483     def test_multi_challenge_skipnomatch_findexplicit(self):
484         from repoze.who.interfaces import IChallenger
485         credentials = {'login':'chris', 'password':'password'}
486         identifier = DummyIdentifier(credentials)
487         identity = {'login':'chris',
488                     'password':'password',
489                     'identifier': identifier}
490         environ = self._makeEnviron()
491         environ['repoze.who.identity'] = identity
492         app1 = DummyApp()
493         app2 = DummyApp()
494         challenger1 = DummyChallenger(app1)
495         challenger1.classifications = {IChallenger:['nomatch']}
496         challenger2 = DummyChallenger(app2)
497         challenger2.classifications = {IChallenger:['match']}
498         plugins = [ ('challenge1', challenger1), ('challenge2', challenger2) ]
499         api = self._makeOne(environ=environ, challengers=plugins,
500                             request_classifier=lambda environ: 'match')
501         result = api.challenge('401 Unauthorized', [])
502         self.assertEqual(result, app2)
503         self.assertEqual(environ['challenged'], app2)
504         self.assertEqual(identifier.forgotten, identity)
505
fdd86d 506     def test_remember_identifier_plugin_returns_none(self):
TS 507         class _Identifier:
508             def identify(self, environ):
509                 return None
510             def remember(self, environ, identity):
511                 return ()
512             def forget(self, environ, identity):
513                 return ()
514         identity = {'identifier': _Identifier()}
515         api = self._makeOne()
516         headers = api.remember(identity=identity)
517         self.assertEqual(tuple(headers), ())
518
52bc23 519     def test_remember_no_identity_passed_or_in_environ(self):
TS 520         logger = DummyLogger()
521         environ = self._makeEnviron()
522         api = self._makeOne(environ=environ)
523         self.assertEqual(len(api.remember()), 0)
524         self.assertEqual(len(logger._info), 0)
525         self.assertEqual(len(logger._debug), 0)
526
527     def test_remember_no_identity_passed_but_in_environ(self):
528         HEADERS = [('Foo', 'Bar'), ('Baz', 'Qux')]
529         logger = DummyLogger()
530         class _Identifier:
531             def remember(self, environ, identity):
532                 return HEADERS
533         environ = self._makeEnviron()
534         environ['repoze.who.identity'] = {'identifier': _Identifier()}
535         api = self._makeOne(environ=environ, logger=logger)
536         self.assertEqual(api.remember(), HEADERS)
537         self.assertEqual(len(logger._info), 2)
538         self.assertEqual(logger._info[0], 'request classification: browser')
539         self.failUnless(logger._info[1].startswith(
540                                         'remembering via headers from'))
541         self.failUnless(logger._info[1].endswith(repr(HEADERS)))
542         self.assertEqual(len(logger._debug), 0)
543
544     def test_remember_w_identity_passed_no_identifier(self):
545         logger = DummyLogger()
546         environ = self._makeEnviron()
547         api = self._makeOne(environ=environ, logger=logger)
548         identity = {}
549         self.assertEqual(len(api.remember(identity)), 0)
550         self.assertEqual(len(logger._info), 1)
551         self.assertEqual(logger._info[0], 'request classification: browser')
552         self.assertEqual(len(logger._debug), 0)
553
554     def test_remember_w_identity_passed_w_identifier(self):
555         HEADERS = [('Foo', 'Bar'), ('Baz', 'Qux')]
556         logger = DummyLogger()
557         class _Identifier:
558             def remember(self, environ, identity):
559                 return HEADERS
560         environ = self._makeEnviron()
561         api = self._makeOne(environ=environ, logger=logger)
562         identity = {'identifier': _Identifier()}
563         self.assertEqual(api.remember(identity), HEADERS)
564         self.assertEqual(len(logger._info), 2)
565         self.assertEqual(logger._info[0], 'request classification: browser')
566         self.failUnless(logger._info[1].startswith(
567                                         'remembering via headers from'))
568         self.failUnless(logger._info[1].endswith(repr(HEADERS)))
569         self.assertEqual(len(logger._debug), 0)
fdd86d 570
TS 571     def test_forget_identifier_plugin_returns_none(self):
572         class _Identifier:
573             def identify(self, environ):
574                 return None
575             def remember(self, environ, identity):
576                 return ()
577             def forget(self, environ, identity):
578                 return ()
579         identity = {'identifier': _Identifier()}
580         api = self._makeOne()
581         headers = api.forget(identity=identity)
582         self.assertEqual(tuple(headers), ())
52bc23 583
TS 584     def test_forget_no_identity_passed_or_in_environ(self):
585         logger = DummyLogger()
586         environ = self._makeEnviron()
587         api = self._makeOne(environ=environ, logger=logger)
588         self.assertEqual(len(api.forget()), 0)
589         self.assertEqual(len(logger._info), 1)
590         self.assertEqual(logger._info[0], 'request classification: browser')
591         self.assertEqual(len(logger._debug), 0)
592
593     def test_forget_no_identity_passed_but_in_environ(self):
594         HEADERS = [('Foo', 'Bar'), ('Baz', 'Qux')]
595         logger = DummyLogger()
596         class _Identifier:
597             def forget(self, environ, identity):
598                 return HEADERS
599         environ = self._makeEnviron()
600         environ['repoze.who.identity'] = {'identifier': _Identifier()}
601         api = self._makeOne(environ=environ, logger=logger)
602         self.assertEqual(api.forget(), HEADERS)
603         self.assertEqual(len(logger._info), 2)
604         self.assertEqual(logger._info[0], 'request classification: browser')
605         self.failUnless(logger._info[1].startswith(
606                                         'forgetting via headers from'))
607         self.failUnless(logger._info[1].endswith(repr(HEADERS)))
608         self.assertEqual(len(logger._debug), 0)
609
610     def test_forget_w_identity_passed_no_identifier(self):
611         environ = self._makeEnviron()
612         logger = DummyLogger()
613         api = self._makeOne(environ=environ, logger=logger)
614         identity = {}
615         self.assertEqual(len(api.forget(identity)), 0)
616         self.assertEqual(len(logger._info), 1)
617         self.assertEqual(logger._info[0], 'request classification: browser')
618         self.assertEqual(len(logger._debug), 0)
619
620     def test_forget_w_identity_passed_w_identifier(self):
621         HEADERS = [('Foo', 'Bar'), ('Baz', 'Qux')]
622         logger = DummyLogger()
623         class _Identifier:
624             def forget(self, environ, identity):
625                 return HEADERS
626         environ = self._makeEnviron()
627         api = self._makeOne(environ=environ, logger=logger)
628         identity = {'identifier': _Identifier()}
629         self.assertEqual(api.forget(identity), HEADERS)
630         self.assertEqual(len(logger._info), 2)
631         self.assertEqual(logger._info[0], 'request classification: browser')
632         self.failUnless(logger._info[1].startswith(
633                                         'forgetting via headers from'))
634         self.failUnless(logger._info[1].endswith(repr(HEADERS)))
635         self.assertEqual(len(logger._debug), 0)
993216 636
9a8e60 637     def test_login_w_identifier_name_hit(self):
TS 638         REMEMBER_HEADERS = [('Foo', 'Bar'), ('Baz', 'Qux')]
639         FORGET_HEADERS = [('Spam', 'Blah')]
640         class _Identifier:
641             def identify(self, environ):
642                 pass
643             def remember(self, environ, identity):
fdd86d 644                 return REMEMBER_HEADERS[1:]
9a8e60 645             def forget(self, environ, identity):
TS 646                 return FORGET_HEADERS
647         class _BogusIdentifier:
648             def identify(self, environ):
649                 pass
650             def remember(self, environ, identity):
fdd86d 651                 return REMEMBER_HEADERS[:1]
9a8e60 652             def forget(self, environ, identity):
TS 653                 pass
654         authenticator = DummyAuthenticator('chrisid')
655         environ = self._makeEnviron()
656         identifiers = [('bogus', _BogusIdentifier()),
657                        ('valid', _Identifier()),
658                       ]
659         api = self._makeOne(identifiers=identifiers,
660                             authenticators=[('authentic', authenticator)],
661                             environ=environ)
662         identity, headers = api.login({'login': 'chrisid'}, 'valid')
663         self.assertEqual(identity['repoze.who.userid'], 'chrisid')
fdd86d 664         self.assertEqual(headers, REMEMBER_HEADERS[1:])
cfe26c 665
9a8e60 666     def test_login_wo_identifier_name_hit(self):
TS 667         REMEMBER_HEADERS = [('Foo', 'Bar'), ('Baz', 'Qux')]
668         FORGET_HEADERS = [('Spam', 'Blah')]
669         class _Identifier:
670             def identify(self, environ):
671                 pass
672             def remember(self, environ, identity):
fdd86d 673                 return REMEMBER_HEADERS[1:]
9a8e60 674             def forget(self, environ, identity):
TS 675                 return FORGET_HEADERS
676         class _BogusIdentifier:
677             def identify(self, environ):
678                 pass
679             def remember(self, environ, identity):
fdd86d 680                 return REMEMBER_HEADERS[:1]
9a8e60 681             def forget(self, environ, identity):
TS 682                 pass
683         authenticator = DummyAuthenticator('chrisid')
684         environ = self._makeEnviron()
fdd86d 685         identifiers = [('bogus', _BogusIdentifier()),
TS 686                        ('valid', _Identifier()),
9a8e60 687                       ]
TS 688         api = self._makeOne(identifiers=identifiers,
689                             authenticators=[('authentic', authenticator)],
690                             environ=environ)
691         identity, headers = api.login({'login': 'chrisid'})
fdd86d 692         self.assertEqual(identity['repoze.who.userid'], 'chrisid')
9a8e60 693         self.assertEqual(headers, REMEMBER_HEADERS)
TS 694
695     def test_login_w_identifier_name_miss(self):
696         REMEMBER_HEADERS = [('Foo', 'Bar'), ('Baz', 'Qux')]
697         FORGET_HEADERS = [('Spam', 'Blah')]
698         class _Identifier:
699             def identify(self, environ):
700                 pass
701             def remember(self, environ, identity):
702                 return REMEMBER_HEADERS
703             def forget(self, environ, identity):
704                 return FORGET_HEADERS
705         class _BogusIdentifier:
706             def identify(self, environ):
707                 pass
708             def remember(self, environ, identity):
fdd86d 709                 return ()
9a8e60 710             def forget(self, environ, identity):
fdd86d 711                 return ()
9a8e60 712         authenticator = DummyFailAuthenticator()
TS 713         environ = self._makeEnviron()
714         identifiers = [('bogus', _BogusIdentifier()),
715                        ('valid', _Identifier()),
716                       ]
717         api = self._makeOne(identifiers=identifiers,
718                             authenticators=[('authentic', authenticator)],
719                             environ=environ)
720         identity, headers = api.login({'login': 'notchrisid'}, 'valid')
721         self.assertEqual(identity, None)
722         self.assertEqual(headers, FORGET_HEADERS)
723
fdd86d 724     def test_logout_wo_identifier_name_miss(self):
924f24 725         FORGET_HEADERS = [('Spam', 'Blah')]
TS 726         class _Identifier:
727             def identify(self, environ):
728                 pass
729             def remember(self, environ, identity):
fdd86d 730                 return ()
924f24 731             def forget(self, environ, identity):
fdd86d 732                 return FORGET_HEADERS[:1]
924f24 733         class _BogusIdentifier:
TS 734             def identify(self, environ):
735                 pass
736             def remember(self, environ, identity):
fdd86d 737                 return ()
924f24 738             def forget(self, environ, identity):
fdd86d 739                 return FORGET_HEADERS[1:]
924f24 740         environ = self._makeEnviron()
TS 741         identifiers = [('valid', _Identifier()),
742                        ('bogus', _BogusIdentifier()),
743                       ]
744         api = self._makeOne(identifiers=identifiers,
745                             environ=environ)
746         headers = api.logout()
747         self.assertEqual(headers, FORGET_HEADERS)
748
749     def test_logout_w_identifier_name(self):
750         FORGET_HEADERS = [('Spam', 'Blah')]
751         class _Identifier:
752             def identify(self, environ):
753                 pass
754             def remember(self, environ, identity):
fdd86d 755                 return ()
924f24 756             def forget(self, environ, identity):
TS 757                 return FORGET_HEADERS
758         class _BogusIdentifier:
759             def identify(self, environ):
760                 pass
761             def remember(self, environ, identity):
fdd86d 762                 return ()
924f24 763             def forget(self, environ, identity):
fdd86d 764                 return ()
924f24 765         environ = self._makeEnviron()
TS 766         identifiers = [('bogus', _BogusIdentifier()),
767                        ('valid', _Identifier()),
768                       ]
769         api = self._makeOne(identifiers=identifiers,
770                             environ=environ)
771         headers = api.logout('valid')
772         self.assertEqual(headers, FORGET_HEADERS)
773
774     def test_logout_wo_identifier_name(self):
9a8e60 775         REMEMBER_HEADERS = [('Foo', 'Bar'), ('Baz', 'Qux')]
TS 776         FORGET_HEADERS = [('Spam', 'Blah')]
777         class _Identifier:
778             def identify(self, environ):
779                 pass
780             def remember(self, environ, identity):
781                 return REMEMBER_HEADERS
782             def forget(self, environ, identity):
783                 return FORGET_HEADERS
784         class _BogusIdentifier:
785             def identify(self, environ):
786                 pass
787             def remember(self, environ, identity):
fdd86d 788                 return ()
9a8e60 789             def forget(self, environ, identity):
fdd86d 790                 return ()
9a8e60 791         authenticator = DummyFailAuthenticator()
TS 792         environ = self._makeEnviron()
793         identifiers = [('valid', _Identifier()),
794                        ('bogus', _BogusIdentifier()),
795                       ]
796         api = self._makeOne(identifiers=identifiers,
797                             authenticators=[('authentic', authenticator)],
798                             environ=environ)
e24a75 799         headers = api.logout()
9a8e60 800         self.assertEqual(headers, FORGET_HEADERS)
TS 801
e24a75 802     def test_logout_removes_repoze_who_identity(self):
CM 803         class _Identifier:
804             def identify(self, environ):
805                 pass
806             def forget(self, environ, identity):
fdd86d 807                 return ()
e24a75 808             def remember(self, environ, identity):
fdd86d 809                 return ()
e24a75 810         authenticator = DummyFailAuthenticator()
CM 811         environ = self._makeEnviron()
812         environ['repoze.who.identity'] = 'identity'
813         identifiers = [('valid', _Identifier())]
814         api = self._makeOne(identifiers=identifiers,
815                             authenticators=[('authentic', authenticator)],
816                             environ=environ)
817         api.logout()
818         self.failIf('repoze.who.identity' in environ)
819
b482a1 820     def test__identify_success(self):
993216 821         environ = self._makeEnviron()
TS 822         credentials = {'login':'chris', 'password':'password'}
823         identifier = DummyIdentifier(credentials)
824         identifiers = [ ('i', identifier) ]
b482a1 825         api = self._makeOne(environ=environ, identifiers=identifiers)
TS 826         results = api._identify()
993216 827         self.assertEqual(len(results), 1)
TS 828         new_identifier, identity = results[0]
829         self.assertEqual(new_identifier, identifier)
830         self.assertEqual(identity['login'], 'chris')
831         self.assertEqual(identity['password'], 'password')
832
b482a1 833     def test__identify_success_empty_identity(self):
993216 834         environ = self._makeEnviron()
TS 835         identifier = DummyIdentifier({})
836         identifiers = [ ('i', identifier) ]
b482a1 837         api = self._makeOne(environ=environ, identifiers=identifiers)
TS 838         results = api._identify()
993216 839         self.assertEqual(len(results), 1)
TS 840         new_identifier, identity = results[0]
841         self.assertEqual(new_identifier, identifier)
842         self.assertEqual(identity, {})
843
b482a1 844     def test__identify_fail(self):
52bc23 845         logger = DummyLogger()
993216 846         environ = self._makeEnviron()
TS 847         plugin = DummyNoResultsIdentifier()
848         plugins = [ ('dummy', plugin) ]
52bc23 849         api = self._makeOne(environ=environ,
TS 850                             identifiers=plugins,
851                             logger=logger)
b482a1 852         results = api._identify()
993216 853         self.assertEqual(len(results), 0)
52bc23 854         self.assertEqual(len(logger._info), 1)
TS 855         self.assertEqual(logger._info[0], 'request classification: browser')
856         self.assertEqual(len(logger._debug), 4)
857         self.failUnless(logger._debug[0].startswith(
858                                         'identifier plugins registered: ['))
859         self.failUnless(logger._debug[1].startswith(
860                                         'identifier plugins matched for '
861                                         'classification "browser": ['))
862         self.failUnless(logger._debug[2].startswith(
863                                         'no identity returned from <'))
864         self.failUnless(logger._debug[2].endswith('> (None)'))
865         self.assertEqual(logger._debug[3], 'identities found: []')
993216 866
b482a1 867     def test__identify_success_skip_noresults(self):
993216 868         environ = self._makeEnviron()
TS 869         api = self._makeOne()
870         plugin1 = DummyNoResultsIdentifier()
871         credentials = {'login':'chris', 'password':'password'}
872         plugin2 = DummyIdentifier(credentials)
873         plugins = [ ('identifier1', plugin1), ('identifier2', plugin2) ]
b482a1 874         api = self._makeOne(environ=environ, identifiers=plugins)
TS 875         results = api._identify()
993216 876         self.assertEqual(len(results), 1)
TS 877         new_identifier, identity = results[0]
878         self.assertEqual(new_identifier, plugin2)
879         self.assertEqual(identity['login'], 'chris')
880         self.assertEqual(identity['password'], 'password')
881
b482a1 882     def test__identify_success_multiresults(self):
993216 883         environ = self._makeEnviron()
TS 884         api = self._makeOne()
885         plugin1 = DummyIdentifier({'login':'fred','password':'fred'})
886         plugin2 = DummyIdentifier({'login':'bob','password':'bob'})
887         plugins = [ ('identifier1', plugin1), ('identifier2', plugin2) ]
b482a1 888         api = self._makeOne(environ=environ, identifiers=plugins)
TS 889         results = api._identify()
993216 890         self.assertEqual(len(results), 2)
TS 891         new_identifier, identity = results[0]
892         self.assertEqual(new_identifier, plugin1)
893         self.assertEqual(identity['login'], 'fred')
894         self.assertEqual(identity['password'], 'fred')
895         new_identifier, identity = results[1]
896         self.assertEqual(new_identifier, plugin2)
897         self.assertEqual(identity['login'], 'bob')
898         self.assertEqual(identity['password'], 'bob')
899
b482a1 900     def test__identify_find_implicit_classifier(self):
993216 901         environ = self._makeEnviron()
TS 902         api = self._makeOne()
903         plugin1 = DummyIdentifier({'login':'fred','password':'fred'})
904         from repoze.who.interfaces import IIdentifier
905         plugin1.classifications = {IIdentifier:['nomatch']}
906         plugin2 = DummyIdentifier({'login':'bob','password':'bob'})
907         plugins = [ ('identifier1', plugin1),  ('identifier2', plugin2) ]
b482a1 908         api = self._makeOne(environ=environ, identifiers=plugins,
TS 909                             request_classifier=lambda environ: 'match')
910         results = api._identify()
993216 911         self.assertEqual(len(results), 1)
TS 912         plugin, creds = results[0]
913         self.assertEqual(creds['login'], 'bob')
914         self.assertEqual(creds['password'], 'bob')
915         self.assertEqual(plugin, plugin2)
916
b482a1 917     def test__identify_find_explicit_classifier(self):
993216 918         environ = self._makeEnviron()
TS 919         from repoze.who.interfaces import IIdentifier
920         plugin1 = DummyIdentifier({'login':'fred','password':'fred'})
921         plugin1.classifications = {IIdentifier:['nomatch']}
922         plugin2 = DummyIdentifier({'login':'bob','password':'bob'})
923         plugin2.classifications = {IIdentifier:['match']}
924         plugins= [ ('identifier1', plugin1), ('identifier2', plugin2) ]
b482a1 925         api = self._makeOne(environ=environ, identifiers=plugins,
TS 926                             request_classifier=lambda environ: 'match')
927         results = api._identify()
993216 928         self.assertEqual(len(results), 1)
TS 929         plugin, creds = results[0]
930         self.assertEqual(creds['login'], 'bob')
931         self.assertEqual(creds['password'], 'bob')
932         self.assertEqual(plugin, plugin2)
933
b482a1 934     def test__authenticate_success(self):
993216 935         environ = self._makeEnviron()
TS 936         plugin1 = DummyAuthenticator('a')
937         plugins = [ ('identifier1', plugin1) ]
b482a1 938         api = self._makeOne(environ=environ, authenticators=plugins)
993216 939         identities = [ (None, {'login':'chris', 'password':'password'}) ]
b482a1 940         results = api._authenticate(identities)
993216 941         self.assertEqual(len(results), 1)
TS 942         result = results[0]
943         rank, authenticator, identifier, creds, userid = result
944         self.assertEqual(rank, (0,0))
945         self.assertEqual(authenticator, plugin1)
946         self.assertEqual(identifier, None)
947         self.assertEqual(creds['login'], 'chris')
948         self.assertEqual(creds['password'], 'password')
949         self.assertEqual(userid, 'a')
950
b482a1 951     def test__authenticate_fail(self):
52bc23 952         logger = DummyLogger()
993216 953         environ = self._makeEnviron()
52bc23 954         # no authenticators
TS 955         api = self._makeOne(environ=environ, logger=logger)
993216 956         identities = [ (None, {'login':'chris', 'password':'password'}) ]
b482a1 957         result = api._authenticate(identities)
993216 958         self.assertEqual(len(result), 0)
52bc23 959         self.assertEqual(len(logger._info), 1)
TS 960         self.assertEqual(logger._info[0], 'request classification: browser')
961         self.assertEqual(len(logger._debug), 3)
962         self.assertEqual(logger._debug[0], 'authenticator plugins '
963                                            'registered: []')
964         self.assertEqual(logger._debug[1], 'authenticator plugins matched '
965                                            'for classification "browser": []')
966         self.assertEqual(logger._debug[2], 'identities authenticated: []')
993216 967
b482a1 968     def test__authenticate_success_skip_fail(self):
52bc23 969         logger = DummyLogger()
993216 970         environ = self._makeEnviron()
TS 971         plugin1 = DummyFailAuthenticator()
972         plugin2 = DummyAuthenticator()
973         plugins = [ ('dummy1', plugin1), ('dummy2', plugin2) ]
52bc23 974         api = self._makeOne(authenticators=plugins, logger=logger)
993216 975         creds = {'login':'chris', 'password':'password'}
TS 976         identities = [ (None, {'login':'chris', 'password':'password'}) ]
b482a1 977         results = api._authenticate(identities)
993216 978         self.assertEqual(len(results), 1)
TS 979         result = results[0]
980         rank, authenticator, identifier, creds, userid = result
981         self.assertEqual(rank, (1,0))
982         self.assertEqual(authenticator, plugin2)
983         self.assertEqual(identifier, None)
984         self.assertEqual(creds['login'], 'chris')
985         self.assertEqual(creds['password'], 'password')
986         self.assertEqual(userid, 'chris')
987
52bc23 988         self.assertEqual(len(logger._info), 1)
TS 989         self.assertEqual(logger._info[0], 'request classification: browser')
990         self.assertEqual(len(logger._debug), 5)
991         self.failUnless(logger._debug[0].startswith(
992                                         'authenticator plugins registered: ['))
993         self.failUnless(logger._debug[1].startswith(
994                                         'authenticator plugins matched for '
995                                         'classification "browser": ['))
996         self.failUnless(logger._debug[2].startswith('no userid returned from'))
997         self.failUnless(logger._debug[3].startswith('userid returned from'))
998         self.failUnless(logger._debug[3].endswith('"chris"'))
999         self.failUnless(logger._debug[4].startswith(
1000                                          'identities authenticated: [((1, 0),'))
1001
b482a1 1002     def test__authenticate_success_multiresult(self):
52bc23 1003         logger = DummyLogger()
993216 1004         environ = self._makeEnviron()
TS 1005         plugin1 = DummyAuthenticator('chris_id1')
1006         plugin2 = DummyAuthenticator('chris_id2')
1007         plugins = [ ('dummy1',plugin1), ('dummy2',plugin2) ]
52bc23 1008         api = self._makeOne(environ=environ,
TS 1009                             authenticators=plugins, logger=logger)
993216 1010         creds = {'login':'chris', 'password':'password'}
TS 1011         identities = [ (None, {'login':'chris', 'password':'password'}) ]
b482a1 1012         results = api._authenticate(identities)
993216 1013         self.assertEqual(len(results), 2)
TS 1014         result = results[0]
1015         rank, authenticator, identifier, creds, userid = result
1016         self.assertEqual(rank, (0,0,))
1017         self.assertEqual(authenticator, plugin1)
1018         self.assertEqual(identifier, None)
1019         self.assertEqual(creds['login'], 'chris')
1020         self.assertEqual(creds['password'], 'password')
1021         self.assertEqual(userid, 'chris_id1')
1022         result = results[1]
1023         rank, authenticator, identifier, creds, userid = result
1024         self.assertEqual(rank, (1,0))
1025         self.assertEqual(authenticator, plugin2)
1026         self.assertEqual(identifier, None)
1027         self.assertEqual(creds['login'], 'chris')
1028         self.assertEqual(creds['password'], 'password')
1029         self.assertEqual(userid, 'chris_id2')
52bc23 1030
TS 1031         self.assertEqual(len(logger._info), 1)
1032         self.assertEqual(logger._info[0], 'request classification: browser')
1033         self.assertEqual(len(logger._debug), 5)
1034         self.failUnless(logger._debug[0].startswith(
1035                                         'authenticator plugins registered: ['))
1036         self.failUnless(logger._debug[1].startswith(
1037                                         'authenticator plugins matched for '
1038                                         'classification "browser": ['))
1039         self.failUnless(logger._debug[2].startswith('userid returned from'))
1040         self.failUnless(logger._debug[2].endswith('"chris_id1"'))
1041         self.failUnless(logger._debug[3].startswith('userid returned from'))
1042         self.failUnless(logger._debug[3].endswith('"chris_id2"'))
1043         self.failUnless(logger._debug[4].startswith(
1044                                          'identities authenticated: [((0, 0),')
1045                                          )
993216 1046
b482a1 1047     def test__authenticate_find_implicit_classifier(self):
993216 1048         from repoze.who.interfaces import IAuthenticator
b482a1 1049         environ = self._makeEnviron()
TS 1050         plugin1 = DummyAuthenticator('chris_id1')
993216 1051         plugin1.classifications = {IAuthenticator:['nomatch']}
TS 1052         plugin2 = DummyAuthenticator('chris_id2')
1053         plugins = [ ('auth1', plugin1), ('auth2', plugin2) ]
b482a1 1054         api = self._makeOne(environ=environ, authenticators=plugins,
TS 1055                             request_classifier=lambda environ: 'match')
993216 1056         identities = [ (None, {'login':'chris', 'password':'password'}) ]
b482a1 1057         results = api._authenticate(identities)
993216 1058         self.assertEqual(len(results), 1)
TS 1059         result = results[0]
1060         rank, authenticator, identifier, creds, userid = result
1061         self.assertEqual(rank, (0,0))
1062         self.assertEqual(authenticator, plugin2)
1063         self.assertEqual(identifier, None)
1064         self.assertEqual(creds['login'], 'chris')
1065         self.assertEqual(creds['password'], 'password')
1066         self.assertEqual(userid, 'chris_id2')
1067
b482a1 1068     def test__authenticate_find_explicit_classifier(self):
993216 1069         from repoze.who.interfaces import IAuthenticator
b482a1 1070         environ = self._makeEnviron()
993216 1071         plugin1 = DummyAuthenticator('chris_id1')
TS 1072         plugin1.classifications = {IAuthenticator:['nomatch']}
1073         plugin2 = DummyAuthenticator('chris_id2')
1074         plugin2.classifications = {IAuthenticator:['match']}
1075         plugins = [ ('auth1', plugin1), ('auth2', plugin2) ]
b482a1 1076         api = self._makeOne(environ=environ, authenticators=plugins,
TS 1077                             request_classifier=lambda environ: 'match')
993216 1078         identities = [ (None, {'login':'chris', 'password':'password'}) ]
b482a1 1079         results = api._authenticate(identities)
993216 1080         self.assertEqual(len(results), 1)
TS 1081         result = results[0]
1082         rank, authenticator, identifier, creds, userid = result
1083         self.assertEqual(rank, (0, 0))
1084         self.assertEqual(authenticator, plugin2)
1085         self.assertEqual(identifier, None)
1086         self.assertEqual(creds['login'], 'chris')
1087         self.assertEqual(creds['password'], 'password')
1088         self.assertEqual(userid, 'chris_id2')
1089
b482a1 1090     def test__authenticate_user_null_but_not_none(self):
993216 1091         environ = self._makeEnviron()
TS 1092         plugin1 = DummyAuthenticator(0)
1093         plugins = [ ('identifier1', plugin1) ]
b482a1 1094         api = self._makeOne(environ=environ, authenticators=plugins)
993216 1095         identities = [ (None, {'login':'chris', 'password':'password'}) ]
b482a1 1096         results = api._authenticate(identities)
993216 1097         self.assertEqual(len(results), 1)
TS 1098         result = results[0]
1099         rank, authenticator, identifier, creds, userid = result
1100         self.assertEqual(rank, (0,0))
1101         self.assertEqual(authenticator, plugin1)
1102         self.assertEqual(identifier, None)
1103         self.assertEqual(creds['login'], 'chris')
1104         self.assertEqual(creds['password'], 'password')
1105         self.assertEqual(userid, 0)
1106
b482a1 1107     def test__add_metadata(self):
993216 1108         environ = self._makeEnviron()
TS 1109         plugin1 = DummyMDProvider({'foo':'bar'})
1110         plugin2 = DummyMDProvider({'fuz':'baz'})
1111         plugins = [ ('meta1', plugin1), ('meta2', plugin2) ]
b482a1 1112         api = self._makeOne(environ=environ, mdproviders=plugins)
993216 1113         classification = ''
TS 1114         identity = {}
b482a1 1115         results = api._add_metadata(identity)
993216 1116         self.assertEqual(identity['foo'], 'bar')
TS 1117         self.assertEqual(identity['fuz'], 'baz')
1118
b482a1 1119     def test__add_metadata_w_classification(self):
993216 1120         environ = self._makeEnviron()
TS 1121         plugin1 = DummyMDProvider({'foo':'bar'})
1122         plugin2 = DummyMDProvider({'fuz':'baz'})
1123         from repoze.who.interfaces import IMetadataProvider
1124         plugin2.classifications = {IMetadataProvider:['foo']}
1125         plugins = [ ('meta1', plugin1), ('meta2', plugin2) ]
b482a1 1126         api = self._makeOne(environ=environ, mdproviders=plugins)
993216 1127         classification = 'monkey'
TS 1128         identity = {}
b482a1 1129         api._add_metadata(identity)
993216 1130         self.assertEqual(identity['foo'], 'bar')
TS 1131         self.assertEqual(identity.get('fuz'), None)
1132
1133
9c1e6f 1134 class TestIdentityDict(_Base):
b482a1 1135
TS 1136     def _getTargetClass(self):
1137         from repoze.who.api import Identity
1138         return Identity
1139
1140     def _makeOne(self, **kw):
1141         klass = self._getTargetClass()
1142         return klass(**kw)
1143
1144     def test_str(self):
1145         identity = self._makeOne(foo=1)
1146         self.failUnless(str(identity).startswith('<repoze.who identity'))
1147         self.assertEqual(identity['foo'], 1)
1148
1149     def test_repr(self):
1150         identity = self._makeOne(foo=1)
1151         self.failUnless(str(identity).startswith('<repoze.who identity'))
1152         self.assertEqual(identity['foo'], 1)
1153
993216 1154
TS 1155
1156 class DummyIdentifier:
1157     forgotten = False
1158     remembered = False
1159
1160     def __init__(self, credentials=None, remember_headers=None,
1161                  forget_headers=None, replace_app=None):
1162         self.credentials = credentials
1163         self.remember_headers = remember_headers
1164         self.forget_headers = forget_headers
1165         self.replace_app = replace_app
1166
1167     def identify(self, environ):
1168         if self.replace_app:
1169             environ['repoze.who.application'] = self.replace_app
1170         return self.credentials
1171
1172     def forget(self, environ, identity):
1173         self.forgotten = identity
1174         return self.forget_headers
1175
1176     def remember(self, environ, identity):
1177         self.remembered = identity
1178         return self.remember_headers
1179
1180
1181 class DummyNoResultsIdentifier:
1182
1183     def identify(self, environ):
1184         return None
1185
1186     def remember(self, *arg, **kw):
1187         pass
1188
1189     def forget(self, *arg, **kw):
1190         pass
1191
1192
1193 class DummyAuthenticator:
1194     def __init__(self, userid=None):
1195         self.userid = userid
1196
1197     def authenticate(self, environ, credentials):
1198         if self.userid is None:
1199             return credentials['login']
1200         return self.userid
1201
1202
1203 class DummyFailAuthenticator:
1204     def authenticate(self, environ, credentials):
1205         return None
1206
1207
1208 class DummyChallenger:
52bc23 1209     _challenged_with = None
993216 1210     def __init__(self, app=None):
TS 1211         self.app = app
1212
1213     def challenge(self, environ, status, app_headers, forget_headers):
1214         environ['challenged'] = self.app
52bc23 1215         self._challenged_with = (environ, status, app_headers, forget_headers)
993216 1216         return self.app
TS 1217
1218
1219 class DummyMDProvider:
1220     def __init__(self, metadata=None):
1221         self._metadata = metadata
1222
1223     def add_metadata(self, environ, identity):
1224         return identity.update(self._metadata)
1225
1226
1227 class DummyMultiPlugin:
1228     pass
1229
1230
1231 class DummyRequestClassifier:
1232     def __call__(self, environ):
1233         return 'browser'
1234
1235
1236 class DummyChallengeDecider:
1237     def __call__(self, environ, status, headers):
1238         if status.startswith('401 '):
1239             return True
1240
1241
52bc23 1242 class DummyLogger:
TS 1243     _info = _debug = ()
1244     def info(self, msg):
1245         self._info += (msg,)
1246     def debug(self, msg):
1247         self._debug += (msg,)
1248
993216 1249 class DummyApp:
TS 1250     environ = None
1251     def __call__(self, environ, start_response):
1252         self.environ = environ
1253         return []