Esempio n. 1
0
 def test_date(self):
     s1 = ejson.dumps(datetime.date(2015, 1, 25))
     self.assertEqual('{"$date": 1422144000000}', s1)
     self.assertEqual(datetime.datetime(2015, 1, 25, tzinfo=ejson.timezone.utc), ejson.loads(s1))
     s2 = ejson.dumps(datetime.datetime(2015, 1, 25, 10, 30, 1, tzinfo=ejson.timezone.utc))
     self.assertEqual('{"$date": 1422181801000}', s2)
     self.assertEqual(datetime.datetime(2015, 1, 25, 10, 30, 1, tzinfo=ejson.timezone.utc), ejson.loads(s2))
Esempio n. 2
0
    def _handle_message(self, msg, socket):
        if msg.tp == sockjs.MSG_OPEN:
            socket._ddp_session = None

        elif msg.tp == sockjs.MSG_MESSAGE:

            try:
                try:
                    mbody = ejson.loads(msg.data)
                    if type(mbody) != dict or mbody.get("msg") == None:
                        self.logger.debug(
                            "Discarding non-object DDP message {msg}"
                            .format(msg=msg.data),
                            )
                        socket.send(ejson.dumps({
                            "msg": "error",
                            "reason": "Bad request",
                            "offendingMessage": mbody,
                            }))
                        return
                except ValueError:
                    self.logger.debug(
                        "Discarding message with invalid JSON {msg}"
                        .format(msg=msg.data),
                        )
                    socket.send(json.dumps({
                        "msg": "error",
                        "reason": "Bad request",
                        }))
                    return

                if mbody["msg"] == "connect":
                    if socket._ddp_session:
                        socket.send(json.dumps({
                            "msg": "error",
                            "reason": "Already connected",
                            "offendingMessage": mbody,
                            }))
                        return
                    asyncio.async(self._handle_connect(mbody, socket),
                                  loop=self.loop)
                    return

                if not socket._ddp_session:
                    socket.send(ejson.dumps({
                        "msg": "error",
                        "reason": "Must connect first",
                        "offendingMessage": mbody,
                        }))
                    return

                socket._ddp_session.process_message(mbody)

            except Exception:
                self.logger.error(
                    "Internal exception while processing message {msg}\n{err}"
                    .format(msg=msg.data, err=traceback.format_exc())
                    )
Esempio n. 3
0
 def test_binary(self):
     if six.PY3:
         s = ejson.dumps([six.binary_type('foo', 'ascii'), 'foo'])
         self.assertEqual('[{"$binary": "Zm9v"}, "foo"]', s)
         self.assertEqual([six.binary_type('foo', 'ascii'), 'foo'], ejson.loads(s))
     else:
         s = ejson.dumps(['foo', six.text_type('foo')])
         self.assertEqual('["foo", "foo"]', s)
         self.assertEqual(['foo', 'foo'], ejson.loads('[{"$binary": "Zm9v"}, "foo"]'))
Esempio n. 4
0
    def send(self, data, tx_id=None):
        """Send `data` (raw string or EJSON payload) to WebSocket client."""
        # buffer data until we get pre-requisite data
        if tx_id is None:
            tx_id = self.get_tx_id()
        self._tx_buffer[tx_id] = data

        # de-queue messages from buffer
        while self._tx_next_id in self._tx_buffer:
            # pull next message from buffer
            data = self._tx_buffer.pop(self._tx_next_id)
            if self._tx_buffer:
                safe_call(self.logger.debug, 'TX found %d', self._tx_next_id)
            # advance next message ID
            self._tx_next_id = next(self._tx_next_id_gen)
            if not isinstance(data, basestring):
                # ejson payload
                msg = data.get('msg', None)
                if msg in (ADDED, CHANGED, REMOVED):
                    ids = self.remote_ids[data['collection']]
                    meteor_id = data['id']
                    if msg == ADDED:
                        if meteor_id in ids:
                            msg = data['msg'] = CHANGED
                        else:
                            ids.add(meteor_id)
                    elif msg == CHANGED:
                        if meteor_id not in ids:
                            # object has become visible, treat as `added`.
                            msg = data['msg'] = ADDED
                            ids.add(meteor_id)
                    elif msg == REMOVED:
                        try:
                            ids.remove(meteor_id)
                        except KeyError:
                            continue  # client doesn't have this, don't send.
                data = 'a%s' % ejson.dumps([ejson.dumps(data)])
            # send message
            safe_call(self.logger.debug, '> %s %r', self, data)
            try:
                self.ws.send(data)
            except geventwebsocket.WebSocketError:
                self.ws.close()
                self._tx_buffer.clear()
                break
        num_waiting = len(self._tx_buffer)
        if num_waiting > 10:
            safe_call(
                self.logger.warn,
                'TX received %d, waiting for %d, have %d waiting: %r.',
                tx_id,
                self._tx_next_id,
                num_waiting,
                self._tx_buffer,
            )
