[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')