Java tutorial
/* * Cloud Foundry 2012.02.03 Beta * Copyright (c) [2009-2012] VMware, Inc. All Rights Reserved. * * This product is licensed to you under the Apache License, Version 2.0 (the "License"). * You may not use this product except in compliance with the License. * * This product includes a number of subcomponents with * separate copyright notices and license terms. Your use of these * subcomponents is subject to the terms and conditions of the * subcomponent's license, as noted in the LICENSE file. */ package org.cloudfoundry.identity.uaa.integration; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import org.cloudfoundry.identity.uaa.scim.ScimUser; import org.cloudfoundry.identity.uaa.test.TestAccountSetup; import org.cloudfoundry.identity.uaa.test.UaaTestAccounts; import org.codehaus.jackson.map.ObjectMapper; import org.junit.Assume; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.oauth2.client.test.OAuth2ContextConfiguration; import org.springframework.security.oauth2.client.test.OAuth2ContextSetup; import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; import org.springframework.web.client.RestOperations; /** * @author Luke Taylor * @author Dave Syer */ @OAuth2ContextConfiguration(OAuth2ContextConfiguration.ClientCredentials.class) public class ScimUserEndpointsIntegrationTests { private final String JOEL = "joel_" + new RandomValueStringGenerator().generate().toLowerCase(); private final String JOE = "joe_" + new RandomValueStringGenerator().generate().toLowerCase(); private final String DELETE_ME = "deleteme_" + new RandomValueStringGenerator().generate().toLowerCase(); private final String userEndpoint = "/Users"; private final String usersEndpoint = "/Users"; private static final int NUM_DEFAULT_GROUPS_ON_STARTUP = 8; @Rule public ServerRunning serverRunning = ServerRunning.isRunning(); private UaaTestAccounts testAccounts = UaaTestAccounts.standard(serverRunning); @Rule public OAuth2ContextSetup context = OAuth2ContextSetup.withTestAccounts(serverRunning, testAccounts); @Rule public TestAccountSetup testAccountSetup = TestAccountSetup.standard(serverRunning, testAccounts); private RestOperations client; @Before public void createRestTemplate() throws Exception { // Assume.assumeTrue(!testAccounts.isProfileActive("vcap")); client = serverRunning.getRestTemplate(); } @SuppressWarnings("rawtypes") private ResponseEntity<Map> deleteUser(String id, int version) { HttpHeaders headers = new HttpHeaders(); headers.add("If-Match", "\"" + version + "\""); return client.exchange(serverRunning.getUrl(userEndpoint + "/{id}"), HttpMethod.DELETE, new HttpEntity<Void>(headers), Map.class, id); } private ResponseEntity<ScimUser> createUser(String username, String firstName, String lastName, String email) { ScimUser user = new ScimUser(); user.setUserName(username); user.setName(new ScimUser.Name(firstName, lastName)); user.addEmail(email); return client.postForEntity(serverRunning.getUrl(userEndpoint), user, ScimUser.class); } // curl -v -H "Content-Type: application/json" -H "Accept: application/json" --data // "{\"userName\":\"joe\",\"schemas\":[\"urn:scim:schemas:core:1.0\"]}" http://localhost:8080/uaa/User @Test public void createUserSucceeds() throws Exception { ResponseEntity<ScimUser> response = createUser(JOE, "Joe", "User", "joe@blah.com"); ScimUser joe1 = response.getBody(); assertEquals(JOE, joe1.getUserName()); // Check we can GET the user ScimUser joe2 = client.getForObject(serverRunning.getUrl(userEndpoint + "/{id}"), ScimUser.class, joe1.getId()); assertEquals(joe1.getId(), joe2.getId()); } @Test public void createUserWithNoEmailFails() throws Exception { ScimUser user = new ScimUser(); user.setUserName("dave"); user.setName(new ScimUser.Name("Dave", "Syer")); @SuppressWarnings("rawtypes") ResponseEntity<Map> response = client.postForEntity(serverRunning.getUrl(userEndpoint), user, Map.class); @SuppressWarnings("unchecked") Map<String, String> error = response.getBody(); System.err.println(error); assertEquals(HttpStatus.BAD_REQUEST, response.getStatusCode()); assertEquals("invalid_scim_resource", error.get("error")); } @Test public void getUserHasEtag() throws Exception { ResponseEntity<ScimUser> response = createUser(JOE, "Joe", "User", "joe@blah.com"); ScimUser joe = response.getBody(); assertEquals(JOE, joe.getUserName()); // Check we can GET the user ResponseEntity<ScimUser> result = client.getForEntity(serverRunning.getUrl(userEndpoint + "/{id}"), ScimUser.class, joe.getId()); assertEquals("\"" + joe.getVersion() + "\"", result.getHeaders().getFirst("ETag")); } // curl -v -H "Content-Type: application/json" -X PUT -H "Accept: application/json" --data // "{\"userName\":\"joe\",\"schemas\":[\"urn:scim:schemas:core:1.0\"]}" http://localhost:8080/uaa/User @Test public void updateUserSucceeds() throws Exception { ResponseEntity<ScimUser> response = createUser(JOE, "Joe", "User", "joe@blah.com"); ScimUser joe = response.getBody(); assertEquals(JOE, joe.getUserName()); joe.setName(new ScimUser.Name("Joe", "Bloggs")); HttpHeaders headers = new HttpHeaders(); headers.add("If-Match", "\"" + joe.getVersion() + "\""); response = client.exchange(serverRunning.getUrl(userEndpoint) + "/{id}", HttpMethod.PUT, new HttpEntity<ScimUser>(joe, headers), ScimUser.class, joe.getId()); ScimUser joe1 = response.getBody(); assertEquals(JOE, joe1.getUserName()); assertEquals(joe.getId(), joe1.getId()); } @Test public void updateUserNameSucceeds() throws Exception { ResponseEntity<ScimUser> response = createUser(JOE, "Joe", "User", "joe@blah.com"); ScimUser joe = response.getBody(); assertEquals(JOE, joe.getUserName()); joe.setUserName(JOE + "new"); HttpHeaders headers = new HttpHeaders(); headers.add("If-Match", "\"" + joe.getVersion() + "\""); response = client.exchange(serverRunning.getUrl(userEndpoint) + "/{id}", HttpMethod.PUT, new HttpEntity<ScimUser>(joe, headers), ScimUser.class, joe.getId()); ScimUser joe1 = response.getBody(); assertEquals(JOE + "new", joe1.getUserName()); assertEquals(joe.getId(), joe1.getId()); } @SuppressWarnings({ "rawtypes", "unchecked" }) @Test public void updateUserWithBadAttributeFails() throws Exception { ResponseEntity<ScimUser> created = createUser(JOE, "Joe", "User", "joe@blah.com"); ScimUser joe = created.getBody(); HttpHeaders headers = new HttpHeaders(); headers.add("If-Match", "\"" + joe.getVersion() + "\""); ObjectMapper mapper = new ObjectMapper(); Map<String, Object> map = new HashMap<String, Object>( mapper.readValue(mapper.writeValueAsString(joe), Map.class)); map.put("nottheusername", JOE + "0"); ResponseEntity<Map> response = client.exchange(serverRunning.getUrl(userEndpoint) + "/{id}", HttpMethod.PUT, new HttpEntity<Map>(map, headers), Map.class, joe.getId()); Map<String, Object> joe1 = response.getBody(); assertTrue("Wrong message: " + joe1, ((String) joe1.get("message")).toLowerCase().contains("unrecognized field")); } @SuppressWarnings({ "rawtypes", "unchecked" }) @Test public void testJsonCaseInsensitivity() throws Exception { ResponseEntity<ScimUser> created = createUser(JOE, "Joe", "User", "joe@blah.com"); ScimUser joe = created.getBody(); HttpHeaders headers = new HttpHeaders(); headers.add("If-Match", "\"" + joe.getVersion() + "\""); ObjectMapper mapper = new ObjectMapper(); Map<String, Object> map = new HashMap<String, Object>( mapper.readValue(mapper.writeValueAsString(joe), Map.class)); map.put("username", JOE + "0"); map.remove("userName"); ResponseEntity<ScimUser> response = client.exchange(serverRunning.getUrl(userEndpoint) + "/{id}", HttpMethod.PUT, new HttpEntity<Map>(map, headers), ScimUser.class, joe.getId()); ScimUser joe1 = response.getBody(); assertEquals(JOE + "0", joe1.getUserName()); } @Test public void updateUserWithNewAuthoritiesSucceeds() throws Exception { ResponseEntity<ScimUser> response = createUser(JOE, "Joe", "User", "joe@blah.com"); ScimUser joe = response.getBody(); assertEquals(JOE, joe.getUserName()); joe.setUserType("admin"); HttpHeaders headers = new HttpHeaders(); headers.add("If-Match", "\"" + joe.getVersion() + "\""); response = client.exchange(serverRunning.getUrl(userEndpoint) + "/{id}", HttpMethod.PUT, new HttpEntity<ScimUser>(joe, headers), ScimUser.class, joe.getId()); ScimUser joe1 = response.getBody(); assertEquals(JOE, joe1.getUserName()); assertEquals(joe.getId(), joe1.getId()); assertNull(joe1.getUserType()); // check that authorities was not updated } @Test public void updateUserGroupsDoesNothing() { ResponseEntity<ScimUser> response = createUser(JOE, "Joe", "User", "joe@blah.com"); ScimUser joe = response.getBody(); assertEquals(JOE, joe.getUserName()); assertEquals(NUM_DEFAULT_GROUPS_ON_STARTUP, joe.getGroups().size()); joe.setGroups(Arrays.asList(new ScimUser.Group(UUID.randomUUID().toString(), "uaa.admin"))); HttpHeaders headers = new HttpHeaders(); headers.add("If-Match", "\"" + joe.getVersion() + "\""); response = client.exchange(serverRunning.getUrl(userEndpoint) + "/{id}", HttpMethod.PUT, new HttpEntity<ScimUser>(joe, headers), ScimUser.class, joe.getId()); ScimUser joe1 = response.getBody(); assertEquals(JOE, joe1.getUserName()); assertEquals(joe.getId(), joe1.getId()); assertEquals(NUM_DEFAULT_GROUPS_ON_STARTUP, joe1.getGroups().size()); } // curl -v -H "Content-Type: application/json" -H "Accept: application/json" -H 'If-Match: "0"' --data // "{\"userName\":\"joe\",\"schemas\":[\"urn:scim:schemas:core:1.0\"]}" http://localhost:8080/uaa/User @Test public void createUserTwiceFails() throws Exception { ScimUser user = new ScimUser(); user.setUserName(JOEL); user.setName(new ScimUser.Name("Joel", "D'sa")); user.addEmail("joel@blah.com"); @SuppressWarnings("rawtypes") ResponseEntity<Map> response = client.postForEntity(serverRunning.getUrl(userEndpoint), user, Map.class); @SuppressWarnings("unchecked") Map<String, String> joel = response.getBody(); assertEquals(JOEL, joel.get("userName")); response = client.postForEntity(serverRunning.getUrl(userEndpoint), user, Map.class); @SuppressWarnings("unchecked") Map<String, String> error = response.getBody(); // System.err.println(error); assertEquals("scim_resource_already_exists", error.get("error")); } @Test public void createUserWithJustACaseChangeFails() throws Exception { String userName = JOEL; String userNameDifferenceCase = userName.toUpperCase(); ScimUser user = new ScimUser(); user.setUserName(userName); user.setName(new ScimUser.Name("Joel", "D'sa")); user.addEmail("joel@blah.com"); @SuppressWarnings("rawtypes") ResponseEntity<Map> response = client.postForEntity(serverRunning.getUrl(userEndpoint), user, Map.class); @SuppressWarnings("unchecked") Map<String, String> joel = response.getBody(); assertEquals(JOEL, joel.get("userName")); ScimUser userDifferentCase = new ScimUser(); userDifferentCase.setUserName(userNameDifferenceCase); userDifferentCase.setName(new ScimUser.Name("Joel", "D'sa")); userDifferentCase.addEmail("joel@blah.com"); response = client.postForEntity(serverRunning.getUrl(userEndpoint), userDifferentCase, Map.class); @SuppressWarnings("unchecked") Map<String, String> error = response.getBody(); // System.err.println(error); assertEquals("scim_resource_already_exists", error.get("error")); } // curl -v -H "Content-Type: application/json" -H "Accept: application/json" -X DELETE // -H "If-Match: 0" http://localhost:8080/uaa/User/joel @Test public void deleteUserWithWrongIdFails() throws Exception { @SuppressWarnings("rawtypes") ResponseEntity<Map> response = deleteUser("9999", 0); @SuppressWarnings("unchecked") Map<String, String> error = response.getBody(); // System.err.println(error); assertEquals("scim_resource_not_found", error.get("error")); assertEquals("User 9999 does not exist", error.get("message")); } // curl -v -H "Content-Type: application/json" -H "Accept: application/json" -X DELETE // http://localhost:8080/uaa/User/joel @Test public void deleteUserWithNoEtagSucceeds() throws Exception { ScimUser deleteMe = createUser(DELETE_ME, "Delete", "Me", "deleteme@blah.com").getBody(); @SuppressWarnings("rawtypes") ResponseEntity<Map> response = client.exchange(serverRunning.getUrl(userEndpoint + "/{id}"), HttpMethod.DELETE, new HttpEntity<Void>((Void) null), Map.class, deleteMe.getId()); assertEquals(HttpStatus.OK, response.getStatusCode()); } @Test public void getReturnsNotFoundForNonExistentUser() throws Exception { @SuppressWarnings("rawtypes") ResponseEntity<Map> response = client.exchange(serverRunning.getUrl(userEndpoint + "/{id}"), HttpMethod.GET, new HttpEntity<Void>((Void) null), Map.class, "9999"); @SuppressWarnings("unchecked") Map<String, String> error = response.getBody(); assertEquals(HttpStatus.NOT_FOUND, response.getStatusCode()); assertEquals("scim_resource_not_found", error.get("error")); assertEquals("User 9999 does not exist", error.get("message")); } @Test public void findUsers() throws Exception { @SuppressWarnings("rawtypes") ResponseEntity<Map> response = serverRunning.getForObject(usersEndpoint, Map.class); @SuppressWarnings("rawtypes") Map results = response.getBody(); assertEquals(HttpStatus.OK, response.getStatusCode()); assertTrue("There should be more than zero users", (Integer) results.get("totalResults") > 0); int size = ((Collection<?>) results.get("resources")).size(); assertTrue("There should be some resources", size > 0); int lastUserIndex = size - 1; // Using last user here instead of first so that tests pass even with a dirty db @SuppressWarnings("rawtypes") Map lastUser = (Map) ((List) results.get("resources")).get(lastUserIndex); // [cfid-111] All attributes should be returned if no attributes supplied in query // for (Object name: lastUser.keySet()){ // System.out.println("User found: "); // String key = name.toString(); // String value = lastUser.get(name).toString(); // System.out.println(key + " " + value); // } assertTrue(lastUser.containsKey("id")); assertTrue(lastUser.containsKey("userName")); assertTrue(lastUser.containsKey("name")); assertTrue(lastUser.containsKey("emails")); assertTrue(lastUser.containsKey("groups")); } @Test @SuppressWarnings({ "rawtypes", "unchecked" }) public void findUsersWithAttributes() throws Exception { ResponseEntity<Map> response = serverRunning.getForObject(usersEndpoint + "?attributes=id,userName", Map.class); Map<String, Object> results = response.getBody(); assertEquals(HttpStatus.OK, response.getStatusCode()); assertTrue("There should be more than zero users", (Integer) results.get("totalResults") > 0); Map firstUser = (Map) ((List) results.get("resources")).get(0); // All attributes should be returned if no attributes supplied in query assertTrue(firstUser.containsKey("id")); assertTrue(firstUser.containsKey("userName")); assertFalse(firstUser.containsKey("name")); assertFalse(firstUser.containsKey("emails")); } @Test public void findUsersWithSortBy() throws Exception { @SuppressWarnings("rawtypes") ResponseEntity<Map> response = serverRunning.getForObject(usersEndpoint + "?sortBy=emails.value", Map.class); @SuppressWarnings("unchecked") Map<String, Object> results = response.getBody(); assertEquals(HttpStatus.OK, response.getStatusCode()); assertTrue("There should be more than zero users", (Integer) results.get("totalResults") > 0); } @Test public void findUsersWithPagination() throws Exception { @SuppressWarnings("rawtypes") ResponseEntity<Map> response = serverRunning.getForObject(usersEndpoint + "?startIndex=2&count=3", Map.class); @SuppressWarnings("unchecked") Map<String, Object> results = response.getBody(); System.err.println(results); assertEquals(HttpStatus.OK, response.getStatusCode()); assertTrue("There should be more than zero users", (Integer) results.get("totalResults") > 0); assertEquals(new Integer(2), results.get("startIndex")); } @Test public void findUsersWithExtremePagination() throws Exception { @SuppressWarnings("rawtypes") ResponseEntity<Map> response = serverRunning.getForObject(usersEndpoint + "?startIndex=0&count=3000", Map.class); @SuppressWarnings("unchecked") Map<String, Object> results = response.getBody(); System.err.println(results); assertEquals(HttpStatus.OK, response.getStatusCode()); assertTrue("There should be more than zero users", (Integer) results.get("totalResults") > 0); assertEquals(new Integer(1), results.get("startIndex")); } }