You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by sn...@apache.org on 2015/05/28 21:43:21 UTC

[45/50] [abbrv] incubator-usergrid git commit: Merge branch 'master' into two-dot-o

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/rest/src/test/java/org/apache/usergrid/rest/management/ManagementResourceIT.java
----------------------------------------------------------------------
diff --cc stack/rest/src/test/java/org/apache/usergrid/rest/management/ManagementResourceIT.java
index 9b6e842,cec172d..7955ebc
--- a/stack/rest/src/test/java/org/apache/usergrid/rest/management/ManagementResourceIT.java
+++ b/stack/rest/src/test/java/org/apache/usergrid/rest/management/ManagementResourceIT.java
@@@ -17,86 -17,176 +17,103 @@@
  package org.apache.usergrid.rest.management;
  
  
--import java.util.ArrayList;
--import java.util.HashMap;
--import java.util.LinkedHashMap;
--import java.util.List;
--import java.util.Map;
--import java.util.UUID;
--
--import javax.ws.rs.core.MediaType;
--
 +import com.fasterxml.jackson.databind.JsonNode;
- 
- import org.junit.Rule;
- import org.junit.Test;
- 
- import org.apache.commons.lang.StringUtils;
- 
- 
- import org.apache.usergrid.management.OrganizationInfo;
++import com.sun.jersey.api.client.ClientResponse.Status;
++import com.sun.jersey.api.client.UniformInterfaceException;
++import com.sun.jersey.api.representation.Form;
+ import org.apache.commons.lang.RandomStringUtils;
 -import org.codehaus.jackson.JsonNode;
 -import org.junit.Test;
 -
 -import org.apache.commons.lang.StringUtils;
 -
 -import org.apache.usergrid.cassandra.Concurrent;
 -import org.apache.usergrid.management.OrganizationInfo;
  import org.apache.usergrid.management.OrganizationOwnerInfo;
 +import org.apache.usergrid.persistence.index.utils.UUIDUtils;
  import org.apache.usergrid.rest.AbstractRestIT;
- import org.apache.usergrid.rest.TestContextSetup;
  import org.apache.usergrid.rest.management.organizations.OrganizationsResource;
 -
 -import com.sun.jersey.api.client.ClientResponse.Status;
 -import com.sun.jersey.api.client.UniformInterfaceException;
 -import com.sun.jersey.api.representation.Form;
++import org.junit.Test;
+ import org.slf4j.Logger;
+ import org.slf4j.LoggerFactory;
  
- import com.sun.jersey.api.client.ClientResponse.Status;
- import com.sun.jersey.api.client.UniformInterfaceException;
- import com.sun.jersey.api.representation.Form;
- 
 -import static org.apache.usergrid.utils.MapUtils.hashMap;
++import javax.ws.rs.core.MediaType;
 +import java.io.IOException;
++import java.util.*;
  
+ import static org.apache.usergrid.rest.management.ManagementResource.USERGRID_CENTRAL_URL;
 +import static org.apache.usergrid.utils.MapUtils.hashMap;
- import static org.junit.Assert.assertEquals;
- import static org.junit.Assert.assertNotNull;
- import static org.junit.Assert.assertNull;
- import static org.junit.Assert.assertTrue;
+ import static org.junit.Assert.*;
  
  
  /**
   * @author tnine
   */
 -@Concurrent()
 +
  public class ManagementResourceIT extends AbstractRestIT {
  
-     @Rule
-     public TestContextSetup context = new TestContextSetup( this );
+     private static final Logger logger = LoggerFactory.getLogger(ManagementResourceIT.class);
  
 +
      public ManagementResourceIT() throws Exception {
  
      }
  
  
      /**
+      * Test if we can reset our password as an admin
+      */
+     @Test
+     public void setSelfAdminPasswordAsAdmin() {
+ 
+         String newPassword = "foo";
+ 
+         Map<String, String> data = new HashMap<String, String>();
+         data.put( "newpassword", newPassword );
+         data.put( "oldpassword", "test" );
+ 
+         // change the password as admin. The old password isn't required
+         JsonNode node = resource().path( "/management/users/test/password" ).accept( MediaType.APPLICATION_JSON )
+                                   .type( MediaType.APPLICATION_JSON_TYPE ).post( JsonNode.class, data );
+ 
+         assertNull( getError( node ) );
+ 
+         adminAccessToken = mgmtToken( "test", newPassword );
+ 
+         data.put( "oldpassword", newPassword );
+         data.put( "newpassword", "test" );
+ 
+         node = resource().path( "/management/users/test/password" ).queryParam( "access_token", adminAccessToken )
+                          .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE )
+                          .post( JsonNode.class, data );
+ 
+         assertNull( getError( node ) );
+     }
+ 
+ 
 -    @Test
 -    public void passwordMismatchErrorAdmin() {
 -        String origPassword = "foo";
 -        String newPassword = "bar";
 -
 -        Map<String, String> data = new HashMap<String, String>();
 -        data.put( "newpassword", origPassword );
 -
 -        // now change the password, with an incorrect old password
 -
 -        data.put( "oldpassword", origPassword );
 -        data.put( "newpassword", newPassword );
 -
 -        Status responseStatus = null;
 -
 -        try {
 -            resource().path( "/management/users/test/password" ).accept( MediaType.APPLICATION_JSON )
 -                      .type( MediaType.APPLICATION_JSON_TYPE ).post( JsonNode.class, data );
 -        }
 -        catch ( UniformInterfaceException uie ) {
 -            responseStatus = uie.getResponse().getClientResponseStatus();
 -        }
 -
 -        assertNotNull( responseStatus );
 -
 -        assertEquals( Status.BAD_REQUEST, responseStatus );
 -    }
 -
 -
 -    @Test
 -    public void setAdminPasswordAsSysAdmin() {
 -
 -        String superToken = superAdminToken();
 -
 -        String newPassword = "foo";
 -
 -        Map<String, String> data = new HashMap<String, String>();
 -        data.put( "newpassword", newPassword );
 -
 -        // change the password as admin. The old password isn't required
 -        JsonNode node = resource().path( "/management/users/test/password" ).queryParam( "access_token", superToken )
 -                                  .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE )
 -                                  .post( JsonNode.class, data );
 -
 -        assertNull( getError( node ) );
 -
 -        // log in with the new password
 -        String token = mgmtToken( "test", newPassword );
 -
 -        assertNotNull( token );
 -
 -        data.put( "newpassword", "test" );
 -
 -        // now change the password back
 -        node = resource().path( "/management/users/test/password" ).queryParam( "access_token", superToken )
 -                         .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE )
 -                         .post( JsonNode.class, data );
 -
 -        assertNull( getError( node ) );
 -    }
 -