Esempio n. 5
0
    def send(self, data, tx_id=None):
        """Send `data` (raw string or EJSON payload) to WebSocket client."""
        # buffer data until we get pre-requisite data
        if tx_id is None:
            tx_id = self.get_tx_id()
        self._tx_buffer[tx_id] = data

        # de-queue messages from buffer
        while self._tx_next_id in self._tx_buffer:
            # pull next message from buffer
            data = self._tx_buffer.pop(self._tx_next_id)
            if self._tx_buffer:
                safe_call(self.logger.debug, "TX found %d", self._tx_next_id)
            # advance next message ID
            self._tx_next_id = next(self._tx_next_id_gen)
            if not isinstance(data, basestring):
                # ejson payload
                msg = data.get("msg", None)
                if msg in (ADDED, CHANGED, REMOVED):
                    ids = self.remote_ids[data["collection"]]
                    meteor_id = data["id"]
                    if msg == ADDED:
                        if meteor_id in ids:
                            msg = data["msg"] = CHANGED
                        else:
                            ids.add(meteor_id)
                    elif msg == CHANGED:
                        if meteor_id not in ids:
                            # object has become visible, treat as `added`.
                            msg = data["msg"] = ADDED
                            ids.add(meteor_id)
                    elif msg == REMOVED:
                        try:
                            ids.remove(meteor_id)
                        except KeyError:
                            continue  # client doesn't have this, don't send.
                data = "a%s" % ejson.dumps([ejson.dumps(data)])
            # send message
            safe_call(self.logger.debug, "> %s %r", self, data)
            try:
                self.ws.send(data)
            except geventwebsocket.WebSocketError:
                self.ws.close()
                self._tx_buffer.clear()
                break
        num_waiting = len(self._tx_buffer)
        if num_waiting > 10:
            safe_call(
                self.logger.warn,
                "TX received %d, waiting for %d, have %d waiting: %r.",
                tx_id,
                self._tx_next_id,
                num_waiting,
                self._tx_buffer,
            )
Esempio n. 6
0
    async def _handle_messages(
            self, websocket: websockets.protocol.WebSocketCommonProtocol,
            _path: str):
        async def send(data: object) -> None:
            await websocket.send(ejson.dumps(data))

        async def fail():
            await send({
                "msg": "failed",
                "version": "1",
            })

        data = ejson.loads(await websocket.recv())
        if data["msg"] != "connect":
            return await fail()
        await websocket.send(
            ejson.dumps({
                "msg": "connected",
                "session": str(uuid.uuid4())
            }))
        async for message in websocket:
            data = ejson.loads(message)
            if data["msg"] == "method":
                assert data["method"] in self._method_handlers
                await send({
                    "id":
                    data["id"],
                    "msg":
                    "result",
                    "result":
                    self._method_handlers[data["method"]](*data["params"]),
                })
                continue
            await fail()
Esempio n. 7
0
def ddpp_sockjs_info(environ, start_response):
    """Inform client that WebSocket service is available."""
    start_response(
        '200 OK',
        [
            ('Content-Type', 'application/json; charset=UTF-8'),
            (
                'Access-Control-Allow-Origin',
                '/'.join(environ['HTTP_REFERER'].split('/')[:3]),
            ),
            ('Access-Control-Allow-Credentials', 'true'),
            #  ('access-control-allow-credentials', 'true'),
            ('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0'),
            ('Connection', 'keep-alive'),
            ('Vary', 'Origin'),
        ],
    )
    yield ejson.dumps(collections.OrderedDict([
        ('websocket', True),
        ('origins', [
            '*:*',
        ]),
        ('cookie_needed', False),
        ('entropy', random.getrandbits(32)),
    ]))
Esempio n. 8
0
    async def connect(self):
        '''This coroutine establishes a connection to a server.
        It blocks until the connection is established or an exception is raised.
        
        Raises ddp_asyncio.ConnectionError if the server reports a failure (usually caused by incomplatible versions of the DDP protocol.)
        '''

        self._websocket = await websockets.connect(self.url)

        msg = {'msg': 'connect', 'version': '1', 'support': ['1']}

        await self._websocket.send(ejson.dumps(msg))

        while self._websocket.open:
            msg = await self._websocket.recv()
            msg = ejson.loads(msg)
            _type = msg.get('msg')

            if _type == 'failed':
                raise ConnectionError(
                    'The server is not compatible with version 1 of the DDP protocol.'
                )
            elif _type == 'connected':
                # Ensure all Collections are in their default states
                for col in self._cols.values():
                    col._data = {}

                self.is_connected = True
                self._disconnection_event.clear()
                self._event_loop.create_task(self.__handler__())

                return
