58 lines
2.0 KiB
TypeScript
58 lines
2.0 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { getSessionUser, canMutate } from "@/lib/session";
|
|
import { getTenant } from "@/lib/k8s";
|
|
import { removeTenantAssignment } from "@/lib/db";
|
|
import { safeError } from "@/lib/errors";
|
|
|
|
/**
|
|
* DELETE /api/tenants/[name]/assignments/[userId]
|
|
*
|
|
* Revoke a user's assignment to a tenant. Owner+platform only.
|
|
*
|
|
* No-op if the assignment didn't exist (delete is idempotent at the
|
|
* DB layer). We don't surface "not found" because that would let a
|
|
* caller probe for assignment existence — the boolean response is
|
|
* just "you're authorized to do this".
|
|
*
|
|
* Note on self-revocation: an owner can revoke their own row even
|
|
* though it has no practical effect (owners see all tenants). A
|
|
* `user`-role member cannot revoke their own assignment because
|
|
* they're already gated out by canMutate.
|
|
*/
|
|
export async function DELETE(
|
|
_req: NextRequest,
|
|
{ params }: { params: Promise<{ name: string; userId: string }> }
|
|
) {
|
|
const user = await getSessionUser();
|
|
if (!user) {
|
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
}
|
|
if (!canMutate(user)) {
|
|
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
|
|
}
|
|
|
|
const { name, userId } = await params;
|
|
|
|
const tenant = await getTenant(name);
|
|
if (!tenant) {
|
|
return NextResponse.json({ error: "Not found" }, { status: 404 });
|
|
}
|
|
// Same cross-org boundary as assign: customer owners can only manage
|
|
// their own org's tenants; platform users can manage anywhere.
|
|
const tenantOrgId = tenant.metadata.labels?.["pieced.ch/zitadel-org-id"];
|
|
if (!user.isPlatform && tenantOrgId !== user.orgId) {
|
|
return NextResponse.json({ error: "Not found" }, { status: 404 });
|
|
}
|
|
|
|
try {
|
|
await removeTenantAssignment(name, userId);
|
|
return NextResponse.json({ message: "Assignment revoked." });
|
|
} catch (e: any) {
|
|
console.error("Failed to remove tenant assignment:", e);
|
|
return NextResponse.json(
|
|
{ error: safeError(e, "Failed to revoke assignment") },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
}
|