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>
This commit is contained in:
		
							parent
							
								
									a669ec832b
								
							
						
					
					
						commit
						dbbd9477fd
					
				@ -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,
 | 
			
		||||
 | 
			
		||||
@ -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 (
 | 
			
		||||
    <StaticLayout>
 | 
			
		||||
      <div className='p-4 text-center'>
 | 
			
		||||
@ -35,14 +45,14 @@ export default function Email () {
 | 
			
		||||
          <Image className='rounded-1 shadow-sm' width='640' height='302' src={`${process.env.NEXT_PUBLIC_ASSET_PREFIX}/cowboy-saloon.gif`} fluid />
 | 
			
		||||
        </video>
 | 
			
		||||
        <h2 className='pt-4'>Check your email</h2>
 | 
			
		||||
        <h4 className='text-muted pt-2 pb-4'>a magic code has been sent to {callback ? callback.email : 'your email address'}</h4>
 | 
			
		||||
        <MagicCodeForm onSubmit={(token) => pushCallback(token)} disabled={!callback} />
 | 
			
		||||
        <h4 className='text-muted pt-2 pb-4'>{buildMessage()}</h4>
 | 
			
		||||
        <MagicCodeForm onSubmit={(token) => pushCallback(token)} disabled={!callback} signin={signin} />
 | 
			
		||||
      </div>
 | 
			
		||||
    </StaticLayout>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const MagicCodeForm = ({ onSubmit, disabled }) => {
 | 
			
		||||
export const MagicCodeForm = ({ onSubmit, disabled, signin }) => {
 | 
			
		||||
  return (
 | 
			
		||||
    <Form
 | 
			
		||||
      initial={{
 | 
			
		||||
@ -64,7 +74,7 @@ export const MagicCodeForm = ({ onSubmit, disabled }) => {
 | 
			
		||||
        hideError // hide error message on every input, allow custom error message
 | 
			
		||||
        disabled={disabled} // disable the form if no callback is provided
 | 
			
		||||
      />
 | 
			
		||||
      <SubmitButton variant='primary' className='px-4' disabled={disabled}>login</SubmitButton>
 | 
			
		||||
      <SubmitButton variant='primary' className='px-4' disabled={disabled}>{signin ? 'login' : 'signup'}</SubmitButton>
 | 
			
		||||
    </Form>
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user