alphax/app/web/routes_auth.py
2026-06-08 08:15:27 +08:00

159 lines
5.9 KiB
Python

from fastapi import APIRouter, Cookie, HTTPException, Request
from fastapi.responses import JSONResponse
from app.db import auth_db
from app.web.shared import (
ChangePasswordRequest,
CompleteRegistrationRequest,
LoginRequest,
RegisterRequest,
ResendVerificationRequest,
SendCodeRequest,
VerifyEmailRequest,
auth_error,
has_active_subscription,
require_user,
)
router = APIRouter()
@router.post("/api/auth/register")
async def api_auth_register(req: RegisterRequest):
try:
result = auth_db.register_user(req.email, req.password, req.invite_code)
smtp_ready = auth_db.is_smtp_configured()
return {
"ok": True,
"user": {k: v for k, v in result.items() if k not in ("verification_code", "user_id")},
"dev_verification_code": None if smtp_ready else result.get("verification_code"),
"email_sent": bool(result.get("email_sent")),
"message": "注册成功,请查收邮箱验证码" if smtp_ready else "注册成功,请完成邮箱验证码验证",
}
except auth_db.AuthError as exc:
auth_error(exc)
@router.post("/api/auth/send-code")
async def api_auth_send_code(req: SendCodeRequest):
try:
result = auth_db.send_registration_code(req.email)
smtp_ready = auth_db.is_smtp_configured()
return {
"ok": True,
"email": result["email"],
"dev_verification_code": None if smtp_ready else result.get("verification_code"),
"email_sent": bool(result.get("email_sent")),
"message": "验证码已发送,请查收邮箱" if smtp_ready else "验证码已生成",
}
except auth_db.AuthError as exc:
auth_error(exc)
@router.post("/api/auth/complete-registration")
async def api_auth_complete_registration(req: CompleteRegistrationRequest):
try:
user = auth_db.complete_registration(req.email, req.code, req.password, req.invite_code)
return {"ok": True, "user": user, "message": "注册成功,请登录"}
except auth_db.AuthError as exc:
auth_error(exc)
@router.post("/api/auth/verify-email")
async def api_auth_verify_email(req: VerifyEmailRequest):
try:
user = auth_db.verify_email(req.email, req.code)
return {"ok": True, "user": user, "message": "邮箱验证成功"}
except auth_db.AuthError as exc:
auth_error(exc)
@router.post("/api/auth/resend-verification")
async def api_auth_resend_verification(req: ResendVerificationRequest):
try:
result = auth_db.resend_verification_code(req.email)
smtp_ready = auth_db.is_smtp_configured()
return {
"ok": True,
"email": result["email"],
"dev_verification_code": None if smtp_ready else result.get("verification_code"),
"email_sent": bool(result.get("email_sent")),
"message": "验证码已重新发送,请查收邮箱" if smtp_ready else "验证码已重新生成",
}
except auth_db.AuthError as exc:
auth_error(exc)
@router.post("/api/auth/login")
async def api_auth_login(req: LoginRequest, request: Request = None):
try:
session = auth_db.login_user(req.email, req.password)
auth_db.log_user_activity(session["user"]["id"], "login", "auth", ip=request.client.host if request.client else "")
sub = auth_db.get_current_subscription(session["user"]["id"])
next_path = "/app" if sub else "/subscription?welcome=1"
resp = JSONResponse({
"ok": True,
"user": session["user"],
"expires_at": session["expires_at"],
"subscription": sub,
"subscription_active": bool(sub),
"next": next_path,
})
resp.set_cookie("altcoin_session", session["token"], httponly=True, samesite="lax", max_age=30 * 24 * 3600)
return resp
except auth_db.AuthError as exc:
auth_error(exc, status_code=400)
@router.get("/api/auth/me")
async def api_auth_me(altcoin_session: str = Cookie(default="")):
user = require_user(altcoin_session)
sub = auth_db.get_current_subscription(user["id"])
if not user.get("local_debug") and not has_active_subscription(user):
raise HTTPException(status_code=402, detail="订阅已过期或未开通,请先开通订阅")
return {"ok": True, "user": user, "subscription": sub, "subscription_active": bool(sub)}
@router.post("/api/auth/change-password")
async def api_auth_change_password(req: ChangePasswordRequest, altcoin_session: str = Cookie(default="")):
user = require_user(altcoin_session)
try:
return auth_db.change_password(user["id"], req.old_password, req.new_password)
except auth_db.AuthError as exc:
auth_error(exc)
@router.post("/api/auth/logout")
async def api_auth_logout(altcoin_session: str = Cookie(default="")):
auth_db.logout_user(altcoin_session)
resp = JSONResponse({"ok": True, "message": "已退出登录"})
resp.delete_cookie("altcoin_session")
return resp
@router.post("/api/subscriptions/free-trial")
async def api_subscription_free_trial(altcoin_session: str = Cookie(default="")):
user = require_user(altcoin_session)
try:
sub = auth_db.claim_free_trial(user["id"])
return {"ok": True, "subscription": sub, "message": "已开通新用户免费体验1个月"}
except auth_db.AuthError as exc:
auth_error(exc)
@router.get("/api/subscription/plans")
async def api_subscription_plans():
auth_db.init_auth_db()
conn = auth_db.get_conn()
rows = conn.execute("SELECT * FROM subscription_plan ORDER BY sort_order ASC").fetchall()
conn.close()
return [dict(r) for r in rows]
@router.get("/api/referral/stats")
async def api_referral_stats(altcoin_session: str = Cookie(default="")):
user = auth_db.get_user_by_session_token(altcoin_session)
if not user:
raise HTTPException(status_code=401, detail="请先登录")
return auth_db.get_referral_stats(user["id"])