Ejemplo n.º 1
0
def update_ticket_progress():
    action = request.json.get('status')
    ticket_id = request.json.get('ticket_id')

    ticket = db.tickets[ticket_id]
    if ticket is None:
        abort(400, "no such ticket exists")

    idx = valid_statuses.index(action)
    print(idx)
    if idx == 0:  # not started
        EventLogger.log_status_change("Not Started", ticket_id,
                                      Helper.get_user())
        ticket.update_record(started=None, completed=None)

    elif idx == 1:  # in progress
        EventLogger.log_status_change("In Progress", ticket_id,
                                      Helper.get_user())
        ticket.update_record(started=Helper.get_time(), completed=None)

    elif idx == 2:  # completed
        EventLogger.log_status_change("Completed", ticket_id,
                                      Helper.get_user())
        ticket.update_record(started=Helper.get_time()
                             if ticket.started is None else ticket.started,
                             completed=Helper.get_time())

    return dict(ticket_id=ticket_id, status=action)
Ejemplo n.º 2
0
def edit_phone(contact_id=None, phone_id=None):
    assert contact_id is not None
    assert phone_id is not None
    # match the phone owner's id as well as the number's id
    row = db(
        (db.phone.contact_id == contact_id) &
        (db.phone.id == phone_id)
    ).select().first()
    if row is None:
        redirect(URL('edit_phones', contact_id))

    contact_inf = db(db.contact.id == contact_id).select().first()
    if contact_inf.user_email != get_user_email():
        abort(403)

    form = Form([Field('Phone', 'string'), Field('Kind', 'string')],
                record=dict(Phone=row.number, Kind=row.phone_type), deletable=False, csrf_session=session, formstyle=FormStyleBulma)
    form.param.sidecar.append(SPAN(" ", A("Back", _class="button", _href=URL('edit_phones', contact_id))))

    if form.accepted:
        # insert the number for that contact
        number = form.vars['Phone']
        phone_type = form.vars['Kind']
        db((db.phone.contact_id == contact_id) & (db.phone.id == phone_id)).update(
            number=number,
            phone_type=phone_type
        )
        redirect(URL('edit_phones', contact_id))

    contact_inf = db.contact[contact_id]
    first_name = contact_inf.first_name
    last_name = contact_inf.last_name
    name = f"{first_name} {last_name}"
    return dict(form=form, name=name)
Ejemplo n.º 3
0
 def abort_or_rediect(self, page):
     """
     return HTTP 403 if content_type is applicaitons/json
     else redirects to page"""
     if request.content_type == "application/json":
         abort(403)
     redirect(URL(self.auth.route, page))
Ejemplo n.º 4
0
 def abort_or_redirect(self, page, message=''):
     """
     return HTTP 403 if 'application/json' in HTTP_ACCEPT
     else redirects to page"""
     if REX_APPJSON.search(request.headers.get("accept", "")):
         abort(403)
     redirect_next = request.fullpath
     if request.query_string:
         redirect_next = redirect_next + "?{}".format(request.query_string)
     redirect(URL(self.auth.route, page, vars=dict(next=redirect_next, flash=message)))
Ejemplo n.º 5
0
 def on_request(self):
     """Checks the request's signature"""
     # extra and remove the signature from the query
     signature = request.query.get("_signature")
     if signature is None:
         abort(403)
     del request.query["_signature"]
     # Verifies the query keys.
     if signature != self.url_signer._sign(request.fullpath, request.query):
         abort(403)
Ejemplo n.º 6
0
def get_pinned_tickets():  # grabs pinned tickets for logged in user
    # Grab the current user's ID
    userID = Helper.get_user()
    if userID is None:
        abort(500, "No User ID obtained (is this possible?")

    # Query for pinned tickets given user ID
    pinnedTicketsQuery = db(
        db.user_pins.auth_user_id == userID).select().as_list()
    pinnedTickets = list(map(lambda x: x['ticket_id'], pinnedTicketsQuery))
    return (dict(pinned_tickets=pinnedTickets))