+ 
+     /**
       * Test that admins can't view organizations they're not authorized to view.
       */
      @Test
      public void crossOrgsNotViewable() throws Exception {
  
 -        OrganizationOwnerInfo orgInfo = setup.getMgmtSvc().createOwnerAndOrganization( "crossOrgsNotViewable",
 -                "crossOrgsNotViewable", "TestName", "crossOrgsNotViewable@usergrid.org", "password" );
 +        String username = "test" + UUIDUtils.newTimeUUID();
 +        String name = username;
 +        String email = username + "@usergrid.com";
 +        String password = "password";
 +        String orgName = username;
  
 -        // check that the test admin cannot access the new org info
 -
 -        Status status = null;
 +        Map payload =
 +                hashMap( "email", email ).map( "username", username ).map( "name", name ).map( "password", password )
 +                                         .map( "organization", orgName ).map( "company", "Apigee" );
  
 -        try {
 -            resource().path( String.format( "/management/orgs/%s", orgInfo.getOrganization().getName() ) )
 -                      .queryParam( "access_token", adminAccessToken ).accept( MediaType.APPLICATION_JSON )
 -                      .type( MediaType.APPLICATION_JSON_TYPE ).get( JsonNode.class );
 -        }
 -        catch ( UniformInterfaceException uie ) {
 -            status = uie.getResponse().getClientResponseStatus();
 -        }
 +        JsonNode node = mapper.readTree(
 +                resource().path( "/management/organizations" ).accept( MediaType.APPLICATION_JSON )
 +                          .type( MediaType.APPLICATION_JSON_TYPE ).post( String.class, payload ) );
  
 -        assertNotNull( status );
 -        assertEquals( Status.UNAUTHORIZED, status );
 +        // check that the test admin cannot access the new org info
  
 -        status = null;
 +        Status status = null;
  
          try {
 -            resource().path( String.format( "/management/orgs/%s", orgInfo.getOrganization().getUuid() ) )
 -                      .queryParam( "access_token", adminAccessToken ).accept( MediaType.APPLICATION_JSON )
 -                      .type( MediaType.APPLICATION_JSON_TYPE ).get( JsonNode.class );
++            this.
 +            resource().path( String.format( "/management/orgs/%s", orgName ) )
-                       .queryParam( "access_token", context.getActiveUser().getToken() )
++                      .queryParam( "access_token", this.adminToken() )
 +                      .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE ).get( String.class );
          }
          catch ( UniformInterfaceException uie ) {
              status = uie.getResponse().getClientResponseStatus();
@@@ -108,9 -198,9 +125,9 @@@
          // this admin should have access to test org
          status = null;
          try {
-             resource().path( "/management/orgs/" + context.getOrgName() )
-                       .queryParam( "access_token", context.getActiveUser().getToken() )
 -            resource().path( "/management/orgs/test-organization" ).queryParam( "access_token", adminAccessToken )
 -                      .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE )
 -                      .get( JsonNode.class );
++            resource().path( "/management/orgs/" + this.orgInfo.getName())
++                      .queryParam( "access_token", this.adminToken() )
 +                      .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE ).get( String.class );
          }
          catch ( UniformInterfaceException uie ) {
              status = uie.getResponse().getClientResponseStatus();
@@@ -122,9 -212,9 +139,9 @@@
  
          status = null;
          try {
-             resource().path( String.format( "/management/orgs/%s", context.getOrgUuid() ) )
-                       .queryParam( "access_token", context.getActiveUser().getToken() )
 -            resource().path( String.format( "/management/orgs/%s", org.getUuid() ) )
 -                      .queryParam( "access_token", adminAccessToken ).accept( MediaType.APPLICATION_JSON )
 -                      .type( MediaType.APPLICATION_JSON_TYPE ).get( JsonNode.class );
++            resource().path( String.format( "/management/orgs/%s", this.orgInfo.getUuid() ) )
++                      .queryParam( "access_token", this.adminToken() )
 +                      .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE ).get( String.class );
          }
          catch ( UniformInterfaceException uie ) {
              status = uie.getResponse().getClientResponseStatus();
@@@ -145,9 -245,6 +162,9 @@@
          for ( i = 0; i < 10; i++ ) {
              users1.add( "follower" + Integer.toString( i ) );
          }
 +
-         refreshIndex( context.getOrgName(), context.getAppName() );
++        refreshIndex( this.orgInfo.getName(), this.appInfo.getName() );
 +
          checkFeed( "leader1", users1 );
          //try with 11
          List<String> users2 = new ArrayList<String>();
@@@ -158,25 -255,17 +175,25 @@@
      }
  
  
 -    private void checkFeed( String leader, List<String> followers ) {
 +    private void checkFeed( String leader, List<String> followers ) throws IOException {
          JsonNode userFeed;
 +
          //create user
          createUser( leader );
-         refreshIndex( context.getOrgName(), context.getAppName() );
++        refreshIndex( this.orgInfo.getName(), this.appInfo.getName() );
 +
          String preFollowContent = leader + ": pre-something to look for " + UUID.randomUUID().toString();
 +
          addActivity( leader, leader + " " + leader + "son", preFollowContent );
-         refreshIndex( context.getOrgName(), context.getAppName() );
++        refreshIndex( this.orgInfo.getName(), this.appInfo.getName() );
 +
          String lastUser = followers.get( followers.size() - 1 );
          int i = 0;
          for ( String user : followers ) {
              createUser( user );
-             refreshIndex( context.getOrgName(), context.getAppName() );
++            refreshIndex( this.orgInfo.getName(), this.appInfo.getName() );
              follow( user, leader );
-             refreshIndex( context.getOrgName(), context.getAppName() );
++            refreshIndex( this.orgInfo.getName(), this.appInfo.getName() );
          }
          userFeed = getUserFeed( lastUser );
          assertTrue( userFeed.size() == 1 );
@@@ -186,9 -275,6 +203,9 @@@
          assertTrue( userFeed.size() == 1 );
          String postFollowContent = leader + ": something to look for " + UUID.randomUUID().toString();
          addActivity( leader, leader + " " + leader + "son", postFollowContent );
 +
-         refreshIndex( context.getOrgName(), context.getAppName() );
++        refreshIndex( this.orgInfo.getName(), this.appInfo.getName() );
 +
          //check feed
          userFeed = getUserFeed( lastUser );
          assertNotNull( userFeed );
@@@ -202,28 -288,25 +219,28 @@@
      private void createUser( String username ) {
          Map<String, Object> payload = new LinkedHashMap<String, Object>();
          payload.put( "username", username );
-         resource().path( "" + context.getOrgName() + "/" + context.getAppName() + "/users" )
-                   .queryParam( "access_token", context.getActiveUser().getToken() ).accept( MediaType.APPLICATION_JSON )
 -        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 );
++        resource().path( "" + orgInfo.getName() + "/" + appInfo.getName() + "/users" )
++                  .queryParam( "access_token", this.adminToken() ).accept( MediaType.APPLICATION_JSON )
 +                  .type( MediaType.APPLICATION_JSON_TYPE ).post( String.class, payload );
      }
  
  
 -    private JsonNode getUserFeed( String username ) {
 -        JsonNode userFeed = resource().path( "/test-organization/test-app/users/" + username + "/feed" )
 -                                      .queryParam( "access_token", access_token ).accept( MediaType.APPLICATION_JSON )
 -                                      .get( JsonNode.class );
 +    private JsonNode getUserFeed( String username ) throws IOException {
 +        JsonNode userFeed = mapper.readTree( resource()
-                 .path( "/" + context.getOrgName() + "/" + context.getAppName() + "/users/" + username + "/feed" )
-                 .queryParam( "access_token", context.getActiveUser().getToken() ).accept( MediaType.APPLICATION_JSON )
++                .path( "/" + orgInfo.getName() + "/" + appInfo.getName() + "/users/" + username + "/feed" )
++                .queryParam( "access_token", this.adminToken() ).accept( MediaType.APPLICATION_JSON )
 +                .get( String.class ) );
          return userFeed.get( "entities" );
      }
  
  
      private void follow( String user, String followUser ) {
          //post follow
 -        resource().path( "/test-organization/test-app/users/" + user + "/following/users/" + followUser )
 -                  .queryParam( "access_token", access_token ).accept( MediaType.APPLICATION_JSON )
 -                  .type( MediaType.APPLICATION_JSON_TYPE ).post( JsonNode.class, new HashMap<String, String>() );
 +        resource()
-                 .path( "/" + context.getOrgName() + "/" + context.getAppName() + "/users/" + user + "/following/users/"
-                         + followUser ).queryParam( "access_token", context.getActiveUser().getToken() )
++                .path( "/" + orgInfo.getName() + "/" + appInfo.getName() + "/users/" + user + "/following/users/"
++                        + followUser ).queryParam( "access_token", this.adminToken() )
 +                .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE )
 +                .post( String.class, new HashMap<String, String>() );
      }
  
  
@@@ -235,9 -318,9 +252,9 @@@
          actorMap.put( "displayName", name );
          actorMap.put( "username", user );
          activityPayload.put( "actor", actorMap );
-         resource().path( "/" + context.getOrgName() + "/" + context.getAppName() + "/users/" + user + "/activities" )
-                   .queryParam( "access_token", context.getActiveUser().getToken() ).accept( MediaType.APPLICATION_JSON )
 -        resource().path( "/test-organization/test-app/users/" + user + "/activities" )
 -                  .queryParam( "access_token", access_token ).accept( MediaType.APPLICATION_JSON )
 -                  .type( MediaType.APPLICATION_JSON_TYPE ).post( JsonNode.class, activityPayload );
++        resource().path( "/" + orgInfo.getName() + "/" + appInfo.getName() + "/users/" + user + "/activities" )
++                  .queryParam( "access_token", this.adminToken() ).accept( MediaType.APPLICATION_JSON )
 +                  .type( MediaType.APPLICATION_JSON_TYPE ).post( String.class, activityPayload );
      }
  
  
