/** * Copyright (C) 2010-2017 Structr GmbH * * This file is part of Structr <http://structr.org>. * * Structr is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * Structr is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Structr. If not, see <http://www.gnu.org/licenses/>. */ package org.structr.rest; import com.jayway.restassured.RestAssured; import com.jayway.restassured.filter.log.ResponseLoggingFilter; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertNotNull; import org.junit.Test; import org.structr.web.auth.UiAuthenticator; import org.structr.web.StructrUiTest; /** * * */ public class NestedResourcesTest extends StructrUiTest { /** * Test the creation of related objects using JSON objecs and plain strings. */ @Test public void testNodeAssociationOnCreate() { this.grant("User", UiAuthenticator.NON_AUTH_USER_POST, true); this.grant("TestThree", UiAuthenticator.AUTH_USER_POST, false); this.grant("TestFour", UiAuthenticator.AUTH_USER_POST | UiAuthenticator.AUTH_USER_GET, false); this.grant("TestFour/_Test", UiAuthenticator.AUTH_USER_GET, false); createEntity("/User", "{ name: user1, password: password1 }"); createEntity("/User", "{ name: user2, password: password2 }"); // Associate related object upon CREATION using a simple string { String testThree = createEntityAsUser("user2", "password2", "/TestThree", "{ name: \"TestThree\", visibleToAuthenticatedUsers: true }"); assertNotNull(testThree); String testFour = createEntityAsUser("user1", "password1", "/TestFour", "{ name: \"TestFour\", oneToOneTestThree: \"" + testThree + "\" }"); assertNotNull(testFour); // check association RestAssured .given() .contentType("application/json; charset=UTF-8") .filter(ResponseLoggingFilter.logResponseTo(System.out)) .header("X-User", "user1") .header("X-Password", "password1") .expect() .statusCode(200) .body("result_count", equalTo(1)) .body("result.id", equalTo(testFour)) .body("result.oneToOneTestThree.id", equalTo(testThree)) .when() .get("/TestFour/" + testFour + "/test"); } // Associate related object upon CREATION using a JSON object { String testThree = createEntityAsUser("user2", "password2", "/TestThree", "{ name: \"TestThree\", visibleToAuthenticatedUsers: true }"); assertNotNull(testThree); // Associate related object upon CREATION using a simple string String testFour = createEntityAsUser("user1", "password1", "/TestFour", "{ name: \"TestFour\", oneToOneTestThree: { id: \"" + testThree + "\" } }"); assertNotNull(testFour); // check association RestAssured .given() .contentType("application/json; charset=UTF-8") .header("X-User", "user1") .header("X-Password", "password1") .expect() .statusCode(200) .body("result_count", equalTo(1)) .body("result.id", equalTo(testFour)) .body("result.oneToOneTestThree.id", equalTo(testThree)) .when() .get("/TestFour/" + testFour + "/test"); } } /** * Test the creation of related objects using JSON objecs and plain strings. */ @Test public void testNodeAssociationOnUpdate() { this.grant("User", UiAuthenticator.NON_AUTH_USER_POST, true); this.grant("TestThree", UiAuthenticator.AUTH_USER_POST, false); this.grant("TestFour", UiAuthenticator.AUTH_USER_POST | UiAuthenticator.AUTH_USER_PUT, false); this.grant("TestFour/_Test", UiAuthenticator.AUTH_USER_GET, false); createEntity("/User", "{ name: user1, password: password1 }"); createEntity("/User", "{ name: user2, password: password2 }"); // Associate related object upon UPDATE using a simple string { String testThree = createEntityAsUser("user2", "password2", "/TestThree", "{ name: \"TestThree\", visibleToAuthenticatedUsers: true }"); assertNotNull(testThree); String testFour = createEntityAsUser("user1", "password1", "/TestFour", "{ name: \"TestFour\" }"); assertNotNull(testFour); // associate objects RestAssured .given() .contentType("application/json; charset=UTF-8") .body("{ oneToOneTestThree: \"" + testThree + "\" }") .header("X-User", "user1") .header("X-Password", "password1") .expect() .statusCode(200) .when() .put("/TestFour/" + testFour); // check association RestAssured .given() .contentType("application/json; charset=UTF-8") .filter(ResponseLoggingFilter.logResponseTo(System.out)) .header("X-User", "user1") .header("X-Password", "password1") .expect() .statusCode(200) .body("result_count", equalTo(1)) .body("result.id", equalTo(testFour)) .body("result.oneToOneTestThree.id", equalTo(testThree)) .when() .get("/TestFour/" + testFour + "/test"); } // Associate related object upon UPDATE using a simple string { String testThree = createEntityAsUser("user2", "password2", "/TestThree", "{ name: \"TestThree\", visibleToAuthenticatedUsers: true }"); assertNotNull(testThree); String testFour = createEntityAsUser("user1", "password1", "/TestFour", "{ name: \"TestFour\" }"); assertNotNull(testFour); // associate objects RestAssured .given() .contentType("application/json; charset=UTF-8") .body("{ oneToOneTestThree: { id: \"" + testThree + "\" } }") .header("X-User", "user1") .header("X-Password", "password1") .expect() .statusCode(200) .when() .put("/TestFour/" + testFour); // check association RestAssured .given() .contentType("application/json; charset=UTF-8") .filter(ResponseLoggingFilter.logResponseTo(System.out)) .header("X-User", "user1") .header("X-Password", "password1") .expect() .statusCode(200) .body("result_count", equalTo(1)) .body("result.id", equalTo(testFour)) .body("result.oneToOneTestThree.id", equalTo(testThree)) .when() .get("/TestFour/" + testFour + "/test"); } } /** * Test the creation of related objects using JSON objecs and plain strings, * including the (failed) modification of a property value on the related * object. This test expects a 403 Forbidden error. */ @Test public void testFailingNodeAssociationOnUpdateWithProperties() { this.grant("User", UiAuthenticator.NON_AUTH_USER_POST, true); this.grant("TestThree", UiAuthenticator.AUTH_USER_POST, false); this.grant("TestFour", UiAuthenticator.AUTH_USER_POST | UiAuthenticator.AUTH_USER_PUT, false); this.grant("TestFour/_Test", UiAuthenticator.AUTH_USER_GET, false); createEntity("/User", "{ name: user1, password: password1 }"); createEntity("/User", "{ name: user2, password: password2 }"); // Associate related object upon UPDATE using a simple string { String testThree = createEntityAsUser("user2", "password2", "/TestThree", "{ name: \"TestThree\", visibleToAuthenticatedUsers: true }"); assertNotNull(testThree); String testFour = createEntityAsUser("user1", "password1", "/TestFour", "{ name: \"TestFour\" }"); assertNotNull(testFour); // associate objects RestAssured .given() .contentType("application/json; charset=UTF-8") .body("{ oneToOneTestThree: { id: \"" + testThree + "\", name: \"test123\" } }") .header("X-User", "user1") .header("X-Password", "password1") .expect() .statusCode(403) .when() .put("/TestFour/" + testFour); } } /** * Test the creation of related objects using JSON objecs and plain strings, * including the modification of a property value on the related object. */ @Test public void testSuccessfulNodeAssociationOnUpdateWithProperties() { this.grant("User", UiAuthenticator.NON_AUTH_USER_POST, true); this.grant("TestThree", UiAuthenticator.AUTH_USER_POST, false); this.grant("TestFour", UiAuthenticator.AUTH_USER_POST | UiAuthenticator.AUTH_USER_PUT, false); this.grant("TestFour/_Test", UiAuthenticator.AUTH_USER_GET, false); createEntity("/User", "{ name: user1, password: password1 }"); // Associate related object upon UPDATE using a simple string { String testThree = createEntityAsUser("user1", "password1", "/TestThree", "{ name: \"TestThree\", visibleToAuthenticatedUsers: true }"); assertNotNull(testThree); String testFour = createEntityAsUser("user1", "password1", "/TestFour", "{ name: \"TestFour\" }"); assertNotNull(testFour); // associate objects RestAssured .given() .contentType("application/json; charset=UTF-8") .body("{ oneToOneTestThree: { id: \"" + testThree + "\", name: \"test123\" } }") .header("X-User", "user1") .header("X-Password", "password1") .expect() .statusCode(200) .when() .put("/TestFour/" + testFour); // check association RestAssured .given() .contentType("application/json; charset=UTF-8") .filter(ResponseLoggingFilter.logResponseTo(System.out)) .header("X-User", "user1") .header("X-Password", "password1") .expect() .statusCode(200) .body("result_count", equalTo(1)) .body("result.id", equalTo(testFour)) .body("result.oneToOneTestThree.id", equalTo(testThree)) .body("result.oneToOneTestThree.name", equalTo("test123")) .when() .get("/TestFour/" + testFour + "/test"); } } }