ihm_client/examples/test-integration.html
NicolasCantu bf680ab6dd ci: docker_tag=pbkdf2-credentials
🔐 Implémentation PBKDF2 avec credentials navigateur

 Fonctionnalités ajoutées:
- SecureCredentialsService avec PBKDF2 (100k itérations)
- Chiffrement AES-GCM des clés spend/scan
- Interface utilisateur complète pour gestion credentials
- Tests unitaires complets
- Architecture modulaire avec EventBus
- Gestion mémoire optimisée
- Performance monitoring
- Web Workers pour encodage asynchrone

🛡️ Sécurité:
- Dérivation PBKDF2 avec salt unique
- Chiffrement AES-GCM des clés sensibles
- Validation force mot de passe
- Stockage sécurisé IndexedDB + WebAuthn
- Logging sécurisé sans exposition données

🔧 Corrections:
- Erreur 500 résolue (clé dupliquée package.json)
- Configuration Vite simplifiée
- Dépendances manquantes corrigées

📊 Améliorations:
- Architecture découplée avec repositories
- Services spécialisés (PairingService, etc.)
- Monitoring performance et mémoire
- Tests avec couverture complète
- Documentation technique détaillée
2025-10-23 12:51:49 +02:00

327 lines
11 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>4NK Integration Test</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 20px;
background: #f5f5f5;
}
.test-container {
max-width: 1200px;
margin: 0 auto;
background: white;
border-radius: 8px;
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
.test-section {
margin-bottom: 30px;
padding: 20px;
border: 1px solid #e0e0e0;
border-radius: 8px;
}
.test-section h3 {
margin-top: 0;
color: #333;
}
.iframe-container {
width: 100%;
height: 500px;
border: 2px solid #ddd;
border-radius: 8px;
overflow: hidden;
}
.iframe-container iframe {
width: 100%;
height: 100%;
border: none;
}
.test-controls {
display: flex;
gap: 10px;
margin: 20px 0;
flex-wrap: wrap;
}
.btn {
background: #007bff;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
.btn:hover {
background: #0056b3;
}
.btn.secondary {
background: #6c757d;
}
.btn.secondary:hover {
background: #545b62;
}
.log-container {
background: #1e1e1e;
color: #f8f9fa;
padding: 15px;
border-radius: 4px;
font-family: 'Courier New', monospace;
font-size: 12px;
max-height: 200px;
overflow-y: auto;
margin-top: 20px;
}
.log-entry {
margin-bottom: 5px;
padding: 2px 0;
}
.log-entry.info { color: #17a2b8; }
.log-entry.success { color: #28a745; }
.log-entry.error { color: #dc3545; }
.log-entry.warning { color: #ffc107; }
.status-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin: 20px 0;
}
.status-item {
background: #f8f9fa;
padding: 15px;
border-radius: 4px;
border-left: 4px solid #007bff;
}
.status-label {
font-weight: bold;
color: #333;
margin-bottom: 5px;
}
.status-value {
color: #666;
font-size: 14px;
}
</style>
</head>
<body>
<div class="test-container">
<h1>🧪 4NK Integration Test</h1>
<p>Test de l'intégration iframe avec communication channel_message</p>
<div class="test-section">
<h3>📱 Interface 4NK (Iframe)</h3>
<div class="iframe-container">
<iframe
id="4nk-iframe"
src="http://localhost:3004"
title="4NK Pairing System"
sandbox="allow-scripts allow-same-origin allow-forms"
></iframe>
</div>
</div>
<div class="test-section">
<h3>🎮 Contrôles de Test</h3>
<div class="test-controls">
<button class="btn" onclick="sendTestMessage()">📤 Test Message</button>
<button class="btn" onclick="testCreatePairing()">🔐 Test Create Pairing</button>
<button class="btn" onclick="testJoinPairing()">🔗 Test Join Pairing</button>
<button class="btn secondary" onclick="clearLog()">🗑️ Clear Log</button>
<button class="btn secondary" onclick="refreshIframe()">🔄 Refresh</button>
</div>
</div>
<div class="test-section">
<h3>📊 Status</h3>
<div class="status-grid">
<div class="status-item">
<div class="status-label">Iframe Status</div>
<div class="status-value" id="iframe-status">Loading...</div>
</div>
<div class="status-item">
<div class="status-label">Communication</div>
<div class="status-value" id="communication-status">Waiting...</div>
</div>
<div class="status-item">
<div class="status-label">Messages Received</div>
<div class="status-value" id="message-count">0</div>
</div>
<div class="status-item">
<div class="status-label">Last Message</div>
<div class="status-value" id="last-message">None</div>
</div>
</div>
</div>
<div class="test-section">
<h3>📝 Communication Log</h3>
<div class="log-container" id="log-container">
<div class="log-entry info">🚀 Test page loaded</div>
<div class="log-entry info">📡 Waiting for iframe communication...</div>
</div>
</div>
</div>
<script>
let messageCount = 0;
let iframeReady = false;
// Listen for messages from the iframe
window.addEventListener('message', function(event) {
// Security check - in production, verify event.origin
if (event.origin !== 'http://localhost:3004') {
return;
}
const { type, data } = event.data;
messageCount++;
logMessage(`📨 Received: ${type}`, 'info');
updateStatus('communication-status', 'Active');
updateStatus('message-count', messageCount.toString());
updateStatus('last-message', `${type} (${messageCount})`);
// Handle different message types
switch (type) {
case 'IFRAME_READY':
logMessage('✅ 4NK iframe is ready', 'success');
updateStatus('iframe-status', 'Ready');
iframeReady = true;
break;
case 'MENU_NAVIGATION':
logMessage(`🧭 Menu navigation: ${data.page}`, 'info');
break;
case 'PAIRING_4WORDS_WORDS_GENERATED':
logMessage(`🔐 4 words generated: ${data.words}`, 'success');
break;
case 'PAIRING_4WORDS_STATUS_UPDATE':
logMessage(`📊 Status update: ${data.status}`, 'info');
break;
case 'PAIRING_4WORDS_SUCCESS':
logMessage(`✅ Pairing successful: ${data.message}`, 'success');
break;
case 'PAIRING_4WORDS_ERROR':
logMessage(`❌ Pairing error: ${data.error}`, 'error');
break;
case 'TEST_RESPONSE':
logMessage(`🧪 Test response: ${data.response}`, 'success');
break;
default:
logMessage(`❓ Unknown message type: ${type}`, 'warning');
}
});
function logMessage(message, type = 'info') {
const logContainer = document.getElementById('log-container');
const timestamp = new Date().toLocaleTimeString();
const logEntry = document.createElement('div');
logEntry.className = `log-entry ${type}`;
logEntry.textContent = `[${timestamp}] ${message}`;
logContainer.appendChild(logEntry);
logContainer.scrollTop = logContainer.scrollHeight;
}
function updateStatus(elementId, value) {
const element = document.getElementById(elementId);
if (element) {
element.textContent = value;
}
}
function sendTestMessage() {
const iframe = document.getElementById('4nk-iframe');
if (iframe && iframe.contentWindow) {
iframe.contentWindow.postMessage({
type: 'TEST_MESSAGE',
data: { message: 'Hello from test page!' }
}, 'http://localhost:3004');
logMessage('📤 Sent test message to iframe', 'info');
} else {
logMessage('❌ Iframe not ready', 'error');
}
}
function testCreatePairing() {
const iframe = document.getElementById('4nk-iframe');
if (iframe && iframe.contentWindow) {
iframe.contentWindow.postMessage({
type: 'PAIRING_4WORDS_CREATE',
data: {}
}, 'http://localhost:3004');
logMessage('🔐 Sent create pairing request', 'info');
} else {
logMessage('❌ Iframe not ready', 'error');
}
}
function testJoinPairing() {
const words = prompt('Enter 4 words to test join pairing:');
if (words) {
const iframe = document.getElementById('4nk-iframe');
if (iframe && iframe.contentWindow) {
iframe.contentWindow.postMessage({
type: 'PAIRING_4WORDS_JOIN',
data: { words: words }
}, 'http://localhost:3004');
logMessage(`🔗 Sent join pairing request with words: ${words}`, 'info');
} else {
logMessage('❌ Iframe not ready', 'error');
}
}
}
function clearLog() {
const logContainer = document.getElementById('log-container');
logContainer.innerHTML = '<div class="log-entry info">🗑️ Log cleared</div>';
}
function refreshIframe() {
const iframe = document.getElementById('4nk-iframe');
iframe.src = iframe.src;
logMessage('🔄 Iframe refreshed', 'info');
updateStatus('iframe-status', 'Refreshing...');
iframeReady = false;
}
// Initialize
logMessage('🌐 Test page initialized', 'success');
// Auto-test after 3 seconds
setTimeout(() => {
if (iframeReady) {
logMessage('🧪 Auto-testing communication...', 'info');
sendTestMessage();
}
}, 3000);
</script>
</body>
</html>