@@@ -247,45 -330,462 +264,475 @@@
          Map<String, String> data = new HashMap<String, String>();
          data.put( "name", "mgmt-org-app" );
  
-         String orgName = context.getOrgName();
++        String orgName = orgInfo.getName();
 +
          // POST /applications
 -        JsonNode appdata = resource().path( "/management/orgs/" + orgInfo.getUuid() + "/applications" )
 -                                     .queryParam( "access_token", adminToken() ).accept( MediaType.APPLICATION_JSON )
 -                                     .type( MediaType.APPLICATION_JSON_TYPE ).post( JsonNode.class, data );
 +        JsonNode appdata = mapper.readTree( resource().path( "/management/orgs/" + orgName + "/applications" )
-                                                       .queryParam( "access_token", context.getActiveUser().getToken() )
++                                                      .queryParam( "access_token", this.adminToken() )
 +                                                      .accept( MediaType.APPLICATION_JSON )
 +                                                      .type( MediaType.APPLICATION_JSON_TYPE )
 +                                                      .post( String.class, data ) );
          logNode( appdata );
          appdata = getEntity( appdata, 0 );
  
-         refreshIndex( orgName, context.getAppName() );
 -        assertEquals( "test-organization/mgmt-org-app", appdata.get( "name" ).asText() );
++        refreshIndex( this.orgInfo.getName(), this.appInfo.getName() );
 +
 +        assertEquals( orgName.toLowerCase() + "/mgmt-org-app", appdata.get( "name" ).asText() );
 +        assertNotNull( appdata.get( "metadata" ) );
 +        assertNotNull( appdata.get( "metadata" ).get( "collections" ) );
 +        assertNotNull( appdata.get( "metadata" ).get( "collections" ).get( "roles" ) );
 +        assertNotNull( appdata.get( "metadata" ).get( "collections" ).get( "roles" ).get( "title" ) );
          assertEquals( "Roles", appdata.get( "metadata" ).get( "collections" ).get( "roles" ).get( "title" ).asText() );
          assertEquals( 3, appdata.get( "metadata" ).get( "collections" ).get( "roles" ).get( "count" ).asInt() );
  
-         refreshIndex( orgName, context.getAppName() );
++        refreshIndex( this.orgInfo.getName(), this.appInfo.getName() );
 +
          // GET /applications/mgmt-org-app
 -        appdata = resource().path( "/management/orgs/" + orgInfo.getUuid() + "/applications/mgmt-org-app" )
 -                            .queryParam( "access_token", adminToken() ).accept( MediaType.APPLICATION_JSON )
 -                            .type( MediaType.APPLICATION_JSON_TYPE ).get( JsonNode.class );
 +        appdata = mapper.readTree(
-                 resource().path( "/management/orgs/" + context.getOrgUuid() + "/applications/mgmt-org-app" )
-                           .queryParam( "access_token", context.getActiveUser().getToken() )
++                resource().path( "/management/orgs/" + orgInfo.getUuid() + "/applications/mgmt-org-app" )
++                          .queryParam( "access_token", this.adminToken() )
 +                          .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE )
 +                          .get( String.class ) );
          logNode( appdata );
  
 -        assertEquals( "test-organization", appdata.get( "organization" ).asText() );
 +        assertEquals( orgName.toLowerCase(), appdata.get( "organization" ).asText() );
          assertEquals( "mgmt-org-app", appdata.get( "applicationName" ).asText() );
 -        assertEquals( "http://sometestvalue/test-organization/mgmt-org-app", appdata.get( "uri" ).getTextValue() );
 +        assertEquals( "http://sometestvalue/" + orgName.toLowerCase() + "/mgmt-org-app",
 +                appdata.get( "uri" ).textValue() );
          appdata = getEntity( appdata, 0 );
  
 -        assertEquals( "test-organization/mgmt-org-app", appdata.get( "name" ).asText() );
 +        assertEquals( orgName.toLowerCase() + "/mgmt-org-app", appdata.get( "name" ).asText() );
          assertEquals( "Roles", appdata.get( "metadata" ).get( "collections" ).get( "roles" ).get( "title" ).asText() );
          assertEquals( 3, appdata.get( "metadata" ).get( "collections" ).get( "roles" ).get( "count" ).asInt() );
      }
+ 
 -
