def test_authorize_func(self):
        def f(ctx, identity, op):
            self.assertEqual(identity.id(), 'bob')
            if op.entity == 'a':
                return False, None
            elif op.entity == 'b':
                return True, None
            elif op.entity == 'c':
                return True, [
                    checkers.Caveat(location='somewhere', condition='c')
                ]
            elif op.entity == 'd':
                return True, [
                    checkers.Caveat(location='somewhere', condition='d')
                ]
            else:
                self.fail('unexpected entity: ' + op.Entity)

        ops = [
            macaroonbakery.Op('a', 'x'),
            macaroonbakery.Op('b', 'x'),
            macaroonbakery.Op('c', 'x'),
            macaroonbakery.Op('d', 'x')
        ]
        allowed, caveats = macaroonbakery.AuthorizerFunc(f).authorize(
            checkers.AuthContext(), macaroonbakery.SimpleIdentity('bob'), ops)
        self.assertEqual(allowed, [False, True, True, True])
        self.assertEqual(caveats, [
            checkers.Caveat(location='somewhere', condition='c'),
            checkers.Caveat(location='somewhere', condition='d')
        ])
    def test_context_wired_properly(self):
        ctx = checkers.AuthContext({'a': 'aval'})

        class Visited:
            in_f = False
            in_allow = False
            in_get_acl = False

        def f(ctx, identity, op):
            self.assertEqual(ctx.get('a'), 'aval')
            Visited.in_f = True
            return False, None

        macaroonbakery.AuthorizerFunc(f).authorize(
            ctx, macaroonbakery.SimpleIdentity('bob'), ['op1'])
        self.assertTrue(Visited.in_f)

        class TestIdentity(SimplestIdentity, macaroonbakery.ACLIdentity):
            def allow(other, ctx, acls):
                self.assertEqual(ctx.get('a'), 'aval')
                Visited.in_allow = True
                return False

        def get_acl(ctx, acl):
            self.assertEqual(ctx.get('a'), 'aval')
            Visited.in_get_acl = True
            return []

        macaroonbakery.ACLAuthorizer(allow_public=False,
                                     get_acl=get_acl).authorize(
                                         ctx, TestIdentity('bob'), ['op1'])
        self.assertTrue(Visited.in_get_acl)
        self.assertTrue(Visited.in_allow)
    def test_auth_with_third_party_caveats(self):
        locator = _DischargerLocator()
        ids = _IdService('ids', locator, self)

        # We make an authorizer that requires a third party discharge
        # when authorizing.
        def authorize_with_tp_discharge(ctx, id, op):
            if (id is not None and id.id() == 'bob'
                    and op == macaroonbakery.Op(entity='something',
                                                action='read')):
                return True, [
                    checkers.Caveat(condition='question',
                                    location='other third party')
                ]
            return False, None

        auth = macaroonbakery.AuthorizerFunc(authorize_with_tp_discharge)
        ts = _Service('myservice', auth, ids, locator)

        class _LocalDischargeChecker(macaroonbakery.ThirdPartyCaveatChecker):
            def check_third_party_caveat(_, ctx, info):
                if info.condition != 'question':
                    raise ValueError('third party condition not recognized')
                self._discharges.append(
                    _DischargeRecord(location='other third party',
                                     user=ctx.get(_DISCHARGE_USER_KEY)))
                return []

        locator['other third party'] = _Discharger(
            key=macaroonbakery.generate_key(),
            checker=_LocalDischargeChecker(),
            locator=locator,
        )
        client = _Client(locator)
        ctx = test_context.with_value(_DISCHARGE_USER_KEY, 'bob')
        client.do(ctx, ts,
                  [macaroonbakery.Op(entity='something', action='read')])
        self.assertEqual(self._discharges, [
            _DischargeRecord(location='ids', user='******'),
            _DischargeRecord(location='other third party', user='******')
        ])