[CMF-checkins] CVS: CMF/CMFCollector - Collector.py:1.24

Ken Manheimer klm@zope.com
Thu, 21 Feb 2002 12:00:33 -0500


Update of /cvs-repository/CMF/CMFCollector
In directory cvs.zope.org:/tmp/cvs-serv10012

Modified Files:
	Collector.py 
Log Message:
Enabled alternate collector policies about who can followup with
comments on existing issues.  Now the collector configurer can enable
comments by only staff and issue participants (the prior and default
situation), by any authenticated user, or by anyone including
authenticated users.

.participation: new attribute that tracks the collector issue
    participation modes.

 - 'staff' is the old policy - only staff and requester can comment
 - 'authenticated' enables any authenticated visitor to comment
 - 'anyone' enables anyone, including anonymous visitors.

.edit(): handle new .participation mode setting.

    Also, fixed small bug where state_email configuration setting was
    being recognized as changing even when it wasn't actually changed.

._adjust_participation_mode(): Set role privileges according to
    participation mode.

._reindex_issues(): Added adjustment of existing issues so they
    acquire AddCollectorIssueFollowup permission.  This is more than
    "reindex"ing, but that's just because the function name is wrong,
    not the place for the functionality...-)


=== CMF/CMFCollector/Collector.py 1.23 => 1.24 ===
 from Globals import InitializeClass, DTMLFile, package_home
 
-from AccessControl import ClassSecurityInfo, ModuleSecurityInfo
+from AccessControl import ClassSecurityInfo, ModuleSecurityInfo, Permission
 from AccessControl import getSecurityManager
 
 from Products.CMFDefault.DublinCore import DefaultDublinCoreImpl
@@ -89,6 +89,8 @@
 
     managers = ()
     dispatching = 1
+    # participation modes: 'staff', 'authenticated', 'anyone'
+    participation = 'staff'
 
     # state_email - a dictionary pairing state names with email destinations
     # for all notifications occuring within that state.
@@ -202,6 +204,7 @@
     def edit(self, title=None, description=None,
              abbrev=None, email=None,
              managers=None, supporters=None, dispatching=None,
+             participation=None,
              state_email=None,
              topics=None, classifications=None,
              importances=None,
@@ -214,15 +217,19 @@
         if title is not None and title != self.title:
             self.title = title
             changes.append("Title")
+
         if description is not None and self.description != description:
             self.description = description
             changes.append("Description")
+
         if abbrev is not None and self.abbrev != abbrev:
             self.abbrev = abbrev
             changes.append("Abbrev")
+
         if email is not None and self.email != email:
             self.email = email
             changes.append("Email")
+
         if not self.email:
             raise ValueError, ('<strong>'
                                '<font color="red">'
@@ -230,6 +237,7 @@
                                ' have an email address'
                                '</font>'
                                '</strong>')
+
         if managers is not None or not self.managers:
             # XXX Vette managers - they must exist, etc.
             x = filter(None, managers)
@@ -251,6 +259,7 @@
                 changes.append("Managers")
                 self.managers = x
                 staff_changed = 1
+
         if supporters is not None:
             # XXX Vette supporters - they must exist, etc.
             x = filter(None, supporters)
@@ -258,25 +267,40 @@
                 changes.append("Supporters")
                 self.supporters = x
                 staff_changed = 1
+
         if staff_changed:
             changes.extend(self._adjust_staff_roles())
+
         if dispatching is not None and self.dispatching != dispatching:
             self.dispatching = dispatching
             changes.append("Dispatching %s"
                            % ((dispatching and "on") or "off"))
-        if state_email is not None and self.state_email != state_email:
-            self.state_email = state_email
-            changes.append("State email")
+
+        if participation is not None and self.participation != participation:
+            self._adjust_participation_mode(participation)
+            changes.append("Participation => '%s'" % participation)
+
+        if state_email is not None:
+            changed = 0
+            for k, v in state_email.items():
+                if self.state_email[k] != v:
+                    changed = 1
+                    self.state_email[k] = v
+            if changed:
+                changes.append("State email")
+
         if topics is not None:
             x = filter(None, topics)
             if self.topics != x:
                 self.topics = x
                 changes.append("Topics")
+
         if classifications is not None:
             x = filter(None, classifications)
             if self.classifications != x:
                 self.classifications = x
                 changes.append("Classifications")
+
         if importances is not None:
             x = filter(None, importances)
             if self.importances != x:
@@ -321,6 +345,22 @@
 
         return change_notes
 
+    def _adjust_participation_mode(self, mode):
+        """Set role privileges according to participation mode."""
+
+        target_roles = ['Reviewer', 'Manager', 'Owner']
+
+        if mode == 'authenticated':
+            target_roles = target_roles + ['Authenticated']
+        elif mode == 'anyone':
+            target_roles = target_roles + ['Authenticated', 'Anonymous']
+
+        self.manage_permission(AddCollectorIssueFollowup,
+                               roles=target_roles,
+                               acquire=1)
+
+        self.participation = mode
+
     security.declareProtected(ManageCollector, 'reinstate_catalog')
     def reinstate_catalog(self, internal_only=1):
         """Recreate and reload internal catalog, to accommodate drastic
@@ -333,8 +373,22 @@
         self._reindex_issues(internal_only=internal_only)
 
     def _reindex_issues(self, internal_only=1):
-        """For, eg, allowedRolesAndUsers recompute after local_role changes."""
+        """For, eg, allowedRolesAndUsers recompute after local_role changes.
+
+        We also make sure that the AddCollectorIssueFollowup permission
+        acquires (old workflows controlled this).  This isn't exactly the
+        right place, but it is an expedient one."""
+
         for i in self.objectValues(spec='CMF Collector Issue'):
+
+            # Ensure the issue acquires AddCollectorIssueFollowup permission.
+            for m in i.ac_inherited_permissions(1):
+                if m[0] == AddCollectorIssueFollowup:
+                    perm = Permission.Permission(m[0], m[1], i)
+                    roles = perm.getRoles()
+                    if type(roles) == type(()):
+                        perm.setRoles(list(roles))
+
             i.reindexObject(internal_only=internal_only)
 
     security.declareProtected(ManageCollector, 'issue_states')