Skip to content
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
5ee2360
DRAFT using mydata/retrieve API
stevenwinship Jul 23, 2025
2b8d4ee
DRAFT using mydata/retrieve API
stevenwinship Jul 23, 2025
f4d017c
DRAFT using mydata/retrieve API
stevenwinship Jul 23, 2025
2dee3f7
adding new api endpoint
stevenwinship Jul 24, 2025
6004421
update docs
stevenwinship Jul 24, 2025
d3d8358
new endpoint
stevenwinship Jul 28, 2025
ec0bdcf
switch to GetUserPermittedCollectionsCommand
stevenwinship Jul 29, 2025
e4da1b5
fix doc
stevenwinship Jul 29, 2025
d4d2db3
remove unused includes from test
stevenwinship Jul 29, 2025
639923a
remove unused method from test
stevenwinship Jul 29, 2025
9688bc0
adding superuser bypass
stevenwinship Jul 29, 2025
da46343
Merge branch 'develop' into 11525-retrieve-collections-a-user-can-cre…
stevenwinship Jul 29, 2025
ebbb223
adding id to json response
stevenwinship Jul 29, 2025
3ba39fe
Merge branch 'develop' into 11525-retrieve-collections-a-user-can-cre…
stevenwinship Aug 1, 2025
9a87d0f
Merge branch 'develop' into 11525-retrieve-collections-a-user-can-cre…
stevenwinship Aug 25, 2025
2b51bba
Update doc/sphinx-guides/source/api/native-api.rst
stevenwinship Aug 25, 2025
65fb72c
review comments and refactor
stevenwinship Aug 25, 2025
b752b22
review comments and refactor
stevenwinship Aug 25, 2025
785c4a3
adding unit test
stevenwinship Aug 25, 2025
09544db
refactor
stevenwinship Aug 26, 2025
3813f9b
review comments
stevenwinship Aug 26, 2025
a82b90b
review comments
stevenwinship Aug 26, 2025
baf0b00
if api key is present do not use session
stevenwinship Aug 27, 2025
9a977ab
review comments
stevenwinship Aug 29, 2025
9ea5df8
adding debug for testing
stevenwinship Aug 29, 2025
3abf810
adding debug for testing
stevenwinship Aug 29, 2025
174c136
remove debugging
stevenwinship Sep 2, 2025
abc7dc3
Merge branch 'develop' into 11525-retrieve-collections-a-user-can-cre…
stevenwinship Sep 5, 2025
b368b46
change collections to dataverses
stevenwinship Sep 5, 2025
2e449f3
addressing review comment
stevenwinship Sep 5, 2025
c792497
Update src/main/java/edu/harvard/iq/dataverse/engine/command/impl/Get…
stevenwinship Sep 8, 2025
2678e69
Refactor: removed unused logger and applied final keyword in class le…
GPortas Sep 8, 2025
cf7482e
Added: unit tests for GetUserPermittedCollectionsCommand
GPortas Sep 8, 2025
801d8cc
Fixed: incorrect response code in testUserPermittedDataverses IT
GPortas Sep 8, 2025
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
### New API to retrieve a list of collections that an authenticated user can create a dataset in

The API GET /api/mydata/retrieve/collectionList will return all the dataverse objects that the user can add to

