From affb6899cc2a04468324556108e51b0a70008e8f Mon Sep 17 00:00:00 2001 From: leeheejin Date: Tue, 23 Sep 2025 16:05:30 +0900 Subject: [PATCH] =?UTF-8?q?=EC=88=98=EC=A0=95=ED=95=A0=EB=95=8C=20?= =?UTF-8?q?=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=20=ED=8B=80=EB=A6=AC?= =?UTF-8?q?=EB=A9=B4=20=EC=97=B0=EA=B2=B0=EC=95=88=EB=90=98=EA=B2=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/routes/externalDbConnectionRoutes.ts | 4 +- .../services/externalDbConnectionService.ts | 49 ++++++++++++++++--- .../admin/ExternalDbConnectionModal.tsx | 2 +- frontend/lib/api/externalDbConnection.ts | 5 +- 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/backend-node/src/routes/externalDbConnectionRoutes.ts b/backend-node/src/routes/externalDbConnectionRoutes.ts index d008293c..950e6c25 100644 --- a/backend-node/src/routes/externalDbConnectionRoutes.ts +++ b/backend-node/src/routes/externalDbConnectionRoutes.ts @@ -262,7 +262,9 @@ router.post( }); } - const result = await ExternalDbConnectionService.testConnectionById(id); + // 테스트용 비밀번호가 제공된 경우 사용 + const testData = req.body.password ? { password: req.body.password } : undefined; + const result = await ExternalDbConnectionService.testConnectionById(id, testData); return res.status(200).json({ success: result.success, diff --git a/backend-node/src/services/externalDbConnectionService.ts b/backend-node/src/services/externalDbConnectionService.ts index bd9f8e86..b41b9be7 100644 --- a/backend-node/src/services/externalDbConnectionService.ts +++ b/backend-node/src/services/externalDbConnectionService.ts @@ -239,13 +239,43 @@ export class ExternalDbConnectionService { } } + // 비밀번호가 변경되는 경우, 연결 테스트 먼저 수행 + if (data.password && data.password !== "***ENCRYPTED***") { + // 임시 연결 설정으로 테스트 + const testConfig = { + host: data.host || existingConnection.host, + port: data.port || existingConnection.port, + database: data.database_name || existingConnection.database_name, + user: data.username || existingConnection.username, + password: data.password, // 새로 입력된 비밀번호로 테스트 + connectionTimeoutMillis: data.connection_timeout != null ? data.connection_timeout * 1000 : undefined, + queryTimeoutMillis: data.query_timeout != null ? data.query_timeout * 1000 : undefined, + ssl: (data.ssl_enabled || existingConnection.ssl_enabled) === "Y" ? { rejectUnauthorized: false } : false + }; + + // 연결 테스트 수행 + const testResult = await DbConnectionManager.testConnection( + id, + existingConnection.db_type, + testConfig + ); + + if (!testResult.success) { + return { + success: false, + message: "새로운 연결 정보로 테스트에 실패했습니다. 수정할 수 없습니다.", + error: testResult.error ? `${testResult.error.code}: ${testResult.error.details}` : undefined + }; + } + } + // 업데이트 데이터 준비 const updateData: any = { ...data, updated_date: new Date(), }; - // 비밀번호가 변경된 경우 암호화 + // 비밀번호가 변경된 경우 암호화 (연결 테스트 통과 후) if (data.password && data.password !== "***ENCRYPTED***") { updateData.password = PasswordEncryption.encrypt(data.password); } else { @@ -320,7 +350,8 @@ export class ExternalDbConnectionService { * 데이터베이스 연결 테스트 (ID 기반) */ static async testConnectionById( - id: number + id: number, + testData?: { password?: string } ): Promise { try { // 저장된 연결 정보 조회 @@ -339,9 +370,15 @@ export class ExternalDbConnectionService { }; } - // 비밀번호 복호화 - const decryptedPassword = await this.getDecryptedPassword(id); - if (!decryptedPassword) { + // 비밀번호 결정 (테스트용 비밀번호가 제공된 경우 그것을 사용, 아니면 저장된 비밀번호 복호화) + let password: string | null; + if (testData?.password) { + password = testData.password; + } else { + password = await this.getDecryptedPassword(id); + } + + if (!password) { return { success: false, message: "비밀번호 복호화에 실패했습니다.", @@ -358,7 +395,7 @@ export class ExternalDbConnectionService { port: connection.port, database: connection.database_name, user: connection.username, - password: decryptedPassword, + password: password, connectionTimeoutMillis: connection.connection_timeout != null ? connection.connection_timeout * 1000 : undefined, queryTimeoutMillis: connection.query_timeout != null ? connection.query_timeout * 1000 : undefined, ssl: connection.ssl_enabled === "Y" ? { rejectUnauthorized: false } : false diff --git a/frontend/components/admin/ExternalDbConnectionModal.tsx b/frontend/components/admin/ExternalDbConnectionModal.tsx index 4959f6fe..cb23768f 100644 --- a/frontend/components/admin/ExternalDbConnectionModal.tsx +++ b/frontend/components/admin/ExternalDbConnectionModal.tsx @@ -221,7 +221,7 @@ export const ExternalDbConnectionModal: React.FC return; } - const result = await ExternalDbConnectionAPI.testConnection(connection.id); + const result = await ExternalDbConnectionAPI.testConnection(connection.id, formData.password); setTestResult(result); if (result.success) { diff --git a/frontend/lib/api/externalDbConnection.ts b/frontend/lib/api/externalDbConnection.ts index ca6911db..d553a66f 100644 --- a/frontend/lib/api/externalDbConnection.ts +++ b/frontend/lib/api/externalDbConnection.ts @@ -205,10 +205,11 @@ export class ExternalDbConnectionAPI { /** * 데이터베이스 연결 테스트 (ID 기반) */ - static async testConnection(connectionId: number): Promise { + static async testConnection(connectionId: number, password?: string): Promise { try { const response = await apiClient.post>( - `${this.BASE_PATH}/${connectionId}/test` + `${this.BASE_PATH}/${connectionId}/test`, + password ? { password } : undefined ); if (!response.data.success) {