import json import flask import sqlite3 from werkzeug.datastructures.file_storage import FileStorage from solution_handler import SolutionHandler from user_handler import UserHandler, User from bounty_handler import BountyHandler, Bounty app = flask.Flask(__name__) app.secret_key = "few`3r9i3r" app.config['SESSION_TYPE'] = 'filesystem' @app.get("/") def a(): return flask.send_file("../assets/apifiletest/index.html") # ---------- USER ---------- @app.get("/index.js") def an(): return flask.send_file("../assets/apifiletest/index.js") #@app.post("/get-user-by-email") #def get_user_by_email() -> flask.Response: # request_data = dict(flask.request.form) # if "email" not in request_data: # return flask.Response("email or password missing", status=422) # try: # user = UserHandler.get_user_by_email( # request_data["email"], # ) # except KeyError: # return flask.Response("User does not exist", status=404) # return flask.Response( # response=json.dumps({ # "handle": user.handle, # "display_name": user.display_name, # }), # status=200, # mimetype='application/json' # ) # # @app.post("/get-user-by-id") def get_user_by_id() -> flask.Response: request_data = dict(flask.request.form) try: user_id = int(request_data["user_id"]) except KeyError: return flask.Response("user_id missing", status=422) except ValueError: return flask.Response("user_id wasn't int", status=422) try: user = UserHandler.get_user_by_id(user_id) except KeyError: return flask.Response("User does not exist", status=404) return flask.Response( response=json.dumps({ "handle": user.handle, "display_name": user.display_name, }), status=200, mimetype='application/json' ) @app.post("/get-user-by-handle") def get_user_by_handle() -> flask.Response: request_data = dict(flask.request.form) try: handle = request_data["handle"] except KeyError: return flask.Response("handle or password missing", status=422) try: user = UserHandler.get_user_by_handle(handle) except KeyError: return flask.Response("User does not exist", status=404) return flask.Response( response=json.dumps({ "handle": user.handle, "display_name": user.display_name, }), status=200, mimetype='application/json' ) @app.post("/register") def register() -> flask.Response: request_data = dict(flask.request.form) try: email = request_data["email"] handle = request_data["handle"] password = request_data["password"] except KeyError: return flask.Response("email, handle or password missing", status=422) if "display_name" not in request_data: request_data["display_name"] = request_data["handle"] try: UserHandler.create_user( User( -1, email, request_data["handle"], request_data["password"], request_data["display_name"], ) ) except sqlite3.IntegrityError as error: if "handle" in str(error): return flask.Response("Handle exists", status=409) else: return flask.Response("Email exists", status=409) if "profile_picture" in flask.request.files: flask.request.files["profile_picture"].save(f"../assets/profile_pictures/{request_data['handle']}") return flask.Response(status=200) @app.post("/validate-login") def validate_login(): if "user_id" not in flask.session: return flask.Response("Authentication error", status=401) if not isinstance(flask.session["user_id"], int): return flask.Response("Authentication error", status=401) return flask.Response(status=200) @app.post("/login") def login() -> flask.Response: request_data = dict(flask.request.form) try: email = request_data["email"] password = request_data["password"] except KeyError: return flask.Response("email or password missing", status=422) try: assert UserHandler.verify_password_by_email(email, password) except KeyError: return flask.Response("User does not exist", status=404) except AssertionError: return flask.Response("Wrong password", status=409) user = UserHandler.get_user_by_email(request_data["email"]) flask.session["user_id"] = user.user_id return flask.Response(status=200) @app.post("/logout") def logout() -> flask.Response: if "user_id" not in flask.session: return flask.Response("Authentication error", status=401) flask.session.pop("user_id") return flask.Response(status=200) @app.post("/change-user-profile-picture") def change_user_profile_picture() -> flask.Response: login_validation = validate_login() if login_validation.status_code != 200: return login_validation try: image = flask.request.files["image"] except KeyError: return flask.Response("image is missing", status=422) image_name = UserHandler.get_user_by_id(flask.session["user_id"]).handle image.save( f"../assets/profile_pictures/{image_name}" ) return flask.Response(status=200) @app.post("/change-user-display-name") def change_user_display_name(): login_validation = validate_login() if login_validation.status_code != 200: return login_validation request_data = dict(flask.request.form) if "display_name" not in request_data: return flask.Response("display_name is missing", status=422) UserHandler.change_display_name(flask.session["user_id"], request_data["display_name"]) return flask.Response(status=200) @app.get("/profile-picture/") def get_profile_picture(handle: str) -> flask.Response: try: return flask.send_file(f"../assets/profile_pictures/{handle}") except FileNotFoundError: return flask.Response(f"{handle} does not exist", 404) # ---------- BOUNTY ---------- @app.post("/create-bounty") def create_bounty() -> flask.Response: request_data = dict(flask.request.form) login_validation = validate_login() if login_validation.status_code != 200: return login_validation if "title" not in request_data or \ "description" not in request_data: return flask.Response("title or description is missing", status=422) if "field" not in request_data: request_data["field"] = "other" if "languages" not in request_data: request_data["language"] = "any" try: BountyHandler.create_bounty(Bounty( -1, flask.session["user_id"], request_data["title"], request_data["description"], languages=request_data["languages"], field=request_data["field"] )) return flask.Response(status=200) except AssertionError: return flask.Response("Unknown language/ field", status=403) @app.post("/get-bounty-by-id") def bounty_get_by_id() -> flask.Response: login_validation = validate_login() user_id = -1 if login_validation.status_code == 200: user_id = flask.session["user_id"] request_data = dict(flask.request.form) if "bounty_id" not in request_data: return flask.Response("bounty_id is missing", status=422) try: bounty_id = int(request_data["bounty_id"]) except ValueError: return flask.Response("user_id wasn't int", status=422) try: bounty = BountyHandler.get_bounty_by_id(bounty_id) except KeyError: return flask.Response("Doesn't exist", status=404) number_of_ratings: int = BountyHandler.get_number_of_ratings(bounty_id) return flask.Response( response=json.dumps({ "title": bounty.title, "description": bounty.description, "languages": bounty.languages, "field": bounty.field, "average_rating": BountyHandler.get_sum_of_ratings(bounty_id) / number_of_ratings, "number_of_ratings": number_of_ratings, "users_rating": BountyHandler.get_rating_of_user(user_id, bounty.bounty_id), }), status=200, mimetype='application/json' ) @app.post("/create-session-for-bounty-get-random") def create_session_for_bounty_get_random() -> flask.Response: login_validation = validate_login() rater_id = -1 if login_validation.status_code == 200: rater_id = flask.session["user_id"] bounties = BountyHandler.get_randomized_bounty_list() bounties = [ { "id": bounty.bounty_id, "creator_identifie": bounty.user_id, "title": bounty.title, "description": bounty.description, "languages": bounty.languages, "field": bounty.field, "average_rating": BountyHandler.get_sum_of_ratings(bounty.bounty_id) /\ BountyHandler.get_number_of_ratings(bounty.bounty_id), "number_of_ratings": BountyHandler.get_number_of_ratings(bounty.bounty_id), "users_rating": BountyHandler.get_rating_of_user(rater_id, bounty.bounty_id), } for bounty in bounties ] flask.session["bounties"] = bounties response = flask.Response(status=200) return response @app.post("/bounty-get-random") def bounty_get_random() -> flask.Response: request_data = dict(flask.request.form) if "bounties" not in flask.session: return flask.Response("/create-session-for-bounty-get-random not called", status=401) try: page_number = int(request_data["page_number"]) except KeyError: return flask.Response("page_number is missing", status=422) except ValueError: return flask.Response("page_number wasn't int", status=422) return flask.Response( response=json.dumps( flask.session["bounties"][page_number * 20 : (page_number + 1) * 20] ), status=200, mimetype='application/json' ) @app.post("/bounty-rate") def bounty_rate() -> flask.Response: request_data = dict(flask.request.form) login_validation = validate_login() if login_validation.status_code != 200: return login_validation try: BountyHandler.rate( int(request_data["bounty_id"]), flask.session["user_id"], int(request_data["rating"]), ) except sqlite3.IntegrityError: return flask.Response("Rating gotta be between 1 and 10", status=403) except ValueError: return flask.Response("bounty_id or rating wasn't int", status=422) except KeyError: return flask.Response("bounty_id or rating missing", status=422) return flask.Response(status=200) # ---------- SOLUTIONS ---------- @app.post("/test") def test(): files = flask.request.files.getlist("files") for file in files: if file.filename: file.filename = file.filename.replace("/", r"|") file.save(f"../assets/{file.filename}") else: return flask.Response(status=400) return flask.Response() @app.post("/submit-solution") def submit_answer() -> flask.Response: request_data = dict(flask.request.form) login_validation = validate_login() if login_validation.status_code != 200: return login_validation user_id = flask.session["user_id"] try: bounty_id = int(request_data["bounty_id"]) except KeyError: return flask.Response("Bounty id missing", status=422) except ValueError: return flask.Response("bounty_id wasn't int", status=422) files : list[FileStorage]= flask.request.files.getlist("files") if not files: return flask.Response("files missing", status=422) SolutionHandler.submit_solution(files, bounty_id, user_id) return flask.Response() @app.post("/get-solution-by-id") def get_solution_by_id() -> flask.Response: request_data = dict(flask.request.form) try: solution_id = request_data["solution_id"] except KeyError: return flask.Response("Solution id missing", status=422) try: return flask.jsonify(SolutionHandler.get_solution_by_id(solution_id)) except KeyError: return flask.Response("Solution doesn't exist", status=404) @app.post("/get-solution-list") def get_solution_list() -> flask.Response: request_data = dict(flask.request.form) try: solution_id = int(request_data["bounty_id"]) except KeyError: return flask.Response("Bounty id missing", status=422) except ValueError: return flask.Response("bounty_id wasn't int", status=422) return flask.jsonify(SolutionHandler.get_solution_list(solution_id)) @app.post("/like-solution") def like_solution() -> flask.Response: request_data = dict(flask.request.form) login_validation = validate_login() if login_validation.status_code != 200: return login_validation try: solution_id = request_data["solution_id"] user_id = flask.session["user_id"] except KeyError: return flask.Response("Solution id missing", status=422) SolutionHandler.like(solution_id=solution_id, user_id=user_id) return flask.Response(status=200) @app.post("/unlike-solution") def unlike_solution() -> flask.Response: request_data = dict(flask.request.form) login_validation = validate_login() if login_validation.status_code != 200: return login_validation try: solution_id = request_data["solution_id"] user_id = flask.session["user_id"] except KeyError: return flask.Response("Solution id missing", status=422) SolutionHandler.unlike(solution_id=solution_id, user_id=user_id) return flask.Response(status=200) @app.post("/has-user-liked") def has_user_liked() -> flask.Response: request_data = dict(flask.request.form) login_validation = validate_login() if login_validation.status_code != 200: return login_validation try: solution_id = request_data["solution_id"] user_id = flask.session["user_id"] except KeyError: return flask.Response("Solution id missing", status=422) return flask.jsonify(SolutionHandler.has_user_liked(user_id=user_id, solution_id=solution_id))