Esempio n. 9
0
    def recvloop(self):
        while self.websocket.open:
            while len(self.callcache) > 0:
                self.call(*self.callcache.pop(0))

            msg = yield from self.websocket.recv()
            if not msg: continue
            msg = ejson.loads(msg)

            if msg.get('msg') == 'connected':
                self.connected = True
                self.session = msg['session']

            elif msg.get('msg') == 'ping':
                yield from self.websocket.send(
                    ejson.dumps({
                        'msg': 'pong',
                        'id': msg.get('id')
                    }))

            elif msg.get('msg') == 'ready':
                for sub in self.subs.values():
                    if sub.id in msg['subs']:
                        yield from sub.ready_cb(sub)

            elif msg.get('msg') == 'added':
                sub = self.subs.get(msg['collection'])
                if sub:
                    sub.data[msg['id']] = msg['fields']
                    yield from sub.added_cb(sub, msg['id'], msg['fields'])

            elif msg.get('msg') == 'changed':
                sub = self.subs.get(msg['collection'])
                if sub:
                    if msg.get('fields'):
                        sub.data[msg['id']].update(msg['fields'])
                        yield from sub.changed_cb(sub, msg['id'],
                                                  msg['fields'])
                    elif msg.get('cleared'):
                        for key in msg['cleared']:
                            del sub.data[key]
                        yield from sub.changed_cb(sub, msg['id'],
                                                  msg['cleared'])

            elif msg.get('msg') == 'removed':
                sub = self.subs.get(msg['collection'])
                if sub:
                    del sub.data[msg['id']]
                    yield from sub.removed_cb(sub, msg['id'])

            elif msg.get('msg') == 'result':
                c = self.calls.get(msg['id'])
                if c:
                    yield from c.onfinished(msg.get('result'),
                                            msg.get('error'))

        self.connected = False
        while True:
            yield from self.connect()
            return
Esempio n. 10
0
 def get(self, request, path):
     """Return HTML (or other related content) for Meteor."""
     if path == '/meteor_runtime_config.js':
         config = {
             'DDP_DEFAULT_CONNECTION_URL': request.build_absolute_uri('/'),
             'ROOT_URL': request.build_absolute_uri(
                 '%s/' % self.runtime_config.get('ROOT_URL_PATH_PREFIX', ''),
             ),
             'ROOT_URL_PATH_PREFIX': '',
         }
         # Use HTTPS instead of HTTP if SECURE_SSL_REDIRECT is set
         if config['DDP_DEFAULT_CONNECTION_URL'].startswith('http:') \
                 and settings.SECURE_SSL_REDIRECT:
             config['DDP_DEFAULT_CONNECTION_URL'] = 'https:%s' % (
                 config['DDP_DEFAULT_CONNECTION_URL'].split(':', 1)[1],
             )
         config.update(self.runtime_config)
         return HttpResponse(
             '__meteor_runtime_config__ = %s;' % dumps(config),
             content_type='text/javascript',
         )
     try:
         file_path, content_type = self.url_map[path]
         with open(file_path, 'r') as content:
             return HttpResponse(
                 content.read(),
                 content_type=content_type,
             )
     except KeyError:
         print(path)
         return HttpResponse(self.html)
Esempio n. 11
0
 def get(self, request, path):
     """Return HTML (or other related content) for Meteor."""
     if path == '/meteor_runtime_config.js':
         config = {
             'DDP_DEFAULT_CONNECTION_URL':
             request.build_absolute_uri('/'),
             'ROOT_URL':
             request.build_absolute_uri(
                 '%s/' %
                 self.runtime_config.get('ROOT_URL_PATH_PREFIX', ''), ),
             'ROOT_URL_PATH_PREFIX':
             '',
         }
         # Use HTTPS instead of HTTP if SECURE_SSL_REDIRECT is set
         if config['DDP_DEFAULT_CONNECTION_URL'].startswith('http:') \
                 and settings.SECURE_SSL_REDIRECT:
             config['DDP_DEFAULT_CONNECTION_URL'] = 'https:%s' % (
                 config['DDP_DEFAULT_CONNECTION_URL'].split(':', 1)[1], )
         config.update(self.runtime_config)
         return HttpResponse(
             '__meteor_runtime_config__ = %s;' % dumps(config),
             content_type='text/javascript',
         )
     try:
         file_path, content_type = self.url_map[path]
         with open(file_path, 'r') as content:
             return HttpResponse(
                 content.read(),
                 content_type=content_type,
             )
     except KeyError:
         print(path)
         return HttpResponse(self.html)
Esempio n. 12
0
def ddpp_sockjs_info(environ, start_response):
    """Inform client that WebSocket service is available."""
    import random
    import ejson

    start_response(
        '200 OK',
        [
            ('Content-Type', 'application/json; charset=UTF-8'),
            (
                'Access-Control-Allow-Origin',
                '/'.join(environ['HTTP_REFERER'].split('/')[:3]),
            ),
            ('Access-Control-Allow-Credentials', 'true'),
            #  ('access-control-allow-credentials', 'true'),
            ('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0'
             ),
            ('Connection', 'keep-alive'),
            ('Vary', 'Origin'),
        ],
    )
    yield ejson.dumps(
        collections.OrderedDict([
            ('websocket', True),
            ('origins', [
                '*:*',
            ]),
            ('cookie_needed', False),
            ('entropy', random.getrandbits(32)),
        ]))
Esempio n. 13
0
def test_serialization_with_datetime():
    ejson.cleanup_registry()
    value = {'dt': datetime(2012, 8, 22, 3, 44, 0o5)}

    # Before registering
    ejson.dumps.when.called_with(value, sort_keys=True).should.throw(
        TypeError,
        'datetime.datetime(2012, 8, 22, 3, 44, 5) is not JSON serializable')

    # After registering
    @ejson.register_serializer(datetime)
    def serialize_datetime(instance):
        return instance.isoformat()


    ejson.dumps(value, sort_keys=True).should.be.equals(
        '{"dt": {"__class__": "datetime.datetime", "__value__": "2012-08-22T03:44:05"}}')
