# SPDX-FileCopyrightText: WTF Kooperative eG # # SPDX-License-Identifier: AGPL-3.0-or-later import os from flask import g, make_response, request, send_file from functools import wraps from ki.auth import auth from ki.handlers import find_profiles as find_profiles_handler from ki.handlers import update_profile as update_profile_handler from ki.models import ContactType, Language, Skill, Token, User from app import app content_type_svg = "image/svg+xml" content_type_png = "image/png" def token_auth(func): @wraps(func) def _token_auth(*args, **kwargs): auth_header = request.headers.get("Authorization") if (auth_header is None): return make_response({}, 401) if not auth_header.startswith("Bearer"): return make_response({}, 401) token = Token.query.filter(Token.token == auth_header[7:]).first() if token is None: return make_response({}, 403) g.user = token.user return func(*args, **kwargs) return _token_auth def models_to_list(models): models_list = [] for model in models: models_list.append(model.to_dict()) return models_list def handle_completion_request(model, key): query = model.query if "search" in request.args: query = query.filter(model.name.startswith(request.args.get("search"))) results = query.order_by(model.name) \ .limit(10) \ .all() api_results = models_to_list(results) response_data = {} response_data[key] = api_results return response_data def handle_icon_request(model, id, path): object = model.query.get(id) if object is None: return make_response({}, 404) icon_base_path = path + str(id) icon_svg_path = icon_base_path + ".svg" if os.path.exists(icon_svg_path): return send_file(icon_svg_path, mimetype=content_type_svg) icon_png_path = icon_base_path + ".png" if os.path.exists(icon_png_path): return send_file(icon_png_path, mimetype=content_type_png) unknown_svg_path = path + "unknown.svg" if os.path.exists(unknown_svg_path): return send_file(unknown_svg_path, mimetype=content_type_svg) unknown_png_path = path + "unknown.png" if os.path.exists(unknown_png_path): return send_file(unknown_png_path, mimetype=content_type_png) return make_response({"error": "icon not found"}, 404) @app.route("/") def hello_world(): return "KI" @app.route("/users/login", methods=["POST"]) def login(): username = request.json.get("username", "") password = request.json.get("password", "") token = auth(username, password) if token is None: return make_response({}, 403) return make_response({"token": token.token, "user_id": token.user_id}) @app.route("/users//profile") @token_auth def get_user_profile(user_id): user = User.query.filter(User.id == int(user_id)).first() if user is None: return make_response({}, 404) profile = user.profile if profile is None: return make_response({}, 404) if not profile.visible and profile.user.id != g.user.id: return make_response({}, 403) return make_response({ "profile": profile.to_dict(), }) @app.route("/users//profile", methods=["POST"]) @token_auth def update_profile(user_id): if g.user.id != int(user_id): return make_response({}, 403) return update_profile_handler(int(user_id)) @app.route("/contacttypes") @token_auth def get_contacttypes(): return handle_completion_request(ContactType, "contacttypes") @app.route("/users/profiles") @token_auth def find_profiles(): return find_profiles_handler() @app.route("/skills") @token_auth def get_skills(): return handle_completion_request(Skill, "skills") @app.route("/skills//icon") def get_skill_icon(skill_id): skill_icons_path = app.config["KI_DATA_DIR"] + "/imgs/skill_icons/" return handle_icon_request(Skill, skill_id, skill_icons_path) @app.route("/languages") @token_auth def get_languages(): return handle_completion_request(Language, "languages") @app.route("/languages//icon") def get_language_icon(language_id): language_flags_path = app.config["KI_DATA_DIR"] + "/imgs/flags/" return handle_icon_request(Language, language_id, language_flags_path)