feat: add migration

This commit is contained in:
Mauricio Siu
2025-02-09 18:19:21 -06:00
parent 6b9fd596e5
commit c04bf3c7e0
31 changed files with 5790 additions and 440 deletions

View File

@@ -0,0 +1,7 @@
import { auth } from "@dokploy/server/index";
import { toNodeHandler } from "better-auth/node";
// Disallow body parsing, we will parse it manually
export const config = { api: { bodyParser: false } };
export default toNodeHandler(auth.handler);

View File

@@ -18,224 +18,224 @@ export default async function handler(
req: NextApiRequest,
res: NextApiResponse,
) {
if (!endpointSecret) {
return res.status(400).send("Webhook Error: Missing Stripe Secret Key");
}
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: "2024-09-30.acacia",
maxNetworkRetries: 3,
});
// if (!endpointSecret) {
// return res.status(400).send("Webhook Error: Missing Stripe Secret Key");
// }
// const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
// apiVersion: "2024-09-30.acacia",
// maxNetworkRetries: 3,
// });
const buf = await buffer(req);
const sig = req.headers["stripe-signature"] as string;
// const buf = await buffer(req);
// const sig = req.headers["stripe-signature"] as string;
let event: Stripe.Event;
// let event: Stripe.Event;
try {
event = stripe.webhooks.constructEvent(buf, sig, endpointSecret);
} catch (err) {
console.error(
"Webhook signature verification failed.",
err instanceof Error ? err.message : err,
);
return res.status(400).send("Webhook Error: ");
}
// try {
// event = stripe.webhooks.constructEvent(buf, sig, endpointSecret);
// } catch (err) {
// console.error(
// "Webhook signature verification failed.",
// err instanceof Error ? err.message : err,
// );
// return res.status(400).send("Webhook Error: ");
// }
const webhooksAllowed = [
"customer.subscription.created",
"customer.subscription.deleted",
"customer.subscription.updated",
"invoice.payment_succeeded",
"invoice.payment_failed",
"customer.deleted",
"checkout.session.completed",
];
// const webhooksAllowed = [
// "customer.subscription.created",
// "customer.subscription.deleted",
// "customer.subscription.updated",
// "invoice.payment_succeeded",
// "invoice.payment_failed",
// "customer.deleted",
// "checkout.session.completed",
// ];
if (!webhooksAllowed.includes(event.type)) {
return res.status(400).send("Webhook Error: Invalid Event Type");
}
// if (!webhooksAllowed.includes(event.type)) {
// return res.status(400).send("Webhook Error: Invalid Event Type");
// }
switch (event.type) {
case "checkout.session.completed": {
const session = event.data.object as Stripe.Checkout.Session;
const adminId = session?.metadata?.adminId as string;
// switch (event.type) {
// case "checkout.session.completed": {
// const session = event.data.object as Stripe.Checkout.Session;
// const adminId = session?.metadata?.adminId as string;
const subscription = await stripe.subscriptions.retrieve(
session.subscription as string,
);
await db
.update(admins)
.set({
stripeCustomerId: session.customer as string,
stripeSubscriptionId: session.subscription as string,
serversQuantity: subscription?.items?.data?.[0]?.quantity ?? 0,
})
.where(eq(admins.adminId, adminId))
.returning();
// const subscription = await stripe.subscriptions.retrieve(
// session.subscription as string,
// );
// await db
// .update(admins)
// .set({
// stripeCustomerId: session.customer as string,
// stripeSubscriptionId: session.subscription as string,
// serversQuantity: subscription?.items?.data?.[0]?.quantity ?? 0,
// })
// .where(eq(admins.adminId, adminId))
// .returning();
const admin = await findAdminById(adminId);
if (!admin) {
return res.status(400).send("Webhook Error: Admin not found");
}
const newServersQuantity = admin.serversQuantity;
await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
break;
}
case "customer.subscription.created": {
const newSubscription = event.data.object as Stripe.Subscription;
// const admin = await findAdminById(adminId);
// if (!admin) {
// return res.status(400).send("Webhook Error: Admin not found");
// }
// const newServersQuantity = admin.serversQuantity;
// await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
// break;
// }
// case "customer.subscription.created": {
// const newSubscription = event.data.object as Stripe.Subscription;
await db
.update(admins)
.set({
stripeSubscriptionId: newSubscription.id,
stripeCustomerId: newSubscription.customer as string,
})
.where(eq(admins.stripeCustomerId, newSubscription.customer as string))
.returning();
// await db
// .update(admins)
// .set({
// stripeSubscriptionId: newSubscription.id,
// stripeCustomerId: newSubscription.customer as string,
// })
// .where(eq(admins.stripeCustomerId, newSubscription.customer as string))
// .returning();
break;
}
// break;
// }
case "customer.subscription.deleted": {
const newSubscription = event.data.object as Stripe.Subscription;
// case "customer.subscription.deleted": {
// const newSubscription = event.data.object as Stripe.Subscription;
await db
.update(admins)
.set({
stripeSubscriptionId: null,
serversQuantity: 0,
})
.where(eq(admins.stripeCustomerId, newSubscription.customer as string));
// await db
// .update(admins)
// .set({
// stripeSubscriptionId: null,
// serversQuantity: 0,
// })
// .where(eq(admins.stripeCustomerId, newSubscription.customer as string));
const admin = await findAdminByStripeCustomerId(
newSubscription.customer as string,
);
// const admin = await findAdminByStripeCustomerId(
// newSubscription.customer as string,
// );
if (!admin) {
return res.status(400).send("Webhook Error: Admin not found");
}
// if (!admin) {
// return res.status(400).send("Webhook Error: Admin not found");
// }
await disableServers(admin.adminId);
break;
}
case "customer.subscription.updated": {
const newSubscription = event.data.object as Stripe.Subscription;
// await disableServers(admin.adminId);
// break;
// }
// case "customer.subscription.updated": {
// const newSubscription = event.data.object as Stripe.Subscription;
const admin = await findAdminByStripeCustomerId(
newSubscription.customer as string,
);
// const admin = await findAdminByStripeCustomerId(
// newSubscription.customer as string,
// );
if (!admin) {
return res.status(400).send("Webhook Error: Admin not found");
}
// if (!admin) {
// return res.status(400).send("Webhook Error: Admin not found");
// }
if (newSubscription.status === "active") {
await db
.update(admins)
.set({
serversQuantity: newSubscription?.items?.data?.[0]?.quantity ?? 0,
})
.where(
eq(admins.stripeCustomerId, newSubscription.customer as string),
);
// if (newSubscription.status === "active") {
// await db
// .update(admins)
// .set({
// serversQuantity: newSubscription?.items?.data?.[0]?.quantity ?? 0,
// })
// .where(
// eq(admins.stripeCustomerId, newSubscription.customer as string),
// );
const newServersQuantity = admin.serversQuantity;
await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
} else {
await disableServers(admin.adminId);
await db
.update(admins)
.set({ serversQuantity: 0 })
.where(
eq(admins.stripeCustomerId, newSubscription.customer as string),
);
}
// const newServersQuantity = admin.serversQuantity;
// await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
// } else {
// await disableServers(admin.adminId);
// await db
// .update(admins)
// .set({ serversQuantity: 0 })
// .where(
// eq(admins.stripeCustomerId, newSubscription.customer as string),
// );
// }
break;
}
case "invoice.payment_succeeded": {
const newInvoice = event.data.object as Stripe.Invoice;
// break;
// }
// case "invoice.payment_succeeded": {
// const newInvoice = event.data.object as Stripe.Invoice;
const suscription = await stripe.subscriptions.retrieve(
newInvoice.subscription as string,
);
// const suscription = await stripe.subscriptions.retrieve(
// newInvoice.subscription as string,
// );
if (suscription.status !== "active") {
console.log(
`Skipping invoice.payment_succeeded for subscription ${suscription.id} with status ${suscription.status}`,
);
break;
}
// if (suscription.status !== "active") {
// console.log(
// `Skipping invoice.payment_succeeded for subscription ${suscription.id} with status ${suscription.status}`,
// );
// break;
// }
await db
.update(admins)
.set({
serversQuantity: suscription?.items?.data?.[0]?.quantity ?? 0,
})
.where(eq(admins.stripeCustomerId, suscription.customer as string));
// await db
// .update(admins)
// .set({
// serversQuantity: suscription?.items?.data?.[0]?.quantity ?? 0,
// })
// .where(eq(admins.stripeCustomerId, suscription.customer as string));
const admin = await findAdminByStripeCustomerId(
suscription.customer as string,
);
// const admin = await findAdminByStripeCustomerId(
// suscription.customer as string,
// );
if (!admin) {
return res.status(400).send("Webhook Error: Admin not found");
}
const newServersQuantity = admin.serversQuantity;
await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
break;
}
case "invoice.payment_failed": {
const newInvoice = event.data.object as Stripe.Invoice;
// if (!admin) {
// return res.status(400).send("Webhook Error: Admin not found");
// }
// const newServersQuantity = admin.serversQuantity;
// await updateServersBasedOnQuantity(admin.adminId, newServersQuantity);
// break;
// }
// case "invoice.payment_failed": {
// const newInvoice = event.data.object as Stripe.Invoice;
const subscription = await stripe.subscriptions.retrieve(
newInvoice.subscription as string,
);
// const subscription = await stripe.subscriptions.retrieve(
// newInvoice.subscription as string,
// );
if (subscription.status !== "active") {
const admin = await findAdminByStripeCustomerId(
newInvoice.customer as string,
);
// if (subscription.status !== "active") {
// const admin = await findAdminByStripeCustomerId(
// newInvoice.customer as string,
// );
if (!admin) {
return res.status(400).send("Webhook Error: Admin not found");
}
await db
.update(admins)
.set({
serversQuantity: 0,
})
.where(eq(admins.stripeCustomerId, newInvoice.customer as string));
// if (!admin) {
// return res.status(400).send("Webhook Error: Admin not found");
// }
// await db
// .update(admins)
// .set({
// serversQuantity: 0,
// })
// .where(eq(admins.stripeCustomerId, newInvoice.customer as string));
await disableServers(admin.adminId);
}
// await disableServers(admin.adminId);
// }
break;
}
// break;
// }
case "customer.deleted": {
const customer = event.data.object as Stripe.Customer;
// case "customer.deleted": {
// const customer = event.data.object as Stripe.Customer;
const admin = await findAdminByStripeCustomerId(customer.id);
if (!admin) {
return res.status(400).send("Webhook Error: Admin not found");
}
// const admin = await findAdminByStripeCustomerId(customer.id);
// if (!admin) {
// return res.status(400).send("Webhook Error: Admin not found");
// }
await disableServers(admin.adminId);
await db
.update(admins)
.set({
stripeCustomerId: null,
stripeSubscriptionId: null,
serversQuantity: 0,
})
.where(eq(admins.stripeCustomerId, customer.id));
// await disableServers(admin.adminId);
// await db
// .update(admins)
// .set({
// stripeCustomerId: null,
// stripeSubscriptionId: null,
// serversQuantity: 0,
// })
// .where(eq(admins.stripeCustomerId, customer.id));
break;
}
default:
console.log(`Unhandled event type: ${event.type}`);
}
// break;
// }
// default:
// console.log(`Unhandled event type: ${event.type}`);
// }
return res.status(200).json({ received: true });
}

View File

@@ -70,9 +70,9 @@ import type {
} from "next";
import Head from "next/head";
import { useRouter } from "next/router";
import { useMemo, useState, type ReactElement } from "react";
import superjson from "superjson";
import { type ReactElement, useMemo, useState } from "react";
import { toast } from "sonner";
import superjson from "superjson";
export type Services = {
appName: string;

View File

@@ -201,51 +201,51 @@ Home.getLayout = (page: ReactElement) => {
return <OnboardingLayout>{page}</OnboardingLayout>;
};
export async function getServerSideProps(context: GetServerSidePropsContext) {
if (IS_CLOUD) {
try {
const { user } = await validateRequest(context.req, context.res);
// if (IS_CLOUD) {
// try {
// const { user } = await validateRequest(context.req, context.res);
if (user) {
return {
redirect: {
permanent: true,
destination: "/dashboard/projects",
},
};
}
} catch (error) {}
// if (user) {
// return {
// redirect: {
// permanent: true,
// destination: "/dashboard/projects",
// },
// };
// }
// } catch (error) {}
return {
props: {
IS_CLOUD: IS_CLOUD,
},
};
}
const hasAdmin = await isAdminPresent();
// return {
// props: {
// IS_CLOUD: IS_CLOUD,
// },
// };
// }
// const hasAdmin = await isAdminPresent();
if (!hasAdmin) {
return {
redirect: {
permanent: true,
destination: "/register",
},
};
}
// if (!hasAdmin) {
// return {
// redirect: {
// permanent: true,
// destination: "/register",
// },
// };
// }
const { user } = await validateRequest(context.req, context.res);
// const { user } = await validateRequest(context.req, context.res);
if (user) {
return {
redirect: {
permanent: true,
destination: "/dashboard/projects",
},
};
}
// if (user) {
// return {
// redirect: {
// permanent: true,
// destination: "/dashboard/projects",
// },
// };
// }
return {
props: {
hasAdmin,
// hasAdmin,
},
};
}