Skip to content

Commit 173b1be

Browse files
authored
Merge pull request #12110 from IQSS/12001-api-support-termofuse-guestbook
Feature Request: API to support Download Terms of Use and Guestbook
2 parents ee079f1 + 05f9b92 commit 173b1be

33 files changed

Lines changed: 2484 additions & 694 deletions
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
## Feature Request: API to support Download Terms of Use and Guestbook
2+
3+
## New Endpoints to download a file or files that required a Guestbook Response: POST
4+
A post to these endpoints with the body containing a JSON Guestbook Response will save the response and return a signed URL to download the file(s)
5+
6+
`/api/access/datafile/{fileId:.+}`
7+
`/api/access/datafiles/{fileIds}`
8+
`/api/access/dataset/{id}`
9+
`/api/access/dataset/{id}/versions/{versionId}`
10+
11+
A post to these endpoints with the body containing a JSON Guestbook Response will save the response before continuing the download.
12+
No signed URL option exists.
13+
`/api/access/datafiles`
14+
`/api/access/datafile/bundle/{fileId}` POST returns BundleDownloadInstance after processing Guestbook Responses from body.
15+
16+
## New CRUD Endpoints for Guestbook:
17+
Create a Guestbook: POST `/api/guestbooks/{dataverseIdentifier}`
18+
Get a Guestbook: GET `/api/guestbooks/{id}`
19+
Get a list of Guestbooks linked to a Dataverse Collection: GET `/api/guestbooks/{dataverseIdentifier}/list`
20+
Enable/Disable a Guestbook: PUT `/api/guestbooks/{dataverseIdentifier}/{id}/enabled` Body: `true` or `false`
21+
Note: There is no Update or Delete at this time. You can disable a Guestbook and create a new one.
22+
23+
## For Guestbook At Request:
24+
When JVM setting -Ddataverse.files.guestbook-at-request=true is used a request for access may require a Guestbook Response.
25+
PUT `/api/access/datafile/{id}/requestAccess` will now take a JSON Guestbook Response in the body.

doc/sphinx-guides/source/api/changelog.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,29 @@ This API changelog is experimental and we would love feedback on its usefulness.
77
:local:
88
:depth: 1
99

10+
v6.10
11+
-----
12+
- The following GET APIs will now return ``400`` if a required Guestbook Response is not supplied. A Guestbook Response can be passed to these APIs in the JSON body using a POST call. See the notes under :ref:`basic-file-access` and :ref:`download-by-dataset-by-version` for details.
13+
14+
- **/api/access/datafile/{fileId:.+}**
15+
16+
- **/api/access/datafiles/{fileIds}**
17+
18+
- **/api/access/dataset/{id}**
19+
20+
- **/api/access/dataset/{id}/versions/{versionId}**
21+
22+
- The following POST APIs will now return ``400`` if a required Guestbook Response is not supplied. A Guestbook Response can be passed to these APIs in the JSON body. See the note under :ref:`basic-download-by-dataset` for details.
23+
24+
- **/api/access/datafiles**
25+
26+
- **/api/access/datafile/bundle/{fileId}**
27+
28+
- The following PUT APIs will now return ``400`` if a required Guestbook Response is not supplied. When JVM setting -Ddataverse.files.guestbook-at-request=true is set a Guestbook Response may be required to be passed to these APIs in the JSON body. See the note under Configuration :ref:`dataverse.files.guestbook-at-request` for details.
29+
30+
- **/api/access/datafile/{id}/requestAccess**
31+
32+
1033
v6.9
1134
----
1235

doc/sphinx-guides/source/api/dataaccess.rst

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,15 @@ Please note that in addition to the files from dataset, an additional file call
2727

2828
There are two forms of the "download by dataset" API, a basic form and one that supports dataset versions.
2929

30+
.. _basic-download-by-dataset:
31+
3032
Basic Download By Dataset
3133
~~~~~~~~~~~~~~~~~~~~~~~~~
3234

3335
The basic form downloads files from the latest accessible version of the dataset. If you are not using an API token, this means the most recently published version. If you are using an API token with full access to the dataset, this means the draft version or the most recently published version if no draft exists.
3436

