[Checkins] SVN: five.customerize/trunk/src/five/customerize/ Add
permission registration/checking
Alec Mitchell
apm13 at columbia.edu
Sun Oct 29 18:59:49 EST 2006
Log message for revision 70976:
Add permission registration/checking
Changed:
U five.customerize/trunk/src/five/customerize/browser.py
U five.customerize/trunk/src/five/customerize/customerize.txt
A five.customerize/trunk/src/five/customerize/testviewtemplate.pt
U five.customerize/trunk/src/five/customerize/zpt.py
-=-
Modified: five.customerize/trunk/src/five/customerize/browser.py
===================================================================
--- five.customerize/trunk/src/five/customerize/browser.py 2006-10-29 20:14:44 UTC (rev 70975)
+++ five.customerize/trunk/src/five/customerize/browser.py 2006-10-29 23:59:49 UTC (rev 70976)
@@ -81,6 +81,7 @@
'zptfile': mangleAbsoluteFilename(reg.factory.index.filename),
'zcmlfile': mangleAbsoluteFilename(reg.info.file)
}
+
def viewClassFromViewName(self, viewname):
view = zope.component.getMultiAdapter((self.context, self.request),
name=viewname)
@@ -89,12 +90,11 @@
# (generally object or BrowserView) we return the full class
# and hope that it can be pickled
klass = view.__class__
- bases =klass.__bases__
- if len(bases) == 1:
+ base =klass.__bases__[0]
+ if base is BrowserView or base is object:
return klass
- return bases[0]
+ return base
-
def templateFromViewName(self, viewname):
view = zope.component.getMultiAdapter((self.context, self.request),
name=viewname)
@@ -104,6 +104,14 @@
template = self.templateFromViewName(viewname)
return open(template.filename, 'rb').read() #XXX: bad zope
+ def permissionFromViewName(self, viewname):
+ view = zope.component.getMultiAdapter((self.context, self.request),
+ name=viewname)
+ permissions = view.__class__.__ac_permissions__
+ for permission, methods in permissions:
+ if methods[0] in ('', '__call__'):
+ return permission
+
def doCustomizeTemplate(self, viewname):
# find the nearest site
site = findSite(self.context, IObjectManagerSite)
@@ -118,7 +126,9 @@
template_file = self.templateCodeFromViewName(viewname)
viewclass = self.viewClassFromViewName(viewname)
- viewzpt = TTWTemplate(zpt_id, template_file, view=viewclass)
+ permission = self.permissionFromViewName(viewname)
+ viewzpt = TTWTemplate(zpt_id, template_file, view=viewclass,
+ permission=permission)
site._setObject(zpt_id, viewzpt) #XXXthere could be a naming conflict
components = site.getSiteManager()
Modified: five.customerize/trunk/src/five/customerize/customerize.txt
===================================================================
--- five.customerize/trunk/src/five/customerize/customerize.txt 2006-10-29 20:14:44 UTC (rev 70975)
+++ five.customerize/trunk/src/five/customerize/customerize.txt 2006-10-29 23:59:49 UTC (rev 70976)
@@ -29,8 +29,13 @@
>>> zcml.load_config('configure.zcml', Products.Five)
>>> zcml.load_config('configure.zcml', five.customerize)
+Make this test a usable module
+
+ >>> from zope.testing.module import setUp, tearDown
+ >>> setUp(test, name='five.customerize.testcustomerize')
+
XXX: we are using root as the app name
- >>> root = app
+ >>> root = self.folder
1. Turning an ObjectManager into a site
@@ -156,10 +161,21 @@
>>> from zope.app.component.hooks import setSite
>>> setSite(site)
-Now look it up and compare its output:
+The newly registered adapter has an explicit security check that
+matches the original (in this case 'Manage Five local sites'),
+so the adapter lookup will fail unless logged in:
>>> view = zope.component.getMultiAdapter((item, request),
... name=u"customizezpt.html")
+ Traceback (most recent call last):
+ ...
+ Unauthorized: The current user does not have the required "Manage Five local sites" permission
+
+Now look it up as manager and compare its output:
+
+ >>> self.setRoles(['Manager',])
+ >>> view = zope.component.getMultiAdapter((item, request),
+ ... name=u"customizezpt.html")
>>> view = view.__of__(item)
>>> print view() #doctest: +ELLIPSIS
context: <SimpleContent at item>
@@ -171,11 +187,7 @@
nothing:
<BLANKLINE>
- >>> view.__class__.__bases__
- XXX
-
-
-5. Deleting view templates
+6. Deleting view templates
--------------------------
Once in a while we would like to get rid of the customized view. The
@@ -196,7 +208,63 @@
<code tal:content="request/form/viewname">viewname</code>:</p>
...
+5. Views with custom classes
+----------------------------
+Sometimes view classes have custom base classes which we need to be
+available to the customized local view. We create one of these views
+(using all the normal browser:page insanity) and then customize it:
+
+ >>> from Products.Five.browser import BrowserView
+ >>> class TestView(BrowserView):
+ ... """A view class"""
+ ... __name__ = 'mystaticview.html'
+ ... def foo_method(self):
+ ... return 'baz'
+ >>> from Products.Five.browser.metaconfigure import makeClassForTemplate
+ >>> from Products.Five.security import getSecurityInfo, protectClass
+ >>> from Globals import InitializeClass
+ >>> cdict = getSecurityInfo(TestView)
+ >>> cdict['__name__'] = 'simpleview.html'
+ >>> viewclass = makeClassForTemplate('testviewtemplate.pt', globals=globals(),
+ ... bases=(TestView,), cdict=cdict, name='simpleview.html')
+ >>> protectClass(viewclass, 'zope.Public')
+ >>> InitializeClass(viewclass)
+ >>> from zope.component import provideAdapter
+ >>> from zope.interface import Interface
+ >>> from zope.publisher.interfaces.browser import IDefaultBrowserLayer
+ >>> provideAdapter(viewclass, (Interface, IDefaultBrowserLayer),
+ ... Interface, name='simpleview.html')
+
+Now we retrieve the view and make sure it does what it should:
+
+ >>> view = zope.component.getMultiAdapter((item, request),
+ ... name=u"simpleview.html")
+ >>> print view()
+ <html>
+ ...
+ A simple view template with a class
+ baz
+ ...
+
+And we customize it:
+
+ >>> customizeview = zope.component.getMultiAdapter((item, request),
+ ... name=u"customizezpt.html")
+ >>> zpt = customizeview.doCustomizeTemplate(u'simpleview.html')
+ >>> template = getattr(site, 'testviewtemplate.pt')
+ >>> template.pt_edit('''\
+ ... A customized view
+ ... <span tal:replace="view/foo_method" />''', content_type=None)
+
+And render it again:
+
+ >>> view = zope.component.getMultiAdapter((item, request),
+ ... name=u"simpleview.html")
+ >>> print view()
+ A customized view
+ baz
+
Clean up:
---------
Added: five.customerize/trunk/src/five/customerize/testviewtemplate.pt
===================================================================
--- five.customerize/trunk/src/five/customerize/testviewtemplate.pt 2006-10-29 20:14:44 UTC (rev 70975)
+++ five.customerize/trunk/src/five/customerize/testviewtemplate.pt 2006-10-29 23:59:49 UTC (rev 70976)
@@ -0,0 +1,10 @@
+<html metal:use-macro="context/@@standard_macros/view"
+ i18n:domain="zope">
+ <body>
+ <div metal:fill-slot="body">
+
+ A simple view template with a class
+ <span tal:replace="view/foo_method"/>
+ </div>
+ </body>
+</html>
\ No newline at end of file
Modified: five.customerize/trunk/src/five/customerize/zpt.py
===================================================================
--- five.customerize/trunk/src/five/customerize/zpt.py 2006-10-29 20:14:44 UTC (rev 70975)
+++ five.customerize/trunk/src/five/customerize/zpt.py 2006-10-29 23:59:49 UTC (rev 70976)
@@ -1,4 +1,7 @@
import zope.component
+from AccessControl import getSecurityManager
+from AccessControl import Unauthorized
+
from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
from zope.app.container.interfaces import IObjectRemovedEvent
@@ -6,13 +9,19 @@
"""A template class used to generate Zope 3 views TTW"""
def __init__(self, id, text=None, content_type=None, encoding='utf-8',
- strict=False, view=None):
-
+ strict=False, view=None, permission=None):
self.view = view
+ self.permission = permission
super(TTWTemplate, self).__init__(id, text, content_type, encoding,
strict)
def __call__(self, context, request):
+ sm = getSecurityManager()
+ if self.permission:
+ allowed = sm.checkPermission(self.permission, context)
+ if not allowed:
+ raise Unauthorized, 'The current user does not have the '\
+ 'required "%s" permission'%self.permission
return TTWTemplateRenderer(context, request, self, self.view)
@@ -26,17 +35,21 @@
def __call__(self, *args, **kwargs):
"""Add the zope user to the security context, as done in
PageTemplateFile"""
- view = self.view
- if view is not None:
- class TTWView(view):
- __allow_access_to_unprotected_subobjects__ = 1
- view = TTWView(self.context, self.request)
+ view = self._getView()
bound_names = {'view': view,
'request': self.request,
'context': self.context}
template = self.template.__of__(self.context)
return template._exec(bound_names, args, kwargs)
+ def _getView(self):
+ view = self.view
+ if view is not None:
+ class TTWView(view):
+ __allow_access_to_unprotected_subobjects__ = 1
+ view = TTWView(self.context, self.request)
+ return view
+
def __of__(self, obj):
return self
@@ -48,4 +61,3 @@
break
components.unregisterAdapter(reg.factory, reg.required, reg.provided,
reg.name)
-
More information about the Checkins
mailing list