Fixes for linked collections
Project: http://git-wip-us.apache.org/repos/asf/usergrid/repo Commit: http://git-wip-us.apache.org/repos/asf/usergrid/commit/7f49c806 Tree: http://git-wip-us.apache.org/repos/asf/usergrid/tree/7f49c806 Diff: http://git-wip-us.apache.org/repos/asf/usergrid/diff/7f49c806 Branch: refs/heads/master Commit: 7f49c8068ab68ab440d3c2e430cb69f68befc53e Parents: 9efa3b4 Author: Mike Dunker <[email protected]> Authored: Wed Jun 22 13:41:12 2016 -0700 Committer: Mike Dunker <[email protected]> Committed: Wed Jun 22 13:41:12 2016 -0700 ---------------------------------------------------------------------- .../corepersistence/CpRelationManager.java | 32 +++++--- .../usergrid/rest/management/AdminUsersIT.java | 80 ++++++++++++++++++++ .../cassandra/ManagementServiceImpl.java | 33 +++++--- .../services/devices/DevicesService.java | 2 + 4 files changed, 126 insertions(+), 21 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/usergrid/blob/7f49c806/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpRelationManager.java ---------------------------------------------------------------------- diff --git a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpRelationManager.java b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpRelationManager.java index 4082b45..39b3161 100644 --- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpRelationManager.java +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpRelationManager.java @@ -501,9 +501,9 @@ public class CpRelationManager implements RelationManager { @Override public void removeFromCollection( String collectionName, EntityRef itemRef ) throws Exception { - // special handling for roles collection of the application if ( headEntity.getUuid().equals( applicationId ) ) { if ( collectionName.equals( COLLECTION_ROLES ) ) { + // special handling for roles collection of the application Entity itemEntity = em.get( itemRef ); if ( itemEntity != null ) { RoleRef roleRef = SimpleRoleRef.forRoleEntity( itemEntity ); @@ -511,12 +511,12 @@ public class CpRelationManager implements RelationManager { return; } } + // handles normal app collection deletes em.delete( itemRef ); return; } - // load the entity to be removed to the collection - + // headEntity is not an application (used for management entities and entity collections like user devices) if ( logger.isDebugEnabled() ) { logger.debug( "Loading entity to remove from collection {}:{} from app {}\n", @@ -531,12 +531,26 @@ public class CpRelationManager implements RelationManager { GraphManager gm = managerCache.getGraphManager( applicationScope ); + List<Edge> removedEdges = new ArrayList<>(); //run our delete gm.loadEdgeVersions( CpNamingUtils.createEdgeFromCollectionName( cpHeadEntity.getId(), collectionName, memberEntity.getId() ) ) - .flatMap(edge -> gm.markEdge(edge)).flatMap(edge -> gm.deleteEdge(edge)).toBlocking() + .flatMap(edge -> gm.markEdge(edge)).flatMap(edge -> gm.deleteEdge(edge)) + .doOnNext(edge -> removedEdges.add(edge)).toBlocking() .lastOrDefault(null); + CollectionInfo collection = getDefaultSchema().getCollection( headEntity.getType(), collectionName ); + if (collection != null && collection.getLinkedCollection() != null) { + // delete reverse edges + final String pluralType = InflectionUtils.pluralize( cpHeadEntity.getId().getType() ); + gm.loadEdgeVersions( + CpNamingUtils.createEdgeFromCollectionName( memberEntity.getId(), pluralType, cpHeadEntity.getId() ) ) + .flatMap(reverseEdge -> gm.markEdge(reverseEdge)) + .flatMap(reverseEdge -> gm.deleteEdge(reverseEdge)) + .doOnNext(reverseEdge -> removedEdges.add(reverseEdge)) + .toBlocking().lastOrDefault(null); + } + /** * Remove from the index @@ -544,12 +558,10 @@ public class CpRelationManager implements RelationManager { */ - //TODO: this should not happen here, needs to go to SQS - //indexProducer.put(batch).subscribe(); - if ( !skipIndexingForType( memberEntity.getId().getType() ) ) { - - indexService.queueEntityDelete(applicationScope, memberEntity.getId()); - } + // item not deindexed, only edges + removedEdges.forEach(edge -> { + indexService.queueDeleteEdge(applicationScope, edge); + }); // special handling for roles collection of a group if ( headEntity.getType().equals( Group.ENTITY_TYPE ) ) { http://git-wip-us.apache.org/repos/asf/usergrid/blob/7f49c806/stack/rest/src/test/java/org/apache/usergrid/rest/management/AdminUsersIT.java ---------------------------------------------------------------------- diff --git a/stack/rest/src/test/java/org/apache/usergrid/rest/management/AdminUsersIT.java b/stack/rest/src/test/java/org/apache/usergrid/rest/management/AdminUsersIT.java index 07132cb..3adc719 100644 --- a/stack/rest/src/test/java/org/apache/usergrid/rest/management/AdminUsersIT.java +++ b/stack/rest/src/test/java/org/apache/usergrid/rest/management/AdminUsersIT.java @@ -435,6 +435,7 @@ public class AdminUsersIT extends AbstractRestIT { //Add a property to management user Entity userProperty = new Entity( ).chainPut( "company","usergrid" ); management().users().user( newOrg.getUsername() ).put( userProperty ); + fail("Should not have been allowed"); } catch( NotAuthorizedException e ){ @@ -445,6 +446,85 @@ public class AdminUsersIT extends AbstractRestIT { } + @Test + public void testAdminRemovalFromOrg() throws Exception { + Organization newOrg = createOrgPayload( "testAdminRemovalFromOrg", null ); + Organization orgReturned = clientSetup.getRestClient().management().orgs().post(newOrg); + User owner = orgReturned.getOwner(); + assertNotNull(owner); + String orgName = orgReturned.getName(); + Token ownerToken = management.token().get(owner.getUsername(), orgName); + + // add a new admin user to the org + Entity adminUserPayload = new Entity(); + String newAdminUserName = "newAdminUser"+UUIDUtils.newTimeUUID(); + adminUserPayload.put( "username", newAdminUserName ); + adminUserPayload.put( "name", newAdminUserName ); + adminUserPayload.put( "email", newAdminUserName+"@usergrid.com" ); + adminUserPayload.put( "password", newAdminUserName ); + + management.token().setToken(ownerToken); + management.orgs().org(orgName).users().post(User.class, adminUserPayload); + + // get token of the new admin user + Token adminToken = management.token().get(newAdminUserName, newAdminUserName); + assertNotNull(adminToken); + + // get org info + try { + management.token().setToken(adminToken); + management.orgs().org(orgName).get(); + } + catch (Exception e) { + // should have been allowed + fail("Should have worked: " + e.getMessage()); + } + + // remove access + try { + management.token().setToken(ownerToken); + management.orgs().org(orgName).users().user(newAdminUserName).delete(); + } + catch (Exception e) { + // should have been allowed + fail("Should have worked: " + e.getMessage()); + } + + // get org info (should be unsuccessful) + try { + management.token().setToken(adminToken); + management.orgs().org(orgName).get(); + fail("Should not have allowed org access"); + } + catch (NotAuthorizedException nae) { + // this is the right return + + } + catch (Exception e) { + fail("Should have been unauthorized: " + e.getMessage()); + } + + // restore access + try { + management.token().setToken(ownerToken); + management.orgs().org(orgName).users().user(newAdminUserName).put(new Entity()); + } + catch (Exception e) { + // should have been allowed + fail("Should have worked: " + e.getMessage()); + } + + // get org info + try { + management.token().setToken(adminToken); + management.orgs().org(orgName).get(); + } + catch (Exception e) { + // should have been allowed + fail("Should have worked: " + e.getMessage()); + } + + } /** http://git-wip-us.apache.org/repos/asf/usergrid/blob/7f49c806/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java ---------------------------------------------------------------------- diff --git a/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java b/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java index 73a56c8..b56f211 100644 --- a/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java +++ b/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java @@ -1580,7 +1580,8 @@ public class ManagementServiceImpl implements ManagementService { BiMap<UUID, String> organizations = HashBiMap.create(); EntityManager em = emf.getEntityManager( smf.getManagementAppId() ); - Results results = em.getCollection( new SimpleEntityRef( User.ENTITY_TYPE, userId ), + EntityRef userRef = new SimpleEntityRef(User.ENTITY_TYPE, userId); + Results results = em.getCollection( userRef, Schema.COLLECTION_GROUPS, null, 1000, Level.ALL_PROPERTIES, false ); do { @@ -1592,10 +1593,17 @@ public class ManagementServiceImpl implements ManagementService { path = path.toLowerCase(); } - try { - organizations.put( entity.getUuid(), path ); - } catch (IllegalArgumentException e) { - logger.warn("Error adding {}:{} to BiMap: {}", entity.getUuid(), path, e.getMessage() ); + // check that user is in users collection for org + EntityRef groupRef = new SimpleEntityRef(Group.ENTITY_TYPE, entity.getUuid()); + if (em.isCollectionMember(groupRef, Schema.COLLECTION_USERS, userRef)) { + try { + organizations.put(entity.getUuid(), path); + } catch (IllegalArgumentException e) { + logger.warn("Error adding {}:{} to BiMap: {}", entity.getUuid(), path, e.getMessage()); + } + } else { + // org doesn't know about user, so read repair + em.removeFromCollection(userRef, Schema.COLLECTION_GROUPS, groupRef); } } @@ -1698,16 +1706,18 @@ public class ManagementServiceImpl implements ManagementService { EntityManager em = emf.getEntityManager( smf.getManagementAppId() ); + EntityRef orgRef = new SimpleEntityRef( Group.ENTITY_TYPE, organization.getUuid() ); + EntityRef userRef = new SimpleEntityRef( User.ENTITY_TYPE, user.getUuid() ); + - if(em.getCollection(organization.getUuid() ,"users",Query.fromQL( "select * where uuid ="+user.getUuid() ),Level.IDS ).size() >0){ + if(em.isCollectionMember(orgRef, Schema.COLLECTION_USERS, userRef)) { if(logger.isDebugEnabled()) { logger.debug( "addAdminUserToOrganization - Found value: {} already in collection", user.getName() ); } return; } - em.addToCollection(new SimpleEntityRef(Group.ENTITY_TYPE, organization.getUuid()), "users", - new SimpleEntityRef(User.ENTITY_TYPE, user.getUuid())); + em.addToCollection(orgRef, Schema.COLLECTION_USERS, userRef); invalidateManagementAppAuthCache(); @@ -1733,10 +1743,11 @@ public class ManagementServiceImpl implements ManagementService { EntityManager em = emf.getEntityManager( smf.getManagementAppId() ); try { - int size = em.getCollection( new SimpleEntityRef( Group.ENTITY_TYPE, organizationId ), - "users", null, 2, Level.IDS, false ).size(); + Results collection = em.getCollection( new SimpleEntityRef( Group.ENTITY_TYPE, organizationId ), + "users", null, 2, Level.IDS, false ); + int size = collection.size(); - if ( !force && size <= 1 ) { + if ( !force && (size == 0 || (size == 1 && collection.getId() == userId))) { throw new Exception(); } } http://git-wip-us.apache.org/repos/asf/usergrid/blob/7f49c806/stack/services/src/main/java/org/apache/usergrid/services/devices/DevicesService.java ---------------------------------------------------------------------- diff --git a/stack/services/src/main/java/org/apache/usergrid/services/devices/DevicesService.java b/stack/services/src/main/java/org/apache/usergrid/services/devices/DevicesService.java index f57a03a..111c96a 100644 --- a/stack/services/src/main/java/org/apache/usergrid/services/devices/DevicesService.java +++ b/stack/services/src/main/java/org/apache/usergrid/services/devices/DevicesService.java @@ -85,6 +85,8 @@ public class DevicesService extends AbstractCollectionService { for (EntityRef userDevice : userDevices) { if(userDevice.getUuid().equals(deviceRef.getUuid())) { //only remove the current device from user em.removeFromCollection(user, "devices", userDevice); + // TODO: may want to actually remove the device + // em.delete(userDevice); } } em.removeFromCollection(deviceRef, "users", user);
