diff --git a/doc/release-notes/1083-mydata-npe-with-harvested-dataverses.md b/doc/release-notes/1083-mydata-npe-with-harvested-dataverses.md new file mode 100644 index 00000000000..230d69c9b9f --- /dev/null +++ b/doc/release-notes/1083-mydata-npe-with-harvested-dataverses.md @@ -0,0 +1 @@ +Fix a bug with My Data where listing dataverses for a user with only rights on harvested dataverses would result in a server error response. \ No newline at end of file diff --git a/src/main/java/edu/harvard/iq/dataverse/mydata/MyDataFinder.java b/src/main/java/edu/harvard/iq/dataverse/mydata/MyDataFinder.java index 5626a442762..091fbde484e 100644 --- a/src/main/java/edu/harvard/iq/dataverse/mydata/MyDataFinder.java +++ b/src/main/java/edu/harvard/iq/dataverse/mydata/MyDataFinder.java @@ -439,19 +439,6 @@ private boolean runStep1RoleAssignments() { if (results == null) { this.addErrorMessage(BundleUtil.getStringFromBundle("myDataFinder.error.result.null")); return false; - } else if (results.isEmpty()) { - List roleNames = this.rolePermissionHelper.getRoleNamesByIdList(this.filterParams.getRoleIds()); - if ((roleNames == null) || (roleNames.isEmpty())) { - this.addErrorMessage(BundleUtil.getStringFromBundle("myDataFinder.error.result.no.role")); - } else { - final List args = Arrays.asList(StringUtils.join(roleNames, ", ")); - if (roleNames.size() == 1) { - this.addErrorMessage(BundleUtil.getStringFromBundle("myDataFinder.error.result.role.empty", args)); - } else { - this.addErrorMessage(BundleUtil.getStringFromBundle("myDataFinder.error.result.roles.empty", args)); - } - } - return false; } // Iterate through assigned objects, a single object may end up in @@ -485,6 +472,21 @@ private boolean runStep1RoleAssignments() { } directDvObjectIds.add(dvId); } + + if (directDvObjectIds.isEmpty()) { + List roleNames = this.rolePermissionHelper.getRoleNamesByIdList(this.filterParams.getRoleIds()); + if ((roleNames == null) || (roleNames.isEmpty())) { + this.addErrorMessage(BundleUtil.getStringFromBundle("myDataFinder.error.result.no.role")); + } else { + final List args = Arrays.asList(StringUtils.join(roleNames, ", ")); + if (roleNames.size() == 1) { + this.addErrorMessage(BundleUtil.getStringFromBundle("myDataFinder.error.result.role.empty", args)); + } else { + this.addErrorMessage(BundleUtil.getStringFromBundle("myDataFinder.error.result.roles.empty", args)); + } + } + return false; + } return true; } diff --git a/src/test/java/edu/harvard/iq/dataverse/api/DataRetrieverApiIT.java b/src/test/java/edu/harvard/iq/dataverse/api/DataRetrieverApiIT.java index 3cd03abeb38..d5c80cde1aa 100644 --- a/src/test/java/edu/harvard/iq/dataverse/api/DataRetrieverApiIT.java +++ b/src/test/java/edu/harvard/iq/dataverse/api/DataRetrieverApiIT.java @@ -3,8 +3,10 @@ import io.restassured.RestAssured; import io.restassured.response.Response; import edu.harvard.iq.dataverse.api.auth.ApiKeyAuthMechanism; +import edu.harvard.iq.dataverse.authorization.DataverseRole; import edu.harvard.iq.dataverse.util.BundleUtil; +import io.restassured.path.json.JsonPath; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -44,12 +46,62 @@ public void testRetrieveMyDataAsJsonString() { assertEquals(prettyPrintError("dataretrieverAPI.user.not.found", Arrays.asList(badUserIdentifier)), invalidUserIdentifierResponse.prettyPrint()); assertEquals(OK.getStatusCode(), invalidUserIdentifierResponse.getStatusCode()); - // Call as superuser with valid user identifier + // Call as superuser with valid user identifier and no roles Response createSecondUserResponse = UtilIT.createRandomUser(); String userIdentifier = UtilIT.getUsernameFromResponse(createSecondUserResponse); Response validUserIdentifierResponse = UtilIT.retrieveMyDataAsJsonString(superUserApiToken, userIdentifier, emptyRoleIdsList); assertEquals(prettyPrintError("myDataFinder.error.result.no.role", null), validUserIdentifierResponse.prettyPrint()); assertEquals(OK.getStatusCode(), validUserIdentifierResponse.getStatusCode()); + + // Call as normal user with one valid role and no results + Response createNormalUserResponse = UtilIT.createRandomUser(); + String normalUserUsername = UtilIT.getUsernameFromResponse(createNormalUserResponse); + String normalUserApiToken = UtilIT.getApiTokenFromResponse(createNormalUserResponse); + Response noResultwithOneRoleResponse = UtilIT.retrieveMyDataAsJsonString(normalUserApiToken, "", new ArrayList<>(Arrays.asList(5L))); + assertEquals(prettyPrintError("myDataFinder.error.result.role.empty", Arrays.asList("Dataset Creator")), noResultwithOneRoleResponse.prettyPrint()); + assertEquals(OK.getStatusCode(), noResultwithOneRoleResponse.getStatusCode()); + + // Call as normal user with multiple valid roles and no results + Response noResultWithMultipleRoleResponse = UtilIT.retrieveMyDataAsJsonString(normalUserApiToken, "", new ArrayList<>(Arrays.asList(5L, 6L))); + assertEquals(prettyPrintError("myDataFinder.error.result.roles.empty", Arrays.asList("Dataset Creator, Contributor")), noResultWithMultipleRoleResponse.prettyPrint()); + assertEquals(OK.getStatusCode(), noResultWithMultipleRoleResponse.getStatusCode()); + + // Call as normal user with one valid dataset role and one dataset result + Response createDataverseResponse = UtilIT.createRandomDataverse(normalUserApiToken); + createDataverseResponse.prettyPrint(); + String dataverseAlias = UtilIT.getAliasFromResponse(createDataverseResponse); + + Response createDatasetResponse = UtilIT.createRandomDatasetViaNativeApi(dataverseAlias, normalUserApiToken); + createDatasetResponse.prettyPrint(); + Integer datasetId = UtilIT.getDatasetIdFromResponse(createDatasetResponse); + UtilIT.sleepForReindex(datasetId.toString(), normalUserApiToken, 4); + Response oneDatasetResponse = UtilIT.retrieveMyDataAsJsonString(normalUserApiToken, "", new ArrayList<>(Arrays.asList(6L))); + assertEquals(OK.getStatusCode(), oneDatasetResponse.getStatusCode()); + JsonPath jsonPathOneDataset = oneDatasetResponse.getBody().jsonPath(); + assertEquals(1, jsonPathOneDataset.getInt("data.total_count")); + assertEquals(datasetId, jsonPathOneDataset.getInt("data.items[0].entity_id")); + + // Call as normal user with one valid dataverse role and one dataverse result + UtilIT.grantRoleOnDataverse(dataverseAlias, DataverseRole.DS_CONTRIBUTOR.toString(), + "@" + normalUserUsername, superUserApiToken); + Response oneDataverseResponse = UtilIT.retrieveMyDataAsJsonString(normalUserApiToken, "", new ArrayList<>(Arrays.asList(5L))); + assertEquals(OK.getStatusCode(), oneDataverseResponse.getStatusCode()); + JsonPath jsonPathOneDataverse = oneDataverseResponse.getBody().jsonPath(); + assertEquals(1, jsonPathOneDataverse.getInt("data.total_count")); + assertEquals(dataverseAlias, jsonPathOneDataverse.getString("data.items[0].name")); + + // Clean up + Response deleteDatasetResponse = UtilIT.deleteDatasetViaNativeApi(datasetId, normalUserApiToken); + deleteDatasetResponse.prettyPrint(); + assertEquals(200, deleteDatasetResponse.getStatusCode()); + + Response deleteDataverseResponse = UtilIT.deleteDataverse(dataverseAlias, normalUserApiToken); + deleteDataverseResponse.prettyPrint(); + assertEquals(200, deleteDataverseResponse.getStatusCode()); + + Response deleteUserResponse = UtilIT.deleteUser(normalUserUsername); + deleteUserResponse.prettyPrint(); + assertEquals(200, deleteUserResponse.getStatusCode()); } private static String prettyPrintError(String resourceBundleKey, List params) {