From 2663d6f23a010d8684cd6d5d1f7f7b686d01f827 Mon Sep 17 00:00:00 2001 From: alma Date: Sat, 3 May 2025 15:40:58 +0200 Subject: [PATCH] equipes keycloak flow --- app/api/users/[userId]/roles/route.ts | 25 +++++++---- components/sidebar.tsx | 2 +- lib/keycloak.ts | 60 +++++++++++++++++++-------- 3 files changed, 60 insertions(+), 27 deletions(-) diff --git a/app/api/users/[userId]/roles/route.ts b/app/api/users/[userId]/roles/route.ts index 5f98de49..ba484638 100644 --- a/app/api/users/[userId]/roles/route.ts +++ b/app/api/users/[userId]/roles/route.ts @@ -2,7 +2,6 @@ import { NextResponse } from "next/server"; import { getServerSession } from "next-auth"; import { authOptions } from "@/app/api/auth/[...nextauth]/route"; import { getKeycloakAdminClient } from "@/lib/keycloak"; -import { RoleRepresentation } from "@keycloak/keycloak-admin-client/lib/defs/roleRepresentation"; export async function GET( request: Request, @@ -14,7 +13,12 @@ export async function GET( return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } - const { userId } = params; + // Safely access the userId parameter + const userId = String(params?.userId || ''); + if (!userId) { + return NextResponse.json({ error: "User ID is required" }, { status: 400 }); + } + const kcAdminClient = await getKeycloakAdminClient(); // Get all available roles @@ -48,7 +52,12 @@ export async function PUT( return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); } - const { userId } = params; + // Safely access the userId parameter + const userId = String(params?.userId || ''); + if (!userId) { + return NextResponse.json({ error: "User ID is required" }, { status: 400 }); + } + const { roles } = await request.json(); const kcAdminClient = await getKeycloakAdminClient(); @@ -62,19 +71,19 @@ export async function PUT( // Find roles to add and remove const rolesToAdd = roles.filter( - (role: string) => !currentRoles.realmMappings?.some((r: RoleRepresentation) => r.name === role) + (role: string) => !currentRoles.realmMappings?.some((r: any) => r.name === role) ); const rolesToRemove = currentRoles.realmMappings?.filter( - (role: RoleRepresentation) => !roles.includes(role.name) + (role: any) => !roles.includes(role.name) ); // Add new roles for (const roleName of rolesToAdd) { - const role = availableRoles.find((r: RoleRepresentation) => r.name === roleName); + const role = availableRoles.find((r: any) => r.name === roleName); if (role) { await kcAdminClient.users.addRealmRoleMappings({ id: userId, - roles: [role], + roles: [role as any], }); } } @@ -83,7 +92,7 @@ export async function PUT( if (rolesToRemove && rolesToRemove.length > 0) { await kcAdminClient.users.delRealmRoleMappings({ id: userId, - roles: rolesToRemove, + roles: rolesToRemove as any, }); } diff --git a/components/sidebar.tsx b/components/sidebar.tsx index 0e616c5a..2e20b026 100644 --- a/components/sidebar.tsx +++ b/components/sidebar.tsx @@ -212,7 +212,7 @@ export function Sidebar({ isOpen, onClose }: SidebarProps) { icon: Building2, href: "/mediation", iframe: process.env.NEXT_PUBLIC_IFRAME_MEDIATIONS_URL, - requiredRole: "mediation", + requiredRole: ["mediation", "expression"], }, ]; diff --git a/lib/keycloak.ts b/lib/keycloak.ts index 2095c89d..fb9fa4e7 100644 --- a/lib/keycloak.ts +++ b/lib/keycloak.ts @@ -21,27 +21,51 @@ export async function getKeycloakAdminClient(): Promise { } } - const kcAdminClient = new KcAdminClient({ - baseUrl: process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER || 'http://localhost:8080', - realmName: 'master', // Use master realm to manage other realms - }); + const keycloakUrl = process.env.KEYCLOAK_BASE_URL || process.env.NEXT_PUBLIC_KEYCLOAK_ISSUER || 'http://localhost:8080'; + const adminClientId = process.env.KEYCLOAK_ADMIN_CLIENT_ID || 'admin-cli'; + const adminUsername = process.env.KEYCLOAK_ADMIN_USERNAME || 'admin'; + const adminPassword = process.env.KEYCLOAK_ADMIN_PASSWORD || 'admin'; + const realmName = process.env.KEYCLOAK_REALM || 'cercle'; - // Authenticate admin client - await kcAdminClient.auth({ - clientId: process.env.KEYCLOAK_ADMIN_CLIENT_ID || 'admin-cli', - username: process.env.KEYCLOAK_ADMIN_USERNAME || 'admin', - password: process.env.KEYCLOAK_ADMIN_PASSWORD || 'admin', - grantType: 'password', - } as Credentials); + console.log(`Connecting to Keycloak at ${keycloakUrl}, realm: ${realmName}`); + + try { + const kcAdminClient = new KcAdminClient({ + baseUrl: keycloakUrl, + realmName: 'master', // Use master realm to manage other realms + }); - // Set the target realm to work with - kcAdminClient.setConfig({ - realmName: process.env.KEYCLOAK_REALM || 'cercle', - }); + // Authenticate admin client + await kcAdminClient.auth({ + clientId: adminClientId, + username: adminUsername, + password: adminPassword, + grantType: 'password', + } as Credentials); - // Cache the admin client - adminClient = kcAdminClient; - return kcAdminClient; + console.log('Successfully authenticated with Keycloak admin client'); + + // Set the target realm to work with + kcAdminClient.setConfig({ + realmName: realmName, + }); + + // Cache the admin client + adminClient = kcAdminClient; + return kcAdminClient; + } catch (error) { + console.error('Error connecting to Keycloak:', error); + // Add more detailed error information + if (error instanceof Error) { + console.error(`Error message: ${error.message}`); + console.error(`Error cause: ${error.cause}`); + } + + // For debugging - show what values we're trying to use (without exposing the password) + console.error(`Debug info - URL: ${keycloakUrl}, Client ID: ${adminClientId}, Username: ${adminUsername}, Realm: ${realmName}`); + + throw new Error(`Failed to connect to Keycloak: ${error instanceof Error ? error.message : String(error)}`); + } } /**