363 lines
10 KiB
TypeScript
363 lines
10 KiB
TypeScript
import { z } from "zod";
|
|
import type { PageableList, PageableParams } from "@/shared/model";
|
|
|
|
export const USER_STATE_CODE = {
|
|
대기: "00",
|
|
정상: "01",
|
|
정지: "07",
|
|
탈퇴: "08",
|
|
삭제: "09",
|
|
} as const;
|
|
|
|
export type UserStateCode =
|
|
(typeof USER_STATE_CODE)[keyof typeof USER_STATE_CODE];
|
|
|
|
// 사용자 검색 파라미터
|
|
export interface UserSearchParams extends PageableParams {
|
|
keywordType?: string;
|
|
keyword?: string;
|
|
userStateCode?: string;
|
|
aprvYn?: string;
|
|
grpId?: string;
|
|
frDateYmd?: string;
|
|
toDateYmd?: string;
|
|
userName?: string;
|
|
}
|
|
|
|
// 사용자 목록 응답 인터페이스
|
|
export interface UserListResponse {
|
|
userId: string;
|
|
userName: string;
|
|
email: string;
|
|
roleId: string;
|
|
roleName: string;
|
|
userStateCode: UserStateCode;
|
|
userStateCodeName: string;
|
|
lastLoginDate: string;
|
|
loginFailCount: number;
|
|
userUnqId: string;
|
|
mphn: string;
|
|
telno: string;
|
|
aprvYn: string;
|
|
regDt: string;
|
|
laeSeCd: string;
|
|
laeSeNm: string;
|
|
ogdpSeCd: string;
|
|
ogdpSeNm: string;
|
|
instSeCd: string;
|
|
instSeNm: string;
|
|
aprvYmd: string;
|
|
}
|
|
|
|
// 사용자 상세 응답 인터페이스
|
|
export interface UserDetailResponse {
|
|
regDt: string;
|
|
mdfcnDt: string;
|
|
rgtr: string;
|
|
mdfr: string;
|
|
userUnqId: string;
|
|
userId: string;
|
|
userName: string;
|
|
email: string;
|
|
encryptedPassword: string;
|
|
refreshToken: string;
|
|
userStateCode: UserStateCode;
|
|
lastLoginDate: string;
|
|
loginFailCount: number;
|
|
pswdHnt: string;
|
|
pswdAns: string;
|
|
mphn: string;
|
|
telno: string;
|
|
zip: string;
|
|
addr: string;
|
|
daddr: string;
|
|
laeSeCd: string;
|
|
ogdpSeCd: string;
|
|
aprvYn: string;
|
|
autzrId: string;
|
|
expryYmd: string;
|
|
lastPswdChgDt: string;
|
|
googleId: string;
|
|
kakaoId: string;
|
|
naverId: string;
|
|
isSocialUser: boolean;
|
|
hasPassword: boolean;
|
|
twoFactorEnabled: boolean;
|
|
adminRoleYn: string;
|
|
instSeCd: string;
|
|
aprvYmd: string;
|
|
enoCd: string;
|
|
dtlInstCd: string;
|
|
laeSeNm: string;
|
|
ogdpSeNm: string;
|
|
instSeNm: string;
|
|
userStateNm: string;
|
|
pswdHntNm: string;
|
|
ecoNm: string;
|
|
dtlInstNm: string;
|
|
}
|
|
|
|
// 사용자 상태 통계 응답 인터페이스
|
|
export interface UserSttsStatsResponse {
|
|
sttsCd: string;
|
|
sttsNm: string;
|
|
cnt: number;
|
|
}
|
|
|
|
// 관리자 목록 응답 인터페이스
|
|
export interface AdminUserListResponse {
|
|
userUnqId: string;
|
|
userId: string;
|
|
userName: string;
|
|
groupId: string;
|
|
groupNm: string;
|
|
userStateCode: string;
|
|
userStateCodeName: string;
|
|
laeSeCd: string;
|
|
laeSeNm: string;
|
|
ogdpSeCd: string;
|
|
ogdpSeNm: string;
|
|
instSeCd: string;
|
|
instSeNm: string;
|
|
dtlInstCd: string;
|
|
dtlInstNm: string;
|
|
mdfr: string;
|
|
mdfrNm: string;
|
|
mdfcnDt: string;
|
|
}
|
|
|
|
// 사용자 수정 요청 스키마
|
|
export const userUpdateSchema = z.object({
|
|
userId: z.string().optional(),
|
|
userName: z.string(),
|
|
email: z.string().email().optional(),
|
|
password: z
|
|
.string()
|
|
.regex(
|
|
/^(?=.*[a-zA-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]).{8,20}$/,
|
|
"비밀번호는 8~20자, 영문/숫자/특수기호를 모두 포함해야 합니다.",
|
|
)
|
|
.optional(),
|
|
roleId: z.string().optional(),
|
|
userStateCode: z.string(),
|
|
pswdHnt: z.string().max(10),
|
|
pswdAns: z.string().max(100).optional(),
|
|
mphn: z.string().max(11).optional(),
|
|
telno: z.string().max(11).optional(),
|
|
zip: z.string().max(5).optional(),
|
|
addr: z.string().max(200).optional(),
|
|
daddr: z.string().max(200).optional(),
|
|
laeSeCd: z.string().max(10),
|
|
ogdpSeCd: z.string().max(10),
|
|
aprvYn: z.string(),
|
|
autzrId: z.string().uuid().optional(),
|
|
expryYmd: z.string().max(8),
|
|
instSeCd: z.string().optional(),
|
|
dtlInstCd: z.string().optional(),
|
|
aprvYmd: z.string().max(8).optional(),
|
|
enoCd: z.string().optional(),
|
|
});
|
|
|
|
// 사용자 비밀번호 변경 스키마
|
|
export const userPasswordUpdateSchema = z
|
|
.object({
|
|
password: z.string().optional(),
|
|
provider: z.string().optional(),
|
|
token: z.string().optional(),
|
|
newPassword: z
|
|
.string()
|
|
.regex(
|
|
/^(?=.*[a-zA-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]).{8,20}$/,
|
|
"비밀번호는 8~20자, 영문/숫자/특수기호를 모두 포함해야 합니다.",
|
|
),
|
|
newPasswordConfirm: z.string(),
|
|
})
|
|
.refine((data) => data.newPassword === data.newPasswordConfirm, {
|
|
message: "비밀번호가 일치하지 않습니다.",
|
|
path: ["newPasswordConfirm"],
|
|
});
|
|
|
|
// 사용자 비밀번호 찾기 변경 스키마
|
|
export const userFindPasswordUpdateSchema = z.object({
|
|
tokenValue: z.string(),
|
|
password: z
|
|
.string()
|
|
.regex(
|
|
/^(?=.*[a-zA-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]).{8,20}$/,
|
|
"비밀번호는 8~20자, 영문/숫자/특수기호를 모두 포함해야 합니다.",
|
|
),
|
|
});
|
|
|
|
// 사용자 비밀번호 확인 스키마
|
|
export const userPasswordMatchSchema = z.object({
|
|
password: z
|
|
.string()
|
|
.regex(
|
|
/^(?=.*[a-zA-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]).{8,20}$/,
|
|
"비밀번호는 8~20자, 영문/숫자/특수기호를 모두 포함해야 합니다.",
|
|
),
|
|
});
|
|
|
|
// 사용자 회원정보 변경 스키마
|
|
export const userUpdateInfoSchema = z.object({
|
|
password: z
|
|
.string()
|
|
.regex(
|
|
/^(?=.*[a-zA-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]).{8,20}$/,
|
|
"비밀번호는 8~20자, 영문/숫자/특수기호를 모두 포함해야 합니다.",
|
|
)
|
|
.optional(),
|
|
provider: z.string().optional(),
|
|
token: z.string().optional(),
|
|
userName: z.string(),
|
|
email: z.string().email().optional(),
|
|
});
|
|
|
|
// 사용자 저장 스키마
|
|
export const userSaveSchema = z.object({
|
|
userId: z.string(),
|
|
userName: z.string(),
|
|
email: z.string().email().optional(),
|
|
password: z
|
|
.string()
|
|
.regex(
|
|
/^(?=.*[a-zA-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]).{8,20}$/,
|
|
"비밀번호는 8~20자, 영문/숫자/특수기호를 모두 포함해야 합니다.",
|
|
),
|
|
pswdHnt: z.string().max(10),
|
|
pswdAns: z.string().max(100).optional(),
|
|
mphn: z.string().max(11).optional(),
|
|
telno: z.string().max(11).optional(),
|
|
zip: z.string().max(5).optional(),
|
|
addr: z.string().max(200).optional(),
|
|
daddr: z.string().max(200).optional(),
|
|
laeSeCd: z.string().max(10),
|
|
ogdpSeCd: z.string().max(10),
|
|
expryYmd: z.string().max(8),
|
|
instSeCd: z.string().optional(),
|
|
dtlInstCd: z.string().optional(),
|
|
enoCd: z.string().optional(),
|
|
});
|
|
|
|
// 사용자 비밀번호 찾기 저장 스키마
|
|
export const userFindPasswordSaveSchema = z.object({
|
|
userName: z.string(),
|
|
emailAddr: z.string().email(),
|
|
mainUrl: z.string(),
|
|
changePasswordUrl: z.string(),
|
|
});
|
|
|
|
// 사용자 인증 요청 스키마
|
|
export const userVerifySchema = z.object({
|
|
password: z
|
|
.string()
|
|
.regex(/((?=.*[0-9])(?=.*[a-zA-Z])(?=.*\W)(?=\S+$).{8,20})|()/)
|
|
.optional(),
|
|
provider: z.string().optional(),
|
|
token: z.string().optional(),
|
|
});
|
|
|
|
// 사용자 이메일 요청 스키마
|
|
export const userEmailSchema = z.object({
|
|
userId: z.string().optional(),
|
|
email: z.string().email(),
|
|
});
|
|
|
|
// 사용자 ID 요청 스키마
|
|
export const userIdSchema = z.object({
|
|
userId: z.string(),
|
|
});
|
|
|
|
// Zod 스키마 타입 정의
|
|
export type UserUpdateData = z.infer<typeof userUpdateSchema>;
|
|
export type UserPasswordUpdateData = z.infer<typeof userPasswordUpdateSchema>;
|
|
export type UserFindPasswordUpdateData = z.infer<
|
|
typeof userFindPasswordUpdateSchema
|
|
>;
|
|
export type UserPasswordMatchData = z.infer<typeof userPasswordMatchSchema>;
|
|
export type UserUpdateInfoData = z.infer<typeof userUpdateInfoSchema>;
|
|
export type UserSaveData = z.infer<typeof userSaveSchema>;
|
|
export type UserFindPasswordSaveData = z.infer<
|
|
typeof userFindPasswordSaveSchema
|
|
>;
|
|
export type UserVerifyData = z.infer<typeof userVerifySchema>;
|
|
export type UserEmailData = z.infer<typeof userEmailSchema>;
|
|
export type UserIdData = z.infer<typeof userIdSchema>;
|
|
|
|
// 페이지네이션 타입 정의
|
|
export type UserList = PageableList<UserListResponse>;
|
|
export type UserSttsStatsList = UserSttsStatsResponse[];
|
|
export type AdminUserList = PageableList<AdminUserListResponse>;
|
|
|
|
// 사용자 서비스 인터페이스
|
|
export interface UserService {
|
|
// 사용자 목록 조회
|
|
findPageUser: (params: UserSearchParams) => Promise<UserList>;
|
|
|
|
// 사용자 단건 조회
|
|
findByUserUnqId: (userUnqId: string) => Promise<UserDetailResponse>;
|
|
|
|
// 로그인한 사용자 정보 조회
|
|
findByUserUnqIdByLogin: () => Promise<UserDetailResponse>;
|
|
|
|
// 사용자 회원상태 통계 조회
|
|
selectUserSttsStats: () => Promise<UserSttsStatsList>;
|
|
|
|
// 사용자 저장
|
|
saveUser: (data: UserSaveData) => Promise<string>;
|
|
|
|
// 사용자 수정
|
|
updateUser: (userUnqId: string, data: UserUpdateData) => Promise<string>;
|
|
|
|
// 사용자 삭제
|
|
deleteUser: (userUnqId: string) => Promise<boolean>;
|
|
|
|
// 사용자 계정잠금 처리
|
|
lockUser: (userUnqId: string) => Promise<boolean>;
|
|
|
|
// 사용자 계정잠금 해제처리
|
|
unlockUser: (userUnqId: string) => Promise<boolean>;
|
|
|
|
// 리프레시 토큰 정보 재발급
|
|
refreshToken: () => Promise<void>;
|
|
|
|
// 사용자 비밀번호 변경
|
|
updatePassword: (data: UserPasswordUpdateData) => Promise<boolean>;
|
|
|
|
// 사용자 비밀번호 초기화(관리자용)
|
|
initializePassword: (
|
|
userUnqId: string,
|
|
data: UserPasswordUpdateData,
|
|
) => Promise<boolean>;
|
|
|
|
// 사용자 비밀번호 찾기 변경
|
|
changePassword: (data: UserFindPasswordUpdateData) => Promise<boolean>;
|
|
|
|
// 사용자 비밀번호 확인
|
|
matchPassword: (data: UserPasswordMatchData) => Promise<boolean>;
|
|
|
|
// 사용자 비밀번호 찾기
|
|
findPasswordUser: (data: UserFindPasswordSaveData) => Promise<boolean>;
|
|
|
|
// 사용자 비밀번호 찾기 유효성 확인
|
|
validPassword: (token: string) => Promise<boolean>;
|
|
|
|
// 사용자 회원정보 변경
|
|
updateInfo: (userUnqId: string, data: UserUpdateInfoData) => Promise<string>;
|
|
|
|
// 사용자 승인처리
|
|
applyUser: (userUnqId: string) => Promise<boolean>;
|
|
|
|
// 사용자 회원탈퇴
|
|
leaveUser: (data: UserVerifyData) => Promise<boolean>;
|
|
|
|
// 사용자 이메일 중복 체크
|
|
existsEmail: (data: UserEmailData) => Promise<boolean>;
|
|
|
|
// 사용자 아이디 중복 체크
|
|
existsUserId: (data: UserIdData) => Promise<boolean>;
|
|
|
|
// 관리자 목록 조회
|
|
findPageAdminUser: (params: UserSearchParams) => Promise<AdminUserList>;
|
|
}
|