def setUp(self):
        super(Test, self).setUp()

        component.provideUtility(Permission(P1), IPermission, P1)
        component.provideUtility(Permission(P2), IPermission, P2)

        class B(object):
            def m1(self):
                return "m1"

            def m2(self):
                return "m2"

        class C(B):
            implements(I)

            def m3(self):
                return "m3"

            def m4(self):
                return "m4"

        TestModule.test_base = B
        TestModule.test_class = C
        TestModule.test_instance = C()
        self.assertState()
Exemple #2
0
class IRedefinePermission(Interface):
    """Define a permission to replace another permission."""

    from_ = Permission(title=u"Original permission",
                       description=u"Original permission ID to redefine.",
                       required=True)

    to = Permission(title=u"Substituted permission",
                    description=u"Substituted permission ID.",
                    required=True)
Exemple #3
0
    def test_subclass(self):

        # Mock schema model
        class ITestSchema(Interface):
            test = zope.schema.TextLine(title=u"Test")

        ITestSchema.setTaggedValue(READ_PERMISSIONS_KEY,
                                   dict(test='zope2.View', foo='foo.View'))

        class Foo(Item):
            pass

        # Mock FTI
        fti_mock = self.mocker.mock(DexterityFTI)
        self.expect(fti_mock.lookupSchema()).result(ITestSchema)
        self.expect(fti_mock.lookupSchema()).result(ITestSchema)
        self.expect(fti_mock.lookupSchema()).result(ITestSchema)

        self.mock_utility(fti_mock, IDexterityFTI, u'testtype')

        # Mock permissions
        self.mock_utility(Permission(u'zope2.View', u"View"), IPermission,
                          u'zope2.View')
        self.mock_utility(Permission(u'foo.View', u"View foo"), IPermission,
                          u'foo.View')

        # Content item
        item = Foo('test')
        item.portal_type = u"testtype"
        item.test = u"foo"
        item.foo = u"bar"

        # Check permission
        securityManager_mock = self.mocker.mock()
        self.expect(securityManager_mock.checkPermission("View",
                                                         item)).result(False)
        self.expect(securityManager_mock.checkPermission("View foo",
                                                         item)).result(True)
        getSecurityManager_mock = self.mocker.replace(
            'AccessControl.getSecurityManager')
        self.expect(
            getSecurityManager_mock()).result(securityManager_mock).count(2)

        self.mocker.replay()

        self.assertFalse(
            item.__allow_access_to_unprotected_subobjects__('test', u"foo"))
        self.assertTrue(
            item.__allow_access_to_unprotected_subobjects__('foo', u"bar"))

        # Unknown attributes are allowed
        self.assertTrue(
            item.__allow_access_to_unprotected_subobjects__(
                'random', u"stuff"))
Exemple #4
0
class IRedefinePermission(Interface):
    """Define a permission to replace another permission."""

    from_ = Permission(
        title=_u("Original permission"),
        description=_u("Original permission id to redefine."),
        required=True)

    to = Permission(
        title=_u("Substituted permission"),
        description=_u("Substituted permission id."),
        required=True)
Exemple #5
0
    def testProtectedPageViews(self):
        component.provideUtility(Permission('p', 'P'), IPermission, 'p')

        request = TestRequest()
        self.assertEqual(
            component.queryMultiAdapter((ob, request), name='test'), None)

        xmlconfig(
            StringIO(template % u'''
            <include package="zope.security" file="meta.zcml" />

            <permission id="zope.TestPermission" title="Test permission" />

            <browser:pages
                class="zope.browserpage.tests.test_page.V1"
                for="zope.browserpage.tests.test_page.IC"
                permission="zope.TestPermission"
                >

              <browser:page name="index.html" attribute="index" />
              <browser:page name="action.html" attribute="action" />
            </browser:pages>
            '''))

        v = component.getMultiAdapter((ob, request), name='index.html')
        v = ProxyFactory(v)
        zope.security.management.getInteraction().add(request)
        self.assertRaises(Exception, v)
        v = component.getMultiAdapter((ob, request), name='action.html')
        v = ProxyFactory(v)
        self.assertRaises(Exception, v)
