Skip to content

Commit 0311c59

Browse files
committed
Handle errors in the management action
1 parent cb59c75 commit 0311c59

File tree

1 file changed

+70
-60
lines changed
  • apps/webapp/app/routes/resources.account.mfa.setup

1 file changed

+70
-60
lines changed

apps/webapp/app/routes/resources.account.mfa.setup/route.tsx

Lines changed: 70 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { ActionFunctionArgs } from "@remix-run/server-runtime";
22
import { typedjson } from "remix-typedjson";
33
import { z } from "zod";
4-
import { redirectWithSuccessMessage, typedJsonWithSuccessMessage } from "~/models/message.server";
4+
import { redirectWithSuccessMessage, redirectWithErrorMessage, typedJsonWithSuccessMessage } from "~/models/message.server";
55
import { MultiFactorAuthenticationService } from "~/services/mfa/multiFactorAuthentication.server";
66
import { requireUserId } from "~/services/session.server";
7+
import { ServiceValidationError } from "~/v3/services/baseService.server";
78
import { useMfaSetup } from "./useMfaSetup";
89
import { MfaToggle } from "./MfaToggle";
910
import { MfaSetupDialog } from "./MfaSetupDialog";
@@ -49,82 +50,91 @@ function validateForm(formData: FormData) {
4950
}
5051

5152
export async function action({ request }: ActionFunctionArgs) {
52-
const userId = await requireUserId(request);
53+
try {
54+
const userId = await requireUserId(request);
5355

54-
const formData = await request.formData();
56+
const formData = await request.formData();
5557

56-
const submission = validateForm(formData);
57-
58-
if (!submission.valid) {
59-
return typedjson({
60-
action: "invalid-form" as const,
61-
errors: submission.errors,
62-
});
63-
}
64-
65-
const mfaSetupService = new MultiFactorAuthenticationService();
66-
67-
switch (submission.data.action) {
68-
case "enable-mfa": {
69-
const result = await mfaSetupService.enableTotp(userId);
58+
const submission = validateForm(formData);
7059

60+
if (!submission.valid) {
7161
return typedjson({
72-
action: "enable-mfa" as const,
73-
secret: result.secret,
74-
otpAuthUrl: result.otpAuthUrl,
62+
action: "invalid-form" as const,
63+
errors: submission.errors,
7564
});
7665
}
77-
case "disable-mfa": {
78-
const result = await mfaSetupService.disableTotp(userId, {
79-
totpCode: submission.data.totpCode,
80-
recoveryCode: submission.data.recoveryCode,
81-
});
8266

83-
if (result.success) {
84-
return typedJsonWithSuccessMessage(
85-
{
86-
action: "disable-mfa" as const,
87-
success: true as const,
88-
},
89-
request,
90-
"Successfully disabled MFA"
91-
);
92-
} else {
67+
const mfaSetupService = new MultiFactorAuthenticationService();
68+
69+
switch (submission.data.action) {
70+
case "enable-mfa": {
71+
const result = await mfaSetupService.enableTotp(userId);
72+
9373
return typedjson({
94-
action: "disable-mfa" as const,
95-
success: false as const,
96-
error: "Invalid code provided. Please try again.",
74+
action: "enable-mfa" as const,
75+
secret: result.secret,
76+
otpAuthUrl: result.otpAuthUrl,
9777
});
9878
}
99-
}
100-
case "validate-totp": {
101-
const result = await mfaSetupService.validateTotpSetup(userId, submission.data.totpCode);
79+
case "disable-mfa": {
80+
const result = await mfaSetupService.disableTotp(userId, {
81+
totpCode: submission.data.totpCode,
82+
recoveryCode: submission.data.recoveryCode,
83+
});
10284

103-
if (result.success) {
85+
if (result.success) {
86+
return typedJsonWithSuccessMessage(
87+
{
88+
action: "disable-mfa" as const,
89+
success: true as const,
90+
},
91+
request,
92+
"Successfully disabled MFA"
93+
);
94+
} else {
95+
return typedjson({
96+
action: "disable-mfa" as const,
97+
success: false as const,
98+
error: "Invalid code provided. Please try again.",
99+
});
100+
}
101+
}
102+
case "validate-totp": {
103+
const result = await mfaSetupService.validateTotpSetup(userId, submission.data.totpCode);
104+
105+
if (result.success) {
106+
return typedjson({
107+
action: "validate-totp" as const,
108+
success: true as const,
109+
recoveryCodes: result.recoveryCodes,
110+
});
111+
} else {
112+
return typedjson({
113+
action: "validate-totp" as const,
114+
success: false as const,
115+
error: "Invalid code provided. Please try again.",
116+
otpAuthUrl: result.otpAuthUrl,
117+
secret: result.secret,
118+
});
119+
}
120+
}
121+
case "cancel-totp": {
104122
return typedjson({
105-
action: "validate-totp" as const,
123+
action: "cancel-totp" as const,
106124
success: true as const,
107-
recoveryCodes: result.recoveryCodes,
108-
});
109-
} else {
110-
return typedjson({
111-
action: "validate-totp" as const,
112-
success: false as const,
113-
error: "Invalid code provided. Please try again.",
114-
otpAuthUrl: result.otpAuthUrl,
115-
secret: result.secret,
116125
});
117126
}
127+
case "saved-recovery-codes": {
128+
return redirectWithSuccessMessage("/account/security", request, "Successfully enabled MFA");
129+
}
118130
}
119-
case "cancel-totp": {
120-
return typedjson({
121-
action: "cancel-totp" as const,
122-
success: true as const,
123-
});
124-
}
125-
case "saved-recovery-codes": {
126-
return redirectWithSuccessMessage("/account/security", request, "Successfully enabled MFA");
131+
} catch (error) {
132+
if (error instanceof ServiceValidationError) {
133+
return redirectWithErrorMessage("/account/security", request, error.message);
127134
}
135+
136+
// Re-throw unexpected errors
137+
throw error;
128138
}
129139
}
130140

0 commit comments

Comments
 (0)