diff options
Diffstat (limited to 'module/web/api_app.py')
| -rw-r--r-- | module/web/api_app.py | 47 | 
1 files changed, 28 insertions, 19 deletions
| diff --git a/module/web/api_app.py b/module/web/api_app.py index 1629c1677..b2d7fa5b6 100644 --- a/module/web/api_app.py +++ b/module/web/api_app.py @@ -7,10 +7,11 @@ from traceback import format_exc, print_exc  from bottle import route, request, response, HTTPError -from utils import toDict, set_session +from utils import set_session, get_user_api  from webinterface import PYLOAD  from module.common.json_layer import json +from module.utils import remove_chars, to_dict  from module.lib.SafeEval import const_eval as literal_eval  from module.Api import BaseObject @@ -19,26 +20,32 @@ class TBaseEncoder(json.JSONEncoder):      def default(self, o):          if isinstance(o, BaseObject): -            return toDict(o) +            return to_dict(o)          return json.JSONEncoder.default(self, o) -# accepting positional arguments, as well as kwargs via post and get +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", "*")  # allow xhr requests -@route("/api/:func:args#[a-zA-Z0-9\-_/\"'\[\]%{}]*#") -@route("/api/:func:args#[a-zA-Z0-9\-_/\"'\[\]%{}]*#", method="POST") +# 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=""): -    response.headers.replace("Content-type", "application/json") -    response.headers.append("Cache-Control", "no-cache, must-revalidate") +    add_header(response)      s = request.environ.get('beaker.session')      if 'session' in request.POST: -        s = s.get_by_id(request.POST['session']) +        # removes "' so it works on json strings +        s = s.get_by_id(remove_chars(request.POST['session'], "'\"")) -    if not s or not s.get("authenticated", False): +    api = get_user_api(s) +    if not api:          return HTTPError(403, json.dumps("Forbidden")) -    if not PYLOAD.isAuthorized(func, {"role": s["role"], "permission": s["perms"]}): +    if not PYLOAD.isAuthorized(func, api.user):          return HTTPError(401, json.dumps("Unauthorized"))      args = args.split("/")[1:] @@ -54,16 +61,18 @@ def call_api(func, args=""):          print_exc()          return HTTPError(500, json.dumps({"error": e.message, "traceback": format_exc()})) +# Better error codes on invalid input  def callApi(func, *args, **kwargs):      if not hasattr(PYLOAD.EXTERNAL, func) or func.startswith("_"):          print "Invalid API call", func          return HTTPError(404, json.dumps("Not Found")) +    # TODO: encoding      result = getattr(PYLOAD, func)(*[literal_eval(x) for x in args],                                     **dict([(x, literal_eval(y)) for x, y in kwargs.iteritems()])) -    # null is invalid json  response +    # null is invalid json response      if result is None: result = True      return json.dumps(result, cls=TBaseEncoder) @@ -72,31 +81,31 @@ def callApi(func, *args, **kwargs):  #post -> username, password  @route("/api/login", method="POST")  def login(): -    response.headers.replace("Content-type", "application/json") -    response.headers.append("Cache-Control", "no-cache, must-revalidate") +    add_header(response) -    user = request.forms.get("username") +    username = request.forms.get("username")      password = request.forms.get("password") -    info = PYLOAD.checkAuth(user, password) +    user = PYLOAD.checkAuth(username, password) -    if not info: +    if not user:          return json.dumps(False) -    s = set_session(request, info) +    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 json.dumps(sid)      except: +        print "Could not get session"          return json.dumps(True)  @route("/api/logout") +@route("/api/logout", method="POST")  def logout(): -    response.headers.replace("Content-type", "application/json") -    response.headers.append("Cache-Control", "no-cache, must-revalidate") +    add_header(response)      s = request.environ.get('beaker.session')      s.delete() | 