Exemple #6
0
    def after(self):
        permission = Permission(self.id, self.title, self.description)
        utility(self.context, IPermission, permission, name=self.id)

        zope2_permission = str(self.title)
        if self.roles:
            addPermission(zope2_permission, default_roles=tuple(self.roles))
        else:
            addPermission(zope2_permission)
Exemple #7
0
def zcml_transition_permission(pid, title, roles):
    ZCML_LINES.append(ZCML_INDENT)
    ZCML_LINES.append('%s<permission id="%s" title="%s" />' % (
        ZCML_INDENT, pid, title))
    provideUtility(Permission(pid), IPermission, pid)
    for role in roles:
        ZCML_LINES.append(
            '%s<grant permission="%s" role="%s" />' % (ZCML_INDENT, pid, role))
        rpm.grantPermissionToRole(pid, role, check=False)
Exemple #8
0
    def testAllRolePermissionsFormForLocalPermissions(self):
        permission = Permission(u"id", u"Local Permission")
        zope.component.provideUtility(permission, IPermission)
        self.testAllRolePermissions()

        response = self.publish(
            '/++etc++site/@@AllRolePermissions.html',
            basic='mgr:mgrpw')
        body = response.getBody()
        self.assert_('Local Permission' in body)
Exemple #9
0
    def setUp(self):

        # On Zope 2.10, the default is True, on 2.12 it's False
        self.defaultWrap = plone.directives.form.meta.DEFAULT_WRAP
        plone.directives.form.meta.DEFAULT_WRAP = False

        grokcore.component.testing.grok('grokcore.component.meta')
        grokcore.component.testing.grok('grokcore.security.meta')
        grokcore.component.testing.grok('grokcore.view.meta.templates')
        grokcore.component.testing.grok('grokcore.view.meta.views')
        grokcore.component.testing.grok('grokcore.view.meta.skin')
        grokcore.component.testing.grok('five.grok.meta')
        grokcore.component.testing.grok('plone.directives.form.meta')

        grokcore.component.testing.grok('grokcore.view.templatereg')

        provideUtility(Permission('zope2.View'), name='zope2.View')
        provideUtility(Permission('cmf.ModifyPortalContent'),
                       name='cmf.ModifyPortalContent')
        provideUtility(Permission('cmf.AddPortalContent'),
                       name='cmf.AddPortalContent')
def addCheckerPublic():
    """Add the CheckerPublic permission as 'zope.Public'"""

    perm = Permission(
        'zope.Public', 'Public',
        """Special permission used for resources that are always public

            The public permission is effectively an optimization, sine
            it allows security computation to be bypassed.
            """)
    gsm = component.getGlobalSiteManager()
    gsm.registerUtility(perm, interfaces.IPermission, perm.id)
Exemple #11
0
    def grok(self, name, module, context, module_info, templates):
        permissions = module_info.getAnnotation('grok.define_permission', [])
        for permission in permissions:
            # IPermission.title says that permission ids (and titles,
            # descriptions) *must* be unicode objects.  Good news is
            # that the directive handler already made sure we either
            # got pure ASCII or unicode here:
            permission = unicode(permission)
            # TODO permission title and description
            component.provideUtility(Permission(permission, title=permission),
                                     name=permission)

        return True
Exemple #12
0
    def setUp(self):
        from zope.security.permission import Permission
        provideUtility(Permission('foo', u'foo', u''), name=u'foo')

        class DummySecurityManager(object):
            checks = []

            def checkPermission(self, perm, context):
                self.checks.append(perm)
                return False

        self.secman = DummySecurityManager()
        setSecurityManager(self.secman)
Exemple #13
0
 def grok(self, name, factory, context, module_info, templates):
     permission_name = util.class_annotation(factory, 'grok.name', None)
     if permission_name is None:
         raise GrokError(
             "A permission needs to have a dotted name for its id. Use "
             "grok.name to specify one.", factory)
     permission_name = unicode(permission_name)
     title = unicode(
         util.class_annotation(factory, 'grok.title', permission_name))
     # TODO permission description
     component.provideUtility(Permission(permission_name, title=title),
                              name=permission_name)
     return True
