사용자 계정 관리 API 연동 및 기능 개선
- 사용자 비밀번호 변경 API 추가 - 메뉴 권한 관리 API 추가 (조회/저장) - 인증 방법 수정 API 추가 - 사용자 권한 업데이트 API 추가 - 계정 관리 UI 컴포넌트 개선 - Docker 및 Makefile 설정 업데이트 🤖 Generated with Claude Code (https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import { UserMenuPermissionData } from '@/entities/user/model/types';
|
||||
|
||||
export enum AccountTabKeys {
|
||||
UserManage = 'UserManage',
|
||||
PasswordManage = 'PasswordManage',
|
||||
@@ -11,40 +13,53 @@ export enum AccountUserTabKeys {
|
||||
};
|
||||
export interface AccountUserTabProps {
|
||||
activeTab: AccountUserTabKeys;
|
||||
tid: string;
|
||||
mid?: string;
|
||||
usrid?: string;
|
||||
idCl?: string;
|
||||
status?: string;
|
||||
};
|
||||
export interface AuthItem {
|
||||
useYn?: boolean;
|
||||
authName?: string;
|
||||
tid?: string;
|
||||
};
|
||||
|
||||
export interface UserManageAuthListProps {
|
||||
userItems: Array<any>;
|
||||
userItems: Array<UserManageAuthItemProps>;
|
||||
mid: string;
|
||||
};
|
||||
export interface UserManageAuthItemProps extends AuthItem {
|
||||
export interface UserManageAuthItemProps {
|
||||
usrid?: string;
|
||||
mid?: string;
|
||||
idCl?: string;
|
||||
status?: string;
|
||||
};
|
||||
export interface UserLoginAuthInfoWrapProps {
|
||||
mid: string;
|
||||
usrid: string;
|
||||
};
|
||||
export interface UserAccountAuthWrapProps {
|
||||
tid: string;
|
||||
mid: string;
|
||||
usrid: string;
|
||||
idCl: string;
|
||||
status: string;
|
||||
};
|
||||
export interface PermItem {
|
||||
menuId?: string;
|
||||
permName?: string;
|
||||
menuName?: string;
|
||||
subMenu?: Array<PermItem>;
|
||||
};
|
||||
export interface UserAccountAuthPermListProps {
|
||||
tid: string;
|
||||
permItems: Array<PermItem>;
|
||||
mid: string;
|
||||
usrid: string;
|
||||
idCl: string;
|
||||
status: string;
|
||||
menuItems: Array<PermItem>;
|
||||
menuGrants: Array<UserMenuPermissionData>;
|
||||
};
|
||||
export interface UserAccountAuthPermItemProps extends PermItem {
|
||||
tid: string;
|
||||
mid: string;
|
||||
usrid: string;
|
||||
idCl: string;
|
||||
status: string;
|
||||
menuName: string;
|
||||
subMenu: Array<PermItem>;
|
||||
menuGrants: Array<UserMenuPermissionData>;
|
||||
};
|
||||
|
||||
export interface VerificationItem {
|
||||
|
||||
@@ -7,9 +7,10 @@ import {
|
||||
|
||||
export const AccountUserTab = ({
|
||||
activeTab,
|
||||
tid,
|
||||
mid,
|
||||
usrid
|
||||
usrid,
|
||||
idCl,
|
||||
status,
|
||||
}: AccountUserTabProps) => {
|
||||
const { navigate } = useNavigate();
|
||||
|
||||
@@ -18,18 +19,20 @@ export const AccountUserTab = ({
|
||||
if(tab === AccountUserTabKeys.LoginAuthInfo){
|
||||
navigate(PATHS.account.user.loginAuthInfo, {
|
||||
state: {
|
||||
tid: tid,
|
||||
mid: mid,
|
||||
usrid: usrid
|
||||
usrid: usrid,
|
||||
idCl: idCl,
|
||||
status: status
|
||||
}
|
||||
});
|
||||
}
|
||||
else if(tab === AccountUserTabKeys.AccountAuth){
|
||||
navigate(PATHS.account.user.accountAuth, {
|
||||
state: {
|
||||
tid: tid,
|
||||
mid: mid,
|
||||
usrid: usrid
|
||||
usrid: usrid,
|
||||
idCl: idCl,
|
||||
status: status
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,17 +3,28 @@ import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
||||
import { UserAccountAuthPermItemProps } from '../model/types';
|
||||
|
||||
export const UserAccountAuthPermItem = ({
|
||||
tid,
|
||||
mid,
|
||||
usrid,
|
||||
idCl,
|
||||
status,
|
||||
menuId,
|
||||
permName
|
||||
menuName,
|
||||
subMenu,
|
||||
menuGrants,
|
||||
}: UserAccountAuthPermItemProps) => {
|
||||
const { navigate } = useNavigate();
|
||||
|
||||
const onClickToNavigation = () => {
|
||||
navigate(PATHS.account.user.menuAuth, {
|
||||
state: {
|
||||
tid: tid,
|
||||
menuId: menuId
|
||||
mid: mid,
|
||||
usrid: usrid,
|
||||
idCl: idCl,
|
||||
status: status,
|
||||
menuId: menuId,
|
||||
menuName: menuName,
|
||||
subMenu: subMenu,
|
||||
menuGrants: menuGrants,
|
||||
}
|
||||
})
|
||||
};
|
||||
@@ -23,7 +34,7 @@ export const UserAccountAuthPermItem = ({
|
||||
className="perm-item"
|
||||
onClick={ () => onClickToNavigation() }
|
||||
>
|
||||
<span className="perm-name">{ permName }</span>
|
||||
<span className="perm-name">{ menuName }</span>
|
||||
<span className="ic20 arrow-right"></span>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@@ -1,30 +1,37 @@
|
||||
import { UserAccountAuthPermListProps } from '../model/types';
|
||||
import { UserAccountAuthPermItem } from './user-account-auth-perm-item';
|
||||
|
||||
export const UserAccountAuthPermList = ({
|
||||
tid,
|
||||
permItems
|
||||
mid,
|
||||
usrid,
|
||||
idCl,
|
||||
status,
|
||||
menuItems,
|
||||
menuGrants,
|
||||
}: UserAccountAuthPermListProps) => {
|
||||
|
||||
const getPermItems = () => {
|
||||
let rs = [];
|
||||
for(let i=0;i<permItems.length;i++){
|
||||
rs.push(
|
||||
<UserAccountAuthPermItem
|
||||
key={ 'key-perm-item-' + i }
|
||||
tid={ tid }
|
||||
menuId={ permItems[i]?.menuId }
|
||||
permName={ permItems[i]?.permName }
|
||||
></UserAccountAuthPermItem>
|
||||
);
|
||||
}
|
||||
return rs;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="perm-list">
|
||||
{ getPermItems() }
|
||||
</div>
|
||||
</>
|
||||
<div className="perm-list">
|
||||
{menuItems.map((item, index) => {
|
||||
// 해당 메뉴와 서브메뉴에 대한 권한만 필터링
|
||||
const subMenuIds = (item.subMenu ?? []).map(sub => Number(sub.menuId));
|
||||
const relevantGrants = (menuGrants ?? []).filter(grant =>
|
||||
subMenuIds.includes(grant.menuId)
|
||||
);
|
||||
|
||||
return (
|
||||
<UserAccountAuthPermItem
|
||||
key={`perm-${item.menuId || index}`}
|
||||
mid={mid}
|
||||
usrid={usrid}
|
||||
idCl={idCl}
|
||||
status={status}
|
||||
menuId={item.menuId}
|
||||
menuName={item.menuName ?? ''}
|
||||
subMenu={item.subMenu ?? []}
|
||||
menuGrants={relevantGrants}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,19 +1,112 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { UserAccountAuthWrapProps } from '../model/types';
|
||||
import { UserAccountAuthPermList } from './user-account-auth-perm-list';
|
||||
import { useUserMenuPermissionsMutation } from '@/entities/user/api/use-user-menu-permission-mutation';
|
||||
import { useUserUpdatePermissionsMutation } from '@/entities/user/api/use-user-update-permission-mutation';
|
||||
import { UserMenuPermissionData } from '@/entities/user/model/types';
|
||||
|
||||
export const UserAccountAuthWrap = ({
|
||||
tid
|
||||
mid,
|
||||
usrid,
|
||||
idCl,
|
||||
status,
|
||||
}: UserAccountAuthWrapProps) => {
|
||||
const [currentStatus, setCurrentStatus] = useState(status);
|
||||
const [currentIdCl, setCurrentIdCl] = useState(idCl);
|
||||
const [menuGrants, setMenuGrants] = useState<Array<UserMenuPermissionData>>([]);
|
||||
const [hasChanges, setHasChanges] = useState(false);
|
||||
console.log('mid : ', mid);
|
||||
console.log('usrid : ', usrid);
|
||||
console.log('idCl : ', idCl);
|
||||
console.log('status : ', status);
|
||||
const { mutateAsync: userMenuPermissions } = useUserMenuPermissionsMutation();
|
||||
const updatePermissionsMutation = useUserUpdatePermissionsMutation();
|
||||
useEffect(() => {
|
||||
if (mid && usrid) {
|
||||
console.log('userMenuPermissions');
|
||||
userMenuPermissions({mid: mid, usrid: usrid}).then((res) => {
|
||||
console.log('res : ', res);
|
||||
setMenuGrants(res?.data || res || []);
|
||||
}).catch((error) => {
|
||||
console.error('Failed to fetch menu permissions:', error);
|
||||
setMenuGrants([]);
|
||||
});
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [mid, usrid]);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('menuGrants : ', menuGrants);
|
||||
}, [menuGrants]);
|
||||
|
||||
// 변경 사항 감지
|
||||
useEffect(() => {
|
||||
const statusChanged = currentStatus !== status;
|
||||
const idClChanged = currentIdCl !== idCl;
|
||||
setHasChanges(statusChanged || idClChanged);
|
||||
}, [currentStatus, currentIdCl, status, idCl]);
|
||||
|
||||
let menuItems = [
|
||||
{menuId: 'menu1', permName: '거래조회'},
|
||||
{menuId: 'menu2', permName: '정산조회'},
|
||||
{menuId: 'menu3', permName: '가맹점 관리'},
|
||||
{menuId: 'menu4', permName: '결제 관리'},
|
||||
{menuId: 'menu5', permName: '계정 관리'},
|
||||
{menuId: 'menu6', permName: '부가세 신고 자료'},
|
||||
{menuId: 'menu7', permName: '부가서비스'},
|
||||
{menuId: 'menu8', permName: '고객지원'},
|
||||
];
|
||||
{menuId: '30', parent: '30', menuName: '거래조회', subMenu:
|
||||
[
|
||||
{menuId: '31', parent: '30', menuName: '거래내역조회'},
|
||||
{menuId: '32', parent: '30', menuName: '현금영수증 발행'},
|
||||
{menuId: '33', parent: '30', menuName: '에스크로'},
|
||||
{menuId: '34', parent: '30', menuName: '빌링'}
|
||||
]
|
||||
},
|
||||
{menuId: '35', parent: '35', menuName: '정산조회', subMenu:
|
||||
[
|
||||
{menuId: '36', parent: '35', menuName: '정산달력'},
|
||||
{menuId: '37', parent: '35', menuName: '정산내역'},
|
||||
]
|
||||
},
|
||||
{menuId: '38', parent: '38', menuName: '가맹점 관리', subMenu:
|
||||
[
|
||||
{menuId: '39', parent: '38', menuName: '가맹점 정보'},
|
||||
{menuId: '40', parent: '38', menuName: '등록 현황'},
|
||||
]
|
||||
},
|
||||
{menuId: '41', parent: '41', menuName: '결제 관리', subMenu:
|
||||
[
|
||||
{menuId: '42', parent: '41', menuName: '결제 정보'},
|
||||
{menuId: '43', parent: '41', menuName: '결제데이터통보'},
|
||||
]
|
||||
},
|
||||
{menuId: '44', parent: '44', menuName: '계정관리', subMenu:
|
||||
[
|
||||
{menuId: '45', parent: '44', menuName: '사용자관리'},
|
||||
{menuId: '46', parent: '44', menuName: '비밀번호관리'},
|
||||
]
|
||||
},
|
||||
{menuId: '47', parent: '47', menuName: '부가세신고자료', subMenu:
|
||||
[
|
||||
{menuId: '48', parent: '47', menuName: '부가세신고자료'},
|
||||
{menuId: '49', parent: '47', menuName: '부가세참고'},
|
||||
]
|
||||
},
|
||||
{menuId: '50', parent: '50', menuName: '부가서비스', subMenu:
|
||||
[
|
||||
{menuId: '51', parent: '50', menuName: '부가서비스소개'},
|
||||
{menuId: '52', parent: '50', menuName: '신용카드ARS카드결제'},
|
||||
{menuId: '53', parent: '50', menuName: '계좌이체ARS카드결제'},
|
||||
{menuId: '54', parent: '50', menuName: '가상계좌ARS카드결제'},
|
||||
{menuId: '55', parent: '50', menuName: '휴대폰ARS카드결제'},
|
||||
{menuId: '56', parent: '50', menuName: '계좌간편결제ARS카드결제'},
|
||||
{menuId: '57', parent: '50', menuName: 'SSG머니ARS카드결제'},
|
||||
{menuId: '58', parent: '50', menuName: 'SSG은행계좌ARS카드결제'},
|
||||
{menuId: '59', parent: '50', menuName: '문화상품권ARS카드결제'},
|
||||
{menuId: '60', parent: '50', menuName: '티머니페이ARS카드결제'},
|
||||
]
|
||||
},
|
||||
{menuId: '61', parent: '61', menuName: '고객지원', subMenu:
|
||||
[
|
||||
{menuId: '62', parent: '61', menuName: '공지사항'},
|
||||
{menuId: '63', parent: '61', menuName: '자주묻는질문'},
|
||||
{menuId: '64', parent: '61', menuName: '1:1문의'},
|
||||
]
|
||||
},
|
||||
]
|
||||
return (
|
||||
<>
|
||||
<div className="ing-list pdtop">
|
||||
@@ -21,19 +114,18 @@ export const UserAccountAuthWrap = ({
|
||||
<div className="perm-field">
|
||||
<div className="perm-label">계정 상태</div>
|
||||
<div className="perm-control">
|
||||
<select>
|
||||
<option selected>사용</option>
|
||||
<option>미사용</option>
|
||||
<select value={currentStatus} onChange={(e) => setCurrentStatus(e.target.value)}>
|
||||
<option value="NORMAL">사용</option>
|
||||
<option value="SUSPENDED">미사용</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div className="perm-field">
|
||||
<div className="perm-label">로그인 범위</div>
|
||||
<div className="perm-control">
|
||||
<select>
|
||||
<option>MID</option>
|
||||
<option>GID</option>
|
||||
<option selected>MID + GID</option>
|
||||
<select value={currentIdCl} onChange={(e) => setCurrentIdCl(e.target.value)}>
|
||||
<option value="MID">MID</option>
|
||||
<option value="GID">MID + GID</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -42,16 +134,34 @@ export const UserAccountAuthWrap = ({
|
||||
<div className="ing-title fs18">메뉴별 권한 설정</div>
|
||||
|
||||
<UserAccountAuthPermList
|
||||
tid={ tid }
|
||||
permItems={ menuItems }
|
||||
mid={ mid }
|
||||
usrid={ usrid }
|
||||
idCl={ currentIdCl }
|
||||
status={ currentStatus }
|
||||
menuItems={ menuItems }
|
||||
menuGrants={ menuGrants }
|
||||
></UserAccountAuthPermList>
|
||||
|
||||
<div className="apply-row bottom-padding">
|
||||
<button
|
||||
<button
|
||||
className="btn-50 btn-blue flex-1"
|
||||
type="button"
|
||||
>저장</button>
|
||||
type="button"
|
||||
disabled={!hasChanges || updatePermissionsMutation.isPending}
|
||||
onClick={() => {
|
||||
console.log('updatePermissionMutation');
|
||||
updatePermissionsMutation.mutate(
|
||||
{
|
||||
mid: mid,
|
||||
usrid: usrid,
|
||||
idCl: currentIdCl,
|
||||
status: currentStatus
|
||||
});
|
||||
}}
|
||||
>
|
||||
{updatePermissionsMutation.isPending ? '저장 중...' : '저장'}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import { UserFindAuthMethodParams, UserAuthMethodData } from '@/entities/user/model/types';
|
||||
import { UserFindAuthMethodParams, UserAuthMethodData, AuthMethodModifyItem } from '@/entities/user/model/types';
|
||||
import { useUserFindAuthMethodMutation } from '@/entities/user/api/use-user-find-authmethod-mutation';
|
||||
import { DEFAULT_PAGE_PARAM } from '@/entities/common/model/constant';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useUserModifyAuthMethodMutation } from '@/entities/user/api/use-user-modify-authmethod-mutation';
|
||||
|
||||
export const UserLoginAuthInfoWrap = ({
|
||||
mid,
|
||||
usrid,
|
||||
idCl,
|
||||
status,
|
||||
}: UserFindAuthMethodParams) => {
|
||||
const { mutateAsync: userFindAuthMethod } = useUserFindAuthMethodMutation();
|
||||
const { mutateAsync: userModifyAuthMethod } = useUserModifyAuthMethodMutation();
|
||||
const [pageParam] = useState(DEFAULT_PAGE_PARAM);
|
||||
const [authMethodData, setAuthMethodData] = useState<UserAuthMethodData>();
|
||||
const [initialData, setInitialData] = useState<UserAuthMethodData>();
|
||||
@@ -18,6 +22,8 @@ export const UserLoginAuthInfoWrap = ({
|
||||
const [readOnlyEmails, setReadOnlyEmails] = useState<Set<number>>(new Set());
|
||||
const [readOnlyPhones, setReadOnlyPhones] = useState<Set<number>>(new Set());
|
||||
|
||||
console.log("UserLoginAuthInfoWrap", mid, usrid, idCl, status);
|
||||
|
||||
const handleRemoveExistingEmail = (index: number) => {
|
||||
if (authMethodData?.emails) {
|
||||
const updatedEmails = authMethodData.emails.filter((_, i) => i !== index);
|
||||
@@ -36,6 +42,8 @@ export const UserLoginAuthInfoWrap = ({
|
||||
let params: UserFindAuthMethodParams = {
|
||||
mid: mid,
|
||||
usrid: usrid,
|
||||
idCl: idCl,
|
||||
status: status,
|
||||
page: pageParam
|
||||
};
|
||||
userFindAuthMethod(params).then((rs: any) => {
|
||||
@@ -260,6 +268,107 @@ export const UserLoginAuthInfoWrap = ({
|
||||
return hasChanges;
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
try {
|
||||
const addMethods: AuthMethodModifyItem[] = [];
|
||||
const removeMethods: AuthMethodModifyItem[] = [];
|
||||
|
||||
// 삭제된 이메일 항목 수집
|
||||
if (initialData?.emails) {
|
||||
initialData.emails.forEach((email) => {
|
||||
const stillExists = authMethodData?.emails?.some(
|
||||
e => e.content === email.content && e.sequence === email.sequence
|
||||
);
|
||||
if (!stillExists) {
|
||||
removeMethods.push({
|
||||
usrid: usrid,
|
||||
systemAdminClassId: mid,
|
||||
idCl: "MID",
|
||||
authMethodType: "EMAIL",
|
||||
sequence: email.sequence,
|
||||
content: email.content
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 삭제된 전화번호 항목 수집
|
||||
if (initialData?.phones) {
|
||||
initialData.phones.forEach((phone) => {
|
||||
const stillExists = authMethodData?.phones?.some(
|
||||
p => p.content === phone.content && p.sequence === phone.sequence
|
||||
);
|
||||
if (!stillExists) {
|
||||
removeMethods.push({
|
||||
usrid: usrid,
|
||||
systemAdminClassId: mid,
|
||||
idCl: "MID",
|
||||
authMethodType: "PHONE",
|
||||
sequence: phone.sequence,
|
||||
content: phone.content
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 새로 추가된 이메일 항목 수집
|
||||
const validNewEmails = newEmails.filter(e => e.trim());
|
||||
validNewEmails.forEach((email, index) => {
|
||||
const existingEmailCount = authMethodData?.emails?.length || 0;
|
||||
addMethods.push({
|
||||
usrid: usrid,
|
||||
systemAdminClassId: mid,
|
||||
idCl: "MID",
|
||||
authMethodType: "EMAIL",
|
||||
sequence: existingEmailCount + index + 1,
|
||||
content: email
|
||||
});
|
||||
});
|
||||
|
||||
// 새로 추가된 전화번호 항목 수집
|
||||
const validNewPhones = newPhones.filter(p => p.trim());
|
||||
validNewPhones.forEach((phone, index) => {
|
||||
const existingPhoneCount = authMethodData?.phones?.length || 0;
|
||||
addMethods.push({
|
||||
usrid: usrid,
|
||||
systemAdminClassId: mid,
|
||||
idCl: "MID",
|
||||
authMethodType: "PHONE",
|
||||
sequence: existingPhoneCount + index + 1,
|
||||
content: phone
|
||||
});
|
||||
});
|
||||
|
||||
const requestBody = {
|
||||
addMethods: addMethods.length > 0 ? addMethods : undefined,
|
||||
removeMethods: removeMethods.length > 0 ? removeMethods : undefined
|
||||
};
|
||||
|
||||
// 빈 배열 제거
|
||||
const finalRequestBody = Object.fromEntries(
|
||||
Object.entries(requestBody).filter(([_, value]) => value !== undefined)
|
||||
);
|
||||
|
||||
console.log("Save request body:", finalRequestBody);
|
||||
|
||||
// API 호출
|
||||
await userModifyAuthMethod(finalRequestBody);
|
||||
|
||||
// 성공 후 데이터 새로고침
|
||||
callUserFindAuthMethod(mid, usrid);
|
||||
|
||||
// 새로 추가한 항목들 초기화
|
||||
setNewEmails([]);
|
||||
setNewPhones([]);
|
||||
setEditableEmailIndex(-1);
|
||||
setEditablePhoneIndex(-1);
|
||||
setReadOnlyEmails(new Set());
|
||||
setReadOnlyPhones(new Set());
|
||||
} catch (error) {
|
||||
console.error("Failed to save auth methods:", error);
|
||||
}
|
||||
};
|
||||
|
||||
console.log("Rendering with authMethodData: ", authMethodData);
|
||||
console.log("Emails: ", authMethodData?.emails);
|
||||
console.log("Phones: ", authMethodData?.phones);
|
||||
@@ -369,6 +478,7 @@ export const UserLoginAuthInfoWrap = ({
|
||||
<button
|
||||
className="btn-50 btn-blue flex-1"
|
||||
disabled={!isSaveButtonEnabled()}
|
||||
onClick={handleSave}
|
||||
>
|
||||
저장
|
||||
</button>
|
||||
|
||||
@@ -4,33 +4,25 @@ import { UserManageAuthItemProps } from '../model/types';
|
||||
|
||||
export const UserManageAuthItem = ({
|
||||
usrid,
|
||||
tid,
|
||||
mid,
|
||||
idCl,
|
||||
status,
|
||||
}: UserManageAuthItemProps) => {
|
||||
console.log("UserManageAuthItem", usrid, mid, idCl, status);
|
||||
const { navigate } = useNavigate();
|
||||
|
||||
const onClickToNavigation = () => {
|
||||
// state를 통해 데이터 전달
|
||||
const handleClick = () => {
|
||||
navigate(PATHS.account.user.loginAuthInfo, {
|
||||
state: {
|
||||
tid: tid,
|
||||
mid: mid,
|
||||
usrid: usrid
|
||||
}
|
||||
state: { mid, usrid, idCl, status }
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className="auth-item"
|
||||
onClick={ () => onClickToNavigation() }
|
||||
>
|
||||
<div className="auth-item-left">
|
||||
{/* <span className={ `tag-pill ${(!!useYn)? '': 'red'}` }>{ (!!useYn)? '사용': '미사용' }</span> */}
|
||||
<span className="auth-name">{ usrid }</span>
|
||||
</div>
|
||||
<span className="ic20 arrow-right"></span>
|
||||
<div className="auth-item" onClick={handleClick}>
|
||||
<div className="auth-item-left">
|
||||
<span className="auth-name">{usrid}</span>
|
||||
</div>
|
||||
</>
|
||||
<span className="ic20 arrow-right"></span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -5,26 +5,18 @@ export const UserManageAuthList = ({
|
||||
userItems,
|
||||
mid
|
||||
}: UserManageAuthListProps) => {
|
||||
|
||||
const getUserManageAuthItems = () => {
|
||||
let rs = [];
|
||||
for(let i=0;i<userItems.length;i++){
|
||||
rs.push(
|
||||
<UserManageAuthItem
|
||||
key={ userItems[i]?.usrid }
|
||||
usrid={ userItems[i]?.usrid }
|
||||
tid={ userItems[i]?.tid }
|
||||
mid={ mid }
|
||||
></UserManageAuthItem>
|
||||
);
|
||||
}
|
||||
return rs;
|
||||
}
|
||||
console.log("UserManageAuthList", userItems, mid);
|
||||
return (
|
||||
<>
|
||||
<div className="auth-list">
|
||||
{ getUserManageAuthItems() }
|
||||
</div>
|
||||
</>
|
||||
<div className="auth-list">
|
||||
{userItems.map((item) => (
|
||||
<UserManageAuthItem
|
||||
key={item.usrid}
|
||||
usrid={item.usrid}
|
||||
mid={mid}
|
||||
idCl={item.idCl}
|
||||
status={item.status}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { PATHS } from '@/shared/constants/paths';
|
||||
import { useNavigate } from '@/shared/lib/hooks/use-navigate';
|
||||
import { AuthItem } from '../model/types';
|
||||
import { DEFAULT_PAGE_PARAM } from '@/entities/common/model/constant';
|
||||
import { UserManageAuthList } from './user-manage-auth-list';
|
||||
import { useUserFindMutation } from '@/entities/user/api/use-user-find-mutation';
|
||||
@@ -23,12 +22,18 @@ export const UserManageWrap = () => {
|
||||
const callList = (mid: string) => {
|
||||
setPageParam(pageParam);
|
||||
userFind({ mid: mid, page: pageParam }).then((rs) => {
|
||||
console.log('API Response:', rs);
|
||||
console.log('Content:', rs.content);
|
||||
setUserItems(rs.content || []);
|
||||
});
|
||||
};
|
||||
|
||||
const onClickToNavigation = () => {
|
||||
navigate(PATHS.account.user.addAccount);
|
||||
navigate(PATHS.account.user.addAccount, {
|
||||
state: {
|
||||
mid: mid,
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -133,7 +133,8 @@ export interface CodesGroupByCodeClParams {
|
||||
codeCl: string;
|
||||
};
|
||||
export interface CodesGroupByCodeClResponse extends CodeGroupItem {
|
||||
|
||||
status: boolean;
|
||||
error?: ErrorResponse;
|
||||
}
|
||||
export interface CodesCacheStatusResponse {
|
||||
additionalProp1: string;
|
||||
@@ -141,13 +142,15 @@ export interface CodesCacheStatusResponse {
|
||||
additionalProp3: string;
|
||||
};
|
||||
export interface CodesCacheRefreshResponse {
|
||||
|
||||
status: boolean;
|
||||
error?: ErrorResponse;
|
||||
};
|
||||
export interface CodesCacheRefreshByCodeClParams {
|
||||
codeCl: string;
|
||||
};
|
||||
export interface CodesCacheRefreshByCodeClResponse {
|
||||
|
||||
status: boolean;
|
||||
error?: ErrorResponse;
|
||||
};
|
||||
export interface EmptyTokenVerifyCodeParams {
|
||||
usrid: string;
|
||||
@@ -177,7 +180,8 @@ export interface EmptyTokenChangeParams {
|
||||
newConfirmPassword: string;
|
||||
};
|
||||
export interface EmptyTokenChangeResponse {
|
||||
|
||||
status: boolean;
|
||||
error?: ErrorResponse;
|
||||
};
|
||||
export interface EmptyTokenAddSendCodeParams {
|
||||
usrid: string;
|
||||
@@ -196,3 +200,12 @@ export interface SectionArrowProps {
|
||||
export interface BannerInfo {
|
||||
HomneBottomBanner: boolean;
|
||||
};
|
||||
|
||||
export interface ErrorResponse {
|
||||
root: string;
|
||||
errKey: string;
|
||||
code: string;
|
||||
message: string;
|
||||
timestamp: string;
|
||||
details: Record<string, string>;
|
||||
}
|
||||
29
src/entities/user/api/use-user-change-password-mutation.ts
Normal file
29
src/entities/user/api/use-user-change-password-mutation.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import axios from 'axios';
|
||||
import { API_URL_USER } from '@/shared/api/api-url-user';
|
||||
import { resultify } from '@/shared/lib/resultify';
|
||||
import { CBDCAxiosError } from '@/shared/@types/error';
|
||||
import {
|
||||
ChangePasswordParams,
|
||||
ChangePasswordResponse
|
||||
} from '../model/types';
|
||||
import {
|
||||
useMutation,
|
||||
UseMutationOptions
|
||||
} from '@tanstack/react-query';
|
||||
|
||||
export const userChangePassword = (params: ChangePasswordParams) => {
|
||||
return resultify(
|
||||
axios.post<ChangePasswordResponse>(API_URL_USER.changePassword(), params),
|
||||
);
|
||||
};
|
||||
|
||||
export const useUserChangePasswordMutation = (options?: UseMutationOptions<ChangePasswordResponse, CBDCAxiosError, ChangePasswordParams>) => {
|
||||
const mutation = useMutation<ChangePasswordResponse, CBDCAxiosError, ChangePasswordParams>({
|
||||
...options,
|
||||
mutationFn: (params: ChangePasswordParams) => userChangePassword(params),
|
||||
});
|
||||
|
||||
return {
|
||||
...mutation,
|
||||
};
|
||||
};
|
||||
28
src/entities/user/api/use-user-menu-permission-mutation.ts
Normal file
28
src/entities/user/api/use-user-menu-permission-mutation.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import axios from 'axios';
|
||||
import { API_URL_USER } from '@/shared/api/api-url-user';
|
||||
import { resultify } from '@/shared/lib/resultify';
|
||||
import { CBDCAxiosError } from '@/shared/@types/error';
|
||||
import {
|
||||
UserMenuPermissionsParams,
|
||||
UserMenuPermissionsResponse
|
||||
} from '../model/types';
|
||||
import {
|
||||
useMutation,
|
||||
UseMutationOptions
|
||||
} from '@tanstack/react-query';
|
||||
|
||||
export const userMenuPermissions = (params: UserMenuPermissionsParams) => {
|
||||
return resultify(
|
||||
axios.post<UserMenuPermissionsResponse>(API_URL_USER.findMenuPermissions(), params),
|
||||
);
|
||||
};
|
||||
|
||||
export const useUserMenuPermissionsMutation = (options?: UseMutationOptions<UserMenuPermissionsResponse, CBDCAxiosError, UserMenuPermissionsParams>) => {
|
||||
const mutation = useMutation<UserMenuPermissionsResponse, CBDCAxiosError, UserMenuPermissionsParams>({
|
||||
...options,
|
||||
mutationFn: (params: UserMenuPermissionsParams) => userMenuPermissions(params),
|
||||
});
|
||||
return {
|
||||
...mutation,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
import axios from 'axios';
|
||||
import { API_URL_USER } from '@/shared/api/api-url-user';
|
||||
import { resultify } from '@/shared/lib/resultify';
|
||||
import { CBDCAxiosError } from '@/shared/@types/error';
|
||||
import {
|
||||
UserMenuPermissionsSaveParams,
|
||||
UserMenuPermissionsSaveResponse
|
||||
} from '../model/types';
|
||||
import {
|
||||
useMutation,
|
||||
UseMutationOptions
|
||||
} from '@tanstack/react-query';
|
||||
|
||||
export const userMenuPermissionsSave = (params: UserMenuPermissionsSaveParams) => {
|
||||
return resultify(
|
||||
axios.post<UserMenuPermissionsSaveResponse>(API_URL_USER.saveMenuPermissions(), params),
|
||||
);
|
||||
};
|
||||
|
||||
export const useUserMenuPermissionsSaveMutation = (options?: UseMutationOptions<UserMenuPermissionsSaveResponse, CBDCAxiosError, UserMenuPermissionsSaveParams>) => {
|
||||
const mutation = useMutation<UserMenuPermissionsSaveResponse, CBDCAxiosError, UserMenuPermissionsSaveParams>({
|
||||
...options,
|
||||
mutationFn: (params: UserMenuPermissionsSaveParams) => userMenuPermissionsSave(params),
|
||||
});
|
||||
|
||||
return {
|
||||
...mutation,
|
||||
};
|
||||
};
|
||||
29
src/entities/user/api/use-user-modify-authmethod-mutation.ts
Normal file
29
src/entities/user/api/use-user-modify-authmethod-mutation.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import axios from 'axios';
|
||||
import { API_URL_USER } from '@/shared/api/api-url-user';
|
||||
import { resultify } from '@/shared/lib/resultify';
|
||||
import { CBDCAxiosError } from '@/shared/@types/error';
|
||||
import {
|
||||
UserModifyAuthMethodParams,
|
||||
UserModifyAuthMethodResponse
|
||||
} from '../model/types';
|
||||
import {
|
||||
useMutation,
|
||||
UseMutationOptions
|
||||
} from '@tanstack/react-query';
|
||||
|
||||
export const userModifyAuthMethod = (params: UserModifyAuthMethodParams) => {
|
||||
return resultify(
|
||||
axios.post<UserModifyAuthMethodResponse>(API_URL_USER.modifyAuthMethod(), params),
|
||||
);
|
||||
};
|
||||
|
||||
export const useUserModifyAuthMethodMutation = (options?: UseMutationOptions<UserModifyAuthMethodResponse, CBDCAxiosError, UserModifyAuthMethodParams>) => {
|
||||
const mutation = useMutation<UserModifyAuthMethodResponse, CBDCAxiosError, UserModifyAuthMethodParams>({
|
||||
...options,
|
||||
mutationFn: (params: UserModifyAuthMethodParams) => userModifyAuthMethod(params),
|
||||
});
|
||||
|
||||
return {
|
||||
...mutation,
|
||||
};
|
||||
};
|
||||
29
src/entities/user/api/use-user-update-permission-mutation.ts
Normal file
29
src/entities/user/api/use-user-update-permission-mutation.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import axios from 'axios';
|
||||
import { API_URL_USER } from '@/shared/api/api-url-user';
|
||||
import { resultify } from '@/shared/lib/resultify';
|
||||
import { CBDCAxiosError } from '@/shared/@types/error';
|
||||
import {
|
||||
UserUpdatePermissionsParams,
|
||||
UserUpdatePermissionsResponse
|
||||
} from '../model/types';
|
||||
import {
|
||||
useMutation,
|
||||
UseMutationOptions
|
||||
} from '@tanstack/react-query';
|
||||
|
||||
export const userUpdatePermissions = (params: UserUpdatePermissionsParams) => {
|
||||
return resultify(
|
||||
axios.post<UserUpdatePermissionsResponse>(API_URL_USER.updatePermissions(), params),
|
||||
);
|
||||
};
|
||||
|
||||
export const useUserUpdatePermissionsMutation = (options?: UseMutationOptions<UserUpdatePermissionsResponse, CBDCAxiosError, UserUpdatePermissionsParams>) => {
|
||||
const mutation = useMutation<UserUpdatePermissionsResponse, CBDCAxiosError, UserUpdatePermissionsParams>({
|
||||
...options,
|
||||
mutationFn: (params: UserUpdatePermissionsParams) => userUpdatePermissions(params),
|
||||
});
|
||||
|
||||
return {
|
||||
...mutation,
|
||||
};
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
DefaulResponsePagination,
|
||||
DefaultRequestPagination
|
||||
DefaultRequestPagination,
|
||||
ErrorResponse,
|
||||
} from '@/entities/common/model/types';
|
||||
|
||||
export interface LoginParams {
|
||||
@@ -28,16 +29,19 @@ export interface LoginResponse {
|
||||
};
|
||||
|
||||
export interface UserInfo extends LoginResponse {
|
||||
|
||||
status: boolean;
|
||||
error?: ErrorResponse;
|
||||
}
|
||||
export interface UserParams {
|
||||
|
||||
status: boolean;
|
||||
error?: ErrorResponse;
|
||||
};
|
||||
|
||||
export interface UserListItem {
|
||||
usrid: string;
|
||||
idCl: string;
|
||||
status: string;
|
||||
tid: string;
|
||||
}
|
||||
|
||||
export interface UserFindResponse extends DefaulResponsePagination {
|
||||
@@ -56,6 +60,8 @@ export interface UserExistsUseridParams {
|
||||
export interface UserFindAuthMethodParams {
|
||||
mid: string;
|
||||
usrid: string;
|
||||
idCl: string;
|
||||
status: string;
|
||||
page?: DefaultRequestPagination;
|
||||
};
|
||||
|
||||
@@ -68,16 +74,86 @@ export interface UserExistsUseridResponse {
|
||||
exists: boolean;
|
||||
};
|
||||
|
||||
export interface AuthMethodModifyItem {
|
||||
usrid: string;
|
||||
systemAdminClassId: string;
|
||||
idCl: string;
|
||||
authMethodType: string;
|
||||
sequence: number;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface UserModifyAuthMethodParams {
|
||||
addMethods?: Array<AuthMethodModifyItem>;
|
||||
removeMethods?: Array<AuthMethodModifyItem>;
|
||||
};
|
||||
|
||||
export interface UserModifyAuthMethodResponse {
|
||||
status: boolean;
|
||||
error?: ErrorResponse;
|
||||
};
|
||||
|
||||
export interface UserUpdatePermissionsParams {
|
||||
mid: string;
|
||||
usrid: string;
|
||||
idCl: string;
|
||||
status: string;
|
||||
}
|
||||
|
||||
export interface UserUpdatePermissionsResponse {
|
||||
status: boolean;
|
||||
error?: ErrorResponse;
|
||||
}
|
||||
|
||||
export interface UserMenuPermissionsParams {
|
||||
mid: string;
|
||||
usrid: string;
|
||||
}
|
||||
|
||||
export interface UserMenuPermissionsResponse {
|
||||
status: boolean;
|
||||
data: Array<UserMenuPermissionData>;
|
||||
}
|
||||
|
||||
export interface UserMenuPermissionsSaveParams {
|
||||
mid: string;
|
||||
namsUserMenuAccess: Array<UserMenuPermissionData>;
|
||||
}
|
||||
|
||||
export interface UserMenuPermissionsSaveResponse {
|
||||
status: boolean;
|
||||
error?: ErrorResponse;
|
||||
}
|
||||
|
||||
|
||||
export interface UserMenuPermissionData {
|
||||
menuId: number;
|
||||
usrid: string;
|
||||
grant: number;
|
||||
}
|
||||
|
||||
export interface ChangePasswordParams {
|
||||
mid: string;
|
||||
usrid: string;
|
||||
password: string;
|
||||
}
|
||||
|
||||
export interface ChangePasswordResponse {
|
||||
status: boolean;
|
||||
error?: ErrorResponse;
|
||||
}
|
||||
|
||||
export interface VerificationsItem {
|
||||
type: string;
|
||||
contact: string;
|
||||
};
|
||||
|
||||
export interface UserCreateParams {
|
||||
userId: string;
|
||||
mid: string;
|
||||
usrid: string;
|
||||
password: string;
|
||||
loginRange: string;
|
||||
verification: Array<VerificationsItem>
|
||||
verifications: Array<VerificationsItem>
|
||||
};
|
||||
|
||||
export interface UserData {
|
||||
|
||||
Reference in New Issue
Block a user