Merge pull request #557 from specklesystems/emailVerification
Email verification again
This commit is contained in:
@@ -49,9 +49,9 @@
|
||||
</v-app-bar>
|
||||
<v-main class="background">
|
||||
<email-verification-banner
|
||||
v-if="!user.verified"
|
||||
v-if="user && !user.verified"
|
||||
:user="user"
|
||||
class="my-2 mx-4"
|
||||
class="my-2 mx-4 email-banner"
|
||||
></email-verification-banner>
|
||||
<v-container fluid class="px-4">
|
||||
<transition name="fade">
|
||||
@@ -74,9 +74,7 @@ export default {
|
||||
SearchBar: () => import('@/cleanup/components/common/SearchBar'),
|
||||
GlobalToast: () => import('@/cleanup/components/common/GlobalToast'),
|
||||
GlobalLoading: () => import('@/cleanup/components/common/GlobalLoading'),
|
||||
EmailVerificationBanner: () => {
|
||||
return import('@/cleanup/components/user/EmailVerificationBanner')
|
||||
}
|
||||
EmailVerificationBanner: () => import('@/cleanup/components/user/EmailVerificationBanner')
|
||||
},
|
||||
apollo: {
|
||||
serverInfo: {
|
||||
@@ -205,4 +203,7 @@ export default {
|
||||
opacity: 0.5;
|
||||
width: 0px;
|
||||
}
|
||||
.email-banner {
|
||||
z-index: 2;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,7 +3,7 @@ const knex = require( `${appRoot}/db/knex` )
|
||||
|
||||
const { getUserByEmail } = require( `${appRoot}/modules/core/services/users` )
|
||||
const { contextMiddleware } = require( `${appRoot}/modules/shared` )
|
||||
const { sendEmailVerification } = require( '../services/verification' )
|
||||
const { sendEmailVerification, isVerificationValid } = require( '../services/verification' )
|
||||
|
||||
const Verifications = () => knex( 'email_verifications' )
|
||||
const Users = () => knex( 'users' )
|
||||
@@ -35,6 +35,8 @@ module.exports = ( app ) => {
|
||||
|
||||
return res.status( 200 ).send( 'Email verification initiated.' )
|
||||
} catch ( error ) {
|
||||
if ( error.message.includes( 'You already have a valid' ) )
|
||||
return res.status( 400 ).send( error.message )
|
||||
return res.status( 500 ).send( error.message )
|
||||
}
|
||||
},
|
||||
@@ -51,8 +53,7 @@ module.exports = ( app ) => {
|
||||
return res.status( 404 ).send( 'No verification with this token.' )
|
||||
}
|
||||
|
||||
const timeDiff = Math.abs( Date.now() - new Date( verification.createdAt ) )
|
||||
if ( timeDiff > 8.64e+7 ) {
|
||||
if ( !isVerificationValid( verification ) ) {
|
||||
return res
|
||||
.status( 400 )
|
||||
.send( 'Verification expired, please request a new one.' )
|
||||
|
||||
@@ -12,6 +12,10 @@ const sendEmailVerification = async ( { recipient } ) => {
|
||||
// we need to validate email here, since we'll send it out,
|
||||
// even if technically there is no chance ATM that an incorrect addr comes in
|
||||
const serverInfo = await getServerInfo()
|
||||
const existingVerifications = await Verifications()
|
||||
.where( { 'email': recipient } )
|
||||
if ( existingVerifications.some( ver => isVerificationValid( ver ) ) )
|
||||
throw new Error( 'You already have a valid verification message, please check your inbox' )
|
||||
const verificationId = await createEmailVerification( { 'email': recipient } )
|
||||
const verificationLink = new URL(
|
||||
`auth/verifyemail?t=${verificationId}`, process.env.CANONICAL_URL,
|
||||
@@ -27,6 +31,11 @@ const sendEmailVerification = async ( { recipient } ) => {
|
||||
} )
|
||||
}
|
||||
|
||||
const isVerificationValid = ( { createdAt } ) => {
|
||||
const timeDiff = Math.abs( Date.now() - new Date( createdAt ) )
|
||||
return timeDiff < 8.64e+7
|
||||
}
|
||||
|
||||
const prepareMessage = async ( { verificationLink, serverInfo } ) => {
|
||||
const subject = `Speckle Server ${serverInfo.name} email verification`
|
||||
const text = `
|
||||
@@ -90,4 +99,4 @@ const createEmailVerification = async ( { email } ) => {
|
||||
return verification.id
|
||||
}
|
||||
|
||||
module.exports = { sendEmailVerification }
|
||||
module.exports = { sendEmailVerification, isVerificationValid }
|
||||
|
||||
@@ -68,6 +68,8 @@ describe( 'Email verifications @emails', () => {
|
||||
|
||||
expect( sentResult.message ).to.contain( expectedVerificationUrl )
|
||||
|
||||
await Verifications( ).where( { id: ver.id } ).del()
|
||||
|
||||
await request( expressApp )
|
||||
.post( '/auth/emailverification/request' )
|
||||
.send( { email: userA.email } )
|
||||
@@ -87,6 +89,23 @@ describe( 'Email verifications @emails', () => {
|
||||
.set( 'Authorization', userB.token )
|
||||
.expect( 403 )
|
||||
} )
|
||||
it( 'Should not create a new verification while the previous is valid', async () => {
|
||||
await request( expressApp )
|
||||
.post( '/auth/emailverification/request' )
|
||||
.send( { email: userA.email } )
|
||||
.set( 'Authorization', userA.token )
|
||||
.expect( 400 )
|
||||
} )
|
||||
it( 'Should create a new verification if the previous is invalid', async () => {
|
||||
await Verifications().where( { email: userA.email } )
|
||||
.update( { createdAt: new Date( 0 ) } )
|
||||
|
||||
await request( expressApp )
|
||||
.post( '/auth/emailverification/request' )
|
||||
.send( { email: userA.email } )
|
||||
.set( 'Authorization', userA.token )
|
||||
.expect( 200 )
|
||||
} )
|
||||
} )
|
||||
describe( 'Use email verification', () => {
|
||||
it( 'Should not verify without a token', async () => {
|
||||
@@ -125,7 +144,7 @@ describe( 'Email verifications @emails', () => {
|
||||
expect( verifications ).to.have.lengthOf( 2 )
|
||||
|
||||
await request( expressApp )
|
||||
.get( `/auth/verifyemail?t=${verifications[0].id}` )
|
||||
.get( `/auth/verifyemail?t=${verifications[1].id}` )
|
||||
.expect( 302 )
|
||||
|
||||
verifications = await Verifications().where( { email: userA.email } )
|
||||
|
||||
Reference in New Issue
Block a user