Exemple #1
0
    def test_publish_traced_events(self):
        """
        with two subscribers and message tracing the last event should
        have a magic flag
        """
        # we want to trigger a deeply-nested condition in
        # processPublish in class Broker -- lets try w/o refactoring
        # anything first...

        class TestSession(ApplicationSession):
            pass
        session0 = TestSession()
        session1 = TestSession()
        session2 = TestSession()
        router = mock.MagicMock()
        router.send = mock.Mock()
        router.new_correlation_id = lambda: u'fake correlation id'
        router.is_traced = True
        broker = Broker(router, reactor)

        # let's just "cheat" our way a little to the right state by
        # injecting our subscription "directly" (e.g. instead of
        # faking out an entire Subscribe etc. flow
        # ...so we need _subscriptions_map to have at least one
        # subscription (our test one) for the topic we'll publish to
        broker._subscription_map.add_observer(session0, u'test.topic')
        broker._subscription_map.add_observer(session1, u'test.topic')

        session0._session_id = 1000
        session0._transport = mock.MagicMock()
        session0._transport.get_channel_id = mock.MagicMock(return_value=b'deadbeef')

        session1._session_id = 1001
        session1._transport = mock.MagicMock()
        session1._transport.get_channel_id = mock.MagicMock(return_value=b'deadbeef')

        session2._session_id = 1002
        session2._transport = mock.MagicMock()
        session2._transport.get_channel_id = mock.MagicMock(return_value=b'deadbeef')

        # here's the main "cheat"; we're faking out the
        # router.authorize because we need it to callback immediately
        router.authorize = mock.MagicMock(return_value=txaio.create_future_success(dict(allow=True, cache=False, disclose=True)))

        # now we scan call "processPublish" such that we get to the
        # condition we're interested in (this "comes from" session1
        # beacuse by default publishes don't go to the same session)
        pubmsg = message.Publish(123, u'test.topic')
        broker.processPublish(session2, pubmsg)

        # extract all the event calls
        events = [
            call[1][1]
            for call in router.send.mock_calls
            if call[1][0] in [session0, session1, session2]
        ]

        self.assertEqual(2, len(events))
        self.assertFalse(events[0].correlation_is_last)
        self.assertTrue(events[1].correlation_is_last)
    def _unsubscribe(self, subscription):
        """
        Called from :meth:`autobahn.wamp.protocol.Subscription.unsubscribe`
        """
        assert (isinstance(subscription, Subscription))
        assert subscription.active
        assert (subscription.id in self._subscriptions)
        assert (subscription in self._subscriptions[subscription.id])

        if not self._transport:
            raise exception.TransportLost()

        # remove handler subscription and mark as inactive
        self._subscriptions[subscription.id].remove(subscription)
        subscription.active = False

        # number of handler subscriptions left ..
        scount = len(self._subscriptions[subscription.id])

        if scount == 0:
            # if the last handler was removed, unsubscribe from broker ..
            request_id = self._request_id_gen.next()

            on_reply = txaio.create_future()
            self._unsubscribe_reqs[request_id] = UnsubscribeRequest(
                request_id, on_reply, subscription.id)

            msg = message.Unsubscribe(request_id, subscription.id)

            self._transport.send(msg)
            return on_reply
        else:
            # there are still handlers active on the subscription!
            return txaio.create_future_success(scount)