Exemple #14
0
    def add_retract_transitions(wf):
        def getRoles(transition):
            original_roles = transition.user_data.get("_roles", [])
            allowed_roles = set()
            #transitions to  source
            tx_to_source = wf.get_transitions_to(transition.source)
            for tx in tx_to_source:
                if tx.source is None:
                    allowed_roles.update(set(original_roles))
                else:
                    for role in tx.user_data.get("_roles", []):
                        if role in original_roles:
                            allowed_roles.add(role)
            if not len(allowed_roles):
                allowed_roles = original_roles
            return allowed_roles

        transitions = wf._transitions_by_id.values()
        terminal_transitions = [
            transition for transition in transitions
            if (wf.get_transitions_from(transition.destination) == [] and
                transition.source and transition.trigger in [MANUAL, SYSTEM])
        ]
        for transition in terminal_transitions:
            roles = getRoles(transition)
            if roles:
                title = _("revert_transition_title",
                          default="Undo - ${title}",
                          mapping={
                              "title":
                              translate(transition.title, domain="bungeni")
                          })
                title = "Undo - %s" % transition.title
                tid = "%s.%s" % (transition.destination, transition.source)
                pid = "bungeni.%s.wf.%s" % (wf.name, tid)
                ntransition = Transition(title,
                                         transition.destination,
                                         transition.source,
                                         trigger=MANUAL,
                                         condition=allow_retract,
                                         permission=pid,
                                         condition_args=True,
                                         roles=roles)
                if ntransition.id in wf._transitions_by_id:
                    continue
                log.debug("adding transition %s", ntransition.id)
                provideUtility(Permission(pid), IPermission, pid)
                for role in roles:
                    role_perm_mgr.grantPermissionToRole(pid, role, check=False)
                transitions.append(ntransition)
        wf.refresh(wf._states_by_id.values(), transitions)
    def testInherited(self):

        class B1(object):
            def g(self): return 'B1.g'

        class B2(object):
            def h(self): return 'B2.h'

        class S(B1, B2):
            pass

        component.provideUtility(Permission('B1', ''), IPermission, 'B1')
        component.provideUtility(Permission('S', ''), IPermission, 'S')
        protectName(B1, 'g', 'B1')
        protectName(S, 'g', 'S')
        protectName(S, 'h', 'S')

        self.assertEqual(selectChecker(B1()).permission_id('g'), 'B1')
        self.assertEqual(selectChecker(B2()).permission_id('h'), None)
        self.assertEqual(selectChecker(S()).permission_id('g'), 'S')
        self.assertEqual(selectChecker(S()).permission_id('h'), 'S')

        self.assertEqual(S().g(), 'B1.g')
        self.assertEqual(S().h(), 'B2.h')
