- Ajout de 3 nouveaux paramètres globaux : délai d'expiration QR codes (minutes), durée de validité tokens (heures), notifications actives (boolean) - Création de la table historiqueParametres pour tracer toutes les modifications avec userId, userName, champModifié, ancienneValeur, nouvelleValeur et dateModification - Ajout d'un bouton "Tester l'URL" avec indicateur visuel de statut (vert si accessible, rouge si erreur) - Affichage de l'historique des modifications dans un tableau avec toutes les informations de traçabilité - Mise à jour automatique de l'historique lors de chaque modification de paramètre
134 lines
3.6 KiB
TypeScript
134 lines
3.6 KiB
TypeScript
import { eq, sql } from "drizzle-orm";
|
|
import { getDb } from "./db";
|
|
import { parametres, historiqueParametres } from "../drizzle/schema";
|
|
|
|
/**
|
|
* Récupérer les paramètres de l'application
|
|
* S'il n'y a pas de paramètres, en créer un avec les valeurs par défaut
|
|
*/
|
|
export async function getParametres() {
|
|
const db = await getDb();
|
|
if (!db) throw new Error("Database not available");
|
|
|
|
const result = await db.select().from(parametres).limit(1);
|
|
|
|
if (result.length === 0) {
|
|
// Créer les paramètres par défaut
|
|
await db.insert(parametres).values({
|
|
urlPublique: "https://formations.itinova.org",
|
|
});
|
|
|
|
const newResult = await db.select().from(parametres).limit(1);
|
|
return newResult[0];
|
|
}
|
|
|
|
return result[0];
|
|
}
|
|
|
|
/**
|
|
* Mettre à jour les paramètres de l'application
|
|
* Enregistre automatiquement l'historique des modifications
|
|
*/
|
|
export async function updateParametres(
|
|
updates: Partial<{
|
|
urlPublique: string;
|
|
delaiExpirationQR: number;
|
|
dureeValiditeToken: number;
|
|
notificationsActives: boolean;
|
|
}>,
|
|
userId: number,
|
|
userName: string
|
|
) {
|
|
const db = await getDb();
|
|
if (!db) throw new Error("Database not available");
|
|
|
|
const params = await getParametres();
|
|
|
|
// Enregistrer l'historique pour chaque champ modifié
|
|
for (const [key, value] of Object.entries(updates)) {
|
|
const oldValue = params[key as keyof typeof params];
|
|
if (oldValue !== value) {
|
|
await db.insert(historiqueParametres).values({
|
|
userId,
|
|
userName,
|
|
champModifie: key,
|
|
ancienneValeur: oldValue !== null && oldValue !== undefined ? String(oldValue) : null,
|
|
nouvelleValeur: value !== null && value !== undefined ? String(value) : null,
|
|
});
|
|
}
|
|
}
|
|
|
|
// Mettre à jour les paramètres
|
|
await db.update(parametres)
|
|
.set(updates)
|
|
.where(eq(parametres.id, params.id));
|
|
|
|
return getParametres();
|
|
}
|
|
|
|
/**
|
|
* Mettre à jour l'URL publique (fonction de compatibilité)
|
|
*/
|
|
export async function updateUrlPublique(urlPublique: string, userId?: number, userName?: string) {
|
|
return updateParametres(
|
|
{ urlPublique },
|
|
userId || 1,
|
|
userName || "Système"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Récupérer l'historique des modifications des paramètres
|
|
*/
|
|
export async function getHistoriqueParametres(limit: number = 50) {
|
|
const db = await getDb();
|
|
if (!db) throw new Error("Database not available");
|
|
|
|
return db.select()
|
|
.from(historiqueParametres)
|
|
.orderBy(sql`${historiqueParametres.dateModification} DESC`)
|
|
.limit(limit);
|
|
}
|
|
|
|
/**
|
|
* Tester l'accessibilité d'une URL
|
|
*/
|
|
export async function testerUrl(url: string): Promise<{ accessible: boolean; message: string; statusCode?: number }> {
|
|
try {
|
|
// Vérifier le format de l'URL
|
|
const urlObj = new URL(url);
|
|
if (!['http:', 'https:'].includes(urlObj.protocol)) {
|
|
return {
|
|
accessible: false,
|
|
message: "L'URL doit commencer par http:// ou https://"
|
|
};
|
|
}
|
|
|
|
// Tenter une requête HEAD pour vérifier l'accessibilité
|
|
const response = await fetch(url, {
|
|
method: 'HEAD',
|
|
signal: AbortSignal.timeout(5000), // Timeout de 5 secondes
|
|
});
|
|
|
|
return {
|
|
accessible: response.ok,
|
|
message: response.ok
|
|
? "L'URL est accessible"
|
|
: `L'URL a retourné une erreur HTTP ${response.status}`,
|
|
statusCode: response.status
|
|
};
|
|
} catch (error) {
|
|
if (error instanceof TypeError && error.message.includes('Invalid URL')) {
|
|
return {
|
|
accessible: false,
|
|
message: "Format d'URL invalide"
|
|
};
|
|
}
|
|
|
|
return {
|
|
accessible: false,
|
|
message: `Erreur lors du test: ${error instanceof Error ? error.message : 'Erreur inconnue'}`
|
|
};
|
|
}
|
|
}
|