diff --git a/server/src/main/java/org/cloudfoundry/identity/uaa/approval/JdbcApprovalStore.java b/server/src/main/java/org/cloudfoundry/identity/uaa/approval/JdbcApprovalStore.java index b5331b54713..b3333896352 100644 --- a/server/src/main/java/org/cloudfoundry/identity/uaa/approval/JdbcApprovalStore.java +++ b/server/src/main/java/org/cloudfoundry/identity/uaa/approval/JdbcApprovalStore.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Cloud Foundry + * Cloud Foundry * Copyright (c) [2009-2016] Pivotal Software, Inc. All Rights Reserved. * * This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -12,23 +12,14 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.approval; -import static org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus.APPROVED; - -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.util.Date; -import java.util.List; -import java.util.Map; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.cloudfoundry.identity.uaa.audit.event.ApprovalModifiedEvent; import org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus; +import org.cloudfoundry.identity.uaa.audit.event.ApprovalModifiedEvent; import org.cloudfoundry.identity.uaa.resources.jdbc.JdbcPagingListFactory; import org.cloudfoundry.identity.uaa.resources.jdbc.SearchQueryConverter; import org.cloudfoundry.identity.uaa.resources.jdbc.SearchQueryConverter.ProcessedFilter; +import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; @@ -43,6 +34,17 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.util.Assert; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus.APPROVED; + public class JdbcApprovalStore implements ApprovalStore, ApplicationEventPublisherAware { private final JdbcTemplate jdbcTemplate; @@ -143,17 +145,17 @@ public boolean revokeApprovals(String filter) { logger.debug(String.format("Filtering approvals with filter: [%s]", where)); String sql; - Map sqlParams; + Map sqlParams = new HashMap<>(where.getParams()); if (handleRevocationsAsExpiry) { // just expire all approvals matching the filter sql = EXPIRE_AUTHZ_SQL + " where " + where.getSql(); - sqlParams = where.getParams(); sqlParams.put("expiry", new Timestamp(new Date().getTime() - 1)); } else { // delete the records sql = DELETE_AUTHZ_SQL + " where " + where.getSql(); - sqlParams = where.getParams(); } + sqlParams.put("__identity_zone_id", IdentityZoneHolder.get().getId()); + sql = sql + " and user_id in (select id from users where identity_zone_id = :__identity_zone_id)"; try { int revoked = new NamedParameterJdbcTemplate(jdbcTemplate).update(sql, sqlParams); @@ -185,8 +187,14 @@ public List getApprovals(String filter) { ProcessedFilter where = queryConverter.convert(filter, null, true); logger.debug(String.format("Filtering approvals with filter: [%s]", where)); try { - return pagingListFactory.createJdbcPagingList(GET_AUTHZ_SQL + " where " + - where.getSql(), where.getParams(), rowMapper, 200); + Map params = new HashMap(where.getParams()); + params.put("__identity_zone_id", IdentityZoneHolder.get().getId()); + return pagingListFactory.createJdbcPagingList( + GET_AUTHZ_SQL + " where " + where.getSql() + " and user_id in (select id from users where identity_zone_id = :__identity_zone_id)", + params, + rowMapper, + 200 + ); } catch (DataAccessException e) { logger.error("Error filtering approvals with filter: " + where, e); throw new IllegalArgumentException("Invalid filter: " + filter); diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/oauth/UserManagedAuthzApprovalHandlerTests.java b/server/src/test/java/org/cloudfoundry/identity/uaa/oauth/UserManagedAuthzApprovalHandlerTests.java index 30a72e01e43..3e5355d894d 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/oauth/UserManagedAuthzApprovalHandlerTests.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/oauth/UserManagedAuthzApprovalHandlerTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Cloud Foundry + * Cloud Foundry * Copyright (c) [2009-2016] Pivotal Software, Inc. All Rights Reserved. * * This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -12,22 +12,6 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.oauth; -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.Set; - -import static java.util.Collections.singleton; -import static org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus.APPROVED; -import static org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus.DENIED; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; - import org.cloudfoundry.identity.uaa.approval.Approval; import org.cloudfoundry.identity.uaa.approval.ApprovalStore; import org.cloudfoundry.identity.uaa.approval.JdbcApprovalStore; @@ -49,6 +33,22 @@ import org.springframework.security.oauth2.provider.ClientDetails; import org.springframework.security.oauth2.provider.client.BaseClientDetails; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; + +import static java.util.Collections.singleton; +import static org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus.APPROVED; +import static org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus.DENIED; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; + public class UserManagedAuthzApprovalHandlerTests extends JdbcTestBase { private final UserManagedAuthzApprovalHandler handler = new UserManagedAuthzApprovalHandler(); @@ -70,17 +70,18 @@ public void initUserManagedAuthzApprovalHandlerTests() { handler.setApprovalStore(approvalStore); handler.setClientDetailsService( mockClientDetailsService( - "foo", + "foo", new String[]{ "cloud_controller.read", - "cloud_controller.write", + "cloud_controller.write", "openid", "space.*.developer" - }, + }, Collections.emptySet() ) ); userId = new RandomValueStringGenerator().generate(); + testAccounts.addRandomUser(jdbcTemplate, userId); userAuthentication = new TestAuthentication(userId, testAccounts.getUserName(), true); } @@ -106,7 +107,7 @@ public void testNoScopeApproval() { @Test public void testNoPreviouslyApprovedScopes() { AuthorizationRequest request = new AuthorizationRequest( - "foo", + "foo", new HashSet<>( Arrays.asList("cloud_controller.read", "cloud_controller.write") ) @@ -121,7 +122,7 @@ public void testNoPreviouslyApprovedScopes() { @Test public void testAuthzApprovedButNoPreviouslyApprovedScopes() { AuthorizationRequest request = new AuthorizationRequest( - "foo", + "foo", new HashSet<>( Arrays.asList("cloud_controller.read", "cloud_controller.write") ) @@ -162,7 +163,7 @@ public void testNoRequestedScopesButSomeApprovedScopes() { @Test public void testRequestedScopesDontMatchApprovalsAtAll() { AuthorizationRequest request = new AuthorizationRequest( - "foo", + "foo", new HashSet<>( Arrays.asList("openid") ) @@ -193,7 +194,7 @@ public void testRequestedScopesDontMatchApprovalsAtAll() { @Test public void testOnlySomeRequestedScopeMatchesApproval() { AuthorizationRequest request = new AuthorizationRequest( - "foo", + "foo", new HashSet<>( Arrays.asList("openid", "cloud_controller.read") ) @@ -224,7 +225,7 @@ public void testOnlySomeRequestedScopeMatchesApproval() { @Test public void testOnlySomeRequestedScopeMatchesDeniedApprovalButScopeAutoApproved() { AuthorizationRequest request = new AuthorizationRequest( - "foo", + "foo", new HashSet<>( Arrays.asList("openid", "cloud_controller.read") ) @@ -236,10 +237,10 @@ public void testOnlySomeRequestedScopeMatchesDeniedApprovalButScopeAutoApproved( handler.setClientDetailsService( mockClientDetailsService( - "foo", + "foo", new String[]{ "cloud_controller.read", - "cloud_controller.write", + "cloud_controller.write", "openid" }, singleton("true") @@ -266,11 +267,11 @@ public void testOnlySomeRequestedScopeMatchesDeniedApprovalButScopeAutoApproved( @Test public void testRequestedScopesMatchApprovalButAdditionalScopesRequested() { AuthorizationRequest request = new AuthorizationRequest( - "foo", + "foo", new HashSet<>( Arrays.asList( - "openid", - "cloud_controller.read", + "openid", + "cloud_controller.read", "cloud_controller.write" ) ) @@ -301,11 +302,11 @@ public void testRequestedScopesMatchApprovalButAdditionalScopesRequested() { @Test public void testAllRequestedScopesMatchApproval() { AuthorizationRequest request = new AuthorizationRequest( - "foo", + "foo", new HashSet<>( Arrays.asList( - "openid", - "cloud_controller.read", + "openid", + "cloud_controller.read", "cloud_controller.write" ) ) @@ -342,11 +343,11 @@ public void testAllRequestedScopesMatchApproval() { @Test public void testRequestedScopesMatchApprovalButSomeDenied() { AuthorizationRequest request = new AuthorizationRequest( - "foo", + "foo", new HashSet<>( Arrays.asList( - "openid", - "cloud_controller.read", + "openid", + "cloud_controller.read", "cloud_controller.write" ) ) @@ -383,11 +384,11 @@ public void testRequestedScopesMatchApprovalButSomeDenied() { @Test public void testRequestedScopesMatchApprovalSomeDeniedButDeniedScopesAutoApproved() { AuthorizationRequest request = new AuthorizationRequest( - "foo", + "foo", new HashSet<>( Arrays.asList( - "openid", - "cloud_controller.read", + "openid", + "cloud_controller.read", "cloud_controller.write" ) ) @@ -400,7 +401,7 @@ public void testRequestedScopesMatchApprovalSomeDeniedButDeniedScopesAutoApprove "foo", new String[]{ "cloud_controller.read", - "cloud_controller.write", + "cloud_controller.write", "openid" }, singleton("cloud_controller.write"))); @@ -561,7 +562,7 @@ public void testRequestedScopesMatchByWildcard() { @Test public void testSomeRequestedScopesMatchApproval() { AuthorizationRequest request = new AuthorizationRequest( - "foo", + "foo", new HashSet<>(Arrays.asList("openid")) ); request.setApproved(false); diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/oauth/approval/ApprovalsAdminEndpointsTests.java b/server/src/test/java/org/cloudfoundry/identity/uaa/oauth/approval/ApprovalsAdminEndpointsTests.java index d63278e0a61..69377063412 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/oauth/approval/ApprovalsAdminEndpointsTests.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/oauth/approval/ApprovalsAdminEndpointsTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Cloud Foundry + * Cloud Foundry * Copyright (c) [2009-2016] Pivotal Software, Inc. All Rights Reserved. * * This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -12,50 +12,57 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.oauth.approval; -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import static org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus.APPROVED; -import static org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus.DENIED; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - import com.fasterxml.jackson.core.type.TypeReference; import org.cloudfoundry.identity.uaa.approval.Approval; +import org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus; import org.cloudfoundry.identity.uaa.approval.ApprovalsAdminEndpoints; import org.cloudfoundry.identity.uaa.approval.JdbcApprovalStore; -import org.cloudfoundry.identity.uaa.oauth.client.ClientConstants; import org.cloudfoundry.identity.uaa.error.UaaException; -import org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus; import org.cloudfoundry.identity.uaa.resources.jdbc.JdbcPagingListFactory; import org.cloudfoundry.identity.uaa.resources.jdbc.SimpleSearchQueryConverter; import org.cloudfoundry.identity.uaa.security.SecurityContextAccessor; import org.cloudfoundry.identity.uaa.test.JdbcTestBase; import org.cloudfoundry.identity.uaa.test.TestUtils; import org.cloudfoundry.identity.uaa.test.UaaTestAccounts; -import org.cloudfoundry.identity.uaa.user.MockUaaUserDatabase; +import org.cloudfoundry.identity.uaa.user.JdbcUaaUserDatabase; import org.cloudfoundry.identity.uaa.user.UaaUser; import org.cloudfoundry.identity.uaa.user.UaaUserDatabase; import org.cloudfoundry.identity.uaa.util.JsonUtils; +import org.cloudfoundry.identity.uaa.util.TimeServiceImpl; +import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; import org.junit.After; import org.junit.Before; import org.junit.Test; +import org.springframework.jdbc.core.BatchPreparedStatementSetter; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.security.oauth2.provider.client.InMemoryClientDetailsService; +import java.lang.reflect.Method; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus.APPROVED; +import static org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus.DENIED; +import static org.cloudfoundry.identity.uaa.test.UaaTestAccounts.INSERT_BARE_BONE_USER; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + public class ApprovalsAdminEndpointsTests extends JdbcTestBase { private UaaTestAccounts testAccounts = null; - + private JdbcApprovalStore dao; private UaaUserDatabase userDao = null; @@ -67,8 +74,10 @@ public class ApprovalsAdminEndpointsTests extends JdbcTestBase { @Before public void initApprovalsAdminEndpointsTests() { testAccounts = UaaTestAccounts.standard(null); - String userId = testAccounts.getUserWithRandomID().getId(); - userDao = new MockUaaUserDatabase(u -> u.withId(userId).withUsername(testAccounts.getUserName()).withEmail("marissa@test.com").withGivenName("Marissa").withFamilyName("Bloggs")); + String userId = testAccounts.addRandomUser(jdbcTemplate); + + userDao = new JdbcUaaUserDatabase(jdbcTemplate, new TimeServiceImpl()); + jdbcTemplate = new JdbcTemplate(dataSource); marissa = userDao.retrieveUserById(userId); assertNotNull(marissa); @@ -89,6 +98,8 @@ public void initApprovalsAdminEndpointsTests() { endpoints.setSecurityContextAccessor(mockSecurityContextAccessor(marissa.getUsername(), marissa.getId())); } + + private void addApproval(String userName, String clientId, String scope, int expiresIn, ApprovalStatus status) { dao.addApproval(new Approval() .setUserId(userName) @@ -320,4 +331,66 @@ public void canRevokeApprovals() { assertEquals("ok", endpoints.revokeApprovals("c1").getStatus()); assertEquals(0, endpoints.getApprovals("user_id pr", 1, 100).size()); } + + @Test + public void performance_is_acceptable() throws Exception { + doWithTiming("addUsers", 10000); + } + + + public double doWithTiming(String methodName, Object... args) throws Exception { + Method method = this.getClass().getMethod(methodName, Arrays.stream(args).map(a -> a.getClass()).collect(Collectors.toList()).toArray(new Class[0])); + double start = System.currentTimeMillis(); + method.invoke(this, args); + double stop = System.currentTimeMillis(); + double timing = (stop - start) / 1000d; + System.err.println(String.format("\nPerformed %s(%s) in %.4f seconds", methodName, Arrays.toString(args), timing)); + return timing; + } + + + + public void addUsers(final Integer size) throws Exception { + jdbcTemplate.batchUpdate(INSERT_BARE_BONE_USER, new BatchPreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps, int i) throws SQLException { + String userId = "user-"+i; + int pos = 1; + ps.setString(pos++, userId); + ps.setString(pos++, userId); + ps.setString(pos++, userId); + ps.setString(pos++, userId + "@test.com"); + ps.setString(pos++, IdentityZoneHolder.get().getId()); + } + + @Override + public int getBatchSize() { + return size; + } + }); + } + + + public void addApprovals(final int minUserId, final int maxUserId, final int countPerUser) throws Exception { + jdbcTemplate.batchUpdate("insert into authz_approval (user_id, client_id, scope) values (?,?,?)", new BatchPreparedStatementSetter() { + @Override + public void setValues(PreparedStatement ps, int i) throws SQLException { + int index = i / countPerUser; + String userId = "user-"+(i+index); + int pos = 1; + ps.setString(pos++, userId); + ps.setString(pos++, userId); + ps.setString(pos++, userId); + ps.setString(pos++, userId); + ps.setString(pos++, userId + "@test.com"); + ps.setString(pos++, IdentityZoneHolder.get().getId()); + } + + @Override + public int getBatchSize() { + return (maxUserId - minUserId) * countPerUser; + } + }); + } + } diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/oauth/approval/JdbcApprovalStoreTests.java b/server/src/test/java/org/cloudfoundry/identity/uaa/oauth/approval/JdbcApprovalStoreTests.java index 223cad660fc..e36a043a403 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/oauth/approval/JdbcApprovalStoreTests.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/oauth/approval/JdbcApprovalStoreTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Cloud Foundry + * Cloud Foundry * Copyright (c) [2009-2016] Pivotal Software, Inc. All Rights Reserved. * * This product is licensed to you under the Apache License, Version 2.0 (the "License"). @@ -12,22 +12,10 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.oauth.approval; -import java.sql.Timestamp; -import java.util.Date; -import java.util.List; - -import static org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus.APPROVED; -import static org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus.DENIED; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.Is.is; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - import org.cloudfoundry.identity.uaa.approval.Approval; +import org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus; import org.cloudfoundry.identity.uaa.approval.JdbcApprovalStore; import org.cloudfoundry.identity.uaa.audit.event.ApprovalModifiedEvent; -import org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus; import org.cloudfoundry.identity.uaa.resources.jdbc.JdbcPagingListFactory; import org.cloudfoundry.identity.uaa.resources.jdbc.SimpleSearchQueryConverter; import org.cloudfoundry.identity.uaa.test.JdbcTestBase; @@ -35,20 +23,47 @@ import org.cloudfoundry.identity.uaa.test.TestApplicationEventPublisher; import org.cloudfoundry.identity.uaa.test.TestUtils; import org.cloudfoundry.identity.uaa.test.UaaTestAccounts; +import org.cloudfoundry.identity.uaa.zone.IdentityZone; +import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; +import org.cloudfoundry.identity.uaa.zone.MultitenancyFixture; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.springframework.security.core.context.SecurityContextHolder; + +import java.sql.Timestamp; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import static org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus.APPROVED; +import static org.cloudfoundry.identity.uaa.approval.Approval.ApprovalStatus.DENIED; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; @Ignore //we're having issues with these tests right now public class JdbcApprovalStoreTests extends JdbcTestBase { + + private JdbcApprovalStore dao; private TestApplicationEventPublisher eventPublisher; + private IdentityZone otherZone; + + private UaaTestAccounts testAccounts = UaaTestAccounts.standard(null); + @Before public void initJdbcApprovalStoreTests() { + IdentityZoneHolder.clear(); + otherZone = MultitenancyFixture.identityZone("other-zone", "other-domain"); + for (String userId : Arrays.asList("u1", "u2", "u3")) { + testAccounts.addRandomUser(jdbcTemplate, userId); + } dao = new JdbcApprovalStore(jdbcTemplate, new JdbcPagingListFactory(jdbcTemplate, limitSqlAdapter), new SimpleSearchQueryConverter()); @@ -61,11 +76,11 @@ public void initJdbcApprovalStoreTests() { addApproval("u2", "c1", "openid", 6000, APPROVED); } - private void addApproval(String userName, String clientId, String scope, long expiresIn, ApprovalStatus status) { + private void addApproval(String userId, String clientId, String scope, long expiresIn, ApprovalStatus status) { Date expiresAt = new Timestamp(new Date().getTime() + expiresIn); Date lastUpdatedAt = new Date(); Approval newApproval = new Approval() - .setUserId(userName) + .setUserId(userId) .setClientId(clientId) .setScope(scope) .setExpiresAt(expiresAt) @@ -78,30 +93,32 @@ private void addApproval(String userName, String clientId, String scope, long ex public void cleanupDataSource() throws Exception { TestUtils.deleteFrom(dataSource, "authz_approvals"); assertThat(jdbcTemplate.queryForObject("select count(*) from authz_approvals", Integer.class), is(0)); + IdentityZoneHolder.clear(); } @Test public void testAddAndGetApproval() { - String userName = "user"; + String userId = "user"; String clientId = "client"; String scope = "uaa.user"; long expiresIn = 1000l; Date lastUpdatedAt = new Date(); ApprovalStatus status = APPROVED; + testAccounts.addRandomUser(jdbcTemplate, userId); Date expiresAt = new Timestamp(new Date().getTime() + expiresIn); Approval newApproval = new Approval() - .setUserId(userName) + .setUserId(userId) .setClientId(clientId) .setScope(scope) .setExpiresAt(expiresAt) .setStatus(status) .setLastUpdatedAt(lastUpdatedAt); dao.addApproval(newApproval); - List approvals = dao.getApprovals(userName, clientId); + List approvals = dao.getApprovals(userId, clientId); assertEquals(clientId, approvals.get(0).getClientId()); - assertEquals(userName, approvals.get(0).getUserId()); + assertEquals(userId, approvals.get(0).getUserId()); assertEquals(Math.round(expiresAt.getTime() / 1000), Math.round(approvals.get(0).getExpiresAt().getTime() / 1000)); assertEquals(Math.round(lastUpdatedAt.getTime() / 1000), Math.round(approvals.get(0).getLastUpdatedAt().getTime() / 1000)); @@ -133,6 +150,17 @@ public void canAddApproval() { assertEquals(APPROVED, app.getStatus()); } + @Test + public void approvals_is_zone_aware() throws Exception { + String filter = "client_id eq \"c1\" or client_id eq \"c2\" or client_id eq \"c3\""; + assertEquals(3, dao.getApprovals(filter).size()); + IdentityZoneHolder.set(otherZone); + assertEquals(0, dao.getApprovals(filter).size()); + dao.revokeApprovals(filter); + IdentityZoneHolder.clear(); + assertEquals(3, dao.getApprovals(filter).size()); + } + @Test public void canRevokeApprovals() { assertEquals(2, dao.getApprovals("user_id eq \"u1\"").size()); diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/test/UaaTestAccounts.java b/server/src/test/java/org/cloudfoundry/identity/uaa/test/UaaTestAccounts.java index 74950df4f21..fc835fc3eff 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/test/UaaTestAccounts.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/test/UaaTestAccounts.java @@ -12,12 +12,6 @@ *******************************************************************************/ package org.cloudfoundry.identity.uaa.test; -import java.util.Arrays; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.cloudfoundry.identity.uaa.constants.OriginKeys; @@ -25,6 +19,7 @@ import org.cloudfoundry.identity.uaa.user.UaaUser; import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; import org.springframework.core.env.Environment; +import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.security.crypto.codec.Base64; import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; import org.springframework.security.oauth2.client.test.TestAccounts; @@ -33,11 +28,17 @@ import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails; import org.springframework.security.oauth2.common.AuthenticationScheme; -import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.security.oauth2.provider.ClientDetails; +import org.springframework.security.oauth2.provider.client.BaseClientDetails; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.util.StringUtils; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + /** * UAA specific test account data externalized with * {@link TestProfileEnvironment}. @@ -272,4 +273,18 @@ public AuthorizationCodeResourceDetails getDefaultAuthorizationCodeResource() { result.setPreEstablishedRedirectUri(redirectUri); return result; } + + public static final String INSERT_BARE_BONE_USER = "insert into users (id, username, password, email, identity_zone_id) values (?,?,?,?,?)"; + public String addRandomUser(JdbcTemplate jdbcTemplate) { + String id = UUID.randomUUID().toString(); + return addRandomUser(jdbcTemplate, id); + } + public String addRandomUser(JdbcTemplate jdbcTemplate, String id) { + return addRandomUser(jdbcTemplate, id, IdentityZoneHolder.get().getId()); + } + public String addRandomUser(JdbcTemplate jdbcTemplate, String id, String zoneId) { + String username = id + "-testuser"; + jdbcTemplate.update(INSERT_BARE_BONE_USER, id, username, "password", username+"@test.com", zoneId); + return id; + } } diff --git a/server/src/test/java/org/cloudfoundry/identity/uaa/zone/MultitenantJdbcClientDetailsServiceTests.java b/server/src/test/java/org/cloudfoundry/identity/uaa/zone/MultitenantJdbcClientDetailsServiceTests.java index 2020a6dda1b..b1876655dd2 100644 --- a/server/src/test/java/org/cloudfoundry/identity/uaa/zone/MultitenantJdbcClientDetailsServiceTests.java +++ b/server/src/test/java/org/cloudfoundry/identity/uaa/zone/MultitenantJdbcClientDetailsServiceTests.java @@ -5,6 +5,7 @@ import org.cloudfoundry.identity.uaa.constants.OriginKeys; import org.cloudfoundry.identity.uaa.oauth.UaaOauth2Authentication; import org.cloudfoundry.identity.uaa.oauth.client.ClientConstants; +import org.cloudfoundry.identity.uaa.test.UaaTestAccounts; import org.cloudfoundry.identity.uaa.util.JsonUtils; import org.flywaydb.core.Flyway; import org.flywaydb.core.api.MigrationVersion; @@ -69,7 +70,7 @@ public class MultitenantJdbcClientDetailsServiceTests { private static final String INSERT_APPROVAL = "insert into authz_approvals (client_id, user_id, scope, status, expiresat, lastmodifiedat) values (?,?,?,?,?,?)"; - private static final String INSERT_BARE_BONE_USER = "insert into users (id, username, password, email, identity_zone_id) values (?,?,?,?,?)"; + private UaaTestAccounts testAccounts = UaaTestAccounts.standard(null); private IdentityZone otherIdentityZone; @@ -119,7 +120,7 @@ protected void addApproval(String clientId) { String zoneId = IdentityZoneHolder.get().getId(); String userId = zoneId + clientId; jdbcTemplate.update(INSERT_APPROVAL, clientId, userId, "uaa.user", "APPROVED", timestamp, timestamp); - jdbcTemplate.update(INSERT_BARE_BONE_USER, userId, userId, userId, userId+"@test.com", zoneId); + testAccounts.addRandomUser(jdbcTemplate, userId, zoneId); } @Test