Enhance user management with SUPER_ADMIN access control
- Updated the user list retrieval logic to ensure proper filtering based on company codes, enhancing security for user data access. - Implemented checks to restrict access to company management APIs, allowing only SUPER_ADMIN users to perform actions related to company data. - Adjusted the user interface to reflect access restrictions for non-SUPER_ADMIN users, providing clear feedback when access is denied. These changes strengthen the integrity of user management and ensure that sensitive company information is only accessible to authorized personnel.
This commit is contained in:
@@ -237,7 +237,7 @@ export const getUserList = async (req: AuthenticatedRequest, res: Response) => {
|
||||
|
||||
// 회사 코드 필터 (권한 그룹 멤버 관리 시 사용)
|
||||
if (companyCode && typeof companyCode === "string" && companyCode.trim()) {
|
||||
whereConditions.push(`company_code = $${paramIndex}`);
|
||||
whereConditions.push(`u.company_code = $${paramIndex}`);
|
||||
queryParams.push(companyCode.trim());
|
||||
paramIndex++;
|
||||
logger.info("회사 코드 필터 적용", { companyCode });
|
||||
@@ -246,7 +246,7 @@ export const getUserList = async (req: AuthenticatedRequest, res: Response) => {
|
||||
// 최고 관리자 필터링 (회사 관리자와 일반 사용자는 최고 관리자를 볼 수 없음)
|
||||
if (req.user && req.user.companyCode !== "*") {
|
||||
// 최고 관리자가 아닌 경우, company_code가 "*"인 사용자는 제외
|
||||
whereConditions.push(`company_code != '*'`);
|
||||
whereConditions.push(`u.company_code != '*'`);
|
||||
logger.info("최고 관리자 필터링 적용", {
|
||||
userCompanyCode: req.user.companyCode,
|
||||
});
|
||||
@@ -259,15 +259,15 @@ export const getUserList = async (req: AuthenticatedRequest, res: Response) => {
|
||||
const searchTerm = search.trim();
|
||||
|
||||
whereConditions.push(`(
|
||||
sabun ILIKE $${paramIndex} OR
|
||||
user_type_name ILIKE $${paramIndex} OR
|
||||
dept_name ILIKE $${paramIndex} OR
|
||||
position_name ILIKE $${paramIndex} OR
|
||||
user_id ILIKE $${paramIndex} OR
|
||||
user_name ILIKE $${paramIndex} OR
|
||||
tel ILIKE $${paramIndex} OR
|
||||
cell_phone ILIKE $${paramIndex} OR
|
||||
email ILIKE $${paramIndex}
|
||||
u.sabun ILIKE $${paramIndex} OR
|
||||
u.user_type_name ILIKE $${paramIndex} OR
|
||||
u.dept_name ILIKE $${paramIndex} OR
|
||||
u.position_name ILIKE $${paramIndex} OR
|
||||
u.user_id ILIKE $${paramIndex} OR
|
||||
u.user_name ILIKE $${paramIndex} OR
|
||||
u.tel ILIKE $${paramIndex} OR
|
||||
u.cell_phone ILIKE $${paramIndex} OR
|
||||
u.email ILIKE $${paramIndex}
|
||||
)`);
|
||||
queryParams.push(`%${searchTerm}%`);
|
||||
paramIndex++;
|
||||
@@ -277,21 +277,21 @@ export const getUserList = async (req: AuthenticatedRequest, res: Response) => {
|
||||
// 단일 필드 검색
|
||||
searchType = "single";
|
||||
const fieldMap: { [key: string]: string } = {
|
||||
sabun: "sabun",
|
||||
companyName: "user_type_name",
|
||||
deptName: "dept_name",
|
||||
positionName: "position_name",
|
||||
userId: "user_id",
|
||||
userName: "user_name",
|
||||
tel: "tel",
|
||||
cellPhone: "cell_phone",
|
||||
email: "email",
|
||||
sabun: "u.sabun",
|
||||
companyName: "u.user_type_name",
|
||||
deptName: "u.dept_name",
|
||||
positionName: "u.position_name",
|
||||
userId: "u.user_id",
|
||||
userName: "u.user_name",
|
||||
tel: "u.tel",
|
||||
cellPhone: "u.cell_phone",
|
||||
email: "u.email",
|
||||
};
|
||||
|
||||
if (fieldMap[searchField as string]) {
|
||||
if (searchField === "tel") {
|
||||
whereConditions.push(
|
||||
`(tel ILIKE $${paramIndex} OR cell_phone ILIKE $${paramIndex})`
|
||||
`(u.tel ILIKE $${paramIndex} OR u.cell_phone ILIKE $${paramIndex})`
|
||||
);
|
||||
queryParams.push(`%${searchValue}%`);
|
||||
paramIndex++;
|
||||
@@ -307,13 +307,13 @@ export const getUserList = async (req: AuthenticatedRequest, res: Response) => {
|
||||
} else {
|
||||
// 고급 검색 (개별 필드별 AND 조건)
|
||||
const advancedSearchFields = [
|
||||
{ param: search_sabun, field: "sabun" },
|
||||
{ param: search_companyName, field: "user_type_name" },
|
||||
{ param: search_deptName, field: "dept_name" },
|
||||
{ param: search_positionName, field: "position_name" },
|
||||
{ param: search_userId, field: "user_id" },
|
||||
{ param: search_userName, field: "user_name" },
|
||||
{ param: search_email, field: "email" },
|
||||
{ param: search_sabun, field: "u.sabun" },
|
||||
{ param: search_companyName, field: "u.user_type_name" },
|
||||
{ param: search_deptName, field: "u.dept_name" },
|
||||
{ param: search_positionName, field: "u.position_name" },
|
||||
{ param: search_userId, field: "u.user_id" },
|
||||
{ param: search_userName, field: "u.user_name" },
|
||||
{ param: search_email, field: "u.email" },
|
||||
];
|
||||
|
||||
let hasAdvancedSearch = false;
|
||||
@@ -330,7 +330,7 @@ export const getUserList = async (req: AuthenticatedRequest, res: Response) => {
|
||||
// 전화번호 검색
|
||||
if (search_tel && typeof search_tel === "string" && search_tel.trim()) {
|
||||
whereConditions.push(
|
||||
`(tel ILIKE $${paramIndex} OR cell_phone ILIKE $${paramIndex})`
|
||||
`(u.tel ILIKE $${paramIndex} OR u.cell_phone ILIKE $${paramIndex})`
|
||||
);
|
||||
queryParams.push(`%${search_tel.trim()}%`);
|
||||
paramIndex++;
|
||||
@@ -354,7 +354,7 @@ export const getUserList = async (req: AuthenticatedRequest, res: Response) => {
|
||||
|
||||
// 현재 로그인한 사용자의 회사 코드 필터 (슈퍼관리자가 아닌 경우)
|
||||
if (req.user && req.user.companyCode !== "*" && !companyCode) {
|
||||
whereConditions.push(`company_code = $${paramIndex}`);
|
||||
whereConditions.push(`u.company_code = $${paramIndex}`);
|
||||
queryParams.push(req.user.companyCode);
|
||||
paramIndex++;
|
||||
logger.info("사용자 회사 코드 필터 적용", {
|
||||
@@ -364,13 +364,13 @@ export const getUserList = async (req: AuthenticatedRequest, res: Response) => {
|
||||
|
||||
// 기존 필터들
|
||||
if (deptCode) {
|
||||
whereConditions.push(`dept_code = $${paramIndex}`);
|
||||
whereConditions.push(`u.dept_code = $${paramIndex}`);
|
||||
queryParams.push(deptCode);
|
||||
paramIndex++;
|
||||
}
|
||||
|
||||
if (status) {
|
||||
whereConditions.push(`status = $${paramIndex}`);
|
||||
whereConditions.push(`u.status = $${paramIndex}`);
|
||||
queryParams.push(status);
|
||||
paramIndex++;
|
||||
}
|
||||
@@ -383,7 +383,7 @@ export const getUserList = async (req: AuthenticatedRequest, res: Response) => {
|
||||
// 총 개수 조회
|
||||
const countQuery = `
|
||||
SELECT COUNT(*) as total
|
||||
FROM user_info
|
||||
FROM user_info u
|
||||
${whereClause}
|
||||
`;
|
||||
const countResult = await query<{ total: string }>(countQuery, queryParams);
|
||||
@@ -394,26 +394,28 @@ export const getUserList = async (req: AuthenticatedRequest, res: Response) => {
|
||||
const offset = (Number(page) - 1) * limit;
|
||||
const usersQuery = `
|
||||
SELECT
|
||||
sabun,
|
||||
user_id,
|
||||
user_name,
|
||||
user_name_eng,
|
||||
dept_code,
|
||||
dept_name,
|
||||
position_code,
|
||||
position_name,
|
||||
email,
|
||||
tel,
|
||||
cell_phone,
|
||||
user_type,
|
||||
user_type_name,
|
||||
regdate,
|
||||
status,
|
||||
company_code,
|
||||
locale
|
||||
FROM user_info
|
||||
u.sabun,
|
||||
u.user_id,
|
||||
u.user_name,
|
||||
u.user_name_eng,
|
||||
u.dept_code,
|
||||
u.dept_name,
|
||||
u.position_code,
|
||||
u.position_name,
|
||||
u.email,
|
||||
u.tel,
|
||||
u.cell_phone,
|
||||
u.user_type,
|
||||
u.user_type_name,
|
||||
u.regdate,
|
||||
u.status,
|
||||
u.company_code,
|
||||
u.locale,
|
||||
c.company_name
|
||||
FROM user_info u
|
||||
LEFT JOIN company_mng c ON u.company_code = c.company_code
|
||||
${whereClause}
|
||||
ORDER BY regdate DESC, user_name ASC
|
||||
ORDER BY u.regdate DESC, u.user_name ASC
|
||||
LIMIT $${paramIndex} OFFSET $${paramIndex + 1}
|
||||
`;
|
||||
|
||||
@@ -436,6 +438,7 @@ export const getUserList = async (req: AuthenticatedRequest, res: Response) => {
|
||||
userTypeName: user.user_type_name || null,
|
||||
status: user.status || "active",
|
||||
companyCode: user.company_code || null,
|
||||
companyName: user.company_name || null,
|
||||
locale: user.locale || null,
|
||||
regDate: user.regdate
|
||||
? new Date(user.regdate).toISOString().split("T")[0]
|
||||
|
||||
Reference in New Issue
Block a user