refactor(auth): replace 2FA string sentinel with typed error
Use a dedicated TwoFactorRequiredError and shared type guard to keep login flow checks type-safe and less brittle than matching magic strings. Made-with: Cursor
This commit is contained in:
+6
-5
@@ -1,6 +1,10 @@
|
||||
import { api } from '@/lib/api'
|
||||
import { resetHeicodeAuthenticatedSession } from '@/features/auth/heicode-authenticated-session'
|
||||
import { saveUserId } from '@/features/auth/lib/storage'
|
||||
import {
|
||||
isTwoFactorRequiredError,
|
||||
TwoFactorRequiredError,
|
||||
} from '@/features/auth/errors'
|
||||
import type {
|
||||
LoginPayload,
|
||||
LoginResponse,
|
||||
@@ -72,7 +76,7 @@ async function establishManagerCookieSession(payload: LoginPayload) {
|
||||
throw new Error(body?.message || 'Unable to establish Manager session')
|
||||
}
|
||||
if (body.data?.require_2fa) {
|
||||
throw new Error('TWO_FACTOR_REQUIRED')
|
||||
throw new TwoFactorRequiredError()
|
||||
}
|
||||
if (body.data?.id != null) {
|
||||
saveUserId(body.data.id)
|
||||
@@ -151,10 +155,7 @@ export async function login(payload: LoginPayload) {
|
||||
try {
|
||||
await establishManagerCookieSession(payload)
|
||||
} catch (syncErr) {
|
||||
if (
|
||||
syncErr instanceof Error &&
|
||||
syncErr.message === 'TWO_FACTOR_REQUIRED'
|
||||
) {
|
||||
if (isTwoFactorRequiredError(syncErr)) {
|
||||
throw syncErr
|
||||
}
|
||||
clearHeicodeTokens()
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
export class TwoFactorRequiredError extends Error {
|
||||
constructor() {
|
||||
super('Two-factor authentication is required')
|
||||
this.name = 'TwoFactorRequiredError'
|
||||
}
|
||||
}
|
||||
|
||||
export function isTwoFactorRequiredError(
|
||||
error: unknown
|
||||
): error is TwoFactorRequiredError {
|
||||
return error instanceof TwoFactorRequiredError
|
||||
}
|
||||
@@ -71,6 +71,7 @@ export {
|
||||
getAffiliateCode,
|
||||
saveAffiliateCode,
|
||||
} from './lib/storage'
|
||||
export { TwoFactorRequiredError, isTwoFactorRequiredError } from './errors'
|
||||
|
||||
export {
|
||||
isValidOTP,
|
||||
|
||||
+2
-4
@@ -22,6 +22,7 @@ import { loginFormSchema } from '@/features/auth/constants'
|
||||
import { useAuthRedirect } from '@/features/auth/hooks/use-auth-redirect'
|
||||
import { useTurnstile } from '@/features/auth/hooks/use-turnstile'
|
||||
import { Turnstile } from '@/components/turnstile'
|
||||
import { isTwoFactorRequiredError } from '@/features/auth/errors'
|
||||
import type { AuthFormProps } from '@/features/auth/types'
|
||||
|
||||
export function UserAuthForm({
|
||||
@@ -78,10 +79,7 @@ export function UserAuthForm({
|
||||
toast.error(res.message)
|
||||
}
|
||||
} catch (error) {
|
||||
if (
|
||||
error instanceof Error &&
|
||||
error.message === 'TWO_FACTOR_REQUIRED'
|
||||
) {
|
||||
if (isTwoFactorRequiredError(error)) {
|
||||
redirectTo2FA()
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user