Ejemplo n.º 7
0
 def prepare_target_dir(form, target_dir):
     """Prepares the target directory for the new app.
     If should_exist is False, leaves the directory blank."""
     if form["mode"] == "new":
         if os.path.exists(target_dir):
             abort(500)  # already validated client side
     elif form["mode"] == "replace":
         if os.path.exists(target_dir):
             shutil.rmtree(target_dir)
         else:
             abort(500)  # not a replacement
Ejemplo n.º 8
0
 def on_request(self):
     """Checks the request's signature"""
     # extra and remove the signature from the query
     token = request.query.get("_signature")
     if token is None:
         abort(403)
     try:
         key = self.url_signer.get_url_key(request.fullpath, request.query)
         jwt.decode(token, key, algorithms=["HS256"])
         # We remove the signature, not to pollute the request.
         del request.query["_signature"]
     except:
         abort(403)
Ejemplo n.º 9
0
 def on_request(self):
     """Checks the request's signature"""
     # extra and remove the signature from the query
     signature = request.query.get("_signature")
     if signature is None:
         abort(403)
     try:
         h = self.url_signer.algo(self.url_signer.get_key())
         signature = request.query["_signature"]
         sig_content = base64.b85decode(
             signature.encode("utf-8")).decode("utf-8")
         sig_dict = json.loads(sig_content)
         ts = sig_dict["ts"]
         salt = sig_dict["salt"]
         sig = sig_dict["sig"]
         h.update(
             self.url_signer.get_info_to_sign(request.fullpath,
                                              request.query, ts, salt))
         computed_sig = base64.b85encode(h.digest()).decode("utf-8")
         if sig != computed_sig:
             abort(403)
         # We remove the signature, not to pollute the request.
         del request.query["_signature"]
         # Checks the expiration time.
         if self.url_signer.lifespan is not None:
             if float(ts) + self.url_signer.lifespan < time.time():
                 abort(403)
     except:
         abort(403)
Ejemplo n.º 10
0
 def new_app():
     form = request.json
     # Directory for zipped assets
     assets_dir = os.path.join(os.path.dirname(py4web.__file__), "assets")
     app_name = form["name"]
     target_dir = safe_join(FOLDER, app_name)
     if form["type"] == "minimal":
         source = os.path.join(assets_dir, "py4web.app._minimal.zip")
         source_dir = safe_join(FOLDER, "_minimal")
         prepare_target_dir(form, target_dir)
         install_by_unzip_or_treecopy(source, source_dir, target_dir)
     elif form["type"] == "scaffold":
         source = os.path.join(assets_dir, "py4web.app._scaffold.zip")
         source_dir = safe_join(FOLDER, "_scaffold")
         prepare_target_dir(form, target_dir)
         install_by_unzip_or_treecopy(source, source_dir, target_dir)
     elif form["type"] == "web":
         prepare_target_dir(form, target_dir)
         source = form["source"]
         if source.endswith(".zip"):  # install from the web (zip file)
             res = requests.get(source)
             mem_zip = io.BytesIO(res.content)
             zfile = zipfile.ZipFile(mem_zip, "r")
             zfile.extractall(target_dir)
             zfile.close()
         elif source.endswith(".git"):  # clone from a git repo
             process = subprocess.Popen(
                 ["git", "clone", source, form["name"]], cwd=FOLDER
             )
             process.communicate()
             if process.returncode != 0:
                 abort(500)
     elif form["type"] == "upload":
         print(request.files.keys())
         prepare_target_dir(form, target_dir)
         source_stream = io.BytesIO(base64.b64decode(form["file"]))
         zfile = zipfile.ZipFile(source_stream, "r")
         zfile.extractall(target_dir)
         zfile.close()
     else:
         abort(500)
     settings = os.path.join(target_dir, "settings.py")
     if os.path.exists(settings):
         with open(settings) as fp:
             data = fp.read()
         data = data.replace("<session-secret-key>", str(uuid.uuid4()))
         with open(settings, "w") as fp:
             fp.write(data)
     Reloader.import_app(app_name)
     return {"status": "success"}
