mirror of
https://github.com/koala73/worldmonitor.git
synced 2026-05-05 06:41:59 +02:00
* feat(checkout): prefill Dodo checkout with Clerk name and email Reads givenName, familyName, and email from Convex auth identity (populated by Clerk JWT) and passes them to the Dodo checkout customer field. Users no longer need to re-enter their details. Requires npx convex deploy after merge. * fix(checkout): use resolveUserIdentity helper, fix name:undefined P2: Added resolveUserIdentity to convex/lib/auth.ts instead of calling ctx.auth.getUserIdentity() directly (violates convention). P1: name field now only included when non-empty, preventing name:undefined from being silently dropped by JSON serialization.
62 lines
1.8 KiB
TypeScript
62 lines
1.8 KiB
TypeScript
import { QueryCtx, MutationCtx, ActionCtx } from "../_generated/server";
|
|
|
|
export const DEV_USER_ID = "test-user-001";
|
|
|
|
/**
|
|
* True only when explicitly running `convex dev` (which sets CONVEX_IS_DEV).
|
|
* Never infer dev mode from missing env vars — that would make production
|
|
* behave like dev if CONVEX_CLOUD_URL happens to be unset.
|
|
*/
|
|
export const isDev = process.env.CONVEX_IS_DEV === "true";
|
|
|
|
/**
|
|
* Returns the current user's ID, or null if unauthenticated.
|
|
*
|
|
* Resolution order:
|
|
* 1. Real auth identity from Clerk/Convex auth (ctx.auth.getUserIdentity)
|
|
* 2. Dev-only fallback to test-user-001 (only when CONVEX_IS_DEV=true)
|
|
*
|
|
* This is the sole entry point for resolving the current user —
|
|
* no Convex function should call auth APIs directly.
|
|
*/
|
|
export async function resolveUserId(
|
|
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
): Promise<string | null> {
|
|
const identity = await ctx.auth.getUserIdentity();
|
|
if (identity?.subject) {
|
|
return identity.subject;
|
|
}
|
|
|
|
if (isDev) {
|
|
return DEV_USER_ID;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Returns the full user identity (name, email, etc.) or null.
|
|
* Use when you need more than just the user ID (e.g., checkout prefill).
|
|
*/
|
|
export async function resolveUserIdentity(
|
|
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
): Promise<{ subject: string; name?: string; givenName?: string; familyName?: string; email?: string } | null> {
|
|
const identity = await ctx.auth.getUserIdentity();
|
|
if (identity?.subject) return identity;
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Returns the current user's ID or throws if unauthenticated.
|
|
* Use for mutations/actions that always require auth.
|
|
*/
|
|
export async function requireUserId(
|
|
ctx: QueryCtx | MutationCtx | ActionCtx,
|
|
): Promise<string> {
|
|
const userId = await resolveUserId(ctx);
|
|
if (!userId) {
|
|
throw new Error("Authentication required");
|
|
}
|
|
return userId;
|
|
}
|