import express from 'express'; import { ApiKeyService } from '../../services/ApiKeyService'; import { validateApiKey } from '../../middleware/auth/validateApiKey'; import { requireMasterKey } from '../../middleware/auth/requireMasterKey'; const router = express.Router(); const apiKeyService = new ApiKeyService(); // All admin routes require master key router.use(validateApiKey); router.use(requireMasterKey); /** * Create a new API key * POST /api/admin/keys */ router.post('/', async (req, res) => { try { const { type, projectId, name, expiresInDays } = req.body; // Validation if (!type || !['master', 'project'].includes(type)) { return res.status(400).json({ error: 'Invalid type', message: 'Type must be either "master" or "project"', }); } if (type === 'project' && !projectId) { return res.status(400).json({ error: 'Missing projectId', message: 'Project keys require a projectId', }); } // Create key const result = type === 'master' ? await apiKeyService.createMasterKey(name, req.apiKey!.id) : await apiKeyService.createProjectKey( projectId, name, req.apiKey!.id, expiresInDays || 90 ); console.log(`[${new Date().toISOString()}] New API key created by admin: ${result.metadata.id} (${result.metadata.keyType}) - by: ${req.apiKey!.id}`); res.status(201).json({ apiKey: result.key, metadata: { id: result.metadata.id, type: result.metadata.keyType, projectId: result.metadata.projectId, name: result.metadata.name, expiresAt: result.metadata.expiresAt, scopes: result.metadata.scopes, createdAt: result.metadata.createdAt, }, message: 'IMPORTANT: Save this key securely. You will not see it again!', }); } catch (error) { console.error(`[${new Date().toISOString()}] Error creating API key:`, error); res.status(500).json({ error: 'Failed to create API key', message: 'An error occurred while creating the key', }); } }); /** * List all API keys * GET /api/admin/keys */ router.get('/', async (req, res) => { try { const keys = await apiKeyService.listKeys(); // Don't expose key hashes const safeKeys = keys.map(key => ({ id: key.id, type: key.keyType, projectId: key.projectId, name: key.name, scopes: key.scopes, isActive: key.isActive, createdAt: key.createdAt, expiresAt: key.expiresAt, lastUsedAt: key.lastUsedAt, createdBy: key.createdBy, })); res.json({ keys: safeKeys, total: safeKeys.length, }); } catch (error) { console.error(`[${new Date().toISOString()}] Error listing API keys:`, error); res.status(500).json({ error: 'Failed to list keys', message: 'An error occurred while fetching keys', }); } }); /** * Revoke an API key * DELETE /api/admin/keys/:keyId */ router.delete('/:keyId', async (req, res) => { try { const { keyId } = req.params; const success = await apiKeyService.revokeKey(keyId); if (!success) { return res.status(404).json({ error: 'Key not found', message: 'The specified API key does not exist', }); } console.log(`[${new Date().toISOString()}] API key revoked: ${keyId} - by: ${req.apiKey!.id}`); res.json({ message: 'API key revoked successfully', keyId, }); } catch (error) { console.error(`[${new Date().toISOString()}] Error revoking API key:`, error); res.status(500).json({ error: 'Failed to revoke key', message: 'An error occurred while revoking the key', }); } }); export default router;