summaryrefslogtreecommitdiff
path: root/lib/users
diff options
context:
space:
mode:
Diffstat (limited to 'lib/users')
-rw-r--r--lib/users/auth/passwordUtil.ts83
1 files changed, 75 insertions, 8 deletions
diff --git a/lib/users/auth/passwordUtil.ts b/lib/users/auth/passwordUtil.ts
index 4d5d69f6..e4090aee 100644
--- a/lib/users/auth/passwordUtil.ts
+++ b/lib/users/auth/passwordUtil.ts
@@ -786,21 +786,21 @@ export async function verifyEmailToken(
)
)
.limit(1);
-
+
if (!mfaToken[0]) {
return { success: false, error: '잘못된 인증번호입니다' };
}
-
+
// 만료 체크
if (mfaToken[0].expiresAt < new Date()) {
await db
.update(mfaTokens)
.set({ isActive: false })
.where(eq(mfaTokens.id, mfaToken[0].id));
-
+
return { success: false, error: '인증번호가 만료되었습니다' };
}
-
+
// 시도 횟수 증가
const newAttempts = mfaToken[0].attempts + 1;
if (newAttempts > 3) {
@@ -808,10 +808,10 @@ export async function verifyEmailToken(
.update(mfaTokens)
.set({ isActive: false })
.where(eq(mfaTokens.id, mfaToken[0].id));
-
+
return { success: false, error: '시도 횟수를 초과했습니다' };
}
-
+
// 토큰 사용 처리
await db
.update(mfaTokens)
@@ -821,15 +821,82 @@ export async function verifyEmailToken(
attempts: newAttempts,
})
.where(eq(mfaTokens.id, mfaToken[0].id));
-
+
return { success: true };
-
+
} catch (error) {
console.error('Email token verification error:', error);
return { success: false, error: '인증 중 오류가 발생했습니다' };
}
}
+// ========== 입찰 공고 알림 SMS 전송 ==========
+
+// 입찰 공고 알림 SMS 템플릿
+const BIDDING_NOTICE_SMS_TEMPLATES = {
+ '82': '[입찰공고] {title} 입찰이 생성되었습니다. 확인 부탁드립니다.', // 한국
+ '1': '[Bidding Notice] {title} bidding has been created. Please check.', // 미국
+ '81': '[入札公告] {title} 入札が作成されました。ご確認ください。', // 일본
+ '86': '[招标公告] {title} 投标已创建。请确认。', // 중국
+ 'default': '[입찰공고] {title} 입찰이 생성되었습니다. 확인 부탁드립니다.' // 기본값 (한국어)
+} as const;
+
+// 입찰 공고 알림용 SMS 메시지 생성
+function getBiddingNoticeSmsMessage(phoneNumber: string, title: string): string {
+ try {
+ const countryInfo = extractCountryInfo(phoneNumber);
+ if (!countryInfo) {
+ return BIDDING_NOTICE_SMS_TEMPLATES.default.replace('{title}', title);
+ }
+
+ const template = BIDDING_NOTICE_SMS_TEMPLATES[countryInfo.countryCode as keyof typeof BIDDING_NOTICE_SMS_TEMPLATES] || BIDDING_NOTICE_SMS_TEMPLATES.default;
+ return template.replace('{title}', title);
+ } catch (error) {
+ return BIDDING_NOTICE_SMS_TEMPLATES.default.replace('{title}', title); // 에러 시 기본값
+ }
+}
+
+// 입찰 공고 알림 SMS 전송
+export async function sendBiddingNoticeSms(
+ phoneNumber: string,
+ biddingTitle: string
+): Promise<{ success: boolean; error?: string }> {
+ try {
+ // 전화번호 유효성 검사
+ if (!isValidPhoneNumber(phoneNumber)) {
+ console.log(`Invalid phone number format: ${phoneNumber}`);
+ return { success: false, error: '유효하지 않은 전화번호입니다' };
+ }
+
+ // 전화번호 정규화
+ const normalizedPhone = normalizePhoneNumber(phoneNumber);
+ if (!normalizedPhone) {
+ console.log(`Failed to normalize phone number: ${phoneNumber}`);
+ return { success: false, error: '전화번호 형식이 올바르지 않습니다' };
+ }
+
+ // 메시지 생성
+ const message = getBiddingNoticeSmsMessage(normalizedPhone, biddingTitle);
+
+ console.log(`Sending bidding notice SMS to ${normalizedPhone}: ${message}`);
+
+ // SMS 전송
+ const smsResult = await sendSmsMessage(normalizedPhone, message);
+
+ if (smsResult) {
+ console.log(`Bidding notice SMS sent successfully to ${normalizedPhone}`);
+ return { success: true };
+ } else {
+ console.error(`Failed to send bidding notice SMS to ${normalizedPhone}`);
+ return { success: false, error: 'SMS 전송에 실패했습니다' };
+ }
+
+ } catch (error) {
+ console.error('Bidding notice SMS send error:', error);
+ return { success: false, error: 'SMS 전송 중 오류가 발생했습니다' };
+ }
+}
+
// 패스워드 강제 변경 필요 체크
export async function checkPasswordChangeRequired(userId: number): Promise<boolean> {
const user = await db