Esempio n. 14
0
def test_serialization_with_datetime():
    ejson.cleanup_registry()
    value = {'dt': datetime(2012, 8, 22, 3, 44, 0o5)}

    # Before registering
    ejson.dumps.when.called_with(value, sort_keys=True).should.throw(
        TypeError,
        'datetime.datetime(2012, 8, 22, 3, 44, 5) is not JSON serializable')

    # After registering
    @ejson.register_serializer(datetime)
    def serialize_datetime(instance):
        return instance.isoformat()

    ejson.dumps(value, sort_keys=True).should.be.equals(
        '{"dt": {"__class__": "datetime.datetime", "__value__": "2012-08-22T03:44:05"}}'
    )
Esempio n. 15
0
 def save(self, filename=None):
     import ejson
     if not os.path.exists(self.workdir):
         os.makedirs(self.workdir)
     if filename is None:
         filename = 'task.ejson'
     with open(os.path.join(self.workdir, filename), 'w') as f:
         f.write(ejson.dumps(self.taskDoc))
Esempio n. 16
0
def test_escaping_string_on_dumps():
    # Given that I have some data to serialize
    data = {'blah': '<h1>blah & bleh</h1>'}

    # When I try to dump it using the "escape" flag
    escaped = ejson.dumps(data, escape=True)

    # Then I see it was escaped properly
    escaped.should.equal('{"blah": "&lt;h1&gt;blah &amp; bleh&lt;/h1&gt;"}')
Esempio n. 17
0
def test_escaping_string_on_dumps():
    # Given that I have some data to serialize
    data = {'blah': '<h1>blah & bleh</h1>'}

    # When I try to dump it using the "escape" flag
    escaped = ejson.dumps(data, escape=True)

    # Then I see it was escaped properly
    escaped.should.equal('{"blah": "&lt;h1&gt;blah &amp; bleh&lt;/h1&gt;"}')
Esempio n. 18
0
def test_log_when_debug_is_false(conf, datetime, find_event, tasks):
    conf.getsetting.return_value = False
    core.cleanup_handlers()
    datetime.now.return_value = 'tea time'

    eventlib.log('app.Event')
    tasks.process_task.delay.assert_called_once_with('app.Event', ejson.dumps({
        '__ip_address__': '0.0.0.0', '__datetime__': 'tea time',
    }))
Esempio n. 19
0
 def ejson_serialize(self):
     """
     """
     message_dict = {"msg": self.msg}
     for arg in self._serialize_args:
         if arg == "error" and not self.error:
             continue
         message_dict[arg] = self.__dict__.get(arg, None)
     return ejson.dumps(message_dict)
Esempio n. 20
0
def test_process_raises_the_exception_when_debugging(settings, find_event):
    core.cleanup_handlers()
    settings.DEBUG = True

    handler_fail = Mock()
    handler_fail.side_effect = ValueError('P0wned!!!')
    eventlib.handler('myapp.CoolEvent')(handler_fail)
    name, data = 'myapp.CoolEvent', ejson.dumps({'a': 1})
    core.process.when.called_with(name, data).should.throw(
        ValueError, 'P0wned!!!')
Esempio n. 21
0
    async def unsubscribe(self, sub):
        '''Coroutine that unsubscribes from a publication.
        
        Raises ddp_asyncio.NotConnectedError if called while not connected to a server.
        '''

        await self._websocket.send(ejson.dumps({
            'msg': 'unsub',
            'id': sub._id
        }))
Esempio n. 22
0
def test_process_raises_the_exception_when_debugging(settings, find_event):
    core.cleanup_handlers()
    settings.DEBUG = True

    handler_fail = Mock()
    handler_fail.side_effect = ValueError('P0wned!!!')
    eventlib.handler('myapp.CoolEvent')(handler_fail)
    name, data = 'myapp.CoolEvent', ejson.dumps({'a': 1})
    core.process.when.called_with(name,
                                  data).should.throw(ValueError, 'P0wned!!!')
Esempio n. 23
0
 def do_sub(self, id_, name, silent, *params):
     """Subscribe the current thread to the specified publication."""
     try:
         pub = self.get_pub_by_name(name)
     except KeyError:
         if not silent:
             raise MeteorError(404, 'Subscription not found')
         return
     sub, created = Subscription.objects.get_or_create(
         connection_id=this.ws.connection.pk,
         sub_id=id_,
         user_id=getattr(this, 'user_id', None),
         defaults={
             'publication': pub.name,
             'params_ejson': ejson.dumps(params),
         },
     )
     this.subs.setdefault(sub.publication, set()).add(sub.pk)
     if not created:
         if not silent:
             this.send({'msg': 'ready', 'subs': [id_]})
         return
     # re-read from DB so we can get transaction ID (xmin)
     sub = Subscription.objects.extra(**XMIN).get(pk=sub.pk)
     for col, qs in self.sub_unique_objects(
             sub, params, pub, xmin__lte=sub.xmin,
     ):
         sub.collections.create(
             model_name=model_name(qs.model),
             collection_name=col.name,
         )
         if isinstance(col.model._meta.pk, AleaIdField):
             meteor_ids = None
         elif len([
             field
             for field
             in col.model._meta.local_fields
             if (
                 isinstance(field, AleaIdField)
             ) and (
                 field.unique
             ) and (
                 not field.null
             )
         ]) == 1:
             meteor_ids = None
         else:
             meteor_ids = get_meteor_ids(
                 qs.model, qs.values_list('pk', flat=True),
             )
         for obj in qs.select_related():
             payload = col.obj_change_as_msg(obj, ADDED, meteor_ids)
             this.send(payload)
     if not silent:
         this.send({'msg': 'ready', 'subs': [id_]})
