PloneNotification (0.1)
- PloneNotification download link: http://www.zopevillage.com/contributions/index_html-en/PloneNotification/PloneNotification-0.1.tar.gz
- Homepage of PloneNotification: http://www.zopevillage.com/contributions/index_html-en/PloneNotification
There are currently no items in this folder.
Proxy roles, workflow scripts and Plone 2.5.2/Zope 2.9.6
I spent some time solving this one. You now need Manager role access to read state_change.new_state, state_change.old_state and state_change.transition, but Manager role set as proxy doesn't work. This seems related to this problem: http://www.zope.org/Collectors/Zope/1779. Fortunately I was able to read state_change.status["review_state"] to replace state_change.new_state.getId().
Here is my not proxied script:
## Script (Python) "sendWorkflowNotification"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=state_change
##title=User part of email notification
##
object = getattr(state_change, object)
state = state_change
comment=state_change.kwargs.get(comment, No comments)
context.proxied_sendWorkflowNotification(object, state, comment)
And the proxied script:
## Script (Python) "proxied_sendWorkflowNotification" ##bind container=container ##bind context=context ##bind namespace= ##bind script=script ##bind subpath=traverse_subpath ##parameters=object, state, comment ##title=Heavy lifting of notification ## mship = context.portal_membership mhost = context.MailHost
ADUsers = context.acl_users.LDAPMulti.acl_users
#users = context.plone_utils.getInheritedLocalRoles(object)
#new_state = state.new_state.getId() # Plone workflows use variable called "review_state" to store state id # of the object state new_state = state.status["review_state"]
if (new_state == Reviewing):
notify_role = Member
awaiting = review
elif (new_state == Scrub):
notify_role = Reviewer
awaiting = scrub
else:
notify_role = Manager
awaiting = debugging
local_users = object.computeRoleMap() group_users = ADUsers.getGroupedUsers([(notify_role, notify_role)])
users = []
for u in group_users: users.append(u.id)
for u in local_users: if (notify_role in u["local"]): users.append(u["id"])
# the message format, %s will be filled in from data message = """ From: %s To: %s Subject: CTO Office item awaiting %s - %s
%s
%s
%s
URL: %s """
authorid = mship.getAuthenticatedMember().getUserName() author = ADUsers.getUserById(authorid).fullname note = author + " has submitted this item for " + awaiting + ", with comment: " \ + comment
for userid in users: user = ADUsers.getUserById(userid) if user.email: msg = message % ( context.email_from_address, user.email, awaiting, object.TitleOrId(), note, object.TitleOrId(), object.Description(), object.absolute_url() ) mhost.send(msg)



access Products.DCWorkflow.Expression.StateChangeInfo on recent zope builds, even with a proxy role.
Consequently, it is impossible to change state from (say) 'visible' to 'pending' with the script in place.
VerboseSecurity gives the message:
Unauthorized: The owner of the executing script is defined
outside the context of the object being accessed. The
script has proxy roles, but they do not apply in this
context.. Access to 'object' of
(Products.DCWorkflow.Expression.StateChangeInfo instance
at 0x9d6a4ac) denied. Access requires View_Permission,
granted to the following roles: ['Manager', 'Owner',
'Reviewer']. The executing script is (PythonScript at
/my_site/portal_workflow/plone_workflow/scripts/proxied_sendWorkflowNotification),
owned by Manager.
A workaround is provided by duncan.booth at suttoncourtenay.org.uk, see http://mail.zope.org/pipermail/zope-cmf/2005-April/022152.html
Put a script sendWorkflowNotification in plone_workflow with no proxy permission:
<snip>
## Script (Python) "sendWorkflowNotification"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=state_change
##title=send an email to recipients.
##
# Plone objects with proxy permissions can't access some 'deep' zope objects
# the workaround is to access the 'deep' objects here, without proxy,
# then to call a proxied script to do the work that a non-proxied script
# cannot do.
#
# kudos to duncan.booth at suttoncourtenay.org.uk
#http://mail.zope.org/pipermail/zope-cmf/2005-April/022152.html
object = getattr(state_change, 'object')
old_state = state_change.old_state.getId()
new_state = state_change.new_state.getId()
comment=state_change.kwargs.get('comment', 'No comments')
return container.proxied_sendWorkflowNotification(object,old_state,new_state,comment)
</snip>
Then put a second script proxied_sendWorkflowNotification in plone_workflow with Manager proxy:
<snip>
## Script (Python) "proxy_sendWorkflowNotification"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=object,old_state,new_state,comment
##title=send an email to recipients.
##
portal = context.portal_url.getPortalObject()
mtool = context.portal_membership
member = mtool.getAuthenticatedMember()
member_id = member.getId()
emails = getattr(object, 'notification_recipients')
object_title = object.title_or_id()
object_url = object.absolute_url()
for email in emails:
variables = {'send_to_address' : email,
'send_from_address' : portal.getProperty('email_from_address'),
'title' : 'Workflow modification on "%s" plone site - object "%s" is now "%s"' % (portal.Title(), object_title, new_state),
'object_title' : object_title,
'old_state' : old_state,
'new_state' : new_state,
'object_url' : object_url,
'comments' : comment}
mail_text = context.workflow_notif_mail_template(context, **variables)
host = context.MailHost
host.send(mail_text)
return
</snip>