37+
.. note:: Files that require a Guestbook Response will require an additional step to supply the Guestbook Response. A POST to the same endpoint with the Guestbook Response in the body can return a signed url that can be used to download the file(s) via a browser or download manager. To determine what information is required in the response you must first get the Guestbook for the Dataset whose file(s) you are trying to access along with any Custom Questions. Call ``GET http://$SERVER/api/guestbooks/{id}`` with the guestbookId from the Dataset (See :ref:`dataset-json-representation` to get the Dataset with guestbookId) to retrieve the Guestbook and Custom Questions. Build the JSON response with the information requested and add it to the body of the POST call within "guestbookResponse":{}. For more about guestbooks, see :ref:`dataset-guestbooks` in the User Guide.
38+
3539
A curl example using a DOI (no version):
3640

3741
.. code-block:: bash
@@ -48,6 +52,8 @@ The fully expanded example above (without environment variables) looks like this
4852
4953
curl -L -O -J -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx https://demo.dataverse.org/api/access/dataset/:persistentId/?persistentId=doi:10.70122/FK2/N2XGBJ
5054
55+
.. _download-by-dataset-by-version:
56+
5157
Download By Dataset By Version
5258
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5359

@@ -59,6 +65,8 @@ The second form of the "download by dataset" API allows you to specify which ver
5965
* ``x.y`` a specific version, where ``x`` is the major version number and ``y`` is the minor version number.
6066
* ``x`` same as ``x.0``
6167

68+
.. note:: Files that require a Guestbook Response will require an additional step to supply the Guestbook Response. A POST to the same endpoint with the Guestbook Response in the body can return a signed url that can be used to download the file(s) via a browser or download manager. To determine what information is required in the response you must first get the Guestbook for the Dataset whose file(s) you are trying to access along with any Custom Questions. Call ``GET http://$SERVER/api/guestbooks/{id}`` with the guestbookId from the Dataset (See :ref:`dataset-json-representation` to get the Dataset with guestbookId) to retrieve the Guestbook and Custom Questions. Build the JSON response with the information requested and add it to the body of the POST call within "guestbookResponse":{}. For more about guestbooks, see :ref:`dataset-guestbooks` in the User Guide.
69+
6270
A curl example using a DOI (with version):
6371

6472
.. code-block:: bash
@@ -78,6 +86,8 @@ The fully expanded example above (without environment variables) looks like this
7886
7987
curl -O -J -H X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx https://demo.dataverse.org/api/access/dataset/:persistentId/versions/2.0?persistentId=doi:10.70122/FK2/N2XGBJ
8088
89+
.. _basic-file-access:
90+
8191
Basic File Access
8292
-----------------
8393

@@ -91,6 +101,11 @@ Basic access URI:
91101

92102
GET http://$SERVER/api/access/datafile/:persistentId?persistentId=doi:10.5072/FK2/J8SJZB
93103

104+
.. note:: Files that require a Guestbook Response will require an additional step to supply the Guestbook Response. A POST to the same endpoint with the Guestbook Response in the body can return a signed url that can be used to download the file(s) via a browser or download manager. For more about guestbooks, see :ref:`dataset-guestbooks` in the User Guide. In the following JSON example please note that the `name`, `email`, `institution`, and `position` fields will default to the User's account information if not included in the response. Call ``GET http://$SERVER/api/guestbooks/{id}`` with the guestbookId from the Dataset (See :ref:`dataset-json-representation` to get the Dataset with guestbookId) to retrieve the Guestbook and Custom Questions. Build the JSON response with the information requested and add it to the body of the POST call within "guestbookResponse":{}.
105+
106+
Example ::
107+
108+
POST http://$SERVER/api/access/datafile/:persistentId?persistentId=doi:10.5072/FK2/J8SJZB&signed=true -d '{"guestbookResponse": {"name": "My Name", "email": "myemail@example.com", "institution": "Harvard","position": "Staff", "answers": [{"id": 123,"value": "Good"},{"id": 124,"value": ["Multi","Line"]},{"id": 125,"value": "Yellow"}]}}'
94109

95110
Parameters:
96111
~~~~~~~~~~~
@@ -198,6 +213,8 @@ Returns the files listed, zipped. As of v6.7 the name of the zipped bundle will
198213

199214
.. note:: If any of the datafiles have the ``DirectoryLabel`` attributes in the corresponding ``FileMetadata`` entries, these will be added as folders to the Zip archive, and the files will be placed in them accordingly.
200215

216+
.. note:: If Guestbook Responses are required they can be included in the body along with the file ids as JSON: ``{"fileIds" :[1,2,3], {"guestbookResponse": {"answers": []}}}``. For more about guestbooks, see :ref:`dataset-guestbooks` in the User Guide.
217+
201218
Parameters:
202219
~~~~~~~~~~~
203220

