/* * 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.core; import static com.erudika.para.core.App.ALLOW_ALL; import static com.erudika.para.core.App.AllowedMethods.ALL; import static com.erudika.para.core.App.AllowedMethods.DELETE; import static com.erudika.para.core.App.AllowedMethods.GET; import static com.erudika.para.core.App.AllowedMethods.GUEST; import static com.erudika.para.core.App.AllowedMethods.NONE; import static com.erudika.para.core.App.AllowedMethods.PATCH; import static com.erudika.para.core.App.AllowedMethods.POST; import static com.erudika.para.core.App.AllowedMethods.PUT; import static com.erudika.para.core.App.AllowedMethods.READ; import static com.erudika.para.core.App.AllowedMethods.READ_AND_WRITE; import static com.erudika.para.core.App.AllowedMethods.READ_ONLY; import static com.erudika.para.core.App.AllowedMethods.READ_WRITE; import static com.erudika.para.core.App.AllowedMethods.WRITE; import static com.erudika.para.core.App.AllowedMethods.WRITE_ONLY; import com.erudika.para.utils.Config; import static com.erudika.para.validation.Constraint.url; import java.io.IOException; import java.util.Arrays; import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; import org.junit.AfterClass; import static org.junit.Assert.*; import org.junit.BeforeClass; import org.junit.Test; /** * * @author Alex Bogdanovski [alex@erudika.com] */ public class AppTest { @BeforeClass public static void setUpClass() throws InterruptedException, IOException { System.setProperty("para.clients_can_access_root_app", "true"); } @AfterClass public static void tearDownClass() { System.setProperty("para.clients_can_access_root_app", "false"); } @Test public void testCreate() { App app = new App("test"); app.setAppid("notRoot"); assertNull(app.create()); app.setAppid(Config.APP_NAME_NS); assertNotNull(app.create()); } @Test public void testSetId() { App app = new App(); assertNull(app.getId()); app.setId(null); assertNull(app.getId()); app.setId("test app"); assertEquals("app:test-app", app.getId()); app.setId("app:test app"); assertEquals("app:test-app", app.getId()); app.setId("app:app:test app ? @#$%^&>?<~`|\\;:./>-= COOL"); assertEquals("app:test-app-cool", app.getId()); app.setId("test app ? @#$%^&>?<~`|\\;:./>-= COOL"); assertEquals("app:test-app-cool", app.getId()); // if coming from db app.setId("app:test-app"); assertEquals("app:test-app", app.getId()); app.setId(" test-app"); assertEquals("app:test-app", app.getId()); assertEquals("test-app", app.getAppIdentifier()); app.setId(" test-app "); assertEquals("app:test-app", app.getId()); assertEquals("test-app", app.getAppIdentifier()); } @Test public void testGetAppIdentifier() { App app = new App(); assertTrue(app.getAppIdentifier().isEmpty()); app.setId(null); assertTrue(app.getAppIdentifier().isEmpty()); app.setId("test app"); assertEquals("test-app", app.getAppIdentifier()); app.setId("app:test app"); assertEquals("test-app", app.getAppIdentifier()); } @Test public void testGetCredentials() { App app = new App(); assertTrue(app.getCredentials().isEmpty()); app.setId("test app"); assertFalse(app.getCredentials().isEmpty()); } @Test public void testAddRemoveDatatypes() { App app = new App(); assertTrue(app.getDatatypes().isEmpty()); app.addDatatype("", "type"); app.addDatatype("", ""); app.addDatatype("null", null); assertTrue(app.getDatatypes().isEmpty()); app.addDatatype("types", "type"); assertTrue(app.getDatatypes().containsKey("types")); app.addDatatype("typess", "type"); assertFalse(app.getDatatypes().containsKey("typess")); app.addDatatype("types", "typee"); assertFalse(app.getDatatypes().containsValue("typee")); } @Test public void testGetAllValidationConstraints() { App app = new App(Config.PARA); assertTrue(app.getAllValidationConstraints().size() > 2); assertTrue(app.getAllValidationConstraints().size() > 2); assertTrue(app.getAllValidationConstraints().containsKey("app")); assertTrue(app.getAllValidationConstraints(new String[]{null}).isEmpty()); assertTrue(app.getAllValidationConstraints("123").isEmpty()); assertFalse(app.getAllValidationConstraints(new String[0]).isEmpty()); assertFalse(app.getAllValidationConstraints().isEmpty()); assertFalse(app.getAllValidationConstraints("tag").isEmpty()); } @Test public void testAddRemoveValidationConstraint() { App app = new App(Config.PARA); // add app.addValidationConstraint("testtype", "urlField", url()); assertTrue(app.getValidationConstraints().get("testtype").containsKey("urlField")); assertTrue(app.getValidationConstraints().get("testtype").get("urlField").containsKey("url")); // remove app.removeValidationConstraint("testtype", "urlField", "url"); assertTrue(app.getValidationConstraints().isEmpty()); } @Test public void testGetAllResourcePermissions() { App app = new App(Config.PARA); assertTrue(app.getAllResourcePermissions().isEmpty()); app.grantResourcePermission("123", ALLOW_ALL, READ); assertTrue(app.getAllResourcePermissions().containsKey("123")); assertTrue(app.getAllResourcePermissions(new String[]{null}).isEmpty()); assertFalse(app.getAllResourcePermissions("123").isEmpty()); assertFalse(app.getAllResourcePermissions(new String[0]).isEmpty()); assertFalse(app.getAllResourcePermissions().isEmpty()); } @Test public void testIsAllowedTo() { App app = new App(Config.PARA); assertFalse(app.isAllowedTo(null, null, null)); assertFalse(app.isAllowedTo("", " ", "")); assertFalse(app.isAllowedTo(ALLOW_ALL, ALLOW_ALL, GET.toString())); app.grantResourcePermission("123", ALLOW_ALL, READ); assertFalse(app.isAllowedTo("123", ALLOW_ALL, POST.toString())); assertTrue(app.isAllowedTo("123", "_test", GET.toString())); assertTrue(app.isAllowedTo("123", "_test1", READ_ONLY.toString())); app.revokeAllResourcePermissions("123"); assertFalse(app.isAllowedTo("123", "_test", GET.toString())); assertFalse(app.isAllowedTo("123", "_test1", READ_ONLY.toString())); } @Test public void testGrantRevokeResourcePermission() { App app = new App(Config.PARA); assertFalse(app.isAllowedTo(ALLOW_ALL, ALLOW_ALL, GET.toString())); app.grantResourcePermission(null, ALLOW_ALL, READ); assertTrue(app.getResourcePermissions().isEmpty()); app.grantResourcePermission("", ALLOW_ALL, READ); assertTrue(app.getResourcePermissions().isEmpty()); app.grantResourcePermission("123", "", READ); assertTrue(app.getResourcePermissions().isEmpty()); app.grantResourcePermission("123", ALLOW_ALL, EnumSet.noneOf(App.AllowedMethods.class)); assertTrue(app.getResourcePermissions().isEmpty()); app.grantResourcePermission("123", "res", NONE); assertFalse(app.getResourcePermissions().isEmpty()); assertFalse(app.isAllowedTo("123", "test", "GET")); assertFalse(app.isAllowedTo("123", "test", "GET")); app.grantResourcePermission("123", ALLOW_ALL, READ); assertTrue(app.isAllowedTo("123", ALLOW_ALL, READ_ONLY.toString())); app.grantResourcePermission("1235", ALLOW_ALL, EnumSet.of(READ_ONLY, PATCH)); assertTrue(app.isAllowedTo("1235", ALLOW_ALL, READ_ONLY.toString())); assertFalse(app.isAllowedTo("1235", ALLOW_ALL, PATCH.toString())); assertFalse(app.isAllowedTo("1235", ALLOW_ALL, DELETE.toString())); app.grantResourcePermission("1236", ALLOW_ALL, EnumSet.of(READ_ONLY, WRITE_ONLY)); assertTrue(app.isAllowedTo("1236", ALLOW_ALL, ALLOW_ALL)); // explicitly denied above assertFalse(app.isAllowedTo("123", "res", "gEt")); assertTrue(app.isAllowedTo("123", "res1/res2", "gEt")); assertFalse(app.isAllowedTo("1234", ALLOW_ALL, READ_ONLY.toString())); app.revokeResourcePermission("123", "_test"); assertTrue(app.isAllowedTo("123", ALLOW_ALL, READ_ONLY.toString())); app.revokeResourcePermission(ALLOW_ALL, ALLOW_ALL); assertTrue(app.isAllowedTo("123", ALLOW_ALL, READ_ONLY.toString())); assertTrue(app.isAllowedTo("123", ALLOW_ALL, "get")); assertFalse(app.isAllowedTo("123", ALLOW_ALL, "bad_method")); app.revokeResourcePermission("123", ALLOW_ALL); assertFalse(app.isAllowedTo("123", ALLOW_ALL, READ_ONLY.toString())); app.grantResourcePermission(ALLOW_ALL, "/0123/", READ); assertTrue(app.isAllowedTo(ALLOW_ALL, "0123", "get")); app.grantResourcePermission(ALLOW_ALL, "/4.5.6/", READ); assertTrue(app.isAllowedTo(ALLOW_ALL, "456", "get")); assertFalse(app.isAllowedTo("4.5.6", ALLOW_ALL, "get")); } @Test public void testIsAllowed() { App app = new App(); assertFalse(app.isAllowed(null, null, null)); assertFalse(app.isAllowed("user1", "posts", "GET")); app.setResourcePermissions(new HashMap<String, Map<String, List<String>>>() {{ put("user1", new HashMap<String, List<String>>() {{ put("posts", Arrays.asList("GET", "PUT")); put("posts/123", Arrays.asList("DELETE")); // subpaths put("_users/admins", Arrays.asList("GET")); put("_users/admins/321", Arrays.asList("PUT", "POST")); // simple "allow all" put("users", Arrays.asList(ALLOW_ALL)); }}); put(ALLOW_ALL, new HashMap<String, List<String>>() {{ // simple "allow all" put("super/secret/resource", Arrays.asList(NONE.toString())); }}); }}); assertTrue(app.isAllowed("user1", "posts", "get")); assertTrue(app.isAllowed("user1", "posts", "PUT")); assertFalse(app.isAllowed("user1", "posts123", "PUT")); // !!! important assertTrue(app.isAllowed("user1", "posts/456", "PUT")); assertFalse(app.isAllowed("user1", "posts", "DELETE")); assertTrue(app.isAllowed("user1", "posts/123", "DELETE")); assertFalse(app.isAllowed("user1", "posts/1234", "DELETE")); // !!! important assertFalse(app.isAllowed("user1", "posts", "ELSE")); // subpaths assertFalse(app.isAllowed("user1", "_users", "GET")); assertTrue(app.isAllowed("user1", "_users/admins", "GET")); assertFalse(app.isAllowed("user1", "_users/admins", "PUT")); assertTrue(app.isAllowed("user1", "_users/admins/123", "GET")); assertFalse(app.isAllowed("user1", "_users/admins/123", "PUT")); assertFalse(app.isAllowed("user1", "_users/admin", "GET")); assertFalse(app.isAllowed("user1", "_users/123", "GET")); assertFalse(app.isAllowed("user1", "_users/123", "PUT")); assertTrue(app.isAllowed("user1", "_users/admins/321", "GET")); assertTrue(app.isAllowed("user1", "_users/admins/321", "POST")); assertFalse(app.isAllowed("user1", "_users/admins/321", "DELETE")); // allow all assertTrue(app.isAllowed("user1", "users/12345", "DELETE")); assertTrue(app.isAllowed("user1", "users/12345", "PUT")); assertTrue(app.isAllowed("user1", "users/12345", "POST")); assertFalse(app.isAllowed("user2", "users/12345", "POST")); assertTrue(app.isAllowed("user1", "users/12345", "ELSE")); // deny all assertFalse(app.isAllowed(ALLOW_ALL, "super/secret/resource", "GET")); assertFalse(app.isAllowed(ALLOW_ALL, "super/secret/resource", "PUT")); assertFalse(app.isAllowed("user1", "super/secret/resource", "GET")); assertFalse(app.isAllowed("user2", "super/secret/resource", "POST")); assertFalse(app.isAllowed("user2", "super/secret/resource", NONE.toString())); // guest access assertFalse(app.isAllowed(ALLOW_ALL, "users/12345", GUEST.toString())); assertFalse(app.isAllowed(ALLOW_ALL, "guest/access", GUEST.toString())); app.grantResourcePermission(ALLOW_ALL, "guest/access", READ, true); assertTrue(app.isAllowed(ALLOW_ALL, "guest/access", "GET")); assertTrue(app.isAllowed(ALLOW_ALL, "guest/access", GUEST.toString())); app.grantResourcePermission(ALLOW_ALL, "guest/test", EnumSet.of(PUT, READ_WRITE), false); assertFalse(app.isAllowed(ALLOW_ALL, "guest/test", GUEST.toString())); app.grantResourcePermission(ALLOW_ALL, "publicRes", ALL, true); assertTrue(app.isAllowed(ALLOW_ALL, "publicRes/test", GUEST.toString())); app.grantResourcePermission(ALLOW_ALL, "publicSubResource", READ_AND_WRITE, false); assertFalse(app.isAllowed(ALLOW_ALL, "publicSubResource", GUEST.toString())); assertFalse(app.isAllowed(ALLOW_ALL, "publicSubResource/test", GUEST.toString())); app.grantResourcePermission(ALLOW_ALL, "publicSubResource/test", EnumSet.of(GUEST), false); assertTrue(app.isAllowed(ALLOW_ALL, "publicSubResource/test", GUEST.toString())); // this is not valid because subject can't be authenticated app.grantResourcePermission("someUser1", "illegalPublic", EnumSet.of(GET, GUEST), true); assertFalse(app.isAllowed(ALLOW_ALL, "illegalPublic", GUEST.toString())); assertFalse(app.isAllowed("someUser1", "illegalPublic", GUEST.toString())); } @Test public void testIsDeniedExplicitly() { App app = new App(); App app2 = new App(); User u = new User("u123"); User u2 = new User("someone_else"); String res1 = "some/resource/1"; String res2 = "cant/touch/this"; assertFalse(app.isDeniedExplicitly(u.getId(), res2, "GET")); app.grantResourcePermission(ALLOW_ALL, res1, WRITE); assertTrue(app.isAllowedTo(u.getId(), res1, "POST")); assertTrue(app.isAllowedTo(u2.getId(), res1, "POST")); assertFalse(app.isDeniedExplicitly(u.getId(), ALLOW_ALL, "GET")); assertFalse(app.isDeniedExplicitly(u2.getId(), ALLOW_ALL, "GET")); assertFalse(app.isDeniedExplicitly(u.getId(), ALLOW_ALL, "POST")); assertFalse(app.isDeniedExplicitly(u.getId(), res1, "POST")); assertFalse(app.isDeniedExplicitly(u2.getId(), res1, "PUT")); // explicit restrictions app.grantResourcePermission(u2.getId(), res2, NONE); assertFalse(app.isAllowedTo(u2.getId(), res2, "GET")); assertTrue(app.isDeniedExplicitly(u2.getId(), res2, "GET")); assertTrue(app.isDeniedExplicitly(u2.getId(), res2, "DELETE")); assertFalse(app.isDeniedExplicitly(u2.getId(), ALLOW_ALL, "PUT")); // specific restrictions per "id" take precedence app.grantResourcePermission(ALLOW_ALL, res2, READ); assertFalse(app.isAllowedTo(u2.getId(), res2, "GET")); assertTrue(app.isDeniedExplicitly(u2.getId(), res2, "GET")); app.grantResourcePermission(ALLOW_ALL, ALLOW_ALL, READ); assertFalse(app.isDeniedExplicitly(u2.getId(), "this/is/test", "GET")); assertTrue(app.isDeniedExplicitly(u2.getId(), res2, "GET")); // wildcard restrictions assertFalse(app2.isDeniedExplicitly(u.getId(), res2, "POST")); app2.grantResourcePermission(ALLOW_ALL, res2, READ); assertTrue(app2.isDeniedExplicitly(u.getId(), res2, "POST")); assertTrue(app2.isDeniedExplicitly(u2.getId(), res2, "PUT")); } }