Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions doc/release-notes/11465-api-fetch-download-size-file-count.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
The following APIs have now been blocked for Guest Users:

/api/v1/datasets/:persistentId/versions/:latest-published/downloadsize?persistentId=doi:10.5072/FK2/VSAYEM&includeDeaccessioned=true&mode=Archival
/api/v1/datasets/:persistentId/versions/1.0/files/counts?persistentId=doi:10.5072/FK2/VSAYEM&includeDeaccessioned=true
3 changes: 3 additions & 0 deletions doc/sphinx-guides/source/api/native-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1800,6 +1800,8 @@ The returned file counts are based on different criteria:
- Per tabular tag name
- Per access status (Possible values: Public, Restricted, EmbargoedThenRestricted, EmbargoedThenPublic, RetentionPeriodExpired)

Note: Authentication is required. This call will return a 403/Forbidden response for Guest users.

.. code-block:: bash

export SERVER_URL=https://demo.dataverse.org
Expand Down Expand Up @@ -2781,6 +2783,7 @@ Get the size of Downloading all the files of a Dataset Version
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Shows the combined size in bytes of all the files available for download from version ``versionId`` of dataset ``id``.
Note: Authentication is required. This call will return a 403/Forbidden response for Guest users.

.. code-block:: bash

Expand Down
11 changes: 10 additions & 1 deletion src/main/java/edu/harvard/iq/dataverse/api/Datasets.java
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,11 @@ public Response getVersionFileCounts(@Context ContainerRequestContext crc,
@QueryParam("includeDeaccessioned") boolean includeDeaccessioned,
@Context UriInfo uriInfo,
@Context HttpHeaders headers) {
try {
getRequestAuthenticatedUserOrDie(crc);
} catch (WrappedResponse e) {
return forbidden(BundleUtil.getStringFromBundle("datasets.api.version.files.invalid.auth"));
}
return response(req -> {
FileSearchCriteria fileSearchCriteria;
try {
Expand Down Expand Up @@ -3514,7 +3519,11 @@ public Response getDownloadSize(@Context ContainerRequestContext crc,
@QueryParam("includeDeaccessioned") boolean includeDeaccessioned,
@Context UriInfo uriInfo,
@Context HttpHeaders headers) {

try {
getRequestAuthenticatedUserOrDie(crc);
} catch (WrappedResponse e) {
return forbidden(BundleUtil.getStringFromBundle("datasets.api.version.files.invalid.auth"));
}
return response(req -> {
FileSearchCriteria fileSearchCriteria;
try {
Expand Down
1 change: 1 addition & 0 deletions src/main/java/propertyFiles/Bundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2833,6 +2833,7 @@ datasets.api.curationstatuscreatetime=Status Set Time
datasets.api.curationstatussetter=Status Set By
datasets.api.version.files.invalid.order.criteria=Invalid order criteria: {0}
datasets.api.version.files.invalid.access.status=Invalid access status: {0}
datasets.api.version.files.invalid.auth=Only authenticated users can access this information.
datasets.api.deaccessionDataset.invalid.version.identifier.error=Only {0} or a specific version can be deaccessioned
datasets.api.deaccessionDataset.invalid.forward.url=Invalid deaccession forward URL: {0}
datasets.api.globusdownloaddisabled=File transfer from Dataverse via Globus is not available for this dataset.
Expand Down
8 changes: 4 additions & 4 deletions src/test/java/edu/harvard/iq/dataverse/api/DatasetsIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -5616,10 +5616,10 @@ public void getVersionFileCounts() throws IOException, InterruptedException {
// Test that the dataset file counts for a deaccessioned dataset cannot be accessed by a guest
// By latest published version
Response getDatasetVersionResponse = UtilIT.getVersionFileCounts(datasetId, DS_VERSION_LATEST_PUBLISHED, null, null, null, null, null, true, null);
getDatasetVersionResponse.then().assertThat().statusCode(NOT_FOUND.getStatusCode());
getDatasetVersionResponse.then().assertThat().statusCode(FORBIDDEN.getStatusCode());
// By specific version 1.0
getDatasetVersionResponse = UtilIT.getVersionFileCounts(datasetId, "1.0", null, null, null, null, null, true, null);
getDatasetVersionResponse.then().assertThat().statusCode(NOT_FOUND.getStatusCode());
getDatasetVersionResponse.then().assertThat().statusCode(FORBIDDEN.getStatusCode());
}

@Test
Expand Down Expand Up @@ -5806,10 +5806,10 @@ public void getDownloadSize() throws IOException, InterruptedException {
// Test that the dataset file counts for a deaccessioned dataset cannot be accessed by a guest
// By latest published version
Response getVersionFileCountsGuestUserResponse = UtilIT.getDownloadSize(datasetId, DS_VERSION_LATEST_PUBLISHED, null, null, null, null, null, DatasetVersionFilesServiceBean.FileDownloadSizeMode.All.toString(), true, null);
getVersionFileCountsGuestUserResponse.then().assertThat().statusCode(NOT_FOUND.getStatusCode());
getVersionFileCountsGuestUserResponse.then().assertThat().statusCode(FORBIDDEN.getStatusCode());
// By specific version 1.0
getVersionFileCountsGuestUserResponse = UtilIT.getDownloadSize(datasetId, "1.0", null, null, null, null, null, DatasetVersionFilesServiceBean.FileDownloadSizeMode.All.toString(), true, null);
getVersionFileCountsGuestUserResponse.then().assertThat().statusCode(NOT_FOUND.getStatusCode());
getVersionFileCountsGuestUserResponse.then().assertThat().statusCode(FORBIDDEN.getStatusCode());
}

@Test
Expand Down
79 changes: 78 additions & 1 deletion src/test/java/edu/harvard/iq/dataverse/api/FilesIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -1442,13 +1442,90 @@ public void testDataSizeInDataverse() throws InterruptedException {

magicControlString = MessageFormat.format(BundleUtil.getStringFromBundle("datasets.api.datasize.download"), magicSizeNumber);

Response datasetDownloadSizeResponse = UtilIT.findDatasetDownloadSize(datasetId.toString());
Response datasetDownloadSizeResponse = UtilIT.findDatasetDownloadSize(datasetId.toString(), apiTokenRando, null, null, null);
datasetDownloadSizeResponse.prettyPrint();

assertEquals(magicControlString, JsonPath.from(datasetDownloadSizeResponse.body().asString()).getString("data.message"));

}

@Test
public void testDeaccessionedDatasetGetDownloadSize() {
// Create user
String apiToken = createUserGetToken();
// Create Dataverse
String dataverseAlias = createDataverseGetAlias(apiToken);
// Create Dataset
String datasetId1 = createDatasetGetId(dataverseAlias, apiToken).toString();
String datasetId2 = createDatasetGetId(dataverseAlias, apiToken).toString();
String pathToFile = "scripts/search/data/binary/trees.png";
Response addResponse = UtilIT.uploadFileViaNative(datasetId1, pathToFile, apiToken);

// Publish
UtilIT.publishDataverseViaNativeApi(dataverseAlias, apiToken);
UtilIT.publishDatasetViaNativeApi(datasetId1, "major", apiToken);
UtilIT.publishDatasetViaNativeApi(datasetId2, "major", apiToken);

// Test get sizes from Published Dataset with no files
Response datasetDownloadSizeResponse = UtilIT.findDatasetDownloadSize(datasetId2, apiToken, null, Boolean.TRUE, null);
datasetDownloadSizeResponse.prettyPrint();
datasetDownloadSizeResponse.then().assertThat()
.body("data.message", containsString("0 bytes"))
.body("data.storageSize", equalTo(0))
.statusCode(OK.getStatusCode());
// Test get files count from Published Dataset with no files
Response datasetFilesCountResponse = UtilIT.findDatasetFilesCount(datasetId2, apiToken, null, Boolean.TRUE);
datasetFilesCountResponse.prettyPrint();
datasetFilesCountResponse.then().assertThat()
.body("data.total", equalTo(0))
.statusCode(OK.getStatusCode());

// Deaccession the Dataset
UtilIT.deaccessionDataset(datasetId1, "1.0", "reason", null, apiToken).prettyPrint();
UtilIT.deaccessionDataset(datasetId2, "1.0", "reason", null, apiToken).prettyPrint();

// Test get sizes from Deaccessioned Dataset with files (Auth user)
datasetDownloadSizeResponse = UtilIT.findDatasetDownloadSize(datasetId1, apiToken, null, Boolean.TRUE, "Archival");
datasetDownloadSizeResponse.prettyPrint();
datasetDownloadSizeResponse.then().assertThat()
.body("data.message", containsString("8,361 bytes"))
.body("data.storageSize", equalTo(8361))
.statusCode(OK.getStatusCode());
// Test get sizes from Deaccessioned Dataset with files (Guest user)
datasetDownloadSizeResponse = UtilIT.findDatasetDownloadSize(datasetId1, null, null, Boolean.TRUE, "Archival");
datasetDownloadSizeResponse.prettyPrint();
datasetDownloadSizeResponse.then().assertThat()
.statusCode(FORBIDDEN.getStatusCode())
.body("message", equalTo(BundleUtil.getStringFromBundle("datasets.api.version.files.invalid.auth")));

// Test get sizes from Deaccessioned Dataset with no files (Auth user)
datasetDownloadSizeResponse = UtilIT.findDatasetDownloadSize(datasetId2, apiToken, null, Boolean.TRUE, "Archival");
datasetDownloadSizeResponse.prettyPrint();
datasetDownloadSizeResponse.then().assertThat()
.body("data.message", containsString("0 bytes"))
.body("data.storageSize", equalTo(0))
.statusCode(OK.getStatusCode());
// Test get sizes from Deaccessioned Dataset with no files (Guest user)
datasetDownloadSizeResponse = UtilIT.findDatasetDownloadSize(datasetId2, null, null, Boolean.TRUE, "Archival");
datasetDownloadSizeResponse.prettyPrint();
datasetDownloadSizeResponse.then().assertThat()
.statusCode(FORBIDDEN.getStatusCode())
.body("message", equalTo(BundleUtil.getStringFromBundle("datasets.api.version.files.invalid.auth")));

// Test get files count from Deaccessioned Dataset with no files (Auth user)
datasetFilesCountResponse = UtilIT.findDatasetFilesCount(datasetId2, apiToken, null, Boolean.TRUE);
datasetFilesCountResponse.prettyPrint();
datasetFilesCountResponse.then().assertThat()
.body("data.total", equalTo(0))
.statusCode(OK.getStatusCode());
// Test get files count from Deaccessioned Dataset with no files (Guest user)
datasetFilesCountResponse = UtilIT.findDatasetFilesCount(datasetId2, null, null, Boolean.TRUE);
datasetFilesCountResponse.prettyPrint();
datasetFilesCountResponse.then().assertThat()
.statusCode(FORBIDDEN.getStatusCode())
.body("message", equalTo(BundleUtil.getStringFromBundle("datasets.api.version.files.invalid.auth")));
}

@Test
public void GetFileVersionDifferences() {
// Create superuser and regular user
Expand Down
49 changes: 48 additions & 1 deletion src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -3691,7 +3691,54 @@ static Response findDatasetDownloadSize(String datasetId, String version, Strin
.header(API_TOKEN_HTTP_HEADER, apiToken)
.get("/api/datasets/" + datasetId + "/versions/" + version + "/downloadsize");
}


static Response findDatasetDownloadSize(String datasetId, String apiToken, String version, Boolean includeDeaccessioned, String mode) {
String id = datasetId;
if (version == null) {
version = ":latest-published";
}
RequestSpecification requestSpecification = given();

if (datasetId.startsWith("doi:")) {
id = ":persistentId";
requestSpecification.queryParam("persistentId", datasetId);
}
if (includeDeaccessioned != null) {
requestSpecification.queryParam("includeDeaccessioned", includeDeaccessioned);
}
if (mode != null) {
requestSpecification.queryParam("mode", mode);
}

if (apiToken != null) {
requestSpecification.header(UtilIT.API_TOKEN_HTTP_HEADER, apiToken);
}
return requestSpecification
.get("/api/datasets/" + id + "/versions/" + version + "/downloadsize");
}

static Response findDatasetFilesCount(String datasetId, String apiToken, String version, Boolean includeDeaccessioned) {
String id = datasetId;
if (version == null) {
version = ":latest-published";
}
RequestSpecification requestSpecification = given();

if (datasetId.startsWith("doi:")) {
id = ":persistentId";
requestSpecification.queryParam("persistentId", datasetId);
}
if (includeDeaccessioned != null) {
requestSpecification.queryParam("includeDeaccessioned", includeDeaccessioned);
}

if (apiToken != null) {
requestSpecification.header(UtilIT.API_TOKEN_HTTP_HEADER, apiToken);
}
return requestSpecification
.get("/api/datasets/" + id + "/versions/" + version + "/files/counts");
}

static Response addBannerMessage(String pathToJsonFile) {
String jsonIn = getDatasetJson(pathToJsonFile);

Expand Down