import { ConvexError } from "convex/values"; import type { Id } from "./_generated/dataModel"; import type { MutationCtx, QueryCtx } from "./_generated/server"; export interface AuthContext { readonly auth: { readonly getUserIdentity: () => Promise<{ readonly tokenIdentifier: string; } | null>; }; } export const requireOwnerId = async (ctx: AuthContext): Promise => { const identity = await ctx.auth.getUserIdentity(); if (!identity) { throw new ConvexError("Authentication required"); } return identity.tokenIdentifier; }; /** * Resolve the authenticated identity and prove it is a member of the given * organization. Throws on unauthenticated or non-member access. Returns the * canonical user ID (the Better Auth `tokenIdentifier`). */ export const requireOrganizationMember = async ( ctx: QueryCtx | MutationCtx, organizationId: Id<"organizations"> ): Promise => { const userId = await requireOwnerId(ctx); const membership = await ctx.db .query("organizationMembers") .withIndex("by_organizationId_and_userId", (q) => q.eq("organizationId", organizationId).eq("userId", userId) ) .unique(); if (!membership) { throw new ConvexError("Organization membership required"); } return userId; };