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 | 
