Merged in feat/sas-otp-error-handling (pull request #1272)

Feat/sas otp error handling

* Improve error handling for SAS OTP
* Remove failing and deprecated test

Approved-by: Joakim Jäderberg
This commit is contained in:
Anton Gunnarsson
2025-02-07 14:18:00 +00:00
parent fbe05eb456
commit 18288cb849
11 changed files with 187 additions and 94 deletions

View File

@@ -13,12 +13,15 @@ import OneTimePasswordForm from "./OneTimePasswordForm"
import type { LangParams, PageArgs, SearchParams } from "@/types/params"
import type { Lang } from "@/constants/languages"
const otpError = z.enum(["invalidCode", "expiredCode"])
const searchParamsSchema = z.object({
intent: z.enum(["link"]),
to: z.string(),
error: z.enum(["invalidCode"]).optional(),
error: otpError.optional(),
})
export type OtpError = z.infer<typeof otpError>
export default async function SASxScandicOneTimePasswordPage({
searchParams,
params,
@@ -37,37 +40,48 @@ export default async function SASxScandicOneTimePasswordPage({
redirect(`/${params.lang}/sas-x-scandic/login?intent=${intent}`)
}
const errors = {
invalidCode: intl.formatMessage({
id: "The code youve entered is incorrect.",
}),
}
async function handleOtpVerified({ otp }: { otp: string }) {
"use server"
const [data, error] = await safeTry(
serverClient().partner.sas.verifyOtp({ otp })
)
// TODO correct status?
// TODO handle all errors
// STATUS === VERIFIED => ok
// STATUS === ABUSED => otpRetryCount > otpMaxRetryCount
if (error || data?.status !== "VERIFIED") {
const search = new URLSearchParams({
...searchParams,
error: "invalidCode",
}).toString()
if (error || !data) {
throw error || new Error("OTP verification failed")
}
redirect(`/${params.lang}/sas-x-scandic/otp?${search}`)
switch (data.status) {
case "ABUSED":
redirect(
`/${params.lang}/sas-x-scandic/error?errorCode=tooManyFailedAttempts`
)
case "EXPIRED": {
const search = new URLSearchParams({
...searchParams,
error: "expiredCode",
}).toString()
redirect(`/${params.lang}/sas-x-scandic/otp?${search}`)
}
case "RETRY": {
const search = new URLSearchParams({
...searchParams,
error: "invalidCode",
}).toString()
redirect(`/${params.lang}/sas-x-scandic/otp?${search}`)
}
case "NOTSENT":
case "NULL":
case "SENT":
case "PENDING":
// These errors should never happen for verify, but according to the API spec they can
throw new Error("Unhandled OTP status")
}
switch (intent) {
case "link":
return handleLinkAccount({ lang: params.lang })
default:
throw new Error("")
}
}
@@ -93,7 +107,7 @@ export default async function SASxScandicOneTimePasswordPage({
})}
otpLength={6}
onSubmit={handleOtpVerified}
error={error ? errors[error] : undefined}
error={error}
/>
)
}