fix: enforce active organization boundary

This commit is contained in:
2026-07-10 18:42:12 +08:00
parent f07f280b8f
commit d730e51c3d
24 changed files with 1686 additions and 460 deletions
@@ -9,6 +9,8 @@ import {
sessionCookieHeader,
} from "../../src/admin/routes/authRoutes.js";
import { DEFAULT_ORG_ID, prisma, resetDb } from "./helpers.js";
import { addOrgMember } from "../../src/org/members.js";
import { addTeamMember, archiveTeam, createTeam, updateTeam } from "../../src/org/teams.js";
const SESSION_SECRET = "integration-test-session-secret";
@@ -158,4 +160,49 @@ describe("admin members + teams API", () => {
await app.close();
}
});
it("blocks direct member and team mutations for a suspended organization", async () => {
await seedOwner();
await prisma.user.create({ data: { id: "u-direct-member", feishuOpenId: "ou_direct", displayName: "Direct" } });
await prisma.organizationMembership.create({
data: { organizationId: DEFAULT_ORG_ID, userId: "u-direct-member", role: "MEMBER" },
});
const team = await prisma.team.create({
data: { organizationId: DEFAULT_ORG_ID, slug: "existing", name: "Existing" },
});
await prisma.organization.update({ where: { id: DEFAULT_ORG_ID }, data: { status: "SUSPENDED" } });
const expected = `organization ${DEFAULT_ORG_ID} is SUSPENDED`;
await expect(addOrgMember(prisma, {
organizationId: DEFAULT_ORG_ID,
actorRole: "OWNER",
feishuOpenId: "ou_blocked",
role: "MEMBER",
})).rejects.toThrow(expected);
await expect(createTeam(prisma, {
organizationId: DEFAULT_ORG_ID,
slug: "blocked",
name: "Blocked",
})).rejects.toThrow(expected);
await expect(updateTeam(prisma, {
organizationId: DEFAULT_ORG_ID,
teamId: team.id,
name: "Changed",
})).rejects.toThrow(expected);
await expect(addTeamMember(prisma, {
organizationId: DEFAULT_ORG_ID,
teamId: team.id,
userId: "u-direct-member",
})).rejects.toThrow(expected);
await expect(archiveTeam(prisma, {
organizationId: DEFAULT_ORG_ID,
teamId: team.id,
})).rejects.toThrow(expected);
await expect(prisma.user.findUnique({ where: { feishuOpenId: "ou_blocked" } })).resolves.toBeNull();
await expect(prisma.team.findUniqueOrThrow({ where: { id: team.id } })).resolves.toMatchObject({
name: "Existing",
archivedAt: null,
});
});
});