const { query } = require('../database/db'); const { hashApiKey, generateApiKey } = require('../middleware/auth'); class ApiKey { /** * Create a new API key * @param {object} keyData - Key data * @returns {object} - Created key with plain key (shown once) */ static async create(keyData) { try { const { name, description, createdBy, expiresAt, rateLimit, allowedIps } = keyData; const key = generateApiKey(); const keyHash = hashApiKey(key); const id = 'apk_' + Date.now(); await query(` INSERT INTO api_keys ( id, key_hash, name, description, created_by, expires_at, rate_limit, allowed_ips ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) `, [ id, keyHash, name, description || null, createdBy || null, expiresAt || null, rateLimit || 1000, allowedIps || null ]); // Return the plain key ONCE (never stored) return { id, key, // Plain key - show only once name, createdAt: new Date().toISOString() }; } catch (error) { console.error('Error creating API key:', error); throw error; } } /** * Get all API keys (without plain keys) * @returns {array} - All API keys */ static async getAll() { try { const result = await query(` SELECT id, name, description, created_by, is_active, created_at, last_used_at, expires_at, rate_limit FROM api_keys ORDER BY created_at DESC `, []); return result.rows.map(this.formatRecord); } catch (error) { console.error('Error getting all API keys:', error); throw error; } } /** * Get API key by ID * @param {string} id - Key ID * @returns {object|null} - API key or null */ static async getById(id) { try { const result = await query(` SELECT id, name, description, created_by, is_active, created_at, last_used_at, expires_at, rate_limit, allowed_ips FROM api_keys WHERE id = $1 `, [id]); if (result.rows.length === 0) return null; return this.formatRecord(result.rows[0]); } catch (error) { console.error('Error getting API key by ID:', error); throw error; } } /** * Update API key status (activate/deactivate) * @param {string} id - Key ID * @param {boolean} isActive - Active status * @returns {object|null} - Updated key or null */ static async updateStatus(id, isActive) { try { const result = await query('UPDATE api_keys SET is_active = $1 WHERE id = $2', [isActive ? 1 : 0, id]); if (result.rowCount === 0) return null; return this.getById(id); } catch (error) { console.error('Error updating API key status:', error); throw error; } } /** * Delete an API key * @param {string} id - Key ID * @returns {boolean} - True if deleted */ static async delete(id) { try { const result = await query('DELETE FROM api_keys WHERE id = $1', [id]); return result.rowCount > 0; } catch (error) { console.error('Error deleting API key:', error); throw error; } } /** * Format database record to camelCase * @param {object} record - Database record * @returns {object} - Formatted record */ static formatRecord(record) { return { id: record.id, name: record.name, description: record.description, createdBy: record.created_by, isActive: Boolean(record.is_active), createdAt: record.created_at, lastUsedAt: record.last_used_at, expiresAt: record.expires_at, rateLimit: record.rate_limit, allowedIps: record.allowed_ips }; } } module.exports = ApiKey;