Exemple #3
0
    def test_publish_traced_events(self):
        """
        with two subscribers and message tracing the last event should
        have a magic flag
        """
        # we want to trigger a deeply-nested condition in
        # processPublish in class Broker -- lets try w/o refactoring
        # anything first...

        class TestSession(ApplicationSession):
            pass
        session0 = TestSession()
        session1 = TestSession()
        session2 = TestSession()
        router = mock.MagicMock()
        router.send = mock.Mock()
        router.new_correlation_id = lambda: 'fake correlation id'
        router.is_traced = True
        broker = Broker(router, reactor)

        # let's just "cheat" our way a little to the right state by
        # injecting our subscription "directly" (e.g. instead of
        # faking out an entire Subscribe etc. flow
        # ...so we need _subscriptions_map to have at least one
        # subscription (our test one) for the topic we'll publish to
        broker._subscription_map.add_observer(session0, 'test.topic')
        broker._subscription_map.add_observer(session1, 'test.topic')

        session0._session_id = 1000
        session0._transport = mock.MagicMock()
        session0._transport.get_channel_id = mock.MagicMock(return_value=b'deadbeef')

        session1._session_id = 1001
        session1._transport = mock.MagicMock()
        session1._transport.get_channel_id = mock.MagicMock(return_value=b'deadbeef')

        session2._session_id = 1002
        session2._transport = mock.MagicMock()
        session2._transport.get_channel_id = mock.MagicMock(return_value=b'deadbeef')

        # here's the main "cheat"; we're faking out the
        # router.authorize because we need it to callback immediately
        router.authorize = mock.MagicMock(return_value=txaio.create_future_success(dict(allow=True, cache=False, disclose=True)))

        # now we scan call "processPublish" such that we get to the
        # condition we're interested in (this "comes from" session1
        # beacuse by default publishes don't go to the same session)
        pubmsg = message.Publish(123, 'test.topic')
        broker.processPublish(session2, pubmsg)

        # extract all the event calls
        events = [
            call[1][1]
            for call in router.send.mock_calls
            if call[1][0] in [session0, session1, session2]
        ]

        self.assertEqual(2, len(events))
        self.assertFalse(events[0].correlation_is_last)
        self.assertTrue(events[1].correlation_is_last)
Exemple #4
0
def test_as_future_recursive(framework):
    '''
    Returns another Future from as_future
    '''
    errors = []
    results = []
    calls = []
    f1 = txaio.create_future_success(42)

    def method(*args, **kw):
        calls.append((args, kw))
        return f1
    f0 = txaio.as_future(method, 1, 2, 3, key='word')

    def cb(x):
        results.append(x)

    def errback(f):
        errors.append(f)

    txaio.add_callbacks(f0, cb, errback)

    run_once()

    assert len(results) == 1
    assert len(errors) == 0
    assert results[0] == 42
    assert calls[0] == ((1, 2, 3), dict(key='word'))
    def _unsubscribe(self, subscription):
        """
        Called from :meth:`autobahn.wamp.protocol.Subscription.unsubscribe`
        """
        assert(isinstance(subscription, Subscription))
        assert subscription.active
        assert(subscription.id in self._subscriptions)
        assert(subscription in self._subscriptions[subscription.id])

        if not self._transport:
            raise exception.TransportLost()

        # remove handler subscription and mark as inactive
        self._subscriptions[subscription.id].remove(subscription)
        subscription.active = False

        # number of handler subscriptions left ..
        scount = len(self._subscriptions[subscription.id])

        if scount == 0:
            # if the last handler was removed, unsubscribe from broker ..
            request_id = util.id()

            on_reply = txaio.create_future()
            self._unsubscribe_reqs[request_id] = UnsubscribeRequest(request_id, on_reply, subscription.id)

            msg = message.Unsubscribe(request_id, subscription.id)

            self._transport.send(msg)
            return on_reply
        else:
            # there are still handlers active on the subscription!
            return txaio.create_future_success(scount)
Exemple #6
0
def test_as_future_recursive(framework):
    '''
    Returns another Future from as_future
    '''
    errors = []
    results = []
    calls = []
    f1 = txaio.create_future_success(42)

    def method(*args, **kw):
        calls.append((args, kw))
        return f1

    f0 = txaio.as_future(method, 1, 2, 3, key='word')

    def cb(x):
        results.append(x)

    def errback(f):
        errors.append(f)

    txaio.add_callbacks(f0, cb, errback)

    run_once()

    assert len(results) == 1
    assert len(errors) == 0
    assert results[0] == 42
    assert calls[0] == ((1, 2, 3), dict(key='word'))
Exemple #7
0
 def create_connection(protocol_factory=None, server_hostname=None, host=None, port=None, ssl=False):
     if actual_protocol[0] is None:
         protocol = protocol_factory()
         actual_protocol[0] = protocol
         protocol.connection_made(fake_transport)
         return txaio.create_future_success((fake_transport, protocol))
     else:
         return txaio.create_future_error(RuntimeError("second connection fails completely"))
