관리자 레이아웃과 네비게이션 정리

This commit is contained in:
2026-05-13 10:23:18 +09:00
parent ec9f9ea57f
commit b490d5b90f
17 changed files with 484 additions and 164 deletions

View File

@@ -37,6 +37,38 @@ export const invalidatePendingOtpChallenges = async (sql, email, purpose) => {
`
}
/**
* 특정 OTP를 제외한 동일 이메일·용도의 미소진 OTP를 무효화한다.
* @param {import('postgres').TransactionSql} sql - sql 또는 트랜잭션
* @param {string} email - 정규화된 이메일
* @param {string} purpose - signup | password_reset
* @param {string} keepId - 유지할 챌린지 ID
* @returns {Promise<void>}
*/
export const invalidatePendingOtpChallengesExcept = async (sql, email, purpose, keepId) => {
await sql`
UPDATE email_otp_challenges
SET consumed_at = now()
WHERE lower(email) = lower(${email})
AND purpose = ${purpose}
AND id <> ${keepId}
AND consumed_at IS NULL
`
}
/**
* 특정 OTP 챌린지를 삭제한다.
* @param {import('postgres').TransactionSql} sql - sql 또는 트랜잭션
* @param {string} id - 챌린지 ID
* @returns {Promise<void>}
*/
export const deleteOtpChallengeById = async (sql, id) => {
await sql`
DELETE FROM email_otp_challenges
WHERE id = ${id}
`
}
/**
* 최근 짧은 시간 내 동일 이메일·용도 발송이 있는지 확인한다.
* @param {import('postgres').Sql} sql - sql