Files
ShooterHub/blueprints/api/auth.py

84 lines
2.3 KiB
Python

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))