Skip to content

Commit 24d3dbb

Browse files
committed
Merge remote-tracking branch 'downstream/dtq-dev' into backport-1338-to-dtq-dev
2 parents f03f13f + 82085cb commit 24d3dbb

46 files changed

Lines changed: 3664 additions & 191 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

dspace-api/src/main/java/org/dspace/administer/ItemVersionLinker.java

Lines changed: 383 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* The contents of this file are subject to the license and copyright
3+
* detailed in the LICENSE and NOTICE files at the root of the source
4+
* tree and available online at
5+
*
6+
* http://www.dspace.org/license/
7+
*/
8+
package org.dspace.administer;
9+
10+
import org.apache.commons.cli.Options;
11+
import org.dspace.scripts.configuration.ScriptConfiguration;
12+
13+
/**
14+
* The {@link ScriptConfiguration} for the {@link ItemVersionLinker} script.
15+
*
16+
* @author Milan Kuchtiak
17+
*/
18+
public class ItemVersionLinkerConfiguration extends ScriptConfiguration<ItemVersionLinker> {
19+
20+
private Class<ItemVersionLinker> dspaceRunnableClass;
21+
22+
/**
23+
* Generic getter for the dspaceRunnableClass
24+
*
25+
* @return the dspaceRunnableClass value of this ScriptConfiguration
26+
*/
27+
@Override
28+
public Class<ItemVersionLinker> getDspaceRunnableClass() {
29+
return dspaceRunnableClass;
30+
}
31+
32+
/**
33+
* Generic setter for the dspaceRunnableClass
34+
*
35+
* @param dspaceRunnableClass The dspaceRunnableClass to be set for this ScriptConfiguration
36+
*/
37+
@Override
38+
public void setDspaceRunnableClass(Class<ItemVersionLinker> dspaceRunnableClass) {
39+
this.dspaceRunnableClass = dspaceRunnableClass;
40+
}
41+
42+
/**
43+
* The getter for the options of the Script
44+
*
45+
* @return the options value of this ScriptConfiguration
46+
*/
47+
@Override
48+
public Options getOptions() {
49+
if (options == null) {
50+
51+
Options options = new Options();
52+
53+
options.addOption("h", "help", false, "help");
54+
55+
options.addOption("l", "link", false, "link item with the previous item");
56+
57+
options.addOption("u", "unlink", false, "unlink item from the previous item in version history");
58+
59+
options.addOption("p", "previous", true,
60+
"item handle, or UUID, of the previous(left) item that is intended to be linked with the (right)" +
61+
" item (only required for link option)");
62+
63+
options.addOption("i", "item", true,
64+
"item handle, or UUID, of the (right) item that is intended to be linked/unlinked with/from the " +
65+
"previous item (required for both link and unlink options)");
66+
options.getOption("i").setRequired(true);
67+
68+
options.addOption("e", "eperson", true, "ePerson email");
69+
options.getOption("e").setRequired(false);
70+
71+
super.options = options;
72+
}
73+
return options;
74+
}
75+
}

dspace-api/src/main/java/org/dspace/app/util/MetadataExposureServiceImpl.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.dspace.authorize.service.AuthorizeService;
2222
import org.dspace.content.Item;
2323
import org.dspace.core.Context;
24+
import org.dspace.eperson.EPerson;
2425
import org.dspace.services.ConfigurationService;
2526
import org.springframework.beans.factory.annotation.Autowired;
2627

@@ -117,10 +118,12 @@ public boolean isHidden(Context context, String schema, String element, String q
117118
}
118119

