Skip to content

Commit

Permalink
Add version handling to AROMA
Browse files Browse the repository at this point in the history
From now, the users will get a read-only version of the opened RO-CRATE in AROMA if:
 - they do not have the permission to edit the dataset
 - the dataset version is already published
 - they are is not logged in (this worked previously too)
  • Loading branch information
fintanorbert committed Nov 15, 2023
1 parent 1f48cc1 commit e822dbb
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 19 deletions.
55 changes: 37 additions & 18 deletions src/main/java/edu/harvard/iq/dataverse/api/arp/ArpApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -597,9 +597,9 @@ public Response updateMdb(@PathParam("dvIdtf") String dvIdtf, File file) {
}

@GET
@Path("/rocrate/{persistentId : .+}")
@Path("/rocrate/{version}/{persistentId : .+}")
@Produces("application/json")
public Response getRoCrate(@PathParam("persistentId") String persistentId) throws WrappedResponse
public Response getRoCrate(@PathParam("persistentId") String persistentId, @PathParam("version") String version) throws WrappedResponse
{
// Get the dataset by pid so that we get is actual ID.
Dataset dataset = datasetService.findByGlobalId(persistentId);
Expand All @@ -608,39 +608,58 @@ public Response getRoCrate(@PathParam("persistentId") String persistentId) throw
arpConfig.get("arp.rocrate.previewgenerator.address");

return response( req -> {
AuthenticatedUser authenticatedUser = null;
try {
authenticatedUser = findAuthenticatedUserOrDie();
} catch (WrappedResponse ex) {
// ignore. If authenticatedUser == null then it is a guest, and can only be readonly anyway,
// otherwise this is a token authenticated user and we check EditDataset permission
}

// When we get here user's auth is already checked. We are either an authenticated user or guest.
final Dataset retrieved = execCommand(new GetDatasetCommand(req, findDatasetOrDie(String.valueOf(dataset.getId()))));
// The latest version is the latest version accessible to the user. Fro guest it must be a published version
// for an author it is either the published version or DRAFT.
final DatasetVersion latest = execCommand(new GetLatestAccessibleDatasetVersionCommand(req, retrieved));
// The opened version is either the version that was requested if that is available to the user or the latest version accessible to the user.
// For a guest it must be a published version for an author it is either the opened version or DRAFT.
DatasetVersion opened = null;
if (!version.equals("undefined")) {
if (version.equals("DRAFT") && (authenticatedUser == null || !permissionService.userOn(authenticatedUser, dataset).has(Permission.EditDataset))) {
opened = execCommand(new GetLatestAccessibleDatasetVersionCommand(req, retrieved));
} else {
var openedVersion = retrieved.getVersions().stream().filter(dsv -> dsv.getFriendlyVersionNumber().equals(version)).findFirst();
if (openedVersion.isPresent()) {
opened = openedVersion.get();
}
}
} else {
// If the opened version is "undefined" that means the last published version was opened
opened = retrieved.getReleasedVersion();
}
// If a wrong version was requested by the user always provide the latest accessible
if (opened == null) {
opened = execCommand(new GetLatestAccessibleDatasetVersionCommand(req, retrieved));
}

try {
Gson gson = new GsonBuilder().setPrettyPrinting().create();
var versionNumber = latest.getFriendlyVersionNumber();
String roCratePath = roCrateManager.getRoCratePath(latest);
var versionNumber = opened.getFriendlyVersionNumber();
String roCratePath = roCrateManager.getRoCratePath(opened);
if (!Files.exists(Paths.get(roCratePath))) {
roCrateManager.createOrUpdateRoCrate(latest);
roCrateManager.createOrUpdateRoCrate(opened);
}
BufferedReader bufferedReader = new BufferedReader(new FileReader(roCratePath));
JsonObject roCrateJson = gson.fromJson(bufferedReader, JsonObject.class);
// Check whether something is missing or wrong with this ro crate, in which case we regenerate
if (needToRegenerate(roCrateJson)) {
roCrateManager.createOrUpdateRoCrate(latest);
roCrateManager.createOrUpdateRoCrate(opened);
bufferedReader = new BufferedReader(new FileReader(roCratePath));
roCrateJson = gson.fromJson(bufferedReader, JsonObject.class);
}
var resp = Response.ok(roCrateJson.toString());
// If returning the released version it is readonly
// In any other case the user is already checked to have access to a draft version and can edit
// Note: need to add Access-Control-Expose-Headers to make X-Arp-RoCrate-Readonly accessible via CORS
AuthenticatedUser authenticatedUser = null;
try {
authenticatedUser = findAuthenticatedUserOrDie();
} catch (WrappedResponse ex) {
// ignore. If authenticatedUser == null then it is a guest, and can only be readonly anyway,
// otherwise this is a token authenticated user and we check EditDataset permission
}

if (authenticatedUser == null || dataset.isLocked() || !permissionService.userOn(authenticatedUser, dataset).has(Permission.EditDataset)) {
if (authenticatedUser == null || dataset.isLocked() || !permissionService.userOn(authenticatedUser, dataset).has(Permission.EditDataset)
|| (opened.isReleased() && !dataset.getLatestVersion().equals(opened))) {
resp = resp.header("X-Arp-RoCrate-Readonly", true)
.header("Access-Control-Expose-Headers", "X-Arp-RoCrate-Readonly");
}
Expand Down
4 changes: 4 additions & 0 deletions src/main/webapp/aroma.xhtml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,14 @@
const currentUserApiKey = "#{DatasetPage.currentUserApiKey}"; // Somehow it ccannot be passed from file.xhmtl or dataset.xhtml
const language = "#{language}";
const showFile = "#{showFile}";
const version = "#{version}";
let uri = "#{aromaAddress}?dataset=" + encodeURIComponent(persistentId)+"&apiKey="+currentUserApiKey+"&lang="+language;
if (showFile) {
uri += "&showFile="+showFile;
}
if (version) {
uri += "&version="+version;
}
document.getElementById('iframeId').src = uri;
}, 10)
</script>
Expand Down
3 changes: 2 additions & 1 deletion src/main/webapp/dataset.xhtml
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,7 @@
#{bundle['file.dataFilesTab.metadata.downloadRoCrate']}
</p:commandLink>
<h:outputLink
styleClass="#{DatasetPage.dataset.hasJsonCrate(DatasetPage.workingVersion.getFriendlyVersionNumber())? 'btn btn-default btn-access btn-disabled' : 'btn btn-default btn-access'}" value="#{DatasetPage.aromaAddress}?dataset=#{DatasetPage.uriEncodedPersistentId}&amp;apiKey=#{DatasetPage.currentUserApiKey}&amp;lang=#{DatasetPage.language}"
styleClass="#{DatasetPage.dataset.hasJsonCrate(DatasetPage.workingVersion.getFriendlyVersionNumber())? 'btn btn-default btn-access btn-disabled' : 'btn btn-default btn-access'}" value="#{DatasetPage.aromaAddress}?dataset=#{DatasetPage.uriEncodedPersistentId}&amp;apiKey=#{DatasetPage.currentUserApiKey}&amp;lang=#{DatasetPage.language}&amp;version=#{DatasetPage.workingVersion.getFriendlyVersionNumber()}"
rendered="#{!widgetWrapper.widgetView}"
disabled="#{DatasetPage.dataset.hasJsonCrate(DatasetPage.workingVersion.getFriendlyVersionNumber())}"
target="_blank">
Expand Down Expand Up @@ -967,6 +967,7 @@
<ui:param name="userApiKey" value="#{DatasetPage.currentUserApiKey}"/>
<ui:param name="aromaAddress" value="#{DatasetPage.aromaAddress}"/>
<ui:param name="language" value="#{DatasetPage.language}"/>
<ui:param name="version" value="#{DatasetPage.workingVersion.getFriendlyVersionNumber()}"/>
</ui:include>
</p:tab>
</p:tabView>
Expand Down
1 change: 1 addition & 0 deletions src/main/webapp/file.xhtml
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,7 @@
<ui:param name="aromaAddress" value="#{FilePage.aromaAddress}"/>
<ui:param name="showFile" value="#{FilePage.fileId}"/>
<ui:param name="language" value="#{FilePage.language}"/>
<ui:param name="version" value="#{FilePage.version}"/>
</ui:include>
</p:tab>
</p:tabView>
Expand Down

0 comments on commit e822dbb

Please sign in to comment.