Ejemplo n.º 11
0
def get_helppage(pagename: str):
    print("GOT HELPFILE REQUEST FOR PAGE " + pagename)
    VALID_PAGENAMES = {'usage': 'USAGE.md', 'attribution': 'ATTRIBUTION.md'}
    if pagename not in VALID_PAGENAMES:
        abort(403, "Not a valid help page.")

    help_file_path = settings.APP_FOLDER + "/" + VALID_PAGENAMES[pagename]

    if not path.exists(help_file_path):
        abort(404, "Help file not found; this is an error")

    helpFileContents = str()
    # Otherwise read and serve the file
    with open(help_file_path, 'r') as file:
        helpFileContents = file.read()

    return helpFileContents
Ejemplo n.º 12
0
 def abort_or_redirect(self, page, message=""):
     """
     return HTTP 403 if 'application/json' in HTTP_ACCEPT
     else redirects to page"""
     if re.search(REGEX_APPJSON, request.headers.get("accept", "")):
         abort(403)
     redirect_next = request.fullpath
     if request.query_string:
         redirect_next = redirect_next + "?{}".format(request.query_string)
     self.auth.flash.set(message)
     redirect(
         URL(
             self.auth.route,
             page,
             vars=dict(next=redirect_next),
             use_appname=self.auth.param.use_appname_in_redirects,
         ))
Ejemplo n.º 13
0
def pin_ticket():
    ticketID = request.json.get("ticket_id")
    if ticketID is None:
        abort(400, "Ticket ID to pin not provided")
    userID = Helper.get_user()
    if userID is None:
        abort(500, "No User ID obtained (is this possible?)")

    potentialPinQuery = db((db.user_pins.auth_user_id == userID) & \
                           (db.user_pins.ticket_id == ticketID))  # the query
    pin = potentialPinQuery.select()  # fetch query from db
    if not pin:
        # Create a pin record
        db.user_pins.insert(auth_user_id=userID, ticket_id=ticketID)
    else:
        # Delete it
        potentialPinQuery.delete()
    return "ok"
Ejemplo n.º 14
0
 def save(path, reload_app=True):
     """Saves a file"""
     app_name = path.split("/")[0]
     path = safe_join(FOLDER, path) or abort()
     with open(path, "wb") as myfile:
         myfile.write(request.body.read())
     if reload_app:
         Reloader.import_app(app_name)
     return {"status": "success"}
Ejemplo n.º 15
0
def delete_phone(contact_id=None, phone_id=None):
    assert contact_id is not None
    assert phone_id is not None
    # match the phone owner's id as well as the number's id
    row = db(
        (db.phone.contact_id == contact_id) &
        (db.phone.id == phone_id)
    ).select().first()
    # row.id is the id of the phone number being targeted
    if row.id is None:
        redirect(URL('edit_phones', contact_id))

    contact_inf = db(db.contact.id == contact_id).select().first()
    if contact_inf.user_email != get_user_email():
        abort(403)
    db(
        db.phone.id == row.id
    ).delete()
    redirect(URL('edit_phones', contact_id))
Ejemplo n.º 16
0
 def new_app():
     form = request.json
     # Directory for zipped assets
     assets_dir = os.path.join(os.path.dirname(py4web.__file__), "assets")
     target_dir = safe_join(FOLDER, form["name"])
     if form["type"] == "minimal":
         source = os.path.join(assets_dir, "py4web.app._minimal.zip")
         source_dir = safe_join(FOLDER, "_minimal")
         prepare_target_dir(form, target_dir)
         install_by_unzip_or_treecopy(source, source_dir, target_dir)
     elif form["type"] == "scaffold":
         source = os.path.join(assets_dir, "py4web.app._scaffold.zip")
         source_dir = safe_join(FOLDER, "_scaffold")
         prepare_target_dir(form, target_dir)
         install_by_unzip_or_treecopy(source, source_dir, target_dir)
     elif form["type"] == "web":
         prepare_target_dir(form, target_dir)
         source = form["source"]
         if source.endswith(".zip"):  # install from the web (zip file)
             res = requests.get(source)
             mem_zip = io.BytesIO(res.content)
             zfile = zipfile.ZipFile(mem_zip, "r")
             zfile.extractall(target_dir)
             zfile.close()
         elif source.endswith(".git"):  # clone from a git repo
             process = subprocess.Popen(
                 ["git", "clone", source, form["name"]], cwd=FOLDER
             )
             process.communicate()
             if process.returncode != 0:
                 abort(500)
     elif form["type"] == "upload":
         prepare_target_dir(form, target_dir)
         source_stream = io.BytesIO(base64.b64decode(form["file"]))
         zfile = zipfile.ZipFile(source_stream, "r")
         zfile.extractall(target_dir)
         zfile.close()
     else:
         abort(500)
     return {"status": "success"}
