Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,19 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import javax.mail.MessagingException;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.NotFoundException;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.collections4.CollectionUtils;
Comment thread
Copilot marked this conversation as resolved.
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -57,7 +62,6 @@
import org.dspace.core.I18nUtil;
import org.dspace.eperson.EPerson;
import org.dspace.services.ConfigurationService;
import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -74,6 +78,8 @@ public class ClarinUserMetadataRestController {

public static final String CHECK_EMAIL_RESPONSE_CONTENT = "checkEmail";

private static final List<String> OPTIONAL_METADATA_KEYS = List.of("ORGANIZATION");

@Autowired
ClarinUserMetadataService clarinUserMetadataService;
@Autowired
Expand All @@ -93,14 +99,17 @@ public class ClarinUserMetadataRestController {
@Autowired
ConfigurationService configurationService;

@Autowired
ObjectMapper objectMapper;

// Enum to distinguish between the two types of the email
enum MailType { ALLZIP, BITSTREAM }

@RequestMapping(value = "/zip", method = POST, consumes = APPLICATION_JSON)
@PreAuthorize("permitAll()")
public ResponseEntity manageUserMetadataForZIP(@RequestParam("itemUUID") UUID itemUUID,
HttpServletRequest request)
throws SQLException, ParseException, IOException, AuthorizeException, MessagingException {
HttpServletRequest request)
throws SQLException, IOException, AuthorizeException {

// Get context from the request
Context context = obtainContext(request);
Expand All @@ -127,17 +136,26 @@ public ResponseEntity manageUserMetadataForZIP(@RequestParam("itemUUID") UUID it

boolean shouldEmailToken = false;
ClarinLicense clarinLicense = null;
// Get ClarinUserMetadataRest Array from the request body
ClarinUserMetadataRest[] clarinUserMetadataRestArray =
new ObjectMapper().readValue(request.getInputStream(), ClarinUserMetadataRest[].class);
if (Objects.isNull(clarinUserMetadataRestArray)) {
throw new RuntimeException("The clarinUserMetadataRestArray cannot be null. It could be empty, but" +
" not null");
}
Set<String> requiredInfoKeys = new HashSet<>();

// Convert Array to the List
List<ClarinUserMetadataRest> clarinUserMetadataRestList = Arrays.asList(clarinUserMetadataRestArray);
List<Bundle> bundles = item.getBundles("ORIGINAL");
if (!bundles.isEmpty()) {
List<Bitstream> bitstreams = bundles.get(0).getBitstreams();
if (!bitstreams.isEmpty()) {
ClarinLicenseResourceMapping clarinLicenseResourceMapping =
this.getLicenseResourceMapping(context, bitstreams.get(0).getID());
clarinLicense = getClarinLicense(clarinLicenseResourceMapping);
shouldEmailToken = this.shouldEmailToken(clarinLicenseResourceMapping);
requiredInfoKeys.addAll(getRequiredInfoKeys(clarinLicense));
}
}

ClarinUserMetadataRest[] clarinUserMetadataRestArray = getClarinUserMetadata(request);
checkForRequiredInfoKeys(clarinUserMetadataRestArray, requiredInfoKeys);
List<ClarinUserMetadataRest> clarinUserMetadataRestList = (clarinLicense == null)
? Arrays.asList(clarinUserMetadataRestArray)
: getFilteredUserMetadataForClarinLicense(clarinUserMetadataRestArray, requiredInfoKeys);

for (Bundle original : bundles) {
List<Bitstream> bss = original.getBitstreams();
for (Bitstream bitstream : bss) {
Expand All @@ -159,18 +177,11 @@ public ResponseEntity manageUserMetadataForZIP(@RequestParam("itemUUID") UUID it
this.processSignedInUser(context, currentUser, clarinUserMetadataRestList,
clarinLicenseResourceMapping, downloadToken);
}

// Check (only once) if the Clarin License contains the required information to SEND_TOKEN, which means
// the item must be downloaded after the user confirms the download with the token sent by email.
if (Objects.isNull(clarinLicense)) {
clarinLicense = this.getClarinLicense(clarinLicenseResourceMapping);
shouldEmailToken = this.shouldEmailToken(clarinLicenseResourceMapping);
}
}
}

context.commit();
if (shouldEmailToken) {
if (clarinLicense != null && shouldEmailToken) {
// If yes - send token to e-mail
try {
String email = getEmailFromUserMetadata(clarinUserMetadataRestList);
Expand All @@ -191,8 +202,8 @@ public ResponseEntity manageUserMetadataForZIP(@RequestParam("itemUUID") UUID it
@RequestMapping(method = POST, consumes = APPLICATION_JSON)
@PreAuthorize("permitAll()")
public ResponseEntity manageUserMetadata(@RequestParam("bitstreamUUID") UUID bitstreamUUID,
HttpServletRequest request)
throws SQLException, ParseException, IOException, AuthorizeException, MessagingException {
HttpServletRequest request)
throws SQLException, IOException, AuthorizeException {

// Get context from the request
Context context = obtainContext(request);
Expand All @@ -201,7 +212,6 @@ public ResponseEntity manageUserMetadata(@RequestParam("bitstreamUUID") UUID bit
return null;
}


Bitstream bitstream = bitstreamService.find(context, bitstreamUUID);
if (Objects.isNull(bitstream)) {
log.error("Cannot find the bitstream with ID: " + bitstreamUUID);
Expand All @@ -228,16 +238,13 @@ public ResponseEntity manageUserMetadata(@RequestParam("bitstreamUUID") UUID bit
throw new AuthorizeException("Anonymous user is not allowed to get access token");
}

// Get ClarinUserMetadataRest Array from the request body
ClarinUserMetadataRest[] clarinUserMetadataRestArray =
new ObjectMapper().readValue(request.getInputStream(), ClarinUserMetadataRest[].class);
if (Objects.isNull(clarinUserMetadataRestArray)) {
throw new RuntimeException("The clarinUserMetadataRestArray cannot be null. It could be empty, but" +
" not null");
}
ClarinUserMetadataRest[] clarinUserMetadataRestArray = getClarinUserMetadata(request);

Set<String> requiredInfoKeys = getRequiredInfoKeys(clarinLicense);
checkForRequiredInfoKeys(clarinUserMetadataRestArray, requiredInfoKeys);
List<ClarinUserMetadataRest> clarinUserMetadataRestList = getFilteredUserMetadataForClarinLicense(
clarinUserMetadataRestArray, requiredInfoKeys);

// Convert Array to the List
List<ClarinUserMetadataRest> clarinUserMetadataRestList = Arrays.asList(clarinUserMetadataRestArray);
if (Objects.isNull(currentUser)) {
// The user is not signed in
this.processNonSignedInUser(context, clarinUserMetadataRestList, clarinLicenseResourceMapping,
Expand Down Expand Up @@ -284,7 +291,7 @@ private void sendEmailWithDownloadLink(Context context, DSpaceObject dso,
MailType mailType,
List<ClarinUserMetadataRest> clarinUserMetadataRestList,
String itemHandle)
throws IOException, SQLException, MessagingException {
throws IOException, MessagingException {
if (StringUtils.isBlank(email)) {
log.error("Cannot send email with download link because the email is empty.");
throw new DSpaceBadRequestException("Cannot send email with download link because the email is empty.");
Expand Down Expand Up @@ -611,4 +618,80 @@ private List<ClarinUserMetadata> createUserMetadataFromRequest(Context context,
}
return clarinUserMetadataList;
}

/**
* Get ClarinUserMetadataRest array from the request body. Throws exception if the request body is empty or invalid.
*
* @param request request
* @return ClarinUserMetadataRest array
*/
private ClarinUserMetadataRest[] getClarinUserMetadata(HttpServletRequest request) throws IOException {
ClarinUserMetadataRest[] clarinUserMetadataRestArray;
try {
clarinUserMetadataRestArray = objectMapper.readValue(
request.getInputStream(), ClarinUserMetadataRest[].class);
} catch (JsonProcessingException ex) {
throw new DSpaceBadRequestException("Missing or Invalid User Data", ex);
}
Comment thread
Copilot marked this conversation as resolved.
if (Objects.isNull(clarinUserMetadataRestArray)) {
throw new DSpaceBadRequestException("Missing or Invalid User Data");
}
Comment thread
Copilot marked this conversation as resolved.
return clarinUserMetadataRestArray;
}

/**
* Gets the required info keys for the given ClarinLicense.
* Note that "SEND_TOKEN" is not considered required.
*
* @param clarinLicense the ClarinLicense object to get required info keys from
* @return Set of required info keys for the given ClarinLicense
*/
private static Set<String> getRequiredInfoKeys(ClarinLicense clarinLicense) {
return Optional.ofNullable(clarinLicense.getRequiredInfo())
.map(requiredInfo -> Arrays.stream(requiredInfo.split(","))
.filter(s -> StringUtils.isNotBlank(s)
&& !"SEND_TOKEN".equals(s))
.map(String::trim)
.collect(Collectors.toSet()))
.orElse(Set.of());
Comment thread
kuchtiak-ufal marked this conversation as resolved.
}

/**
* Checks if the given array of ClarinUserMetadataRest objects contains all required info keys.
* Note that the OPTIONAL_METADATA_KEYS are not required.
*
* @param clarinUserMetadataRestArray the array of ClarinUserMetadataRest objects to check
* @param requiredInfoKeys the set of required info keys to check against
*/
private static void checkForRequiredInfoKeys(ClarinUserMetadataRest[] clarinUserMetadataRestArray,
Set<String> requiredInfoKeys) {
if (!requiredInfoKeys.stream().allMatch(requiredInfoKey ->
OPTIONAL_METADATA_KEYS.contains(requiredInfoKey) ||
Arrays.stream(clarinUserMetadataRestArray)
.anyMatch(clarinUserMetadataRest ->
requiredInfoKey.equals(clarinUserMetadataRest.getMetadataKey())
&& StringUtils.isNotBlank(clarinUserMetadataRest.getMetadataValue())))) {
throw new DSpaceBadRequestException("Missing required user metadata keys for the license.");
}
}

/**
* Filters the given array of ClarinUserMetadataRest objects to include only those
* required by the given ClarinLicense.
* Note that the "IP" should be included if present.
*
* @param clarinUserMetadataRestArray the array of ClarinUserMetadataRest objects to filter
* @param requiredInfoKeys the set of required keys for the given ClarinLicense
* @return a list of filtered ClarinUserMetadataRest objects
*/
private static List<ClarinUserMetadataRest> getFilteredUserMetadataForClarinLicense(
ClarinUserMetadataRest[] clarinUserMetadataRestArray,
Set<String> requiredInfoKeys) {
return Arrays.stream(clarinUserMetadataRestArray)
.filter(clarinUserMetadataRest ->
StringUtils.isNotBlank(clarinUserMetadataRest.getMetadataValue())
&& ("IP".equals(clarinUserMetadataRest.getMetadataKey())
|| requiredInfoKeys.contains(clarinUserMetadataRest.getMetadataKey())))
.collect(Collectors.toList());
}
}
Loading
Loading