Merge branch '2.1-release' of https://git-wip-us.apache.org/repos/asf/usergrid
# Conflicts: # stack/core/src/main/java/org/apache/usergrid/corepersistence/asyncevents/AmazonAsyncEventService.java # stack/core/src/main/java/org/apache/usergrid/corepersistence/asyncevents/EventBuilderImpl.java # stack/core/src/main/java/org/apache/usergrid/corepersistence/asyncevents/InMemoryAsyncEventService.java # stack/core/src/main/java/org/apache/usergrid/corepersistence/index/IndexProcessorFig.java # stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java # stack/rest/src/main/java/org/apache/usergrid/rest/applications/users/UserResource.java # stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/OrganizationsResource.java # stack/rest/src/main/java/org/apache/usergrid/rest/system/MigrateResource.java # stack/rest/src/main/java/org/apache/usergrid/rest/system/SystemResource.java # stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/users/UserResourceIT.java Project: http://git-wip-us.apache.org/repos/asf/usergrid/repo Commit: http://git-wip-us.apache.org/repos/asf/usergrid/commit/b422364e Tree: http://git-wip-us.apache.org/repos/asf/usergrid/tree/b422364e Diff: http://git-wip-us.apache.org/repos/asf/usergrid/diff/b422364e Branch: refs/heads/USERGRID-909 Commit: b422364e20c14a657de076b793bc6b7c1160a556 Parents: 9d3cf5b eb2756b Author: Todd Nine <tn...@apigee.com> Authored: Fri Oct 30 16:32:23 2015 -0600 Committer: Todd Nine <tn...@apigee.com> Committed: Fri Oct 30 16:32:23 2015 -0600 ---------------------------------------------------------------------- .../corepersistence/CpEntityManagerFactory.java | 7 +- .../corepersistence/CpRelationManager.java | 16 +- .../asyncevents/AmazonAsyncEventService.java | 99 +-- .../asyncevents/AsyncEventService.java | 5 + .../asyncevents/EventBuilder.java | 25 +- .../asyncevents/EventBuilderImpl.java | 60 +- .../index/IndexProcessorFig.java | 15 +- .../corepersistence/index/IndexServiceImpl.java | 5 +- .../pipeline/read/FilterResult.java | 7 + .../read/traverse/AbstractReadGraphFilter.java | 136 +++- .../read/traverse/EdgeCursorSerializer.java | 8 +- .../read/traverse/EntityLoadVerifyFilter.java | 24 +- .../traverse/ReadGraphCollectionFilter.java | 11 +- .../ReadGraphConnectionByTypeFilter.java | 11 +- .../traverse/ReadGraphConnectionFilter.java | 11 +- .../results/ObservableQueryExecutor.java | 7 + .../service/StatusServiceImpl.java | 3 +- .../usergrid/persistence/CredentialsInfo.java | 46 ++ .../persistence/ObservableIterator.java | 83 --- .../index/AsyncIndexServiceTest.java | 3 +- .../corepersistence/index/IndexServiceTest.java | 12 +- .../pipeline/cursor/CursorTest.java | 24 +- .../service/ConnectionServiceImplTest.java | 5 +- .../persistence/ApplicationServiceIT.java | 4 +- .../persistence/core/astyanax/CassandraFig.java | 2 +- .../core/astyanax/MultiRowColumnIterator.java | 46 +- .../persistence/core/rx/ObservableIterator.java | 2 +- .../usergrid/persistence/graph/GraphFig.java | 4 +- .../persistence/graph/GraphManager.java | 14 +- .../usergrid/persistence/graph/MarkedEdge.java | 15 +- .../persistence/graph/guice/GraphModule.java | 11 +- .../graph/impl/GraphManagerImpl.java | 90 ++- .../graph/impl/SimpleMarkedEdge.java | 62 +- .../impl/stage/NodeDeleteListenerImpl.java | 27 +- .../impl/EdgeSerializationImpl.java | 17 +- .../impl/shard/AsyncTaskExecutor.java | 34 + .../graph/serialization/impl/shard/Shard.java | 15 + .../impl/shard/ShardEntryGroup.java | 13 +- .../impl/shard/ShardGroupCompaction.java | 4 - .../impl/shard/ShardGroupDeletion.java | 78 +++ .../impl/shard/impl/AsyncTaskExecutorImpl.java | 53 ++ .../shard/impl/NodeShardAllocationImpl.java | 81 ++- .../shard/impl/ShardGroupColumnIterator.java | 72 +- .../shard/impl/ShardGroupCompactionImpl.java | 10 +- .../impl/shard/impl/ShardGroupDeletionImpl.java | 230 +++++++ .../impl/shard/impl/ShardsColumnIterator.java | 10 + .../persistence/graph/GraphManagerIT.java | 76 +-- .../persistence/graph/GraphManagerLoadTest.java | 10 +- .../graph/GraphManagerShardConsistencyIT.java | 382 ++++++++--- .../graph/GraphManagerStressTest.java | 16 +- .../impl/shard/ShardEntryGroupTest.java | 14 + .../impl/shard/ShardGroupCompactionTest.java | 30 +- .../shard/impl/ShardGroupDeletionImplTest.java | 341 +++++++++ stack/corepersistence/pom.xml | 2 +- .../persistence/index/CandidateResult.java | 11 +- .../persistence/index/EntityIndexBatch.java | 2 +- .../usergrid/persistence/index/IndexFig.java | 6 + .../index/impl/DeIndexOperation.java | 5 + .../index/impl/EsEntityIndexBatchImpl.java | 34 +- .../index/impl/EsEntityIndexImpl.java | 188 +++-- .../persistence/index/impl/IndexingUtils.java | 2 +- .../persistence/index/impl/EntityIndexTest.java | 14 +- .../usergrid/persistence/queue/QueueFig.java | 2 +- .../org/apache/usergrid/rest/IndexResource.java | 350 ---------- .../apache/usergrid/rest/MigrateResource.java | 275 -------- .../apache/usergrid/rest/SystemResource.java | 111 --- .../rest/applications/ApplicationResource.java | 50 ++ .../rest/applications/users/UserResource.java | 134 +++- .../organizations/OrganizationsResource.java | 33 + .../rest/system/ConnectionResource.java | 216 ++++++ .../usergrid/rest/system/DatabaseResource.java | 2 + .../usergrid/rest/system/IndexResource.java | 353 ++++++++++ .../usergrid/rest/system/MigrateResource.java | 277 ++++++++ .../usergrid/rest/system/SystemResource.java | 121 ++++ .../collection/users/UserResourceIT.java | 117 ++++ stack/scripts/create_test_data.py | 222 ++++++ stack/scripts/migrate_entity_data.py | 18 +- stack/scripts/multitenant_migrate.py | 683 +++++++++++++++++++ .../management/AppInfoMigrationPlugin.java | 5 +- .../usergrid/management/ManagementService.java | 14 +- .../cassandra/ManagementServiceImpl.java | 43 +- 81 files changed, 4231 insertions(+), 1445 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpEntityManagerFactory.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/core/src/main/java/org/apache/usergrid/corepersistence/CpRelationManager.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/core/src/main/java/org/apache/usergrid/corepersistence/asyncevents/AmazonAsyncEventService.java ---------------------------------------------------------------------- diff --cc stack/core/src/main/java/org/apache/usergrid/corepersistence/asyncevents/AmazonAsyncEventService.java index 14fbdaa,6b9abbc..e5c25fb --- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/asyncevents/AmazonAsyncEventService.java +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/asyncevents/AmazonAsyncEventService.java @@@ -315,25 -316,34 +315,31 @@@ public class AmazonAsyncEventService im boolean validateEmptySets = true; Observable<IndexOperationMessage> indexoperationObservable; //merge each operation to a master observable; - if (event instanceof EdgeDeleteEvent) { - indexoperationObservable = handleEdgeDelete(message); - } else if (event instanceof EdgeIndexEvent) { - indexoperationObservable = handleEdgeIndex(message); - } else if (event instanceof EntityDeleteEvent) { - indexoperationObservable = handleEntityDelete(message); - } else if (event instanceof EntityIndexEvent) { - indexoperationObservable = handleEntityIndexUpdate(message); - } else if (event instanceof InitializeApplicationIndexEvent) { + if ( event instanceof EdgeDeleteEvent ) { + indexoperationObservable = handleEdgeDelete( message ); + } + else if ( event instanceof EdgeIndexEvent ) { + indexoperationObservable = handleEdgeIndex( message ); + } + else if ( event instanceof EntityDeleteEvent ) { + indexoperationObservable = handleEntityDelete( message ); + validateEmptySets = false; // do not check this one for an empty set b/c it can be empty + + } + else if ( event instanceof EntityIndexEvent ) { + indexoperationObservable = handleEntityIndexUpdate( message ); + } + else if ( event instanceof InitializeApplicationIndexEvent ) { //does not return observable - handleInitializeApplicationIndex( event, message ); - indexoperationObservable = Observable.just( new IndexOperationMessage() ); + handleInitializeApplicationIndex(event, message); + indexoperationObservable = Observable.just(new IndexOperationMessage()); validateEmptySets = false; //do not check this one for an empty set b/c it will be empty. - } - else if ( event instanceof ElasticsearchIndexEvent ) { - handleIndexOperation( ( ElasticsearchIndexEvent ) event ); - indexoperationObservable = Observable.just( new IndexOperationMessage() ); + } else if (event instanceof ElasticsearchIndexEvent) { + handleIndexOperation((ElasticsearchIndexEvent) event); + indexoperationObservable = Observable.just(new IndexOperationMessage()); validateEmptySets = false; //do not check this one for an empty set b/c it will be empty. - } - - else { - throw new Exception( "Unknown EventType" );//TODO: print json instead + } else { + throw new Exception("Unknown EventType");//TODO: print json instead } //collect all of the http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/IndexProcessorFig.java ---------------------------------------------------------------------- diff --cc stack/core/src/main/java/org/apache/usergrid/corepersistence/index/IndexProcessorFig.java index 69d5e18,9d02717..c991b36 --- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/IndexProcessorFig.java +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/IndexProcessorFig.java @@@ -70,10 -72,19 +72,19 @@@ public interface IndexProcessorFig exte int getIndexQueueVisibilityTimeout(); /** + * The number of worker threads used when handing off messages from the SQS thread + */ + @Default( "20" ) + @Key( EVENT_CONCURRENCY_FACTOR ) + int getEventConcurrencyFactor(); + + + + /** * The number of worker threads used to read index write requests from the queue. */ - @Default( "8" ) - @Key( ELASTICSEARCH_WORKER_COUNT ) + @Default("16") + @Key(ELASTICSEARCH_WORKER_COUNT) int getWorkerCount(); /** http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/IndexServiceImpl.java ---------------------------------------------------------------------- diff --cc stack/core/src/main/java/org/apache/usergrid/corepersistence/index/IndexServiceImpl.java index 7efe8e4,b2a1a2a..301a7ae --- a/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/IndexServiceImpl.java +++ b/stack/core/src/main/java/org/apache/usergrid/corepersistence/index/IndexServiceImpl.java @@@ -218,10 -219,10 +219,10 @@@ public class IndexServiceImpl implement //collect results into a single batch .collect( () -> ei.createBatch(), ( batch, candidateResult ) -> { logger.debug( "Deindexing on edge {} for entity {} added to batch",searchEdge , entityId ); - batch.deindex( searchEdge, candidateResult ); + batch.deindex( candidateResult ); } ) //return the future from the batch execution - .flatMap( batch ->Observable.just(batch.build()) ); + .map( batch ->batch.build() ); return ObservableTimer.time(batches, indexTimer); } http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/core/src/test/java/org/apache/usergrid/persistence/ApplicationServiceIT.java ---------------------------------------------------------------------- diff --cc stack/core/src/test/java/org/apache/usergrid/persistence/ApplicationServiceIT.java index f8079e5,658d3eb..9ad90eb --- a/stack/core/src/test/java/org/apache/usergrid/persistence/ApplicationServiceIT.java +++ b/stack/core/src/test/java/org/apache/usergrid/persistence/ApplicationServiceIT.java @@@ -85,15 -87,10 +86,16 @@@ public class ApplicationServiceIT exten , Long.MAX_VALUE, SearchByEdgeType.Order.DESCENDING, Optional.<Edge>absent() ); - Iterator<Edge> results = graphManager.loadEdgesFromSource(simpleSearchByEdgeType).toBlocking().getIterator(); + Iterator<MarkedEdge> + results = graphManager.loadEdgesFromSource(simpleSearchByEdgeType).toBlocking().getIterator(); if(results.hasNext()){ - Assert.fail("should be empty"); + int i = 0; + + while(results.hasNext()){ + results.next(); + i++; + } + Assert.fail("should be empty but has "+i); }else{ Results searchCollection = entityManager.searchCollection(entityManager.getApplication(), "tests", Query.all()); http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/corepersistence/pom.xml ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexBatchImpl.java ---------------------------------------------------------------------- diff --cc stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexBatchImpl.java index 1ffcd02,a8fb751..a49e217 --- a/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexBatchImpl.java +++ b/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexBatchImpl.java @@@ -117,7 -136,13 +136,12 @@@ public class EsEntityIndexBatchImpl imp return deindex( searchEdge, entity.getId(), entity.getVersion() ); } + @Override + public EntityIndexBatch deindex( final CandidateResult entity ) { + + return deindexWithDocId(entity.getDocId()); + } - @Override public IndexOperationMessage build() { return container; http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/corepersistence/queryindex/src/main/java/org/apache/usergrid/persistence/index/impl/EsEntityIndexImpl.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/corepersistence/queryindex/src/test/java/org/apache/usergrid/persistence/index/impl/EntityIndexTest.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java ---------------------------------------------------------------------- diff --cc stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java index e830876,162565f..769b836 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/applications/ApplicationResource.java @@@ -17,7 -17,9 +17,8 @@@ package org.apache.usergrid.rest.applications; + import com.fasterxml.jackson.databind.ObjectMapper; -import com.sun.jersey.api.json.JSONWithPadding; -import com.sun.jersey.api.view.Viewable; +import com.fasterxml.jackson.jaxrs.json.annotation.JSONP; import org.apache.amber.oauth2.common.error.OAuthError; import org.apache.amber.oauth2.common.exception.OAuthProblemException; import org.apache.amber.oauth2.common.message.OAuthResponse; @@@ -47,9 -48,9 +48,10 @@@ import org.apache.usergrid.rest.excepti import org.apache.usergrid.rest.exceptions.RedirectionException; import org.apache.usergrid.rest.security.annotations.RequireApplicationAccess; import org.apache.usergrid.rest.security.annotations.RequireOrganizationAccess; + import org.apache.usergrid.rest.security.annotations.RequireSystemAccess; import org.apache.usergrid.security.oauth.AccessInfo; import org.apache.usergrid.security.oauth.ClientCredentialsInfo; +import org.glassfish.jersey.server.mvc.Viewable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.Scope; @@@ -601,6 -601,54 +603,54 @@@ public class ApplicationResource extend if(value==null){ throw new EntityNotFoundException("apigeeMobileConfig not found, it is possibly not enabled for your config."); } - return new JSONWithPadding( value, callback ); + return value; } + + // Specifically require superuser access as this is setting app properties directly (only way to currently do this + // with Apigee's apigeeMobileConfig + @RequireOrganizationAccess + @POST + @Path("apm/apigeeMobileConfig") + @Consumes(APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) - public JSONWithPadding setAPMConfig( @Context UriInfo ui, - @QueryParam("callback") @DefaultValue("callback") String callback, - Map<String, Object> json) throws Exception { ++ public String setAPMConfig( @Context UriInfo ui, ++ @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback, ++ Map<String, Object> json ) throws Exception { + + if(json == null || json.size() < 1){ + logger.error("Param {} cannot be null for POST apm/apigeeMobileConfig", APIGEE_MOBILE_APM_CONFIG_JSON_KEY); + throw new IllegalArgumentException("Request body cannot be empty and must include apigeeMobileConfig params"); + } + + final String requestAppUUID = (String) json.get("applicationUUID"); + if(!requestAppUUID.equalsIgnoreCase(applicationId.toString())){ + logger.error("Provided application UUID {} does not match actual application UUID {}", + requestAppUUID, + applicationId.toString()); + throw new IllegalArgumentException( + String.format("Provided application UUID %s does not match actual application UUID %s", + requestAppUUID, + applicationId.toString()) + ); + } + + final String apmConfig = new ObjectMapper().writeValueAsString(json); + if(logger.isDebugEnabled()){ + logger.debug("Received request to set apigeeMobileConfig properties with: {}", apmConfig); + } + + + EntityManager em = emf.getEntityManager( applicationId ); + em.setProperty(new SimpleEntityRef(Application.ENTITY_TYPE, applicationId), + APIGEE_MOBILE_APM_CONFIG_JSON_KEY, + apmConfig + ); + + logger.info("Successfully set apigeeMobileConfig properties with: {}", apmConfig); + - return new JSONWithPadding(apmConfig, callback); ++ return apmConfig; + + } + + } http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/rest/src/main/java/org/apache/usergrid/rest/applications/users/UserResource.java ---------------------------------------------------------------------- diff --cc stack/rest/src/main/java/org/apache/usergrid/rest/applications/users/UserResource.java index b84fc08,fb2962e..130658cd --- a/stack/rest/src/main/java/org/apache/usergrid/rest/applications/users/UserResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/applications/users/UserResource.java @@@ -17,38 -17,63 +17,63 @@@ package org.apache.usergrid.rest.applications.users; --import com.fasterxml.jackson.databind.JsonNode; --import com.fasterxml.jackson.databind.ObjectMapper; - import com.fasterxml.jackson.jaxrs.json.annotation.JSONP; - import net.tanesha.recaptcha.ReCaptchaImpl; - import net.tanesha.recaptcha.ReCaptchaResponse; + 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.PUT; + 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.PathSegment; + import javax.ws.rs.core.Response; + import javax.ws.rs.core.UriInfo; + ++import org.glassfish.jersey.server.mvc.Viewable; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import org.springframework.context.annotation.Scope; + import org.springframework.stereotype.Component; + import org.apache.amber.oauth2.common.exception.OAuthProblemException; import org.apache.amber.oauth2.common.message.OAuthResponse; import org.apache.commons.lang.StringUtils; + import org.apache.usergrid.management.ActivationState; + import org.apache.usergrid.persistence.CredentialsInfo; import org.apache.usergrid.persistence.EntityManager; -import org.apache.usergrid.persistence.index.query.Identifier; import org.apache.usergrid.persistence.entities.User; +import org.apache.usergrid.persistence.index.query.Identifier; import org.apache.usergrid.rest.AbstractContextResource; import org.apache.usergrid.rest.ApiResponse; import org.apache.usergrid.rest.applications.ServiceResource; import org.apache.usergrid.rest.exceptions.RedirectionException; import org.apache.usergrid.rest.security.annotations.RequireApplicationAccess; + import org.apache.usergrid.rest.security.annotations.RequireSystemAccess; import org.apache.usergrid.security.oauth.AccessInfo; import org.apache.usergrid.security.tokens.exceptions.TokenException; - import org.glassfish.jersey.server.mvc.Viewable; - import org.slf4j.Logger; - import org.slf4j.LoggerFactory; - import org.springframework.context.annotation.Scope; - import org.springframework.stereotype.Component; - import javax.ws.rs.*; - import javax.ws.rs.core.*; - import java.util.Map; - import java.util.UUID; -import com.sun.jersey.api.json.JSONWithPadding; -import com.sun.jersey.api.view.Viewable; ++import com.fasterxml.jackson.databind.JsonNode; ++import com.fasterxml.jackson.databind.ObjectMapper; ++import com.fasterxml.jackson.jaxrs.json.annotation.JSONP; - import static javax.servlet.http.HttpServletResponse.*; - import static org.apache.usergrid.security.shiro.utils.SubjectUtils.*; + import net.tanesha.recaptcha.ReCaptchaImpl; + import net.tanesha.recaptcha.ReCaptchaResponse; + + import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST; + import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN; + import static javax.servlet.http.HttpServletResponse.SC_OK; + + import static org.apache.usergrid.security.shiro.utils.SubjectUtils.getSubjectUserId; + import static org.apache.usergrid.security.shiro.utils.SubjectUtils.isApplicationAdmin; + import static org.apache.usergrid.security.shiro.utils.SubjectUtils.isApplicationUser; import static org.apache.usergrid.utils.ConversionUtils.string; @@@ -143,9 -164,84 +168,84 @@@ public class UserResource extends Servi management.setAppUserPassword( getApplicationId(), targetUserId, oldPassword, newPassword ); } - return new JSONWithPadding( response, callback ); + return response; } + @GET + @RequireSystemAccess + @Path("credentials") - public JSONWithPadding getUserCredentials(@QueryParam("callback") @DefaultValue("callback") String callback ) ++ public ApiResponse getUserCredentials(@QueryParam("callback") @DefaultValue("callback") String callback ) + throws Exception { + + logger.info( "UserResource.getUserCredentials" ); + + + final ApiResponse response = createApiResponse(); + response.setAction( "get user credentials" ); + + final UUID applicationId = getApplicationId(); + final UUID targetUserId = getUserUuid(); + + if ( applicationId == null ) { + response.setError( "Application not found" ); - return new JSONWithPadding( response, callback ); ++ return response; + } + + if ( targetUserId == null ) { + response.setError( "User not found" ); - return new JSONWithPadding( response, callback ); ++ return response; + } + + final CredentialsInfo credentialsInfo = management.getAppUserCredentialsInfo( applicationId, targetUserId ); + + + response.setProperty( "credentials", credentialsInfo ); + + - return new JSONWithPadding( response, callback ); ++ return response; + } + + + + @PUT + @RequireSystemAccess + @Path("credentials") - public JSONWithPadding setUserCredentials( @Context UriInfo ui, Map<String, Object> json, ++ public ApiResponse setUserCredentials( @Context UriInfo ui, Map<String, Object> json, + @QueryParam("callback") @DefaultValue("callback") String callback ) + throws Exception { + + logger.info( "UserResource.setUserCredentials" ); + + if ( json == null ) { + return null; + } + + ApiResponse response = createApiResponse(); + response.setAction( "set user credentials" ); + Map<String, Object> credentialsJson = ( Map<String, Object> ) json.get( "credentials" ); + + + if ( credentialsJson == null ) { + throw new IllegalArgumentException( "credentials sub object is required" ); + } + + final CredentialsInfo credentials = CredentialsInfo.fromJson( credentialsJson ); + + UUID applicationId = getApplicationId(); + UUID targetUserId = getUserUuid(); + + if ( targetUserId == null ) { + response.setError( "User not found" ); - return new JSONWithPadding( response, callback ); ++ return response; + } + + + management.setAppUserCredentialsInfo( applicationId, targetUserId, credentials ); + + - return new JSONWithPadding( response, callback ); ++ return response; + } + @POST @Path("password") @@@ -202,9 -292,7 +302,9 @@@ @POST @Path("sendpin") - public JSONWithPadding postSendPin( @Context UriInfo ui, + @JSONP - @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) ++ @Produces({ MediaType.APPLICATION_JSON, "application/javascript"}) + public ApiResponse postSendPin( @Context UriInfo ui, @QueryParam("callback") @DefaultValue("callback") String callback ) throws Exception { return sendPin( ui, callback ); http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/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 28d8c87,ac07aaa..f48168e --- 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 @@@ -17,34 -17,29 +17,40 @@@ package org.apache.usergrid.rest.management.organizations; -import java.util.*; -import javax.ws.rs.*; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.UriInfo; +import com.fasterxml.jackson.jaxrs.json.annotation.JSONP; +import com.google.common.base.Preconditions; +import org.apache.commons.lang.StringUtils; +import org.apache.usergrid.management.ApplicationCreator; +import org.apache.usergrid.management.OrganizationInfo; +import org.apache.usergrid.management.OrganizationOwnerInfo; +import org.apache.usergrid.management.exceptions.ManagementException; +import org.apache.usergrid.persistence.index.query.Identifier; +import org.apache.usergrid.rest.AbstractContextResource; +import org.apache.usergrid.rest.ApiResponse; import org.apache.usergrid.rest.RootResource; import org.apache.usergrid.rest.management.ManagementResource; +import org.apache.usergrid.rest.security.annotations.RequireOrganizationAccess; + import org.apache.usergrid.rest.security.annotations.RequireSystemAccess; ++ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; -import org.apache.usergrid.management.ApplicationCreator; -import org.apache.usergrid.management.OrganizationInfo; -import org.apache.usergrid.management.OrganizationOwnerInfo; -import org.apache.usergrid.management.exceptions.ManagementException; -import org.apache.usergrid.rest.AbstractContextResource; -import org.apache.usergrid.rest.ApiResponse; -import org.apache.usergrid.rest.security.annotations.RequireOrganizationAccess; -import org.apache.commons.lang.StringUtils; -import com.google.common.base.Preconditions; -import com.sun.jersey.api.json.JSONWithPadding; + +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.ArrayList; ++import java.util.HashMap; ++import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static org.apache.usergrid.rest.exceptions.SecurityException.mappableSecurityException; +import static org.apache.usergrid.security.shiro.utils.SubjectUtils.isPermittedAccessToOrganization; @Component( "org.apache.usergrid.rest.management.organizations.OrganizationsResource" ) @@@ -67,7 -62,34 +73,34 @@@ public class OrganizationsResource exte public OrganizationsResource() { } + + @GET + @RequireSystemAccess - public JSONWithPadding getAllOrganizations() throws Exception{ ++ public ApiResponse getAllOrganizations() throws Exception{ + + ApiResponse response = createApiResponse(); + List<OrganizationInfo> orgs = management.getOrganizations(null, 10000); + List<Object> jsonOrgList = new ArrayList<>(); + + for(OrganizationInfo org: orgs){ + + + Map<String, Object> jsonOrg = new HashMap<>(); + Map<String, UUID> apps = management.getApplicationsForOrganization(org.getUuid()).inverse(); + + jsonOrg.put("name", org.getName()); + jsonOrg.put("uuid", org.getUuid()); + jsonOrg.put("properties", org.getProperties()); + jsonOrg.put("applications", apps); + jsonOrgList.add(jsonOrg); + } + + response.setProperty("organizations", jsonOrgList); - return new JSONWithPadding(response); ++ ++ return response; + } + @Path(RootResource.ORGANIZATION_ID_PATH) - @RequireOrganizationAccess public OrganizationResource getOrganizationById( @Context UriInfo ui, @PathParam( "organizationId" ) String organizationIdStr ) throws Exception { http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/rest/src/main/java/org/apache/usergrid/rest/system/ConnectionResource.java ---------------------------------------------------------------------- diff --cc stack/rest/src/main/java/org/apache/usergrid/rest/system/ConnectionResource.java index 0000000,14b79f3..ff2a739 mode 000000,100644..100644 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/system/ConnectionResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/system/ConnectionResource.java @@@ -1,0 -1,218 +1,216 @@@ + /* + * 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.rest.system; + + + import java.util.HashMap; + import java.util.Map; + import java.util.UUID; + import java.util.concurrent.TimeUnit; + import java.util.concurrent.atomic.AtomicLong; + + import javax.ws.rs.DefaultValue; + 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.MediaType; + + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import org.springframework.context.annotation.Scope; + import org.springframework.stereotype.Component; + + import org.apache.usergrid.corepersistence.service.ConnectionService; + import org.apache.usergrid.corepersistence.service.ConnectionServiceImpl; + import org.apache.usergrid.corepersistence.service.StatusService; + import org.apache.usergrid.corepersistence.util.CpNamingUtils; + import org.apache.usergrid.persistence.core.scope.ApplicationScope; + import org.apache.usergrid.persistence.index.query.Identifier; + import org.apache.usergrid.persistence.index.utils.UUIDUtils; + import org.apache.usergrid.persistence.model.util.UUIDGenerator; + import org.apache.usergrid.rest.AbstractContextResource; + import org.apache.usergrid.rest.ApiResponse; + import org.apache.usergrid.rest.RootResource; + import org.apache.usergrid.rest.security.annotations.RequireSystemAccess; + + import com.google.common.base.Preconditions; -import com.sun.jersey.api.json.JSONWithPadding; + + import rx.Observable; -import rx.functions.Action1; + import rx.schedulers.Schedulers; + + + /** + * system/index/otherstuff + */ + @Component + @Scope( "singleton" ) + @Produces( { + MediaType.APPLICATION_JSON, "application/javascript", "application/x-javascript", "text/ecmascript", + "application/ecmascript", "text/jscript" + } ) + public class ConnectionResource extends AbstractContextResource { + + private static final Logger logger = LoggerFactory.getLogger( ConnectionResource.class ); + + public ConnectionResource() { + super(); + } + + + @RequireSystemAccess + @POST + @Path( "dedup/" + RootResource.APPLICATION_ID_PATH ) - public JSONWithPadding rebuildIndexesPost( @PathParam( "applicationId" ) String applicationIdStr, - @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) ++ public ApiResponse rebuildIndexesPost( @PathParam( "applicationId" ) String applicationIdStr, ++ @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) + throws Exception { + + + logger.info( "Rebuilding all applications" ); + + final UUID applicationId = UUIDUtils.tryGetUUID( applicationIdStr ); + + Preconditions.checkNotNull( applicationId, "applicationId must be specified" ); + + return executeAndCreateResponse( applicationId, callback ); + } + + + @RequireSystemAccess + @GET + @Path( "dedup/{jobId: " + Identifier.UUID_REX + "}" ) - public JSONWithPadding rebuildIndexesGet( @PathParam( "jobId" ) String jobId, - @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) ++ public ApiResponse rebuildIndexesGet( @PathParam( "jobId" ) String jobId, ++ @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) + throws Exception { + logger.info( "Getting status for index jobs" ); + + Preconditions.checkNotNull( jobId, "query param jobId must not be null" ); + + + final UUID jobUUID = UUIDUtils.tryGetUUID( jobId ); + + final StatusService.JobStatus + job = getStatusService().getStatus( CpNamingUtils.MANAGEMENT_APPLICATION_ID, jobUUID ).toBlocking().lastOrDefault( + null ); + + Preconditions.checkNotNull( job, "job with id '" + jobId + "' does not exist" ); + + + return createResult( job, callback ); + } + + + private ConnectionService getConnectionService() { + return injector.getInstance( ConnectionServiceImpl.class ); + } + + + private StatusService getStatusService() { + return injector.getInstance( StatusService.class ); + } + + + + /** + * Execute the request and return the response. + */ - private JSONWithPadding executeAndCreateResponse( final UUID applicationId, final String callback ) { ++ private ApiResponse executeAndCreateResponse( final UUID applicationId, final String callback ) { + + final Observable<ApplicationScope> applicationScopeObservable = + Observable.just( CpNamingUtils.getApplicationScope( applicationId ) ); + + final UUID jobId = UUIDGenerator.newTimeUUID(); + + final StatusService statusService = getStatusService(); + final ConnectionService connectionService = getConnectionService(); + + final AtomicLong count = new AtomicLong( 0 ); + + //start de duping and run in the background + connectionService.deDupeConnections( applicationScopeObservable ).buffer( 10, TimeUnit.SECONDS, 1000 ) + .doOnNext(buffer -> { + + + final long runningTotal = count.addAndGet(buffer.size()); + + final Map<String, Object> status = new HashMap<String, Object>() {{ + put("countProcessed", runningTotal); + put("updatedTimestamp", System.currentTimeMillis()); + }}; + + statusService.setStatus(CpNamingUtils.MANAGEMENT_APPLICATION_ID, jobId, + StatusService.Status.INPROGRESS, status).toBlocking().lastOrDefault(null); + }).doOnSubscribe(() -> { + + statusService.setStatus(CpNamingUtils.MANAGEMENT_APPLICATION_ID, + jobId, StatusService.Status.STARTED, new HashMap<>()).toBlocking().lastOrDefault(null); + + }).doOnCompleted(() -> { + + final long runningTotal = count.get(); + + final Map<String, Object> status = new HashMap<String, Object>() {{ + put("countProcessed", runningTotal); + put("updatedTimestamp", System.currentTimeMillis()); + }}; + + statusService.setStatus(CpNamingUtils.MANAGEMENT_APPLICATION_ID, + jobId, StatusService.Status.COMPLETE, status).toBlocking().lastOrDefault(null); + + }).doOnError( (throwable) -> { + logger.error("Error deduping connections", throwable); + + final Map<String, Object> status = new HashMap<String, Object>() {{ + put("error", throwable.getMessage() ); + }}; + + statusService.setStatus(CpNamingUtils.MANAGEMENT_APPLICATION_ID, + jobId, StatusService.Status.FAILED, status).toBlocking().lastOrDefault(null);; + + } ).subscribeOn(Schedulers.newThread()).subscribe(); + + + final StatusService.JobStatus status = + new StatusService.JobStatus( jobId, StatusService.Status.STARTED, new HashMap<>( ) ); + + return createResult( status, callback ); + } + + + /** + * Create a response with the specified data. + * @param jobStatus + * @param callback + * @return + */ - private JSONWithPadding createResult(final StatusService.JobStatus jobStatus, final String callback){ ++ private ApiResponse createResult(final StatusService.JobStatus jobStatus, final String callback){ + + final ApiResponse response = createApiResponse(); + + response.setAction( "de-dup connections" ); + response.setProperty( "status", jobStatus ); + response.setSuccess(); + - return new JSONWithPadding( response, callback ); ++ return response; + } + } + + + http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/rest/src/main/java/org/apache/usergrid/rest/system/DatabaseResource.java ---------------------------------------------------------------------- diff --cc stack/rest/src/main/java/org/apache/usergrid/rest/system/DatabaseResource.java index b261c96,42a63ca..f3ce8b7 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/system/DatabaseResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/system/DatabaseResource.java @@@ -34,8 -31,12 +34,10 @@@ import org.slf4j.LoggerFactory import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; + import org.apache.usergrid.rest.AbstractContextResource; + import org.apache.usergrid.rest.ApiResponse; import org.apache.usergrid.rest.security.annotations.RequireSystemAccess; -import com.sun.jersey.api.json.JSONWithPadding; - @Component @Scope( "singleton" ) http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/rest/src/main/java/org/apache/usergrid/rest/system/IndexResource.java ---------------------------------------------------------------------- diff --cc stack/rest/src/main/java/org/apache/usergrid/rest/system/IndexResource.java index 0000000,8e2946c..bbbe8b3 mode 000000,100644..100644 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/system/IndexResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/system/IndexResource.java @@@ -1,0 -1,331 +1,353 @@@ + /* + * + * * Licensed to the Apache Software Foundation (ASF) under one or more + * * contributor license agreements. 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. For additional information regarding + * * copyright in this work, please see the NOTICE file in the top level + * * directory of this distribution. + * + */ + + package org.apache.usergrid.rest.system; + + ++import com.fasterxml.jackson.jaxrs.json.annotation.JSONP; + import com.google.common.base.Preconditions; -import com.sun.jersey.api.json.JSONWithPadding; + import org.apache.usergrid.corepersistence.index.ReIndexRequestBuilder; + import org.apache.usergrid.corepersistence.index.ReIndexRequestBuilderImpl; + import org.apache.usergrid.corepersistence.index.ReIndexService; + import org.apache.usergrid.persistence.EntityManager; + import org.apache.usergrid.persistence.index.utils.ConversionUtils; + import org.apache.usergrid.persistence.index.utils.UUIDUtils; + import org.apache.usergrid.rest.AbstractContextResource; + import org.apache.usergrid.rest.ApiResponse; + import org.apache.usergrid.rest.RootResource; + import org.apache.usergrid.rest.security.annotations.RequireSystemAccess; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import org.springframework.context.annotation.Scope; + import org.springframework.stereotype.Component; + + 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.HashMap; + import java.util.Map; + import java.util.UUID; + + + /** + * system/index/otherstuff + */ + @Component + @Scope( "singleton" ) + @Produces( { + MediaType.APPLICATION_JSON, "application/javascript", "application/x-javascript", "text/ecmascript", + "application/ecmascript", "text/jscript" + } ) + public class IndexResource extends AbstractContextResource { + + private static final Logger logger = LoggerFactory.getLogger( IndexResource.class ); + private static final String UPDATED_FIELD = "updated"; + + + + public IndexResource() { + super(); + } + + + @RequireSystemAccess + @POST + @Path( "rebuild" ) - public JSONWithPadding rebuildIndexesPost( @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) ++ public ApiResponse rebuildIndexesPost( @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) + throws Exception { + + + logger.info("Rebuilding all applications"); + + final ReIndexRequestBuilder request = createRequest(); + + return executeAndCreateResponse( request, callback ); + } + + @RequireSystemAccess + @GET + @Path( "rebuild/{jobId}" ) - public JSONWithPadding rebuildIndexesGet(@PathParam( "jobId" ) String jobId, @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) ++ @JSONP ++ @Produces({ MediaType.APPLICATION_JSON, "application/javascript" }) ++ public ApiResponse rebuildIndexesGet( ++ @PathParam( "jobId" ) String jobId, ++ @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) ++ ++ + throws Exception { + logger.info("Getting status for index jobs"); + + Preconditions + .checkNotNull(jobId, "query param jobId must not be null" ); + + + ReIndexService.ReIndexStatus status = getReIndexService().getStatus(jobId); + + final ApiResponse response = createApiResponse(); + + response.setAction( "rebuild indexes" ); + response.setProperty( "jobId", status.getJobId() ); + response.setProperty( "status", status.getStatus() ); + response.setProperty( "lastUpdatedEpoch", status.getLastUpdated() ); + response.setProperty( "numberQueued", status.getNumberProcessed() ); + response.setSuccess(); + - return new JSONWithPadding( response, callback ); ++ return response; + } + + @RequireSystemAccess + @PUT + @Path( "rebuild" ) - public JSONWithPadding rebuildIndexesPut( final Map<String, Object> payload, ++ @JSONP ++ @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) ++ public ApiResponse rebuildIndexesPut( final Map<String, Object> payload, + @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) + throws Exception { + + + logger.info( "Resuming rebuilding all applications" ); + final ReIndexRequestBuilder request = createRequest(); + + return executeResumeAndCreateResponse( payload, request, callback ); + } + + + @RequireSystemAccess + @POST + @Path( "rebuild/" + RootResource.APPLICATION_ID_PATH ) - public JSONWithPadding rebuildIndexesPut( @PathParam( "applicationId" ) String applicationIdStr, ++ @JSONP ++ @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) ++ public ApiResponse rebuildIndexesPut( @PathParam( "applicationId" ) String applicationIdStr, + @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback, + @QueryParam( "delay" ) @DefaultValue( "10" ) final long delay ) + + throws Exception { + + + logger.info( "Rebuilding application {}", applicationIdStr ); + + + final UUID appId = UUIDUtils.tryExtractUUID( applicationIdStr ); + + final ReIndexRequestBuilder request = createRequest().withApplicationId( appId ); + + return executeAndCreateResponse( request, callback ); + } + + + @RequireSystemAccess + @PUT + @Path( "rebuild/" + RootResource.APPLICATION_ID_PATH ) - public JSONWithPadding rebuildIndexesPut( final Map<String, Object> payload, ++ @JSONP ++ @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) ++ public ApiResponse rebuildIndexesPut( final Map<String, Object> payload, + @PathParam( "applicationId" ) String applicationIdStr, + @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback, + @QueryParam( "delay" ) @DefaultValue( "10" ) final long delay ) + + throws Exception { + + logger.info( "Resuming rebuilding application {}", applicationIdStr ); + + final UUID appId = UUIDUtils.tryExtractUUID( applicationIdStr ); + + final ReIndexRequestBuilder request = createRequest().withApplicationId( appId ); + + return executeResumeAndCreateResponse( payload, request, callback ); + } + + + @RequireSystemAccess + @POST + @Path( "rebuild/" + RootResource.APPLICATION_ID_PATH + "/{collectionName}" ) - public JSONWithPadding rebuildIndexesPost( @PathParam( "applicationId" ) final String applicationIdStr, ++ @JSONP ++ @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) ++ public ApiResponse rebuildIndexesPost( @PathParam( "applicationId" ) final String applicationIdStr, + @PathParam( "collectionName" ) final String collectionName, + @QueryParam( "reverse" ) @DefaultValue( "false" ) final Boolean reverse, + @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) + throws Exception { + + + logger.info( "Rebuilding collection {} in application {}", collectionName, applicationIdStr ); + + final UUID appId = UUIDUtils.tryExtractUUID( applicationIdStr ); + + final ReIndexRequestBuilder request = + createRequest().withApplicationId( appId ).withCollection( collectionName ); + + return executeAndCreateResponse( request, callback ); + } + + + @RequireSystemAccess + @PUT + @Path( "rebuild/" + RootResource.APPLICATION_ID_PATH + "/{collectionName}" ) - public JSONWithPadding rebuildIndexesPut( final Map<String, Object> payload, ++ @JSONP ++ @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) ++ public ApiResponse rebuildIndexesPut( final Map<String, Object> payload, + @PathParam( "applicationId" ) final String applicationIdStr, + @PathParam( "collectionName" ) final String collectionName, + @QueryParam( "reverse" ) @DefaultValue( "false" ) final Boolean reverse, + @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) + throws Exception { + + logger.info( "Resuming rebuilding collection {} in application {}", collectionName, applicationIdStr ); + + final UUID appId = UUIDUtils.tryExtractUUID( applicationIdStr ); + + final ReIndexRequestBuilder request = + createRequest().withApplicationId( appId ).withCollection( collectionName ); + + return executeResumeAndCreateResponse( payload, request, callback ); + } + + + @RequireSystemAccess + @POST + @Path( "rebuild/management" ) - public JSONWithPadding rebuildInternalIndexesPost( ++ @JSONP ++ @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) ++ public ApiResponse rebuildInternalIndexesPost( + @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) throws Exception { + + + final UUID managementAppId = emf.getManagementAppId(); + + logger.info( "Rebuilding management application with id {} ", managementAppId ); + final ReIndexRequestBuilder request = createRequest().withApplicationId( managementAppId ); + + return executeAndCreateResponse( request, callback ); + } + + + @RequireSystemAccess + @PUT + @Path( "rebuild/management" ) - public JSONWithPadding rebuildInternalIndexesPut( final Map<String, Object> payload, ++ @JSONP ++ @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) ++ public ApiResponse rebuildInternalIndexesPut( final Map<String, Object> payload, + @QueryParam( "callback" ) @DefaultValue( "callback" ) + String callback ) throws Exception { + + + final UUID managementAppId = emf.getManagementAppId(); + + logger.info( "Resuming rebuilding management application with id {} ", managementAppId ); + final ReIndexRequestBuilder request = createRequest().withApplicationId( managementAppId ); + + return executeResumeAndCreateResponse( payload, request, callback ); + } + + + @RequireSystemAccess + @POST + @Path(RootResource.APPLICATION_ID_PATH) - public JSONWithPadding addIndex( @Context UriInfo ui, ++ @JSONP ++ @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) ++ public ApiResponse addIndex( @Context UriInfo ui, + @PathParam( "applicationId" ) final String applicationIdStr, + Map<String, Object> config, + @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) + throws Exception { + + Preconditions + .checkNotNull( config, "Payload for config is null, please pass {replicas:int, shards:int} in body" ); + + ApiResponse response = createApiResponse(); + + if ( !config.containsKey( "replicas" ) || !config.containsKey( "shards" ) || + !( config.get( "replicas" ) instanceof Integer ) || !( config.get( "shards" ) instanceof Integer ) ) { + throw new IllegalArgumentException( "body must contains 'replicas' of type int and 'shards' of type int" ); + } + + if ( !config.containsKey( "indexSuffix" ) ) { + throw new IllegalArgumentException( "Please add an indexSuffix to your post" ); + } + final UUID appId = UUIDUtils.tryExtractUUID( applicationIdStr ); + + if(appId == null){ + throw new IllegalArgumentException("app id was not parsed"); + } + + EntityManager em = emf.getEntityManager(appId); + em.addIndex(config.get("indexSuffix").toString(), (int) config.get("shards"), + (int) config.get("replicas"), (String) config.get("writeConsistency")); + response.setAction( "Add index to alias" ); + - return new JSONWithPadding( response, callback ); ++ return response; + } + + + private ReIndexService getReIndexService() { + return injector.getInstance( ReIndexService.class ); + } + + + private ReIndexRequestBuilder createRequest() { + //TODO: wire this up through spring, and in the future guice. + return new ReIndexRequestBuilderImpl(); + } + + - private JSONWithPadding executeResumeAndCreateResponse( final Map<String, Object> payload, ++ private ApiResponse executeResumeAndCreateResponse( final Map<String, Object> payload, + final ReIndexRequestBuilder request, + final String callback ) { + + Map<String,Object> newPayload = payload; + if(newPayload == null || !payload.containsKey( UPDATED_FIELD )){ + newPayload = new HashMap<>(1); + newPayload.put(UPDATED_FIELD,0); + } + + Preconditions.checkArgument(newPayload.get(UPDATED_FIELD) instanceof Number, + "You must specified the field \"updated\" in the payload and it must be a timestamp" ); + + //add our updated timestamp to the request + if ( newPayload.containsKey( UPDATED_FIELD ) ) { + final long timestamp = ConversionUtils.getLong(newPayload.get(UPDATED_FIELD)); + request.withStartTimestamp( timestamp ); + } + + return executeAndCreateResponse( request, callback ); + } + + + /** + * Execute the request and return the response. + */ - private JSONWithPadding executeAndCreateResponse( final ReIndexRequestBuilder request, final String callback ) { ++ private ApiResponse executeAndCreateResponse( final ReIndexRequestBuilder request, final String callback ) { + + + final ReIndexService.ReIndexStatus status = getReIndexService().rebuildIndex( request ); + + final ApiResponse response = createApiResponse(); + + response.setAction( "rebuild indexes" ); + response.setProperty( "jobId", status.getJobId() ); + response.setProperty( "status", status.getStatus() ); + response.setProperty( "lastUpdatedEpoch", status.getLastUpdated() ); + response.setProperty( "numberQueued", status.getNumberProcessed() ); + response.setSuccess(); + - return new JSONWithPadding( response, callback ); ++ return response; + } + } http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/rest/src/main/java/org/apache/usergrid/rest/system/MigrateResource.java ---------------------------------------------------------------------- diff --cc stack/rest/src/main/java/org/apache/usergrid/rest/system/MigrateResource.java index 0000000,c5a6dbc..7a6100b mode 000000,100644..100644 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/system/MigrateResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/system/MigrateResource.java @@@ -1,0 -1,270 +1,277 @@@ + /* + * 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.rest.system; + + -import java.util.Map; -import java.util.Set; - -import javax.ws.rs.*; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.UriInfo; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; - ++import com.fasterxml.jackson.databind.node.JsonNodeFactory; ++import com.fasterxml.jackson.databind.node.ObjectNode; ++import com.fasterxml.jackson.jaxrs.json.annotation.JSONP; ++import com.google.common.base.Preconditions; ++import com.google.inject.Injector; + import org.apache.usergrid.persistence.core.migration.data.DataMigrationManager; + import org.apache.usergrid.persistence.core.migration.schema.MigrationManager; + import org.apache.usergrid.rest.AbstractContextResource; + import org.apache.usergrid.rest.ApiResponse; + import org.apache.usergrid.rest.security.annotations.RequireSystemAccess; ++import org.slf4j.Logger; ++import org.slf4j.LoggerFactory; ++import org.springframework.beans.factory.annotation.Autowired; ++import org.springframework.context.annotation.Scope; ++import org.springframework.stereotype.Component; + -import com.fasterxml.jackson.databind.node.JsonNodeFactory; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.base.Preconditions; -import com.google.inject.Injector; -import com.sun.jersey.api.json.JSONWithPadding; ++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.Map; ++import java.util.Set; + + + @Component + @Scope( "singleton" ) + @Produces( { + MediaType.APPLICATION_JSON, + "application/javascript", + "application/x-javascript", + "text/ecmascript", + "application/ecmascript", + "text/jscript" + } ) + public class MigrateResource extends AbstractContextResource { + + private static final Logger logger = LoggerFactory.getLogger( MigrateResource.class ); + + public MigrateResource() { + logger.info( "SystemResource initialized" ); + } + + @Autowired + private Injector guiceInjector; + + @RequireSystemAccess + @PUT + @Path( "run" ) - public JSONWithPadding migrateData( @Context UriInfo ui, ++ @JSONP ++ @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) ++ public ApiResponse migrateData( @Context UriInfo ui, + @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) + throws Exception { + + ApiResponse response = createApiResponse(); + response.setAction( "Migrate Data" ); + //TODO make this use the task scheduler + + + final Thread migrate = new Thread() { + + @Override + public void run() { + + logger.info( "Migrating Schema" ); + + try { + getMigrationManager().migrate(); + } + catch ( Exception e ) { + logger.error( "Unable to migrate data", e ); + } + + logger.info( "Migrating Data" ); + + try { + getDataMigrationManager().migrate(); + } + catch ( Exception e ) { + logger.error( "Unable to migrate data", e ); + } + } + }; + + migrate.setName( "Index migrate data formats" ); + migrate.setDaemon( true ); + migrate.start(); + + response.setSuccess(); + - return new JSONWithPadding( response, callback ); ++ return response; + } + + @RequireSystemAccess + @PUT + @Path( "run/{pluginName}" ) - public JSONWithPadding migrateData(@PathParam("pluginName") String pluginName , @Context UriInfo ui, ++ @JSONP ++ @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) ++ public ApiResponse migrateData(@PathParam("pluginName") String pluginName , @Context UriInfo ui, + @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) + throws Exception { + + if(!getDataMigrationManager().pluginExists(pluginName)){ + throw new IllegalArgumentException("Plugin doesn't exits name:"+pluginName); + } + + ApiResponse response = createApiResponse(); + response.setAction( "Migrate Data: "+ pluginName ); + //TODO make this use the task scheduler + + + + + final Thread migrate = new Thread() { + + @Override + public void run() { + + logger.info( "Migrating Data for plugin: " + pluginName ); + + try { + getDataMigrationManager().migrate(pluginName); + } + catch ( Exception e ) { + logger.error( "Unable to migrate data for plugin: " + pluginName, e ); + } + } + }; + + migrate.setName( "Index migrate data formats: "+pluginName ); + migrate.setDaemon( true ); + migrate.start(); + + response.setSuccess(); + - return new JSONWithPadding( response, callback ); ++ return response; + } + + @RequireSystemAccess + @PUT + @Path( "set" ) - public JSONWithPadding setMigrationVersion( ++ @JSONP ++ @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) ++ public ApiResponse setMigrationVersion( + @Context UriInfo ui, Map<String, Object> json, + @QueryParam( "callback" ) @DefaultValue( "" ) String callback ) + throws Exception { + + logger.debug( "setMigrationVersion" ); + + Preconditions.checkNotNull( json, "You must provide a json body" ); + Preconditions.checkArgument( json.keySet().size() > 0, "You must specify at least one module and version" ); + + ApiResponse response = createApiResponse(); + response.setAction("Set Migration Versions"); + + ObjectNode node = JsonNodeFactory.instance.objectNode(); + + final DataMigrationManager dataMigrationManager = getDataMigrationManager(); + final Set<String> plugins = dataMigrationManager.getPluginNames(); + + /** + * Set the migration version for the plugins specified + */ + for ( final String key : json.keySet() ) { + + int version = ( int ) json.get( key ); + + dataMigrationManager.resetToVersion(key, version); + } + + + /** + * Echo back a response of the current versions for all plugins + */ + for(final String pluginName: plugins){ + node.put(pluginName, dataMigrationManager.getCurrentVersion(pluginName)); + } + + + response.setData( node ); + response.setSuccess(); + - return new JSONWithPadding( response, callback ); ++ return response; + } + + + @RequireSystemAccess + @GET + @Path( "status" ) - public JSONWithPadding migrateStatus( ++ @JSONP ++ @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) ++ public ApiResponse migrateStatus( + @Context UriInfo ui, + @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) + throws Exception { + + ApiResponse response = createApiResponse(); + response.setAction( "Migrate Schema indexes" ); + + ObjectNode node = JsonNodeFactory.instance.objectNode(); + + + + final DataMigrationManager dataMigrationManager = getDataMigrationManager(); + + final Set<String> plugins = dataMigrationManager.getPluginNames(); + + for(final String pluginName: plugins){ + node.put( pluginName, dataMigrationManager.getCurrentVersion( pluginName ) ); + } + + response.setData( node ); + + response.setSuccess(); + - return new JSONWithPadding( response, callback ); ++ return response; + } + + + @RequireSystemAccess + @GET + @Path( "count" ) - public JSONWithPadding migrateCount( ++ @JSONP ++ @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) ++ public ApiResponse migrateCount( + @Context UriInfo ui, + @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) + throws Exception { + + ApiResponse response = createApiResponse(); + response.setAction( "Current entity count in system" ); + + response.setProperty( "count", emf.performEntityCount() ); + + response.setSuccess(); + - return new JSONWithPadding( response, callback ); ++ return response; + } + + + /** + * Get the schema migration manager + */ + private MigrationManager getMigrationManager() { + return guiceInjector.getInstance( MigrationManager.class ); + } + + /** + * Get the Data migration manager + */ + private DataMigrationManager getDataMigrationManager() { + return guiceInjector.getInstance( DataMigrationManager.class ); + } + } + http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/rest/src/main/java/org/apache/usergrid/rest/system/SystemResource.java ---------------------------------------------------------------------- diff --cc stack/rest/src/main/java/org/apache/usergrid/rest/system/SystemResource.java index 0000000,a5174e6..a83756d mode 000000,100644..100644 --- a/stack/rest/src/main/java/org/apache/usergrid/rest/system/SystemResource.java +++ b/stack/rest/src/main/java/org/apache/usergrid/rest/system/SystemResource.java @@@ -1,0 -1,108 +1,121 @@@ + /* + * 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.rest.system; + + + import javax.ws.rs.DefaultValue; + import javax.ws.rs.GET; + 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.UriInfo; + ++import org.apache.usergrid.rest.system.ApplicationsResource; ++import org.apache.usergrid.rest.system.DatabaseResource; ++import org.apache.usergrid.rest.system.QueueSystemResource; + import org.slf4j.Logger; + import org.slf4j.LoggerFactory; + import org.springframework.context.annotation.Scope; + import org.springframework.stereotype.Component; + + import org.apache.usergrid.rest.AbstractContextResource; + import org.apache.usergrid.rest.ApiResponse; + import org.apache.usergrid.rest.security.annotations.RequireSystemAccess; + -import com.sun.jersey.api.json.JSONWithPadding; ++import javax.ws.rs.*; ++import javax.ws.rs.core.Context; ++import javax.ws.rs.core.MediaType; ++import javax.ws.rs.core.UriInfo; + + + @Path( "/system" ) + @Component + @Scope( "singleton" ) + @Produces( { + MediaType.APPLICATION_JSON, "application/javascript", "application/x-javascript", "text/ecmascript", + "application/ecmascript", "text/jscript" + } ) + public class SystemResource extends AbstractContextResource { + + private static final Logger logger = LoggerFactory.getLogger( SystemResource.class ); + + + public SystemResource() { + logger.info( "SystemResource initialized" ); + } + + + @RequireSystemAccess + @GET ++ + @Path( "superuser/setup" ) - public JSONWithPadding getSetupSuperuser( @Context UriInfo ui, - @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) ++ @Produces({MediaType.APPLICATION_JSON, "application/javascript"}) ++ public ApiResponse getSetupSuperuser( @Context UriInfo ui, ++ @QueryParam( "callback" ) @DefaultValue( "callback" ) String callback ) + throws Exception { + + ApiResponse response = createApiResponse(); + response.setAction( "superuser setup" ); + + logger.info( "Setting up Superuser" ); + + try { + management.provisionSuperuser(); + } + catch ( Exception e ) { + logger.error( "Unable to complete superuser setup", e ); + } + + response.setSuccess(); + - return new JSONWithPadding( response, callback ); ++ return response; + } + + + + @Path( "migrate" ) + public MigrateResource migrate() { + return getSubResource( MigrateResource.class ); + } + + + @Path( "index" ) + public IndexResource index() { return getSubResource( IndexResource.class ); } + + + @Path( "database" ) + public DatabaseResource database() { + return getSubResource( DatabaseResource.class ); + } + ++ @Path( "queue" ) ++ public QueueSystemResource queue() { ++ return getSubResource( QueueSystemResource.class ); ++ } ++ + @Path( "applications" ) + public ApplicationsResource applications() { + return getSubResource( ApplicationsResource.class ); + } + + + @Path( "connection" ) + public ConnectionResource connection() { return getSubResource( ConnectionResource.class ); } + + } http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/users/UserResourceIT.java ---------------------------------------------------------------------- diff --cc stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/users/UserResourceIT.java index 0df2416,f258f94..eddf7ed --- a/stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/users/UserResourceIT.java +++ b/stack/rest/src/test/java/org/apache/usergrid/rest/applications/collection/users/UserResourceIT.java @@@ -18,6 -18,6 +18,10 @@@ package org.apache.usergrid.rest.applic import com.fasterxml.jackson.databind.JsonNode; ++import com.sun.jersey.api.client.UniformInterfaceException; ++import com.sun.jersey.api.client.WebResource; ++import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; ++ import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@@ -27,6 -27,6 +31,8 @@@ import java.util.UUID import org.apache.usergrid.rest.test.resource.AbstractRestIT; import org.apache.usergrid.rest.test.resource.endpoints.CollectionEndpoint; import org.apache.usergrid.rest.test.resource.model.*; ++ ++import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; @@@ -36,10 -36,16 +42,14 @@@ import org.slf4j.LoggerFactory import org.apache.usergrid.rest.applications.utils.UserRepo; import org.apache.usergrid.utils.UUIDUtils; -import com.sun.jersey.api.client.ClientResponse.Status; -import com.sun.jersey.api.client.GenericType; -import com.sun.jersey.api.client.UniformInterfaceException; -import com.sun.jersey.api.client.WebResource; -import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter; - ++import javax.ws.rs.BadRequestException; +import javax.ws.rs.ClientErrorException; ++import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Response; import java.io.IOException; + import javax.ws.rs.core.MediaType; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@@ -1129,4 -1109,105 +1139,111 @@@ public class UserResourceIT extends Abs assertEquals(response.getResponse().getEntities().get(0).get("uuid").toString(), userId.toString()); } + + + + @Test + public void testCredentialsTransfer() throws Exception { + + usersResource.post(new User("test_1", "Test1 User", "tes...@test.com", "test123")); // client.setApiUrl(apiUrl); + refreshIndex(); + + //Entity appInfo = this.app().get().getResponse().getEntities().get(0); + + Token token = this.app().token().post(new Token("test_1", "test123")); + + assertNotNull(token.getAccessToken()); + + final String superUserName = this.clientSetup.getSuperuserName(); + final String superUserPassword = this.clientSetup.getSuperuserPassword(); + + + //get the credentials info + final CollectionEndpoint collection = userResource.entity("test_1").collection( "credentials" ); + - final WebResource resource = collection.getResource(); ++ final WebTarget resource = collection.getTarget(); ++ ++ ++ final HttpAuthenticationFeature httpBasicAuth = HttpAuthenticationFeature.basicBuilder() ++ .credentials( superUserName, superUserPassword ).build(); + - resource.addFilter( new HTTPBasicAuthFilter(superUserName, superUserPassword) ); + ++ final ApiResponse response = resource.register( httpBasicAuth ).request() ++ .accept( MediaType.APPLICATION_JSON ).get( ++ org.apache.usergrid.rest.test.resource.model.ApiResponse.class ); + + - final ApiResponse response = resource.type( MediaType.APPLICATION_JSON_TYPE) - .accept( MediaType.APPLICATION_JSON ).get( org.apache.usergrid.rest.test.resource.model.ApiResponse.class ); + + + //now get the credentials sub object + + final Map<String, Object> credentials = ( Map<String, Object> ) response.getProperties().get( "credentials" ); + + + + //get out the hash and change it so we can validate + final String originalSecret = ( String ) credentials.get( "secret" ); + + + //here we modify the hash a little, this way we can break password validation, then re-set it to ensure we're actually updating the credentials info correctly. + final String borkedSecret = originalSecret.substring( 0, originalSecret.length() -1 ); + + credentials.put( "secret", borkedSecret ); + + //now PUT it + + + final Map<String, Map<String, Object>> wrapper = new HashMap<>( ); + wrapper.put( "credentials", credentials ); + - final WebResource putResource = collection.getResource(); ++ final WebTarget putResource = collection.getTarget(); + - putResource.addFilter( new HTTPBasicAuthFilter(superUserName, superUserPassword) ); + + - putResource.type( MediaType.APPLICATION_JSON_TYPE) - .accept( MediaType.APPLICATION_JSON ).put( - org.apache.usergrid.rest.test.resource.model.ApiResponse.class, wrapper ); ++ putResource.register( httpBasicAuth ).request() ++ .accept( MediaType.APPLICATION_JSON ) ++ .put( javax.ws.rs.client.Entity.json(wrapper), org.apache.usergrid.rest.test.resource.model.ApiResponse.class ); + + + //now try to get a password, it should fail because the hash is no longer correct + + int status = 0; + + // bad access token + try { + this.app().token().post(new Token("test_1", "test123")); + fail("Should have thrown an exception"); - } catch (UniformInterfaceException uie) { ++ } catch (BadRequestException uie) { + status = uie.getResponse().getStatus(); - log.info("Error Response Body: " + uie.getResponse().getEntity(String.class)); ++ log.info("Error Response Body: {}" , uie.getResponse().getEntity()); + } + - assertEquals(Status.BAD_REQUEST.getStatusCode(), status); ++ assertEquals( Response.Status.BAD_REQUEST.getStatusCode(), status); + + + //now put the correct one + + + credentials.put( "secret", originalSecret ); + + - final WebResource putResource2 = collection.getResource(); ++ final WebTarget putResource2 = collection.getTarget(); ++ ++ ++ ++ putResource2.register( httpBasicAuth ).request() ++ .accept( MediaType.APPLICATION_JSON ) ++ .put( javax.ws.rs.client.Entity.json( wrapper ), ++ org.apache.usergrid.rest.test.resource.model.ApiResponse.class ); + - putResource2.addFilter( new HTTPBasicAuthFilter( superUserName, superUserPassword ) ); + + - putResource2.type( MediaType.APPLICATION_JSON_TYPE) - .accept( MediaType.APPLICATION_JSON ).put( - org.apache.usergrid.rest.test.resource.model.ApiResponse.class, wrapper ); + + + //now auth, should be good + final Token nextToken = this.app().token().post(new Token("test_1", "test123")); + + assertNotNull( nextToken.getAccessToken() ); + + } } http://git-wip-us.apache.org/repos/asf/usergrid/blob/b422364e/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java ----------------------------------------------------------------------