// 외부 DB 연결 API 라우트 // 작성일: 2024-12-17 import { Router, Response } from "express"; import { ExternalDbConnectionService } from "../services/externalDbConnectionService"; import { ExternalDbConnection, ExternalDbConnectionFilter, } from "../types/externalDbTypes"; import { authenticateToken } from "../middleware/authMiddleware"; import { AuthenticatedRequest } from "../types/auth"; const router = Router(); /** * GET /api/external-db-connections * 외부 DB 연결 목록 조회 */ router.get( "/", authenticateToken, async (req: AuthenticatedRequest, res: Response) => { try { const filter: ExternalDbConnectionFilter = { db_type: req.query.db_type as string, is_active: req.query.is_active as string, company_code: req.query.company_code as string, search: req.query.search as string, }; // 빈 값 제거 Object.keys(filter).forEach((key) => { if (!filter[key as keyof ExternalDbConnectionFilter]) { delete filter[key as keyof ExternalDbConnectionFilter]; } }); const result = await ExternalDbConnectionService.getConnections(filter); if (result.success) { return res.status(200).json(result); } else { return res.status(400).json(result); } } catch (error) { console.error("외부 DB 연결 목록 조회 오류:", error); return res.status(500).json({ success: false, message: "서버 내부 오류가 발생했습니다.", error: error instanceof Error ? error.message : "알 수 없는 오류", }); } } ); /** * GET /api/external-db-connections/:id * 특정 외부 DB 연결 조회 */ router.get( "/:id", authenticateToken, async (req: AuthenticatedRequest, res: Response) => { try { const id = parseInt(req.params.id); if (isNaN(id)) { return res.status(400).json({ success: false, message: "유효하지 않은 ID입니다.", }); } const result = await ExternalDbConnectionService.getConnectionById(id); if (result.success) { return res.status(200).json(result); } else { return res.status(404).json(result); } } catch (error) { console.error("외부 DB 연결 조회 오류:", error); return res.status(500).json({ success: false, message: "서버 내부 오류가 발생했습니다.", error: error instanceof Error ? error.message : "알 수 없는 오류", }); } } ); /** * POST /api/external-db-connections * 새 외부 DB 연결 생성 */ router.post( "/", authenticateToken, async (req: AuthenticatedRequest, res: Response) => { try { const connectionData: ExternalDbConnection = req.body; // 사용자 정보 추가 if (req.user) { connectionData.created_by = req.user.userId; connectionData.updated_by = req.user.userId; } const result = await ExternalDbConnectionService.createConnection(connectionData); if (result.success) { return res.status(201).json(result); } else { return res.status(400).json(result); } } catch (error) { console.error("외부 DB 연결 생성 오류:", error); return res.status(500).json({ success: false, message: "서버 내부 오류가 발생했습니다.", error: error instanceof Error ? error.message : "알 수 없는 오류", }); } } ); /** * PUT /api/external-db-connections/:id * 외부 DB 연결 수정 */ router.put( "/:id", authenticateToken, async (req: AuthenticatedRequest, res: Response) => { try { const id = parseInt(req.params.id); if (isNaN(id)) { return res.status(400).json({ success: false, message: "유효하지 않은 ID입니다.", }); } const updateData: Partial = req.body; // 사용자 정보 추가 if (req.user) { updateData.updated_by = req.user.userId; } const result = await ExternalDbConnectionService.updateConnection( id, updateData ); if (result.success) { return res.status(200).json(result); } else { return res.status(400).json(result); } } catch (error) { console.error("외부 DB 연결 수정 오류:", error); return res.status(500).json({ success: false, message: "서버 내부 오류가 발생했습니다.", error: error instanceof Error ? error.message : "알 수 없는 오류", }); } } ); /** * DELETE /api/external-db-connections/:id * 외부 DB 연결 삭제 (물리 삭제) */ router.delete( "/:id", authenticateToken, async (req: AuthenticatedRequest, res: Response) => { try { const id = parseInt(req.params.id); if (isNaN(id)) { return res.status(400).json({ success: false, message: "유효하지 않은 ID입니다.", }); } const result = await ExternalDbConnectionService.deleteConnection(id); if (result.success) { return res.status(200).json(result); } else { return res.status(404).json(result); } } catch (error) { console.error("외부 DB 연결 삭제 오류:", error); return res.status(500).json({ success: false, message: "서버 내부 오류가 발생했습니다.", error: error instanceof Error ? error.message : "알 수 없는 오류", }); } } ); /** * POST /api/external-db-connections/test * 데이터베이스 연결 테스트 */ router.post( "/test", authenticateToken, async (req: AuthenticatedRequest, res: Response) => { try { const testData = req.body as import("../types/externalDbTypes").ConnectionTestRequest; // 필수 필드 검증 const requiredFields = [ "db_type", "host", "port", "database_name", "username", "password", ]; const missingFields = requiredFields.filter( (field) => !testData[field as keyof typeof testData] ); if (missingFields.length > 0) { return res.status(400).json({ success: false, message: "필수 필드가 누락되었습니다.", error: { code: "MISSING_FIELDS", details: `다음 필드가 필요합니다: ${missingFields.join(", ")}`, }, }); } const result = await ExternalDbConnectionService.testConnection(testData); return res.status(200).json({ success: result.success, data: result, message: result.message, }); } catch (error) { console.error("연결 테스트 오류:", error); return res.status(500).json({ success: false, message: "연결 테스트 중 서버 오류가 발생했습니다.", error: { code: "SERVER_ERROR", details: error instanceof Error ? error.message : "알 수 없는 오류", }, }); } } ); /** * GET /api/external-db-connections/types/supported * 지원하는 DB 타입 목록 조회 */ router.get( "/types/supported", authenticateToken, async (req: AuthenticatedRequest, res: Response) => { try { const { DB_TYPE_OPTIONS, DB_TYPE_DEFAULTS } = await import( "../types/externalDbTypes" ); return res.status(200).json({ success: true, data: { types: DB_TYPE_OPTIONS, defaults: DB_TYPE_DEFAULTS, }, message: "지원하는 DB 타입 목록을 조회했습니다.", }); } catch (error) { console.error("DB 타입 목록 조회 오류:", error); return res.status(500).json({ success: false, message: "서버 내부 오류가 발생했습니다.", error: error instanceof Error ? error.message : "알 수 없는 오류", }); } } ); export default router;