Esempio n. 24
0
def test_process_data_clean_raise_errors(logger, find_event):
    core.cleanup_handlers()

    class MyEvent(eventlib.BaseEvent):
        def clean(self):
            raise exceptions.ValidationError('Owned!!11')

    data = {'name': 'Lincoln', 'answer': 42}
    find_event.return_value = MyEvent
    core.process.when.called_with('stuff', ejson.dumps(data)).should.throw(
        exceptions.ValidationError)
Esempio n. 25
0
def ddpp_sockjs_info(environ, start_response):
    """Inform client that WebSocket service is available."""
    import random
    import ejson

    start_response("200 OK", [("Content-Type", "application/json; charset=UTF-8")] + common_headers(environ))
    yield ejson.dumps(
        collections.OrderedDict(
            [("websocket", True), ("origins", ["*:*"]), ("cookie_needed", False), ("entropy", random.getrandbits(32))]
        )
    )
Esempio n. 26
0
    def test_escape_encode(self):
        s = ejson.dumps({
                            "foo": "bar",
                            "bat": {
                                "$escape": {
                                    "baz": "bazam"
                                }
                            }
                        }, sort_keys=True)

        self.assertEqual('{"bat": {"$escape": {"$escape": {"baz": "bazam"}}}, "foo": "bar"}', s)
Esempio n. 27
0
def test_log_when_debug_is_false(conf, datetime, find_event, tasks):
    conf.getsetting.return_value = False
    core.cleanup_handlers()
    datetime.now.return_value = 'tea time'

    eventlib.log('app.Event')
    tasks.process_task.delay.assert_called_once_with(
        'app.Event',
        ejson.dumps({
            '__ip_address__': '0.0.0.0',
            '__datetime__': 'tea time',
        }))
Esempio n. 28
0
    def recvloop(self):
        while self.websocket.open:
            while len(self.callcache) > 0:
                self.call(*self.callcache.pop(0))
            
            msg = yield from self.websocket.recv()
            if not msg: continue
            msg = ejson.loads(msg)

            if msg.get('msg') == 'connected':
                self.connected = True
                self.session = msg['session']
                
            elif msg.get('msg') == 'ping':
                yield from self.websocket.send(ejson.dumps({'msg': 'pong', 'id': msg.get('id')}))
                
            elif msg.get('msg') == 'ready':
                for sub in self.subs.values():
                    if sub.id in msg['subs']:
                        yield from sub.ready_cb(sub)

            elif msg.get('msg') == 'added':
                sub = self.subs.get(msg['collection'])
                if sub:
                    sub.data[msg['id']] = msg['fields']
                    yield from sub.added_cb(sub, msg['id'], msg['fields'])
                    
            elif msg.get('msg') == 'changed':
                sub = self.subs.get(msg['collection'])
                if sub:
                    if msg.get('fields'):
                        sub.data[msg['id']].update(msg['fields'])
                        yield from sub.changed_cb(sub, msg['id'], msg['fields'])
                    elif msg.get('cleared'):
                        for key in msg['cleared']:
                            del sub.data[key]
                        yield from sub.changed_cb(sub, msg['id'], msg['cleared'])
                    
            elif msg.get('msg') == 'removed':
                sub = self.subs.get(msg['collection'])
                if sub:
                    del sub.data[msg['id']]
                    yield from sub.removed_cb(sub, msg['id'])
                    
            elif msg.get('msg') == 'result':
                c = self.calls.get(msg['id'])
                if c:
                    yield from c.onfinished(msg.get('result'), msg.get('error'))
                    
        self.connected = False
        while True:
            yield from self.connect()
            return
Esempio n. 29
0
    def _broadcast(self):
        if conf.getsetting('UNIT_TESTING'):
            raise AssertionError(
                'Eventlib calls must be mocked when settings.UNIT_TESTING is True')

        data = self.broadcast(self.data)
        client = redis_connection.get_connection()
        if client:
            # If not redis client, don't broadcast
            data['name'] = self.name
            data = ejson.dumps(data)
            client.publish("eventlib", data)
Esempio n. 30
0
 async def subscribe(self, name: str) -> asyncio.Queue:
     id = str(uuid.uuid4())
     sub_future = asyncio.get_event_loop().create_future()
     self._pending_subscription_data[id] = PendingSubscriptionData(
         name, sub_future)
     await super().send(
         ejson.dumps({
             "id": id,
             "msg": "sub",
             "name": name,
         }))
     return await sub_future
