diff --git a/app/api/users/[userId]/route.ts b/app/api/users/[userId]/route.ts index 24392473..e0190cde 100644 --- a/app/api/users/[userId]/route.ts +++ b/app/api/users/[userId]/route.ts @@ -1,45 +1,11 @@ -import { getServerSession } from "next-auth"; +import { getServerSession } from "next-auth/next"; import { authOptions } from "@/app/api/auth/[...nextauth]/route"; import { NextResponse } from "next/server"; // Helper function to delete user from Leantime -async function deleteLeantimeUser(email: string): Promise<{ success: boolean; error?: string }> { +async function deleteLeantimeUser(userId: string): Promise<{ success: boolean; error?: string }> { try { - // First, get all users from Leantime - const getUsersResponse = await fetch('https://agilite.slm-lab.net/api/jsonrpc', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'X-API-Key': process.env.LEANTIME_TOKEN || '', - }, - body: JSON.stringify({ - method: 'leantime.rpc.Users.Users.getAll', - jsonrpc: '2.0', - id: 1, - params: {} - }) - }); - - const getUsersData = await getUsersResponse.json(); - console.log('Leantime get users response:', getUsersData); - - if (!getUsersResponse.ok || !getUsersData.result) { - console.error('Failed to get Leantime users:', getUsersData); - return { - success: false, - error: getUsersData.error?.message || 'Failed to get users in Leantime' - }; - } - - // Find the user with matching email - const user = getUsersData.result.find((u: any) => u.username === email); - if (!user) { - console.log('User not found in Leantime, might have been already deleted'); - return { success: true }; // Consider it a success if user doesn't exist - } - - // Now delete the user using their Leantime ID - const deleteResponse = await fetch('https://agilite.slm-lab.net/api/jsonrpc', { + const response = await fetch('https://agilite.slm-lab.net/api/jsonrpc', { method: 'POST', headers: { 'Content-Type': 'application/json', @@ -50,19 +16,19 @@ async function deleteLeantimeUser(email: string): Promise<{ success: boolean; er jsonrpc: '2.0', id: 1, params: { - id: user.id + id: userId } }) }); - const deleteData = await deleteResponse.json(); - console.log('Leantime delete response:', deleteData); + const data = await response.json(); + console.log('Leantime delete response:', data); - if (!deleteResponse.ok || !deleteData.result) { - console.error('Leantime user deletion failed:', deleteData); + if (!response.ok || !data.result) { + console.error('Leantime user deletion failed:', data); return { success: false, - error: deleteData.error?.message || 'Failed to delete user in Leantime' + error: data.error?.message || 'Failed to delete user in Leantime' }; } @@ -76,7 +42,6 @@ async function deleteLeantimeUser(email: string): Promise<{ success: boolean; er } } -//TODO: Ajouter la suppression automatique du compte Nextcloud export async function DELETE( req: Request, { params }: { params: { userId: string } } @@ -88,7 +53,7 @@ export async function DELETE( } try { - // First get an admin token using client credentials + // Get admin token const tokenResponse = await fetch( `${process.env.KEYCLOAK_BASE_URL}/realms/${process.env.KEYCLOAK_REALM}/protocol/openid-connect/token`, { @@ -105,16 +70,12 @@ export async function DELETE( ); const tokenData = await tokenResponse.json(); - - if (!tokenResponse.ok) { + if (!tokenResponse.ok || !tokenData.access_token) { console.error("Failed to get admin token:", tokenData); - return NextResponse.json( - { error: "Erreur d'authentification" }, - { status: 401 } - ); + return NextResponse.json({ error: "Erreur d'authentification" }, { status: 401 }); } - // Get user details before deletion to get their email + // Get user details before deletion const userResponse = await fetch( `${process.env.KEYCLOAK_BASE_URL}/admin/realms/${process.env.KEYCLOAK_REALM}/users/${params.userId}`, { @@ -145,22 +106,17 @@ export async function DELETE( } ); - console.log("Keycloak delete response:", { - status: deleteResponse.status, - ok: deleteResponse.ok - }); - if (!deleteResponse.ok) { - const errorText = await deleteResponse.text(); - console.error("Delete error:", errorText); + const errorData = await deleteResponse.json(); + console.error("Keycloak delete error:", errorData); return NextResponse.json( - { error: "Erreur lors de la suppression", details: errorText }, + { error: "Erreur lors de la suppression de l'utilisateur", details: errorData }, { status: deleteResponse.status } ); } // Delete user from Leantime - const leantimeResult = await deleteLeantimeUser(userDetails.email); + const leantimeResult = await deleteLeantimeUser(params.userId); if (!leantimeResult.success) { console.error("Leantime user deletion failed:", leantimeResult.error); @@ -169,6 +125,7 @@ export async function DELETE( } return NextResponse.json({ success: true }); + } catch (error) { console.error("Error deleting user:", error); return NextResponse.json( diff --git a/app/api/users/route.ts b/app/api/users/route.ts index bceec674..d3fd2f58 100644 --- a/app/api/users/route.ts +++ b/app/api/users/route.ts @@ -213,7 +213,6 @@ async function createLeantimeUser(userData: { method: 'POST', headers: { 'Content-Type': 'application/json', - 'Authorization': `Bearer ${process.env.LEANTIME_TOKEN}`, 'X-API-Key': process.env.LEANTIME_TOKEN || '', }, body: JSON.stringify({ @@ -222,14 +221,38 @@ async function createLeantimeUser(userData: { id: 1, params: { values: { - firstname: userData.firstName, // First name goes in firstname field - lastname: userData.lastName, // Last name goes in lastname field - username: userData.email, // Use email as username - email: userData.email, - password: userData.password, + '0': 0, // This will be set by Leantime + '1': userData.lastName, + '2': userData.firstName, + '3': '20', // Default role + '4': '', // profileId + '5': 'a', // status + '6': userData.email, + '7': 0, // twoFAEnabled + '8': 0, // clientId + '9': null, // clientName + '10': '', // jobTitle + '11': '', // jobLevel + '12': '', // department + '13': new Date().toISOString(), // modified + lastname: userData.lastName, + firstname: userData.firstName, + role: '20', // Default role + profileId: '', status: 'a', - role: '10', // Use '10' as role - source: 'keycloak' + username: userData.email, + password: userData.password, + twoFAEnabled: 0, + clientId: 0, + clientName: null, + jobTitle: '', + jobLevel: '', + department: '', + modified: new Date().toISOString(), + createdOn: new Date().toISOString(), + source: 'keycloak', + notifications: 1, + settings: '{}' } } }) @@ -443,3 +466,107 @@ export async function POST(req: Request) { ); } } + +// Helper function to delete user from Leantime +async function deleteLeantimeUser(email: string): Promise<{ success: boolean; error?: string }> { + try { + const response = await fetch('https://agilite.slm-lab.net/api/jsonrpc', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-API-Key': process.env.LEANTIME_TOKEN || '', + }, + body: JSON.stringify({ + method: 'leantime.rpc.Users.Users.deleteUser', + jsonrpc: '2.0', + id: 1, + params: { + email: email + } + }) + }); + + const data = await response.json(); + console.log('Leantime delete response:', data); + + if (!response.ok || !data.result) { + console.error('Leantime user deletion failed:', data); + return { + success: false, + error: data.error?.message || 'Failed to delete user in Leantime' + }; + } + + return { success: true }; + } catch (error) { + console.error('Error deleting Leantime user:', error); + return { + success: false, + error: 'Error deleting user in Leantime' + }; + } +} + +export async function DELETE(req: Request) { + const session = await getServerSession(authOptions); + + if (!session) { + return NextResponse.json({ error: "Non autorisé" }, { status: 401 }); + } + + try { + const { searchParams } = new URL(req.url); + const userId = searchParams.get('id'); + const email = searchParams.get('email'); + + if (!userId || !email) { + return NextResponse.json( + { error: "ID utilisateur et email requis" }, + { status: 400 } + ); + } + + const token = await getAdminToken(); + if (!token) { + return NextResponse.json({ error: "Erreur d'authentification" }, { status: 401 }); + } + + // Delete user from Keycloak + const deleteResponse = await fetch( + `${process.env.KEYCLOAK_BASE_URL}/admin/realms/${process.env.KEYCLOAK_REALM}/users/${userId}`, + { + method: "DELETE", + headers: { + Authorization: `Bearer ${token}`, + }, + } + ); + + if (!deleteResponse.ok) { + const errorData = await deleteResponse.json(); + console.error("Keycloak delete error:", errorData); + return NextResponse.json( + { error: "Erreur lors de la suppression de l'utilisateur", details: errorData }, + { status: deleteResponse.status } + ); + } + + // Delete user from Leantime + const leantimeResult = await deleteLeantimeUser(email); + + if (!leantimeResult.success) { + console.error("Leantime user deletion failed:", leantimeResult.error); + // We don't return an error here since Keycloak user was deleted successfully + // We just log the error and continue + } + + return NextResponse.json({ success: true }); + + } catch (error) { + console.error("Error deleting user:", error); + return NextResponse.json( + { error: "Erreur serveur", details: error }, + { status: 500 } + ); + } +}