Exemple #8
0
    def test_publish_closed_session(self):
        """
        ensure a session doesn't get Events if it's closed
        (see also issue #431)
        """

        # we want to trigger a deeply-nested condition in
        # processPublish in class Broker -- lets try w/o refactoring
        # anything first...

        class TestSession(ApplicationSession):
            pass

        session0 = TestSession()
        session1 = TestSession()
        router = mock.MagicMock()
        router.new_correlation_id = lambda: 'fake correlation id'
        broker = Broker(router, reactor)

        # let's just "cheat" our way a little to the right state by
        # injecting our subscription "directly" (e.g. instead of
        # faking out an entire Subscribe etc. flow
        # ...so we need _subscriptions_map to have at least one
        # subscription (our test one) for the topic we'll publish to
        broker._subscription_map.add_observer(session0, 'test.topic')

        # simulate the session state we want, which is that a
        # transport is connected (._transport != None) but there
        # _session_id *is* None (not joined yet, or left already)
        self.assertIs(None, session0._session_id)
        session0._transport = mock.MagicMock()
        session0._transport.transport_details = TransportDetails(
            channel_id={'tls-unique': b'deadbeef'})
        session1._session_id = 1234  # "from" session should look connected + joined
        session1._transport = mock.MagicMock()
        session1._transport.transport_details = TransportDetails(
            channel_id={'tls-unique': b'aaaabeef'})

        # here's the main "cheat"; we're faking out the
        # router.authorize because we need it to callback immediately
        router.authorize = mock.MagicMock(
            return_value=txaio.create_future_success(
                dict(allow=True, cache=False, disclose=True)))

        # now we scan call "processPublish" such that we get to the
        # condition we're interested in (this "comes from" session1
        # beacuse by default publishes don't go to the same session)
        pubmsg = message.Publish(123, 'test.topic')
        broker.processPublish(session1, pubmsg)

        # neither session should have sent anything on its transport
        self.assertEqual(session0._transport.method_calls, [])
        self.assertEqual(session1._transport.method_calls, [])
Exemple #9
0
    def authorize(self, session, uri, action, options):
        """
        Authorizes a session for an action on an URI.

        Implements :func:`autobahn.wamp.interfaces.IRouter.authorize`
        """
        assert (type(uri) == str)
        assert (action in [u'call', u'register', u'publish', u'subscribe'])

        # the role under which the session that wishes to perform the given action on
        # the given URI was authenticated under
        role = session._authrole

        if role in self._roles:
            # the authorizer procedure of the role which we will call ..
            authorize = self._roles[role].authorize
            d = txaio.as_future(authorize, session, uri, action, options)
        else:
            # normally, the role should exist on the router (and hence we should not arrive
            # here), but the role might have been dynamically removed - and anyway, safety first!
            d = txaio.create_future_success(False)

        # XXX would be nicer for dynamic-authorizer authors if we
        # sanity-checked the return-value ('authorization') here
        # (i.e. is it a dict? does it have 'allow' in it? does it have
        # disallowed keys in it?)

        def got_authorization(authorization):
            # backward compatibility
            if isinstance(authorization, bool):
                authorization = {u'allow': authorization, u'cache': False}
                if action in [u'call', u'publish']:
                    authorization[u'disclose'] = False

            auto_disclose_trusted = False
            if auto_disclose_trusted and role == u'trusted' and action in [
                    u'call', u'publish'
            ]:
                authorization[u'disclose'] = True

            self.log.debug(
                "Authorized action '{action}' for URI '{uri}' by session {session_id} with authid '{authid}' and authrole '{authrole}' -> authorization: {authorization}",
                session_id=session._session_id,
                uri=uri,
                action=action,
                authid=session._authid,
                authrole=session._authrole,
                authorization=authorization)

            return authorization

        d.addCallback(got_authorization)
        return d
