feat: 인증 미들웨어 적용 및 화면 그룹 삭제 로직 개선
- 모든 라우트에 인증 미들웨어를 적용하여 보안을 강화하였습니다. - 화면 그룹 삭제 시 회사 코드 확인 및 권한 체크 로직을 추가하여, 다른 회사의 그룹 삭제를 방지하였습니다. - 채번 규칙, 카테고리 값, 테이블 타입 컬럼 복제 시 같은 회사로 복제하는 경우 경고 메시지를 추가하였습니다. - 메뉴 URL 업데이트 기능을 추가하여 복제된 화면 ID에 맞게 URL을 재매핑하도록 하였습니다.
This commit is contained in:
@@ -5,9 +5,13 @@
|
||||
import { Router, Request, Response } from "express";
|
||||
import { categoryTreeService, CreateCategoryValueInput, UpdateCategoryValueInput } from "../services/categoryTreeService";
|
||||
import { logger } from "../utils/logger";
|
||||
import { authenticateToken } from "../middleware/authMiddleware";
|
||||
|
||||
const router = Router();
|
||||
|
||||
// 모든 라우트에 인증 미들웨어 적용
|
||||
router.use(authenticateToken);
|
||||
|
||||
// 인증된 사용자 타입
|
||||
interface AuthenticatedRequest extends Request {
|
||||
user?: {
|
||||
|
||||
@@ -308,18 +308,42 @@ export const deleteScreenGroup = async (req: AuthenticatedRequest, res: Response
|
||||
|
||||
await client.query('BEGIN');
|
||||
|
||||
// 1. 삭제할 그룹과 하위 그룹 ID 수집 (CASCADE 삭제 대상)
|
||||
// 0. 삭제할 그룹의 company_code 확인
|
||||
const targetGroupResult = await client.query(
|
||||
`SELECT company_code FROM screen_groups WHERE id = $1`,
|
||||
[id]
|
||||
);
|
||||
if (targetGroupResult.rows.length === 0) {
|
||||
await client.query('ROLLBACK');
|
||||
return res.status(404).json({ success: false, message: "화면 그룹을 찾을 수 없습니다." });
|
||||
}
|
||||
const targetCompanyCode = targetGroupResult.rows[0].company_code;
|
||||
|
||||
// 권한 체크: 최고관리자가 아닌 경우 자신의 회사 그룹만 삭제 가능
|
||||
if (companyCode !== "*" && targetCompanyCode !== companyCode) {
|
||||
await client.query('ROLLBACK');
|
||||
return res.status(403).json({ success: false, message: "권한이 없습니다." });
|
||||
}
|
||||
|
||||
// 1. 삭제할 그룹과 하위 그룹 ID 수집 (같은 회사만 - CASCADE 삭제 대상)
|
||||
const childGroupsResult = await client.query(`
|
||||
WITH RECURSIVE child_groups AS (
|
||||
SELECT id FROM screen_groups WHERE id = $1
|
||||
SELECT id, company_code FROM screen_groups WHERE id = $1 AND company_code = $2
|
||||
UNION ALL
|
||||
SELECT sg.id FROM screen_groups sg
|
||||
JOIN child_groups cg ON sg.parent_group_id = cg.id
|
||||
SELECT sg.id, sg.company_code FROM screen_groups sg
|
||||
JOIN child_groups cg ON sg.parent_group_id = cg.id AND sg.company_code = cg.company_code
|
||||
)
|
||||
SELECT id FROM child_groups
|
||||
`, [id]);
|
||||
`, [id, targetCompanyCode]);
|
||||
const groupIdsToDelete = childGroupsResult.rows.map((r: any) => r.id);
|
||||
|
||||
logger.info("화면 그룹 삭제 대상", {
|
||||
companyCode,
|
||||
targetCompanyCode,
|
||||
groupId: id,
|
||||
childGroupIds: groupIdsToDelete
|
||||
});
|
||||
|
||||
// 2. menu_info에서 삭제될 screen_group 참조를 NULL로 정리
|
||||
if (groupIdsToDelete.length > 0) {
|
||||
await client.query(`
|
||||
@@ -329,18 +353,11 @@ export const deleteScreenGroup = async (req: AuthenticatedRequest, res: Response
|
||||
`, [groupIdsToDelete]);
|
||||
}
|
||||
|
||||
// 3. screen_groups 삭제
|
||||
let query = `DELETE FROM screen_groups WHERE id = $1`;
|
||||
const params: any[] = [id];
|
||||
|
||||
if (companyCode !== "*") {
|
||||
query += ` AND company_code = $2`;
|
||||
params.push(companyCode);
|
||||
}
|
||||
|
||||
query += " RETURNING id";
|
||||
|
||||
const result = await client.query(query, params);
|
||||
// 3. screen_groups 삭제 (해당 그룹만 - 하위 그룹은 프론트엔드에서 순차 삭제)
|
||||
const result = await client.query(
|
||||
`DELETE FROM screen_groups WHERE id = $1 AND company_code = $2 RETURNING id`,
|
||||
[id, targetCompanyCode]
|
||||
);
|
||||
|
||||
if (result.rows.length === 0) {
|
||||
await client.query('ROLLBACK');
|
||||
@@ -349,7 +366,7 @@ export const deleteScreenGroup = async (req: AuthenticatedRequest, res: Response
|
||||
|
||||
await client.query('COMMIT');
|
||||
|
||||
logger.info("화면 그룹 삭제", { companyCode, groupId: id, cleanedRefs: groupIdsToDelete.length });
|
||||
logger.info("화면 그룹 삭제 완료", { companyCode, targetCompanyCode, groupId: id, cleanedRefs: groupIdsToDelete.length });
|
||||
|
||||
res.json({ success: true, message: "화면 그룹이 삭제되었습니다." });
|
||||
} catch (error: any) {
|
||||
|
||||
Reference in New Issue
Block a user