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, 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"]) 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"])