Esempio n. 31
0
def get_user_token(user, purpose, days_valid):
    """Return login token info for given user."""
    token = ''.join(
        dumps([
            user.get_username(),
            get_auth_hash(user, purpose),
        ]).encode('base64').split('\n'))
    return {
        'id': get_meteor_id(user),
        'token': token,
        'tokenExpires': calc_expiry_time(days_valid),
    }
Esempio n. 32
0
 def subscribe(self, name, *params, ready_cb = noop,
               added_cb = noop, changed_cb = noop, removed_cb = noop):
     sub = Subscription(name, ready_cb, added_cb, changed_cb, removed_cb)
     self.subs[name] = sub
     yield from self.websocket.send(ejson.dumps(
         {'msg': 'sub',
          'id': sub.id,
          'name': name,
          'params': params}
     ))
     
     return sub
Esempio n. 33
0
 def do_sub(self, id_, name, silent, *params):
     """Subscribe the current thread to the specified publication."""
     try:
         pub = self.get_pub_by_name(name)
     except KeyError:
         if not silent:
             raise MeteorError(404, 'Subscription not found')
         return
     sub, created = Subscription.objects.get_or_create(
         connection_id=this.ws.connection.pk,
         sub_id=id_,
         user_id=getattr(this, 'user_id', None),
         defaults={
             'publication': pub.name,
             'params_ejson': ejson.dumps(params),
         },
     )
     this.subs.setdefault(sub.publication, set()).add(sub.pk)
     if not created:
         if not silent:
             this.send({'msg': 'ready', 'subs': [id_]})
         return
     # re-read from DB so we can get transaction ID (xmin)
     sub = Subscription.objects.extra(**XMIN).get(pk=sub.pk)
     for col, qs in self.sub_unique_objects(
             sub,
             params,
             pub,
             xmin__lte=sub.xmin,
     ):
         sub.collections.create(
             model_name=model_name(qs.model),
             collection_name=col.name,
         )
         if isinstance(col.model._meta.pk, AleaIdField):
             meteor_ids = None
         elif len([
                 field for field in col.model._meta.local_fields
                 if (isinstance(field, AleaIdField)) and (
                     field.unique) and (not field.null)
         ]) == 1:
             meteor_ids = None
         else:
             meteor_ids = get_meteor_ids(
                 qs.model,
                 qs.values_list('pk', flat=True),
             )
         for obj in qs.select_related():
             payload = col.obj_change_as_msg(obj, ADDED, meteor_ids)
             this.send(payload)
     if not silent:
         this.send({'msg': 'ready', 'subs': [id_]})
Esempio n. 34
0
    async def _handle_messages(self, websocket: WebSocketServerProtocol,
                               _path: str):
        async def send(data: object) -> None:
            await websocket.send(ejson.dumps(data))

        self._subscription_task = asyncio.create_task(
            self._send_subscription_messages(send=send, ))

        async def fail():
            await send({
                "msg": "failed",
                "version": "1",
            })

        data = ejson.loads(await websocket.recv())
        if data["msg"] != "connect":
            return await fail()
        await websocket.send(
            ejson.dumps({
                "msg": "connected",
                "session": str(uuid.uuid4())
            }))
        async for message in websocket:
            data = ejson.loads(message)
            if data["msg"] == "method":
                assert data["method"] in self._method_handlers
                await send({
                    "id":
                    data["id"],
                    "msg":
                    "result",
                    "result":
                    self._method_handlers[data["method"]](*data["params"]),
                })
                continue
            if data["msg"] == "sub":
                self._subscriptions[data["name"]] = data["id"]
                await send({
                    "msg": "ready",
                    "subs": [data["id"]],
                })
                continue
            if data["msg"] == "unsub":
                topic = [
                    topic for topic, id in self._subscriptions.items()
                    if id == data["id"]
                ][0]
                del self._subscriptions[topic]
                # Nothing to respond with in this case.
                continue

            await fail()
Esempio n. 35
0
def test_process_data_clean_raise_errors(logger, find_event):
    core.cleanup_handlers()

    class MyEvent(eventlib.BaseEvent):
        def clean(self):
            raise exceptions.ValidationError('Owned!!11')

    data = {'name': 'Lincoln', 'answer': 42}
    find_event.return_value = MyEvent
    core.process.when.called_with(
        'stuff',
        ejson.dumps(data)
    ).should.throw(exceptions.ValidationError)
Esempio n. 36
0
def get_user_token(user, purpose, minutes_valid):
    """Return login token info for given user."""
    token = ''.join(
        dumps([
            user.get_username(),
            get_auth_hash(user, purpose),
        ]).encode('base64').split('\n')
    )
    return {
        'id': get_meteor_id(user),
        'token': token,
        'tokenExpires': calc_expiry_time(minutes_valid),
    }
Esempio n. 37
0
 async def invoke_method(self, method: str, params: List[Any] = []) -> Any:
     id = str(uuid.uuid4())
     recv_future = asyncio.get_event_loop().create_future()
     self._invoke_method_futures[id] = recv_future
     await super().send(
         ejson.dumps({
             "id": id,
             "msg": "method",
             "method": method,
             "params": params,
         }))
     recv = await recv_future
     return recv["result"]
