def get(self, event): if self._check_permission(event) is False: response = { 'component': 'hfos.ui.configurator', 'action': 'get', 'data': False } self.log('No permission to access configuration', event.user, lvl=warn) self.fireEvent(send(event.client.uuid, response)) return try: comp = event.data['uuid'] except KeyError: comp = None if not comp: self.log('Invalid get request without schema or component', lvl=error) return self.log("Config data get request for ", event.data, "from", event.user) component = model_factory(Schema).find_one({'uuid': comp}) response = { 'component': 'hfos.ui.configurator', 'action': 'get', 'data': component.serializablefields() } self.fireEvent(send(event.client.uuid, response))
def schemarequest(self, event): """Handles schema requests. :param event: SchemaRequest with actions * Get * All """ try: if event.action == "Get": self.log("Schemarequest for ", event.data, "from", event.user) if event.data in schemastore: response = {'component': 'schema', 'action': 'Get', 'data': self.schemata[event.data] } self.fireEvent(send(event.client.uuid, response)) elif event.action == "All": self.log("Schemarequest for all schemata from ", event.user) response = {'component': 'schema', 'action': 'All', 'data': schemastore} self.fireEvent(send(event.client.uuid, response)) except Exception as e: self.log("Overall error: ", e, type(e), lvl=error, exc=True)
def remotecontrolrequest(self, event): """Remote control event handler for incoming events :param event: RemoteControlRequest with action being one of ['takeControl', 'leaveControl', 'controlData'] """ self.log("Event: '%s'" % event.__dict__) try: action = event.action data = event.data username = event.user.account.name clientname = event.client.name clientuuid = event.client.uuid if action == "takeControl": self.log("Client wants to remote control: ", username, clientname, lvl=warn) if not self.remotecontroller: self.log("Success!") self.remotecontroller = clientuuid self.fireEvent(send(clientuuid, {'component': 'remotectrl', 'action': 'takeControl', 'data': True})) else: self.log("No, we're already being remote controlled!") self.fireEvent( send(clientuuid, {'component': 'remotectrl', 'action': 'takeControl', 'data': False})) return elif action == "leaveControl": if self.remotecontroller == event.client.uuid: self.log("Client leaves control!", username, clientname, lvl=warn) self.remotecontroller = None self.fireEvent( send(clientuuid, {'component': 'remotectrl', 'action': 'takeControl', 'data': False})) return elif action == "controlData": self.log("Control data received: ", data) if event.client.uuid == self.remotecontroller: self.log("Valid data, handing on to machineroom.") self.fireEvent(remotecontrolupdate(data), "machineroom") else: self.log("Invalid control data update request!", lvl=warn) except Exception as e: self.log("Error: '%s' %s" % (e, type(e)), lvl=error, exc=True)
def list(self, event): """Processes configuration list requests :param event: """ try: componentlist = model_factory(Schema).find({}) data = [] for comp in componentlist: data.append({ 'name': comp.name, 'uuid': comp.uuid, 'class': comp.componentclass, 'active': comp.active }) data = sorted(data, key=lambda x: x['name']) response = { 'component': 'hfos.ui.configurator', 'action': 'list', 'data': data } self.fireEvent(send(event.client.uuid, response)) return except Exception as e: self.log("List error: ", e, type(e), lvl=error, exc=True)
def put(self, event): self.log("Configuration put request ", event.user) try: if self._check_permission(event) is False: raise PermissionError component = model_factory(Schema).find_one( {'uuid': event.data['uuid']}) component.update(event.data) component.save() response = { 'component': 'hfos.ui.configurator', 'action': 'put', 'data': True } self.log('Updated component configuration:', component.name) except (KeyError, ValueError, ValidationError, PermissionError) as e: response = { 'component': 'hfos.ui.configurator', 'action': 'put', 'data': False } self.log('Storing component configuration failed: ', type(e), e, exc=True, lvl=error) self.fireEvent(send(event.client.uuid, response)) return
def _delete(self, schema, data): if True: # try: uuid = data['uuid'] if schema in objectmodels.keys(): self.log("Looking for object to be deleted.", lvl=debug) storageobject = objectmodels[schema].find_one({'uuid': uuid}) self.log("Found object.", lvl=debug) self.log("Fields:", storageobject._fields, "\n\n\n", storageobject.__dict__) storageobject.delete() self.log("Preparing notification.", lvl=debug) notification = objectdeletion(uuid, schema) if uuid in self.subscriptions: deletion = {'component': 'objectmanager', 'action': 'deletion', 'data': uuid } for recipient in self.subscriptions[uuid]: self.fireEvent(send(recipient, deletion)) del (self.subscriptions[uuid]) result = {'component': 'objectmanager', 'action': 'delete', 'data': (True, schema, storageobject.uuid), } return result, notification else: self.log("Unknown schema encountered: ", schema, lvl=warn)
def join(self, event): """Chat event handler for incoming events :param event: say-event with incoming chat message """ try: channel_uuid = event.data user_uuid = event.user.uuid if channel_uuid in self.chat_channels: self.log('User joins a known channel', lvl=debug) if user_uuid in self.chat_channels[channel_uuid].users: self.log('User already joined', lvl=warn) else: self.chat_channels[channel_uuid].users.append(user_uuid) self.chat_channels[channel_uuid].save() packet = { 'component': 'hfos.chat.host', 'action': 'join', 'data': channel_uuid } self.fireEvent(send(event.client.uuid, packet)) else: self.log('Request to join unavailable channel', lvl=warn) except Exception as e: self.log('Join error:', e, type(e), exc=True, lvl=error)
def _broadcast(self, camera_packet, camera_uuid): try: for recipient in self._subscribers[camera_uuid]: self.fireEvent(send(recipient, camera_packet, raw=True), "hfosweb") except Exception as e: self.log("Failed broadcast: ", e, type(e), lvl=error)
def mapimport(self, event): self.log('Map import request!', lvl=hilight) name = event.data['name'] self.log(name) # self.log(event.data['raw']) filename = os.path.join(self.storagepath, name) with open(filename, 'wb') as f: f.write(event.data['raw']) temp_file = filename.replace('.KAP', '.vrt') target = os.path.join(self.tilepath, name) self._translate(filename, temp_file) self._tile(temp_file, target) self.log('Done tiling: ', filename, target, lvl=hilight) newlayer = self._register_map(name.rstrip('.KAP'), target, event.client) notification = { 'component': 'hfos.alert.manager', 'action': 'success', 'data': 'New rasterchart rendered: <a href="#!/editor/layer/' + str(newlayer.uuid) + '/edit">' + newlayer.name + '</a>' } self.fireEvent(send(event.client.uuid, notification))
def change(self, event): uuid = event.data['uuid'] status = event.data['status'] if status not in ['Open', 'Pending', 'Accepted', 'Denied', 'Resend']: self.log('Erroneous status for enrollment requested!', lvl=warn) return self.log('Changing status of an enrollment', uuid, 'to', status) enrollment = objectmodels['enrollment'].find_one({'uuid': uuid}) if enrollment is not None: self.log('Enrollment found', lvl=debug) else: return if status == 'Resend': enrollment.timestamp = std_now() enrollment.save() self._send_mail(enrollment) reply = {True: 'Resent'} else: enrollment.status = status enrollment.save() reply = {True: enrollment.serializablefields()} packet = { 'component': 'hfos.enrol.manager', 'action': 'change', 'data': reply } self.log('packet:', packet, lvl=verbose) self.fireEvent(send(event.client.uuid, packet)) self.log('Enrollment changed', lvl=debug)
def invite(self, event): self.log('Inviting new user to enrol') name = event.data['name'] email = event.data['email'] method = event.data['method'] props = { 'uuid': std_uuid(), 'status': 'Open', 'name': name, 'method': method, 'email': email, 'timestamp': std_now() } enrollment = objectmodels['enrollment'](props) enrollment.save() self.log('Enrollment stored', lvl=debug) if method == 'Invited': self._send_mail(enrollment) packet = { 'component': 'hfos.enrol.manager', 'action': 'invite', 'data': {True: enrollment.serializablefields()} } self.fireEvent(send(event.client.uuid, packet))
def createuser(self, event): self.log("Creating user") try: newuser = objectmodels['user']({ 'name': event.username, 'passhash': event.passhash, 'uuid': str(uuid4()) }) newuser.save() except Exception as e: self.log("Problem creating new user: "******"New profile uuid: ", newprofile.uuid, lvl=verbose) # TODO: Fix this - yuk! newprofile.components = { 'enabled': ["dashboard", "map", "weather", "settings"]} newprofile.save() except Exception as e: self.log("Problem creating new profile: ", type(e), e, lvl=error) return try: # TODO: Clone or reference systemwide default configuration newclientconfig = objectmodels['client']() newclientconfig.uuid = event.clientuuid newclientconfig.name = "New client" newclientconfig.description = "New client configuration " \ "from " + newuser.name newclientconfig.useruuid = newuser.uuid newclientconfig.save() except Exception as e: self.log("Problem creating new clientconfig: ", type(e), e, lvl=error) return try: self.fireEvent( authentication(newuser.name, (newuser, newprofile, newclientconfig), event.clientuuid, newuser.uuid, event.sock), "auth") self.fireEvent(send(event.clientuuid, { 'component': 'auth', 'action': 'new', 'data': 'registration successful' }, sendtype="client"), "hfosweb") except Exception as e: self.log("Error during new account confirmation transmission", e, lvl=error)
def _augmentBook(self, schema, uuid, client): """ Checks if the newly created object is a book and only has an ISBN. If so, tries to fetch the book data off the internet. :param schema: must be 'book' :param uuid: uuid of book to augment """ try: if schema == 'book': if not isbnmeta: self.log( "No isbntools found! Install it to get full " "functionality!", lvl=warn) return newbook = objectmodels['book'].find_one({'uuid': uuid}) try: if len(newbook.isbn) != 0: self.log('Got a lookup candidate: ', newbook._fields) try: meta = isbnmeta(newbook.isbn, service=self.config.isbnservice) mapping = libraryfieldmapping[ self.config.isbnservice] for key in meta.keys(): if key in mapping: if isinstance(mapping[key], tuple): name, conv = mapping[key] meta[name] = conv(meta.pop(key)) else: meta[mapping[key]] = meta.pop(key) newbook.update(meta) newbook.save() self.log("Book successfully augmented from ", self.config.isbnservice) except Exception as e: self.log("Error during meta lookup: ", e, type(e), newbook.isbn, lvl=error, exc=True) self.fireEvent(send(client.uuid, {'component': 'alert', 'action': 'error', 'data': 'Could not look up metadata, sorry:' + str( e)})) else: self.log( 'Saw something, but it is not to be looked up: ', newbook._fields) except Exception as e: self.log("Error during book update.") except Exception as e: self.log("Book creation notification error: ", uuid, e, type(e), lvl=error, exc=True)
def fail(uuid): self.log('Sending failure feedback to', uuid, lvl=debug) fail_msg = { 'component': 'hfos.enrol.manager', 'action': 'accept', 'data': False } self.fireEvent(send(uuid, fail_msg))
def all(self, event): self.log("Schemarequest for all schemata from", event.user, lvl=debug) response = { 'component': 'hfos.events.schemamanager', 'action': 'all', 'data': schemastore } self.fireEvent(send(event.client.uuid, response))
def userlogin(self, event): """Checks if an alert is ongoing and alerts the newly connected client, if so.""" clientuuid = event.clientuuid if self.mobalert: alertpacket = {'component': 'alert', 'action': 'mob', 'data': True} self.fireEvent(send(clientuuid, alertpacket))
def logupdate(self, event): self.log('Updating syslog viewers', lvl=debug) packet = { 'component': 'hfos.ui.syslog', 'action': 'update', 'data': event.message.serializablefields() } for subscriber in self.subscribers: self.fireEvent(send(subscriber, packet))
def camera_list(self, event): try: client_uuid = event.client.uuid db_list = self._generate_camera_list() self.fireEvent(send(client_uuid, { 'component': 'hfos.camera.manager', 'action': 'list', 'data': db_list }), "hfosweb") except Exception as e: self.log("Listing error: ", e, type(e), lvl=error)
def get(self, event): self.log("Schemarequest for", event.data, "from", event.user, lvl=debug) if event.data in schemastore: response = { 'component': 'hfos.events.schemamanager', 'action': 'get', 'data': schemastore[event.data] } self.fireEvent(send(event.client.uuid, response)) else: self.log("Unavailable schema requested!", lvl=warn)
def sensordata(self, event): """ Generates a new reference frame from incoming sensordata :param event: new sensordata to be merged into referenceframe """ if len(self.datatypes) == 0: return data = event.data timestamp = event.timestamp # bus = event.bus # TODO: What about multiple busses? That is prepared, but how exactly # should they be handled? self.log("New incoming navdata:", data, lvl=verbose) for name, value in data.items(): if name in self.datatypes: ref = self.datatypes[name] self.sensed[name] = ref if ref.lastvalue != str(value): # self.log("Reference outdated:", ref._fields) item = {"value": value, "timestamp": timestamp, "type": name} self.referenceframe[name] = value self.referenceages[name] = timestamp # self.log("Subscriptions:", self.subscriptions, ref.name) if ref.name in self.subscriptions: packet = {"component": "navdata", "action": "update", "data": item} self.log("Serving update: ", packet, lvl=verbose) for uuid in self.subscriptions[ref.name]: self.fireEvent(send(uuid, packet), "hfosweb") # self.log("New item: ", item) sensordata = objectmodels["sensordata"](item) # self.log("Value entry:", sensordata._fields) if ref.record: self.log("Recording updated reference:", sensordata._fields) sensordata.save() ref.lastvalue = str(value) ref.timestamp = timestamp else: self.log("Unknown sensor data received!", data, lvl=warn)
def configuration(self, event): try: self.log("Schemarequest for all configuration schemata from", event.user.account.name, lvl=debug) response = { 'component': 'hfos.events.schemamanager', 'action': 'configuration', 'data': configschemastore } self.fireEvent(send(event.client.uuid, response)) except Exception as e: self.log("ERROR:", e)
def userlogin(self, event): """Checks if an alert is ongoing and alerts the newly connected client, if so.""" client_uuid = event.clientuuid if self.mob_alert: alert_packet = { 'component': 'hfos.alert.manager', 'action': 'alert', 'data': True } self.fireEvent(send(client_uuid, alert_packet))
def _updateSubscribers(self, updateobject): # Notify frontend subscribers self.log('Notifying subscribers about update.', lvl=debug) if updateobject.uuid in self.subscriptions: update = {'component': 'objectmanager', 'action': 'update', 'data': updateobject.serializablefields() } for recipient in self.subscriptions[updateobject.uuid]: self.log('Notifying subscriber: ', recipient, lvl=verbose) self.fireEvent(send(recipient, update))
def camera_list(self, event): try: client_uuid = event.client.uuid db_list = self._generate_camera_list() self.fireEvent( send( client_uuid, { 'component': 'hfos.camera.manager', 'action': 'list', 'data': db_list }), "hfosweb") except Exception as e: self.log("Listing error: ", e, type(e), lvl=error)
def control_request(self, event): username = event.user.account.name client_name = event.client.name client_uuid = event.client.uuid self.log("Client wants to remote control: ", username, client_name, lvl=warn) if not self.remote_controller: self.log("Success!") self.remote_controller = client_uuid self.fireEvent(send(client_uuid, { 'component': 'hfos.robot.rcmanager', 'action': 'control_request', 'data': True })) else: self.log("No, we're already being remote controlled!") self.fireEvent(send(client_uuid, { 'component': 'hfos.robot.rcmanager', 'action': 'control_request', 'data': False })) return
def get_events(self, event): self.log('Automatable event list requested:', event.user.account.name) events = deepcopy(self.authorized_events) for source in events: for value in events[source].values(): del (value['event']) packet = { 'component': 'hfos.automat.manager', 'action': 'get_events', 'data': events } self.fireEvent(send(event.client.uuid, packet))
def _check_flood_protection(self, component, action, clientuuid): if clientuuid not in self._flood_counter: self._flood_counter[clientuuid] = 0 self._flood_counter[clientuuid] += 1 if self._flood_counter[clientuuid] > 100: packet = { 'component': 'hfos.ui.clientmanager', 'action': 'Flooding', 'data': True } self.fireEvent(send(clientuuid, packet)) self.log('Flooding from', clientuuid) return True
def history(self, event): try: channel = event.data['channel'] limit = event.data['limit'] end = event.data['end'] except (KeyError, AttributeError) as e: self.log('Error during event lookup:', e, type(e), exc=True, lvl=error) return self.log('History requested:', channel, limit, end) messages = [] om = objectmodels['chatmessage'] try: for msg in om.find( { 'recipient': channel, 'timestamp': { '$lte': end } }, sort=[('timestamp', -1)], limit=limit): messages.insert(0, msg.serializablefields()) except Exception as e: self.log('Error during history lookup:', e, type(e), exc=True, lvl=error) return history_packet = { 'component': 'hfos.chat.host', 'action': 'history', 'data': { 'channel': channel, 'limit': limit, 'end': end, 'history': messages } } self.fireEvent(send(event.client.uuid, history_packet))
def sensed(self, event): sensed = [] for value in self.sensed.values(): sensed.append(value.serializablefields()) packet = { 'component': 'hfos.navdata.sensors', 'action': 'sensed', 'data': { 'sensed': sensed } } self.log("Transmitting list of sensed values:", self.sensed) self.fireEvent(send(event.client.uuid, packet), 'hfosweb')
def control_release(self, event): username = event.user.account.name client_name = event.client.name client_uuid = event.client.uuid if self.remote_controller == event.client.uuid: self.log("Client leaves control!", username, client_name, lvl=warn) # TODO: Switch to a possible fallback controller self.remote_controller = None self.fireEvent(send(client_uuid, { 'component': 'hfos.robot.rcmanager', 'action': 'control_release', 'data': True })) return
def camerarequest(self, event): """ Handles new camera category requests :param event: CameraRequest with actions * subscribe * unsubscribe * update """ self.log("Event: '%s'" % event.__dict__) try: try: action = event.action data = event.data clientuuid = event.client.uuid except Exception as e: raise ValueError("[CAM] Problem during event unpacking:", e, type(e)) if action == "list": try: dblist = self._generatecameralist() self.fireEvent( send(clientuuid, {"component": "camera", "action": "list", "data": dblist}), "hfosweb" ) except Exception as e: self.log("Listing error: ", e, type(e), lvl=error) return elif action == "get": return elif action == "subscribe": # TODO: Verify everything and send a response if data in self._subscribers: if clientuuid not in self._subscribers[data]: self._subscribers[data].append(clientuuid) else: self._subscribers[data] = [clientuuid] self.log("Subscription registered: ", data, clientuuid) return elif action == "unsubscribe": self._unsubscribe(clientuuid, data) return except Exception as e: self.log("Global Error: '%s' %s" % (e, type(e)), lvl=error)
def accept(self, event): def fail(uuid): self.log('Sending failure feedback to', uuid, lvl=debug) fail_msg = { 'component': 'hfos.enrol.manager', 'action': 'accept', 'data': False } self.fireEvent(send(uuid, fail_msg)) self.log('Invitation accepted:', event.__dict__, lvl=debug) try: enrollment = objectmodels['enrollment'].find_one({ 'uuid': event.data }) if enrollment is not None: self.log('Enrollment found', lvl=debug) if enrollment.status == 'Open': self.log('Enrollment is still open', lvl=debug) if enrollment.method in ('Invited', 'Manual') and \ self.config.auto_accept: enrollment.status = 'Accepted' data = 'You can now log in to the system and start to use it.' # TODO: Actually create account else: enrollment.status = 'Pending' data = 'Someone has to confirm your registration ' \ 'first. Thank you, for your patience.' # TODO: Alert admin users enrollment.save() packet = { 'component': 'hfos.enrol.manager', 'action': 'accept', 'data': {True: data} } self.fireEvent(send(event.client.uuid, packet)) else: self.log('Enrollment has been closed already!', lvl=warn) fail(event.client.uuid) else: self.log('No enrollment available.', lvl=warn) fail(event.client.uuid) except Exception as e: self.log('Error during invitation accept handling:', e, type(e), lvl=warn, exc=True)
def _on_exception(self, error_type, value, traceback, handler=None, fevent=None): try: s = [] if handler is None: handler = "" else: handler = reprhandler(handler) msg = "ERROR" msg += "{0:s} ({1:s}) ({2:s}): {3:s}\n".format( handler, repr(fevent), repr(error_type), repr(value)) s.append(msg) s.extend(traceback) s.append("\n") self.log("\n".join(s), lvl=critical) alert = { 'component': 'hfos.alert.manager', 'action': 'danger', 'data': { 'message': "\n".join(s), 'title': 'Exception Monitor' } } for user in self.config.notificationusers: self.fireEvent( send(None, alert, username=user, sendtype='user')) except Exception as e: self.log("Exception during exception handling: ", e, type(e), lvl=critical)
def broadcast(self, event): """Broadcasts an event either to all users or clients, depending on event flag""" try: if event.broadcasttype == "users": if len(self._users) > 0: self.log("Broadcasting to all users:", event.content, lvl=network) for useruuid in self._users.keys(): self.fireEvent( send(useruuid, event.content, sendtype="user")) # else: # self.log("Not broadcasting, no users connected.", # lvl=debug) elif event.broadcasttype == "clients": if len(self._clients) > 0: self.log("Broadcasting to all clients: ", event.content, lvl=network) for client in self._clients.values(): self.fireEvent(write(client.sock, event.content), "wsserver") # else: # self.log("Not broadcasting, no clients # connected.", # lvl=debug) elif event.broadcasttype == "socks": if len(self._sockets) > 0: self.log("Emergency?! Broadcasting to all sockets: ", event.content) for sock in self._sockets: self.fireEvent(write(sock, event.content), "wsserver") # else: # self.log("Not broadcasting, no sockets # connected.", # lvl=debug) except Exception as e: self.log("Error during broadcast: ", e, type(e), lvl=critical)
def rescan(self, event): self.log('Rescanning gdal map folder for new maps') charts = [] for (dirpath, dirnames, filenames) in os.walk(self.tilepath): charts.extend(dirnames) break self.log('Found folders:', charts, lvl=hilight) count = 0 for chart in charts: target = os.path.join(self.tilepath, chart) if os.path.exists(os.path.join(target, 'tilemapresource.xml')): self.log('Raster chart found:', chart) layer = objectmodels['layer'].find_one({'path': chart}) if layer is not None: self.log('Layer exists: ', layer.uuid, layer.name) else: self._register_map(chart, target, event.client) count += 1 else: self.log('Invalid raster tilecache found: ', chart, lvl=warn) if count > 0: data = 'Found and added %i new rasterchart' % count if count > 1: data += 's' data += ' during rasterchart rescan.' else: data = 'No new rastercharts added.' notification = { 'component': 'hfos.alert.manager', 'action': 'warning' if count == 0 else 'success', 'data': data } self.fireEvent(send(event.client.uuid, notification))
def say(self, event): """Chat event handler for incoming events :param event: say-event with incoming chat message """ try: userid = event.user.uuid recipient = self._get_recipient(event) content = self._get_content(event) message = objectmodels['chatmessage']({ 'timestamp': time(), 'recipient': recipient, 'sender': userid, 'content': content, 'uuid': std_uuid() }) message.save() chat_packet = { 'component': 'hfos.chat.host', 'action': 'say', 'data': message.serializablefields() } if recipient in self.chat_channels: for useruuid in self.users: if useruuid in self.chat_channels[recipient].users: self.log('User in channel', lvl=debug) self.update_lastlog(useruuid, recipient) self.log('Sending message', lvl=debug) self.fireEvent( send(useruuid, chat_packet, sendtype='user')) except Exception as e: self.log("Error: '%s' %s" % (e, type(e)), exc=True, lvl=error)
def _on_exception(self, error_type, value, traceback, handler=None, fevent=None): try: s = [] if handler is None: handler = "" else: handler = reprhandler(handler) msg = "ERROR" msg += "{0:s} ({1:s}) ({2:s}): {3:s}\n".format( handler, repr(fevent), repr(error_type), repr(value) ) s.append(msg) s.extend(traceback) s.append("\n") self.log("\n".join(s), lvl=critical) alert = { 'component': 'alert', 'action': 'danger', 'data': { 'message': "\n".join(s), 'title': 'Exception Monitor' } } for user in self.config.notificationusers: self.fireEvent(send(None, alert, username=user, sendtype='user')) except Exception as e: self.log("Exception during exception handling: ", e, type(e), lvl=critical)
def _send_status(self, user_uuid, client_uuid=None): try: joined = [] for uuid, channel in self.chat_channels.items(): if user_uuid in channel.users: joined.append(uuid) unread = self._get_unread(user_uuid) self.log('User joined:', joined, ' and has unread:', unread, pretty=True, lvl=debug) packet = { 'component': 'hfos.chat.host', 'action': 'status', 'data': { 'joined': joined, 'unread': unread } } if not client_uuid: uuid = user_uuid sendtype = 'user' else: uuid = client_uuid sendtype = 'client' self.fireEvent(send(uuid, packet, sendtype=sendtype)) except Exception as e: self.log('Error', e, type(e), lvl=error, exc=True)
def navdatarequest(self, event): if event.action == "list": if event.data == "sensed": packet = {"component": "navdata", "action": "list", "data": {"sensed": None}} sensed = [] for value in self.sensed.values(): sensed.append(value.serializablefields()) packet["data"]["sensed"] = sensed self.log("Transmitting list of sensed values:", self.sensed) self.fireEvent(send(event.client.uuid, packet), "hfosweb") elif event.action == "subscribe": self.log("Navdata subscription requested for", event.data) for item in event.data: if item in self.subscriptions: self.subscriptions[item].append(event.client.uuid) self.log("Appended subscription for ", item) else: self.subscriptions[item] = [event.client.uuid] self.log("Created new subscription for ", item)
def sensordata(self, event): """ Generates a new reference frame from incoming sensordata :param event: new sensordata to be merged into referenceframe """ if len(self.datatypes) == 0: return data = event.data timestamp = event.timestamp # bus = event.bus # TODO: What about multiple busses? That is prepared, but how exactly # should they be handled? self.log("New incoming navdata:", data, lvl=verbose) for name, value in data.items(): if name in self.datatypes: ref = self.datatypes[name] self.sensed[name] = ref if ref.lastvalue != str(value): # self.log("Reference outdated:", ref._fields) item = { 'value': value, 'timestamp': timestamp, 'type': name } self.referenceframe[name] = value self.referenceages[name] = timestamp # self.log("Subscriptions:", self.subscriptions, ref.name) if ref.name in self.subscriptions: packet = { 'component': 'hfos.navdata.sensors', 'action': 'update', 'data': item } self.log("Serving update: ", packet, lvl=verbose) for uuid in self.subscriptions[ref.name]: self.log("Serving to ", uuid, lvl=events) self.fireEvent(send(uuid, packet), 'hfosweb') # self.log("New item: ", item) sensordata = objectmodels['sensordata'](item) # self.log("Value entry:", sensordata._fields) if ref.record: self.log("Recording updated reference:", sensordata._fields) sensordata.save() ref.lastvalue = str(value) ref.timestamp = timestamp else: self.log("Unknown sensor data received!", data, lvl=warn)
def _augment_book(self, uuid, event): """ Checks if the newly created object is a book and only has an ISBN. If so, tries to fetch the book data off the internet. :param uuid: uuid of book to augment :param client: requesting client """ try: if not isbnmeta: self.log( "No isbntools found! Install it to get full " "functionality!", lvl=warn) return new_book = objectmodels['book'].find_one({'uuid': uuid}) try: if len(new_book.isbn) != 0: self.log('Got a lookup candidate: ', new_book._fields) try: meta = isbnmeta(new_book.isbn, service=self.config.isbnservice) mapping = libraryfieldmapping[self.config.isbnservice] new_meta = {} for key in meta.keys(): if key in mapping: if isinstance(mapping[key], tuple): name, conv = mapping[key] try: new_meta[name] = conv(meta[key]) except ValueError: self.log('Bad value from lookup:', name, conv, key) else: new_meta[mapping[key]] = meta[key] new_book.update(new_meta) new_book.save() self._notify_result(event, new_book) self.log("Book successfully augmented from ", self.config.isbnservice) except Exception as e: self.log("Error during meta lookup: ", e, type(e), new_book.isbn, lvl=error, exc=True) error_response = { 'component': 'hfos.alert.manager', 'action': 'error', 'data': 'Could not look up metadata, sorry:' + str(e) } self.log(event, event.client, pretty=True) self.fireEvent(send(event.client.uuid, error_response)) except Exception as e: self.log("Error during book update.", e, type(e), exc=True, lvl=error) except Exception as e: self.log("Book creation notification error: ", uuid, e, type(e), lvl=error, exc=True)
def authenticationrequest(self, event): """Handles authentication requests from clients :param event: AuthenticationRequest with user's credentials """ # TODO: Refactor to simplify if event.auto: self.log("Verifying automatic login request") try: clientconfig = objectmodels['client'].find_one({ 'uuid': event.requestedclientuuid }) except Exception: clientconfig = None if clientconfig is None or clientconfig.autologin is False: self.log("Autologin failed:", event.requestedclientuuid, lvl=error) return if clientconfig.autologin is True: try: useraccount = objectmodels['user'].find_one({ 'uuid': clientconfig.owner }) self.log("Autologin for", useraccount.name, lvl=debug) except Exception as e: self.log("No user object due to error: ", e, type(e), lvl=error) try: userprofile = objectmodels['profile'].find_one({ 'owner': str(useraccount.uuid) }) self.log("Profile: ", userprofile, useraccount.uuid, lvl=debug) useraccount.passhash = "" self.fireEvent( authentication(useraccount.name, ( useraccount, userprofile, clientconfig), event.clientuuid, useraccount.uuid, event.sock), "auth") self.log("Autologin successful!", lvl=warn) except Exception as e: self.log("No profile due to error: ", e, type(e), lvl=error) else: self.log("Auth request for ", event.username, event.clientuuid) # TODO: Move registration to its own part # TODO: Define the requirements for secure passwords etc. if (len(event.username) < 3) or (len(event.password) < 3): self.log("Illegal username or password received, " "login cancelled", lvl=warn) notification = { 'component': 'auth', 'action': 'fail', 'data': 'Password or username too short' } self.fireEvent(send(event.clientuuid, notification, sendtype='client')) return useraccount = None clientconfig = None userprofile = None # TODO: Notify problems here back to the frontend try: useraccount = objectmodels['user'].find_one({ 'name': event.username }) self.log("Account: %s" % useraccount._fields, lvl=debug) except Exception as e: self.log("No userobject due to error: ", e, type(e), lvl=error) if useraccount: self.log("User found.", lvl=debug) if self.makehash(event.password) == useraccount.passhash: self.log("Passhash matches, checking client and profile.", lvl=debug) requestedclientuuid = event.requestedclientuuid # Client requests to get an existing client # configuration or has none clientconfig = objectmodels['client'].find_one({ 'uuid': requestedclientuuid }) if clientconfig: self.log("Checking client configuration permissions", lvl=debug) if clientconfig.owner != useraccount.uuid: clientconfig = None self.log("Unauthorized client configuration " "requested", lvl=warn) else: self.log("Unknown client configuration requested: ", requestedclientuuid, event.__dict__, lvl=warn) if not clientconfig: self.log("Creating new default client configuration") # Either no configuration was found or requested # -> Create a new client configuration uuid = event.clientuuid if event.clientuuid is not \ None else str(uuid4()) clientconfig = objectmodels['client']({'uuid': uuid}) clientconfig.name = "New client" clientconfig.description = "New client configuration" \ " from " + useraccount.name clientconfig.owner = useraccount.uuid # TODO: Make sure the profile is only saved if the # client could store it, too clientconfig.save() try: userprofile = objectmodels['profile'].find_one( {'owner': str(useraccount.uuid)}) self.log("Profile: ", userprofile, useraccount.uuid, lvl=debug) useraccount.passhash = "" self.fireEvent( authentication(useraccount.name, ( useraccount, userprofile, clientconfig), event.clientuuid, useraccount.uuid, event.sock), "auth") except Exception as e: self.log("No profile due to error: ", e, type(e), lvl=error) else: self.log("Password was wrong!", lvl=warn) self.fireEvent(send(event.clientuuid, { 'component': 'auth', 'action': 'fail', 'data': 'N/A' }, sendtype="client"), "hfosweb") self.log("Done with Login request", lvl=debug) elif self.systemconfig.allowregister: self.createuser(event) else: self.log('User not found and system configuration does not ' 'allow new users to be created', lvl=warn)
def objectmanagerrequest(self, event): """OM event handler for incoming events :param event: OMRequest with incoming OM pagename and pagedata """ self.log("Event: '%s'" % event.__dict__) action = event.action data = event.data if action not in ['subscribe', 'unsubscribe']: if 'schema' in data: schema = data['schema'] else: self.log("No Schema given, cannot act!", lvl=critical) return if 'filter' in data: objectfilter = data['filter'] else: objectfilter = {} result = None notification = None if action == "list": if schema in objectmodels.keys(): if 'fields' in data: fields = data['fields'] else: fields = [] objlist = [] if objectmodels[schema].count(objectfilter) > WARNSIZE: self.log("Getting a very long list of items for ", schema, lvl=warn) for item in objectmodels[schema].find(objectfilter): try: if fields in ('*', ['*']): objlist.append(item.serializablefields()) else: listitem = {'uuid': item.uuid} if 'name' in item._fields: listitem['name'] = item._fields['name'] for field in fields: if field in item._fields: listitem[field] = item._fields[field] else: listitem[field] = None objlist.append(listitem) except Exception as e: self.log("Faulty object or field: ", e, type(e), item._fields, fields, lvl=error, exc=True) self.log("Generated object list: ", objlist) result = {'component': 'objectmanager', 'action': 'list', 'data': {'schema': schema, 'list': objlist } } else: self.log("Schemata: ", objectmodels.keys()) self.log("List for unavailable schema requested: ", schema, lvl=warn) elif action == "search": if schema in objectmodels.keys(): # objectfilter['$text'] = {'$search': str(data['search'])} objectfilter = { 'name': {'$regex': str(data['search']), '$options': '$i'}} # if 'fields' in data: # fields = data['fields'] # else: fields = [] reqid = data['req'] objlist = [] if collections[schema].count() > WARNSIZE: self.log("Getting a very long list of items for ", schema, lvl=warn) self.log("Objectfilter: ", objectfilter, ' Schema: ', schema, lvl=warn) # for item in collections[schema].find(objectfilter): for item in collections[schema].find(objectfilter): self.log("Search found item: ", item, lvl=warn) try: # TODO: Fix bug in warmongo that needs this workaround: item = objectmodels[schema](item) listitem = {'uuid': item.uuid} if 'name' in item._fields: listitem['name'] = item.name for field in fields: if field in item._fields: listitem[field] = item._fields[field] else: listitem[field] = None objlist.append(listitem) except Exception as e: self.log("Faulty object or field: ", e, type(e), item._fields, fields, lvl=error) self.log("Generated object search list: ", objlist) result = {'component': 'objectmanager', 'action': 'search', 'data': {'schema': schema, 'list': objlist, 'req': reqid } } else: self.log("List for unavailable schema requested: ", schema, lvl=warn) elif action == "get": if 'subscribe' in data: subscribe = data['subscribe'] is True else: subscribe = False try: uuid = str(data['uuid']) except (KeyError, TypeError): uuid = "" if objectfilter == {}: if uuid == "": self.log('Object with no filter/uuid requested:', schema, data, lvl=error) return objectfilter = {'uuid': uuid} storageobject = None if schema in objectmodels.keys(): storageobject = objectmodels[schema].find_one(objectfilter) if not storageobject: if uuid.upper == "CREATE": # TODO: Fix this, a request for an existing object is a # request for an existing object, a creation request is # not. self.log("Object not found, creating: ", data) storageobject = objectmodels[schema]({'uuid': str(uuid4())}) if "useruuid" in schemastore[schema]['schema']['properties']: storageobject.useruuid = event.user.uuid self.log("Attached initial owner's id: ", event.user.uuid) else: self.log("Object not found and not willing to create.", lvl=warn) result = { 'component': 'objectmanager', 'action': 'nonexistant', 'data': { 'schema': schema, } } else: self.log('Object for invalid schema requested!', schema, lvl=error) if storageobject: self.log("Object found, delivering: ", data) if subscribe and uuid != "": self.log('Updating subscriptions', lvl=debug) if uuid in self.subscriptions: if not event.client.uuid in self.subscriptions[uuid]: self.subscriptions[uuid].append(event.client.uuid) else: self.subscriptions[uuid] = [event.client.uuid] result = {'component': 'objectmanager', 'action': 'get', 'data': storageobject.serializablefields() } elif action == "subscribe": uuid = data if uuid in self.subscriptions: if not event.client.uuid in self.subscriptions[uuid]: self.subscriptions[uuid].append(event.client.uuid) else: self.subscriptions[uuid] = [event.client.uuid] result = {'component': 'objectmanager', 'action': 'subscribe', 'data': {'uuid': uuid, 'success': True} } elif action == "unsubscribe": # TODO: Automatic Unsubscription uuid = data if uuid in self.subscriptions: self.subscriptions[uuid].remove(event.client.uuid) if len(self.subscriptions[uuid]) == 0: del (self.subscriptions[uuid]) result = {'component': 'objectmanager', 'action': 'unsubscribe', 'data': {'uuid': uuid, 'success': True} } elif action == "put": result, notification = self._put(schema, data) elif action == 'delete': result, notification = self._delete(schema, data) elif action == 'change': result, notification = self._change(schema, data) else: self.log("Unsupported action: ", action, event, event.__dict__, lvl=warn) return if notification: try: self.fireEvent(notification) except Exception as e: self.log("Transmission error during notification: %s" % e, lvl=error) if result: try: self.fireEvent(send(event.client.uuid, result)) except Exception as e: self.log("Transmission error during response: %s" % e, lvl=error)
def createuser(self, event): self.log("Creating user") try: newuser = objectmodels['user']({ 'name': event.username, 'passhash': self.makehash(event.password), 'uuid': str(uuid4()) }) newuser.save() except Exception as e: self.log("Problem creating new user: "******"New profile uuid: ", newprofile.uuid, lvl=verbose) # TODO: Fix this - yuk! newprofile.components = { 'enabled': ["dashboard", "map", "weather", "settings"] } newprofile.save() except Exception as e: self.log("Problem creating new profile: ", type(e), e, lvl=error) return try: # TODO: Clone or reference systemwide default configuration uuid = event.clientuuid if event.clientuuid is not None else str( uuid4()) newclientconfig = objectmodels['client']({'uuid': uuid}) newclientconfig.name = "New client" newclientconfig.description = "New client configuration " \ "from " + newuser.name newclientconfig.owner = newuser.uuid newclientconfig.save() except Exception as e: self.log("Problem creating new clientconfig: ", type(e), e, lvl=error) return try: self.fireEvent( authentication(newuser.name, (newuser, newprofile, newclientconfig), event.clientuuid, newuser.uuid, event.sock), "auth") self.fireEvent( send(event.clientuuid, { 'component': 'auth', 'action': 'new', 'data': 'registration successful' }, sendtype="client"), "hfosweb") except Exception as e: self.log("Error during new account confirmation transmission", e, lvl=error)
def authenticationrequest(self, event): """Handles authentication requests from clients :param event: AuthenticationRequest with user's credentials """ # TODO: Refactor to simplify if event.auto: self.log("Verifying automatic login request") try: clientconfig = objectmodels['client'].find_one( {'uuid': event.requestedclientuuid}) except Exception: clientconfig = None if clientconfig is None or clientconfig.autologin is False: self.log("Autologin failed:", event.requestedclientuuid, lvl=error) return if clientconfig.autologin is True: try: useraccount = objectmodels['user'].find_one( {'uuid': clientconfig.owner}) self.log("Autologin for", useraccount.name, lvl=debug) except Exception as e: self.log("No user object due to error: ", e, type(e), lvl=error) try: userprofile = objectmodels['profile'].find_one( {'owner': str(useraccount.uuid)}) self.log("Profile: ", userprofile, useraccount.uuid, lvl=debug) useraccount.passhash = "" self.fireEvent( authentication( useraccount.name, (useraccount, userprofile, clientconfig), event.clientuuid, useraccount.uuid, event.sock), "auth") self.log("Autologin successful!", lvl=warn) except Exception as e: self.log("No profile due to error: ", e, type(e), lvl=error) else: self.log("Auth request for ", event.username, event.clientuuid) # TODO: Move registration to its own part # TODO: Define the requirements for secure passwords etc. if (len(event.username) < 3) or (len(event.password) < 3): self.log( "Illegal username or password received, " "login cancelled", lvl=warn) notification = { 'component': 'auth', 'action': 'fail', 'data': 'Password or username too short' } self.fireEvent( send(event.clientuuid, notification, sendtype='client')) return useraccount = None clientconfig = None userprofile = None # TODO: Notify problems here back to the frontend try: useraccount = objectmodels['user'].find_one( {'name': event.username}) self.log("Account: %s" % useraccount._fields, lvl=debug) except Exception as e: self.log("No userobject due to error: ", e, type(e), lvl=error) if useraccount: self.log("User found.", lvl=debug) if self.makehash(event.password) == useraccount.passhash: self.log("Passhash matches, checking client and profile.", lvl=debug) requestedclientuuid = event.requestedclientuuid # Client requests to get an existing client # configuration or has none clientconfig = objectmodels['client'].find_one( {'uuid': requestedclientuuid}) if clientconfig: self.log("Checking client configuration permissions", lvl=debug) if clientconfig.owner != useraccount.uuid: clientconfig = None self.log( "Unauthorized client configuration " "requested", lvl=warn) else: self.log("Unknown client configuration requested: ", requestedclientuuid, event.__dict__, lvl=warn) if not clientconfig: self.log("Creating new default client configuration") # Either no configuration was found or requested # -> Create a new client configuration uuid = event.clientuuid if event.clientuuid is not \ None else str(uuid4()) clientconfig = objectmodels['client']({'uuid': uuid}) clientconfig.name = "New client" clientconfig.description = "New client configuration" \ " from " + useraccount.name clientconfig.owner = useraccount.uuid # TODO: Make sure the profile is only saved if the # client could store it, too clientconfig.save() try: userprofile = objectmodels['profile'].find_one( {'owner': str(useraccount.uuid)}) self.log("Profile: ", userprofile, useraccount.uuid, lvl=debug) useraccount.passhash = "" self.fireEvent( authentication( useraccount.name, (useraccount, userprofile, clientconfig), event.clientuuid, useraccount.uuid, event.sock), "auth") except Exception as e: self.log("No profile due to error: ", e, type(e), lvl=error) else: self.log("Password was wrong!", lvl=warn) self.fireEvent( send(event.clientuuid, { 'component': 'auth', 'action': 'fail', 'data': 'N/A' }, sendtype="client"), "hfosweb") self.log("Done with Login request", lvl=debug) elif self.systemconfig.allowregister: self.createuser(event) else: self.log( 'User not found and system configuration does not ' 'allow new users to be created', lvl=warn)
def reserve(self, event): try: uuid = event.data['uuid'] reserve_from = event.data['from'] reserve_to = event.data['to'] reserve_title = None if 'title' not in event.data else \ event.data['title'] reserve_description = "" if 'description' not in event.data \ else event.data['description'] shareable_model = objectmodels['shareable'] shareable = shareable_model.find_one({'uuid': uuid}) early = shareable_model.find_one({ 'uuid': uuid, 'reservations': { '$elemMatch': { 'starttime': { '$lte': reserve_from }, 'endtime': { '$gte': reserve_from } } } }) self.log('Any early reservation:', early, lvl=debug) late = shareable_model.find_one({ 'uuid': uuid, 'reservations': { '$elemMatch': { 'starttime': { '$lte': reserve_to }, 'endtime': { '$gte': reserve_to } } } }) self.log('Any late reservation:', late, lvl=debug) if not late and not early: reservation = { 'useruuid': event.user.uuid, 'starttime': reserve_from, 'endtime': reserve_to, 'title': reserve_title if reserve_title else "Reserved by " + event.user.account.name, 'description': reserve_description } shareable.reservations.append(reservation) shareable.save() self.log('Successfully stored reservation!') response = { 'component': 'hfos.shareables.manager', 'action': 'reserve', 'data': True } else: self.log('Not able to store reservation due to ' 'overlapping reservations.') response = { 'component': 'hfos.shareables.manager', 'action': 'reserve', 'data': False } self.fireEvent(send(event.client.uuid, response)) except Exception as e: self.log('Unknown failure:', e, type(e), exc=True)