@@ -378,7 +395,9 @@ This method requests access to the datafile whose id is passed on the behalf of
378395
A curl example using an ``id``::
379396

380397
curl -H "X-Dataverse-key:$API_TOKEN" -X PUT http://$SERVER/api/access/datafile/{id}/requestAccess
381-
398+
399+
.. note:: Some installations of Dataverse may require you to provide a Guestbook Response when requesting access to certain restricted files. The response can be passed in the body of this call. See "Get a Guestbook for a Dataverse Collection" in the :doc:`native-api`.
400+
382401
Grant File Access:
383402
~~~~~~~~~~~~~~~~~~
384403

doc/sphinx-guides/source/api/native-api.rst

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,6 +1168,100 @@ The fully expanded example above (without environment variables) looks like this
11681168
11691169
curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" "https://demo.dataverse.org/api/dataverses/root/guestbookResponses?guestbookId=1" -o myResponses.csv
11701170
1171+
.. _guestbook-api:
1172+
1173+
Guestbooks
1174+
~~~~~~~~~~
1175+
1176+
Create a Guestbook for a Dataverse Collection
1177+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1178+
1179+
For more about guestbooks, see :ref:`dataset-guestbooks` in the User Guide.
1180+
1181+
Create a Guestbook that can be selected for a Dataset.
1182+
You must have "EditDataverse" permission on the Dataverse collection.
1183+
1184+
.. code-block:: bash
1185+
1186+
export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
1187+
export SERVER_URL=https://demo.dataverse.org
1188+
export ID=root
1189+
export JSON='{"name": "my test guestbook","enabled": true,"emailRequired": true,"nameRequired": true,"institutionRequired": false,"positionRequired": false,"customQuestions": [{"question": "how is your day","required": true,"displayOrder": 0,"type": "text","hidden": false}]}'
1190+
1191+
curl -POST -H "X-Dataverse-key:$API_TOKEN" "$SERVER_URL/api/guestbooks/{ID}" -d "$JSON"
1192+
1193+
The fully expanded example above (without environment variables) looks like this:
1194+
1195+
.. code-block:: bash
1196+
1197+
curl -POST -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" "https://demo.dataverse.org/api/guestbooks/root" -d '{"name": "my test guestbook","enabled": true,"emailRequired": true,"nameRequired": true,"institutionRequired": false,"positionRequired": false}'
1198+
1199+
Get a list of Guestbooks for a Dataverse Collection
1200+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1201+
1202+
For more about guestbooks, see :ref:`dataset-guestbooks` in the User Guide.
1203+
1204+
Get a list of Guestbooks for a Dataverse Collection
1205+
You must have "EditDataverse" permission on the Dataverse collection.
1206+
1207+
.. code-block:: bash
1208+
1209+
export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
1210+
export SERVER_URL=https://demo.dataverse.org
1211+
export ID=root
1212+
1213+
curl -H "X-Dataverse-key:$API_TOKEN" "$SERVER_URL/api/guestbooks/{ID}/list"`
1214+
1215+
The fully expanded example above (without environment variables) looks like this:
1216+
1217+
.. code-block:: bash
1218+
1219+
curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" "https://demo.dataverse.org/api/guestbooks/root/list"
1220+
1221+
Get a Guestbook for a Dataverse Collection
1222+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1223+
1224+
For more about guestbooks, see :ref:`dataset-guestbooks` in the User Guide.
1225+
1226+
Get a Guestbook by its id
1227+
1228+
.. code-block:: bash
1229+
1230+
export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
1231+
export SERVER_URL=https://demo.dataverse.org
1232+
export ID=1234
1233+
1234+
curl -H "X-Dataverse-key:$API_TOKEN" "$SERVER_URL/api/guestbooks/{ID}"`
1235+
1236+
The fully expanded example above (without environment variables) looks like this:
1237+
1238+
.. code-block:: bash
1239+
1240+
curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" "https://demo.dataverse.org/api/guestbooks/1234"
1241+
1242+
Enable or Disable a Guestbook for a Dataverse Collection
1243+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1244+
1245+
For more about guestbooks, see :ref:`dataset-guestbooks` in the User Guide.
1246+
1247+
Use this endpoint to enable or disable the Guestbook. A Guestbook can not be deleted or modified since there may be responses linked to it.
1248+
You must have "EditDataverse" permission on the Dataverse collection.
1249+
1250+
.. code-block:: bash
1251+
1252+
export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
1253+
export SERVER_URL=https://demo.dataverse.org
1254+
export dataverseIdentifier=root
1255+
export ID=1234
1256+
1257+
curl -X PUT -d 'true' -H "X-Dataverse-key:$API_TOKEN" "$SERVER_URL/api/guestbooks/{dataverseIdentifier}/{ID}/enabled"
1258+
1259+
The fully expanded example above (without environment variables) looks like this:
1260+
1261+
.. code-block:: bash
1262+
1263+
curl -X PUT -d 'true' -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" "https://demo.dataverse.org/api/guestbooks/root/1234"
1264+
11711265
.. _collection-attributes-api:
11721266

