2018-09-01 13:58:06 -04:00
'use strict' ;
2016-07-19 01:10:36 -05:00
2023-01-09 08:02:12 +11:00
const Auth = require ( '../lib/Auth' ) ;
2018-07-02 23:30:14 -04:00
const Config = require ( '../lib/Config' ) ;
2018-09-24 17:07:51 -04:00
const request = require ( '../lib/request' ) ;
2024-01-06 16:41:13 +01:00
const MockEmailAdapterWithOptions = require ( './support/MockEmailAdapterWithOptions' ) ;
2016-07-19 01:10:36 -05:00
2018-09-01 13:58:06 -04:00
describe ( 'Email Verification Token Expiration: ' , ( ) => {
2017-05-10 14:02:16 +01:00
it ( 'show the invalid verification link page, if the user clicks on the verify email link after the email verify token expires' , done => {
2018-02-17 09:55:30 -05:00
const user = new Parse . User ( ) ;
let sendEmailOptions ;
const emailAdapter = {
2016-07-19 01:10:36 -05:00
sendVerificationEmail : options => {
sendEmailOptions = options ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
} ;
2016-07-19 01:10:36 -05:00
reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 0.5 , // 0.5 second
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-07-19 01:10:36 -05:00
} )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'testEmailVerifyTokenValidity' ) ;
user . setPassword ( 'expiringToken' ) ;
2017-06-20 09:15:26 -07:00
user . set ( 'email' , 'user@parse.com' ) ;
return user . signUp ( ) ;
2018-09-01 13:58:06 -04:00
} )
. then ( ( ) => {
// wait for 1 second - simulate user behavior to some extent
2017-06-20 09:15:26 -07:00
setTimeout ( ( ) => {
expect ( sendEmailOptions ) . not . toBeUndefined ( ) ;
2016-07-19 01:10:36 -05:00
2018-09-24 17:07:51 -04:00
request ( {
url : sendEmailOptions . link ,
followRedirects : false ,
} ) . then ( response => {
expect ( response . status ) . toEqual ( 302 ) ;
expect ( response . text ) . toEqual (
'Found. Redirecting to http://localhost:8378/1/apps/invalid_verification_link.html?username=testEmailVerifyTokenValidity&appId=test'
) ;
done ( ) ;
} ) ;
2017-06-20 09:15:26 -07:00
} , 1000 ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( err => {
2017-06-20 09:15:26 -07:00
jfail ( err ) ;
done ( ) ;
} ) ;
2016-07-19 01:10:36 -05:00
} ) ;
2016-08-15 16:48:39 -04:00
it ( 'emailVerified should set to false, if the user does not verify their email before the email verify token expires' , done => {
2018-02-17 09:55:30 -05:00
const user = new Parse . User ( ) ;
let sendEmailOptions ;
const emailAdapter = {
2016-07-19 01:10:36 -05:00
sendVerificationEmail : options => {
sendEmailOptions = options ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
} ;
2016-07-19 01:10:36 -05:00
reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 0.5 , // 0.5 second
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-07-19 01:10:36 -05:00
} )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'testEmailVerifyTokenValidity' ) ;
user . setPassword ( 'expiringToken' ) ;
2017-06-20 09:15:26 -07:00
user . set ( 'email' , 'user@parse.com' ) ;
return user . signUp ( ) ;
2018-09-01 13:58:06 -04:00
} )
. then ( ( ) => {
// wait for 1 second - simulate user behavior to some extent
2017-06-20 09:15:26 -07:00
setTimeout ( ( ) => {
expect ( sendEmailOptions ) . not . toBeUndefined ( ) ;
2016-07-19 01:10:36 -05:00
2018-09-24 17:07:51 -04:00
request ( {
url : sendEmailOptions . link ,
followRedirects : false ,
} ) . then ( response => {
expect ( response . status ) . toEqual ( 302 ) ;
user
. fetch ( )
. then ( ( ) => {
expect ( user . get ( 'emailVerified' ) ) . toEqual ( false ) ;
done ( ) ;
} )
. catch ( error => {
jfail ( error ) ;
done ( ) ;
} ) ;
} ) ;
2017-06-20 09:15:26 -07:00
} , 1000 ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( error => {
2017-06-20 09:15:26 -07:00
jfail ( error ) ;
done ( ) ;
} ) ;
2016-07-19 01:10:36 -05:00
} ) ;
2016-08-15 16:48:39 -04:00
it ( 'if user clicks on the email verify link before email verification token expiration then show the verify email success page' , done => {
2018-02-17 09:55:30 -05:00
const user = new Parse . User ( ) ;
let sendEmailOptions ;
const emailAdapter = {
2016-07-19 01:10:36 -05:00
sendVerificationEmail : options => {
sendEmailOptions = options ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
} ;
2016-07-19 01:10:36 -05:00
reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 , // 5 seconds
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-07-19 01:10:36 -05:00
} )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'testEmailVerifyTokenValidity' ) ;
user . setPassword ( 'expiringToken' ) ;
2017-06-20 09:15:26 -07:00
user . set ( 'email' , 'user@parse.com' ) ;
return user . signUp ( ) ;
2018-09-01 13:58:06 -04:00
} )
2024-01-15 15:44:49 +01:00
. then ( ( ) => jasmine . timeout ( ) )
2018-09-01 13:58:06 -04:00
. then ( ( ) => {
2018-09-24 17:07:51 -04:00
request ( {
url : sendEmailOptions . link ,
followRedirects : false ,
} ) . then ( response => {
expect ( response . status ) . toEqual ( 302 ) ;
expect ( response . text ) . toEqual (
'Found. Redirecting to http://localhost:8378/1/apps/verify_email_success.html?username=testEmailVerifyTokenValidity'
) ;
done ( ) ;
} ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( error => {
2017-06-20 09:15:26 -07:00
jfail ( error ) ;
2016-07-19 01:10:36 -05:00
done ( ) ;
} ) ;
} ) ;
2016-08-15 16:48:39 -04:00
it ( 'if user clicks on the email verify link before email verification token expiration then emailVerified should be true' , done => {
2018-02-17 09:55:30 -05:00
const user = new Parse . User ( ) ;
let sendEmailOptions ;
const emailAdapter = {
2016-07-19 01:10:36 -05:00
sendVerificationEmail : options => {
sendEmailOptions = options ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
} ;
2016-07-19 01:10:36 -05:00
reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 , // 5 seconds
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-07-19 01:10:36 -05:00
} )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'testEmailVerifyTokenValidity' ) ;
user . setPassword ( 'expiringToken' ) ;
2017-06-20 09:15:26 -07:00
user . set ( 'email' , 'user@parse.com' ) ;
return user . signUp ( ) ;
2018-09-01 13:58:06 -04:00
} )
2024-01-15 15:44:49 +01:00
. then ( ( ) => jasmine . timeout ( ) )
2018-09-01 13:58:06 -04:00
. then ( ( ) => {
2018-09-24 17:07:51 -04:00
request ( {
url : sendEmailOptions . link ,
followRedirects : false ,
} ) . then ( response => {
expect ( response . status ) . toEqual ( 302 ) ;
user
. fetch ( )
. then ( ( ) => {
expect ( user . get ( 'emailVerified' ) ) . toEqual ( true ) ;
done ( ) ;
} )
. catch ( error => {
jfail ( error ) ;
done ( ) ;
} ) ;
} ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( error => {
2017-06-20 09:15:26 -07:00
jfail ( error ) ;
done ( ) ;
2016-07-19 01:10:36 -05:00
} ) ;
} ) ;
2016-08-15 16:48:39 -04:00
it ( 'if user clicks on the email verify link before email verification token expiration then user should be able to login' , done => {
2018-02-17 09:55:30 -05:00
const user = new Parse . User ( ) ;
let sendEmailOptions ;
const emailAdapter = {
2016-07-19 01:10:36 -05:00
sendVerificationEmail : options => {
sendEmailOptions = options ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
} ;
2016-07-19 01:10:36 -05:00
reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 , // 5 seconds
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-07-19 01:10:36 -05:00
} )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'testEmailVerifyTokenValidity' ) ;
user . setPassword ( 'expiringToken' ) ;
2017-06-20 09:15:26 -07:00
user . set ( 'email' , 'user@parse.com' ) ;
return user . signUp ( ) ;
2018-09-01 13:58:06 -04:00
} )
2024-01-15 15:44:49 +01:00
. then ( ( ) => jasmine . timeout ( ) )
2018-09-01 13:58:06 -04:00
. then ( ( ) => {
2018-09-24 17:07:51 -04:00
request ( {
url : sendEmailOptions . link ,
followRedirects : false ,
} ) . then ( response => {
expect ( response . status ) . toEqual ( 302 ) ;
Parse . User . logIn ( 'testEmailVerifyTokenValidity' , 'expiringToken' )
. then ( user => {
expect ( typeof user ) . toBe ( 'object' ) ;
expect ( user . get ( 'emailVerified' ) ) . toBe ( true ) ;
done ( ) ;
} )
. catch ( error => {
jfail ( error ) ;
done ( ) ;
} ) ;
} ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( error => {
2017-06-20 09:15:26 -07:00
jfail ( error ) ;
done ( ) ;
2016-07-19 01:10:36 -05:00
} ) ;
} ) ;
2016-08-15 16:48:39 -04:00
it ( 'sets the _email_verify_token_expires_at and _email_verify_token fields after user SignUp' , done => {
2018-02-17 09:55:30 -05:00
const user = new Parse . User ( ) ;
let sendEmailOptions ;
const emailAdapter = {
2016-07-19 01:10:36 -05:00
sendVerificationEmail : options => {
sendEmailOptions = options ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
} ;
2016-07-19 01:10:36 -05:00
reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 , // 5 seconds
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-07-19 01:10:36 -05:00
} )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
user . setUsername ( 'sets_email_verify_token_expires_at' ) ;
user . setPassword ( 'expiringToken' ) ;
user . set ( 'email' , 'user@parse.com' ) ;
return user . signUp ( ) ;
} )
. then ( ( ) => {
2017-10-23 08:43:05 -04:00
const config = Config . get ( 'test' ) ;
2023-01-09 08:02:12 +11:00
return config . database . find (
'_User' ,
{
username : 'sets_email_verify_token_expires_at' ,
} ,
{ } ,
Auth . maintenance ( config )
) ;
2017-06-20 09:15:26 -07:00
} )
. then ( results => {
expect ( results . length ) . toBe ( 1 ) ;
const user = results [ 0 ] ;
expect ( typeof user ) . toBe ( 'object' ) ;
expect ( user . emailVerified ) . toEqual ( false ) ;
expect ( typeof user . _email _verify _token ) . toBe ( 'string' ) ;
expect ( typeof user . _email _verify _token _expires _at ) . toBe ( 'object' ) ;
expect ( sendEmailOptions ) . toBeDefined ( ) ;
done ( ) ;
} )
. catch ( error => {
jfail ( error ) ;
done ( ) ;
} ) ;
2016-07-19 01:10:36 -05:00
} ) ;
2023-06-23 16:29:32 +02:00
it ( 'can conditionally send emails' , async ( ) => {
let sendEmailOptions ;
const emailAdapter = {
sendVerificationEmail : options => {
sendEmailOptions = options ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
sendMail : ( ) => { } ,
} ;
const verifyUserEmails = {
method ( req ) {
2023-12-17 01:50:19 +01:00
expect ( Object . keys ( req ) ) . toEqual ( [ 'original' , 'object' , 'master' , 'ip' , 'installationId' ] ) ;
2023-06-23 16:29:32 +02:00
return false ;
} ,
} ;
const verifySpy = spyOn ( verifyUserEmails , 'method' ) . and . callThrough ( ) ;
await reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : verifyUserEmails . method ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 , // 5 seconds
publicServerURL : 'http://localhost:8378/1' ,
} ) ;
const beforeSave = {
method ( req ) {
req . object . set ( 'emailVerified' , true ) ;
} ,
} ;
const saveSpy = spyOn ( beforeSave , 'method' ) . and . callThrough ( ) ;
const emailSpy = spyOn ( emailAdapter , 'sendVerificationEmail' ) . and . callThrough ( ) ;
Parse . Cloud . beforeSave ( Parse . User , beforeSave . method ) ;
const user = new Parse . User ( ) ;
user . setUsername ( 'sets_email_verify_token_expires_at' ) ;
user . setPassword ( 'expiringToken' ) ;
user . set ( 'email' , 'user@example.com' ) ;
await user . signUp ( ) ;
const config = Config . get ( 'test' ) ;
const results = await config . database . find (
'_User' ,
{
username : 'sets_email_verify_token_expires_at' ,
} ,
{ } ,
Auth . maintenance ( config )
) ;
expect ( results . length ) . toBe ( 1 ) ;
const user _data = results [ 0 ] ;
expect ( typeof user _data ) . toBe ( 'object' ) ;
expect ( user _data . emailVerified ) . toEqual ( true ) ;
expect ( user _data . _email _verify _token ) . toBeUndefined ( ) ;
expect ( user _data . _email _verify _token _expires _at ) . toBeUndefined ( ) ;
expect ( emailSpy ) . not . toHaveBeenCalled ( ) ;
expect ( saveSpy ) . toHaveBeenCalled ( ) ;
expect ( sendEmailOptions ) . toBeUndefined ( ) ;
expect ( verifySpy ) . toHaveBeenCalled ( ) ;
} ) ;
it ( 'can conditionally send emails and allow conditional login' , async ( ) => {
let sendEmailOptions ;
const emailAdapter = {
sendVerificationEmail : options => {
sendEmailOptions = options ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
sendMail : ( ) => { } ,
} ;
const verifyUserEmails = {
method ( req ) {
2023-12-17 01:50:19 +01:00
expect ( Object . keys ( req ) ) . toEqual ( [ 'original' , 'object' , 'master' , 'ip' , 'installationId' ] ) ;
2023-06-23 16:29:32 +02:00
if ( req . object . get ( 'username' ) === 'no_email' ) {
return false ;
}
return true ;
} ,
} ;
const verifySpy = spyOn ( verifyUserEmails , 'method' ) . and . callThrough ( ) ;
await reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : verifyUserEmails . method ,
preventLoginWithUnverifiedEmail : verifyUserEmails . method ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 , // 5 seconds
publicServerURL : 'http://localhost:8378/1' ,
} ) ;
const user = new Parse . User ( ) ;
user . setUsername ( 'no_email' ) ;
user . setPassword ( 'expiringToken' ) ;
user . set ( 'email' , 'user@example.com' ) ;
await user . signUp ( ) ;
expect ( sendEmailOptions ) . toBeUndefined ( ) ;
expect ( user . getSessionToken ( ) ) . toBeDefined ( ) ;
expect ( verifySpy ) . toHaveBeenCalledTimes ( 2 ) ;
const user2 = new Parse . User ( ) ;
user2 . setUsername ( 'email' ) ;
user2 . setPassword ( 'expiringToken' ) ;
user2 . set ( 'email' , 'user2@example.com' ) ;
await user2 . signUp ( ) ;
2024-01-15 15:44:49 +01:00
await jasmine . timeout ( ) ;
2023-06-23 16:29:32 +02:00
expect ( user2 . getSessionToken ( ) ) . toBeUndefined ( ) ;
expect ( sendEmailOptions ) . toBeDefined ( ) ;
2023-12-26 21:01:27 +01:00
expect ( verifySpy ) . toHaveBeenCalledTimes ( 5 ) ;
2023-06-23 16:29:32 +02:00
} ) ;
it ( 'can conditionally send user email verification' , async ( ) => {
const emailAdapter = {
sendVerificationEmail : ( ) => { } ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
sendMail : ( ) => { } ,
} ;
const sendVerificationEmail = {
method ( req ) {
expect ( req . user ) . toBeDefined ( ) ;
expect ( req . master ) . toBeDefined ( ) ;
return false ;
} ,
} ;
const sendSpy = spyOn ( sendVerificationEmail , 'method' ) . and . callThrough ( ) ;
await reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 , // 5 seconds
publicServerURL : 'http://localhost:8378/1' ,
sendUserEmailVerification : sendVerificationEmail . method ,
} ) ;
const emailSpy = spyOn ( emailAdapter , 'sendVerificationEmail' ) . and . callThrough ( ) ;
const newUser = new Parse . User ( ) ;
newUser . setUsername ( 'unsets_email_verify_token_expires_at' ) ;
newUser . setPassword ( 'expiringToken' ) ;
newUser . set ( 'email' , 'user@example.com' ) ;
await newUser . signUp ( ) ;
await Parse . User . requestEmailVerification ( 'user@example.com' ) ;
2024-01-15 15:44:49 +01:00
await jasmine . timeout ( ) ;
2023-06-23 16:29:32 +02:00
expect ( sendSpy ) . toHaveBeenCalledTimes ( 2 ) ;
expect ( emailSpy ) . toHaveBeenCalledTimes ( 0 ) ;
} ) ;
2024-01-15 15:44:49 +01:00
it ( 'provides full user object in email verification function on email and username change' , async ( ) => {
const emailAdapter = {
sendVerificationEmail : ( ) => { } ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
sendMail : ( ) => { } ,
} ;
const sendVerificationEmail = {
method ( req ) {
expect ( req . user ) . toBeDefined ( ) ;
expect ( req . user . id ) . toBeDefined ( ) ;
expect ( req . user . get ( 'createdAt' ) ) . toBeDefined ( ) ;
expect ( req . user . get ( 'updatedAt' ) ) . toBeDefined ( ) ;
expect ( req . master ) . toBeDefined ( ) ;
return false ;
} ,
} ;
await reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 ,
publicServerURL : 'http://localhost:8378/1' ,
sendUserEmailVerification : sendVerificationEmail . method ,
} ) ;
const user = new Parse . User ( ) ;
user . setPassword ( 'password' ) ;
user . setUsername ( 'new@example.com' ) ;
user . setEmail ( 'user@example.com' ) ;
await user . save ( null , { useMasterKey : true } ) ;
// Update email and username
user . setUsername ( 'new@example.com' ) ;
user . setEmail ( 'new@example.com' ) ;
await user . save ( null , { useMasterKey : true } ) ;
} ) ;
2023-06-23 16:29:32 +02:00
it ( 'beforeSave options do not change existing behaviour' , async ( ) => {
let sendEmailOptions ;
const emailAdapter = {
sendVerificationEmail : options => {
sendEmailOptions = options ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
sendMail : ( ) => { } ,
} ;
await reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 , // 5 seconds
publicServerURL : 'http://localhost:8378/1' ,
} ) ;
const emailSpy = spyOn ( emailAdapter , 'sendVerificationEmail' ) . and . callThrough ( ) ;
const newUser = new Parse . User ( ) ;
newUser . setUsername ( 'unsets_email_verify_token_expires_at' ) ;
newUser . setPassword ( 'expiringToken' ) ;
newUser . set ( 'email' , 'user@parse.com' ) ;
await newUser . signUp ( ) ;
2024-01-15 15:44:49 +01:00
await jasmine . timeout ( ) ;
2023-06-23 16:29:32 +02:00
const response = await request ( {
url : sendEmailOptions . link ,
followRedirects : false ,
} ) ;
expect ( response . status ) . toEqual ( 302 ) ;
const config = Config . get ( 'test' ) ;
const results = await config . database . find ( '_User' , {
username : 'unsets_email_verify_token_expires_at' ,
} ) ;
expect ( results . length ) . toBe ( 1 ) ;
const user = results [ 0 ] ;
expect ( typeof user ) . toBe ( 'object' ) ;
expect ( user . emailVerified ) . toEqual ( true ) ;
expect ( typeof user . _email _verify _token ) . toBe ( 'undefined' ) ;
expect ( typeof user . _email _verify _token _expires _at ) . toBe ( 'undefined' ) ;
expect ( emailSpy ) . toHaveBeenCalled ( ) ;
} ) ;
2016-08-15 16:48:39 -04:00
it ( 'unsets the _email_verify_token_expires_at and _email_verify_token fields in the User class if email verification is successful' , done => {
2018-02-17 09:55:30 -05:00
const user = new Parse . User ( ) ;
let sendEmailOptions ;
const emailAdapter = {
2016-07-19 01:10:36 -05:00
sendVerificationEmail : options => {
sendEmailOptions = options ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
} ;
2016-07-19 01:10:36 -05:00
reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 , // 5 seconds
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-07-19 01:10:36 -05:00
} )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'unsets_email_verify_token_expires_at' ) ;
user . setPassword ( 'expiringToken' ) ;
2017-06-20 09:15:26 -07:00
user . set ( 'email' , 'user@parse.com' ) ;
return user . signUp ( ) ;
} )
2024-01-15 15:44:49 +01:00
. then ( ( ) => jasmine . timeout ( ) )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2018-09-24 17:07:51 -04:00
request ( {
url : sendEmailOptions . link ,
followRedirects : false ,
} ) . then ( response => {
expect ( response . status ) . toEqual ( 302 ) ;
const config = Config . get ( 'test' ) ;
return config . database
. find ( '_User' , {
username : 'unsets_email_verify_token_expires_at' ,
} )
. then ( results => {
expect ( results . length ) . toBe ( 1 ) ;
return results [ 0 ] ;
} )
. then ( user => {
expect ( typeof user ) . toBe ( 'object' ) ;
expect ( user . emailVerified ) . toEqual ( true ) ;
expect ( typeof user . _email _verify _token ) . toBe ( 'undefined' ) ;
2020-10-25 15:06:58 -05:00
expect ( typeof user . _email _verify _token _expires _at ) . toBe ( 'undefined' ) ;
2018-09-24 17:07:51 -04:00
done ( ) ;
} )
. catch ( error => {
jfail ( error ) ;
done ( ) ;
} ) ;
} ) ;
2017-06-20 09:15:26 -07:00
} )
. catch ( error => {
jfail ( error ) ;
done ( ) ;
2016-07-19 01:10:36 -05:00
} ) ;
} ) ;
2017-05-10 14:02:16 +01:00
it ( 'clicking on the email verify link by an email VERIFIED user that was setup before enabling the expire email verify token should show email verify email success' , done => {
2018-02-17 09:55:30 -05:00
const user = new Parse . User ( ) ;
let sendEmailOptions ;
const emailAdapter = {
2016-07-19 01:10:36 -05:00
sendVerificationEmail : options => {
sendEmailOptions = options ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
} ;
2018-02-17 09:55:30 -05:00
const serverConfig = {
2016-07-19 01:10:36 -05:00
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-07-19 01:10:36 -05:00
} ;
// setup server WITHOUT enabling the expire email verify token flag
reconfigureServer ( serverConfig )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'testEmailVerifyTokenValidity' ) ;
user . setPassword ( 'expiringToken' ) ;
2017-06-20 09:15:26 -07:00
user . set ( 'email' , 'user@parse.com' ) ;
return user . signUp ( ) ;
} )
2024-01-15 15:44:49 +01:00
. then ( ( ) => jasmine . timeout ( ) )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2018-09-24 17:07:51 -04:00
return request ( {
url : sendEmailOptions . link ,
followRedirects : false ,
} ) . then ( response => {
expect ( response . status ) . toEqual ( 302 ) ;
return user . fetch ( ) ;
2017-06-20 09:15:26 -07:00
} ) ;
} )
. then ( ( ) => {
expect ( user . get ( 'emailVerified' ) ) . toEqual ( true ) ;
// RECONFIGURE the server i.e., ENABLE the expire email verify token flag
serverConfig . emailVerifyTokenValidityDuration = 5 ; // 5 seconds
return reconfigureServer ( serverConfig ) ;
} )
. then ( ( ) => {
2018-09-24 17:07:51 -04:00
request ( {
url : sendEmailOptions . link ,
followRedirects : false ,
} ) . then ( response => {
expect ( response . status ) . toEqual ( 302 ) ;
expect ( response . text ) . toEqual (
'Found. Redirecting to http://localhost:8378/1/apps/verify_email_success.html?username=testEmailVerifyTokenValidity'
) ;
done ( ) ;
} ) ;
2017-06-20 09:15:26 -07:00
} )
2018-09-01 13:58:06 -04:00
. catch ( error => {
2017-06-20 09:15:26 -07:00
jfail ( error ) ;
2016-07-19 01:10:36 -05:00
done ( ) ;
} ) ;
} ) ;
2017-05-10 14:02:16 +01:00
it ( 'clicking on the email verify link by an email UNVERIFIED user that was setup before enabling the expire email verify token should show invalid verficiation link page' , done => {
2018-02-17 09:55:30 -05:00
const user = new Parse . User ( ) ;
let sendEmailOptions ;
const emailAdapter = {
2016-07-19 01:10:36 -05:00
sendVerificationEmail : options => {
sendEmailOptions = options ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
} ;
2018-02-17 09:55:30 -05:00
const serverConfig = {
2016-07-19 01:10:36 -05:00
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-07-19 01:10:36 -05:00
} ;
// setup server WITHOUT enabling the expire email verify token flag
reconfigureServer ( serverConfig )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'testEmailVerifyTokenValidity' ) ;
user . setPassword ( 'expiringToken' ) ;
2017-06-20 09:15:26 -07:00
user . set ( 'email' , 'user@parse.com' ) ;
return user . signUp ( ) ;
} )
. then ( ( ) => {
2018-09-01 13:58:06 -04:00
// just get the user again - DO NOT email verify the user
2017-06-20 09:15:26 -07:00
return user . fetch ( ) ;
} )
. then ( ( ) => {
expect ( user . get ( 'emailVerified' ) ) . toEqual ( false ) ;
// RECONFIGURE the server i.e., ENABLE the expire email verify token flag
serverConfig . emailVerifyTokenValidityDuration = 5 ; // 5 seconds
return reconfigureServer ( serverConfig ) ;
} )
. then ( ( ) => {
2018-09-24 17:07:51 -04:00
request ( {
url : sendEmailOptions . link ,
followRedirects : false ,
} ) . then ( response => {
expect ( response . status ) . toEqual ( 302 ) ;
expect ( response . text ) . toEqual (
'Found. Redirecting to http://localhost:8378/1/apps/invalid_verification_link.html?username=testEmailVerifyTokenValidity&appId=test'
) ;
done ( ) ;
} ) ;
2017-06-20 09:15:26 -07:00
} )
2018-09-01 13:58:06 -04:00
. catch ( error => {
2017-06-20 09:15:26 -07:00
jfail ( error ) ;
2016-07-19 01:10:36 -05:00
done ( ) ;
} ) ;
} ) ;
2016-08-15 16:48:39 -04:00
it ( 'setting the email on the user should set a new email verification token and new expiration date for the token when expire email verify token flag is set' , done => {
2016-12-07 15:17:05 -08:00
const user = new Parse . User ( ) ;
2016-07-19 01:10:36 -05:00
let userBeforeEmailReset ;
let sendEmailOptions ;
2016-12-07 15:17:05 -08:00
const emailAdapter = {
2016-07-19 01:10:36 -05:00
sendVerificationEmail : options => {
sendEmailOptions = options ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
2016-07-19 01:10:36 -05:00
} ;
2016-12-07 15:17:05 -08:00
const serverConfig = {
2016-07-19 01:10:36 -05:00
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 , // 5 seconds
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-07-19 01:10:36 -05:00
} ;
reconfigureServer ( serverConfig )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'newEmailVerifyTokenOnEmailReset' ) ;
user . setPassword ( 'expiringToken' ) ;
2017-06-20 09:15:26 -07:00
user . set ( 'email' , 'user@parse.com' ) ;
return user . signUp ( ) ;
} )
. then ( ( ) => {
2017-10-23 08:43:05 -04:00
const config = Config . get ( 'test' ) ;
2018-09-01 13:58:06 -04:00
return config . database
. find ( '_User' , { username : 'newEmailVerifyTokenOnEmailReset' } )
. then ( results => {
return results [ 0 ] ;
} ) ;
2017-06-20 09:15:26 -07:00
} )
. then ( userFromDb => {
expect ( typeof userFromDb ) . toBe ( 'object' ) ;
userBeforeEmailReset = userFromDb ;
2016-07-19 01:10:36 -05:00
2017-06-20 09:15:26 -07:00
// trigger another token generation by setting the email
user . set ( 'email' , 'user@parse.com' ) ;
2018-09-01 13:58:06 -04:00
return new Promise ( resolve => {
// wait for half a sec to get a new expiration time
2017-06-20 09:15:26 -07:00
setTimeout ( ( ) => resolve ( user . save ( ) ) , 500 ) ;
} ) ;
} )
. then ( ( ) => {
2017-10-23 08:43:05 -04:00
const config = Config . get ( 'test' ) ;
2018-09-01 13:58:06 -04:00
return config . database
2023-01-09 08:02:12 +11:00
. find (
'_User' ,
{ username : 'newEmailVerifyTokenOnEmailReset' } ,
{ } ,
Auth . maintenance ( config )
)
2018-09-01 13:58:06 -04:00
. then ( results => {
return results [ 0 ] ;
} ) ;
2017-06-20 09:15:26 -07:00
} )
. then ( userAfterEmailReset => {
expect ( typeof userAfterEmailReset ) . toBe ( 'object' ) ;
2018-09-01 13:58:06 -04:00
expect ( userBeforeEmailReset . _email _verify _token ) . not . toEqual (
userAfterEmailReset . _email _verify _token
) ;
expect ( userBeforeEmailReset . _email _verify _token _expires _at ) . not . toEqual (
2020-11-26 04:30:52 +11:00
userAfterEmailReset . _email _verify _token _expires _at
2018-09-01 13:58:06 -04:00
) ;
2017-06-20 09:15:26 -07:00
expect ( sendEmailOptions ) . toBeDefined ( ) ;
done ( ) ;
} )
2018-09-01 13:58:06 -04:00
. catch ( error => {
2017-06-20 09:15:26 -07:00
jfail ( error ) ;
done ( ) ;
2016-08-15 16:48:39 -04:00
} ) ;
2016-07-19 01:10:36 -05:00
} ) ;
2017-03-04 13:30:52 -08:00
it ( 'should send a new verification email when a resend is requested and the user is UNVERIFIED' , done => {
2018-02-17 09:55:30 -05:00
const user = new Parse . User ( ) ;
let sendEmailOptions ;
let sendVerificationEmailCallCount = 0 ;
2018-02-01 15:35:08 -08:00
let userBeforeRequest ;
2018-02-17 09:55:30 -05:00
const emailAdapter = {
2017-03-04 13:30:52 -08:00
sendVerificationEmail : options => {
sendEmailOptions = options ;
sendVerificationEmailCallCount ++ ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
} ;
2017-03-04 13:30:52 -08:00
reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 , // 5 seconds
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2017-03-04 13:30:52 -08:00
} )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
user . setUsername ( 'resends_verification_token' ) ;
user . setPassword ( 'expiringToken' ) ;
user . set ( 'email' , 'user@parse.com' ) ;
return user . signUp ( ) ;
} )
. then ( ( ) => {
2018-02-01 15:35:08 -08:00
const config = Config . get ( 'test' ) ;
2018-09-01 13:58:06 -04:00
return config . database
. find ( '_User' , { username : 'resends_verification_token' } )
. then ( results => {
return results [ 0 ] ;
} ) ;
2018-02-01 15:35:08 -08:00
} )
2018-09-01 13:58:06 -04:00
. then ( newUser => {
2018-02-01 15:35:08 -08:00
// store this user before we make our email request
userBeforeRequest = newUser ;
2017-06-20 09:15:26 -07:00
expect ( sendVerificationEmailCallCount ) . toBe ( 1 ) ;
2017-03-04 13:30:52 -08:00
2018-09-24 17:07:51 -04:00
return request ( {
url : 'http://localhost:8378/1/verificationEmailRequest' ,
method : 'POST' ,
2017-06-20 09:15:26 -07:00
body : {
2018-09-01 13:58:06 -04:00
email : 'user@parse.com' ,
2017-06-20 09:15:26 -07:00
} ,
headers : {
'X-Parse-Application-Id' : Parse . applicationId ,
'X-Parse-REST-API-Key' : 'rest' ,
2018-09-24 17:07:51 -04:00
'Content-Type' : 'application/json' ,
2017-06-20 09:15:26 -07:00
} ,
2018-02-01 15:35:08 -08:00
} ) ;
} )
2018-09-01 13:58:06 -04:00
. then ( response => {
2018-09-24 17:07:51 -04:00
expect ( response . status ) . toBe ( 200 ) ;
2024-01-15 15:44:49 +01:00
} )
. then ( ( ) => jasmine . timeout ( ) )
. then ( ( ) => {
2018-02-01 15:35:08 -08:00
expect ( sendVerificationEmailCallCount ) . toBe ( 2 ) ;
expect ( sendEmailOptions ) . toBeDefined ( ) ;
// query for this user again
const config = Config . get ( 'test' ) ;
2018-09-01 13:58:06 -04:00
return config . database
2023-01-09 08:02:12 +11:00
. find ( '_User' , { username : 'resends_verification_token' } , { } , Auth . maintenance ( config ) )
2018-09-01 13:58:06 -04:00
. then ( results => {
return results [ 0 ] ;
} ) ;
2018-02-01 15:35:08 -08:00
} )
2018-09-01 13:58:06 -04:00
. then ( userAfterRequest => {
2018-02-01 15:35:08 -08:00
// verify that our token & expiration has been changed for this new request
expect ( typeof userAfterRequest ) . toBe ( 'object' ) ;
2018-09-01 13:58:06 -04:00
expect ( userBeforeRequest . _email _verify _token ) . not . toEqual (
userAfterRequest . _email _verify _token
) ;
expect ( userBeforeRequest . _email _verify _token _expires _at ) . not . toEqual (
2020-11-26 04:30:52 +11:00
userAfterRequest . _email _verify _token _expires _at
2018-09-01 13:58:06 -04:00
) ;
2018-02-01 15:35:08 -08:00
done ( ) ;
2017-03-04 13:30:52 -08:00
} )
2017-06-20 09:15:26 -07:00
. catch ( error => {
2023-01-09 08:02:12 +11:00
console . log ( error ) ;
2017-06-20 09:15:26 -07:00
jfail ( error ) ;
2017-03-04 13:30:52 -08:00
done ( ) ;
} ) ;
} ) ;
2024-01-06 16:41:13 +01:00
it ( 'provides function arguments in verifyUserEmails on verificationEmailRequest' , async ( ) => {
const user = new Parse . User ( ) ;
user . setUsername ( 'user' ) ;
user . setPassword ( 'pass' ) ;
user . set ( 'email' , 'test@example.com' ) ;
await user . signUp ( ) ;
const verifyUserEmails = {
method : async ( params ) => {
expect ( params . object ) . toBeInstanceOf ( Parse . User ) ;
expect ( params . ip ) . toBeDefined ( ) ;
expect ( params . master ) . toBeDefined ( ) ;
expect ( params . installationId ) . toBeDefined ( ) ;
expect ( params . resendRequest ) . toBeTrue ( ) ;
return true ;
} ,
} ;
const verifyUserEmailsSpy = spyOn ( verifyUserEmails , 'method' ) . and . callThrough ( ) ;
await reconfigureServer ( {
appName : 'test' ,
publicServerURL : 'http://localhost:1337/1' ,
verifyUserEmails : verifyUserEmails . method ,
preventLoginWithUnverifiedEmail : verifyUserEmails . method ,
preventSignupWithUnverifiedEmail : true ,
emailAdapter : MockEmailAdapterWithOptions ( {
fromAddress : 'parse@example.com' ,
apiKey : 'k' ,
domain : 'd' ,
} ) ,
} ) ;
await expectAsync ( Parse . User . requestEmailVerification ( 'test@example.com' ) ) . toBeResolved ( ) ;
expect ( verifyUserEmailsSpy ) . toHaveBeenCalledTimes ( 1 ) ;
} ) ;
2020-11-26 04:30:52 +11:00
it ( 'should throw with invalid emailVerifyTokenReuseIfValid' , async done => {
const sendEmailOptions = [ ] ;
const emailAdapter = {
sendVerificationEmail : ( ) => Promise . resolve ( ) ,
sendPasswordResetEmail : options => {
sendEmailOptions . push ( options ) ;
} ,
sendMail : ( ) => { } ,
} ;
try {
await reconfigureServer ( {
appName : 'passwordPolicy' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 * 60 , // 5 minutes
emailVerifyTokenReuseIfValid : [ ] ,
publicServerURL : 'http://localhost:8378/1' ,
} ) ;
fail ( 'should have thrown.' ) ;
} catch ( e ) {
expect ( e ) . toBe ( 'emailVerifyTokenReuseIfValid must be a boolean value' ) ;
}
try {
await reconfigureServer ( {
appName : 'passwordPolicy' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenReuseIfValid : true ,
publicServerURL : 'http://localhost:8378/1' ,
} ) ;
fail ( 'should have thrown.' ) ;
} catch ( e ) {
expect ( e ) . toBe (
'You cannot use emailVerifyTokenReuseIfValid without emailVerifyTokenValidityDuration'
) ;
}
done ( ) ;
} ) ;
it ( 'should match codes with emailVerifyTokenReuseIfValid' , async done => {
let sendEmailOptions ;
let sendVerificationEmailCallCount = 0 ;
const emailAdapter = {
sendVerificationEmail : options => {
sendEmailOptions = options ;
sendVerificationEmailCallCount ++ ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
sendMail : ( ) => { } ,
} ;
await reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 * 60 , // 5 minutes
publicServerURL : 'http://localhost:8378/1' ,
emailVerifyTokenReuseIfValid : true ,
} ) ;
const user = new Parse . User ( ) ;
user . setUsername ( 'resends_verification_token' ) ;
user . setPassword ( 'expiringToken' ) ;
user . set ( 'email' , 'user@example.com' ) ;
await user . signUp ( ) ;
const config = Config . get ( 'test' ) ;
const [ userBeforeRequest ] = await config . database . find ( '_User' , {
username : 'resends_verification_token' ,
2024-01-14 01:37:20 +01:00
} , { } , Auth . maintenance ( config ) ) ;
2020-11-26 04:30:52 +11:00
// store this user before we make our email request
expect ( sendVerificationEmailCallCount ) . toBe ( 1 ) ;
await new Promise ( resolve => {
setTimeout ( ( ) => {
resolve ( ) ;
} , 1000 ) ;
} ) ;
const response = await request ( {
url : 'http://localhost:8378/1/verificationEmailRequest' ,
method : 'POST' ,
body : {
email : 'user@example.com' ,
} ,
headers : {
'X-Parse-Application-Id' : Parse . applicationId ,
'X-Parse-REST-API-Key' : 'rest' ,
'Content-Type' : 'application/json' ,
} ,
} ) ;
2024-01-15 15:44:49 +01:00
await jasmine . timeout ( ) ;
2020-11-26 04:30:52 +11:00
expect ( response . status ) . toBe ( 200 ) ;
expect ( sendVerificationEmailCallCount ) . toBe ( 2 ) ;
expect ( sendEmailOptions ) . toBeDefined ( ) ;
const [ userAfterRequest ] = await config . database . find ( '_User' , {
username : 'resends_verification_token' ,
2024-01-14 01:37:20 +01:00
} , { } , Auth . maintenance ( config ) ) ;
2020-11-26 04:30:52 +11:00
2024-01-14 01:37:20 +01:00
// Verify that token & expiration haven't been changed for this new request
2020-11-26 04:30:52 +11:00
expect ( typeof userAfterRequest ) . toBe ( 'object' ) ;
2024-01-14 01:37:20 +01:00
expect ( userBeforeRequest . _email _verify _token ) . toBeDefined ( ) ;
2020-11-26 04:30:52 +11:00
expect ( userBeforeRequest . _email _verify _token ) . toEqual ( userAfterRequest . _email _verify _token ) ;
2024-01-14 01:37:20 +01:00
expect ( userBeforeRequest . _email _verify _token _expires _at ) . toBeDefined ( ) ;
expect ( userBeforeRequest . _email _verify _token _expires _at ) . toEqual ( userAfterRequest . _email _verify _token _expires _at ) ;
2020-11-26 04:30:52 +11:00
done ( ) ;
} ) ;
2017-03-04 13:30:52 -08:00
it ( 'should not send a new verification email when a resend is requested and the user is VERIFIED' , done => {
2018-02-17 09:55:30 -05:00
const user = new Parse . User ( ) ;
let sendEmailOptions ;
let sendVerificationEmailCallCount = 0 ;
const emailAdapter = {
2017-03-04 13:30:52 -08:00
sendVerificationEmail : options => {
sendEmailOptions = options ;
sendVerificationEmailCallCount ++ ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
} ;
2017-03-04 13:30:52 -08:00
reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 , // 5 seconds
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2017-03-04 13:30:52 -08:00
} )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
user . setUsername ( 'no_new_verification_token_once_verified' ) ;
user . setPassword ( 'expiringToken' ) ;
user . set ( 'email' , 'user@parse.com' ) ;
return user . signUp ( ) ;
2017-03-04 13:30:52 -08:00
} )
2024-01-15 15:44:49 +01:00
. then ( ( ) => jasmine . timeout ( ) )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2018-09-24 17:07:51 -04:00
return request ( {
url : sendEmailOptions . link ,
followRedirects : false ,
} ) . then ( response => {
expect ( response . status ) . toEqual ( 302 ) ;
} ) ;
2017-03-04 13:30:52 -08:00
} )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2017-03-04 13:30:52 -08:00
expect ( sendVerificationEmailCallCount ) . toBe ( 1 ) ;
2017-06-20 09:15:26 -07:00
2018-09-24 17:07:51 -04:00
return request ( {
url : 'http://localhost:8378/1/verificationEmailRequest' ,
method : 'POST' ,
body : {
email : 'user@parse.com' ,
} ,
headers : {
'X-Parse-Application-Id' : Parse . applicationId ,
'X-Parse-REST-API-Key' : 'rest' ,
'Content-Type' : 'application/json' ,
} ,
} )
. then ( fail , res => res )
2018-09-01 13:58:06 -04:00
. then ( response => {
2018-09-24 17:07:51 -04:00
expect ( response . status ) . toBe ( 400 ) ;
2017-06-20 09:15:26 -07:00
expect ( sendVerificationEmailCallCount ) . toBe ( 1 ) ;
done ( ) ;
} ) ;
} )
. catch ( error => {
jfail ( error ) ;
2017-03-04 13:30:52 -08:00
done ( ) ;
} ) ;
} ) ;
it ( 'should not send a new verification email if this user does not exist' , done => {
2018-02-17 09:55:30 -05:00
let sendEmailOptions ;
let sendVerificationEmailCallCount = 0 ;
const emailAdapter = {
2017-03-04 13:30:52 -08:00
sendVerificationEmail : options => {
sendEmailOptions = options ;
sendVerificationEmailCallCount ++ ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
} ;
2017-03-04 13:30:52 -08:00
reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 , // 5 seconds
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2017-03-04 13:30:52 -08:00
} )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2018-09-24 17:07:51 -04:00
return request ( {
url : 'http://localhost:8378/1/verificationEmailRequest' ,
method : 'POST' ,
body : {
email : 'user@parse.com' ,
} ,
headers : {
'X-Parse-Application-Id' : Parse . applicationId ,
'X-Parse-REST-API-Key' : 'rest' ,
'Content-Type' : 'application/json' ,
} ,
} )
. then ( fail )
. catch ( response => response )
2017-06-20 09:15:26 -07:00
. then ( response => {
2018-09-24 17:07:51 -04:00
expect ( response . status ) . toBe ( 400 ) ;
2017-06-20 09:15:26 -07:00
expect ( sendVerificationEmailCallCount ) . toBe ( 0 ) ;
expect ( sendEmailOptions ) . not . toBeDefined ( ) ;
done ( ) ;
} ) ;
2017-03-04 13:30:52 -08:00
} )
2017-06-20 09:15:26 -07:00
. catch ( error => {
jfail ( error ) ;
2017-03-04 13:30:52 -08:00
done ( ) ;
} ) ;
} ) ;
it ( 'should fail if no email is supplied' , done => {
2018-02-17 09:55:30 -05:00
let sendEmailOptions ;
let sendVerificationEmailCallCount = 0 ;
const emailAdapter = {
2017-03-04 13:30:52 -08:00
sendVerificationEmail : options => {
sendEmailOptions = options ;
sendVerificationEmailCallCount ++ ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
} ;
2017-03-04 13:30:52 -08:00
reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 , // 5 seconds
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2017-03-04 13:30:52 -08:00
} )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2018-09-24 17:07:51 -04:00
request ( {
url : 'http://localhost:8378/1/verificationEmailRequest' ,
method : 'POST' ,
body : { } ,
headers : {
'X-Parse-Application-Id' : Parse . applicationId ,
'X-Parse-REST-API-Key' : 'rest' ,
'Content-Type' : 'application/json' ,
2017-06-20 09:15:26 -07:00
} ,
2018-09-24 17:07:51 -04:00
} )
. then ( fail , response => response )
. then ( response => {
expect ( response . status ) . toBe ( 400 ) ;
expect ( response . data . code ) . toBe ( Parse . Error . EMAIL _MISSING ) ;
expect ( response . data . error ) . toBe ( 'you must provide an email' ) ;
2018-09-01 13:58:06 -04:00
expect ( sendVerificationEmailCallCount ) . toBe ( 0 ) ;
expect ( sendEmailOptions ) . not . toBeDefined ( ) ;
done ( ) ;
2018-09-24 17:07:51 -04:00
} ) ;
2017-06-20 09:15:26 -07:00
} )
. catch ( error => {
jfail ( error ) ;
2017-03-04 13:30:52 -08:00
done ( ) ;
} ) ;
} ) ;
it ( 'should fail if email is not a string' , done => {
2018-02-17 09:55:30 -05:00
let sendEmailOptions ;
let sendVerificationEmailCallCount = 0 ;
const emailAdapter = {
2017-03-04 13:30:52 -08:00
sendVerificationEmail : options => {
sendEmailOptions = options ;
sendVerificationEmailCallCount ++ ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
} ;
2017-03-04 13:30:52 -08:00
reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 , // 5 seconds
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2017-03-04 13:30:52 -08:00
} )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2018-09-24 17:07:51 -04:00
request ( {
url : 'http://localhost:8378/1/verificationEmailRequest' ,
method : 'POST' ,
body : { email : 3 } ,
headers : {
'X-Parse-Application-Id' : Parse . applicationId ,
'X-Parse-REST-API-Key' : 'rest' ,
'Content-Type' : 'application/json' ,
2017-06-20 09:15:26 -07:00
} ,
2018-09-24 17:07:51 -04:00
} )
. then ( fail , res => res )
. then ( response => {
expect ( response . status ) . toBe ( 400 ) ;
expect ( response . data . code ) . toBe ( Parse . Error . INVALID _EMAIL _ADDRESS ) ;
2020-10-25 15:06:58 -05:00
expect ( response . data . error ) . toBe ( 'you must provide a valid email string' ) ;
2018-09-01 13:58:06 -04:00
expect ( sendVerificationEmailCallCount ) . toBe ( 0 ) ;
expect ( sendEmailOptions ) . not . toBeDefined ( ) ;
done ( ) ;
2018-09-24 17:07:51 -04:00
} ) ;
2017-06-20 09:15:26 -07:00
} )
. catch ( error => {
jfail ( error ) ;
2017-03-04 13:30:52 -08:00
done ( ) ;
} ) ;
} ) ;
2016-08-15 16:48:39 -04:00
it ( 'client should not see the _email_verify_token_expires_at field' , done => {
2018-02-17 09:55:30 -05:00
const user = new Parse . User ( ) ;
let sendEmailOptions ;
const emailAdapter = {
2016-07-19 01:10:36 -05:00
sendVerificationEmail : options => {
sendEmailOptions = options ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
} ;
2016-07-19 01:10:36 -05:00
reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 , // 5 seconds
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2016-07-19 01:10:36 -05:00
} )
. then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'testEmailVerifyTokenValidity' ) ;
user . setPassword ( 'expiringToken' ) ;
2017-06-20 09:15:26 -07:00
user . set ( 'email' , 'user@parse.com' ) ;
return user . signUp ( ) ;
2016-07-19 01:10:36 -05:00
} )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
2018-09-01 13:58:06 -04:00
user
. fetch ( )
2017-06-20 09:15:26 -07:00
. then ( ( ) => {
expect ( user . get ( 'emailVerified' ) ) . toEqual ( false ) ;
2020-10-25 15:06:58 -05:00
expect ( typeof user . get ( '_email_verify_token_expires_at' ) ) . toBe ( 'undefined' ) ;
2017-06-20 09:15:26 -07:00
expect ( sendEmailOptions ) . toBeDefined ( ) ;
done ( ) ;
} )
. catch ( error => {
jfail ( error ) ;
done ( ) ;
} ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( error => {
2016-08-15 16:48:39 -04:00
jfail ( error ) ;
2016-07-19 01:10:36 -05:00
done ( ) ;
} ) ;
} ) ;
2018-02-01 19:39:57 -03:00
it ( 'emailVerified should be set to false after changing from an already verified email' , done => {
2018-02-17 09:55:30 -05:00
const user = new Parse . User ( ) ;
let sendEmailOptions ;
const emailAdapter = {
2018-02-01 19:39:57 -03:00
sendVerificationEmail : options => {
sendEmailOptions = options ;
} ,
sendPasswordResetEmail : ( ) => Promise . resolve ( ) ,
2018-09-01 13:58:06 -04:00
sendMail : ( ) => { } ,
} ;
2018-02-01 19:39:57 -03:00
reconfigureServer ( {
appName : 'emailVerifyToken' ,
verifyUserEmails : true ,
emailAdapter : emailAdapter ,
emailVerifyTokenValidityDuration : 5 , // 5 seconds
2018-09-01 13:58:06 -04:00
publicServerURL : 'http://localhost:8378/1' ,
2018-02-01 19:39:57 -03:00
} )
. then ( ( ) => {
2018-09-01 13:58:06 -04:00
user . setUsername ( 'testEmailVerifyTokenValidity' ) ;
user . setPassword ( 'expiringToken' ) ;
2018-02-01 19:39:57 -03:00
user . set ( 'email' , 'user@parse.com' ) ;
return user . signUp ( ) ;
2018-09-01 13:58:06 -04:00
} )
2024-01-15 15:44:49 +01:00
. then ( ( ) => jasmine . timeout ( ) )
2018-09-01 13:58:06 -04:00
. then ( ( ) => {
2018-09-24 17:07:51 -04:00
request ( {
url : sendEmailOptions . link ,
followRedirects : false ,
} ) . then ( response => {
expect ( response . status ) . toEqual ( 302 ) ;
Parse . User . logIn ( 'testEmailVerifyTokenValidity' , 'expiringToken' )
. then ( user => {
expect ( typeof user ) . toBe ( 'object' ) ;
expect ( user . get ( 'emailVerified' ) ) . toBe ( true ) ;
2018-02-01 19:39:57 -03:00
2018-09-24 17:07:51 -04:00
user . set ( 'email' , 'newEmail@parse.com' ) ;
return user . save ( ) ;
} )
. then ( ( ) => user . fetch ( ) )
. then ( user => {
expect ( typeof user ) . toBe ( 'object' ) ;
expect ( user . get ( 'email' ) ) . toBe ( 'newEmail@parse.com' ) ;
expect ( user . get ( 'emailVerified' ) ) . toBe ( false ) ;
2018-09-01 13:58:06 -04:00
2018-09-24 17:07:51 -04:00
request ( {
url : sendEmailOptions . link ,
followRedirects : false ,
} ) . then ( response => {
expect ( response . status ) . toEqual ( 302 ) ;
2018-02-01 19:39:57 -03:00
done ( ) ;
} ) ;
2018-09-24 17:07:51 -04:00
} )
. catch ( error => {
jfail ( error ) ;
done ( ) ;
} ) ;
} ) ;
2018-09-01 13:58:06 -04:00
} )
. catch ( error => {
2018-02-01 19:39:57 -03:00
jfail ( error ) ;
done ( ) ;
} ) ;
} ) ;
2018-09-01 13:58:06 -04:00
} ) ;