See also [the guides](https://guides.dataverse.org/en/latest/api/native-api.html#mydata) and #11525.
16 changes: 16 additions & 0 deletions doc/sphinx-guides/source/api/native-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7869,3 +7869,19 @@ Parameters:

``per_page`` Number of results returned per page.

MyData Collection List
----------------------

The MyData Collection List API is used to get a list of the collections an authenticated user can create a Dataset in.
Param userIdentifier={userName} is used by a superuser to get the collections for a specific user.

A curl example listing collections:

.. code-block:: bash

export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
export SERVER_URL=https://demo.dataverse.org

curl -H "X-Dataverse-key:$API_TOKEN" "$SERVER_URL/api/mydata/retrieve/collectionList"
curl -H "X-Dataverse-key:$API_TOKEN" "$SERVER_URL/api/mydata/retrieve/collectionList?userIdentifier=anotherUser"

19 changes: 14 additions & 5 deletions src/main/java/edu/harvard/iq/dataverse/PermissionServiceBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ public class PermissionServiceBean {
@Inject
DatasetVersionFilesServiceBean datasetVersionFilesServiceBean;

private static final String LIST_ALL_DATAVERSES_SUPERUSER_HAS_PERMISSION = """
SELECT id, name, alias FROM DATAVERSE
""";

private static final String LIST_ALL_DATAVERSES_USER_HAS_PERMISSION = """
WITH grouplist AS (
SELECT explicitgroup_authenticateduser.explicitgroup_id as id FROM explicitgroup_authenticateduser
Expand Down Expand Up @@ -928,6 +932,7 @@ public List<Dataverse> findPermittedCollections(DataverseRequest request, Authen
String ipRangeSQL = "FALSE";
if (request != null
&& request.getAuthenticatedUser() != null
&& !request.getAuthenticatedUser().isSuperuser()
&& request.getSourceAddress() != null
&& request.getAuthenticatedUser().getUserIdentifier().equalsIgnoreCase(user.getUserIdentifier())) {
IpAddress ip = request.getSourceAddress();
Expand All @@ -950,11 +955,15 @@ public List<Dataverse> findPermittedCollections(DataverseRequest request, Authen
}
}
}

String sqlCode = LIST_ALL_DATAVERSES_USER_HAS_PERMISSION
.replace("@USERID", String.valueOf(user.getId()))
.replace("@PERMISSIONBIT", String.valueOf(permissionBit))
.replace("@IPRANGESQL", ipRangeSQL);
String sqlCode;
if (user.isSuperuser()) {
sqlCode = LIST_ALL_DATAVERSES_SUPERUSER_HAS_PERMISSION;
} else {
sqlCode = LIST_ALL_DATAVERSES_USER_HAS_PERMISSION
.replace("@USERID", String.valueOf(user.getId()))
.replace("@PERMISSIONBIT", String.valueOf(permissionBit))
.replace("@IPRANGESQL", ipRangeSQL);
}
return em.createNativeQuery(sqlCode, Dataverse.class).getResultList();
}
return null;
Expand Down
6 changes: 4 additions & 2 deletions src/main/java/edu/harvard/iq/dataverse/api/Users.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
package edu.harvard.iq.dataverse.api;

import edu.harvard.iq.dataverse.Dataverse;
import edu.harvard.iq.dataverse.api.auth.AuthRequired;
import edu.harvard.iq.dataverse.authorization.users.ApiToken;
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
Expand All @@ -26,6 +27,7 @@
import java.util.logging.Logger;

import edu.harvard.iq.dataverse.util.json.JsonParseException;
import edu.harvard.iq.dataverse.util.json.JsonPrinter;
import edu.harvard.iq.dataverse.util.json.JsonUtil;
import jakarta.ejb.Stateless;
import jakarta.json.JsonArray;
Expand Down Expand Up @@ -286,8 +288,8 @@ public Response getUserPermittedCollections(@Context ContainerRequestContext crc
}
try {
AuthenticatedUser userToQuery = authSvc.getAuthenticatedUser(identifier);
JsonObjectBuilder jsonObj = execCommand(new GetUserPermittedCollectionsCommand(createDataverseRequest(getRequestUser(crc)), userToQuery, permission));
return ok(jsonObj);
List<Dataverse> collections = execCommand(new GetUserPermittedCollectionsCommand(createDataverseRequest(getRequestUser(crc)), userToQuery, permission));
return ok(JsonPrinter.jsonArray(collections));
} catch (WrappedResponse ex) {
return ex.getResponse();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,24 @@
import edu.harvard.iq.dataverse.Dataverse;
import edu.harvard.iq.dataverse.DvObject;
import edu.harvard.iq.dataverse.authorization.Permission;
import edu.harvard.iq.dataverse.authorization.groups.impl.ipaddress.ip.IpAddress;
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
import edu.harvard.iq.dataverse.engine.command.AbstractCommand;
import edu.harvard.iq.dataverse.engine.command.CommandContext;
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
import edu.harvard.iq.dataverse.engine.command.RequiredPermissions;
import edu.harvard.iq.dataverse.engine.command.exception.CommandException;
import jakarta.json.Json;
import jakarta.json.JsonArrayBuilder;
import jakarta.json.JsonObjectBuilder;

import java.util.List;
import java.util.logging.Logger;

import static edu.harvard.iq.dataverse.util.json.JsonPrinter.json;

@RequiredPermissions({})
public class GetUserPermittedCollectionsCommand extends AbstractCommand<JsonObjectBuilder> {
@RequiredPermissions({}) // No specific permission is needed to execute this command. To filter the collection a list of permissions are passed in
public class GetUserPermittedCollectionsCommand extends AbstractCommand<List<Dataverse>> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still not addressed / replied: #11681 (comment)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed

Comment thread
stevenwinship marked this conversation as resolved.
Outdated
private static final Logger logger = Logger.getLogger(GetUserPermittedCollectionsCommand.class.getCanonicalName());

private DataverseRequest request;
private AuthenticatedUser user;
private String permission;

public GetUserPermittedCollectionsCommand(DataverseRequest request, AuthenticatedUser user, String permission) {
super(request, (DvObject) null);
this.request = request;
Expand All @@ -34,7 +29,7 @@ public GetUserPermittedCollectionsCommand(DataverseRequest request, Authenticate
}

@Override
public JsonObjectBuilder execute(CommandContext ctxt) throws CommandException {
public List<Dataverse> execute(CommandContext ctxt) throws CommandException {
if (user == null) {
throw new CommandException("User not found.", this);
}
Expand All @@ -45,17 +40,6 @@ public JsonObjectBuilder execute(CommandContext ctxt) throws CommandException {
} catch (IllegalArgumentException e) {
throw new CommandException("Permission not valid.", this);
}
List<Dataverse> collections = ctxt.permissions().findPermittedCollections(request, user, permissionBit);
if (collections != null) {
JsonObjectBuilder job = Json.createObjectBuilder();
JsonArrayBuilder jab = Json.createArrayBuilder();
for (Dataverse dv : collections) {
jab.add(json(dv));
}
job.add("count", collections.size());
job.add("items", jab);
return job;
}
return null;
return ctxt.permissions().findPermittedCollections(request, user, permissionBit);
}
}
Loading