Exemple #16
0
    def testRolesWithPermissionsFormForLocalPermission(self):
        permission = Permission(u"id", u"Local Permission")
        zope.component.provideUtility(permission, IPermission, 'id')

        response = self.publish(
            '/++etc++site/@@AllRolePermissions.html',
            form={'role_id': 'zope.Manager',
                  'Allow': ['id'],
                  'Deny': ['id'],
                  'SUBMIT_ROLE': 'Save Changes'},
            basic='mgr:mgrpw',
            handle_errors=True)
        body = response.getBody()
        self.assert_('You choose both allow and deny for permission'
            ' "Local Permission". This is not allowed.' in body)
    def test_no_read_permission(self):

        # Mock schema model
        class ITestSchema(Interface):
            test = zope.schema.TextLine(title='Test')

        ITestSchema.setTaggedValue(READ_PERMISSIONS_KEY, dict(foo='foo.View'))

        # Mock FTI
        fti_mock = self.mocker.proxy(DexterityFTI('testtype'))
        self.expect(fti_mock.lookupSchema()).result(ITestSchema)
        self.expect(fti_mock.behaviors).result(tuple())

        self.mock_utility(fti_mock, IDexterityFTI, 'testtype')

        # Mock permissions
        self.mock_utility(Permission('foo.View', u'View foo'), IPermission,
                          u'foo.View')

        # Content item
        item = Item('test')
        item.portal_type = 'testtype'
        item.test = 'foo'
        item.foo = 'bar'

        # Check permission
        securityManager_mock = self.mocker.mock()
        self.expect(securityManager_mock.checkPermission('View foo',
                                                         item)).result(True)
        getSecurityManager_mock = self.mocker.replace(
            'zopepolicy.ZopeSecurityPolicy.getSecurityManager')
        self.expect(
            getSecurityManager_mock()).result(securityManager_mock).count(1)

        self.mocker.replay()

        SCHEMA_CACHE.clear()

        self.assertTrue(
            item.__allow_access_to_unprotected_subobjects__('test', 'foo'))
        self.assertTrue(
            item.__allow_access_to_unprotected_subobjects__('foo', 'bar'))

        # Unknown attributes are allowed
        self.assertTrue(
            item.__allow_access_to_unprotected_subobjects__('random', 'stuff'))
    def test_no_read_permission(self):

        # Mock schema model
        class ITestSchema(Interface):
            test = zope.schema.TextLine(title=u"Test")

        ITestSchema.setTaggedValue(READ_PERMISSIONS_KEY, dict(foo='foo.View'))

        # Mock FTI
        fti_mock = DexterityFTI(u"testtype")
        fti_mock.lookupSchema = Mock(return_value=ITestSchema)
        fti_mock.behaviors = ()

        self.mock_utility(fti_mock, IDexterityFTI, u'testtype')

        # Mock permissions
        self.mock_utility(Permission(u'foo.View', u"View foo"), IPermission,
                          u'foo.View')

        # Content item
        item = Item('test')
        item.portal_type = u"testtype"
        item.test = u"foo"
        item.foo = u"bar"

        # Check permission
        security_manager_mock = Mock()
        security_manager_mock.checkPermission = Mock(return_value=True)
        from AccessControl import getSecurityManager
        self.patch_global(getSecurityManager,
                          return_value=security_manager_mock)

        SCHEMA_CACHE.clear()

        self.assertTrue(
            item.__allow_access_to_unprotected_subobjects__('test', u"foo"))
        self.assertTrue(
            item.__allow_access_to_unprotected_subobjects__('foo', u"bar"))

        # Unknown attributes are allowed
        self.assertTrue(
            item.__allow_access_to_unprotected_subobjects__(
                'random', u"stuff"))
Exemple #19
0
def permission(_context, id, title, description=u''):
    from zope.security.interfaces import IPermission
    from zope.security.permission import Permission
    from zope.component.zcml import utility
    permission = Permission(id, title, description)
    utility(_context, IPermission, permission, name=id)
