150 lines
4.4 KiB
TypeScript
150 lines
4.4 KiB
TypeScript
/**
|
||
* Script de nettoyage des calendriers de groupes orphelins
|
||
*
|
||
* Ce script supprime les calendriers de groupes dont le groupe n'existe plus dans Keycloak.
|
||
*
|
||
* Usage:
|
||
* npx tsx scripts/clean-orphan-calendars.ts
|
||
*/
|
||
|
||
import { prisma } from '../lib/prisma';
|
||
|
||
async function getAdminToken() {
|
||
try {
|
||
const tokenResponse = await fetch(
|
||
`${process.env.KEYCLOAK_BASE_URL}/realms/${process.env.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: process.env.KEYCLOAK_CLIENT_ID!,
|
||
client_secret: process.env.KEYCLOAK_CLIENT_SECRET!,
|
||
}),
|
||
}
|
||
);
|
||
|
||
const data = await tokenResponse.json();
|
||
if (!tokenResponse.ok || !data.access_token) {
|
||
console.error('❌ Erreur token:', data);
|
||
return null;
|
||
}
|
||
|
||
return data.access_token;
|
||
} catch (error) {
|
||
console.error('❌ Erreur token:', error);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
async function getAllKeycloakGroups(token: string): Promise<Set<string>> {
|
||
try {
|
||
const response = await fetch(
|
||
`${process.env.KEYCLOAK_BASE_URL}/admin/realms/${process.env.KEYCLOAK_REALM}/groups`,
|
||
{
|
||
headers: {
|
||
Authorization: `Bearer ${token}`,
|
||
},
|
||
}
|
||
);
|
||
|
||
if (!response.ok) {
|
||
throw new Error('Failed to fetch groups from Keycloak');
|
||
}
|
||
|
||
const groups = await response.json();
|
||
const groupNames = new Set<string>();
|
||
|
||
groups.forEach((group: any) => {
|
||
groupNames.add(group.name);
|
||
});
|
||
|
||
return groupNames;
|
||
} catch (error) {
|
||
console.error('❌ Erreur lors de la récupération des groupes:', error);
|
||
return new Set();
|
||
}
|
||
}
|
||
|
||
async function cleanOrphanCalendars() {
|
||
console.log('🧹 Début du nettoyage des calendriers orphelins...\n');
|
||
|
||
// 1. Récupérer le token Keycloak
|
||
const token = await getAdminToken();
|
||
if (!token) {
|
||
console.error('❌ Impossible d\'obtenir le token Keycloak');
|
||
process.exit(1);
|
||
}
|
||
|
||
// 2. Récupérer tous les groupes existants dans Keycloak
|
||
console.log('📋 Récupération des groupes depuis Keycloak...');
|
||
const keycloakGroups = await getAllKeycloakGroups(token);
|
||
console.log(`✅ ${keycloakGroups.size} groupes trouvés dans Keycloak\n`);
|
||
|
||
// 3. Récupérer tous les calendriers de groupes
|
||
console.log('📋 Récupération des calendriers de groupes depuis la base...');
|
||
const groupCalendars = await prisma.calendar.findMany({
|
||
where: {
|
||
name: {
|
||
startsWith: 'Groupe: ',
|
||
},
|
||
},
|
||
});
|
||
console.log(`✅ ${groupCalendars.length} calendriers de groupes trouvés\n`);
|
||
|
||
// 4. Identifier les calendriers orphelins
|
||
const orphanCalendars = groupCalendars.filter((calendar) => {
|
||
const groupName = calendar.name.replace('Groupe: ', '');
|
||
return !keycloakGroups.has(groupName);
|
||
});
|
||
|
||
if (orphanCalendars.length === 0) {
|
||
console.log('✅ Aucun calendrier orphelin trouvé. Base de données propre!\n');
|
||
return;
|
||
}
|
||
|
||
console.log(`⚠️ ${orphanCalendars.length} calendrier(s) orphelin(s) trouvé(s):\n`);
|
||
orphanCalendars.forEach((cal) => {
|
||
console.log(` - ${cal.name} (ID: ${cal.id})`);
|
||
});
|
||
|
||
// 5. Demander confirmation (commentez cette section si vous voulez une suppression automatique)
|
||
console.log('\n⚠️ ATTENTION: Les calendriers ci-dessus vont être supprimés avec tous leurs événements!');
|
||
console.log('Pour confirmer, lancez le script avec: npx tsx scripts/clean-orphan-calendars.ts --confirm\n');
|
||
|
||
const isConfirmed = process.argv.includes('--confirm');
|
||
|
||
if (!isConfirmed) {
|
||
console.log('❌ Suppression annulée. Utilisez --confirm pour supprimer.');
|
||
return;
|
||
}
|
||
|
||
// 6. Supprimer les calendriers orphelins
|
||
console.log('\n🗑️ Suppression des calendriers orphelins...\n');
|
||
|
||
for (const calendar of orphanCalendars) {
|
||
try {
|
||
await prisma.calendar.delete({
|
||
where: { id: calendar.id },
|
||
});
|
||
console.log(` ✅ Supprimé: ${calendar.name}`);
|
||
} catch (error) {
|
||
console.error(` ❌ Erreur lors de la suppression de ${calendar.name}:`, error);
|
||
}
|
||
}
|
||
|
||
console.log(`\n✅ Nettoyage terminé! ${orphanCalendars.length} calendrier(s) supprimé(s).\n`);
|
||
}
|
||
|
||
// Exécuter le script
|
||
cleanOrphanCalendars()
|
||
.then(() => {
|
||
process.exit(0);
|
||
})
|
||
.catch((error) => {
|
||
console.error('❌ Erreur fatale:', error);
|
||
process.exit(1);
|
||
});
|