class Authorization: def __init__(self): self._spine = Spine() self._active = None @property def active(self): if self._active == None: self._active = self._spine.send_query("authorizationActive") return self._active def authorize(self, user_name, password): user = self._spine.send_query("authorizationAuthorizeUser", user_name, password) return user def allow_anonymous(self): return self._spine.send_query("authorizationAllowAnonymousUser") def valid_session_header(self, headers): return self._spine.send_query("authorizationValidSessionHeader", headers) def remove_session(self, session_id): return self._spine.send_command("authorizationRemoveSession", session_id) def get_users(self): return self._spine.send_query("authorizationGetUsers")
def is_session_valid(headers): spine = Spine() json_header = {} for header in headers: json_header[header] = headers[header] res = spine.send_query("validSessionHeader", json_header) return res
class Settings(object): """ Class that persists settings to the Kervi database. :param group: To avoid name clash with other settings in the Kervi application enter name to group your settings under. :type group: ``str`` """ def __init__(self, settings_group=None): self.group = settings_group self.spine = Spine() def store_value(self, name, value): """Store a value to DB""" self.spine.send_command("storeSetting", self.group, name, value) def retrieve_value(self, name, default_value=None): """Retrieve a value from DB""" value = self.spine.send_query("retrieveSetting", self.group, name, processes=["kervi-main"]) if value is None: return default_value elif isinstance(value, list) and len(value) == 0: return default_value elif isinstance(default_value, int): return int(value) elif isinstance(default_value, float): return float(value) else: return value
def do_GET(self): try: if self.server.do_authorize( ) and self.headers['Authorization'] == None: self.do_AUTHHEAD() #self.wfile.write('no auth header received') pass elif self.server.authorize(self.headers['Authorization']): if self.path.startswith("/cam"): path = self.path.split("/") cam_id = path[-1] spine = Spine() info = spine.send_query("getComponentInfo", cam_id) if info: conn = http.client.HTTPConnection( info["ui"]["source"]["server"], timeout=self.timeout) conn.request("GET", info["ui"]["source"]["path"]) res = conn.getresponse() self.send_response(res.status) for line in res.headers: self.send_header(line, res.headers[line]) self.end_headers() while not self.server.terminate: chunk = res.read(8192) if not chunk: break self.wfile.write(chunk) elif self.path.endswith("global.js"): self.send_response(200) self.send_header('Content-type', 'text/javascript') self.end_headers() if encryption.enabled(): response = bytes( "kerviSocketAddress='" + str(self.server.ip_address) + ":" + str(self.server.ws_port) + "';\n\rsocketProtocol='wss';", 'utf-8') else: response = bytes( "kerviSocketAddress='" + str(self.server.ip_address) + ":" + str(self.server.ws_port) + "';\n\rsocketProtocol='ws';", 'utf-8') self.wfile.write(response) elif self.path.endswith("kervitexts.js"): self.send_response(200) self.send_header('Content-type', 'text/javascript') self.end_headers() texts = json.dumps(self.server.texts) response = bytes("kerviUITexts=" + texts, 'utf-8') self.wfile.write(response) else: if self.path.startswith( "/dashboard/") or self.path.startswith("/connect"): path = self.server.docpath else: path = self.server.docpath + self.path if os.path.exists(path) and os.path.isdir(path): index_files = [ '/index.html', '/index.htm', ] for index_file in index_files: tmppath = path + index_file if os.path.exists(tmppath): path = tmppath break _, ext = os.path.splitext(path) ext = ext.lower() content_type = { '.css': 'text/css', '.gif': 'image/gif', '.htm': 'text/html', '.html': 'text/html', '.jpeg': 'image/jpeg', '.jpg': 'image/jpg', '.js': 'text/javascript', '.png': 'image/png', '.text': 'text/plain', '.txt': 'text/plain', } if ext in content_type: self.send_response(200) # OK self.send_header('Content-type', content_type[ext]) self.end_headers() with open(path, 'rb') as ifp: self.wfile.write(ifp.read()) else: self.send_response(200) # OK self.send_header('Content-type', 'text/plain') self.end_headers() with open(path, 'rb') as ifp: self.wfile.write(ifp.read()) else: self.do_AUTHHEAD() except IOError: self.send_error(404, 'file not found')
def active(): spine = Spine() res = spine.send_query("authorizationActive") return res
class _SpineProtocol(WebSocketServerProtocol): def __init__(self): self.spine = Spine() WebSocketServerProtocol.__init__(self) self.handlers = {"command": [], "query": [], "event": []} self.authenticated = False self.session = None self.user = None self._authorization = Authorization() def add_command_handler(self, command): found = False for command_handler in self.handlers["command"]: if command_handler.command == command: found = True if not found: self.handlers["command"] += [_WebCommandHandler(command, self)] def add_query_handler(self, query): found = False for query_handler in self.handlers["query"]: if query_handler.query == query: found = True if not found: self.handlers["query"] += [_WebQueryHandler(query, self)] def add_event_handler(self, event, id_event): #print("ah", event, id_event) found = False for event_handler in self.handlers["event"]: if event_handler.event == event and event_handler.id_event == id_event: found = True if not found: self.handlers["event"] += [_WebEventHandler(event, id_event, self)] def send_response(self, id, response, state="ok", message=""): res = { "id": id, "messageType": "response", "state": state, "message": message, "response": response } jsonres = json.dumps(res, ensure_ascii=False).encode('utf8') self.sendMessage(jsonres, False) def onConnect(self, request): #print("Web socket Client connecting: {}".format(request.peer)) pass def onOpen(self): if self._authorization.active: res = {"messageType": "authenticate"} else: self.authenticated = True res = { "messageType": "session_authenticated", "session": "123456", } jsonres = json.dumps(res, ensure_ascii=False).encode('utf8') self.sendMessage(jsonres, False) def onMessage(self, payload, is_binary): try: obj = json.loads(payload.decode('utf8')) if obj["messageType"] == "authenticate": session, user = self._authorization.authorize( obj["userName"], obj["password"]) if session is None: print("authorization failed for:", obj["userName"]) res = { "messageType": "authentication_failed", } #self.close() else: self.session = session self.user = user self.authenticated = True res = { "messageType": "session_authenticated", "session": session, } jsonres = json.dumps(res, ensure_ascii=False).encode('utf8') self.sendMessage(jsonres, False) elif obj["messageType"] == "logoff": self.authenticated = False self.session = None self._authorization.remove_session(obj["session"]) res = {"messageType": "session_logoff"} jsonres = json.dumps(res, ensure_ascii=False).encode('utf8') self.sendMessage(jsonres, False) else: self.spine.log.debug("WS onMessage:{0}", obj) if not self.authenticated: pass elif obj["messageType"] == "query": res = self.spine.send_query(obj["query"], *obj["args"], injected="socketSpine", session=self.user) self.spine.log.debug("query response:{0}", res) self.send_response(obj["id"], res) elif obj["messageType"] == "registerQueryHandler": self.add_query_handler(obj["query"]) self.send_response(None, None) elif obj["messageType"] == "command": self.spine.send_command(obj["command"], *obj["args"], injected="socketSpine", session=self.user) self.send_response(obj["id"], None) elif obj["messageType"] == "registerCommandHandler": self.add_command_handler(obj["command"]) self.send_response(obj["id"], None) elif obj["messageType"] == "event": self.spine.trigger_event(obj["event"], obj["id"], obj["args"], injected="socketSpine") self.send_response(obj["id"], None) elif obj["messageType"] == "registerEventHandler": self.add_event_handler(obj["event"], obj["eventId"]) self.send_response(obj["id"], None) except: self.spine.log.exception("WS onMessage exception")
class _SpineProtocol(WebSocketServerProtocol): loop = None def __init__(self): self.spine = Spine() WebSocketServerProtocol.__init__(self) self.handlers = {"command":[], "query":[], "event":[], "stream":[]} self.authenticated = False self.session = None self.user = None self._authorization = Authorization() @classmethod def broadcast_message(cls, connection, data, is_binary=False): #for c in set(cls.connections): cls.loop.call_soon_threadsafe(cls.sendMessage, connection, data, is_binary) def add_command_handler(self, command): found = False for command_handler in self.handlers["command"]: if command_handler.command == command: found = True if not found: self.handlers["command"] += [_WebCommandHandler(command, self)] def add_query_handler(self, query): found = False for query_handler in self.handlers["query"]: if query_handler.query == query: found = True if not found: self.handlers["query"] += [_WebQueryHandler(query, self)] def add_event_handler(self, event, id_event): found = False for event_handler in self.handlers["event"]: if event_handler.event == event and event_handler.id_event == id_event: found = True if not found: self.handlers["event"] += [_WebEventHandler(event, id_event, self)] def add_stream_handler(self, stream_id, stream_event): found = False for stream_handler in self.handlers["stream"]: if stream_handler.stream_id == stream_id: if stream_event and stream_handler.stream_event == stream_event: found = True elif not stream_event: found = True if not found: self.handlers["stream"] += [_WebStreamHandler(stream_id, stream_event, self)] def remove_stream_handler(self, stream_id, stream_event): #print("r", stream_id, stream_event) found_handler = None for stream_handler in self.handlers["stream"]: if stream_handler.stream_id == stream_id: if stream_event and stream_handler.stream_event == stream_event: found_handler = stream_handler elif not stream_event: found_handler = stream_handler if found_handler: found_handler.close() self.handlers["stream"].remove(found_handler) def send_response(self, id, response, state="ok", message=""): res = { "id":id, "messageType":"response", "state":state, "message":message, "response":response } jsonres = json.dumps(res, ensure_ascii=False).encode('utf8') self.sendMessage(jsonres, False) def onConnect(self, request): pass def onOpen(self): if self._authorization.active: res = { "messageType":"authenticate" } else: self.authenticated = True res = { "messageType":"session_authenticated", "session":"123456", } jsonres = json.dumps(res, ensure_ascii=False).encode('utf8') self.sendMessage(jsonres, False) # @asyncio.coroutine # def async_query(self, query, query_args, injected, session): # def do_req(): # return self.spine.send_query(query, *query_args, injected=injected, session=session) # #self.spine.log.debug("query response:{0}", res) # #self.send_response(obj["id"], res) # #return requests.get('https://api.github.com/user', auth=HTTPBasicAuth('user', 'pass')) # req = self.loop.run_in_executor(None, do_req) # resp = yield from req # return resp def onMessage(self, payload, is_binary): try: obj = json.loads(payload.decode('utf8')) if obj["messageType"] == "authenticate": session, user = self._authorization.authorize(obj["userName"], obj["password"]) if session is None: if obj["userName"] == "anonymous": self.spine.log.warning("Anonymous user disabled") else: self.spine.log.warning("authorization failed for: %s", obj["userName"]) res = { "messageType":"authentication_failed", } #self.close() else: self.session = session self.user = user self.authenticated = True res = { "messageType":"session_authenticated", "session":session, } jsonres = json.dumps(res, ensure_ascii=False).encode('utf8') self.sendMessage(jsonres, False) elif obj["messageType"] == "logoff": self.authenticated = False self.session = None self._authorization.remove_session(obj["session"]) res = { "messageType":"session_logoff" } jsonres = json.dumps(res, ensure_ascii=False).encode('utf8') self.sendMessage(jsonres, False) else: #self.spine.log.debug("WS onMessage:{0}", obj) if not self.authenticated: pass elif obj["messageType"] == "query": #res = yield from self.async_query(obj["query"], obj["args"], injected="socketSpine", session=self.user) res = self.spine.send_query(obj["query"], *obj["args"], injected="socketSpine", session=self.user) self.spine.log.debug("query response:{0}", res) self.send_response(obj["id"], res) elif obj["messageType"] == "registerQueryHandler": self.add_query_handler(obj["query"]) self.send_response(None, None) elif obj["messageType"] == "command": self.spine.send_command(obj["command"], *obj["args"], injected="socketSpine", session=self.user) self.send_response(obj["id"], None) elif obj["messageType"] == "registerCommandHandler": self.add_command_handler(obj["command"]) self.send_response(obj["id"], None) elif obj["messageType"] == "event": self.spine.trigger_event( obj["event"], obj["id"], obj["args"], injected="socketSpine" ) self.send_response(obj["id"], None) elif obj["messageType"] == "registerEventHandler": self.add_event_handler(obj["event"], obj["eventId"]) self.send_response(obj["id"], None) elif obj["messageType"] == "registerStreamHandler": self.add_stream_handler(obj["streamId"], obj["streamEvent"]) self.send_response(obj["id"], None) elif obj["messageType"] == "removeStreamHandler": self.remove_stream_handler(obj["streamId"], obj["streamEvent"]) self.send_response(obj["id"], None) except: self.spine.log.exception("WS onMessage exception")