Exemple #20
0
def _load(workflow_name, workflow):
    """ (workflow_name:str, workflow:etree_doc) -> Workflow
    """
    workflow_title = xas(workflow, "title")
    naming.MSGIDS.add(workflow_title)
    workflow_description = xas(workflow, "description")
    naming.MSGIDS.add(workflow_description)
    transitions = []
    states = []
    note = xas(workflow, "note")
    
    # initial_state, in XML indicated with a transition.@source=""
    initial_state = None
    
    ZCML_PROCESSED = bool(workflow_name in ZCML_WORKFLOWS_PROCESSED)
    if not ZCML_PROCESSED:
        ZCML_WORKFLOWS_PROCESSED.add(workflow_name)
        ZCML_LINES.append(ZCML_INDENT)
        ZCML_LINES.append(ZCML_INDENT)
        ZCML_LINES.append("%s<!-- %s -->" % (ZCML_INDENT, workflow_name))
    
    def validate_id(id, tag):
        """Ensure that ID values are unique within the same XML doc scope.
        """
        m = "Invalid element <%s> id=%r in workflow %r" % (tag, id, workflow_name)
        assert id not in validate_id.wuids, "%s -- id not unique in workflow document" % (m)
        validate_id.wuids.add(id)
    validate_id.wuids = set() # unique IDs in this XML workflow file
    
    def get_from_state(state_id):
        if state_id is None:
            return
        for state in states:
            if state.id == state_id:
                return state
        raise ValueError("Invalid value: permissions_from_state=%r" % (state_id))
    
    def check_not_global_grant(pid, role):
        # ensure global and local assignments are distinct
        # (global: global_pid_roles, workflow_name)
        global_proles = global_pid_roles.get(pid, "")
        assert role not in global_proles, ("Workflow [%s] may not mix "
            "global and local granting of a same permission [%s] to a "
            "same role [%s].") % (workflow_name, pid, role)
    
    # permission_actions -> permissions for this type
    for (key, permission_action) in capi.schema.qualified_permission_actions(
            workflow_name, xas(workflow, "permission_actions", "").split()
        ):
        pid = "bungeni.%s.%s" % (key, permission_action)
        title = "%s %s" % (
            permission_action, naming.split_camel(naming.model_name(key)))
        # !+ add to a Workflow.defines_permissions list
        ZCML_LINES.append(
            '%s<permission id="%s" title="%s" />' % (ZCML_INDENT, pid, title))
        provideUtility(Permission(pid), IPermission, pid)
    
    # global grants
    global_pid_roles = {} # {pid: [role]}
    global_grants = get_permissions_from_allows(workflow_name, workflow)
    for (setting, pid, role) in global_grants:
        # for each global permission, build list of roles it is set to
        global_pid_roles.setdefault(pid, []).append(role)
        assert setting and pid and role, \
            "Global grant must specify valid permission/role" #!+RNC
        # !+ add to a Workflow.global_grants list
        ZCML_LINES.append(
            '%s<grant permission="%s" role="%s" />' % (ZCML_INDENT, pid, role))
        # no real need to check that the permission and role of a global grant 
        # are properly registered in the system -- an error should be raised 
        # by the zcml if either is not defined.
        rpm.grantPermissionToRole(pid, role, check=False)

    for perm, roles in global_pid_roles.items():
        # assert roles mix limitations for state permissions
        assert_distinct_permission_scopes(perm, roles, workflow_name, "global grants")
    
    # all workflow features (enabled AND disabled)
    workflow_features = load_features(workflow_name, workflow)
    enabled_feature_names = [None] + [ 
        f.name for f in workflow_features if f.enabled ]
    # !+EVENT_FEATURE_TYPES add each as enabled_feature_names, or extend the 
    # facet quailifer by feature_name(sub_type_key).facet_ref?
    # workflow facets
    workflow_facets = load_facets(workflow_name, workflow)
    
    # states
    for s in workflow.iterchildren("state"):
        # @id
        state_id = xas(s, "id")
        assert state_id, "Workflow State must define @id" #!+RNC
        validate_id(state_id, "state")
        
        # @actions - transition-to-state actions
        state_actions = []
        for action_name in xas(s, "actions", "").split():
            state_actions.append(capi.get_workflow_action(action_name))
        
        # @permissions_from_state
        permissions = [] # [ tuple(bool:int, permission:str, role:str) ]
        # state.@permissions_from_state : to reduce repetition and enhance 
        # maintainibility of workflow XML files, a state may inherit ALL 
        # permissions defined by the specified state. NO other permissions 
        # may be specified by this state. 
        from_state = get_from_state(xas(s, "permissions_from_state"))
        parent_permissions = xab(s, "parent_permissions")
        if parent_permissions:
            pass # no own permission definitions allowed
        elif from_state:
            # assimilate (no more no less) the state's permissions !+tuple, use same?
            permissions[:] = from_state.permissions
        else:
            used_facets_fq = resolve_state_facets(
                workflow_name, workflow_facets, enabled_feature_names, s)
            # assimilate permissions from facets from None and all enabled features
            def add_facet_permissions(facet):
                for perm in facet.permissions:
                    check_add_assign_permission(workflow_name, permissions, perm)
                    check_not_global_grant(perm[1], perm[2])
            for (feature_name, qtk) in used_facets_fq:
                # debug check that feature is enabled
                assert feature_name in enabled_feature_names
                facet = used_facets_fq[(feature_name, qtk)]
                if facet is not None:
                    add_facet_permissions(facet)
        
        # states
        state_title = xas(s, "title")
        naming.MSGIDS.add(state_title)
        states.append(
            State(state_id, state_title,
                xas(s, "note"),
                state_actions, permissions,
                parent_permissions,
                xab(s, "obsolete"),
            )
        )
    
    STATE_IDS = [ s.id for s in states ]
    
    # transitions
    for t in workflow.iterchildren("transition"):
        title = xas(t, "title")
        naming.MSGIDS.add(title)
        # sources, empty string -> initial_state
        sources = t.get("source").split() or [initial_state]
        assert len(sources) == len(set(sources)), \
            "Transition contains duplicate sources [%s]" % (sources)
        for source in sources:
            if source is not initial_state:
                assert source in STATE_IDS, \
                    "Unknown transition source state [%s]" % (source)
        # destination must be a valid state
        destination = t.get("destination")
        assert destination in STATE_IDS, \
            "Unknown transition destination state [%s]" % (destination)
        
        # optionals -- only set on kw IFF explicitly defined
        kw = {}
        for i in TRANS_ATTRS_OPTIONALS:
            val = xas(t, i)
            if not val:
                # we let setting of defaults be handled downstream
                continue
            kw[i] = val
        
        # data up-typing
        #
        # trigger
        if "trigger" in kw:
            kw["trigger"] = trigger_value_map[kw["trigger"]]
        # roles -> permission - one-to-one per transition
        roles = capi.schema.qualified_roles(kw.pop("roles", ""))
        if not is_zcml_permissionable(t):
            assert not roles, "Workflow [%s] - non-permissionable transition " \
                "does not allow @roles [%s]." % (workflow_name, roles) #!+RNC
            kw["permission"] = None # None -> CheckerPublic
        # !+CAN_EDIT_AS_DEFAULT_TRANSITION_PERMISSION(mr, oct-2011) this feature
        # is functional (uncomment following elif clause) but as yet not enabled. 
        #
        # Advantage would be that it would be easier to keep transitions 
        # permissions in sync with object permissions (set in state) as the 
        # majority of transition require exactly this as privilege; for the 
        # occassional transition needing a different privilege, the current 
        # transition.@roles mechanism may be used to make this explicit. 
        #
        # Need to consider implications further; the zope_principal_role_map db 
        # table, that caches contextual roles for principals, should probably 
        # first be reworked to be db-less (as for zope_role_permission_map).
        #
        #elif not roles:
        #    # then as fallback transition permission use can modify object
        #    kw["permission"] = "bungeni.%s.Edit" % (workflow_name) # fallback permission
        else:
            # Dedicated permission for XML multi-source transition.
            # Given that, irrespective of how sources are grouped into 
            # multi-source XML <transition> elements, there may be only *one* 
            # path from any given *source* to any given *destination* state, 
            # it suffices to use only the first source element + the destination 
            # to guarantee a unique identifier for an XML transition element.
            #
            # Note: the "-" char is not allowed within a permission id 
            # (so we use "." also here).
            #
            tid = "%s.%s" % (sources[0] or "", destination)
            pid = "bungeni.%s.wf.%s" % (workflow_name, tid)
            if not ZCML_PROCESSED:
                zcml_transition_permission(pid, title, roles)
                # remember list of roles from xml
                kw["_roles"] = roles
            kw["permission"] = pid
        # python resolvables
        if "condition" in kw:
            kw["condition"] = capi.get_workflow_condition(kw["condition"])
        # numeric
        if "order" in kw:
            kw["order"] = float(kw["order"]) # ValueError if not numeric
        # bool
        if "require_confirmation" in kw:
            try:
                kw["require_confirmation"] = misc.as_bool(kw["require_confirmation"])
                assert kw["require_confirmation"] is not None #!+RNC
            except:
                raise ValueError("Invalid transition value "
                    '[require_confirmation="%s"]' % (
                        t.get("require_confirmation")))
        # multiple-source transitions are really multiple "transition paths"
        for source in sources:
            args = (title, source, destination)
            transitions.append(Transition(*args, **kw))
            log.debug("[%s] adding transition [%s-%s] [%s]" % (
                workflow_name, source or "", destination, kw))
    
    return Workflow(workflow_name,
        workflow_features, workflow_facets, states, transitions, global_grants,
        workflow_title, workflow_description, note)
