diff options
author | 2013-03-11 19:49:20 +0100 | |
---|---|---|
committer | 2013-03-11 19:50:54 +0100 | |
commit | 763b142db70ce77952cb46cfccf84d9800f15651 (patch) | |
tree | d2636e48766d365bd8a9d079de603b127ab88744 /module/remote/wsbackend | |
parent | Merge pull request #33 from stickell/patch-3 (diff) | |
download | pyload-763b142db70ce77952cb46cfccf84d9800f15651.tar.xz |
websocket login via session, websocket pushes server status, webui renders server status
Diffstat (limited to 'module/remote/wsbackend')
-rw-r--r-- | module/remote/wsbackend/AbstractHandler.py | 54 | ||||
-rw-r--r-- | module/remote/wsbackend/ApiHandler.py | 13 | ||||
-rw-r--r-- | module/remote/wsbackend/AsyncHandler.py | 35 |
3 files changed, 72 insertions, 30 deletions
diff --git a/module/remote/wsbackend/AbstractHandler.py b/module/remote/wsbackend/AbstractHandler.py index f843fc278..45fbb134c 100644 --- a/module/remote/wsbackend/AbstractHandler.py +++ b/module/remote/wsbackend/AbstractHandler.py @@ -41,11 +41,38 @@ class AbstractHandler: def do_extra_handshake(self, req): self.log.debug("WS Connected: %s" % req) + req.api = None #when api is set client is logged in + + # allow login via session when webinterface is active + if self.core.config['webinterface']['activated']: + cookie = req.headers_in.getheader('Cookie') + s = self.load_session(cookie) + if s: + uid = s.get('uid', None) + req.api = self.api.withUserContext(uid) + self.log.debug("WS authenticated with cookie: %d" % uid) + self.on_open(req) def on_open(self, req): pass + def load_session(self, cookies): + from Cookie import SimpleCookie + from beaker.session import Session + from module.web.webinterface import session + + cookies = SimpleCookie(cookies) + sid = cookies.get(session.options['key']) + if not sid: + return None + + s = Session({}, use_cookies=False, id=sid.value, **session.options) + if s.is_new: + return None + + return s + def passive_closing_handshake(self, req): self.log.debug("WS Closed: %s" % req) self.on_close(req) @@ -59,8 +86,6 @@ class AbstractHandler: def handle_call(self, msg, req): """ Parses the msg for an argument call. If func is null an response was already sent. - :param msg: - :param req: :return: func, args, kwargs """ try: @@ -70,11 +95,15 @@ class AbstractHandler: self.send_result(req, self.ERROR, "No JSON request") return None, None, None - if type(o) != list and len(o) not in range(1,4): + if not isinstance(o, basestring) and type(o) != list and len(o) not in range(1, 4): self.log.debug("Invalid Api call: %s" % o) self.send_result(req, self.ERROR, "Invalid Api call") return None, None, None - if len(o) == 1: # arguments omitted + + # called only with name, no args + if isinstance(o, basestring): + return o, [], {} + elif len(o) == 1: # arguments omitted return o[0], [], {} elif len(o) == 2: func, args = o @@ -85,5 +114,20 @@ class AbstractHandler: else: return tuple(o) + def do_login(self, req, args, kwargs): + user = self.api.checkAuth(*args, **kwargs) + if user: + req.api = self.api.withUserContext(user.uid) + return self.send_result(req, self.OK, True) + else: + return self.send_result(req, self.FORBIDDEN, "Forbidden") + + def do_logout(self, req): + req.api = None + return self.send_result(req, self.OK, True) + def send_result(self, req, code, result): - return send_message(req, dumps([code, result]))
\ No newline at end of file + return send_message(req, dumps([code, result])) + + def send(self, req, obj): + return send_message(req, dumps(obj))
\ No newline at end of file diff --git a/module/remote/wsbackend/ApiHandler.py b/module/remote/wsbackend/ApiHandler.py index eec546d47..e985e10be 100644 --- a/module/remote/wsbackend/ApiHandler.py +++ b/module/remote/wsbackend/ApiHandler.py @@ -55,18 +55,9 @@ class ApiHandler(AbstractHandler): return # handle_call already sent the result if func == 'login': - user = self.api.checkAuth(*args, **kwargs) - if user: - req.api = self.api.withUserContext(user.uid) - return self.send_result(req, self.OK, True) - - else: - return self.send_result(req, self.OK, False) - + return self.do_login(req, args, kwargs) elif func == 'logout': - req.api = None - return self.send_result(req, self.OK, True) - + return self.do_logout(req) else: if not req.api: return self.send_result(req, self.FORBIDDEN, "Forbidden") diff --git a/module/remote/wsbackend/AsyncHandler.py b/module/remote/wsbackend/AsyncHandler.py index a8382a211..2f9b43ad2 100644 --- a/module/remote/wsbackend/AsyncHandler.py +++ b/module/remote/wsbackend/AsyncHandler.py @@ -16,7 +16,7 @@ # @author: RaNaN ############################################################################### -from Queue import Queue +from Queue import Queue, Empty from threading import Lock from mod_pywebsocket.msgutil import receive_message @@ -34,13 +34,13 @@ class AsyncHandler(AbstractHandler): Progress information are continuous and will be pushed in a fixed interval when available. After connect you have to login and can set the interval by sending the json command ["setInterval", xy]. - To start receiving updates call "start", afterwards no more incoming messages will be accept! + To start receiving updates call "start", afterwards no more incoming messages will be accepted! """ PATH = "/async" COMMAND = "start" - PROGRESS_INTERVAL = 1 + PROGRESS_INTERVAL = 2 STATUS_INTERVAL = 60 def __init__(self, api): @@ -57,7 +57,10 @@ class AsyncHandler(AbstractHandler): @lock def on_close(self, req): - self.clients.remove(req) + try: + self.clients.remove(req) + except ValueError: # ignore when not in list + pass @lock def add_event(self, event): @@ -86,21 +89,15 @@ class AsyncHandler(AbstractHandler): return # Result was already sent if func == 'login': - user = self.api.checkAuth(*args, **kwargs) - if user: - req.api = self.api.withUserContext(user.uid) - return self.send_result(req, self.OK, True) - - else: - return self.send_result(req, self.FORBIDDEN, "Forbidden") + return self.do_login(req, args, kwargs) elif func == 'logout': - req.api = None - return self.send_result(req, self.OK, True) + return self.do_logout(req) else: if not req.api: return self.send_result(req, self.FORBIDDEN, "Forbidden") + if func == "setInterval": req.interval = args[0] elif func == self.COMMAND: @@ -109,4 +106,14 @@ class AsyncHandler(AbstractHandler): def mode_running(self, req): """ Listen for events, closes socket when returning True """ - self.send_result(req, "update", "test")
\ No newline at end of file + try: + ev = req.queue.get(True, req.interval) + self.send(req, ev) + + except Empty: + # TODO: server status is not enough + # modify core api to include progress? think of other needed information to show + # notifications + + self.send(req, self.api.getServerStatus()) + self.send(req, self.api.getProgressInfo())
\ No newline at end of file |