-
Notifications
You must be signed in to change notification settings - Fork 77
Expand file tree
/
Copy pathroute.ts
More file actions
83 lines (72 loc) · 2.54 KB
/
Copy pathroute.ts
File metadata and controls
83 lines (72 loc) · 2.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import { and, count, eq, isNotNull, isNull } from "drizzle-orm";
import { NextResponse } from "next/server";
import { db } from "@/lib/db";
import { organization, workflows } from "@/lib/db/schema";
import { authenticateKhAdmin } from "@/lib/kh-admin-auth";
import { ErrorCategory, logSystemError } from "@/lib/logging";
import { buildAuditMetadata, recordAuditEvent } from "@/lib/security/audit-log";
export async function POST(
request: Request,
context: { params: Promise<{ orgId: string }> }
): Promise<NextResponse> {
const auth = authenticateKhAdmin(request);
if (!auth.authenticated) {
return NextResponse.json({ error: auth.error }, { status: 401 });
}
const { orgId } = await context.params;
try {
const now = new Date();
const result = await db.transaction(async (tx) => {
const [existing] = await tx
.select({ id: organization.id, deactivatedAt: organization.deactivatedAt })
.from(organization)
.where(eq(organization.id, orgId))
.limit(1);
if (!existing) {
return { conflict: "not_found" as const };
}
if (!existing.deactivatedAt) {
return { conflict: "not_deactivated" as const };
}
await tx
.update(organization)
.set({ deactivatedAt: null })
.where(eq(organization.id, orgId));
const [{ value: workflowsStillDeactivated }] = await tx
.select({ value: count() })
.from(workflows)
.where(
and(
eq(workflows.organizationId, orgId),
isNotNull(workflows.deactivatedAt),
isNull(workflows.deletedAt)
)
);
return { orgId, activatedAt: now, workflowsStillDeactivated };
});
if ("conflict" in result) {
if (result.conflict === "not_found") {
return NextResponse.json({ error: "Organization not found" }, { status: 404 });
}
return NextResponse.json({ error: "Organization is not deactivated" }, { status: 409 });
}
await recordAuditEvent({
actor: {
userId: null,
organizationId: result.orgId,
authMethod: "kh-admin",
actorLabel: "KeeperHub admin",
},
action: "org.reactivated",
resourceType: "organization",
resourceId: result.orgId,
metadata: buildAuditMetadata(request),
});
return NextResponse.json(result);
} catch (error) {
logSystemError(ErrorCategory.DATABASE, "[Admin] Failed to activate org", error, {
orgId,
});
return NextResponse.json({ error: "Internal server error" }, { status: 500 });
}
}