feat: restrict admin access to club operations and rollout test environment
CI Pipeline / Backend Build & Test (pull_request) Successful in 53s
CI Pipeline / Frontend Lint, Test & Build (pull_request) Failing after 16s
CI Pipeline / Infrastructure Validation (pull_request) Successful in 3s

This commit is contained in:
WorkClub Automation
2026-03-18 09:08:45 +01:00
parent 9cb80e4517
commit 821459966c
22 changed files with 507 additions and 203 deletions
+16 -5
View File
@@ -9,6 +9,7 @@ declare module "next-auth" {
email?: string | null
image?: string | null
clubs?: Record<string, string>
isAdmin?: boolean
}
accessToken?: string
}
@@ -16,6 +17,7 @@ declare module "next-auth" {
interface JWT {
clubs?: Record<string, string>
accessToken?: string
isAdmin?: boolean
}
}
@@ -43,19 +45,28 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
],
callbacks: {
async jwt({ token, account }) {
if (account) {
if (account && account.access_token) {
// Add clubs claim from Keycloak access token
token.clubs = (account as Record<string, unknown>).clubs as Record<string, string> || {}
token.accessToken = account.access_token
token.clubs = (account as any).clubs as Record<string, string> || {}
token.accessToken = account.access_token as string
try {
const payload = JSON.parse(Buffer.from((token.accessToken as string).split('.')[1], 'base64').toString());
const roles = payload.realm_access?.roles || [];
token.isAdmin = roles.includes('admin');
} catch (e) {
token.isAdmin = false;
}
}
return token
},
async session({ session, token }) {
// Expose clubs to client
if (session.user) {
session.user.clubs = token.clubs as Record<string, string> | undefined
session.user.clubs = (token as any).clubs as Record<string, string> | undefined
session.user.isAdmin = (token as any).isAdmin as boolean | undefined
}
session.accessToken = token.accessToken as string | undefined
session.accessToken = (token as any).accessToken as string | undefined
return session
}
}