Compare commits
No commits in common. "c0f2fbbd885d0f2f78020827ccf301f8744eccea" and "561d9cb855a580adacb4b11a0e5a840d985c07e6" have entirely different histories.
c0f2fbbd88
...
561d9cb855
|
|
@ -461,13 +461,12 @@ export class CommonCodeController {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 카테고리 중복 검사 (회사별)
|
* 카테고리 중복 검사
|
||||||
* GET /api/common-codes/categories/check-duplicate?field=categoryCode&value=USER_STATUS&excludeCode=OLD_CODE
|
* GET /api/common-codes/categories/check-duplicate?field=categoryCode&value=USER_STATUS&excludeCode=OLD_CODE
|
||||||
*/
|
*/
|
||||||
async checkCategoryDuplicate(req: AuthenticatedRequest, res: Response) {
|
async checkCategoryDuplicate(req: AuthenticatedRequest, res: Response) {
|
||||||
try {
|
try {
|
||||||
const { field, value, excludeCode } = req.query;
|
const { field, value, excludeCode } = req.query;
|
||||||
const userCompanyCode = req.user?.companyCode;
|
|
||||||
|
|
||||||
// 입력값 검증
|
// 입력값 검증
|
||||||
if (!field || !value) {
|
if (!field || !value) {
|
||||||
|
|
@ -489,8 +488,7 @@ export class CommonCodeController {
|
||||||
const result = await this.commonCodeService.checkCategoryDuplicate(
|
const result = await this.commonCodeService.checkCategoryDuplicate(
|
||||||
field as "categoryCode" | "categoryName" | "categoryNameEng",
|
field as "categoryCode" | "categoryName" | "categoryNameEng",
|
||||||
value as string,
|
value as string,
|
||||||
excludeCode as string,
|
excludeCode as string
|
||||||
userCompanyCode
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
|
|
@ -513,14 +511,13 @@ export class CommonCodeController {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 코드 중복 검사 (회사별)
|
* 코드 중복 검사
|
||||||
* GET /api/common-codes/categories/:categoryCode/codes/check-duplicate?field=codeValue&value=ACTIVE&excludeCode=OLD_CODE
|
* GET /api/common-codes/categories/:categoryCode/codes/check-duplicate?field=codeValue&value=ACTIVE&excludeCode=OLD_CODE
|
||||||
*/
|
*/
|
||||||
async checkCodeDuplicate(req: AuthenticatedRequest, res: Response) {
|
async checkCodeDuplicate(req: AuthenticatedRequest, res: Response) {
|
||||||
try {
|
try {
|
||||||
const { categoryCode } = req.params;
|
const { categoryCode } = req.params;
|
||||||
const { field, value, excludeCode } = req.query;
|
const { field, value, excludeCode } = req.query;
|
||||||
const userCompanyCode = req.user?.companyCode;
|
|
||||||
|
|
||||||
// 입력값 검증
|
// 입력값 검증
|
||||||
if (!field || !value) {
|
if (!field || !value) {
|
||||||
|
|
@ -543,8 +540,7 @@ export class CommonCodeController {
|
||||||
categoryCode,
|
categoryCode,
|
||||||
field as "codeValue" | "codeName" | "codeNameEng",
|
field as "codeValue" | "codeName" | "codeNameEng",
|
||||||
value as string,
|
value as string,
|
||||||
excludeCode as string,
|
excludeCode as string
|
||||||
userCompanyCode
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return res.json({
|
return res.json({
|
||||||
|
|
|
||||||
|
|
@ -87,10 +87,7 @@ router.get(
|
||||||
filter,
|
filter,
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = await ExternalDbConnectionService.getConnections(
|
const result = await ExternalDbConnectionService.getConnections(filter);
|
||||||
filter,
|
|
||||||
userCompanyCode
|
|
||||||
);
|
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
return res.status(200).json(result);
|
return res.status(200).json(result);
|
||||||
|
|
@ -322,12 +319,7 @@ router.delete(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const userCompanyCode = req.user?.companyCode;
|
const result = await ExternalDbConnectionService.deleteConnection(id);
|
||||||
|
|
||||||
const result = await ExternalDbConnectionService.deleteConnection(
|
|
||||||
id,
|
|
||||||
userCompanyCode
|
|
||||||
);
|
|
||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
return res.status(200).json(result);
|
return res.status(200).json(result);
|
||||||
|
|
@ -525,10 +517,7 @@ router.get(
|
||||||
});
|
});
|
||||||
|
|
||||||
const externalConnections =
|
const externalConnections =
|
||||||
await ExternalDbConnectionService.getConnections(
|
await ExternalDbConnectionService.getConnections(filter);
|
||||||
filter,
|
|
||||||
userCompanyCode
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!externalConnections.success) {
|
if (!externalConnections.success) {
|
||||||
return res.status(400).json(externalConnections);
|
return res.status(400).json(externalConnections);
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,8 @@ router.get(
|
||||||
company_code: req.query.company_code as string,
|
company_code: req.query.company_code as string,
|
||||||
};
|
};
|
||||||
|
|
||||||
const userCompanyCode = req.user?.companyCode;
|
const result =
|
||||||
|
await ExternalRestApiConnectionService.getConnections(filter);
|
||||||
const result = await ExternalRestApiConnectionService.getConnections(
|
|
||||||
filter,
|
|
||||||
userCompanyCode
|
|
||||||
);
|
|
||||||
|
|
||||||
return res.status(result.success ? 200 : 400).json(result);
|
return res.status(result.success ? 200 : 400).json(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -66,12 +62,8 @@ router.get(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const userCompanyCode = req.user?.companyCode;
|
const result =
|
||||||
|
await ExternalRestApiConnectionService.getConnectionById(id);
|
||||||
const result = await ExternalRestApiConnectionService.getConnectionById(
|
|
||||||
id,
|
|
||||||
userCompanyCode
|
|
||||||
);
|
|
||||||
|
|
||||||
return res.status(result.success ? 200 : 404).json(result);
|
return res.status(result.success ? 200 : 404).json(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -137,12 +129,9 @@ router.put(
|
||||||
updated_by: req.user?.userId || "system",
|
updated_by: req.user?.userId || "system",
|
||||||
};
|
};
|
||||||
|
|
||||||
const userCompanyCode = req.user?.companyCode;
|
|
||||||
|
|
||||||
const result = await ExternalRestApiConnectionService.updateConnection(
|
const result = await ExternalRestApiConnectionService.updateConnection(
|
||||||
id,
|
id,
|
||||||
data,
|
data
|
||||||
userCompanyCode
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return res.status(result.success ? 200 : 400).json(result);
|
return res.status(result.success ? 200 : 400).json(result);
|
||||||
|
|
@ -175,12 +164,8 @@ router.delete(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const userCompanyCode = req.user?.companyCode;
|
const result =
|
||||||
|
await ExternalRestApiConnectionService.deleteConnection(id);
|
||||||
const result = await ExternalRestApiConnectionService.deleteConnection(
|
|
||||||
id,
|
|
||||||
userCompanyCode
|
|
||||||
);
|
|
||||||
|
|
||||||
return res.status(result.success ? 200 : 404).json(result);
|
return res.status(result.success ? 200 : 404).json(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
|
||||||
|
|
@ -604,13 +604,12 @@ export class CommonCodeService {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 카테고리 중복 검사 (회사별)
|
* 카테고리 중복 검사
|
||||||
*/
|
*/
|
||||||
async checkCategoryDuplicate(
|
async checkCategoryDuplicate(
|
||||||
field: "categoryCode" | "categoryName" | "categoryNameEng",
|
field: "categoryCode" | "categoryName" | "categoryNameEng",
|
||||||
value: string,
|
value: string,
|
||||||
excludeCategoryCode?: string,
|
excludeCategoryCode?: string
|
||||||
userCompanyCode?: string
|
|
||||||
): Promise<{ isDuplicate: boolean; message: string }> {
|
): Promise<{ isDuplicate: boolean; message: string }> {
|
||||||
try {
|
try {
|
||||||
if (!value || !value.trim()) {
|
if (!value || !value.trim()) {
|
||||||
|
|
@ -656,12 +655,6 @@ export class CommonCodeService {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 회사별 필터링 (최고 관리자가 아닌 경우)
|
|
||||||
if (userCompanyCode && userCompanyCode !== "*") {
|
|
||||||
sql += ` AND company_code = $${paramIndex++}`;
|
|
||||||
values.push(userCompanyCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 수정 시 자기 자신 제외
|
// 수정 시 자기 자신 제외
|
||||||
if (excludeCategoryCode) {
|
if (excludeCategoryCode) {
|
||||||
sql += ` AND category_code != $${paramIndex++}`;
|
sql += ` AND category_code != $${paramIndex++}`;
|
||||||
|
|
@ -682,10 +675,6 @@ export class CommonCodeService {
|
||||||
categoryNameEng: "카테고리 영문명",
|
categoryNameEng: "카테고리 영문명",
|
||||||
};
|
};
|
||||||
|
|
||||||
logger.info(
|
|
||||||
`카테고리 중복 검사: ${field}=${value}, 회사=${userCompanyCode}, 중복=${isDuplicate}`
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isDuplicate,
|
isDuplicate,
|
||||||
message: isDuplicate
|
message: isDuplicate
|
||||||
|
|
@ -699,14 +688,13 @@ export class CommonCodeService {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 코드 중복 검사 (회사별)
|
* 코드 중복 검사
|
||||||
*/
|
*/
|
||||||
async checkCodeDuplicate(
|
async checkCodeDuplicate(
|
||||||
categoryCode: string,
|
categoryCode: string,
|
||||||
field: "codeValue" | "codeName" | "codeNameEng",
|
field: "codeValue" | "codeName" | "codeNameEng",
|
||||||
value: string,
|
value: string,
|
||||||
excludeCodeValue?: string,
|
excludeCodeValue?: string
|
||||||
userCompanyCode?: string
|
|
||||||
): Promise<{ isDuplicate: boolean; message: string }> {
|
): Promise<{ isDuplicate: boolean; message: string }> {
|
||||||
try {
|
try {
|
||||||
if (!value || !value.trim()) {
|
if (!value || !value.trim()) {
|
||||||
|
|
@ -755,12 +743,6 @@ export class CommonCodeService {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 회사별 필터링 (최고 관리자가 아닌 경우)
|
|
||||||
if (userCompanyCode && userCompanyCode !== "*") {
|
|
||||||
sql += ` AND company_code = $${paramIndex++}`;
|
|
||||||
values.push(userCompanyCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 수정 시 자기 자신 제외
|
// 수정 시 자기 자신 제외
|
||||||
if (excludeCodeValue) {
|
if (excludeCodeValue) {
|
||||||
sql += ` AND code_value != $${paramIndex++}`;
|
sql += ` AND code_value != $${paramIndex++}`;
|
||||||
|
|
@ -778,10 +760,6 @@ export class CommonCodeService {
|
||||||
codeNameEng: "코드 영문명",
|
codeNameEng: "코드 영문명",
|
||||||
};
|
};
|
||||||
|
|
||||||
logger.info(
|
|
||||||
`코드 중복 검사: ${categoryCode}.${field}=${value}, 회사=${userCompanyCode}, 중복=${isDuplicate}`
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isDuplicate,
|
isDuplicate,
|
||||||
message: isDuplicate
|
message: isDuplicate
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,7 @@ export class ExternalDbConnectionService {
|
||||||
* 외부 DB 연결 목록 조회
|
* 외부 DB 연결 목록 조회
|
||||||
*/
|
*/
|
||||||
static async getConnections(
|
static async getConnections(
|
||||||
filter: ExternalDbConnectionFilter,
|
filter: ExternalDbConnectionFilter
|
||||||
userCompanyCode?: string
|
|
||||||
): Promise<ApiResponse<ExternalDbConnection[]>> {
|
): Promise<ApiResponse<ExternalDbConnection[]>> {
|
||||||
try {
|
try {
|
||||||
// WHERE 조건 동적 생성
|
// WHERE 조건 동적 생성
|
||||||
|
|
@ -26,26 +25,6 @@ export class ExternalDbConnectionService {
|
||||||
const params: any[] = [];
|
const params: any[] = [];
|
||||||
let paramIndex = 1;
|
let paramIndex = 1;
|
||||||
|
|
||||||
// 회사별 필터링 (최고 관리자가 아닌 경우 필수)
|
|
||||||
if (userCompanyCode && userCompanyCode !== "*") {
|
|
||||||
whereConditions.push(`company_code = $${paramIndex++}`);
|
|
||||||
params.push(userCompanyCode);
|
|
||||||
logger.info(`회사별 외부 DB 연결 필터링: ${userCompanyCode}`);
|
|
||||||
} else if (userCompanyCode === "*") {
|
|
||||||
logger.info(`최고 관리자: 모든 외부 DB 연결 조회`);
|
|
||||||
// 필터가 있으면 적용
|
|
||||||
if (filter.company_code) {
|
|
||||||
whereConditions.push(`company_code = $${paramIndex++}`);
|
|
||||||
params.push(filter.company_code);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// userCompanyCode가 없는 경우 (하위 호환성)
|
|
||||||
if (filter.company_code) {
|
|
||||||
whereConditions.push(`company_code = $${paramIndex++}`);
|
|
||||||
params.push(filter.company_code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 필터 조건 적용
|
// 필터 조건 적용
|
||||||
if (filter.db_type) {
|
if (filter.db_type) {
|
||||||
whereConditions.push(`db_type = $${paramIndex++}`);
|
whereConditions.push(`db_type = $${paramIndex++}`);
|
||||||
|
|
@ -57,6 +36,11 @@ export class ExternalDbConnectionService {
|
||||||
params.push(filter.is_active);
|
params.push(filter.is_active);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (filter.company_code) {
|
||||||
|
whereConditions.push(`company_code = $${paramIndex++}`);
|
||||||
|
params.push(filter.company_code);
|
||||||
|
}
|
||||||
|
|
||||||
// 검색 조건 적용 (연결명 또는 설명에서 검색)
|
// 검색 조건 적용 (연결명 또는 설명에서 검색)
|
||||||
if (filter.search && filter.search.trim()) {
|
if (filter.search && filter.search.trim()) {
|
||||||
whereConditions.push(
|
whereConditions.push(
|
||||||
|
|
@ -512,36 +496,23 @@ export class ExternalDbConnectionService {
|
||||||
/**
|
/**
|
||||||
* 외부 DB 연결 삭제 (물리 삭제)
|
* 외부 DB 연결 삭제 (물리 삭제)
|
||||||
*/
|
*/
|
||||||
static async deleteConnection(
|
static async deleteConnection(id: number): Promise<ApiResponse<void>> {
|
||||||
id: number,
|
|
||||||
userCompanyCode?: string
|
|
||||||
): Promise<ApiResponse<void>> {
|
|
||||||
try {
|
try {
|
||||||
let selectQuery = `SELECT id FROM external_db_connections WHERE id = $1`;
|
const existingConnection = await queryOne(
|
||||||
const selectParams: any[] = [id];
|
`SELECT id FROM external_db_connections WHERE id = $1`,
|
||||||
|
[id]
|
||||||
// 회사별 필터링 (최고 관리자가 아닌 경우)
|
);
|
||||||
if (userCompanyCode && userCompanyCode !== "*") {
|
|
||||||
selectQuery += ` AND company_code = $2`;
|
|
||||||
selectParams.push(userCompanyCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
const existingConnection = await queryOne(selectQuery, selectParams);
|
|
||||||
|
|
||||||
if (!existingConnection) {
|
if (!existingConnection) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: "해당 연결 설정을 찾을 수 없거나 권한이 없습니다.",
|
message: "해당 연결 설정을 찾을 수 없습니다.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 물리 삭제 (실제 데이터 삭제)
|
// 물리 삭제 (실제 데이터 삭제)
|
||||||
await query(`DELETE FROM external_db_connections WHERE id = $1`, [id]);
|
await query(`DELETE FROM external_db_connections WHERE id = $1`, [id]);
|
||||||
|
|
||||||
logger.info(
|
|
||||||
`외부 DB 연결 삭제: ID ${id} (회사: ${userCompanyCode || "전체"})`
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
message: "연결 설정이 삭제되었습니다.",
|
message: "연결 설정이 삭제되었습니다.",
|
||||||
|
|
@ -776,11 +747,8 @@ export class ExternalDbConnectionService {
|
||||||
try {
|
try {
|
||||||
// 보안 검증: SELECT 쿼리만 허용
|
// 보안 검증: SELECT 쿼리만 허용
|
||||||
const trimmedQuery = query.trim().toUpperCase();
|
const trimmedQuery = query.trim().toUpperCase();
|
||||||
if (!trimmedQuery.startsWith("SELECT")) {
|
if (!trimmedQuery.startsWith('SELECT')) {
|
||||||
console.log("보안 오류: SELECT가 아닌 쿼리 시도:", {
|
console.log("보안 오류: SELECT가 아닌 쿼리 시도:", { id, query: query.substring(0, 100) });
|
||||||
id,
|
|
||||||
query: query.substring(0, 100),
|
|
||||||
});
|
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: "외부 데이터베이스에서는 SELECT 쿼리만 실행할 수 있습니다.",
|
message: "외부 데이터베이스에서는 SELECT 쿼리만 실행할 수 있습니다.",
|
||||||
|
|
@ -788,32 +756,16 @@ export class ExternalDbConnectionService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 위험한 키워드 검사
|
// 위험한 키워드 검사
|
||||||
const dangerousKeywords = [
|
const dangerousKeywords = ['INSERT', 'UPDATE', 'DELETE', 'DROP', 'CREATE', 'ALTER', 'TRUNCATE', 'EXEC', 'EXECUTE', 'CALL', 'MERGE'];
|
||||||
"INSERT",
|
const hasDangerousKeyword = dangerousKeywords.some(keyword =>
|
||||||
"UPDATE",
|
|
||||||
"DELETE",
|
|
||||||
"DROP",
|
|
||||||
"CREATE",
|
|
||||||
"ALTER",
|
|
||||||
"TRUNCATE",
|
|
||||||
"EXEC",
|
|
||||||
"EXECUTE",
|
|
||||||
"CALL",
|
|
||||||
"MERGE",
|
|
||||||
];
|
|
||||||
const hasDangerousKeyword = dangerousKeywords.some((keyword) =>
|
|
||||||
trimmedQuery.includes(keyword)
|
trimmedQuery.includes(keyword)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (hasDangerousKeyword) {
|
if (hasDangerousKeyword) {
|
||||||
console.log("보안 오류: 위험한 키워드 포함 쿼리 시도:", {
|
console.log("보안 오류: 위험한 키워드 포함 쿼리 시도:", { id, query: query.substring(0, 100) });
|
||||||
id,
|
|
||||||
query: query.substring(0, 100),
|
|
||||||
});
|
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message:
|
message: "데이터를 변경하거나 삭제하는 쿼리는 허용되지 않습니다. SELECT 쿼리만 사용해주세요.",
|
||||||
"데이터를 변경하거나 삭제하는 쿼리는 허용되지 않습니다. SELECT 쿼리만 사용해주세요.",
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,7 @@ export class ExternalRestApiConnectionService {
|
||||||
* REST API 연결 목록 조회
|
* REST API 연결 목록 조회
|
||||||
*/
|
*/
|
||||||
static async getConnections(
|
static async getConnections(
|
||||||
filter: ExternalRestApiConnectionFilter = {},
|
filter: ExternalRestApiConnectionFilter = {}
|
||||||
userCompanyCode?: string
|
|
||||||
): Promise<ApiResponse<ExternalRestApiConnection[]>> {
|
): Promise<ApiResponse<ExternalRestApiConnection[]>> {
|
||||||
try {
|
try {
|
||||||
let query = `
|
let query = `
|
||||||
|
|
@ -40,27 +39,11 @@ export class ExternalRestApiConnectionService {
|
||||||
const params: any[] = [];
|
const params: any[] = [];
|
||||||
let paramIndex = 1;
|
let paramIndex = 1;
|
||||||
|
|
||||||
// 회사별 필터링 (최고 관리자가 아닌 경우 필수)
|
// 회사 코드 필터
|
||||||
if (userCompanyCode && userCompanyCode !== "*") {
|
if (filter.company_code) {
|
||||||
query += ` AND company_code = $${paramIndex}`;
|
query += ` AND company_code = $${paramIndex}`;
|
||||||
params.push(userCompanyCode);
|
params.push(filter.company_code);
|
||||||
paramIndex++;
|
paramIndex++;
|
||||||
logger.info(`회사별 REST API 연결 필터링: ${userCompanyCode}`);
|
|
||||||
} else if (userCompanyCode === "*") {
|
|
||||||
logger.info(`최고 관리자: 모든 REST API 연결 조회`);
|
|
||||||
// 필터가 있으면 적용
|
|
||||||
if (filter.company_code) {
|
|
||||||
query += ` AND company_code = $${paramIndex}`;
|
|
||||||
params.push(filter.company_code);
|
|
||||||
paramIndex++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// userCompanyCode가 없는 경우 (하위 호환성)
|
|
||||||
if (filter.company_code) {
|
|
||||||
query += ` AND company_code = $${paramIndex}`;
|
|
||||||
params.push(filter.company_code);
|
|
||||||
paramIndex++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 활성 상태 필터
|
// 활성 상태 필터
|
||||||
|
|
@ -122,11 +105,10 @@ export class ExternalRestApiConnectionService {
|
||||||
* REST API 연결 상세 조회
|
* REST API 연결 상세 조회
|
||||||
*/
|
*/
|
||||||
static async getConnectionById(
|
static async getConnectionById(
|
||||||
id: number,
|
id: number
|
||||||
userCompanyCode?: string
|
|
||||||
): Promise<ApiResponse<ExternalRestApiConnection>> {
|
): Promise<ApiResponse<ExternalRestApiConnection>> {
|
||||||
try {
|
try {
|
||||||
let query = `
|
const query = `
|
||||||
SELECT
|
SELECT
|
||||||
id, connection_name, description, base_url, default_headers,
|
id, connection_name, description, base_url, default_headers,
|
||||||
auth_type, auth_config, timeout, retry_count, retry_delay,
|
auth_type, auth_config, timeout, retry_count, retry_delay,
|
||||||
|
|
@ -136,20 +118,12 @@ export class ExternalRestApiConnectionService {
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const params: any[] = [id];
|
const result: QueryResult<any> = await pool.query(query, [id]);
|
||||||
|
|
||||||
// 회사별 필터링 (최고 관리자가 아닌 경우)
|
|
||||||
if (userCompanyCode && userCompanyCode !== "*") {
|
|
||||||
query += ` AND company_code = $2`;
|
|
||||||
params.push(userCompanyCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
const result: QueryResult<any> = await pool.query(query, params);
|
|
||||||
|
|
||||||
if (result.rows.length === 0) {
|
if (result.rows.length === 0) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: "연결을 찾을 수 없거나 권한이 없습니다.",
|
message: "연결을 찾을 수 없습니다.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -251,12 +225,11 @@ export class ExternalRestApiConnectionService {
|
||||||
*/
|
*/
|
||||||
static async updateConnection(
|
static async updateConnection(
|
||||||
id: number,
|
id: number,
|
||||||
data: Partial<ExternalRestApiConnection>,
|
data: Partial<ExternalRestApiConnection>
|
||||||
userCompanyCode?: string
|
|
||||||
): Promise<ApiResponse<ExternalRestApiConnection>> {
|
): Promise<ApiResponse<ExternalRestApiConnection>> {
|
||||||
try {
|
try {
|
||||||
// 기존 연결 확인 (회사 코드로 권한 체크)
|
// 기존 연결 확인
|
||||||
const existing = await this.getConnectionById(id, userCompanyCode);
|
const existing = await this.getConnectionById(id);
|
||||||
if (!existing.success) {
|
if (!existing.success) {
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
|
|
@ -380,38 +353,24 @@ export class ExternalRestApiConnectionService {
|
||||||
/**
|
/**
|
||||||
* REST API 연결 삭제
|
* REST API 연결 삭제
|
||||||
*/
|
*/
|
||||||
static async deleteConnection(
|
static async deleteConnection(id: number): Promise<ApiResponse<void>> {
|
||||||
id: number,
|
|
||||||
userCompanyCode?: string
|
|
||||||
): Promise<ApiResponse<void>> {
|
|
||||||
try {
|
try {
|
||||||
let query = `
|
const query = `
|
||||||
DELETE FROM external_rest_api_connections
|
DELETE FROM external_rest_api_connections
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
|
RETURNING connection_name
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const params: any[] = [id];
|
const result: QueryResult<any> = await pool.query(query, [id]);
|
||||||
|
|
||||||
// 회사별 필터링 (최고 관리자가 아닌 경우)
|
|
||||||
if (userCompanyCode && userCompanyCode !== "*") {
|
|
||||||
query += ` AND company_code = $2`;
|
|
||||||
params.push(userCompanyCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
query += ` RETURNING connection_name`;
|
|
||||||
|
|
||||||
const result: QueryResult<any> = await pool.query(query, params);
|
|
||||||
|
|
||||||
if (result.rows.length === 0) {
|
if (result.rows.length === 0) {
|
||||||
return {
|
return {
|
||||||
success: false,
|
success: false,
|
||||||
message: "연결을 찾을 수 없거나 권한이 없습니다.",
|
message: "연결을 찾을 수 없습니다.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.info(
|
logger.info(`REST API 연결 삭제 성공: ${result.rows[0].connection_name}`);
|
||||||
`REST API 연결 삭제 성공: ${result.rows[0].connection_name} (회사: ${userCompanyCode || "전체"})`
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue