/* * Copyright 2013-2017 Erudika. https://erudika.com * * Licensed 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 issues and patches go to: https://github.com/erudika */ package com.erudika.para.client; import com.erudika.para.Para; import com.erudika.para.ParaServer; import com.erudika.para.core.Address; import com.erudika.para.core.App; import com.erudika.para.core.App.AllowedMethods; import com.erudika.para.core.utils.CoreUtils; import com.erudika.para.core.ParaObject; import com.erudika.para.core.Sysprop; import com.erudika.para.core.Tag; import com.erudika.para.core.User; import com.erudika.para.core.Votable; import com.erudika.para.core.Vote; import com.erudika.para.search.ElasticSearchUtils; import com.erudika.para.security.AuthenticatedUserDetails; import com.erudika.para.security.filters.FacebookAuthFilter; import com.erudika.para.security.SecurityModule; import com.erudika.para.security.UserAuthentication; import com.erudika.para.utils.Config; import static com.erudika.para.validation.Constraint.*; import com.erudika.para.utils.HumanTime; import com.erudika.para.utils.Pager; import com.erudika.para.utils.Utils; import com.google.inject.util.Modules; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import org.junit.AfterClass; import static org.junit.Assert.*; import org.junit.BeforeClass; import org.junit.Test; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.Banner; import org.springframework.boot.SpringApplication; /** * * @author Alex Bogdanovski [alex@erudika.com] */ public class ParaClientIT { private static final Logger logger = LoggerFactory.getLogger(ParaClientIT.class); private static ParaClient pc; private static ParaClient pc2; private static ParaClient pcc; private static final String catsType = "cat"; private static final String dogsType = "dog"; private static final String batsType = "bat"; private static final String APP_NAME = "para-test"; private static final String APP_NAME_CHILD = "para-test-child"; protected static Sysprop u; protected static Sysprop u1; protected static Sysprop u2; protected static Tag t; protected static Sysprop s1; protected static Sysprop s2; protected static Address a1; protected static Address a2; protected static User fbUser; @BeforeClass public static void setUpClass() throws InterruptedException, IOException { System.setProperty("para.env", "embedded"); System.setProperty("para.print_logo", "false"); System.setProperty("para.app_name", APP_NAME); System.setProperty("para.cluster_name", "para-test"); String endpoint = "http://localhost:8080"; fbUser = new User("fbUser_1"); fbUser.setEmail("test@user.com"); fbUser.setIdentifier("fb:1234"); fbUser.setGroups("users"); fbUser.setActive(true); fbUser.setAppid(APP_NAME); UserAuthentication ua = new UserAuthentication(new AuthenticatedUserDetails(fbUser)); SpringApplication app = new SpringApplication(ParaServer.class); app.setWebEnvironment(true); app.setBannerMode(Banner.Mode.OFF); SecurityModule secMod = new SecurityModule(); FacebookAuthFilter fbaf = new FacebookAuthFilter("/"); fbaf = spy(fbaf); when(fbaf.getOrCreateUser((App) any(), anyString())).thenReturn(ua); secMod.setFacebookFilter(fbaf); Para.initialize(Modules.override(ParaServer.getCoreModules()).with(secMod)); app.run(); CoreUtils.getInstance().setDao(Para.getDAO()); CoreUtils.getInstance().setSearch(Para.getSearch()); ParaClient temp = new ParaClient("x", "x"); temp.setEndpoint(endpoint); assertNull(temp.me()); assertTrue(temp.newId().isEmpty()); App rootApp = Para.getDAO().read(App.id(APP_NAME)); if (rootApp == null) { rootApp = new App(APP_NAME); rootApp.setName(APP_NAME); rootApp.setSharingIndex(false); rootApp.create(); } else { rootApp.resetSecret(); Para.getDAO().create(rootApp); } Map<String, String> creds = Para.setup(APP_NAME_CHILD, "Child app with routing", true); ElasticSearchUtils.addIndexAlias(APP_NAME, APP_NAME_CHILD, true); pc = new ParaClient(App.id(APP_NAME), rootApp.getSecret()); pc.setEndpoint(endpoint); pc2 = new ParaClient(App.id(APP_NAME), rootApp.getSecret()); pc2.setEndpoint(endpoint); pcc = new ParaClient(App.id(APP_NAME_CHILD), creds.get("secretKey")); pcc.setEndpoint(endpoint); logger.info("accessKey: {}, secretKey: {}", rootApp.getId(), rootApp.getSecret()); u = new Sysprop("c111"); u.setName("John Doe"); u.setTimestamp(Utils.timestamp()); u.setTags(CoreUtils.getInstance().addTags(u.getTags(), "one", "two", "three")); u1 = new Sysprop("c222"); u1.setName("Joe Black"); u1.setTimestamp(Utils.timestamp()); u1.setTags(CoreUtils.getInstance().addTags(u1.getTags(), "two", "four", "three")); u2 = new Sysprop("c333"); u2.setName("Ann Smith"); u2.setTimestamp(Utils.timestamp()); u2.setTags(CoreUtils.getInstance().addTags(u2.getTags(), "four", "five", "three")); t = new Tag("test"); t.setCount(3); t.setTimestamp(Utils.timestamp()); a1 = new Address("adr1"); a1.setName("Place 1"); a1.setAddress("NYC"); a1.setCountry("US"); a1.setLatlng("40.67,-73.94"); a1.setParentid(u.getId()); a1.setCreatorid(u.getId()); a2 = new Address("adr2"); a2.setName("Place 2"); a2.setAddress("NYC"); a2.setCountry("US"); a2.setLatlng("40.69,-73.95"); a2.setParentid(t.getId()); a2.setCreatorid(t.getId()); s1 = new Sysprop("s1"); s1.setName("This is a little test sentence. Testing, one, two, three."); s1.setTimestamp(Utils.timestamp()); s2 = new Sysprop("s2"); s2.setName("We are testing this thing. This sentence is a test. One, two."); s2.setTimestamp(Utils.timestamp()); assertNotNull(fbUser.create()); pc.createAll(Arrays.asList(u, u1, u2, t, s1, s2, a1, a2)); Thread.sleep(1000); } @AfterClass public static void tearDownClass() { System.setProperty("para.clients_can_access_root_app", "false"); Para.getDAO().delete(new App(APP_NAME_CHILD)); Para.getDAO().deleteAll(Arrays.asList(u, u1, u2, t, s1, s2, a1, a2)); Para.destroy(); } @Test public void testCRUD() { assertNull(pc.create(null)); Tag t1 = pc.create(new Tag("test1")); User ux = null; try { // validation fails ux = pc.create(new User("u1")); } catch (Exception e) {} assertNotNull(t1); assertNull(ux); assertNull(pc.read(null, null)); assertNull(pc.read("", "")); Tag trID = pc.read(t1.getId()); assertNotNull(trID); assertNotNull(trID.getTimestamp()); assertEquals(t1.getTag(), trID.getTag()); Tag tr = pc.read(t1.getType(), t1.getId()); assertNotNull(tr); assertNotNull(tr.getTimestamp()); assertEquals(t1.getTag(), tr.getTag()); tr.setCount(15); Tag tu = pc.update(tr); assertNull(pc.update(new Tag("null"))); assertNotNull(tu); assertEquals(tu.getCount(), tr.getCount()); assertNotNull(tu.getUpdated()); Sysprop s = new Sysprop(); s.setType(dogsType); s.addProperty("foo", "bark!"); s = pc.create(s); Sysprop dog = pc.read(dogsType, s.getId()); assertTrue(dog.hasProperty("foo")); assertEquals("bark!", dog.getProperty("foo")); pc.delete(t1); pc.delete(dog); assertNull(pc.read(tr.getType(), tr.getId())); // app must not overwrite itself assertNull(pc.create(new App(APP_NAME))); // app can read itself assertNotNull(pc.read(Utils.type(App.class), APP_NAME)); } @Test public void testBatchCRUD() throws InterruptedException { ArrayList<Sysprop> dogs = new ArrayList<Sysprop>(); for (int i = 0; i < 3; i++) { Sysprop s = new Sysprop(); s.setType(dogsType); s.addProperty("foo", "bark!"); dogs.add(s); } assertTrue(pc.createAll(null).isEmpty()); List<Sysprop> l1 = pc.createAll(dogs); assertEquals(3, l1.size()); assertNotNull(l1.get(0).getId()); assertTrue(pc.readAll(null).isEmpty()); ArrayList<String> nl = new ArrayList<String>(3); assertTrue(pc.readAll(nl).isEmpty()); nl.add(l1.get(0).getId()); nl.add(l1.get(1).getId()); nl.add(l1.get(2).getId()); List<Sysprop> l2 = pc.readAll(nl); assertEquals(3, l2.size()); assertEquals(l1.get(0).getId(), l2.get(0).getId()); assertEquals(l1.get(1).getId(), l2.get(1).getId()); assertTrue(l2.get(0).hasProperty("foo")); assertEquals("bark!", l2.get(0).getProperty("foo")); assertTrue(pc.updateAll(null).isEmpty()); Sysprop part1 = new Sysprop(l1.get(0).getId()); Sysprop part2 = new Sysprop(l1.get(1).getId()); Sysprop part3 = new Sysprop(l1.get(2).getId()); part1.setType(dogsType); part2.setType(dogsType); part3.setType(dogsType); part1.addProperty("custom", "prop"); part1.setName("NewName1"); part2.setName("NewName2"); part3.setName("NewName3"); List<Sysprop> l3 = pc.updateAll(Arrays.asList(part1, part2, part3)); assertTrue(l3.get(0).hasProperty("custom")); assertEquals(dogsType, l3.get(0).getType()); assertEquals(dogsType, l3.get(1).getType()); assertEquals(dogsType, l3.get(2).getType()); assertEquals(part1.getName(), l3.get(0).getName()); assertEquals(part2.getName(), l3.get(1).getName()); assertEquals(part3.getName(), l3.get(2).getName()); pc.deleteAll(nl); Thread.sleep(1000); List<Sysprop> l4 = pc.list(dogsType); assertTrue(l4.isEmpty()); assertTrue(pc.getApp().getDatatypes().containsValue(dogsType)); } @Test public void testBatchCRUDForChildApp() throws InterruptedException { ArrayList<Sysprop> articles = new ArrayList<Sysprop>(); for (int i = 0; i < 3; i++) { Sysprop s = new Sysprop(); s.setType("article"); // DO NOT SET appid, must be always set automatically on the server // depending on which app is currently in context (i.e. making the requests) s.addProperty("text", "a b c"); articles.add(s); } Para.getDAO().deleteAll(pcc.findQuery("article", "*")); List<Sysprop> l1 = pcc.createAll(articles); assertEquals(3, l1.size()); assertNotNull(l1.get(0).getId()); assertNotNull(l1.get(1).getId()); assertNotNull(l1.get(2).getId()); assertTrue(l1.get(0).hasProperty("text")); assertEquals("a b c", l1.get(0).getProperty("text")); assertEquals(APP_NAME_CHILD, l1.get(0).getAppid()); assertEquals(APP_NAME_CHILD, l1.get(1).getAppid()); assertEquals(APP_NAME_CHILD, l1.get(2).getAppid()); // test if appid is set on partial update // test if old data is not lost on partial update // test if new custom properties are merged with old ones in case of partial update Sysprop part1 = new Sysprop(l1.get(0).getId()); Sysprop part2 = new Sysprop(l1.get(1).getId()); Sysprop part3 = new Sysprop(l1.get(2).getId()); // DO NOT SET appid - should work without it in partial updateAll() part1.setType("update_must_not_change_type"); part2.setType("update_must_not_change_type"); part3.setType("update_must_not_change_type"); part1.addProperty("text2", "d e f"); part2.addProperty("text2", "d e f"); part2.setName("NewName2"); part3.setName("NewName3"); List<Sysprop> lu = pcc.updateAll(Arrays.asList(part1, part2, part3)); assertEquals(3, lu.size()); List<Sysprop> l2 = pcc.readAll(Arrays.asList(part1.getId(), part2.getId(), part3.getId())); assertEquals(3, l2.size()); assertTrue(l2.get(0).hasProperty("text")); assertTrue(l2.get(1).hasProperty("text")); assertTrue(l2.get(2).hasProperty("text")); assertTrue(l2.get(0).hasProperty("text2")); assertTrue(l2.get(1).hasProperty("text2")); assertEquals(2, l2.get(0).getProperties().size()); assertEquals("a b c", l2.get(0).getProperty("text")); assertEquals(part2.getName(), l2.get(1).getName()); assertEquals(part3.getName(), l2.get(2).getName()); assertEquals("article", l2.get(0).getType()); assertEquals("article", l2.get(1).getType()); assertEquals("article", l2.get(2).getType()); assertEquals(APP_NAME_CHILD, l2.get(0).getAppid()); assertEquals(APP_NAME_CHILD, l2.get(1).getAppid()); assertEquals(APP_NAME_CHILD, l2.get(2).getAppid()); // test if objects are validated on updateAll() pcc.addValidationConstraint("article", "text", required()); part1.addProperty("text", ""); part2.addProperty("text", ""); List<Sysprop> lu2 = pcc.updateAll(Arrays.asList(part1, part2)); assertTrue(lu2.isEmpty()); Para.getDAO().deleteAll(l1); pcc.deleteAll(Arrays.asList(part1.getId(), part2.getId(), part3.getId())); } @Test public void testCRUDWithNonStandardIDs() throws InterruptedException { String id1 = "test/123/file.txt"; String id2 = "file.txt?/!./=-+)))(*&^%+$#@><`~±_|'"; String type1 = "type?/!./=-+)))(*&^%+$#@><`~±_|'"; // # should be removed String type2 = "___ type 123 +__"; Sysprop so1 = new Sysprop(Utils.urlEncode(id1)); Sysprop so2 = new Sysprop(Utils.urlEncode(id2)); so1.setType(Utils.urlEncode(type1)); so2.setType(Utils.urlEncode(type2)); Sysprop obj1 = pc.create(so1); Sysprop obj2 = pc.create(so2); assertNotNull(obj1); assertNotNull(obj2); Sysprop sr1 = pc.read(so1.getId()); Sysprop sr2 = pc.read(so2.getId()); assertNotNull(sr1); assertNotNull(sr2); assertNotNull(sr1.getTimestamp()); assertNotNull(sr2.getTimestamp()); assertEquals(id1, sr1.getId()); assertEquals(id2, sr2.getId()); assertNotNull(pc.read(Utils.urlEncode(obj1.getType()), Utils.urlEncode(obj1.getId()))); assertNotNull(pc.read(Utils.urlEncode(obj2.getType()), Utils.urlEncode(obj2.getId()))); so1.setName("test name"); Sysprop su = pc.update(so1); assertNotNull(su); assertEquals(so1.getName(), su.getName()); assertNotNull(su.getUpdated()); pc.delete(so1); pc.delete(so2); assertNull(pc.read(so1.getId())); assertNull(pc.read(so2.getId())); assertNull(pc.read(so1.getType(), so1.getId())); assertNull(pc.read(so2.getType(), so2.getId())); pc.createAll(Arrays.asList(sr1, sr2)); List<Sysprop> srl = pc.readAll(Arrays.asList(id1, id2)); assertEquals(2, srl.size()); assertEquals(id1, srl.get(0).getId()); assertEquals(id2, srl.get(1).getId()); pc.deleteAll(Arrays.asList(id1, id2)); assertTrue(pc.readAll(Arrays.asList(id1, id2)).isEmpty()); } @Test public void testList() throws InterruptedException { ArrayList<ParaObject> cats = new ArrayList<ParaObject>(); for (int i = 0; i < 3; i++) { Sysprop s = new Sysprop(catsType + i); s.setType(catsType); cats.add(s); } pc.createAll(cats); Thread.sleep(1000); assertTrue(pc.list(null).isEmpty()); assertTrue(pc.list("").isEmpty()); List<Sysprop> list1 = pc.list(catsType); assertFalse(list1.isEmpty()); assertEquals(3, list1.size()); assertEquals(Sysprop.class, list1.get(0).getClass()); List<Sysprop> list2 = pc.list(catsType, new Pager(2)); assertFalse(list2.isEmpty()); assertEquals(2, list2.size()); ArrayList<String> nl = new ArrayList<String>(3); nl.add(cats.get(0).getId()); nl.add(cats.get(1).getId()); nl.add(cats.get(2).getId()); pc.deleteAll(nl); assertTrue(pc.getApp().getDatatypes().containsValue(catsType)); } @Test public void testSearch() throws InterruptedException { assertNull(pc.findById(null)); assertNull(pc.findById("")); assertNotNull(pc.findById(u.getId())); assertNotNull(pc.findById(t.getId())); assertTrue(pc.findByIds(null).isEmpty()); List<?> res1 = pc.findByIds(Arrays.asList(u.getId(), u1.getId(), u2.getId())); assertEquals(3, res1.size()); Sysprop withRouting1 = new Sysprop("routed_object1"); Sysprop withRouting2 = new Sysprop("routed_object2"); Para.getDAO().deleteAll(Arrays.asList(withRouting1, withRouting2)); withRouting1.setAppid(APP_NAME_CHILD); withRouting2.setAppid(APP_NAME_CHILD); pcc.createAll(Arrays.asList(withRouting1, withRouting2)); Thread.sleep(1000); assertEquals(2, pcc.findByIds(Arrays.asList(withRouting1.getId(), withRouting2.getId())).size()); Para.getDAO().deleteAll(APP_NAME_CHILD, Arrays.asList(withRouting1, withRouting2)); assertTrue(pc.findNearby(null, null, 100, 1, 1).isEmpty()); assertFalse(pc.findNearby(u.getType(), "*", 10, 40.60, -73.90).isEmpty()); assertFalse(pc.findNearby(t.getType(), "*", 10, 40.62, -73.91).isEmpty()); assertTrue(pc.findPrefix(null, null, "").isEmpty()); assertTrue(pc.findPrefix("", "null", "xx").isEmpty()); assertFalse(pc.findPrefix(u.getType(), Config._NAME, "ann").isEmpty()); assertFalse(pc.findQuery(null, null).isEmpty()); assertFalse(pc.findQuery("", "*").isEmpty()); assertEquals(2, pc.findQuery(a1.getType(), "country:US").size()); assertFalse(pc.findQuery(u.getType(), "ann").isEmpty()); assertFalse(pc.findQuery(u.getType(), "Ann").isEmpty()); assertTrue(pc.findQuery(null, "*").size() > 4); Pager p = new Pager(); assertEquals(0, p.getCount()); List<?> res = pc.findQuery(u.getType(), "*", p); assertEquals(res.size(), p.getCount()); assertTrue(p.getCount() > 0); assertTrue(pc.findSimilar(t.getType(), "", null, null).isEmpty()); assertTrue(pc.findSimilar(t.getType(), "", new String[0], "").isEmpty()); res = pc.findSimilar(s1.getType(), s1.getId(), new String[]{Config._NAME}, s1.getName()); assertFalse(res.isEmpty()); assertEquals(s2, res.get(0)); int i0 = pc.findTagged(u.getType(), null).size(); int i1 = pc.findTagged(u.getType(), new String[]{"two"}).size(); int i2 = pc.findTagged(u.getType(), new String[]{"one", "two"}).size(); int i3 = pc.findTagged(u.getType(), new String[]{"three"}).size(); int i4 = pc.findTagged(u.getType(), new String[]{"four", "three"}).size(); int i5 = pc.findTagged(u.getType(), new String[]{"five", "three"}).size(); int i6 = pc.findTagged(t.getType(), new String[]{"four", "three"}).size(); assertEquals(0, i0); assertEquals(2, i1); assertEquals(1, i2); assertEquals(3, i3); assertEquals(2, i4); assertEquals(1, i5); assertEquals(0, i6); assertFalse(pc.findTags(null).isEmpty()); assertFalse(pc.findTags("").isEmpty()); assertTrue(pc.findTags("unknown").isEmpty()); assertTrue(pc.findTags(t.getTag()).size() >= 1); assertEquals(3, pc.findTermInList(u.getType(), Config._ID, Arrays.asList(u.getId(), u1.getId(), u2.getId(), "xxx", "yyy")).size()); // many terms Map<String, Object> terms = new HashMap<String, Object>(); // terms.put(Config._TYPE, u.getType()); terms.put(Config._ID, u.getId()); Map<String, Object> terms1 = new HashMap<String, Object>(); terms1.put(Config._TYPE, null); terms1.put(Config._ID, " "); Map<String, Object> terms2 = new HashMap<String, Object>(); terms2.put(" ", "bad"); terms2.put("", ""); assertEquals(1, pc.findTerms(u.getType(), terms, true).size()); assertTrue(pc.findTerms(u.getType(), terms1, true).isEmpty()); assertTrue(pc.findTerms(u.getType(), terms2, true).isEmpty()); // single term assertTrue(pc.findTerms(null, null, true).isEmpty()); assertTrue(pc.findTerms(u.getType(), Collections.singletonMap("", null), true).isEmpty()); assertTrue(pc.findTerms(u.getType(), Collections.singletonMap("", ""), true).isEmpty()); assertTrue(pc.findTerms(u.getType(), Collections.singletonMap("term", null), true).isEmpty()); assertTrue(pc.findTerms(u.getType(), Collections.singletonMap(Config._TYPE, u.getType()), true).size() >= 2); assertTrue(pc.findWildcard(u.getType(), null, null).isEmpty()); assertTrue(pc.findWildcard(u.getType(), "", "").isEmpty()); assertFalse(pc.findWildcard(u.getType(), Config._NAME, "an*").isEmpty()); assertTrue(pc.getCount(null).intValue() > 4); assertNotEquals(0, pc.getCount("").intValue()); assertEquals(0, pc.getCount("test").intValue()); assertTrue(pc.getCount(u.getType()).intValue() >= 3); assertEquals(0L, pc.getCount(null, null).intValue()); assertEquals(0L, pc.getCount(u.getType(), Collections.singletonMap(Config._ID, " ")).intValue()); assertEquals(1L, pc.getCount(u.getType(), Collections.singletonMap(Config._ID, u.getId())).intValue()); assertTrue(pc.getCount(null, Collections.singletonMap(Config._TYPE, u.getType())).intValue() > 1); } @Test public void testLinks() throws InterruptedException { assertNotNull(pc.link(u, t.getId())); assertNotNull(pc.link(u, u2.getId())); assertFalse(pc.isLinked(u, null)); assertTrue(pc.isLinked(u, t)); assertTrue(pc.isLinked(u, u2)); Thread.sleep(1000); assertEquals(1, pc.getLinkedObjects(u, Utils.type(Tag.class)).size()); assertEquals(1, pc.getLinkedObjects(u, Utils.type(Sysprop.class)).size()); assertEquals(0, pc.countLinks(u, null).intValue()); assertEquals(1, pc.countLinks(u, Utils.type(Tag.class)).intValue()); assertEquals(1, pc.countLinks(u, Utils.type(Sysprop.class)).intValue()); pc.unlinkAll(u); assertFalse(pc.isLinked(u, t)); assertFalse(pc.isLinked(u, u2)); Sysprop second1 = new Sysprop("secondLink1"); Sysprop second2 = new Sysprop("secondLink2"); Sysprop second3 = new Sysprop("secondLink3"); second1.addProperty("text", "hello from the other side"); second2.addProperty("text", "hello kitty"); second3.setName("gordon"); Sysprop child1 = new Sysprop("child1"); Sysprop child2 = new Sysprop("child2"); Sysprop child3 = new Sysprop("child3"); child1.setParentid(u.getId()); child2.setParentid(u.getId()); child3.setParentid(u.getId()); child1.addProperty("text", "hello from the other side"); child2.addProperty("text", "hello kitty"); child3.setName("gordon"); pc.createAll(Arrays.asList(second1, second2, second3, child1, child2, child3)); Thread.sleep(1000); assertNotNull(pc.link(u, second1.getId())); assertNotNull(pc.link(u, second2.getId())); assertNotNull(pc.link(u, second3.getId())); Thread.sleep(1000); // test linked objects search assertEquals(3, pc.findLinkedObjects(u, second1.getType(), Config._NAME, null).size()); List<Sysprop> found1 = pc.findLinkedObjects(u, second1.getType(), Config._NAME, "gord*"); assertFalse(found1.isEmpty()); assertTrue(found1.get(0).getId().equals(second3.getId())); List<Sysprop> found2 = pc.findLinkedObjects(u, second1.getType(), "properties.text", "kitt*"); assertFalse(found2.isEmpty()); assertTrue(found2.get(0).getId().equals(second2.getId())); List<Sysprop> found3 = pc.findLinkedObjects(u, second1.getType(), "properties.text", "hello"); assertEquals(2, found3.size()); assertTrue(found3.get(0).getId().equals(second1.getId()) || found3.get(1).getId().equals(second1.getId())); assertTrue(found3.get(0).getId().equals(second2.getId()) || found3.get(1).getId().equals(second2.getId())); // test children search assertEquals(3, pc.findChildren(u, child1.getType(), null).size()); List<Sysprop> result1 = pc.findChildren(u, child1.getType(), "gord*"); assertFalse(result1.isEmpty()); assertTrue(result1.get(0).getId().equals(child3.getId())); List<Sysprop> result2 = pc.findChildren(u, child1.getType(), "kitt*"); assertFalse(result2.isEmpty()); assertTrue(result2.get(0).getId().equals(child2.getId())); List<Sysprop> result3 = pc.findChildren(u, child1.getType(), "hello"); assertEquals(2, result3.size()); assertTrue(result3.get(0).getId().equals(child1.getId()) || result3.get(1).getId().equals(child1.getId())); assertTrue(result3.get(0).getId().equals(child2.getId()) || result3.get(1).getId().equals(child2.getId())); pc.unlinkAll(u); pc.deleteAll(Arrays.asList(second1.getId(), second2.getId(), second3.getId(), child1.getId(), child2.getId(), child3.getId())); } @Test public void testUtils() { String id1 = pc.newId(); String id2 = pc.newId(); assertNotNull(id1); assertFalse(id1.isEmpty()); assertNotEquals(id1, id2); final Long ts = pc.getTimestamp(); assertNotNull(ts); assertNotEquals(0, ts.intValue()); String date1 = pc.formatDate("MM dd yyyy", Locale.US); String date2 = Utils.formatDate("MM dd yyyy", Locale.US); assertEquals(date1, date2); String ns1 = pc.noSpaces(" test 123 test ", ""); String ns2 = Utils.noSpaces(" test 123 test ", ""); assertEquals(ns1, ns2); String st1 = pc.stripAndTrim(" %^&*( cool ) @!"); String st2 = Utils.stripAndTrim(" %^&*( cool ) @!"); assertEquals(st1, st2); String md1 = pc.markdownToHtml("**test** #hello"); String md2 = Utils.markdownToHtml("**test** #hello"); assertEquals(md1, md2); String ht1 = pc.approximately(15000); String ht2 = HumanTime.approximately(15000); assertEquals(ht1, ht2); } @Test public void testMisc() { Map<String, String> types = pc.types(); assertNotNull(types); assertFalse(types.isEmpty()); assertTrue(types.containsKey(new User().getPlural())); assertEquals(App.id(APP_NAME), pc.me().getId()); } @Test public void testValidationConstraints() { // Validations String kittenType = "kitten"; Map<String, ?> constraints = pc.validationConstraints(); assertNotNull(constraints); assertFalse(constraints.isEmpty()); assertTrue(constraints.containsKey("app")); assertTrue(constraints.containsKey("user")); Map<String, Map<String, Map<String, Map<String, ?>>>> constraint = pc.validationConstraints("app"); assertFalse(constraint.isEmpty()); assertTrue(constraint.containsKey("app")); assertEquals(1, constraint.size()); pc.addValidationConstraint(kittenType, "paws", required()); constraint = pc.validationConstraints(kittenType); assertNotNull(constraint); assertNotNull(constraint.get(kittenType)); assertTrue(constraint.get(kittenType).containsKey("paws")); Sysprop ct = new Sysprop("felix"); Para.getDAO().delete(ct); Para.getDAO().deleteAll(pc.findQuery("vote", "*")); ct.setType(kittenType); Sysprop ct2 = null; try { // validation fails ct2 = pc.create(ct); } catch (Exception e) {} assertNull(ct2); ct.addProperty("paws", "4"); assertNotNull(pc.create(ct)); pc.removeValidationConstraint(kittenType, "paws", "required"); constraint = pc.validationConstraints(kittenType); assertFalse(constraint.containsKey(kittenType)); Integer votes = ct.getVotes() + 1; assertTrue(pc.voteUp(ct, u.getId())); assertEquals(votes, pc.read(ct.getId()).getVotes()); assertFalse(pc.voteUp(ct, u.getId())); votes -= 1; assertTrue(pc.voteDown(ct, u.getId())); assertEquals(votes, pc.read(ct.getId()).getVotes()); votes -= 1; assertTrue(pc.voteDown(ct, u.getId())); assertFalse(pc.voteDown(ct, u.getId())); assertEquals(votes, pc.read(ct.getId()).getVotes()); Para.getDAO().delete(ct); Para.getDAO().delete(new Vote(u.getId(), ct.getId(), Votable.VoteValue.UP)); } @Test public void testResourcePermissions() { // Permissions Map<String, Map<String, List<String>>> permits = pc.resourcePermissions(); assertNotNull(permits); assertTrue(pc.grantResourcePermission(null, dogsType, EnumSet.noneOf(AllowedMethods.class)).isEmpty()); assertTrue(pc.grantResourcePermission(" ", "", EnumSet.noneOf(AllowedMethods.class)).isEmpty()); pc.grantResourcePermission(u1.getId(), dogsType, AllowedMethods.READ); permits = pc.resourcePermissions(u1.getId()); assertTrue(permits.containsKey(u1.getId())); assertTrue(permits.get(u1.getId()).containsKey(dogsType)); assertTrue(pc.isAllowedTo(u1.getId(), dogsType, AllowedMethods.GET.toString())); assertFalse(pc.isAllowedTo(u1.getId(), dogsType, AllowedMethods.POST.toString())); permits = pc.resourcePermissions(); assertTrue(permits.containsKey(u1.getId())); assertTrue(permits.get(u1.getId()).containsKey(dogsType)); pc.revokeResourcePermission(u1.getId(), dogsType); permits = pc.resourcePermissions(u1.getId()); assertFalse(permits.get(u1.getId()).containsKey(dogsType)); assertFalse(pc.isAllowedTo(u1.getId(), dogsType, AllowedMethods.GET.toString())); assertFalse(pc.isAllowedTo(u1.getId(), dogsType, AllowedMethods.POST.toString())); pc.grantResourcePermission(u2.getId(), App.ALLOW_ALL, AllowedMethods.WRITE); assertTrue(pc.isAllowedTo(u2.getId(), dogsType, AllowedMethods.PUT.toString())); assertTrue(pc.isAllowedTo(u2.getId(), dogsType, AllowedMethods.PATCH.toString())); pc.revokeAllResourcePermissions(u2.getId()); permits = pc.resourcePermissions(); assertFalse(pc.isAllowedTo(u2.getId(), dogsType, AllowedMethods.PUT.toString())); assertFalse(permits.containsKey(u2.getId())); // assertTrue(permits.get(u2.getId()).isEmpty()); pc.grantResourcePermission(u1.getId(), dogsType, AllowedMethods.WRITE); pc.grantResourcePermission(App.ALLOW_ALL, catsType, AllowedMethods.WRITE); pc.grantResourcePermission(App.ALLOW_ALL, App.ALLOW_ALL, AllowedMethods.READ); // user-specific permissions are in effect assertTrue(pc.isAllowedTo(u1.getId(), dogsType, AllowedMethods.PUT.toString())); assertFalse(pc.isAllowedTo(u1.getId(), dogsType, AllowedMethods.GET.toString())); assertTrue(pc.isAllowedTo(u1.getId(), catsType, AllowedMethods.PUT.toString())); assertTrue(pc.isAllowedTo(u1.getId(), catsType, AllowedMethods.GET.toString())); pc.revokeAllResourcePermissions(u1.getId()); // user-specific permissions not found so check wildcard assertFalse(pc.isAllowedTo(u1.getId(), dogsType, AllowedMethods.PUT.toString())); assertTrue(pc.isAllowedTo(u1.getId(), dogsType, AllowedMethods.GET.toString())); assertTrue(pc.isAllowedTo(u1.getId(), catsType, AllowedMethods.PUT.toString())); assertTrue(pc.isAllowedTo(u1.getId(), catsType, AllowedMethods.GET.toString())); pc.revokeResourcePermission(App.ALLOW_ALL, catsType); // resource-specific permissions not found so check wildcard assertFalse(pc.isAllowedTo(u1.getId(), dogsType, AllowedMethods.PUT.toString())); assertFalse(pc.isAllowedTo(u1.getId(), catsType, AllowedMethods.PUT.toString())); assertTrue(pc.isAllowedTo(u1.getId(), dogsType, AllowedMethods.GET.toString())); assertTrue(pc.isAllowedTo(u1.getId(), catsType, AllowedMethods.GET.toString())); assertTrue(pc.isAllowedTo(u2.getId(), dogsType, AllowedMethods.GET.toString())); assertTrue(pc.isAllowedTo(u2.getId(), catsType, AllowedMethods.GET.toString())); pc.revokeAllResourcePermissions(App.ALLOW_ALL); pc.revokeAllResourcePermissions(u1.getId()); } @Test public void testAppSettings() { Map<String, Object> settings = pc.appSettings(); assertNotNull(settings); assertTrue(settings.isEmpty()); pc.addAppSetting("", null); pc.addAppSetting(" ", " "); pc.addAppSetting(null, " "); pc.addAppSetting("prop1", 1); pc.addAppSetting("prop2", true); pc.addAppSetting("prop3", "string"); settings = pc.appSettings(); assertEquals(3, settings.size()); assertEquals(settings, pc.appSettings(null)); assertEquals(1, settings.get("prop1")); assertEquals(true, settings.get("prop2")); assertEquals("string", settings.get("prop3")); pc.removeAppSetting("prop3"); pc.removeAppSetting(" "); pc.removeAppSetting(null); settings = pc.appSettings(); assertFalse(settings.containsKey("prop3")); assertEquals(2, settings.size()); pc.removeAppSetting("prop2"); pc.removeAppSetting("prop1"); pc.addAppSetting("propZ", 1); Map<String, Object> newSettings = new HashMap<String, Object>(); newSettings.put("propX", "X"); newSettings.put("propY", "Y"); pc.setAppSettings(newSettings); settings = pc.appSettings(); assertEquals(2, settings.size()); assertFalse(settings.containsKey("propZ")); assertTrue(settings.containsKey("propX")); assertTrue(settings.containsKey("propY")); newSettings.clear(); pc.setAppSettings(newSettings); settings = pc.appSettings(); assertTrue(settings.isEmpty()); } @Test public void testAccessTokens() throws IOException, InterruptedException { assertNotNull(fbUser); assertNull(pc2.getAccessToken()); // fails with google+ - service not mocked User failsNotMocked = pc2.signIn("google", "test_token"); assertNull(failsNotMocked); // should fail to create user for root app System.setProperty("para.clients_can_access_root_app", "false"); User notSignedIn = pc2.signIn("facebook", "test_token"); Thread.sleep(500); logger.info(pc2.getAccessToken()); assertNull(notSignedIn); assertNull(pc2.getAccessToken()); // then allow clients to modify root app System.setProperty("para.clients_can_access_root_app", "true"); User signedIn = pc2.signIn("facebook", "test_token"); logger.info(pc2.getAccessToken()); assertNotNull(signedIn); assertNotNull(pc2.getAccessToken()); assertEquals(fbUser.getId(), signedIn.getId()); assertTrue(signedIn.getActive()); // test without permissions - signed in but you can't access anything yet pc2.revokeAllResourcePermissions(fbUser.getId()); ParaObject me = pc2.me(); assertNotNull(me); assertEquals("user", me.getType()); assertTrue(pc2.newId().isEmpty()); assertTrue(pc2.getTimestamp() == 0L); // test with permissions - logout first to use app credentials (full access) pc2.signOut(); pc2.grantResourcePermission(fbUser.getId(), App.ALLOW_ALL, AllowedMethods.READ_AND_WRITE); signedIn = pc2.signIn("facebook", "test_token"); logger.info(pc2.getAccessToken()); Thread.sleep(800); assertNotNull(signedIn); assertNotNull(pc2.getAccessToken()); me = pc2.me(); assertNotNull(me); assertFalse(pc2.newId().isEmpty()); assertEquals(signedIn.getName(), me.getName()); Thread.sleep(500); // now switch back to App access pc2.signOut(); assertNull(pc2.getAccessToken()); me = pc2.me(); // app assertNotNull(me); assertEquals("app", me.getType()); assertFalse(pc2.newId().isEmpty()); signedIn = pc2.signIn("facebook", "test_token"); logger.info(pc2.getAccessToken()); Thread.sleep(500); me = pc2.me(); // user assertNotNull(me); assertEquals("user", me.getType()); assertEquals(signedIn.getId(), me.getId()); assertNull(pc2.newKeys()); // users can't change API keys! // test revoke tokens pc2.revokeAllTokens(); assertTrue(pc2.newId().isEmpty()); assertTrue(pc2.getTimestamp() == 0L); assertNull(pc2.me()); pc2.signOut(); // test anonymous permissions String utilsPath = "utils/timestamp"; ParaClient guest = new ParaClient(App.id(APP_NAME), null); guest.setEndpoint(pc2.getEndpoint()); assertFalse(guest.getTimestamp() > 0); assertFalse(guest.isAllowedTo(App.ALLOW_ALL, utilsPath, AllowedMethods.GET.toString())); pc2.grantResourcePermission(App.ALLOW_ALL, utilsPath, AllowedMethods.READ, true); assertTrue(guest.getTimestamp() > 0); // test user should not be created twice if signed in with email and password // User signedInWithEmail = pc2.signIn("password", "test@user.com::123456"); // assertNotNull(signedInWithEmail); // pc2.signOut(); // Thread.sleep(800); // long existingUsers = pc2.getCount("user"); // pc2.signIn("password", "test@user.com::123456"); // pc2.signOut(); // long existingUsers2 = pc2.getCount("user"); // assertEquals(existingUsers2, existingUsers); // User badPass = pc2.signIn("password", "test@user.com::1234567"); // assertNull(badPass); // pc2.signOut(); // long existingUsers3 = pc2.getCount("user"); // assertEquals(existingUsers3, existingUsers2); // fbUser.delete(); } }