119120
// The user is not administrator, but he could be a submitter
120-
if (hidden && Objects.nonNull(context) && Objects.nonNull(item) &&
121-
this.submitterShouldSee(schema, element, qualifier)) {
122-
// the submitters override
123-
hidden = !item.getSubmitter().equals(context.getCurrentUser());
121+
if (hidden && Objects.nonNull(context) && Objects.nonNull(item)) {
122+
EPerson submitter = item.getSubmitter();
123+
if (Objects.nonNull(submitter) && this.submitterShouldSee(schema, element, qualifier)) {
124+
// the submitters override
125+
hidden = !submitter.equals(context.getCurrentUser());
126+
}
124127
}
125128

126129
return hidden;

dspace-api/src/main/java/org/dspace/content/InstallItemServiceImpl.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@
4141
import org.dspace.services.ConfigurationService;
4242
import org.dspace.supervision.SupervisionOrder;
4343
import org.dspace.supervision.service.SupervisionOrderService;
44+
import org.dspace.versioning.Version;
45+
import org.dspace.versioning.service.VersionHistoryService;
46+
import org.dspace.versioning.service.VersioningService;
4447
import org.springframework.beans.factory.annotation.Autowired;
4548

4649
/**
@@ -71,6 +74,10 @@ public class InstallItemServiceImpl implements InstallItemService {
7174
private ResourcePolicyService resourcePolicyService;
7275
@Autowired(required = true)
7376
protected ConfigurationService configurationService;
77+
@Autowired(required = true)
78+
protected VersioningService versioningService;
79+
@Autowired(required = true)
80+
protected VersionHistoryService versionHistoryService;
7481

7582
Logger log = LogManager.getLogger(InstallItemServiceImpl.class);
7683

@@ -108,6 +115,8 @@ public Item installItem(Context c, InProgressSubmission is,
108115
// Finish up / archive the item
109116
item = finishItem(c, item, is);
110117

118+
fixRelationMetadata(c, item);
119+
111120
// As this is a BRAND NEW item, as a final step we need to remove the
112121
// submitter item policies created during deposit and replace them with
113122
// the default policies from the collection.
@@ -410,4 +419,64 @@ private void createResourcePolicy(Context context, Item item, int action) throws
410419
context.restoreAuthSystemState();
411420
}
412421

422+
/**
423+
* This method adds the "dc.relation.isreplacedby" metadata field to the previous item, if exists.
424+
*
425+
* @param c Context
426+
* @param item Item being installed
427+
* @throws SQLException If there is an issue interacting with the database.
428+
*/
429+
private void fixRelationMetadata(Context c, Item item) throws SQLException, AuthorizeException {
430+
String dcRelationReplaces = itemService.getMetadataFirstValue(item, "dc", "relation", "replaces", Item.ANY);
431+
if (dcRelationReplaces == null) {
432+
// nothing need to be done if the new item doesn't have "dc.relation.replaces" metadata field
433+
return;
434+
}
435+
Version itemVersion = versioningService.getVersion(c, item);
436+
if (itemVersion != null) {
437+
Version previousItemVersion =
438+
versionHistoryService.getPrevious(c, itemVersion.getVersionHistory(), itemVersion);
439+
if (previousItemVersion != null) {
440+
Item previousItem = previousItemVersion.getItem();
441+
if (previousItem != null) {
442+
String previousIdentifierUri =
443+
itemService.getMetadataFirstValue(previousItem, "dc", "identifier", "uri", Item.ANY);
444+
if (dcRelationReplaces.equals(previousIdentifierUri)) {
445+
// set "dc.relation.isreplacedby" metadata field to the previous item,
446+
// pointing to the handle of the new item
447+
// reload the previous item to avoid "detached entity" error
448+
// when updating it in the setIsReplacedByMetadata() method
449+
setIsReplacedByMetadata(c, c.reloadEntity(previousItem), item);
450+
}
451+
}
452+
}
453+
}
454+
}
455+
456+
private void setIsReplacedByMetadata(Context c, Item previousItem, Item newItem)
457+
throws SQLException, AuthorizeException {
458+
String identifierUri = itemService.getMetadataFirstValue(newItem, "dc", "identifier","uri", Item.ANY);
459+
if (StringUtils.isBlank(identifierUri)) {
460+
log.warn("The new item (id: {}) doesn't have the metadata dc.identifier.uri, " +
461+
"so it's not possible to add dc.relation.isreplacedby to the previous item",
462+
newItem.getID());
463+
} else {
464+
boolean isReplacedByAlreadyExists =
465+
itemService.getMetadata(previousItem, "dc", "relation", "isreplacedby", Item.ANY)
466+
.stream()
467+
.anyMatch(m -> identifierUri.equals(m.getValue()));
468+
if (!isReplacedByAlreadyExists) {
469+
itemService.addMetadata(c, previousItem, "dc", "relation", "isreplacedby", null, identifierUri);
470+
try {
471+
c.turnOffAuthorisationSystem();
472+
itemService.update(c, previousItem);
473+
} catch (AuthorizeException e) {
474+
throw new SQLException("Unable to update previous item after adding dc.relation.isreplacedby", e);
475+
} finally {
476+
c.restoreAuthSystemState();
477+
}
478+
}
479+
}
480+
}
481+
413482
}

dspace-api/src/main/java/org/dspace/content/PreviewContentServiceImpl.java

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -155,21 +155,26 @@ public List<PreviewContent> findAll(Context context) throws SQLException {
155155
@Override
156156
public boolean canPreview(Context context, Bitstream bitstream, boolean authorization)
157157
throws SQLException, AuthorizeException {
158-
try {
159-
// Check it is allowed by configuration
160-
boolean isAllowedByCfg = configurationService.getBooleanProperty("file.preview.enabled", true);
161-
if (!isAllowedByCfg) {
162-
return false;
163-
}
164-
165-
// Check it is allowed by license
166-
if (authorization) {
158+
// Check it is allowed by configuration
159+
boolean isAllowedByCfg = configurationService.getBooleanProperty("file.preview.enabled", true);
160+
if (!isAllowedByCfg) {
161+
return false;
162+
}
163+
if (authorization) {
164+
// Verify that bitstream policy allows user to READ the bitstream.
165+
// If not, the preview content is disabled.
166+
try {
167167
authorizeService.authorizeAction(context, bitstream, Constants.READ);
168+
} catch (AuthorizeException e) {
169+
// In case the license agreement(for bitstream downloading) is needed,
170+
// the MissingLicenseAgreementException, that extends AuthorizeException, is thrown.
171+
// For this case we also disable the content preview.
172+
// Otherwise, user could see the content of some files without accepting the agreement,
173+
// which could cause a security issue.
174+
return false;
168175
}
169-
return true;
170-
} catch (MissingLicenseAgreementException e) {
171-
return false;
172176
}
177+
return true;
173178
}
174179

175180
@Override
@@ -178,13 +183,16 @@ public List<FileInfo> getFilePreviewContent(Context context, Bitstream bitstream
178183
File file = null;
179184

180185
try {
181-
file = bitstreamService.retrieveFile(context, bitstream, false); // Retrieve the file
186+
file = bitstreamService.retrieveFile(context, bitstream, true); // Retrieve the file
182187

183188
if (Objects.nonNull(file)) {
184189
fileInfos = processFileToFilePreview(context, bitstream, file);
185190
}
186191
} catch (MissingLicenseAgreementException e) {
187-
log.error("Missing license agreement: ", e);
192+
log.warn("File Preview disabled: Missing license agreement!");
193+
throw e;
194+
} catch (AuthorizeException e) {
195+
log.warn("File Preview disabled: Authorization error!");
188196
throw e;
189197
} catch (IOException e) {
190198
log.error("IOException during file processing: ", e);

0 commit comments

Comments
 (0)