Allow Preview User to download files without requiring a Guestbook Re… - #12584
Allow Preview User to download files without requiring a Guestbook Re…#12584stevenwinship wants to merge 8 commits into
Conversation
|
This PR replaces #12548 |
| Dataset d = df.getOwner(); | ||
| boolean required = df.getOwner().hasEnabledGuestbook() && !d.getEffectiveGuestbookEntryAtRequest(); | ||
| Dataset ds = df.getOwner(); | ||
| boolean required = ds.hasEnabledGuestbook() && !ds.getEffectiveGuestbookEntryAtRequest() && !(user instanceof PrivateUrlUser); |
There was a problem hiding this comment.
I think this skips checking if the PrivateUrlUser has access to this dataset?
There was a problem hiding this comment.
That happens in checkAuthorization which is called before checkGuestbookRequiredResponse
There was a problem hiding this comment.
OK - fair. I'd suggest moving this down so required is just about the guestbooks and then, in your if (required) block, handle the PreviewUrlUser and Authenticated user separately with a note - PreviewUrlUsers don't need another check because they can only be downloading because they have the ViewUnpublished perm whereas authenticatedUsers who can download may have that perm or FileDownload perm, so need to distinguish those two cases here.
| if (required) { | ||
| User requestor = getRequestor(user); | ||
| if (requestor instanceof AuthenticatedUser && permissionService.userOn(requestor, df.getOwner()).has(Permission.EditDataset)) { | ||
| if (user instanceof AuthenticatedUser && permissionService.userOn(user, ds).has(Permission.EditDataset)) { |
There was a problem hiding this comment.
Versus if you change here to drop the instanceof AuthenticatedUser part, this permissionService check should verify the PrivateUrlUser has an assignment on this dataset. (And this would be the perm I suggested might be ViewUnpublishedDataset to match the overall access check.)
There was a problem hiding this comment.
changed to ViewUnpublishedDataset
This comment has been minimized.
This comment has been minimized.
1 similar comment
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
1 similar comment
This comment has been minimized.
This comment has been minimized.
qqmyers
left a comment
There was a problem hiding this comment.
Getting close - this simplifies and fixes the checkGuestbook required logic which should fix both the previewUrlUser and LFAIR issues (so this should close the LFAIR issue too).
I noted two issues to fix in other comments and added LFAIR to the release note.
| private boolean isAccessApi(ContainerRequestContext containerRequestContext) { | ||
| return "GET".equalsIgnoreCase(containerRequestContext.getMethod()) | ||
| && containerRequestContext.getUriInfo() != null | ||
| && containerRequestContext.getUriInfo().getPath().toLowerCase().startsWith("access/"); |
There was a problem hiding this comment.
The ApiKey auth checks for the path starting with / - is that needed here too? (using final static constant as well)
There was a problem hiding this comment.
How does that even work? The path doesn't have a leading '/'
containerRequestContext.getUriInfo().getPath() access/datafile/4|#]
There was a problem hiding this comment.
Good catch! Not sure it does - could be review/QA 0f #9303 didn't catch the problem. If you're not seeing a leading /, we are probably leaving the other APIs open to users of anonymized preview url users when we shouldn't - up to you whether you want to try fixing that here (just removing the / I think) and adding that to QA or an automated test scenario, or just reporting as a separate bug.
There was a problem hiding this comment.
fixed SessionCookie but not ApiKeyAuth
There was a problem hiding this comment.
I'm looking into ApiKeyAuth separately
| required = false; | ||
| // PrivateUrlUsers are exempt from this requirement | ||
| if (user instanceof PrivateUrlUser) { | ||
| return false; |
There was a problem hiding this comment.
I think you still need a check for Authenticated users though, since they may have gotten here with either ViewUnpublished (where they wouldn't make a gbr) or FIle download perms (where they would be required). (As you said, PrivateUrlUsers can skip that check because the checkAuth guarantees they have the ViewUnpublished perm).
There was a problem hiding this comment.
added checkAuthorization
There was a problem hiding this comment.
Not seeing a change? I'd expect something like if ((user instanceof PrivateUrlUser) || (user instanceof AuthenticatedUser && permissionService.userOn(user, ds).has(Permission.ViewUnpublishedDataset)))
There was a problem hiding this comment.
I see checkAuthorization - that assures that an AuthenticatedUser has either ViewUnpublished (which means no gbr required) or FileDownload (which would). So calling it here doesn't help distinguish the two cases and you need to explicitly check for the perm that would result in returning false.
This comment has been minimized.
This comment has been minimized.
aaf3218 to
477ed98
Compare
This comment has been minimized.
This comment has been minimized.
1 similar comment
This comment has been minimized.
This comment has been minimized.
477ed98 to
cf7d78c
Compare
This comment has been minimized.
This comment has been minimized.
| @Inject | ||
| DataverseSession session; | ||
|
|
||
| public static final String ACCESS_DATAFILE_PATH_PREFIX = "access/datafile/"; |
There was a problem hiding this comment.
I think you need to allow broader access, e.g. to the access/dataset path as well (that could apply to the api key issue as well)? Since the access api overall is nominally about files, I'm not sure you need to check beyond "access/".
|
|
📦 Pushed preview images as 🚢 See on GHCR. Use by referencing with full name as printed above, mind the registry name. |
|
|
||
| private boolean isAccessApi(ContainerRequestContext containerRequestContext) { | ||
| String requestPath = containerRequestContext.getUriInfo() != null ? containerRequestContext.getUriInfo().getPath() : ""; | ||
| return ("GET".equalsIgnoreCase(containerRequestContext.getMethod()) && |
There was a problem hiding this comment.
At least the main Access Dataset /DownloadZip menu item calls the POST API, so PrivateURLUsers also need access to that. (Since the browser blocks other sites from sending our cookie for POST/PUT/etc. this shouldn't raise cross-site issues.)


The guestbook popup does not appear to collect a response before the download attempt is made. Disabling the guestbook on the dataset resolves the issue and files download normally through the Preview URL. This fix reinstates the behavior of the JSF UI from prior versions of Dataverse.
Which issue(s) this PR closes:#12535
Closes #12535
Special notes for your reviewer:
Suggestions on how to test this: Create a dataset with a guestbook. Generate a Preview URL. Using the preview url try to download files and dataset zip file. This should work without requiring the guestbook response.
Does this PR introduce a user interface change? If mockups are available, please link/include them here:
Is there a release notes update needed for this change?: Included
Additional documentation: