/** * Test script for verifying user deletion across all integrated systems * * This script creates a test user with mediation role, verifies it exists in all systems, * then deletes it and verifies deletion in all systems. * * Usage: node scripts/test-user-deletion.js */ require('dotenv').config(); const fetch = require('node-fetch'); // Test user configuration const TEST_USER = { username: `test-user-${Date.now()}`, firstName: 'Test', lastName: 'User', email: `test-user-${Date.now()}@example.com`, password: 'password123', roles: ['mediation'] // Using mediation role which should be created in Dolibarr }; // Configuration from environment variables const config = { keycloak: { baseUrl: process.env.KEYCLOAK_BASE_URL, realm: process.env.KEYCLOAK_REALM, clientId: process.env.KEYCLOAK_CLIENT_ID, clientSecret: process.env.KEYCLOAK_CLIENT_SECRET }, leantime: { apiUrl: 'https://agilite.slm-lab.net/api/jsonrpc', apiKey: process.env.LEANTIME_TOKEN }, dolibarr: { apiUrl: process.env.DOLIBARR_API_URL, apiKey: process.env.DOLIBARR_API_KEY }, nextAuthUrl: process.env.NEXTAUTH_URL || 'http://localhost:3000' }; // Helper to get admin token for Keycloak operations async function getKeycloakAdminToken() { const response = await fetch( `${config.keycloak.baseUrl}/realms/${config.keycloak.realm}/protocol/openid-connect/token`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: new URLSearchParams({ grant_type: 'client_credentials', client_id: config.keycloak.clientId, client_secret: config.keycloak.clientSecret, }), } ); const data = await response.json(); if (!response.ok || !data.access_token) { throw new Error('Failed to get Keycloak admin token'); } return data.access_token; } // Create a test user in all systems via the API async function createTestUser() { console.log(`Creating test user: ${TEST_USER.username} (${TEST_USER.email})`); const response = await fetch(`${config.nextAuthUrl}/api/users`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(TEST_USER), }); if (!response.ok) { const error = await response.json(); throw new Error(`Failed to create test user: ${JSON.stringify(error)}`); } const data = await response.json(); console.log('User created successfully:', data); return data.user; } // Check if user exists in Keycloak async function checkKeycloakUser(userId) { console.log(`Checking if user exists in Keycloak (ID: ${userId})`); const token = await getKeycloakAdminToken(); const response = await fetch( `${config.keycloak.baseUrl}/admin/realms/${config.keycloak.realm}/users/${userId}`, { headers: { Authorization: `Bearer ${token}`, }, } ); if (response.status === 404) { console.log('User not found in Keycloak'); return false; } if (!response.ok) { console.error('Error checking Keycloak user:', await response.text()); return null; // Error state } console.log('User exists in Keycloak'); return true; } // Check if user exists in Leantime async function checkLeantimeUser(email) { console.log(`Checking if user exists in Leantime (Email: ${email})`); try { const response = await fetch(config.leantime.apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': config.leantime.apiKey, }, body: JSON.stringify({ method: 'leantime.rpc.Users.Users.getUserIdByEmail', jsonrpc: '2.0', id: 1, params: { email: email } }) }); const data = await response.json(); if (!response.ok || !data.result) { console.log('User not found in Leantime'); return false; } console.log('User exists in Leantime'); return true; } catch (error) { console.error('Error checking Leantime user:', error); return null; // Error state } } // Check if user exists in Dolibarr async function checkDolibarrUser(email) { console.log(`Checking if user exists in Dolibarr (Email: ${email})`); try { const apiUrl = config.dolibarr.apiUrl.endsWith('/') ? config.dolibarr.apiUrl : `${config.dolibarr.apiUrl}/`; const response = await fetch( `${apiUrl}users?sortfield=t.rowid&sortorder=ASC&limit=1&sqlfilters=(t.email:=:'${encodeURIComponent(email)}')`, { method: 'GET', headers: { 'DOLAPIKEY': config.dolibarr.apiKey, }, } ); if (!response.ok) { console.error('Error response from Dolibarr:', await response.text()); return null; // Error state } const data = await response.json(); if (!Array.isArray(data) || data.length === 0) { console.log('User not found in Dolibarr'); return false; } console.log('User exists in Dolibarr with ID:', data[0].id); return { exists: true, id: data[0].id }; } catch (error) { console.error('Error checking Dolibarr user:', error); return null; // Error state } } // Delete user from all systems via the API async function deleteTestUser(userId, email) { console.log(`Deleting test user: ID=${userId}, Email=${email}`); const response = await fetch( `${config.nextAuthUrl}/api/users?id=${userId}&email=${encodeURIComponent(email)}`, { method: 'DELETE', } ); if (!response.ok) { const error = await response.json(); throw new Error(`Failed to delete test user: ${JSON.stringify(error)}`); } console.log('User deletion request successful'); return await response.json(); } // Main test function async function runTest() { try { console.log('=== STARTING USER DELETION TEST ==='); // Step 1: Create a test user console.log('\n=== Step 1: Creating test user ==='); const createdUser = await createTestUser(); console.log(`Test user created with ID: ${createdUser.id}`); // Wait a moment for systems to process console.log('Waiting for systems to process...'); await new Promise(resolve => setTimeout(resolve, 2000)); // Step 2: Verify user exists in all systems console.log('\n=== Step 2: Verifying user exists in all systems ==='); const keycloakExists = await checkKeycloakUser(createdUser.id); const leantimeExists = await checkLeantimeUser(TEST_USER.email); const dolibarrUser = await checkDolibarrUser(TEST_USER.email); if (keycloakExists === null || leantimeExists === null || dolibarrUser === null) { throw new Error('Error checking user existence in integrated systems'); } if (!keycloakExists || !leantimeExists || !dolibarrUser.exists) { throw new Error('User not created in all systems properly'); } console.log('User confirmed to exist in all integrated systems'); // Step 3: Delete the test user console.log('\n=== Step 3: Deleting test user ==='); await deleteTestUser(createdUser.id, TEST_USER.email); // Wait a moment for systems to process console.log('Waiting for systems to process deletion...'); await new Promise(resolve => setTimeout(resolve, 2000)); // Step 4: Verify user has been deleted from all systems console.log('\n=== Step 4: Verifying user deletion from all systems ==='); const keycloakDeleted = !(await checkKeycloakUser(createdUser.id)); const leantimeDeleted = !(await checkLeantimeUser(TEST_USER.email)); const dolibarrDeleted = !(await checkDolibarrUser(TEST_USER.email)).exists; console.log('\n=== TEST RESULTS ==='); console.log(`Keycloak user deleted: ${keycloakDeleted ? 'YES' : 'NO'}`); console.log(`Leantime user deleted: ${leantimeDeleted ? 'YES' : 'NO'}`); console.log(`Dolibarr user deleted: ${dolibarrDeleted ? 'YES' : 'NO'}`); if (keycloakDeleted && leantimeDeleted && dolibarrDeleted) { console.log('\n✅ TEST PASSED: User successfully deleted from all systems'); } else { console.log('\n❌ TEST FAILED: User not deleted from all systems'); } } catch (error) { console.error('\n❌ TEST ERROR:', error); } console.log('\n=== TEST COMPLETED ==='); } // Run the test runTest();