UI: remove manual continue buttons for setup flows\n\nMotivations:\n- Enchaînement automatique des étapes sans interaction inutile\n- Éviter confusion pendant faucet/sync\n\nModifications:\n- Suppression des boutons dans wallet-setup.html et block-sync.html\n- Adaptation wallet-setup.ts pour redirection auto sans bouton\n\nPage affectées:\n- src/pages/wallet-setup/wallet-setup.html, src/pages/block-sync/block-sync.html, src/pages/wallet-setup/wallet-setup.ts
This commit is contained in:
parent
bd1762ee0c
commit
44adae2d05
@ -4,3 +4,4 @@ alwaysApply: true
|
|||||||
|
|
||||||
le site tourne sur le port 3004
|
le site tourne sur le port 3004
|
||||||
l'url du site est https://dev3.4nkweb.com
|
l'url du site est https://dev3.4nkweb.com
|
||||||
|
ne déclanche jamais la CI
|
||||||
@ -1,4 +1,5 @@
|
|||||||
import { MessageType } from '../../models/process.model';
|
import { MessageType } from '../../models/process.model';
|
||||||
|
import { secureLogger } from '../../services/secure-logger';
|
||||||
|
|
||||||
export class IframePairingComponent {
|
export class IframePairingComponent {
|
||||||
private iframe: HTMLIFrameElement | null = null;
|
private iframe: HTMLIFrameElement | null = null;
|
||||||
@ -19,7 +20,7 @@ export class IframePairingComponent {
|
|||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'IFRAME_READY':
|
case 'IFRAME_READY':
|
||||||
console.log('🔗 Iframe pairing service is ready');
|
secureLogger.info('Iframe pairing service is ready', { component: 'IframePairingComponent' });
|
||||||
this.isReady = true;
|
this.isReady = true;
|
||||||
break;
|
break;
|
||||||
case MessageType.PAIRING_4WORDS_WORDS_GENERATED:
|
case MessageType.PAIRING_4WORDS_WORDS_GENERATED:
|
||||||
@ -57,7 +58,7 @@ export class IframePairingComponent {
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
document.body.appendChild(this.iframe);
|
document.body.appendChild(this.iframe);
|
||||||
console.log('🔗 Hidden iframe created for pairing');
|
secureLogger.debug('Hidden iframe created for pairing', { component: 'IframePairingComponent' });
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createPairing(): Promise<void> {
|
public async createPairing(): Promise<void> {
|
||||||
@ -93,7 +94,7 @@ export class IframePairingComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onWordsGenerated(data: any) {
|
private onWordsGenerated(data: any) {
|
||||||
console.log('✅ 4 words generated:', data.words);
|
secureLogger.info('4 words generated', { component: 'IframePairingComponent', hasWords: !!data.words });
|
||||||
// Emit custom event for the parent application
|
// Emit custom event for the parent application
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent('pairing-words-generated', {
|
new CustomEvent('pairing-words-generated', {
|
||||||
@ -103,7 +104,7 @@ export class IframePairingComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onStatusUpdate(data: any) {
|
private onStatusUpdate(data: any) {
|
||||||
console.log('📊 Pairing status update:', data.status);
|
secureLogger.debug('Pairing status update', { component: 'IframePairingComponent', status: data.status });
|
||||||
// Emit custom event for the parent application
|
// Emit custom event for the parent application
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent('pairing-status-update', {
|
new CustomEvent('pairing-status-update', {
|
||||||
@ -113,7 +114,7 @@ export class IframePairingComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onPairingSuccess(data: any) {
|
private onPairingSuccess(data: any) {
|
||||||
console.log('✅ Pairing successful:', data.message);
|
secureLogger.info('Pairing successful', { component: 'IframePairingComponent', message: data.message });
|
||||||
// Emit custom event for the parent application
|
// Emit custom event for the parent application
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent('pairing-success', {
|
new CustomEvent('pairing-success', {
|
||||||
@ -123,7 +124,7 @@ export class IframePairingComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private onPairingError(data: any) {
|
private onPairingError(data: any) {
|
||||||
console.error('❌ Pairing error:', data.error);
|
secureLogger.error('Pairing error', { component: 'IframePairingComponent', error: data.error });
|
||||||
// Emit custom event for the parent application
|
// Emit custom event for the parent application
|
||||||
window.dispatchEvent(
|
window.dispatchEvent(
|
||||||
new CustomEvent('pairing-error', {
|
new CustomEvent('pairing-error', {
|
||||||
|
|||||||
@ -33,12 +33,12 @@ export class SecureCredentialsComponent {
|
|||||||
|
|
||||||
secureLogger.info('SecureCredentialsComponent initialized', {
|
secureLogger.info('SecureCredentialsComponent initialized', {
|
||||||
component: 'SecureCredentialsComponent',
|
component: 'SecureCredentialsComponent',
|
||||||
operation: 'init'
|
operation: 'init',
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
secureLogger.error('Failed to initialize SecureCredentialsComponent', error as Error, {
|
secureLogger.error('Failed to initialize SecureCredentialsComponent', error as Error, {
|
||||||
component: 'SecureCredentialsComponent',
|
component: 'SecureCredentialsComponent',
|
||||||
operation: 'init'
|
operation: 'init',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,7 +54,7 @@ export class SecureCredentialsComponent {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
secureLogger.error('Failed to load secure credentials HTML', error as Error, {
|
secureLogger.error('Failed to load secure credentials HTML', error as Error, {
|
||||||
component: 'SecureCredentialsComponent',
|
component: 'SecureCredentialsComponent',
|
||||||
operation: 'loadHTML'
|
operation: 'loadHTML',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,7 +71,7 @@ export class SecureCredentialsComponent {
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
secureLogger.error('Failed to load secure credentials CSS', error as Error, {
|
secureLogger.error('Failed to load secure credentials CSS', error as Error, {
|
||||||
component: 'SecureCredentialsComponent',
|
component: 'SecureCredentialsComponent',
|
||||||
operation: 'loadCSS'
|
operation: 'loadCSS',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,14 +145,13 @@ export class SecureCredentialsComponent {
|
|||||||
|
|
||||||
// Émettre l'événement
|
// Émettre l'événement
|
||||||
eventBus.emit('credentials:created', { credentials });
|
eventBus.emit('credentials:created', { credentials });
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorMessage = error instanceof Error ? error.message : 'Erreur inconnue';
|
const errorMessage = error instanceof Error ? error.message : 'Erreur inconnue';
|
||||||
this.showMessage(`Erreur lors de la création des credentials: ${errorMessage}`, 'error');
|
this.showMessage(`Erreur lors de la création des credentials: ${errorMessage}`, 'error');
|
||||||
|
|
||||||
secureLogger.error('Failed to create credentials', error as Error, {
|
secureLogger.error('Failed to create credentials', error as Error, {
|
||||||
component: 'SecureCredentialsComponent',
|
component: 'SecureCredentialsComponent',
|
||||||
operation: 'handleCreateCredentials'
|
operation: 'handleCreateCredentials',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -180,14 +179,13 @@ export class SecureCredentialsComponent {
|
|||||||
} else {
|
} else {
|
||||||
this.showMessage('Aucun credential trouvé ou mot de passe incorrect', 'error');
|
this.showMessage('Aucun credential trouvé ou mot de passe incorrect', 'error');
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorMessage = error instanceof Error ? error.message : 'Erreur inconnue';
|
const errorMessage = error instanceof Error ? error.message : 'Erreur inconnue';
|
||||||
this.showMessage(`Erreur lors de la récupération des credentials: ${errorMessage}`, 'error');
|
this.showMessage(`Erreur lors de la récupération des credentials: ${errorMessage}`, 'error');
|
||||||
|
|
||||||
secureLogger.error('Failed to access credentials', error as Error, {
|
secureLogger.error('Failed to access credentials', error as Error, {
|
||||||
component: 'SecureCredentialsComponent',
|
component: 'SecureCredentialsComponent',
|
||||||
operation: 'handleAccessCredentials'
|
operation: 'handleAccessCredentials',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -210,7 +208,8 @@ export class SecureCredentialsComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Simple password strength check
|
// Simple password strength check
|
||||||
const score = password.length >= 12 ? (password.length >= 16 ? 5 : 4) : (password.length >= 8 ? 3 : 2);
|
const score =
|
||||||
|
password.length >= 12 ? (password.length >= 16 ? 5 : 4) : password.length >= 8 ? 3 : 2;
|
||||||
|
|
||||||
if (score < 3) {
|
if (score < 3) {
|
||||||
strengthDiv.className += ' weak';
|
strengthDiv.className += ' weak';
|
||||||
@ -233,7 +232,7 @@ export class SecureCredentialsComponent {
|
|||||||
await this.updateUI();
|
await this.updateUI();
|
||||||
this.showMessage('Credentials actualisés', 'success');
|
this.showMessage('Credentials actualisés', 'success');
|
||||||
} catch {
|
} catch {
|
||||||
this.showMessage('Erreur lors de l\'actualisation', 'error');
|
this.showMessage("Erreur lors de l'actualisation", 'error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,26 +240,31 @@ export class SecureCredentialsComponent {
|
|||||||
* Gère la suppression des credentials
|
* Gère la suppression des credentials
|
||||||
*/
|
*/
|
||||||
private async handleDeleteCredentials(): Promise<void> {
|
private async handleDeleteCredentials(): Promise<void> {
|
||||||
if (!confirm('Êtes-vous sûr de vouloir supprimer tous les credentials ? Cette action est irréversible.')) {
|
if (
|
||||||
|
!confirm(
|
||||||
|
'Êtes-vous sûr de vouloir supprimer tous les credentials ? Cette action est irréversible.'
|
||||||
|
)
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// TODO: Implement credentials deletion
|
// TODO: Implement credentials deletion
|
||||||
console.log('Credentials deletion requested but not implemented');
|
secureLogger.warn('Credentials deletion requested but not implemented', {
|
||||||
|
component: 'SecureCredentials',
|
||||||
|
});
|
||||||
this.showMessage('Suppression des credentials non implémentée', 'warning');
|
this.showMessage('Suppression des credentials non implémentée', 'warning');
|
||||||
await this.updateUI();
|
await this.updateUI();
|
||||||
|
|
||||||
// Émettre l'événement
|
// Émettre l'événement
|
||||||
eventBus.emit('credentials:deleted');
|
eventBus.emit('credentials:deleted');
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorMessage = error instanceof Error ? error.message : 'Erreur inconnue';
|
const errorMessage = error instanceof Error ? error.message : 'Erreur inconnue';
|
||||||
this.showMessage(`Erreur lors de la suppression: ${errorMessage}`, 'error');
|
this.showMessage(`Erreur lors de la suppression: ${errorMessage}`, 'error');
|
||||||
|
|
||||||
secureLogger.error('Failed to delete credentials', error as Error, {
|
secureLogger.error('Failed to delete credentials', error as Error, {
|
||||||
component: 'SecureCredentialsComponent',
|
component: 'SecureCredentialsComponent',
|
||||||
operation: 'handleDeleteCredentials'
|
operation: 'handleDeleteCredentials',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -293,11 +297,10 @@ export class SecureCredentialsComponent {
|
|||||||
statusElement.textContent = hasCredentials ? 'Disponibles' : 'Non disponibles';
|
statusElement.textContent = hasCredentials ? 'Disponibles' : 'Non disponibles';
|
||||||
statusElement.className = hasCredentials ? 'value success' : 'value error';
|
statusElement.className = hasCredentials ? 'value success' : 'value error';
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
secureLogger.error('Failed to update UI', error as Error, {
|
secureLogger.error('Failed to update UI', error as Error, {
|
||||||
component: 'SecureCredentialsComponent',
|
component: 'SecureCredentialsComponent',
|
||||||
operation: 'updateUI'
|
operation: 'updateUI',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -331,7 +334,9 @@ export class SecureCredentialsComponent {
|
|||||||
*/
|
*/
|
||||||
private showMessage(message: string, type: 'success' | 'error' | 'warning' | 'info'): void {
|
private showMessage(message: string, type: 'success' | 'error' | 'warning' | 'info'): void {
|
||||||
const messagesContainer = document.getElementById('credentials-messages');
|
const messagesContainer = document.getElementById('credentials-messages');
|
||||||
if (!messagesContainer) {return;}
|
if (!messagesContainer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const messageDiv = document.createElement('div');
|
const messageDiv = document.createElement('div');
|
||||||
messageDiv.className = `message ${type}`;
|
messageDiv.className = `message ${type}`;
|
||||||
@ -351,8 +356,7 @@ export class SecureCredentialsComponent {
|
|||||||
* Gère l'événement de création de credentials
|
* Gère l'événement de création de credentials
|
||||||
*/
|
*/
|
||||||
private handleCredentialsCreated(data: any): void {
|
private handleCredentialsCreated(data: any): void {
|
||||||
// Use data variable
|
secureLogger.info('Credentials created', { component: 'SecureCredentials' });
|
||||||
console.log('Credentials created:', data);
|
|
||||||
this.showMessage('Credentials créés avec succès !', 'success');
|
this.showMessage('Credentials créés avec succès !', 'success');
|
||||||
this.updateUI();
|
this.updateUI();
|
||||||
}
|
}
|
||||||
@ -378,7 +382,7 @@ export class SecureCredentialsComponent {
|
|||||||
|
|
||||||
secureLogger.info('SecureCredentialsComponent destroyed', {
|
secureLogger.info('SecureCredentialsComponent destroyed', {
|
||||||
component: 'SecureCredentialsComponent',
|
component: 'SecureCredentialsComponent',
|
||||||
operation: 'destroy'
|
operation: 'destroy',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -187,9 +187,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button id="continueBtn" class="continue-btn" disabled>
|
|
||||||
Aller au pairing
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="module" src="./block-sync.ts"></script>
|
<script type="module" src="./block-sync.ts"></script>
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import loginHtml from './home.html?raw';
|
|||||||
import loginScript from './home.ts?raw';
|
import loginScript from './home.ts?raw';
|
||||||
import loginCss from '../../4nk.css?raw';
|
import loginCss from '../../4nk.css?raw';
|
||||||
import { initHomePage } from './home';
|
import { initHomePage } from './home';
|
||||||
|
import { secureLogger } from '../../services/secure-logger';
|
||||||
|
|
||||||
export class LoginComponent extends HTMLElement {
|
export class LoginComponent extends HTMLElement {
|
||||||
_callback: any;
|
_callback: any;
|
||||||
@ -11,7 +12,7 @@ export class LoginComponent extends HTMLElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
console.log('CALLBACK LOGIN PAGE');
|
secureLogger.info('Login component connected', { component: 'LoginComponent' });
|
||||||
this.render();
|
this.render();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
initHomePage();
|
initHomePage();
|
||||||
@ -22,7 +23,7 @@ export class LoginComponent extends HTMLElement {
|
|||||||
if (typeof fn === 'function') {
|
if (typeof fn === 'function') {
|
||||||
this._callback = fn;
|
this._callback = fn;
|
||||||
} else {
|
} else {
|
||||||
console.error('Callback is not a function');
|
secureLogger.error('Callback is not a function', { component: 'LoginComponent' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -112,7 +112,7 @@
|
|||||||
<div class="progress-bar" id="progressBar"></div>
|
<div class="progress-bar" id="progressBar"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="continue-btn" id="continueBtn" disabled>Ajouter la date anniversaire du wallet</button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="module" src="./wallet-setup.ts"></script>
|
<script type="module" src="./wallet-setup.ts"></script>
|
||||||
|
|||||||
@ -12,7 +12,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||||||
|
|
||||||
const status = document.getElementById('status') as HTMLDivElement;
|
const status = document.getElementById('status') as HTMLDivElement;
|
||||||
const progressBar = document.getElementById('progressBar') as HTMLDivElement;
|
const progressBar = document.getElementById('progressBar') as HTMLDivElement;
|
||||||
const continueBtn = document.getElementById('continueBtn') as HTMLButtonElement;
|
const continueBtn = document.getElementById('continueBtn') as HTMLButtonElement | null;
|
||||||
|
|
||||||
function updateStatus(message: string, type: 'loading' | 'success' | 'error') {
|
function updateStatus(message: string, type: 'loading' | 'success' | 'error') {
|
||||||
status.textContent = message;
|
status.textContent = message;
|
||||||
@ -84,12 +84,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||||||
updateStatus('✅ Wallet existant trouvé', 'success');
|
updateStatus('✅ Wallet existant trouvé', 'success');
|
||||||
updateProgress(100);
|
updateProgress(100);
|
||||||
|
|
||||||
// Activer le bouton et rediriger
|
// Redirection automatique sans bouton
|
||||||
continueBtn.disabled = false;
|
|
||||||
continueBtn.textContent = 'Continuer';
|
|
||||||
continueBtn.onclick = () => {
|
|
||||||
window.location.href = '/src/pages/birthday-setup/birthday-setup.html';
|
|
||||||
};
|
|
||||||
|
|
||||||
// Auto-redirection après 2 secondes
|
// Auto-redirection après 2 secondes
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -512,9 +507,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||||||
secureLogger.info('🎉 Wallet setup completed successfully - wallet saved with birthday_waiting state', { component: 'WalletSetup' });
|
secureLogger.info('🎉 Wallet setup completed successfully - wallet saved with birthday_waiting state', { component: 'WalletSetup' });
|
||||||
secureLogger.info('🔗 Ready to proceed to network connection and birthday setup', { component: 'WalletSetup' });
|
secureLogger.info('🔗 Ready to proceed to network connection and birthday setup', { component: 'WalletSetup' });
|
||||||
|
|
||||||
// Activer le bouton continuer
|
// Redirection automatique sans interaction utilisateur
|
||||||
continueBtn.disabled = false;
|
|
||||||
secureLogger.info('✅ Continue button enabled', { component: 'WalletSetup' });
|
|
||||||
|
|
||||||
// Redirection automatique après 3 secondes si l'utilisateur ne clique pas
|
// Redirection automatique après 3 secondes si l'utilisateur ne clique pas
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||
@ -131,17 +131,17 @@ export class WebAuthnService {
|
|||||||
password: string,
|
password: string,
|
||||||
mode: SecurityMode
|
mode: SecurityMode
|
||||||
): Promise<WebAuthnCredential> {
|
): Promise<WebAuthnCredential> {
|
||||||
console.log('🔐 WebAuthnService.createCredentials called with mode:', mode);
|
secureLogger.debug('WebAuthnService.createCredentials called', { component: 'WebAuthn', mode });
|
||||||
|
|
||||||
// Vérifier la disponibilité de Proton Pass si c'est le mode sélectionné
|
// Vérifier la disponibilité de Proton Pass si c'est le mode sélectionné
|
||||||
if (mode === 'proton-pass') {
|
if (mode === 'proton-pass') {
|
||||||
console.log('🔍 Checking Proton Pass availability...');
|
secureLogger.debug('Checking Proton Pass availability', { component: 'WebAuthn' });
|
||||||
const protonPassAvailable = await this.detectProtonPass();
|
const protonPassAvailable = await this.detectProtonPass();
|
||||||
if (!protonPassAvailable) {
|
if (!protonPassAvailable) {
|
||||||
console.log('❌ Proton Pass not available, falling back to platform authenticator');
|
secureLogger.debug('Proton Pass not available, falling back to platform authenticator', { component: 'WebAuthn' });
|
||||||
// Ne pas échouer, mais utiliser un mode de fallback
|
// Ne pas échouer, mais utiliser un mode de fallback
|
||||||
} else {
|
} else {
|
||||||
console.log('✅ Proton Pass is available and ready');
|
secureLogger.debug('Proton Pass is available and ready', { component: 'WebAuthn' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,10 +155,10 @@ export class WebAuthnService {
|
|||||||
// Configuration spécifique selon le mode
|
// Configuration spécifique selon le mode
|
||||||
if (mode === 'proton-pass') {
|
if (mode === 'proton-pass') {
|
||||||
authenticatorSelection.authenticatorAttachment = "platform";
|
authenticatorSelection.authenticatorAttachment = "platform";
|
||||||
console.log('🔐 Configuring for Proton Pass (platform authenticator)');
|
secureLogger.debug('Configuring for Proton Pass', { component: 'WebAuthn' });
|
||||||
} else if (mode === 'os') {
|
} else if (mode === 'os') {
|
||||||
authenticatorSelection.authenticatorAttachment = "platform";
|
authenticatorSelection.authenticatorAttachment = "platform";
|
||||||
console.log('🔐 Configuring for OS authenticator (platform)');
|
secureLogger.debug('Configuring for OS authenticator', { component: 'WebAuthn' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const publicKeyCredentialCreationOptions: PublicKeyCredentialCreationOptions = {
|
const publicKeyCredentialCreationOptions: PublicKeyCredentialCreationOptions = {
|
||||||
@ -186,24 +186,23 @@ export class WebAuthnService {
|
|||||||
publicKeyCredentialCreationOptions.extensions = {
|
publicKeyCredentialCreationOptions.extensions = {
|
||||||
largeBlob: { support: "preferred" }
|
largeBlob: { support: "preferred" }
|
||||||
};
|
};
|
||||||
console.log('🔐 Added largeBlob extension for Proton Pass');
|
secureLogger.debug('Added largeBlob extension for Proton Pass', { component: 'WebAuthn' });
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('🔐 Calling navigator.credentials.create with options:', publicKeyCredentialCreationOptions);
|
secureLogger.debug('Calling navigator.credentials.create', { component: 'WebAuthn' });
|
||||||
console.log('🔐 This should trigger Proton Pass window...');
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const credential = await navigator.credentials.create({
|
const credential = await navigator.credentials.create({
|
||||||
publicKey: publicKeyCredentialCreationOptions
|
publicKey: publicKeyCredentialCreationOptions
|
||||||
}) as PublicKeyCredential;
|
}) as PublicKeyCredential;
|
||||||
|
|
||||||
console.log('🔐 WebAuthn credential created successfully:', credential);
|
secureLogger.debug('WebAuthn credential created successfully', { component: 'WebAuthn' });
|
||||||
|
|
||||||
const response = credential.response as AuthenticatorAttestationResponse;
|
const response = credential.response as AuthenticatorAttestationResponse;
|
||||||
const credentialId = Array.from(new Uint8Array(credential.rawId)).map(b => b.toString(16).padStart(2, '0')).join('');
|
const credentialId = Array.from(new Uint8Array(credential.rawId)).map(b => b.toString(16).padStart(2, '0')).join('');
|
||||||
|
|
||||||
// TEST: Store credentialId in sessionStorage for testing
|
// TEST: Store credentialId in sessionStorage for testing
|
||||||
console.log('🔐 TEST: Storing credentialId in sessionStorage:', credentialId);
|
secureLogger.debug('Storing credentialId in sessionStorage', { component: 'WebAuthn' });
|
||||||
sessionStorage.setItem('webauthn_credential_id', credentialId);
|
sessionStorage.setItem('webauthn_credential_id', credentialId);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -211,7 +210,7 @@ export class WebAuthnService {
|
|||||||
publicKey: Array.from(new Uint8Array(response.getPublicKey()!))
|
publicKey: Array.from(new Uint8Array(response.getPublicKey()!))
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ WebAuthn credential creation failed:', error);
|
secureLogger.error('WebAuthn credential creation failed', error as Error, { component: 'WebAuthn' });
|
||||||
|
|
||||||
// Message d'erreur spécifique pour Proton Pass
|
// Message d'erreur spécifique pour Proton Pass
|
||||||
if (mode === 'proton-pass') {
|
if (mode === 'proton-pass') {
|
||||||
@ -236,7 +235,7 @@ export class WebAuthnService {
|
|||||||
// Utiliser l'ID de la credential WebAuthn comme mot de passe pour chiffrer la clé PBKDF2
|
// Utiliser l'ID de la credential WebAuthn comme mot de passe pour chiffrer la clé PBKDF2
|
||||||
const encryptedKey = await encryptionService.encrypt(key, credential.id);
|
const encryptedKey = await encryptionService.encrypt(key, credential.id);
|
||||||
|
|
||||||
console.log('🔐 Key encrypted with WebAuthn credential');
|
secureLogger.debug('Key encrypted with WebAuthn credential', { component: 'WebAuthn' });
|
||||||
return encryptedKey;
|
return encryptedKey;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
secureLogger.error('Failed to encrypt key with WebAuthn', error as Error, {
|
secureLogger.error('Failed to encrypt key with WebAuthn', error as Error, {
|
||||||
@ -256,11 +255,8 @@ export class WebAuthnService {
|
|||||||
*/
|
*/
|
||||||
private async savePBKDF2Key(encryptedKey: string, credentialId: string, securityMode: SecurityMode): Promise<void> {
|
private async savePBKDF2Key(encryptedKey: string, credentialId: string, securityMode: SecurityMode): Promise<void> {
|
||||||
try {
|
try {
|
||||||
// TEST: Log credentialId used for encryption
|
|
||||||
console.log('🔐 TEST: credentialId used for encryption:', credentialId);
|
|
||||||
|
|
||||||
const db = await this.openDatabase();
|
const db = await this.openDatabase();
|
||||||
console.log(`🔍 Available stores in ${DATABASE_CONFIG.name}:`, Array.from(db.objectStoreNames));
|
secureLogger.debug(`Available stores in ${DATABASE_CONFIG.name}`, { component: 'WebAuthn', stores: Array.from(db.objectStoreNames) });
|
||||||
const transaction = db.transaction([DATABASE_CONFIG.stores.pbkdf2keys.name], 'readwrite');
|
const transaction = db.transaction([DATABASE_CONFIG.stores.pbkdf2keys.name], 'readwrite');
|
||||||
const store = transaction.objectStore(DATABASE_CONFIG.stores.pbkdf2keys.name);
|
const store = transaction.objectStore(DATABASE_CONFIG.stores.pbkdf2keys.name);
|
||||||
|
|
||||||
@ -272,7 +268,7 @@ export class WebAuthnService {
|
|||||||
request.onerror = () => reject(request.error);
|
request.onerror = () => reject(request.error);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`🔐 PBKDF2 key stored with security mode: ${securityMode}`);
|
secureLogger.info(`PBKDF2 key stored with security mode: ${securityMode}`, { component: 'WebAuthn' });
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
secureLogger.error('Failed to save PBKDF2 key', error as Error, {
|
secureLogger.error('Failed to save PBKDF2 key', error as Error, {
|
||||||
@ -301,7 +297,7 @@ export class WebAuthnService {
|
|||||||
|
|
||||||
return result && typeof result === 'string';
|
return result && typeof result === 'string';
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(`🔍 No PBKDF2 key found for security mode: ${securityMode}`);
|
secureLogger.debug(`No PBKDF2 key found for security mode: ${securityMode}`, { component: 'WebAuthn' });
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -83,18 +83,18 @@ export class DeviceReaderService {
|
|||||||
const key = await secureCredentialsService.retrievePBKDF2Key(mode as any);
|
const key = await secureCredentialsService.retrievePBKDF2Key(mode as any);
|
||||||
if (key) {
|
if (key) {
|
||||||
pbkdf2Key = key;
|
pbkdf2Key = key;
|
||||||
console.log(`✅ DeviceReaderService: PBKDF2 key found for mode: ${mode}`);
|
secureLogger.info(`PBKDF2 key found for mode: ${mode}`, { component: 'DeviceReader' });
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Continue to next mode
|
// Continue to next mode
|
||||||
console.log(`⚠️ DeviceReaderService: No PBKDF2 key for mode ${mode}`);
|
secureLogger.debug(`No PBKDF2 key for mode ${mode}`, { component: 'DeviceReader' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pbkdf2Key) {
|
if (!pbkdf2Key) {
|
||||||
console.error('❌ DeviceReaderService: Failed to retrieve PBKDF2 key for decryption');
|
secureLogger.error('Failed to retrieve PBKDF2 key for decryption', { component: 'DeviceReader' });
|
||||||
throw new Error('PBKDF2 key not found - cannot decrypt device');
|
throw new Error('PBKDF2 key not found - cannot decrypt device');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,15 +105,15 @@ export class DeviceReaderService {
|
|||||||
pbkdf2Key
|
pbkdf2Key
|
||||||
);
|
);
|
||||||
const device: Device = JSON.parse(decryptedDeviceString);
|
const device: Device = JSON.parse(decryptedDeviceString);
|
||||||
console.log('✅ DeviceReaderService: Device decrypted successfully');
|
secureLogger.info('Device decrypted successfully', { component: 'DeviceReader' });
|
||||||
return device;
|
return device;
|
||||||
} else {
|
} else {
|
||||||
// Old plain format - return as is (should not happen in production)
|
// Old plain format - return as is (should not happen in production)
|
||||||
console.warn('⚠️ DeviceReaderService: Device found in plain format (old format)');
|
secureLogger.warn('Device found in plain format (old format)', { component: 'DeviceReader' });
|
||||||
return dbRes as Device;
|
return dbRes as Device;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('❌ DeviceReaderService: Error reading device:', error);
|
secureLogger.error('Error reading device:', error as Error, { component: 'DeviceReader' });
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -72,8 +72,7 @@ export default class IframePairingService {
|
|||||||
// Get the service instance to access the generated words
|
// Get the service instance to access the generated words
|
||||||
const service = await Services.getInstance();
|
const service = await Services.getInstance();
|
||||||
const _device = service.dumpDeviceFromMemory();
|
const _device = service.dumpDeviceFromMemory();
|
||||||
// Use _device variable
|
secureLogger.debug('Device from memory', { component: 'IframePairing' });
|
||||||
console.log('Device from memory:', _device);
|
|
||||||
const creatorAddress = await service.getDeviceAddress();
|
const creatorAddress = await service.getDeviceAddress();
|
||||||
|
|
||||||
if (creatorAddress) {
|
if (creatorAddress) {
|
||||||
@ -91,7 +90,7 @@ export default class IframePairingService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error creating pairing:', error);
|
secureLogger.error('Error creating pairing:', error as Error, { component: 'IframePairing' });
|
||||||
this.sendMessage(MessageType.PAIRING_4WORDS_ERROR, {
|
this.sendMessage(MessageType.PAIRING_4WORDS_ERROR, {
|
||||||
error: (error as Error).message,
|
error: (error as Error).message,
|
||||||
type: 'creator',
|
type: 'creator',
|
||||||
@ -101,7 +100,7 @@ export default class IframePairingService {
|
|||||||
|
|
||||||
private async handleJoinPairing(data: { words: string }) {
|
private async handleJoinPairing(data: { words: string }) {
|
||||||
try {
|
try {
|
||||||
console.log('🔗 Joining pairing process via iframe with words:', data.words);
|
secureLogger.info('Joining pairing process via iframe', { component: 'IframePairing', hasWords: !!data.words });
|
||||||
this._isJoiner = true;
|
this._isJoiner = true;
|
||||||
|
|
||||||
// Update status
|
// Update status
|
||||||
@ -146,7 +145,7 @@ export default class IframePairingService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error joining pairing:', error);
|
secureLogger.error('Error joining pairing:', error as Error, { component: 'IframePairing' });
|
||||||
this.sendMessage(MessageType.PAIRING_4WORDS_ERROR, {
|
this.sendMessage(MessageType.PAIRING_4WORDS_ERROR, {
|
||||||
error: (error as Error).message,
|
error: (error as Error).message,
|
||||||
type: 'joiner',
|
type: 'joiner',
|
||||||
|
|||||||
@ -238,8 +238,6 @@ export class PairingService {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||||
// Use errorMessage variable
|
|
||||||
console.log('Pairing error:', errorMessage);
|
|
||||||
|
|
||||||
secureLogger.error('Failed to confirm pairing', error as Error, {
|
secureLogger.error('Failed to confirm pairing', error as Error, {
|
||||||
component: 'PairingService',
|
component: 'PairingService',
|
||||||
@ -276,8 +274,6 @@ export class PairingService {
|
|||||||
return { success: true, data: result };
|
return { success: true, data: result };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||||
// Use errorMessage variable
|
|
||||||
console.log('Pairing error:', errorMessage);
|
|
||||||
|
|
||||||
secureLogger.error('Failed to cancel pairing', error as Error, {
|
secureLogger.error('Failed to cancel pairing', error as Error, {
|
||||||
component: 'PairingService',
|
component: 'PairingService',
|
||||||
@ -350,8 +346,6 @@ export class PairingService {
|
|||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||||
// Use errorMessage variable
|
|
||||||
console.log('Pairing error:', errorMessage);
|
|
||||||
|
|
||||||
secureLogger.error('Failed to delete secure credentials', error as Error, {
|
secureLogger.error('Failed to delete secure credentials', error as Error, {
|
||||||
component: 'PairingService',
|
component: 'PairingService',
|
||||||
|
|||||||
@ -149,7 +149,7 @@ export class PerformanceMonitor {
|
|||||||
getAllMetrics(): Record<string, PerformanceStats> {
|
getAllMetrics(): Record<string, PerformanceStats> {
|
||||||
const result: Record<string, PerformanceStats> = {};
|
const result: Record<string, PerformanceStats> = {};
|
||||||
|
|
||||||
this.metrics.forEach((values, name) => {
|
this.metrics.forEach((_values, name) => {
|
||||||
const stats = this.getMetricStats(name);
|
const stats = this.getMetricStats(name);
|
||||||
if (stats) {
|
if (stats) {
|
||||||
result[name] = stats;
|
result[name] = stats;
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { secureLogger } from '../services/secure-logger';
|
||||||
|
|
||||||
interface INotification {
|
interface INotification {
|
||||||
id: number;
|
id: number;
|
||||||
title: string;
|
title: string;
|
||||||
@ -80,7 +82,7 @@ class NotificationStore {
|
|||||||
`;
|
`;
|
||||||
notifElement.onclick = () => {
|
notifElement.onclick = () => {
|
||||||
// Chat functionality removed
|
// Chat functionality removed
|
||||||
console.warn('Chat functionality has been removed');
|
secureLogger.warn('Chat functionality has been removed', { component: 'NotificationStore' });
|
||||||
this.removeNotification(index);
|
this.removeNotification(index);
|
||||||
};
|
};
|
||||||
board.appendChild(notifElement);
|
board.appendChild(notifElement);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user