Esempio n. 38
0
    def _broadcast(self):
        if conf.getsetting('UNIT_TESTING'):
            raise AssertionError(
                'Eventlib calls must be mocked when settings.UNIT_TESTING is True'
            )

        data = self.broadcast(self.data)
        client = redis_connection.get_connection()
        if client:
            # If not redis client, don't broadcast
            data['name'] = self.name
            data = ejson.dumps(data)
            client.publish("eventlib", data)
Esempio n. 39
0
def test_decimal():
    # Given that I have a decimal object
    obj = decimal.Decimal("0.14285714285714285")

    # When I try to serialize it
    serialized = ejson.dumps(obj)

    # Then I see the proper string description of the object
    serialized.should.contain('"__class__": "decimal.Decimal"')
    serialized.should.contain('"__value__": "0.14285714285714285"')

    # When I try to deserialize, I see that it also works
    ejson.loads(serialized).should.equal(obj)
Esempio n. 40
0
def test_time():
    # Given that I have a time object to serialize
    obj = datetime.time(1, 12, 50, 123)

    # When I serialize it
    serialized = ejson.dumps(obj)

    # Then I see that it was correctly serialized
    serialized.should.contain('"__class__": "datetime.time"')
    serialized.should.contain('"__value__": "01:12:50.000123"')

    # When I try to deserialize, I see that it also works
    ejson.loads(serialized).should.equal(obj)
Esempio n. 41
0
def test_log(conf, find_event, process, datetime):
    conf.getsetting.return_value = True
    core.cleanup_handlers()
    datetime.now.return_value = 'tea time'

    event_cls = Mock()
    find_event.return_value = event_cls

    data = {'name': 'Event System', 'code': 42}
    eventlib.log('app.Event', data)
    find_event.assert_called_once_with('app.Event')
    event_cls.assert_called_once_with('app.Event', data)
    event_cls.return_value.validate.assert_called_once()
    process.assert_called_once_with('app.Event', ejson.dumps(data))
Esempio n. 42
0
def test_time_with_timezone():
    # Given that I have a time object to serialize
    obj = datetime.time(1, 12, 50, 123,
                        ejson.serializers.TZInfoHelper(-120, "FNT"))

    # When I serialize it
    serialized = ejson.dumps(obj)

    # Then I see that it was correctly serialized
    serialized.should.contain('"__class__": "datetime.time"')
    serialized.should.contain('"__value__": "01:12:50.000123-02:00"')

    # When I try to deserialize, I see that it also works
    ejson.loads(serialized).should.equal(obj)
Esempio n. 43
0
def test_process(find_event):
    core.cleanup_handlers()

    handler = Mock()
    eventlib.handler('app.Event')(handler)

    handler2 = Mock()
    eventlib.handler('app.Event')(handler2)

    data = {'file': '/etc/passwd', 'server': 'yipster'}
    core.process('app.Event', ejson.dumps(data))

    handler.assert_called_once_with(data)
    handler2.assert_called_once_with(data)
Esempio n. 44
0
 async def invoke_method(self, method: str, params: List[Any] = []) -> Any:
     async with self._method_lock:
         id = str(uuid.uuid4())
         await super().send(
             ejson.dumps({
                 "id": id,
                 "msg": "method",
                 "method": method,
                 "params": params,
             }))
         recv = ejson.loads(await super().recv())
         if recv["id"] != id or recv["msg"] != "result":
             raise websockets.exceptions.ProtocolError("Unexpected message")
         return recv["result"]
Esempio n. 45
0
 def get_user_token(cls, user, session_key, expiry_date, purpose):
     """Return login token info for given user."""
     token = ''.join(
         dumps([
             user.get_username(),
             session_key,
             cls.get_auth_hash(user, purpose),
         ]).encode('base64').split('\n')
     )
     return {
         'id': get_meteor_id(user),
         'token': token,
         'tokenExpires': expiry_date,
     }
Esempio n. 46
0
def test_process(find_event):
    core.cleanup_handlers()

    handler = Mock()
    eventlib.handler('app.Event')(handler)

    handler2 = Mock()
    eventlib.handler('app.Event')(handler2)

    data = {'file': '/etc/passwd', 'server': 'yipster'}
    core.process('app.Event', ejson.dumps(data))

    handler.assert_called_once_with(data)
    handler2.assert_called_once_with(data)
Esempio n. 47
0
def test_log(conf, find_event, process, datetime):
    conf.getsetting.return_value = True
    core.cleanup_handlers()
    datetime.now.return_value = 'tea time'

    event_cls = Mock()
    find_event.return_value = event_cls

    data = {'name': 'Event System', 'code': 42}
    eventlib.log('app.Event', data)
    find_event.assert_called_once_with('app.Event')
    event_cls.assert_called_once_with('app.Event', data)
    event_cls.return_value.validate.assert_called_once()
    process.assert_called_once_with('app.Event', ejson.dumps(data))
