def send(self, data): log.debug('sending {!r}', data) assert self.connected, 'tried to send data on closed websocket {!r}'.format( self.url) if isinstance(data, Mapping): data = json.dumps(data) return WebSocketClient.send(self, data)
def received_message(self, message): s = str(message) log.debug('received {!r}', s) try: parsed = json.loads(s) except: log.error('failed to parse incoming message', exc_info=True) else: self.dispatcher.defer(parsed)
def received_message(self, message): message = message.data if isinstance(message.data, six.text_type) else message.data.decode('utf-8') log.debug('received {!r}', message) try: message = json.loads(message) except: log.debug('failed to parse incoming message', exc_info=True) finally: self.dispatcher.defer(message)
def _dispatch(self, message): log.debug('dispatching {}', message) assert 'client' in message or 'callback' in message, 'no callback or client in message {}'.format(message) id = message.get('client') or message.get('callback') assert id in self._callbacks, 'unknown dispatchee {}'.format(id) if 'error' in message: self._callbacks[id]['errback'](message['error']) else: self._callbacks[id]['callback'](message.get('data'))
def received_message(self, message): message = str(message) log.debug('received {!r}', message) try: message = json.loads(message) except: log.debug('failed to parse incoming message', exc_info=True) finally: self.dispatcher.defer(message)
def _send(self, **kwargs): log.debug('sending {}', kwargs) with self._lock: assert self.connected, 'tried to send data on closed websocket {!r}'.format(self.url) try: return self.ws.send(kwargs) except: log.warn('failed to send {!r} on {!r}, closing websocket and will attempt to reconnect', kwargs, self.url) self.ws.close() raise
def _send(self, **kwargs): log.debug('sending {}', kwargs) with self._lock: assert self.connected, 'tried to send data on closed websocket {!r}'.format(self.url) try: return self.ws.send(kwargs) except: log.error('failed to send {!r} on {!r}, closing websocket and will attempt to reconnect', kwargs, self.url) self.ws.close() raise
def received_message(self, message): try: fields = json.loads(str(message.data)) assert isinstance(fields, dict) except: message = 'incoming websocket message was not a json object: {}'.format(message.data) log.error(message) self.send(error=message) else: log.debug('received {}', fields) responder.defer(self, fields)
def received_message(self, message): try: data = message.data if isinstance(message.data, six.text_type) else message.data.decode('utf-8') fields = json.loads(data) assert isinstance(fields, dict) except: message = 'incoming websocket message was not a json object: {}'.format(message.data) log.error(message) self.send(error=message) else: log.debug('received {}', fields) responder.defer(self, fields)
def jsonrpc_handler(self): id = None def error(code, message): body = {'jsonrpc': '2.0', 'id': id, 'error': {'code': code, 'message': message}} log.warn('returning error message: {!r}', body) return body body = cherrypy.request.json if not isinstance(body, dict): return error(ERR_INVALID_JSON, 'invalid json input {!r}'.format( cherrypy.request.body)) log.debug('jsonrpc request body: {!r}', body) id, params = body.get('id'), body.get('params', []) if 'method' not in body: return error(ERR_INVALID_RPC, '"method" field required for jsonrpc request') method = body['method'] if method.count('.') != 1: return error(ERR_MISSING_FUNC, 'invalid method ' + method) module, function = method.split('.') if module not in services: return error(ERR_MISSING_FUNC, 'no module ' + module) service = services[module] if not hasattr(service, function): return error(ERR_MISSING_FUNC, 'no function ' + method) if not isinstance(params, (list, dict)): return error(ERR_INVALID_PARAMS, 'invalid parameter list: {!r}'.format(params)) args, kwargs = (params, {}) if isinstance(params, list) else ([], params) precall(body) try: response = {'jsonrpc': '2.0', 'id': id, 'result': getattr(service, function)(*args, **kwargs)} log.debug('returning success message: {!r}', response) return response except Exception as e: errback(e, 'unexpected jsonrpc error calling ' + method) message = 'unexpected error' if debug: message += ': ' + traceback.format_exc() return error(ERR_FUNC_EXCEPTION, message)
def _dispatch(self, message): log.debug('dispatching {}', message) try: assert isinstance(message, Mapping), 'incoming message is not a dictionary' assert 'client' in message or 'callback' in message, 'no callback or client in message {}'.format(message) id = message.get('client') or message.get('callback') assert id in self._callbacks, 'unknown dispatchee {}'.format(id) except AssertionError: self.fallback(message) else: if 'error' in message: self._callbacks[id]['errback'](message['error']) else: self._callbacks[id]['callback'](message.get('data'))
def mainloop_daemon(): log.info('starting Sideboard daemon process') args = parser.parse_args() if os.fork() == 0: pid = os.fork() if pid == 0: mainloop() else: log.debug('writing pid ({}) to pidfile ({})', pid, args.pidfile) try: with open(args.pidfile, 'w') as f: f.write('{}'.format(pid)) except: log.error('unexpected error writing pid ({}) to pidfile ({})', pid, args.pidfile, exc_info=True)
def received_message(self, message): try: data = message.data if isinstance( message.data, six.text_type) else message.data.decode('utf-8') fields = json.loads(data) assert isinstance(fields, dict) except: message = 'incoming websocket message was not a json object: {}'.format( message.data) log.error(message) self.send(error=message) else: log.debug('received {}', fields) responder.defer(self, fields)
def ldap_auth(username, password): if not username or not password: return False try: ssl_material = ( config['ldap.cacert'], config['ldap.cert'], config['ldap.key'] ) server_kwargs = {} tls_kwargs = {} if config['ldap.url'].startswith('ldaps') or any(ssl_material): server_kwargs['use_ssl'] = True else: server_kwargs['use_ssl'] = False server_kwargs['host'] = config['ldap.url'] if config['ldap.cacert']: tls_kwargs['ca_certs_file'] = config['ldap.cacert'] # if we specify a CA certs file, assume we want to validate it tls_kwargs['validate'] = ssl.CERT_REQUIRED if tls_kwargs: server_kwargs['tls'] = ldap3.Tls(**tls_kwargs) server = ldap3.Server(**server_kwargs) except: log.error('Error initializing LDAP server', exc_info=True) raise # attempt to bind on each base DN that was configured for basedn in listify(config['ldap.basedn']): dn = '{}={},{}'.format(config['ldap.userattr'], username, basedn) log.debug('attempting to bind with dn {}', dn) try: connection = ldap3.Connection(server, user=dn, password=password) connection.start_tls() is_bound = connection.bind() except: log.warning("Error binding to LDAP server with dn", exc_info=True) raise if is_bound: return True # we couldn't auth on anything return False
def send(self, **message): message = {k: v for k, v in message.items() if v is not None} if 'data' in message and 'client' in message: fingerprint = _fingerprint(message['data']) client, callback = message['client'], message.get('callback') repeat_send = callback in self.cached_fingerprints[client] cached_fingerprint = self.cached_fingerprints[client].get(callback) self.cached_fingerprints[client][callback] = fingerprint if cached_fingerprint == fingerprint and repeat_send: return log.debug('sending {}', message) message = json.dumps(message, cls=sideboard.lib.serializer, separators=(',', ':'), sort_keys=True) with self.send_lock: WebSocket.send(self, message)
def received_message(self, message): """ This overrides the default ws4py event handler to parse the incoming message and pass it off to our pool of background threads, which call this class' handle_message function to perform the relevant RPC actions. """ try: data = message.data if isinstance(message.data, six.text_type) else message.data.decode('utf-8') fields = json.loads(data) assert isinstance(fields, dict) except: message = 'incoming websocket message was not a json object: {}'.format(message.data) log.error(message) self.send(error=message) else: log.debug('received {}', fields) responder.defer(self, fields)
def jsonrpc_handler(self): id = None def error(code, message): body = {"jsonrpc": "2.0", "id": id, "error": {"code": code, "message": message}} log.warn("returning error message: {!r}", body) return body body = cherrypy.request.json if not isinstance(body, dict): return error(ERR_INVALID_JSON, "invalid json input {!r}".format(cherrypy.request.body)) log.debug("jsonrpc request body: {!r}", body) id, params = body.get("id"), body.get("params", []) if "method" not in body: return error(ERR_INVALID_RPC, '"method" field required for jsonrpc request') method = body["method"] if method.count(".") != 1: return error(ERR_MISSING_FUNC, "invalid method " + method) module, function = method.split(".") if module not in services: return error(ERR_MISSING_FUNC, "no module " + module) service = services[module] if not hasattr(service, function): return error(ERR_MISSING_FUNC, "no function " + method) if not isinstance(params, (list, dict)): return error(ERR_INVALID_PARAMS, "invalid parameter list: {!r}".format(params)) args, kwargs = (params, {}) if isinstance(params, list) else ([], params) precall(body) try: response = {"jsonrpc": "2.0", "id": id, "result": getattr(service, function)(*args, **kwargs)} log.debug("returning success message: {!r}", response) return response except Exception as e: errback(e, "unexpected jsonrpc error calling " + method) message = "unexpected error" if debug: message += ": " + traceback.format_exc() return error(ERR_FUNC_EXCEPTION, message)
def send(self, **message): """ This overrides the ws4py-provided send to implement three new features: 1) Instead of taking a string, this method treats its keyword arguments as the message, serializes them to JSON, and sends that. 2) For subscription responses, we keep track of the most recent response we sent for the given subscription. If neither the request or response have changed since the last time we pushed data back to the client for this subscription, we don't send anything. 3) We lock when sending to ensure that our sends are thread-safe. Surprisingly, the "ws4py.threadedclient" class isn't thread-safe! 4) Subscriptions firing will sometimes trigger a send on a websocket which has already been marked as closed. When this happens we log a debug message and then exit without error. """ if self.is_closed: log.debug('ignoring send on an already closed websocket: {}', message) self.unsubscribe_all() return message = {k: v for k, v in message.items() if v is not None} if 'data' in message and 'client' in message: fingerprint = _fingerprint(message['data']) client, callback = message['client'], message.get('callback') repeat_send = callback in self.cached_fingerprints[client] cached_fingerprint = self.cached_fingerprints[client].get(callback) self.cached_fingerprints[client][callback] = fingerprint if cached_fingerprint == fingerprint and repeat_send: return log.debug('sending {}', message) message = json.dumps(message, cls=sideboard.lib.serializer, separators=(',', ':'), sort_keys=True) with self.send_lock: if not self.is_closed: WebSocket.send(self, message)
def received_message(self, message): """ This overrides the default ws4py event handler to parse the incoming message and pass it off to our pool of background threads, which call this class' handle_message function to perform the relevant RPC actions. """ try: data = message.data if isinstance( message.data, six.text_type) else message.data.decode('utf-8') fields = json.loads(data) assert isinstance(fields, dict) except: message = 'incoming websocket message was not a json object: {}'.format( message.data) log.error(message) self.send(error=message) else: log.debug('received {}', fields) responder.defer(self, fields)
def ldap_auth(username, password): if not username or not password: return False try: conn = ldap.initialize(config['ldap.url']) force_start_tls = False if config['ldap.cacert']: ldap.set_option(ldap.OPT_X_TLS_CACERTFILE, config['ldap.cacert']) force_start_tls = True if config['ldap.cert']: ldap.set_option(ldap.OPT_X_TLS_CERTFILE, config['ldap.cert']) force_start_tls = True if config['ldap.key']: ldap.set_option(ldap.OPT_X_TLS_KEYFILE, config['ldap.key']) force_start_tls = True if force_start_tls: conn.start_tls_s() else: conn.set_option(ldap.OPT_X_TLS_DEMAND, config['ldap.start_tls']) except: log.error('Error initializing LDAP connection', exc_info=True) raise for basedn in listify(config['ldap.basedn']): dn = '{}={},{}'.format(config['ldap.userattr'], username, basedn) log.debug('attempting to bind with dn {}', dn) try: conn.simple_bind_s(dn, password) except ldap.INVALID_CREDENTIALS as x: continue except: log.warning("Error binding to LDAP server with dn", exc_info=True) raise else: return True
def test_omit_keys_that_are_returned_by_default(self): results = Session.crud.read({'_model': 'Account'}, { '_model': False, 'id': False, 'username': True, 'password': False, 'user': { '_model': False, 'id': False, 'name': True } }) for account in results['results']: log.debug('account: {}', account) self.assertNotIn('_model', account) self.assertNotIn('id', account) self.assertNotIn('password', account) self.assertNotIn('_model', account['user']) self.assertNotIn('id', account['user']) self.assertIn('username', account) self.assertIn('name', account['user'])
def crud_method(*args, **kwargs): log.debug('mocked crud.{}'.format(name)) assert not getattr(self.mr, name + '_error', False) return uuid4().hex
def index(self): log.debug("this data will be used to render a template") return {"plugin": "drafts-as-a-service", "header": True}
def poll(self): """empty method which exists only to help keep WebSockets alive""" log.debug('sideboard.poll by user {}', threadlocal.get('username'))
def jsonrpc_handler(self=None): id = None def error(code, message): body = { 'jsonrpc': '2.0', 'id': id, 'error': { 'code': code, 'message': message } } log.warn('returning error message: {!r}', body) return body body = cherrypy.request.json if not isinstance(body, dict): return error( ERR_INVALID_JSON, 'invalid json input {!r}'.format(cherrypy.request.body)) log.debug('jsonrpc request body: {!r}', body) id, params = body.get('id'), body.get('params', []) if 'method' not in body: return error(ERR_INVALID_RPC, '"method" field required for jsonrpc request') method = body['method'] if method.count('.') != 1: return error(ERR_MISSING_FUNC, 'invalid method ' + method) module, function = method.split('.') if module not in services: return error(ERR_MISSING_FUNC, 'no module ' + module) service = services[module] if not hasattr(service, function): return error(ERR_MISSING_FUNC, 'no function ' + method) if not isinstance(params, (list, dict)): return error(ERR_INVALID_PARAMS, 'invalid parameter list: {!r}'.format(params)) args, kwargs = (params, {}) if isinstance(params, list) else ([], params) precall(body) try: response = { 'jsonrpc': '2.0', 'id': id, 'result': getattr(service, function)(*args, **kwargs) } log.debug('returning success message: {!r}', response) return response except Exception as e: errback(e, 'unexpected jsonrpc error calling ' + method) message = 'unexpected error' if debug: message += ': ' + traceback.format_exc() return error(ERR_FUNC_EXCEPTION, message) finally: trigger_delayed_notifications()
def send(self, data): log.debug('sending {!r}', data) assert self.connected, 'tried to send data on closed websocket {!r}'.format(self.url) if isinstance(data, dict): data = json.dumps(data) return WebSocketClient.send(self, data)