diff --git a/.env b/.env index 981d2bf5..462eba20 100644 --- a/.env +++ b/.env @@ -9,6 +9,9 @@ KEYCLOAK_BASE_URL=https://connect.slm-lab.net KEYCLOAK_ADMIN_USERNAME=alma KEYCLOAK_ADMIN_PASSWORD=PW5jfqX00m +DOLIBARR_API_URL=https://mediations.slm-lab.net/api/index.php/ +DOLIBARR_API_KEY=2znq976PzZz1q2JSe9DG2A3hmbNMGIh8 + NEXTCLOUD_URL=https://espace.slm-lab.net NEXTCLOUD_CLIENT_ID=espace.slm-lab.net NEXTCLOUD_CLIENT_SECRET=YHLVMGpu0nGRaP7gMDpSjRr1ia6HiSr1 diff --git a/app/api/auth/debug-keycloak/route.ts b/app/api/auth/debug-keycloak/route.ts index 31030b56..88c320f0 100644 --- a/app/api/auth/debug-keycloak/route.ts +++ b/app/api/auth/debug-keycloak/route.ts @@ -36,10 +36,17 @@ export async function GET() { }, { status: 400 }); } + if (!realm) { + return NextResponse.json({ + error: 'Missing Realm', + message: 'KEYCLOAK_REALM is required' + }, { status: 400 }); + } + console.log('Environment variables check:', envVars); - // Try direct authentication - const url = `${keycloakUrl}/realms/master/protocol/openid-connect/token`; + // Try direct authentication using the application realm, not master + const url = `${keycloakUrl}/realms/${realm}/protocol/openid-connect/token`; const formData = new URLSearchParams(); // Try client credentials if available @@ -47,6 +54,7 @@ export async function GET() { formData.append('client_id', clientId); formData.append('client_secret', clientSecret); formData.append('grant_type', 'client_credentials'); + console.log('Using client credentials flow'); } // Fall back to password grant else if (adminUsername && adminPassword) { @@ -54,6 +62,7 @@ export async function GET() { formData.append('username', adminUsername); formData.append('password', adminPassword); formData.append('grant_type', 'password'); + console.log('Using password grant flow'); } else { return NextResponse.json({ error: 'Missing authentication credentials', diff --git a/app/api/users/route.ts b/app/api/users/route.ts index d3fd2f58..1583ed32 100644 --- a/app/api/users/route.ts +++ b/app/api/users/route.ts @@ -1,6 +1,7 @@ import { getServerSession } from "next-auth/next"; import { authOptions } from "@/app/api/auth/[...nextauth]/route"; import { NextResponse } from "next/server"; +import { createDolibarrUser, checkDolibarrUserExists } from "@/lib/dolibarr-api"; export async function GET() { const session = await getServerSession(authOptions); @@ -450,11 +451,48 @@ export async function POST(req: Request) { // We just log the error and continue } + // Check if the user has mediation or expression role and create in Dolibarr if needed + const hasMediationRole = validRoles.includes('mediation'); + const hasExpressionRole = validRoles.includes('expression'); + + let dolibarrUserId = null; + + if (hasMediationRole || hasExpressionRole) { + console.log(`User has special role (mediation: ${hasMediationRole}, expression: ${hasExpressionRole}), creating in Dolibarr`); + + // First check if the user already exists in Dolibarr + const existingUser = await checkDolibarrUserExists(data.email); + + if (existingUser.exists) { + console.log(`User already exists in Dolibarr with ID: ${existingUser.id}`); + dolibarrUserId = existingUser.id; + } else { + // Create user in Dolibarr + const dolibarrResult = await createDolibarrUser({ + username: data.username, + firstName: data.firstName, + lastName: data.lastName, + email: data.email, + password: data.password, + }); + + if (dolibarrResult.success) { + console.log(`User created in Dolibarr with ID: ${dolibarrResult.id}`); + dolibarrUserId = dolibarrResult.id; + } else { + console.error("Dolibarr user creation failed:", dolibarrResult.error); + // We don't return an error here since Keycloak user was created successfully + // We just log the error and continue + } + } + } + return NextResponse.json({ success: true, user: { ...user, roles: validRoles, + dolibarrId: dolibarrUserId, // Include the Dolibarr ID if created }, }); diff --git a/app/types/dolibarr.ts b/app/types/dolibarr.ts new file mode 100644 index 00000000..a6fa086e --- /dev/null +++ b/app/types/dolibarr.ts @@ -0,0 +1,38 @@ +/** + * Dolibarr API response types + */ + +export interface DolibarrErrorResponse { + error: { + code: string; + message: string; + }; +} + +export interface DolibarrThirdParty { + id: number; + name: string; + name_alias?: string; + email?: string; + phone?: string; + address?: string; + zip?: string; + town?: string; + status: number; + client: number; + code_client: string; + date_creation: string; + date_modification?: string; +} + +export interface DolibarrUser { + id: number; + login: string; + lastname?: string; + firstname?: string; + email?: string; + status: number; + admin: number; + entity: number; + employee: number; +} \ No newline at end of file diff --git a/components/sidebar.tsx b/components/sidebar.tsx index 81265f88..cdfbfe5c 100644 --- a/components/sidebar.tsx +++ b/components/sidebar.tsx @@ -45,7 +45,7 @@ interface MenuItem { } export function Sidebar({ isOpen, onClose }: SidebarProps) { - const { data: session, status } = useSession(); + const { data: session, status, update } = useSession(); const router = useRouter(); const pathname = usePathname(); @@ -59,6 +59,13 @@ export function Sidebar({ isOpen, onClose }: SidebarProps) { pathname }); + // Function to manually refresh the session from the server + const refreshSession = async () => { + console.log('Manually refreshing session...'); + await update(); // Force update the session + console.log('Session refreshed!'); + }; + // Show loading state while session is being checked if (status === 'loading') { return null; @@ -212,7 +219,7 @@ export function Sidebar({ isOpen, onClose }: SidebarProps) { icon: Building2, href: "/mediation", iframe: process.env.NEXT_PUBLIC_IFRAME_MEDIATIONS_URL, - requiredRole: ["mediation", "expression"], + requiredRole: "mediation", }, ]; @@ -270,6 +277,14 @@ export function Sidebar({ isOpen, onClose }: SidebarProps) { height={16.5} className="text-black" /> + {/* Add session refresh button */} + {/* Menu Items */} @@ -296,6 +311,12 @@ export function Sidebar({ isOpen, onClose }: SidebarProps) {
User: {session?.user?.name}
Email: {session?.user?.email}
+
diff --git a/components/users/users-table.tsx b/components/users/users-table.tsx
index 7de49f53..6fcf1781 100644
--- a/components/users/users-table.tsx
+++ b/components/users/users-table.tsx
@@ -48,6 +48,7 @@ interface User {
createdTimestamp: number;
roles: string[];
enabled: boolean;
+ dolibarrId?: number;
}
interface Role {
@@ -513,6 +514,7 @@ export function UsersTable({ userRole = [] }: UsersTableProps) {
Email
Created At
Roles
+ Dolibarr
Actions
@@ -535,6 +537,15 @@ export function UsersTable({ userRole = [] }: UsersTableProps) {
))}