Skip to content

Commit

Permalink
expose contacts via API, warn about email privacy #5724
Browse files Browse the repository at this point in the history
  • Loading branch information
pdurbin committed Apr 10, 2019
1 parent 50c0de8 commit 50c5c2d
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 11 deletions.
6 changes: 4 additions & 2 deletions doc/sphinx-guides/source/api/native-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,14 @@ Download the :download:`JSON example <../_static/api/dataverse-complete.json>` f

.. literalinclude:: ../_static/api/dataverse-complete.json

.. _view-dataverse:

View a Dataverse
~~~~~~~~~~~~~~~~

|CORS| View data about the dataverse identified by ``$id``. ``$id`` can be the id number of the dataverse, its alias, or the special value ``:root``. ::
|CORS| View data about the dataverse identified by ``$id``. ``$id`` can be the id number of the dataverse, its identifier (a.k.a. alias), or the special value ``:root`` for the root dataverse.

GET http://$SERVER/api/dataverses/$id
``curl $SERVER_URL/api/dataverses/$id``

Delete a Dataverse
~~~~~~~~~~~~~~~~~~
Expand Down
9 changes: 8 additions & 1 deletion doc/sphinx-guides/source/installation/config.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,15 @@ Forcing HTTPS

To avoid having your users send credentials in the clear, it's strongly recommended to force all web traffic to go through HTTPS (port 443) rather than HTTP (port 80). The ease with which one can install a valid SSL cert into Apache compared with the same operation in Glassfish might be a compelling enough reason to front Glassfish with Apache. In addition, Apache can be configured to rewrite HTTP to HTTPS with rules such as those found at https://wiki.apache.org/httpd/RewriteHTTPToHTTPS or in the section on :doc:`shibboleth`.

.. _PrivacyConsiderations:

Privacy Considerations
++++++++++++++++++++++

Out of the box, Dataverse will list email addresses of the "contacts" for datasets when users visit a dataset page and click the "Export Metadata" button. If you prefer to exclude email addresses of dataset contacts from metadata export, set :ref:`:ExcludeEmailFromExport <:ExcludeEmailFromExport>` to true.
Email Privacy
^^^^^^^^^^^^^

Out of the box, Dataverse will list email addresses of the contacts for datasets when users visit a dataset page and click the "Export Metadata" button. Additionally, out of the box, Dataverse will list email addresses of dataverse contacts via API (see :ref:`View a Dataverse <view-dataverse>` in the :doc:`/api/native-api` section of the API Guide). If you would like to exclude these email addresses from export, set :ref:`:ExcludeEmailFromExport <:ExcludeEmailFromExport>` to true.

Additional Recommendations
++++++++++++++++++++++++++
Expand Down Expand Up @@ -1150,6 +1155,8 @@ API users can retrieve this URL from the SWORD Service Document or the "info" se
:ExcludeEmailFromExport
+++++++++++++++++++++++

See also :ref:`Privacy Considerations <PrivacyConsiderations>` above.

Set ``:ExcludeEmailFromExport`` to prevent email addresses for contacts from being exposed in XML or JSON representations of dataset and dataverse metadata. For a list exported formats such as DDI, see the :doc:`/admin/metadataexport` section of the Admin Guide.

``curl -X PUT -d true http://localhost:8080/api/admin/settings/:ExcludeEmailFromExport``
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,11 +263,14 @@ public static JsonObjectBuilder json(Dataverse dv, Boolean hideEmail) {
}

public static JsonArrayBuilder json(List<DataverseContact> dataverseContacts) {
return dataverseContacts.stream()
.map(dc -> jsonObjectBuilder()
.add("displayOrder", dc.getDisplayOrder())
.add("contactEmail", dc.getContactEmail())
).collect(toJsonArray());
JsonArrayBuilder jsonArrayOfContacts = Json.createArrayBuilder();
for (DataverseContact dataverseContact : dataverseContacts) {
NullSafeJsonBuilder contactJsonObject = NullSafeJsonBuilder.jsonObjectBuilder();
contactJsonObject.add("displayOrder", dataverseContact.getDisplayOrder());
contactJsonObject.add("contactEmail", dataverseContact.getContactEmail());
jsonArrayOfContacts.add(contactJsonObject);
}
return jsonArrayOfContacts;
}

