diff src/test/java/edu/harvard/iq/dataverse/api/SearchIT.java @ 10:a50cf11e5178

Rewrite LGDataverse completely upgrading to dataverse4.0
author Zoe Hong <zhong@mpiwg-berlin.mpg.de>
date Tue, 08 Sep 2015 17:00:21 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/java/edu/harvard/iq/dataverse/api/SearchIT.java	Tue Sep 08 17:00:21 2015 +0200
@@ -0,0 +1,416 @@
+package edu.harvard.iq.dataverse.api;
+
+import static com.jayway.restassured.RestAssured.given;
+import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.path.json.JsonPath;
+import static com.jayway.restassured.path.xml.XmlPath.from;
+import com.jayway.restassured.response.Response;
+import edu.harvard.iq.dataverse.Dataverse;
+import edu.harvard.iq.dataverse.search.SearchFields;
+import edu.harvard.iq.dataverse.settings.SettingsServiceBean;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.logging.Logger;
+import javax.json.Json;
+import javax.json.JsonArrayBuilder;
+import javax.json.JsonObject;
+import javax.json.JsonObjectBuilder;
+import junit.framework.Assert;
+import static junit.framework.Assert.assertEquals;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class SearchIT {
+
+    private static final Logger logger = Logger.getLogger(SearchIT.class.getCanonicalName());
+
+    private static final String builtinUserKey = "burrito";
+    private static final String EMPTY_STRING = "";
+    private static final String idKey = "id";
+    private static final String apiTokenKey = "apiToken";
+    private static final String usernameKey = "userName";
+    private static final String emailKey = "email";
+    private static TestUser homer;
+    private static TestUser ned;
+    private static final String dv1 = "dv1";
+    private static String dataset1;
+    private static long nedAdminOnRootAssignment;
+    private static final String dataverseToCreateDataset1In = "root";
+
+    public SearchIT() {
+    }
+
+    @BeforeClass
+    public static void setUpClass() {
+
+        boolean enabled = true;
+        if (!enabled) {
+            return;
+        }
+
+        logger.info("Running setup...");
+
+        JsonObject homerJsonObject = createUser(getUserAsJsonString("homer", "Homer", "Simpson"));
+        homer = new TestUser(homerJsonObject);
+
+        JsonObject nedJsonObject = createUser(getUserAsJsonString("ned", "Ned", "Flanders"));
+        ned = new TestUser(nedJsonObject);
+    }
+
+    @Test
+    public void homerGivesNedPermissionAtRoot() {
+
+        Response enableNonPublicSearch = enableSetting(SettingsServiceBean.Key.SearchApiNonPublicAllowed);
+        assertEquals(200, enableNonPublicSearch.getStatusCode());
+
+        Response makeSuperUserResponse = makeSuperuser(homer.getUsername());
+        assertEquals(200, makeSuperUserResponse.getStatusCode());
+
+        String xmlIn = getDatasetXml(homer.getUsername(), homer.getUsername(), homer.getUsername());
+        Response createDataset1Response = createDataset(xmlIn, dataverseToCreateDataset1In, homer.getApiToken());
+        assertEquals(201, createDataset1Response.getStatusCode());
+
+        dataset1 = getGlobalId(createDataset1Response);
+
+        Integer idHomerFound = printDatasetId(dataset1, homer);
+        assertEquals(true, idHomerFound != null);
+
+        Integer idNedFoundBeforeBecomingAdmin = printDatasetId(dataset1, ned);
+        String roleToAssign = "admin";
+        assertEquals(null, idNedFoundBeforeBecomingAdmin);
+
+        Response grantNedAdminOnRoot = grantRole(dataverseToCreateDataset1In, roleToAssign, ned.getUsername(), homer.getApiToken());
+        assertEquals(200, grantNedAdminOnRoot.getStatusCode());
+
+        Integer idNedFoundAfterBecomingAdmin = printDatasetId(dataset1, ned);
+        assertEquals(idHomerFound, idNedFoundAfterBecomingAdmin);
+
+        nedAdminOnRootAssignment = getRoleAssignmentId(grantNedAdminOnRoot);
+        Response revokeNedAdminOnRoot = revokeRole(dataverseToCreateDataset1In, nedAdminOnRootAssignment, homer.getApiToken());
+        assertEquals(200, revokeNedAdminOnRoot.getStatusCode());
+
+        Integer idNedFoundAfterNoLongerAdmin = printDatasetId(dataset1, ned);
+        assertEquals(null, idNedFoundAfterNoLongerAdmin);
+
+        Response disableNonPublicSearch = deleteSetting(SettingsServiceBean.Key.SearchApiNonPublicAllowed);
+        assertEquals(200, disableNonPublicSearch.getStatusCode());
+
+    }
+
+    @Test
+    public void dataverseCategory() {
+        Response enableNonPublicSearch = enableSetting(SettingsServiceBean.Key.SearchApiNonPublicAllowed);
+        assertEquals(200, enableNonPublicSearch.getStatusCode());
+
+        /**
+         * Unfortunately, it appears that the ability to specify the category of
+         * a dataverse when creating it is a GUI-only feature. It can't
+         * currently be done via the API, to our knowledge. You also can't tell
+         * from the API which category was persisted but it always seems to be
+         * "UNCATEGORIZED"
+         */
+        TestDataverse dataverseToCreate = new TestDataverse(dv1, "dv1", Dataverse.DataverseType.ORGANIZATIONS_INSTITUTIONS);
+        Response createDvResponse = createDataverse(dataverseToCreate, homer);
+        assertEquals(201, createDvResponse.getStatusCode());
+
+        TestSearchQuery query = new TestSearchQuery("dv1");
+        Response searchResponse = search(query, homer);
+        JsonPath jsonPath = JsonPath.from(searchResponse.body().asString());
+        String dv1Category = jsonPath.get("data.facets." + SearchFields.DATAVERSE_CATEGORY).toString();
+        String msg = "dv1Category: " + dv1Category;
+        assertEquals("dv1Category: [null]", msg);
+
+        Response disableNonPublicSearch = deleteSetting(SettingsServiceBean.Key.SearchApiNonPublicAllowed);
+        assertEquals(200, disableNonPublicSearch.getStatusCode());
+    }
+
+    @AfterClass
+    public static void cleanup() {
+
+        boolean enabled = true;
+        if (!enabled) {
+            return;
+        }
+
+        logger.info("Running cleanup...");
+
+        /**
+         * We revoke roles here just in case an assertion failed because role
+         * assignments are currently not deleted when you delete a user per
+         * https://github.com/IQSS/dataverse/issues/1929
+         *
+         * You can also delete the role assignments manually like this:
+         *
+         * "DELETE FROM roleassignment WHERE assigneeidentifier='@ned';"
+         */
+        Response revokeNedAdminOnRoot = revokeRole(dataverseToCreateDataset1In, nedAdminOnRootAssignment, homer.getApiToken());
+        System.out.println("cleanup - status code revoking admin on root from ned: " + revokeNedAdminOnRoot.getStatusCode());
+        Response deleteDataset1Response = deleteDataset(dataset1, homer.getApiToken());
+        assertEquals(204, deleteDataset1Response.getStatusCode());
+
+        Response deleteDv1Response = deleteDataverse(dv1, homer);
+        assertEquals(200, deleteDv1Response.getStatusCode());
+
+        deleteUser(homer.getUsername());
+        deleteUser(ned.getUsername());
+    }
+
+    private Response enableSetting(SettingsServiceBean.Key settingKey) {
+        Response response = given().body("true").when().put("/api/admin/settings/" + settingKey);
+        return response;
+    }
+
+    private Response deleteSetting(SettingsServiceBean.Key settingKey) {
+        Response response = given().when().delete("/api/admin/settings/" + settingKey);
+        return response;
+    }
+
+    private Response checkSetting(SettingsServiceBean.Key settingKey) {
+        Response response = given().when().get("/api/admin/settings/" + settingKey);
+        return response;
+    }
+
+    private static Response createDataverse(TestDataverse dataverseToCreate, TestUser creator) {
+        JsonArrayBuilder contactArrayBuilder = Json.createArrayBuilder();
+        contactArrayBuilder.add(Json.createObjectBuilder().add("contactEmail", creator.getEmail()));
+        JsonArrayBuilder subjectArrayBuilder = Json.createArrayBuilder();
+        subjectArrayBuilder.add("Other");
+        JsonObject dvData = Json.createObjectBuilder()
+                .add("alias", dataverseToCreate.alias)
+                .add("name", dataverseToCreate.name)
+                .add("dataverseContacts", contactArrayBuilder)
+                .add("dataverseSubjects", subjectArrayBuilder)
+                .build();
+        Response createDataverseResponse = given()
+                .body(dvData.toString()).contentType(ContentType.JSON)
+                .when().post("/api/dataverses/:root?key=" + creator.apiToken);
+        return createDataverseResponse;
+    }
+
+    private Response createDataset(String xmlIn, String dataverseToCreateDatasetIn, String apiToken) {
+        Response createDatasetResponse = given()
+                .auth().basic(apiToken, EMPTY_STRING)
+                .body(xmlIn)
+                .contentType("application/atom+xml")
+                .post("/dvn/api/data-deposit/v1.1/swordv2/collection/dataverse/" + dataverseToCreateDatasetIn);
+        return createDatasetResponse;
+    }
+
+    private static JsonObject createUser(String jsonStr) {
+        JsonObjectBuilder createdUser = Json.createObjectBuilder();
+        Response response = createUserViaApi(jsonStr, getPassword(jsonStr));
+        Assert.assertEquals(200, response.getStatusCode());
+        JsonPath jsonPath = JsonPath.from(response.body().asString());
+        createdUser.add(idKey, jsonPath.getInt("data.user." + idKey));
+        createdUser.add(usernameKey, jsonPath.get("data.user." + usernameKey).toString());
+        createdUser.add(apiTokenKey, jsonPath.get("data." + apiTokenKey).toString());
+        return createdUser.build();
+    }
+
+    private static String getPassword(String jsonStr) {
+        String password = JsonPath.from(jsonStr).get(usernameKey);
+        return password;
+    }
+
+    private static String getUserAsJsonString(String username, String firstName, String lastName) {
+        JsonObjectBuilder builder = Json.createObjectBuilder();
+        builder.add(usernameKey, username);
+        builder.add("firstName", firstName);
+        builder.add("lastName", lastName);
+        builder.add(emailKey, getEmailFromUserName(username));
+        String userAsJson = builder.build().toString();
+        logger.fine("User to create: " + userAsJson);
+        return userAsJson;
+    }
+
+    private static String getEmailFromUserName(String username) {
+        return username + "@mailinator.com";
+    }
+
+    private static Response createUserViaApi(String jsonStr, String password) {
+        Response response = given().body(jsonStr).contentType(ContentType.JSON).when().post("/api/builtin-users?key=" + builtinUserKey + "&password=" + password);
+        return response;
+    }
+
+    private static Response makeSuperuser(String userToMakeSuperuser) {
+        Response response = given().post("/api/admin/superuser/" + userToMakeSuperuser);
+        return response;
+    }
+
+    private Response grantRole(String definitionPoint, String role, String roleAssignee, String apiToken) {
+        JsonObjectBuilder roleBuilder = Json.createObjectBuilder();
+        roleBuilder.add("assignee", "@" + roleAssignee);
+        roleBuilder.add("role", role);
+        JsonObject roleObject = roleBuilder.build();
+        System.out.println("Granting role on dataverse alias \"" + definitionPoint + "\": " + roleObject);
+        return given()
+                .body(roleObject).contentType(ContentType.JSON)
+                .post("api/dataverses/" + definitionPoint + "/assignments?key=" + apiToken);
+    }
+
+    private static Response revokeRole(String definitionPoint, long doomed, String apiToken) {
+        System.out.println("Attempting to revoke role assignment id " + doomed);
+        /**
+         * OUTPUT=`curl -s -X DELETE
+         * "http://localhost:8080/api/dataverses/$BIRDS_DATAVERSE/assignments/$SPRUCE_ADMIN_ON_BIRDS?key=$FINCHKEY"`
+         */
+        return given()
+                .delete("api/dataverses/" + definitionPoint + "/assignments/" + doomed + "?key=" + apiToken);
+    }
+
+    private String getGlobalId(Response createDatasetResponse) {
+        String xml = createDatasetResponse.body().asString();
+        String datasetSwordIdUrl = from(xml).get("entry.id");
+        /**
+         * @todo stop assuming the last 22 characters are the doi/globalId
+         */
+        return datasetSwordIdUrl.substring(datasetSwordIdUrl.length() - 22);
+    }
+
+    /**
+     * Assumes you have turned on experimental non-public search
+     * https://github.com/IQSS/dataverse/issues/1299
+     *
+     * curl -X PUT -d true
+     * http://localhost:8080/api/admin/settings/:SearchApiNonPublicAllowed
+     *
+     * @return The Integer found or null.
+     */
+    private static Integer findDatasetIdFromGlobalId(String globalId, String apiToken) {
+        Response searchForGlobalId = given()
+                .get("api/search?key=" + apiToken
+                        + "&q=dsPersistentId:\""
+                        + globalId.replace(":", "\\:")
+                        + "\"&show_entity_ids=true");
+        JsonPath jsonPath = JsonPath.from(searchForGlobalId.body().asString());
+        int id;
+        try {
+            id = jsonPath.get("data.items[0].entity_id");
+        } catch (IllegalArgumentException ex) {
+            return null;
+        }
+        return id;
+    }
+
+    private String getDatasetXml(String title, String author, String description) {
+        String xmlIn = "<?xml version=\"1.0\"?>\n"
+                + "<entry xmlns=\"http://www.w3.org/2005/Atom\" xmlns:dcterms=\"http://purl.org/dc/terms/\">\n"
+                + "   <dcterms:title>" + title + "</dcterms:title>\n"
+                + "   <dcterms:creator>" + author + "</dcterms:creator>\n"
+                + "   <dcterms:description>" + description + "</dcterms:description>\n"
+                + "</entry>\n"
+                + "";
+        return xmlIn;
+    }
+
+    private static Response deleteDataverse(String doomed, TestUser user) {
+        return given().delete("/api/dataverses/" + doomed + "?key=" + user.getApiToken());
+    }
+
+    private static Response deleteDataset(String globalId, String apiToken) {
+        return given()
+                .auth().basic(apiToken, EMPTY_STRING)
+                .relaxedHTTPSValidation()
+                .delete("/dvn/api/data-deposit/v1.1/swordv2/edit/study/" + globalId);
+    }
+
+    private static void deleteUser(String username) {
+        Response deleteUserResponse = given().delete("/api/admin/authenticatedUsers/" + username + "/");
+        assertEquals(200, deleteUserResponse.getStatusCode());
+    }
+
+    private long getRoleAssignmentId(Response response) {
+        JsonPath jsonPath = JsonPath.from(response.body().asString());
+        return jsonPath.getInt("data.id");
+    }
+
+    private Integer printDatasetId(String dataset1, TestUser user) {
+        Integer datasetIdFound = findDatasetIdFromGlobalId(dataset1, user.getApiToken());
+        System.out.println(dataset1 + " id " + datasetIdFound + " found by " + user);
+        return datasetIdFound;
+    }
+
+    private Response search(TestSearchQuery query, TestUser user) {
+        return given()
+                .get("api/search?key=" + user.getApiToken()
+                        + "&q=" + query.getQuery()
+                        + "&show_facets=" + true
+                );
+    }
+
+    private static class TestUser {
+
+        private long id;
+        private String username;
+        private String apiToken;
+
+        private TestUser(JsonObject json) {
+            this.id = json.getInt(idKey);
+            this.username = json.getString(usernameKey);
+            this.apiToken = json.getString(apiTokenKey);
+        }
+
+        public long getId() {
+            return id;
+        }
+
+        public String getUsername() {
+            return username;
+        }
+
+        public String getApiToken() {
+            return apiToken;
+        }
+
+        public String getEmail() {
+            return getEmailFromUserName(username);
+        }
+
+        @Override
+        public String toString() {
+            return "TestUser{" + "id=" + id + ", username=" + username + '}';
+        }
+
+    }
+
+    private static class TestDataverse {
+
+        String alias;
+        String name;
+        Dataverse.DataverseType category;
+
+        public TestDataverse(String alias, String name, Dataverse.DataverseType category) {
+            this.alias = alias;
+            this.name = name;
+            this.category = category;
+        }
+
+    }
+
+    private static class TestSearchQuery {
+
+        private String query;
+        private List<String> filterQueries = new ArrayList<>();
+
+        private TestSearchQuery(String query) {
+            this.query = query;
+        }
+
+        public TestSearchQuery(String query, List<String> filterQueries) {
+            this.query = query;
+            if (!filterQueries.isEmpty()) {
+                this.filterQueries = filterQueries;
+            }
+        }
+
+        public String getQuery() {
+            return query;
+        }
+
+        public List<String> getFilterQueries() {
+            return filterQueries;
+        }
+
+    }
+}