diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/db/StoreSubDomainAsLowerCase_V2_7_3.java b/common/src/main/java/org/cloudfoundry/identity/uaa/db/StoreSubDomainAsLowerCase_V2_7_3.java new file mode 100644 index 0000000000..0506ec0c96 --- /dev/null +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/db/StoreSubDomainAsLowerCase_V2_7_3.java @@ -0,0 +1,94 @@ +/* + * ***************************************************************************** + * Cloud Foundry + * Copyright (c) [2009-2015] Pivotal Software, 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.db; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.cloudfoundry.identity.uaa.zone.IdentityZone; +import org.cloudfoundry.identity.uaa.zone.IdentityZoneProvisioning; +import org.cloudfoundry.identity.uaa.zone.JdbcIdentityZoneProvisioning; +import org.flywaydb.core.api.migration.spring.SpringJdbcMigration; +import org.flywaydb.core.internal.util.StringUtils; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class StoreSubDomainAsLowerCase_V2_7_3 implements SpringJdbcMigration { + + Log logger = LogFactory.getLog(StoreSubDomainAsLowerCase_V2_7_3.class); + + @Override + public synchronized void migrate(JdbcTemplate jdbcTemplate) throws Exception { + RandomValueStringGenerator generator = new RandomValueStringGenerator(3); + IdentityZoneProvisioning provisioning = new JdbcIdentityZoneProvisioning(jdbcTemplate); + Map> zones = new HashMap<>(); + Set duplicates = new HashSet<>(); + for (IdentityZone zone : provisioning.retrieveAll()) { + addToMap(zone, zones, duplicates); + } + for (String s : duplicates) { + logger.debug("Processing zone duplicates for subdomain:" + s); + List dupZones = zones.get(s); + for (int i=1; dupZones.size()>1 && i> zones, Set duplicates) { + if (zone==null || zone.getSubdomain()==null) { + return; + } + String subdomain = zone.getSubdomain().toLowerCase(); + if (zones.get(subdomain)==null) { + List list = new LinkedList<>(); + list.add(zone); + zones.put(subdomain, list); + } else { + logger.warn("Found duplicate zone for subdomain:"+subdomain); + duplicates.add(subdomain); + zones.get(subdomain).add(zone); + } + } + + +} diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/db/hsqldb/V2_7_3__Migrate_Zone_Subdomain_To_Lowercase.java b/common/src/main/java/org/cloudfoundry/identity/uaa/db/hsqldb/V2_7_3__Migrate_Zone_Subdomain_To_Lowercase.java new file mode 100644 index 0000000000..243c0fabdb --- /dev/null +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/db/hsqldb/V2_7_3__Migrate_Zone_Subdomain_To_Lowercase.java @@ -0,0 +1,21 @@ +/* + * ****************************************************************************** + * * Cloud Foundry + * * Copyright (c) [2009-2015] Pivotal Software, 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.db.hsqldb; + +import org.cloudfoundry.identity.uaa.db.StoreSubDomainAsLowerCase_V2_7_3; + +public class V2_7_3__Migrate_Zone_Subdomain_To_Lowercase extends StoreSubDomainAsLowerCase_V2_7_3 { +} diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/db/mysql/V2_7_3__Migrate_Zone_Subdomain_To_Lowercase.java b/common/src/main/java/org/cloudfoundry/identity/uaa/db/mysql/V2_7_3__Migrate_Zone_Subdomain_To_Lowercase.java new file mode 100644 index 0000000000..2f2e5c0f7d --- /dev/null +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/db/mysql/V2_7_3__Migrate_Zone_Subdomain_To_Lowercase.java @@ -0,0 +1,21 @@ +/* + * ****************************************************************************** + * * Cloud Foundry + * * Copyright (c) [2009-2015] Pivotal Software, 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.db.mysql; + +import org.cloudfoundry.identity.uaa.db.StoreSubDomainAsLowerCase_V2_7_3; + +public class V2_7_3__Migrate_Zone_Subdomain_To_Lowercase extends StoreSubDomainAsLowerCase_V2_7_3 { +} diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/db/postgresql/V2_7_3__Migrate_Zone_Subdomain_To_Lowercase.java b/common/src/main/java/org/cloudfoundry/identity/uaa/db/postgresql/V2_7_3__Migrate_Zone_Subdomain_To_Lowercase.java new file mode 100644 index 0000000000..ea9c08bdd3 --- /dev/null +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/db/postgresql/V2_7_3__Migrate_Zone_Subdomain_To_Lowercase.java @@ -0,0 +1,21 @@ +/* + * ****************************************************************************** + * * Cloud Foundry + * * Copyright (c) [2009-2015] Pivotal Software, 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.db.postgresql; + +import org.cloudfoundry.identity.uaa.db.StoreSubDomainAsLowerCase_V2_7_3; + +public class V2_7_3__Migrate_Zone_Subdomain_To_Lowercase extends StoreSubDomainAsLowerCase_V2_7_3 { +} diff --git a/common/src/main/java/org/cloudfoundry/identity/uaa/zone/JdbcIdentityZoneProvisioning.java b/common/src/main/java/org/cloudfoundry/identity/uaa/zone/JdbcIdentityZoneProvisioning.java index 115e6e33b7..42784f6665 100644 --- a/common/src/main/java/org/cloudfoundry/identity/uaa/zone/JdbcIdentityZoneProvisioning.java +++ b/common/src/main/java/org/cloudfoundry/identity/uaa/zone/JdbcIdentityZoneProvisioning.java @@ -35,11 +35,11 @@ public class JdbcIdentityZoneProvisioning implements IdentityZoneProvisioning { public static final String CREATE_IDENTITY_ZONE_SQL = "insert into identity_zone(" + ID_ZONE_FIELDS + ") values (?,?,?,?,?,?,?)"; public static final String UPDATE_IDENTITY_ZONE_SQL = "update identity_zone set " + ID_ZONE_UPDATE_FIELDS + " where id=?"; - + public static final String IDENTITY_ZONES_QUERY = "select " + ID_ZONE_FIELDS + " from identity_zone "; public static final String IDENTITY_ZONE_BY_ID_QUERY = IDENTITY_ZONES_QUERY + "where id=?"; - + public static final String IDENTITY_ZONE_BY_SUBDOMAIN_QUERY = "select " + ID_ZONE_FIELDS + " from identity_zone " + "where subdomain=?"; protected final JdbcTemplate jdbcTemplate; @@ -60,7 +60,7 @@ public IdentityZone retrieve(String id) { throw new ZoneDoesNotExistsException("Zone["+id+"] not found.", x); } } - + @Override public List retrieveAll() { return jdbcTemplate.query(IDENTITY_ZONES_QUERY, mapper); @@ -68,7 +68,10 @@ public List retrieveAll() { @Override public IdentityZone retrieveBySubdomain(String subdomain) { - IdentityZone identityZone = jdbcTemplate.queryForObject(IDENTITY_ZONE_BY_SUBDOMAIN_QUERY, mapper, subdomain); + if (subdomain==null) { + throw new EmptyResultDataAccessException("Subdomain cannot be null", 1); + } + IdentityZone identityZone = jdbcTemplate.queryForObject(IDENTITY_ZONE_BY_SUBDOMAIN_QUERY, mapper, subdomain.toLowerCase()); return identityZone; } @@ -84,7 +87,7 @@ public void setValues(PreparedStatement ps) throws SQLException { ps.setTimestamp(3, new Timestamp(new Date().getTime())); ps.setTimestamp(4, new Timestamp(new Date().getTime())); ps.setString(5, identityZone.getName()); - ps.setString(6, identityZone.getSubdomain()); + ps.setString(6, identityZone.getSubdomain().toLowerCase()); ps.setString(7, identityZone.getDescription()); } }); @@ -105,7 +108,7 @@ public void setValues(PreparedStatement ps) throws SQLException { ps.setInt(1, identityZone.getVersion() + 1); ps.setTimestamp(2, new Timestamp(new Date().getTime())); ps.setString(3, identityZone.getName()); - ps.setString(4, identityZone.getSubdomain()); + ps.setString(4, identityZone.getSubdomain().toLowerCase()); ps.setString(5, identityZone.getDescription()); ps.setString(6, identityZone.getId().trim()); } @@ -117,7 +120,7 @@ public void setValues(PreparedStatement ps) throws SQLException { return retrieve(identityZone.getId()); } - private static final class IdentityZoneRowMapper implements RowMapper { + public static final class IdentityZoneRowMapper implements RowMapper { @Override public IdentityZone mapRow(ResultSet rs, int rowNum) throws SQLException { diff --git a/common/src/test/java/org/cloudfoundry/identity/uaa/db/StoreSubDomainAsLowerCase_V2_7_3_Tests.java b/common/src/test/java/org/cloudfoundry/identity/uaa/db/StoreSubDomainAsLowerCase_V2_7_3_Tests.java new file mode 100644 index 0000000000..145ff53d27 --- /dev/null +++ b/common/src/test/java/org/cloudfoundry/identity/uaa/db/StoreSubDomainAsLowerCase_V2_7_3_Tests.java @@ -0,0 +1,147 @@ +/* + * ***************************************************************************** + * Cloud Foundry + * Copyright (c) [2009-2015] Pivotal Software, 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.db; + +import org.cloudfoundry.identity.uaa.test.JdbcTestBase; +import org.cloudfoundry.identity.uaa.zone.IdentityZone; +import org.cloudfoundry.identity.uaa.zone.IdentityZoneProvisioning; +import org.cloudfoundry.identity.uaa.zone.JdbcIdentityZoneProvisioning; +import org.cloudfoundry.identity.uaa.zone.MultitenancyFixture; +import org.junit.Before; +import org.junit.Test; +import org.springframework.dao.DuplicateKeyException; +import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; + +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assume.assumeTrue; + +public class StoreSubDomainAsLowerCase_V2_7_3_Tests extends JdbcTestBase { + + private IdentityZoneProvisioning provisioning; + private StoreSubDomainAsLowerCase_V2_7_3 migration; + private RandomValueStringGenerator generator; + + @Before + public void setUpDuplicateZones() { + provisioning = new JdbcIdentityZoneProvisioning(jdbcTemplate); + migration = new StoreSubDomainAsLowerCase_V2_7_3(); + generator = new RandomValueStringGenerator(6); + } + + @Test + public void ensure_that_subdomains_get_lower_cased() throws Exception { + List subdomains = Arrays.asList( + "Zone1" + generator.generate(), + "Zone2" + generator.generate(), + "Zone3" + generator.generate(), + "Zone4+generator.generate()" + ); + + for (String subdomain : subdomains) { + IdentityZone zone = MultitenancyFixture.identityZone(subdomain, subdomain); + IdentityZone created = provisioning.create(zone); + assertEquals(subdomain.toLowerCase(), created.getSubdomain()); + jdbcTemplate.update("UPDATE identity_zone SET subdomain = ? WHERE id = ?", subdomain, subdomain); + assertEquals(subdomain, jdbcTemplate.queryForObject("SELECT subdomain FROM identity_zone where id = ?", String.class, subdomain)); + } + + migration.migrate(jdbcTemplate); + for (String subdomain : subdomains) { + for (IdentityZone zone : + Arrays.asList( + provisioning.retrieve(subdomain), + provisioning.retrieveBySubdomain(subdomain.toLowerCase()), + provisioning.retrieveBySubdomain(subdomain) + ) + ) { + assertNotNull(zone); + assertEquals(subdomain, zone.getId()); + assertEquals(subdomain.toLowerCase(), zone.getSubdomain()); + } + } + } + + @Test + public void test_duplicate_subdomains() throws Exception { + check_db_is_case_sensitive(); + List ids = Arrays.asList( + "id1"+generator.generate().toLowerCase(), + "id2"+generator.generate().toLowerCase(), + "id3"+generator.generate().toLowerCase(), + "id4"+generator.generate().toLowerCase(), + "id5"+generator.generate().toLowerCase() + ); + List subdomains = Arrays.asList( + "domain1", + "Domain1", + "doMain1", + "domain4"+generator.generate().toLowerCase(), + "domain5"+generator.generate().toLowerCase() + ); + for (int i=0; i { + ps.setString(1, identityZone.getId().trim()); + ps.setInt(2, identityZone.getVersion()); + ps.setTimestamp(3, new Timestamp(new Date().getTime())); + ps.setTimestamp(4, new Timestamp(new Date().getTime())); + ps.setString(5, identityZone.getName()); + ps.setString(6, identityZone.getSubdomain()); + ps.setString(7, identityZone.getDescription()); + }); + } +} \ No newline at end of file diff --git a/common/src/test/java/org/cloudfoundry/identity/uaa/zone/IdentityZoneResolvingFilterTest.java b/common/src/test/java/org/cloudfoundry/identity/uaa/zone/IdentityZoneResolvingFilterTest.java index e18381d17b..5b3b010d08 100644 --- a/common/src/test/java/org/cloudfoundry/identity/uaa/zone/IdentityZoneResolvingFilterTest.java +++ b/common/src/test/java/org/cloudfoundry/identity/uaa/zone/IdentityZoneResolvingFilterTest.java @@ -1,31 +1,35 @@ package org.cloudfoundry.identity.uaa.zone; -import static org.junit.Assert.*; -import static org.mockito.Matchers.anyString; -import static org.mockito.Mockito.when; - -import java.io.IOException; -import java.sql.SQLNonTransientConnectionException; -import java.util.Arrays; -import java.util.HashSet; +import org.cloudfoundry.identity.uaa.test.JdbcTestBase; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.springframework.mock.web.MockFilterChain; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.mock.web.MockHttpServletResponse; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; -import org.junit.Test; -import org.mockito.Mockito; -import org.springframework.dao.EmptyResultDataAccessException; -import org.springframework.jdbc.CannotGetJdbcConnectionException; -import org.springframework.mock.web.MockFilterChain; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpServletResponse; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; -public class IdentityZoneResolvingFilterTest { +public class IdentityZoneResolvingFilterTest extends JdbcTestBase { private boolean wasFilterExecuted = false; + private IdentityZoneProvisioning dao; + + @Before + public void createDao() { + dao = new JdbcIdentityZoneProvisioning(jdbcTemplate); + } @Test public void holderIsSetWithDefaultIdentityZone() { @@ -51,9 +55,6 @@ public void holderIsSetWithUAAIdentityZone() throws Exception { @Test public void doNotThrowException_InCase_RetrievingZoneFails() throws Exception { - IdentityZoneProvisioning dao = Mockito.mock(IdentityZoneProvisioning.class); - when(dao.retrieveBySubdomain(anyString())).thenThrow(new CannotGetJdbcConnectionException("blah", new SQLNonTransientConnectionException())); - MockHttpServletRequest request = new MockHttpServletRequest(); String incomingSubdomain = "not_a_zone"; String uaaHostname = "uaa.mycf.com"; @@ -67,21 +68,25 @@ public void doNotThrowException_InCase_RetrievingZoneFails() throws Exception { filter.setAdditionalInternalHostnames(new HashSet<>(Arrays.asList(uaaHostname))); filter.doFilter(request, response, chain); - assertEquals(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, response.getStatus()); + assertEquals(HttpServletResponse.SC_NOT_FOUND, response.getStatus()); assertEquals(IdentityZone.getUaa(), IdentityZoneHolder.get()); Mockito.verifyZeroInteractions(chain); } - private void assertFindsCorrectSubdomain(final String expectedSubdomain, final String incomingHostname, String... additionalInternalHostnames) throws ServletException, IOException { - + private void assertFindsCorrectSubdomain(final String subDomainInput, final String incomingHostname, String... additionalInternalHostnames) throws ServletException, IOException { + final String expectedSubdomain = subDomainInput.toLowerCase(); IdentityZoneResolvingFilter filter = new IdentityZoneResolvingFilter(); - IdentityZoneProvisioning dao = Mockito.mock(IdentityZoneProvisioning.class); filter.setIdentityZoneProvisioning(dao); filter.setAdditionalInternalHostnames(new HashSet<>(Arrays.asList(additionalInternalHostnames))); - IdentityZone identityZone = new IdentityZone(); - identityZone.setSubdomain(expectedSubdomain); - when(dao.retrieveBySubdomain(Mockito.eq(expectedSubdomain))).thenReturn(identityZone); + IdentityZone identityZone = MultitenancyFixture.identityZone(subDomainInput, subDomainInput); + identityZone.setSubdomain(subDomainInput); + try { + identityZone = dao.create(identityZone); + } catch (ZoneAlreadyExistsException x) { + identityZone = dao.retrieveBySubdomain(subDomainInput); + } + assertEquals(expectedSubdomain, identityZone.getSubdomain()); MockHttpServletRequest request = new MockHttpServletRequest(); request.setServerName(incomingHostname); @@ -97,7 +102,6 @@ public void doFilter(ServletRequest request, ServletResponse response) throws IO filter.doFilter(request, response, filterChain); assertTrue(wasFilterExecuted); - Mockito.verify(dao).retrieveBySubdomain(Mockito.eq(expectedSubdomain)); assertEquals(IdentityZone.getUaa(), IdentityZoneHolder.get()); } @@ -108,14 +112,13 @@ public void holderIsNotSetWithNonMatchingIdentityZone() throws Exception { String incomingHostname = incomingSubdomain+"."+uaaHostname; IdentityZoneResolvingFilter filter = new IdentityZoneResolvingFilter(); - IdentityZoneProvisioning dao = Mockito.mock(IdentityZoneProvisioning.class); + FilterChain chain = Mockito.mock(FilterChain.class); filter.setIdentityZoneProvisioning(dao); filter.setAdditionalInternalHostnames(new HashSet<>(Arrays.asList(uaaHostname))); IdentityZone identityZone = new IdentityZone(); identityZone.setSubdomain(incomingSubdomain); - when(dao.retrieveBySubdomain(Mockito.eq(incomingSubdomain))).thenThrow(new EmptyResultDataAccessException(1)); MockHttpServletRequest request = new MockHttpServletRequest(); request.setServerName(incomingHostname); diff --git a/common/src/test/java/org/cloudfoundry/identity/uaa/zone/JdbcIdentityZoneProvisioningTests.java b/common/src/test/java/org/cloudfoundry/identity/uaa/zone/JdbcIdentityZoneProvisioningTests.java index 6007b1ecaf..36d3c8ede1 100644 --- a/common/src/test/java/org/cloudfoundry/identity/uaa/zone/JdbcIdentityZoneProvisioningTests.java +++ b/common/src/test/java/org/cloudfoundry/identity/uaa/zone/JdbcIdentityZoneProvisioningTests.java @@ -1,18 +1,18 @@ package org.cloudfoundry.identity.uaa.zone; -import java.util.UUID; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.fail; import org.cloudfoundry.identity.uaa.test.JdbcTestBase; import org.junit.Before; import org.junit.Test; +import org.springframework.dao.EmptyResultDataAccessException; import org.springframework.security.oauth2.common.util.RandomValueStringGenerator; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + public class JdbcIdentityZoneProvisioningTests extends JdbcTestBase { private JdbcIdentityZoneProvisioning db; - + private RandomValueStringGenerator generator = new RandomValueStringGenerator(8); @Before public void createDatasource() throws Exception { db = new JdbcIdentityZoneProvisioning(jdbcTemplate); @@ -20,8 +20,8 @@ public void createDatasource() throws Exception { @Test public void testCreateIdentityZone() throws Exception { - IdentityZone identityZone = MultitenancyFixture.identityZone(UUID.randomUUID().toString(),UUID.randomUUID().toString()); - identityZone.setId(UUID.randomUUID().toString()); + IdentityZone identityZone = MultitenancyFixture.identityZone(generator.generate(),generator.generate()); + identityZone.setId(generator.generate()); IdentityZone createdIdZone = db.create(identityZone); @@ -31,10 +31,30 @@ public void testCreateIdentityZone() throws Exception { assertEquals(identityZone.getDescription(), createdIdZone.getDescription()); } + @Test + public void testCreateIdentityZone_Subdomain_Becomes_LowerCase() throws Exception { + String subdomain = generator.generate().toUpperCase(); + IdentityZone identityZone = MultitenancyFixture.identityZone(generator.generate(),subdomain); + identityZone.setId(generator.generate()); + + identityZone.setSubdomain(subdomain); + IdentityZone createdIdZone = db.create(identityZone); + + assertEquals(identityZone.getId(), createdIdZone.getId()); + assertEquals(subdomain.toLowerCase(), createdIdZone.getSubdomain()); + assertEquals(identityZone.getName(), createdIdZone.getName()); + assertEquals(identityZone.getDescription(), createdIdZone.getDescription()); + } + + @Test(expected = EmptyResultDataAccessException.class) + public void test_null_subdomain() { + db.retrieveBySubdomain(null); + } + @Test public void testUpdateIdentityZone() throws Exception { - IdentityZone identityZone = MultitenancyFixture.identityZone(UUID.randomUUID().toString(),UUID.randomUUID().toString()); - identityZone.setId(UUID.randomUUID().toString()); + IdentityZone identityZone = MultitenancyFixture.identityZone(generator.generate(), generator.generate()); + identityZone.setId(generator.generate()); IdentityZone createdIdZone = db.create(identityZone); @@ -50,22 +70,46 @@ public void testUpdateIdentityZone() throws Exception { IdentityZone updatedIdZone = db.update(createdIdZone); assertEquals(createdIdZone.getId(), updatedIdZone.getId()); - assertEquals(createdIdZone.getSubdomain(), updatedIdZone.getSubdomain()); + assertEquals(createdIdZone.getSubdomain().toLowerCase(), updatedIdZone.getSubdomain()); + assertEquals(createdIdZone.getName(), updatedIdZone.getName()); + assertEquals(createdIdZone.getDescription(), updatedIdZone.getDescription()); + } + + @Test + public void testUpdateIdentityZone_SubDomain_Is_LowerCase() throws Exception { + IdentityZone identityZone = MultitenancyFixture.identityZone(generator.generate(),generator.generate()); + identityZone.setId(generator.generate()); + + IdentityZone createdIdZone = db.create(identityZone); + + assertEquals(identityZone.getId(), createdIdZone.getId()); + assertEquals(identityZone.getSubdomain(), createdIdZone.getSubdomain()); + assertEquals(identityZone.getName(), createdIdZone.getName()); + assertEquals(identityZone.getDescription(), createdIdZone.getDescription()); + + String newDomain = new RandomValueStringGenerator().generate(); + createdIdZone.setSubdomain(newDomain.toUpperCase()); + createdIdZone.setDescription("new desc"); + createdIdZone.setName("new name"); + IdentityZone updatedIdZone = db.update(createdIdZone); + + assertEquals(createdIdZone.getId(), updatedIdZone.getId()); + assertEquals(createdIdZone.getSubdomain().toLowerCase(), updatedIdZone.getSubdomain()); assertEquals(createdIdZone.getName(), updatedIdZone.getName()); assertEquals(createdIdZone.getDescription(), updatedIdZone.getDescription()); } @Test(expected = ZoneDoesNotExistsException.class) public void testUpdateNonExistentIdentityZone() throws Exception { - IdentityZone identityZone = MultitenancyFixture.identityZone(UUID.randomUUID().toString(),UUID.randomUUID().toString()); - identityZone.setId(UUID.randomUUID().toString()); + IdentityZone identityZone = MultitenancyFixture.identityZone(generator.generate(),generator.generate()); + identityZone.setId(generator.generate()); db.update(identityZone); } @Test public void testCreateDuplicateIdentityZone() throws Exception { IdentityZone identityZone = MultitenancyFixture.identityZone("there-can-be-only-one","there-can-be-only-one"); - identityZone.setId(UUID.randomUUID().toString()); + identityZone.setId(generator.generate()); db.create(identityZone); try { db.create(identityZone); @@ -78,7 +122,7 @@ public void testCreateDuplicateIdentityZone() throws Exception { @Test public void testCreateDuplicateIdentityZoneSubdomain() throws Exception { IdentityZone identityZone = MultitenancyFixture.identityZone("there-can-be-only-one","there-can-be-only-one"); - identityZone.setId(UUID.randomUUID().toString()); + identityZone.setId(generator.generate()); db.create(identityZone); try { identityZone.setId(new RandomValueStringGenerator().generate()); diff --git a/common/src/test/java/org/cloudfoundry/identity/uaa/zone/MultitenancyFixture.java b/common/src/test/java/org/cloudfoundry/identity/uaa/zone/MultitenancyFixture.java index 8f29c33e06..964611a9b0 100644 --- a/common/src/test/java/org/cloudfoundry/identity/uaa/zone/MultitenancyFixture.java +++ b/common/src/test/java/org/cloudfoundry/identity/uaa/zone/MultitenancyFixture.java @@ -6,7 +6,7 @@ public class MultitenancyFixture { public static IdentityZone identityZone(String id, String subdomain) { IdentityZone identityZone = new IdentityZone(); identityZone.setId(id); - identityZone.setSubdomain(subdomain); + identityZone.setSubdomain(subdomain.toLowerCase()); identityZone.setName("The Twiglet Zone"); identityZone.setDescription("Like the Twilight Zone but tastier."); return identityZone; diff --git a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneEndpointsMockMvcTests.java b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneEndpointsMockMvcTests.java index b3d2ad890e..6dbbde7405 100644 --- a/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneEndpointsMockMvcTests.java +++ b/uaa/src/test/java/org/cloudfoundry/identity/uaa/mock/zones/IdentityZoneEndpointsMockMvcTests.java @@ -228,7 +228,7 @@ public void testCreateZone() throws Exception { String id = generator.generate(); IdentityZone zone = createZone(id, HttpStatus.CREATED, identityClientToken); assertEquals(id, zone.getId()); - assertEquals(id, zone.getSubdomain()); + assertEquals(id.toLowerCase(), zone.getSubdomain()); checkAuditEventListener(1, AuditEventType.IdentityZoneCreatedEvent, zoneModifiedEventListener, IdentityZone.getUaa().getId(), "http://localhost:8080/uaa/oauth/token", "identity"); } @@ -513,8 +513,8 @@ public void testCreatesZonesWithDuplicateSubdomains() throws Exception { @Test public void testZoneAdminTokenAgainstZoneEndpoints() throws Exception { - String zone1 = generator.generate(); - String zone2 = generator.generate(); + String zone1 = generator.generate().toLowerCase(); + String zone2 = generator.generate().toLowerCase(); IdentityZoneCreationResult result1 = MockMvcUtils.utils().createOtherIdentityZoneAndReturnResult(zone1, getMockMvc(), getWebApplicationContext(), null); IdentityZoneCreationResult result2 = MockMvcUtils.utils().createOtherIdentityZoneAndReturnResult(zone2, getMockMvc(), getWebApplicationContext(), null); @@ -567,7 +567,7 @@ public void testZoneAdminTokenAgainstZoneEndpoints() throws Exception { @Test public void testSuccessfulUserManagementInZoneUsingAdminClient() throws Exception { - String subdomain = generator.generate(); + String subdomain = generator.generate().toLowerCase(); BaseClientDetails adminClient = new BaseClientDetails("admin", null, null, "client_credentials", "scim.read,scim.write"); adminClient.setClientSecret("admin-secret"); IdentityZoneCreationResult creationResult = mockMvcUtils.createOtherIdentityZoneAndReturnResult(subdomain, getMockMvc(), getWebApplicationContext(), adminClient); @@ -681,7 +681,7 @@ public void userCanReadAZone_withZoneZoneIdReadToken() throws Exception { String scimWriteToken = testClient.getClientCredentialsOAuthAccessToken("admin", "adminsecret", "scim.write"); ScimUser user = createUser(scimWriteToken, null); - String id = generator.generate(); + String id = generator.generate().toLowerCase(); IdentityZone identityZone = createZone(id, HttpStatus.CREATED, identityClientToken); ScimGroup group = new ScimGroup();