""" main.py - Flask API with auth routes and module registry Domain routes are registered via the routes registry. """ import os import flask from flask_cors import CORS import core.auth as auth import core.users as users import core.postgres as postgres import api.routes.routines as routines_routes import api.routes.medications as medications_routes import api.routes.routine_steps_extended as routine_steps_extended_routes import api.routes.routine_sessions_extended as routine_sessions_extended_routes import api.routes.routine_templates as routine_templates_routes import api.routes.routine_stats as routine_stats_routes import api.routes.routine_tags as routine_tags_routes app = flask.Flask(__name__) CORS(app) ROUTE_MODULES = [ routines_routes, medications_routes, routine_steps_extended_routes, routine_sessions_extended_routes, routine_templates_routes, routine_stats_routes, routine_tags_routes, ] def register_routes(module): """Register a routes module. Module should have a register(app) function.""" ROUTE_MODULES.append(module) # ── Auth Routes ──────────────────────────────────────────────────── @app.route("/api/register", methods=["POST"]) def api_register(): data = flask.request.get_json() username = data.get("username") password = data.get("password") if not username or not password: return flask.jsonify({"error": "username and password required"}), 400 result = users.registerUser(username, password, data) if result: return flask.jsonify({"success": True}), 201 else: return flask.jsonify({"error": "username taken"}), 409 @app.route("/api/login", methods=["POST"]) def api_login(): data = flask.request.get_json() username = data.get("username") password = data.get("password") if not username or not password: return flask.jsonify({"error": "username and password required"}), 400 token = auth.getLoginToken(username, password) if token: return flask.jsonify({"token": token}), 200 else: return flask.jsonify({"error": "invalid credentials"}), 401 # ── User Routes ──────────────────────────────────────────────────── @app.route("/api/getUserUUID/", methods=["GET"]) def api_getUserUUID(username): header = flask.request.headers.get("Authorization", "") if not header.startswith("Bearer "): return flask.jsonify({"error": "missing token"}), 401 token = header[7:] if auth.verifyLoginToken(token, username): return flask.jsonify(users.getUserUUID(username)), 200 else: return flask.jsonify({"error": "unauthorized"}), 401 @app.route("/api/user/", methods=["GET"]) def api_getUser(userUUID): header = flask.request.headers.get("Authorization", "") if not header.startswith("Bearer "): return flask.jsonify({"error": "missing token"}), 401 token = header[7:] if auth.verifyLoginToken(token, userUUID=userUUID): user = postgres.select_one("users", {"id": userUUID}) if user: user.pop("password_hashed", None) return flask.jsonify(user), 200 else: return flask.jsonify({"error": "user not found"}), 404 else: return flask.jsonify({"error": "unauthorized"}), 401 @app.route("/api/user/", methods=["PUT"]) def api_updateUser(userUUID): header = flask.request.headers.get("Authorization", "") if not header.startswith("Bearer "): return flask.jsonify({"error": "missing token"}), 401 token = header[7:] if auth.verifyLoginToken(token, userUUID=userUUID): data = flask.request.get_json() result = users.updateUser(userUUID, data) if result: return flask.jsonify({"success": True}), 200 else: return flask.jsonify({"error": "no valid fields to update"}), 400 else: return flask.jsonify({"error": "unauthorized"}), 401 @app.route("/api/user/", methods=["DELETE"]) def api_deleteUser(userUUID): header = flask.request.headers.get("Authorization", "") if not header.startswith("Bearer "): return flask.jsonify({"error": "missing token"}), 401 token = header[7:] if auth.verifyLoginToken(token, userUUID=userUUID): data = flask.request.get_json() password = data.get("password") if not password: return flask.jsonify( {"error": "password required for account deletion"} ), 400 result = auth.unregisterUser(userUUID, password) if result: return flask.jsonify({"success": True}), 200 else: return flask.jsonify({"error": "invalid password"}), 401 else: return flask.jsonify({"error": "unauthorized"}), 401 # ── Health Check ─────────────────────────────────────────────────── @app.route("/health", methods=["GET"]) def health_check(): return flask.jsonify({"status": "ok"}), 200 if __name__ == "__main__": for module in ROUTE_MODULES: if hasattr(module, "register"): module.register(app) app.run(host="0.0.0.0", port=5000)