Skip to content

Allow Preview User to download files without requiring a Guestbook Re… - #12584

Open
stevenwinship wants to merge 8 commits into
developfrom
12535-download-without-guestbook-response-for-preview-user2
Open

Allow Preview User to download files without requiring a Guestbook Re…#12584
stevenwinship wants to merge 8 commits into
developfrom
12535-download-without-guestbook-response-for-preview-user2

Conversation

@stevenwinship

Copy link
Copy Markdown
Contributor

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:

@stevenwinship stevenwinship self-assigned this Aug 3, 2026
@github-actions github-actions Bot added FY27 Sprint 1 FY27 Sprint 1 (2026-07-01 - 2026-07-15) FY27 Sprint 2 FY27 Sprint 2 (2026-07-15 - 2026-07-29) Original size: 20 Type: Bug a defect labels Aug 3, 2026
@stevenwinship stevenwinship moved this to In Progress 💻 in IQSS Dataverse Project Aug 3, 2026
@stevenwinship stevenwinship added this to the 6.12 milestone Aug 3, 2026
@stevenwinship

Copy link
Copy Markdown
Contributor Author

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);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this skips checking if the PrivateUrlUser has access to this dataset?

@stevenwinship stevenwinship Aug 3, 2026

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.

That happens in checkAuthorization which is called before checkGuestbookRequiredResponse

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.

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.

Made a change

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)) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.)

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.

changed to ViewUnpublishedDataset

@coveralls

coveralls commented Aug 3, 2026

Copy link
Copy Markdown

Coverage Status

coverage: 25.005% (+0.003%) from 25.002% — 12535-download-without-guestbook-response-for-preview-user2 into develop

@github-actions

This comment has been minimized.

1 similar comment
@github-actions

This comment has been minimized.

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Test Results

403 tests  ±0   388 ✅ +1   33m 40s ⏱️ - 5m 0s
 55 suites ±0    15 💤 ±0 
 55 files   ±0     0 ❌  - 1 

Results for commit f01525d. ± Comparison against base commit ad7ada1.

♻️ This comment has been updated with latest results.

@github-actions

This comment has been minimized.

1 similar comment
@github-actions

This comment has been minimized.

@stevenwinship stevenwinship moved this from In Progress 💻 to Ready for Review ⏩ in IQSS Dataverse Project Aug 4, 2026
@stevenwinship stevenwinship removed their assignment Aug 4, 2026

@qqmyers qqmyers left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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/");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The ApiKey auth checks for the path starting with / - is that needed here too? (using final static constant as well)

public static final String ACCESS_DATAFILE_PATH_PREFIX = "/access/datafile/";

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.

How does that even work? The path doesn't have a leading '/'

containerRequestContext.getUriInfo().getPath() access/datafile/4|#]

@qqmyers qqmyers Aug 5, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.

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.

fixed SessionCookie but not ApiKeyAuth

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.

I'm looking into ApiKeyAuth separately

required = false;
// PrivateUrlUsers are exempt from this requirement
if (user instanceof PrivateUrlUser) {
return false;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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).

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.

added checkAuthorization

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Not seeing a change? I'd expect something like if ((user instanceof PrivateUrlUser) || (user instanceof AuthenticatedUser && permissionService.userOn(user, ds).has(Permission.ViewUnpublishedDataset)))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.

@qqmyers qqmyers moved this from Ready for Review ⏩ to In Review 🔎 in IQSS Dataverse Project Aug 5, 2026
@github-actions

This comment has been minimized.

@stevenwinship
stevenwinship force-pushed the 12535-download-without-guestbook-response-for-preview-user2 branch from aaf3218 to 477ed98 Compare August 5, 2026 19:03
@github-actions

This comment has been minimized.

1 similar comment
@github-actions

This comment has been minimized.

@stevenwinship
stevenwinship force-pushed the 12535-download-without-guestbook-response-for-preview-user2 branch from 477ed98 to cf7d78c Compare August 5, 2026 21:09
@github-actions

This comment has been minimized.

@Inject
DataverseSession session;

public static final String ACCESS_DATAFILE_PATH_PREFIX = "access/datafile/";

@qqmyers qqmyers Aug 6, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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/".

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.

fixed

@sonarqubecloud

sonarqubecloud Bot commented Aug 7, 2026

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
21.4% Coverage on New Code (required ≥ 80%)

See analysis details on SonarQube Cloud

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

📦 Pushed preview images as

ghcr.io/gdcc/dataverse:12535-download-without-guestbook-response-for-preview-user2
ghcr.io/gdcc/configbaker:12535-download-without-guestbook-response-for-preview-user2

🚢 See on GHCR. Use by referencing with full name as printed above, mind the registry name.

@stevenwinship stevenwinship removed their assignment Aug 7, 2026

private boolean isAccessApi(ContainerRequestContext containerRequestContext) {
String requestPath = containerRequestContext.getUriInfo() != null ? containerRequestContext.getUriInfo().getPath() : "";
return ("GET".equalsIgnoreCase(containerRequestContext.getMethod()) &&

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

FY27 Sprint 1 FY27 Sprint 1 (2026-07-01 - 2026-07-15) FY27 Sprint 2 FY27 Sprint 2 (2026-07-15 - 2026-07-29) Original size: 20 Type: Bug a defect

Projects

Status: In Review 🔎

Development

Successfully merging this pull request may close these issues.

When there is a guestbook, you cannot download files using a Preview URL

4 participants