from flask import Blueprint, request from flask_jwt_extended import create_access_token, jwt_required from extensions import db from models import User from .utils import created, err, ok, current_api_user, serialize_user auth_bp = Blueprint("api_auth", __name__, url_prefix="/auth") @auth_bp.post("/register") def register(): body = request.get_json(silent=True) or {} email = (body.get("email") or "").strip().lower() password = body.get("password") or "" display_name = (body.get("display_name") or "").strip() or None # Validation if not email or "@" not in email or "." not in email.split("@")[-1]: return err("A valid email address is required.", 400) if len(password) < 8: return err("Password must be at least 8 characters.", 400) # Uniqueness check existing = db.session.scalar( db.select(User).where(User.email == email) ) if existing: return err("Email already registered.", 409) u = User( email=email, display_name=display_name, provider="local", provider_id=email, email_confirmed=True, ) u.set_password(password) db.session.add(u) db.session.commit() token = create_access_token(identity=str(u.id)) return created({"user": serialize_user(u), "access_token": token}) @auth_bp.post("/login") def login(): body = request.get_json(silent=True) or {} email = (body.get("email") or "").strip().lower() password = body.get("password") or "" u = db.session.scalar( db.select(User).where(User.email == email, User.provider == "local") ) if not u or not u.check_password(password): return err("Invalid email or password.", 401) token = create_access_token(identity=str(u.id)) return ok({"user": serialize_user(u), "access_token": token}) @auth_bp.get("/me") @jwt_required() def me(): u = current_api_user() if not u: return err("User not found.", 404) return ok(serialize_user(u)) @auth_bp.patch("/me") @jwt_required() def update_me(): u = current_api_user() if not u: return err("User not found.", 404) body = request.get_json(silent=True) or {} if "display_name" in body: u.display_name = (body["display_name"] or "").strip() or None db.session.commit() return ok(serialize_user(u))