Esempio n. 48
0
def test_date():
    # Given that I have an instance of the date object that must be serialized
    obj = datetime.date(2013, 0o3, 30)

    # When I serialize it
    serialized = ejson.dumps(obj)

    # Then I see the proper representation of the instance that will allow us
    # to deserialize it later
    serialized.should.contain('"__class__": "datetime.date"')
    serialized.should.contain('"__value__": "2013-03-30"')

    # When I try to load this info again, Then I see that it also works
    ejson.loads(serialized).should.equal(obj)
Esempio n. 49
0
def test_process_data_clean(logger, find_event):
    core.cleanup_handlers()

    class MyEvent(eventlib.BaseEvent):
        def clean(self):
            raise exceptions.ValidationError('Owned!!11')

    data = {'name': 'Lincoln', 'answer': 42}
    find_event.return_value = MyEvent
    core.process('stuff', ejson.dumps(data))
    logger.warning.assert_called_once_with(
        'The event system just got an exception while cleaning data '
        "for the event 'stuff'\n"
        "data: {\"answer\": 42, \"name\": \"Lincoln\"}\n"
        "exc: Owned!!11")
Esempio n. 50
0
def test_process_data_clean(logger, find_event):
    core.cleanup_handlers()

    class MyEvent(eventlib.BaseEvent):
        def clean(self):
            raise exceptions.ValidationError('Owned!!11')

    data = {'name': 'Lincoln', 'answer': 42}
    find_event.return_value = MyEvent
    core.process('stuff', ejson.dumps(data))
    logger.warning.assert_called_once_with(
        'The event system just got an exception while cleaning data '
        "for the event 'stuff'\n"
        "data: {\"answer\": 42, \"name\": \"Lincoln\"}\n"
        "exc: Owned!!11")
Esempio n. 51
0
def _assert_serialize_deserialize_equals_and_is_binary(
    ejson_obj, json_obj, json_str, is_binary
):
    assert json_str == ejson.stringify(ejson_obj)
    assert json_str == ejson.dumps(ejson_obj)
    assert json_obj == ejson.to_json_value(ejson_obj)

    assert ejson_obj == ejson.parse(json_str)
    assert ejson_obj == ejson.loads(json_str)
    assert ejson_obj == ejson.from_json_value(json_obj)

    ejson_obj2 = deepcopy(ejson_obj)

    assert ejson.equals(ejson_obj, ejson_obj2)
    assert ejson.equals(ejson_obj, ejson.clone(ejson_obj))
    assert is_binary == ejson.is_binary(ejson_obj)
Esempio n. 52
0
def test_serialization_with_custom_object():
    ejson.cleanup_registry()
    value = Person('Lincoln', 25)

    # Before registering
    ejson.dumps.when.called_with(value, sort_keys=True).should.throw(
        TypeError, 'Person("Lincoln", 25) is not JSON serializable')

    # After registering
    @ejson.register_serializer(Person)
    def serialize_person(instance):
        return {"name": instance.name, "age": instance.age}

    dumped = ejson.dumps(value, sort_keys=True)
    dumped.should.be.contain('"__class__": "tests.unit.test_ejson.Person"')
    dumped.should.be.contain('"__value__": {"age": 25, "name": "Lincoln"}')
Esempio n. 53
0
    def call(self, method, *params, callback = None, wait = True):
        c = MethodCall(callback)
        self.calls[c.id] = c

        yield from self.websocket.send(ejson.dumps(
            {'msg': 'method',
             'method': method,
             'params': params,
             'id': c.id}
        ))
        
        if wait:
            while not c.finished:
                yield from asyncio.sleep(0.1)
                
            return c.result
Esempio n. 54
0
    def connect(self):
        c = False
        while not c:
            try:
                self.websocket = yield from websockets.connect(self.address)
                c = self.websocket.open
                print(c)
            except ConnectionRefusedError:
                yield from asyncio.sleep(1)
        
        msg = {'msg': 'connect', 'version': '1', 'support': ['1']}
        if self.session: msg['session'] = self.session
        yield from self.websocket.send(ejson.dumps(msg))

        asyncio.async(self.recvloop())
        while not self.connected:
            yield from asyncio.sleep(0.1)
Esempio n. 55
0
def test_process_fails_gracefully(settings, logger, find_event):
    core.cleanup_handlers()
    settings.DEBUG = False

    handler_fail = Mock()
    handler_fail.side_effect = ValueError('P0wned!!!')
    eventlib.handler('myapp.CoolEvent')(handler_fail)

    handler = Mock()
    eventlib.handler('myapp.CoolEvent')(handler)

    data = {'a': 1}
    event = 'myapp.CoolEvent'
    core.process(event, ejson.dumps(data))

    logger.warning.assert_called_once_with(
        'One of the handlers for the event "myapp.CoolEvent" has '
        'failed with the following exception: P0wned!!!')
    handler.assert_called_once_with(data)
Esempio n. 56
0
def ddpp_sockjs_info(environ, start_response):
    """Inform client that WebSocket service is available."""
    import random
    import ejson

    start_response(
        '200 OK',
        [
            ('Content-Type', 'application/json; charset=UTF-8'),
        ] + common_headers(environ),
    )
    yield ejson.dumps(collections.OrderedDict([
        ('websocket', True),
        ('origins', [
            '*:*',
        ]),
        ('cookie_needed', False),
        ('entropy', random.getrandbits(32)),
    ]))