diff options
author | RaNaN <Mast3rRaNaN@hotmail.de> | 2013-06-09 18:10:22 +0200 |
---|---|---|
committer | RaNaN <Mast3rRaNaN@hotmail.de> | 2013-06-09 18:10:23 +0200 |
commit | 16af85004c84d0d6c626b4f8424ce9647669a0c1 (patch) | |
tree | 025d479862d376dbc17e934f4ed20031c8cd97d1 /pyload/web/api_app.py | |
parent | adapted to jshint config (diff) | |
download | pyload-16af85004c84d0d6c626b4f8424ce9647669a0c1.tar.xz |
moved everything from module to pyload
Diffstat (limited to 'pyload/web/api_app.py')
-rw-r--r-- | pyload/web/api_app.py | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/pyload/web/api_app.py b/pyload/web/api_app.py new file mode 100644 index 000000000..3ffc507aa --- /dev/null +++ b/pyload/web/api_app.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from urllib import unquote +from itertools import chain +from traceback import format_exc, print_exc + +from bottle import route, request, response, HTTPError, parse_auth + +from utils import set_session, get_user_api +from webinterface import PYLOAD + +from pyload.Api import ExceptionObject +from pyload.remote.json_converter import loads, dumps +from pyload.utils import remove_chars + +def add_header(r): + r.headers.replace("Content-type", "application/json") + r.headers.append("Cache-Control", "no-cache, must-revalidate") + r.headers.append("Access-Control-Allow-Origin", request.get_header('Origin', '*')) + r.headers.append("Access-Control-Allow-Credentials", "true") + +# accepting positional arguments, as well as kwargs via post and get +# only forbidden path symbol are "?", which is used to separate GET data and # +@route("/api/<func><args:re:[^#?]*>") +@route("/api/<func><args:re:[^#?]*>", method="POST") +def call_api(func, args=""): + add_header(response) + + s = request.environ.get('beaker.session') + # Accepts standard http auth + auth = parse_auth(request.get_header('Authorization', '')) + if 'session' in request.POST or 'session' in request.GET: + # removes "' so it works on json strings + s = s.get_by_id(remove_chars(request.params.get('session'), "'\"")) + elif auth: + user = PYLOAD.checkAuth(auth[0], auth[1], request.environ.get('REMOTE_ADDR', None)) + # if auth is correct create a pseudo session + if user: s = {'uid': user.uid} + + api = get_user_api(s) + if not api: + return HTTPError(401, dumps("Unauthorized"), **response.headers) + + if not PYLOAD.isAuthorized(func, api.user): + return HTTPError(403, dumps("Forbidden"), **response.headers) + + if not hasattr(PYLOAD.EXTERNAL, func) or func.startswith("_"): + print "Invalid API call", func + return HTTPError(404, dumps("Not Found"), **response.headers) + + # TODO: possible encoding + # TODO Better error codes on invalid input + + args = [loads(unquote(arg)) for arg in args.split("/")[1:]] + kwargs = {} + + # accepts body as json dict + if request.json: + kwargs = request.json + + # convert arguments from json to obj separately + for x, y in chain(request.GET.iteritems(), request.POST.iteritems()): + if not x or not y or x == "session": continue + kwargs[x] = loads(unquote(y)) + + try: + result = getattr(api, func)(*args, **kwargs) + # null is invalid json response + if result is None: result = True + return dumps(result) + + except ExceptionObject, e: + return HTTPError(400, dumps(e), **response.headers) + except Exception, e: + print_exc() + return HTTPError(500, dumps({"error": e.message, "traceback": format_exc()}), **response.headers) + + +@route("/api/login") +@route("/api/login", method="POST") +def login(): + add_header(response) + + username = request.params.get("username") + password = request.params.get("password") + + user = PYLOAD.checkAuth(username, password, request.environ.get('REMOTE_ADDR', None)) + + if not user: + return dumps(False) + + s = set_session(request, user) + + # get the session id by dirty way, documentations seems wrong + try: + sid = s._headers["cookie_out"].split("=")[1].split(";")[0] + return dumps(sid) + except: + print "Could not get session" + return dumps(True) + + +@route("/api/logout") +@route("/api/logout", method="POST") +def logout(): + add_header(response) + + s = request.environ.get('beaker.session') + s.delete() + + return dumps(True) |