Ejemplo n.º 17
0
def compile_py():
    fp = request.json.get('fp')
    w23p_app = request.json.get('w23p_app')
    code = request.json.get('code')

    fp = fp[0] == '/' and fp[1:] or fp
    fp = os.path.join(APPS_FOLDER, w23p_app, fp)
    if not os.path.isfile(fp):
        #raise HTTP(404, web2py_error =  '`%s` not found' % fp)
        abort(404, '`%s` not found' % fp)
    if not fp.endswith('.py'):
        raise abort(400, '`%s` is not python file' % fp)

    code_raw = code if code is not None else fs2json.safe_read(fp)
    code = code_raw.rstrip().replace('\r\n', '\n') + '\n'
    highlight = None
    import _ast
    error = None
    try:
        compile(code, fp, "exec", _ast.PyCF_ONLY_AST)
    except Exception as e:
        # offset calculation is only used for textarea (start/stop)
        start = sum([len(line) + 1 for l, line
                     in enumerate(code_raw.split("\n"))
                     if l < e.lineno - 1])
        if e.text and e.offset:
            offset = e.offset - (len(e.text) - len(
                e.text.splitlines()[-1]))
        else:
            offset = 0
        highlight = {'start': start, 'end': start +
                     offset + 1, 'lineno': e.lineno, 'offset': offset}
        try:
            ex_name = e.__class__.__name__
        except:
            ex_name = 'unknown exception!'
        error = dict(line = e.lineno, col = offset, message = ex_name)
    return dict(err = error )
Ejemplo n.º 18
0
 def new_app():
     form = request.json
     # Directory for zipped assets
     assets_dir = os.path.join(os.path.dirname(py4web.__file__), 'assets')
     target_dir = safe_join(FOLDER, form['name'])
     if form['type'] == 'minimal':
         source = os.path.join(assets_dir,'py4web.app._minimal.zip')
         source_dir = safe_join(FOLDER, '_minimal')
         prepare_target_dir(form, target_dir)
         install_by_unzip_or_treecopy(source, source_dir, target_dir)
     elif form['type'] == 'scaffold':
         source = os.path.join(assets_dir,'py4web.app._scaffold.zip')
         source_dir = safe_join(FOLDER, '_scaffold')
         prepare_target_dir(form, target_dir)
         install_by_unzip_or_treecopy(source, source_dir, target_dir)
     elif form['type'] == 'web':
         prepare_target_dir(form, target_dir)
         source = form['source']
         if source.endswith('.zip'):  # install from the web (zip file)
             res = requests.get(source)
             mem_zip = io.BytesIO(res.content)
             zfile = zipfile.ZipFile(mem_zip, 'r')
             zfile.extractall(target_dir)
             zfile.close()
         elif source.endswith('.git'):  # clone from a git repo
             if subprocess.call(['git', 'clone', source, form['name']]):
                 abort(500)
     elif form['type'] == 'upload':
         prepare_target_dir(form, target_dir)
         source_stream = io.BytesIO(base64.b64decode(form['file']))
         zfile = zipfile.ZipFile(source_stream, 'r')
         zfile.extractall(target_dir)
         zfile.close()
     else:
         abort(500)
     return {'status':'success'}
