84 lines
2.3 KiB
Python
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))
|