Skip to content

Commit 0cebb9c

Browse files
committed
Merge branch 'develop' into 11912-edit-template-api
2 parents af9d040 + 50d04e6 commit 0cebb9c

11 files changed

Lines changed: 243 additions & 30 deletions

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
### Feature: Extend List File Access Requests API ###
2+
3+
Added ability to get access request history via the `/datafile/{id}/listRequests` API. The API returns a list of users/groups where the request for access is waiting for an accept or reject. Already accepted or rejected requests are not returned.
4+
5+
By adding the flag 'includeHistory=true' all of the requests will be returned. Pagination is also implemented in this feature. Adding a start page parameter and max list size (`&start=0` and `&per_page=20`) can limit the amount of data being returned.
6+
7+
See https://guides.dataverse.org/en/latest/api/dataaccess.html#list-file-access-requests
8+

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

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,22 @@ This method returns a list of Authenticated Users who have requested access to t
440440

441441
A curl example using an ``id``::
442442

443-
curl -H "X-Dataverse-key:$API_TOKEN" -X GET http://$SERVER/api/access/datafile/{id}/listRequests
443+
curl -H "X-Dataverse-key:$API_TOKEN" -X GET $SERVER/api/access/datafile/{id}/listRequests
444+
445+
Query parameters have been added to retrieve the historical list of "created", "granted", and "rejected" requests:
446+
447+
* `includeHistory` When `true` this will force the return of all requests and not just the "created" ones.
448+
* `start` For pagination, use this to request a specific page.
449+
* `per_page` For pagination, use this to limit the number of items in each paged list.
450+
451+
.. note:: Pagination is only available when `includeHistory` is `true`
452+
453+
If requesting a page beyond the last page this API will return a 404 "There are no access requests for this file:..."
454+
If requesting a page before page 1 or requesting the number of items to be 0 or less this API will ignore these parameters and return the entire list.
455+
456+
A curl example using an ``id``::
457+
458+
curl -H "X-Dataverse-key:$API_TOKEN" -X GET "$SERVER/api/access/datafile/{id}/listRequests?includeHistory=true&start=1&per_page=20"
444459

445460
User Has Requested Access to a File:
446461
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -451,7 +466,7 @@ This method returns true or false depending on whether or not the calling user h
451466

452467
A curl example using an ``id``::
453468

454-
curl -H "X-Dataverse-key:$API_TOKEN" -X GET "http://$SERVER/api/access/datafile/{id}/userFileAccessRequested"
469+
curl -H "X-Dataverse-key:$API_TOKEN" -X GET "$SERVER/api/access/datafile/{id}/userFileAccessRequested"
455470

456471

457472
Get User Permissions on a File:

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

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -247,11 +247,31 @@ public String toUri() {
247247
inverseJoinColumns = @JoinColumn(name = "authenticated_user_id"))
248248
private List<AuthenticatedUser> fileAccessRequesters;
249249