public static JsonObjectBuilder json( DataverseTheme theme ) {
Expand Down
44 changes: 41 additions & 3 deletions src/test/java/edu/harvard/iq/dataverse/api/DataversesIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.logging.Logger;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import static javax.ws.rs.core.Response.Status.CREATED;
import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
import javax.ws.rs.core.Response.Status;
Expand Down Expand Up @@ -163,16 +164,44 @@ public void testReturnEmail() throws FileNotFoundException {
createUser.prettyPrint();
String username = UtilIT.getUsernameFromResponse(createUser);
String apiToken = UtilIT.getApiTokenFromResponse(createUser);

Response createDataverseResponse = UtilIT.createRandomDataverse(apiToken);
String dataverseAlias = UtilIT.getRandomDvAlias();
String emailAddressOfFirstDataverseContact = dataverseAlias + "@mailinator.com";
JsonObjectBuilder jsonToCreateDataverse = Json.createObjectBuilder()
.add("name", dataverseAlias)
.add("alias", dataverseAlias)
.add("dataverseContacts", Json.createArrayBuilder()
.add(Json.createObjectBuilder()
.add("contactEmail", emailAddressOfFirstDataverseContact)
)
);
;

Response createDataverseResponse = UtilIT.createDataverse(jsonToCreateDataverse.build(), apiToken);
createDataverseResponse.prettyPrint();
createDataverseResponse.then().assertThat().statusCode(CREATED.getStatusCode());
String dataverseAlias = UtilIT.getAliasFromResponse(createDataverseResponse);

createDataverseResponse.then().assertThat()
.statusCode(CREATED.getStatusCode())
.body("data.alias", equalTo(dataverseAlias))
.body("data.name", equalTo(dataverseAlias))
.body("data.dataverseContacts[0].displayOrder", equalTo(0))
.body("data.dataverseContacts[0].contactEmail", equalTo(emailAddressOfFirstDataverseContact))
.body("data.permissionRoot", equalTo(true))
.body("data.dataverseType", equalTo("UNCATEGORIZED"));

Response exportDataverseAsJson = UtilIT.exportDataverse(dataverseAlias, apiToken);
exportDataverseAsJson.prettyPrint();
exportDataverseAsJson.then().assertThat()
.statusCode(OK.getStatusCode());

exportDataverseAsJson.then().assertThat()
.statusCode(OK.getStatusCode())
.body("data.alias", equalTo(dataverseAlias))
.body("data.name", equalTo(dataverseAlias))
.body("data.dataverseContacts", equalTo(null))
.body("data.permissionRoot", equalTo(true))
.body("data.dataverseType", equalTo("UNCATEGORIZED"));

RestAssured.unregisterParser("text/plain");

List dataverseEmailNotAllowed = with(exportDataverseAsJson.body().asString())
Expand All @@ -187,6 +216,15 @@ public void testReturnEmail() throws FileNotFoundException {
exportDataverseAsJson2.prettyPrint();
exportDataverseAsJson2.then().assertThat()
.statusCode(OK.getStatusCode());
exportDataverseAsJson2.then().assertThat()
.statusCode(OK.getStatusCode())
.body("data.alias", equalTo(dataverseAlias))
.body("data.name", equalTo(dataverseAlias))
.body("data.dataverseContacts[0].displayOrder", equalTo(0))
.body("data.dataverseContacts[0].contactEmail", equalTo(emailAddressOfFirstDataverseContact))
.body("data.permissionRoot", equalTo(true))
.body("data.dataverseType", equalTo("UNCATEGORIZED"));

RestAssured.unregisterParser("text/plain");
List dataverseEmailAllowed = with(exportDataverseAsJson2.body().asString())
.getJsonObject("data.dataverseContacts");
Expand Down

0 comments on commit 50c5c2d

Please sign in to comment.