Exemple #21
0
    def test_item(self):

        # Mock schema model
        class ITestSchema(Interface):
            test = zope.schema.TextLine(title=u"Test")

        ITestSchema.setTaggedValue(READ_PERMISSIONS_KEY,
                                   dict(test='zope2.View', foo='foo.View'))

        from plone.autoform.interfaces import IFormFieldProvider

        @provider(IFormFieldProvider)
        class ITestBehavior(Interface):
            test2 = zope.schema.TextLine(title=u"Test")

        ITestBehavior.setTaggedValue(READ_PERMISSIONS_KEY,
                                     dict(test2='zope2.View', foo2='foo.View'))

        # Mock a test behavior
        from plone.behavior.registration import BehaviorRegistration
        registration = BehaviorRegistration(
            title=u"Test Behavior",
            description=u"Provides test behavior",
            interface=ITestBehavior,
            marker=Interface,
            factory=None)
        from plone.behavior.interfaces import IBehavior
        self.mock_utility(registration, IBehavior,
                          ITestBehavior.__identifier__)
        from plone.dexterity.behavior import DexterityBehaviorAssignable
        from plone.dexterity.interfaces import IDexterityContent
        from plone.behavior.interfaces import IBehaviorAssignable
        self.mock_adapter(DexterityBehaviorAssignable, IBehaviorAssignable,
                          (IDexterityContent, ))

        # Mock FTI
        fti_mock = self.mocker.proxy(DexterityFTI(u"testtype"))
        self.mock_utility(fti_mock, IDexterityFTI, u'testtype')

        # Mock permissions
        self.mock_utility(Permission(u'zope2.View', u"View"), IPermission,
                          u'zope2.View')
        self.mock_utility(Permission(u'foo.View', u"View foo"), IPermission,
                          u'foo.View')

        # Content item
        item = Item('test')
        item.portal_type = u"testtype"
        item.test = u"foo"
        item.foo = u"bar"

        # mock security manager
        securityManager_mock = self.mocker.mock()
        getSecurityManager_mock = self.mocker.replace(
            'AccessControl.getSecurityManager')

        # expectations
        # run 1
        # lookupSchema is always called twice: cache and __providedBy__
        self.expect(fti_mock.lookupSchema()).result(ITestSchema)
        self.expect(fti_mock.behaviors).result(tuple())
        self.expect(securityManager_mock.checkPermission("View",
                                                         item)).result(False)

        # run 2
        self.expect(fti_mock.lookupSchema()).result(ITestSchema)
        self.expect(fti_mock.behaviors).result(tuple())
        self.expect(securityManager_mock.checkPermission("View foo",
                                                         item)).result(True)

        # run 3
        self.expect(fti_mock.lookupSchema()).result(ITestSchema)
        self.expect(fti_mock.behaviors).result(tuple())

        # # run 4
        self.expect(fti_mock.lookupSchema()).result(ITestSchema)
        self.expect(fti_mock.behaviors).result([ITestBehavior.__identifier__])
        self.expect(securityManager_mock.checkPermission("View",
                                                         item)).result(True)

        # # run 5
        self.expect(fti_mock.lookupSchema()).result(None)
        self.expect(fti_mock.behaviors).result([ITestBehavior.__identifier__])
        self.expect(securityManager_mock.checkPermission("View",
                                                         item)).result(True)

        # for all 5 runs
        self.expect(
            getSecurityManager_mock()).result(securityManager_mock).count(4)

        self.mocker.replay()

        # run 1: schema and no behavior access to schema protected attribute
        SCHEMA_CACHE.clear()
        self.assertFalse(
            item.__allow_access_to_unprotected_subobjects__('test', u"foo"))

        # # run 2: schema and no behavior access to known non schema attribute
        SCHEMA_CACHE.clear()
        self.assertTrue(
            item.__allow_access_to_unprotected_subobjects__('foo', u"bar"))

        # # run 3: schema and no behavior, unknown attributes are allowed
        SCHEMA_CACHE.clear()
        self.assertTrue(
            item.__allow_access_to_unprotected_subobjects__(
                'random', u"stuff"))

        # # run 4: schema and behavior
        SCHEMA_CACHE.clear()
        self.assertTrue(
            item.__allow_access_to_unprotected_subobjects__('test2', u"foo2"))

        # run 5: no schema but behavior
        SCHEMA_CACHE.clear()
        self.assertTrue(
            item.__allow_access_to_unprotected_subobjects__('test2', u"foo2"))
