1
1
import { InboxArrowDownIcon } from "@heroicons/react/24/solid" ;
2
2
import type { ActionFunctionArgs , LoaderFunctionArgs } from "@remix-run/node" ;
3
3
import { redirect } from "@remix-run/node" ;
4
- import { Form , useNavigation } from "@remix-run/react" ;
4
+ import { Form , useActionData , useNavigation } from "@remix-run/react" ;
5
5
import { getMatchesData , metaV1 } from "@remix-run/v1-meta" ;
6
6
import {
7
7
TypedMetaFunction ,
@@ -74,6 +74,18 @@ export async function action({ request }: ActionFunctionArgs) {
74
74
. parse ( payload ) ;
75
75
76
76
if ( action === "send" ) {
77
+ const { email } = z
78
+ . object ( {
79
+ email : z . string ( ) . email ( ) ,
80
+ } )
81
+ . parse ( payload ) ;
82
+
83
+ if ( process . env . WHITELISTED_EMAILS && ! new RegExp ( process . env . WHITELISTED_EMAILS ) . test ( email ) ) {
84
+ return {
85
+ error : "This email is unauthorized" ,
86
+ } ;
87
+ }
88
+
77
89
return authenticator . authenticate ( "email-link" , request , {
78
90
successRedirect : "/login/magic" ,
79
91
failureRedirect : "/login/magic" ,
@@ -92,6 +104,7 @@ export async function action({ request }: ActionFunctionArgs) {
92
104
93
105
export default function LoginMagicLinkPage ( ) {
94
106
const { magicLinkSent, magicLinkError } = useTypedLoaderData < typeof loader > ( ) ;
107
+ const actionData = useActionData < typeof action > ( ) ;
95
108
const navigate = useNavigation ( ) ;
96
109
97
110
const isLoading =
@@ -176,6 +189,7 @@ export default function LoginMagicLinkPage() {
176
189
/>
177
190
{ isLoading ? "Sending…" : "Send a magic link" }
178
191
</ Button >
192
+ { actionData ?. error && < FormError > { actionData ?. error } </ FormError > }
179
193
{ magicLinkError && < FormError > { magicLinkError } </ FormError > }
180
194
</ Fieldset >
181
195
< Paragraph variant = "extra-small" className = "mb-4 mt-6 text-center" >
0 commit comments