Ejemplo n.º 19
0
 def new_app():
     form = request.json
     target_dir = safe_join(FOLDER, form['name'])
     if os.path.exists(target_dir):
         if form['mode'] == 'new':
             abort(500)  # already validated client side
         elif form['mode'] == 'replace':
             shutil.rmtree(target_dir)
     elif form['type'] != 'web' and not form['source'].endswith('.git'):
         os.mkdir(target_dir)
     assets_dir = os.path.join(os.path.dirname(py4web.__file__), 'assets')
     source = None
     if form['type'] == 'minimal':
         source = os.path.join(assets_dir, 'py4web.app._minimal.zip')
     elif form['type'] == 'scaffold':
         source = os.path.join(assets_dir, 'py4web.app._scaffold.zip')
     elif form['type'] == 'web':
         source = form['source']
     elif form['type'] == 'upload':
         source_stream = io.BytesIO(base64.b64decode(form['file']))
     else:
         abort(500)
     # TODO catch and report better errors below
     if form['type'] == 'upload':
         zip = zipfile.ZipFile(source_stream, 'r')
         zip.extractall(target_dir)
         zip.close()
     elif not '://' in source:  # install from a local asset (zip) file
         zip = zipfile.ZipFile(source, 'r')
         zip.extractall(target_dir)
         zip.close()
     elif source.endswith('.zip'):  # install from the web (zip file)
         res = requests.get(source)
         mem_zip = io.BytesIO(res.content)
         zipfile.ZipFile(mem_zip, 'r')
         zip.extractall(target_dir)
         zip.close()
     elif source.endswith('.git'):  # clone from a git repo
         if subprocess.call(['git', 'clone', source, form['name']]):
             abort(500)
     else:
         abort(400)
     return {'status': 'success'}
Ejemplo n.º 20
0
def edit_ticket():
    ticket_id = request.json.get('id')
    title = request.json.get('title')
    text = request.json.get('text')
    tag_list = request.json.get('tag_list')
    due_date = request.json.get('due_date')  # TODO: implement due dates here

    ticket = db.tickets[ticket_id]
    if ticket is None:
        abort(400, "could not find specified ticket")

    if type(tag_list) is not list and tag_list is not None:
        print("wrong type for tag_list")
        abort(500, "wrong type for tag_list")

    if type(title) is not str:
        print("wrong values for title or text")
        abort(500, "wrong values for title and text")

    ticket.update_record(ticket_title=title.strip(),
                         ticket_text=text.strip() if text else "",
                         due=parse(due_date) if due_date else None)

    current_tickets = Helper.get_ticket_tags_by_id(ticket_id)

    # tag ids should be unique so this should not cause an error
    tag_set = set()
    for tag in tag_list:
        tag_id = tag.get('id')
        if tag_id is None:
            tag_id = db(db.global_tag).insert(tag_name=tag.get('tag_name'))
        tag_set.add(tag_id)

    current_set = {tag.get('id')
                   for tag in current_tickets
                   } if current_tickets is not None else set()

    # yay inefficient tag update, set difference does not work on sets full of dicts
    for tag_id in current_set.difference(tag_set):
        db((db.ticket_tag.ticket_id == ticket_id)
           & (db.ticket_tag.tag_id == tag_id)).delete()

    for tag_id in tag_set.difference(current_set):
        db.ticket_tag.insert(ticket_id=ticket_id, tag_id=tag_id)

    return "ok"
Ejemplo n.º 21
0
 def abort_or_rediect(self, page):
     if request.content_type == 'application/json':
         abort(403)
     redirect(URL(self.auth.route + page))
Ejemplo n.º 22
0
def abort_response():
    abort(400)
Ejemplo n.º 23
0
 def on_request(self):
     user = self.session.get("user")
     if not user or not user.get("id"):
         abort(403)
Ejemplo n.º 24
0
 def delete(path):
     """Deletes a file"""
     fullpath = safe_join(FOLDER, path) or abort()
     recursive_unlink(fullpath)
     return {"status": "success"}
Ejemplo n.º 25
0
 def load_bytes(path):
     """Loads a binary file"""
     path = safe_join(FOLDER, path) or abort()
     return open(path, "rb").read()
Ejemplo n.º 26
0
 def load(path):
     """Loads a text file"""
     path = safe_join(FOLDER, path) or abort()
     content = open(path, "rb").read().decode("utf8")
     return {"payload": content, "status": "success"}
