package org.cloudfoundry.identity.uaa.integration.feature;
import com.dumbster.smtp.SimpleSmtpServer;
import com.dumbster.smtp.SmtpMessage;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.web.client.RestTemplate;
import java.net.URI;
import java.security.SecureRandom;
import java.util.Iterator;
import static org.apache.commons.lang3.StringUtils.contains;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.springframework.http.HttpStatus.FOUND;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = DefaultIntegrationTestConfig.class)
public class ChangeEmailIT {
@Autowired @Rule
public IntegrationTestRule integrationTestRule;
@Autowired
WebDriver webDriver;
@Value("${integration.test.base_url}")
String baseUrl;
@Autowired
SimpleSmtpServer simpleSmtpServer;
@Autowired
TestClient testClient;
private String userEmail;
@Before
@After
public void logout_and_clear_cookies() {
try {
webDriver.get(baseUrl + "/logout.do");
}catch (org.openqa.selenium.TimeoutException x) {
//try again - this should not be happening - 20 second timeouts
webDriver.get(baseUrl + "/logout.do");
}
webDriver.manage().deleteAllCookies();
}
@Before
public void setUp() throws Exception {
int randomInt = new SecureRandom().nextInt();
String adminAccessToken = testClient.getOAuthAccessToken("admin", "adminsecret", "client_credentials", "clients.read clients.write clients.secret clients.admin");
String scimClientId = "scim" + randomInt;
testClient.createScimClient(adminAccessToken, scimClientId);
String scimAccessToken = testClient.getOAuthAccessToken(scimClientId, "scimsecret", "client_credentials", "scim.read scim.write password.write");
userEmail = "user" + randomInt + "@example.com";
testClient.createUser(scimAccessToken, userEmail, userEmail, "secr3T", true);
}
@Test
public void testChangeEmailWithLogout() throws Exception {
testChangeEmail(true);
}
@Test
public void testChangeEmailWithoutLogout() throws Exception {
testChangeEmail(false);
}
public void testChangeEmail(boolean logout) throws Exception {
signIn(userEmail, "secr3T");
int receivedEmailSize = simpleSmtpServer.getReceivedEmailSize();
webDriver.get(baseUrl + "/profile");
Assert.assertEquals(userEmail, webDriver.findElement(By.cssSelector(".profile .email")).getText());
webDriver.findElement(By.linkText("Change Email")).click();
Assert.assertEquals("Current Email Address: " + userEmail, webDriver.findElement(By.cssSelector(".email-display")).getText());
String newEmail = userEmail.replace("user", "new");
webDriver.findElement(By.name("newEmail")).sendKeys(newEmail);
webDriver.findElement(By.xpath("//input[@value='Send Verification Link']")).click();
assertThat(webDriver.findElement(By.cssSelector("h1")).getText(), containsString("Instructions Sent"));
assertEquals(receivedEmailSize + 1, simpleSmtpServer.getReceivedEmailSize());
Iterator receivedEmail = simpleSmtpServer.getReceivedEmail();
SmtpMessage message = (SmtpMessage) receivedEmail.next();
receivedEmail.remove();
assertEquals(newEmail, message.getHeaderValue("To"));
assertThat(message.getBody(), containsString("Verify your email"));
String link = testClient.extractLink(message.getBody());
assertFalse(contains(link, "@"));
assertFalse(contains(link, "%40"));
if (logout) {
webDriver.get(baseUrl + "/logout.do");
}
webDriver.get(link);
assertThat(webDriver.findElement(By.cssSelector("h1")).getText(), containsString("Account Settings"));
assertThat(webDriver.findElement(By.cssSelector(".alert-success")).getText(), containsString("Email address successfully verified."));
assertThat(webDriver.findElement(By.cssSelector(".nav")).getText(), containsString(newEmail));
assertThat(webDriver.findElement(By.cssSelector(".profile")).getText(), containsString(newEmail));
}
@Test
public void testChangeEmailWithClientRedirect() throws Exception{
signIn(userEmail, "secr3T");
webDriver.get(baseUrl + "/change_email?client_id=app");
String newEmail = userEmail.replace("user", "new");
webDriver.findElement(By.name("newEmail")).sendKeys(newEmail);
webDriver.findElement(By.xpath("//input[@value='Send Verification Link']")).click();
Iterator receivedEmail = simpleSmtpServer.getReceivedEmail();
SmtpMessage message = (SmtpMessage) receivedEmail.next();
receivedEmail.remove();
String link = testClient.extractLink(message.getBody());
//rest template that does NOT follow redirects
RestTemplate restTemplate = new RestTemplate(new DefaultIntegrationTestConfig.HttpClientFactory());
ResponseEntity<String> responseEntity = restTemplate.getForEntity(link, String.class);
assertEquals(FOUND, responseEntity.getStatusCode());
assertEquals(new URI("http://localhost:8080/app/"), responseEntity.getHeaders().getLocation());
}
private void signIn(String userName, String password) {
webDriver.get(baseUrl + "/logout.do");
webDriver.get(baseUrl + "/login");
webDriver.findElement(By.name("username")).sendKeys(userName);
webDriver.findElement(By.name("password")).sendKeys(password);
webDriver.findElement(By.xpath("//input[@value='Sign in']")).click();
assertThat(webDriver.findElement(By.cssSelector("h1")).getText(), containsString("Where to?"));
}
}