[Zope-CVS] CVS: Products/CompositePage - perm_names.py:1.1
version.txt:1.1 README.txt:1.3 composite.py:1.2
interfaces.py:1.2 slot.py:1.2 tool.py:1.2 transformers.py:1.2
Shane Hathaway
shane at zope.com
Wed Oct 1 15:00:03 EDT 2003
Update of /cvs-repository/Products/CompositePage
In directory cvs.zope.org:/tmp/cvs-serv28549
Modified Files:
README.txt composite.py interfaces.py slot.py tool.py
transformers.py
Added Files:
perm_names.py version.txt
Log Message:
Preparation for the first release:
- Finished the initial documentation.
- Added security checks.
=== Added File Products/CompositePage/perm_names.py ===
##############################################################################
#
# Copyright (c) 2003 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.
#
##############################################################################
"""Names of permissions used by CompositePage.
$Id: perm_names.py,v 1.1 2003/10/01 18:59:31 shane Exp $
"""
change_composites = "Change Composites"
view = "View"
=== Added File Products/CompositePage/version.txt ===
CompositePage-0.1
=== Products/CompositePage/README.txt 1.2 => 1.3 ===
--- Products/CompositePage/README.txt:1.2 Mon Sep 29 12:30:29 2003
+++ Products/CompositePage/README.txt Wed Oct 1 14:59:31 2003
@@ -1,5 +1,22 @@
+Contents
+========
+
+ - Introduction
+
+ - How to use CompositePage
+
+ - How to write a template
+
+ - How it works
+
+ - Adapting CompositePage to other applications
+
+ - Near-term directions
+
+
+
Introduction
============
@@ -29,8 +46,8 @@
- Create a Composite Tool instance in a central location, possibly the
root folder.
-- Create a Composite object. Turn on the "create a default template"
-checkbox.
+- Create a Composite object. Leave the "create a default template"
+checkbox checked.
- Visit the Composite object and select the "Design" tab. You should
see a three-column layout with blue dotted lines in the places where
@@ -61,7 +78,7 @@
=======================
Templates can be any Zope object, but ZPTs (Zope Page Templates) are
-the most useful. A template designed for use with composites uses the
+the most common. A template designed for use with composites uses the
'slots' attribute of the composite. The 'slots' attribute is a
mapping-like object.
@@ -90,10 +107,10 @@
that clash existing folder attributes.
Templates use either the single() or the multiple() method of a slot.
-single() returns a string, while multiple() returns a list of
-strings. Use single() when you expect the slot to never contain more
-than one element. Use multiple() to allow more than one element.
-In either case, don't forget the 'structure' keyword, since the
+single() returns a string, while multiple() returns a list of strings.
+Use single() when you expect the slot to never contain more than one
+element. Use multiple() to allow more than one element. In either
+case, don't forget to use the ZPT 'structure' keyword, since the
returned strings contain HTML that should not be escaped.
@@ -168,22 +185,21 @@
to express these constraints.
-Scope
-=====
-
+Adapting CompositePage to other applications
+============================================
+CompositePage provides a default user interface that integrates with
+the Zope management interface, but mechanisms are provided for
+integrating with any user interface. Look at transformers.py, the
+'common' subdirectory, and the 'zmi' subdirectory for guidance.
+Simple customizations probably do not require more code than the 'zmi'
+transformer.
-Developer Notes
-===============
-CompositePage is currently completely insecure. Anonymous users can
-change composites. Must fix. ;-)
-CompositePage is only loosely tied into the ZMI (Zope Management
-Interface). The product has a way to plug into other user interfaces
-like Zope4Intranets, CMF, and Plone. Take a look at transformers.py
-and the "zmi" and "common" subdirectories to see how this is done.
+Near-term directions
+====================
I would like CompositePage to work reliably with as many browsers as
possible, but Mozilla 1.4 is the current reference browser. Try it in
=== Products/CompositePage/composite.py 1.1 => 1.2 ===
--- Products/CompositePage/composite.py:1.1 Fri Sep 26 17:21:05 2003
+++ Products/CompositePage/composite.py Wed Oct 1 14:59:31 2003
@@ -29,6 +29,7 @@
from interfaces import ISlot, CompositeError
from slot import Slot
+import perm_names
_www = os.path.join(os.path.dirname(__file__), "www")
@@ -87,9 +88,11 @@
f._setId("filled_slots")
self._setObject(f.getId(), f)
+ security.declareProtected(perm_names.view, "getTemplate")
def getTemplate(self):
return self.restrictedTraverse(self.template_path)
+ security.declareProtected(perm_names.change_composites, "generateSlots")
def generateSlots(self):
"""Creates the slots defined by the template.
"""
@@ -99,6 +102,7 @@
finally:
self._v_generating = 0
+ security.declareProtected(perm_names.view, "__call__")
def __call__(self):
"""Renders the composite.
"""
@@ -115,6 +119,7 @@
index_html = None
+ security.declareProtected(perm_names.change_composites, "design")
def design(self, transformer="common"):
"""Renders the composite with editing features.
"""
@@ -135,11 +140,14 @@
tf = guarded_getattr(tool.transformers, transformer)
return tf.transform(self, text)
+ security.declareProtected(perm_names.change_composites,
+ "manage_designForm")
def manage_designForm(self):
"""Renders the composite with editing and ZMI features.
"""
return self.design("zmi")
+ security.declareProtected(perm_names.view, "isEditing")
def isEditing(self):
return self._v_editing
=== Products/CompositePage/interfaces.py 1.1 => 1.2 ===
--- Products/CompositePage/interfaces.py:1.1 Fri Sep 26 17:21:05 2003
+++ Products/CompositePage/interfaces.py Wed Oct 1 14:59:31 2003
@@ -21,6 +21,31 @@
"""A slot in a composite.
"""
+ def single():
+ """Renders to a string as a single-element slot.
+ """
+
+ def multiple():
+ """Renders to a sequence of strings as a multiple-element slot.
+ """
+
+ def reorder(name, new_index):
+ """Moves an item to a new index.
+ """
+
+ def nullify(name):
+ """Removes an item from the slot, returning the old item.
+
+ Leaves a null element in its place. The null element ensures
+ that other items temporarily keep their index within the slot.
+ """
+
+ def pack():
+ """Removes all null elements from the slot.
+ """
+
+
+
class CompositeError(Exception):
"""An error in constructing a composite
"""
=== Products/CompositePage/slot.py 1.1 => 1.2 ===
--- Products/CompositePage/slot.py:1.1 Fri Sep 26 17:21:05 2003
+++ Products/CompositePage/slot.py Wed Oct 1 14:59:31 2003
@@ -20,14 +20,17 @@
import sys
from cgi import escape
+import Globals
from Acquisition import aq_base, aq_inner, aq_parent
from ZODB.POSException import ConflictError
from OFS.SimpleItem import SimpleItem
from OFS.OrderedFolder import OrderedFolder
from DocumentTemplate.DT_Util import safe_callable
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
+from AccessControl import ClassSecurityInfo
from interfaces import ISlot
+import perm_names
_www = os.path.join(os.path.dirname(__file__), "www")
@@ -48,20 +51,25 @@
__implements__ = ISlot, OrderedFolder.__implements__
+ security = ClassSecurityInfo()
+
null_element = NullElement("null_element")
def __init__(self, id):
self.id = id
+ security.declareProtected(perm_names.view, "single")
def single(self):
"""Renders as a single-element slot."""
allow_add = (not self._objects)
return "".join(self.renderToList(allow_add))
+ security.declareProtected(perm_names.view, "multiple")
def multiple(self):
return self.renderToList(1)
+ security.declareProtected(perm_names.change_composites, "reorder")
def reorder(self, name, new_index):
if name not in self.objectIds():
raise KeyError, name
@@ -70,6 +78,7 @@
{'id': name, 'meta_type': getattr(self, name).meta_type})
self._objects = tuple(objs)
+ security.declareProtected(perm_names.change_composites, "nullify")
def nullify(self, name):
res = self[name]
objs = list(self._objects)
@@ -80,10 +89,12 @@
delattr(self, name)
return res
+ security.declareProtected(perm_names.change_composites, "nullify")
def pack(self):
objs = [info for info in self._objects if info["id"] != "null_element"]
self._objects = tuple(objs)
+ security.declareProtected(perm_names.view, "renderToList")
def renderToList(self, allow_add):
"""Renders the items to a list.
"""
@@ -133,6 +144,7 @@
return res
+Globals.InitializeClass(Slot)
=== Products/CompositePage/tool.py 1.1 => 1.2 ===
--- Products/CompositePage/tool.py:1.1 Fri Sep 26 17:21:05 2003
+++ Products/CompositePage/tool.py Wed Oct 1 14:59:31 2003
@@ -20,6 +20,7 @@
from Acquisition import aq_base, aq_parent, aq_inner
from OFS.SimpleItem import SimpleItem
from AccessControl import ClassSecurityInfo
+from AccessControl.ZopeGuards import guarded_getattr
from interfaces import ISlot, CompositeError
@@ -37,7 +38,9 @@
class Transformers(SimpleItem):
- """Makes page transformers accessible through URL traversal.
+ """The container of transformer objects.
+
+ Makes page transformers accessible through URL traversal.
"""
def __init__(self, id):
@@ -62,6 +65,8 @@
security.declarePublic("transformers")
transformers = Transformers("transformers")
+ _check_security = 1 # Turned off in unit tests
+
security.declarePublic("moveElements")
def moveElements(self, source_paths, target_path, target_index):
@@ -106,19 +111,21 @@
slot_id = id(aq_base(slot))
if not orig_slots.has_key(slot_id):
orig_slots[slot_id] = slot
- # validate(slot, "nullify")
- element = slot.nullify(source[-1])
+ nullify = guarded_getattr(slot, "nullify") # Check security
+ element = nullify(source[-1])
elements.append(element)
# Add the elements and reorder.
slot = root.restrictedTraverse(target_path)
assert ISlot.isImplementedBy(slot), repr(slot)
for element in elements:
- # verifyObjectPaste(element, container=slot)
+ if self._check_security:
+ slot._verifyObjectPaste(element) # Check security
new_id = slot._get_id(element.getId())
element._setId(new_id)
slot._setObject(new_id, element)
- slot.reorder(new_id, target_index)
+ reorder = guarded_getattr(slot, "reorder") # Check security
+ reorder(new_id, target_index)
target_index += 1
finally:
# Clear the nulls just added.
@@ -144,8 +151,8 @@
slot_id = id(aq_base(slot))
if not orig_slots.has_key(slot_id):
orig_slots[slot_id] = slot
- # validate(slot, "nullify")
- slot.nullify(source[-1])
+ nullify = guarded_getattr(slot, "nullify") # Check security
+ nullify(source[-1])
finally:
# Clear the nulls just added.
for slot in orig_slots.values():
=== Products/CompositePage/transformers.py 1.1 => 1.2 ===
--- Products/CompositePage/transformers.py:1.1 Fri Sep 26 17:21:05 2003
+++ Products/CompositePage/transformers.py Wed Oct 1 14:59:31 2003
@@ -24,9 +24,11 @@
from OFS.SimpleItem import SimpleItem
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
from AccessControl import ClassSecurityInfo
+from AccessControl.ZopeGuards import guarded_getattr
from rawfile import RawFile
+
_common = os.path.join(os.path.dirname(__file__), "common")
_zmi = os.path.join(os.path.dirname(__file__), "zmi")
@@ -67,6 +69,7 @@
bottom_templates = (PageTemplateFile("bottom.pt", _common),)
+ security.declarePublic("transform")
def transform(self, composite, text):
"""Adds scripts to a rendered composite.
"""
@@ -136,6 +139,7 @@
bottom_templates = (PageTemplateFile("bottom.pt", _zmi),
) + CommonTransformer.bottom_templates
+ security.declarePublic("showElement")
def showElement(self, path, RESPONSE):
"""Redirects to the workspace for an element.
"""
@@ -143,6 +147,7 @@
obj = root.restrictedTraverse(path)
RESPONSE.redirect(obj.absolute_url() + "/manage_workspace")
+ security.declarePublic("showSlot")
def showSlot(self, path, RESPONSE):
"""Redirects to (and possibly creates) the workspace for a slot.
"""
@@ -157,7 +162,8 @@
except TypeError:
is_comp = 0 # Python 2.1 bug
if is_comp:
- obj.generateSlots()
+ gen = guarded_getattr(obj, "generateSlots")
+ gen()
RESPONSE.redirect(obj.absolute_url() + "/manage_workspace")
Globals.InitializeClass(ZMITransformer)
More information about the Zope-CVS
mailing list