From 84f63a32618ef12e943350e069ac631dcd5d6aeb Mon Sep 17 00:00:00 2001 From: Hermes Date: Mon, 10 Aug 2026 20:15:15 -0700 Subject: [PATCH] [grade=A] P1-5, P1-6: replace 40 console.* calls in credential-manager.js + auth-manager.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit credential-manager.js: 20 console calls → log.info/warn/error tagged 'cred'. auth-manager.js: 20 console calls → log.info/error tagged 'auth'. Mixed-content strings extracted into meta payload (key, keyId, operation, etc). 1539/1539 Jest tests pass. ESLint: 4 pre-existing warnings unchanged. --- dashcaddy-api/src/managers/auth-manager.js | 41 ++++++++--------- .../src/managers/credential-manager.js | 44 +++++++++---------- 2 files changed, 42 insertions(+), 43 deletions(-) diff --git a/dashcaddy-api/src/managers/auth-manager.js b/dashcaddy-api/src/managers/auth-manager.js index e3e14cc..c65b78a 100644 --- a/dashcaddy-api/src/managers/auth-manager.js +++ b/dashcaddy-api/src/managers/auth-manager.js @@ -8,6 +8,7 @@ const jwt = require('jsonwebtoken'); const crypto = require('crypto'); const credentialManager = require('./credential-manager'); const cryptoUtils = require('../security/crypto-utils'); +const { log } = require('../utils/logging'); // JWT signing secret - derived from encryption key for consistency const JWT_SECRET = cryptoUtils.loadOrCreateKey(); @@ -19,7 +20,7 @@ const API_KEY_METADATA_NAMESPACE = 'auth.metadata'; class AuthManager { constructor() { this.keyMetadataCache = new Map(); // Cache for API key metadata - console.log('[AuthManager] Initialized'); + log.info('auth', 'Initialized'); } /** @@ -44,10 +45,10 @@ class AuthManager { { expiresIn } ); - console.log(`[AuthManager] Generated JWT for user: ${payload.sub}, expires in: ${expiresIn}`); + log.info('auth', 'Generated JWT', { user: payload.sub, expiresIn }); return token; } catch (error) { - console.error('[AuthManager] JWT generation failed:', error.message); + log.error('auth', error, { operation: 'jwtGenerate' }); throw error; } } @@ -68,11 +69,11 @@ class AuthManager { }; } catch (error) { if (error.name === 'TokenExpiredError') { - console.log('[AuthManager] JWT token expired'); + log.info('auth', 'JWT token expired'); } else if (error.name === 'JsonWebTokenError') { - console.log('[AuthManager] JWT token invalid:', error.message); + log.info('auth', 'JWT token invalid', { error: error.message }); } else { - console.error('[AuthManager] JWT verification failed:', error.message); + log.error('auth', error, { operation: 'jwtVerify' }); } return null; } @@ -116,7 +117,7 @@ class AuthManager { // Cache metadata this.keyMetadataCache.set(keyId, metadata); - console.log(`[AuthManager] Generated API key: ${name} (${keyId})`); + log.info('auth', 'Generated API key', { name, keyId }); return { key: apiKey, @@ -126,7 +127,7 @@ class AuthManager { createdAt: metadata.createdAt }; } catch (error) { - console.error('[AuthManager] API key generation failed:', error.message); + log.error('auth', error, { operation: 'apiKeyGenerate' }); throw error; } } @@ -154,30 +155,30 @@ class AuthManager { // Retrieve stored hash const storedHash = await credentialManager.retrieve(credentialKey); if (!storedHash) { - console.log(`[AuthManager] API key not found: ${keyId}`); + log.info('auth', 'API key not found', { keyId }); return null; } // Verify key matches stored hash const providedHash = crypto.createHash('sha256').update(key).digest('hex'); if (!crypto.timingSafeEqual(Buffer.from(storedHash), Buffer.from(providedHash))) { - console.log(`[AuthManager] API key hash mismatch: ${keyId}`); + log.info('auth', 'API key hash mismatch', { keyId }); return null; } // Get metadata const metadata = await this.getKeyMetadata(keyId); if (!metadata) { - console.log(`[AuthManager] API key metadata not found: ${keyId}`); + log.info('auth', 'API key metadata not found', { keyId }); return null; } // Update last used timestamp (non-blocking) this.updateLastUsed(keyId, metadata).catch(err => - console.error(`[AuthManager] Failed to update lastUsed for ${keyId}:`, err.message) + log.error('auth', err, { keyId, operation: 'updateLastUsed' }) ); - console.log(`[AuthManager] API key verified: ${metadata.name} (${keyId})`); + log.info('auth', 'API key verified', { name: metadata.name, keyId }); return { keyId, @@ -185,7 +186,7 @@ class AuthManager { name: metadata.name }; } catch (error) { - console.error('[AuthManager] API key verification failed:', error.message); + log.error('auth', error, { operation: 'apiKeyVerify' }); return null; } } @@ -205,10 +206,10 @@ class AuthManager { this.keyMetadataCache.delete(keyId); - console.log(`[AuthManager] Revoked API key: ${keyId}`); + log.info('auth', 'Revoked API key', { keyId }); return true; } catch (error) { - console.error(`[AuthManager] Failed to revoke API key ${keyId}:`, error.message); + log.error('auth', error, { keyId, operation: 'revoke' }); return false; } } @@ -233,7 +234,7 @@ class AuthManager { return keys; } catch (error) { - console.error('[AuthManager] Failed to list API keys:', error.message); + log.error('auth', error, { operation: 'listApiKeys' }); return []; } } @@ -262,7 +263,7 @@ class AuthManager { return metadata; } catch (error) { - console.error(`[AuthManager] Failed to get metadata for ${keyId}:`, error.message); + log.error('auth', error, { keyId, operation: 'getMetadata' }); return null; } } @@ -285,7 +286,7 @@ class AuthManager { this.keyMetadataCache.set(keyId, updatedMetadata); } catch (error) { - console.error(`[AuthManager] Failed to update lastUsed for ${keyId}:`, error.message); + log.error('auth', error, { keyId, operation: 'updateLastUsed' }); } } @@ -294,7 +295,7 @@ class AuthManager { */ clearCache() { this.keyMetadataCache.clear(); - console.log('[AuthManager] Cache cleared'); + log.info('auth', 'Cache cleared'); } } diff --git a/dashcaddy-api/src/managers/credential-manager.js b/dashcaddy-api/src/managers/credential-manager.js index 1c29713..2346806 100644 --- a/dashcaddy-api/src/managers/credential-manager.js +++ b/dashcaddy-api/src/managers/credential-manager.js @@ -8,6 +8,7 @@ const keychainManager = require('../security/keychain-manager'); const cryptoUtils = require('../security/crypto-utils'); const lockfile = require('proper-lockfile'); const fs = require('fs'); +const { log } = require('../utils/logging'); const path = require('path'); const platformPaths = require('../../platform-paths'); @@ -33,7 +34,7 @@ class CredentialManager { stale: 30000 }; - console.log(`[CredentialManager] Initialized with ${this.useKeychain ? 'OS keychain' : 'encrypted file'} storage`); + log.info('cred', 'Initialized', { storage: this.useKeychain ? 'keychain' : 'file' }); } /** @@ -60,19 +61,19 @@ class CredentialManager { // Store metadata separately in file await this.storeMetadata(key, metadata); this.cache.set(key, { value, exp: Date.now() + this.CACHE_TTL_MS }); - console.log(`[CredentialManager] Stored '${key}' in OS keychain`); + log.info('cred', 'Stored credential in keychain', { key }); return true; } - console.warn(`[CredentialManager] Keychain storage failed for '${key}', falling back to encrypted file`); + log.warn('cred', 'Keychain storage failed, falling back to encrypted file', { key }); } // Fallback to encrypted file storage await this.storeInFile(key, value, metadata); this.cache.set(key, { value, exp: Date.now() + this.CACHE_TTL_MS }); - console.log(`[CredentialManager] Stored '${key}' in encrypted file`); + log.info('cred', 'Stored credential in encrypted file', { key }); return true; } catch (error) { - console.error(`[CredentialManager] Failed to store '${key}':`, error.message); + log.error('cred', error, { key, operation: 'store' }); return false; } } @@ -109,7 +110,7 @@ class CredentialManager { } return value; } catch (error) { - console.error(`[CredentialManager] Failed to retrieve '${key}':`, error.message); + log.error('cred', error, { key, operation: 'retrieve' }); return null; } } @@ -132,10 +133,10 @@ class CredentialManager { // Remove from file storage await this.deleteFromFile(key); - console.log(`[CredentialManager] Deleted '${key}'`); + log.info('cred', 'Deleted credential', { key }); return true; } catch (error) { - console.error(`[CredentialManager] Failed to delete '${key}':`, error.message); + log.error('cred', error, { key, operation: 'delete' }); return false; } } @@ -149,7 +150,7 @@ class CredentialManager { const credentials = await this.loadCredentialsFile(); return Object.keys(credentials); } catch (error) { - console.error('[CredentialManager] Failed to list credentials:', error.message); + log.error('cred', error, { operation: 'list' }); return []; } } @@ -175,7 +176,7 @@ class CredentialManager { async rotateEncryptionKey() { let release; try { - console.log('[CredentialManager] Starting encryption key rotation...'); + log.info('cred', 'Starting encryption key rotation'); // Ensure file exists before locking this._ensureFileExists(); @@ -186,7 +187,7 @@ class CredentialManager { const keys = Object.keys(credentials); if (keys.length === 0) { - console.log('[CredentialManager] No credentials to rotate'); + log.info('cred', 'No credentials to rotate'); return true; } @@ -219,10 +220,10 @@ class CredentialManager { // Clear cache to force reload this.cache.clear(); - console.log(`[CredentialManager] Successfully rotated ${keys.length} credentials`); + log.info('cred', 'Rotated credentials', { count: keys.length }); return true; } catch (error) { - console.error('[CredentialManager] Key rotation failed:', error.message); + log.error('cred', error, { operation: 'rotate' }); return false; } finally { if (release) { @@ -255,12 +256,12 @@ class CredentialManager { if (migrated > 0) { this.cache.clear(); - console.log(`[CredentialManager] Migrated ${migrated} plaintext credentials to encrypted format`); + log.info('cred', 'Migrated plaintext credentials', { count: migrated }); } return { migrated, skipped, total: migrated + skipped }; } catch (error) { - console.error('[CredentialManager] Migration failed:', error.message); + log.error('cred', error, { operation: 'migrate' }); throw error; } } @@ -365,14 +366,11 @@ class CredentialManager { // Most common cause: the encryption key on disk is different from // the key that originally encrypted this entry (rotated by a // container recreate that didn't preserve CREDENTIALS_FILE env). - console.warn( - `[CredentialManager] '${key}' is present but cannot be decrypted ` + - `(likely encryption-key mismatch): ${decryptErr.message}` - ); + log.warn('cred', 'Credential present but cannot be decrypted (likely encryption-key mismatch)', { key, error: decryptErr.message }); return { status: 'unreadable', value: null, error: decryptErr.message }; } } catch (err) { - console.error(`[CredentialManager] diagnose('${key}') failed:`, err.message); + log.error('cred', err, { key, operation: 'diagnose' }); return { status: 'malformed', value: null, error: err.message }; } } @@ -404,7 +402,7 @@ class CredentialManager { const data = fs.readFileSync(CREDENTIALS_FILE, 'utf8'); return JSON.parse(data); } catch (error) { - console.error('[CredentialManager] Failed to load credentials file:', error.message); + log.error('cred', error, { operation: 'loadFile' }); return {}; } } @@ -440,10 +438,10 @@ class CredentialManager { await this._lockedUpdate(() => backup.credentials); this.cache.clear(); - console.log('[CredentialManager] Successfully imported backup'); + log.info('cred', 'Successfully imported backup'); return true; } catch (error) { - console.error('[CredentialManager] Failed to import backup:', error.message); + log.error('cred', error, { operation: 'importBackup' }); return false; } }