[Zope3-checkins] SVN: Zope3/trunk/src/zope/ Merged Zope3/branches/mgedmin-security 24595:24640

Marius Gedminas marius at pov.lt
Fri May 14 06:45:26 EDT 2004


Log message for revision 24642:
Merged Zope3/branches/mgedmin-security 24595:24640

This is UnificationOfRequestsAndSecurityContextsThroughUse:
  - Security managers and security contexts are gone.
  - Interactions and participations replace them.
  - BaseRequest is now IParticipation.
  - request.user was renamed to request.principal because of the above.




-=-
Modified: Zope3/trunk/src/zope/app/_app.py
===================================================================
--- Zope3/trunk/src/zope/app/_app.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/_app.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -21,9 +21,20 @@
 from zope.publisher.publish import publish as _publish, debug_call
 from zope.publisher.browser import TestRequest
 from zope.app.publication.browser import BrowserPublication
+from zope.security.interfaces import IParticipation
+from zope.security.management import system_user
+from zope.interface import implements
 
 __metaclass__ = type
 
+
+class SystemConfigurationParticipation:
+    implements(IParticipation)
+
+    principal = system_user
+    interaction = None
+
+
 _configured = 0
 def config(file, execute=True):
     "Configure site globals"
@@ -35,16 +46,15 @@
     from zope.configuration import xmlconfig
 
     # Set user to system_user, so we can do anything we want
-    from zope.security.management import system_user
-    from zope.security.management import newSecurityManager
-    newSecurityManager(system_user)
+    from zope.security.management import newInteraction
+    newInteraction(SystemConfigurationParticipation())
 
     # Load server-independent site config
     context = xmlconfig.file(file, execute=execute)
 
     # Reset user
-    from zope.security.management import noSecurityManager
-    noSecurityManager()
+    from zope.security.management import endInteraction
+    endInteraction()
 
     _configured = execute
 

Modified: Zope3/trunk/src/zope/app/basicskin/view_macros.pt
===================================================================
--- Zope3/trunk/src/zope/app/basicskin/view_macros.pt	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/basicskin/view_macros.pt	2004-05-14 10:45:25 UTC (rev 24642)
@@ -32,7 +32,8 @@
 
   <div metal:define-macro="logged_user">
   <p i18n:translate="">User: 
-    <span tal:replace="request/user/title" i18n:name="user_title">User</span>
+    <span tal:replace="request/principal/title"
+          i18n:name="user_title">User</span>
   </p>
   </div>
 

Modified: Zope3/trunk/src/zope/app/component/tests/test_contentdirective.py
===================================================================
--- Zope3/trunk/src/zope/app/component/tests/test_contentdirective.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/component/tests/test_contentdirective.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -26,7 +26,8 @@
 from zope.component.exceptions import ComponentLookupError
 from zope.configuration.xmlconfig import xmlconfig, XMLConfig
 from zope.app.tests.placelesssetup import PlacelessSetup
-from zope.security.management import newSecurityManager, system_user
+from zope.security.management import system_user
+from zope.security.management import newInteraction
 from zope.app.component.interface import queryInterface
 
 # explicitly import ExampleClass and IExample using full paths
@@ -35,6 +36,13 @@
 from zope.app.component.tests.exampleclass import IExample, IExample2
 
 