11731267
Change Collection Attributes
@@ -1774,6 +1868,8 @@ In all commands below, dataset versions can be referred to as:
17741868
* ``x.y`` a specific version, where ``x`` is the major version number and ``y`` is the minor version number.
17751869
* ``x`` same as ``x.0``
17761870

1871+
.. _dataset-json-representation:
1872+
17771873
Get JSON Representation of a Dataset
17781874
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17791875

docker-compose-dev.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ services:
6060
-Ddataverse.pid.fake.label=FakeDOIProvider
6161
-Ddataverse.pid.fake.authority=10.5072
6262
-Ddataverse.pid.fake.shoulder=FK2/
63+
#-Ddataverse.files.guestbook-at-request=true
6364
#-Ddataverse.lang.directory=/dv/lang
6465
ports:
6566
- "8080:8080" # HTTP (Dataverse Application)
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{"guestbookResponse": {
2+
"answers": [
3+
{
4+
"id": @QID1,
5+
"value": "Good"
6+
},
7+
{
8+
"id": @QID2,
9+
"value": ["Multi","Line"]
10+
},
11+
{
12+
"id": @QID3,
13+
"value": "Yellow"
14+
}
15+
]
16+
}
17+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
{
2+
"name": "my test guestbook",
3+
"enabled": true,
4+
"emailRequired": true,
5+
"nameRequired": true,
6+
"institutionRequired": false,
7+
"positionRequired": false,
8+
"customQuestions": [
9+
{
10+
"question": "how's your day",
11+
"required": true,
12+
"displayOrder": 0,
13+
"type": "text",
14+
"hidden": false
15+
},
16+
{
17+
"question": "Describe yourself",
18+
"required": false,
19+
"displayOrder": 1,
20+
"type": "textarea",
21+
"hidden": false
22+
},
23+
{
24+
"question": "What color car do you drive",
25+
"required": true,
26+
"displayOrder": 2,
27+
"type": "options",
28+
"hidden": false,
29+
"optionValues": [
30+
{
31+
"value": "Red",
32+
"displayOrder": 0
33+
},
34+
{
35+
"value": "White",
36+
"displayOrder": 1
37+
},
38+
{
39+
"value": "Yellow",
40+
"displayOrder": 2
41+
},
42+
{
43+
"value": "Purple",
44+
"displayOrder": 3
45+
}
46+
]
47+
}
48+
]
49+
}

src/main/java/edu/harvard/iq/dataverse/CustomQuestion.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package edu.harvard.iq.dataverse;
2-
import java.io.Serializable;
3-
import java.util.List;
2+
43
import jakarta.persistence.*;
54
import jakarta.validation.constraints.NotBlank;
65

6+
import java.io.Serializable;
7+
import java.util.List;
8+
import java.util.stream.Collectors;
9+
710
/**
811
*
912
* @author skraffmiller
@@ -92,6 +95,12 @@ public void setQuestionString(String questionString) {
9295
public List<CustomQuestionValue> getCustomQuestionValues() {
9396
return customQuestionValues;
9497
}
98+
99+
public List<String> getCustomQuestionOptions() {
100+
return customQuestionValues.stream()
101+
.map(CustomQuestionValue::getValueString)
102+
.collect(Collectors.toList());
103+
}
95104

96105
public String getCustomQuestionValueString(){
97106
String retString = "";

src/main/java/edu/harvard/iq/dataverse/CustomQuestionResponse.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55
*/
66
package edu.harvard.iq.dataverse;
77

8-
import java.io.Serializable;
9-
import java.util.List;
108
import jakarta.faces.model.SelectItem;
119
import jakarta.persistence.*;
1210

11+
import java.io.Serializable;
12+
import java.util.List;
13+
1314
/**
1415
*
1516
* @author skraffmiller

0 commit comments

Comments
 (0)