Exemple #10
0
    def authorize(self, session, uri, action, options):
        """
        Authorizes a session for an action on an URI.

        Implements :func:`autobahn.wamp.interfaces.IRouter.authorize`
        """
        assert(type(uri) == str)
        assert(action in [u'call', u'register', u'publish', u'subscribe'])

        # the role under which the session that wishes to perform the given action on
        # the given URI was authenticated under
        role = session._authrole

        if role in self._roles:
            # the authorizer procedure of the role which we will call ..
            authorize = self._roles[role].authorize
            d = txaio.as_future(authorize, session, uri, action, options)
        else:
            # normally, the role should exist on the router (and hence we should not arrive
            # here), but the role might have been dynamically removed - and anyway, safety first!
            d = txaio.create_future_success(False)

        # XXX would be nicer for dynamic-authorizer authors if we
        # sanity-checked the return-value ('authorization') here
        # (i.e. is it a dict? does it have 'allow' in it? does it have
        # disallowed keys in it?)

        def got_authorization(authorization):
            # backward compatibility
            if isinstance(authorization, bool):
                authorization = {
                    u'allow': authorization,
                    u'cache': False
                }
                if action in [u'call', u'publish']:
                    authorization[u'disclose'] = False

            auto_disclose_trusted = False
            if auto_disclose_trusted and role == u'trusted' and action in [u'call', u'publish']:
                authorization[u'disclose'] = True

            self.log.debug("Authorized action '{action}' for URI '{uri}' by session {session_id} with authid '{authid}' and authrole '{authrole}' -> authorization: {authorization}",
                           session_id=session._session_id,
                           uri=uri,
                           action=action,
                           authid=session._authid,
                           authrole=session._authrole,
                           authorization=authorization)

            return authorization

        d.addCallback(got_authorization)
        return d
Exemple #11
0
def test_immediate_result(framework):
    f = txaio.create_future_success("it worked")
    results = []

    def cb(f):
        results.append(f)
    txaio.add_callbacks(f, cb, None)

    run_once()

    assert len(results) == 1
    assert results[0] == "it worked"
Exemple #12
0
def test_immediate_result(framework):
    f = txaio.create_future_success("it worked")
    results = []

    def cb(f):
        results.append(f)

    txaio.add_callbacks(f, cb, None)

    run_once()

    assert len(results) == 1
    assert results[0] == "it worked"
Exemple #13
0
 def stop(self):
     self._stopping = True
     if self._session and self._session.is_attached():
         return self._session.leave()
     elif self._delay_f:
         # This cancel request will actually call the "error" callback of
         # the _delay_f future. Nothing to worry about.
         return txaio.as_future(txaio.cancel, self._delay_f)
     # if (for some reason -- should we log warning here to figure
     # out if this can evern happen?) we've not fired _done_f, we
     # do that now (causing our "main" to exit, and thus react() to
     # quit)
     if not txaio.is_called(self._done_f):
         txaio.resolve(self._done_f, None)
     return txaio.create_future_success(None)
Exemple #14
0
 def stop(self):
     self._stopping = True
     if self._session and self._session.is_attached():
         return self._session.leave()
     elif self._delay_f:
         # This cancel request will actually call the "error" callback of
         # the _delay_f future. Nothing to worry about.
         return txaio.as_future(txaio.cancel, self._delay_f)
     # if (for some reason -- should we log warning here to figure
     # out if this can evern happen?) we've not fired _done_f, we
     # do that now (causing our "main" to exit, and thus react() to
     # quit)
     if not txaio.is_called(self._done_f):
         txaio.resolve(self._done_f, None)
     return txaio.create_future_success(None)
Exemple #15
0
    def test_publish_closed_session(self):
        """
        ensure a session doesn't get Events if it's closed
        (see also issue #431)
        """
        # we want to trigger a deeply-nested condition in
        # processPublish in class Broker -- lets try w/o refactoring
        # anything first...

        class TestSession(ApplicationSession):
            pass
        session0 = TestSession()
        session1 = TestSession()
        router = mock.MagicMock()
        router.new_correlation_id = lambda: u'fake correlation id'
        broker = Broker(router, reactor)

        # let's just "cheat" our way a little to the right state by
        # injecting our subscription "directly" (e.g. instead of
        # faking out an entire Subscribe etc. flow
        # ...so we need _subscriptions_map to have at least one
        # subscription (our test one) for the topic we'll publish to
        broker._subscription_map.add_observer(session0, u'test.topic')

        # simulate the session state we want, which is that a
        # transport is connected (._transport != None) but there
        # _session_id *is* None (not joined yet, or left already)
        self.assertIs(None, session0._session_id)
        session0._transport = mock.MagicMock()
        session0._transport.get_channel_id = mock.MagicMock(return_value=b'deadbeef')
        session1._session_id = 1234  # "from" session should look connected + joined
        session1._transport = mock.MagicMock()
        session1._transport.channel_id = b'aaaabeef'

        # here's the main "cheat"; we're faking out the
        # router.authorize because we need it to callback immediately
        router.authorize = mock.MagicMock(return_value=txaio.create_future_success(dict(allow=True, cache=False, disclose=True)))

        # now we scan call "processPublish" such that we get to the
        # condition we're interested in (this "comes from" session1
        # beacuse by default publishes don't go to the same session)
        pubmsg = message.Publish(123, u'test.topic')
        broker.processPublish(session1, pubmsg)

        # neither session should have sent anything on its transport
        self.assertEquals(session0._transport.method_calls, [])
        self.assertEquals(session1._transport.method_calls, [])