+     @Test
+     public void tokenTtl() throws Exception {
+ 
+         long ttl = 2000;
+ 
+         JsonNode node = resource().path( "/management/token" ).queryParam( "grant_type", "password" )
+                                   .queryParam( "username", "test@usergrid.com" ).queryParam( "password", "test" )
+                                   .queryParam( "ttl", String.valueOf( ttl ) ).accept( MediaType.APPLICATION_JSON )
+                                   .get( JsonNode.class );
+ 
+         long startTime = System.currentTimeMillis();
+ 
 -        String token = node.get( "access_token" ).getTextValue();
++        String token = node.get( "access_token" ).textValue();
+ 
+         assertNotNull( token );
+ 
+         JsonNode userdata = resource().path( "/management/users/test@usergrid.com" ).queryParam( "access_token", token )
+                                       .accept( MediaType.APPLICATION_JSON ).get( JsonNode.class );
+ 
+         assertEquals( "test@usergrid.com", userdata.get( "data" ).get( "email" ).asText() );
+ 
+         // wait for the token to expire
+         Thread.sleep( ttl - (System.currentTimeMillis() - startTime) + 1000 );
+ 
+         Status responseStatus = null;
+         try {
+             userdata = resource().path( "/management/users/test@usergrid.com" ).accept( MediaType.APPLICATION_JSON )
+                                  .type( MediaType.APPLICATION_JSON_TYPE ).get( JsonNode.class );
+         }
+         catch ( UniformInterfaceException uie ) {
+             responseStatus = uie.getResponse().getClientResponseStatus();
+         }
+ 
+         assertEquals( Status.UNAUTHORIZED, responseStatus );
+     }
+ 
+ 
+     @Test
+     public void token() throws Exception {
+         JsonNode node = resource().path( "/management/token" ).queryParam( "grant_type", "password" )
+                                   .queryParam( "username", "test@usergrid.com" ).queryParam( "password", "test" )
+                                   .accept( MediaType.APPLICATION_JSON ).get( JsonNode.class );
+ 
+         logNode( node );
 -        String token = node.get( "access_token" ).getTextValue();
++        String token = node.get( "access_token" ).textValue();
+         assertNotNull( token );
+ 
+         // set an organization property
+         HashMap<String, Object> payload = new HashMap<String, Object>();
+         Map<String, Object> properties = new HashMap<String, Object>();
+         properties.put( "securityLevel", 5 );
+         payload.put( OrganizationsResource.ORGANIZATION_PROPERTIES, properties );
+         node = resource().path( "/management/organizations/test-organization" )
+                          .queryParam( "access_token", superAdminToken() ).accept( MediaType.APPLICATION_JSON )
+                          .type( MediaType.APPLICATION_JSON_TYPE ).put( JsonNode.class, payload );
+ 
+         // ensure the organization property is included
+         node = resource().path( "/management/token" ).queryParam( "access_token", token )
+                          .accept( MediaType.APPLICATION_JSON ).get( JsonNode.class );
+         logNode( node );
+ 
+         JsonNode securityLevel = node.findValue( "securityLevel" );
+         assertNotNull( securityLevel );
+         assertEquals( 5L, securityLevel.asLong() );
+     }
+ 
+ 
+     @Test
+     public void meToken() throws Exception {
+         JsonNode node = resource().path( "/management/me" ).queryParam( "grant_type", "password" )
+                                   .queryParam( "username", "test@usergrid.com" ).queryParam( "password", "test" )
+                                   .accept( MediaType.APPLICATION_JSON ).get( JsonNode.class );
+ 
+         logNode( node );
 -        String token = node.get( "access_token" ).getTextValue();
++        String token = node.get( "access_token" ).textValue();
+         assertNotNull( token );
+ 
+         node = resource().path( "/management/me" ).queryParam( "access_token", token )
+                          .accept( MediaType.APPLICATION_JSON ).get( JsonNode.class );
+         logNode( node );
+ 
+         assertNotNull( node.get( "passwordChanged" ) );
+         assertNotNull( node.get( "access_token" ) );
+         assertNotNull( node.get( "expires_in" ) );
+         JsonNode userNode = node.get( "user" );
+         assertNotNull( userNode );
+         assertNotNull( userNode.get( "uuid" ) );
+         assertNotNull( userNode.get( "username" ) );
+         assertNotNull( userNode.get( "email" ) );
+         assertNotNull( userNode.get( "name" ) );
+         assertNotNull( userNode.get( "properties" ) );
+         JsonNode orgsNode = userNode.get( "organizations" );
+         assertNotNull( orgsNode );
+         JsonNode orgNode = orgsNode.get( "test-organization" );
+         assertNotNull( orgNode );
+         assertNotNull( orgNode.get( "name" ) );
+         assertNotNull( orgNode.get( "properties" ) );
+     }
+ 
+ 
+     @Test
+     public void meTokenPost() throws Exception {
+         Map<String, String> payload =
+                 hashMap( "grant_type", "password" ).map( "username", "test@usergrid.com" ).map( "password", "test" );
+ 
+         JsonNode node = resource().path( "/management/me" ).accept( MediaType.APPLICATION_JSON )
+                                   .type( MediaType.APPLICATION_JSON_TYPE ).post( JsonNode.class, payload );
+ 
+         logNode( node );
 -        String token = node.get( "access_token" ).getTextValue();
++        String token = node.get( "access_token" ).textValue();
+ 
+         assertNotNull( token );
+ 
+         node = resource().path( "/management/me" ).queryParam( "access_token", token )
+                          .accept( MediaType.APPLICATION_JSON ).get( JsonNode.class );
+         logNode( node );
+     }
+ 
+ 
+     @Test
+     public void meTokenPostForm() {
+ 
+         Form form = new Form();
+         form.add( "grant_type", "password" );
+         form.add( "username", "test@usergrid.com" );
+         form.add( "password", "test" );
+ 
+         JsonNode node = resource().path( "/management/me" ).accept( MediaType.APPLICATION_JSON )
+                                   .type( MediaType.APPLICATION_FORM_URLENCODED_TYPE )
+                                   .entity( form, MediaType.APPLICATION_FORM_URLENCODED_TYPE ).post( JsonNode.class );
+ 
+         logNode( node );
 -        String token = node.get( "access_token" ).getTextValue();
++        String token = node.get( "access_token" ).textValue();
+ 
+         assertNotNull( token );
+ 
+         node = resource().path( "/management/me" ).queryParam( "access_token", token )
+                          .accept( MediaType.APPLICATION_JSON ).get( JsonNode.class );
+         logNode( node );
+     }
+ 
+ 
+     @Test
+     public void ttlNan() throws Exception {
+ 
+         Map<String, String> payload =
+                 hashMap( "grant_type", "password" ).map( "username", "test@usergrid.com" ).map( "password", "test" )
+                                                    .map( "ttl", "derp" );
+ 
+         Status responseStatus = null;
+         try {
+             resource().path( "/management/token" ).accept( MediaType.APPLICATION_JSON )
+                       .type( MediaType.APPLICATION_JSON_TYPE ).post( JsonNode.class, payload );
+         }
+         catch ( UniformInterfaceException uie ) {
+             responseStatus = uie.getResponse().getClientResponseStatus();
+         }
+ 
+         assertEquals( Status.BAD_REQUEST, responseStatus );
+     }
+ 
+ 
+     @Test
+     public void ttlOverMax() throws Exception {
+ 
+         Map<String, String> payload =
+                 hashMap( "grant_type", "password" ).map( "username", "test@usergrid.com" ).map( "password", "test" )
+                                                    .map( "ttl", Long.MAX_VALUE + "" );
+ 
+         Status responseStatus = null;
+ 
+         try {
+             resource().path( "/management/token" ).accept( MediaType.APPLICATION_JSON )
+                       .type( MediaType.APPLICATION_JSON_TYPE ).post( JsonNode.class, payload );
+         }
+         catch ( UniformInterfaceException uie ) {
+             responseStatus = uie.getResponse().getClientResponseStatus();
+         }
+ 
+         assertEquals( Status.BAD_REQUEST, responseStatus );
+     }
+ 
+ 
+     @Test
+     public void revokeToken() throws Exception {
+         String token1 = super.adminToken();
+         String token2 = super.adminToken();
+ 
+         JsonNode response = resource().path( "/management/users/test" ).queryParam( "access_token", token1 )
+                                       .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE )
+                                       .get( JsonNode.class );
+ 
+         assertEquals( "test@usergrid.com", response.get( "data" ).get( "email" ).asText() );
+ 
+         response = resource().path( "/management/users/test" ).queryParam( "access_token", token2 )
+                              .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE )
+                              .get( JsonNode.class );
+ 
+         assertEquals( "test@usergrid.com", response.get( "data" ).get( "email" ).asText() );
+ 
+         // now revoke the tokens
+         response =
+                 resource().path( "/management/users/test/revoketokens" ).queryParam( "access_token", superAdminToken() )
+                           .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE )
+                           .post( JsonNode.class );
+ 
+         // the tokens shouldn't work
+ 
+         Status status = null;
+ 
+         try {
+             response = resource().path( "/management/users/test" ).queryParam( "access_token", token1 )
+                                  .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE )
+                                  .get( JsonNode.class );
+         }
+         catch ( UniformInterfaceException uie ) {
+             status = uie.getResponse().getClientResponseStatus();
+         }
+ 
+         assertEquals( Status.UNAUTHORIZED, status );
+ 
+         status = null;
+ 
+         try {
+             response = resource().path( "/management/users/test" ).queryParam( "access_token", token2 )
+                                  .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE )
+                                  .get( JsonNode.class );
+         }
+         catch ( UniformInterfaceException uie ) {
+             status = uie.getResponse().getClientResponseStatus();
+         }
+ 
+         assertEquals( Status.UNAUTHORIZED, status );
+ 
+         String token3 = super.adminToken();
+         String token4 = super.adminToken();
+ 
+         response = resource().path( "/management/users/test" ).queryParam( "access_token", token3 )
+                              .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE )
+                              .get( JsonNode.class );
+ 
+         assertEquals( "test@usergrid.com", response.get( "data" ).get( "email" ).asText() );
+ 
+         response = resource().path( "/management/users/test" ).queryParam( "access_token", token4 )
+                              .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE )
+                              .get( JsonNode.class );
+ 
+         assertEquals( "test@usergrid.com", response.get( "data" ).get( "email" ).asText() );
+ 
+         // now revoke the token3
+         response = resource().path( "/management/users/test/revoketoken" ).queryParam( "access_token", token3 )
+                              .queryParam( "token", token3 ).accept( MediaType.APPLICATION_JSON )
+                              .type( MediaType.APPLICATION_JSON_TYPE ).post( JsonNode.class );
+ 
+         // the token3 shouldn't work
+ 
+         status = null;
+ 
+         try {
+             response = resource().path( "/management/users/test" ).queryParam( "access_token", token3 )
+                                  .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE )
+                                  .get( JsonNode.class );
+         }
+         catch ( UniformInterfaceException uie ) {
+             status = uie.getResponse().getClientResponseStatus();
+         }
+ 
+         assertEquals( Status.UNAUTHORIZED, status );
+ 
+         status = null;
+ 
+         try {
+             response = resource().path( "/management/users/test" ).queryParam( "access_token", token4 )
+                                  .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE )
+                                  .get( JsonNode.class );
+ 
+             status = Status.OK;
+         }
+         catch ( UniformInterfaceException uie ) {
+             status = uie.getResponse().getClientResponseStatus();
+         }
+ 
+         assertEquals( Status.OK, status );
+     }
+ 
+ 
+     @Test
+     public void testValidateExternalToken() throws Exception {
+ 
+         // create a new admin user, get access token
+ 
+         String rand = RandomStringUtils.randomAlphanumeric(10);
+         final String username = "user_" + rand;
+         OrganizationOwnerInfo orgInfo = setup.getMgmtSvc().createOwnerAndOrganization(
+                 username, username, "Test User", username + "@example.com", "password" );
+ 
+         Map<String, Object> loginInfo = new HashMap<String, Object>() {{
+             put("username", username );
+             put("password", "password");
+             put("grant_type", "password");
+         }};
+         JsonNode accessInfoNode = resource().path("/management/token")
+             .type( MediaType.APPLICATION_JSON_TYPE )
+             .post( JsonNode.class, loginInfo );
 -        String accessToken = accessInfoNode.get( "access_token" ).getTextValue();
++        String accessToken = accessInfoNode.get( "access_token" ).textValue();
+ 
+         // set the Usergrid Central SSO URL because Tomcat port is dynamically assigned
+ 
+         String suToken = superAdminToken();
+         Map<String, String> props = new HashMap<String, String>();
+         props.put( USERGRID_CENTRAL_URL, getBaseURI().toURL().toExternalForm() );
+         resource().path( "/testproperties" )
+                 .queryParam( "access_token", suToken)
+                 .accept( MediaType.APPLICATION_JSON )
+                 .type( MediaType.APPLICATION_JSON_TYPE )
+                 .post( props );
+ 
+         // attempt to validate the token, must be valid
+ 
+         JsonNode validatedNode = resource().path( "/management/externaltoken" )
+             .queryParam( "access_token", suToken ) // as superuser
+             .queryParam( "ext_access_token", accessToken )
+             .queryParam( "ttl", "1000" )
+             .get( JsonNode.class );
 -        String validatedAccessToken = validatedNode.get( "access_token" ).getTextValue();
++        String validatedAccessToken = validatedNode.get( "access_token" ).textValue();
+         assertEquals( accessToken, validatedAccessToken );
+ 
+         // attempt to validate an invalid token, must fail
+ 
+         try {
+             resource().path( "/management/externaltoken" )
+                 .queryParam( "access_token", suToken ) // as superuser
+                 .queryParam( "ext_access_token", "rubbish_token")
+                 .queryParam( "ttl", "1000" )
+                 .get( JsonNode.class );
+             fail("Validation should have failed");
+         } catch ( UniformInterfaceException actual ) {
+             assertEquals( 404, actual.getResponse().getStatus() );
+             String errorMsg = actual.getResponse().getEntity( JsonNode.class ).get( "error_description" ).toString();
+             logger.error( "ERROR: " + errorMsg );
+             assertTrue( errorMsg.contains( "Cannot find Admin User" ) );
+         }
+ 
+ 
+ 
+         // TODO: how do we test the create new user and organization case?
+ 
+ 
+ 
+         // unset the Usergrid Central SSO URL so it does not interfere with other tests
+ 
+         props.put( USERGRID_CENTRAL_URL, "" );
+         resource().path( "/testproperties" )
+                 .queryParam( "access_token", suToken)
+                 .accept( MediaType.APPLICATION_JSON )
+                 .type( MediaType.APPLICATION_JSON_TYPE )
+                 .post( props );
+ 
+     }
+ 
+ 
+     @Test
+     public void testSuperuserOnlyWhenValidateExternalTokensEnabled() throws Exception {
+ 
+         // create an org and an admin user
+ 
+         String rand = RandomStringUtils.randomAlphanumeric( 10 );
+         final String username = "user_" + rand;
+         OrganizationOwnerInfo orgInfo = setup.getMgmtSvc().createOwnerAndOrganization(
+                 username, username, "Test User", username + "@example.com", "password" );
+ 
+         // turn on validate external tokens by setting the usergrid.central.url
+ 
+         String suToken = superAdminToken();
+         Map<String, String> props = new HashMap<String, String>();
+         props.put( USERGRID_CENTRAL_URL, getBaseURI().toURL().toExternalForm());
+         resource().path( "/testproperties" )
+                 .queryParam( "access_token", suToken)
+                 .accept( MediaType.APPLICATION_JSON )
+                 .type( MediaType.APPLICATION_JSON_TYPE )
+                 .post( props );
+ 
+         // calls to login as an Admin User must now fail
+ 
+         try {
+ 
+             Map<String, Object> loginInfo = new HashMap<String, Object>() {{
+                 put("username", username );
+                 put("password", "password");
+                 put("grant_type", "password");
+             }};
+             JsonNode accessInfoNode = resource().path("/management/token")
+                     .type( MediaType.APPLICATION_JSON_TYPE )
+                     .post( JsonNode.class, loginInfo );
+             fail("Login as Admin User must fail when validate external tokens is enabled");
+ 
+         } catch ( UniformInterfaceException actual ) {
+             assertEquals( 400, actual.getResponse().getStatus() );
+             String errorMsg = actual.getResponse().getEntity( JsonNode.class ).get( "error_description" ).toString();
+             logger.error( "ERROR: " + errorMsg );
+             assertTrue( errorMsg.contains( "Admin Users must login via" ));
+ 
+         } catch ( Exception e ) {
+             fail( "We expected a UniformInterfaceException" );
+         }
+ 
+         // login as superuser must succeed
+ 
+         Map<String, Object> loginInfo = new HashMap<String, Object>() {{
+             put("username", "superuser");
+             put("password", "superpassword");
+             put("grant_type", "password");
+         }};
+         JsonNode accessInfoNode = resource().path("/management/token")
+                 .type( MediaType.APPLICATION_JSON_TYPE )
+                 .post( JsonNode.class, loginInfo );
 -        String accessToken = accessInfoNode.get( "access_token" ).getTextValue();
++        String accessToken = accessInfoNode.get( "access_token" ).textValue();
+         assertNotNull( accessToken );
+ 
+         // turn off validate external tokens by un-setting the usergrid.central.url
+ 
+         props.put( USERGRID_CENTRAL_URL, "" );
+         resource().path( "/testproperties" )
+                 .queryParam( "access_token", suToken)
+                 .accept( MediaType.APPLICATION_JSON )
+                 .type( MediaType.APPLICATION_JSON_TYPE )
+                 .post( props );
+     }
+ 
  }

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/rest/src/test/java/org/apache/usergrid/rest/test/resource2point0/AbstractRestIT.java
----------------------------------------------------------------------
diff --cc stack/rest/src/test/java/org/apache/usergrid/rest/test/resource2point0/AbstractRestIT.java
index 4e3b480,0000000..9ae5e3b
mode 100644,000000..100644
--- a/stack/rest/src/test/java/org/apache/usergrid/rest/test/resource2point0/AbstractRestIT.java
+++ b/stack/rest/src/test/java/org/apache/usergrid/rest/test/resource2point0/AbstractRestIT.java
@@@ -1,179 -1,0 +1,177 @@@
 +/*
 + * 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.test.resource2point0;
 +
 +
 +import com.fasterxml.jackson.databind.JsonNode;
 +import com.fasterxml.jackson.databind.ObjectMapper;
 +import com.sun.jersey.api.client.UniformInterfaceException;
 +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.test.framework.AppDescriptor;
 +import com.sun.jersey.test.framework.JerseyTest;
 +import com.sun.jersey.test.framework.WebAppDescriptor;
 +import com.sun.jersey.test.framework.spi.container.TestContainerFactory;
 +import org.apache.usergrid.rest.TomcatRuntime;
 +import org.apache.usergrid.rest.test.resource2point0.endpoints.ApplicationsResource;
 +import org.apache.usergrid.rest.test.resource2point0.endpoints.OrganizationResource;
 +import org.apache.usergrid.rest.test.resource2point0.endpoints.mgmt.ManagementResource;
 +import org.apache.usergrid.rest.test.resource2point0.model.Token;
 +import org.apache.usergrid.rest.test.resource2point0.state.ClientContext;
 +import org.junit.Rule;
 +
 +import java.net.URI;
 +import java.net.URISyntaxException;
 +import java.net.URLClassLoader;
 +import java.util.Arrays;
 +
 +import static org.junit.Assert.assertEquals;
 +
 +
 +
 +/**
 + * Base class for REST tests.
 + */
 +//@RunWith( Arquillian.class )
 +public class AbstractRestIT extends JerseyTest {
 +
 +    private static ClientConfig clientConfig = new DefaultClientConfig();
 +
 +    public static TomcatRuntime tomcatRuntime = TomcatRuntime.getInstance();
 +
- 
- 
 +    @Rule
 +    public ClientSetup clientSetup = new ClientSetup( this.getBaseURI().toString() );
 +
 +    protected static final AppDescriptor descriptor;
 +
 +    public AbstractRestIT() {
 +        super( descriptor );
 +    }
 +
 +
 +    protected ObjectMapper mapper = new ObjectMapper();
 +
 +    static {
 +        clientConfig.getFeatures().put( JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE );
 +        descriptor = new WebAppDescriptor.Builder( "org.apache.usergrid.rest" )
 +                .clientConfig( clientConfig ).build();
 +        dumpClasspath( AbstractRestIT.class.getClassLoader() );
 +    }
 +
 +
 +//    //We set testable = false so we deploy the archive to the server and test it locally
 +//    @Deployment( testable = false )
 +//    public static WebArchive createTestArchive() {
 +//
 +//        //we use the MavenImporter from shrinkwrap to just produce whatever maven would build then test with it
 +//
 +//        //set maven to be in offline mode
 +//
 +//        System.setProperty( "org.apache.maven.offline", "true" );
 +//
 +//        return ShrinkWrap.create( MavenImporter.class ).loadPomFromFile( "pom.xml", "arquillian-tomcat" )
 +//                         .importBuildOutput().as( WebArchive.class );
 +//    }
 +
 +    public static void dumpClasspath( ClassLoader loader ) {
 +        System.out.println( "Classloader " + loader + ":" );
 +
 +        if ( loader instanceof URLClassLoader ) {
 +            URLClassLoader ucl = ( URLClassLoader ) loader;
 +            System.out.println( "\t" + Arrays.toString( ucl.getURLs() ) );
 +        }
 +        else {
 +            System.out.println( "\t(cannot display components as not a URLClassLoader)" );
 +        }
 +
 +        if ( loader.getParent() != null ) {
 +            dumpClasspath( loader.getParent() );
 +        }
 +    }
 +
 +    @Override
 +    protected URI getBaseURI() {
 +        try {
 +            return new URI("http://localhost:" + tomcatRuntime.getPort());
 +        } catch (URISyntaxException e) {
 +            throw new RuntimeException("Error determining baseURI", e);
 +        }
 +    }
 +
 +    @Override
 +    protected TestContainerFactory getTestContainerFactory() {
 +        return new com.sun.jersey.test.framework.spi.container.external.ExternalTestContainerFactory();
 +    }
 +
 +    ///myorg/
 +    protected OrganizationResource org(){
 +        return clientSetup.restClient.org( clientSetup.getOrganization().getName() );
 +    }
 +
 +    //myorg/myapp
 +    protected ApplicationsResource app(){
 +        return clientSetup.restClient.org(clientSetup.getOrganization().getName()).app(clientSetup.getAppName());
 +
 +    }
 +
 +    protected ManagementResource management(){
 +        return clientSetup.restClient.management();
 +    }
 +
 +    protected ClientContext context(){
 +        return this.clientSetup.getRestClient().getContext();
 +    }
 +
 +
 +    protected Token getAppUserToken(String username, String password){
 +        return this.app().token().post(new Token(username,password));
 +    }
 +
 +    public void refreshIndex() {
 +        //TODO: add error checking and logging
 +        clientSetup.refreshIndex();
 +    }
 +
 +
 +    /**
 +     * Takes in the expectedStatus message and the expectedErrorMessage then compares it to the UniformInterfaceException
 +     * to make sure that we got what we expected.
 +     * @param expectedStatus
 +     * @param expectedErrorMessage
 +     * @param uie
 +     */
 +    public void errorParse(int expectedStatus, String expectedErrorMessage, UniformInterfaceException uie){
 +        assertEquals(expectedStatus,uie.getResponse().getStatus());
 +        JsonNode errorJson = uie.getResponse().getEntity( JsonNode.class );
 +        assertEquals( expectedErrorMessage, errorJson.get( "error" ).asText() );
 +
 +    }
 +
 +
 +    protected Token getAdminToken(String username, String password){
 +        return this.clientSetup.getRestClient().management().token().post(
 +                new Token(username, password)
 +        );
 +    }
 +
 +    protected Token getAdminToken(){
 +        return this.clientSetup.getRestClient().management().token().post(
 +                new Token(this.clientSetup.getUsername(),this.clientSetup.getUsername())
 +        );
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/rest/src/test/java/org/apache/usergrid/rest/test/resource2point0/ClientSetup.java
----------------------------------------------------------------------
diff --cc stack/rest/src/test/java/org/apache/usergrid/rest/test/resource2point0/ClientSetup.java
index 3455744,0000000..e033c2d
mode 100644,000000..100644
--- a/stack/rest/src/test/java/org/apache/usergrid/rest/test/resource2point0/ClientSetup.java
+++ b/stack/rest/src/test/java/org/apache/usergrid/rest/test/resource2point0/ClientSetup.java
@@@ -1,140 -1,0 +1,152 @@@
 +/**
 + * Created by ApigeeCorporation on 12/4/14.
 + */
 +/*
 + * 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.test.resource2point0;
 +
 +
 +import java.io.IOException;
 +
 +import org.apache.usergrid.rest.test.resource2point0.model.Application;
 +import org.apache.usergrid.rest.test.resource2point0.model.Token;
 +import org.junit.rules.TestRule;
 +import org.junit.runner.Description;
 +import org.junit.runners.model.Statement;
 +
 +import org.apache.usergrid.persistence.index.utils.UUIDUtils;
 +import org.apache.usergrid.rest.test.resource2point0.model.Organization;
++import org.slf4j.Logger;
++import org.slf4j.LoggerFactory;
 +
 +import javax.ws.rs.core.MediaType;
 +
 +
 +/**
 + * This class is used to setup the client rule that will setup the RestClient and create default applications.
 + */
 +public class ClientSetup implements TestRule {
 +
++    private Logger logger = LoggerFactory.getLogger( ClientSetup.class );
++
 +    RestClient restClient;
 +
 +    protected String username;
 +    protected String password;
 +    protected String orgName;
 +    protected String appName;
 +    protected Token superuserToken;
 +    protected String superuserName = "superuser";
 +    protected String superuserPassword = "superpassword";
 +
 +    protected Organization organization;
 +    protected Application application;
 +
 +
 +    public ClientSetup (String serverUrl) {
 +
 +        restClient = new RestClient( serverUrl );
 +    }
 +
 +    public Statement apply( Statement base, Description description ) {
 +        return statement( base, description );
 +    }
 +
 +
 +    private Statement statement( final Statement base, final Description description ) {
 +        return new Statement() {
 +            @Override
 +            public void evaluate() throws Throwable {
 +                before( description );
 +                try {
 +                    base.evaluate();
 +                }
 +                finally {
 +                    cleanup();
 +                }
 +            }
 +        };
 +    }
 +
 +
 +    protected void cleanup() {
 +        // might want to do something here later
 +    }
 +
 +
 +    protected void before( Description description ) throws IOException {
 +        String testClass = description.getTestClass().getName();
 +        String methodName = description.getMethodName();
 +        String name = testClass + "." + methodName;
 +
-         restClient.superuserSetup();
-         superuserToken = restClient.management().token().post( new Token( superuserName, superuserPassword ) );
++        try {
++            restClient.superuserSetup();
++            superuserToken = restClient.management().token().post( new Token( superuserName, superuserPassword ) );
++        } catch ( Exception e ) {
++            if ( logger.isDebugEnabled() ) {
++                logger.debug( "Error creating superuser, may already exist", e );
++            } else {
++                logger.warn( "Error creating superuser, may already exist");
++            }
++        }
 +
 +        username = "user_"+name + UUIDUtils.newTimeUUID();
 +        password = username;
 +        orgName = "org_"+name+UUIDUtils.newTimeUUID();
 +        appName = "app_"+name+UUIDUtils.newTimeUUID();
 +
 +        organization = restClient.management().orgs().post(new Organization( orgName,username,username+"@usergrid.com",username,username, null  ));
 +
 +        restClient.management().token().post(new Token(username,username));
 +
 +        restClient.management().orgs().organization(organization.getName()).app().post(new Application(appName));
 +
 +    }
 +
 +    public String getUsername(){return username;}
 +
 +    public String getEmail(){return username+"@usergrid.com";}
 +
 +    public String getPassword(){return password;}
 +
 +    public Organization getOrganization(){return organization;}
 +
 +    public String getOrganizationName(){return orgName;}
 +
 +    public String getAppName() {return appName;}
 +
 +    public Token getSuperuserToken() {
 +        return superuserToken;
 +    }
 +
 +    public String getSuperuserName() {
 +        return superuserName;
 +    }
 +
 +    public String getSuperuserPassword() {
 +        return superuserPassword;
 +    }
 +
 +    public void refreshIndex() {
 +        this.restClient.refreshIndex(getOrganizationName(),getAppName());
 +    }
 +
 +    public RestClient getRestClient(){
 +        return restClient;
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/services/pom.xml
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java
----------------------------------------------------------------------
diff --cc stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java
index 0c319ca,5b77534..85ddcbb
--- a/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java
+++ b/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java
@@@ -1443,9 -1391,16 +1443,16 @@@ public class ManagementServiceImpl impl
      }
  
  
+     @Override
+     public void importTokenForAdminUser(UUID userId, String token, long ttl) throws Exception {
+         tokens.importToken( token, TokenCategory.ACCESS, null,
 -                new AuthPrincipalInfo( ADMIN_USER, userId, MANAGEMENT_APPLICATION_ID ), null, ttl );
++                new AuthPrincipalInfo( ADMIN_USER, userId, smf.getManagementAppId() ), null, ttl );
+     }
+ 
+ 
      /*
     * (non-Javadoc)
 -   * 
 +   *
     * @see
     * org.apache.usergrid.management.ManagementService#revokeAccessTokensForAdminUser
     * (java.util.UUID)

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/services/src/main/java/org/apache/usergrid/security/shiro/Realm.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/services/src/main/java/org/apache/usergrid/security/tokens/cassandra/TokenServiceImpl.java
----------------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/services/src/main/java/org/apache/usergrid/services/assets/data/S3BinaryStore.java
----------------------------------------------------------------------
diff --cc stack/services/src/main/java/org/apache/usergrid/services/assets/data/S3BinaryStore.java
index 90bd24f,f59e79c..a805e42
--- a/stack/services/src/main/java/org/apache/usergrid/services/assets/data/S3BinaryStore.java
+++ b/stack/services/src/main/java/org/apache/usergrid/services/assets/data/S3BinaryStore.java
@@@ -17,49 -17,45 +17,38 @@@
  package org.apache.usergrid.services.assets.data;
  
  
--import java.io.BufferedOutputStream;
--import java.io.ByteArrayOutputStream;
--import java.io.File;
--import java.io.FileOutputStream;
--import java.io.IOException;
--import java.io.InputStream;
--import java.io.OutputStream;
- import java.security.MessageDigest;
- import java.security.NoSuchAlgorithmException;
--import java.util.Map;
 -import java.util.Properties;
 -import java.util.Stack;
--import java.util.UUID;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
 -import java.util.concurrent.*;
--
- import com.google.common.hash.HashCode;
++import com.google.common.collect.ImmutableSet;
 +import com.google.common.hash.HashFunction;
 +import com.google.common.hash.Hashing;
 +import com.google.common.io.Files;
++import com.google.inject.Module;
++import org.apache.commons.codec.binary.Hex;
++import org.apache.commons.io.FileUtils;
++import org.apache.commons.io.IOUtils;
++import org.apache.usergrid.persistence.Entity;
++import org.apache.usergrid.persistence.EntityManager;
++import org.apache.usergrid.persistence.EntityManagerFactory;
+ import org.apache.usergrid.utils.StringUtils;
  import org.jclouds.ContextBuilder;
--import org.jclouds.blobstore.AsyncBlobStore;
  import org.jclouds.blobstore.BlobStore;
  import org.jclouds.blobstore.BlobStoreContext;
  import org.jclouds.blobstore.domain.Blob;
  import org.jclouds.blobstore.domain.BlobBuilder;
  import org.jclouds.blobstore.options.GetOptions;
--import org.jclouds.blobstore.options.PutOptions;
  import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
  import org.jclouds.logging.log4j.config.Log4JLoggingModule;
  import org.jclouds.netty.config.NettyPayloadModule;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.springframework.beans.factory.annotation.Autowired;
--import org.apache.usergrid.persistence.Entity;
--import org.apache.usergrid.persistence.EntityManager;
--import org.apache.usergrid.persistence.EntityManagerFactory;
- 
- import org.apache.commons.codec.binary.Hex;
- import org.apache.commons.io.FileUtils;
- import org.apache.commons.io.IOUtils;
  
 -import org.apache.commons.codec.binary.Hex;
 -import org.apache.commons.io.FileUtils;
 -import org.apache.commons.io.IOUtils;
 -
--import com.google.common.collect.ImmutableSet;
--import com.google.common.util.concurrent.ListenableFuture;
--import com.google.inject.Module;
++import java.io.*;
++import java.util.Map;
++import java.util.Properties;
++import java.util.UUID;
++import java.util.concurrent.Callable;
++import java.util.concurrent.ExecutorService;
++import java.util.concurrent.Executors;
  
  
  public class S3BinaryStore implements BinaryStore {
@@@ -115,18 -116,17 +109,19 @@@
          long written = IOUtils.copyLarge( inputStream, baos, 0, FIVE_MB );
          byte[] data = baos.toByteArray();
  
-         final Map<String, Object> fileMetadata = AssetUtils.getFileMetadata( entity );
-         fileMetadata.put( AssetUtils.LAST_MODIFIED, System.currentTimeMillis() );
+         if ( written < FIVE_MB ) { // total smaller than 5mb
  
-         String mimeType = AssetMimeHandler.get().getMimeType( entity, data );
+             final String uploadFileName = AssetUtils.buildAssetKey( appId, entity );
+             final String mimeType = AssetMimeHandler.get().getMimeType( entity, data );
  
-         if ( written < FIVE_MB ) { // total smaller than 5mb
+             final Map<String, Object> fileMetadata = AssetUtils.getFileMetadata( entity );
+             fileMetadata.put( AssetUtils.LAST_MODIFIED, System.currentTimeMillis() );
  
              BlobStore blobStore = getContext().getBlobStore();
 -            BlobBuilder.PayloadBlobBuilder bb = blobStore.blobBuilder( uploadFileName )
 -                    .payload( data ).calculateMD5().contentType( mimeType );
 +            BlobBuilder.PayloadBlobBuilder bb = blobStore.blobBuilder(uploadFileName)
-                 .payload(data)
-                 .contentMD5(Hashing.md5().newHasher().putBytes( data ).hash())
-                 .contentType(mimeType);
++                .payload( data )
++                .contentMD5( Hashing.md5().newHasher().putBytes( data ).hash() )
++                .contentType( mimeType );
  
              fileMetadata.put( AssetUtils.CONTENT_LENGTH, written );
              if ( fileMetadata.get( AssetUtils.CONTENT_DISPOSITION ) != null ) {
@@@ -142,56 -142,31 +137,30 @@@
          }
          else { // bigger than 5mb... dump 5 mb tmp files and upload from them
  
-             // todo: yes, AsyncBlobStore is deprecated, but there appears to be no replacement yet
-             final AsyncBlobStore blobStore = getContext().getAsyncBlobStore();
+             ExecutorService executors = getExecutorService();
  
-             File tempFile = File.createTempFile( entity.getUuid().toString(), "tmp" );
-             tempFile.deleteOnExit();
-             OutputStream os = null;
-             try {
-                 os = new BufferedOutputStream( new FileOutputStream( tempFile.getAbsolutePath() ) );
-                 os.write( data );
-                 written += IOUtils.copyLarge( inputStream, os, 0, ( FileUtils.ONE_GB * 5 ) );
-             }
-             finally {
-                 IOUtils.closeQuietly( os );
-             }
+             executors.submit( new UploadWorker( appId, entity, inputStream, data, written ) );
+         }
+     }
  
-             BlobBuilder.PayloadBlobBuilder bb = blobStore.blobBuilder( uploadFileName )
-                 .payload(tempFile)
-                 .contentMD5(Files.hash(tempFile, Hashing.md5()))
-                 .contentType(mimeType);
 -
+     private ExecutorService getExecutorService() {
  
-             fileMetadata.put( AssetUtils.CONTENT_LENGTH, written );
-             if ( fileMetadata.get( AssetUtils.CONTENT_DISPOSITION ) != null ) {
-                 bb.contentDisposition( fileMetadata.get( AssetUtils.CONTENT_DISPOSITION ).toString() );
-             }
-             final Blob blob = bb.build();
+         if ( executorService == null ) {
+             synchronized (this) {
  
-             final File finalTempFile = tempFile;
-             final ListenableFuture<String> future =
-                     blobStore.putBlob( bucketName, blob, PutOptions.Builder.multipart() );
+                 int workers = 40;
+                 String workersString = properties.getProperty( WORKERS_PROP_NAME, "40");
  
-             Runnable listener = new Runnable() {
-                 @Override
-                 public void run() {
-                     try {
-                         String eTag = future.get();
-                         fileMetadata.put( AssetUtils.E_TAG, eTag );
-                         EntityManager em = emf.getEntityManager( appId );
-                         em.update( entity );
-                         finalTempFile.delete();
-                     }
-                     catch ( Exception e ) {
-                         LOG.error( "error uploading", e );
-                     }
-                     if ( finalTempFile != null && finalTempFile.exists() ) {
-                         finalTempFile.delete();
-                     }
+                 if ( StringUtils.isNumeric( workersString ) ) {
+                     workers = Integer.parseInt( workersString );
+                 } else if ( !StringUtils.isEmpty( workersString )) {
+                     LOG.error("Ignoring invalid setting for {}", WORKERS_PROP_NAME);
                  }
-             };
-             future.addListener( listener, executor );
+                 executorService = Executors.newFixedThreadPool( workers );
+             }
          }
+ 
+         return executorService;
      }
  
  
@@@ -224,5 -199,124 +193,133 @@@
          BlobStore blobStore = getContext().getBlobStore();
          blobStore.removeBlob( bucketName, AssetUtils.buildAssetKey( appId, entity ) );
      }
+ 
+     class UploadWorker implements Callable<Void> {
+ 
+         private UUID appId;
+         private Entity entity;
+         private InputStream inputStream;
+         private byte[] data;
+         private long written;
+ 
+ 
+         public UploadWorker( UUID appId, Entity entity, InputStream is, byte[] data, long written ) {
+             this.appId = appId;
+             this.entity = entity;
+             this.inputStream = is;
+             this.data = data;
+             this.written = written;
+         }
+ 
+         @Override
+         public Void call() {
+ 
+             LOG.debug( "Writing temp file for S3 upload" );
+ 
+             // determine max size file allowed, default to 50mb
+             long maxSizeBytes = 50 * FileUtils.ONE_MB;
+             String maxSizeMbString = properties.getProperty( "usergrid.binary.max-size-mb", "50" );
+             if (StringUtils.isNumeric( maxSizeMbString )) {
+                 maxSizeBytes = Long.parseLong( maxSizeMbString ) * FileUtils.ONE_MB;
+             }
+ 
+             // always allow files up to 5mb
+             if (maxSizeBytes < 5 * FileUtils.ONE_MB ) {
+                 maxSizeBytes = 5 * FileUtils.ONE_MB;
+             }
+ 
+             // write temporary file, slightly larger than our size limit
+             OutputStream os = null;
+             File tempFile;
+             try {
+                 tempFile = File.createTempFile( entity.getUuid().toString(), "tmp" );
+                 tempFile.deleteOnExit();
+                 os = new BufferedOutputStream( new FileOutputStream( tempFile.getAbsolutePath() ) );
+                 os.write( data );
++                written += data.length;
+                 written += IOUtils.copyLarge( inputStream, os, 0, maxSizeBytes + 1 );
+ 
++                LOG.debug("Write temp file {} length {}", tempFile.getName(), written);
++
+             } catch ( IOException e ) {
+                 throw new RuntimeException( "Error creating temp file", e );
+ 
+             } finally {
+                 if ( os != null ) {
++                    try {
++                        os.flush();
++                    } catch (IOException e) {
++                        LOG.error( "Error flushing data to temporary upload file", e );
++                    }
+                     IOUtils.closeQuietly( os );
+                 }
+             }
+ 
+             // if tempFile is too large, delete it, add error to entity file metadata and abort
+ 
+             Map<String, Object> fileMetadata = AssetUtils.getFileMetadata( entity );
+ 
+             if ( tempFile.length() > maxSizeBytes ) {
+                 LOG.debug("File too large. Temp file size (bytes) = {}, " +
 -                        "Max file size (bytes) = {} ", tempFile.length(), maxSizeBytes);
++                          "Max file size (bytes) = {} ", tempFile.length(), maxSizeBytes);
+                 try {
+                     EntityManager em = emf.getEntityManager( appId );
+                     fileMetadata.put( "error", "Asset size " + tempFile.length()
+                                     + " is larger than max size of " + maxSizeBytes );
+                     em.update( entity );
+                     tempFile.delete();
+ 
+                 } catch ( Exception e ) {
+                     LOG.error( "Error updating entity with error message", e);
+                 }
+                 return null;
+             }
+ 
+             String uploadFileName = AssetUtils.buildAssetKey( appId, entity );
+             String mimeType = AssetMimeHandler.get().getMimeType( entity, data );
+ 
+             try {  // start the upload
+ 
+                 LOG.debug( "S3 upload thread started" );
+ 
+                 BlobStore blobStore = getContext().getBlobStore();
+ 
 -                BlobBuilder.PayloadBlobBuilder bb =  blobStore.blobBuilder( uploadFileName )
 -                        .payload( tempFile ).calculateMD5().contentType( mimeType );
++                BlobBuilder.PayloadBlobBuilder bb = blobStore.blobBuilder( uploadFileName )
++                    .payload( tempFile )
++                    .contentMD5( Files.hash( tempFile, Hashing.md5() ) )
++                    .contentType( mimeType );
+ 
+                 if ( fileMetadata.get( AssetUtils.CONTENT_DISPOSITION ) != null ) {
+                     bb.contentDisposition( fileMetadata.get( AssetUtils.CONTENT_DISPOSITION ).toString() );
+                 }
+                 final Blob blob = bb.build();
+ 
+                 String md5sum = Hex.encodeHexString( blob.getMetadata().getContentMetadata().getContentMD5() );
+                 fileMetadata.put( AssetUtils.CHECKSUM, md5sum );
+ 
+                 LOG.debug( "S3 upload starting" );
+ 
+                 String eTag = blobStore.putBlob( bucketName, blob );
+ 
+                 LOG.debug( "S3 upload complete eTag=" + eTag);
+ 
 -                // update entity with information about uploaded asset
 -
++                // update entity with eTag
+                 EntityManager em = emf.getEntityManager( appId );
 -                fileMetadata.put( AssetUtils.E_TAG, eTag );
+                 fileMetadata.put( AssetUtils.LAST_MODIFIED, System.currentTimeMillis() );
+                 fileMetadata.put( AssetUtils.CONTENT_LENGTH, written );
++                fileMetadata.put( AssetUtils.E_TAG, eTag );
+                 em.update( entity );
+             }
+             catch ( Exception e ) {
+                 LOG.error( "error uploading", e );
+             }
+ 
+             if ( tempFile != null && tempFile.exists() ) {
+                 tempFile.delete();
+             }
+ 
+             return null;
+         }
+     }
  }
  

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/a7840164/stack/services/src/test/java/org/apache/usergrid/security/tokens/TokenServiceIT.java
----------------------------------------------------------------------