238 lines
9.5 KiB
HTML
238 lines
9.5 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="fr">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Diagnostic Token - Admin</title>
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body {
|
|
font-family: 'Courier New', monospace;
|
|
background: #1a1a1a;
|
|
color: #00ff00;
|
|
padding: 20px;
|
|
line-height: 1.6;
|
|
}
|
|
.container { max-width: 1200px; margin: 0 auto; }
|
|
h1 { color: #00ffff; margin-bottom: 20px; font-size: 24px; }
|
|
.section { background: #2a2a2a; padding: 20px; margin-bottom: 20px; border-radius: 8px; border: 1px solid #444; }
|
|
.section h2 { color: #ffff00; margin-bottom: 15px; font-size: 18px; }
|
|
.log { padding: 10px; margin: 5px 0; border-radius: 4px; }
|
|
.success { background: #1a4d1a; color: #00ff00; }
|
|
.error { background: #4d1a1a; color: #ff6b6b; }
|
|
.warning { background: #4d4d1a; color: #ffff00; }
|
|
.info { background: #1a1a4d; color: #6bb6ff; }
|
|
button {
|
|
background: #00ff00;
|
|
color: #000;
|
|
border: none;
|
|
padding: 12px 24px;
|
|
font-size: 14px;
|
|
font-weight: bold;
|
|
cursor: pointer;
|
|
border-radius: 4px;
|
|
margin: 5px;
|
|
}
|
|
button:hover { background: #00cc00; }
|
|
.token-box {
|
|
background: #000;
|
|
padding: 15px;
|
|
border-radius: 4px;
|
|
word-break: break-all;
|
|
margin: 10px 0;
|
|
border: 1px solid #444;
|
|
}
|
|
pre { white-space: pre-wrap; word-wrap: break-word; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<h1>🔍 DIAGNOSTIC COMPLET - ERREUR 403 FORBIDDEN</h1>
|
|
|
|
<div class="section">
|
|
<h2>📋 ÉTAPE 1 : VÉRIFICATION LOCAL STORAGE</h2>
|
|
<div id="step1"></div>
|
|
<button onclick="checkLocalStorage()">Vérifier LocalStorage</button>
|
|
</div>
|
|
|
|
<div class="section">
|
|
<h2>🔧 ÉTAPE 2 : INSTALLATION DU BON TOKEN</h2>
|
|
<div id="step2"></div>
|
|
<button onclick="installToken()">Installer le Token avec la Bonne Clé</button>
|
|
</div>
|
|
|
|
<div class="section">
|
|
<h2>🧪 ÉTAPE 3 : TEST DE CONNEXION AU BACKEND</h2>
|
|
<div id="step3"></div>
|
|
<button onclick="testBackend()">Tester le Backend</button>
|
|
</div>
|
|
|
|
<div class="section">
|
|
<h2>📡 ÉTAPE 4 : TEST DE L'ENDPOINT TIRAGE</h2>
|
|
<div id="step4"></div>
|
|
<button onclick="testDrawEndpoint()">Tester l'Endpoint Tirage</button>
|
|
</div>
|
|
|
|
<div class="section">
|
|
<h2>🚀 ÉTAPE 5 : REDIRECTION VERS LA PAGE</h2>
|
|
<button onclick="goToTirage()">Aller à la Page de Tirage</button>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
const CORRECT_TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI1YTIzOThkZi00NWNiLTQyOGQtOWY1ZS04YzQwNzQxNzEyNGIiLCJpYXQiOjE3NjMwODM0NjksImV4cCI6MTc2MzY4ODI2OX0.fCxlIzy-RkCqvCwjatHmIZ5pjqC61Vs-RAnZwulNd_Q';
|
|
|
|
function log(target, message, type = 'info') {
|
|
const div = document.getElementById(target);
|
|
const logDiv = document.createElement('div');
|
|
logDiv.className = `log ${type}`;
|
|
logDiv.innerHTML = message;
|
|
div.appendChild(logDiv);
|
|
}
|
|
|
|
function clear(target) {
|
|
document.getElementById(target).innerHTML = '';
|
|
}
|
|
|
|
function checkLocalStorage() {
|
|
clear('step1');
|
|
|
|
// Vérifier toutes les clés possibles
|
|
const keys = ['token', 'auth_token', 'user_data', 'authToken'];
|
|
log('step1', '📊 ANALYSE DU LOCAL STORAGE:', 'info');
|
|
|
|
keys.forEach(key => {
|
|
const value = localStorage.getItem(key);
|
|
if (value) {
|
|
const preview = value.length > 50 ? value.substring(0, 50) + '...' : value;
|
|
log('step1', `✅ Clé "${key}" trouvée: ${preview}`, 'success');
|
|
} else {
|
|
log('step1', `❌ Clé "${key}" NON trouvée`, 'error');
|
|
}
|
|
});
|
|
|
|
// Lister TOUTES les clés présentes
|
|
log('step1', '<br>📋 Toutes les clés présentes dans localStorage:', 'info');
|
|
for (let i = 0; i < localStorage.length; i++) {
|
|
const key = localStorage.key(i);
|
|
log('step1', ` • ${key}`, 'info');
|
|
}
|
|
}
|
|
|
|
function installToken() {
|
|
clear('step2');
|
|
log('step2', '🔧 Installation du token avec TOUTES les clés possibles...', 'info');
|
|
|
|
try {
|
|
// Nettoyer d'abord
|
|
localStorage.clear();
|
|
sessionStorage.clear();
|
|
log('step2', '✅ LocalStorage et SessionStorage vidés', 'success');
|
|
|
|
// Installer avec TOUTES les clés possibles
|
|
localStorage.setItem('auth_token', CORRECT_TOKEN);
|
|
localStorage.setItem('token', CORRECT_TOKEN);
|
|
localStorage.setItem('authToken', CORRECT_TOKEN);
|
|
|
|
log('step2', '✅ Token installé avec les clés:', 'success');
|
|
log('step2', ' • auth_token ✓', 'success');
|
|
log('step2', ' • token ✓', 'success');
|
|
log('step2', ' • authToken ✓', 'success');
|
|
|
|
// Vérifier
|
|
const check = localStorage.getItem('auth_token');
|
|
if (check === CORRECT_TOKEN) {
|
|
log('step2', '<br>✅ VÉRIFICATION RÉUSSIE: Token correctement enregistré', 'success');
|
|
} else {
|
|
log('step2', '<br>❌ ERREUR: Token non enregistré correctement', 'error');
|
|
}
|
|
|
|
} catch (error) {
|
|
log('step2', `❌ ERREUR: ${error.message}`, 'error');
|
|
}
|
|
}
|
|
|
|
async function testBackend() {
|
|
clear('step3');
|
|
log('step3', '🧪 Test de connexion au backend...', 'info');
|
|
|
|
try {
|
|
const response = await fetch('http://localhost:4000');
|
|
const data = await response.json();
|
|
|
|
if (response.ok) {
|
|
log('step3', `✅ Backend accessible: ${data.message}`, 'success');
|
|
} else {
|
|
log('step3', `❌ Backend répond mais avec erreur: ${response.status}`, 'error');
|
|
}
|
|
} catch (error) {
|
|
log('step3', `❌ Backend NON accessible: ${error.message}`, 'error');
|
|
log('step3', '💡 Vérifiez que le backend est démarré sur le port 4000', 'warning');
|
|
}
|
|
}
|
|
|
|
async function testDrawEndpoint() {
|
|
clear('step4');
|
|
log('step4', '📡 Test de l\'endpoint /api/draw/eligible-participants...', 'info');
|
|
|
|
const token = localStorage.getItem('auth_token') || localStorage.getItem('token');
|
|
|
|
if (!token) {
|
|
log('step4', '❌ Aucun token trouvé! Installez d\'abord le token (Étape 2)', 'error');
|
|
return;
|
|
}
|
|
|
|
log('step4', `🔑 Token utilisé: ${token.substring(0, 50)}...`, 'info');
|
|
|
|
try {
|
|
log('step4', '<br>📤 Envoi de la requête...', 'info');
|
|
|
|
const response = await fetch('http://localhost:4000/api/draw/eligible-participants?minTickets=1&verified=true', {
|
|
headers: {
|
|
'Authorization': `Bearer ${token}`,
|
|
'Content-Type': 'application/json'
|
|
}
|
|
});
|
|
|
|
log('step4', `📥 Réponse reçue: Status ${response.status} ${response.statusText}`,
|
|
response.ok ? 'success' : 'error');
|
|
|
|
const data = await response.json();
|
|
|
|
if (response.ok) {
|
|
log('step4', `<br>✅ SUCCÈS! ${data.data.total} participants trouvés:`, 'success');
|
|
data.data.participants.forEach((p, i) => {
|
|
log('step4', ` ${i+1}. ${p.first_name} ${p.last_name} - ${p.tickets_played} ticket(s)`, 'success');
|
|
});
|
|
log('step4', '<br>🎉 LE PROBLÈME EST RÉSOLU! Vous pouvez aller sur la page de tirage.', 'success');
|
|
} else {
|
|
log('step4', `<br>❌ ERREUR ${response.status}: ${data.message || data.error || 'Erreur inconnue'}`, 'error');
|
|
|
|
if (response.status === 403) {
|
|
log('step4', '<br>🔍 Diagnostic de l\'erreur 403:', 'warning');
|
|
log('step4', ' Causes possibles:', 'warning');
|
|
log('step4', ' 1. Token invalide ou expiré', 'warning');
|
|
log('step4', ' 2. Utilisateur n\'a pas le rôle ADMIN', 'warning');
|
|
log('step4', ' 3. JWT_SECRET différent entre frontend et backend', 'warning');
|
|
}
|
|
}
|
|
} catch (error) {
|
|
log('step4', `❌ ERREUR RÉSEAU: ${error.message}`, 'error');
|
|
log('step4', '💡 Le backend n\'est peut-être pas accessible', 'warning');
|
|
}
|
|
}
|
|
|
|
function goToTirage() {
|
|
window.location.href = 'http://localhost:3000/admin/tirages';
|
|
}
|
|
|
|
// Auto-exécution au chargement
|
|
window.addEventListener('load', () => {
|
|
setTimeout(() => {
|
|
checkLocalStorage();
|
|
}, 500);
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|