Exemple #16
0
    def sign(self, data):
        """
        Sign some data.

        :param data: The data to be signed.
        :type data: bytes

        :returns: The signature.
        :rtype: bytes
        """
        if not self._is_private:
            raise Exception("private key required to sign")

        if type(data) != six.binary_type:
            raise Exception("data to be signed must be binary")

        return create_future_success(self._key.sign(data))
Exemple #17
0
    def sign(self, data):
        """
        Sign some data.

        :param data: The data to be signed.
        :type data: bytes

        :returns: The signature.
        :rtype: bytes
        """
        if not self._is_private:
            raise Exception("private key required to sign")

        if type(data) != six.binary_type:
            raise Exception("data to be signed must be binary")

        return create_future_success(self._key.sign(data))
Exemple #18
0
    def authorize(self, session, uri, action):
        """
        Authorizes a session for an action on an URI.

        Implements :func:`autobahn.wamp.interfaces.IRouter.authorize`
        """
        assert(type(uri) == six.text_type)
        assert(action in [u'call', u'register', u'publish', u'subscribe'])

        # the role under which the session that wishes to perform the given action on
        # the given URI was authenticated under
        role = session._authrole

        if role in self._roles:
            # the authorizer procedure of the role which we will call ..
            authorize = self._roles[role].authorize
            d = txaio.as_future(authorize, session, uri, action)
        else:
            # normally, the role should exist on the router (and hence we should not arrive
            # here), but the role might have been dynamically removed - and anyway, safety first!
            d = txaio.create_future_success(False)

        def got_authorization(authorization):
            # backward compatibility
            if type(authorization) == bool:
                authorization = {
                    u'allow': authorization,
                    u'cache': False
                }
                if action in [u'call', u'publish']:
                    authorization[u'disclose'] = False

            self.log.debug("Authorized action '{action}' for URI '{uri}' by session {session_id} with authid '{authid}' and authrole '{authrole}' -> authorization: {authorization}",
                           session_id=session._session_id,
                           uri=uri,
                           action=action,
                           authid=session._authid,
                           authrole=session._authrole,
                           authorization=authorization)

            return authorization

        d.addCallback(got_authorization)
        return d
Exemple #19
0
    def authorize(self, session, uri, action):
        """
        Authorizes a session for an action on an URI.

        Implements :func:`autobahn.wamp.interfaces.IRouter.authorize`
        """
        assert (type(uri) == six.text_type)
        assert (action in [u'call', u'register', u'publish', u'subscribe'])

        # the role under which the session that wishes to perform the given action on
        # the given URI was authenticated under
        role = session._authrole

        if role in self._roles:
            # the authorizer procedure of the role which we will call ..
            authorize = self._roles[role].authorize
            d = txaio.as_future(authorize, session, uri, action)
        else:
            # normally, the role should exist on the router (and hence we should not arrive
            # here), but the role might have been dynamically removed - and anyway, safety first!
            d = txaio.create_future_success(False)

        def got_authorization(authorization):
            # backward compatibility
            if type(authorization) == bool:
                authorization = {u'allow': authorization, u'cache': False}
                if action in [u'call', u'publish']:
                    authorization[u'disclose'] = False

            self.log.info(
                "Authorized action '{action}' for URI '{uri}' by session {session_id} with authid '{authid}' and authrole '{authrole}' -> authorization: {authorization}",
                session_id=session._session_id,
                uri=uri,
                action=action,
                authid=session._authid,
                authrole=session._authrole,
                authorization=authorization)

            return authorization

        d.addCallback(got_authorization)
        return d
