Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/api/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@

export { appRouter, type AppRouter } from "./root";
export { createContext, type Context } from "./context";
export { createTRPCRouter, publicProcedure, protectedProcedure } from "./trpc";
export { createTRPCRouter, publicProcedure, protectedProcedure } from "./trpc";
export { rateLimit, RATE_LIMITS } from "./middleware/security";
export { cache, CacheKeys } from "./middleware/cache";
59 changes: 37 additions & 22 deletions packages/api/src/routers/stripe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,32 +37,47 @@ export const stripeRouter = createTRPCRouter({
});
}

const session = await stripe.checkout.sessions.create({
payment_method_types: ["card"],
line_items: [
{
price_data: {
currency: "usd",
product_data: {
name: "DSGT Membership",
description: "One year membership to Data Science at Georgia Tech",
// images: ["https://example.com/logo.png"], // Optional: Add a logo if available
try {
const session = await stripe.checkout.sessions.create({
payment_method_types: ["card"],
line_items: [
{
price_data: {
currency: "usd",
product_data: {
name: "DSGT Membership",
description: "One year membership to Data Science at Georgia Tech",
// images: ["https://example.com/logo.png"], // Optional: Add a logo if available
},
unit_amount: 2500, // $15.00
},
unit_amount: 2500, // $15.00
quantity: 1,
},
quantity: 1,
],
mode: "payment",
success_url: `${input.returnUrl}?payment=success&session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${input.returnUrl}?payment=cancelled`,
customer_email: user.email,
metadata: {
userId: ctx.userId!,
},
],
mode: "payment",
success_url: `${input.returnUrl}?payment=success&session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${input.returnUrl}?payment=cancelled`,
customer_email: user.email,
metadata: {
userId: ctx.userId!,
},
});
});

return { url: session.url };
return { url: session.url };
} catch (error: any) {
console.error("Stripe Checkout Error:", error);
// Check for invalid API key errors specifically if possible, but obscure all
if (error.message?.includes("Invalid API Key")) {
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: "Payment configuration error. Please contact support.",
});
}
throw new TRPCError({
code: "INTERNAL_SERVER_ERROR",
message: "Failed to create checkout session. Please try again later.",
});
}
}),

/**
Expand Down
28 changes: 17 additions & 11 deletions packages/auth/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,17 +121,23 @@ export const authConfig: NextAuthConfig = {
"https://datasciencegt.org";
const host = new URL(baseUrl).host;

const result = await transport.sendMail({
to: identifier,
from: provider.from,
subject: `${code} — Your sign-in code for ${host}`,
text: `Your sign-in code is: ${code}\n\nEnter this code on ${host} to sign in. It expires in 10 minutes.\n\nIf you didn't request this, you can safely ignore this email.\n`,
html: html({ code, host }),
});

const failed = result.rejected.concat(result.pending).filter(Boolean);
if (failed.length) {
throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`);
try {
const result = await transport.sendMail({
to: identifier,
from: provider.from,
subject: `${code} — Your sign-in code for ${host}`,
text: `Your sign-in code is: ${code}\n\nEnter this code on ${host} to sign in. It expires in 10 minutes.\n\nIf you didn't request this, you can safely ignore this email.\n`,
html: html({ code, host }),
});

const failed = result.rejected.concat(result.pending).filter(Boolean);
if (failed.length) {
console.error(`[sendVerificationRequest] Email(s) could not be sent: ${failed.join(", ")}`);
throw new Error(`Email(s) could not be sent`);
}
} catch (error) {
console.error("[sendVerificationRequest] Failed to send email:", error);
throw new Error("Failed to send verification email. Please try again later.");
}
},
}),
Expand Down
7 changes: 5 additions & 2 deletions packages/db/src/schemas/stripe.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { pgTable, text, timestamp, uuid, integer, boolean } from "drizzle-orm/pg-core";
import { pgTable, text, timestamp, uuid, integer, boolean, index } from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm";
import { users } from "./auth";
import { members } from "./members";
Expand Down Expand Up @@ -33,7 +33,10 @@ export const stripePayments = pgTable("stripe_payment", {
metadata: text("metadata"), // JSON string for any extra Stripe metadata
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(),
});
}, (table) => ({
customerEmailIdx: index("stripe_payment_customer_email_idx").on(table.customerEmail),
linkedUserIdIdx: index("stripe_payment_linked_user_id_idx").on(table.linkedUserId),
}));

/**
* Links users who signed in with a different email (e.g., Google)
Expand Down
Loading
Loading