You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by sn...@apache.org on 2015/07/10 15:37:20 UTC
[14/50] [abbrv] incubator-usergrid git commit: Add organization
export to ExportAdmins tool and organization import to ImportAdmins tool.
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c5187d22/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 5b77534..8561300 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
@@ -496,7 +496,7 @@ public class ManagementServiceImpl implements ManagementService {
user = createAdminUserInternal( username, name, email, password, activated, disabled, userProperties );
}
- organization = createOrganizationInternal( organizationName, user, true, organizationProperties );
+ organization = createOrganizationInternal( null, organizationName, user, true, organizationProperties );
}
finally {
emailLock.unlock();
@@ -508,14 +508,16 @@ public class ManagementServiceImpl implements ManagementService {
}
- private OrganizationInfo createOrganizationInternal( String organizationName, UserInfo user, boolean activated )
- throws Exception {
- return createOrganizationInternal( organizationName, user, activated, null );
+ private OrganizationInfo createOrganizationInternal(
+ UUID orgUuid, String organizationName, UserInfo user, boolean activated) throws Exception {
+ return createOrganizationInternal( orgUuid, organizationName, user, activated, null );
}
- private OrganizationInfo createOrganizationInternal( String organizationName, UserInfo user, boolean activated,
- Map<String, Object> properties ) throws Exception {
+ private OrganizationInfo createOrganizationInternal(
+ UUID orgUuid, String organizationName, UserInfo user, boolean activated,
+ Map<String, Object> properties ) throws Exception {
+
if ( ( organizationName == null ) || ( user == null ) ) {
return null;
}
@@ -524,7 +526,13 @@ public class ManagementServiceImpl implements ManagementService {
Group organizationEntity = new Group();
organizationEntity.setPath( organizationName );
- organizationEntity = em.create( organizationEntity );
+
+ if ( orgUuid == null ) {
+ organizationEntity = em.create( organizationEntity );
+ } else {
+ em.create( orgUuid, Group.ENTITY_TYPE, organizationEntity.getProperties() );
+ organizationEntity = em.get( orgUuid, Group.class );
+ }
em.addToCollection( organizationEntity, "users", new SimpleEntityRef( User.ENTITY_TYPE, user.getUuid() ) );
@@ -536,20 +544,29 @@ public class ManagementServiceImpl implements ManagementService {
new OrganizationInfo( organizationEntity.getUuid(), organizationName, properties );
updateOrganization( organization );
- logger.info( "createOrganizationInternal: {}", organizationName );
- postOrganizationActivity( organization.getUuid(), user, "create", organizationEntity, "Organization",
- organization.getName(),
- "<a href=\"mailto:" + user.getEmail() + "\">" + user.getName() + " (" + user.getEmail()
- + ")</a> created a new organization account named " + organizationName, null );
+ if ( orgUuid == null ) { // no import ID specified, so do the activation email flow stuff
- startOrganizationActivationFlow( organization );
+ logger.info( "createOrganizationInternal: {}", organizationName );
+ postOrganizationActivity( organization.getUuid(), user, "create", organizationEntity, "Organization",
+ organization.getName(),
+ "<a href=\"mailto:" + user.getEmail() + "\">" + user.getName() + " (" + user.getEmail()
+ + ")</a> created a new organization account named " + organizationName, null );
+
+ startOrganizationActivationFlow( organization );
+ }
return organization;
}
@Override
- public OrganizationInfo createOrganization( String organizationName, UserInfo user, boolean activated )
+ public OrganizationInfo createOrganization(String organizationName, UserInfo user, boolean activated)
+ throws Exception {
+ return createOrganization( organizationName, user, activated );
+ }
+
+ @Override
+ public OrganizationInfo createOrganization(UUID orgUuid, String organizationName, UserInfo user, boolean activated)
throws Exception {
if ( ( organizationName == null ) || ( user == null ) ) {
@@ -563,7 +580,7 @@ public class ManagementServiceImpl implements ManagementService {
}
try {
groupLock.lock();
- return createOrganizationInternal( organizationName, user, activated );
+ return createOrganizationInternal( orgUuid, organizationName, user, activated );
}
finally {
groupLock.unlock();
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c5187d22/stack/tools/pom.xml
----------------------------------------------------------------------
diff --git a/stack/tools/pom.xml b/stack/tools/pom.xml
index 0fac833..77fcee4 100644
--- a/stack/tools/pom.xml
+++ b/stack/tools/pom.xml
@@ -35,7 +35,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
- <version>2.7</version>
+ <version>2.9.1</version>
</plugin>
</plugins>
</reporting>
@@ -233,5 +233,21 @@
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>org.apache.usergrid</groupId>
+ <artifactId>usergrid-test-utils</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.usergrid</groupId>
+ <artifactId>usergrid-services</artifactId>
+ <classifier>tests</classifier>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
</dependencies>
</project>
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c5187d22/stack/tools/src/main/java/org/apache/usergrid/tools/ExportAdmins.java
----------------------------------------------------------------------
diff --git a/stack/tools/src/main/java/org/apache/usergrid/tools/ExportAdmins.java b/stack/tools/src/main/java/org/apache/usergrid/tools/ExportAdmins.java
index fe2752f..8831b89 100644
--- a/stack/tools/src/main/java/org/apache/usergrid/tools/ExportAdmins.java
+++ b/stack/tools/src/main/java/org/apache/usergrid/tools/ExportAdmins.java
@@ -1,6 +1,3 @@
-/**
- * Created by ApigeeCorporation on 4/9/15.
- */
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
@@ -26,6 +23,7 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
+import com.google.common.collect.BiMap;
import org.codehaus.jackson.JsonGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -39,7 +37,6 @@ import org.apache.usergrid.persistence.Query;
import org.apache.usergrid.persistence.Results;
import org.apache.usergrid.persistence.Results.Level;
import org.apache.usergrid.persistence.cassandra.CassandraService;
-import org.apache.usergrid.utils.JsonUtils;
/**
@@ -47,8 +44,10 @@ import org.apache.usergrid.utils.JsonUtils;
*/
public class ExportAdmins extends ExportingToolBase {
- static final Logger logger = LoggerFactory.getLogger( Export.class );
+ static final Logger logger = LoggerFactory.getLogger( ExportAdmins.class );
+ public static final String ADMIN_USERS_PREFIX = "admin-users";
+ public static final String ADMIN_USER_METADATA_PREFIX = "admin-user-metadata";
@Override
public void runTool( CommandLine line ) throws Exception {
@@ -61,30 +60,29 @@ public class ExportAdmins extends ExportingToolBase {
outputDir = createOutputParentDir();
logger.info( "Export directory: " + outputDir.getAbsolutePath() );
- exportApplicationsForOrg( null );
+ exportAdminUsers();
}
- private void exportApplicationsForOrg( Map.Entry<UUID, String> organization ) throws Exception {
+ private void exportAdminUsers() throws Exception {
+
+ int count = 0;
EntityManager em = emf.getEntityManager( CassandraService.MANAGEMENT_APPLICATION_ID );
- // Get the JSon serializer.
- JsonGenerator jg = getJsonGenerator( createOutputFile( "application", em.getApplication().getName() ) );
+ // write one JSON file for management application users
- jg.writeStartArray();
+ JsonGenerator usersFile =
+ getJsonGenerator( createOutputFile( ADMIN_USERS_PREFIX, em.getApplication().getName() ) );
+ usersFile.writeStartArray();
- // Create a GENERATOR for the application collections.
- JsonGenerator collectionsJg =
- getJsonGenerator( createOutputFile( "collections", em.getApplication().getName() ) );
- collectionsJg.writeStartObject();
+ // write one JSON file for metadata: collections, connections and dictionaries of those users
- Map<String, Object> metadata = em.getApplicationCollectionMetadata();
- echo( JsonUtils.mapToFormattedJsonString( metadata ) );
+ JsonGenerator metadataFile =
+ getJsonGenerator( createOutputFile( ADMIN_USER_METADATA_PREFIX, em.getApplication().getName() ) );
+ metadataFile.writeStartObject();
- // Loop through the collections. This is the only way to loop
- // through the entities in the application (former namespace).
- // for ( String collectionName : metadata.keySet() ) {
+ // query for and loop through all users in management application
Query query = new Query();
query.setLimit( MAX_ENTITY_FETCH );
@@ -95,33 +93,37 @@ public class ExportAdmins extends ExportingToolBase {
while ( entities.size() > 0 ) {
for ( Entity entity : entities ) {
- // Export the entity first and later the collections for
- // this entity.
- jg.writeObject( entity );
+
+ // write user to application file
+ usersFile.writeObject( entity );
echo( entity );
- saveCollectionMembers( collectionsJg, em, null, entity );
+ // write user's collections, connections, etc. to collections file
+ saveEntityMetadata( metadataFile, em, null, entity );
+
+ logger.debug("Exported user {}", entity.getProperty( "email" ));
+
+ count++;
+ if ( count % 1000 == 0 ) {
+ logger.info("Exported {} admin users", count);
+ }
+
}
- //we're done
if ( entities.getCursor() == null ) {
break;
}
-
query.setCursor( entities.getCursor() );
-
entities = em.searchCollection( em.getApplicationRef(), "users", query );
}
- //}
- // Close writer for the collections for this application.
- collectionsJg.writeEndObject();
- collectionsJg.close();
+ metadataFile.writeEndObject();
+ metadataFile.close();
- // Close writer and file for this application.
- jg.writeEndArray();
- jg.close();
- // }
+ usersFile.writeEndArray();
+ usersFile.close();
+
+ logger.info("Exported total of {} admin users", count);
}
@@ -132,8 +134,20 @@ public class ExportAdmins extends ExportingToolBase {
* @param application Application name
* @param entity entity
*/
- private void saveCollectionMembers( JsonGenerator jg, EntityManager em, String application, Entity entity )
- throws Exception {
+ private void saveEntityMetadata(
+ JsonGenerator jg, EntityManager em, String application, Entity entity) throws Exception {
+
+ saveCollections( jg, em, entity );
+ saveConnections( entity, em, jg );
+ saveOrganizations( entity, em, jg );
+ saveDictionaries( entity, em, jg );
+
+ // End the object if it was Started
+ jg.writeEndObject();
+ }
+
+
+ private void saveCollections(JsonGenerator jg, EntityManager em, Entity entity) throws Exception {
Set<String> collections = em.getCollections( entity );
@@ -164,17 +178,9 @@ public class ExportAdmins extends ExportingToolBase {
// End collection array.
jg.writeEndArray();
}
-
- // Write connections
- saveConnections( entity, em, jg );
-
- // Write dictionaries
- saveDictionaries( entity, em, jg );
-
- // End the object if it was Started
- jg.writeEndObject();
}
+
/**
* Persists the connection for this entity.
*/
@@ -207,8 +213,9 @@ public class ExportAdmins extends ExportingToolBase {
jg.writeEndObject();
}
+
/**
- * Persists the connection for this entity.
+ * Persists the outgoing connections for this entity.
*/
private void saveConnections( Entity entity, EntityManager em, JsonGenerator jg ) throws Exception {
@@ -232,5 +239,34 @@ public class ExportAdmins extends ExportingToolBase {
}
jg.writeEndObject();
}
+
+
+ /**
+ * Persists the incoming connections for this entity.
+ */
+ private void saveOrganizations(Entity entity, EntityManager em, JsonGenerator jg) throws Exception {
+
+ final BiMap<UUID, String> orgs = managementService.getOrganizationsForAdminUser( entity.getUuid() );
+
+ jg.writeFieldName( "organizations" );
+
+ jg.writeStartArray();
+
+ for ( UUID uuid : orgs.keySet() ) {
+
+ jg.writeStartObject();
+
+ jg.writeFieldName( "uuid" );
+ jg.writeObject( uuid );
+
+ jg.writeFieldName( "name" );
+ jg.writeObject( orgs.get( uuid ) );
+
+ jg.writeEndObject();
+ }
+
+ jg.writeEndArray();
+ }
+
}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c5187d22/stack/tools/src/main/java/org/apache/usergrid/tools/ImportAdmins.java
----------------------------------------------------------------------
diff --git a/stack/tools/src/main/java/org/apache/usergrid/tools/ImportAdmins.java b/stack/tools/src/main/java/org/apache/usergrid/tools/ImportAdmins.java
index 76b2343..bf0a2e4 100644
--- a/stack/tools/src/main/java/org/apache/usergrid/tools/ImportAdmins.java
+++ b/stack/tools/src/main/java/org/apache/usergrid/tools/ImportAdmins.java
@@ -17,33 +17,29 @@
package org.apache.usergrid.tools;
-import java.io.File;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.UUID;
-
-import org.codehaus.jackson.JsonFactory;
-import org.codehaus.jackson.JsonNode;
-import org.codehaus.jackson.JsonParser;
-import org.codehaus.jackson.JsonToken;
-import org.codehaus.jackson.map.ObjectMapper;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.io.filefilter.PrefixFileFilter;
-
import org.apache.usergrid.management.OrganizationInfo;
-import org.apache.usergrid.persistence.Entity;
+import org.apache.usergrid.management.UserInfo;
import org.apache.usergrid.persistence.EntityManager;
import org.apache.usergrid.persistence.EntityRef;
-import org.apache.usergrid.persistence.entities.Application;
+import org.apache.usergrid.persistence.entities.User;
import org.apache.usergrid.persistence.exceptions.DuplicateUniquePropertyExistsException;
-import org.apache.usergrid.utils.JsonUtils;
+import org.codehaus.jackson.JsonFactory;
+import org.codehaus.jackson.JsonParser;
+import org.codehaus.jackson.JsonToken;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
import static org.apache.usergrid.persistence.Schema.PROPERTY_TYPE;
import static org.apache.usergrid.persistence.Schema.PROPERTY_UUID;
@@ -75,14 +71,15 @@ public class ImportAdmins extends ToolBase {
@SuppressWarnings( "static-access" )
public Options createOptions() {
- Option hostOption =
- OptionBuilder.withArgName( "host" ).hasArg().withDescription( "Cassandra host" ).create( "host" );
+ Option hostOption = OptionBuilder.withArgName( "host" )
+ .hasArg().withDescription( "Cassandra host" ).create( "host" );
- Option inputDir = OptionBuilder.hasArg().withDescription( "input directory -inputDir" ).create( INPUT_DIR );
+ Option inputDir = OptionBuilder
+ .hasArg().withDescription( "input directory -inputDir" ).create( INPUT_DIR );
- Option verbose =
- OptionBuilder.withDescription( "Print on the console an echo of the content written to the file" )
- .create( VERBOSE );
+ Option verbose = OptionBuilder
+ .withDescription( "Print on the console an echo of the content written to the file" )
+ .create( VERBOSE );
Options options = new Options();
options.addOption( hostOption );
@@ -95,118 +92,101 @@ public class ImportAdmins extends ToolBase {
@Override
public void runTool( CommandLine line ) throws Exception {
+
startSpring();
setVerbose( line );
openImportDirectory( line );
- importApplications();
-
- importCollections();
+ importAdminUsers();
- //forces the counters to flush
- logger.info( "Sleeping 35 seconds for batcher" );
+ importMetadata();
- Thread.sleep( 35000 );
+ // forces the counters to flush
+// logger.info( "Sleeping 35 seconds for batcher" );
+// Thread.sleep( 35000 );
}
/**
- * Import applications
+ * Import admin users.
*/
- private void importApplications() throws Exception {
- String[] nanemspaceFileNames = importDir.list( new PrefixFileFilter( "application." ) );
- logger.info( "Applications to read: " + nanemspaceFileNames.length );
+ private void importAdminUsers() throws Exception {
+ String[] fileNames = importDir.list( new PrefixFileFilter( ExportAdmins.ADMIN_USERS_PREFIX + "." ) );
+ logger.info( "Applications to read: " + fileNames.length );
//this fails on the second run of the applications find out why.
- for ( String applicationName : nanemspaceFileNames ) {
+ for ( String fileName : fileNames ) {
try {
- importApplication( applicationName );
+ importAdminUsers( fileName );
}
catch ( Exception e ) {
- logger.warn( "Unable to import application: " + applicationName, e );
+ logger.warn( "Unable to import application: " + fileName, e );
}
}
}
/**
- * Imports a application
+ * Imports admin users.
*
- * @param applicationName file name where the application was exported.
+ * @param fileName Name of admin user data file.
*/
- private void importApplication( String applicationName ) throws Exception {
- // Open up application file.
- File applicationFile = new File( importDir, applicationName );
-
- logger.info( "Loading application file: " + applicationFile.getAbsolutePath() );
- JsonParser jp = getJsonParserForFile( applicationFile );
-
- JsonToken token = jp.nextToken();
- validateStartArray( token );
+ private void importAdminUsers( String fileName ) throws Exception {
- // Move to next object (the application).
- // The application object is the first object followed by all the
- // objects in this application.
- token = jp.nextValue();
-
- Application application = jp.readValueAs( Application.class );
-
- UUID appId = MANAGEMENT_APPLICATION_ID;
-
- EntityManager em = emf.getEntityManager( appId );
-
- // we now need to remove all roles, they'll be imported again below
-
- for ( Entry<String, String> entry : em.getRoles().entrySet() ) {
- em.deleteRole( entry.getKey() );
- }
+ int count = 0;
- //load all the dictionaries
- @SuppressWarnings( "unchecked" ) Map<String, Object> dictionaries =
- ( Map<String, Object> ) application.getMetadata( "dictionaries" );
+ File adminUsersFile = new File( importDir, fileName );
- if ( dictionaries != null ) {
- EntityManager rootEm = emf.getEntityManager( MANAGEMENT_APPLICATION_ID );
+ logger.info( "----- Loading file: " + adminUsersFile.getAbsolutePath() );
+ JsonParser jp = getJsonParserForFile( adminUsersFile );
- Entity appEntity = rootEm.get( appId );
+ JsonToken token = jp.nextToken();
+ validateStartArray( token );
+ EntityManager em = emf.getEntityManager( MANAGEMENT_APPLICATION_ID );
- for ( Entry<String, Object> dictionary : dictionaries.entrySet() ) {
- @SuppressWarnings( "unchecked" ) Map<Object, Object> value =
- ( Map<Object, Object> ) dictionary.getValue();
+ while ( jp.nextValue() != JsonToken.END_ARRAY ) {
- em.addMapToDictionary( appEntity, dictionary.getKey(), value );
- }
- }
+ @SuppressWarnings( "unchecked" )
+ Map<String, Object> entityProps = jp.readValueAs( HashMap.class );
- while ( jp.nextValue() != JsonToken.END_ARRAY ) {
- @SuppressWarnings( "unchecked" ) Map<String, Object> entityProps = jp.readValueAs( HashMap.class );
// Import/create the entity
UUID uuid = getId( entityProps );
String type = getType( entityProps );
+
try {
em.create( uuid, type, entityProps );
+
+ logger.debug( "Imported admin user {} {}", uuid, entityProps.get( "username" ) );
+ count++;
+ if ( count % 1000 == 0 ) {
+ logger.info("Imported {} admin users", count);
+ }
}
catch ( DuplicateUniquePropertyExistsException de ) {
- logger.error( "Unable to create entity. It appears to be a duplicate", de );
+ logger.warn( "Unable to create entity. It appears to be a duplicate: " +
+ "id={}, type={}, name={}, username={}",
+ new Object[] { uuid, type, entityProps.get("name"), entityProps.get("username")});
+ if ( logger.isDebugEnabled() ) {
+ logger.debug( "Exception" , de );
+ }
continue;
}
if ( em.get( uuid ) == null ) {
- logger.error( "Holy hell, we wrote an entity and it's missing. Entity Id was {} and type is {}", uuid,
- type );
+ logger.error( "Holy hell, we wrote an entity and it's missing. " +
+ "Entity Id was {} and type is {}", uuid, type );
System.exit( 1 );
}
-
- logger.info( "Counts {}", JsonUtils.mapToFormattedJsonString( em.getApplicationCounters() ) );
-
echo( entityProps );
}
- logger.info( "----- End of application:" + application.getName() );
+ logger.info( "----- End: Imported {} admin users from file {}",
+ count, adminUsersFile.getAbsolutePath() );
+
jp.close();
}
@@ -238,198 +218,181 @@ public class ImportAdmins extends ToolBase {
/**
* Import collections. Collections files are named: collections.<application_name>.Timestamp.json
*/
- private void importCollections() throws Exception {
- String[] collectionsFileNames = importDir.list( new PrefixFileFilter( "collections." ) );
- logger.info( "Collections to read: " + collectionsFileNames.length );
+ private void importMetadata() throws Exception {
+
+ String[] fileNames = importDir.list(
+ new PrefixFileFilter( ExportAdmins.ADMIN_USER_METADATA_PREFIX + "." ) );
+ logger.info( "Metadata files to read: " + fileNames.length );
- for ( String collectionName : collectionsFileNames ) {
+ for ( String fileName : fileNames ) {
try {
- importCollection( collectionName );
+ importMetadata( fileName );
}
catch ( Exception e ) {
- logger.warn( "Unable to import collection: " + collectionName, e );
+ logger.warn( "Unable to import metadata file: " + fileName, e );
}
}
}
- private void importCollection( String collectionFileName ) throws Exception {
- // Retrieve the namepsace for this collection. It's part of the name
- String applicationName = getApplicationFromColllection( collectionFileName );
-
- UUID appId = emf.lookupApplication( applicationName );
-
- //no org in path, this is a pre public beta so we need to create the new path
- if ( appId == null && !applicationName.contains( "/" ) ) {
- String fileName = collectionFileName.replace( "collections", "application" );
-
- File applicationFile = new File( importDir, fileName );
+ @SuppressWarnings( "unchecked" )
+ private void importMetadata( String fileName ) throws Exception {
- if ( !applicationFile.exists() ) {
- logger.error( "Could not load application file {} to search for org information",
- applicationFile.getAbsolutePath() );
- return;
- }
-
-
- logger.info( "Loading application file: " + applicationFile.getAbsolutePath() );
+ EntityManager em = emf.getEntityManager( MANAGEMENT_APPLICATION_ID );
- JsonParser jp = getJsonParserForFile( applicationFile );
+ File metadataFile = new File( importDir, fileName );
- JsonToken token = jp.nextToken();
- validateStartArray( token );
+ logger.info( "----- Loading metadata file: " + metadataFile.getAbsolutePath() );
- // Move to next object (the application).
- // The application object is the first object followed by all the
- // objects in this application.
- token = jp.nextValue();
+ JsonParser jp = getJsonParserForFile( metadataFile );
- Application application = jp.readValueAs( Application.class );
+ JsonToken jsonToken = null; // jp.nextToken();// START_OBJECT this is the outer hashmap
- jp.close();
+ int depth = 1;
- @SuppressWarnings( "unchecked" ) String orgName =
- ( ( Map<String, String> ) application.getMetadata( "organization" ) ).get( "value" );
+ while ( depth > 0 ) {
- OrganizationInfo info = managementService.getOrganizationByName( orgName );
+ jsonToken = jp.nextToken();
- if ( info == null ) {
- logger.error( "Could not find org with name {}", orgName );
- return;
+ if ( jsonToken == null ) {
+ logger.info("token is null, breaking");
+ break;
}
- applicationName = orgName + "/" + applicationName;
-
- appId = emf.lookupApplication( applicationName );
- }
-
-
- if ( appId == null ) {
- logger.error( "Unable to find application with name {}. Skipping collections", appId );
- return;
- }
-
- File collectionFile = new File( importDir, collectionFileName );
-
- logger.info( "Loading collections file: " + collectionFile.getAbsolutePath() );
-
- JsonParser jp = getJsonParserForFile( collectionFile );
+ if (jsonToken.equals( JsonToken.START_OBJECT )) {
+ depth++;
+ } else if (jsonToken.equals( JsonToken.END_OBJECT )) {
+ depth--;
+ }
- jp.nextToken(); // START_OBJECT this is the outter hashmap
+ if (jsonToken.equals( JsonToken.FIELD_NAME ) && depth == 2 ) {
+ jp.nextToken();
- EntityManager em = emf.getEntityManager( appId );
+ String entityOwnerId = jp.getCurrentName();
+ EntityRef entityRef = em.getRef( UUID.fromString( entityOwnerId ) );
- while ( jp.nextToken() != JsonToken.END_OBJECT ) {
- try {
- importEntitysStuff( jp, em );
- }
- catch ( NullPointerException nae ) {
- //consume the read of the value so we can move on to process the next token.
- jp.readValueAs( JsonNode.class );
+ Map<String, Object> metadata = (Map<String, Object>)jp.readValueAs( Map.class );
+ importEntityMetadata( em, entityRef, metadata );
}
}
- logger.info( "----- End of collections -----" );
+ logger.info( "----- End of metadata -----" );
jp.close();
}
/**
* Imports the entity's connecting references (collections and connections)
- *
- * @param jp JsonPrser pointing to the beginning of the object.
*/
- private void importEntitysStuff( JsonParser jp, EntityManager em ) throws Exception {
- // The entity that owns the collections
- String entityOwnerId = jp.getCurrentName();
- EntityRef ownerEntityRef = em.getRef( UUID.fromString( entityOwnerId ) );
-
-
- jp.nextToken(); // start object
-
- //this is done after getting the next token so that we only capture the JsonNode object
- // and not the entire file response.
- if ( ownerEntityRef == null ) {
- throw new NullPointerException( "Couldn't retrieve entity ref from: " + entityOwnerId );
+ @SuppressWarnings("unchecked")
+ private void importEntityMetadata(
+ EntityManager em, EntityRef entityRef, Map<String, Object> metadata ) throws Exception {
+
+ Map<String, Object> connectionsMap = (Map<String, Object>) metadata.get( "connections" );
+
+ if (connectionsMap != null && !connectionsMap.isEmpty()) {
+ for (String type : connectionsMap.keySet()) {
+ try {
+ UUID uuid = UUID.fromString( (String) connectionsMap.get( type ) );
+ EntityRef connectedEntityRef = em.getRef( uuid );
+ em.createConnection( entityRef, type, connectedEntityRef );
+
+ logger.debug( "Creating connection from {} type {} target {}",
+ new Object[]{entityRef, type, connectedEntityRef});
+
+ } catch (Exception e) {
+ if (logger.isDebugEnabled()) {
+ logger.error( "Error importing connection of type "
+ + type + " for user " + entityRef.getUuid(), e );
+ } else {
+ logger.error( "Error importing connection of type "
+ + type + " for user " + entityRef.getUuid() );
+ }
+ }
+ }
}
- // Go inside the value after getting the owner entity id.
- while ( jp.nextToken() != JsonToken.END_OBJECT ) {
- String collectionName = jp.getCurrentName();
+ Map<String, Object> dictionariesMap = (Map<String, Object>) metadata.get( "dictionaries" );
- if ( collectionName.equals( "connections" ) ) {
+ if (dictionariesMap != null && !dictionariesMap.isEmpty()) {
+ for (String name : dictionariesMap.keySet()) {
+ try {
+ Map<String, Object> dictionary = (Map<String, Object>) dictionariesMap.get( name );
+ em.addMapToDictionary( entityRef, name, dictionary );
- jp.nextToken(); // START_OBJECT
- while ( jp.nextToken() != JsonToken.END_OBJECT ) {
- String connectionType = jp.getCurrentName();
+ logger.debug("Creating dictionary for {} name {} map {}",
+ new Object[] { entityRef, name, dictionary });
- jp.nextToken(); // START_ARRAY
- while ( jp.nextToken() != JsonToken.END_ARRAY ) {
- String entryId = jp.getText();
- EntityRef entryRef = em.getRef( UUID.fromString( entryId ) );
- // Store in DB
- em.createConnection( ownerEntityRef, connectionType, entryRef );
+ } catch (Exception e) {
+ if (logger.isDebugEnabled()) {
+ logger.error( "Error importing dictionary name "
+ + name + " for user " + entityRef.getUuid(), e );
+ } else {
+ logger.error( "Error importing dictionary name "
+ + name + " for user " + entityRef.getUuid() );
}
}
}
- else if ( collectionName.equals( "dictionaries" ) ) {
+ }
- jp.nextToken(); // START_OBJECT
- while ( jp.nextToken() != JsonToken.END_OBJECT ) {
+ List<String> collectionsList = (List<String>) metadata.get( "collections" );
+ if (collectionsList != null && !collectionsList.isEmpty()) {
+ for (String name : collectionsList) {
+ try {
+ UUID uuid = UUID.fromString( (String) connectionsMap.get( name ) );
+ EntityRef collectedEntityRef = em.getRef( uuid );
+ em.addToCollection( entityRef, name, collectedEntityRef );
+
+ logger.debug("Add to collection of {} name {} entity {}",
+ new Object[] { entityRef, name, collectedEntityRef });
+
+ } catch (Exception e) {
+ if (logger.isDebugEnabled()) {
+ logger.error( "Error adding to collection "
+ + name + " for user " + entityRef.getUuid(), e );
+ } else {
+ logger.error( "Error adding to collection "
+ + name + " for user " + entityRef.getUuid() );
+ }
+ }
+ }
+ }
- String dictionaryName = jp.getCurrentName();
+ List<Object> organizationsList = (List<Object>) metadata.get( "organizations" );
+ if (organizationsList != null && !organizationsList.isEmpty()) {
- jp.nextToken();
+ for ( Object orgObject : organizationsList ) {
- @SuppressWarnings( "unchecked" ) Map<String, Object> dictionary = jp.readValueAs( HashMap.class );
+ Map<String, Object> orgMap = (Map<String, Object>)orgObject;
+ UUID orgUuid = UUID.fromString( (String)orgMap.get("uuid") );
+ String orgName = (String)orgMap.get("name");
- em.addMapToDictionary( ownerEntityRef, dictionaryName, dictionary );
- }
- }
+ User user = em.get( entityRef, User.class );
+ final UserInfo userInfo = managementService.getAdminUserByEmail( user.getEmail() );
- else {
- // Regular collections
+ // create org only if it does not exist
+ OrganizationInfo orgInfo = managementService.getOrganizationByUuid( orgUuid );
+ if ( orgInfo == null ) {
+ try {
+ managementService.createOrganization( orgUuid, orgName, userInfo, false );
+ orgInfo = managementService.getOrganizationByUuid( orgUuid );
- jp.nextToken(); // START_ARRAY
- while ( jp.nextToken() != JsonToken.END_ARRAY ) {
- String entryId = jp.getText();
- EntityRef entryRef = em.getRef( UUID.fromString( entryId ) );
+ logger.debug( "Created new org {} for user {}",
+ new Object[]{orgInfo.getName(), user.getEmail()} );
- // store it
- em.addToCollection( ownerEntityRef, collectionName, entryRef );
+ } catch (DuplicateUniquePropertyExistsException dpee ) {
+ logger.error("Org {} already exists", orgName );
+ }
+ } else {
+ managementService.addAdminUserToOrganization( userInfo, orgInfo, false );
+ logger.debug( "Added user {} to org {}", new Object[]{user.getEmail(), orgName} );
}
}
}
}
- /**
- * Extract a application name from a collectionsFileName in the way:
- * collections.<a_name_space_name>.TIMESTAMP.json
- *
- * @param collectionFileName
- * a collection file name
- * @return the application name for this collections file name
- */
- /**
- * Extract a application name from a collectionsFileName in the way: collections.<a_name_space_name>.TIMESTAMP.json
- *
- * @param collectionFileName a collection file name
- *
- * @return the application name for this collections file name
- */
- private String getApplicationFromColllection( String collectionFileName ) {
- int firstDot = collectionFileName.indexOf( "." );
- int secondDot = collectionFileName.indexOf( ".", firstDot + 1 );
-
- // The application will be in the subString between the dots.
-
- String appName = collectionFileName.substring( firstDot + 1, secondDot );
-
- return appName.replace( PATH_REPLACEMENT, "/" );
- }
-
/**
* Open up the import directory based on <code>importDir</code>
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c5187d22/stack/tools/src/main/java/org/apache/usergrid/tools/ToolBase.java
----------------------------------------------------------------------
diff --git a/stack/tools/src/main/java/org/apache/usergrid/tools/ToolBase.java b/stack/tools/src/main/java/org/apache/usergrid/tools/ToolBase.java
index d0780a6..63187a4 100644
--- a/stack/tools/src/main/java/org/apache/usergrid/tools/ToolBase.java
+++ b/stack/tools/src/main/java/org/apache/usergrid/tools/ToolBase.java
@@ -64,7 +64,7 @@ public abstract class ToolBase {
static final Logger logger = LoggerFactory.getLogger( ToolBase.class );
- protected static final String PATH_REPLACEMENT = "USERGIRD-PATH-BACKSLASH";
+ protected static final String PATH_REPLACEMENT = "-";
protected EmbeddedServerHelper embedded = null;
@@ -80,6 +80,10 @@ public abstract class ToolBase {
public void startTool( String[] args ) {
+ startTool( args, true );
+ }
+
+ public void startTool( String[] args, boolean exit ) {
CommandLineParser parser = new GnuParser();
CommandLine line = null;
try {
@@ -103,7 +107,9 @@ public abstract class ToolBase {
catch ( Exception e ) {
e.printStackTrace();
}
- System.exit( 0 );
+ if ( exit ) {
+ System.exit( 0 );
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c5187d22/stack/tools/src/main/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/stack/tools/src/main/resources/log4j.properties b/stack/tools/src/main/resources/log4j.properties
index e9c23e5..73ade48 100644
--- a/stack/tools/src/main/resources/log4j.properties
+++ b/stack/tools/src/main/resources/log4j.properties
@@ -26,20 +26,21 @@ log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p (%t) [%c] - %m%n
-log4j.category.org.apache.usergrid.tools=TRACE, stdout
-
-log4j.logger.org.apache.usergrid.persistence.cassandra.DB=WARN, stdout
-log4j.logger.org.apache.usergrid.persistence.cassandra.BATCH=WARN, stdout
-log4j.logger.org.apache.usergrid.persistence.cassandra.EntityManagerFactoryImpl=WARN, stdout
-log4j.logger.org.apache.usergrid.persistence.cassandra.DaoUtils=WARN, stdout
-log4j.logger.org.apache.usergrid.persistence.cassandra.EntityManagerImpl=WARN, stdout
-log4j.logger.org.apache.usergrid.persistence.cassandra.ConnectionRefImpl=WARN, stdout
-log4j.logger.me.prettyprint.cassandra.hector.TimingLogger=WARN, stdout
-log4j.logger.org.apache.usergrid.rest.security.AllowAjaxFilter=WARN, stdout
-log4j.logger.me.prettyprint.hector.api.beans.AbstractComposite=ERROR, stdout
+log4j.logger.org.apache.usergrid.tools=DEBUG
+log4j.logger.org.apache.usergrid.management.cassandra=DEBUB
+
+log4j.logger.org.apache.usergrid.persistence.cassandra.DB=WARN
+log4j.logger.org.apache.usergrid.persistence.cassandra.BATCH=WARN
+log4j.logger.org.apache.usergrid.persistence.cassandra.EntityManagerFactoryImpl=WARN
+log4j.logger.org.apache.usergrid.persistence.cassandra.DaoUtils=WARN
+log4j.logger.org.apache.usergrid.persistence.cassandra.EntityManagerImpl=WARN
+log4j.logger.org.apache.usergrid.persistence.cassandra.ConnectionRefImpl=WARN
+log4j.logger.me.prettyprint.cassandra.hector.TimingLogger=WARN
+log4j.logger.org.apache.usergrid.rest.security.AllowAjaxFilter=WARN
+log4j.logger.me.prettyprint.hector.api.beans.AbstractComposite=ERROR
#log4j.logger.org.apache.usergrid.locking.singlenode.SingleNodeLockManagerImpl=DEBUG, stdout
-log4j.logger.org.apache.usergrid.persistence.hector.CountingMutator=INFO, stdout
+log4j.logger.org.apache.usergrid.persistence.hector.CountingMutator=INFO
#log4j.logger.org.apache.cassandra.service.StorageProxy=DEBUG, stdout
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c5187d22/stack/tools/src/test/java/org/apache/usergrid/tools/ExportImportAdminsTest.java
----------------------------------------------------------------------
diff --git a/stack/tools/src/test/java/org/apache/usergrid/tools/ExportImportAdminsTest.java b/stack/tools/src/test/java/org/apache/usergrid/tools/ExportImportAdminsTest.java
new file mode 100644
index 0000000..bab6150
--- /dev/null
+++ b/stack/tools/src/test/java/org/apache/usergrid/tools/ExportImportAdminsTest.java
@@ -0,0 +1,232 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.usergrid.tools;
+
+import com.google.common.collect.BiMap;
+import com.google.common.io.Files;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.usergrid.ServiceITSetup;
+import org.apache.usergrid.ServiceITSetupImpl;
+import org.apache.usergrid.ServiceITSuite;
+import org.apache.usergrid.management.OrganizationInfo;
+import org.apache.usergrid.management.OrganizationOwnerInfo;
+import org.apache.usergrid.management.UserInfo;
+import org.apache.usergrid.utils.UUIDUtils;
+import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.junit.ClassRule;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import static junit.framework.TestCase.assertNotNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+
+public class ExportImportAdminsTest {
+ static final Logger logger = LoggerFactory.getLogger( ExportImportAdminsTest.class );
+
+ @ClassRule
+ public static ServiceITSetup setup = new ServiceITSetupImpl( ServiceITSuite.cassandraResource );
+
+ @org.junit.Test
+ public void testExportUserAndOrg() throws Exception {
+
+ // create two orgs each with owning user
+
+ final String random1 = RandomStringUtils.randomAlphanumeric( 10 );
+ final OrganizationOwnerInfo orgOwnerInfo1 = setup.getMgmtSvc().createOwnerAndOrganization(
+ "org_" + random1, "user_" + random1, "user_" + random1,
+ "user_" + random1 + "@example.com", "password" );
+
+ final String random2 = RandomStringUtils.randomAlphanumeric( 10 );
+ final OrganizationOwnerInfo orgOwnerInfo2 = setup.getMgmtSvc().createOwnerAndOrganization(
+ "org_" + random2, "user_" + random2, "user_" + random2,
+ "user_" + random2 + "@example.com", "password" );
+
+ // Add user1 to org2
+
+ setup.getMgmtSvc().addAdminUserToOrganization(
+ orgOwnerInfo1.getOwner(), orgOwnerInfo2.getOrganization(), false );
+
+ setup.getMgmtSvc().addAdminUserToOrganization(
+ orgOwnerInfo1.getOwner(), orgOwnerInfo2.getOrganization(), false );
+
+ // export to file
+
+ String directoryName = "./target/export" + RandomStringUtils.randomAlphanumeric(10);
+
+ ExportAdmins exportAdmins = new ExportAdmins();
+ exportAdmins.startTool( new String[] {
+ "-host", "localhost:" + ServiceITSuite.cassandraResource.getRpcPort(),
+ "-outputDir", directoryName
+ }, false );
+
+ // read, parse and verify files
+
+ // first, the admin users file
+
+ File directory = new File( directoryName );
+ String[] adminUsersFileNames = directory.list( new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return name.startsWith("admin-users.");
+ }
+ });
+
+ // only one. read it into a map
+
+ File adminUsersFile = new File(
+ directory.getAbsolutePath() + File.separator + adminUsersFileNames[0] );
+
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode node = mapper.readTree( adminUsersFile );
+ assertTrue( node.isArray() );
+
+ // does file contain our two admin users?
+
+ Set<String> usernames = new HashSet<String>();
+ for ( int i=0; i<node.size(); i++) {
+ JsonNode jsonNode = node.get( i );
+ usernames.add( jsonNode.get("username").asText() );
+ }
+ assertTrue( usernames.contains( "user_" + random1 ));
+ assertTrue( usernames.contains( "user_" + random2 ));
+
+ // second, the metadata file
+
+ String[] metadataFileNames = directory.list( new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return name.startsWith("admin-user-metadata.");
+ }
+ });
+
+ // only one, read it into a map
+
+ File metadataFile = new File(
+ directory.getAbsolutePath() + File.separator + metadataFileNames[0] );
+
+ mapper = new ObjectMapper();
+ node = mapper.readTree( metadataFile );
+ assertTrue( node.isObject() );
+
+ // do users belong to correct orgs
+
+ JsonNode user1node = node.findValue( orgOwnerInfo1.getOwner().getUuid().toString() );
+ JsonNode orgs1 = user1node.findValue( "organizations");
+ assertEquals( 2, orgs1.size() );
+
+ JsonNode user2node = node.findValue( orgOwnerInfo2.getOwner().getUuid().toString() );
+ JsonNode orgs2 = user2node.findValue( "organizations");
+ assertEquals( 1, orgs2.size() );
+ }
+
+
+ @org.junit.Test
+ public void testImportAdminUsersAndOrgs() throws Exception {
+
+ // first: generate the data file with unique user and org IDs and names
+
+ String rand1 = RandomStringUtils.randomAlphanumeric( 10 );
+ String rand2 = RandomStringUtils.randomAlphanumeric( 10 );
+
+ UUID user_uuid_1 = UUIDUtils.newTimeUUID();
+ UUID user_uuid_2 = UUIDUtils.newTimeUUID();
+
+ UUID org_uuid_1 = UUIDUtils.newTimeUUID();
+ UUID org_uuid_2 = UUIDUtils.newTimeUUID();
+
+ String user_name_1 = "user_" + rand1;
+ String user_name_2 = "user_" + rand2;
+
+ String org_name_1 = "org_" + rand1;
+ String org_name_2 = "org_" + rand2;
+
+ // loop through resource files with prefix 'admin-user' those are the data file templates
+
+ File resourcesDir = new File("./target/test-classes");
+ String[] fileNames = resourcesDir.list();
+ File tempDir = Files.createTempDir();
+
+ for ( String fileName : fileNames ) {
+
+ if ( fileName.startsWith("admin-user")) {
+
+ // substitute our new unique IDs and names and write data files to temp directory
+
+ String fileContent = IOUtils.toString( new FileInputStream(
+ resourcesDir.getAbsolutePath() + File.separator + fileName ) );
+
+ fileContent = fileContent.replaceAll( "USER_UUID_1", user_uuid_1.toString() );
+ fileContent = fileContent.replaceAll( "USER_UUID_2", user_uuid_2.toString() );
+
+ fileContent = fileContent.replaceAll( "ORG_UUID_1", org_uuid_1.toString() );
+ fileContent = fileContent.replaceAll( "ORG_UUID_2", org_uuid_2.toString() );
+
+ fileContent = fileContent.replaceAll( "USER_NAME_1", user_name_1 );
+ fileContent = fileContent.replaceAll( "USER_NAME_2", user_name_2 );
+
+ fileContent = fileContent.replaceAll( "ORG_NAME_1", org_name_1 );
+ fileContent = fileContent.replaceAll( "ORG_NAME_2", org_name_2 );
+
+ FileOutputStream os = new FileOutputStream(
+ tempDir.getAbsolutePath() + File.separator + fileName );
+
+ IOUtils.write( fileContent, os );
+ os.close();
+ }
+ }
+
+ // import data from temp directory
+
+ ImportAdmins importAdmins = new ImportAdmins();
+ importAdmins.startTool( new String[] {
+ "-host", "localhost:" + ServiceITSuite.cassandraResource.getRpcPort(),
+ "-inputDir", tempDir.getAbsolutePath()
+ }, false );
+
+ // verify that users and orgs were created correctly
+
+ OrganizationInfo orgInfo1 = setup.getMgmtSvc().getOrganizationByUuid( org_uuid_1 );
+ assertNotNull( orgInfo1 );
+
+ OrganizationInfo orgInfo2 = setup.getMgmtSvc().getOrganizationByUuid( org_uuid_2 );
+ assertNotNull( orgInfo2 );
+
+ BiMap<UUID, String> user1_orgs = setup.getMgmtSvc().getOrganizationsForAdminUser( user_uuid_1 );
+ assertEquals("user1 has two orgs", 2, user1_orgs.size() );
+
+ BiMap<UUID, String> user2_orgs = setup.getMgmtSvc().getOrganizationsForAdminUser( user_uuid_2 );
+ assertEquals("user2 has one orgs", 1, user2_orgs.size() );
+
+ List<UserInfo> org1_users = setup.getMgmtSvc().getAdminUsersForOrganization( org_uuid_1 );
+ assertEquals("org1 has one user", 1, org1_users.size() );
+
+ List<UserInfo> org2_users = setup.getMgmtSvc().getAdminUsersForOrganization( org_uuid_2 );
+ assertEquals("org2 has two users", 2, org2_users.size() );
+ }
+
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c5187d22/stack/tools/src/test/resources/admin-user-metadata.usergrid-management.1433331614293.json
----------------------------------------------------------------------
diff --git a/stack/tools/src/test/resources/admin-user-metadata.usergrid-management.1433331614293.json b/stack/tools/src/test/resources/admin-user-metadata.usergrid-management.1433331614293.json
new file mode 100644
index 0000000..320f8ed
--- /dev/null
+++ b/stack/tools/src/test/resources/admin-user-metadata.usergrid-management.1433331614293.json
@@ -0,0 +1,85 @@
+{
+ "USER_UUID_1" : {
+ "activities" : [ ],
+ "devices" : [ ],
+ "feed" : [ "4c6275ba-09e5-11e5-bccc-97be717704cf" ],
+ "groups" : [ "4c5444ea-09e5-11e5-908d-61d76b477be4", "4c88c26a-09e5-11e5-8a66-594dd93a503d" ],
+ "roles" : [ ],
+ "connections" : { },
+ "organizations" : [ {
+ "uuid" : "ORG_UUID_1",
+ "name" : "ORG_NAME_1"
+ }, {
+ "uuid" : "ORG_UUID_2",
+ "name" : "ORG_NAME_2"
+ } ],
+ "dictionaries" : {
+ "credentials" : {
+ "mongo_pwd" : {
+ "recoverable" : true,
+ "encrypted" : false,
+ "secret" : "e045e38bbe5bf23334407ca9419ac94c",
+ "hashType" : null,
+ "created" : 1433331613575,
+ "cryptoChain" : [ "plaintext" ]
+ },
+ "password" : {
+ "recoverable" : false,
+ "encrypted" : true,
+ "secret" : "JDJhJDA5JEFpeC5IbHlpclo4ODFFVVNVTmN3Q3VEeGJ5emMyQlBwREN5WGZ6aHkydkVLdThJQlFzZExL",
+ "hashType" : null,
+ "created" : 1433331613505,
+ "cryptoChain" : [ "bcrypt" ]
+ },
+ "secret" : {
+ "recoverable" : true,
+ "encrypted" : false,
+ "secret" : "YWQ6bpC6YOMVf0s0dIQZ1CUdXIxDTY0",
+ "hashType" : null,
+ "created" : 1433331613575,
+ "cryptoChain" : [ "plaintext" ]
+ }
+ }
+ }
+ },
+ "USER_UUID_2" : {
+ "activities" : [ ],
+ "devices" : [ ],
+ "feed" : [ "4c8fee64-09e5-11e5-b3c6-57bd4e12c0b1" ],
+ "groups" : [ "4c88c26a-09e5-11e5-8a66-594dd93a503d" ],
+ "roles" : [ ],
+ "connections" : { },
+ "organizations" : [ {
+ "uuid" : "ORG_UUID_2",
+ "name" : "ORG_NAME_2"
+ } ],
+ "dictionaries" : {
+ "credentials" : {
+ "mongo_pwd" : {
+ "recoverable" : true,
+ "encrypted" : false,
+ "secret" : "e7b4fc7db5b97088997e44eced015d42",
+ "hashType" : null,
+ "created" : 1433331614067,
+ "cryptoChain" : [ "plaintext" ]
+ },
+ "password" : {
+ "recoverable" : false,
+ "encrypted" : true,
+ "secret" : "JDJhJDA5JER0RTdNSldMRjkxSUlJVm5hZWJMTy5DelFLemwvd2tXdUttaHViZWdyRjRURVdxYk5TUGJt",
+ "hashType" : null,
+ "created" : 1433331614018,
+ "cryptoChain" : [ "bcrypt" ]
+ },
+ "secret" : {
+ "recoverable" : true,
+ "encrypted" : false,
+ "secret" : "YWQ6Rx9A-m5U-TihpkPVS4PmyQO4qig",
+ "hashType" : null,
+ "created" : 1433331614067,
+ "cryptoChain" : [ "plaintext" ]
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c5187d22/stack/tools/src/test/resources/admin-users.usergrid-management.1433331614293.json
----------------------------------------------------------------------
diff --git a/stack/tools/src/test/resources/admin-users.usergrid-management.1433331614293.json b/stack/tools/src/test/resources/admin-users.usergrid-management.1433331614293.json
new file mode 100644
index 0000000..5f192bf
--- /dev/null
+++ b/stack/tools/src/test/resources/admin-users.usergrid-management.1433331614293.json
@@ -0,0 +1,23 @@
+[ {
+ "uuid" : "USER_UUID_1",
+ "type" : "user",
+ "name" : "USER_NAME_1",
+ "created" : 1433331613479,
+ "modified" : 1433331613479,
+ "username" : "USER_NAME_1",
+ "email" : "USER_NAME_1@example.com",
+ "activated" : true,
+ "confirmed" : true,
+ "disabled" : false
+}, {
+ "uuid" : "USER_UUID_2",
+ "type" : "user",
+ "name" : "USER_NAME_2",
+ "created" : 1433331614002,
+ "modified" : 1433331614002,
+ "username" : "USER_NAME_2",
+ "email" : "USER_NAME_2@example.com",
+ "activated" : true,
+ "confirmed" : true,
+ "disabled" : false
+} ]
\ No newline at end of file