Exemple #20
0
    def callRemoteMessage(self, mcall, timeout = None):
        """
        Uses the specified L{message.MethodCallMessage} to call a remote method.

        @rtype: L{twisted.internet.defer.Deferred}
        @returns: a Deferred to the result of the remote method call
        """
        assert isinstance(mcall, message.MethodCallMessage)
        
        if mcall.expectReply:
            d = txaio.create_future()

            if timeout:
                timeout = txaio.call_later(timeout, self._onMethodTimeout, mcall.serial, d)

            self._pendingCalls[ mcall.serial ] = (d, timeout)

            self.sendMessage( mcall )

            return d
        else:
            self.sendMessage( mcall )

            return txaio.create_future_success(None)
Exemple #21
0
        def sign(self, data):
            """
            Sign some data.

            :param data: The data to be signed.
            :type data: bytes

            :returns: The signature.
            :rtype: bytes
            """
            if not self._can_sign:
                raise Exception("a signing key required to sign")

            if type(data) != six.binary_type:
                raise Exception("data to be signed must be binary")

            # sig is a nacl.signing.SignedMessage
            sig = self._key.sign(data)

            # we only return the actual signature! if we return "sig",
            # it get coerced into the concatenation of message + signature
            # not sure which order, but we don't want that. we only want
            # the signature
            return create_future_success(sig.signature)
        def sign(self, data):
            """
            Sign some data.

            :param data: The data to be signed.
            :type data: bytes

            :returns: The signature.
            :rtype: bytes
            """
            if not self._can_sign:
                raise Exception("a signing key required to sign")

            if type(data) != six.binary_type:
                raise Exception("data to be signed must be binary")

            # sig is a nacl.signing.SignedMessage
            sig = self._key.sign(data)

            # we only return the actual signature! if we return "sig",
            # it get coerced into the concatenation of message + signature
            # not sure which order, but we don't want that. we only want
            # the signature
            return create_future_success(sig.signature)
Exemple #23
0
    def authorize(self, session: ISession, uri: str, action: str,
                  options: Dict[str, Any]):
        """
        Authorizes a session for an action on an URI.

        Implements :func:`autobahn.wamp.interfaces.IRouter.authorize`
        """
        assert (action in ['call', 'register', 'publish', 'subscribe'])

        # the realm, authid and authrole under which the session that wishes to perform the
        # given action on the given URI was authenticated under
        realm = session._realm
        # authid = session._authid
        authrole = session._authrole

        # the permission of a WAMP client is always determined (only) from
        # WAMP realm, authrole, URI and action already
        cache_key = (realm, authrole, uri, action)

        # if we do have a cache entry, use the authorization cached
        cached_authorization = self._authorization_cache.get(cache_key, None)

        # normally, the role should exist on the router (and hence we should not arrive
        # here), but the role might have been dynamically removed - and anyway, safety first!
        if authrole in self._roles:
            if cached_authorization:
                self.log.debug(
                    '{func} authorization cache entry found key {cache_key}:\n{authorization}',
                    func=hltype(self.authorize),
                    cache_key=hlval(cache_key),
                    authorization=pformat(cached_authorization))
                d = txaio.create_future_success(cached_authorization)
            else:
                # the authorizer procedure of the role which we will call
                authorize = self._roles[authrole].authorize
                d = txaio.as_future(authorize, session, uri, action, options)
        else:
            # remove cache entry
            if cached_authorization:
                del self._authorization_cache[cache_key]

            # outright deny, since the role isn't active anymore
            d = txaio.create_future_success(False)

        # XXX would be nicer for dynamic-authorizer authors if we
        # sanity-checked the return-value ('authorization') here
        # (i.e. is it a dict? does it have 'allow' in it? does it have
        # disallowed keys in it?)

        def got_authorization(authorization):
            # backward compatibility
            if isinstance(authorization, bool):
                authorization = {'allow': authorization, 'cache': False}
                if action in ['call', 'publish']:
                    authorization['disclose'] = False

            auto_disclose_trusted = True
            if auto_disclose_trusted and authrole == 'trusted' and action in [
                    'call', 'publish'
            ]:
                authorization['disclose'] = True

            if not cached_authorization and authorization.get('cache', False):
                self._authorization_cache[cache_key] = authorization
                self.log.debug(
                    '{func} add authorization cache entry for key {cache_key}:\n{authorization}',
                    func=hltype(got_authorization),
                    cache_key=hlval(cache_key),
                    authorization=pformat(authorization))

            self.log.debug(
                "Authorized action '{action}' for URI '{uri}' by session {session_id} with authid '{authid}' and "
                "authrole '{authrole}' -> authorization: {authorization}",
                session_id=session._session_id,
                uri=uri,
                action=action,
                authid=session._authid,
                authrole=session._authrole,
                authorization=authorization)

            return authorization

        d.addCallback(got_authorization)
        return d
