sync with new models

This commit is contained in:
Efstratios Giannopoulos 2023-12-11 15:08:00 +02:00
parent c5570d15b7
commit c048d7047f
16 changed files with 617 additions and 391 deletions

View File

@ -58,6 +58,11 @@
<artifactId>json</artifactId>
<version>20160810</version>
</dependency>
<dependency>
<groupId>gr.cite</groupId>
<artifactId>cache</artifactId>
<version>2.1.0</version>
</dependency>
</dependencies>
<build>

View File

@ -8,26 +8,19 @@ import java.util.List;
@ConfigurationProperties(prefix = "funder")
public class FunderProperties {
private final List<DOIFunder> available;
private List<DoiFunder> available;
@ConstructorBinding
public FunderProperties(List<DOIFunder> available) {
this.available = available;
}
public List<DOIFunder> getAvailable() {
public List<DoiFunder> getAvailable() {
return available;
}
public static class DOIFunder {
private final String funder;
private final String doi;
public void setAvailable(List<DoiFunder> available) {
this.available = available;
}
@ConstructorBinding
public DOIFunder(String funder, String doi) {
this.funder = funder;
this.doi = doi;
}
public static class DoiFunder {
private String funder;
private String doi;
public String getFunder() {
return funder;
@ -36,5 +29,13 @@ public class FunderProperties {
public String getDoi() {
return doi;
}
public void setFunder(String funder) {
this.funder = funder;
}
public void setDoi(String doi) {
this.doi = doi;
}
}
}

View File

@ -7,14 +7,13 @@ import java.util.List;
@ConfigurationProperties(prefix = "identifiers")
public class IdentifierProperties {
private final List<String> related;
@ConstructorBinding
public IdentifierProperties(List<String> related) {
this.related = related;
}
private List<String> related;
public List<String> getRelated() {
return related;
}
public void setRelated(List<String> related) {
this.related = related;
}
}

View File

@ -8,14 +8,8 @@ import java.util.List;
@ConfigurationProperties(prefix = "pid")
public class PidProperties {
private final List<String> acceptedTypes;
private final PidFieldNames fields;
@ConstructorBinding
public PidProperties(List<String> acceptedTypes, PidFieldNames fields) {
this.acceptedTypes = acceptedTypes;
this.fields = fields;
}
private List<String> acceptedTypes;
private PidFieldNames fields;
public List<String> getAcceptedTypes() {
return acceptedTypes;
@ -25,22 +19,32 @@ public class PidProperties {
return fields;
}
public static class PidFieldNames {
private final String pidName;
private final String pidTypeName;
public void setAcceptedTypes(List<String> acceptedTypes) {
this.acceptedTypes = acceptedTypes;
}
@ConstructorBinding
public PidFieldNames(String pidName, String pidTypeName) {
this.pidName = pidName;
this.pidTypeName = pidTypeName;
}
public void setFields(PidFieldNames fields) {
this.fields = fields;
}
public static class PidFieldNames {
private String pidName;
private String pidTypeName;
public String getPidName() {
return pidName;
}
public void setPidName(String pidName) {
this.pidName = pidName;
}
public String getPidTypeName() {
return pidTypeName;
}
public void setPidTypeName(String pidTypeName) {
this.pidTypeName = pidTypeName;
}
}
}

View File

@ -11,15 +11,10 @@ import java.util.Map;
@ConfigurationProperties(prefix = "zenodo")
public class ZenodoProperties {
private final String tempStorage;
private String tempStorage;
private final List<ZenodoConfig> configuration;
private List<ZenodoConfig> configuration;
@ConstructorBinding
public ZenodoProperties(Map<String, String> storage, List<ZenodoConfig> configuration) {
this.tempStorage = storage.get("temp");
this.configuration = configuration;
}
public String getTempStorage() {
return tempStorage;
@ -29,108 +24,182 @@ public class ZenodoProperties {
return configuration;
}
public void setTempStorage(String tempStorage) {
this.tempStorage = tempStorage;
}
public void setConfiguration(List<ZenodoConfig> configuration) {
this.configuration = configuration;
}
public static class ZenodoConfig extends RepositoryDepositConfiguration {
private final DepositType depositType;
private final String repositoryId;
private final String accessToken;
private final String repositoryUrl;
private final String repositoryAuthorizationUrl;
private final String repositoryRecordUrl;
private final String repositoryAccessTokenUrl;
private final String repositoryClientId;
private final String repositoryClientSecret;
private final String redirectUri;
private final boolean hasLogo;
private final String logo;
private final String doiFunder;
private final String community;
private final String affiliation;
private final String domain;
@ConstructorBinding
public ZenodoConfig(DepositType depositType, String repositoryId, String accessToken, String repositoryUrl, String repositoryAuthorizationUrl, String repositoryRecordUrl, String repositoryAccessTokenUrl, String repositoryClientId, String repositoryClientSecret, String redirectUri, boolean hasLogo, String logo, String doiFunder, String community, String affiliation, String domain) {
this.depositType = depositType;
this.repositoryId = repositoryId;
this.accessToken = accessToken;
this.repositoryUrl = repositoryUrl;
this.repositoryAuthorizationUrl = repositoryAuthorizationUrl;
this.repositoryRecordUrl = repositoryRecordUrl;
this.repositoryAccessTokenUrl = repositoryAccessTokenUrl;
this.repositoryClientId = repositoryClientId;
this.repositoryClientSecret = repositoryClientSecret;
this.redirectUri = redirectUri;
this.hasLogo = hasLogo;
this.logo = logo;
this.doiFunder = doiFunder;
this.community = community;
this.affiliation = affiliation;
this.domain = domain;
}
private DepositType depositType;
private String repositoryId;
private String accessToken;
private String repositoryUrl;
private String repositoryAuthorizationUrl;
private String repositoryRecordUrl;
private String repositoryAccessTokenUrl;
private String repositoryClientId;
private String repositoryClientSecret;
private String redirectUri;
private boolean hasLogo;
private String logo;
private String doiFunder;
private String community;
private String affiliation;
private String domain;
@Override
public DepositType getDepositType() {
return depositType;
}
@Override
public void setDepositType(DepositType depositType) {
this.depositType = depositType;
}
@Override
public String getRepositoryId() {
return repositoryId;
}
@Override
public void setRepositoryId(String repositoryId) {
this.repositoryId = repositoryId;
}
@Override
public String getAccessToken() {
return accessToken;
}
@Override
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
@Override
public String getRepositoryUrl() {
return repositoryUrl;
}
@Override
public void setRepositoryUrl(String repositoryUrl) {
this.repositoryUrl = repositoryUrl;
}
@Override
public String getRepositoryAuthorizationUrl() {
return repositoryAuthorizationUrl;
}
@Override
public void setRepositoryAuthorizationUrl(String repositoryAuthorizationUrl) {
this.repositoryAuthorizationUrl = repositoryAuthorizationUrl;
}
@Override
public String getRepositoryRecordUrl() {
return repositoryRecordUrl;
}
@Override
public void setRepositoryRecordUrl(String repositoryRecordUrl) {
this.repositoryRecordUrl = repositoryRecordUrl;
}
@Override
public String getRepositoryAccessTokenUrl() {
return repositoryAccessTokenUrl;
}
@Override
public void setRepositoryAccessTokenUrl(String repositoryAccessTokenUrl) {
this.repositoryAccessTokenUrl = repositoryAccessTokenUrl;
}
@Override
public String getRepositoryClientId() {
return repositoryClientId;
}
@Override
public void setRepositoryClientId(String repositoryClientId) {
this.repositoryClientId = repositoryClientId;
}
@Override
public String getRepositoryClientSecret() {
return repositoryClientSecret;
}
@Override
public void setRepositoryClientSecret(String repositoryClientSecret) {
this.repositoryClientSecret = repositoryClientSecret;
}
@Override
public String getRedirectUri() {
return redirectUri;
}
@Override
public void setRedirectUri(String redirectUri) {
this.redirectUri = redirectUri;
}
@Override
public boolean isHasLogo() {
return hasLogo;
}
@Override
public void setHasLogo(boolean hasLogo) {
this.hasLogo = hasLogo;
}
public String getLogo() {
return logo;
}
public void setLogo(String logo) {
this.logo = logo;
}
public String getDoiFunder() {
return doiFunder;
}
public void setDoiFunder(String doiFunder) {
this.doiFunder = doiFunder;
}
public String getCommunity() {
return community;
}
public void setCommunity(String community) {
this.community = community;
}
public String getAffiliation() {
return affiliation;
}
public void setAffiliation(String affiliation) {
this.affiliation = affiliation;
}
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
public RepositoryDepositConfiguration toRepoConfig() {
RepositoryDepositConfiguration config = new RepositoryDepositConfiguration();
config.setDepositType(this.depositType);

View File

@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ZenodoComunity {
public class ZenodoCommunity {
private String identifier;

View File

@ -32,7 +32,7 @@ public class ZenodoDepositMetadata {
private List<String> references;
private List<ZenodoComunity> communities;
private List<ZenodoCommunity> communities;
@JsonProperty("access_right")
private ZenodoAccessRight accessRight;
@ -126,11 +126,11 @@ public class ZenodoDepositMetadata {
this.version = version;
}
public List<ZenodoComunity> getCommunities() {
public List<ZenodoCommunity> getCommunities() {
return communities;
}
public void setCommunities(List<ZenodoComunity> communities) {
public void setCommunities(List<ZenodoCommunity> communities) {
this.communities = communities;
}

View File

@ -1,4 +1,4 @@
package eu.eudat.depositinterface.zenodorepository.mapper;
package eu.eudat.depositinterface.zenodorepository.model.builder;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
@ -25,14 +25,25 @@ import java.util.stream.Collectors;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ZenodoBuilderMapper {
public class ZenodoBuilder {
private static final String UPLOAD_TYPE = "publication";
private static final String PUBLICATION_TYPE = "datamanagementplan";
private static final String IS_IDENTICAL_TO = "isIdenticalTo";
private static final String CONTRIBUTOR_TYPE_RESEARCHER = "Researcher";
private static final String CONTRIBUTOR_TYPE_PROJECT_MANAGER = "ProjectMember";
private static final String SOURCE_OPENAIRE = "openaire";
private static final String SOURCE_ORCID = "ORCID";
private static final String PID = "pid";
private final PidProperties pidProperties;
private final IdentifierProperties identifierProperties;
private final FunderProperties funderProperties;
@Autowired
public ZenodoBuilderMapper(PidProperties pidProperties, IdentifierProperties identifierProperties, FunderProperties funderProperties){
public ZenodoBuilder(PidProperties pidProperties, IdentifierProperties identifierProperties, FunderProperties funderProperties){
this.pidProperties = pidProperties;
this.identifierProperties = identifierProperties;
this.funderProperties = funderProperties;
@ -42,13 +53,13 @@ public class ZenodoBuilderMapper {
ZenodoDeposit deposit = new ZenodoDeposit();
this.applyZenodoRelator(dmp, deposit);
deposit.getMetadata().setTitle(dmp.getLabel());
deposit.getMetadata().setUploadType("publication");
deposit.getMetadata().setPublicationType("datamanagementplan");
deposit.getMetadata().setUploadType(UPLOAD_TYPE);
deposit.getMetadata().setPublicationType(PUBLICATION_TYPE);
deposit.getMetadata().setDescription((dmp.getDescription() != null && !dmp.getDescription().isEmpty() ? dmp.getDescription() : "<p></p>"));
deposit.getMetadata().setVersion(String.valueOf(dmp.getVersion()));
String zenodoCommunity = zenodoConfig.getCommunity();
if(zenodoCommunity != null && !zenodoCommunity.isEmpty()) {
ZenodoComunity community = new ZenodoComunity();
ZenodoCommunity community = new ZenodoCommunity();
community.setIdentifier(zenodoCommunity);
deposit.getMetadata().getCommunities().add(community);
}
@ -65,7 +76,7 @@ public class ZenodoBuilderMapper {
return deposit;
}
private List<DatasetFieldsDepositModel> findSchemanticValues(String relatedId, List<DatasetFieldsDepositModel> fields){
private List<DatasetFieldsDepositModel> findSchematicValues(String relatedId, List<DatasetFieldsDepositModel> fields){
return fields.stream().filter(f -> f.getSchematics().contains(relatedId)).collect(Collectors.toList());
}
@ -162,7 +173,7 @@ public class ZenodoBuilderMapper {
List<ZenodoRelator> relatedIdentifiers = new ArrayList<>();
for(DescriptionDepositModel descriptionDepositModel: dmp.getDescriptions()){
for(String relatedId: this.identifierProperties.getRelated()){
List<DatasetFieldsDepositModel> fields = findSchemanticValues(relatedId, descriptionDepositModel.getFields());
List<DatasetFieldsDepositModel> fields = findSchematicValues(relatedId, descriptionDepositModel.getFields());
Set<String> values = extractSchematicValues(fields, acceptedPidTypes);
for(String value: values){
ZenodoRelator relator = new ZenodoRelator();
@ -205,7 +216,7 @@ public class ZenodoBuilderMapper {
if (dmp.getAccessType().equals(DmpAccessType.Public)) {
ZenodoRelator relator = new ZenodoRelator();
relator.setIdentifier(zenodoConfig.getDomain() + "/external/zenodo/" + dmp.getId().toString());
relator.setRelation("isIdenticalTo");
relator.setRelation(IS_IDENTICAL_TO);
if (deposit.getMetadata().getRelatedIdentifiers() == null)deposit.getMetadata().setRelatedIdentifiers(new ArrayList<>());
deposit.getMetadata().getRelatedIdentifiers().add(relator);
}
@ -217,7 +228,7 @@ public class ZenodoBuilderMapper {
List<ReferenceDepositModel> dmpLicenses = this.getReferenceDepositModelOfType(dmp, ReferenceType.Licenses);
if (dmpLicenses != null && !dmpLicenses.isEmpty()) {
for (ReferenceDepositModel dmpLicense : dmpLicenses) {
String pid = dmpLicense.getDefinition().getFields().stream().filter(x-> "pid".equalsIgnoreCase(x.getCode())).map(FieldDepositModel::getValue).findFirst().orElse(null);
String pid = dmpLicense.getDefinition().getFields().stream().filter(x-> PID.equalsIgnoreCase(x.getCode())).map(FieldDepositModel::getValue).findFirst().orElse(null);
if (pid != null && !pid.isBlank()) {
deposit.getMetadata().setLicense(pid);
break;
@ -235,9 +246,9 @@ public class ZenodoBuilderMapper {
for (ReferenceDepositModel researcher : dmpResearchers) {
ZenodoContributor contributor = new ZenodoContributor();
contributor.setName(researcher.getLabel());
contributor.setType("Researcher");
contributor.setType(CONTRIBUTOR_TYPE_RESEARCHER);
contributor.setAffiliation(researcher.getSource());
if (researcher.getSource().equalsIgnoreCase("ORCID")) {
if (researcher.getSource().equalsIgnoreCase(SOURCE_ORCID)) {
contributor.setOrcid(researcher.getReference());
}
researchers.add(contributor);
@ -256,14 +267,14 @@ public class ZenodoBuilderMapper {
if (dmpGrants != null && !dmpGrants.isEmpty()) {
ReferenceDepositModel depositGrant = dmpGrants.stream().filter(x-> x.getSource().equals("openaire")).findFirst().orElse(null);
ReferenceDepositModel depositGrant = dmpGrants.stream().filter(x-> x.getSource().equals(SOURCE_OPENAIRE)).findFirst().orElse(null);
if (depositGrant != null) {
String grantReferenceTail = depositGrant.getReference().split(":")[2];
List<FunderProperties.DOIFunder> doiFunders = this.funderProperties.getAvailable();
List<FunderProperties.DoiFunder> doiFunders = this.funderProperties.getAvailable();
if (dmpFunders != null && !dmpFunders.isEmpty()) {
ReferenceDepositModel depositFunder = dmpFunders.get(0);
FunderProperties.DOIFunder doiFunder = doiFunders.stream()
FunderProperties.DoiFunder doiFunder = doiFunders.stream()
.filter(doiFunder1 -> depositFunder.getLabel().contains(doiFunder1.getFunder()) || doiFunder1.getFunder().contains(depositFunder.getLabel()))
.findFirst().orElse(null);
if (doiFunder != null) {
@ -290,7 +301,7 @@ public class ZenodoBuilderMapper {
for (UserDmpDepositModel userDMP: dmp.getUsers()) {
ZenodoContributor contributor = new ZenodoContributor();
contributor.setName(userDMP.getUser().getName());
contributor.setType("ProjectMember");
contributor.setType(CONTRIBUTOR_TYPE_PROJECT_MANAGER);
if (dmpOrganizations != null && !dmpOrganizations.isEmpty()) {
contributor.setAffiliation(dmpOrganizations.stream().map(ReferenceDepositModel::getLabel).collect(Collectors.joining(", ")));
} else {

View File

@ -0,0 +1,10 @@
package eu.eudat.depositinterface.zenodorepository.service;
import gr.cite.tools.cache.CacheOptions;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "cache.logo-by-repository")
public class RepositoryLogoCacheOptions extends CacheOptions {
}

View File

@ -0,0 +1,65 @@
package eu.eudat.depositinterface.zenodorepository.service;
import gr.cite.tools.cache.CacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.HashMap;
@Service
public class RepositoryLogoCacheService extends CacheService<RepositoryLogoCacheService.RepositoryLogoCacheValue> {
public static class RepositoryLogoCacheValue {
public RepositoryLogoCacheValue() {
}
public RepositoryLogoCacheValue(String repositoryId, byte[] logo) {
this.repositoryId = repositoryId;
this.logo = logo;
}
private String repositoryId;
public String getRepositoryId() {
return repositoryId;
}
public void setRepositoryId(String repositoryId) {
this.repositoryId = repositoryId;
}
private byte[] logo;
public byte[] getLogo() {
return logo;
}
public void setLogo(byte[] logo) {
this.logo = logo;
}
}
@Autowired
public RepositoryLogoCacheService(RepositoryLogoCacheOptions options) {
super(options);
}
@Override
protected Class<RepositoryLogoCacheValue> valueClass() {
return RepositoryLogoCacheValue.class;
}
@Override
public String keyOf(RepositoryLogoCacheValue value) {
return this.buildKey(value.getRepositoryId());
}
public String buildKey(String repositoryId) {
HashMap<String, String> keyParts = new HashMap<>();
keyParts.put("$repo$", repositoryId);
return this.generateKey(keyParts);
}
}

View File

@ -0,0 +1,335 @@
package eu.eudat.depositinterface.zenodorepository.service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.depositinterface.models.DmpDepositModel;
import eu.eudat.depositinterface.models.FileEnvelope;
import eu.eudat.depositinterface.repository.RepositoryDeposit;
import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration;
import eu.eudat.depositinterface.zenodorepository.configuration.zenodo.ZenodoProperties;
import eu.eudat.depositinterface.zenodorepository.model.ZenodoDeposit;
import eu.eudat.depositinterface.zenodorepository.model.builder.ZenodoBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ResourceUtils;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;
@Component
public class ZenodoDepositService implements RepositoryDeposit {
private static final String PUBLISH_ID = "conceptdoi";
private static final String CLIENT_ID = "client_id";
private static final String CLIENT_SECRET = "client_secret";
private static final String GRANT_TYPE = "grant_type";
private static final String AUTHORIZATION_CODE = "authorization_code";
private static final String CODE = "code";
private static final String ZENODO_LINKS = "links";
private static final String REDIRECT_URI = "redirect_uri";
private static final String ACCESS_TOKEN = "access_token";
private static final String ZENODO_LINKS_BUCKET = "bucket";
private static final String ZENODO_LINKS_PUBLISH = "publish";
private static final String ZENODO_LINKS_SELF = "self";
private static final String ZENODO_LINKS_LATEST_DRAFT = "latest_draft";
private static final String ZENODO_METADATA = "metadata";
private static final String ZENODO_METADATA_VERSION = "version";
private static final Logger logger = LoggerFactory.getLogger(ZenodoDepositService.class);
private static final ObjectMapper objectMapper = new ObjectMapper();
private final ZenodoProperties zenodoProperties;
private final ZenodoBuilder mapper;
private final RepositoryLogoCacheService repositoryLogoCacheService;
@Autowired
public ZenodoDepositService(ZenodoProperties zenodoProperties, ZenodoBuilder mapper, RepositoryLogoCacheService repositoryLogoCacheService){
this.zenodoProperties = zenodoProperties;
this.mapper = mapper;
this.repositoryLogoCacheService = repositoryLogoCacheService;
}
@Override
public String deposit(String repositoryId, DmpDepositModel dmpDepositModel, String zenodoToken) throws Exception {
RepositoryDepositConfiguration repositoryDepositConfiguration = this.getConfiguration().stream().filter(x -> x.getRepositoryId().equals(repositoryId)).findFirst().orElse(null);
if(repositoryDepositConfiguration != null) {
if (zenodoToken == null || zenodoToken.isEmpty()) {
zenodoToken = repositoryDepositConfiguration.getAccessToken();
}
String zenodoUrl = repositoryDepositConfiguration.getRepositoryUrl();
// First step, post call to Zenodo, to create the entry.
WebClient zenodoClient = WebClient.builder().build();
ZenodoProperties.ZenodoConfig zenodoConfig = this.zenodoProperties.getConfiguration().stream().filter(x -> x.getRepositoryId().equals(repositoryId)).findFirst().orElse(null);
if (zenodoConfig == null) return null;
eu.eudat.depositinterface.zenodorepository.model.ZenodoDeposit deposit = mapper.build(dmpDepositModel, zenodoConfig);
LinkedHashMap<String, String> links;
String previousDOI = dmpDepositModel.getPreviousDOI();
String unpublishedUrl = null;
String publishUrl;
try {
if (previousDOI == null) {
links = deposit(zenodoToken, zenodoUrl, zenodoClient, deposit);
} else {
unpublishedUrl = this.getUnpublishedDOI(zenodoUrl, previousDOI, zenodoToken, dmpDepositModel.getVersion());
if (unpublishedUrl == null) {
//It requires more than one step to create a new version
//First, get the deposit related to the concept DOI
links = depositNewVersion(zenodoToken, zenodoUrl, previousDOI, zenodoClient, deposit);
} else {
links = depositFromPreviousDoi(zenodoToken, zenodoUrl, previousDOI, zenodoClient);
}
}
if (unpublishedUrl == null) {
// Second step, add the file to the entry.
FileEnvelope pdfEnvelope = dmpDepositModel.getPdfFile();
if (links == null || !links.containsKey(ZENODO_LINKS_BUCKET)) throw new Exception("bucket not found");
String addFileUrl = links.get(ZENODO_LINKS_BUCKET) + "/" + pdfEnvelope.getFilename() + "?access_token=" + zenodoToken;
zenodoClient.put().uri(addFileUrl)
.body(BodyInserters
.fromResource(new ByteArrayResource(pdfEnvelope.getFile())))
.retrieve().toEntity(Map.class).block();
FileEnvelope rdaJsonEnvelope = dmpDepositModel.getRdaJsonFile();
String jsonFileName = rdaJsonEnvelope.getFilename();
addFileUrl = links.get(ZENODO_LINKS_BUCKET) + "/" + jsonFileName + "?access_token=" + zenodoToken;
zenodoClient.put().uri(addFileUrl).headers(httpHeaders -> httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM)).body(BodyInserters.fromResource(new ByteArrayResource(rdaJsonEnvelope.getFile()))).retrieve().toEntity(Map.class).block();
if (dmpDepositModel.getSupportingFilesZip() != null) {
String supportingFilesZipName = dmpDepositModel.getSupportingFilesZip().getFilename();
addFileUrl = links.get(ZENODO_LINKS_BUCKET) + "/" + supportingFilesZipName + "?access_token=" + zenodoToken;
zenodoClient.put().uri(addFileUrl).body(BodyInserters.fromResource(new ByteArrayResource(supportingFilesZipName.getBytes()))).retrieve().toEntity(Map.class).block();
}
// Third post call to Zenodo to publish the entry and return the DOI.
publishUrl = links.get(ZENODO_LINKS_PUBLISH) + "?access_token=" + zenodoToken;
} else {
publishUrl = unpublishedUrl + "?access_token=" + zenodoToken;
}
return this.publish(publishUrl);
} catch (HttpClientErrorException | HttpServerErrorException ex) {
Map<String, String> parsedException = objectMapper.readValue(ex.getResponseBodyAsString(), Map.class);
throw new IOException(parsedException.get("message"), ex);
}
}
return null;
}
private static LinkedHashMap<String, String> depositNewVersion(String zenodoToken, String zenodoUrl, String previousDOI, WebClient zenodoClient, ZenodoDeposit deposit) throws Exception {
Map<String, LinkedHashMap<String, String>> createResponse;
LinkedHashMap<String, String> links;
String listUrl = zenodoUrl + "deposit/depositions" + "?q=conceptdoi:\"" + previousDOI + "\"&access_token=" + zenodoToken;
logger.debug("listUrl = " + listUrl);
ResponseEntity<List<Map>> listResponses = zenodoClient.get().uri(listUrl).retrieve().toEntityList(Map.class).block();
if (listResponses == null || listResponses.getBody() == null || listResponses.getBody().isEmpty()) return null;
createResponse = (Map<String, LinkedHashMap<String, String>>) listResponses.getBody().get(0);
logger.debug("createResponse-previousDoi:");
logger.debug(objectMapper.writeValueAsString(createResponse));
links = (LinkedHashMap<String, String>) createResponse.getOrDefault(ZENODO_LINKS, new LinkedHashMap<>());
//Second, make the new version (not in the links?)
if (!links.containsKey(ZENODO_LINKS_SELF)) throw new Exception("previousDOI not found");
String newVersionUrl = links.get(ZENODO_LINKS_SELF) + "/actions/newversion" + "?access_token=" + zenodoToken;
logger.debug("new version url: " + newVersionUrl);
createResponse = zenodoClient.post().uri(newVersionUrl)
.bodyValue(null).exchangeToMono(mono -> mono.bodyToMono(new ParameterizedTypeReference<Map<String, LinkedHashMap<String, String>>>() {})).block();
logger.debug("createResponse-newVersion:");
logger.debug(objectMapper.writeValueAsString(createResponse));
links = createResponse == null ? new LinkedHashMap<>() : createResponse.getOrDefault(ZENODO_LINKS, new LinkedHashMap<>());
//Third, get the new deposit
if (!links.containsKey(ZENODO_LINKS_LATEST_DRAFT)) throw new Exception("can not create latest draft");
String latestDraftUrl = links.get(ZENODO_LINKS_LATEST_DRAFT) + "?access_token=" + zenodoToken;
createResponse = zenodoClient.get().uri(latestDraftUrl)
.exchangeToMono(mono -> mono.bodyToMono(new ParameterizedTypeReference<Map<String, LinkedHashMap<String, String>>>() {})).block();
logger.debug("createResponse-latestDraft:");
logger.debug(objectMapper.writeValueAsString(createResponse));
links = createResponse == null ? new LinkedHashMap<>() : createResponse.getOrDefault(ZENODO_LINKS, new LinkedHashMap<>());
//At this point it might fail to perform the next requests so enclose them with try catch
try {
//Forth, update the new deposit's metadata
String updateUrl = links.get(ZENODO_LINKS_SELF) + "?access_token=" + zenodoToken;
zenodoClient.put().uri(updateUrl)
.headers(httpHeaders -> {
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
})
.bodyValue(deposit).retrieve().toEntity(Map.class).block();
//And finally remove pre-existing files from it
String fileListUrl = links.get(ZENODO_LINKS_SELF) + "/files" + "?access_token=" + zenodoToken;
ResponseEntity<List<Map>> fileListResponse = zenodoClient.get().uri(fileListUrl).retrieve().toEntityList(Map.class).block();
for (Map file : fileListResponse.getBody()) {
String fileDeleteUrl = links.get(ZENODO_LINKS_SELF) + "/files/" + file.get("id") + "?access_token=" + zenodoToken;
zenodoClient.delete().uri(fileDeleteUrl).retrieve().toEntity(Map.class).block();
}
} catch (Exception e) {
//In case the last two steps fail delete the latest Deposit it in order to create a new one (only one at a time is allowed)
//restTemplate.delete(latestDraftUrl);
zenodoClient.delete().uri(latestDraftUrl).retrieve().toEntity(Map.class).block();
throw e;
}
return links;
}
private static LinkedHashMap<String, String> depositFromPreviousDoi(String zenodoToken, String zenodoUrl, String previousDOI, WebClient zenodoClient) {
Map<String, LinkedHashMap<String, String>> createResponse;
String listUrl = zenodoUrl + "deposit/depositions" + "?q=conceptdoi:\"" + previousDOI + "\"&access_token=" + zenodoToken;
ResponseEntity<List<Map>> listResponses = zenodoClient.get().uri(listUrl).retrieve().toEntityList(Map.class).block();
if (listResponses == null || listResponses.getBody() == null || listResponses.getBody().isEmpty()) return null;
createResponse = (Map<String, LinkedHashMap<String, String>>) listResponses.getBody().get(0);
return createResponse.getOrDefault(ZENODO_LINKS, null);
}
private LinkedHashMap<String, String> deposit(String zenodoToken, String zenodoUrl, WebClient zenodoClient, ZenodoDeposit deposit) {
Map<String, Object> createResponse;
String createUrl = zenodoUrl + "deposit/depositions" + "?access_token=" + zenodoToken;
createResponse = zenodoClient.post().uri(createUrl).headers(httpHeaders -> {
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
})
.bodyValue(deposit).exchangeToMono(mono -> mono.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {})).block();
return (LinkedHashMap<String, String>) createResponse.getOrDefault(ZENODO_LINKS, null);
}
private String publish(String publishUrl){
WebClient webClient = WebClient.builder().build();
Map<String, Object> publishResponse = webClient.post().uri(publishUrl).bodyValue("").exchangeToMono(mono -> {
if (!mono.statusCode().is2xxSuccessful()) {
mono.createException();
throw new UnsupportedOperationException("Failed to publish to Zenodo");
}
return mono.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {
});
}).block();
if (publishResponse == null) throw new UnsupportedOperationException("Failed to publish to Zenodo");
return (String) publishResponse.get(PUBLISH_ID);
}
@Override
public List<RepositoryDepositConfiguration> getConfiguration() {
List<ZenodoProperties.ZenodoConfig> zenodoConfigs = this.zenodoProperties.getConfiguration();
return (zenodoConfigs != null) ? zenodoConfigs.stream().map(ZenodoProperties.ZenodoConfig::toRepoConfig).collect(Collectors.toList()) : null;
}
@Override
public String authenticate(String repositoryId, String code){
RepositoryDepositConfiguration repositoryDepositConfiguration = this.getConfiguration().stream().filter(x -> x.getRepositoryId().equals(repositoryId)).findFirst().orElse(null);
if(repositoryDepositConfiguration != null) {
WebClient client = WebClient.builder().defaultHeaders(httpHeaders -> {
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
}).build();
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add(CLIENT_ID, repositoryDepositConfiguration.getRepositoryClientId());
map.add(CLIENT_SECRET, repositoryDepositConfiguration.getRepositoryClientSecret());
map.add(GRANT_TYPE, AUTHORIZATION_CODE);
map.add(CODE, code);
map.add(REDIRECT_URI, repositoryDepositConfiguration.getRedirectUri());
try {
Map<String, Object> values = client.post().uri(repositoryDepositConfiguration.getRepositoryAccessTokenUrl()).bodyValue(map).exchangeToMono(mono -> {
if (!mono.statusCode().is2xxSuccessful()) {
mono.createException();
throw new HttpClientErrorException(mono.statusCode());
}
return mono.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {
});
}).block();
return values != null ? (String) values.getOrDefault(ACCESS_TOKEN, null) : null;
} catch (HttpClientErrorException ex) {
logger.error(ex.getResponseBodyAsString(), ex);
return null;
}
}
return null;
}
@Override
public String getLogo(String repositoryId) {
ZenodoProperties.ZenodoConfig zenodoConfig = this.zenodoProperties.getConfiguration().stream().filter(x -> x.getRepositoryId().equals(repositoryId)).findFirst().orElse(null);
if(zenodoConfig != null && zenodoConfig.isHasLogo() && zenodoConfig.getLogo() != null && !zenodoConfig.getLogo().isBlank()) {
RepositoryLogoCacheService.RepositoryLogoCacheValue cacheValue = this.repositoryLogoCacheService.lookup(this.repositoryLogoCacheService.buildKey(repositoryId));
byte[] logo = null;
if (cacheValue != null) {
logo = cacheValue.getLogo();
} else {
try {
java.io.File logoFile = ResourceUtils.getFile(zenodoConfig.getLogo());
if (!logoFile.exists()) return null;
try(InputStream inputStream = new FileInputStream(logoFile)){
logo = inputStream.readAllBytes();
};
} catch (IOException e) {
throw new RuntimeException(e);
}
this.repositoryLogoCacheService.put(new RepositoryLogoCacheService.RepositoryLogoCacheValue(repositoryId, logo));
}
return (logo != null && logo.length != 0) ? Base64.getEncoder().encodeToString(logo) : null;
}
return null;
}
private String getUnpublishedDOI(String zenodoUrl, String doi, String token, Short version) {
try {
WebClient client = WebClient.builder().build();
Map<String, LinkedHashMap<String, String>> createResponse = null;
LinkedHashMap<String, String> links;
LinkedHashMap<String, String> metadata;
String listUrl = zenodoUrl + "deposit/depositions" + "?q=conceptdoi:\"" + doi + "\"&access_token=" + token;
ResponseEntity<List<Map>> listResponses = client.get().uri(listUrl).retrieve().toEntityList(Map.class).block();
if (listResponses == null || listResponses.getBody() == null || listResponses.getBody().isEmpty()) return null;
createResponse = (Map<String, LinkedHashMap<String, String>>) listResponses.getBody().get(0);
metadata = createResponse.getOrDefault(ZENODO_METADATA, new LinkedHashMap<>());
links = createResponse.getOrDefault(ZENODO_LINKS, new LinkedHashMap<>());
if (metadata.get(ZENODO_METADATA_VERSION).equals(version.toString())) {
return links.get(ZENODO_LINKS_PUBLISH);
} else {
return null;
}
}catch (Exception e) {
logger.warn(e.getMessage(), e);
return null;
}
}
}

View File

@ -1,275 +0,0 @@
package eu.eudat.depositinterface.zenodorepository.service.zenodo;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.depositinterface.models.DmpDepositModel;
import eu.eudat.depositinterface.models.FileEnvelope;
import eu.eudat.depositinterface.repository.RepositoryDeposit;
import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration;
import eu.eudat.depositinterface.zenodorepository.configuration.zenodo.ZenodoProperties;
import eu.eudat.depositinterface.zenodorepository.mapper.ZenodoBuilderMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ResourceUtils;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;
@Component
public class ZenodoDepositService implements RepositoryDeposit {
private static final Logger logger = LoggerFactory.getLogger(ZenodoDepositService.class);
private static final ObjectMapper objectMapper = new ObjectMapper();
private final ZenodoProperties zenodoProperties;
private final ZenodoBuilderMapper mapper;
@Autowired
public ZenodoDepositService(ZenodoProperties zenodoProperties, ZenodoBuilderMapper mapper){
this.zenodoProperties = zenodoProperties;
this.mapper = mapper;
}
@Override
public String deposit(String repositoryId, DmpDepositModel dmpDepositModel, String zenodoToken) throws Exception {
RepositoryDepositConfiguration repositoryDepositConfiguration = this.getConfiguration().stream().filter(x -> x.getRepositoryId().equals(repositoryId)).findFirst().orElse(null);
if(repositoryDepositConfiguration != null) {
if (zenodoToken == null || zenodoToken.isEmpty()) {
zenodoToken = repositoryDepositConfiguration.getAccessToken();
}
String zenodoUrl = repositoryDepositConfiguration.getRepositoryUrl();
// First step, post call to Zenodo, to create the entry.
WebClient zenodoClient = WebClient.builder().build();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_JSON);
ZenodoProperties.ZenodoConfig zenodoConfig = this.zenodoProperties.getConfiguration().stream().filter(x -> x.getRepositoryId().equals(repositoryId)).findFirst().orElse(null);
eu.eudat.depositinterface.zenodorepository.model.ZenodoDeposit deposit = mapper.build(dmpDepositModel, zenodoConfig);
Map createResponse;
LinkedHashMap<String, String> links;
String previousDOI = dmpDepositModel.getPreviousDOI();
String unpublishedUrl = null;
String publishUrl;
try {
if (previousDOI == null) {
String createUrl = zenodoUrl + "deposit/depositions" + "?access_token=" + zenodoToken;
createResponse = zenodoClient.post().uri(createUrl).headers(httpHeaders -> {
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
})
.bodyValue(deposit).exchangeToMono(mono -> mono.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {})).block();
links = (LinkedHashMap<String, String>) createResponse.get("links");
} else {
unpublishedUrl = this.getUnpublishedDOI(zenodoUrl, previousDOI, zenodoToken, dmpDepositModel.getVersion());
if (unpublishedUrl == null) {
//It requires more than one step to create a new version
//First, get the deposit related to the concept DOI
String listUrl = zenodoUrl + "deposit/depositions" + "?q=conceptdoi:\"" + previousDOI + "\"&access_token=" + zenodoToken;
logger.debug("listUrl = " + listUrl);
ResponseEntity<List<Map>> listResponses = zenodoClient.get().uri(listUrl).retrieve().toEntityList(Map.class).block();
createResponse = listResponses.getBody().get(0);
logger.debug("createResponse-previousDoi:");
logger.debug(objectMapper.writeValueAsString(createResponse));
links = (LinkedHashMap<String, String>) createResponse.get("links");
//Second, make the new version (not in the links?)
String newVersionUrl = links.get("self") + "/actions/newversion" + "?access_token=" + zenodoToken;
logger.debug("new version url: " + newVersionUrl);
createResponse = zenodoClient.post().uri(newVersionUrl)
.bodyValue(null).exchangeToMono(mono -> mono.bodyToMono(Map.class)).block();
logger.debug("createResponse-newVersion:");
logger.debug(objectMapper.writeValueAsString(createResponse));
links = (LinkedHashMap<String, String>) createResponse.get("links");
//Third, get the new deposit
String latestDraftUrl = links.get("latest_draft") + "?access_token=" + zenodoToken;
createResponse = zenodoClient.get().uri(latestDraftUrl)
.exchangeToMono(mono -> mono.bodyToMono(Map.class)).block();
logger.debug("createResponse-latestDraft:");
logger.debug(objectMapper.writeValueAsString(createResponse));
links = (LinkedHashMap<String, String>) createResponse.get("links");
//At this point it might fail to perform the next requests so enclose them with try catch
try {
//Forth, update the new deposit's metadata
String updateUrl = links.get("self") + "?access_token=" + zenodoToken;
zenodoClient.put().uri(updateUrl)
.headers(httpHeaders -> {
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
})
.bodyValue(deposit).retrieve().toEntity(Map.class).block();
//And finally remove pre-existing files from it
String fileListUrl = links.get("self") + "/files" + "?access_token=" + zenodoToken;
ResponseEntity<List<Map>> fileListResponse = zenodoClient.get().uri(fileListUrl).retrieve().toEntityList(Map.class).block();
for (Map file : fileListResponse.getBody()) {
String fileDeleteUrl = links.get("self") + "/files/" + file.get("id") + "?access_token=" + zenodoToken;
zenodoClient.delete().uri(fileDeleteUrl).retrieve().toEntity(Map.class).block();
}
} catch (Exception e) {
//In case the last two steps fail delete the latest Deposit it in order to create a new one (only one at a time is allowed)
//restTemplate.delete(latestDraftUrl);
zenodoClient.delete().uri(latestDraftUrl).retrieve().toEntity(Map.class).block();
throw e;
}
} else {
String listUrl = zenodoUrl + "deposit/depositions" + "?q=conceptdoi:\"" + previousDOI + "\"&access_token=" + zenodoToken;
ResponseEntity<List<Map>> listResponses = zenodoClient.get().uri(listUrl).retrieve().toEntityList(Map.class).block();//restTemplate.getForEntity(listUrl, Map[].class);
createResponse = listResponses.getBody().get(0);
links = (LinkedHashMap<String, String>) createResponse.get("links");
}
}
if (unpublishedUrl == null) {
// Second step, add the file to the entry.
FileEnvelope pdfEnvelope = dmpDepositModel.getPdfFile();
String addFileUrl = links.get("bucket") + "/" + pdfEnvelope.getFilename() + "?access_token=" + zenodoToken;
zenodoClient.put().uri(addFileUrl)
.body(BodyInserters
.fromResource(new ByteArrayResource(pdfEnvelope.getFile())))
.retrieve().toEntity(Map.class).block();
FileEnvelope rdaJsonEnvelope = dmpDepositModel.getRdaJsonFile();
String jsonFileName = rdaJsonEnvelope.getFilename();
addFileUrl = links.get("bucket") + "/" + jsonFileName + "?access_token=" + zenodoToken;
zenodoClient.put().uri(addFileUrl).headers(httpHeaders -> httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM)).body(BodyInserters.fromResource(new ByteArrayResource(rdaJsonEnvelope.getFile()))).retrieve().toEntity(Map.class).block();
if (dmpDepositModel.getSupportingFilesZip() != null) {
String supportinFilesZipName = dmpDepositModel.getSupportingFilesZip().getFilename();
addFileUrl = links.get("bucket") + "/" + supportinFilesZipName + "?access_token=" + zenodoToken;
zenodoClient.put().uri(addFileUrl).body(BodyInserters.fromResource(new ByteArrayResource(supportinFilesZipName.getBytes()))).retrieve().toEntity(Map.class).block();
}
// Third post call to Zenodo to publish the entry and return the DOI.
publishUrl = links.get("publish") + "?access_token=" + zenodoToken;
} else {
publishUrl = unpublishedUrl + "?access_token=" + zenodoToken;
}
return this.publish(publishUrl);
} catch (HttpClientErrorException | HttpServerErrorException ex) {
Map<String, String> parsedException = objectMapper.readValue(ex.getResponseBodyAsString(), HashMap.class);
throw new IOException(parsedException.get("message"), ex);
}
}
return null;
}
private String publish(String publishUrl){
WebClient webClient = WebClient.builder().build();
Map<String, Object> publishResponce = webClient.post().uri(publishUrl).bodyValue("").exchangeToMono(mono -> {
if (!mono.statusCode().is2xxSuccessful()) {
mono.createException();
throw new UnsupportedOperationException("Failed to publish to Zenodo");
}
return mono.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {
});
}).block();
return (String) publishResponce.get("conceptdoi");
}
@Override
public List<RepositoryDepositConfiguration> getConfiguration() {
List<ZenodoProperties.ZenodoConfig> zenodoConfigs = this.zenodoProperties.getConfiguration();
return (zenodoConfigs != null) ? zenodoConfigs.stream().map(ZenodoProperties.ZenodoConfig::toRepoConfig).collect(Collectors.toList()) : null;
}
@Override
public String authenticate(String repositoryId, String code){
RepositoryDepositConfiguration repositoryDepositConfiguration = this.getConfiguration().stream().filter(x -> x.getRepositoryId().equals(repositoryId)).findFirst().orElse(null);
if(repositoryDepositConfiguration != null) {
WebClient client = WebClient.builder().defaultHeaders(httpHeaders -> {
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
}).build();
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("client_id", repositoryDepositConfiguration.getRepositoryClientId());
map.add("client_secret", repositoryDepositConfiguration.getRepositoryClientSecret());
map.add("grant_type", "authorization_code");
map.add("code", code);
map.add("redirect_uri", repositoryDepositConfiguration.getRedirectUri());
try {
Map<String, Object> values = client.post().uri(repositoryDepositConfiguration.getRepositoryAccessTokenUrl()).bodyValue(map).retrieve().bodyToMono(Map.class).block();
return values != null ? (String) values.get("access_token") : null;
} catch (HttpClientErrorException ex) {
logger.error(ex.getResponseBodyAsString(), ex);
}
return null;
}
return null;
}
@Override
public String getLogo(String repositoryId) {
ZenodoProperties.ZenodoConfig conf = this.zenodoProperties.getConfiguration().stream().filter(x -> x.getRepositoryId().equals(repositoryId)).findFirst().orElse(null);
if(conf != null) {
if(conf.isHasLogo()){
byte[] logo;
try {
java.io.File logoFile = ResourceUtils.getFile(conf.getLogo());
if (!logoFile.exists()) return null;
try(InputStream inputStream = new FileInputStream(logoFile)){
logo = inputStream.readAllBytes();
};
} catch (IOException e) {
throw new RuntimeException(e);
}
return (logo != null && logo.length != 0) ? Base64.getEncoder().encodeToString(logo) : null;
}
}
return null;
}
private String getUnpublishedDOI(String zenodoUrl, String doi, String token, Short version) {
try {
WebClient client = WebClient.builder().build();
Map createResponse = null;
LinkedHashMap<String, String> links;
LinkedHashMap<String, String> metadata;
String listUrl = zenodoUrl + "deposit/depositions" + "?q=conceptdoi:\"" + doi + "\"&access_token=" + token;
ResponseEntity<List<Map>> listResponses = client.get().uri(listUrl).retrieve().toEntityList(Map.class).block();
createResponse = listResponses.getBody().get(0);
metadata = (LinkedHashMap<String, String>) createResponse.get("metadata");
links = (LinkedHashMap<String, String>) createResponse.get("links");
if (metadata.get("version").equals(version.toString())) {
return links.get("publish");
} else {
return null;
}
}catch (Exception e) {
logger.warn(e.getMessage(), e);
return null;
}
}
}

View File

@ -12,6 +12,9 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtDecoders;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter;
@ -21,13 +24,11 @@ import java.util.Set;
@EnableWebSecurity
public class SecurityConfiguration {
private final ApiKeyFilter apiKeyFilter;
private final WebSecurityProperties webSecurityProperties;
private final AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver;
@Autowired
public SecurityConfiguration(ApiKeyFilter apiKeyFilter, WebSecurityProperties webSecurityProperties, AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver) {
this.apiKeyFilter = apiKeyFilter;
public SecurityConfiguration(WebSecurityProperties webSecurityProperties, AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver) {
this.webSecurityProperties = webSecurityProperties;
this.authenticationManagerResolver = authenticationManagerResolver;
}
@ -36,7 +37,6 @@ public class SecurityConfiguration {
protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(AbstractHttpConfigurer::disable)
.cors(Customizer.withDefaults())
.addFilterBefore(apiKeyFilter, AbstractPreAuthenticatedProcessingFilter.class)
.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> authorizationManagerRequestMatcherRegistry
.requestMatchers(buildAntPatterns(webSecurityProperties.getAuthorizedEndpoints())).authenticated()
.requestMatchers(buildAntPatterns(webSecurityProperties.getAllowedEndpoints())).anonymous())

View File

@ -2,7 +2,7 @@ cache:
manager:
fallbackToNoOpCache: true
caffeineCaches:
- names: [ "apikey" ]
- names: [ "logoByRepository" ]
allowNullValues: true
initialCapacity: 100
maximumSize: 500
@ -11,6 +11,8 @@ cache:
expireAfterAccessMinutes: 10
refreshAfterWriteMinutes: 10
mapCaches:
apiKey:
name: apikey
keyPattern: resolve_$keyhash$:v0
logoByRepository:
name: logoByRepository
keyPattern: zenodoplugin_$repo$:v0

View File

@ -0,0 +1,7 @@
web:
security:
idp:
resource:
jwt:
audiences: [ "dmp_zenodo_bridge" ]
validIssuer: ${IDP_ISSUER_URI:}

View File

@ -5,16 +5,9 @@ web:
allowed-endpoints: [ health ]
idp:
api-key:
enabled: true
authorization-header: Authorization
client-id: ${IDP_APIKEY_CLIENT_ID:}
client-secret: ${IDP_APIKEY_CLIENT_SECRET:}
scope: ${IDP_APIKEY_SCOPE:}
enabled: false
resource:
token-type: JWT #| opaque
opaque:
client-id: ${IDP_OPAQUE_CLIENT_ID:}
client-secret: ${IDP_OPAQUE_CLIENT_SECRET:}
jwt:
claims: [ role, x-role ]
issuer-uri: ${IDP_ISSUER_URI:}