[Zope3-checkins] SVN: Zope3/trunk/src/zope/app/authentication/
Added a subscriber that puts all principals authenticated by the
Jim Fulton
jim at zope.com
Mon Feb 7 16:33:49 EST 2005
Log message for revision 29077:
Added a subscriber that puts all principals authenticated by the
pluggable-authentication utility into the authenticated and everybody
groups, if they are defined.
Changed:
U Zope3/trunk/src/zope/app/authentication/README.txt
U Zope3/trunk/src/zope/app/authentication/authentication.py
U Zope3/trunk/src/zope/app/authentication/browser/ftests.py
U Zope3/trunk/src/zope/app/authentication/browser/groupfolder.txt
A Zope3/trunk/src/zope/app/authentication/browser/special-groups.txt
U Zope3/trunk/src/zope/app/authentication/principalplugins.zcml
-=-
Modified: Zope3/trunk/src/zope/app/authentication/README.txt
===================================================================
--- Zope3/trunk/src/zope/app/authentication/README.txt 2005-02-07 21:33:47 UTC (rev 29076)
+++ Zope3/trunk/src/zope/app/authentication/README.txt 2005-02-07 21:33:49 UTC (rev 29077)
@@ -42,34 +42,34 @@
Let's look at an example. We create a simple plugin that provides credential
extraction:
- >>> import zope.interface
+ >>> from zope import interface
>>> from zope.app.authentication import interfaces
>>> class MyExtractor:
...
- ... zope.interface.implements(interfaces.IExtractionPlugin)
+ ... interface.implements(interfaces.IExtractionPlugin)
...
... def extractCredentials(self, request):
... return request.get('credentials')
We need to register this as a utility. Normally, we'd do this in ZCML. For the
example here, we'll use the `provideUtility()` function from
-`zope.app.tests.ztapi`:
+`zope.component`:
- >>> from zope.app.tests.ztapi import provideUtility
- >>> provideUtility(interfaces.IExtractionPlugin, MyExtractor(), name='emy')
+ >>> from zope.component import provideUtility
+ >>> provideUtility(MyExtractor(), name='emy')
Now we also create an authenticator plugin that knows about object 42:
>>> class Auth42:
...
- ... zope.interface.implements(interfaces.IAuthenticationPlugin)
+ ... interface.implements(interfaces.IAuthenticationPlugin)
...
... def authenticateCredentials(self, credentials):
... if credentials == 42:
... return '42', {'domain': 42}
- >>> provideUtility(interfaces.IAuthenticationPlugin, Auth42(), name='a42')
+ >>> provideUtility(Auth42(), name='a42')
We provide a principal factory plugin:
@@ -86,7 +86,7 @@
>>> from zope.event import notify
>>> class PrincipalFactory:
...
- ... zope.interface.implements(interfaces.IPrincipalFactoryPlugin)
+ ... interface.implements(interfaces.IPrincipalFactoryPlugin)
...
... def createAuthenticatedPrincipal(self, id, info, request):
... principal = Principal(id)
@@ -99,8 +99,7 @@
... notify(interfaces.FoundPrincipalCreated(principal, info))
... return principal
- >>> provideUtility(interfaces.IPrincipalFactoryPlugin, PrincipalFactory(),
- ... name='pf')
+ >>> provideUtility(PrincipalFactory(), name='pf')
Finally, we create a pluggable-authentication utility instance:
@@ -166,13 +165,13 @@
>>> class AuthInt:
...
- ... zope.interface.implements(interfaces.IAuthenticationPlugin)
+ ... interface.implements(interfaces.IAuthenticationPlugin)
...
... def authenticateCredentials(self, credentials):
... if isinstance(credentials, int):
... return str(credentials), {'int': credentials}
- >>> provideUtility(interfaces.IAuthenticationPlugin, AuthInt(), name='aint')
+ >>> provideUtility(AuthInt(), name='aint')
If we put it before the original authenticator:
@@ -199,14 +198,14 @@
>>> class OddExtractor:
...
- ... zope.interface.implements(interfaces.IExtractionPlugin)
+ ... interface.implements(interfaces.IExtractionPlugin)
...
... def extractCredentials(self, request):
... credentials = request.get('credentials')
... if isinstance(credentials, int) and (credentials%2):
... return 1
- >>> provideUtility(interfaces.IExtractionPlugin, OddExtractor(), name='eodd')
+ >>> provideUtility(OddExtractor(), name='eodd')
>>> auth.extractors = 'eodd', 'emy'
>>> request = TestRequest(credentials=41)
@@ -226,7 +225,7 @@
>>> class OddFactory:
...
- ... zope.interface.implements(interfaces.IPrincipalFactoryPlugin)
+ ... interface.implements(interfaces.IPrincipalFactoryPlugin)
...
... def createAuthenticatedPrincipal(self, id, info, request):
... i = info.get('int')
@@ -246,8 +245,7 @@
... principal, info))
... return principal
- >>> provideUtility(interfaces.IPrincipalFactoryPlugin, OddFactory(),
- ... name='oddf')
+ >>> provideUtility(OddFactory(), name='oddf')
>>> auth.factories = 'oddf', 'pf'
@@ -277,18 +275,17 @@
>>> class Search42:
...
- ... zope.interface.implements(interfaces.IPrincipalSearchPlugin)
+ ... interface.implements(interfaces.IPrincipalSearchPlugin)
...
... def principalInfo(self, principal_id):
... if principal_id == '42':
... return {'domain': 42}
- >>> provideUtility(interfaces.IPrincipalSearchPlugin, Search42(),
- ... name='s42')
+ >>> provideUtility(Search42(), name='s42')
>>> class IntSearch:
...
- ... zope.interface.implements(interfaces.IPrincipalSearchPlugin)
+ ... interface.implements(interfaces.IPrincipalSearchPlugin)
...
... def principalInfo(self, principal_id):
... try:
@@ -298,8 +295,7 @@
... if (i >= 0 and i < 100):
... return {'int': i}
- >>> provideUtility(interfaces.IPrincipalSearchPlugin, IntSearch(),
- ... name='sint')
+ >>> provideUtility(IntSearch(), name='sint')
>>> auth.searchers = 's42', 'sint'
@@ -328,7 +324,7 @@
>>> class FakeAuthUtility:
...
- ... zope.interface.implements(IAuthentication)
+ ... interface.implements(IAuthentication)
...
... lastGetPrincipalCall = lastUnauthorizedCall = None
...
@@ -368,13 +364,13 @@
>>> class Challenge:
...
- ... zope.interface.implements(interfaces.IChallengePlugin)
+ ... interface.implements(interfaces.IChallengePlugin)
...
... def challenge(self, requests, response):
... response.setHeader('X-Unauthorized', 'True')
... return True
- >>> provideUtility(interfaces.IChallengePlugin, Challenge(), name='c')
+ >>> provideUtility(Challenge(), name='c')
>>> auth.challengers = ('c', )
Now if we call unauthorized:
@@ -422,7 +418,7 @@
add challenges to a X-Challenges headers:
>>> class ColorChallenge:
- ... zope.interface.implements(interfaces.IChallengePlugin)
+ ... interface.implements(interfaces.IChallengePlugin)
...
... protocol = 'bridge'
...
@@ -432,11 +428,11 @@
... challenge + 'favorite color? ')
... return True
- >>> provideUtility(interfaces.IChallengePlugin, ColorChallenge(), name='cc')
+ >>> provideUtility(ColorChallenge(), name='cc')
>>> auth.challengers = 'cc, ', 'c'
>>> class BirdChallenge:
- ... zope.interface.implements(interfaces.IChallengePlugin)
+ ... interface.implements(interfaces.IChallengePlugin)
...
... protocol = 'bridge'
...
@@ -446,7 +442,7 @@
... challenge + 'swallow air speed? ')
... return True
- >>> provideUtility(interfaces.IChallengePlugin, BirdChallenge(), name='bc')
+ >>> provideUtility(BirdChallenge(), name='bc')
>>> auth.challengers = 'cc', 'c', 'bc'
Now if we call unauthorized:
@@ -558,3 +554,78 @@
`ISearchableAuthenticationPlugin` and
`IExtractionAndChallengePlugin`.
+Special groups
+==============
+
+Two special groups, Authenticated, and Everyone may apply to users
+created by the pluggable-authentication utility. There is a
+subscriber, specialGroups, that will set these groups on any non-group
+principals if IAuthenticatedGroup, or IEveryoneGroup utilities are
+provided.
+
+Lets define a group-aware principal:
+
+ >>> import zope.security.interfaces
+ >>> class GroupAwarePrincipal(Principal):
+ ... interface.implements(zope.security.interfaces.IGroupAwarePrincipal)
+ ... def __init__(self, id):
+ ... Principal.__init__(self, id)
+ ... self.groups = []
+
+If we notify the subscriber with this principal, nothing will happen
+because the groups haven't been defined:
+
+ >>> prin = GroupAwarePrincipal('x')
+ >>> event = interfaces.FoundPrincipalCreated(prin, {})
+ >>> authentication.authentication.specialGroups(event)
+ >>> prin.groups
+ []
+
+Now, if we define the Everybody group:
+
+ >>> import zope.app.security.interfaces
+ >>> class EverybodyGroup(Principal):
+ ... interface.implements(zope.app.security.interfaces.IEveryoneGroup)
+
+ >>> everybody = EverybodyGroup('all')
+ >>> provideUtility(everybody)
+
+Then the group will be added to the principal:
+
+ >>> authentication.authentication.specialGroups(event)
+ >>> prin.groups
+ ['all']
+
+Similarly for the authenticated group:
+
+ >>> class AuthenticatedGroup(Principal):
+ ... interface.implements(
+ ... zope.app.security.interfaces.IAuthenticatedGroup)
+
+ >>> authenticated = AuthenticatedGroup('auth')
+ >>> provideUtility(authenticated)
+
+Then the group will be added to the principal:
+
+ >>> prin.groups = []
+ >>> authentication.authentication.specialGroups(event)
+ >>> prin.groups.sort()
+ >>> prin.groups
+ ['all', 'auth']
+
+These groups are only added to non-group principals:
+
+ >>> prin.groups = []
+ >>> interface.directlyProvides(prin, zope.security.interfaces.IGroup)
+ >>> authentication.authentication.specialGroups(event)
+ >>> prin.groups
+ []
+
+And they are only added to group aware principals:
+
+ >>> prin = Principal('eek')
+ >>> prin.groups = []
+ >>> event = interfaces.FoundPrincipalCreated(prin, {})
+ >>> authentication.authentication.specialGroups(event)
+ >>> prin.groups
+ []
Modified: Zope3/trunk/src/zope/app/authentication/authentication.py
===================================================================
--- Zope3/trunk/src/zope/app/authentication/authentication.py 2005-02-07 21:33:47 UTC (rev 29076)
+++ Zope3/trunk/src/zope/app/authentication/authentication.py 2005-02-07 21:33:49 UTC (rev 29077)
@@ -21,11 +21,11 @@
import zope.schema
from persistent import Persistent
+from zope.component import queryUtility
from zope.schema.interfaces import ISourceQueriables
-
-from zope.app import zapi
-
+from zope.security.interfaces import IGroupAwarePrincipal, IGroup
from zope.app.security.interfaces import IAuthentication
+from zope.app.security.interfaces import IAuthenticatedGroup, IEveryoneGroup
from zope.app.utility.utility import queryNextUtility
from zope.app.container.contained import Contained
from zope.app.utility.interfaces import ILocalUtility
@@ -49,10 +49,10 @@
self.prefix = prefix
def authenticate(self, request):
- authenticators = [zapi.queryUtility(IAuthenticationPlugin, name)
+ authenticators = [queryUtility(IAuthenticationPlugin, name)
for name in self.authenticators]
for extractor in self.extractors:
- extractor = zapi.queryUtility(IExtractionPlugin, extractor)
+ extractor = queryUtility(IExtractionPlugin, extractor)
if extractor is None:
continue
credentials = extractor.extractCredentials(request)
@@ -72,7 +72,7 @@
def _create(self, meth, *args):
# We got some data, lets create a user
for factory in self.factories:
- factory = zapi.queryUtility(IPrincipalFactoryPlugin,
+ factory = queryUtility(IPrincipalFactoryPlugin,
factory)
if factory is None:
continue
@@ -89,7 +89,7 @@
id = id[len(self.prefix):]
for searcher in self.searchers:
- searcher = zapi.queryUtility(IPrincipalSearchPlugin, searcher)
+ searcher = queryUtility(IPrincipalSearchPlugin, searcher)
if searcher is None:
continue
@@ -103,7 +103,7 @@
def getQueriables(self):
for searcher_id in self.searchers:
- searcher = zapi.queryUtility(IPrincipalSearchPlugin, searcher_id)
+ searcher = queryUtility(IPrincipalSearchPlugin, searcher_id)
yield searcher_id, searcher
@@ -114,7 +114,7 @@
protocol = None
for challenger in self.challengers:
- challenger = zapi.queryUtility(IChallengePlugin, challenger)
+ challenger = queryUtility(IChallengePlugin, challenger)
if challenger is None:
continue # skip non-existant challengers
@@ -150,3 +150,19 @@
Persistent, Contained):
zope.interface.implements(IPluggableAuthentication,
ILocation, ILocalUtility)
+
+
+def specialGroups(event):
+ principal = event.principal
+ if (IGroup.providedBy(principal)
+ or not IGroupAwarePrincipal.providedBy(principal)
+ ):
+ return
+
+ everyone = queryUtility(IEveryoneGroup)
+ if everyone is not None:
+ principal.groups.append(everyone.id)
+
+ auth = queryUtility(IAuthenticatedGroup)
+ if auth is not None:
+ principal.groups.append(auth.id)
Modified: Zope3/trunk/src/zope/app/authentication/browser/ftests.py
===================================================================
--- Zope3/trunk/src/zope/app/authentication/browser/ftests.py 2005-02-07 21:33:47 UTC (rev 29076)
+++ Zope3/trunk/src/zope/app/authentication/browser/ftests.py 2005-02-07 21:33:49 UTC (rev 29077)
@@ -24,6 +24,7 @@
functional.FunctionalDocFileSuite('groupfolder.txt'),
functional.FunctionalDocFileSuite(
'group_searching_with_empty_string.txt'),
+ functional.FunctionalDocFileSuite('special-groups.txt'),
))
if __name__ == '__main__':
Modified: Zope3/trunk/src/zope/app/authentication/browser/groupfolder.txt
===================================================================
--- Zope3/trunk/src/zope/app/authentication/browser/groupfolder.txt 2005-02-07 21:33:47 UTC (rev 29076)
+++ Zope3/trunk/src/zope/app/authentication/browser/groupfolder.txt 2005-02-07 21:33:49 UTC (rev 29077)
@@ -646,10 +646,10 @@
>>> betty = principals.getPrincipal(u'users.3')
>>> betty.groups.sort()
>>> betty.groups
- [u'groups.1', u'groups.power']
+ [u'groups.1', u'groups.power', 'zope.Authenticated', 'zope.Everybody']
And we'll get Bill, and see that he is only in the power-user group:
>>> bill = principals.getPrincipal(u'users.2')
>>> bill.groups
- [u'groups.power']
+ ['zope.Everybody', 'zope.Authenticated', u'groups.power']
Added: Zope3/trunk/src/zope/app/authentication/browser/special-groups.txt
===================================================================
--- Zope3/trunk/src/zope/app/authentication/browser/special-groups.txt 2005-02-07 21:33:47 UTC (rev 29076)
+++ Zope3/trunk/src/zope/app/authentication/browser/special-groups.txt 2005-02-07 21:33:49 UTC (rev 29077)
@@ -0,0 +1,423 @@
+Granting to unauthenticated
+===========================
+
+There are 3 special groups:
+
+- Everybody, that everybody belongs to,
+
+- Unauthenticated, that unauthenticated users belong to, and
+
+- Authenticating, that authenticated users belong to.
+
+Here's an example:
+
+First, we'll set up a pluggable authentication utility containing a
+principal folder, which we'll create first.
+
+Create the principal folder:
+
+ >>> print http(r"""
+ ... POST /++etc++site/default/+/AddPrincipalFolder.html%3D HTTP/1.1
+ ... Authorization: Basic mgr:mgrpw
+ ... Content-Type: multipart/form-data; boundary=---------------------------51955270618919134971413296540
+ ...
+ ... -----------------------------51955270618919134971413296540
+ ... Content-Disposition: form-data; name="field.prefix"
+ ...
+ ... users.
+ ... -----------------------------51955270618919134971413296540
+ ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+ ...
+ ... Add
+ ... -----------------------------51955270618919134971413296540
+ ... Content-Disposition: form-data; name="add_input_name"
+ ...
+ ...
+ ... -----------------------------51955270618919134971413296540--
+ ... """)
+ HTTP/1.1 303 See Other
+ ...
+
+Register it:
+
+ >>> print http(r"""
+ ... POST /++etc++site/default/PrincipalFolder/addRegistration.html HTTP/1.1
+ ... Authorization: Basic mgr:mgrpw
+ ... Content-Type: multipart/form-data; boundary=---------------------------1211945862063657304996683149
+ ...
+ ... -----------------------------1211945862063657304996683149
+ ... Content-Disposition: form-data; name="field.name"
+ ...
+ ... users
+ ... -----------------------------1211945862063657304996683149
+ ... Content-Disposition: form-data; name="field.interface"
+ ...
+ ... zope.app.authentication.interfaces.ISearchableAuthenticationPlugin
+ ... -----------------------------1211945862063657304996683149
+ ... Content-Disposition: form-data; name="field.interface-empty-marker"
+ ...
+ ... 1
+ ... -----------------------------1211945862063657304996683149
+ ... Content-Disposition: form-data; name="field.permission"
+ ...
+ ...
+ ... -----------------------------1211945862063657304996683149
+ ... Content-Disposition: form-data; name="field.permission-empty-marker"
+ ...
+ ... 1
+ ... -----------------------------1211945862063657304996683149
+ ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+ ...
+ ... Add
+ ... -----------------------------1211945862063657304996683149--
+ ... """)
+ HTTP/1.1 303 See Other
+ ...
+
+Add a principal to it:
+
+ >>> print http(r"""
+ ... POST /++etc++site/default/PrincipalFolder/+/AddPrincipalInformation.html%3D HTTP/1.1
+ ... Authorization: Basic mgr:mgrpw
+ ... Content-Type: multipart/form-data; boundary=---------------------------10033016405103631412002637985
+ ...
+ ... -----------------------------10033016405103631412002637985
+ ... Content-Disposition: form-data; name="field.login"
+ ...
+ ... bob
+ ... -----------------------------10033016405103631412002637985
+ ... Content-Disposition: form-data; name="field.password"
+ ...
+ ... 123
+ ... -----------------------------10033016405103631412002637985
+ ... Content-Disposition: form-data; name="field.title"
+ ...
+ ... Bob
+ ... -----------------------------10033016405103631412002637985
+ ... Content-Disposition: form-data; name="field.description"
+ ...
+ ...
+ ... -----------------------------10033016405103631412002637985
+ ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+ ...
+ ... Add
+ ... -----------------------------10033016405103631412002637985
+ ... Content-Disposition: form-data; name="add_input_name"
+ ...
+ ...
+ ... -----------------------------10033016405103631412002637985--
+ ... """)
+ HTTP/1.1 303 See Other
+ ...
+
+Create a pluggable-authentication utility:
+
+ >>> print http(r"""
+ ... POST /++etc++site/default/@@contents.html HTTP/1.1
+ ... Authorization: Basic mgr:mgrpw
+ ... Content-Type: application/x-www-form-urlencoded
+ ...
+ ... type_name=BrowserAdd__zope.app.authentication.authentication.LocalPluggableAuthentication&new_value=""")
+ HTTP/1.1 303 See Other
+ ...
+
+and register it:
+
+ >>> print http(r"""
+ ... POST /++etc++site/default/LocalPluggableAuthentication/addRegistration.html HTTP/1.1
+ ... Authorization: Basic mgr:mgrpw
+ ... Content-Type: multipart/form-data; boundary=---------------------------2567744622114531019698320091
+ ... Referer: http://localhost:8081/++etc++site/default/LocalPluggableAuthentication/addRegistration.html
+ ...
+ ... -----------------------------2567744622114531019698320091
+ ... Content-Disposition: form-data; name="field.name"
+ ...
+ ...
+ ... -----------------------------2567744622114531019698320091
+ ... Content-Disposition: form-data; name="field.interface"
+ ...
+ ... zope.app.security.interfaces.IAuthentication
+ ... -----------------------------2567744622114531019698320091
+ ... Content-Disposition: form-data; name="field.interface-empty-marker"
+ ...
+ ... 1
+ ... -----------------------------2567744622114531019698320091
+ ... Content-Disposition: form-data; name="field.permission"
+ ...
+ ...
+ ... -----------------------------2567744622114531019698320091
+ ... Content-Disposition: form-data; name="field.permission-empty-marker"
+ ...
+ ... 1
+ ... -----------------------------2567744622114531019698320091
+ ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+ ...
+ ... Add
+ ... -----------------------------2567744622114531019698320091--
+ ... """)
+ HTTP/1.1 303 See Other
+ ...
+
+and configure it:
+
+ >>> print http(r"""
+ ... POST /++etc++site/default/LocalPluggableAuthentication/@@edit.html HTTP/1.1
+ ... Authorization: Basic mgr:mgrpw
+ ... Content-Type: multipart/form-data; boundary=---------------------------12424310211503201098946683515
+ ...
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="field.extractors.to"
+ ...
+ ... HTTP Basic
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="field.extractors-empty-marker"
+ ...
+ ...
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="field.authenticators.to"
+ ...
+ ... users
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="field.authenticators-empty-marker"
+ ...
+ ...
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="field.challengers.to"
+ ...
+ ... No Challenge if Authenticated
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="field.challengers.to"
+ ...
+ ... Zope Realm HTTP Basic
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="field.challengers-empty-marker"
+ ...
+ ...
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="field.factories.to"
+ ...
+ ... Default
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="field.factories-empty-marker"
+ ...
+ ...
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="field.searchers.to"
+ ...
+ ... users
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="field.searchers-empty-marker"
+ ...
+ ...
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="UPDATE_SUBMIT"
+ ...
+ ... Change
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="field.extractors"
+ ...
+ ... HTTP Basic
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="field.authenticators"
+ ...
+ ... users
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="field.challengers"
+ ...
+ ... No Challenge if Authenticated
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="field.challengers"
+ ...
+ ... Zope Realm HTTP Basic
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="field.factories"
+ ...
+ ... Default
+ ... -----------------------------12424310211503201098946683515
+ ... Content-Disposition: form-data; name="field.searchers"
+ ...
+ ... users
+ ... -----------------------------12424310211503201098946683515--
+ ... """)
+ HTTP/1.1 200 Ok
+ ...
+
+Normally, the anonymous role has view, we'll deny it:
+
+ >>> print http(r"""
+ ... POST /++etc++site/AllRolePermissions.html HTTP/1.1
+ ... Authorization: Basic mgr:mgrpw
+ ... Content-Type: application/x-www-form-urlencoded
+ ...
+ ... role_id=zope.Anonymous"""
+ ... """&Deny%3Alist=zope.View"""
+ ... """&Deny%3Alist=zope.app.dublincore.view"""
+ ... """&SUBMIT_ROLE=Save+Changes""")
+ HTTP/1.1 200 Ok
+ ...
+
+Now, if we try to access the main page as an anonymous user, we'll be unauthorized:
+
+ >>> print http(r"""
+ ... GET / HTTP/1.1
+ ... """)
+ HTTP/1.1 401 Unauthorized
+ ...
+
+We'll even be unauthorized if we try to access it as bob:
+
+ >>> print http(r"""
+ ... GET / HTTP/1.1
+ ... Authorization: Basic bob:123
+ ... """)
+ HTTP/1.1 403 Forbidden
+ ...
+
+No, let's grant view to the authenticated group:
+
+ >>> print http(r"""
+ ... POST /@@grant.html HTTP/1.1
+ ... Authorization: Basic mgr:mgrpw
+ ... Content-Type: application/x-www-form-urlencoded
+ ...
+ ... field.principal=em9wZS5BdXRoZW50aWNhdGVk&field.principal.displayed=y"""
+ ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.View=allow"""
+ ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.app.dublincore.view=allow"""
+ ... """&GRANT_SUBMIT=Change""")
+ HTTP/1.1 200 Ok
+ ...
+
+Now, with this, we can access the main page as bob, but not as an
+anonymous user:
+
+ >>> print http(r"""
+ ... GET / HTTP/1.1
+ ... Authorization: Basic bob:123
+ ... """)
+ HTTP/1.1 200 Ok
+ ...
+
+ >>> print http(r"""
+ ... GET / HTTP/1.1
+ ... """)
+ HTTP/1.1 401 Unauthorized
+ ...
+
+Now, we'll grant to unauthenticated:
+
+ >>> print http(r"""
+ ... POST /@@grant.html HTTP/1.1
+ ... Authorization: Basic mgr:mgrpw
+ ... Content-Type: application/x-www-form-urlencoded
+ ... Referer: http://localhost:8081/@@grant.html
+ ...
+ ... field.principal=em9wZS5Bbnlib2R5"""
+ ... """&field.em9wZS5Bbnlib2R5.permission.zope.View=allow"""
+ ... """&field.em9wZS5Bbnlib2R5.permission.zope.app.dublincore.view=allow"""
+ ... """&GRANT_SUBMIT=Change""")
+ HTTP/1.1 200 Ok
+ ...
+
+With this, we can access the page as either bob or anonymous:
+
+ >>> print http(r"""
+ ... GET / HTTP/1.1
+ ... Authorization: Basic bob:123
+ ... """)
+ HTTP/1.1 200 Ok
+ ...
+
+ >>> print http(r"""
+ ... GET / HTTP/1.1
+ ... """)
+ HTTP/1.1 200 Ok
+ ...
+
+Now, we'll remove the authenticated group grant:
+
+ >>> print http(r"""
+ ... POST /@@grant.html HTTP/1.1
+ ... Authorization: Basic mgr:mgrpw
+ ... Content-Type: application/x-www-form-urlencoded
+ ...
+ ... field.principal=em9wZS5BdXRoZW50aWNhdGVk"""
+ ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.View=unset"""
+ ... """&field.em9wZS5BdXRoZW50aWNhdGVk.permission.zope.app.dublincore.view=unset"""
+ ... """&GRANT_SUBMIT=Change""")
+ HTTP/1.1 200 Ok
+ ...
+
+And anonymous people will be able to access the page, but bob won't be able to:
+
+ >>> print http(r"""
+ ... GET / HTTP/1.1
+ ... Authorization: Basic bob:123
+ ... """)
+ HTTP/1.1 403 Forbidden
+ ...
+
+ >>> print http(r"""
+ ... GET / HTTP/1.1
+ ... """)
+ HTTP/1.1 200 Ok
+ ...
+
+Now, we'll remove the unauthenticated group grant:
+
+ >>> print http(r"""
+ ... POST /@@grant.html HTTP/1.1
+ ... Authorization: Basic mgr:mgrpw
+ ... Content-Type: application/x-www-form-urlencoded
+ ... Referer: http://localhost:8081/@@grant.html
+ ...
+ ... field.principal=em9wZS5Bbnlib2R5"""
+ ... """&field.em9wZS5Bbnlib2R5.permission.zope.View=unset"""
+ ... """&field.em9wZS5Bbnlib2R5.permission.zope.app.dublincore.view=unset"""
+ ... """&GRANT_SUBMIT=Change""")
+ HTTP/1.1 200 Ok
+ ...
+
+and neither bob nor anonymous can access:
+
+ >>> print http(r"""
+ ... GET / HTTP/1.1
+ ... Authorization: Basic bob:123
+ ... """)
+ HTTP/1.1 403 Forbidden
+ ...
+
+ >>> print http(r"""
+ ... GET / HTTP/1.1
+ ... """)
+ HTTP/1.1 401 Unauthorized
+ ...
+
+Finally, we'll grant to everybody:
+
+ >>> print http(r"""
+ ... POST /@@grant.html HTTP/1.1
+ ... Authorization: Basic mgr:mgrpw
+ ... Content-Type: application/x-www-form-urlencoded
+ ...
+ ... field.principal=em9wZS5FdmVyeWJvZHk_"""
+ ... """&field.em9wZS5FdmVyeWJvZHk_.permission.zope.View=allow"""
+ ... """&field.em9wZS5FdmVyeWJvZHk_.permission.zope.app.dublincore.view=allow"""
+ ... """&GRANT_SUBMIT=Change""", handle_errors = False)
+ HTTP/1.1 200 Ok
+ ...
+
+and both bob nor anonymous can access:
+
+ >>> print http(r"""
+ ... GET / HTTP/1.1
+ ... Authorization: Basic bob:123
+ ... """)
+ HTTP/1.1 200 Ok
+ ...
+
+ >>> print http(r"""
+ ... GET / HTTP/1.1
+ ... """)
+ HTTP/1.1 200 Ok
+ ...
+
Modified: Zope3/trunk/src/zope/app/authentication/principalplugins.zcml
===================================================================
--- Zope3/trunk/src/zope/app/authentication/principalplugins.zcml 2005-02-07 21:33:47 UTC (rev 29076)
+++ Zope3/trunk/src/zope/app/authentication/principalplugins.zcml 2005-02-07 21:33:49 UTC (rev 29077)
@@ -15,4 +15,9 @@
handler=".principalplugins.addTitleAndDescription"
/>
+ <subscriber
+ for=".interfaces.IPrincipalCreated"
+ handler=".authentication.specialGroups"
+ />
+
</configure>
More information about the Zope3-Checkins
mailing list