diff --git a/.vscode/settings.json b/.vscode/settings.json index 166be53..ff90cbd 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,6 @@ { "liveServer.settings.root": "front-end/", - "python.defaultInterpreterPath": "backend/.venv/bin/python" + "python.defaultInterpreterPath": "backend/.venv/bin/python", + "python-envs.defaultEnvManager": "ms-python.python:system", + "python-envs.pythonProjects": [] } diff --git a/backend/main.py b/backend/main.py index 7ba155f..8d6a6b7 100644 --- a/backend/main.py +++ b/backend/main.py @@ -17,7 +17,7 @@ ) from dotenv import load_dotenv -from flask import Flask +from flask import Flask, jsonify from flask_cors import CORS from flask_jwt_extended import JWTManager @@ -32,34 +32,47 @@ def main(): # Configure CORS to handle preflight requests CORS( app, + resources={r"/*": {"origins": "*"}}, supports_credentials=True, - resources={ - r"/*": { - "origins": "*", - "allow_headers": ["Content-Type", "Authorization"], - "methods": ["GET", "POST", "OPTIONS"], - } - }, + allow_headers=["Content-Type", "Authorization"], + methods=["GET", "POST", "OPTIONS"] ) app.config["JWT_SECRET_KEY"] = os.environ["JWT_SECRET_KEY"] jwt = JWTManager(app) jwt.user_lookup_loader(lookup_user) + # JWT error handlers + @app.errorhandler(422) + def handle_unprocessable_entity(e): + return jsonify({"success": False, "message": "Invalid or missing authentication token"}), 401 + + @jwt.expired_token_loader + def expired_token_callback(jwt_header, jwt_payload): + return jsonify({"success": False, "message": "Token has expired"}), 401 + + @jwt.invalid_token_loader + def invalid_token_callback(error): + return jsonify({"success": False, "message": "Invalid token"}), 401 + + @jwt.unauthorized_loader + def missing_authorization_callback(error): + return jsonify({"success": False, "message": "Missing authorization token"}), 401 + app.add_url_rule("/register", methods=["POST"], view_func=register) app.add_url_rule("/login", methods=["POST"], view_func=login) - app.add_url_rule("/home", view_func=home_timeline) + app.add_url_rule("/home", methods=["GET"], view_func=home_timeline) - app.add_url_rule("/profile", view_func=self_profile) - app.add_url_rule("/profile/", view_func=other_profile) + app.add_url_rule("/profile", methods=["GET"], view_func=self_profile) + app.add_url_rule("/profile/", methods=["GET"], view_func=other_profile) app.add_url_rule("/follow", methods=["POST"], view_func=do_follow) - app.add_url_rule("/suggested-follows/", view_func=suggested_follows) + app.add_url_rule("/suggested-follows/", methods=["GET"], view_func=suggested_follows) app.add_url_rule("/bloom", methods=["POST"], view_func=send_bloom) app.add_url_rule("/bloom/", methods=["GET"], view_func=get_bloom) - app.add_url_rule("/blooms/", view_func=user_blooms) - app.add_url_rule("/hashtag/", view_func=hashtag) + app.add_url_rule("/blooms/", methods=["GET"], view_func=user_blooms) + app.add_url_rule("/hashtag/", methods=["GET"], view_func=hashtag) app.run(host="0.0.0.0", port="3000", debug=True) diff --git a/front-end/lib/api.mjs b/front-end/lib/api.mjs index f4b5339..0ce37cf 100644 --- a/front-end/lib/api.mjs +++ b/front-end/lib/api.mjs @@ -44,10 +44,13 @@ async function _apiRequest(endpoint, options = {}) { if (!endpoint.includes("/login") && !endpoint.includes("/register")) { state.destroyState(); } + if (!endpoint.includes("/profile")) { + handleErrorDialog(error); + } + } else { + handleErrorDialog(error); } - // Pass all errors forward to a dialog on the screen - handleErrorDialog(error); throw error; } diff --git a/front-end/views/hashtag.mjs b/front-end/views/hashtag.mjs index 7b7e996..1ce38dd 100644 --- a/front-end/views/hashtag.mjs +++ b/front-end/views/hashtag.mjs @@ -35,8 +35,8 @@ function hashtagView(hashtag) { createLogin ); document - .querySelector("[data-action='login']") - ?.addEventListener("click", handleLogin); + .querySelector("[data-form='login']") + ?.addEventListener("submit", handleLogin); renderOne( state.currentHashtag, diff --git a/front-end/views/profile.mjs b/front-end/views/profile.mjs index dd2b92a..31139a9 100644 --- a/front-end/views/profile.mjs +++ b/front-end/views/profile.mjs @@ -39,8 +39,8 @@ function profileView(username) { createLogin ); document - .querySelector("[data-action='login']") - ?.addEventListener("click", handleLogin); + .querySelector("[data-form='login']") + ?.addEventListener("submit", handleLogin); const profileData = state.profiles.find((p) => p.username === username); if (profileData) {