From dbbd9477fde552e717c4f9269fc62f1be8fe567a Mon Sep 17 00:00:00 2001
From: soxa <6390896+Soxasora@users.noreply.github.com>
Date: Thu, 20 Mar 2025 21:32:31 +0100
Subject: [PATCH] don't send a verification email during sign in if no match
 (#1999)
* don't send verification email on signin if there's no matching user, update email.js message
* conditional magic code message; signup/signin button
* unnecessary useCallback
* switch to cookie parsing lib
---------
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
---
 pages/api/auth/[...nextauth].js | 13 +++++++++----
 pages/email.js                  | 18 ++++++++++++++----
 2 files changed, 23 insertions(+), 8 deletions(-)
diff --git a/pages/api/auth/[...nextauth].js b/pages/api/auth/[...nextauth].js
index e0fc6ebf..8070d6ea 100644
--- a/pages/api/auth/[...nextauth].js
+++ b/pages/api/auth/[...nextauth].js
@@ -223,7 +223,7 @@ async function nostrEventAuth (event) {
 }
 
 /** @type {import('next-auth/providers').Provider[]} */
-const getProviders = res => [
+const getProviders = (req, res) => [
   CredentialsProvider({
     id: 'lightning',
     name: 'Lightning',
@@ -275,14 +275,14 @@ const getProviders = res => [
     from: process.env.LOGIN_EMAIL_FROM,
     maxAge: 5 * 60, // expires in 5 minutes
     generateVerificationToken: generateRandomString,
-    sendVerificationRequest
+    sendVerificationRequest: (...args) => sendVerificationRequest(...args, req)
   })
 ]
 
 /** @returns {import('next-auth').AuthOptions} */
 export const getAuthOptions = (req, res) => ({
   callbacks: getCallbacks(req, res),
-  providers: getProviders(res),
+  providers: getProviders(req, res),
   adapter: {
     ...PrismaAdapter(prisma),
     createUser: data => {
@@ -421,7 +421,7 @@ async function sendVerificationRequest ({
   url,
   token,
   provider
-}) {
+}, req) {
   let user = await prisma.user.findUnique({
     where: {
       // Look for the user by hashed email
@@ -443,6 +443,11 @@ async function sendVerificationRequest ({
 
     const site = new URL(url).host
 
+    // if we're trying to sign in but no user was found, resolve the promise
+    if (req.cookies.signin && !user) {
+      return resolve()
+    }
+
     nodemailer.createTransport(server).sendMail(
       {
         to: email,
diff --git a/pages/email.js b/pages/email.js
index c455accc..0e7a8d5a 100644
--- a/pages/email.js
+++ b/pages/email.js
@@ -1,4 +1,5 @@
 import Image from 'react-bootstrap/Image'
+import * as cookie from 'cookie'
 import { StaticLayout } from '@/components/layout'
 import { getGetServerSideProps } from '@/api/ssrApollo'
 import { useRouter } from 'next/router'
@@ -12,8 +13,10 @@ export const getServerSideProps = getGetServerSideProps({ query: null })
 export default function Email () {
   const router = useRouter()
   const [callback, setCallback] = useState(null) // callback.email, callback.callbackUrl
+  const [signin, setSignin] = useState(false)
 
   useEffect(() => {
+    setSignin(!!cookie.parse(document.cookie).signin)
     setCallback(JSON.parse(window.sessionStorage.getItem('callback')))
   }, [])
 
@@ -27,6 +30,13 @@ export default function Email () {
     router.push(url)
   }, [callback, router])
 
+  const buildMessage = () => {
+    const email = callback?.email || 'your email address'
+    return signin
+      ? `if there's a match, a magic code will be sent to ${email}`
+      : `a magic code has been sent to ${email}`
+  }
+
   return (
     Check your email
-        a magic code has been sent to {callback ? callback.email : 'your email address'}
-        {buildMessage()}
+