Ejemplo n.º 27
0
 def save(path):
     """Saves a file"""
     path = safe_join(FOLDER, path) or abort()
     with open(path, 'wb') as myfile:
         myfile.write(request.body.read())
     return {'status':'success'}
Ejemplo n.º 28
0
 def on_request(self):
     user = self.session.get('user')
     if not user or not user.get('id'):
         abort(403)
Ejemplo n.º 29
0
 def action(self, path, method, get_vars, post_vars, env=None):
     """action that handles all the HTTP requests for Auth"""
     env = env or {}
     if path.startswith("plugin/"):
         parts = path.split("/", 2)
         plugin = self.plugins.get(parts[1])
         if plugin:
             return plugin.handle_request(
                 self, parts[2], request.query, request.json
             )
         else:
             abort(404)
     if path.startswith("api/"):
         data = {}
         if method == "GET":
             # Should we use the username?
             if path == "api/use_username":
                 return {"use_username": self.use_username}
             if path == "api/config":
                 fields = [
                     dict(name=f.name, type=f.type)
                     for f in self.db.auth_user
                     if f.type in ["string", "bool", "integer", "float"]
                     and f.writable
                     and f.readable
                 ]
                 return {
                     "allowed_actions": self.allowed_actions,
                     "plugins": ["local"] + [key for key in self.plugins],
                     "fields": fields,
                 }
             # Otherwise, we assume the user exists.
             user = self.get_user(safe=True)
             if not user:
                 data = self._error("not authorized", 401)
             if path == "api/profile":
                 return {"user": user}
         elif method == "POST" and self.db:
             vars = dict(post_vars)
             user = self.get_user(safe=False)
             if path == "api/register":
                 data = self.register(vars, send=True).as_dict()
             elif path == "api/login":
                 # Prioritize PAM or LDAP logins if enabled
                 if "pam" in self.plugins or "ldap" in self.plugins:
                     plugin_name = "pam" if "pam" in self.plugins else "ldap"
                     username, password = vars.get("email"), vars.get("password")
                     check = self.plugins[plugin_name].check_credentials(
                         username, password
                     )
                     if check:
                         data = {
                             "username": username,
                             # "email": username + "@localhost",
                             "sso_id": plugin_name + ":" + username,
                         }
                         # and register the user if we have one, just in case
                         if self.db:
                             data = self.get_or_register_user(data)
                             self.session["user"] = {"id": data["id"]}
                             self.session["recent_activity"] = calendar.timegm(
                                 time.gmtime()
                             )
                             self.session["uuid"] = str(uuid.uuid1())
                     else:
                         data = self._error("Invalid Credentials")
                 # Else use normal login
                 else:
                     user, error = self.login(**vars)
                     if user:
                         self.session["user"] = {"id": user.id}
                         self.session["recent_activity"] = calendar.timegm(
                             time.gmtime()
                         )
                         self.session["uuid"] = str(uuid.uuid1())
                         user = {
                             f.name: user[f.name]
                             for f in self.db.auth_user
                             if f.readable
                         }
                         data = {"user": user}
                     else:
                         data = self._error(error)
             elif path == "api/request_reset_password":
                 if not self.request_reset_password(**vars):
                     data = self._error("invalid user")
             elif path == "api/reset_password":
                 if not self.reset_password(
                     vars.get("token"), vars.get("new_password")
                 ):
                     data = self._error("invalid token, request expired")
             elif user and path == "api/logout":
                 self.session["user"] = None
             elif user and path == "api/unsubscribe":
                 self.session["user"] = None
                 self.gdpr_unsubscribe(user, send=True)
             elif user and path == "api/change_password":
                 data = self.change_password(
                     user, vars.get("new_password"), vars.get("old_password")
                 )
             elif user and path == "api/change_email":
                 data = self.change_email(
                     user, vars.get("new_email"), vars.get("password")
                 )
             elif user and path == "api/profile":
                 data = self.update_profile(user, **vars)
             else:
                 data = {"status": "error", "message": "undefined"}
         if not "status" in data and data.get("errors"):
             data.update(status="error", message="validation errors", code=401)
         elif "errors" in data and not data["errors"]:
             del data["errors"]
         data["status"] = data.get("status", "success")
         data["code"] = data.get("code", 200)
         return data
     elif path == "logout":
         self.session.clear()
         # Somehow call revoke for active plugin
     elif path == "verify_email" and self.db:
         token = get_vars.get("token")
         if self.verify_email(token):
             next = b16d(token.split("/")[1])
             redirect(
                 next
                 or URL(
                     "auth",
                     "email_verified",
                     use_appname=self.use_appname_in_redirects,
                 )
             )
         else:
             redirect(
                 URL(
                     "auth",
                     "token_expired",
                     use_appname=self.use_appname_in_redirects,
                 )
             )
     env["path"] = path
     return Template("auth.html").transform(env)
