Adds ability to expire email verify token (#2216)
This commit is contained in:
committed by
Drew
parent
033bc317e6
commit
6f292059ba
515
spec/EmailVerificationToken.spec.js
Normal file
515
spec/EmailVerificationToken.spec.js
Normal file
@@ -0,0 +1,515 @@
|
||||
"use strict";
|
||||
|
||||
const MockEmailAdapterWithOptions = require('./MockEmailAdapterWithOptions');
|
||||
const request = require('request');
|
||||
const MongoClient = require("mongodb").MongoClient;
|
||||
|
||||
describe("Email Verification Token Expiration: ", () => {
|
||||
|
||||
it_exclude_dbs(['postgres'])('show the invalid link page, if the user clicks on the verify email link after the email verify token expires', done => {
|
||||
var user = new Parse.User();
|
||||
var sendEmailOptions;
|
||||
var emailAdapter = {
|
||||
sendVerificationEmail: options => {
|
||||
sendEmailOptions = options;
|
||||
},
|
||||
sendPasswordResetEmail: () => Promise.resolve(),
|
||||
sendMail: () => {}
|
||||
}
|
||||
reconfigureServer({
|
||||
appName: 'emailVerifyToken',
|
||||
verifyUserEmails: true,
|
||||
emailAdapter: emailAdapter,
|
||||
emailVerifyTokenValidityDuration: 0.5, // 0.5 second
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
})
|
||||
.then(() => {
|
||||
user.setUsername("testEmailVerifyTokenValidity");
|
||||
user.setPassword("expiringToken");
|
||||
user.set('email', 'user@parse.com');
|
||||
return user.signUp();
|
||||
}).then(() => {
|
||||
// wait for 1 second - simulate user behavior to some extent
|
||||
setTimeout(() => {
|
||||
expect(sendEmailOptions).not.toBeUndefined();
|
||||
|
||||
request.get(sendEmailOptions.link, {
|
||||
followRedirect: false,
|
||||
}, (error, response, body) => {
|
||||
expect(response.statusCode).toEqual(302);
|
||||
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html');
|
||||
done();
|
||||
});
|
||||
}, 1000);
|
||||
});
|
||||
});
|
||||
|
||||
it_exclude_dbs(['postgres'])('emailVerified should set to false, if the user does not verify their email before the email verify token expires', done => {
|
||||
var user = new Parse.User();
|
||||
var sendEmailOptions;
|
||||
var emailAdapter = {
|
||||
sendVerificationEmail: options => {
|
||||
sendEmailOptions = options;
|
||||
},
|
||||
sendPasswordResetEmail: () => Promise.resolve(),
|
||||
sendMail: () => {}
|
||||
}
|
||||
reconfigureServer({
|
||||
appName: 'emailVerifyToken',
|
||||
verifyUserEmails: true,
|
||||
emailAdapter: emailAdapter,
|
||||
emailVerifyTokenValidityDuration: 0.5, // 0.5 second
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
})
|
||||
.then(() => {
|
||||
user.setUsername("testEmailVerifyTokenValidity");
|
||||
user.setPassword("expiringToken");
|
||||
user.set('email', 'user@parse.com');
|
||||
return user.signUp();
|
||||
}).then(() => {
|
||||
// wait for 1 second - simulate user behavior to some extent
|
||||
setTimeout(() => {
|
||||
expect(sendEmailOptions).not.toBeUndefined();
|
||||
|
||||
request.get(sendEmailOptions.link, {
|
||||
followRedirect: false,
|
||||
}, (error, response, body) => {
|
||||
expect(response.statusCode).toEqual(302);
|
||||
user.fetch()
|
||||
.then(() => {
|
||||
expect(user.get('emailVerified')).toEqual(false);
|
||||
done();
|
||||
})
|
||||
.catch((err) => {
|
||||
fail("this should not fail");
|
||||
done();
|
||||
});
|
||||
});
|
||||
}, 1000);
|
||||
});
|
||||
});
|
||||
|
||||
it_exclude_dbs(['postgres'])('if user clicks on the email verify link before email verification token expiration then show the verify email success page', done => {
|
||||
var user = new Parse.User();
|
||||
var sendEmailOptions;
|
||||
var emailAdapter = {
|
||||
sendVerificationEmail: options => {
|
||||
sendEmailOptions = options;
|
||||
},
|
||||
sendPasswordResetEmail: () => Promise.resolve(),
|
||||
sendMail: () => {}
|
||||
}
|
||||
reconfigureServer({
|
||||
appName: 'emailVerifyToken',
|
||||
verifyUserEmails: true,
|
||||
emailAdapter: emailAdapter,
|
||||
emailVerifyTokenValidityDuration: 5, // 5 seconds
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
})
|
||||
.then(() => {
|
||||
user.setUsername("testEmailVerifyTokenValidity");
|
||||
user.setPassword("expiringToken");
|
||||
user.set('email', 'user@parse.com');
|
||||
return user.signUp();
|
||||
}).then(() => {
|
||||
request.get(sendEmailOptions.link, {
|
||||
followRedirect: false,
|
||||
}, (error, response, body) => {
|
||||
expect(response.statusCode).toEqual(302);
|
||||
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/verify_email_success.html?username=testEmailVerifyTokenValidity');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it_exclude_dbs(['postgres'])('if user clicks on the email verify link before email verification token expiration then emailVerified should be true', done => {
|
||||
var user = new Parse.User();
|
||||
var sendEmailOptions;
|
||||
var emailAdapter = {
|
||||
sendVerificationEmail: options => {
|
||||
sendEmailOptions = options;
|
||||
},
|
||||
sendPasswordResetEmail: () => Promise.resolve(),
|
||||
sendMail: () => {}
|
||||
}
|
||||
reconfigureServer({
|
||||
appName: 'emailVerifyToken',
|
||||
verifyUserEmails: true,
|
||||
emailAdapter: emailAdapter,
|
||||
emailVerifyTokenValidityDuration: 5, // 5 seconds
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
})
|
||||
.then(() => {
|
||||
user.setUsername("testEmailVerifyTokenValidity");
|
||||
user.setPassword("expiringToken");
|
||||
user.set('email', 'user@parse.com');
|
||||
return user.signUp();
|
||||
}).then(() => {
|
||||
request.get(sendEmailOptions.link, {
|
||||
followRedirect: false,
|
||||
}, (error, response, body) => {
|
||||
expect(response.statusCode).toEqual(302);
|
||||
user.fetch()
|
||||
.then(() => {
|
||||
expect(user.get('emailVerified')).toEqual(true);
|
||||
done();
|
||||
})
|
||||
.catch((err) => {
|
||||
fail("this should not fail");
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it_exclude_dbs(['postgres'])('if user clicks on the email verify link before email verification token expiration then user should be able to login', done => {
|
||||
var user = new Parse.User();
|
||||
var sendEmailOptions;
|
||||
var emailAdapter = {
|
||||
sendVerificationEmail: options => {
|
||||
sendEmailOptions = options;
|
||||
},
|
||||
sendPasswordResetEmail: () => Promise.resolve(),
|
||||
sendMail: () => {}
|
||||
}
|
||||
reconfigureServer({
|
||||
appName: 'emailVerifyToken',
|
||||
verifyUserEmails: true,
|
||||
emailAdapter: emailAdapter,
|
||||
emailVerifyTokenValidityDuration: 5, // 5 seconds
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
})
|
||||
.then(() => {
|
||||
user.setUsername("testEmailVerifyTokenValidity");
|
||||
user.setPassword("expiringToken");
|
||||
user.set('email', 'user@parse.com');
|
||||
return user.signUp();
|
||||
}).then(() => {
|
||||
request.get(sendEmailOptions.link, {
|
||||
followRedirect: false,
|
||||
}, (error, response, body) => {
|
||||
expect(response.statusCode).toEqual(302);
|
||||
Parse.User.logIn("testEmailVerifyTokenValidity", "expiringToken")
|
||||
.then(user => {
|
||||
expect(typeof user).toBe('object');
|
||||
expect(user.get('emailVerified')).toBe(true);
|
||||
done();
|
||||
})
|
||||
.catch((error) => {
|
||||
fail('login should have succeeded');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it_exclude_dbs(['postgres'])('sets the _email_verify_token_expires_at and _email_verify_token fields after user SignUp', done => {
|
||||
var user = new Parse.User();
|
||||
var sendEmailOptions;
|
||||
var emailAdapter = {
|
||||
sendVerificationEmail: options => {
|
||||
sendEmailOptions = options;
|
||||
},
|
||||
sendPasswordResetEmail: () => Promise.resolve(),
|
||||
sendMail: () => {}
|
||||
}
|
||||
reconfigureServer({
|
||||
appName: 'emailVerifyToken',
|
||||
verifyUserEmails: true,
|
||||
emailAdapter: emailAdapter,
|
||||
emailVerifyTokenValidityDuration: 5, // 5 seconds
|
||||
publicServerURL: 'http://localhost:8378/1'
|
||||
})
|
||||
.then(() => {
|
||||
user.setUsername('sets_email_verify_token_expires_at');
|
||||
user.setPassword('expiringToken');
|
||||
user.set('email', 'user@parse.com');
|
||||
return user.signUp();
|
||||
})
|
||||
.then(() => {
|
||||
const databaseURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase';
|
||||
return MongoClient.connect(databaseURI);
|
||||
})
|
||||
.then(database => {
|
||||
expect(typeof database).toBe('object');
|
||||
return database.collection('test__User').findOne({username: 'sets_email_verify_token_expires_at'});
|
||||
})
|
||||
.then(user => {
|
||||
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');
|
||||
done();
|
||||
})
|
||||
.catch(error => {
|
||||
fail("this should not fail");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it_exclude_dbs(['postgres'])('unsets the _email_verify_token_expires_at and _email_verify_token fields in the User class if email verification is successful', done => {
|
||||
var user = new Parse.User();
|
||||
var sendEmailOptions;
|
||||
var emailAdapter = {
|
||||
sendVerificationEmail: options => {
|
||||
sendEmailOptions = options;
|
||||
},
|
||||
sendPasswordResetEmail: () => Promise.resolve(),
|
||||
sendMail: () => {}
|
||||
}
|
||||
reconfigureServer({
|
||||
appName: 'emailVerifyToken',
|
||||
verifyUserEmails: true,
|
||||
emailAdapter: emailAdapter,
|
||||
emailVerifyTokenValidityDuration: 5, // 5 seconds
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
})
|
||||
.then(() => {
|
||||
user.setUsername("unsets_email_verify_token_expires_at");
|
||||
user.setPassword("expiringToken");
|
||||
user.set('email', 'user@parse.com');
|
||||
return user.signUp();
|
||||
})
|
||||
.then(() => {
|
||||
request.get(sendEmailOptions.link, {
|
||||
followRedirect: false,
|
||||
}, (error, response, body) => {
|
||||
expect(response.statusCode).toEqual(302);
|
||||
|
||||
const databaseURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase';
|
||||
MongoClient.connect(databaseURI)
|
||||
.then(database => {
|
||||
expect(typeof database).toBe('object');
|
||||
return database.collection('test__User').findOne({username: 'unsets_email_verify_token_expires_at'});
|
||||
})
|
||||
.then(user => {
|
||||
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');
|
||||
done();
|
||||
})
|
||||
.catch(error => {
|
||||
fail("this should not fail");
|
||||
done();
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(error => {
|
||||
fail("this should not fail");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it_exclude_dbs(['postgres'])('clicking on the email verify link by an email VERIFIED user that was setup before enabling the expire email verify token should show an invalid link', done => {
|
||||
var user = new Parse.User();
|
||||
var sendEmailOptions;
|
||||
var emailAdapter = {
|
||||
sendVerificationEmail: options => {
|
||||
sendEmailOptions = options;
|
||||
},
|
||||
sendPasswordResetEmail: () => Promise.resolve(),
|
||||
sendMail: () => {}
|
||||
}
|
||||
var serverConfig = {
|
||||
appName: 'emailVerifyToken',
|
||||
verifyUserEmails: true,
|
||||
emailAdapter: emailAdapter,
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
};
|
||||
|
||||
// setup server WITHOUT enabling the expire email verify token flag
|
||||
reconfigureServer(serverConfig)
|
||||
.then(() => {
|
||||
user.setUsername("testEmailVerifyTokenValidity");
|
||||
user.setPassword("expiringToken");
|
||||
user.set('email', 'user@parse.com');
|
||||
return user.signUp();
|
||||
})
|
||||
.then(() => {
|
||||
return new Promise((resolve, reject) => {
|
||||
request.get(sendEmailOptions.link, { followRedirect: false, })
|
||||
.on('error', error => reject(error))
|
||||
.on('response', (response) => {
|
||||
expect(response.statusCode).toEqual(302);
|
||||
resolve(user.fetch());
|
||||
});
|
||||
});
|
||||
})
|
||||
.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(() => {
|
||||
request.get(sendEmailOptions.link, {
|
||||
followRedirect: false,
|
||||
}, (error, response, body) => {
|
||||
expect(response.statusCode).toEqual(302);
|
||||
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html');
|
||||
done();
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
fail("this should not fail");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it_exclude_dbs(['postgres'])('clicking on the email verify link by an email UNVERIFIED user that was setup before enabling the expire email verify token should show an invalid link', done => {
|
||||
var user = new Parse.User();
|
||||
var sendEmailOptions;
|
||||
var emailAdapter = {
|
||||
sendVerificationEmail: options => {
|
||||
sendEmailOptions = options;
|
||||
},
|
||||
sendPasswordResetEmail: () => Promise.resolve(),
|
||||
sendMail: () => {}
|
||||
}
|
||||
var serverConfig = {
|
||||
appName: 'emailVerifyToken',
|
||||
verifyUserEmails: true,
|
||||
emailAdapter: emailAdapter,
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
};
|
||||
|
||||
// setup server WITHOUT enabling the expire email verify token flag
|
||||
reconfigureServer(serverConfig)
|
||||
.then(() => {
|
||||
user.setUsername("testEmailVerifyTokenValidity");
|
||||
user.setPassword("expiringToken");
|
||||
user.set('email', 'user@parse.com');
|
||||
return user.signUp();
|
||||
})
|
||||
.then(() => {
|
||||
// just get the user again - DO NOT email verify the user
|
||||
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(() => {
|
||||
request.get(sendEmailOptions.link, {
|
||||
followRedirect: false,
|
||||
}, (error, response, body) => {
|
||||
expect(response.statusCode).toEqual(302);
|
||||
expect(response.body).toEqual('Found. Redirecting to http://localhost:8378/1/apps/invalid_link.html');
|
||||
done();
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
fail("this should not fail");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it_exclude_dbs(['postgres'])('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 => {
|
||||
|
||||
const databaseURI = 'mongodb://localhost:27017/parseServerMongoAdapterTestDatabase';
|
||||
let db;
|
||||
|
||||
let user = new Parse.User();
|
||||
let userBeforeEmailReset;
|
||||
|
||||
let sendEmailOptions;
|
||||
let emailAdapter = {
|
||||
sendVerificationEmail: options => {
|
||||
sendEmailOptions = options;
|
||||
},
|
||||
sendPasswordResetEmail: () => Promise.resolve(),
|
||||
sendMail: () => {}
|
||||
};
|
||||
let serverConfig = {
|
||||
appName: 'emailVerifyToken',
|
||||
verifyUserEmails: true,
|
||||
emailAdapter: emailAdapter,
|
||||
emailVerifyTokenValidityDuration: 5, // 5 seconds
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
};
|
||||
|
||||
reconfigureServer(serverConfig)
|
||||
.then(() => {
|
||||
user.setUsername("newEmailVerifyTokenOnEmailReset");
|
||||
user.setPassword("expiringToken");
|
||||
user.set('email', 'user@parse.com');
|
||||
return user.signUp();
|
||||
})
|
||||
.then(() => {
|
||||
return MongoClient.connect(databaseURI);
|
||||
})
|
||||
.then(database => {
|
||||
expect(typeof database).toBe('object');
|
||||
db = database; //save the db object for later use
|
||||
return db.collection('test__User').findOne({username: 'newEmailVerifyTokenOnEmailReset'});
|
||||
})
|
||||
.then(userFromDb => {
|
||||
expect(typeof userFromDb).toBe('object');
|
||||
userBeforeEmailReset = userFromDb;
|
||||
|
||||
// trigger another token generation by setting the email
|
||||
user.set('email', 'user@parse.com');
|
||||
return new Promise((resolve, reject) => {
|
||||
// wait for half a sec to get a new expiration time
|
||||
setTimeout( () => resolve(user.save()), 500 );
|
||||
});
|
||||
})
|
||||
.then(() => {
|
||||
// get user data after email reset and new token generation
|
||||
return db.collection('test__User').findOne({username: 'newEmailVerifyTokenOnEmailReset'});
|
||||
})
|
||||
.then(userAfterEmailReset => {
|
||||
expect(typeof userAfterEmailReset).toBe('object');
|
||||
expect(userBeforeEmailReset._email_verify_token).not.toEqual(userAfterEmailReset._email_verify_token);
|
||||
expect(userBeforeEmailReset._email_verify_token_expires_at).not.toEqual(userAfterEmailReset.__email_verify_token_expires_at);
|
||||
done();
|
||||
})
|
||||
.catch((err) => {
|
||||
fail("this should not fail");
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it_exclude_dbs(['postgres'])('client should not see the _email_verify_token_expires_at field', done => {
|
||||
var user = new Parse.User();
|
||||
var sendEmailOptions;
|
||||
var emailAdapter = {
|
||||
sendVerificationEmail: options => {
|
||||
sendEmailOptions = options;
|
||||
},
|
||||
sendPasswordResetEmail: () => Promise.resolve(),
|
||||
sendMail: () => {}
|
||||
}
|
||||
reconfigureServer({
|
||||
appName: 'emailVerifyToken',
|
||||
verifyUserEmails: true,
|
||||
emailAdapter: emailAdapter,
|
||||
emailVerifyTokenValidityDuration: 5, // 5 seconds
|
||||
publicServerURL: "http://localhost:8378/1"
|
||||
})
|
||||
.then(() => {
|
||||
user.setUsername("testEmailVerifyTokenValidity");
|
||||
user.setPassword("expiringToken");
|
||||
user.set('email', 'user@parse.com');
|
||||
return user.signUp();
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
user.fetch()
|
||||
.then(() => {
|
||||
expect(user.get('emailVerified')).toEqual(false);
|
||||
expect(typeof user.get('_email_verify_token_expires_at')).toBe('undefined');
|
||||
done();
|
||||
})
|
||||
.catch(error => {
|
||||
fail("this should not fail");
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
})
|
||||
Reference in New Issue
Block a user