blob: 5c98f9c8ce6b76b49ee547d44eb4b5ca1896a9a1 [file] [log] [blame]
/*
* 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.applications.collection;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.ws.rs.ClientErrorException;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.usergrid.persistence.Schema;
import org.apache.usergrid.persistence.entities.Application;
import org.apache.usergrid.persistence.index.utils.UUIDUtils;
import org.apache.usergrid.rest.test.resource.AbstractRestIT;
import org.apache.usergrid.rest.test.resource.model.ApiResponse;
import org.apache.usergrid.rest.test.resource.model.Collection;
import org.apache.usergrid.rest.test.resource.model.Entity;
import org.apache.usergrid.rest.test.resource.model.QueryParameters;
import org.apache.usergrid.rest.test.resource.model.Token;
import com.fasterxml.jackson.databind.JsonNode;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.fail;
/**
* @author zznate
* @author tnine
* @author rockerston
*
* misc tests for collections
*/
public class CollectionsResourceIT extends AbstractRestIT {
private static final Logger log = LoggerFactory.getLogger( CollectionsResourceIT.class );
/***
*
* Test to make sure we get a 400 back when posting to a bad path
*
*/
@Test
public void postToBadPath() throws IOException {
String app = "fakeapp";
String org = this.clientSetup.getOrganizationName();
String entity = "fakeentity";
//try to do a GET on a bad path
try {
this.clientSetup.getRestClient().org(org).app(app).collection("cities").get();
fail("Call to bad path exists, but it should not");
} catch (ClientErrorException e) {
//verify the correct error was returned
JsonNode node = mapper.readTree( e.getResponse().readEntity( String.class ));
assertEquals( "organization_application_not_found", node.get( "error" ).textValue() );
}
//try to do a POST on a bad path
Entity payload = new Entity();
payload.put("name", "Austin");
payload.put("state", "TX");
try {
this.clientSetup.getRestClient().org(org).app(app).collection("cities").post(payload);
fail("Call to bad path exists, but it should not");
} catch (ClientErrorException e) {
//verify the correct error was returned
JsonNode node = mapper.readTree( e.getResponse().readEntity( String.class ));
assertEquals( "organization_application_not_found", node.get( "error" ).textValue() );
}
//try to do a PUT on a bad path
try {
this.clientSetup.getRestClient().org(org).app(app).collection("cities").entity(entity).put(payload);
fail("Call to bad path exists, but it should not");
} catch (ClientErrorException e) {
//verify the correct error was returned
JsonNode node = mapper.readTree( e.getResponse().readEntity( String.class ));
assertEquals( "organization_application_not_found", node.get( "error" ).textValue() );
}
//try to do a delete on a bad path
try {
this.clientSetup.getRestClient().org(org).app(app).collection("cities").entity(entity).delete();
fail("Call to bad path exists, but it should not");
} catch (ClientErrorException e) {
//verify the correct error was returned
JsonNode node = mapper.readTree( e.getResponse().readEntity( String.class ));
assertEquals( "organization_application_not_found", node.get( "error" ).textValue() );
}
}
@Test
public void postToReservedField() throws Exception {
Entity payload = new Entity();
payload.put( "term_date", "12/31/9999" );
payload.put( "effective_date","2015-04-20T17:41:38.035Z" );
payload.put("junk","TEST");
this.app().collection( "testCollection" ).post( payload );
refreshIndex();
Thread.sleep( 1000 );
Collection collection = this.app().collection( "testCollection" ).get();
assertNotEquals(0, collection.getNumOfEntities() );
payload = new Entity();
payload.put( "term_date","1991-17-10" );
payload.put( "effective_date","HELLO WORLD!" );
payload.put("junk","TEST");
this.app().collection( "testCollection" ).post( payload );
refreshIndex();
Thread.sleep( 1000 );
collection = this.app().collection( "testCollection" ).get();
assertEquals( 2, collection.getNumOfEntities() );
}
/**
* Test posts with a user level token on a path with permissions
*/
//TODO: App level permissions aren't functioning.
@Test
public void permissionWithMeInString() throws Exception {
// create user
String username = "sumeet.agarwal@usergrid.com";
String email = "sumeet.agarwal@usergrid.com";
String password = "secret";
String name = "Sumeet Agarwal";
Entity payload = new Entity();
payload.put("username", username);
payload.put("email", email);
payload.put("password", password);
payload.put("name", name);
Entity user = this.app().collection("users").post(payload);
assertEquals(user.get("username"), username);
assertEquals(user.get("email"), email);
this.refreshIndex();
String collectionName = "nestprofiles";
//create a permission with the path "me" in it
payload = new Entity();
payload.put( "permission", "get,post,put,delete:/"+collectionName+"/**" );
//POST to /users/sumeet.agarwal@usergrid.com/permissions
Entity permission = this.app().collection("users").entity(user).collection("permissions").post(payload);
assertEquals(permission.get("data"), "get,post,put,delete:/"+collectionName+"/**");
//delete the default role, which would allow all authenticated requests
this.app().collection("role").uniqueID("Default").delete();
//log our new user in
//TODO:App Level token is broken it seems. Test won't work with it.
Token appToken = this.getAppUserToken(username, password);
management().token().setToken( appToken );
//now post data
payload = new Entity();
String profileName = "profile-sumeet";
payload.put( "name", profileName );
payload.put( "firstname", "sumeet" );
payload.put( "lastname", "agarwal" );
payload.put( "mobile", "122" );
Entity nestProfile = this.app().collection(collectionName).post(payload);
assertEquals(nestProfile.get("name"), profileName);
this.refreshIndex();
Entity nestprofileReturned = this.app().collection(collectionName).entity(nestProfile).get();
assertEquals(nestprofileReturned.get("name"), profileName);
}
@Test
public void stringWithSpaces() throws IOException {
// create entity with a property with spaces
String collection = "calendarlists";
String summaryOverview = "My Summary";
String calType = "personal";
Entity payload = new Entity();
payload.put("summaryOverview", summaryOverview);
payload.put("caltype", calType);
Entity calendarlistOne = this.app().collection(collection).post(payload );
assertEquals( calendarlistOne.get( "summaryOverview" ), summaryOverview );
assertEquals(calendarlistOne.get("caltype"), calType);
this.refreshIndex();
//post a second entity
payload = new Entity();
String summaryOverviewTwo = "Your Summary";
String calTypeTwo = "personal";
payload.put("summaryOverview", summaryOverviewTwo);
payload.put("caltype", calTypeTwo);
Entity calendarlistTwo = this.app().collection(collection).post(payload);
assertEquals( calendarlistTwo.get( "summaryOverview" ), summaryOverviewTwo );
assertEquals(calendarlistTwo.get("caltype"), calTypeTwo);
//query for the first entity
String query = "summaryOverview = 'My Summary'";
QueryParameters queryParameters = new QueryParameters().setQuery(query);
Collection calendarListCollection = this.app().collection(collection).get(queryParameters);
assertEquals(calendarListCollection.hasNext(), true);
}
@Test
public void testDefaultCollectionReturning() throws IOException {
ApiResponse usersDefaultCollection = this.app().get();
LinkedHashMap collectionHashMap = ( LinkedHashMap ) usersDefaultCollection.getEntity().get( "metadata" );
//make sure you have all the other default collections once you have users in place.
Set<String> system_collections = Schema.getDefaultSchema().getCollectionNames( Application.ENTITY_TYPE );
for(String collectionName : system_collections){
assertNotSame( null,((LinkedHashMap)(collectionHashMap.get( "collections" ))).get( collectionName ));
}
}
@Ignore("Ignored because we no longer retain custom collections after deleting the last entity in a collection"
+ "This test can be used to verify that works when we implement it")
@Test
public void testNewlyCreatedCollectionReturnsWhenEmpty(){
String collectionName = "testDefaultCollectionReturnings";
Map<String,Object> payload = new HashMap( );
payload.put( "hello","test" );
ApiResponse testEntity = this.app().collection( collectionName ).post( payload );
//Verify that the below collection actually does exist.
ApiResponse usersDefaultCollection = this.app().get();
LinkedHashMap collectionHashMap = ( LinkedHashMap ) usersDefaultCollection.getEntity().get( "metadata" );
assertNotSame( null,((LinkedHashMap)(collectionHashMap.get( "collections" ))).get( collectionName.toLowerCase() ));
this.refreshIndex();
this.app().collection( collectionName ).entity( testEntity.getEntity().getUuid() ).delete();
this.refreshIndex();
//Verify that the collection still exists despite deleting its only entity.)
usersDefaultCollection = this.app().get();
collectionHashMap = ( LinkedHashMap ) usersDefaultCollection.getEntity().get( "metadata" );
assertNotSame( null,((LinkedHashMap)(collectionHashMap.get( "collections" ))).get( collectionName.toLowerCase() ));
Collection createdCollectionResponse = this.app().collection( collectionName ).get();
assertEquals( 0,createdCollectionResponse.getNumOfEntities() );
}
/**
* Test to verify "name property returns twice in AppServices response" is fixed.
*/
@Test
public void testNoDuplicateFields() throws Exception {
// create user
String name = "fred";
Entity payload = new Entity();
payload.put("name", name);
Entity user = this.app().collection("app_users").post(payload);
assertEquals(user.get("name"), name);
this.refreshIndex();
Entity user2 = this.app().collection("app_users").entity(user).get();
/*
// check REST API response for duplicate name property
// have to look at raw response data, Jackson will remove dups
String s = resource().path( "/test-organization/test-app/app_users/fred" )
.queryParam( "access_token", access_token ).accept( MediaType.APPLICATION_JSON )
.type( MediaType.APPLICATION_JSON_TYPE ).get( String.class );
int firstFred = s.indexOf( "fred" );
int secondFred = s.indexOf( "fred", firstFred + 4 );
Assert.assertEquals( "Should not be more than one name property", -1, secondFred );
*/
}
@Test
public void testBeingAbleToRetreiveMigratedValues() throws Exception {
Entity notifier = new Entity().chainPut("name", "mynotifier").chainPut("provider", "noop");
ApiResponse notifierNode = this.pathResource(getOrgAppPath("notifier")).post(ApiResponse.class,notifier);
UUID uuid = UUIDUtils.newTimeUUID();
// create user
Map payloads = new HashMap<>( );
payloads.put( "mynotifier","hello world" );
Map statistics = new HashMap<>( );
statistics.put( "sent",1 );
statistics.put( "errors",0 );
Entity payload = new Entity();
payload.put("debug", false);
payload.put( "expectedCount",0 );
payload.put( "finished",1438279671229L);
payload.put( "payloads",payloads);
payload.put( "priority","normal");
payload.put( "state","FINISHED");
payload.put( "statistics",statistics);
ApiResponse user = this.app().collection("notifications/"+ UUIDUtils.newTimeUUID()).put(null,payload );
this.refreshIndex();
Collection user2 = this.app().collection("notifications").get();
assertEquals(1,user2.getNumOfEntities());
}
}