feat(cloud): pause members when subscription is cancelled

This commit is contained in:
Henry
2026-05-21 22:52:14 +01:00
parent 971348a397
commit 8d8cfa3bae
8 changed files with 167 additions and 42 deletions

View File

@@ -1,4 +1,4 @@
import { and, count, eq, isNull, or } from "drizzle-orm";
import { and, count, eq, isNull, ne, or } from "drizzle-orm";
import type { dbClient } from "@kan/db/client";
import type { MemberRole, MemberStatus } from "@kan/db/schema";
@@ -92,14 +92,14 @@ export const getByPublicIdsWithUsers = async (
return db.query.workspaceMembers.findMany({
where: (members, { inArray: inArrayFn, eq, and, isNull: isNullFn }) => {
const conditions = [inArrayFn(members.publicId, memberPublicIds)];
if (workspaceId) {
conditions.push(eq(members.workspaceId, workspaceId));
}
conditions.push(eq(members.status, "active"));
conditions.push(isNullFn(members.deletedAt));
return and(...conditions);
},
with: {
@@ -193,6 +193,68 @@ export const pauseAllMembers = async (db: dbClient, workspaceId: number) => {
);
};
export const getPreservableMemberId = async (
db: dbClient,
workspaceId: number,
ownerUserId: string | null,
): Promise<string | null> => {
if (ownerUserId) {
const owner = await db.query.workspaceMembers.findFirst({
columns: { userId: true },
where: and(
eq(workspaceMembers.workspaceId, workspaceId),
eq(workspaceMembers.userId, ownerUserId),
eq(workspaceMembers.status, "active"),
isNull(workspaceMembers.deletedAt),
),
});
if (owner?.userId) return owner.userId;
}
const admin = await db.query.workspaceMembers.findFirst({
columns: { userId: true },
where: and(
eq(workspaceMembers.workspaceId, workspaceId),
eq(workspaceMembers.role, "admin"),
eq(workspaceMembers.status, "active"),
isNull(workspaceMembers.deletedAt),
),
orderBy: (m, { asc }) => [asc(m.createdAt)],
});
if (admin?.userId) return admin.userId;
const anyMember = await db.query.workspaceMembers.findFirst({
columns: { userId: true },
where: and(
eq(workspaceMembers.workspaceId, workspaceId),
eq(workspaceMembers.status, "active"),
isNull(workspaceMembers.deletedAt),
),
orderBy: (m, { asc }) => [asc(m.createdAt)],
});
return anyMember?.userId ?? null;
};
export const pauseMembersExcept = async (
db: dbClient,
workspaceId: number,
preserveUserId: string,
) => {
await db
.update(workspaceMembers)
.set({ status: "paused" })
.where(
and(
eq(workspaceMembers.workspaceId, workspaceId),
eq(workspaceMembers.status, "active"),
or(
isNull(workspaceMembers.userId),
ne(workspaceMembers.userId, preserveUserId),
),
),
);
};
export const updateRole = async (
db: dbClient,
args: {

View File

@@ -176,6 +176,7 @@ export const getByPublicId = (db: dbClient, workspacePublicId: string) => {
name: true,
plan: true,
slug: true,
createdBy: true,
},
where: eq(workspaces.publicId, workspacePublicId),
});