/*
* Copyright (c) 2007-2014 by Public Library of Science
*
* http://plos.org
* http://ambraproject.org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.ambraproject.service.user;
import org.ambraproject.action.BaseTest;
import org.ambraproject.models.UserProfile;
import org.ambraproject.service.password.PasswordDigestService;
import org.ambraproject.testutils.DummyAmbraMailer;
import org.springframework.beans.factory.annotation.Autowired;
import org.testng.annotations.Test;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
/**
* @author Alex Kudlick 9/24/12
*/
public class UserRegistrationServiceTest extends BaseTest {
@Autowired
protected UserRegistrationService userRegistrationService;
@Autowired
protected DummyAmbraMailer dummyMailer;
@Autowired
protected PasswordDigestService passwordDigestService;
@Test
public void testRegisterUser() throws DuplicateUserException {
int numSentEmails = dummyMailer.getEmailsSent().size();
String password = "myCoolPass";
UserProfile profile = new UserProfile("testRegisterUser@example.com", "testRegisterUser", password);
Long userId = userRegistrationService.registerUser(profile, password);
assertNotNull(userId, "returned null id");
UserProfile storedUser = dummyDataStore.get(UserProfile.class, userId);
assertNotNull(storedUser, "failed to save user profile");
assertEquals(storedUser.getEmail(), profile.getEmail(), "stored user with incorrect email");
assertNotNull(storedUser.getPassword(), "failed to store password");
assertTrue(passwordDigestService.verifyPassword(password, storedUser.getPassword()),
"failed to hash password");
assertEquals(dummyMailer.getEmailsSent().size(), numSentEmails + 1, "failed to send verifiction email");
DummyAmbraMailer.DummyEmail verificationEmail = dummyMailer.getEmailsSent().get(numSentEmails);
assertEquals(verificationEmail.getToEmailAddresses(), profile.getEmail(),
"sent verification email to incorrect address");
assertEquals(verificationEmail.getContext().get("email"), profile.getEmail(), "Incorrect email in context");
assertEquals(verificationEmail.getContext().get("verificationToken"), storedUser.getVerificationToken(),
"Incorrect email verification token in context");
assertFalse(storedUser.getVerified(), "Stored user object was already verified");
}
@Test()
public void testRegisterUserWithDuplicateEmail() throws DuplicateUserException {
userRegistrationService.registerUser(
new UserProfile("registerWithDuplicate@example.com", "registerWithDuplicate", "pass"), "pass");
try {
userRegistrationService.registerUser(
new UserProfile("registerWithDuplicate@example.com", "registerWithDuplicate", "pass"), "pass");
fail("should have thrown duplicate user exception");
} catch (DuplicateUserException e) {
assertEquals(e.getField(), DuplicateUserException.Field.EMAIL,
"didn't throw duplicate user exception with appropriate field");
}
}
@Test
public void testResendVerificationEmail() throws DuplicateUserException, UserAlreadyVerifiedException, NoSuchUserException {
UserProfile profile = new UserProfile("testResendVerification@test.org", "resendVerificationEmail@example.com", "pass");
dummyDataStore.store(profile);
String oldVerificationToken = profile.getVerificationToken();
int numSentEmails = dummyMailer.getEmailsSent().size();
userRegistrationService.resendVerificationEmail(profile.getEmail());
String verificationToken = dummyDataStore.get(UserProfile.class, profile.getID()).getVerificationToken();
assertFalse(verificationToken.equals(oldVerificationToken),
"failed to change verification token");
assertEquals(dummyMailer.getEmailsSent().size(), numSentEmails + 1, "failed to resend verifiction email");
DummyAmbraMailer.DummyEmail verificationEmail = dummyMailer.getEmailsSent().get(numSentEmails);
assertEquals(verificationEmail.getToEmailAddresses(), profile.getEmail(),
"sent verification email to incorrect address");
assertEquals(verificationEmail.getContext().get("email"), profile.getEmail(), "Incorrect email in context");
assertEquals(verificationEmail.getContext().get("verificationToken"), verificationToken,
"Incorrect email verification token in context");
}
@Test(expectedExceptions = {UserAlreadyVerifiedException.class})
public void testResendToVerifiedUser() throws DuplicateUserException, UserAlreadyVerifiedException, NoSuchUserException {
String email = "resendToVerifiedUser@test.org";
UserProfile profile = new UserProfile(email, "testResendToVerifiedUser", "pass");
profile.setVerified(true);
dummyDataStore.store(profile);
userRegistrationService.resendVerificationEmail(email);
}
@Test(expectedExceptions = {NoSuchUserException.class})
public void testResendToNonexistentUser() throws UserAlreadyVerifiedException, NoSuchUserException {
userRegistrationService.resendVerificationEmail("NonExistentEmail@example.com");
}
@Test
public void testSendForgotPasswordMessage() throws Exception {
UserProfile profile = new UserProfile(
"sendForgotPasswordMessage@test.org",
"testSendForgotPasswordMessage",
"pass");
profile.setVerified(true);
Long id = Long.valueOf(dummyDataStore.store(profile));
String oldEmailVerificationToken = profile.getVerificationToken();
int numSentEmails = dummyMailer.getEmailsSent().size();
userRegistrationService.sendForgotPasswordMessage(profile.getEmail());
profile = dummyDataStore.get(UserProfile.class, id);
assertNotNull(profile.getVerificationToken(), "nulled out email verification token");
assertFalse(profile.getVerificationToken().equalsIgnoreCase(oldEmailVerificationToken),
"Failed to set new email verification token");
assertEquals(dummyMailer.getEmailsSent().size(), numSentEmails + 1, "failed to send an email");
DummyAmbraMailer.DummyEmail passwordEmail = dummyMailer.getEmailsSent().get(numSentEmails);
assertEquals(passwordEmail.getToEmailAddresses(), profile.getEmail(), "sent email to incorrect email");
assertEquals(passwordEmail.getContext().get("email"), profile.getEmail(), "sent incorrect email in template");
assertEquals(passwordEmail.getContext().get("verificationToken"), profile.getVerificationToken(),
"sent incorrect email verification token");
}
@Test(expectedExceptions = NoSuchUserException.class)
public void testSendForgotPasswordMessageNotVerified() throws Exception {
UserProfile profile = new UserProfile(
"sendForgotPasswordMessage2@test.org",
"testSendForgotPasswordMessage2",
"pass2");
dummyDataStore.store(profile);
userRegistrationService.sendForgotPasswordMessage(profile.getEmail());
}
@Test
public void testValidateEmailVerificationToken() throws Exception {
UserProfile profile1 = new UserProfile("validateEmailToken@test.org", "validateEmail1", "pass");
dummyDataStore.store(profile1);
UserProfile profile2 = new UserProfile("validateEmailToken2@test.org", "validateEmail2", "pass");
dummyDataStore.store(profile2);
assertTrue(userRegistrationService.validateVerificationToken(
profile1.getEmail(),
profile1.getVerificationToken()),
"failed to correctly verify token");
assertFalse(userRegistrationService.validateVerificationToken(
profile2.getEmail(),
profile1.getVerificationToken()),
"should return false for non-matching email and token");
assertFalse(userRegistrationService.validateVerificationToken(
"nonExistent@email.gov",
profile2.getVerificationToken()),
"should return false for non-existent email");
assertFalse(userRegistrationService.validateVerificationToken(
profile2.getEmail(),
"fakeVerificationToken"),
"should return false for non-existent verification token");
}
@Test
public void testResetPassword() throws Exception {
UserProfile profile = new UserProfile("resetPassword@example.com", "resetPassword", "testPass");
dummyDataStore.store(profile);
String passwordToSet = "a new password";
userRegistrationService.resetPassword(profile.getEmail(), passwordToSet);
String storedPassword = dummyDataStore.get(UserProfile.class, profile.getID()).getPassword();
assertFalse(storedPassword.equalsIgnoreCase(profile.getPassword()), "failed to change password");
assertTrue(passwordDigestService.verifyPassword(passwordToSet, storedPassword), "failed to hash new password");
}
@Test
public void testVerfiyUser() throws Exception {
UserProfile profile = new UserProfile("verifyUser@example.com", "verifyUser", "pass");
dummyDataStore.store(profile);
userRegistrationService.verifyUser(profile.getEmail(), profile.getVerificationToken());
assertTrue(dummyDataStore.get(UserProfile.class, profile.getID()).getVerified(),
"failed to verify user");
try {
userRegistrationService.verifyUser(profile.getEmail(), profile.getVerificationToken());
fail("Should have thrown UserAlreadyVerifiedException");
} catch (UserAlreadyVerifiedException e) {
//expected
}
try {
userRegistrationService.verifyUser("nonExistent@user.org", profile.getVerificationToken());
fail("Should have thrown NoSuchUserException");
} catch (NoSuchUserException e) {
//expected
}
}
@Test
public void testSendChangeEmailNotice() throws Exception {
String password = "pass";
int numSentEmails = dummyMailer.getEmailsSent().size();
UserProfile profile = new UserProfile("changeEmailMessage@example.org",
"changeEmailMessage",
passwordDigestService.generateDigest(password));
dummyDataStore.store(profile);
String oldVerificationToken = profile.getVerificationToken();
String newEmail = "newEmail1@example.org";
userRegistrationService.sendEmailChangeMessage(profile.getEmail(), newEmail, password);
assertFalse(dummyDataStore.get(UserProfile.class, profile.getID())
.getVerificationToken().equalsIgnoreCase(oldVerificationToken),
"failed to change verification token");
assertEquals(dummyMailer.getEmailsSent().size(), numSentEmails + 1, "failed to send message");
assertEquals(dummyMailer.getEmailsSent().get(numSentEmails).getToEmailAddresses(), newEmail,
"sent email to incorrect address");
}
@Test(expectedExceptions = {SecurityException.class})
public void testSendChangeEmailNoticeWithInvalidPassword() throws Exception {
UserProfile profile = new UserProfile("invalidPassword@example.org",
"invalidPassword",
passwordDigestService.generateDigest("pass"));
dummyDataStore.store(profile);
userRegistrationService.sendEmailChangeMessage(profile.getEmail(), "foo", "badPass");
}
@Test
public void testChangeEmail() throws Exception {
UserProfile profile = new UserProfile("changeEmail@example.org", "testChangeEmail", "pass");
dummyDataStore.store(profile);
UserProfile userProfile = new UserProfile(
profile.getEmail(),
"displayNameChangeEmail", "pass");
dummyDataStore.store(userProfile);
String newEmail = "newEmail@example.org";
userRegistrationService.updateEmailAddress(profile.getEmail(), newEmail,
profile.getVerificationToken());
assertEquals(dummyDataStore.get(UserProfile.class, profile.getID()).getEmail(), newEmail,
"failed to update email");
}
@Test(expectedExceptions = { DuplicateUserException.class })
public void testSendChangeEmailDupe() throws Exception {
dummyDataStore.store(new UserProfile("test@duplicate.org", "testChangeDupeEmail",
passwordDigestService.generateDigest("pass")));
UserProfile profile = new UserProfile("test1@duplicate.org", "test1ChangeDupeEmail",
passwordDigestService.generateDigest("pass1"));
dummyDataStore.store(profile);
userRegistrationService.sendEmailChangeMessage(profile.getEmail(), "test@duplicate.org", "pass1");
}
@Test(expectedExceptions = { DuplicateUserException.class })
public void testChangeEmailDupe() throws Exception {
dummyDataStore.store(new UserProfile("test@duplicate1.org", "testChangeDupe1Email",
passwordDigestService.generateDigest("pass")));
UserProfile profile = new UserProfile("test1@duplicate1.org", "test1ChangeDupe1Email",
passwordDigestService.generateDigest("pass1"));
dummyDataStore.store(profile);
userRegistrationService.updateEmailAddress(profile.getEmail(), "test@duplicate1.org", profile.getVerificationToken());
}
}