Exemple #22
0
 def setUp(self):
     super(TestFormDirectives, self).setUp()
     self.mock_utility(
         Permission(u'cmf.AddPortalContent', u"Add portal content"),
         IPermission, u'cmf.AddPortalContent')
     grok('plone.directives.dexterity.form')
    def test_item(self):

        # Mock schema model
        class ITestSchema(Interface):
            test = zope.schema.TextLine(title=u"Test")

        ITestSchema.setTaggedValue(READ_PERMISSIONS_KEY,
                                   dict(test='zope2.View', foo='foo.View'))

        from plone.autoform.interfaces import IFormFieldProvider

        @provider(IFormFieldProvider)
        class ITestBehavior(Interface):
            test2 = zope.schema.TextLine(title=u"Test")

        ITestBehavior.setTaggedValue(READ_PERMISSIONS_KEY,
                                     dict(test2='zope2.View', foo2='foo.View'))

        # Mock a test behavior
        from plone.behavior.registration import BehaviorRegistration
        registration = BehaviorRegistration(
            title=u"Test Behavior",
            description=u"Provides test behavior",
            interface=ITestBehavior,
            marker=Interface,
            factory=None)
        from plone.behavior.interfaces import IBehavior
        self.mock_utility(registration, IBehavior,
                          ITestBehavior.__identifier__)
        from plone.dexterity.behavior import DexterityBehaviorAssignable
        from plone.dexterity.interfaces import IDexterityContent
        from plone.behavior.interfaces import IBehaviorAssignable
        self.mock_adapter(DexterityBehaviorAssignable, IBehaviorAssignable,
                          (IDexterityContent, ))

        # Mock FTI
        fti_mock = DexterityFTI(u"testtype")
        fti_mock.behaviors = ()
        fti_mock.lookupSchema = Mock(return_value=ITestSchema)
        self.mock_utility(fti_mock, IDexterityFTI, u'testtype')

        # Mock permissions
        self.mock_utility(Permission(u'zope2.View', u"View"), IPermission,
                          u'zope2.View')
        self.mock_utility(Permission(u'foo.View', u"View foo"), IPermission,
                          u'foo.View')

        # Content item
        item = Item('test')
        item.portal_type = u"testtype"
        item.test = u"foo"
        item.foo = u"bar"

        # mock security manager
        security_manager_mock = Mock()
        from AccessControl import getSecurityManager
        self.patch_global(getSecurityManager,
                          return_value=security_manager_mock)

        # run 1: schema and no behavior access to schema protected attribute
        security_manager_mock.checkPermission = Mock(return_value=False)
        SCHEMA_CACHE.clear()
        self.assertFalse(
            item.__allow_access_to_unprotected_subobjects__('test', u"foo"))
        security_manager_mock.checkPermission.assert_called_with('View', item)

        # run 2: schema and no behavior access to known non schema attribute
        security_manager_mock.checkPermission = Mock(return_value=True)
        SCHEMA_CACHE.clear()
        self.assertTrue(
            item.__allow_access_to_unprotected_subobjects__('foo', u"bar"))
        security_manager_mock.checkPermission.assert_called_with(
            'View foo', item)

        # run 3: schema and no behavior, unknown attributes are allowed
        SCHEMA_CACHE.clear()
        self.assertTrue(
            item.__allow_access_to_unprotected_subobjects__(
                'random', u"stuff"))

        # run 4: schema and behavior
        security_manager_mock.checkPermission = Mock(return_value=True)
        fti_mock.behaviors = [ITestBehavior.__identifier__]
        SCHEMA_CACHE.clear()
        self.assertTrue(
            item.__allow_access_to_unprotected_subobjects__('test2', u"foo2"))
        security_manager_mock.checkPermission.assert_called_with('View', item)

        # run 5: no schema but behavior
        security_manager_mock.checkPermission = Mock(return_value=True)
        fti_mock.lookupSchema = Mock(return_value=None)
        SCHEMA_CACHE.clear()
        self.assertTrue(
            item.__allow_access_to_unprotected_subobjects__('test2', u"foo2"))
        security_manager_mock.checkPermission.assert_called_with('View', item)