Compare commits

...

1 Commits

Author SHA1 Message Date
Henry
7418cc37cc fix: use server-side signInMagicLink for member invites 2025-07-11 13:48:20 +01:00
2 changed files with 35 additions and 22 deletions

View File

@@ -1,7 +1,6 @@
import { TRPCError } from "@trpc/server"; import { TRPCError } from "@trpc/server";
import { z } from "zod"; import { z } from "zod";
import { authClient } from "@kan/auth/client";
import * as memberRepo from "@kan/db/repository/member.repo"; import * as memberRepo from "@kan/db/repository/member.repo";
import * as userRepo from "@kan/db/repository/user.repo"; import * as userRepo from "@kan/db/repository/user.repo";
import * as workspaceRepo from "@kan/db/repository/workspace.repo"; import * as workspaceRepo from "@kan/db/repository/workspace.repo";
@@ -78,16 +77,15 @@ export const memberRouter = createTRPCRouter({
code: "INTERNAL_SERVER_ERROR", code: "INTERNAL_SERVER_ERROR",
}); });
const { error } = await authClient.signIn.magicLink({ const { status } = await ctx.auth.api.signInMagicLink({
email: input.email, email: input.email,
callbackURL: `/boards?type=invite&memberPublicId=${invite.publicId}`, callbackURL: `/boards?type=invite&memberPublicId=${invite.publicId}`,
}); });
if (error) { if (!status) {
console.error("Failed to send magic link invitation:", { console.error("Failed to send magic link invitation:", {
email: input.email, email: input.email,
callbackURL: `/boards?type=invite&memberPublicId=${invite.publicId}`, callbackURL: `/boards?type=invite&memberPublicId=${invite.publicId}`,
error,
}); });
throw new TRPCError({ throw new TRPCError({

View File

@@ -20,58 +20,73 @@ export interface User {
stripeCustomerId?: string | null | undefined; stripeCustomerId?: string | null | undefined;
} }
const createAuthWithHeaders = (
auth: ReturnType<typeof initAuth>,
headers: Headers,
) => {
return {
api: {
getSession: () => auth.api.getSession({ headers }),
signInMagicLink: (input: { email: string; callbackURL: string }) =>
auth.api.signInMagicLink({
headers,
body: { email: input.email, callbackURL: input.callbackURL },
}),
},
};
};
interface CreateContextOptions { interface CreateContextOptions {
user: User | null | undefined; user: User | null | undefined;
db: dbClient; db: dbClient;
auth: ReturnType<typeof createAuthWithHeaders>;
} }
export const createInnerTRPCContext = (opts: CreateContextOptions) => { export const createInnerTRPCContext = (opts: CreateContextOptions) => {
return { return {
user: opts.user, user: opts.user,
db: opts.db, db: opts.db,
auth: opts.auth,
}; };
}; };
export const createTRPCContext = async ({ req }: CreateNextContextOptions) => { export const createTRPCContext = async ({ req }: CreateNextContextOptions) => {
const db = createDrizzleClient(); const db = createDrizzleClient();
const auth = initAuth(db); const baseAuth = initAuth(db);
const headers = new Headers(req.headers as Record<string, string>);
const auth = createAuthWithHeaders(baseAuth, headers);
const session = await auth.api.getSession({ const session = await auth.api.getSession();
// @ts-expect-error
headers: new Headers(req.headers),
});
return createInnerTRPCContext({ db, user: session?.user }); return createInnerTRPCContext({ db, user: session?.user, auth });
}; };
export const createNextApiContext = async (req: NextApiRequest) => { export const createNextApiContext = async (req: NextApiRequest) => {
const db = createDrizzleClient(); const db = createDrizzleClient();
const auth = initAuth(db); const baseAuth = initAuth(db);
const headers = new Headers(req.headers as Record<string, string>);
const auth = createAuthWithHeaders(baseAuth, headers);
const session = await auth.api.getSession({ const session = await auth.api.getSession();
// @ts-expect-error
headers: new Headers(req.headers),
});
return createInnerTRPCContext({ db, user: session?.user }); return createInnerTRPCContext({ db, user: session?.user, auth });
}; };
export const createRESTContext = async ({ req }: CreateNextContextOptions) => { export const createRESTContext = async ({ req }: CreateNextContextOptions) => {
const db = createDrizzleClient(); const db = createDrizzleClient();
const auth = initAuth(db); const baseAuth = initAuth(db);
const headers = new Headers(req.headers as Record<string, string>);
const auth = createAuthWithHeaders(baseAuth, headers);
let session; let session;
try { try {
session = await auth.api.getSession({ session = await auth.api.getSession();
// @ts-expect-error
headers: new Headers(req.headers),
});
} catch (error) { } catch (error) {
console.error("Error getting session, ", error); console.error("Error getting session, ", error);
throw error; throw error;
} }
return createInnerTRPCContext({ db, user: session?.user }); return createInnerTRPCContext({ db, user: session?.user, auth });
}; };
const t = initTRPC const t = initTRPC