+class ParticipationStub:
+
+    def __init__(self, principal):
+        self.principal = principal
+        self.interaction = None
+
+
 def configfile(s):
     return StringIO("""<configure
       xmlns='http://namespaces.zope.org/zope'
@@ -46,7 +54,7 @@
 class TestContentDirective(PlacelessSetup, unittest.TestCase):
     def setUp(self):
         super(TestContentDirective, self).setUp()
-        newSecurityManager(system_user)
+        newInteraction(ParticipationStub(system_user))
         XMLConfig('meta.zcml', zope.app.component)()
         XMLConfig('meta.zcml', zope.app.security)()
 
@@ -64,7 +72,7 @@
 
 
     def testImplements(self):
-        self.assertEqual(queryInterface( 
+        self.assertEqual(queryInterface(
             "zope.app.component.tests.exampleclass.IExample"), None)
 
         f = configfile("""
@@ -75,7 +83,7 @@
         xmlconfig(f)
         self.failUnless(IExample.implementedBy(ExampleClass))
 
-        self.assertEqual(queryInterface( 
+        self.assertEqual(queryInterface(
             "zope.app.component.tests.exampleclass.IExample"), IExample)
 
 
@@ -133,7 +141,7 @@
 class TestFactorySubdirective(PlacelessSetup, unittest.TestCase):
     def setUp(self):
         super(TestFactorySubdirective, self).setUp()
-        newSecurityManager(system_user)
+        newInteraction(ParticipationStub(system_user))
         XMLConfig('meta.zcml', zope.app.component)()
         XMLConfig('meta.zcml', zope.app.security)()
 

Modified: Zope3/trunk/src/zope/app/component/tests/test_factory.py
===================================================================
--- Zope3/trunk/src/zope/app/component/tests/test_factory.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/component/tests/test_factory.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -23,7 +23,7 @@
 from zope.component import createObject
 from zope.proxy import removeAllProxies
 from zope.app.tests.placelesssetup import PlacelessSetup
-from zope.security.management import newSecurityManager, system_user
+from zope.security.management import newInteraction, system_user
 
 from zope.app import zapi
 import zope.app.security
@@ -31,6 +31,14 @@
 
 from zope.app.component.tests.exampleclass import ExampleClass
 
+
+class ParticipationStub:
+
+    def __init__(self, principal):
+        self.principal = principal
+        self.interaction = None
+
+
 def configfile(s):
     return StringIO("""<configure
       xmlns='http://namespaces.zope.org/zope'
@@ -42,7 +50,7 @@
 class Test(PlacelessSetup, unittest.TestCase):
     def setUp(self):
         super(Test, self).setUp()
-        newSecurityManager(system_user)
+        newInteraction(ParticipationStub(system_user))
         XMLConfig('meta.zcml', zope.app.component)()
         XMLConfig('meta.zcml', zope.app.security)()
 

Modified: Zope3/trunk/src/zope/app/component/tests/test_servicedirective.py
===================================================================
--- Zope3/trunk/src/zope/app/component/tests/test_servicedirective.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/component/tests/test_servicedirective.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -29,6 +29,14 @@
 from zope.component import getService
 from zope.app.tests.placelesssetup import PlacelessSetup
 
+
+class ParticipationStub:
+
+    def __init__(self, principal):
+        self.principal = principal
+        self.interaction = None
+
+
 template = """<configure
    xmlns='http://namespaces.zope.org/zope'
    xmlns:test='http://www.zope.org/NS/Zope3/test'
@@ -180,8 +188,8 @@
 
 
         # Need to "log someone in" to turn on checks
-        from zope.security.management import newSecurityManager
-        newSecurityManager('someuser')
+        from zope.security.management import newInteraction
+        newInteraction(ParticipationStub('someuser'))
 
         service = getService(None, "Foo")
         service = ProxyFactory(service) # simulate untrusted code!
@@ -191,9 +199,9 @@
         self.assertRaises(Forbidden, getattr, service, 'bar')
 
 
-
 def test_suite():
     loader=unittest.TestLoader()
     return loader.loadTestsFromTestCase(Test)
+
 if __name__=='__main__':
     unittest.TextTestRunner().run(test_suite())

Modified: Zope3/trunk/src/zope/app/container/browser/contents.py
===================================================================
--- Zope3/trunk/src/zope/app/container/browser/contents.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/container/browser/contents.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -246,7 +246,7 @@
 
         container_path = zapi.getPath(self.context)
 
-        user = self.request.user
+        user = self.request.principal
         annotationsvc = zapi.getService(self.context, 'PrincipalAnnotation')
         annotations = annotationsvc.getAnnotations(user)
         clipboard = IPrincipalClipboard(annotations)
@@ -266,7 +266,7 @@
 
         container_path = zapi.getPath(self.context)
 
-        user = self.request.user
+        user = self.request.principal
         annotationsvc = zapi.getService(self.context, 'PrincipalAnnotation')
         annotations = annotationsvc.getAnnotations(user)
         clipboard = IPrincipalClipboard(annotations)
@@ -281,7 +281,7 @@
         """Decide if there is anything to paste
         """
         target = self.context
-        user = self.request.user
+        user = self.request.principal
         annotationsvc = zapi.getService(self.context, 'PrincipalAnnotation')
         annotations = annotationsvc.getAnnotations(user)
         clipboard = IPrincipalClipboard(annotations)
@@ -310,7 +310,7 @@
         """Paste ojects in the user clipboard to the container
         """
         target = self.context
-        user = self.request.user
+        user = self.request.principal
         annotationsvc = zapi.getService(self.context, 'PrincipalAnnotation')
         annotations = annotationsvc.getAnnotations(user)
         clipboard = IPrincipalClipboard(annotations)
@@ -344,7 +344,7 @@
         if not self.supportsPaste:
             return False
 
-        user = self.request.user
+        user = self.request.principal
 
         annotationsvc = zapi.getService(self.context, 'PrincipalAnnotation')
         annotations = annotationsvc.getAnnotations(user)

Modified: Zope3/trunk/src/zope/app/container/browser/tests/test_contents.py
===================================================================
--- Zope3/trunk/src/zope/app/container/browser/tests/test_contents.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/container/browser/tests/test_contents.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -280,7 +280,7 @@
         from zope.app.container.browser.contents import Contents
         from zope.publisher.browser import TestRequest
         request = TestRequest()
-        request.setUser(Principal())
+        request.setPrincipal(Principal())
         return Contents(container, request)
 
 class Test(BaseTestContentsBrowserView, TestCase):
@@ -296,7 +296,7 @@
         from zope.app.container.browser.contents import Contents
         from zope.publisher.browser import TestRequest
         request = TestRequest()
-        request.setUser(Principal())
+        request.setPrincipal(Principal())
         return Contents(container, request)
 
 def test_suite():

Modified: Zope3/trunk/src/zope/app/dublincore/creatorannotator.py
===================================================================
--- Zope3/trunk/src/zope/app/dublincore/creatorannotator.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/dublincore/creatorannotator.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -17,7 +17,7 @@
 """
 from zope.app.dublincore.interfaces import IZopeDublinCore
 from zope.app.event.interfaces import ISubscriber
-from zope.security.management import getSecurityManager
+from zope.security.management import getInteraction
 from zope.interface import implements
 
 class CreatorAnnotatorClass(object):
@@ -32,11 +32,11 @@
         # Try to find a principal for that one. If there
         # is no principal then we don't touch the list
         # of creators.
-        principal = getSecurityManager().getPrincipal()
-        if principal is None:
-            return
-        principalid = principal.id
-        if not principalid in dc.creators:
-            dc.creators = dc.creators + (unicode(principalid), )
+        interaction = getInteraction()
+        if interaction is not None:
+            for participation in interaction.participations:
+                principalid = participation.principal.id
+                if not principalid in dc.creators:
+                    dc.creators = dc.creators + (unicode(principalid), )
 
 CreatorAnnotator = CreatorAnnotatorClass()

Modified: Zope3/trunk/src/zope/app/dublincore/tests/test_creatorannotator.py
===================================================================
--- Zope3/trunk/src/zope/app/dublincore/tests/test_creatorannotator.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/dublincore/tests/test_creatorannotator.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -26,7 +26,7 @@
 from zope.app.dublincore.interfaces import IZopeDublinCore
 from zope.app.security.interfaces import IPrincipal
 from zope.app.event.interfaces import IEvent
-from zope.security.management import noSecurityManager, newSecurityManager
+from zope.security.management import newInteraction, endInteraction
 
 class IDummyContent(Interface):
     pass
@@ -65,16 +65,20 @@
         self.title = title
         self.description = description
 
+class DummyRequest:
 
+    def __init__(self, principal):
+        self.principal = principal
+        self.interaction = None
+
+
 class Test(PlacefulSetup, TestCase, CleanUp):
 
     def setUp(self):
         PlacefulSetup.setUp(self)
         ztapi.provideAdapter(IDummyContent, IZopeDublinCore, DummyDCAdapter)
-        noSecurityManager()
 
     def tearDown(self):
-        noSecurityManager()
         PlacefulSetup.tearDown(self)
 
     def test_creatorannotation(self):
@@ -91,33 +95,37 @@
                                     'this is a very bad author')
 
         # Check what happens if no user is there
-        noSecurityManager()
+        newInteraction(None)
         CreatorAnnotator.notify(event)
         self.assertEqual(data.creators,())
+        endInteraction()
 
         # Let the bad edit it first
-        security = newSecurityManager(bad_author)
+        newInteraction(DummyRequest(bad_author))
         CreatorAnnotator.notify(event)
 
         self.failIf(len(data.creators) != 1)
         self.failUnless(bad_author.id in data.creators)
+        endInteraction()
 
         # Now let the good edit it
-        security = newSecurityManager(good_author)
+        newInteraction(DummyRequest(good_author))
         CreatorAnnotator.notify(event)
 
         self.failIf(len(data.creators) != 2)
         self.failUnless(good_author.id in data.creators)
         self.failUnless(bad_author.id in data.creators)
+        endInteraction()
 
         # Let the bad edit it again
-        security = newSecurityManager(bad_author)
+        newInteraction(DummyRequest(bad_author))
         CreatorAnnotator.notify(event)
 
         # Check that the bad author hasn't been added twice.
         self.failIf(len(data.creators) != 2)
         self.failUnless(good_author.id in data.creators)
         self.failUnless(bad_author.id in data.creators)
+        endInteraction()
 
 def test_suite():
     return TestSuite((

Modified: Zope3/trunk/src/zope/app/errorservice/__init__.py
===================================================================
--- Zope3/trunk/src/zope/app/errorservice/__init__.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/errorservice/__init__.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -104,18 +104,18 @@
                     url = request.URL
                 try:
                     # XXX: UnauthenticatedPrincipal does not have getLogin()
-                    if hasattr(request.user, 'getLogin'):
-                        login = request.user.getLogin()
+                    if hasattr(request.principal, 'getLogin'):
+                        login = request.principal.getLogin()
                     else:
                         login = 'unauthenticated'
                     username = ', '.join(map(str, (login,
-                                          request.user.id,
-                                          request.user.title,
-                                          request.user.description
+                                          request.principal.id,
+                                          request.principal.title,
+                                          request.principal.description
                                          )))
-                # When there's an unauthorized access, request.user is
+                # When there's an unauthorized access, request.principal is
                 # not set, so we get an AttributeError
-                # XXX is this right? Surely request.user should be set!
+                # XXX is this right? Surely request.principal should be set!
                 # XXX Answer: Catching AttributeError is correct for the
                 #             simple reason that UnauthenticatedUser (which
                 #             I always use during coding), has no 'getLogin()'

Modified: Zope3/trunk/src/zope/app/exception/browser/tests/test_unauthorized.py
===================================================================
--- Zope3/trunk/src/zope/app/exception/browser/tests/test_unauthorized.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/exception/browser/tests/test_unauthorized.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -60,7 +60,7 @@
             pass
         request = TestRequest('/')
         authservice = DummyAuthService()
-        request.setUser(contained(DummyPrincipal(23), authservice))
+        request.setPrincipal(contained(DummyPrincipal(23), authservice))
         u = Unauthorized(exception, request)
         u.issueChallenge()
 
@@ -81,7 +81,7 @@
         authservice = DummyAuthService()
         psrc = DummyPrincipalSource()
         psrc = contained(psrc, authservice)
-        request.setUser(contained(DummyPrincipal(23), psrc))
+        request.setPrincipal(contained(DummyPrincipal(23), psrc))
         u = Unauthorized(exception, request)
         u.issueChallenge()
 

Modified: Zope3/trunk/src/zope/app/exception/browser/unauthorized.py
===================================================================
--- Zope3/trunk/src/zope/app/exception/browser/unauthorized.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/exception/browser/unauthorized.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -25,7 +25,7 @@
         # Set the error status to 403 (Forbidden) in the case when we don't
         # challenge the user
         self.request.response.setStatus(403)
-        principal = self.request.user
+        principal = self.request.principal
         prinreg = zapi.getParent(principal)
         if not IAuthenticationService.providedBy(prinreg):
             # With PluggableAuthenticationService, principals are

Modified: Zope3/trunk/src/zope/app/menu/browser/tests.py
===================================================================
--- Zope3/trunk/src/zope/app/menu/browser/tests.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/menu/browser/tests.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -20,7 +20,7 @@
 from zope.interface import Interface, implements
 from zope.component import getServiceManager
 
-from zope.security.management import newSecurityManager
+from zope.security.management import newInteraction
 from zope.security.checker import defineChecker, NamesChecker, CheckerPublic
 from zope.security.proxy import ProxyFactory
 
@@ -71,7 +71,13 @@
     def __call__(self):
         pass
 
+class ParticipationStub:
 
+    def __init__(self, principal):
+        self.principal = principal
+        self.interaction = None
+
+
 class Test(PlacefulSetup, unittest.TestCase):
 
     def setUp(self):
@@ -89,7 +95,7 @@
                                       abad='waaa'))
 
     def test(self):
-        newSecurityManager('who')
+        newInteraction(ParticipationStub('who'))
         v = MenuAccessView(ProxyFactory(ob), TestRequest())
         self.assertEqual(v['zmi_views'],
                          [{'description': '', 'title':'l1', 'action':'a1'},

Modified: Zope3/trunk/src/zope/app/onlinehelp/browser/skin/view_macros.pt
===================================================================
--- Zope3/trunk/src/zope/app/onlinehelp/browser/skin/view_macros.pt	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/onlinehelp/browser/skin/view_macros.pt	2004-05-14 10:45:25 UTC (rev 24642)
@@ -25,7 +25,7 @@
   <div metal:define-macro="logged_user">
     <p i18n:translate="">
       User: 
-      <span tal:replace="request/user/title" 
+      <span tal:replace="request/principal/title" 
             i18n:name="user_title">User</span>
     </p>
   </div>

Modified: Zope3/trunk/src/zope/app/publication/tests/test_browserpublication.py
===================================================================
--- Zope3/trunk/src/zope/app/publication/tests/test_browserpublication.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/publication/tests/test_browserpublication.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -280,7 +280,7 @@
         # With a normal request, we should get a body:
         output = StringIO()
         request = TestRequest(StringIO(''), output, {'PATH_INFO': '/'})
-        request.setUser(User())
+        request.setPrincipal(User())
         request.response.setBody("spam")
         pub.afterCall(request, None)
         request.response.outputBody()
@@ -296,7 +296,7 @@
         # But with a HEAD request, the body should be empty
         output = StringIO()
         request = TestRequest(StringIO(''), output, {'PATH_INFO': '/'})
-        request.setUser(User())
+        request.setPrincipal(User())
         request.method = 'HEAD'
         request.response.setBody("spam")
         pub.afterCall(request, None)

Modified: Zope3/trunk/src/zope/app/publication/tests/test_zopepublication.py
===================================================================
--- Zope3/trunk/src/zope/app/publication/tests/test_zopepublication.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/publication/tests/test_zopepublication.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -33,7 +33,7 @@
 from zope.publisher.interfaces import IRequest, IPublishTraverse
 from zope.publisher.browser import BrowserResponse
 from zope.security import simplepolicies
-from zope.security.management import setSecurityPolicy, getSecurityManager
+from zope.security.management import setSecurityPolicy, getInteraction
 
 from zope.app import zapi
 from zope.app.tests.placelesssetup import PlacelessSetup
@@ -139,7 +139,7 @@
         self.out = StringIO()
         self.request = TestRequest('/f1/f2', outstream=self.out)
         self.user = Principal('test.principal')
-        self.request.setUser(self.user)
+        self.request.setPrincipal(self.user)
         from zope.interface import Interface
         self.presentation_type = Interface
         self.request._presentation_type = self.presentation_type
@@ -370,20 +370,20 @@
         defineChecker(Folder, InterfaceChecker(IFolder))
 
         self.publication.beforeTraversal(self.request)
-        user = getSecurityManager().getPrincipal()
-        self.assertEqual(user, self.request.user)
-        self.assertEqual(self.request.user.id, 'anonymous')
+        self.assertEqual(list(getInteraction().participations),
+                         [self.request])
+        self.assertEqual(self.request.principal.id, 'anonymous')
         root = self.publication.getApplication(self.request)
         self.publication.callTraversalHooks(self.request, root)
-        self.assertEqual(self.request.user.id, 'anonymous')
+        self.assertEqual(self.request.principal.id, 'anonymous')
         ob = self.publication.traverseName(self.request, root, 'f1')
         self.publication.callTraversalHooks(self.request, ob)
-        self.assertEqual(self.request.user.id, 'test.anonymous')
+        self.assertEqual(self.request.principal.id, 'test.anonymous')
         ob = self.publication.traverseName(self.request, ob, 'f2')
         self.publication.afterTraversal(self.request, ob)
-        self.assertEqual(self.request.user.id, 'test.bob')
-        user = getSecurityManager().getPrincipal()
-        self.assertEqual(user, self.request.user)
+        self.assertEqual(self.request.principal.id, 'test.bob')
+        self.assertEqual(list(getInteraction().participations),
+                         [self.request])
 
     def testTransactionCommitAfterCall(self):
         root = self.db.open().root()

Modified: Zope3/trunk/src/zope/app/publication/zopepublication.py
===================================================================
--- Zope3/trunk/src/zope/app/publication/zopepublication.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/publication/zopepublication.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -27,7 +27,7 @@
 from zope.publisher.interfaces import Retry, IExceptionSideEffects
 from zope.publisher.interfaces import IRequest, IPublication
 
-from zope.security.management import newSecurityManager
+from zope.security.management import newInteraction, endInteraction
 from zope.security.checker import ProxyFactory
 from zope.security.proxy import trustedRemoveSecurityProxy
 from zope.proxy import removeAllProxies
@@ -72,12 +72,12 @@
             if p is None:
                 raise Unauthorized # If there's no default principal
 
-        request.setUser(p)
-        newSecurityManager(request.user)
+        request.setPrincipal(p)
+        newInteraction(request)
         get_transaction().begin()
 
     def _maybePlacefullyAuthenticate(self, request, ob):
-        if not IUnauthenticatedPrincipal.providedBy(request.user):
+        if not IUnauthenticatedPrincipal.providedBy(request.principal):
             # We've already got an authenticated user. There's nothing to do.
             # Note that beforeTraversal guarentees that user is not None.
             return
@@ -101,10 +101,8 @@
                 # nothing to do here
                 return
 
-        request.setUser(principal)
-        newSecurityManager(request.user)
+        request.setPrincipal(principal)
 
-
     def callTraversalHooks(self, request, ob):
         # Call __before_publishing_traverse__ hooks
 
@@ -152,6 +150,11 @@
     def afterCall(self, request, ob):
         txn = get_transaction()
         self.annotateTransaction(txn, request, ob)
+
+        # Make sure the interaction is ended
+        try: endInteraction()
+        except: pass # XXX I do not like this except clause, but it makes tests pass
+
         txn.commit()
 
     def annotateTransaction(self, txn, request, ob):
@@ -161,7 +164,7 @@
         This method is not part of the IPublication interface, since
         it's specific to this particular implementation.
         """
-        txn.setUser(request.user.id)
+        txn.setUser(request.principal.id)
 
         # Work around methods that are usually used for views
         bare = trustedRemoveSecurityProxy(ob)
@@ -227,6 +230,10 @@
         # It must definitely be aborted.
         get_transaction().abort()
 
+        # Make sure the interaction is ended
+        try: endInteraction()
+        except: pass
+
         # Convert ConflictErrors to Retry exceptions.
         if retry_allowed and isinstance(exc_info[1], ConflictError):
             tryToLogWarning('ZopePublication',

Modified: Zope3/trunk/src/zope/app/publisher/browser/globalbrowsermenuservice.py
===================================================================
--- Zope3/trunk/src/zope/app/publisher/browser/globalbrowsermenuservice.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/publisher/browser/globalbrowsermenuservice.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -22,8 +22,9 @@
 from zope.interface.type import TypeRegistry
 from zope.interface import implements
 from zope.security.checker import CheckerPublic
-from zope.security.management import getSecurityManager
-from zope.app.security.permission import checkPermission
+from zope.security import checkPermission
+from zope.app.security.permission import checkPermission \
+                                            as checkPermissionDefined
 from zope.app.component.metaconfigure import handler
 from zope.app.publisher.interfaces.browser import IBrowserMenuService
 from zope.app.publisher.interfaces.browser import IGlobalBrowserMenuService
@@ -92,7 +93,6 @@
 
         result = []
         seen = {}
-        sm = getSecurityManager()
 
         # stuff for figuring out the selected view
         request_url = request.getURL()
@@ -126,8 +126,7 @@
             if permission:
                 # If we have an explicit permission, check that we
                 # can access it.
-                if not sm.checkPermission(permission, object) and \
-                       permission is not CheckerPublic:
+                if not checkPermission(permission, object):
                     continue
 
             elif action:
@@ -216,7 +215,7 @@
             if permission == 'zope.Public':
                 permission = CheckerPublic
             else:
-                checkPermission(None, permission)
+                checkPermissionDefined(None, permission)
 
         data = registry.get(interface) or []
         data.append(

Modified: Zope3/trunk/src/zope/app/publisher/browser/tests/test_directives.py
===================================================================
--- Zope3/trunk/src/zope/app/publisher/browser/tests/test_directives.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/publisher/browser/tests/test_directives.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -706,8 +706,8 @@
 
         # XXX this seems to be no longer needed
         # Need to "log someone in" to turn on checks
-        #from zope.security.management import newSecurityManager
-        #newSecurityManager('someuser')
+        #from zope.security.management import newInteraction
+        #newInteraction(ParticipationStub('someuser'))
 
         view = getView(ob, 'test', request)
         self.assertEqual(view.browserDefault(request)[1], (u'index.html', ))
@@ -873,8 +873,8 @@
 
         # XXX This seems to be no longer needed
         # Need to "log someone in" to turn on checks
-        #from zope.security.management import newSecurityManager
-        #newSecurityManager('someuser')
+        #from zope.security.management import newInteraction
+        #newInteraction(ParticipationStub('someuser'))
 
         v = getView(ob, 'xxx.html', request)
         v = ProxyFactory(v)

Modified: Zope3/trunk/src/zope/app/publisher/browser/tests/test_globalbrowsermenuservice.py
===================================================================
--- Zope3/trunk/src/zope/app/publisher/browser/tests/test_globalbrowsermenuservice.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/publisher/browser/tests/test_globalbrowsermenuservice.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -20,7 +20,8 @@
 from zope.interface import Interface, implements
 from zope.publisher.browser import TestRequest
 from zope.publisher.interfaces.browser import IBrowserPublisher
-from zope.security.management import newSecurityManager, system_user
+from zope.security.management import newInteraction, endInteraction
+from zope.security.management import system_user
 
 from zope.app import zapi
 from zope.app.tests import ztapi
@@ -61,6 +62,13 @@
             }
 
 
+class ParticipationStub:
+
+    def __init__(self, principal):
+        self.principal = principal
+        self.interaction = None
+
+
 class GlobalBrowserMenuServiceTest(PlacelessSetup, unittest.TestCase):
 
     def __reg(self):
@@ -89,7 +97,7 @@
 
     def test_w_permission(self):
         ztapi.provideUtility(IPermission, Permission('p', 'P'), 'p')
-        
+
         r = self.__reg()
         r.menu('test_id', 'test menu')
         r.menuItem('test_id', Interface, 'a1', 't1', 'd1')
@@ -102,17 +110,18 @@
         r.menuItem('test_id', I111, 'u8', 't8', 'd8')
         r.menuItem('test_id', I12, 'a9', 't9', 'd9')
 
-        newSecurityManager('test')
+        newInteraction(ParticipationStub('test'))
 
         menu = r.getMenu('test_id', TestObject(), TestRequest())
 
         self.assertEqual(list(menu), [d(6), d(3), d(2), d(1)])
 
-        newSecurityManager(system_user)
+        endInteraction()
 
+        newInteraction(ParticipationStub(system_user))
+
         menu = r.getMenu('test_id', TestObject(), TestRequest())
         self.assertEqual(list(menu), [d(5), d(6), d(3), d(2), d(1)])
-        
 
     def test_no_dups(self):
         r = self.__reg()

Modified: Zope3/trunk/src/zope/app/rotterdam/dialog_macros.pt
===================================================================
--- Zope3/trunk/src/zope/app/rotterdam/dialog_macros.pt	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/rotterdam/dialog_macros.pt	2004-05-14 10:45:25 UTC (rev 24642)
@@ -49,7 +49,7 @@
 
       <metal:block define-macro="logged_user">
         <span tal:omit-tag="" i18n:translate="">User:</span>
-        <tal:block replace="request/user/title">
+        <tal:block replace="request/principal/title">
           User
         </tal:block>
       </metal:block>

Modified: Zope3/trunk/src/zope/app/rotterdam/template.pt
===================================================================
--- Zope3/trunk/src/zope/app/rotterdam/template.pt	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/rotterdam/template.pt	2004-05-14 10:45:25 UTC (rev 24642)
@@ -44,18 +44,18 @@
       <div id="userDetails">
         <metal:block define-macro="logged_user">
           <span tal:omit-tag="" i18n:translate="">User:</span>
-          <tal:block replace="request/user/title">
+          <tal:block replace="request/principal/title">
             User
           </tal:block>
         </metal:block>
           <a href="" 
             tal:attributes="href string:@@logout.html?nextURL=${request/URL}"
-            tal:condition="python: hasattr(request.user, 'getLogin')"
+            tal:condition="python: hasattr(request.principal, 'getLogin')"
             i18n:translate="">
             [Logout]</a>
           <a href="" 
             tal:attributes="href string:@@login.html?nextURL=${request/URL}"
-            tal:condition="python: not hasattr(request.user, 'getLogin')"
+            tal:condition="python: not hasattr(request.principal, 'getLogin')"
             i18n:translate="">
             [Login]</a>
       </div>

Modified: Zope3/trunk/src/zope/app/rotterdam/view_macros.pt
===================================================================
--- Zope3/trunk/src/zope/app/rotterdam/view_macros.pt	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/rotterdam/view_macros.pt	2004-05-14 10:45:25 UTC (rev 24642)
@@ -33,7 +33,7 @@
 
   <div metal:define-macro="logged_user">
     <p i18n:translate="">User: 
-      <span tal:replace="request/user/title">User</span>
+      <span tal:replace="request/principal/title">User</span>
     </p>
   </div>
 

Modified: Zope3/trunk/src/zope/app/schema/tests/test_field.py
===================================================================
--- Zope3/trunk/src/zope/app/schema/tests/test_field.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/schema/tests/test_field.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -22,12 +22,20 @@
 from zope.configuration import xmlconfig
 from zope.schema import Text, getFieldsInOrder
 from zope.security.checker import ProxyFactory
-from zope.security.management import system_user, newSecurityManager
+from zope.security.management import system_user, newInteraction
 from zope.app.tests import setup
 from zope.app.schema.wrapper import Struct
 from zope.security.checker import getChecker, _defaultChecker
 import zope.app.schema.tests
 
+
+class ParticipationStub:
+
+    def __init__(self, principal):
+        self.principal = principal
+        self.interaction = None
+
+
 class FieldPersistence(unittest.TestCase):
 
     def test_field_change(self):
@@ -46,7 +54,7 @@
     def setUp(self):
         setup.placefulSetUp()
         self.context = xmlconfig.file("fields.zcml", zope.app.schema.tests)
-        newSecurityManager(system_user)
+        newInteraction(ParticipationStub(system_user))
 
     def test_wrapped_field_checker(self):
         f1 = Text(title=u'alpha')

Modified: Zope3/trunk/src/zope/app/schema/tests/test_fieldfactory.py
===================================================================
--- Zope3/trunk/src/zope/app/schema/tests/test_fieldfactory.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/schema/tests/test_fieldfactory.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -23,18 +23,25 @@
 from zope.component.exceptions import ComponentLookupError
 from zope.component.interfaces import IFactory
 from zope.app.tests.placelesssetup import PlacelessSetup
-from zope.security.management import newSecurityManager, system_user
+from zope.security.management import newInteraction, system_user
 from zope.schema.interfaces import IField, IText
 from zope.interface import Interface
 from zope.configuration import xmlconfig
 
+
+class ParticipationStub:
+
+    def __init__(self, principal):
+        self.principal = principal
+        self.interaction = None
+
 class IFoo(Interface): pass
 
 class TestFieldFactory(PlacelessSetup, unittest.TestCase):
 
     def setUp(self):
         super(TestFieldFactory, self).setUp()
-        newSecurityManager(system_user)
+        newInteraction(ParticipationStub(system_user))
         context = xmlconfig.file('tests/test_fieldfactory.zcml',
                                  zope.app.schema)
 

Modified: Zope3/trunk/src/zope/app/schema/tests/test_schemautility.py
===================================================================
--- Zope3/trunk/src/zope/app/schema/tests/test_schemautility.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/schema/tests/test_schemautility.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -18,13 +18,20 @@
 
 from zope.configuration import xmlconfig
 from zope.schema import Text, getFieldNamesInOrder, getFieldsInOrder
-from zope.security.management import system_user, newSecurityManager
+from zope.security.management import system_user, newInteraction
 from zope.security.checker import getChecker, _defaultChecker, ProxyFactory
 from zope.app.schema.schema import SchemaUtility
 from zope.app.tests import setup
 from zope.app import zapi
 import zope.app.schema.tests
 
+class ParticipationStub:
+
+    def __init__(self, principal):
+        self.principal = principal
+        self.interaction = None
+
+
 class SchemaUtilityTests(TestCase):
 
     def _createSchemaUtility(self):
@@ -182,7 +189,7 @@
         s = self.s
         s.addField(u'alpha', self.alpha)
         s = ProxyFactory(s)
-        newSecurityManager(system_user)
+        newInteraction(ParticipationStub(system_user))
         f1 = ProxyFactory(s[u'alpha'])
         order = f1.order
         f1 = zapi.traverse(s, 'alpha')

Modified: Zope3/trunk/src/zope/app/security/browser/auth.py
===================================================================
--- Zope3/trunk/src/zope/app/security/browser/auth.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/security/browser/auth.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -26,7 +26,7 @@
 
     def login(self, nextURL=None):
         """See zope.app.security.interfaces.ILogin"""
-        if isinstance(removeAllProxies(self.request.user), \
+        if isinstance(removeAllProxies(self.request.principal), \
                       UnauthenticatedPrincipal):
             self.request.unauthorized("basic realm='Zope'")
             return self.failed()
@@ -53,7 +53,7 @@
 
     def logout(self, nextURL=None):
         """See zope.app.security.interfaces.ILogout"""
-        if not isinstance(self.request.user, UnauthenticatedPrincipal):
+        if not isinstance(self.request.principal, UnauthenticatedPrincipal):
             self.request.unauthorized("basic realm='Zope'")
             if nextURL:
                 return self.redirect()

Modified: Zope3/trunk/src/zope/app/security/browser/login.pt
===================================================================
--- Zope3/trunk/src/zope/app/security/browser/login.pt	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/security/browser/login.pt	2004-05-14 10:45:25 UTC (rev 24642)
@@ -6,7 +6,7 @@
 
      <p style="font-size: 200%" i18n:translate="">
        You are now logged in as 
-       <em tal:content="view/request/user/title" 
+       <em tal:content="view/request/principal/title" 
            i18n:name="UserTitle">Joe Smith</em>.
      </p>
 

Modified: Zope3/trunk/src/zope/app/security/metaconfigure.py
===================================================================
--- Zope3/trunk/src/zope/app/security/metaconfigure.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/security/metaconfigure.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -19,7 +19,7 @@
 
 from zope.security.checker import moduleChecker, Checker, defineChecker
 from zope.security.checker import CheckerPublic
-from zope.security.manager import setSecurityPolicy
+from zope.security.management import setSecurityPolicy
 from zope.app.security.interfaces import IPermission
 from zope.app.security.permission import Permission
 from zope.app.security.protectclass import checkPermission

Modified: Zope3/trunk/src/zope/app/securitypolicy/tests/test_zopepolicy.py
===================================================================
--- Zope3/trunk/src/zope/app/securitypolicy/tests/test_zopepolicy.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/securitypolicy/tests/test_zopepolicy.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -17,6 +17,7 @@
 """
 import unittest
 from zope.interface import implements
+from zope.interface.verify import verifyObject
 
 from zope.app import zapi
 from zope.app.annotation.attribute import AttributeAnnotations
@@ -46,10 +47,16 @@
 from zope.app.securitypolicy.rolepermission \
     import AnnotationRolePermissionManager
 
-class Context:
-    def __init__(self, user, stack=[]):
-        self.user, self.stack = user, stack
 
+class RequestStub:
+    def __init__(self, principal, interaction=None):
+        self.principal = principal
+        self.interaction = interaction
+
+class Interaction:
+    def __init__(self, user):
+        self.participations = [RequestStub(user, self)]
+
 class Unprotected:
     pass
 
@@ -141,27 +148,43 @@
         permissions.sort()
         self.assertEqual(permissions, expected)
 
-
     def testImport(self):
         from zope.app.securitypolicy.zopepolicy import ZopeSecurityPolicy
 
+    def testInterfaces(self):
+        from zope.security.interfaces import ISecurityPolicy
+        from zope.app.securitypolicy.zopepolicy import ZopeSecurityPolicy
+        verifyObject(ISecurityPolicy, ZopeSecurityPolicy())
 
+    def testCreateInteraction(self):
+        from zope.security.interfaces import IInteraction
+        from zope.app.securitypolicy.zopepolicy import ZopeSecurityPolicy
+        i1 = ZopeSecurityPolicy().createInteraction(None)
+        verifyObject(IInteraction, i1)
+        self.assertEquals(list(i1.participations), [])
+
+        user = object()
+        rq = RequestStub(user)
+        i2 = ZopeSecurityPolicy().createInteraction(rq)
+        verifyObject(IInteraction, i2)
+        self.assertEquals(list(i2.participations), [rq])
+
     def testGlobalCheckPermission(self):
         self.failUnless(
-            self.policy.checkPermission(self.read, None, Context(self.jim)))
+            self.policy.checkPermission(self.read, None, Interaction(self.jim)))
         self.failUnless(
-            self.policy.checkPermission(self.read, None, Context(self.tim)))
+            self.policy.checkPermission(self.read, None, Interaction(self.tim)))
         self.failUnless(
-            self.policy.checkPermission(self.write, None, Context(self.tim)))
+            self.policy.checkPermission(self.write, None, Interaction(self.tim)))
 
         self.failIf(self.policy.checkPermission(
-            self.read, None, Context(self.unknown)))
+            self.read, None, Interaction(self.unknown)))
         self.failIf(self.policy.checkPermission(
-            self.write, None, Context(self.unknown)))
+            self.write, None, Interaction(self.unknown)))
 
         self.failIf(
             self.policy.checkPermission(
-            self.read, None, Context(self.unknown)))
+            self.read, None, Interaction(self.unknown)))
 
         self.__assertPermissions(self.jim, ['create', 'read'])
         self.__assertPermissions(self.tim, ['read', 'write'])
@@ -172,28 +195,28 @@
 
         self.failUnless(
             self.policy.checkPermission(
-            self.read, None, Context(self.unknown)))
+            self.read, None, Interaction(self.unknown)))
 
         self.__assertPermissions(self.unknown, ['read'])
 
         principalPermissionManager.grantPermissionToPrincipal(
             self.write, self.jim.id)
         self.failUnless(
-            self.policy.checkPermission(self.write, None, Context(self.jim)))
+            self.policy.checkPermission(self.write, None, Interaction(self.jim)))
 
         self.__assertPermissions(self.jim, ['create', 'read', 'write'])
 
     def testPlaylessPrincipalRole(self):
         self.failIf(self.policy.checkPermission(
-            self.write, None, Context(self.jim)))
+            self.write, None, Interaction(self.jim)))
         principalRoleManager.assignRoleToPrincipal(
             self.manager, self.jim.id)
         self.failUnless(self.policy.checkPermission(
-            self.write, None, Context(self.jim)))
+            self.write, None, Interaction(self.jim)))
         principalRoleManager.removeRoleFromPrincipal(
             self.manager, self.jim.id)
         self.failIf(self.policy.checkPermission(
-            self.write, None, Context(self.jim)))
+            self.write, None, Interaction(self.jim)))
 
     def testPlayfulPrincipalRole(self):
         ztapi.provideAdapter(
@@ -205,15 +228,15 @@
         ob3 = TestClass(); ob3.__parent__ = ob2
 
         self.failIf(self.policy.checkPermission(
-            self.write, ob3, Context(self.jim)))
+            self.write, ob3, Interaction(self.jim)))
         AnnotationPrincipalRoleManager(ob3).assignRoleToPrincipal(
             self.manager, self.jim.id)
         self.failUnless(self.policy.checkPermission(
-            self.write, ob3, Context(self.jim)))
+            self.write, ob3, Interaction(self.jim)))
         AnnotationPrincipalRoleManager(ob3).removeRoleFromPrincipal(
             self.manager, self.jim.id)
         self.failIf(self.policy.checkPermission(
-            self.write, ob3, Context(self.jim)))
+            self.write, ob3, Interaction(self.jim)))
 
     def testPlayfulRolePermissions(self):
 
@@ -227,21 +250,21 @@
         ob2 = TestClass(); ob2.__parent__ = ob1
         ob3 = TestClass(); ob3.__parent__ = ob2
 
-        self.failIf(self.policy.checkPermission(test, ob3, Context(self.tim)))
+        self.failIf(self.policy.checkPermission(test, ob3, Interaction(self.tim)))
         self.__assertPermissions(self.tim, ['read', 'write'], ob3)
 
         ARPM(ob2).grantPermissionToRole(test, self.manager)
         self.failUnless(self.policy.checkPermission(test, ob3,
-                                                    Context(self.tim)))
+                                                    Interaction(self.tim)))
         self.__assertPermissions(self.tim, ['read', 'test', 'write'], ob3)
 
-        self.failIf(self.policy.checkPermission(test, ob3, Context(self.jim)))
+        self.failIf(self.policy.checkPermission(test, ob3, Interaction(self.jim)))
         self.__assertPermissions(self.jim, ['create', 'read'], ob3)
 
 
         ARPM(ob3).grantPermissionToRole(test, self.peon)
         self.failUnless(self.policy.checkPermission(
-            test, ob3, Context(self.jim)))
+            test, ob3, Interaction(self.jim)))
         self.__assertPermissions(self.jim, ['create', 'read', 'test'], ob3)
 
 
@@ -249,7 +272,7 @@
         principalPermissionManager.denyPermissionToPrincipal(
             test, self.jim.id)
         self.failIf(self.policy.checkPermission(
-            test, ob3, Context(self.jim)))
+            test, ob3, Interaction(self.jim)))
         self.__assertPermissions(self.jim, ['create', 'read'], ob3)
 
         principalPermissionManager.unsetPermissionForPrincipal(
@@ -263,11 +286,11 @@
         new = principalRegistry.definePrincipal('new', 'Newbie',
                                                 'Newbie User', 'new', '098')
         principalRoleManager.assignRoleToPrincipal(self.arole, new.id)
-        self.failUnless(self.policy.checkPermission(test, ob3, Context(new)))
+        self.failUnless(self.policy.checkPermission(test, ob3, Interaction(new)))
         self.__assertPermissions(new, ['test'], ob3)
 
         principalRoleManager.assignRoleToPrincipal(self.peon, new.id)
-        self.failIf(self.policy.checkPermission(test, ob3, Context(new)))
+        self.failIf(self.policy.checkPermission(test, ob3, Interaction(new)))
         self.__assertPermissions(new, ['read'], ob3)
 
     def testPlayfulPrinciplePermissions(self):
@@ -281,30 +304,30 @@
 
         test = definePermission('test', 'Test', '').id
 
-        self.failIf(self.policy.checkPermission(test, ob3, Context(self.tim)))
+        self.failIf(self.policy.checkPermission(test, ob3, Interaction(self.tim)))
 
         self.__assertPermissions(self.tim, ['read', 'write'], ob3)
 
         APPM(ob2).grantPermissionToPrincipal(test, self.tim.id)
         self.failUnless(self.policy.checkPermission(
-            test, ob3, Context(self.tim)))
+            test, ob3, Interaction(self.tim)))
         self.__assertPermissions(self.tim, ['read', 'test', 'write'], ob3)
 
         APPM(ob3).denyPermissionToPrincipal(test, self.tim.id)
         self.failIf(self.policy.checkPermission(
-            test, ob3, Context(self.tim)))
+            test, ob3, Interaction(self.tim)))
         self.__assertPermissions(self.tim, ['read', 'write'], ob3)
 
         APPM(ob1).denyPermissionToPrincipal(test, self.jim.id)
         APPM(ob3).grantPermissionToPrincipal(test, self.jim.id)
         self.failUnless(self.policy.checkPermission(
-            test, ob3, Context(self.jim)))
+            test, ob3, Interaction(self.jim)))
         self.__assertPermissions(self.jim, ['create', 'read', 'test'], ob3)
 
 
         APPM(ob3).unsetPermissionForPrincipal(test, self.jim.id)
         self.failIf(self.policy.checkPermission(
-            test, ob3, Context(self.jim)))
+            test, ob3, Interaction(self.jim)))
         self.__assertPermissions(self.jim, ['create', 'read'], ob3)
 
         # make sure placeless principal permissions override placeful ones
@@ -312,7 +335,7 @@
         principalPermissionManager.denyPermissionToPrincipal(
             test, self.tim.id)
         self.failIf(self.policy.checkPermission(
-            test, ob3, Context(self.tim)))
+            test, ob3, Interaction(self.tim)))
 
         self.__assertPermissions(self.tim, ['read', 'write'], ob3)
 

Modified: Zope3/trunk/src/zope/app/securitypolicy/zopepolicy.py
===================================================================
--- Zope3/trunk/src/zope/app/securitypolicy/zopepolicy.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/securitypolicy/zopepolicy.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -18,6 +18,8 @@
 from zope.interface import implements
 from zope.security.interfaces import ISecurityPolicy
 from zope.security.management import system_user
+from zope.security.simpleinteraction import createInteraction \
+                                            as _createInteraction
 
 from zope.app.location import LocationIterator
 
@@ -64,11 +66,14 @@
         self._ownerous = ownerous
         self._authenticated = authenticated
 
-    def checkPermission(self, permission, object, context):
+    createInteraction = staticmethod(_createInteraction)
+
+    def checkPermission(self, permission, object, interaction):
         # XXX We aren't really handling multiple principals yet
+        assert len(interaction.participations) == 1 # XXX
+        user = interaction.participations[0].principal
 
         # mapping from principal to set of roles
-        user = context.user
         if user is system_user:
             return True
 

Modified: Zope3/trunk/src/zope/app/tests/functional.py
===================================================================
--- Zope3/trunk/src/zope/app/tests/functional.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/tests/functional.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -31,6 +31,7 @@
 from zope.publisher.http import HTTPRequest
 from zope.publisher.publish import publish
 from zope.exceptions import Forbidden, Unauthorized
+from zope.security.management import endInteraction
 
 from zope.app import Application
 from zope.app.publication.zopepublication import ZopePublication
@@ -263,6 +264,9 @@
                 # __del__ methods happen if request.close() is not called here
                 if request:
                     request.close()
+                # Make sure the interaction is ended
+                try: endInteraction()
+                except: pass
         if errors:
             self.fail("%s contains broken links:\n" % path
                       + "\n".join(["  %s:\t%s" % (a, e) for a, e in errors]))

Modified: Zope3/trunk/src/zope/app/traversing/tests/test_traverser.py
===================================================================
--- Zope3/trunk/src/zope/app/traversing/tests/test_traverser.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/traversing/tests/test_traverser.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -39,9 +39,15 @@
 from zope.app.site.tests.placefulsetup import PlacefulSetup
 from zope.security.checker \
     import ProxyFactory, defineChecker, CheckerPublic, Checker
-from zope.security.management import newSecurityManager
+from zope.security.management import newInteraction
 from zope.app.container.contained import Contained, contained
 
+class ParticipationStub:
+
+    def __init__(self, principal):
+        self.principal = principal
+        self.interaction = None
+
 class C(Contained):
     def __init__(self, name):
         self.name = name
@@ -181,7 +187,7 @@
         self.assertEquals(tr.traverse(('folder', 'item')), item)
 
     def testItemDenied(self):
-        newSecurityManager('no one')
+        newInteraction(ParticipationStub('no one'))
         defineChecker(C, Denied('item'))
         tr = Traverser(ProxyFactory(self.root))
         folder = self.folder

Modified: Zope3/trunk/src/zope/app/undo/browser.py
===================================================================
--- Zope3/trunk/src/zope/app/undo/browser.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/undo/browser.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -30,7 +30,8 @@
         """
         request = self.request
         undo = zapi.getUtility(self.context, IUndoManager)
-        txn_info = undo.getPrincipalTransactions(request.user, first=0, last=1)
+        txn_info = undo.getPrincipalTransactions(request.principal, first=0,
+                                                 last=1)
         if txn_info:
             return txn_info[0].get('undo', False)
         return False
@@ -40,10 +41,11 @@
         return where he/she came from"""
         request = self.request
         undo = zapi.getUtility(self.context, IUndoManager)
-        txn_info = undo.getPrincipalTransactions(request.user, first=0, last=1)
+        txn_info = undo.getPrincipalTransactions(request.principal, first=0,
+                                                 last=1)
         if txn_info:
             id = txn_info[0]['id']
-            undo.undoPrincipalTransactions(request.user, [id])
+            undo.undoPrincipalTransactions(request.principal, [id])
         target = request.get('HTTP_REFERER', '@@SelectedManagementView.html')
         request.response.redirect(target)
 
@@ -57,7 +59,7 @@
         """Undo transactions that were issued by the authenticated
         user specified in 'ids'."""
         undo = zapi.getUtility(self.context, IUndoManager)
-        undo.undoPrincipalTransactions(self.request.user, ids)
+        undo.undoPrincipalTransactions(self.request.principal, ids)
         self._redirect()
 
     def _redirect(self):
@@ -76,5 +78,5 @@
         if not showall:
             context = self.context
         undo = zapi.getUtility(self.context, IUndoManager)
-        return undo.getPrincipalTransactions(self.request.user, context,
+        return undo.getPrincipalTransactions(self.request.principal, context,
                                              first, last)

Modified: Zope3/trunk/src/zope/app/undo/tests/test_undoview.py
===================================================================
--- Zope3/trunk/src/zope/app/undo/tests/test_undoview.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/undo/tests/test_undoview.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -63,7 +63,7 @@
         return list[first:abs(last)]
 
     def _emulatePublication(self, request):
-        self._user_name = request.user.id
+        self._user_name = request.principal.id
 
     def undoTransactions(self, ids):
         # just remove an element for now
@@ -96,7 +96,7 @@
     def testPrincipalLastTransactionIsUndo(self):
         request = self.request
         bonobo = principalRegistry.getPrincipal('bonobo')
-        request.setUser(bonobo)
+        request.setPrincipal(bonobo)
 
         view = UndoView(self.folder1, request)
         self.failIf(view.principalLastTransactionIsUndo())
@@ -110,7 +110,7 @@
     def testUndoPrincipalLastTransaction(self):
         request = self.request
         bonobo = principalRegistry.getPrincipal('bonobo')
-        request.setUser(bonobo)
+        request.setPrincipal(bonobo)
 
         self.undo._emulatePublication(request)
         view = UndoView(self.folder1, request)
@@ -135,7 +135,7 @@
     def testGetPrincipalTransactions(self):
         request = self.request
         bonobo = principalRegistry.getPrincipal('bonobo')
-        request.setUser(bonobo)
+        request.setPrincipal(bonobo)
 
         view = UndoView(self.folder1, request)
         expected = self.undo.getPrincipalTransactions(bonobo)
@@ -152,7 +152,7 @@
     def testUndoPrincipalTransactions(self):
         request = self.request
         bonobo = principalRegistry.getPrincipal('bonobo')
-        request.setUser(bonobo)
+        request.setPrincipal(bonobo)
         view = UndoView(self.folder1, request)
 
         # Just test whether it accepts the principal.  We know that

Modified: Zope3/trunk/src/zope/app/wiki/browser/skin/template.pt
===================================================================
--- Zope3/trunk/src/zope/app/wiki/browser/skin/template.pt	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/wiki/browser/skin/template.pt	2004-05-14 10:45:25 UTC (rev 24642)
@@ -68,9 +68,9 @@
 
       <div id="personal" i18n:translate="">
         User:
-        <tal:block replace="request/user/title" 
+        <tal:block replace="request/principal/title" 
             i18n:name="user">User</tal:block>
-        (<tal:block replace="request/user/getLogin" 
+        (<tal:block replace="request/principal/getLogin" 
             tal:on-error="string:anonymous"
             i18n:name="login">login</tal:block>)
 

Modified: Zope3/trunk/src/zope/app/workflow/stateful/instance.py
===================================================================
--- Zope3/trunk/src/zope/app/workflow/stateful/instance.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/workflow/stateful/instance.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -38,9 +38,10 @@
 from zope.interface import directlyProvides, implements
 from zope.proxy import removeAllProxies
 from zope.schema import getFields
-from zope.security.management import getSecurityManager
+from zope.security.management import getInteraction
 from zope.security.checker import CheckerPublic, Checker
 from zope.security.proxy import Proxy
+from zope.security import checkPermission
 from zope.tales.engine import Engine
 
 
@@ -224,7 +225,14 @@
         ctx = {}
         # data should be readonly for condition-evaluation
         ctx['data'] = self.data
-        ctx['principal'] = getSecurityManager().getPrincipal()
+        ctx['principal'] = None
+        interaction = getInteraction()
+        if interaction is not None:
+            principals = [p.principal for p in getInteraction().participations]
+            if principals:
+                # XXX There can be more than one principal
+                assert len(principals) == 1
+                ctx['principal'] = principals[0]
 
         # XXX This needs to be discussed:
         # how can we know if this ProcessInstance is annotated
@@ -273,7 +281,6 @@
         return script(contexts)
 
     def _outgoingTransitions(self, clean_pd):
-        sm = getSecurityManager()
         ret = []
         contexts = self._getContext()
 
@@ -281,11 +288,7 @@
             if self.status == trans.sourceState:
                 # check permissions
                 permission = trans.permission
-                #
-                if (permission is not None
-                    and permission is not CheckerPublic
-                    and not sm.checkPermission(permission, self)
-                    ):
+                if not checkPermission(permission, self):
                     continue
 
                 ctx = self._extendContext(trans, contexts)

Modified: Zope3/trunk/src/zope/app/workflow/stateful/tests/test_instance.py
===================================================================
--- Zope3/trunk/src/zope/app/workflow/stateful/tests/test_instance.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/workflow/stateful/tests/test_instance.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -27,7 +27,7 @@
 from zope.app.security.interfaces import IPermission
 from zope.app.security.permission import Permission
 from zope.security.checker import CheckerPublic
-from zope.security.management import newSecurityManager
+from zope.security.management import newInteraction
 
 from zope.app.annotation.interfaces import IAttributeAnnotatable
 from zope.app.registration.interfaces import IRegisterable
@@ -55,6 +55,13 @@
 from zope.app.utility import UtilityRegistration
 
 
+class ParticipationStub:
+
+    def __init__(self, principal):
+        self.principal = principal
+        self.interaction = None
+
+
 # define and create ProcessDefinition (PD) for tests
 class TestProcessDefinition(StatefulProcessDefinition):
     implements(IAttributeAnnotatable)
@@ -358,7 +365,7 @@
 
         ztapi.provideUtility(IPermission, Permission('deny', 'Deny'), 'deny')
 
-        newSecurityManager('test')
+        newInteraction(ParticipationStub('test'))
 
         pd = TestProcessDefinition()
 

Modified: Zope3/trunk/src/zope/app/zopetop/widget_macros.pt
===================================================================
--- Zope3/trunk/src/zope/app/zopetop/widget_macros.pt	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/app/zopetop/widget_macros.pt	2004-05-14 10:45:25 UTC (rev 24642)
@@ -10,7 +10,7 @@
 
 <div class="user" metal:define-macro="logged_user" i18n:translate="">
    Logged in as
-   <span tal:replace="request/user/title" i18n:name="user_title">
+   <span tal:replace="request/principal/title" i18n:name="user_title">
      dtremea</span>
 </div>
 

Modified: Zope3/trunk/src/zope/publisher/base.py
===================================================================
--- Zope3/trunk/src/zope/publisher/base.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/publisher/base.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -179,7 +179,8 @@
         '_body',             # The request body as a string
         '_publication',      # publication object
         '_presentation_skin', # View skin
-        '_user'               # request user, set by publication
+        '_principal',        # request principal, set by publication
+        'interaction',       # interaction, set by interaction
         )
 
     environment = RequestDataProperty(RequestEnvironment)
@@ -197,15 +198,16 @@
         else:
             self._response = response
         self._response._request = self
-        
+
         self._body_instream = body_instream
         self._held = ()
-        self._user = None
+        self._principal = None
+        self.interaction = None
 
-    def setUser(self, user):
-        self._user = user
+    def setPrincipal(self, principal):
+        self._principal = principal
 
-    user = property(lambda self: self._user)
+    principal = property(lambda self: self._principal)
 
     def _getPublication(self):
         'See IPublisherRequest'

Modified: Zope3/trunk/src/zope/publisher/browser.py
===================================================================
--- Zope3/trunk/src/zope/publisher/browser.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/publisher/browser.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -625,10 +625,10 @@
 
         self.setPresentationSkin(skin)
 
-    def setUser(self, user):
+    def setPrincipal(self, principal):
         # HTTPRequest needs to notify the HTTPTask of the username.
         # We don't want to have to stub HTTPTask in the tests.
-        BaseRequest.setUser(self, user)
+        BaseRequest.setPrincipal(self, principal)
 
 class BrowserResponse(HTTPResponse):
     """Browser response

Modified: Zope3/trunk/src/zope/publisher/http.py
===================================================================
--- Zope3/trunk/src/zope/publisher/http.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/publisher/http.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -453,12 +453,12 @@
         self._response.setHeader("WWW-Authenticate", challenge, True)
         self._response.setStatus(401)
 
-    def setUser(self, user):
+    def setPrincipal(self, principal):
         'See IPublicationRequest'
-        super(HTTPRequest, self).setUser(user)
+        super(HTTPRequest, self).setPrincipal(principal)
 
         if self.response.http_transaction is not None:
-            logging_info = ILoggingInfo(user)
+            logging_info = ILoggingInfo(principal)
             message = logging_info.getLogMessage()
             self.response.http_transaction.setAuthUserName(message)
 

Modified: Zope3/trunk/src/zope/publisher/interfaces/__init__.py
===================================================================
--- Zope3/trunk/src/zope/publisher/interfaces/__init__.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/publisher/interfaces/__init__.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -24,6 +24,7 @@
 from zope.interface import implements
 from zope.interface.common.mapping import IEnumerableMapping
 from zope.interface.common.interfaces import IException
+from zope.security.interfaces import IParticipation
 
 class IPublishingException(IException):
     pass
@@ -279,16 +280,10 @@
         """
 
 
-class IPublicationRequest(IPresentationRequest):
+class IPublicationRequest(IPresentationRequest, IParticipation):
     """Interface provided by requests to IPublication objects
     """
 
-    user = Attribute("""User object associated with the request
-
-                        It is up to the publication object to set this
-                        attribute by calling the setUser method.
-                        """)
-
     response = Attribute("""The request's response object
 
         Return an IPublisherResponse for the request.
@@ -325,8 +320,8 @@
         It's up to the publication object to decide this.
         """
 
-    def setUser(user):
-        """Set the user attribute.
+    def setPrincipal(principal):
+        """Set the principal attribute.
 
         It should be IPrincipal wrapped in it's AuthenticationService's context.
         """
@@ -391,9 +386,9 @@
     """Features that support application logic
     """
 
-    user = Attribute("""User object associated with the request
-                        This is a read-only attribute.
-                        """)
+    principal = Attribute("""Principal object associated with the request
+                             This is a read-only attribute.
+                          """)
 
     body = Attribute("""The body of the request as a string""")
 

Modified: Zope3/trunk/src/zope/publisher/tests/test_http.py
===================================================================
--- Zope3/trunk/src/zope/publisher/tests/test_http.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/publisher/tests/test_http.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -255,7 +255,7 @@
         lpw = req._authUserPW()
         self.assertEquals(lpw, (login, password))
 
-    def testSetUser(self):
+    def testSetPrincipal(self):
         class HTTPTaskStub:
             auth_user_name = None
             def setAuthUserName(self, name):
@@ -263,11 +263,11 @@
 
         task = HTTPTaskStub()
         req = self._createRequest(outstream=task)
-        req.setUser(UserStub("jim"))
+        req.setPrincipal(UserStub("jim"))
         self.assert_(not req.response._outstream.auth_user_name)
         req = self._createRequest(outstream=task)
         req.response.setHTTPTransaction(task)
-        req.setUser(UserStub("jim"))
+        req.setPrincipal(UserStub("jim"))
         self.assertEquals(req.response.http_transaction.auth_user_name, "jim")
 
     def testIPresentationRequest(self):

Modified: Zope3/trunk/src/zope/security/__init__.py
===================================================================
--- Zope3/trunk/src/zope/security/__init__.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/security/__init__.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -5,3 +5,28 @@
 # XXX There's a circular import problem with the proxy package.
 # The proxy framework needs some refactoring, but not today.
 import zope.proxy
+
+from zope.security.checker import CheckerPublic as _CheckerPublic
+from zope.security.management import getInteraction as _getInteraction
+from zope.security.management import getSecurityPolicy as _getSecurityPolicy
+
+def checkPermission(permission, object, interaction=None):
+    """Return whether security policy allows permission on object.
+
+    Arguments:
+    permission -- A permission name
+    object -- The object being accessed according to the permission
+    interaction -- An interaction, which provides access to information
+        such as authenticated principals.  If it is None, the current
+        interaction is used.
+
+    checkPermission is guaranteed to return True if permission is
+    CheckerPublic or None.
+    """
+    if permission is None or permission is _CheckerPublic:
+        return True
+    if interaction is None:
+        interaction = _getInteraction()
+    policy = _getSecurityPolicy()
+    return policy.checkPermission(permission, object, interaction)
+

Modified: Zope3/trunk/src/zope/security/checker.py
===================================================================
--- Zope3/trunk/src/zope/security/checker.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/security/checker.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -37,7 +37,7 @@
 from zope.interface.declarations import Declaration
 from zope.security.interfaces import IChecker, INameBasedChecker
 from zope.security.interfaces import ISecurityProxyFactory
-from zope.security.management import getSecurityManager
+from zope.security.management import getSecurityPolicy, getInteraction
 from zope.security._proxy import _Proxy as Proxy, getChecker
 from zope.exceptions import Unauthorized, ForbiddenAttribute, DuplicationError
 
@@ -143,8 +143,9 @@
         if permission is not None:
             if permission is CheckerPublic:
                 return # Public
-            manager = getSecurityManager()
-            if manager.checkPermission(permission, object):
+            policy = getSecurityPolicy()
+            interaction = getInteraction()
+            if policy.checkPermission(permission, object, interaction):
                 return
             else:
                 __traceback_supplement__ = (TracebackSupplement, object)
@@ -159,8 +160,9 @@
         if permission is not None:
             if permission is CheckerPublic:
                 return # Public
-            manager = getSecurityManager()
-            if manager.checkPermission(permission, object):
+            policy = getSecurityPolicy()
+            interaction = getInteraction()
+            if policy.checkPermission(permission, object, interaction):
                 return
             else:
                 __traceback_supplement__ = (TracebackSupplement, object)
@@ -303,8 +305,9 @@
         if permission is not None:
             if permission is CheckerPublic:
                 return # Public
-            manager = getSecurityManager()
-            if manager.checkPermission(permission, object):
+            policy = getSecurityPolicy()
+            interaction = getInteraction()
+            if policy.checkPermission(permission, object, interaction):
                 return
             else:
                 __traceback_supplement__ = (TracebackSupplement, object)
@@ -320,8 +323,9 @@
         if permission is not None:
             if permission is CheckerPublic:
                 return # Public
-            manager = getSecurityManager()
-            if manager.checkPermission(permission, object):
+            policy = getSecurityPolicy()
+            interaction = getInteraction()
+            if policy.checkPermission(permission, object, interaction):
                 return
             else:
                 __traceback_supplement__ = (TracebackSupplement, object)
@@ -337,8 +341,9 @@
         if permission is not None:
             if permission is CheckerPublic:
                 return # Public
-            manager = getSecurityManager()
-            if manager.checkPermission(permission, object):
+            policy = getSecurityPolicy()
+            interaction = getInteraction()
+            if policy.checkPermission(permission, object, interaction):
                 return
             else:
                 __traceback_supplement__ = (TracebackSupplement, object)

Deleted: Zope3/trunk/src/zope/security/context.py
===================================================================
--- Zope3/trunk/src/zope/security/context.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/security/context.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -1,39 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Default 'ISecurityContext' implementation.
-
-$Id: context.py,v 1.5 2004/02/20 20:42:12 srichter Exp $
-"""
-from zope.security.interfaces import ISecurityContext
-from zope.interface import implements
-
-class SecurityContext:
-    """Capture transient request-specific security information.
-
-    Attribute('stack',
-              'A stack of elements, each either be an ExecutableObject or a'
-              ' tuple consisting of an ExecutableObject and a custom'
-              ' SecurityPolicy.'
-              )
-
-    Attribute('user',
-              'The AUTHENTICATED_USER for the request.'
-              )
-    """
-    implements(ISecurityContext)
-
-    def __init__(self, user):
-        self.stack       = []
-        self.user        = user
-        self.objectCache = {}

Modified: Zope3/trunk/src/zope/security/examples/sandbox.py
===================================================================
--- Zope3/trunk/src/zope/security/examples/sandbox.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/security/examples/sandbox.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -225,6 +225,9 @@
     def setupAgent(self, agent):
         pass
 
+    def teardownAgent(self, agent):
+        pass
+
     def turn(self):
 
         global _homes
@@ -241,12 +244,13 @@
                                                              a._action.__name__)
                     print e
                     print 
+                self.teardownAgent(a)
 
             agents = filter(WanderLust, agents)
 
             for a in agents:
+                self.setupAgent(a)
                 try:
-                    self.setupAgent(a)
                     home = a.getHome()
                     new_home = GreenerPastures(a)
                     home.transportAgent(a, new_home)
@@ -255,7 +259,9 @@
                     print 'moving "%s" from "%s" to "%s"' %(a, h,` new_home`)
                     print e
                     print 
+                self.teardownAgent(a)
 
+
 def WanderLust(agent):
     """ is agent ready to move """
     if int(whrandom.random()*100) <= 30:

Modified: Zope3/trunk/src/zope/security/examples/sandbox_security.py
===================================================================
--- Zope3/trunk/src/zope/security/examples/sandbox_security.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/security/examples/sandbox_security.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -29,8 +29,8 @@
 $Id: sandbox_security.py,v 1.10 2004/03/05 22:09:33 jim Exp $
 """
 import sandbox
-from zope.security.interfaces import ISecurityPolicy
-from zope.security import checker, management
+from zope.security.interfaces import ISecurityPolicy, IParticipation
+from zope.security import checker, management, simpleinteraction
 from zope.interface import implements
 
 
@@ -81,9 +81,10 @@
 
     implements(ISecurityPolicy)
 
-    def checkPermission(self, permission, object, context):
+    createInteraction = staticmethod(simpleinteraction.createInteraction)
+
+    def checkPermission(self, permission, object, interaction):
         """See zope.security.interfaces.ISecurityPolicy"""
-        token = context.user.getAuthenticationToken()
         home = object.getHome()
         db = getattr(SimulationSecurityDatabase, home.getId(), None)
 
@@ -94,13 +95,32 @@
         if permission in allowed or ALL in allowed:
             return True
 
-        allowed = db.get(token, ())
-        if permission in allowed:
-            return True
+        if interaction is None:
+            return False
+        if not interaction.participations:
+            return False
+        for participation in interaction.participations:
+            token = participation.principal.getAuthenticationToken()
+            allowed = db.get(token, ())
+            if permission not in allowed:
+                return False
 
-        return False
+        return True
 
 
+class AgentParticipation:
+    """Agent Participation during the Simulation.
+
+    A very simple participation that is specific to the simulations.
+    """
+
+    implements(IParticipation)
+
+    def __init__(self, agent):
+        self.principal = agent
+        self.interaction = None
+
+
 def PermissionMapChecker(permissions_map={}, setattr_permission_func=NoSetAttr):
     """Create a checker from using the 'permission_map.'"""
     res = {}
@@ -159,10 +179,15 @@
     sandbox.Sandbox.addAgent = addAgent
 
     def setupAgent(self, agent):
-        management.newSecurityManager(agent)
+        management.newInteraction(AgentParticipation(agent))
 
     sandbox.TimeGenerator.setupAgent = setupAgent
 
+    def teardownAgent(self, agent):
+        management.endInteraction()
+
+    sandbox.TimeGenerator.teardownAgent = teardownAgent
+
     def GreenerPastures(agent):
         """ where do they want to go today """
         import whrandom

Modified: Zope3/trunk/src/zope/security/interfaces.py
===================================================================
--- Zope3/trunk/src/zope/security/interfaces.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/security/interfaces.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -17,33 +17,12 @@
 """
 from zope.interface import Interface, Attribute
 
-class ISecurityManagementSetup(Interface):
-    """Methods to manage the security manager.
 
-    Infrastructure (including tests, etc.) calls these things to
-    tweak the security manager.
-    """
-
-    def newSecurityManager(user):
-        """Install a new SecurityManager, using user.
-
-        Return the old SecurityManager, if any, or None.
-        """
-
-    def replaceSecurityManager(old_manager):
-        """Replace the SecurityManager with old_manager.
-
-        old_manager must implement ISecurityManager.
-        """
-
-    def noSecurityManager():
-        """Clear any existing SecurityManager."""
-
 class ISecurityManagement(Interface):
     """Public security management API."""
 
-    def getSecurityManager():
-        """Get a SecurityManager (create if needed)."""
+    def getSecurityPolicy():
+        """Get the system default security policy."""
 
     def setSecurityPolicy(aSecurityPolicy):
         """Set the system default security policy.
@@ -52,66 +31,32 @@
         should never, for example, be called during a web request.
         """
 
-class ISecurityProxyFactory(Interface):
 
-    def __call__(object, checker=None):
-        """Create a security proxy
+class ISecurityChecking(Interface):
+    """Public security API."""
 
-        If a checker is given, then use it, otherwise, try to figure
-        out a checker.
+    def checkPermission(permission, object, interaction=None):
+        """Return whether security policy allows permission on object.
 
-        If the object is already a security proxy, then it will be
-        returned.
-        """
-
-# XXX This interface has too much Zope application dependence. This
-# needs to be refactored somehow.
-
-class ISecurityManager(Interface):
-    """
-        A security manager provides methods for checking access and managing
-        executable context and policies.
-    """
-
-    def getPrincipal():
-        """Return the authenticated principal.
-
-        This is equivalent to something like::
-        REQUEST['AUTHENTICATED_USER']
-        but is a bit cleaner, especially if 'REQUEST' isn't handy.
-
-        An IPrincipal object wrapped in a context of its
-        AuthenticationService is returned.
-        """
-
-    def checkPermission(permission, object):
-        """Return whether security context allows permission on object.
-
         Arguments:
         permission -- A permission name
         object -- The object being accessed according to the permission
+        interaction -- An interaction, which provides access to information
+            such as authenticated principals.  If it is None, the current
+            interaction is used.
         """
 
-    def pushExecutable(anExecutableObject):
-        """
-            Push an ExecutableObject onto the manager's stack, and
-            activate its custom security policy, if any.
-        """
 
-    def popExecutable(anExecutableObject):
-        """
-            Pop the topmost ExecutableObject from the stack, deactivating
-            any custom security policy it might have installed.
-        """
+class ISecurityProxyFactory(Interface):
 
-    def calledByExecutable():
-        """
-            Return a boolean indicating whether the current request has
-            invoked any IExecutableObjects.
+    def __call__(object, checker=None):
+        """Create a security proxy
 
-            This can be used to determine if an object was called
-            (more or less) directly from a URL, or if it was called by
-            through-the-web provided code.
+        If a checker is given, then use it, otherwise, try to figure
+        out a checker.
+
+        If the object is already a security proxy, then it will be
+        returned.
         """
 
 
@@ -167,26 +112,62 @@
 
 class ISecurityPolicy(Interface):
 
-    def checkPermission(permission, object, context):
+    def createInteraction(participation=None):
+        """Creates a new interaction for a given request.
+
+        If participation is not None, it is added to the new interaction.
+
+        XXX perhaps this should be a separate interface IInteractionFactory,
+            and the factory registered by calling
+            ISecurityManagement.global setInteractionFactory(factory).
+        """
+
+    def checkPermission(permission, object, interaction):
         """Return whether security context allows permission on object.
 
         Arguments:
         permission -- A permission name
         object -- The object being accessed according to the permission
-        context -- A SecurityContext, which provides access to information
-            such as the context stack and AUTHENTICATED_USER.
+        interaction -- An interaction, which provides access to information
+            such as authenticated principals.
         """
 
 
-class ISecurityContext(Interface):
-    """Capture transient request-specific security information."""
+class IInteraction(Interface):
+    """A representation of an interaction between some actors and the system.
+    """
 
-    Attribute('stack',
-              'A stack of elements, each either be an ExecutableObject'
-              'or a tuple consisting of an ExecutableObject and a'
-              'custom SecurityPolicy.'
-            )
+    participations = Attribute("""An iterable of participations.""")
 
-    Attribute('user',
-              'The AUTHENTICATED_USER for the request.'
-              )
+    def add(participation):
+        """Add a participation."""
+
+    def remove(participation):
+        """Remove a participation."""
+
+
+class IParticipation(Interface):
+
+    interaction = Attribute("The interaction")
+    principal = Attribute("The authenticated principal")
+
+
+class IInteractionManagement(Interface):
+    """Interaction management API."""
+
+    def newInteraction(participation=None):
+        """Start a new interaction.
+
+        If participation is not None, it is added to the new interaction.
+        """
+
+    def getInteraction():
+        """Return the current interaction.
+
+        Returns None if called outside newInteraction/endInteraction pair.
+        XXX should it raise an exception instead?
+        """
+
+    def endInteraction():
+        """End the current interaction."""
+

Modified: Zope3/trunk/src/zope/security/management.py
===================================================================
--- Zope3/trunk/src/zope/security/management.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/security/management.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -11,81 +11,88 @@
 # FOR A PARTICULAR PURPOSE.
 #
 ##############################################################################
-"""Default 'ISecurityManagement' implementation
+"""Default 'ISecurityManagement' and 'IInteractionManagement' implementation
 
 $Id: management.py,v 1.5 2004/02/20 20:42:12 srichter Exp $
 """
 # Special system user that has all permissions
-# zope.security.manager needs it
+# zope.security.simplepolicies needs it
 system_user = object()
 
+import traceback
+
 from zope.interface import moduleProvides
 from zope.security.interfaces import ISecurityManagement
-from zope.security.interfaces import ISecurityManagementSetup
-from zope.security.manager import SecurityManager
-from zope.security.manager import setSecurityPolicy as _setSecurityPolicy
-from zope.security.context import SecurityContext
+from zope.security.interfaces import IInteractionManagement
+from zope.testing.cleanup import addCleanUp
+from zope.thread import thread_globals
 
-moduleProvides(ISecurityManagement, ISecurityManagementSetup)
+moduleProvides(ISecurityManagement, IInteractionManagement)
 
-try:
-    import thread
-except:
-    get_ident = lambda: 0
-else:
-    get_ident = thread.get_ident
 
-_managers = {}
+def _clear():
+    global _defaultPolicy
+    _defaultPolicy = ParanoidSecurityPolicy()
 
-from zope.testing.cleanup import addCleanUp
-addCleanUp(_managers.clear)
+addCleanUp(_clear)
 
+
 #
-#   ISecurityManagementSetup implementation
+#   ISecurityManagement implementation
 #
-def newSecurityManager(user):
-    """Install a new SecurityManager, using user.
 
-    Return the old SecurityManager, if any, or None.
-    """
-    return replaceSecurityManager(SecurityManager(SecurityContext(user)))
+def getSecurityPolicy():
+    """Get the system default security policy."""
+    return _defaultPolicy
 
-def replaceSecurityManager(old_manager):
-    """Replace the SecurityManager with 'old_manager', which must
-    implement ISecurityManager.
+def setSecurityPolicy(aSecurityPolicy):
+    """Set the system default security policy, and return the previous
+    value.
+
+    This method should only be called by system startup code.
+    It should never, for example, be called during a web request.
     """
+    global _defaultPolicy
 
-    thread_id = get_ident()
-    old = _managers.get(thread_id, None)
-    _managers[thread_id] = old_manager
-    return old
+    last, _defaultPolicy = _defaultPolicy, aSecurityPolicy
 
-def noSecurityManager():
-    """Clear any existing SecurityManager."""
-    try:
-        del _managers[get_ident()]
-    except KeyError:
-        pass
+    return last
 
+
 #
-#   ISecurityManagement implementation
+#   IInteractionManagement implementation
 #
-def getSecurityManager():
-    """Get a SecurityManager (create if needed)."""
-    thread_id = get_ident()
-    manager = _managers.get(thread_id, None)
 
-    if manager is None:
-        newSecurityManager(None)
-        manager = _managers.get(thread_id, None)
+def getInteraction(_thread=None):
+    """Get the current interaction."""
+    return thread_globals(_thread).interaction
 
-    return manager
+def newInteraction(participation=None, _thread=None, _policy=None):
+    """Start a new interaction."""
+    if getInteraction(_thread) is not None:
+        stack = getInteraction(_thread)._newInteraction_called_from
+        raise AssertionError("newInteraction called"
+                             " while another interaction is active:\n%s"
+                             % "".join(traceback.format_list(stack)))
+    interaction = getSecurityPolicy().createInteraction(participation)
+    interaction._newInteraction_called_from = traceback.extract_stack()
+    thread_globals(_thread).interaction = interaction
 
-def setSecurityPolicy(aSecurityPolicy):
-    """Set the system default security policy, and return the previous
-    value.
+def endInteraction(_thread=None):
+    """End the current interaction."""
+    if getInteraction(_thread=_thread) is None:
+        raise AssertionError("endInteraction called"
+                             " without an active interaction")
+    thread_globals(_thread).interaction = None
 
-    This method should only be called by system startup code.
-    It should never, for example, be called during a web request.
-    """
-    return _setSecurityPolicy(aSecurityPolicy)
+
+def _cleanUp():
+    thread_globals().interaction = None
+
+addCleanUp(_cleanUp)
+
+
+# circular imports are not fun
+
+from zope.security.simplepolicies import ParanoidSecurityPolicy
+_defaultPolicy = ParanoidSecurityPolicy()

Deleted: Zope3/trunk/src/zope/security/manager.py
===================================================================
--- Zope3/trunk/src/zope/security/manager.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/security/manager.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -1,151 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Default ISecurityManager implementation
-
-$Id: manager.py,v 1.4 2003/06/02 14:34:49 stevea Exp $
-"""
-from zope.interface import implements
-from zope.security.simplepolicies import ParanoidSecurityPolicy
-
-MAX_STACK_SIZE = 100
-
-_defaultPolicy = ParanoidSecurityPolicy()
-
-def _clear():
-    global _defaultPolicy
-    _defaultPolicy = ParanoidSecurityPolicy()
-
-from zope.testing.cleanup import addCleanUp
-addCleanUp(_clear)
-
-
-def setSecurityPolicy(aSecurityPolicy):
-    """Set the system default security policy.
-
-    This method should only be caused by system startup code. It should never,
-    for example, be called during a web request.
-    """
-    global _defaultPolicy
-
-    last, _defaultPolicy = _defaultPolicy, aSecurityPolicy
-
-    return last
-
-from zope.security.interfaces import ISecurityManager
-
-class SecurityManager:
-    """A security manager provides methods for checking access and managing
-    executable context and policies.
-    """
-    implements(ISecurityManager)
-
-    def __init__(self, context):
-        self._context = context
-        self._policy = None
-
-    def _getPolicy(self):
-        """Find current policy, or default.
-        """
-        policy = self._policy
-        if policy is None:
-            policy = _defaultPolicy
-        return policy
-
-    #
-    #   ISecurityManager implementation
-    #
-    def getPrincipal(self):
-        """Return the authenticated user.
-
-       This is equivalent to something like::
-
-         REQUEST['AUTHENTICATED_USER']
-
-        but is a bit cleaner, especially if 'REQUEST' isn't handy.
-        """
-        return self._context.user
-
-    def checkPermission(self, permission, object):
-        """Check whether the security context allows the given
-        permission on the given object. Return a boolean value.
-
-        Arguments:
-
-            permission -- A permission name
-
-            object -- The object being accessed according to the permission
-        """
-        return self._getPolicy().checkPermission(permission, object,
-                                                 self._context)
-
-    def pushExecutable(self, anExecutableObject):
-        """Push an ExecutableObject onto the manager's stack, and
-        activate its custom security policy, if any.
-        """
-        stack = self._context.stack
-
-        if len(stack) >= MAX_STACK_SIZE:
-            raise SystemError, 'Excessive recursion'
-
-        stack.append(anExecutableObject)
-        p = getattr(anExecutableObject, '_customSecurityPolicy', None)
-
-        if p is not None:
-            p = p()
-
-        self._policy = p
-
-    def popExecutable(self, anExecutableObject):
-        """Pop the topmost ExecutableObject from the stack, deactivating
-        any custom security policy it might have installed.
-        """
-        stack = self._context.stack
-
-        if not stack:
-            return
-
-        top = stack[-1]
-
-        if top is anExecutableObject:
-            del stack[-1]
-        else:
-            indexes = range(len(stack))
-            indexes.reverse()
-            for i in indexes:
-                top = stack[i]
-                if top is anExecutableObject:
-                    del stack[i:]
-                    break
-            else:
-                return
-
-        if stack:
-            top = stack[-1]
-            p = getattr(top, '_customSecurityPolicy', None)
-
-            if p is not None:
-                p = p()
-            self._policy = p
-        else:
-            self._policy = None
-
-    def calledByExecutable(self):
-        """Return a boolean indicating whether the current request has
-        invoked any IExecutableObjects.
-
-        This can be used to determine if an object was called (more or less)
-        directly from a URL, or if it was called by through-the-web provided
-        code.
-        """
-        return len(self._context.stack)

Modified: Zope3/trunk/src/zope/security/readme.txt
===================================================================
--- Zope3/trunk/src/zope/security/readme.txt	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/security/readme.txt	2004-05-14 10:45:25 UTC (rev 24642)
@@ -28,26 +28,17 @@
     objects.  Attribute names are mapped onto permission names when
     checking access and the implementation of the security check is
     defined by the security policy, which receives the object, the
-    permission name, and a context.
+    permission name, and an interaction.
 
-    Security contexts are containers of transient information such as
-    the current principal and the context stack.
+    Interactions are objects that represent the use of the system by
+    one or more principals.  An interaction contains a list of
+    participations, which represents the way a single principal
+    participates in the interaction.  An HTTP request is one example
+    of a participation.
 
-    To explain the concept and usage of the context stack, a little
-    background into the design influences of the default Zope policy
-    is needed, namely the Java language security model.  Within the
-    base language, code is associated with identifiers. I.e. this code
-    came from "Joe Schmoe", and another code archive comes signed from
-    Verisign.  When executing restricted code, it's important access
-    is checked not only for the code currently executing but for the
-    entire call/context stack (unless explicitly short-circuited).
-    I.e.  if Joe Schmoe's code does haven't access to the filesystem,
-    but if the Verisign code does, Joe's code could circumvent the
-    security policy by accessing the filesystem via the Verisign code.
-
     Its important to keep in mind that the policy provided is just a
     default, and it can be substituted with one which doesn't care
-    about principals or context stacks at all.
+    about principals or interactions at all.
 
   Framework Components
 
@@ -81,24 +72,23 @@
 
       Security Management
 
-        Provides accessors for setting up security manager and global
+        Provides accessors for setting up interactions and global
         security policy.
 
-      Security Context
+      Interaction
 
-        Stores transient information on the current principal and the
-        context stack.
+        Stores transient information on the list of participations.
 
-      Security Manager
+      Participation
 
-        Manages security context (execution stack) and delegates
-        permission checks to security policy.
+        Stores information about a principal participating in the
+        interaction.
 
       Security Policy
 
         Provides a single method that accepts the object, the
-        permission, and the context of the access being checked and is
-        used to implement the application logic for the security
+        permission, and the interaction of the access being checked
+        and is used to implement the application logic for the security
         framework.
 
   Narrative (agent sandbox)
@@ -117,7 +107,7 @@
       home to home randomly.
 
       The agent simulation was constructed separately from any
-      security aspects.  now we want to define and integrate a
+      security aspects.  Now we want to define and integrate a
       security model into the simulation.  The full code for the
       simulation and the security model is available separately; we
       present only relevant code snippets here for illustration as we
@@ -162,8 +152,7 @@
         proxy wrappers to automatically check security.
 
       - inserting hooks into the original simulation to register the
-        agents as the active principal within a security manager's
-        context....
+        agents as the active principal in an interaction.
 
     Defining Permission Model
 
@@ -226,27 +215,42 @@
 
       class SimulationSecurityPolicy:
 
-          __implements__ = ISecurityPolicy
+          implements(ISecurityPolicy)
 
-        def checkPermission(self, permission, object, context):
+          createInteraction = staticmethod(simpleinteraction.createInteraction)
 
-            token = context.user.getAuthenticationToken()
-            home = object.getHome()
-            db = getattr(SimulationSecurityDatabase, home.getId(), None)
+          def checkPermission(self, permission, object, interaction):
 
-            if db is None:
-                return False
+              home = object.getHome()
+              db = getattr(SimulationSecurityDatabase, home.getId(), None)
 
-            allowed = db.get('any', ())
-            if permission in allowed or ALL in allowed:
-                return True
+              if db is None:
+                  return False
 
-            allowed = db.get(token, ())
-            if permission in allowed:
-                return True
+              allowed = db.get('any', ())
+              if permission in allowed or ALL in allowed:
+                  return True
 
-            return False
+              if interaction is None:
+                  return False
+              if not interaction.participations:
+                  return False
+              for participation in interaction.participations:
+                  token = participation.principal.getAuthenticationToken()
+                  allowed = db.get(token, ())
+                  if permission not in allowed:
+                      return False
 
+              return True
+
+      There are no specific requirements for the interaction class, so we
+      can just use zope.security.simpleinteraction.Interaction.
+
+      Since an interaction can have more than one principal, we check that
+      *all* of them are given the necessary permission.  This is not really
+      necessary since we only create interactions with a single active
+      principal.
+
       There is some additional code present to allow for shortcuts in
       defining the permission database when defining permissions for
       all auth groups and all permissions.
@@ -271,13 +275,13 @@
       create custom security policies at a finer grained than global,
       but such is left as an exercise for the reader.
 
-    Security Manager Access
+    Interaction Access
 
-      The *default* implementation of the security management
-      interfaces defines security managers on a per thread basis with
+      The *default* implementation of the interaction management
+      interfaces defines interactions on a per thread basis with
       a function for an accessor.  This model is not appropriate for
-      all systems, as it restricts one to a single active user per
-      thread at any given moment.  Reimplementing the manager access
+      all systems, as it restricts one to a single active interaction per
+      thread at any given moment.  Reimplementing the interaction access
       methods though is easily doable and is noted here for
       completeness.
 
@@ -315,3 +319,6 @@
       Kapil Thangavelu <hazmat at objectrealms.net>
 
       Guido Wesdorp <guido at infrae.com>
+
+      Marius Gedminas <marius at pov.lt>
+

Copied: Zope3/trunk/src/zope/security/simpleinteraction.py (from rev 24640, Zope3/branches/mgedmin-security/src/zope/security/simpleinteraction.py)


Property changes on: Zope3/trunk/src/zope/security/simpleinteraction.py
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: Zope3/trunk/src/zope/security/simplepolicies.py
===================================================================
--- Zope3/trunk/src/zope/security/simplepolicies.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/security/simplepolicies.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -16,28 +16,39 @@
 $Id: simplepolicies.py,v 1.6 2004/02/20 20:42:12 srichter Exp $
 """
 
+from zope.interface import implements
 from zope.security.interfaces import ISecurityPolicy
 from zope.security.management import system_user
+from zope.security.simpleinteraction import createInteraction \
+                                            as _createInteraction
 import zope.security.checker
-from zope.interface import implements
 
 class ParanoidSecurityPolicy:
     """Deny all access."""
     implements(ISecurityPolicy)
 
-    def checkPermission(self, permission, object, context):
+    createInteraction = staticmethod(_createInteraction)
+
+    def checkPermission(self, permission, object, interaction):
         if permission is zope.security.checker.CheckerPublic:
             return True
-        if (context.user is system_user   # no user
-            and not context.stack  # no untrusted code
-            ):
+
+        if interaction is None:
+            return False
+
+        users = [p.principal for p in interaction.participations]
+        if len(users) == 1 and users[0] is system_user:
             return True # Nobody not to trust!
 
         return False
 
+
 class PermissiveSecurityPolicy:
     """Allow all access."""
     implements(ISecurityPolicy)
 
-    def checkPermission(self, permission, object, context):
+    createInteraction = staticmethod(_createInteraction)
+
+    def checkPermission(self, permission, object, interaction):
         return True
+

Modified: Zope3/trunk/src/zope/security/tests/test_checker.py
===================================================================
--- Zope3/trunk/src/zope/security/tests/test_checker.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/security/tests/test_checker.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -34,7 +34,7 @@
 class SecurityPolicy:
     implements(ISecurityPolicy)
 
-    def checkPermission(self, permission, object, context):
+    def checkPermission(self, permission, object, interaction):
         'See ISecurityPolicy'
         return permission == 'test_allowed'
 
@@ -45,7 +45,7 @@
         self._checked = []
         self.permissions = {}
 
-    def checkPermission(self, permission, object, context):
+    def checkPermission(self, permission, object, interaction):
         'See ISecurityPolicy'
         self._checked.append(permission)
         return self.permissions.get(permission, True)

Modified: Zope3/trunk/src/zope/security/tests/test_management.py
===================================================================
--- Zope3/trunk/src/zope/security/tests/test_management.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/security/tests/test_management.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -21,96 +21,101 @@
 from zope.interface.verify import verifyObject
 from zope.testing.cleanup import CleanUp
 
-from zope.security.management import noSecurityManager, newSecurityManager
-from zope.security.management import setSecurityPolicy
 
-
 class Test(CleanUp, unittest.TestCase):
 
     def test_import(self):
         from zope.security import management
         from zope.security.interfaces import ISecurityManagement
-        from zope.security.interfaces \
-            import ISecurityManagementSetup
+        from zope.security.interfaces import IInteractionManagement
 
-        verifyObject(ISecurityManagementSetup, management)
         verifyObject(ISecurityManagement, management)
+        verifyObject(IInteractionManagement, management)
 
-    def test_ISecurityManagementSetup(self):
+    def test_securityPolicy(self):
+        from zope.security.management import setSecurityPolicy
+        from zope.security.management import getSecurityPolicy
+        from zope.security.simplepolicies import PermissiveSecurityPolicy
 
-        from zope.security.management import noSecurityManager
-        from zope.security.management import newSecurityManager
-        from zope.security.management import replaceSecurityManager
+        policy = PermissiveSecurityPolicy()
+        setSecurityPolicy(policy)
+        self.assert_(getSecurityPolicy() is policy)
 
-        some_user = []
-        other_user = []
-        old = newSecurityManager(some_user)
-        self.assertEqual(old, None)
+    def test_getInteraction(self):
+        # XXX this test is a bit obfuscated
+        from zope.security.management import getInteraction
 
-        old = newSecurityManager(other_user)
-        self.failUnless(old is not None)
-        self.failUnless(old.getPrincipal() is some_user)
+        marker = object()
+        class ThreadVars:
+            interaction = marker
+        class ThreadStub:
+            __zope3_thread_globals__ = ThreadVars()
 
-        old2 = replaceSecurityManager(old)
-        self.failUnless(old2 is not None)
-        self.failUnless(old2.getPrincipal() is other_user)
+        self.assert_(getInteraction(_thread=ThreadStub()) is marker)
 
-        noSecurityManager()
+    def test_newInteraction(self):
+        # XXX this test is a bit obfuscated
+        from zope.security.management import newInteraction
 
-    def test_getSecurityManager(self):
-        # This is a test for the case when there is no principal
+        class ThreadVars:
+            interaction = None
+        class ThreadStub:
+            __zope3_thread_globals__ = ThreadVars()
 
-        from zope.security.management import noSecurityManager
-        from zope.security.management import replaceSecurityManager
-        from zope.security.management import getSecurityManager
+        rq = None
+        thread = ThreadStub()
+        newInteraction(rq, _thread=thread)
+        self.assert_(thread.__zope3_thread_globals__.interaction is not None)
 
-        noSecurityManager()
-        self.failUnless(replaceSecurityManager(None) is None)
+        self.assertRaises(AssertionError, newInteraction, rq, _thread=thread)
 
-        mgr = getSecurityManager()
-        self.assertEqual(mgr.getPrincipal(), None)
-        # XXX maybe add test for default principal case
-        self.failIf(mgr.calledByExecutable())
-        self.assertEqual(replaceSecurityManager(None), mgr)
+    def test_endInteraction(self):
+        # XXX this test is a bit obfuscated
+        from zope.security.management import endInteraction
 
-        noSecurityManager()
+        marker = object()
+        class ThreadVars:
+            interaction = marker
+        class ThreadStub:
+            __zope3_thread_globals__ = ThreadVars()
 
-    def _setPermissive(self):
-        from zope.security.management import setSecurityPolicy
-        from zope.security.simplepolicies import PermissiveSecurityPolicy
-        setSecurityPolicy(PermissiveSecurityPolicy())
+        thread = ThreadStub()
+        endInteraction(_thread=thread)
+        self.assert_(thread.__zope3_thread_globals__.interaction is None)
 
-    def _setParanoid(self):
+        self.assertRaises(AssertionError, endInteraction, _thread=thread)
+
+    def test_checkPermission(self):
+        from zope.security import checkPermission
         from zope.security.management import setSecurityPolicy
-        from zope.security.simplepolicies import ParanoidSecurityPolicy
-        setSecurityPolicy(ParanoidSecurityPolicy())
+        from zope.security.management import getInteraction
+        from zope.security.management import newInteraction
 
-    def test_setSecurityPolicy(self):
+        permission = 'zope.Test'
+        obj = object()
+        interaction = object()
 
-        from zope.security.management import noSecurityManager
-        from zope.security.management import getSecurityManager
+        class InteractionStub:
+            pass
 
-        # test against default policy (paranoid)
-        self._setParanoid()
-        newSecurityManager('some user')
-        mgr = getSecurityManager()
-        self.failIf(mgr.checkPermission(None, None))
+        class PolicyStub:
+            def createInteraction(s, r):
+                return InteractionStub()
 
-        # test against explicit permissive policy
-        self._setPermissive()
-        newSecurityManager('some user')
-        mgr = getSecurityManager()
-        self.failUnless(mgr.checkPermission(None, None))
+            def checkPermission(s, p, o, i):
+                self.assert_(p is permission)
+                self.assert_(o is obj)
+                self.assert_(i is getInteraction() or i is interaction)
+                return i is interaction
 
-        # test against explicit paranoid policy
-        self._setParanoid()
-        newSecurityManager('some user')
-        mgr = getSecurityManager()
-        self.failIf(mgr.checkPermission(None, None))
+        setSecurityPolicy(PolicyStub())
+        newInteraction(None)
+        self.assertEquals(checkPermission(permission, obj), False)
+        self.assertEquals(checkPermission(permission, obj, interaction), True)
 
 
 def test_suite():
-    loader=unittest.TestLoader()
+    loader = unittest.TestLoader()
     return loader.loadTestsFromTestCase(Test)
 
 if __name__=='__main__':

Deleted: Zope3/trunk/src/zope/security/tests/test_manager.py
===================================================================
--- Zope3/trunk/src/zope/security/tests/test_manager.py	2004-05-14 10:41:07 UTC (rev 24641)
+++ Zope3/trunk/src/zope/security/tests/test_manager.py	2004-05-14 10:45:25 UTC (rev 24642)
@@ -1,159 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
-# All Rights Reserved.
-#
-# This software is subject to the provisions of the Zope Public License,
-# Version 2.0 (ZPL).  A copy of the ZPL should accompany this distribution.
-# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
-# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
-# FOR A PARTICULAR PURPOSE.
-#
-##############################################################################
-"""Unit tests for SecurityManager
-
-$Id: test_manager.py,v 1.5 2004/03/13 17:21:51 philikon Exp $
-"""
-
-import unittest
-
-from zope.interface.verify import verifyClass
-
-from zope.security import manager
-from zope.security.simplepolicies import ParanoidSecurityPolicy
-from zope.security.simplepolicies import PermissiveSecurityPolicy
-from zope.security.context import SecurityContext
-
-class DummyExecutable:
-    """implements( (pseudo) IExecutableObject)"""
-
-class DummyExecutableWithCustomPolicy:
-    """implements( (pseudo) IExecutableObjectWithCustomSecurityPolicy)"""
-
-    def _customSecurityPolicy(self):
-        return PermissiveSecurityPolicy()
-
-class Test(unittest.TestCase):
-
-    def setUp(self):
-        self._oldPolicy = manager._defaultPolicy
-        manager.setSecurityPolicy(ParanoidSecurityPolicy())
-        self._context = SecurityContext('xyzzy')
-
-    def tearDown(self):
-        from zope.security.manager import setSecurityPolicy
-        setSecurityPolicy(self._oldPolicy)
-
-    def _makeMgr(self):
-        from zope.security.manager import SecurityManager
-        return SecurityManager(self._context)
-
-    def _setPermissive(self):
-        from zope.security.manager import setSecurityPolicy
-        setSecurityPolicy(PermissiveSecurityPolicy())
-
-
-    def test_import(self):
-        from zope.security.manager import SecurityManager
-        from zope.security.interfaces import ISecurityManager
-        verifyClass(ISecurityManager, SecurityManager)
-
-    def test_empty(self):
-        mgr = self._makeMgr()
-        self.assertEqual(mgr.getPrincipal(), self._context.user)
-        self.failIf(mgr.calledByExecutable())
-
-    def test_w_default_policy(self):
-        mgr = self._makeMgr()
-        self.failIf(mgr.checkPermission(None, None))
-
-    def test_w_permissive_policy(self):
-        mgr = self._makeMgr()
-        self._setPermissive()
-        self.failUnless(mgr.checkPermission(None, None))
-
-    def test_exec_stack_overflow(self):
-        from zope.security.manager import MAX_STACK_SIZE
-        mgr = self._makeMgr()
-
-        for i in range(MAX_STACK_SIZE):
-            mgr.pushExecutable(None)
-
-        self.assertRaises(SystemError, mgr.pushExecutable, None)
-
-    def test_pushExecutable_simple(self):
-        mgr = self._makeMgr()
-        self.failIf(mgr.calledByExecutable())
-
-        mgr.pushExecutable(DummyExecutable())
-        self.failUnless(mgr.calledByExecutable())
-
-    def test_popExecutable_simple(self):
-        mgr = self._makeMgr()
-        exe = DummyExecutable()
-        exe2 = DummyExecutable()
-
-        mgr.pushExecutable(exe)
-        mgr.pushExecutable(exe2)
-        mgr.popExecutable(exe2)
-        self.failUnless(mgr.calledByExecutable())
-
-        mgr.popExecutable(exe)
-        self.failIf(mgr.calledByExecutable())
-
-    def test_popExecutable_nomatch(self):
-        mgr = self._makeMgr()
-        exe = DummyExecutable()
-        exe2 = DummyExecutable()
-        other = DummyExecutable()
-
-        mgr.pushExecutable(exe)
-        mgr.pushExecutable(exe2)
-        mgr.popExecutable(other) # not on stack => no change
-        self.failUnless(mgr.calledByExecutable())
-
-        mgr.popExecutable(exe) # bottom of stack => empty it
-        self.failIf(mgr.calledByExecutable())
-
-    def test_pushExecutable_customPolicy(self):
-        mgr = self._makeMgr()
-        exe = DummyExecutableWithCustomPolicy()
-        self.failIf(mgr.checkPermission(None, None))
-        mgr.pushExecutable(exe)
-        self.failUnless(mgr.checkPermission(None, None))
-        mgr.popExecutable(exe)
-        self.failIf(mgr.checkPermission(None, None))
-
-    def test_pushPop_complexPolicies(self):
-        mgr = self._makeMgr()
-
-        exe1 = DummyExecutableWithCustomPolicy()
-        exe2 = DummyExecutable()
-        exe3 = DummyExecutableWithCustomPolicy()
-
-        mgr.pushExecutable(exe1) # now has custom permissive policy
-        self.failUnless(mgr.checkPermission(None, None))
-
-        mgr.pushExecutable(exe2) # now has default policy
-        self.failIf(mgr.checkPermission(None, None))
-
-        mgr.pushExecutable(exe3) # now has custom permissive policy
-        self.failUnless(mgr.checkPermission(None, None))
-
-        mgr.popExecutable(exe3) # back to default policy
-        self.failIf(mgr.checkPermission(None, None))
-
-        mgr.popExecutable(exe2) # back to has custom permissive policy
-        self.failUnless(mgr.checkPermission(None, None))
-
-        mgr.popExecutable(exe1) # back to default policy
-        self.failIf(mgr.checkPermission(None, None))
-
-
-def test_suite():
-    loader=unittest.TestLoader()
-    return loader.loadTestsFromTestCase(Test)
-
-if __name__=='__main__':
-    unittest.TextTestRunner().run(test_suite())

Copied: Zope3/trunk/src/zope/security/tests/test_simpleinteraction.py (from rev 24640, Zope3/branches/mgedmin-security/src/zope/security/tests/test_simpleinteraction.py)


Property changes on: Zope3/trunk/src/zope/security/tests/test_simpleinteraction.py
___________________________________________________________________
Name: svn:eol-style
   + native




More information about the Zope3-Checkins mailing list