Exemple #24
0
    def test_publish_traced_events_batched(self):
        """
        with two subscribers and message tracing the last event should
        have a magic flag
        """

        # we want to trigger a deeply-nested condition in
        # processPublish in class Broker -- lets try w/o refactoring
        # anything first...

        class TestSession(ApplicationSession):
            pass

        session0 = TestSession()
        session1 = TestSession()
        session2 = TestSession()
        session3 = TestSession()
        session4 = TestSession()
        # NOTE! We ensure that "session0" (the publishing session) is
        # *last* in the observation-list to trigger a (now fixed)
        # edge-case)
        sessions = [session1, session2, session3, session4, session0]
        router = mock.MagicMock()
        router.send = mock.Mock()
        router.new_correlation_id = lambda: 'fake correlation id'
        router.is_traced = True
        clock = Clock()
        with replace_loop(clock):
            broker = Broker(router, clock)
            broker._options.event_dispatching_chunk_size = 2

            # to ensure we get "session0" last, we turn on ordering in
            # the observations
            broker._subscription_map._ordered = 1

            # let's just "cheat" our way a little to the right state by
            # injecting our subscription "directly" (e.g. instead of
            # faking out an entire Subscribe etc. flow
            # ...so we need _subscriptions_map to have at least one
            # subscription (our test one) for the topic we'll publish to
            for session in sessions:
                broker._subscription_map.add_observer(session, 'test.topic')

            for i, sess in enumerate(sessions):
                sess._session_id = 1000 + i
                sess._transport = mock.MagicMock()
                sess._transport.get_channel_id = mock.MagicMock(
                    return_value=b'deadbeef')

            # here's the main "cheat"; we're faking out the
            # router.authorize because we need it to callback immediately
            router.authorize = mock.MagicMock(
                return_value=txaio.create_future_success(
                    dict(allow=True, cache=False, disclose=True)))

            # now we scan call "processPublish" such that we get to the
            # condition we're interested in; should go to all sessions
            # except session0
            pubmsg = message.Publish(123, 'test.topic')
            broker.processPublish(session0, pubmsg)
            clock.advance(1)
            clock.advance(1)

            # extract all the event calls
            events = [
                call[1][1] for call in router.send.mock_calls if call[1][0] in
                [session0, session1, session2, session3, session4]
            ]

            # all except session0 should have gotten an event, and
            # session4's should have the "last" flag set
            self.assertEqual(4, len(events))
            self.assertFalse(events[0].correlation_is_last)
            self.assertFalse(events[1].correlation_is_last)
            self.assertFalse(events[2].correlation_is_last)
            self.assertTrue(events[3].correlation_is_last)
