diff --git a/docs/settings.md b/docs/settings.md index 140b44a..8b4975e 100644 --- a/docs/settings.md +++ b/docs/settings.md @@ -57,6 +57,9 @@ This setting will override the default `localhost` host This setting will override the default `9999` port +### ```SWAMP_DRAGON_PUBLISH_ENABLED``` + +If set to ```False``` it turns the publishing of changes off. Default value is ```True```. ## JavaScript settings (settings exposed to clients via JavaScript) diff --git a/swampdragon/connections/sockjs_connection.py b/swampdragon/connections/sockjs_connection.py index 2785632..78c4e7e 100644 --- a/swampdragon/connections/sockjs_connection.py +++ b/swampdragon/connections/sockjs_connection.py @@ -5,6 +5,7 @@ from .. import route_handler from ..sessions.sessions import get_session_store from ..same_origin import set_origin_connection, test_origin +from django.utils.importlib import import_module import json @@ -28,6 +29,7 @@ def is_heartbeat_enabled(): class ConnectionMixin(object): + def to_json(self, data): """ If the message is a dict, return it. @@ -44,6 +46,7 @@ def to_json(self, data): class SubscriberConnection(ConnectionMixin, SockJSConnection): pub_sub = None + user = None def __init__(self, session): super(SubscriberConnection, self).__init__(session) @@ -83,6 +86,12 @@ def on_message(self, data): if data == {'heartbeat': '1'}: self.on_heartbeat() return + middleware_classes = getattr(settings, 'SWAMP_DRAGON_MIDDLEWARE_CLASSES', None) + if middleware_classes: + for middleware_class in middleware_classes: + middleware_path, middleware_name = middleware_classes[0].rsplit('.', 1) + middleware = getattr(import_module(middleware_path), middleware_name) + middleware().process_request(self, data) handler = route_handler.get_route_handler(data['route']) handler(self).handle(data) except Exception as e: diff --git a/swampdragon/middleware.py b/swampdragon/middleware.py new file mode 100644 index 0000000..663e33f --- /dev/null +++ b/swampdragon/middleware.py @@ -0,0 +1,21 @@ +from django.utils.six import add_metaclass +from abc import abstractmethod, ABCMeta + + +@add_metaclass(ABCMeta) +class BasicMiddleware(object): + + """MiddleWare Interface for SwampDragon + + Inheriting Classes should implement process_request method + + Returns: + None (might change in future) + """ + + def __init__(self): + pass + + @abstractmethod + def process_request(self, connection, data): + pass diff --git a/swampdragon/mock_middleware.py b/swampdragon/mock_middleware.py new file mode 100644 index 0000000..0046a1a --- /dev/null +++ b/swampdragon/mock_middleware.py @@ -0,0 +1,14 @@ +from .middleware import BasicMiddleware + + +class TestMiddleware(BasicMiddleware): + + """ + Middleware sets 'dummy' variable in the connection + """ + + def __init__(self): + super(TestMiddleware, self).__init__() + + def process_request(self, connection, data): + connection.dummy = True diff --git a/swampdragon/models.py b/swampdragon/models.py index b6a000b..403368a 100644 --- a/swampdragon/models.py +++ b/swampdragon/models.py @@ -1,4 +1,5 @@ from django.db.models import ForeignKey +from django.conf import settings from .pubsub_providers.base_provider import PUBACTIONS from .model_tools import get_property from .pubsub_providers.model_publisher import publish_model @@ -77,7 +78,13 @@ def serialize(self): return self._serializer.serialize() def _publish(self, action, changed_fields=None): - publish_model(self, self._serializer, action, changed_fields) + try: + PUBLISH_ENABLED = getattr(settings, 'SWAMP_DRAGON_PUBLISH_ENABLED', True) + + if PUBLISH_ENABLED: + publish_model(self, self._serializer, action, changed_fields) + except Exception: + pass # not the best practice, but we don't want anything to fail if Redis is unaccessible... def save(self, *args, **kwargs): if not self.pk: diff --git a/tests/test_subscriber_connection.py b/tests/test_subscriber_connection.py index 4bc7529..4ff7a29 100644 --- a/tests/test_subscriber_connection.py +++ b/tests/test_subscriber_connection.py @@ -3,10 +3,12 @@ from swampdragon.route_handler import BaseRouter, UnexpectedVerbException from swampdragon.testing.dragon_testcase import DragonTestCase from swampdragon import route_handler +from django.conf import settings as django_settings import uuid class TestSession(object): + def __init__(self, is_open=True): self.session_id = uuid.uuid4().hex self.is_closed = is_open is False @@ -28,7 +30,9 @@ def say_hello(self, **kwargs): class TestSubscriberConnection(DragonTestCase): + def setUp(self): + django_settings.SWAMP_DRAGON_MIDDLEWARE_CLASSES = ['swampdragon.mock_middleware.TestMiddleware'] self.session = TestSession() self.connection = SubscriberConnection(self.session) @@ -72,3 +76,11 @@ def test_dict_to_json(self): expected = {'key': 'value'} actual = self.connection.to_json(expected) self.assertEqual(expected, actual) + + def test_middleware_processing(self): + route_handler.register(TestRouter) + data = {'verb': 'say_hello', 'route': TestRouter.get_name()} + with self.assertRaises(AttributeError): + self.connection.dummy + self.connection.on_message(data) + self.assertTrue(self.connection.dummy)