"""Object editing testing module"""
import sys
from unittest import TestSuite, makeSuite
from zope.annotation.interfaces import IAnnotations
from AccessControl.SecurityManager import setSecurityPolicy
from AccessControl import ZopeGuards
from AccessControl.ZopeGuards import guarded_getattr, get_safe_globals
from AccessControl.ImplPython import ZopeSecurityPolicy
from AccessControl import Unauthorized
from Acquisition import aq_base
from Testing.ZopeTestCase import user_name
# Restricted Python imports
from RestrictedPython import compile_restricted
from RestrictedPython.Guards import safe_builtins
from RestrictedPython.SafeMapping import SafeMapping
from base import eduCommonsTestCase
class TestEditing(eduCommonsTestCase):
"""Test object editing for different roles and workflow states"""
def afterSetUp(self):
self.catalog = self.portal.portal_catalog
self.workflow = self.portal.portal_workflow
self.membership = self.portal.portal_membership
setSecurityPolicy(ZopeSecurityPolicy(verbose=True))
# We need to manually register the roles from the rolemap with
# the PAS plugin.
self.portal.acl_users.portal_role_manager.addRole('Producer')
self.membership.addMember('producer', 'secret',
['Producer', 'Member',], [])
self.membership.addMember('member', 'secret',
['Member',], [])
self.loginAsPortalOwner()
self.portal.invokeFactory('Division', 'division')
self.portal.division.invokeFactory('Course', 'course')
self.division = self.portal.division
self.course = self.division.course
self.logout()
def beforeTearDown(self):
self.loginAsPortalOwner()
self.portal.manage_delObjects([self.division.id])
self.logout()
def execUntrusted(self, func, *args, **kwargs):
"""Set up a Python environment with Zope security in place"""
globals = get_safe_globals()
globals['__builtins__'] = safe_builtins
globals['_getattr_'] = guarded_getattr
data = {'func' : func,
'args' : ZopeGuards.SafeIter(args),
'kwargs' : kwargs
}
globals.update(data)
body = """func(*args, **kwargs)"""
code = compile_restricted(body, "<string>", "eval")
eval(code, globals)
def assertUnauthorized(self, func, *args, **kwargs):
"""Check that calling func with currently effective roles will
raise Unauthroized.
"""
try:
self.execUntrusted(func, *args, **kwargs)
except Unauthorized, e:
return
raise AssertionError, 'Unauthorized exception was expected'
def assertAuthorized(self, func, *args, **kwargs):
"""Check that calling func with currently effective roles will
not raise Unauthroized.
"""
try:
self.execUntrusted(func, *args, **kwargs)
except Unauthorized, e:
raise AssertionError, 'Unauthorized exception was not expected'
def check_course_edit(self, obj):
# XXX: this doesn't look good enough. Shouldn't the edit method
# raise an Unauthorized exception by itself?
if self.membership.checkPermission('Modify portal content', obj):
obj.edit(text='test Text')
else:
raise Unauthorized
def test_producer_can_edit_inprogress_course(self):
self.login('producer')
self.assertAuthorized(self.check_course_edit, self.course)
self.logout()
def test_producer_cannot_edit_qa_course(self):
self.loginAsPortalOwner()
self.workflow.doActionFor(self.course, 'submit')
self.assertEqual(
self.workflow.getInfoFor(self.course, 'review_state'), 'QA')
self.logout()
self.login('producer')
self.assertUnauthorized(self.check_course_edit, self.course)
self.logout()
def test_suite():
from unittest import TestSuite, makeSuite
suite = TestSuite()
suite.addTest(makeSuite(TestEditing))
return suite
Some of the helper methods are based on code from this blog post.
