[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/pas/ Implemented
delegation for getPrincipal and unauthorized methods of PAS.
Daniel Nouri
dpunktnpunkt at web.de
Sat Oct 9 13:48:15 EDT 2004
Log message for revision 27867:
Implemented delegation for getPrincipal and unauthorized methods of PAS.
Added LocalPAS subclass of PAS, which is our local service.
Changed:
U Zope3/trunk/src/zope/app/pas/README.txt
U Zope3/trunk/src/zope/app/pas/__init__.py
U Zope3/trunk/src/zope/app/pas/pas.py
-=-
Modified: Zope3/trunk/src/zope/app/pas/README.txt
===================================================================
--- Zope3/trunk/src/zope/app/pas/README.txt 2004-10-09 17:43:10 UTC (rev 27866)
+++ Zope3/trunk/src/zope/app/pas/README.txt 2004-10-09 17:48:14 UTC (rev 27867)
@@ -21,7 +21,7 @@
2. It constructs a principal from the given ID, combining information
from a number of sources.
-It uses plug-ins in both phases of it's work. Plugins are named
+It uses plug-ins in both phases of its work. Plugins are named
utilities that the service is configured to use in some order.
In the first phase, the PAS iterates through a sequence of extractor
@@ -105,7 +105,7 @@
Finally, we create a PAS instance:
>>> from zope.app import pas
- >>> service = pas.PAS()
+ >>> service = pas.LocalPAS()
Now, we'll create a request and try to authenticate:
@@ -318,7 +318,33 @@
>>> event.info
{'domain': 42}
+Our PAS will not find a principal with the ID '123'. Therefore it will
+delegate to the next service. To make sure that it's delegated, we put in place
+a fake service.
+ >>> from zope.app.component.localservice import testingNextService
+ >>> from zope.app.site.interfaces import ISiteManager
+ >>> from zope.app import servicenames
+
+ >>> class FakeService:
+ ...
+ ... zope.interface.implements(ISiteManager)
+ ...
+ ... lastGetPrincipalCall = lastUnauthorizedCall = None
+ ...
+ ... def getPrincipal(self, name):
+ ... self.lastGetPrincipalCall = name
+ ...
+ ... def unauthorized(self, id, request):
+ ... self.lastUnauthorizedCall = id
+
+ >>> nextservice = FakeService()
+ >>> testingNextService(service, nextservice, servicenames.Authentication)
+
+ >>> service.getPrincipal('123')
+ >>> '123' == nextservice.lastGetPrincipalCall
+ True
+
Issuing a challenge
===================
@@ -331,7 +357,12 @@
>>> service.unauthorized(42, request)
-What happens if a plugin is registered depends on the plugin. Lets
+However, our next service was asked:
+
+ >>> 42 == nextservice.lastUnauthorizedCall
+ True
+
+What happens if a plugin is registered depends on the plugin. Let's
create a plugin that sets a response header:
>>> class Challenge:
@@ -371,7 +402,7 @@
3. The view gets the authentication service and calls it's
'unauthorized' method.
-4. The PAS will call it's challenge plugins. If none return a value,
+4. The PAS will call its challenge plugins. If none return a value,
then the PAS delegates to the next authentication service above it
in the containment hierarchy, or to the global authentication
service.
@@ -385,9 +416,9 @@
example, the HTTP specification allows multiple challenges to be isued
in a response. A challenge plugin can provide a `protocol`
attribute. If multiple challenge plugins have the same protocol,
-then, if any of them are caled and return True, then they will all be
+then, if any of them are called and return True, then they will all be
called. Let's look at an example. We'll define two challengers that
-add chalenges to a X-Challenges headers:
+add challenges to a X-Challenges headers:
>>> class ColorChallenge:
... zope.interface.implements(interfaces.IChallengePlugin)
@@ -489,8 +520,3 @@
=========
XXX Still workin this out
-
-Delegation
-==========
-
- XXX Still need to write this
Modified: Zope3/trunk/src/zope/app/pas/__init__.py
===================================================================
--- Zope3/trunk/src/zope/app/pas/__init__.py 2004-10-09 17:43:10 UTC (rev 27866)
+++ Zope3/trunk/src/zope/app/pas/__init__.py 2004-10-09 17:48:14 UTC (rev 27867)
@@ -17,4 +17,4 @@
"""
import interfaces
-from zope.app.pas.pas import PAS
+from zope.app.pas.pas import PAS, LocalPAS
Modified: Zope3/trunk/src/zope/app/pas/pas.py
===================================================================
--- Zope3/trunk/src/zope/app/pas/pas.py 2004-10-09 17:43:10 UTC (rev 27866)
+++ Zope3/trunk/src/zope/app/pas/pas.py 2004-10-09 17:48:14 UTC (rev 27867)
@@ -19,9 +19,16 @@
from zope.event import notify
import zope.interface
import zope.schema
+from persistent import Persistent
from zope.app import zapi
+from zope.app.servicenames import Authentication
+from zope.app.component.localservice import queryNextService
+from zope.app.container.contained import Contained
+from zope.app.site.interfaces import ISimpleService
+from zope.app.location.interfaces import ILocation
+
from zope.app.pas import vocabularies, interfaces
from zope.app.pas.interfaces import IExtractionPlugin
from zope.app.pas.interfaces import IAuthenticationPlugin
@@ -115,7 +122,7 @@
def getPrincipal(self, id):
if not id.startswith(self.prefix):
- return
+ return self._delegate('getPrincipal', id)
id = id[len(self.prefix):]
for searcher in self.searchers:
@@ -129,6 +136,8 @@
return self._create('createFoundPrincipal', self.prefix+id, info)
+ return self._delegate('getPrincipal', self.prefix+id)
+
def unauthenticatedPrincipal(self):
pass
@@ -148,6 +157,14 @@
elif protocol is None:
protocol = challenger_protocol
- # XXX Fallback code. This will call unauthorized on higher-level
- # authentication services.
+ return self._delegate('unauthorized', id, request)
+
+ def _delegate(self, meth, *args):
+ # delegate to next AS
+ next = queryNextService(self, Authentication, None)
+ if next is not None:
+ return getattr(next, meth)(*args)
+
+class LocalPAS(PAS, Persistent, Contained):
+ zope.interface.implements(IPAS, ILocation, ISimpleService)
More information about the Zope3-Checkins
mailing list