Role split and owner gating
All checks were successful
Build and Push / build (push) Successful in 1m24s

This commit is contained in:
2026-04-26 22:45:38 +02:00
parent 3521a0ff4f
commit 7c4e20099d
18 changed files with 347 additions and 91 deletions

View File

@@ -1,14 +1,25 @@
import NextAuth from "next-auth";
import type { NextAuthConfig } from "next-auth";
import type { PlatformRole, SessionUser, ZitadelClaims } from "@/types";
import type { PlatformRole, Role, SessionUser, ZitadelClaims } from "@/types";
const PLATFORM_ROLES: PlatformRole[] = ["platform_admin", "platform_operator"];
/**
* Pull the role keys from the ZITADEL `urn:zitadel:iam:org:project:roles`
* claim. The claim is shaped as { roleKey: { orgId: orgName } } — we only
* need the keys.
*
* Slice 5: returns Role[] (the union) rather than PlatformRole[]. The
* keys can be either platform or customer roles depending on what the
* project authorization granted; the SessionUser carries them all and
* downstream helpers (canMutate, isCustomerOwner, requirePlatformRole)
* decide what each subset means.
*/
function extractRoles(
rolesObj?: Record<string, Record<string, string>>
): PlatformRole[] {
): Role[] {
if (!rolesObj) return [];
return Object.keys(rolesObj) as PlatformRole[];
return Object.keys(rolesObj) as Role[];
}
export const authConfig: NextAuthConfig = {
@@ -50,7 +61,7 @@ export const authConfig: NextAuthConfig = {
return token;
},
async session({ session, token }) {
const roles = (token.roles as PlatformRole[]) ?? [];
const roles = (token.roles as Role[]) ?? [];
const sessionUser: SessionUser = {
id: token.sub!,
name: session.user?.name ?? "",
@@ -58,7 +69,9 @@ export const authConfig: NextAuthConfig = {
orgId: token.orgId as string,
orgName: token.orgName as string,
roles,
isPlatform: roles.some((r) => PLATFORM_ROLES.includes(r)),
isPlatform: roles.some((r) =>
PLATFORM_ROLES.includes(r as PlatformRole)
),
};
(session as any).platformUser = sessionUser;
return session;