Add auth profile timing instrumentation

This commit is contained in:
2569718930@qq.com
2026-05-31 18:27:04 +08:00
parent 46effcd45f
commit a4253c224a
5 changed files with 683 additions and 259 deletions
+282 -85
View File
@@ -27,6 +27,104 @@ import {
const API_BASE = process.env.POLYWEATHER_API_BASE_URL; const API_BASE = process.env.POLYWEATHER_API_BASE_URL;
type AuthMeTimingStage = {
durationMs: number;
name: string;
};
type AuthMeTimer = {
hasAuthorization: boolean;
hasSupabaseCookie: boolean;
measure<T>(name: string, action: () => Promise<T>): Promise<T>;
measureSync<T>(name: string, action: () => T): T;
preferSnapshot: boolean;
stages: AuthMeTimingStage[];
totalMs(): number;
};
function authMeNowMs() {
return typeof performance !== "undefined" ? performance.now() : Date.now();
}
function createAuthMeTimer(req: NextRequest): AuthMeTimer {
const startedAt = authMeNowMs();
const stages: AuthMeTimingStage[] = [];
const recordStage = (name: string, stageStartedAt: number) => {
stages.push({
durationMs: Math.round((authMeNowMs() - stageStartedAt) * 10) / 10,
name,
});
};
return {
hasAuthorization: Boolean(req.headers.get("authorization")),
hasSupabaseCookie: hasRequestSupabaseSessionCookie(req),
async measure<T>(name: string, action: () => Promise<T>) {
const stageStartedAt = authMeNowMs();
try {
return await action();
} finally {
recordStage(name, stageStartedAt);
}
},
measureSync<T>(name: string, action: () => T) {
const stageStartedAt = authMeNowMs();
try {
return action();
} finally {
recordStage(name, stageStartedAt);
}
},
preferSnapshot: req.nextUrl.searchParams.get("prefer_snapshot") === "1",
stages,
totalMs() {
return Math.round((authMeNowMs() - startedAt) * 10) / 10;
},
};
}
function formatServerTiming(stages: AuthMeTimingStage[], totalMs: number) {
return [...stages, { durationMs: totalMs, name: "total" }]
.map(({ durationMs, name }) => {
const safeName = name.replace(/[^A-Za-z0-9_-]/g, "_");
return `${safeName};dur=${Math.max(0, durationMs).toFixed(1)}`;
})
.join(", ");
}
function finishAuthMeResponse(
response: NextResponse,
timer: AuthMeTimer,
outcome: string,
extra?: { backendServerTiming?: string },
) {
const total = timer.totalMs();
const ownServerTiming = formatServerTiming(timer.stages, total);
const backendServerTiming = String(extra?.backendServerTiming || "").trim();
response.headers.set(
"Server-Timing",
backendServerTiming
? `${ownServerTiming}, ${backendServerTiming}`
: ownServerTiming,
);
console.info(
"[auth-me-timing]",
JSON.stringify({
backendServerTiming: backendServerTiming || undefined,
hasAuthorization: timer.hasAuthorization,
hasSupabaseCookie: timer.hasSupabaseCookie,
outcome,
preferSnapshot: timer.preferSnapshot,
stagesMs: Object.fromEntries(
timer.stages.map((stage) => [stage.name, stage.durationMs]),
),
status: response.status,
totalMs: total,
}),
);
return response;
}
async function trackAuthDiagnosticEvent( async function trackAuthDiagnosticEvent(
req: NextRequest, req: NextRequest,
{ {
@@ -273,21 +371,30 @@ function hasRequestSupabaseSessionCookie(req: NextRequest) {
} }
export async function GET(req: NextRequest) { export async function GET(req: NextRequest) {
const timer = createAuthMeTimer(req);
const requestHost = const requestHost =
req.headers.get("x-forwarded-host") || req.headers.get("host") || req.nextUrl.host; req.headers.get("x-forwarded-host") || req.headers.get("host") || req.nextUrl.host;
if ( if (
isLocalFullAccessHost(requestHost) || isLocalFullAccessHost(requestHost) ||
isLocalFullAccessHost(req.nextUrl.hostname) isLocalFullAccessHost(req.nextUrl.hostname)
) { ) {
return NextResponse.json(getLocalDevAuthPayload(), { return finishAuthMeResponse(
headers: { "Cache-Control": "no-store" }, NextResponse.json(getLocalDevAuthPayload(), {
}); headers: { "Cache-Control": "no-store" },
}),
timer,
"local_full_access",
);
} }
if (!API_BASE) { if (!API_BASE) {
return NextResponse.json( return finishAuthMeResponse(
{ error: "POLYWEATHER_API_BASE_URL is not configured" }, NextResponse.json(
{ status: 500 }, { error: "POLYWEATHER_API_BASE_URL is not configured" },
{ status: 500 },
),
timer,
"missing_api_base",
); );
} }
@@ -297,16 +404,21 @@ export async function GET(req: NextRequest) {
!req.headers.get("authorization") && !req.headers.get("authorization") &&
hasRequestSupabaseSessionCookie(req) hasRequestSupabaseSessionCookie(req)
) { ) {
const snapshotPayload = entitlementSnapshotToAuthPayload( const snapshotPayload = timer.measureSync(
readEntitlementSnapshot(req), "snapshot_cookie",
() => entitlementSnapshotToAuthPayload(readEntitlementSnapshot(req)),
); );
if (snapshotPayload) { if (snapshotPayload) {
return NextResponse.json( return finishAuthMeResponse(
{ NextResponse.json(
...snapshotPayload, {
entitlement_snapshot_reason: "prefer_snapshot_fast_path", ...snapshotPayload,
}, entitlement_snapshot_reason: "prefer_snapshot_fast_path",
{ headers: { "Cache-Control": "no-store" } }, },
{ headers: { "Cache-Control": "no-store" } },
),
timer,
"prefer_snapshot_fast_path",
); );
} }
} }
@@ -315,11 +427,17 @@ export async function GET(req: NextRequest) {
let bearerIdentity: VerifiedBearerIdentity | null | undefined; let bearerIdentity: VerifiedBearerIdentity | null | undefined;
const getBearerIdentityOnce = async () => { const getBearerIdentityOnce = async () => {
if (bearerIdentity !== undefined) return bearerIdentity; if (bearerIdentity !== undefined) return bearerIdentity;
bearerIdentity = await getVerifiedBearerIdentity(req); bearerIdentity = await timer.measure(
"bearer_identity",
() => getVerifiedBearerIdentity(req),
);
return bearerIdentity; return bearerIdentity;
}; };
try { try {
auth = await buildBackendRequestHeaders(req); auth = await timer.measure(
"auth_headers",
() => buildBackendRequestHeaders(req),
);
if ( if (
hasSupabaseServerEnv() && hasSupabaseServerEnv() &&
!auth.authUserId && !auth.authUserId &&
@@ -331,7 +449,11 @@ export async function GET(req: NextRequest) {
points: 0, points: 0,
}); });
if (!preferSnapshot) clearEntitlementSnapshotCookie(response); if (!preferSnapshot) clearEntitlementSnapshotCookie(response);
return applyAuthResponseCookies(response, auth.response); return finishAuthMeResponse(
applyAuthResponseCookies(response, auth.response),
timer,
"no_session",
);
} }
if (preferSnapshot) { if (preferSnapshot) {
@@ -347,24 +469,35 @@ export async function GET(req: NextRequest) {
response: auth.response, response: auth.response,
userId: identity.userId, userId: identity.userId,
}); });
if (snapshotResponse) return snapshotResponse; if (snapshotResponse) {
return finishAuthMeResponse(
snapshotResponse,
timer,
"prefer_snapshot",
);
}
} }
} }
if (!auth) throw new Error("auth headers unavailable");
const backendAuth = auth;
const controller = new AbortController(); const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 6000); const timeoutId = setTimeout(() => controller.abort(), 6000);
let res: Response; let res: Response;
try { try {
res = await fetch(`${API_BASE}/api/auth/me`, { res = await timer.measure("backend_fetch", async () =>
headers: auth.headers, await fetch(`${API_BASE}/api/auth/me`, {
cache: "no-store", headers: backendAuth.headers,
signal: controller.signal, cache: "no-store",
}); signal: controller.signal,
}),
);
} finally { } finally {
clearTimeout(timeoutId); clearTimeout(timeoutId);
} }
const backendServerTiming = res.headers.get("server-timing") || "";
if (res.status === 401 || res.status === 403) { if (res.status === 401 || res.status === 403) {
const raw = await res.text(); const raw = await timer.measure("backend_read", () => res.text());
const authIdentity = auth.authUserId const authIdentity = auth.authUserId
? { email: auth.authEmail || null, userId: auth.authUserId } ? { email: auth.authEmail || null, userId: auth.authUserId }
: await getBearerIdentityOnce(); : await getBearerIdentityOnce();
@@ -372,30 +505,45 @@ export async function GET(req: NextRequest) {
authIdentity?.userId && authIdentity?.userId &&
isSubscriptionRequiredBackendResponse(res.status, raw) isSubscriptionRequiredBackendResponse(res.status, raw)
) { ) {
return subscriptionRequiredAuthProfileResponse({ return finishAuthMeResponse(
email: authIdentity.email, subscriptionRequiredAuthProfileResponse({
response: auth.response, email: authIdentity.email,
userId: authIdentity.userId, response: auth.response,
}); userId: authIdentity.userId,
}),
timer,
"subscription_required",
{ backendServerTiming },
);
} }
if (auth.authUserId) { if (auth.authUserId) {
return degradedAuthProfileResponse({ return finishAuthMeResponse(
email: auth.authEmail || null, await degradedAuthProfileResponse({
reason: `backend_${res.status}`, email: auth.authEmail || null,
req, reason: `backend_${res.status}`,
response: auth.response, req,
userId: auth.authUserId, response: auth.response,
}); userId: auth.authUserId,
}),
timer,
`degraded_backend_${res.status}`,
{ backendServerTiming },
);
} }
const identity = await getBearerIdentityOnce(); const identity = await getBearerIdentityOnce();
if (identity) { if (identity) {
return degradedAuthProfileResponse({ return finishAuthMeResponse(
email: identity.email, await degradedAuthProfileResponse({
reason: `backend_${res.status}`, email: identity.email,
req, reason: `backend_${res.status}`,
response: auth.response, req,
userId: identity.userId, response: auth.response,
}); userId: identity.userId,
}),
timer,
`degraded_backend_${res.status}`,
{ backendServerTiming },
);
} }
const response = NextResponse.json({ const response = NextResponse.json({
authenticated: false, authenticated: false,
@@ -403,33 +551,53 @@ export async function GET(req: NextRequest) {
points: 0, points: 0,
}); });
clearEntitlementSnapshotCookie(response); clearEntitlementSnapshotCookie(response);
return applyAuthResponseCookies(response, auth.response); return finishAuthMeResponse(
applyAuthResponseCookies(response, auth.response),
timer,
`anonymous_backend_${res.status}`,
{ backendServerTiming },
);
} }
if (!res.ok) { if (!res.ok) {
const raw = await res.text(); const raw = await timer.measure("backend_read", () => res.text());
if (auth.authUserId) { if (auth.authUserId) {
return degradedAuthProfileResponse({ return finishAuthMeResponse(
email: auth.authEmail || null, await degradedAuthProfileResponse({
reason: `backend_${res.status}`, email: auth.authEmail || null,
req, reason: `backend_${res.status}`,
response: auth.response, req,
userId: auth.authUserId, response: auth.response,
}); userId: auth.authUserId,
}),
timer,
`degraded_backend_${res.status}`,
{ backendServerTiming },
);
} }
const identity = await getBearerIdentityOnce(); const identity = await getBearerIdentityOnce();
if (identity) { if (identity) {
return degradedAuthProfileResponse({ return finishAuthMeResponse(
email: identity.email, await degradedAuthProfileResponse({
reason: `backend_${res.status}`, email: identity.email,
req, reason: `backend_${res.status}`,
response: auth.response, req,
userId: identity.userId, response: auth.response,
}); userId: identity.userId,
}),
timer,
`degraded_backend_${res.status}`,
{ backendServerTiming },
);
} }
const response = buildUpstreamErrorResponse(res.status, raw); const response = buildUpstreamErrorResponse(res.status, raw);
return applyAuthResponseCookies(response, auth.response); return finishAuthMeResponse(
applyAuthResponseCookies(response, auth.response),
timer,
`upstream_${res.status}`,
{ backendServerTiming },
);
} }
const data = await res.json(); const data = await timer.measure("backend_read", () => res.json());
if (data?.authenticated === true && data?.subscription_active == null) { if (data?.authenticated === true && data?.subscription_active == null) {
const userId = String(data.user_id || auth.authUserId || "").trim(); const userId = String(data.user_id || auth.authUserId || "").trim();
if (userId) { if (userId) {
@@ -440,47 +608,76 @@ export async function GET(req: NextRequest) {
response: auth.response, response: auth.response,
userId, userId,
}); });
if (snapshotResponse) return snapshotResponse; if (snapshotResponse) {
return finishAuthMeResponse(
snapshotResponse,
timer,
"subscription_unknown_snapshot",
{ backendServerTiming },
);
}
} }
} }
const response = NextResponse.json(data); const response = NextResponse.json(data);
applyEntitlementSnapshotFromAuthPayload(response, data); applyEntitlementSnapshotFromAuthPayload(response, data);
return applyAuthResponseCookies(response, auth.response); return finishAuthMeResponse(
applyAuthResponseCookies(response, auth.response),
timer,
"ok",
{ backendServerTiming },
);
} catch (error) { } catch (error) {
if (auth?.authUserId) { if (auth?.authUserId) {
return degradedAuthProfileResponse({ return finishAuthMeResponse(
email: auth.authEmail || null, await degradedAuthProfileResponse({
reason: String(error), email: auth.authEmail || null,
req, reason: String(error),
response: auth.response, req,
userId: auth.authUserId, response: auth.response,
}); userId: auth.authUserId,
}),
timer,
"exception_degraded",
);
} }
const identity = await getBearerIdentityOnce(); const identity = await getBearerIdentityOnce();
if (identity) { if (identity) {
return degradedAuthProfileResponse({ return finishAuthMeResponse(
email: identity.email, await degradedAuthProfileResponse({
reason: String(error), email: identity.email,
req, reason: String(error),
response: auth?.response || null, req,
userId: identity.userId, response: auth?.response || null,
}); userId: identity.userId,
}),
timer,
"exception_degraded",
);
} }
const snapshotPayload = entitlementSnapshotToAuthPayload( const snapshotPayload = timer.measureSync(
readEntitlementSnapshot(req), "snapshot_cookie",
() => entitlementSnapshotToAuthPayload(readEntitlementSnapshot(req)),
); );
if (snapshotPayload) { if (snapshotPayload) {
const snapshotResponse = NextResponse.json({ const snapshotResponse = NextResponse.json({
...snapshotPayload, ...snapshotPayload,
entitlement_snapshot_reason: "exception_snapshot", entitlement_snapshot_reason: "exception_snapshot",
}); });
return applyAuthResponseCookies(snapshotResponse, auth?.response || null); return finishAuthMeResponse(
applyAuthResponseCookies(snapshotResponse, auth?.response || null),
timer,
"exception_snapshot",
);
} }
return unauthenticatedAuthProfileResponse({ return finishAuthMeResponse(
reason: String(error), await unauthenticatedAuthProfileResponse({
req, reason: String(error),
response: auth?.response || null, req,
}); response: auth?.response || null,
}),
timer,
"exception_anonymous",
);
} }
} }
@@ -0,0 +1,43 @@
import fs from "node:fs";
import path from "node:path";
function assert(condition: unknown, message: string) {
if (!condition) throw new Error(message);
}
export function runTests() {
const projectRoot = process.cwd();
const authMeRouteSource = fs.readFileSync(
path.join(projectRoot, "app", "api", "auth", "me", "route.ts"),
"utf8",
);
assert(
authMeRouteSource.includes("createAuthMeTimer") &&
authMeRouteSource.includes("finishAuthMeResponse"),
"/api/auth/me proxy must centralize timing so every return path can emit instrumentation",
);
assert(
authMeRouteSource.includes('"Server-Timing"') &&
authMeRouteSource.includes("auth_headers") &&
authMeRouteSource.includes("backend_fetch") &&
authMeRouteSource.includes("total"),
"/api/auth/me proxy must expose stage durations through Server-Timing for HAR inspection",
);
const finishStart = authMeRouteSource.indexOf("function finishAuthMeResponse");
const finishEnd = authMeRouteSource.indexOf("async function trackAuthDiagnosticEvent");
const finishSource =
finishStart >= 0 && finishEnd > finishStart
? authMeRouteSource.slice(finishStart, finishEnd)
: "";
assert(
finishSource.includes("[auth-me-timing]") &&
finishSource.includes("hasAuthorization") &&
finishSource.includes("hasSupabaseCookie") &&
!finishSource.includes("authUserId") &&
!finishSource.includes("authEmail") &&
!finishSource.includes("userId") &&
!finishSource.includes("email"),
"/api/auth/me proxy timing logs must include request shape but avoid raw user ids or emails",
);
}
+39
View File
@@ -0,0 +1,39 @@
from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
def test_auth_me_backend_records_stage_timing_without_sensitive_identity():
source = (ROOT / "web" / "services" / "auth_api.py").read_text(encoding="utf-8")
assert "_AuthMeTimer" in source
assert "auth_me_timing" in source
for stage in [
"assert_entitlement",
"bind_identity",
"ensure_signup_trial",
"subscription_window",
"auth_points",
"weekly_profile",
"telegram_pricing",
"referral_summary",
"total",
]:
assert stage in source
log_start = source.index("def _log_auth_me_timing")
log_end = source.index("def _require_auth_identity_without_subscription_gate")
log_source = source[log_start:log_end]
assert "auth_user_id" not in log_source
assert "auth_email" not in log_source
def test_auth_me_backend_exposes_server_timing_header_for_proxy_logs():
router_source = (ROOT / "web" / "routers" / "auth.py").read_text(
encoding="utf-8"
)
assert "Response" in router_source
assert "auth_me_server_timing" in router_source
assert '"Server-Timing"' in router_source
+9 -3
View File
@@ -1,6 +1,6 @@
"""Authentication API routes.""" """Authentication API routes."""
from fastapi import APIRouter, Request from fastapi import APIRouter, Request, Response
from web.core import ReferralApplyRequest, TelegramBindTokenRequest, TelegramLoginRequest from web.core import ReferralApplyRequest, TelegramBindTokenRequest, TelegramLoginRequest
from web.services.auth_api import ( from web.services.auth_api import (
@@ -15,8 +15,14 @@ router = APIRouter(tags=["auth"])
@router.get("/api/auth/me") @router.get("/api/auth/me")
async def auth_me(request: Request): async def auth_me(request: Request, response: Response):
return get_auth_me_payload(request) payload = get_auth_me_payload(request)
server_timing = str(
getattr(request.state, "auth_me_server_timing", "") or ""
).strip()
if server_timing:
response.headers["Server-Timing"] = server_timing
return payload
@router.post("/api/auth/telegram/login") @router.post("/api/auth/telegram/login")
+310 -171
View File
@@ -2,9 +2,11 @@
from __future__ import annotations from __future__ import annotations
from typing import Any, Dict import time
from typing import Any, Callable, Dict, Optional, TypeVar
from fastapi import HTTPException, Request from fastapi import HTTPException, Request
from loguru import logger
from src.auth.telegram_group_pricing import TelegramGroupPricing from src.auth.telegram_group_pricing import TelegramGroupPricing
from src.database.db_manager import DBManager from src.database.db_manager import DBManager
@@ -12,6 +14,70 @@ from web.core import ReferralApplyRequest, TelegramLoginRequest
import web.routes as legacy_routes import web.routes as legacy_routes
T = TypeVar("T")
class _AuthMeTimer:
def __init__(self, request: Request):
self.request = request
self.started = time.perf_counter()
self.timings_ms: Dict[str, float] = {}
def measure(self, stage: str, action: Callable[[], T]) -> T:
started = time.perf_counter()
try:
return action()
finally:
self.timings_ms[stage] = round(
(time.perf_counter() - started) * 1000.0,
1,
)
def finish(
self,
*,
authenticated: Optional[bool],
outcome: str,
status_code: int,
subscription_active: Optional[bool],
) -> None:
self.timings_ms["total"] = round(
(time.perf_counter() - self.started) * 1000.0,
1,
)
server_timing = ", ".join(
f"backend_{stage};dur={max(0.0, duration):.1f}"
for stage, duration in self.timings_ms.items()
)
self.request.state.auth_me_server_timing = server_timing
_log_auth_me_timing(
authenticated=authenticated,
outcome=outcome,
status_code=status_code,
subscription_active=subscription_active,
timings_ms=self.timings_ms,
)
def _log_auth_me_timing(
*,
authenticated: Optional[bool],
outcome: str,
status_code: int,
subscription_active: Optional[bool],
timings_ms: Dict[str, float],
) -> None:
logger.info(
"auth_me_timing outcome={} status_code={} authenticated={} "
"subscription_active={} timings_ms={}",
outcome,
status_code,
authenticated,
subscription_active,
timings_ms,
)
def _require_auth_identity_without_subscription_gate(request: Request) -> Dict[str, str]: def _require_auth_identity_without_subscription_gate(request: Request) -> Dict[str, str]:
request.state.skip_subscription_gate = True request.state.skip_subscription_gate = True
legacy_routes._assert_entitlement(request) legacy_routes._assert_entitlement(request)
@@ -27,180 +93,253 @@ def _subscription_row_is_trial(row: Any) -> bool:
def get_auth_me_payload(request: Request) -> Dict[str, Any]: def get_auth_me_payload(request: Request) -> Dict[str, Any]:
request.state.skip_subscription_gate = True timer = _AuthMeTimer(request)
legacy_routes._assert_entitlement(request) authenticated_for_log: Optional[bool] = None
if not str(getattr(request.state, "auth_user_id", "") or "").strip(): outcome = "ok"
legacy_routes._bind_optional_supabase_identity(request) status_code = 200
subscription_active_for_log: Optional[bool] = None
user_id = getattr(request.state, "auth_user_id", None) try:
email = getattr(request.state, "auth_email", None) request.state.skip_subscription_gate = True
subscription_required = bool( timer.measure("assert_entitlement", lambda: legacy_routes._assert_entitlement(request))
legacy_routes.SUPABASE_ENTITLEMENT.enabled if not str(getattr(request.state, "auth_user_id", "") or "").strip():
and legacy_routes.SUPABASE_ENTITLEMENT.require_subscription timer.measure(
) "bind_identity",
subscription_active = None lambda: legacy_routes._bind_optional_supabase_identity(request),
subscription_plan_code = None
subscription_source = None
subscription_is_trial = False
subscription_starts_at = None
subscription_expires_at = None
subscription_total_expires_at = None
subscription_queued_days = 0
subscription_queued_count = 0
referral = None
if legacy_routes.SUPABASE_ENTITLEMENT.enabled and user_id:
try:
legacy_routes.SUPABASE_ENTITLEMENT.ensure_signup_trial(user_id, email)
try:
subscription_window = legacy_routes.SUPABASE_ENTITLEMENT.get_subscription_window(
user_id,
respect_requirement=False,
bypass_cache=True,
unknown_on_error=True,
)
except TypeError:
subscription_window = legacy_routes.SUPABASE_ENTITLEMENT.get_subscription_window(
user_id,
respect_requirement=False,
)
latest_subscription = None
latest_known_subscription = None
subscription_window_unknown = (
isinstance(subscription_window, dict)
and subscription_window.get("unknown") is True
) )
subscription_window_known = (
isinstance(subscription_window, dict)
and not subscription_window_unknown
)
if subscription_window_known:
current_subscription = subscription_window.get("current")
if isinstance(current_subscription, dict):
latest_subscription = current_subscription
rows = subscription_window.get("rows")
if not latest_subscription and isinstance(rows, list):
latest_known_subscription = next(
(row for row in rows if isinstance(row, dict)),
None,
)
if (
not latest_subscription
and not latest_known_subscription
and not subscription_window_unknown
and not subscription_window_known
and not subscription_required
):
latest_subscription = (
legacy_routes.SUPABASE_ENTITLEMENT.get_latest_active_subscription(
user_id,
respect_requirement=False,
)
)
subscription_active = ( user_id = getattr(request.state, "auth_user_id", None)
None if subscription_window_unknown else bool(latest_subscription) email = getattr(request.state, "auth_email", None)
) authenticated_for_log = bool(user_id)
if ( subscription_required = bool(
subscription_required
and subscription_active is False
):
raise HTTPException(status_code=403, detail="Subscription required")
if not subscription_window_unknown and not latest_known_subscription:
latest_known_subscription = latest_subscription
if not subscription_window_unknown and not latest_known_subscription:
latest_known_subscription = (
legacy_routes.SUPABASE_ENTITLEMENT.get_latest_subscription_any_status(
user_id
)
)
if isinstance(latest_subscription, dict):
subscription_plan_code = latest_subscription.get("plan_code")
subscription_source = latest_subscription.get("source")
subscription_is_trial = _subscription_row_is_trial(latest_subscription)
subscription_starts_at = latest_subscription.get("starts_at")
subscription_expires_at = latest_subscription.get("expires_at")
elif isinstance(latest_known_subscription, dict):
subscription_plan_code = latest_known_subscription.get("plan_code")
subscription_source = latest_known_subscription.get("source")
subscription_is_trial = _subscription_row_is_trial(latest_known_subscription)
subscription_starts_at = latest_known_subscription.get("starts_at")
subscription_expires_at = latest_known_subscription.get("expires_at")
if subscription_window_known:
subscription_total_expires_at = subscription_window.get("total_expires_at")
subscription_queued_days = int(subscription_window.get("queued_days") or 0)
subscription_queued_count = int(subscription_window.get("queued_count") or 0)
referral = legacy_routes.SUPABASE_ENTITLEMENT.get_referral_summary(user_id)
except HTTPException:
raise
except Exception:
if subscription_required:
raise HTTPException(status_code=403, detail="Subscription required")
subscription_active = None
subscription_plan_code = None
subscription_source = None
subscription_is_trial = False
subscription_starts_at = None
subscription_expires_at = None
subscription_total_expires_at = None
subscription_queued_days = 0
subscription_queued_count = 0
referral = None
points = legacy_routes._resolve_auth_points(request)
weekly_profile = legacy_routes._resolve_weekly_profile(request)
telegram_pricing = None
if user_id:
try:
pricing = TelegramGroupPricing()
if pricing.configured:
linked = DBManager().get_user_by_supabase_user_id(user_id)
telegram_id = (
int(linked.get("telegram_id") or 0)
if isinstance(linked, dict)
else 0
)
telegram_pricing = pricing.resolve_price_for_telegram_id(
telegram_id or None
)
except Exception:
telegram_pricing = None
return {
"authenticated": bool(user_id),
"user_id": user_id,
"email": email,
"points": points,
"weekly_points": weekly_profile["weekly_points"],
"weekly_rank": weekly_profile["weekly_rank"],
"entitlement_mode": (
"supabase_required"
if legacy_routes.SUPABASE_ENTITLEMENT.enabled
and legacy_routes._SUPABASE_AUTH_REQUIRED
else "supabase_optional"
if legacy_routes.SUPABASE_ENTITLEMENT.enabled
else "legacy_token"
if legacy_routes._ENTITLEMENT_GUARD_ENABLED
else "disabled"
),
"auth_required": bool(
legacy_routes.SUPABASE_ENTITLEMENT.enabled legacy_routes.SUPABASE_ENTITLEMENT.enabled
and legacy_routes._SUPABASE_AUTH_REQUIRED and legacy_routes.SUPABASE_ENTITLEMENT.require_subscription
), )
"subscription_required": subscription_required, subscription_active = None
"subscription_active": subscription_active, subscription_plan_code = None
"subscription_plan_code": subscription_plan_code, subscription_source = None
"subscription_source": subscription_source, subscription_is_trial = False
"subscription_is_trial": subscription_is_trial, subscription_starts_at = None
"subscription_starts_at": subscription_starts_at, subscription_expires_at = None
"subscription_expires_at": subscription_expires_at, subscription_total_expires_at = None
"subscription_total_expires_at": subscription_total_expires_at, subscription_queued_days = 0
"subscription_queued_days": subscription_queued_days, subscription_queued_count = 0
"subscription_queued_count": subscription_queued_count, referral = None
"telegram_pricing": telegram_pricing,
"referral": referral, if legacy_routes.SUPABASE_ENTITLEMENT.enabled and user_id:
} try:
timer.measure(
"ensure_signup_trial",
lambda: legacy_routes.SUPABASE_ENTITLEMENT.ensure_signup_trial(
user_id,
email,
),
)
try:
subscription_window = timer.measure(
"subscription_window",
lambda: legacy_routes.SUPABASE_ENTITLEMENT.get_subscription_window(
user_id,
respect_requirement=False,
bypass_cache=True,
unknown_on_error=True,
),
)
except TypeError:
subscription_window = timer.measure(
"subscription_window",
lambda: legacy_routes.SUPABASE_ENTITLEMENT.get_subscription_window(
user_id,
respect_requirement=False,
),
)
latest_subscription = None
latest_known_subscription = None
subscription_window_unknown = (
isinstance(subscription_window, dict)
and subscription_window.get("unknown") is True
)
subscription_window_known = (
isinstance(subscription_window, dict)
and not subscription_window_unknown
)
if subscription_window_known:
current_subscription = subscription_window.get("current")
if isinstance(current_subscription, dict):
latest_subscription = current_subscription
rows = subscription_window.get("rows")
if not latest_subscription and isinstance(rows, list):
latest_known_subscription = next(
(row for row in rows if isinstance(row, dict)),
None,
)
if (
not latest_subscription
and not latest_known_subscription
and not subscription_window_unknown
and not subscription_window_known
and not subscription_required
):
latest_subscription = timer.measure(
"latest_active_subscription",
lambda: legacy_routes.SUPABASE_ENTITLEMENT.get_latest_active_subscription(
user_id,
respect_requirement=False,
),
)
subscription_active = (
None if subscription_window_unknown else bool(latest_subscription)
)
subscription_active_for_log = subscription_active
if subscription_required and subscription_active is False:
raise HTTPException(status_code=403, detail="Subscription required")
if not subscription_window_unknown and not latest_known_subscription:
latest_known_subscription = latest_subscription
if not subscription_window_unknown and not latest_known_subscription:
latest_known_subscription = timer.measure(
"latest_subscription_history",
lambda: legacy_routes.SUPABASE_ENTITLEMENT.get_latest_subscription_any_status(
user_id
),
)
if isinstance(latest_subscription, dict):
subscription_plan_code = latest_subscription.get("plan_code")
subscription_source = latest_subscription.get("source")
subscription_is_trial = _subscription_row_is_trial(
latest_subscription
)
subscription_starts_at = latest_subscription.get("starts_at")
subscription_expires_at = latest_subscription.get("expires_at")
elif isinstance(latest_known_subscription, dict):
subscription_plan_code = latest_known_subscription.get("plan_code")
subscription_source = latest_known_subscription.get("source")
subscription_is_trial = _subscription_row_is_trial(
latest_known_subscription
)
subscription_starts_at = latest_known_subscription.get("starts_at")
subscription_expires_at = latest_known_subscription.get("expires_at")
if subscription_window_known:
subscription_total_expires_at = subscription_window.get(
"total_expires_at"
)
subscription_queued_days = int(
subscription_window.get("queued_days") or 0
)
subscription_queued_count = int(
subscription_window.get("queued_count") or 0
)
referral = timer.measure(
"referral_summary",
lambda: legacy_routes.SUPABASE_ENTITLEMENT.get_referral_summary(
user_id
),
)
except HTTPException:
raise
except Exception:
if subscription_required:
raise HTTPException(status_code=403, detail="Subscription required")
subscription_active = None
subscription_active_for_log = None
subscription_plan_code = None
subscription_source = None
subscription_is_trial = False
subscription_starts_at = None
subscription_expires_at = None
subscription_total_expires_at = None
subscription_queued_days = 0
subscription_queued_count = 0
referral = None
points = timer.measure(
"auth_points",
lambda: legacy_routes._resolve_auth_points(request),
)
weekly_profile = timer.measure(
"weekly_profile",
lambda: legacy_routes._resolve_weekly_profile(request),
)
def resolve_telegram_pricing() -> Any:
if not user_id:
return None
pricing = TelegramGroupPricing()
if not pricing.configured:
return None
linked = DBManager().get_user_by_supabase_user_id(user_id)
telegram_id = (
int(linked.get("telegram_id") or 0) if isinstance(linked, dict) else 0
)
return pricing.resolve_price_for_telegram_id(telegram_id or None)
telegram_pricing = None
if user_id:
try:
telegram_pricing = timer.measure(
"telegram_pricing",
resolve_telegram_pricing,
)
except Exception:
telegram_pricing = None
payload = {
"authenticated": bool(user_id),
"user_id": user_id,
"email": email,
"points": points,
"weekly_points": weekly_profile["weekly_points"],
"weekly_rank": weekly_profile["weekly_rank"],
"entitlement_mode": (
"supabase_required"
if legacy_routes.SUPABASE_ENTITLEMENT.enabled
and legacy_routes._SUPABASE_AUTH_REQUIRED
else "supabase_optional"
if legacy_routes.SUPABASE_ENTITLEMENT.enabled
else "legacy_token"
if legacy_routes._ENTITLEMENT_GUARD_ENABLED
else "disabled"
),
"auth_required": bool(
legacy_routes.SUPABASE_ENTITLEMENT.enabled
and legacy_routes._SUPABASE_AUTH_REQUIRED
),
"subscription_required": subscription_required,
"subscription_active": subscription_active,
"subscription_plan_code": subscription_plan_code,
"subscription_source": subscription_source,
"subscription_is_trial": subscription_is_trial,
"subscription_starts_at": subscription_starts_at,
"subscription_expires_at": subscription_expires_at,
"subscription_total_expires_at": subscription_total_expires_at,
"subscription_queued_days": subscription_queued_days,
"subscription_queued_count": subscription_queued_count,
"telegram_pricing": telegram_pricing,
"referral": referral,
}
authenticated_for_log = bool(payload["authenticated"])
subscription_active_for_log = (
payload["subscription_active"]
if isinstance(payload["subscription_active"], bool)
else None
)
return payload
except HTTPException as exc:
outcome = f"http_{exc.status_code}"
status_code = exc.status_code
raise
except Exception:
outcome = "exception"
status_code = 500
raise
finally:
timer.finish(
authenticated=authenticated_for_log,
outcome=outcome,
status_code=status_code,
subscription_active=subscription_active_for_log,
)
def apply_referral_code(request: Request, body: ReferralApplyRequest) -> Dict[str, Any]: def apply_referral_code(request: Request, body: ReferralApplyRequest) -> Dict[str, Any]: