Skip to content

Commit 6fad0b6

Browse files
stripe downgrade (#1905)
* stripe downgrade * ci: apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent e9b7934 commit 6fad0b6

File tree

1 file changed

+107
-18
lines changed

1 file changed

+107
-18
lines changed

packages/api/src/router/stripe/webhook.ts

Lines changed: 107 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,15 @@ import type Stripe from "stripe";
33
import { z } from "zod";
44

55
import { Events, setupAnalytics } from "@openstatus/analytics";
6-
import { eq } from "@openstatus/db";
6+
import { and, asc, eq, isNull, ne } from "@openstatus/db";
77
import {
8+
invitation,
9+
monitor,
10+
notification,
11+
page,
812
selectWorkspaceSchema,
913
user,
14+
usersToWorkspaces,
1015
workspace,
1116
} from "@openstatus/db/src/schema";
1217

@@ -207,24 +212,108 @@ export const webhookRouter = createTRPCRouter({
207212
? subscription.customer
208213
: subscription.customer.id;
209214

210-
const _workspace = await opts.ctx.db
211-
.update(workspace)
212-
.set({
213-
subscriptionId: null,
214-
plan: "free",
215-
paidUntil: null,
216-
})
217-
.where(eq(workspace.stripeId, customerId))
218-
.returning();
215+
const _workspace = await opts.ctx.db.transaction(async (tx) => {
216+
const _workspace = await tx
217+
.update(workspace)
218+
.set({
219+
subscriptionId: null,
220+
plan: "free",
221+
paidUntil: null,
222+
endsAt: null,
223+
limits: JSON.stringify(getLimits("free")),
224+
})
225+
.where(eq(workspace.stripeId, customerId))
226+
.returning();
219227

220-
const customer = await stripe.customers.retrieve(customerId);
228+
if (!_workspace.length) {
229+
throw new TRPCError({
230+
code: "BAD_REQUEST",
231+
message: "Workspace not found",
232+
});
233+
}
221234

222-
if (!_workspace) {
223-
throw new TRPCError({
224-
code: "BAD_REQUEST",
225-
message: "Workspace not found",
226-
});
227-
}
235+
const workspaceId = _workspace[0].id;
236+
237+
const activeMonitors = await tx
238+
.select({ id: monitor.id })
239+
.from(monitor)
240+
.where(
241+
and(
242+
eq(monitor.workspaceId, workspaceId),
243+
eq(monitor.active, true),
244+
isNull(monitor.deletedAt),
245+
),
246+
)
247+
.orderBy(asc(monitor.createdAt));
248+
249+
for (const m of activeMonitors.slice(1)) {
250+
await tx
251+
.update(monitor)
252+
.set({ active: false })
253+
.where(eq(monitor.id, m.id))
254+
.run();
255+
}
256+
257+
const statusPages = await tx
258+
.select({ id: page.id })
259+
.from(page)
260+
.where(eq(page.workspaceId, workspaceId))
261+
.orderBy(asc(page.createdAt));
262+
263+
for (const p of statusPages.slice(1)) {
264+
await tx.delete(page).where(eq(page.id, p.id)).run();
265+
}
266+
267+
if (statusPages.length > 0) {
268+
await tx
269+
.update(page)
270+
.set({
271+
customDomain: "",
272+
password: null,
273+
accessType: "public",
274+
authEmailDomains: null,
275+
})
276+
.where(eq(page.id, statusPages[0].id))
277+
.run();
278+
}
279+
280+
const notifications = await tx
281+
.select({ id: notification.id, provider: notification.provider })
282+
.from(notification)
283+
.where(eq(notification.workspaceId, workspaceId))
284+
.orderBy(asc(notification.createdAt));
285+
286+
const keepNotification =
287+
notifications.find((n) => n.provider === "email") ?? notifications[0];
288+
289+
for (const n of notifications.filter(
290+
(n) => n.id !== keepNotification?.id,
291+
)) {
292+
await tx.delete(notification).where(eq(notification.id, n.id)).run();
293+
}
294+
295+
// Remove all non-owner members from the workspace
296+
await tx
297+
.delete(usersToWorkspaces)
298+
.where(
299+
and(
300+
eq(usersToWorkspaces.workspaceId, workspaceId),
301+
ne(usersToWorkspaces.role, "owner"),
302+
),
303+
)
304+
.run();
305+
306+
// Remove all pending invitations for the workspace
307+
await tx
308+
.delete(invitation)
309+
.where(eq(invitation.workspaceId, workspaceId))
310+
.run();
311+
312+
return _workspace;
313+
});
314+
315+
const workspaceId = _workspace[0].id;
316+
const customer = await stripe.customers.retrieve(customerId);
228317

229318
if (!customer.deleted && customer.email) {
230319
const userResult = await opts.ctx.db
@@ -237,7 +326,7 @@ export const webhookRouter = createTRPCRouter({
237326
const analytics = await setupAnalytics({
238327
userId: `usr_${userResult.id}`,
239328
email: customer.email || undefined,
240-
workspaceId: String(_workspace[0].id),
329+
workspaceId: String(workspaceId),
241330
plan: "free",
242331
});
243332
await analytics.track(Events.DowngradeWorkspace);

0 commit comments

Comments
 (0)