// src/controllers/api-key.controller.js // API 키 컨트롤러 const { ApiKey } = require('../models'); const logger = require('../config/logger.config'); /** * API 키 발급 */ exports.create = async (req, res, next) => { try { const { name, expiresInDays, permissions } = req.body; const userId = req.user.userId; // API 키 생성 const rawKey = ApiKey.generateKey(); const keyHash = ApiKey.hashKey(rawKey); const keyPrefix = rawKey.substring(0, 12); // 만료 일시 계산 let expiresAt = null; if (expiresInDays) { expiresAt = new Date(); expiresAt.setDate(expiresAt.getDate() + expiresInDays); } const apiKey = await ApiKey.create({ userId, name, keyPrefix, keyHash, permissions: permissions || ['chat:read', 'chat:write'], expiresAt, }); logger.info(`API 키 발급: ${name} (user: ${userId})`); // 주의: 원본 키는 이 응답에서만 반환됨 (다시 조회 불가) return res.status(201).json({ success: true, data: { id: apiKey.id, name: apiKey.name, key: rawKey, // 원본 키 (한 번만 표시) keyPrefix: apiKey.keyPrefix, permissions: apiKey.permissions, expiresAt: apiKey.expiresAt, createdAt: apiKey.createdAt, message: '⚠️ API 키는 이 응답에서만 확인할 수 있습니다. 안전한 곳에 저장하세요.', }, }); } catch (error) { return next(error); } }; /** * API 키 목록 조회 */ exports.list = async (req, res, next) => { try { const userId = req.user.userId; const apiKeys = await ApiKey.findAll({ where: { userId }, attributes: [ 'id', 'name', 'keyPrefix', 'permissions', 'rateLimit', 'status', 'expiresAt', 'lastUsedAt', 'totalRequests', 'createdAt', ], order: [['createdAt', 'DESC']], }); return res.json({ success: true, data: apiKeys, }); } catch (error) { return next(error); } }; /** * API 키 상세 조회 */ exports.get = async (req, res, next) => { try { const { id } = req.params; const userId = req.user.userId; const apiKey = await ApiKey.findOne({ where: { id, userId }, attributes: [ 'id', 'name', 'keyPrefix', 'permissions', 'rateLimit', 'status', 'expiresAt', 'lastUsedAt', 'totalRequests', 'createdAt', 'updatedAt', ], }); if (!apiKey) { return res.status(404).json({ success: false, error: { code: 'API_KEY_NOT_FOUND', message: 'API 키를 찾을 수 없습니다.', }, }); } return res.json({ success: true, data: apiKey, }); } catch (error) { return next(error); } }; /** * API 키 수정 */ exports.update = async (req, res, next) => { try { const { id } = req.params; const { name, status } = req.body; const userId = req.user.userId; const apiKey = await ApiKey.findOne({ where: { id, userId }, }); if (!apiKey) { return res.status(404).json({ success: false, error: { code: 'API_KEY_NOT_FOUND', message: 'API 키를 찾을 수 없습니다.', }, }); } if (name) apiKey.name = name; if (status) apiKey.status = status; await apiKey.save(); logger.info(`API 키 수정: ${apiKey.name} (id: ${id})`); return res.json({ success: true, data: { id: apiKey.id, name: apiKey.name, keyPrefix: apiKey.keyPrefix, status: apiKey.status, updatedAt: apiKey.updatedAt, }, }); } catch (error) { return next(error); } }; /** * API 키 폐기 */ exports.revoke = async (req, res, next) => { try { const { id } = req.params; const userId = req.user.userId; const apiKey = await ApiKey.findOne({ where: { id, userId }, }); if (!apiKey) { return res.status(404).json({ success: false, error: { code: 'API_KEY_NOT_FOUND', message: 'API 키를 찾을 수 없습니다.', }, }); } apiKey.status = 'revoked'; await apiKey.save(); logger.info(`API 키 폐기: ${apiKey.name} (id: ${id})`); return res.json({ success: true, data: { message: 'API 키가 폐기되었습니다.', }, }); } catch (error) { return next(error); } };