Initial commit

This commit is contained in:
2026-02-12 17:48:00 -06:00
parent 903df52206
commit 11c4ff5cb7
17 changed files with 1369 additions and 0 deletions

137
api/main.py Normal file
View File

@@ -0,0 +1,137 @@
"""
main.py - Flask API with auth routes and module registry
Domain routes are registered via the routes registry.
"""
import os
import flask
import core.auth as auth
import core.users as users
import core.postgres as postgres
app = flask.Flask(__name__)
ROUTE_MODULES = []
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/<username>", 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/<userUUID>", 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/<userUUID>", 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/<userUUID>", 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)

50
api/routes/example.py Normal file
View File

@@ -0,0 +1,50 @@
"""
Example route module - Copy this pattern for your domain.
This module demonstrates:
1. Registering routes with Flask app
2. Using auth validation
3. Making database calls via postgres module
"""
import flask
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import core.auth as auth
import core.postgres as postgres
def register(app):
"""Register routes with the Flask app."""
@app.route("/api/example", methods=["GET"])
def api_listExamples():
header = flask.request.headers.get("Authorization", "")
if not header.startswith("Bearer "):
return flask.jsonify({"error": "missing token"}), 401
token = header[7:]
decoded = auth.verifyLoginToken(token, userUUID=True)
if decoded != True:
return flask.jsonify({"error": "unauthorized"}), 401
items = postgres.select("examples")
return flask.jsonify(items), 200
@app.route("/api/example", methods=["POST"])
def api_addExample():
header = flask.request.headers.get("Authorization", "")
if not header.startswith("Bearer "):
return flask.jsonify({"error": "missing token"}), 401
token = header[7:]
decoded = auth.verifyLoginToken(token, userUUID=True)
if decoded != True:
return flask.jsonify({"error": "unauthorized"}), 401
data = flask.request.get_json()
item = postgres.insert("examples", data)
return flask.jsonify(item), 201