Exemple #25
0
    def getRemoteObject(self, busName, objectPath, interfaces = None,
                        replaceKnownInterfaces = False):
        """
        Creates a L{RemoteDBusObject} instance to represent the
        specified DBus object.  If explicit interfaces are not
        supplied, DBus object introspection will be used to obtain
        them automatically.

        @type busName: C{string}
        @param busName: Name of the bus exporting the desired object

        @type objectPath: C{string}
        @param objectPath: DBus path of the desired object

        @type interfaces: None, C{string} or L{interface.DBusInterface} or a
                          list of C{string}/L{interface.DBusInterface}
        @param interfaces: May be None, a single value, or a list of string
                           interface names and/or instances of
                           L{interface.DBusInterface}. If None or any of the
                           specified interface names are unknown, full
                           introspection will be attempted.  If interfaces
                           consists of solely of L{interface.DBusInterface}
                           instances and/or known interfacep names, no
                           introspection will be preformed.

        @type replaceKnownInterfaces: C{bool}
        @param replaceKnownInterfaces: If True (defaults to False), any
                                       interfaces discovered during the
                                       introspection process will override any
                                       previous, cached values.

        @rtype: L{twisted.internet.defer.Deferred}
        @returns: A Deferred to the L{RemoteDBusObject} instance
        """

        weak_id = (busName, objectPath, interfaces)

        need_introspection  = False
        required_interfaces = set()
        
        if interfaces is not None:

            ifl = list()
            
            if not isinstance(interfaces, list):
                interfaces = [interfaces]
                    
            for i in interfaces:
                if isinstance(i, interface.DBusInterface ):
                    ifl.append(i)
                    required_interfaces.add(i.name)
                else:
                    required_interfaces.add(i)
                    if i in interface.DBusInterface.knownInterfaces:
                        ifl.append( interface.DBusInterface.knownInterfaces[i] )
                    else:
                        need_introspection = True
                        
            if not need_introspection:
                return txaio.create_future_success( RemoteDBusObject( self, busName, objectPath, ifl ) )

        d = self.conn.introspectRemoteObject( busName,
                                              objectPath,
                                              replaceKnownInterfaces )

        def ok( ifaces ):
            
            missing = required_interfaces - set( [ q.name for q in ifaces ] )
            
            if missing:
                raise error.IntrospectionFailed('Introspection failed to find interfaces: ' +
                                                     ','.join(missing))

            prox = RemoteDBusObject( self, busName, objectPath, ifaces )

            self._weakProxies[ weak_id ] = prox
            
            return prox
            

        txaio.add_callbacks(d, ok, None)

        return d
Exemple #26
0
    def test_publish_traced_events_batched(self):
        """
        with two subscribers and message tracing the last event should
        have a magic flag
        """
        # we want to trigger a deeply-nested condition in
        # processPublish in class Broker -- lets try w/o refactoring
        # anything first...

        class TestSession(ApplicationSession):
            pass
        session0 = TestSession()
        session1 = TestSession()
        session2 = TestSession()
        session3 = TestSession()
        session4 = TestSession()
        # NOTE! We ensure that "session0" (the publishing session) is
        # *last* in the observation-list to trigger a (now fixed)
        # edge-case)
        sessions = [session1, session2, session3, session4, session0]
        router = mock.MagicMock()
        router.send = mock.Mock()
        router.new_correlation_id = lambda: u'fake correlation id'
        router.is_traced = True
        clock = Clock()
        with replace_loop(clock):
            broker = Broker(router, clock)
            broker._options.event_dispatching_chunk_size = 2

            # to ensure we get "session0" last, we turn on ordering in
            # the observations
            broker._subscription_map._ordered = 1

            # let's just "cheat" our way a little to the right state by
            # injecting our subscription "directly" (e.g. instead of
            # faking out an entire Subscribe etc. flow
            # ...so we need _subscriptions_map to have at least one
            # subscription (our test one) for the topic we'll publish to
            for session in sessions:
                broker._subscription_map.add_observer(session, u'test.topic')

            for i, sess in enumerate(sessions):
                sess._session_id = 1000 + i
                sess._transport = mock.MagicMock()
                sess._transport.get_channel_id = mock.MagicMock(return_value=b'deadbeef')

            # here's the main "cheat"; we're faking out the
            # router.authorize because we need it to callback immediately
            router.authorize = mock.MagicMock(return_value=txaio.create_future_success(dict(allow=True, cache=False, disclose=True)))

            # now we scan call "processPublish" such that we get to the
            # condition we're interested in; should go to all sessions
            # except session0
            pubmsg = message.Publish(123, u'test.topic')
            broker.processPublish(session0, pubmsg)
            clock.advance(1)
            clock.advance(1)

            # extract all the event calls
            events = [
                call[1][1]
                for call in router.send.mock_calls
                if call[1][0] in [session0, session1, session2, session3, session4]
            ]

            # all except session0 should have gotten an event, and
            # session4's should have the "last" flag set
            self.assertEqual(4, len(events))
            self.assertFalse(events[0].correlation_is_last)
            self.assertFalse(events[1].correlation_is_last)
            self.assertFalse(events[2].correlation_is_last)
            self.assertTrue(events[3].correlation_is_last)
Exemple #27
0
def test_is_called(framework):
    f = txaio.create_future_success(None)
    assert txaio.is_called(f)