Ejemplo n.º 30
0
 def action(self, path, method, get_vars, post_vars):
     if path.startswith('plugin/'):
         parts = path.split('/', 2)
         plugin = self.plugins.get(parts[1])
         if plugin:
             return plugin.handle_request(self, parts[2], request.query,
                                          request.json)
         else:
             abort(404)
     if path.startswith('api/'):
         data = {}
         if method == 'GET':
             user = self.get_user(safe=True)
             if not user:
                 data = self._error('not authoried', 401)
             if path == 'api/profile':
                 return {'user': user}
         elif method == 'POST' and self.db:
             vars = dict(post_vars)
             user = self.get_user(safe=False)
             if path == 'api/register':
                 data = self.register(vars, send=True).as_dict()
             elif path == 'api/login':
                 # Prioritize PAM or LDAP logins if enabled
                 if 'pam' in self.plugins or 'ldap' in self.plugins:
                     plugin_name = 'pam' if 'pam' in self.plugins else 'ldap'
                     username, password = vars.get('email'), vars.get(
                         'password')
                     check = self.plugins[plugin_name].check_credentials(
                         username, password)
                     if check:
                         data = {
                             'username': username,
                             'email': username + '@localhost',
                             'sso_id': plugin_name + ':' + username,
                         }
                         # and register the user if we have one, just in case
                         if self.db:
                             data = self.get_or_register_user(data)
                     else:
                         data = self._error('Invalid Credentials')
                 # Else use normal login
                 else:
                     user, error = self.login(**vars)
                     if user:
                         self.session['user'] = {'id': user.id}
                         user = {
                             f.name: user[f.name]
                             for f in self.db.auth_user if f.readable
                         }
                         data = {'user': user}
                     else:
                         data = self._error(error)
             elif path == 'api/request_reset_password':
                 if not self.request_reset_password(**vars):
                     data = self._error('invalid user')
             elif path == 'api/reset_password':
                 if not self.reset_password(vars.get('token'),
                                            vars.get('new_password')):
                     data = self._error('invalid token, request expired')
             elif user and path == 'api/logout':
                 self.session['user'] = None
             elif user and path == 'api/unsubscribe':
                 self.session['user'] = None
                 self.gdpr_unsubscribe(user, send=True)
             elif user and path == 'api/change_password':
                 data = self.change_password(user, vars.get('new_password'),
                                             vars.get('password'))
             elif user and path == 'api/change_email':
                 data = self.change_email(user, vars.get('new_email'),
                                          vars.get('password'))
             elif user and path == 'api/profile':
                 data = self.update_profile(user, **vars)
             else:
                 data = {'status': 'error', 'message': 'undefined'}
         if not 'status' in data and data.get('errors'):
             data.update(status='error',
                         message='validation errors',
                         code=401)
         elif 'errors' in data and not data['errors']:
             del data['errors']
         data['status'] = data.get('status', 'success')
         data['code'] = data.get('code', 200)
         return data
     elif path == 'logout':
         self.session['user'] = None
         # Somehow call revoke for active plugin
     elif path == 'verify_email' and self.db:
         if self.verify_email(get_vars.get('token')):
             redirect(URL('auth/email_verified'))
         else:
             redirect(URL('auth/token_expired'))
     return Template('auth.html').transform({'path': path})