250-
251-
public List<FileAccessRequest> getFileAccessRequests(){
252-
return fileAccessRequests;
250+
public List<FileAccessRequest> getFileAccessRequests() {
251+
return getFileAccessRequests(0, 0);
253252
}
254-
253+
254+
/**
255+
* Get Requests with pagination option
256+
* @param numResultsPerPageRequested
257+
* @param paginationStart starts at 1
258+
* @return
259+
*/
260+
public List<FileAccessRequest> getFileAccessRequests(int numResultsPerPageRequested, int paginationStart) {
261+
if (numResultsPerPageRequested < 1 || paginationStart < 1) {
262+
return fileAccessRequests;
263+
} else {
264+
int startIndex = (paginationStart - 1) * numResultsPerPageRequested;
265+
int endIndex = startIndex + numResultsPerPageRequested;
266+
if (startIndex >= fileAccessRequests.size()) {
267+
return List.of();
268+
} else if (endIndex > fileAccessRequests.size()) {
269+
endIndex = fileAccessRequests.size();
270+
}
271+
return fileAccessRequests.subList(startIndex, endIndex);
272+
}
273+
}
274+
255275
public List<FileAccessRequest> getFileAccessRequests(FileAccessRequest.RequestState state){
256276
return fileAccessRequests.stream().filter(far -> far.getState() == state).collect(Collectors.toList());
257277
}
@@ -849,6 +869,15 @@ public void addFileAccessRequest(FileAccessRequest request) {
849869
this.fileAccessRequests.add(request);
850870
}
851871

872+
public List<FileAccessRequest> getAccessRequestsForAssignee(RoleAssignee roleAssignee) {
873+
if (this.fileAccessRequests == null) {
874+
return null;
875+
}
876+
877+
return this.fileAccessRequests.stream()
878+
.filter(fileAccessRequest -> fileAccessRequest.getRequester().equals(roleAssignee)).toList();
879+
}
880+
852881
public FileAccessRequest getAccessRequestForAssignee(RoleAssignee roleAssignee) {
853882
if (this.fileAccessRequests == null) {
854883
return null;

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.Date;
55

66
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
7+
import edu.harvard.iq.dataverse.util.BundleUtil;
78
import jakarta.persistence.Column;
89
import jakarta.persistence.Entity;
910
import jakarta.persistence.EnumType;
@@ -143,6 +144,20 @@ public String getStateLabel() {
143144
}
144145
return null;
145146
}
147+
148+
// For use by UI to allow for internationalization
149+
public String getStateLabelNationalized() {
150+
if(isStateCreated()) {
151+
return BundleUtil.getStringFromBundle("permission.fileAccess.created");
152+
}
153+
if(isStateGranted()) {
154+
return BundleUtil.getStringFromBundle("permission.fileAccess.granted");
155+
}
156+
if(isStateRejected()) {
157+
return BundleUtil.getStringFromBundle("permission.fileAccess.rejected");
158+
}
159+
return null;
160+
}
146161

147162
public void setStateCreated() {
148163
this.requestState = RequestState.CREATED;
@@ -197,4 +212,4 @@ public boolean equals(Object object) {
197212
}
198213

199214

200-
}
215+
}

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

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,15 @@ public boolean isShowDeleted() {
116116
public void setShowDeleted(boolean showDeleted) {
117117
this.showDeleted = showDeleted;
118118
}
119+
private boolean showHistory = false;
120+
121+
public boolean isShowHistory() {
122+
return showHistory;
123+
}
124+
125+
public void setShowHistory(boolean showHistory) {
126+
this.showHistory = showHistory;
127+
}
119128

120129
public Dataset getDataset() {
121130
return dataset;
@@ -143,6 +152,13 @@ public void showDeletedCheckboxChange() {
143152
}
144153

145154
}
155+
private boolean backingShowHistory = false;
156+
public void showHistoryCheckboxChange() {
157+
if (backingShowHistory != showHistory) {
158+
initMaps();
159+
backingShowHistory = showHistory;
160+
}
161+
}
146162

147163
public String init() {
148164
if (dataset.getId() != null) {
@@ -199,7 +215,7 @@ private void initMaps() {
199215
fileMap.put(file, raList);
200216

201217
// populate the file access requests map
202-
for (FileAccessRequest fileAccessRequest : file.getFileAccessRequests(FileAccessRequest.RequestState.CREATED)) {
218+
for (FileAccessRequest fileAccessRequest : !showHistory ? file.getFileAccessRequests(FileAccessRequest.RequestState.CREATED) : file.getFileAccessRequests()) {
203219
List<FileAccessRequest> fileAccessRequestList = fileAccessRequestMap.get(fileAccessRequest.getRequester());
204220
if (fileAccessRequestList == null) {
205221
fileAccessRequestList = new ArrayList<>();
@@ -250,6 +266,21 @@ public String formatAccessRequestTimestamp(List<FileAccessRequest> fileAccessReq
250266
return Util.getDateTimeFormat().format(date);
251267
}
252268

269+
public String getAccessRequestStates(List<FileAccessRequest> fileAccessRequests) {
270+
String result = "";
271+
if (fileAccessRequests != null) {
272+
Map<String, Long> items = fileAccessRequests.stream()
273+
.sorted(Comparator.comparing(FileAccessRequest::getState))
274+
.collect(Collectors.groupingBy(
275+
FileAccessRequest::getStateLabelNationalized,
276+
Collectors.counting()));
277+
278+
result = items.entrySet().stream().map(entry -> entry.getKey() + ":" + entry.getValue())
279+
.collect(Collectors.joining(", ", "[ ", " ]"));
280+
}
281+
return result;
282+
}
283+
253284
private void addFileToRoleAssignee(RoleAssignment assignment, boolean fileDeleted) {
254285
RoleAssignee ra = roleAssigneeService.getRoleAssignee(assignment.getAssigneeIdentifier());
255286
List<RoleAssignmentRow> assignments = roleAssigneeMap.get(ra);

src/main/java/edu/harvard/iq/dataverse/api/Access.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import edu.harvard.iq.dataverse.export.DDIExportServiceBean;
2929
import edu.harvard.iq.dataverse.makedatacount.MakeDataCountLoggingServiceBean;
3030
import edu.harvard.iq.dataverse.makedatacount.MakeDataCountLoggingServiceBean.MakeDataCountEntry;
31+
import edu.harvard.iq.dataverse.mydata.Pager;
3132
import edu.harvard.iq.dataverse.settings.JvmSettings;
3233
import edu.harvard.iq.dataverse.settings.SettingsServiceBean;
3334
import edu.harvard.iq.dataverse.util.*;
@@ -1695,8 +1696,11 @@ public Response requestFileAccess(@Context ContainerRequestContext crc
16951696
@GET
16961697
@AuthRequired
16971698
@Path("/datafile/{id}/listRequests")
1698-
public Response listFileAccessRequests(@Context ContainerRequestContext crc, @PathParam("id") String fileToRequestAccessId, @Context HttpHeaders headers) {
1699-
1699+
public Response listFileAccessRequests(@Context ContainerRequestContext crc, @PathParam("id") String fileToRequestAccessId,
1700+
@QueryParam("includeHistory") boolean includeHistory,
1701+
@QueryParam("per_page") final int numResultsPerPageRequested,
1702+
@QueryParam("start") final int paginationStart,
1703+
@Context HttpHeaders headers) {
17001704
DataverseRequest dataverseRequest;
17011705

17021706
DataFile dataFile;
@@ -1717,7 +1721,8 @@ public Response listFileAccessRequests(@Context ContainerRequestContext crc, @Pa
17171721
return error(FORBIDDEN, BundleUtil.getStringFromBundle("access.api.rejectAccess.failure.noPermissions"));
17181722
}
17191723

1720-
List<FileAccessRequest> requests = dataFile.getFileAccessRequests(FileAccessRequest.RequestState.CREATED);
1724+
List<FileAccessRequest> requests = !includeHistory ? dataFile.getFileAccessRequests(FileAccessRequest.RequestState.CREATED) :
1725+
dataFile.getFileAccessRequests(numResultsPerPageRequested, paginationStart);
17211726

17221727
if (requests == null || requests.isEmpty()) {
17231728
List<String> args = Arrays.asList(dataFile.getDisplayName());
@@ -1727,7 +1732,21 @@ public Response listFileAccessRequests(@Context ContainerRequestContext crc, @Pa
17271732
JsonArrayBuilder userArray = Json.createArrayBuilder();
17281733

17291734
for (FileAccessRequest fileAccessRequest : requests) {
1730-
userArray.add(json(fileAccessRequest.getRequester()));
1735+
userArray.add(json(fileAccessRequest));
1736+
}
1737+
1738+
// Check for pagination request
1739+
if (includeHistory && numResultsPerPageRequested > 0 && paginationStart > 0) {
1740+
JsonObjectBuilder builder = Json.createObjectBuilder()
1741+
.add("status", ApiConstants.STATUS_OK)
1742+
.add("data", userArray);
1743+
1744+
Pager pager = new Pager(dataFile.getFileAccessRequests().size(), numResultsPerPageRequested, paginationStart);
1745+
builder.add("pagination", pager.asJsonObjectBuilder());
1746+
1747+
return Response.ok( builder.build() )
1748+
.type(MediaType.APPLICATION_JSON)
1749+
.build();
17311750
}
17321751

17331752
return ok(userArray);

src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ public static JsonObjectBuilder json(AuthenticatedUser authenticatedUser) {
132132
.add("authenticationProviderId", authenticatedUser.getAuthenticatedUserLookup().getAuthenticationProviderId());
133133
return builder;
134134
}
135+
public static JsonObjectBuilder json(FileAccessRequest fileAccessRequest) {
136+
JsonObjectBuilder builder = json(fileAccessRequest.getRequester())
137+
.add("requestState", fileAccessRequest.getStateLabel());
138+
return builder;
139+
}
135140

136141
public static JsonArrayBuilder jsonRoleAssignments(List<RoleAssignment> roleAssignments) {
137142
JsonArrayBuilder bld = Json.createArrayBuilder();

src/main/java/propertyFiles/Bundle.properties

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,6 +1267,7 @@ dataverse.permissionsFiles.files.invalidMsg=There are no restricted files in thi
12671267
dataverse.permissionsFiles.files.requested=Requested Files
12681268
dataverse.permissionsFiles.files.selected=Selecting {0} of {1} {2}
12691269
dataverse.permissionsFiles.files.includeDeleted=Include Deleted Files
1270+
dataverse.permissionsFiles.files.showHistory=Show Historical Requests
12701271
dataverse.permissionsFiles.files.draftUnpublished=Draft/Unpublished
12711272
dataverse.permissionsFiles.viewRemoveDialog.header=File Access
12721273
dataverse.permissionsFiles.viewRemoveDialog.removeBtn=Remove Access
@@ -2773,6 +2774,9 @@ permission.roleNotAbleToBeRemoved=The role assignment was not able to be removed
27732774
permission.fileAccessGranted=File Access request by {0} was granted.
27742775
permission.fileAccessRejected=File Access request by {0} was rejected.
27752776
permission.roleNotAbleToBeAssigned=The role was not able to be assigned.
2777+
permission.fileAccess.created=Requested
2778+
permission.fileAccess.granted=Granted
2779+
permission.fileAccess.rejected=Rejected
27762780

27772781
#ManageGroupsPage.java
27782782
dataverse.manageGroups.create.success=Successfully created group {0}. Refresh to update your page.

0 commit comments

Comments
 (0)