Skip to content

Commit e1a2ffe

Browse files
committed
Added resending verification emails, auto-verify after accepting invites
1 parent 0298807 commit e1a2ffe

File tree

4 files changed

+71
-6
lines changed

4 files changed

+71
-6
lines changed

app/lib/auth.server.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,10 @@ export async function login({ email, password }: LoginForm) {
7070

7171
if (!user.isVerified) {
7272
return json(
73-
{ error: `You still need to verify your email` },
73+
{
74+
error: `You still need to verify your email address.`,
75+
errorCode: "verify-email",
76+
},
7477
{ status: 400 },
7578
);
7679
}

app/routes/user.accept-invite.$inviteId.$code.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export const action: ActionFunction = async ({ request, params }) => {
5454
password: passwordHash,
5555
verifyCode: invite.verifyCode,
5656
isAdmin: invite.isAdmin,
57+
isVerified: true,
5758
},
5859
});
5960

app/routes/user.login.tsx

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ export default function Login() {
128128

129129
const errors = actionData?.errors || {};
130130
const formError = actionData?.error;
131+
const formErrorCode = actionData?.errorCode;
131132

132133
// Updates the form data when an input changes
133134
const handleInputChange = (
@@ -222,11 +223,33 @@ export default function Login() {
222223
</CardDescription>
223224
</CardHeader>
224225

225-
<Form method="POST">
226-
<CardContent className="grid gap-4">
227-
<div className="text-xs font-semibold text-center tracking-wide text-red-500 w-full">
226+
<CardContent className="grid gap-4">
227+
{formError && (
228+
<div className="w-full font-semibold text-sm tracking-wide text-red-500 border border-red-500 rounded p-2 flex flex-col justify-center items-center gap-2">
228229
{formError}
230+
{formErrorCode &&
231+
formErrorCode === "verify-email" && (
232+
<Form
233+
action="/user/verification/resend"
234+
method="POST"
235+
>
236+
<input
237+
type="hidden"
238+
name="email"
239+
value={formData.email}
240+
/>
241+
<Button
242+
variant="outline"
243+
size="sm"
244+
type="submit"
245+
>
246+
Resend email
247+
</Button>
248+
</Form>
249+
)}
229250
</div>
251+
)}
252+
<Form method="POST">
230253
<FormField
231254
htmlFor="email"
232255
label="Email"
@@ -308,8 +331,8 @@ export default function Login() {
308331
: "Sign In"}
309332
</Button>
310333
</div>
311-
</CardContent>
312-
</Form>
334+
</Form>
335+
</CardContent>
313336
</Card>
314337
<div className="grow flex flex-row justify-center items-end gap-4 pb-5 text-xs">
315338
{org.imprintUrl && (
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import type { ActionFunction } from "@remix-run/node";
2+
import { redirect } from "@remix-run/node";
3+
import { prisma } from "~/lib/prisma.server";
4+
import { sendVerificationEmail } from "~/lib/user.server";
5+
import { validateEmail } from "~/lib/validators.server";
6+
7+
export const action: ActionFunction = async ({ request }) => {
8+
const form = await request.formData();
9+
const email = form.get("email");
10+
const emailError = validateEmail(email);
11+
12+
if (emailError) {
13+
return new Response(null, {
14+
status: 400,
15+
statusText: emailError,
16+
});
17+
}
18+
19+
const user = await prisma.user.findUnique({
20+
where: {
21+
email,
22+
},
23+
});
24+
25+
if (!user) {
26+
throw new Response(null, {
27+
status: 404,
28+
statusText: "Not Found",
29+
});
30+
}
31+
32+
if (user.isVerified) {
33+
return redirect("/user/login");
34+
} else {
35+
await sendVerificationEmail(user);
36+
return redirect("/user/verification-info");
37+
}
38+
};

0 commit comments

Comments
 (0)