summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-10-13 18:24:00 +0900
committerjoonhoekim <26rote@gmail.com>2025-10-13 18:24:00 +0900
commit80e3d0befed487e0447bacffd76ed6539f01e992 (patch)
treede5762bea7161e3dd949401b2d985b6723fd32ee /lib
parentff8a168f9fc67b345f4d32065e55f0901ba05b4c (diff)
(김준회) S-GIPS 로그인시 유저 선택해 sms 전송 처리
Diffstat (limited to 'lib')
-rw-r--r--lib/users/auth/verifyCredentails.ts192
-rw-r--r--lib/users/session/helper.ts65
2 files changed, 170 insertions, 87 deletions
diff --git a/lib/users/auth/verifyCredentails.ts b/lib/users/auth/verifyCredentails.ts
index b3dcd270..b0cbd6c9 100644
--- a/lib/users/auth/verifyCredentails.ts
+++ b/lib/users/auth/verifyCredentails.ts
@@ -482,14 +482,16 @@ export async function verifySGipsCredentials(
password: string
): Promise<{
success: boolean;
- user?: {
+ otpUsers?: Array<{
id: string;
name: string;
- email: string;
+ vndrcd: string;
phone: string;
- companyId?: number;
+ email: string;
+ nation_cd: string;
+ userId?: number; // 로컬 DB 사용자 ID (없으면 생성)
vendorInfo?: any; // 벤더 추가 정보
- };
+ }>;
error?: string;
}> {
try {
@@ -535,42 +537,104 @@ export async function verifySGipsCredentials(
// 2. S-Gips API 응답 확인
if (data.message === "success" && data.code === "0") {
- // 3. username의 앞 8자리로 vendorCode 추출
- const vendorCode = username.substring(0, 8);
-
- // 4. 데이터베이스에서 벤더 정보 조회
- const vendorInfo = await getVendorByCode(vendorCode);
-
- if (!vendorInfo) {
- return {
- success: false,
- error: 'VENDOR_NOT_FOUND'
- };
+ const otpUsers = data.otpUsers || [];
+
+ if (otpUsers.length === 0) {
+ return { success: false, error: 'NO_USERS_FOUND' };
}
- // 5. 사용자 정보 구성
+ // 3. 각 OTP 사용자에 대해 로컬 DB 사용자 확인/생성
+ const processedOtpUsers = await Promise.all(
+ otpUsers.map(async (otpUser: any) => {
+ try {
+ // email로 기존 사용자 검색
+ const localUser = await db
+ .select()
+ .from(users)
+ .where(eq(users.email, otpUser.email))
+ .limit(1);
+
+ let userId: number;
+
+ if (!localUser[0]) {
+ // 사용자가 없으면 벤더코드로 벤더 정보 조회 후 새 사용자 생성
+ const vendorInfo = await getVendorByCode(otpUser.vndrcd);
+
+ if (!vendorInfo) {
+ console.warn(`벤더를 찾을 수 없음: ${otpUser.vndrcd}`);
+ // 벤더가 없어도 사용자 생성은 시도 (기본 정보로)
+ const newUser = await db
+ .insert(users)
+ .values({
+ name: otpUser.name,
+ email: otpUser.email,
+ phone: otpUser.phone,
+ domain: 'partners',
+ mfaEnabled: true,
+ })
+ .returning();
+
+ userId = newUser[0].id;
+ } else {
+ // 벤더 정보를 바탕으로 사용자 생성
+ const newUser = await db
+ .insert(users)
+ .values({
+ name: otpUser.name,
+ email: otpUser.email,
+ phone: otpUser.phone,
+ companyId: vendorInfo.id,
+ domain: 'partners',
+ mfaEnabled: true,
+ })
+ .returning();
+
+ userId = newUser[0].id;
+ }
+ } else {
+ // 기존 사용자가 있으면 S-GIPS 정보로 전화번호 업데이트
+ await db
+ .update(users)
+ .set({
+ phone: otpUser.phone,
+ name: otpUser.name,
+ })
+ .where(eq(users.id, localUser[0].id));
+
+ userId = localUser[0].id;
+ console.log(`S-GIPS 사용자 정보 업데이트: ${otpUser.email} - phone: ${otpUser.phone}`);
+ }
+
+ return {
+ id: otpUser.vndrcd || username,
+ name: otpUser.name,
+ vndrcd: otpUser.vndrcd,
+ phone: otpUser.phone,
+ email: otpUser.email,
+ nation_cd: otpUser.nation_cd,
+ userId: userId,
+ vendorInfo: otpUser.vndrcd ? await getVendorByCode(otpUser.vndrcd) : null,
+ };
+ } catch (error) {
+ console.error(`OTP 사용자 처리 중 오류: ${otpUser.email}`, error);
+ // 오류가 발생해도 다른 사용자는 처리 계속
+ return {
+ id: otpUser.vndrcd || username,
+ name: otpUser.name,
+ vndrcd: otpUser.vndrcd,
+ phone: otpUser.phone,
+ email: otpUser.email,
+ nation_cd: otpUser.nation_cd,
+ userId: undefined, // 생성 실패
+ vendorInfo: null,
+ };
+ }
+ })
+ );
+
return {
success: true,
- user: {
- id: username, // 또는 vendorInfo.id를 사용
- name: vendorInfo.representativeName || vendorInfo.vendorName,
- email: vendorInfo.representativeEmail || vendorInfo.email || '',
- phone: vendorInfo.representativePhone || vendorInfo.phone || '',
- companyId: vendorInfo.id,
- vendorInfo: {
- vendorName: vendorInfo.vendorName,
- vendorCode: vendorInfo.vendorCode,
- status: vendorInfo.status,
- taxId: vendorInfo.taxId,
- address: vendorInfo.address,
- country: vendorInfo.country,
- website: vendorInfo.website,
- vendorTypeId: vendorInfo.vendorTypeId,
- businessSize: vendorInfo.businessSize,
- creditRating: vendorInfo.creditRating,
- cashFlowRating: vendorInfo.cashFlowRating,
- }
- },
+ otpUsers: processedOtpUsers.filter(user => user.userId !== undefined), // userId가 있는 사용자만 반환
};
}
@@ -589,15 +653,16 @@ export async function authenticateWithSGips(
password: string
): Promise<{
success: boolean;
- user?: {
- id: number;
+ otpUsers?: Array<{
+ id: string;
name: string;
+ vndrcd: string;
+ phone: string;
email: string;
- imageUrl?: string | null;
- companyId?: number | null;
- techCompanyId?: number | null;
- domain?: string | null;
- };
+ nation_cd: string;
+ userId: number;
+ vendorInfo?: any;
+ }>;
requiresMfa: boolean;
mfaToken?: string;
error?: string;
@@ -606,7 +671,7 @@ export async function authenticateWithSGips(
// 1. S-Gips API로 인증
const sgipsResult = await verifySGipsCredentials(username, password);
- if (!sgipsResult.success || !sgipsResult.user) {
+ if (!sgipsResult.success || !sgipsResult.otpUsers || sgipsResult.otpUsers.length === 0) {
return {
success: false,
requiresMfa: false,
@@ -614,45 +679,12 @@ export async function authenticateWithSGips(
};
}
- // 2. 로컬 DB에서 사용자 확인 또는 생성
- let localUser = await db
- .select()
- .from(users)
- .where(eq(users.email, sgipsResult.user.email))
- .limit(1);
-
- if (!localUser[0]) {
- // 사용자가 없으면 새로 생성 (S-Gips 사용자는 자동 생성)
- const newUser = await db
- .insert(users)
- .values({
- name: sgipsResult.user.name,
- email: sgipsResult.user.email,
- phone: sgipsResult.user.phone,
- companyId: sgipsResult.user.companyId,
- domain: 'partners', // S-Gips 사용자는 partners 도메인
- mfaEnabled: true, // S-Gips 사용자는 MFA 필수
- })
- .returning();
-
- localUser = newUser;
- }
-
- const user = localUser[0];
-
+ // 2. verifySGipsCredentials에서 이미 사용자 생성/매핑이 완료되었으므로
+ // otpUsers 배열을 그대로 반환 (임시 인증 세션은 개별 사용자 선택 시 생성)
return {
success: true,
- user: {
- id: user.id,
- name: user.name,
- email: user.email,
- imageUrl: user.imageUrl,
- companyId: user.companyId,
- techCompanyId: user.techCompanyId,
- domain: user.domain,
- },
+ otpUsers: sgipsResult.otpUsers,
requiresMfa: true,
- // mfaToken,
};
} catch (error) {
console.error('S-Gips authentication error:', error);
diff --git a/lib/users/session/helper.ts b/lib/users/session/helper.ts
index f99ca80a..03bfd7bc 100644
--- a/lib/users/session/helper.ts
+++ b/lib/users/session/helper.ts
@@ -6,20 +6,35 @@ export const authHelpers = {
// 1차 인증 검증 및 임시 키 생성 (DB 버전)
async performFirstAuth(username: string, password: string, provider: 'email' | 'sgips') {
console.log('performFirstAuth started:', { username, provider })
-
+
try {
let authResult;
-
+
if (provider === 'sgips') {
authResult = await authenticateWithSGips(username, password)
} else {
authResult = await verifyExternalCredentials(username, password)
}
-
- if (!authResult.success || !authResult.user) {
+
+ if (!authResult.success) {
return { success: false, error: authResult.error || 'INVALID_CREDENTIALS' }
}
-
+
+ // S-GIPS의 경우 otpUsers 배열 반환
+ if (provider === 'sgips' && authResult.otpUsers) {
+ console.log('S-GIPS auth successful with otpUsers:', authResult.otpUsers.length)
+
+ return {
+ success: true,
+ otpUsers: authResult.otpUsers
+ }
+ }
+
+ // 일반 사용자의 경우 기존 로직
+ if (!authResult.user) {
+ return { success: false, error: 'INVALID_CREDENTIALS' }
+ }
+
// DB에 임시 인증 세션 생성
const expiresAt = new Date(Date.now() + (10 * 60 * 1000)) // 10분 후 만료
const tempAuthKey = await SessionRepository.createTempAuthSession({
@@ -28,7 +43,7 @@ export const authHelpers = {
authMethod: provider,
expiresAt
})
-
+
console.log('Temp auth stored in DB:', {
tempAuthKey,
userId: authResult.user.id,
@@ -36,7 +51,7 @@ export const authHelpers = {
authMethod: provider,
expiresAt
})
-
+
return {
success: true,
tempAuthKey,
@@ -57,6 +72,42 @@ export const authHelpers = {
// 임시 인증 정보 삭제 (DB 버전)
async clearTempAuth(tempAuthKey: string) {
await SessionRepository.markTempAuthSessionAsUsed(tempAuthKey)
+ },
+
+ // 선택된 S-GIPS 사용자에 대한 임시 인증 세션 생성
+ async createTempAuthForSelectedUser(selectedUser: {
+ userId: number;
+ email: string;
+ name: string;
+ }) {
+ console.log('Creating temp auth for selected S-GIPS user:', selectedUser)
+
+ try {
+ const expiresAt = new Date(Date.now() + (10 * 60 * 1000)) // 10분 후 만료
+ const tempAuthKey = await SessionRepository.createTempAuthSession({
+ userId: selectedUser.userId,
+ email: selectedUser.email,
+ authMethod: 'sgips',
+ expiresAt
+ })
+
+ console.log('Temp auth created for selected user:', {
+ tempAuthKey,
+ userId: selectedUser.userId,
+ email: selectedUser.email,
+ expiresAt
+ })
+
+ return {
+ success: true,
+ tempAuthKey,
+ userId: selectedUser.userId,
+ email: selectedUser.email
+ }
+ } catch (error) {
+ console.error('Error creating temp auth for selected user:', error)
+ return { success: false, error: 'SYSTEM_ERROR' }
+ }
}
}
\ No newline at end of file