Merge branch 'master' into two-dot-o Conflicts: stack/config/src/main/resources/usergrid-default.properties stack/core/src/main/java/org/apache/usergrid/metrics/MetricsFactory.java stack/core/src/main/java/org/apache/usergrid/persistence/cassandra/CassandraService.java stack/pom.xml stack/rest/pom.xml stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/OrganizationsResource.java stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UserResource.java stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UsersResource.java stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/OAuth2AccessTokenSecurityFilter.java stack/rest/src/test/java/org/apache/usergrid/rest/applications/assets/AssetResourceIT.java stack/rest/src/test/java/org/apache/usergrid/rest/management/ManagementResourceIT.java stack/rest/src/test/java/org/apache/usergrid/rest/management/users/MUUserResourceIT.java stack/services/src/main/java/org/apache/usergrid/services/assets/data/S3BinaryStore.java
Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/a7840164 Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/a7840164 Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/a7840164 Branch: refs/heads/USERGRID-628 Commit: a78401642d0de2981c497a7c69f20447b4d1c79a Parents: cb44722 49ae4ac Author: Dave Johnson <dmjohn...@apigee.com> Authored: Wed May 27 15:34:11 2015 -0400 Committer: Dave Johnson <dmjohn...@apigee.com> Committed: Wed May 27 15:34:11 2015 -0400 ---------------------------------------------------------------------- README.md | 2 +- docs/file-storage-configuration.md | 39 ++ docs/get_2.0_running_locally.md | 165 ++++++ docs/index.md | 3 +- .../main/resources/usergrid-default.properties | 24 +- .../persistence/cassandra/CassandraService.java | 79 +-- .../org/apache/usergrid/utils/JsonUtils.java | 2 +- stack/pom.xml | 26 +- .../rest/applications/ServiceResource.java | 2 +- .../rest/management/ManagementResource.java | 442 +++++++++++++-- .../organizations/OrganizationsResource.java | 34 +- .../rest/management/users/UserResource.java | 42 ++ .../rest/management/users/UsersResource.java | 45 +- .../OAuth2AccessTokenSecurityFilter.java | 6 +- .../applications/assets/AssetResourceIT.java | 302 +++++++--- .../rest/applications/utils/UserRepo.java | 36 +- .../rest/management/ManagementResourceIT.java | 553 +++++++++++++++++-- .../rest/test/PropertiesResourceIT.java | 23 +- .../test/resource2point0/AbstractRestIT.java | 2 - .../rest/test/resource2point0/ClientSetup.java | 16 +- .../src/test/resources/cat-larger-than-6mb.jpg | Bin 0 -> 9799257 bytes stack/services/pom.xml | 11 + .../usergrid/management/ManagementService.java | 5 +- .../cassandra/ManagementServiceImpl.java | 7 + .../apache/usergrid/security/shiro/Realm.java | 10 +- .../usergrid/security/tokens/TokenService.java | 3 + .../tokens/cassandra/TokenServiceImpl.java | 44 +- .../assets/data/AwsSdkS3BinaryStore.java | 230 ++++++++ .../services/assets/data/S3BinaryStore.java | 255 ++++++--- .../security/tokens/TokenServiceIT.java | 42 ++ ugc/README.md | 2 +- 31 files changed, 2029 insertions(+), 423 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/README.md ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/config/src/main/resources/usergrid-default.properties ---------------------------------------------------------------------- diff --cc stack/config/src/main/resources/usergrid-default.properties index 53b6445,0a4f218..e5e269e --- a/stack/config/src/main/resources/usergrid-default.properties +++ b/stack/config/src/main/resources/usergrid-default.properties @@@ -78,8 -34,16 +78,12 @@@ cassandra.url=localhost:916 # Name of Cassandra cluster cassandra.cluster=Test Cluster + # Keyspace names to be used (see also the locks keyspace below) + cassandra.system.keyspace=Usergrid + cassandra.application.keyspace=Usergrid_Applications + cassandra.keyspace.strategy=org.apache.cassandra.locator.SimpleStrategy #cassandra.keyspace.strategy=org.apache.cassandra.locator.NetworkTopologyStrategy - #cassandra.keyspace.strategy.options.replication_factor=1 #cassandra.keyspace.strategy.options.us-east=1 @@@ -88,37 -52,21 +92,37 @@@ cassandra.keyspace.replication=replicat cassandra.username= cassandra.password= - #Read consistency level for the cassandra cluster + # Read consistency level for the cassandra cluster cassandra.readcl=QUORUM - #Write consistency level for the cassandra cluster + # Write consistency level for the cassandra cluster cassandra.writecl=QUORUM - #The maximum number of pending mutations allowed in ram before it is flushed to cassandra + # The maximum number of pending mutations allowed in ram before it is flushed to cassandra cassandra.mutation.flushsize=2000 -# Keyspace to use for locking - Used by Hector lock manager: -# Note that if this is deployed in a production cluster, the RF on the keyspace MUST -# be updated to use an odd number for it's replication Factor. Even numbers for RF can -# potentially case the locks to fail, via "split brain" when read at QUORUM on lock verification +# Keyspace to use for locking +# Note that if this is deployed in a production cluster, the RF on the keyspace +# MUST be updated to use an odd number for it's replication Factor. Even numbers +# for RF can potentially case the locks to fail, via "split brain" when read at +# QUORUM on lock verification cassandra.lock.keyspace=Locks +# locking read & write policies +cassandra.lock.readcl=LOCAL_QUORUM +cassandra.lock.writecl=LOCAL_QUORUM + +# Timeout in ms before hector considers a thrift socket dead +cassandra.thriftSocketTimeout=0 +# If hector should use host TCP keep alive settings +cassandra.useSocketKeepalive=false + + + +############################################################################### +# +# General properties + # false to disable test features usergrid.test=false @@@ -132,31 -79,14 +136,32 @@@ usergrid.version.properties=1.0. # build number for display usergrid.version.build=${version} -usergird.service.packages=com.usergrid.services;org.apache.usergrid.services;baas.io +usergird.service.packages=org.apache.usergrid.services -#Batch submit counters ever 1000 updates +# Batch submit counters ever 1000 updates usergrid.counter.batch.size=1000 -#Submit batcher every 30 seconds +# Submit batcher every 30 seconds usergrid.counter.batch.interval=30 +AWS_ACCESS_KEY_ID= +AWS_SECRET_KEY= +usergrid.binary.bucketname=usergrid-test - +usergrid.test.sample_data_url= ++usergrid.binary.max-size-mb=50 ++usergrid.binary.upload-workers=40 + +# Disable Mongo API Server +usergrid.mongo.disable=true + +# Disable WebSocket Server +usergrid.websocket.disable=true + + +############################################################################### +# +# Authentication properties + #usergrid.auth.token_secret_salt=super secret token value #usergrid.auth.token_expires_from_last_use=false #usergrid.auth.token_refresh_reuses_id=false http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/core/src/main/java/org/apache/usergrid/persistence/cassandra/CassandraService.java ---------------------------------------------------------------------- diff --cc stack/core/src/main/java/org/apache/usergrid/persistence/cassandra/CassandraService.java index 96d3fd9,43bfd2d..fb71b69 --- a/stack/core/src/main/java/org/apache/usergrid/persistence/cassandra/CassandraService.java +++ b/stack/core/src/main/java/org/apache/usergrid/persistence/cassandra/CassandraService.java @@@ -17,69 -17,69 +17,35 @@@ package org.apache.usergrid.persistence.cassandra; --import java.nio.ByteBuffer; --import java.util.ArrayList; --import java.util.Collection; --import java.util.HashMap; --import java.util.LinkedHashMap; --import java.util.LinkedHashSet; --import java.util.List; --import java.util.Map; --import java.util.Properties; --import java.util.Set; --import java.util.UUID; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -- --import org.slf4j.Logger; --import org.slf4j.LoggerFactory; --import org.apache.usergrid.locking.LockManager; --import org.apache.usergrid.persistence.IndexBucketLocator; --import org.apache.usergrid.persistence.IndexBucketLocator.IndexType; --import org.apache.usergrid.persistence.cassandra.index.IndexBucketScanner; --import org.apache.usergrid.persistence.cassandra.index.IndexScanner; - import org.apache.usergrid.persistence.core.astyanax.CassandraFig; --import org.apache.usergrid.persistence.hector.CountingMutator; - import org.apache.usergrid.utils.MapUtils; -- +import com.google.inject.Injector; - import me.prettyprint.cassandra.connection.HConnectionManager; import me.prettyprint.cassandra.model.ConfigurableConsistencyLevel; --import me.prettyprint.cassandra.serializers.ByteBufferSerializer; --import me.prettyprint.cassandra.serializers.BytesArraySerializer; --import me.prettyprint.cassandra.serializers.DynamicCompositeSerializer; --import me.prettyprint.cassandra.serializers.LongSerializer; --import me.prettyprint.cassandra.serializers.StringSerializer; --import me.prettyprint.cassandra.serializers.UUIDSerializer; ++import me.prettyprint.cassandra.serializers.*; import me.prettyprint.cassandra.service.CassandraHostConfigurator; import me.prettyprint.cassandra.service.ThriftKsDef; --import me.prettyprint.hector.api.Cluster; --import me.prettyprint.hector.api.ConsistencyLevelPolicy; --import me.prettyprint.hector.api.HConsistencyLevel; --import me.prettyprint.hector.api.Keyspace; --import me.prettyprint.hector.api.Serializer; --import me.prettyprint.hector.api.beans.ColumnSlice; --import me.prettyprint.hector.api.beans.DynamicComposite; --import me.prettyprint.hector.api.beans.HColumn; --import me.prettyprint.hector.api.beans.OrderedRows; --import me.prettyprint.hector.api.beans.Row; --import me.prettyprint.hector.api.beans.Rows; ++import me.prettyprint.hector.api.*; ++import me.prettyprint.hector.api.beans.*; import me.prettyprint.hector.api.ddl.ColumnFamilyDefinition; import me.prettyprint.hector.api.ddl.KeyspaceDefinition; import me.prettyprint.hector.api.factory.HFactory; import me.prettyprint.hector.api.mutation.Mutator; --import me.prettyprint.hector.api.query.ColumnQuery; -import me.prettyprint.hector.api.query.CountQuery; --import me.prettyprint.hector.api.query.MultigetSliceQuery; --import me.prettyprint.hector.api.query.QueryResult; --import me.prettyprint.hector.api.query.RangeSlicesQuery; --import me.prettyprint.hector.api.query.SliceQuery; ++import me.prettyprint.hector.api.query.*; ++import org.apache.usergrid.locking.LockManager; ++import org.apache.usergrid.persistence.IndexBucketLocator; ++import org.apache.usergrid.persistence.IndexBucketLocator.IndexType; ++import org.apache.usergrid.persistence.cassandra.index.IndexBucketScanner; ++import org.apache.usergrid.persistence.cassandra.index.IndexScanner; ++import org.apache.usergrid.persistence.core.astyanax.CassandraFig; ++import org.apache.usergrid.persistence.hector.CountingMutator; ++import org.apache.usergrid.utils.MapUtils; ++import org.slf4j.Logger; ++import org.slf4j.LoggerFactory; --import static me.prettyprint.cassandra.service.FailoverPolicy.ON_FAIL_TRY_ALL_AVAILABLE; --import static me.prettyprint.hector.api.factory.HFactory.createColumn; --import static me.prettyprint.hector.api.factory.HFactory.createMultigetSliceQuery; ++import java.nio.ByteBuffer; ++import java.util.*; --import static me.prettyprint.hector.api.factory.HFactory.createRangeSlicesQuery; --import static me.prettyprint.hector.api.factory.HFactory.createSliceQuery; --import static me.prettyprint.hector.api.factory.HFactory.createVirtualKeyspace; ++import static me.prettyprint.cassandra.service.FailoverPolicy.ON_FAIL_TRY_ALL_AVAILABLE; ++import static me.prettyprint.hector.api.factory.HFactory.*; import static org.apache.commons.collections.MapUtils.getIntValue; import static org.apache.commons.collections.MapUtils.getString; import static org.apache.usergrid.persistence.cassandra.ApplicationCF.ENTITY_ID_SETS; @@@ -93,11 -94,8 +59,13 @@@ import static org.apache.usergrid.utils public class CassandraService { + //make the below two not static + // public static String SYSTEM_KEYSPACE = "Usergrid"; + + public static String applicationKeyspace; + + public static final boolean USE_VIRTUAL_KEYSPACES = true; + public static final String APPLICATIONS_CF = "Applications"; public static final String PROPERTIES_CF = "Properties"; public static final String TOKENS_CF = "Tokens"; http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/core/src/main/java/org/apache/usergrid/utils/JsonUtils.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/pom.xml ---------------------------------------------------------------------- diff --cc stack/pom.xml index c458acb,5c3d4fe..cc61a7c --- a/stack/pom.xml +++ b/stack/pom.xml @@@ -177,52 -154,21 +177,35 @@@ <id>tonuquq</id> <name>Alex Karasulu</name> </developer> + <developer> + <id>snoopdave</id> + <name>Dave Johnson</name> + </developer> </developers> - - <distributionManagement> - <!-- Versioned (non-snapshot) releases are published to this repository --> - <repository> - <id>usergrid.releases</id> - <name>Usergrid Releases</name> - <url>${release.repository.url}</url> - </repository> - - <!-- Snapshots (not-releases) are published to this repository --> - <snapshotRepository> - <id>usergrid.snapshots</id> - <name>Usergrid Snapshots</name> - <url>${snapshot.repository.url}</url> - </snapshotRepository> - </distributionManagement> - <modules> - <module>java-sdk-old</module> + <module>build-tools</module> + <module>test-utils</module> <module>config</module> + <module>corepersistence</module> <module>core</module> <module>services</module> + <module>rest</module> + <!-- <module>tools</module> - <module>mongo-emulator</module> <module>websocket</module> - <module>rest</module> + --> + <!-- + Re-enable when we have a fix for the AppleJavaExtensions jar issue + https://issues.apache.org/jira/browse/USERGRID-224 <module>launcher</module> - <module>test-utils</module> - <!--<module>query-validator</module>--> - <module>build-tools</module> + --> + <module>mongo-emulator</module> + <!-- + Re-enable when query-validator updated to work with Core Persistence. + https://issues.apache.org/jira/browse/USERGRID-221 + <module>query-validator</module> + --> </modules> <dependencyManagement> @@@ -295,8 -241,15 +278,15 @@@ </exclusion> </exclusions> </dependency> - + <dependency> + <groupId>com.amazonaws</groupId> + <artifactId>aws-java-sdk-s3</artifactId> + <version>1.9.31</version> + </dependency> + + + <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-spring</artifactId> <version>5.5.0</version> http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ServiceResource.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java ---------------------------------------------------------------------- diff --cc stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java index a5ff3e3,46d6d6b..acbd84f --- a/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java @@@ -17,39 -17,39 +17,36 @@@ package org.apache.usergrid.rest.management; - import java.net.URLEncoder; - import java.util.Map; - - import javax.ws.rs.Consumes; - import javax.ws.rs.DefaultValue; - import javax.ws.rs.FormParam; - import javax.ws.rs.GET; - import javax.ws.rs.HeaderParam; - import javax.ws.rs.POST; - import javax.ws.rs.Path; - import javax.ws.rs.Produces; - import javax.ws.rs.QueryParam; - import javax.ws.rs.core.Context; - import javax.ws.rs.core.MediaType; - import javax.ws.rs.core.Response; - import javax.ws.rs.core.UriInfo; - - import org.slf4j.Logger; - import org.slf4j.LoggerFactory; - import org.springframework.context.annotation.Scope; - import org.springframework.stereotype.Component; - + import com.codahale.metrics.Counter; + import com.codahale.metrics.Timer; ++import com.google.inject.Injector; + import com.sun.jersey.api.client.Client; + import com.sun.jersey.api.client.config.ClientConfig; + import com.sun.jersey.api.client.config.DefaultClientConfig; + import com.sun.jersey.api.json.JSONConfiguration; + import com.sun.jersey.api.view.Viewable; + import com.sun.jersey.client.apache.ApacheHttpClient; + import com.sun.jersey.client.apache.ApacheHttpClientHandler; import org.apache.amber.oauth2.common.error.OAuthError; import org.apache.amber.oauth2.common.exception.OAuthProblemException; import org.apache.amber.oauth2.common.message.OAuthResponse; import org.apache.amber.oauth2.common.message.types.GrantType; + import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.HttpConnectionManager; + import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; -import org.apache.commons.httpclient.params.HttpClientParams; + import org.apache.commons.httpclient.params.HttpConnectionManagerParams; -import org.apache.commons.httpclient.params.HttpMethodParams; + import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.StringUtils; -import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.shiro.codec.Base64; - + import org.apache.usergrid.exception.NotImplementedException; + import org.apache.usergrid.management.ApplicationCreator; + import org.apache.usergrid.management.OrganizationInfo; + import org.apache.usergrid.management.OrganizationOwnerInfo; import org.apache.usergrid.management.UserInfo; import org.apache.usergrid.management.exceptions.DisabledAdminUserException; import org.apache.usergrid.management.exceptions.UnactivatedAdminUserException; import org.apache.usergrid.management.exceptions.UnconfirmedAdminUserException; -import org.apache.usergrid.metrics.MetricsFactory; ++import org.apache.usergrid.persistence.core.metrics.MetricsFactory; + import org.apache.usergrid.persistence.exceptions.EntityNotFoundException; import org.apache.usergrid.rest.AbstractContextResource; import org.apache.usergrid.rest.exceptions.RedirectionException; import org.apache.usergrid.rest.management.organizations.OrganizationsResource; @@@ -90,17 -104,36 +101,48 @@@ public class ManagementResource extend * * /management/users/<user-name>/login * /management/users/<user-name>/password -- * ++ * */ - private static final Logger logger = LoggerFactory.getLogger( ManagementResource.class ); + @Autowired + private ApplicationCreator applicationCreator; + + @Autowired - MetricsFactory metricsFactory; ++ Injector injector; ++ + + private static Client jerseyClient = null; + + + // names for metrics to be collected + private static final String SSO_TOKENS_REJECTED = "sso_tokens_rejected"; + private static final String SSO_TOKENS_VALIDATED = "sso_tokens_validated"; + private static final String SSO_CREATED_LOCAL_ADMINS = "sso_created_local_admins"; + private static final String SSO_PROCESSING_TIME = "sso_processing_time"; + + // usergrid configuration property names needed + public static final String USERGRID_SYSADMIN_LOGIN_NAME = "usergrid.sysadmin.login.name"; + public static final String USERGRID_CENTRAL_URL = "usergrid.central.url"; + public static final String CENTRAL_CONNECTION_POOL_SIZE = "usergrid.central.connection.pool.size"; + public static final String CENTRAL_CONNECTION_TIMEOUT = "usergrid.central.connection.timeout"; + public static final String CENTRAL_READ_TIMEOUT = "usergrid.central.read.timeout"; + ++ MetricsFactory metricsFactory = null; + + public ManagementResource() { logger.info( "ManagementResource initialized" ); } ++ MetricsFactory getMetricsFactory() { ++ if ( metricsFactory == null ) { ++ metricsFactory = injector.getInstance( MetricsFactory.class ); ++ } ++ return metricsFactory; ++ } ++ ++ private static String wrapWithCallback( AccessInfo accessInfo, String callback ) { return wrapWithCallback( mapToJsonString( accessInfo ), callback ); } @@@ -446,6 -484,308 +498,308 @@@ } + /** + * <p> + * Allows call to validateExternalToken() (see below) with a POST of a JSON object. + * </p> + * + * @param ui Information about calling URI. + * @param json JSON object with fields: ext_access_token, ttl + * @param callback For JSONP support. + * @return Returns JSON object with access_token field. + * @throws Exception Returns 401 if access token cannot be validated + */ + @POST + @Path( "/externaltoken" ) + public Response validateExternalToken( + @Context UriInfo ui, + Map<String, Object> json, + @QueryParam( "callback" ) @DefaultValue( "" ) String callback ) throws Exception { + + if ( StringUtils.isEmpty( properties.getProperty( USERGRID_CENTRAL_URL ))) { + throw new NotImplementedException( "External Token Validation Service is not configured" ); + } + + Object extAccessTokenObj = json.get( "ext_access_token" ); + if ( extAccessTokenObj == null ) { + throw new IllegalArgumentException("ext_access_token must be specified"); + } + String extAccessToken = json.get("ext_access_token").toString(); + + Object ttlObj = json.get( "ttl" ); + if ( ttlObj == null ) { + throw new IllegalArgumentException("ttl must be specified"); + } + long ttl; + try { + ttl = Long.parseLong(ttlObj.toString()); + } catch ( NumberFormatException e ) { + throw new IllegalArgumentException("ttl must be specified as a long"); + } + + return validateExternalToken( ui, extAccessToken, ttl, callback ); + } + + + /** + * <p> + * Validates access token from other or "external" Usergrid system. + * Calls other system's /management/me endpoint to get the User + * associated with the access token. If user does not exist locally, + * then user and organizations will be created. If no user is returned + * from the other cluster, then this endpoint will return 401. + * </p> + * + * <p> Part of Usergrid Central SSO feature. + * See <a href="https://issues.apache.org/jira/browse/USERGRID-567">USERGRID-567</a> + * for details about Usergrid Central SSO. + * </p> + * + * @param ui Information about calling URI. + * @param extAccessToken Access token from external Usergrid system. + * @param ttl Time to live for token. + * @param callback For JSONP support. + * @return Returns JSON object with access_token field. + * @throws Exception Returns 401 if access token cannot be validated + */ + @GET + @Path( "/externaltoken" ) + public Response validateExternalToken( + @Context UriInfo ui, + @QueryParam( "ext_access_token" ) String extAccessToken, + @QueryParam( "ttl" ) @DefaultValue("-1") long ttl, + @QueryParam( "callback" ) @DefaultValue( "" ) String callback ) + throws Exception { + + + if ( StringUtils.isEmpty( properties.getProperty( USERGRID_CENTRAL_URL ))) { + throw new NotImplementedException( "External Token Validation Service is not configured" ); + } + + if ( extAccessToken == null ) { + throw new IllegalArgumentException("ext_access_token must be specified"); + } + + if ( ttl == -1 ) { + throw new IllegalArgumentException("ttl must be specified"); + } + AccessInfo accessInfo = null; + - Timer processingTimer = metricsFactory.getTimer( - ManagementResource.class, SSO_PROCESSING_TIME ); ++ Timer processingTimer = getMetricsFactory().getTimer( ++ ManagementResource.class, SSO_PROCESSING_TIME ); + + Timer.Context timerContext = processingTimer.time(); + + try { + // look up user via UG Central's /management/me endpoint. + + JsonNode accessInfoNode = getMeFromUgCentral( extAccessToken ); + + JsonNode userNode = accessInfoNode.get( "user" ); + String username = userNode.get( "username" ).getTextValue(); + + // if user does not exist locally then we need to fix that + + UserInfo userInfo = management.getAdminUserByUsername( username ); + UUID userId = userInfo == null ? null : userInfo.getUuid(); + + if ( userId == null ) { + + // create local user and and organizations they have on the central Usergrid instance + logger.info("User {} does not exist locally, creating", username ); + + String name = userNode.get( "name" ).getTextValue(); + String email = userNode.get( "email" ).getTextValue(); + String dummyPassword = RandomStringUtils.randomAlphanumeric( 40 ); + + JsonNode orgsNode = userNode.get( "organizations" ); + Iterator<String> fieldNames = orgsNode.getFieldNames(); + + if ( !fieldNames.hasNext() ) { + // no organizations for user exist in response from central Usergrid SSO + // so create user's personal organization and use username as organization name + fieldNames = Collections.singletonList( username ).iterator(); + } + + // create user and any organizations that user is supposed to have + + while ( fieldNames.hasNext() ) { + + String orgName = fieldNames.next(); + + if ( userId == null ) { + + // haven't created user yet so do that now + OrganizationOwnerInfo ownerOrgInfo = management.createOwnerAndOrganization( + orgName, username, name, email, dummyPassword, true, false ); + + applicationCreator.createSampleFor( ownerOrgInfo.getOrganization() ); + + userId = ownerOrgInfo.getOwner().getUuid(); + userInfo = ownerOrgInfo.getOwner(); + - Counter createdAdminsCounter = metricsFactory.getCounter( - ManagementResource.class, SSO_CREATED_LOCAL_ADMINS ); ++ Counter createdAdminsCounter = getMetricsFactory().getCounter( ++ ManagementResource.class, SSO_CREATED_LOCAL_ADMINS ); + createdAdminsCounter.inc(); + + logger.info( "Created user {} and org {}", username, orgName ); + + } else { + + // already created user, so just create an org + final OrganizationInfo organization = management.createOrganization( orgName, userInfo, true ); + + applicationCreator.createSampleFor( organization ); + + logger.info( "Created user {}'s other org {}", username, orgName ); + } + } + + } + + // store the external access_token as if it were one of our own + management.importTokenForAdminUser( userId, extAccessToken, ttl ); + + // success! return JSON object with access_token field + accessInfo = new AccessInfo() + .withExpiresIn( tokens.getMaxTokenAgeInSeconds( extAccessToken ) ) + .withAccessToken( extAccessToken ); + + } catch (Exception e) { + timerContext.stop(); + logger.debug("Error validating external token", e); + throw e; + } + + final Response response = Response.status( SC_OK ).type( jsonMediaType( callback ) ).entity( accessInfo ).build(); + + timerContext.stop(); + + return response; + } + + /** + * Look up Admin User via UG Central's /management/me endpoint. + * + * @param extAccessToken Access token issued by UG Central of Admin User + * @return JsonNode representation of AccessInfo object for Admin User + * @throws EntityNotFoundException if access_token is not valid. + */ + private JsonNode getMeFromUgCentral( String extAccessToken ) throws EntityNotFoundException { + + // prepare to count tokens validated and rejected + - Counter tokensRejectedCounter = metricsFactory.getCounter( - ManagementResource.class, SSO_TOKENS_REJECTED ); - Counter tokensValidatedCounter = metricsFactory.getCounter( ++ Counter tokensRejectedCounter = getMetricsFactory().getCounter( ++ ManagementResource.class, SSO_TOKENS_REJECTED ); ++ Counter tokensValidatedCounter = getMetricsFactory().getCounter( + ManagementResource.class, SSO_TOKENS_VALIDATED ); + + // create URL of central Usergrid's /management/me endpoint + + String externalUrl = properties.getProperty( USERGRID_CENTRAL_URL ).trim(); + + // be lenient about trailing slash + externalUrl = !externalUrl.endsWith( "/" ) ? externalUrl + "/" : externalUrl; + String me = externalUrl + "management/me?access_token=" + extAccessToken; + + // use our favorite HTTP client to GET /management/me + + Client client = getJerseyClient(); + final JsonNode accessInfoNode; + try { + accessInfoNode = client.resource( me ) + .type( MediaType.APPLICATION_JSON_TYPE) + .get(JsonNode.class); + + tokensValidatedCounter.inc(); + + } catch ( Exception e ) { + // user not found 404 + tokensRejectedCounter.inc(); + String msg = "Cannot find Admin User associated with " + extAccessToken; + throw new EntityNotFoundException( msg, e ); + } + + return accessInfoNode; + } + + + private Client getJerseyClient() { + + if ( jerseyClient == null ) { + + synchronized ( this ) { + + // create HTTPClient and with configured connection pool + + int poolSize = 100; // connections + final String poolSizeStr = properties.getProperty( CENTRAL_CONNECTION_POOL_SIZE ); + if ( poolSizeStr != null ) { + poolSize = Integer.parseInt( poolSizeStr ); + } + + MultiThreadedHttpConnectionManager cm = new MultiThreadedHttpConnectionManager(); + HttpConnectionManagerParams cmParams = cm.getParams(); + cmParams.setMaxTotalConnections( poolSize ); + HttpClient httpClient = new HttpClient( cm ); + + // create Jersey Client using that HTTPClient and with configured timeouts + + int timeout = 20000; // ms + final String timeoutStr = properties.getProperty( CENTRAL_CONNECTION_TIMEOUT ); + if ( timeoutStr != null ) { + timeout = Integer.parseInt( timeoutStr ); + } + + int readTimeout = 20000; // ms + final String readTimeoutStr = properties.getProperty( CENTRAL_READ_TIMEOUT ); + if ( readTimeoutStr != null ) { + readTimeout = Integer.parseInt( readTimeoutStr ); + } + + ClientConfig clientConfig = new DefaultClientConfig(); + clientConfig.getFeatures().put( JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE ); + clientConfig.getProperties().put( ClientConfig.PROPERTY_CONNECT_TIMEOUT, timeout ); // ms + clientConfig.getProperties().put( ClientConfig.PROPERTY_READ_TIMEOUT, readTimeout ); // ms + + ApacheHttpClientHandler handler = new ApacheHttpClientHandler( httpClient, clientConfig ); + jerseyClient = new ApacheHttpClient( handler ); + + } + } + + return jerseyClient; + } + + + /** + * Check that authentication is allowed. If external token validation is enabled (Central Usergrid SSO) + * then only superusers should be allowed to login directly to this Usergrid instance. + */ + private void ensureAuthenticationAllowed( String username, String grant_type ) { + + if ( username == null || grant_type == null || !grant_type.equalsIgnoreCase( "password" )) { + return; // we only care about username/password auth + } + + final boolean externalTokensEnabled = + !StringUtils.isEmpty( properties.getProperty( USERGRID_CENTRAL_URL ) ); + + if ( externalTokensEnabled ) { + + // when external tokens enabled then only superuser can obtain an access token + + final String superuserName = properties.getProperty( USERGRID_SYSADMIN_LOGIN_NAME ); + if ( !username.equalsIgnoreCase( superuserName )) { + + // this guy is not the superuser + throw new IllegalArgumentException( "Admin Users must login via " + + properties.getProperty( USERGRID_CENTRAL_URL ) ); + } + } + } + + String errorMsg = ""; String responseType; String clientId; http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/OrganizationsResource.java ---------------------------------------------------------------------- diff --cc stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/OrganizationsResource.java index e6f3de2,e4e9eda..6f3edc2 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/OrganizationsResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/OrganizationsResource.java @@@ -151,12 -147,20 +152,23 @@@ public class OrganizationsResource exte /** Create a new organization */ private JSONWithPadding newOrganization( @Context UriInfo ui, String organizationName, String username, String name, String email, String password, Map<String, Object> userProperties, - Map<String, Object> properties, String callback ) throws Exception { + Map<String, Object> orgProperties, String callback ) throws Exception { - Preconditions.checkArgument( + final boolean externalTokensEnabled = + !StringUtils.isEmpty( properties.getProperty( ManagementResource.USERGRID_CENTRAL_URL ) ); + + if ( externalTokensEnabled ) { + throw new IllegalArgumentException( "Organization / Admin Users must be created via " + + properties.getProperty( ManagementResource.USERGRID_CENTRAL_URL ) ); + } + + Preconditions + .checkArgument( StringUtils.isNotBlank( organizationName ), "The organization parameter was missing" ); + - logger.info( "New organization: {}", organizationName ); ++ Preconditions.checkArgument( + StringUtils.isNotBlank( organizationName ), "The organization parameter was missing" ); + + logger.debug( "New organization: {}", organizationName ); ApiResponse response = createApiResponse(); response.setAction( "new organization" ); @@@ -181,18 -185,18 +193,18 @@@ /* * @POST -- * ++ * * @Consumes(MediaType.MULTIPART_FORM_DATA) public JSONWithPadding * newOrganizationFromMultipart(@Context UriInfo ui, -- * ++ * * @FormDataParam("organization") String organization, -- * ++ * * @FormDataParam("username") String username, -- * ++ * * @FormDataParam("name") String name, -- * ++ * * @FormDataParam("email") String email, -- * ++ * * @FormDataParam("password") String password) throws Exception { return * newOrganizationFromForm(ui, organization, username, name, email, * password); } http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UserResource.java ---------------------------------------------------------------------- diff --cc stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UserResource.java index 7c7dc72,3c755f8..7ea4eec --- a/stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UserResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UserResource.java @@@ -234,8 -244,14 +244,16 @@@ public class UserResource extends Abstr @FormParam( "recaptcha_challenge_field" ) String challenge, @FormParam( "recaptcha_response_field" ) String uresponse ) { + logger.debug("handlePasswordResetForm"); + + final boolean externalTokensEnabled = + !StringUtils.isEmpty( properties.getProperty( ManagementResource.USERGRID_CENTRAL_URL ) ); + + if ( externalTokensEnabled ) { + throw new IllegalArgumentException( "Admin Users must reset passwords via " + + properties.getProperty( ManagementResource.USERGRID_CENTRAL_URL ) ); + } + try { this.token = token; http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UsersResource.java ---------------------------------------------------------------------- diff --cc stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UsersResource.java index 2d5b7a9,d907632..7165d08 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UsersResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/management/users/UsersResource.java @@@ -17,39 -17,47 +17,36 @@@ package org.apache.usergrid.rest.management.users; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.UUID; - -import javax.ws.rs.Consumes; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.FormParam; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.UriInfo; - +import com.sun.jersey.api.json.JSONWithPadding; +import com.sun.jersey.api.view.Viewable; - import java.util.LinkedHashMap; - import java.util.Map; - import java.util.UUID; - import javax.ws.rs.Consumes; - import javax.ws.rs.DefaultValue; - import javax.ws.rs.FormParam; - import javax.ws.rs.GET; - import javax.ws.rs.POST; - import javax.ws.rs.Path; - import javax.ws.rs.PathParam; - import javax.ws.rs.Produces; - import javax.ws.rs.QueryParam; - import javax.ws.rs.core.Context; - import javax.ws.rs.core.MediaType; - import javax.ws.rs.core.UriInfo; +import net.tanesha.recaptcha.ReCaptchaImpl; +import net.tanesha.recaptcha.ReCaptchaResponse; - import static org.apache.commons.lang.StringUtils.isBlank; + import org.apache.commons.lang.StringUtils; -import org.apache.usergrid.management.exceptions.ManagementException; -import org.apache.usergrid.rest.RootResource; -import org.apache.usergrid.rest.management.ManagementResource; -import org.apache.usergrid.services.exceptions.ServiceResourceNotFoundException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.stereotype.Component; import org.apache.usergrid.management.UserInfo; +import org.apache.usergrid.management.exceptions.ManagementException; ++ import org.apache.usergrid.rest.AbstractContextResource; import org.apache.usergrid.rest.ApiResponse; +import org.apache.usergrid.rest.RootResource; import org.apache.usergrid.rest.exceptions.AuthErrorInfo; import org.apache.usergrid.rest.exceptions.RedirectionException; - import static org.apache.usergrid.rest.exceptions.SecurityException.mappableSecurityException; ++import org.apache.usergrid.rest.management.ManagementResource; import org.apache.usergrid.security.shiro.utils.SubjectUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; -import com.sun.jersey.api.json.JSONWithPadding; -import com.sun.jersey.api.view.Viewable; - -import net.tanesha.recaptcha.ReCaptchaImpl; -import net.tanesha.recaptcha.ReCaptchaResponse; ++import javax.ws.rs.*; ++import javax.ws.rs.core.Context; ++import javax.ws.rs.core.MediaType; ++import javax.ws.rs.core.UriInfo; ++import java.util.LinkedHashMap; ++import java.util.Map; ++import java.util.UUID; + + import static org.apache.commons.lang.StringUtils.isBlank; + import static org.apache.usergrid.rest.exceptions.SecurityException.mappableSecurityException; + @Component( "org.apache.usergrid.rest.management.users.UsersResource" ) @Produces( { http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/OAuth2AccessTokenSecurityFilter.java ---------------------------------------------------------------------- diff --cc stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/OAuth2AccessTokenSecurityFilter.java index 36a91bf,e3a7d54..87b85ac --- a/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/OAuth2AccessTokenSecurityFilter.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/OAuth2AccessTokenSecurityFilter.java @@@ -107,12 -104,13 +107,16 @@@ public class OAuth2AccessTokenSecurityF catch ( InvalidTokenException ite ) { throw mappableSecurityException( INVALID_AUTH_ERROR ); } + catch ( IndexOutOfBoundsException ioobe ) { + // token is just some rubbish string + throw mappableSecurityException( BAD_ACCESS_TOKEN_ERROR ); + } catch ( Exception e ) { - // unexpected so we log it - LOG.error( "unable to verify oauth token", e ); + if ( LOG.isDebugEnabled() ) { + LOG.debug( "Unable to verify OAuth token: " + accessToken, e ); + } else { + LOG.warn( "Unable to verify OAuth token" ); + } throw mappableSecurityException( UNVERIFIED_OAUTH_ERROR ); } @@@ -138,8 -136,7 +142,8 @@@ throw mappableSecurityException( BAD_ACCESS_TOKEN_ERROR ); } - token = PrincipalCredentialsToken.getFromAdminUserInfoAndAccessToken( - token = PrincipalCredentialsToken.getFromAdminUserInfoAndAccessToken( user, accessToken ); ++ token = PrincipalCredentialsToken.getFromAdminUserInfoAndAccessToken( + user, accessToken, emf.getManagementAppId() ); } else if ( AuthPrincipalType.APPLICATION_USER.equals( principal.getType() ) ) { http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/rest/src/test/java/org/apache/usergrid/rest/applications/assets/AssetResourceIT.java ---------------------------------------------------------------------- diff --cc stack/rest/src/test/java/org/apache/usergrid/rest/applications/assets/AssetResourceIT.java index dadc87d,c3cab63..6455748 --- a/stack/rest/src/test/java/org/apache/usergrid/rest/applications/assets/AssetResourceIT.java +++ b/stack/rest/src/test/java/org/apache/usergrid/rest/applications/assets/AssetResourceIT.java @@@ -17,124 -17,116 +17,128 @@@ package org.apache.usergrid.rest.applications.assets; - import java.io.IOException; - import java.io.InputStream; - import java.util.Map; - import java.util.UUID; - import java.util.concurrent.TimeoutException; - - import javax.ws.rs.core.MediaType; - +import com.fasterxml.jackson.databind.JsonNode; ++import com.sun.jersey.multipart.FormDataMultiPart; ++import org.apache.commons.io.IOUtils; ++import org.apache.usergrid.rest.applications.utils.UserRepo; +import org.apache.usergrid.rest.test.resource2point0.AbstractRestIT; ++import org.apache.usergrid.services.assets.data.AssetUtils; +import org.junit.Assert; +import org.junit.Before; - import org.junit.Ignore; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + - import org.apache.usergrid.rest.applications.utils.UserRepo; - import org.apache.usergrid.services.assets.data.AssetUtils; - - import org.apache.commons.io.IOUtils; - - import com.sun.jersey.multipart.FormDataMultiPart; ++import javax.ws.rs.core.MediaType; + import java.io.IOException; + import java.io.InputStream; + import java.util.HashMap; + import java.util.Map; + import java.util.UUID; + import java.util.concurrent.TimeoutException; - import static org.junit.Assert.assertEquals; - import static org.junit.Assert.assertFalse; - import static org.junit.Assert.assertNotNull; -import javax.ws.rs.core.MediaType; - -import org.codehaus.jackson.JsonNode; -import org.junit.Assert; -import org.junit.Ignore; -import org.junit.Test; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.usergrid.cassandra.Concurrent; -import org.apache.usergrid.rest.AbstractRestIT; -import org.apache.usergrid.rest.applications.utils.UserRepo; -import org.apache.usergrid.services.assets.data.AssetUtils; - -import org.apache.commons.io.IOUtils; - -import com.sun.jersey.multipart.FormDataMultiPart; - -import static org.apache.usergrid.management.AccountCreationProps.PROPERTIES_ADMIN_USERS_REQUIRE_CONFIRMATION; ++import static org.apache.usergrid.utils.JsonUtils.mapToFormattedJsonString; import static org.apache.usergrid.utils.MapUtils.hashMap; - + import static org.junit.Assert.*; -@Concurrent() public class AssetResourceIT extends AbstractRestIT { + private String access_token; private Logger LOG = LoggerFactory.getLogger( AssetResourceIT.class ); + UserRepo userRepo; + + @Before + public void setup(){ + userRepo = new UserRepo(this.clientSetup); + access_token = this.getAdminToken().getAccessToken(); + } /** @Deprecated Tests legacy API */ @Test public void verifyBinaryCrud() throws Exception { - UserRepo.INSTANCE.load( resource(), access_token ); - UUID userId = UserRepo.INSTANCE.getByUserName( "user1" ); ++ userRepo.load(); ++ ++ this.refreshIndex(); ++ + UUID userId = userRepo.getByUserName( "user1" ); Map<String, String> payload = hashMap( "path", "my/clean/path" ).map( "owner", userId.toString() ).map( "someprop", "somevalue" ); ++ String orgAppPath = clientSetup.getOrganizationName() + "/" + clientSetup.getAppName(); ++ JsonNode node = - mapper.readTree( resource().path( "/test-organization/test-app/assets" ).queryParam( "access_token", access_token ) - resource().path( "/test-organization/test-app/assets" ).queryParam( "access_token", access_token ) -- .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE ) - .post( String.class, payload )); - .post( JsonNode.class, payload ); ++ mapper.readTree( resource().path( orgAppPath + "/assets" ).queryParam( "access_token", access_token ) ++ .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE ) ++ .post( String.class, payload ) ); JsonNode idNode = node.get( "entities" ).get( 0 ).get( "uuid" ); - UUID id = UUID.fromString( idNode.getTextValue() ); - assertNotNull( idNode.getTextValue() ); - logNode( node ); + UUID id = UUID.fromString( idNode.textValue() ); - assertNotNull(idNode.textValue()); ++ assertNotNull( idNode.textValue() ); byte[] data = IOUtils.toByteArray( this.getClass().getResourceAsStream( "/cassandra_eye.jpg" ) ); -- resource().path( "/test-organization/test-app/assets/" + id.toString() + "/data" ) ++ resource().path( orgAppPath + "/assets/" + id.toString() + "/data" ) .queryParam( "access_token", access_token ).type( MediaType.APPLICATION_OCTET_STREAM_TYPE ).put( data ); -- InputStream is = resource().path( "/test-organization/test-app/assets/" + id.toString() + "/data" ) ++ InputStream is = resource().path( orgAppPath + "/assets/" + id.toString() + "/data" ) .queryParam( "access_token", access_token ).get( InputStream.class ); byte[] foundData = IOUtils.toByteArray( is ); assertEquals( 7979, foundData.length ); - node = resource().path( "/test-organization/test-app/assets/my/clean/path" ) - .queryParam( "access_token", access_token ).accept( MediaType.APPLICATION_JSON_TYPE ) - .get( JsonNode.class ); + refreshIndex(); + - node = mapper.readTree( resource().path( "/test-organization/test-app/assets/my/clean/path" ) - .queryParam( "access_token", access_token ).accept( MediaType.APPLICATION_JSON_TYPE ) - .get( String.class )); ++ node = mapper.readTree( resource().path( orgAppPath + "/assets/my/clean/path" ) ++ .queryParam( "access_token", access_token ).accept( MediaType.APPLICATION_JSON_TYPE ) ++ .get( String.class ) ); idNode = node.get( "entities" ).get( 0 ).get( "uuid" ); - assertEquals( id.toString(), idNode.getTextValue() ); + assertEquals( id.toString(), idNode.textValue() ); } @Test public void octetStreamOnDynamicEntity() throws Exception { - UserRepo.INSTANCE.load( resource(), access_token ); + ++ this.refreshIndex(); + Map<String, String> payload = hashMap( "name", "assetname" ); - JsonNode node = mapper.readTree( resource().path( "/test-organization/test-app/foos" ).queryParam( "access_token", access_token ) - JsonNode node = resource().path( "/test-organization/test-app/foos" ).queryParam( "access_token", access_token ) -- .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE ) - .post( String.class, payload )); - .post( JsonNode.class, payload ); ++ String orgAppPath = clientSetup.getOrganizationName() + "/" + clientSetup.getAppName(); ++ ++ JsonNode node = mapper.readTree( resource().path( orgAppPath + "/foos" ).queryParam( "access_token", access_token ) ++ .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE ) ++ .post( String.class, payload ) ); JsonNode idNode = node.get( "entities" ).get( 0 ).get( "uuid" ); - String uuid = idNode.getTextValue(); + String uuid = idNode.textValue(); - assertNotNull(uuid); + assertNotNull( uuid ); - logNode( node ); byte[] data = IOUtils.toByteArray( this.getClass().getResourceAsStream( "/cassandra_eye.jpg" ) ); -- resource().path( "/test-organization/test-app/foos/" + uuid ).queryParam( "access_token", access_token ) ++ resource().path( orgAppPath + "/foos/" + uuid ).queryParam( "access_token", access_token ) .type( MediaType.APPLICATION_OCTET_STREAM_TYPE ).put( data ); // get entity - node = mapper.readTree( resource().path( "/test-organization/test-app/foos/" + uuid ).queryParam( "access_token", access_token ) - node = resource().path( "/test-organization/test-app/foos/" + uuid ).queryParam( "access_token", access_token ) - .accept( MediaType.APPLICATION_JSON_TYPE ).get( JsonNode.class ); - logNode( node ); - Assert.assertEquals( "image/jpeg", node.findValue( AssetUtils.CONTENT_TYPE ).getTextValue() ); - Assert.assertEquals( 7979, node.findValue( "content-length" ).getIntValue() ); ++ node = mapper.readTree( resource().path( orgAppPath + "/foos/" + uuid ).queryParam( "access_token", access_token ) + .accept( MediaType.APPLICATION_JSON_TYPE ).get( String.class )); + Assert.assertEquals( "image/jpeg", node.findValue( AssetUtils.CONTENT_TYPE ).textValue() ); + Assert.assertEquals( 7979, node.findValue( "content-length" ).intValue() ); idNode = node.get( "entities" ).get( 0 ).get( "uuid" ); - assertEquals( uuid, idNode.getTextValue() ); + assertEquals( uuid, idNode.textValue() ); // get data by UUID InputStream is = -- resource().path( "/test-organization/test-app/foos/" + uuid ).queryParam( "access_token", access_token ) ++ resource().path( orgAppPath + "/foos/" + uuid ).queryParam( "access_token", access_token ) .accept( MediaType.APPLICATION_OCTET_STREAM_TYPE ).get( InputStream.class ); byte[] foundData = IOUtils.toByteArray( is ); assertEquals( 7979, foundData.length ); + refreshIndex(); + // get data by name -- is = resource().path( "/test-organization/test-app/foos/assetname" ).queryParam( "access_token", access_token ) ++ is = resource().path( orgAppPath + "/foos/assetname" ).queryParam( "access_token", access_token ) .accept( MediaType.APPLICATION_OCTET_STREAM_TYPE ).get( InputStream.class ); foundData = IOUtils.toByteArray( is ); @@@ -144,52 -136,83 +148,73 @@@ @Test public void multipartPostFormOnDynamicEntity() throws Exception { - UserRepo.INSTANCE.load( resource(), access_token ); + ++ this.refreshIndex(); + byte[] data = IOUtils.toByteArray( this.getClass().getResourceAsStream( "/file-bigger-than-5M" ) ); + FormDataMultiPart form = new FormDataMultiPart().field( "file", data, MediaType.MULTIPART_FORM_DATA_TYPE ); - JsonNode node = mapper.readTree( resource().path( "/test-organization/test-app/foos" ).queryParam( "access_token", access_token ) - .accept( MediaType.APPLICATION_JSON ).type( MediaType.MULTIPART_FORM_DATA ) - .post( String.class, form )); - FormDataMultiPart form = new FormDataMultiPart() - .field( "file", data, MediaType.MULTIPART_FORM_DATA_TYPE ); ++ String orgAppPath = clientSetup.getOrganizationName() + "/" + clientSetup.getAppName(); + - JsonNode node = resource().path( "/test-organization/test-app/foos" ) - .queryParam( "access_token", access_token ) - .accept( MediaType.APPLICATION_JSON ) - .type( MediaType.MULTIPART_FORM_DATA ) - .post( JsonNode.class, form ); ++ JsonNode node = mapper.readTree( resource().path( orgAppPath + "/foos" ) ++ .queryParam( "access_token", access_token ) ++ .accept( MediaType.APPLICATION_JSON ) ++ .type( MediaType.MULTIPART_FORM_DATA ) ++ .post( String.class, form )); JsonNode idNode = node.get( "entities" ).get( 0 ).get( "uuid" ); - String uuid = idNode.getTextValue(); - assertNotNull( uuid ); - logNode( node ); + String uuid = idNode.textValue(); + assertNotNull(uuid); -- // get entity - node = mapper.readTree( resource().path( "/test-organization/test-app/foos/" + uuid ).queryParam( "access_token", access_token ) - .accept( MediaType.APPLICATION_JSON_TYPE ).get( String.class )); - assertEquals( "application/octet-stream", node.findValue( AssetUtils.CONTENT_TYPE ).textValue() ); - assertEquals( 5324800, node.findValue( AssetUtils.CONTENT_LENGTH ).intValue() ); - node = resource().path( "/test-organization/test-app/foos/" + uuid ) - .queryParam( "access_token", access_token ) - .accept( MediaType.APPLICATION_JSON_TYPE ) - .get( JsonNode.class ); - - logNode( node ); - assertEquals( "application/octet-stream", node.findValue( AssetUtils.CONTENT_TYPE ).getTextValue() ); - assertEquals( 5324800, node.findValue( AssetUtils.CONTENT_LENGTH ).getIntValue() ); -- idNode = node.get( "entities" ).get( 0 ).get( "uuid" ); - assertEquals( uuid, idNode.textValue() ); - assertEquals( uuid, idNode.getTextValue() ); ++ this.refreshIndex(); - // get data - InputStream is = - resource().path( "/test-organization/test-app/foos/" + uuid ).queryParam( "access_token", access_token ) - .accept( MediaType.APPLICATION_OCTET_STREAM_TYPE ).get( InputStream.class ); + int retries = 0; + boolean done = false; + byte[] foundData = new byte[0]; + + // retry until upload complete + while ( !done && retries < 30 ) { + + // get data + try { - InputStream is = resource().path( "/test-organization/test-app/foos/" + uuid ) ++ InputStream is = resource().path( orgAppPath + "/foos/" + uuid ) + .queryParam( "access_token", access_token ) + .accept( MediaType.APPLICATION_OCTET_STREAM_TYPE ) + .get( InputStream.class ); + + foundData = IOUtils.toByteArray( is ); + done = true; + + } catch ( Exception intentiallyIgnored ) {} + + Thread.sleep(1000); + retries++; + } - byte[] foundData = IOUtils.toByteArray( is ); assertEquals( 5324800, foundData.length ); // delete - node = mapper.readTree( resource().path( "/test-organization/test-app/foos/" + uuid ).queryParam( "access_token", access_token ) - node = resource().path( "/test-organization/test-app/foos/" + uuid ) - .queryParam( "access_token", access_token ) - .accept( MediaType.APPLICATION_JSON_TYPE ) - .delete( JsonNode.class ); ++ node = mapper.readTree( resource().path( orgAppPath + "/foos/" + uuid ).queryParam( "access_token", access_token ) + .accept( MediaType.APPLICATION_JSON_TYPE ).delete( String.class )); } @Test public void multipartPutFormOnDynamicEntity() throws Exception { - UserRepo.INSTANCE.load( resource(), access_token ); + ++ this.refreshIndex(); + Map<String, String> payload = hashMap( "foo", "bar" ); - JsonNode node = mapper.readTree( resource().path( "/test-organization/test-app/foos" ).queryParam( "access_token", access_token ) - JsonNode node = resource().path( "/test-organization/test-app/foos" ).queryParam( "access_token", access_token ) ++ String orgAppPath = clientSetup.getOrganizationName() + "/" + clientSetup.getAppName(); ++ ++ JsonNode node = mapper.readTree( resource().path( orgAppPath + "/foos" ).queryParam( "access_token", access_token ) .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE ) - .post( JsonNode.class, payload ); + .post( String.class, payload )); JsonNode idNode = node.get( "entities" ).get( 0 ).get( "uuid" ); - String uuid = idNode.getTextValue(); + String uuid = idNode.textValue(); - assertNotNull(uuid); + assertNotNull( uuid ); - logNode( node ); // set file & assetname byte[] data = IOUtils.toByteArray( this.getClass().getResourceAsStream( "/cassandra_eye.jpg" ) ); @@@ -197,58 -220,63 +222,77 @@@ .field( "file", data, MediaType.MULTIPART_FORM_DATA_TYPE ); long created = System.currentTimeMillis(); - node = mapper.readTree( resource().path( "/test-organization/test-app/foos/" + uuid ).queryParam( "access_token", access_token ) - .accept( MediaType.APPLICATION_JSON ).type( MediaType.MULTIPART_FORM_DATA ).put( String.class, form )); - node = resource().path( "/test-organization/test-app/foos/" + uuid ).queryParam( "access_token", access_token ) - .accept( MediaType.APPLICATION_JSON ).type( MediaType.MULTIPART_FORM_DATA ).put( JsonNode.class, form ); - logNode( node ); ++ node = mapper.readTree( resource().path( orgAppPath + "/foos/" + uuid ) ++ .queryParam( "access_token", access_token ) ++ .accept( MediaType.APPLICATION_JSON ) ++ .type( MediaType.MULTIPART_FORM_DATA ) ++ .put( String.class, form )); ++ ++ this.refreshIndex(); // get entity - node = mapper.readTree( resource().path( "/test-organization/test-app/foos/" + uuid ).queryParam( "access_token", access_token ) - .accept( MediaType.APPLICATION_JSON_TYPE ).get( String.class )); - node = resource().path( "/test-organization/test-app/foos/" + uuid ).queryParam( "access_token", access_token ) - .accept( MediaType.APPLICATION_JSON_TYPE ).get( JsonNode.class ); - logNode( node ); - assertEquals( "image/jpeg", node.findValue( AssetUtils.CONTENT_TYPE ).getTextValue() ); - assertEquals( 7979, node.findValue( AssetUtils.CONTENT_LENGTH ).getIntValue() ); ++ node = mapper.readTree( resource().path( orgAppPath + "/foos/" + uuid ) ++ .queryParam( "access_token", access_token ) ++ .accept( MediaType.APPLICATION_JSON_TYPE ) ++ .get( String.class )); ++ LOG.debug( mapToFormattedJsonString(node) ); ++ + assertEquals( "image/jpeg", node.findValue( AssetUtils.CONTENT_TYPE ).textValue() ); + assertEquals( 7979, node.findValue( AssetUtils.CONTENT_LENGTH ).intValue() ); idNode = node.get( "entities" ).get( 0 ).get( "uuid" ); - assertEquals( uuid, idNode.getTextValue() ); + assertEquals( uuid, idNode.textValue() ); JsonNode nameNode = node.get( "entities" ).get( 0 ).get( "foo" ); - assertEquals( "bar2", nameNode.getTextValue() ); - long lastModified = node.findValue( AssetUtils.LAST_MODIFIED ).getLongValue(); + assertEquals( "bar2", nameNode.textValue() ); + long lastModified = node.findValue( AssetUtils.LAST_MODIFIED ).longValue(); Assert.assertEquals( created, lastModified, 500 ); // get data -- InputStream is = -- resource().path( "/test-organization/test-app/foos/" + uuid ).queryParam( "access_token", access_token ) -- .accept( "image/jpeg" ).get( InputStream.class ); ++ InputStream is = resource().path( orgAppPath + "/foos/" + uuid ) ++ .queryParam( "access_token", access_token ) ++ .accept( "image/jpeg" ) ++ .get( InputStream.class ); byte[] foundData = IOUtils.toByteArray( is ); assertEquals( 7979, foundData.length ); // post new data - node = mapper.readTree( resource().path( "/test-organization/test-app/foos/" + uuid ).queryParam( "access_token", access_token ) - .accept( MediaType.APPLICATION_JSON ).type( MediaType.MULTIPART_FORM_DATA ).put( String.class, form )); - node = resource().path( "/test-organization/test-app/foos/" + uuid ).queryParam( "access_token", access_token ) - .accept( MediaType.APPLICATION_JSON ).type( MediaType.MULTIPART_FORM_DATA ).put( JsonNode.class, form ); - logNode( node ); - assertTrue( lastModified != node.findValue( AssetUtils.LAST_MODIFIED ).getLongValue() ); ++ node = mapper.readTree( resource().path( orgAppPath + "/foos/" + uuid ) ++ .queryParam( "access_token", access_token ) ++ .accept( MediaType.APPLICATION_JSON ) ++ .type( MediaType.MULTIPART_FORM_DATA ) ++ .put( String.class, form ) ); + Assert.assertTrue( lastModified != node.findValue( AssetUtils.LAST_MODIFIED ).longValue() ); } @Test - @Ignore("Just enable and run when testing S3 large file upload specifically") public void largeFileInS3() throws Exception { - UserRepo.INSTANCE.load( resource(), access_token ); + ++ this.refreshIndex(); + byte[] data = IOUtils.toByteArray( this.getClass().getResourceAsStream( "/file-bigger-than-5M" ) ); FormDataMultiPart form = new FormDataMultiPart().field( "file", data, MediaType.MULTIPART_FORM_DATA_TYPE ); ++ String orgAppPath = clientSetup.getOrganizationName() + "/" + clientSetup.getAppName(); ++ // send data - JsonNode node = mapper.readTree( resource().path( "/test-organization/test-app/foos" ).queryParam( "access_token", access_token ) - JsonNode node = resource().path( "/test-organization/test-app/foos" ).queryParam( "access_token", access_token ) -- .accept( MediaType.APPLICATION_JSON ).type( MediaType.MULTIPART_FORM_DATA ) - .post( String.class, form )); - .post( JsonNode.class, form ); - logNode( node ); ++ JsonNode node = mapper.readTree( resource().path( orgAppPath + "/foos" ) ++ .queryParam( "access_token", access_token ) ++ .accept( MediaType.APPLICATION_JSON ) ++ .type( MediaType.MULTIPART_FORM_DATA ) ++ .post( String.class, form ) ); JsonNode idNode = node.get( "entities" ).get( 0 ).get( "uuid" ); - String uuid = idNode.getTextValue(); + String uuid = idNode.textValue(); // get entity long timeout = System.currentTimeMillis() + 60000; while ( true ) { - LOG.info("Waiting for upload to finish..."); + LOG.info( "Waiting for upload to finish..." ); Thread.sleep( 2000 ); - node = mapper.readTree( resource().path( "/test-organization/test-app/foos/" + uuid ) - node = resource().path( "/test-organization/test-app/foos/" + uuid ) -- .queryParam( "access_token", access_token ).accept( MediaType.APPLICATION_JSON_TYPE ) - .get( String.class )); - .get( JsonNode.class ); - logNode( node ); ++ node = mapper.readTree( resource().path( orgAppPath + "/foos/" + uuid ) ++ .queryParam( "access_token", access_token ) ++ .accept( MediaType.APPLICATION_JSON_TYPE ) ++ .get( String.class ) ); // poll for the upload to complete if ( node.findValue( AssetUtils.E_TAG ) != null ) { @@@ -261,18 -289,75 +305,82 @@@ LOG.info( "Upload complete!" ); // get data -- InputStream is = -- resource().path( "/test-organization/test-app/foos/" + uuid ).queryParam( "access_token", access_token ) -- .accept( MediaType.APPLICATION_OCTET_STREAM_TYPE ).get( InputStream.class ); ++ InputStream is = resource().path( orgAppPath + "/foos/" + uuid ) ++ .queryParam( "access_token", access_token ) ++ .accept( MediaType.APPLICATION_OCTET_STREAM_TYPE ) ++ .get( InputStream.class ); byte[] foundData = IOUtils.toByteArray( is ); -- assertEquals( 5324800, foundData.length ); ++ assertEquals( data.length, foundData.length ); // delete - node = mapper.readTree( resource().path( "/test-organization/test-app/foos/" + uuid ).queryParam( "access_token", access_token ) - .accept( MediaType.APPLICATION_JSON_TYPE ).delete( String.class )); - node = resource().path( "/test-organization/test-app/foos/" + uuid ).queryParam( "access_token", access_token ) - .accept( MediaType.APPLICATION_JSON_TYPE ).delete( JsonNode.class ); ++ node = mapper.readTree( resource().path( orgAppPath + "/foos/" + uuid ) ++ .queryParam( "access_token", access_token ) ++ .accept( MediaType.APPLICATION_JSON_TYPE ) ++ .delete( String.class ) ); } + @Test + public void fileTooLargeShouldResultInError() throws Exception { + ++ this.refreshIndex(); ++ + Map<String, String> props = new HashMap<String, String>(); + props.put( "usergrid.binary.max-size-mb", "6" ); + resource().path( "/testproperties" ) + .queryParam( "access_token", access_token ) + .accept( MediaType.APPLICATION_JSON ) + .type( MediaType.APPLICATION_JSON_TYPE ).post( props ); + + try { + - UserRepo.INSTANCE.load( resource(), access_token ); ++ //UserRepo.INSTANCE.load( resource(), access_token ); + + byte[] data = IOUtils.toByteArray( this.getClass().getResourceAsStream( "/cat-larger-than-6mb.jpg" ) ); + FormDataMultiPart form = new FormDataMultiPart().field( "file", data, MediaType.MULTIPART_FORM_DATA_TYPE ); + ++ String orgAppPath = clientSetup.getOrganizationName() + "/" + clientSetup.getAppName(); ++ + // send data - JsonNode node = resource().path( "/test-organization/test-app/bars" ).queryParam( "access_token", access_token ) ++ JsonNode node = resource().path( orgAppPath + "/bars" ).queryParam( "access_token", access_token ) + .accept( MediaType.APPLICATION_JSON ).type( MediaType.MULTIPART_FORM_DATA ) + .post( JsonNode.class, form ); + //logNode( node ); + JsonNode idNode = node.get( "entities" ).get( 0 ).get( "uuid" ); - String uuid = idNode.getTextValue(); ++ String uuid = idNode.textValue(); + + // get entity + String errorMessage = null; + long timeout = System.currentTimeMillis() + 60000; + while (true) { + LOG.info( "Waiting for upload to finish..." ); + Thread.sleep( 2000 ); - node = resource().path( "/test-organization/test-app/bars/" + uuid ) ++ node = resource().path( orgAppPath + "/bars/" + uuid ) + .queryParam( "access_token", access_token ).accept( MediaType.APPLICATION_JSON_TYPE ) + .get( JsonNode.class ); + //logNode( node ); + + // poll for the error to happen + if (node.findValue( "error" ) != null) { + errorMessage = node.findValue("error").asText(); + break; + } + if (System.currentTimeMillis() > timeout) { + throw new TimeoutException(); + } + } + + assertTrue( errorMessage.startsWith("Asset size ")); + + } finally { + props = new HashMap<String, String>(); + props.put( "usergrid.binary.max-size-mb", "25" ); + resource().path( "/testproperties" ) + .queryParam( "access_token", access_token ) + .accept( MediaType.APPLICATION_JSON ) + .type( MediaType.APPLICATION_JSON_TYPE ).post( props ); + } + } /** * Deleting a connection to an asset should not delete the asset or the asset's data @@@ -280,26 -365,26 +388,30 @@@ @Test public void deleteConnectionToAsset() throws IOException { - userRepo.load(); - UserRepo.INSTANCE.load( resource(), access_token ); ++ this.refreshIndex(); final String uuid; ++ access_token = this.getAdminToken().getAccessToken(); ++ ++ String orgAppPath = clientSetup.getOrganizationName() + "/" + clientSetup.getAppName(); ++ // create the entity that will be the asset, an image Map<String, String> payload = hashMap("name", "cassandra_eye.jpg"); -- - JsonNode node = resource().path("/test-organization/test-app/foos") - JsonNode node = resource().path("/test-organization/test-app/bars") -- .queryParam("access_token", access_token) -- .accept(MediaType.APPLICATION_JSON) -- .type(MediaType.APPLICATION_JSON_TYPE) -- .post(JsonNode.class, payload); ++ JsonNode node = resource().path(orgAppPath + "/foos") ++ .header( "Authorization", "Bearer " + access_token ) ++ //.queryParam("access_token", access_token) ++ .accept( MediaType.APPLICATION_JSON ) ++ .type( MediaType.APPLICATION_JSON_TYPE ) ++ .post(JsonNode.class, payload); JsonNode idNode = node.get("entities").get(0).get("uuid"); - uuid = idNode.getTextValue(); + uuid = idNode.textValue(); // post image data to the asset entity byte[] data = IOUtils.toByteArray(this.getClass().getResourceAsStream("/cassandra_eye.jpg")); -- resource().path("/test-organization/test-app/foos/" + uuid) ++ resource().path(orgAppPath + "/foos/" + uuid) .queryParam("access_token", access_token) .type(MediaType.APPLICATION_OCTET_STREAM_TYPE) .put(data); @@@ -308,7 -393,7 +420,7 @@@ Map<String, String> imageGalleryPayload = hashMap("name", "my image gallery"); -- JsonNode imageGalleryNode = resource().path("/test-organization/test-app/imagegalleries") ++ JsonNode imageGalleryNode = resource().path(orgAppPath + "/imagegalleries") .queryParam("access_token", access_token) .accept(MediaType.APPLICATION_JSON) .type(MediaType.APPLICATION_JSON_TYPE) @@@ -320,34 -405,34 +432,40 @@@ // connect imagegallery to asset JsonNode connectNode = resource() -- .path("/test-organization/test-app/imagegalleries/" + imageGalleryId + "/contains/" + uuid) ++ .path(orgAppPath + "/imagegalleries/" + imageGalleryId + "/contains/" + uuid) .queryParam("access_token", access_token) .accept(MediaType.APPLICATION_JSON) .type(MediaType.APPLICATION_JSON_TYPE) .post(JsonNode.class); ++ LOG.debug( mapToFormattedJsonString(connectNode) ); ++ ++ this.refreshIndex(); // verify connection from imagegallery to asset JsonNode listConnectionsNode = resource() -- .path("/test-organization/test-app/imagegalleries/" + imageGalleryId + "/contains/") ++ .path(orgAppPath + "/imagegalleries/" + imageGalleryId + "/contains/") .queryParam("access_token", access_token) .accept(MediaType.APPLICATION_JSON) .type(MediaType.APPLICATION_JSON_TYPE) .get(JsonNode.class); - assertEquals(uuid, listConnectionsNode.get("entities").get(0).get("uuid").getTextValue()); ++ LOG.debug( mapToFormattedJsonString(listConnectionsNode) ); + assertEquals(uuid, listConnectionsNode.get("entities").get(0).get("uuid").textValue()); // delete the connection -- resource().path("/test-organization/test-app/imagegalleries/" + imageGalleryId + "/contains/" + uuid) ++ resource().path(orgAppPath + "/imagegalleries/" + imageGalleryId + "/contains/" + uuid) .queryParam("access_token", access_token) .accept(MediaType.APPLICATION_JSON) .type(MediaType.APPLICATION_JSON_TYPE) .delete(); ++ this.refreshIndex(); ++ // verify that connection is gone listConnectionsNode = resource() -- .path("/test-organization/test-app/imagegalleries/" + imageGalleryId + "/contains/") ++ .path(orgAppPath + "/imagegalleries/" + imageGalleryId + "/contains/") .queryParam("access_token", access_token) .accept(MediaType.APPLICATION_JSON) .type(MediaType.APPLICATION_JSON_TYPE) @@@ -356,7 -441,7 +474,7 @@@ // asset should still be there -- JsonNode assetNode = resource().path("/test-organization/test-app/foos/" + uuid) ++ JsonNode assetNode = resource().path(orgAppPath + "/foos/" + uuid) .queryParam("access_token", access_token) .accept(MediaType.APPLICATION_JSON_TYPE) .get(JsonNode.class); @@@ -368,7 -454,7 +486,7 @@@ // asset data should still be there -- InputStream assetIs = resource().path("/test-organization/test-app/foos/" + uuid) ++ InputStream assetIs = resource().path(orgAppPath + "/foos/" + uuid) .queryParam("access_token", access_token) .accept(MediaType.APPLICATION_OCTET_STREAM_TYPE) .get(InputStream.class); http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/rest/src/test/java/org/apache/usergrid/rest/applications/utils/UserRepo.java ---------------------------------------------------------------------- diff --cc stack/rest/src/test/java/org/apache/usergrid/rest/applications/utils/UserRepo.java index 06c3a76,993b30f..fd948aa --- a/stack/rest/src/test/java/org/apache/usergrid/rest/applications/utils/UserRepo.java +++ b/stack/rest/src/test/java/org/apache/usergrid/rest/applications/utils/UserRepo.java @@@ -17,31 -17,22 +17,24 @@@ package org.apache.usergrid.rest.applications.utils; - import com.fasterxml.jackson.databind.JsonNode; - import com.fasterxml.jackson.databind.ObjectMapper; - import com.sun.jersey.api.client.WebResource; - import java.io.IOException; - import java.util.HashMap; - import java.util.Map; - import java.util.UUID; - import java.util.logging.Level; - import java.util.logging.Logger; - import javax.ws.rs.core.MediaType; - import static org.apache.usergrid.utils.MapUtils.hashMap; - - import org.apache.usergrid.rest.test.resource2point0.AbstractRestIT; +import org.apache.usergrid.rest.test.resource2point0.ClientSetup; +import org.apache.usergrid.rest.test.resource2point0.model.Entity; +import org.apache.usergrid.utils.UUIDUtils; + + import java.util.HashMap; + import java.util.Map; + import java.util.UUID; - public class UserRepo { -import javax.ws.rs.core.MediaType; - -import org.codehaus.jackson.JsonNode; -import org.apache.usergrid.utils.UUIDUtils; - -import com.sun.jersey.api.client.WebResource; - -import static org.apache.usergrid.utils.MapUtils.hashMap; ++/** ++ * Creates three users in current app ++ */ ++public class UserRepo { + private final ClientSetup clientSetup; -public enum UserRepo { - INSTANCE; + public UserRepo(ClientSetup clientSetup){ + this.clientSetup = clientSetup; + } private final Map<String, UUID> loaded = new HashMap<String, UUID>(); @@@ -49,42 -41,41 +42,31 @@@ if ( loaded.size() > 0 ) { return; } - - // pause between creation to insure entities are created in order -- - createUser( "user1", "us...@apigee.com", "user1", "Jane Smith 1", resource, accessToken ); - createUser( "user2", "us...@apigee.com", "user2", "John Smith 2", resource, accessToken ); - createUser( "user3", "us...@apigee.com", "user3", "John Smith 3", resource, accessToken ); + createUser( "user1", "us...@apigee.com", "user1", "Jane Smith 1" ); - + createUser( "user2", "us...@apigee.com", "user2", "John Smith 2" ); - + createUser( "user3", "us...@apigee.com", "user3", "John Smith 3" ); } - - private void createUser( String username, String email, String password, String fullName, WebResource resource, - String accessToken ) { - - Map<String, String> payload = hashMap( "email", email ).map( "username", username ).map( "name", fullName ) - .map( "password", password ).map( "pin", "1234" ); - - UUID id = createUser( payload, resource, accessToken ); -- + private void createUser( String username, String email, String password, String fullName) { + Entity entity = new Entity(); + entity.put( "email", email ); + entity.put( "username", username ); + entity.put("name", fullName); + entity.put( "password", password ); + entity.put("pin", "1234"); + UUID id = createUser( entity ); loaded.put( username, id ); } -- public UUID getByUserName( String name ) { return loaded.get( name ); } -- /** Create a user via the REST API and post it. Return the response */ - private UUID createUser( Map<String, String> payload, WebResource resource, String access_token ) { - - JsonNode response = - resource.path( "/test-organization/test-app/users" ).queryParam( "access_token", access_token ) - .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE ) - .post( JsonNode.class, payload ); - - String idString = response.get( "entities" ).get( 0 ).get( "uuid" ).asText(); - + private UUID createUser( Entity payload ) { - - Entity entity = clientSetup.getRestClient().org(clientSetup.getOrganizationName()).app(clientSetup.getAppName()).collection("users").post(payload); - ++ Entity entity = clientSetup.getRestClient().org( ++ clientSetup.getOrganizationName()).app(clientSetup.getAppName()).collection("users").post(payload); + String idString = entity.get("uuid").toString(); - return UUIDUtils.tryExtractUUID( idString ); } -- }