[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