mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-15 14:03:17 +00:00
Merge branch 'main' into DURACOM-127
This commit is contained in:
@@ -0,0 +1,79 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.importer.external.crossref;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.dspace.importer.external.metadatamapping.contributor.JsonPathMetadataProcessor;
|
||||||
|
import org.joda.time.LocalDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used for CrossRef's Live-Import to extract
|
||||||
|
* issued attribute.
|
||||||
|
* Beans are configured in the crossref-integration.xml file.
|
||||||
|
*
|
||||||
|
* @author Francesco Pio Scognamiglio (francescopio.scognamiglio at 4science.com)
|
||||||
|
*/
|
||||||
|
public class CrossRefDateMetadataProcessor implements JsonPathMetadataProcessor {
|
||||||
|
|
||||||
|
private final static Logger log = LogManager.getLogger();
|
||||||
|
|
||||||
|
private String pathToArray;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> processMetadata(String json) {
|
||||||
|
JsonNode rootNode = convertStringJsonToJsonNode(json);
|
||||||
|
Iterator<JsonNode> dates = rootNode.at(pathToArray).iterator();
|
||||||
|
Collection<String> values = new ArrayList<>();
|
||||||
|
while (dates.hasNext()) {
|
||||||
|
JsonNode date = dates.next();
|
||||||
|
LocalDate issuedDate = null;
|
||||||
|
SimpleDateFormat issuedDateFormat = null;
|
||||||
|
if (date.has(0) && date.has(1) && date.has(2)) {
|
||||||
|
issuedDate = new LocalDate(
|
||||||
|
date.get(0).numberValue().intValue(),
|
||||||
|
date.get(1).numberValue().intValue(),
|
||||||
|
date.get(2).numberValue().intValue());
|
||||||
|
issuedDateFormat = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
|
} else if (date.has(0) && date.has(1)) {
|
||||||
|
issuedDate = new LocalDate().withYear(date.get(0).numberValue().intValue())
|
||||||
|
.withMonthOfYear(date.get(1).numberValue().intValue());
|
||||||
|
issuedDateFormat = new SimpleDateFormat("yyyy-MM");
|
||||||
|
} else if (date.has(0)) {
|
||||||
|
issuedDate = new LocalDate().withYear(date.get(0).numberValue().intValue());
|
||||||
|
issuedDateFormat = new SimpleDateFormat("yyyy");
|
||||||
|
}
|
||||||
|
values.add(issuedDateFormat.format(issuedDate.toDate()));
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonNode convertStringJsonToJsonNode(String json) {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
JsonNode body = null;
|
||||||
|
try {
|
||||||
|
body = mapper.readTree(json);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
log.error("Unable to process json response.", e);
|
||||||
|
}
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPathToArray(String pathToArray) {
|
||||||
|
this.pathToArray = pathToArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -120,7 +120,7 @@ public class ItemTemplateRestController {
|
|||||||
* @throws SQLException
|
* @throws SQLException
|
||||||
* @throws AuthorizeException
|
* @throws AuthorizeException
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("hasPermission(#uuid, 'ITEM', 'WRITE')")
|
@PreAuthorize("hasPermission(#uuid, 'ITEMTEMPLATE', 'WRITE')")
|
||||||
@RequestMapping(method = RequestMethod.PATCH)
|
@RequestMapping(method = RequestMethod.PATCH)
|
||||||
public ResponseEntity<RepresentationModel<?>> patch(HttpServletRequest request, @PathVariable UUID uuid,
|
public ResponseEntity<RepresentationModel<?>> patch(HttpServletRequest request, @PathVariable UUID uuid,
|
||||||
@RequestBody(required = true) JsonNode jsonNode)
|
@RequestBody(required = true) JsonNode jsonNode)
|
||||||
@@ -153,7 +153,7 @@ public class ItemTemplateRestController {
|
|||||||
* @throws AuthorizeException
|
* @throws AuthorizeException
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@PreAuthorize("hasPermission(#uuid, 'ITEM', 'DELETE')")
|
@PreAuthorize("hasPermission(#uuid, 'ITEMTEMPLATE', 'DELETE')")
|
||||||
@RequestMapping(method = RequestMethod.DELETE)
|
@RequestMapping(method = RequestMethod.DELETE)
|
||||||
public ResponseEntity<RepresentationModel<?>> deleteTemplateItem(HttpServletRequest request,
|
public ResponseEntity<RepresentationModel<?>> deleteTemplateItem(HttpServletRequest request,
|
||||||
@PathVariable UUID uuid)
|
@PathVariable UUID uuid)
|
||||||
|
@@ -0,0 +1,83 @@
|
|||||||
|
/**
|
||||||
|
* The contents of this file are subject to the license and copyright
|
||||||
|
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||||
|
* tree and available online at
|
||||||
|
*
|
||||||
|
* http://www.dspace.org/license/
|
||||||
|
*/
|
||||||
|
package org.dspace.app.rest.security;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.dspace.app.rest.model.TemplateItemRest;
|
||||||
|
import org.dspace.app.rest.utils.ContextUtil;
|
||||||
|
import org.dspace.authorize.service.AuthorizeService;
|
||||||
|
import org.dspace.content.Collection;
|
||||||
|
import org.dspace.content.service.ItemService;
|
||||||
|
import org.dspace.core.Context;
|
||||||
|
import org.dspace.eperson.EPerson;
|
||||||
|
import org.dspace.services.RequestService;
|
||||||
|
import org.dspace.services.model.Request;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link RestObjectPermissionEvaluatorPlugin} class that evaluate WRITE and DELETE permission over a TemplateItem
|
||||||
|
*
|
||||||
|
* @author Bui Thai Hai (thaihai.bui@dlcorp.com.vn)
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class TemplateItemRestPermissionEvaluatorPlugin extends RestObjectPermissionEvaluatorPlugin {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(TemplateItemRestPermissionEvaluatorPlugin.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RequestService requestService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ItemService its;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AuthorizeService authorizeService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasDSpacePermission(Authentication authentication, Serializable targetId, String targetType,
|
||||||
|
DSpaceRestPermission permission) {
|
||||||
|
|
||||||
|
DSpaceRestPermission restPermission = DSpaceRestPermission.convert(permission);
|
||||||
|
if (!DSpaceRestPermission.WRITE.equals(restPermission) &&
|
||||||
|
!DSpaceRestPermission.DELETE.equals(restPermission)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!StringUtils.equalsIgnoreCase(targetType, TemplateItemRest.NAME)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Request request = requestService.getCurrentRequest();
|
||||||
|
Context context = ContextUtil.obtainContext(request.getHttpServletRequest());
|
||||||
|
|
||||||
|
EPerson ePerson = context.getCurrentUser();
|
||||||
|
if (ePerson == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Allow collection's admin to edit/delete the template
|
||||||
|
|
||||||
|
UUID dsoId = UUID.fromString(targetId.toString());
|
||||||
|
requestService.getCurrentRequest().getHttpServletRequest().getRequestURL();
|
||||||
|
try {
|
||||||
|
Collection coll = its.find(context, dsoId).getTemplateItemOf();
|
||||||
|
if (authorizeService.isAdmin(context, coll)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@@ -146,7 +146,7 @@ public class CrossRefImportMetadataSourceServiceIT extends AbstractLiveImportInt
|
|||||||
+ " Medical College of Prevention of Iodine Deficiency Diseases");
|
+ " Medical College of Prevention of Iodine Deficiency Diseases");
|
||||||
MetadatumDTO author = createMetadatumDTO("dc", "contributor", "author", "L.V. Senyuk");
|
MetadatumDTO author = createMetadatumDTO("dc", "contributor", "author", "L.V. Senyuk");
|
||||||
MetadatumDTO type = createMetadatumDTO("dc", "type", null, "journal-article");
|
MetadatumDTO type = createMetadatumDTO("dc", "type", null, "journal-article");
|
||||||
MetadatumDTO date = createMetadatumDTO("dc", "date", "issued", "2016");
|
MetadatumDTO date = createMetadatumDTO("dc", "date", "issued", "2016-05-19");
|
||||||
MetadatumDTO ispartof = createMetadatumDTO("dc", "relation", "ispartof",
|
MetadatumDTO ispartof = createMetadatumDTO("dc", "relation", "ispartof",
|
||||||
"Ukraïnsʹkij žurnal medicini, bìologìï ta sportu");
|
"Ukraïnsʹkij žurnal medicini, bìologìï ta sportu");
|
||||||
MetadatumDTO doi = createMetadatumDTO("dc", "identifier", "doi", "10.26693/jmbs01.02.184");
|
MetadatumDTO doi = createMetadatumDTO("dc", "identifier", "doi", "10.26693/jmbs01.02.184");
|
||||||
@@ -172,7 +172,7 @@ public class CrossRefImportMetadataSourceServiceIT extends AbstractLiveImportInt
|
|||||||
"Ischemic Heart Disease and Role of Nurse of Cardiology Department");
|
"Ischemic Heart Disease and Role of Nurse of Cardiology Department");
|
||||||
MetadatumDTO author2 = createMetadatumDTO("dc", "contributor", "author", "K. І. Kozak");
|
MetadatumDTO author2 = createMetadatumDTO("dc", "contributor", "author", "K. І. Kozak");
|
||||||
MetadatumDTO type2 = createMetadatumDTO("dc", "type", null, "journal-article");
|
MetadatumDTO type2 = createMetadatumDTO("dc", "type", null, "journal-article");
|
||||||
MetadatumDTO date2 = createMetadatumDTO("dc", "date", "issued", "2016");
|
MetadatumDTO date2 = createMetadatumDTO("dc", "date", "issued", "2016-05-19");
|
||||||
MetadatumDTO ispartof2 = createMetadatumDTO("dc", "relation", "ispartof",
|
MetadatumDTO ispartof2 = createMetadatumDTO("dc", "relation", "ispartof",
|
||||||
"Ukraïnsʹkij žurnal medicini, bìologìï ta sportu");
|
"Ukraïnsʹkij žurnal medicini, bìologìï ta sportu");
|
||||||
MetadatumDTO doi2 = createMetadatumDTO("dc", "identifier", "doi", "10.26693/jmbs01.02.105");
|
MetadatumDTO doi2 = createMetadatumDTO("dc", "identifier", "doi", "10.26693/jmbs01.02.105");
|
||||||
|
@@ -33,6 +33,7 @@ import org.dspace.app.rest.test.AbstractControllerIntegrationTest;
|
|||||||
import org.dspace.authorize.service.ResourcePolicyService;
|
import org.dspace.authorize.service.ResourcePolicyService;
|
||||||
import org.dspace.builder.CollectionBuilder;
|
import org.dspace.builder.CollectionBuilder;
|
||||||
import org.dspace.builder.CommunityBuilder;
|
import org.dspace.builder.CommunityBuilder;
|
||||||
|
import org.dspace.builder.ResourcePolicyBuilder;
|
||||||
import org.dspace.content.Collection;
|
import org.dspace.content.Collection;
|
||||||
import org.dspace.core.Constants;
|
import org.dspace.core.Constants;
|
||||||
import org.hamcrest.Matchers;
|
import org.hamcrest.Matchers;
|
||||||
@@ -243,6 +244,35 @@ public class ItemTemplateRestControllerIT extends AbstractControllerIntegrationT
|
|||||||
)))));
|
)))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Similar to patchTemplateItem(), except it is for collection admin, not repository admin
|
||||||
|
Test case was simplified, since it does not do anything else.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void patchTemplateItemAsCollectionAdmin() throws Exception {
|
||||||
|
setupTestTemplate();
|
||||||
|
|
||||||
|
String itemId = installTestTemplate();
|
||||||
|
|
||||||
|
ResourcePolicyBuilder.createResourcePolicy(context).withUser(eperson)
|
||||||
|
.withAction(Constants.ADMIN)
|
||||||
|
.withDspaceObject(childCollection).build();
|
||||||
|
String collAdminToken = getAuthToken(eperson.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(collAdminToken).perform(patch(getTemplateItemUrlTemplate(itemId))
|
||||||
|
.content(patchBody)
|
||||||
|
.contentType(contentType))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$", Matchers.allOf(
|
||||||
|
hasJsonPath("$.type", is("itemtemplate"))
|
||||||
|
)));
|
||||||
|
|
||||||
|
getClient(collAdminToken).perform(get(getCollectionTemplateItemUrlTemplate(childCollection.getID().toString())))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$", Matchers.allOf(
|
||||||
|
hasJsonPath("$.type", is("itemtemplate"))
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void patchIllegalInArchiveTemplateItem() throws Exception {
|
public void patchIllegalInArchiveTemplateItem() throws Exception {
|
||||||
setupTestTemplate();
|
setupTestTemplate();
|
||||||
@@ -337,6 +367,22 @@ public class ItemTemplateRestControllerIT extends AbstractControllerIntegrationT
|
|||||||
.andExpect(status().isNoContent());
|
.andExpect(status().isNoContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*Similar to deleteTemplateItem(), except it is for collection admin, not repository admin
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void deleteTemplateItemAsCollectionAdmin() throws Exception {
|
||||||
|
setupTestTemplate();
|
||||||
|
String itemId = installTestTemplate();
|
||||||
|
|
||||||
|
ResourcePolicyBuilder.createResourcePolicy(context).withUser(eperson)
|
||||||
|
.withAction(Constants.ADMIN)
|
||||||
|
.withDspaceObject(childCollection).build();
|
||||||
|
String collAdminToken = getAuthToken(eperson.getEmail(), password);
|
||||||
|
|
||||||
|
getClient(collAdminToken).perform(delete(getTemplateItemUrlTemplate(itemId)))
|
||||||
|
.andExpect(status().isNoContent());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void deleteTemplateItemNoRights() throws Exception {
|
public void deleteTemplateItemNoRights() throws Exception {
|
||||||
setupTestTemplate();
|
setupTestTemplate();
|
||||||
|
@@ -69,8 +69,11 @@
|
|||||||
|
|
||||||
<bean id="crossrefYearContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleJsonPathMetadataContributor">
|
<bean id="crossrefYearContrib" class="org.dspace.importer.external.metadatamapping.contributor.SimpleJsonPathMetadataContributor">
|
||||||
<property name="field" ref="crossref.year"/>
|
<property name="field" ref="crossref.year"/>
|
||||||
<property name="query" value="/issued/date-parts/0/0"/>
|
<property name="metadataProcessor" ref="crossrefDateMetadataProcessor"></property>
|
||||||
</bean>
|
</bean>
|
||||||
|
<bean name="crossrefDateMetadataProcessor" class="org.dspace.importer.external.crossref.CrossRefDateMetadataProcessor">
|
||||||
|
<property name="pathToArray" value="/issued/date-parts"></property>
|
||||||
|
</bean>
|
||||||
<bean id="crossref.year" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
<bean id="crossref.year" class="org.dspace.importer.external.metadatamapping.MetadataFieldConfig">
|
||||||
<constructor-arg value="dc.date.issued"/>
|
<constructor-arg value="dc.date.issued"/>
|
||||||
</bean>
|
</bean>
|
||||||
|
4
pom.xml
4
pom.xml
@@ -20,7 +20,7 @@
|
|||||||
<!--=== GENERAL / DSPACE-API DEPENDENCIES ===-->
|
<!--=== GENERAL / DSPACE-API DEPENDENCIES ===-->
|
||||||
<java.version>11</java.version>
|
<java.version>11</java.version>
|
||||||
<spring.version>5.3.27</spring.version>
|
<spring.version>5.3.27</spring.version>
|
||||||
<spring-boot.version>2.7.11</spring-boot.version>
|
<spring-boot.version>2.7.12</spring-boot.version>
|
||||||
<spring-security.version>5.7.8</spring-security.version> <!-- sync with version used by spring-boot-->
|
<spring-security.version>5.7.8</spring-security.version> <!-- sync with version used by spring-boot-->
|
||||||
<hibernate.version>5.6.15.Final</hibernate.version>
|
<hibernate.version>5.6.15.Final</hibernate.version>
|
||||||
<hibernate-validator.version>6.2.5.Final</hibernate-validator.version>
|
<hibernate-validator.version>6.2.5.Final</hibernate-validator.version>
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
<pdfbox-version>2.0.28</pdfbox-version>
|
<pdfbox-version>2.0.28</pdfbox-version>
|
||||||
<rome.version>1.19.0</rome.version>
|
<rome.version>1.19.0</rome.version>
|
||||||
<slf4j.version>1.7.36</slf4j.version>
|
<slf4j.version>1.7.36</slf4j.version>
|
||||||
<tika.version>2.3.0</tika.version>
|
<tika.version>2.5.0</tika.version>
|
||||||
<!-- Sync with whatever version Tika uses -->
|
<!-- Sync with whatever version Tika uses -->
|
||||||
<bouncycastle.version>1.70</bouncycastle.version>
|
<bouncycastle.version>1.70</bouncycastle.version>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user