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
+100
View File
@@ -7,6 +7,7 @@ import {
PrismaPrincipalResolver,
syncExternalPrincipalMemberships,
} from "../../src/permission.js";
import { lockActiveOrganization } from "../../src/org/status.js";
describe("ADR-0019 authorization", () => {
beforeEach(async () => {
@@ -96,6 +97,75 @@ describe("ADR-0019 authorization", () => {
});
});
it.each(["SUSPENDED", "ARCHIVED"] as const)(
"denies every project authorization when the organization is %s",
async (status) => {
await prisma.project.create({
data: { id: `p-org-${status}`, organizationId: DEFAULT_ORG_ID, name: status, workspaceDir: `/tmp/org-${status}` },
});
await prisma.user.create({
data: {
id: `u-org-${status}`,
feishuOpenId: `ou_org_${status}`,
displayName: status,
organizationMemberships: { create: { organizationId: DEFAULT_ORG_ID, role: "OWNER" } },
},
});
await prisma.permissionGrant.create({
data: {
resourceType: "PROJECT",
resourceId: `p-org-${status}`,
principalType: "USER",
principalId: `ou_org_${status}`,
role: "MANAGE",
},
});
await prisma.organization.update({ where: { id: DEFAULT_ORG_ID }, data: { status } });
for (const action of ["project.read", "project.edit", "collaborator.manage", "agent.trigger", "agent.cancel"] as const) {
const decision = await createPermissionAuthorizer(prisma).can({
actor: { feishuOpenId: `ou_org_${status}` },
action,
resource: { type: "PROJECT", id: `p-org-${status}` },
});
expect(decision.allowed).toBe(false);
expect(decision.reason).toContain(`organization ${DEFAULT_ORG_ID} is ${status}`);
}
},
);
it("serializes a lifecycle transition behind an admitted customer transaction", async () => {
let releaseOperation!: () => void;
const operationHeld = new Promise<void>((resolve) => {
releaseOperation = resolve;
});
let markLocked!: () => void;
const rowLocked = new Promise<void>((resolve) => {
markLocked = resolve;
});
const operation = prisma.$transaction(async (tx) => {
await lockActiveOrganization(tx, DEFAULT_ORG_ID);
markLocked();
await operationHeld;
});
await rowLocked;
let transitionCommitted = false;
const transition = prisma.organization.update({
where: { id: DEFAULT_ORG_ID },
data: { status: "SUSPENDED" },
}).then(() => {
transitionCommitted = true;
});
await new Promise((resolve) => setTimeout(resolve, 100));
expect(transitionCommitted).toBe(false);
releaseOperation();
await operation;
await transition;
expect(transitionCommitted).toBe(true);
});
it("uses external Feishu principal memberships as grantable principals", async () => {
await prisma.project.create({
data: { id: "p-auth-ext", organizationId: DEFAULT_ORG_ID, name: "External", workspaceDir: "/tmp/auth-ext" },
@@ -177,6 +247,36 @@ describe("ADR-0019 authorization", () => {
expect(activeB.principals).not.toContainEqual({ type: "FEISHU_DEPARTMENT", id: "dep-b" });
});
it("blocks directory sync and team grants for an archived organization", async () => {
const team = await prisma.team.create({
data: { organizationId: DEFAULT_ORG_ID, slug: "archived-team", name: "Archived Team" },
});
await prisma.project.create({
data: { id: "p-archived-grant", organizationId: DEFAULT_ORG_ID, name: "Archived", workspaceDir: "/tmp/archived" },
});
await prisma.organization.update({ where: { id: DEFAULT_ORG_ID }, data: { status: "ARCHIVED" } });
const expected = `organization ${DEFAULT_ORG_ID} is ARCHIVED`;
await expect(syncExternalPrincipalMemberships(prisma, {
organizationId: DEFAULT_ORG_ID,
source: "blocked-sync",
memberships: [{
feishuOpenId: "ou_blocked_sync",
displayName: "Blocked",
principalType: "FEISHU_DEPARTMENT",
principalId: "dep-blocked",
}],
})).rejects.toThrow(expected);
await expect(grantTeamProjectAccess(prisma, {
projectId: "p-archived-grant",
teamId: team.id,
role: "EDIT",
})).rejects.toThrow(expected);
await expect(prisma.externalDirectoryConnection.count()).resolves.toBe(0);
await expect(prisma.permissionGrant.count({ where: { resourceId: "p-archived-grant" } })).resolves.toBe(0);
});
it("lets PermissionSettings constrain agent trigger without granting by itself", async () => {
await prisma.project.create({
data: { id: "p-auth-policy", organizationId: DEFAULT_ORG_ID, name: "Policy", workspaceDir: "/tmp/auth-policy" },