Compare commits
76 Commits
master
...
plan-workf
|
@ -1,2 +1,4 @@
|
||||||
.idea/
|
.idea/
|
||||||
target/
|
target/
|
||||||
|
logs/
|
||||||
|
web/src/main/resources/config/app.env
|
||||||
|
|
41
Dockerfile
41
Dockerfile
|
@ -1,18 +1,33 @@
|
||||||
####################################### Build stage #######################################
|
####################################### Build stage #######################################
|
||||||
FROM maven:3.6.3-openjdk-11-slim AS build-stage
|
FROM maven:3.9-eclipse-temurin-21-alpine AS build-stage
|
||||||
|
|
||||||
|
ARG MAVEN_ACCOUNT_USR
|
||||||
|
ARG MAVEN_ACCOUNT_PSW
|
||||||
|
ARG REVISION
|
||||||
|
ARG PROFILE
|
||||||
|
ENV server_username=$MAVEN_ACCOUNT_USR
|
||||||
|
ENV server_password=$MAVEN_ACCOUNT_PSW
|
||||||
|
ARG CITE_MAVEN_REPO_URL
|
||||||
|
|
||||||
|
COPY pom.xml /build/
|
||||||
|
COPY core /build/core/
|
||||||
|
COPY web /build/web/
|
||||||
|
COPY settings.xml /root/.m2/settings.xml
|
||||||
|
RUN rm -f /build/web/src/main/resources/config/app.env
|
||||||
|
RUN rm -f /build/web/src/main/resources/config/*-dev.yml
|
||||||
|
# RUN rm -f /build/web/src/main/resources/logging/*.xml
|
||||||
|
|
||||||
COPY . /build/
|
|
||||||
WORKDIR /build/
|
WORKDIR /build/
|
||||||
RUN mvn clean package -DskipTests
|
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} dependency:go-offline
|
||||||
|
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} clean package
|
||||||
|
######################################## Run Stage ########################################
|
||||||
|
FROM eclipse-temurin:21-jre-alpine
|
||||||
|
|
||||||
ARG CREPO_BINARIES_REPO_URL
|
ARG PROFILE
|
||||||
ARG CREPO_BINARIES_CREDENTIAL
|
ARG REVISION
|
||||||
ARG BUILD_VERSION
|
ENV SERVER_PORT=8080
|
||||||
ENV CREPO_BINARIES_REPO_URL=$CREPO_BINARIES_REPO_URL
|
EXPOSE ${SERVER_PORT}
|
||||||
ENV CREPO_BINARIES_CREDENTIAL=$CREPO_BINARIES_CREDENTIAL
|
|
||||||
ENV BUILD_VERSION=$BUILD_VERSION
|
|
||||||
|
|
||||||
RUN curl --location --request PUT "${CREPO_BINARIES_REPO_URL}opendmp/repository-jars/zenodo/zenodo-deposit-${BUILD_VERSION}.jar" \
|
COPY --from=build-stage /build/web/target/repository-deposit-web-${REVISION}.jar /app/repository-deposit-web.jar
|
||||||
--header "Authorization: Basic ${CREPO_BINARIES_CREDENTIAL}" \
|
|
||||||
--header "Content-Type: application/json" \
|
ENTRYPOINT ["java","-Dspring.config.additional-location=file:/config/","-Dspring.profiles.active=${PROFILE}","-Djava.security.egd=file:/dev/./urandom","-jar","/app/repository-deposit-web.jar"]
|
||||||
--data-binary "@/build/target/repositorydepositzenodo-1.0.0-SNAPSHOT.jar"
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
####################################### Build stage #######################################
|
||||||
|
FROM maven:3.9-eclipse-temurin-21-alpine
|
||||||
|
|
||||||
|
ARG MAVEN_ACCOUNT_USR
|
||||||
|
ARG MAVEN_ACCOUNT_PSW
|
||||||
|
ARG REVISION
|
||||||
|
ARG PROFILE
|
||||||
|
ARG ORACLE_URL
|
||||||
|
ARG ORACLE_TOKEN
|
||||||
|
ENV server_username=$MAVEN_ACCOUNT_USR
|
||||||
|
ENV server_password=$MAVEN_ACCOUNT_PSW
|
||||||
|
ARG CITE_MAVEN_REPO_URL
|
||||||
|
|
||||||
|
COPY pom.xml /build/
|
||||||
|
COPY core /build/core/
|
||||||
|
COPY web /build/web/
|
||||||
|
COPY settings.xml /root/.m2/settings.xml
|
||||||
|
RUN rm -f /build/web/src/main/resources/config/*-dev.yml
|
||||||
|
RUN rm -f /build/web/src/main/resources/logging/*.xml
|
||||||
|
|
||||||
|
COPY oracle.local.cite.gr.crt $JAVA_HOME/conf/security
|
||||||
|
RUN cd "$JAVA_HOME"/conf/security && keytool -cacerts -storepass changeit -noprompt -trustcacerts -importcert -alias oraclecert -file oracle.local.cite.gr.crt
|
||||||
|
|
||||||
|
WORKDIR /build/
|
||||||
|
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} dependency:go-offline
|
||||||
|
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} clean package
|
||||||
|
RUN mvn sonar:sonar -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} -Dsonar.projectKey=OpenDMP:repository-deposit-zenodo -Dsonar.login=${ORACLE_TOKEN} -Dsonar.host.url=${ORACLE_URL} -Dsonar.projectName='OpenDMP repository-deposit-zenodo'
|
|
@ -11,15 +11,15 @@ After creating the jar from the project, environment variables should be set sin
|
||||||
### JSON configuration file
|
### JSON configuration file
|
||||||
|
|
||||||
The following fields should be set:<br>
|
The following fields should be set:<br>
|
||||||
**depositType** - an integer representing how the dmp user can deposit in the repository,<br>
|
**depositType** - an integer representing how the plan user can deposit in the repository,<br>
|
||||||
a. **0** stands for system deposition meaning the dmp is deposited using argos credentials to the repository,<br>
|
a. **0** stands for system deposition meaning the plan is deposited using argos credentials to the repository,<br>
|
||||||
b. **1** stands for user deposition in which the argos user specifies his/her own credentials to the repository,<br>
|
b. **1** stands for user deposition in which the argos user specifies his/her own credentials to the repository,<br>
|
||||||
c. **2** stands for both ways deposition if the repository allows the deposits of dmps to be made from both argos and users accounts<br>
|
c. **2** stands for both ways deposition if the repository allows the deposits of plans to be made from both argos and users accounts<br>
|
||||||
**repositoryId** - unique identifier for the repository<br>
|
**repositoryId** - unique identifier for the repository<br>
|
||||||
**accessToken** - access token provided for the system type deposits<br>
|
**accessToken** - access token provided for the system type deposits<br>
|
||||||
**repositoryUrl** - repository's api url e.g "https://sandbox.zenodo.org/api/" <br>
|
**repositoryUrl** - repository's api url e.g "https://sandbox.zenodo.org/api/" <br>
|
||||||
**repositoryAuthorizationUrl** - repository's authorization url e.g. "https://sandbox.zenodo.org/oauth/authorize" <br>
|
**repositoryAuthorizationUrl** - repository's authorization url e.g. "https://sandbox.zenodo.org/oauth/authorize" <br>
|
||||||
**repositoryRecordUrl** - repository's record url, this url is used to index dmps that are created e.g. "https://sandbox.zenodo.org/record/" <br>
|
**repositoryRecordUrl** - repository's record url, this url is used to index plans that are created e.g. "https://sandbox.zenodo.org/record/" <br>
|
||||||
**repositoryAccessTokenUrl** - repository's access token url e.g. "https://sandbox.zenodo.org/oauth/token" <br>
|
**repositoryAccessTokenUrl** - repository's access token url e.g. "https://sandbox.zenodo.org/oauth/token" <br>
|
||||||
**repositoryClientId** - repository's client id<br>
|
**repositoryClientId** - repository's client id<br>
|
||||||
**repositoryClientSecret** - repository's client secret<br>
|
**repositoryClientSecret** - repository's client secret<br>
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.opencdmp</groupId>
|
||||||
|
<artifactId>repository-deposit-parent</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>repositorydepositzenodo</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>OpenCDMP Repository Deposit Zenodo</name>
|
||||||
|
<description>OpenCDMP Repository Deposit Zenodo</description>
|
||||||
|
<url>https://code-repo.d4science.org/MaDgiK-CITE/repository-deposit-zenodo</url>
|
||||||
|
<licenses>
|
||||||
|
<license>
|
||||||
|
<name>MIT License</name>
|
||||||
|
<url>https://code-repo.d4science.org/MaDgiK-CITE/repository-deposit-zenodo/src/branch/master/LICENSE.txt</url>
|
||||||
|
<distribution>repo</distribution>
|
||||||
|
</license>
|
||||||
|
</licenses>
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<name>CITE S.A.</name>
|
||||||
|
<email>maven-central@cite.gr</email>
|
||||||
|
<organization>CITE S.A.</organization>
|
||||||
|
<organizationUrl>https://www.cite.gr</organizationUrl>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
<scm>
|
||||||
|
<connection>scm:git:git://code-repo.d4science.org</connection>
|
||||||
|
<developerConnection>scm:git:ssh://code-repo.d4science.org</developerConnection>
|
||||||
|
<url>https://code-repo.d4science.org/MaDgiK-CITE/repository-deposit-zenodo</url>
|
||||||
|
</scm>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<revision>1.0.0-SNAPSHOT</revision>
|
||||||
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
|
<maven.compiler.target>21</maven.compiler.target>
|
||||||
|
<maven.compiler.release>21</maven.compiler.release>
|
||||||
|
<java.version>21</java.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.json</groupId>
|
||||||
|
<artifactId>json</artifactId>
|
||||||
|
<version>20240303</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>21</source>
|
||||||
|
<target>21</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>single</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
<configuration>
|
||||||
|
<archive>
|
||||||
|
<manifest>
|
||||||
|
<mainClass>org.opencdmp.deposit.DepositApplication</mainClass>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
<descriptorRefs>
|
||||||
|
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||||
|
</descriptorRefs>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<!-- <plugin>-->
|
||||||
|
<!-- <groupId>org.apache.maven.plugins</groupId>-->
|
||||||
|
<!-- <artifactId>maven-shade-plugin</artifactId>-->
|
||||||
|
<!-- <version>3.4.1</version>-->
|
||||||
|
<!-- <executions>-->
|
||||||
|
<!-- <execution>-->
|
||||||
|
<!-- <phase>package</phase>-->
|
||||||
|
<!-- <goals>-->
|
||||||
|
<!-- <goal>shade</goal>-->
|
||||||
|
<!-- </goals>-->
|
||||||
|
<!-- <configuration>-->
|
||||||
|
<!-- <filters>-->
|
||||||
|
<!-- <filter>-->
|
||||||
|
<!-- <artifact>*:*</artifact>-->
|
||||||
|
<!-- <excludes>-->
|
||||||
|
<!-- <exclude>module-info.class</exclude>-->
|
||||||
|
<!-- </excludes>-->
|
||||||
|
<!-- </filter>-->
|
||||||
|
<!-- </filters>-->
|
||||||
|
<!-- <relocations>-->
|
||||||
|
<!-- <relocation>-->
|
||||||
|
<!-- <pattern>org.json</pattern>-->
|
||||||
|
<!-- <shadedPattern>zenodorepository.shaded.org.json</shadedPattern>-->
|
||||||
|
<!-- </relocation>-->
|
||||||
|
<!-- </relocations>-->
|
||||||
|
<!-- </configuration>-->
|
||||||
|
<!-- </execution>-->
|
||||||
|
<!-- </executions>-->
|
||||||
|
<!-- </plugin>-->
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
|
@ -0,0 +1,14 @@
|
||||||
|
package org.opencdmp.deposit.zenodorepository.audit;
|
||||||
|
|
||||||
|
|
||||||
|
import gr.cite.tools.logging.EventId;
|
||||||
|
|
||||||
|
public class AuditableAction {
|
||||||
|
|
||||||
|
public static final EventId Deposit_Deposit = new EventId(1000, "Deposit_Deposit");
|
||||||
|
public static final EventId Deposit_Authenticate = new EventId(1001, "Deposit_Authenticate");
|
||||||
|
public static final EventId Deposit_GetConfiguration = new EventId(1002, "Deposit_GetConfiguration");
|
||||||
|
public static final EventId Deposit_GetLogo = new EventId(1003, "Deposit_GetLogo");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package org.opencdmp.deposit.zenodorepository.configuration;
|
||||||
|
|
||||||
|
import org.opencdmp.deposit.zenodorepository.configuration.funder.FunderProperties;
|
||||||
|
import org.opencdmp.deposit.zenodorepository.configuration.identifier.IdentifierProperties;
|
||||||
|
import org.opencdmp.deposit.zenodorepository.configuration.pid.PidProperties;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableConfigurationProperties({PidProperties.class, FunderProperties.class, IdentifierProperties.class})
|
||||||
|
public class GenericConfiguration {
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package org.opencdmp.deposit.zenodorepository.configuration.funder;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ConfigurationProperties(prefix = "funder")
|
||||||
|
public class FunderProperties {
|
||||||
|
|
||||||
|
private List<DoiFunder> available;
|
||||||
|
|
||||||
|
public List<DoiFunder> getAvailable() {
|
||||||
|
return available;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAvailable(List<DoiFunder> available) {
|
||||||
|
this.available = available;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DoiFunder {
|
||||||
|
private String funder;
|
||||||
|
private String doi;
|
||||||
|
|
||||||
|
public String getFunder() {
|
||||||
|
return funder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDoi() {
|
||||||
|
return doi;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFunder(String funder) {
|
||||||
|
this.funder = funder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDoi(String doi) {
|
||||||
|
this.doi = doi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package org.opencdmp.deposit.zenodorepository.configuration.identifier;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ConfigurationProperties(prefix = "identifiers")
|
||||||
|
public class IdentifierProperties {
|
||||||
|
private List<String> related;
|
||||||
|
|
||||||
|
public List<String> getRelated() {
|
||||||
|
return related;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRelated(List<String> related) {
|
||||||
|
this.related = related;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package org.opencdmp.deposit.zenodorepository.configuration.pid;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ConfigurationProperties(prefix = "pid")
|
||||||
|
public class PidProperties {
|
||||||
|
|
||||||
|
private List<String> acceptedTypes;
|
||||||
|
private PidFieldNames fields;
|
||||||
|
|
||||||
|
public List<String> getAcceptedTypes() {
|
||||||
|
return acceptedTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PidFieldNames getFields() {
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAcceptedTypes(List<String> acceptedTypes) {
|
||||||
|
this.acceptedTypes = acceptedTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package org.opencdmp.deposit.zenodorepository.enums;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonValue;
|
||||||
|
import org.opencdmp.commonmodels.enums.EnumUtils;
|
||||||
|
import org.opencdmp.commonmodels.enums.EnumValueProvider;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public enum ZenodoAccessRight implements EnumValueProvider<String> {
|
||||||
|
RESTRICTED(Names.Restricted), EMBARGOED(Names.Embargoed), OPEN(Names.Open);
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
public static class Names {
|
||||||
|
public static final String Restricted = "restricted";
|
||||||
|
public static final String Embargoed = "embargoed";
|
||||||
|
public static final String Open = "open";
|
||||||
|
}
|
||||||
|
|
||||||
|
ZenodoAccessRight(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@JsonValue
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Map<String, ZenodoAccessRight> map = EnumUtils.getEnumValueMap(ZenodoAccessRight.class);
|
||||||
|
|
||||||
|
public static ZenodoAccessRight of(String i) {
|
||||||
|
return map.get(i);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,11 @@
|
||||||
package eu.eudat.depositinterface.zenodorepository.models;
|
package org.opencdmp.deposit.zenodorepository.model;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
|
||||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
public class ZenodoComunity {
|
public class ZenodoCommunity {
|
||||||
|
|
||||||
private String identifier;
|
private String identifier;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package eu.eudat.depositinterface.zenodorepository.models;
|
package org.opencdmp.deposit.zenodorepository.model;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
@ -1,4 +1,4 @@
|
||||||
package eu.eudat.depositinterface.zenodorepository.models;
|
package org.opencdmp.deposit.zenodorepository.model;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
@ -1,4 +1,4 @@
|
||||||
package eu.eudat.depositinterface.zenodorepository.models;
|
package org.opencdmp.deposit.zenodorepository.model;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
@ -1,8 +1,9 @@
|
||||||
package eu.eudat.depositinterface.zenodorepository.models;
|
package org.opencdmp.deposit.zenodorepository.model;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import org.opencdmp.deposit.zenodorepository.enums.ZenodoAccessRight;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ public class ZenodoDepositMetadata {
|
||||||
|
|
||||||
private List<String> references;
|
private List<String> references;
|
||||||
|
|
||||||
private List<ZenodoComunity> communities;
|
private List<ZenodoCommunity> communities;
|
||||||
|
|
||||||
@JsonProperty("access_right")
|
@JsonProperty("access_right")
|
||||||
private ZenodoAccessRight accessRight;
|
private ZenodoAccessRight accessRight;
|
||||||
|
@ -125,11 +126,11 @@ public class ZenodoDepositMetadata {
|
||||||
this.version = version;
|
this.version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<ZenodoComunity> getCommunities() {
|
public List<ZenodoCommunity> getCommunities() {
|
||||||
return communities;
|
return communities;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCommunities(List<ZenodoComunity> communities) {
|
public void setCommunities(List<ZenodoCommunity> communities) {
|
||||||
this.communities = communities;
|
this.communities = communities;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package eu.eudat.depositinterface.zenodorepository.models;
|
package org.opencdmp.deposit.zenodorepository.model;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
@ -1,4 +1,4 @@
|
||||||
package eu.eudat.depositinterface.zenodorepository.models;
|
package org.opencdmp.deposit.zenodorepository.model;
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
@ -0,0 +1,397 @@
|
||||||
|
package org.opencdmp.deposit.zenodorepository.model.builder;
|
||||||
|
|
||||||
|
import gr.cite.tools.exception.MyApplicationException;
|
||||||
|
import gr.cite.tools.logging.LoggerService;
|
||||||
|
import org.opencdmp.commonmodels.enums.PlanAccessType;
|
||||||
|
import org.opencdmp.commonmodels.enums.PlanUserRole;
|
||||||
|
import org.opencdmp.commonmodels.models.PlanUserModel;
|
||||||
|
import org.opencdmp.commonmodels.models.description.*;
|
||||||
|
import org.opencdmp.commonmodels.models.descriptiotemplate.DefinitionModel;
|
||||||
|
import org.opencdmp.commonmodels.models.descriptiotemplate.fielddata.RadioBoxDataModel;
|
||||||
|
import org.opencdmp.commonmodels.models.descriptiotemplate.fielddata.SelectDataModel;
|
||||||
|
import org.opencdmp.commonmodels.models.plan.PlanBlueprintValueModel;
|
||||||
|
import org.opencdmp.commonmodels.models.plan.PlanModel;
|
||||||
|
import org.opencdmp.commonmodels.models.planblueprint.SectionModel;
|
||||||
|
import org.opencdmp.commonmodels.models.planreference.PlanReferenceModel;
|
||||||
|
import org.opencdmp.commonmodels.models.reference.ReferenceFieldModel;
|
||||||
|
import org.opencdmp.commonmodels.models.reference.ReferenceModel;
|
||||||
|
import org.opencdmp.deposit.zenodorepository.configuration.funder.FunderProperties;
|
||||||
|
import org.opencdmp.deposit.zenodorepository.configuration.identifier.IdentifierProperties;
|
||||||
|
import org.opencdmp.deposit.zenodorepository.configuration.pid.PidProperties;
|
||||||
|
import org.opencdmp.deposit.zenodorepository.enums.ZenodoAccessRight;
|
||||||
|
import org.opencdmp.deposit.zenodorepository.model.*;
|
||||||
|
import org.opencdmp.deposit.zenodorepository.service.zenodo.ZenodoDepositServiceImpl;
|
||||||
|
import org.opencdmp.deposit.zenodorepository.service.zenodo.ZenodoServiceProperties;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
|
import org.springframework.context.annotation.Scope;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||||
|
public class ZenodoBuilder {
|
||||||
|
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(ZenodoDepositServiceImpl.class));
|
||||||
|
|
||||||
|
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 SEMANTIC_PUBLICATION_DATE = "zenodo.publication_date";
|
||||||
|
|
||||||
|
private final PidProperties pidProperties;
|
||||||
|
private final IdentifierProperties identifierProperties;
|
||||||
|
private final FunderProperties funderProperties;
|
||||||
|
private final ZenodoServiceProperties zenodoServiceProperties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public ZenodoBuilder(PidProperties pidProperties, IdentifierProperties identifierProperties, FunderProperties funderProperties, ZenodoServiceProperties zenodoServiceProperties){
|
||||||
|
this.pidProperties = pidProperties;
|
||||||
|
this.identifierProperties = identifierProperties;
|
||||||
|
this.funderProperties = funderProperties;
|
||||||
|
this.zenodoServiceProperties = zenodoServiceProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZenodoDeposit build(PlanModel plan) {
|
||||||
|
ZenodoDeposit deposit = new ZenodoDeposit();
|
||||||
|
this.applyZenodoRelator(plan, deposit);
|
||||||
|
deposit.getMetadata().setTitle(plan.getLabel());
|
||||||
|
deposit.getMetadata().setUploadType(UPLOAD_TYPE);
|
||||||
|
deposit.getMetadata().setPublicationType(PUBLICATION_TYPE);
|
||||||
|
deposit.getMetadata().setDescription((plan.getDescription() != null && !plan.getDescription().isEmpty() ? plan.getDescription() : "<p></p>"));
|
||||||
|
deposit.getMetadata().setVersion(String.valueOf(plan.getVersion()));
|
||||||
|
String zenodoCommunity = zenodoServiceProperties.getCommunity();
|
||||||
|
if(zenodoCommunity != null && !zenodoCommunity.isEmpty()) {
|
||||||
|
if (deposit.getMetadata().getCommunities() == null) deposit.getMetadata().setCommunities(new ArrayList<>());
|
||||||
|
ZenodoCommunity community = new ZenodoCommunity();
|
||||||
|
community.setIdentifier(zenodoCommunity);
|
||||||
|
deposit.getMetadata().getCommunities().add(community);
|
||||||
|
}
|
||||||
|
|
||||||
|
org.opencdmp.commonmodels.models.planblueprint.FieldModel fieldOfSemantic = this.getFieldOfSemantic(plan, SEMANTIC_PUBLICATION_DATE);
|
||||||
|
if (fieldOfSemantic != null){
|
||||||
|
PlanBlueprintValueModel planBlueprintValueModel = this.getPlanBlueprintValue(plan, fieldOfSemantic.getId());
|
||||||
|
if (planBlueprintValueModel != null && planBlueprintValueModel.getDateValue() != null) {
|
||||||
|
deposit.getMetadata().setPublicationDate(DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.systemDefault()).format(planBlueprintValueModel.getDateValue()));
|
||||||
|
} else if (planBlueprintValueModel != null && planBlueprintValueModel.getValue() != null && !planBlueprintValueModel.getValue().isBlank()){
|
||||||
|
try {
|
||||||
|
Instant instant = Instant.parse(planBlueprintValueModel.getValue());
|
||||||
|
deposit.getMetadata().setPublicationDate(DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.systemDefault()).format(instant));
|
||||||
|
}catch (Exception e){
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.applyAccessRight(plan, deposit);
|
||||||
|
this.applyIsIdenticalTo(plan, deposit);
|
||||||
|
this.applyLicenses(plan, deposit);
|
||||||
|
this.applyResearchers(plan, deposit);
|
||||||
|
this.applyGrants(plan, deposit);
|
||||||
|
this.applyContributors(plan, deposit);
|
||||||
|
this.applyCreators(plan, deposit);
|
||||||
|
|
||||||
|
return deposit;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlanBlueprintValueModel getPlanBlueprintValue(PlanModel plan, UUID id){
|
||||||
|
if (plan == null || plan.getProperties() == null || plan.getProperties().getPlanBlueprintValues() == null) return null;
|
||||||
|
return plan.getProperties().getPlanBlueprintValues().stream().filter(x-> x.getFieldId().equals(id)).findFirst().orElse(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private org.opencdmp.commonmodels.models.planblueprint.FieldModel getFieldOfSemantic(PlanModel plan, String semanticKey){
|
||||||
|
if (plan == null || plan.getPlanBlueprint() == null || plan.getPlanBlueprint().getDefinition() == null || plan.getPlanBlueprint().getDefinition().getSections() == null) return null;
|
||||||
|
for (SectionModel sectionModel : plan.getPlanBlueprint().getDefinition().getSections()){
|
||||||
|
if (sectionModel.getFields() != null){
|
||||||
|
org.opencdmp.commonmodels.models.planblueprint.FieldModel fieldModel = sectionModel.getFields().stream().filter(x-> x.getSemantics() != null && x.getSemantics().contains(semanticKey)).findFirst().orElse(null);
|
||||||
|
if (fieldModel != null) return fieldModel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<org.opencdmp.commonmodels.models.descriptiotemplate.FieldModel> findSchematicValues(String relatedId, DefinitionModel definitionModel){
|
||||||
|
return definitionModel.getAllField().stream().filter(x-> x.getSemantics() != null && x.getSemantics().contains(relatedId)).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<FieldModel> findValueFieldsByIds(String fieldId, PropertyDefinitionModel definitionModel){
|
||||||
|
List<FieldModel> models = new ArrayList<>();
|
||||||
|
if (definitionModel == null || definitionModel.getFieldSets() == null || definitionModel.getFieldSets().isEmpty()) return models;
|
||||||
|
for (PropertyDefinitionFieldSetModel propertyDefinitionFieldSetModel : definitionModel.getFieldSets().values()){
|
||||||
|
if (propertyDefinitionFieldSetModel == null ||propertyDefinitionFieldSetModel.getItems() == null || propertyDefinitionFieldSetModel.getItems().isEmpty()) continue;
|
||||||
|
for (PropertyDefinitionFieldSetItemModel propertyDefinitionFieldSetItemModel : propertyDefinitionFieldSetModel.getItems()){
|
||||||
|
if (propertyDefinitionFieldSetItemModel == null ||propertyDefinitionFieldSetItemModel.getFields() == null || propertyDefinitionFieldSetItemModel.getFields().isEmpty()) continue;
|
||||||
|
for (Map.Entry<String, FieldModel> entry : propertyDefinitionFieldSetItemModel.getFields().entrySet()){
|
||||||
|
if (entry == null || entry.getValue() == null) continue;
|
||||||
|
if (entry.getKey().equalsIgnoreCase(fieldId)) models.add(entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return models;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> extractSchematicValues(List<org.opencdmp.commonmodels.models.descriptiotemplate.FieldModel> fields, PropertyDefinitionModel propertyDefinition, List<String> acceptedPidTypes) {
|
||||||
|
Set<String> values = new HashSet<>();
|
||||||
|
for (org.opencdmp.commonmodels.models.descriptiotemplate.FieldModel field : fields) {
|
||||||
|
if (field.getData() == null) continue;
|
||||||
|
List<FieldModel> valueFields = this.findValueFieldsByIds(field.getId(), propertyDefinition);
|
||||||
|
for (FieldModel valueField : valueFields) {
|
||||||
|
switch (field.getData().getFieldType()) {
|
||||||
|
case FREE_TEXT, TEXT_AREA, RICH_TEXT_AREA -> {
|
||||||
|
if (valueField.getTextValue() != null && !valueField.getTextValue().isBlank()) values.add(valueField.getTextValue());
|
||||||
|
}
|
||||||
|
case BOOLEAN_DECISION, CHECK_BOX -> {
|
||||||
|
if (valueField.getBooleanValue() != null) values.add(valueField.getBooleanValue().toString());
|
||||||
|
}
|
||||||
|
case DATE_PICKER -> {
|
||||||
|
if (valueField.getDateValue() != null) values.add(DateTimeFormatter.ISO_DATE.format(valueField.getDateValue()));
|
||||||
|
}
|
||||||
|
case DATASET_IDENTIFIER, VALIDATION -> {
|
||||||
|
if (valueField.getExternalIdentifier() != null && valueField.getExternalIdentifier().getIdentifier() != null && !valueField.getExternalIdentifier().getIdentifier().isBlank()) {
|
||||||
|
values.add(valueField.getExternalIdentifier().getIdentifier());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case TAGS -> {
|
||||||
|
if (valueField.getTextListValue() != null && !valueField.getTextListValue().isEmpty()) {
|
||||||
|
values.addAll(valueField.getTextListValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case SELECT -> {
|
||||||
|
if (valueField.getTextListValue() != null && !valueField.getTextListValue().isEmpty()) {
|
||||||
|
SelectDataModel selectDataModel = (SelectDataModel)field.getData();
|
||||||
|
if (selectDataModel != null && selectDataModel.getOptions() != null && !selectDataModel.getOptions().isEmpty()){
|
||||||
|
for (SelectDataModel.OptionModel option : selectDataModel.getOptions()){
|
||||||
|
if (valueField.getTextListValue().contains(option.getValue()) || valueField.getTextListValue().contains(option.getLabel())) values.add(option.getLabel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case RADIO_BOX -> {
|
||||||
|
if (valueField.getTextListValue() != null && !valueField.getTextListValue().isEmpty()) {
|
||||||
|
RadioBoxDataModel radioBoxModel = (RadioBoxDataModel)field.getData();
|
||||||
|
if (radioBoxModel != null && radioBoxModel.getOptions() != null && !radioBoxModel.getOptions().isEmpty()){
|
||||||
|
for (RadioBoxDataModel.RadioBoxOptionModel option : radioBoxModel.getOptions()){
|
||||||
|
if (valueField.getTextListValue().contains(option.getValue()) || valueField.getTextListValue().contains(option.getLabel())) values.add(option.getLabel());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case REFERENCE_TYPES -> {
|
||||||
|
if (valueField.getReferences() != null && !valueField.getReferences().isEmpty()) {
|
||||||
|
for (ReferenceModel referenceModel : valueField.getReferences()) {
|
||||||
|
if (referenceModel == null
|
||||||
|
|| referenceModel.getType() == null || referenceModel.getType().getCode() == null || referenceModel.getType().getCode().isBlank()
|
||||||
|
|| referenceModel.getDefinition() == null || referenceModel.getDefinition().getFields() == null || referenceModel.getDefinition().getFields().isEmpty()) continue;
|
||||||
|
if (referenceModel.getType().getCode().equals(zenodoServiceProperties.getOrganizationReferenceCode()) || referenceModel.getType().getCode().equals(zenodoServiceProperties.getResearcherReferenceCode())) {
|
||||||
|
if (referenceModel.getReference() != null && !referenceModel.getReference().isBlank()) {
|
||||||
|
values.add(referenceModel.getReference());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String pid = referenceModel.getDefinition().getFields().stream().filter(x -> x.getCode() != null && x.getCode().equals(this.pidProperties.getFields().getPidName())).map(ReferenceFieldModel::getValue).findFirst().orElse(null);
|
||||||
|
String pidType = referenceModel.getDefinition().getFields().stream().filter(x -> x.getCode() != null && x.getCode().equals(this.pidProperties.getFields().getPidTypeName())).map(ReferenceFieldModel::getValue).findFirst().orElse(null);
|
||||||
|
if (pid != null && !pid.isBlank() && pidType != null && !pidType.isBlank() && acceptedPidTypes.contains(pidType)) {
|
||||||
|
values.add(pid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case INTERNAL_ENTRIES_DESCRIPTIONS, INTERNAL_ENTRIES_PlANS, UPLOAD -> throw new MyApplicationException("Invalid type " + field.getData().getFieldType());
|
||||||
|
default -> throw new MyApplicationException("Invalid type " + field.getData().getFieldType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ReferenceModel> getReferenceModelOfType(PlanModel plan, String code){
|
||||||
|
List<ReferenceModel> response = new ArrayList<>();
|
||||||
|
if (plan.getReferences() == null) return response;
|
||||||
|
for (PlanReferenceModel planReferenceModel : plan.getReferences()){
|
||||||
|
if (planReferenceModel.getReference() != null && planReferenceModel.getReference().getType() != null && planReferenceModel.getReference().getType().getCode() != null && planReferenceModel.getReference().getType().getCode().equals(code)){
|
||||||
|
response.add(planReferenceModel.getReference());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyZenodoRelator(PlanModel plan, ZenodoDeposit deposit) {
|
||||||
|
if (deposit.getMetadata() == null) deposit.setMetadata(new ZenodoDepositMetadata());
|
||||||
|
|
||||||
|
List<String> acceptedPidTypes = this.pidProperties.getAcceptedTypes();
|
||||||
|
List<ZenodoRelator> relatedIdentifiers = new ArrayList<>();
|
||||||
|
for(DescriptionModel descriptionModel: plan.getDescriptions()){
|
||||||
|
for(String relatedId: this.identifierProperties.getRelated()){
|
||||||
|
List<org.opencdmp.commonmodels.models.descriptiotemplate.FieldModel> fields = this.findSchematicValues(relatedId, descriptionModel.getDescriptionTemplate().getDefinition());
|
||||||
|
Set<String> values = extractSchematicValues(fields, descriptionModel.getProperties(), acceptedPidTypes);
|
||||||
|
for(String value: values){
|
||||||
|
ZenodoRelator relator = new ZenodoRelator();
|
||||||
|
relator.setRelation(relatedId.substring(relatedId.lastIndexOf(".") + 1));
|
||||||
|
relator.setIdentifier(value);
|
||||||
|
relatedIdentifiers.add(relator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
deposit.getMetadata().setRelatedIdentifiers(relatedIdentifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyAccessRight(PlanModel plan, ZenodoDeposit deposit){
|
||||||
|
if (deposit.getMetadata() == null) deposit.setMetadata(new ZenodoDepositMetadata());
|
||||||
|
|
||||||
|
if (plan.getAccessType() == null) {
|
||||||
|
deposit.getMetadata().setAccessRight(ZenodoAccessRight.RESTRICTED);
|
||||||
|
deposit.getMetadata().setAccessConditions("");
|
||||||
|
} else {
|
||||||
|
if (plan.getAccessType().equals(PlanAccessType.Public)) {
|
||||||
|
Instant publicationDate = plan.getFinalizedAt();
|
||||||
|
if (publicationDate == null) publicationDate = Instant.now().minusSeconds(1);
|
||||||
|
|
||||||
|
if (publicationDate.isBefore(Instant.now())) {
|
||||||
|
deposit.getMetadata().setAccessRight(ZenodoAccessRight.OPEN);
|
||||||
|
} else {
|
||||||
|
deposit.getMetadata().setAccessRight(ZenodoAccessRight.EMBARGOED);
|
||||||
|
deposit.getMetadata().setEmbargoDate(publicationDate.toString());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
deposit.getMetadata().setAccessRight(ZenodoAccessRight.RESTRICTED);
|
||||||
|
deposit.getMetadata().setAccessConditions("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyIsIdenticalTo(PlanModel plan, ZenodoDeposit deposit){
|
||||||
|
if (deposit.getMetadata() == null) deposit.setMetadata(new ZenodoDepositMetadata());
|
||||||
|
|
||||||
|
if (plan.getAccessType().equals(PlanAccessType.Public)) {
|
||||||
|
ZenodoRelator relator = new ZenodoRelator();
|
||||||
|
relator.setIdentifier(zenodoServiceProperties.getDomain() + "/external/zenodo/" + plan.getId().toString());
|
||||||
|
relator.setRelation(IS_IDENTICAL_TO);
|
||||||
|
if (deposit.getMetadata().getRelatedIdentifiers() == null)deposit.getMetadata().setRelatedIdentifiers(new ArrayList<>());
|
||||||
|
deposit.getMetadata().getRelatedIdentifiers().add(relator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyLicenses(PlanModel plan, ZenodoDeposit deposit){
|
||||||
|
if (deposit.getMetadata() == null) deposit.setMetadata(new ZenodoDepositMetadata());
|
||||||
|
|
||||||
|
List<ReferenceModel> planLicenses = this.getReferenceModelOfType(plan, zenodoServiceProperties.getLicensesReferenceCode());
|
||||||
|
if (!planLicenses.isEmpty()) {
|
||||||
|
for (ReferenceModel planLicense : planLicenses) {
|
||||||
|
if (planLicense != null && planLicense.getReference() != null && !planLicense.getReference().isBlank()) {
|
||||||
|
deposit.getMetadata().setLicense(planLicense.getReference());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyResearchers(PlanModel plan, ZenodoDeposit deposit){
|
||||||
|
if (deposit.getMetadata() == null) deposit.setMetadata(new ZenodoDepositMetadata());
|
||||||
|
|
||||||
|
List<ZenodoContributor> researchers = new ArrayList<>();
|
||||||
|
List<ReferenceModel> planResearchers = this.getReferenceModelOfType(plan, zenodoServiceProperties.getResearcherReferenceCode());
|
||||||
|
if (planResearchers != null && !planResearchers.isEmpty()) {
|
||||||
|
for (ReferenceModel researcher : planResearchers) {
|
||||||
|
ZenodoContributor contributor = new ZenodoContributor();
|
||||||
|
contributor.setName(researcher.getLabel());
|
||||||
|
contributor.setType(CONTRIBUTOR_TYPE_RESEARCHER);
|
||||||
|
contributor.setAffiliation(researcher.getSource());
|
||||||
|
if (researcher.getSource().equalsIgnoreCase(zenodoServiceProperties.getOrcidResearcherSourceCode())) {
|
||||||
|
contributor.setOrcid(researcher.getReference());
|
||||||
|
}
|
||||||
|
researchers.add(contributor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deposit.getMetadata().getContributors() == null)deposit.getMetadata().setContributors(new ArrayList<>());
|
||||||
|
|
||||||
|
deposit.getMetadata().getContributors().addAll(researchers);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyGrants(PlanModel plan, ZenodoDeposit deposit){
|
||||||
|
if (deposit.getMetadata() == null) deposit.setMetadata(new ZenodoDepositMetadata());
|
||||||
|
List<ReferenceModel> planGrants = this.getReferenceModelOfType(plan, zenodoServiceProperties.getGrantReferenceCode());
|
||||||
|
List<ReferenceModel> planFunders = this.getReferenceModelOfType(plan, zenodoServiceProperties.getFunderReferenceCode());
|
||||||
|
|
||||||
|
if (!planGrants.isEmpty()) {
|
||||||
|
ReferenceModel depositGrant = planGrants.stream().filter(x-> x.getSource().equalsIgnoreCase(zenodoServiceProperties.getOpenaireGrantSourceCode())).findFirst().orElse(null);
|
||||||
|
|
||||||
|
if (depositGrant != null) {
|
||||||
|
String grantReferenceTail = depositGrant.getReference().split(":")[2];
|
||||||
|
List<FunderProperties.DoiFunder> doiFunders = this.funderProperties.getAvailable();
|
||||||
|
if (!planFunders.isEmpty()) {
|
||||||
|
ReferenceModel depositFunder = planFunders.getFirst();
|
||||||
|
FunderProperties.DoiFunder doiFunder = doiFunders.stream()
|
||||||
|
.filter(doiFunder1 -> depositFunder.getLabel().contains(doiFunder1.getFunder()) || doiFunder1.getFunder().contains(depositFunder.getLabel()))
|
||||||
|
.findFirst().orElse(null);
|
||||||
|
if (doiFunder != null) {
|
||||||
|
String finalId = doiFunder.getDoi() + "::" + grantReferenceTail;
|
||||||
|
ZenodoGrant grant = new ZenodoGrant();
|
||||||
|
grant.setId(finalId);
|
||||||
|
if (deposit.getMetadata().getGrants() == null)deposit.getMetadata().setGrants(new ArrayList<>());
|
||||||
|
deposit.getMetadata().getGrants().add(grant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyContributors(PlanModel plan, ZenodoDeposit deposit){
|
||||||
|
if (plan.getUsers() == null) return;
|
||||||
|
|
||||||
|
if (deposit.getMetadata() == null) deposit.setMetadata(new ZenodoDepositMetadata());
|
||||||
|
|
||||||
|
List<ReferenceModel> planOrganizations = this.getReferenceModelOfType(plan, zenodoServiceProperties.getOrganizationReferenceCode());
|
||||||
|
String zenodoAffiliation = zenodoServiceProperties.getAffiliation();
|
||||||
|
|
||||||
|
List<ZenodoContributor> contributors = new ArrayList<>();
|
||||||
|
for (PlanUserModel planUser: plan.getUsers()) {
|
||||||
|
ZenodoContributor contributor = new ZenodoContributor();
|
||||||
|
contributor.setName(planUser.getUser().getName());
|
||||||
|
contributor.setType(CONTRIBUTOR_TYPE_PROJECT_MANAGER);
|
||||||
|
if (planOrganizations != null && !planOrganizations.isEmpty()) {
|
||||||
|
contributor.setAffiliation(planOrganizations.stream().map(ReferenceModel::getLabel).collect(Collectors.joining(", ")));
|
||||||
|
} else {
|
||||||
|
if(zenodoAffiliation != null && !zenodoAffiliation.isEmpty()) {
|
||||||
|
contributor.setAffiliation(zenodoAffiliation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contributors.add(contributor);
|
||||||
|
}
|
||||||
|
if (deposit.getMetadata().getContributors() == null)deposit.getMetadata().setContributors(new ArrayList<>());
|
||||||
|
|
||||||
|
deposit.getMetadata().getContributors().addAll(contributors);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void applyCreators(PlanModel plan, ZenodoDeposit deposit){
|
||||||
|
if (plan.getUsers() == null) return;
|
||||||
|
|
||||||
|
if (deposit.getMetadata() == null) deposit.setMetadata(new ZenodoDepositMetadata());
|
||||||
|
|
||||||
|
List<ReferenceModel> planOrganizations = this.getReferenceModelOfType(plan, zenodoServiceProperties.getOrganizationReferenceCode());
|
||||||
|
String zenodoAffiliation = zenodoServiceProperties.getAffiliation();
|
||||||
|
|
||||||
|
ZenodoCreator creator = new ZenodoCreator();
|
||||||
|
PlanUserModel planModel = plan.getUsers().stream().filter(planUser -> planUser.getRole().equals(PlanUserRole.Owner)).findFirst().orElse(null);
|
||||||
|
if (planModel == null || planModel.getUser() == null) return;
|
||||||
|
|
||||||
|
creator.setName(planModel.getUser().getName());
|
||||||
|
if (planOrganizations != null && !planOrganizations.isEmpty()) {
|
||||||
|
creator.setAffiliation(planOrganizations.stream().map(ReferenceModel::getLabel).collect(Collectors.joining(", ")));
|
||||||
|
} else {
|
||||||
|
if(zenodoAffiliation != null && !zenodoAffiliation.isEmpty()) {
|
||||||
|
creator.setAffiliation(zenodoAffiliation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (deposit.getMetadata().getCreators() == null)deposit.getMetadata().setCreators(new ArrayList<>());
|
||||||
|
deposit.getMetadata().getCreators().add(creator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package org.opencdmp.deposit.zenodorepository.service.storage;
|
||||||
|
|
||||||
|
public interface FileStorageService {
|
||||||
|
String storeFile(byte[] data);
|
||||||
|
|
||||||
|
byte[] readFile(String fileRef);
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package org.opencdmp.deposit.zenodorepository.service.storage;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableConfigurationProperties({FileStorageServiceProperties.class})
|
||||||
|
public class FileStorageServiceConfiguration {
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package org.opencdmp.deposit.zenodorepository.service.storage;
|
||||||
|
|
||||||
|
import gr.cite.tools.logging.LoggerService;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.StandardOpenOption;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class FileStorageServiceImpl implements FileStorageService {
|
||||||
|
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(FileStorageServiceImpl.class));
|
||||||
|
|
||||||
|
private final FileStorageServiceProperties properties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public FileStorageServiceImpl(FileStorageServiceProperties properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String storeFile(byte[] data) {
|
||||||
|
try {
|
||||||
|
String fileName = UUID.randomUUID().toString().replace("-", "").toLowerCase(Locale.ROOT);
|
||||||
|
Path storagePath = Paths.get(properties.getTransientPath() + "/" + fileName);
|
||||||
|
Files.write(storagePath, data, StandardOpenOption.CREATE_NEW);
|
||||||
|
return fileName;
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] readFile(String fileRef) {
|
||||||
|
try (FileInputStream inputStream = new FileInputStream(properties.getTransientPath() + "/" + fileRef)) {
|
||||||
|
return inputStream.readAllBytes();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package org.opencdmp.deposit.zenodorepository.service.storage;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.boot.context.properties.bind.ConstructorBinding;
|
||||||
|
|
||||||
|
@ConfigurationProperties(prefix = "file.storage")
|
||||||
|
public class FileStorageServiceProperties {
|
||||||
|
private final String temp;
|
||||||
|
private final String transientPath;
|
||||||
|
|
||||||
|
@ConstructorBinding
|
||||||
|
public FileStorageServiceProperties(String temp, String transientPath) {
|
||||||
|
this.temp = temp;
|
||||||
|
this.transientPath = transientPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTemp() {
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTransientPath() {
|
||||||
|
return transientPath;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package org.opencdmp.deposit.zenodorepository.service.zenodo;
|
||||||
|
|
||||||
|
import org.opencdmp.commonmodels.models.plan.PlanModel;
|
||||||
|
import org.opencdmp.depositbase.repository.DepositConfiguration;
|
||||||
|
|
||||||
|
public interface ZenodoDepositService {
|
||||||
|
String deposit(PlanModel planDepositModel, String zenodoToken) throws Exception;
|
||||||
|
|
||||||
|
DepositConfiguration getConfiguration();
|
||||||
|
|
||||||
|
String authenticate(String code);
|
||||||
|
|
||||||
|
String getLogo();
|
||||||
|
}
|
|
@ -0,0 +1,413 @@
|
||||||
|
package org.opencdmp.deposit.zenodorepository.service.zenodo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import gr.cite.tools.exception.MyApplicationException;
|
||||||
|
import gr.cite.tools.logging.LoggerService;
|
||||||
|
import gr.cite.tools.logging.MapLogEntry;
|
||||||
|
import org.opencdmp.commonmodels.models.FileEnvelopeModel;
|
||||||
|
import org.opencdmp.commonmodels.models.plan.PlanModel;
|
||||||
|
import org.opencdmp.deposit.zenodorepository.model.ZenodoDeposit;
|
||||||
|
import org.opencdmp.deposit.zenodorepository.model.builder.ZenodoBuilder;
|
||||||
|
import org.opencdmp.deposit.zenodorepository.service.storage.FileStorageService;
|
||||||
|
import org.opencdmp.depositbase.repository.DepositConfiguration;
|
||||||
|
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.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
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.ExchangeFilterFunction;
|
||||||
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ZenodoDepositServiceImpl implements ZenodoDepositService {
|
||||||
|
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(ZenodoDepositServiceImpl.class));
|
||||||
|
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 ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
|
||||||
|
private final ZenodoServiceProperties zenodoServiceProperties;
|
||||||
|
private final ZenodoBuilder zenodoBuilder;
|
||||||
|
private final FileStorageService storageService;
|
||||||
|
|
||||||
|
private byte[] logo;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public ZenodoDepositServiceImpl(ZenodoServiceProperties zenodoServiceProperties, ZenodoBuilder mapper, FileStorageService storageService){
|
||||||
|
this.zenodoServiceProperties = zenodoServiceProperties;
|
||||||
|
this.zenodoBuilder = mapper;
|
||||||
|
this.storageService = storageService;
|
||||||
|
this.logo = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String deposit(PlanModel planModel, String zenodoToken) throws Exception {
|
||||||
|
|
||||||
|
DepositConfiguration depositConfiguration = this.getConfiguration();
|
||||||
|
|
||||||
|
if(depositConfiguration != null) {
|
||||||
|
|
||||||
|
if (zenodoToken == null || zenodoToken.isEmpty()) {
|
||||||
|
zenodoToken = depositConfiguration.getAccessToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
String zenodoUrl = depositConfiguration.getRepositoryUrl();
|
||||||
|
|
||||||
|
// First step, post call to Zenodo, to create the entry.
|
||||||
|
WebClient zenodoClient = this.getWebClient();
|
||||||
|
|
||||||
|
DepositConfiguration zenodoConfig = this.zenodoServiceProperties.getDepositConfiguration();
|
||||||
|
if (zenodoConfig == null) return null;
|
||||||
|
ZenodoDeposit deposit = zenodoBuilder.build(planModel);
|
||||||
|
|
||||||
|
LinkedHashMap<String, String> links;
|
||||||
|
String previousDOI = planModel.getPreviousDOI();
|
||||||
|
String unpublishedUrl = null;
|
||||||
|
String publishUrl;
|
||||||
|
try {
|
||||||
|
|
||||||
|
if (previousDOI == null) {
|
||||||
|
links = deposit(zenodoToken, zenodoUrl, zenodoClient, deposit);
|
||||||
|
} else {
|
||||||
|
unpublishedUrl = this.getUnpublishedDOI(zenodoClient, zenodoUrl, previousDOI, zenodoToken, planModel.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.
|
||||||
|
FileEnvelopeModel pdfEnvelope = planModel.getPdfFile();
|
||||||
|
|
||||||
|
if (links == null || !links.containsKey(ZENODO_LINKS_BUCKET)) throw new MyApplicationException("bucket not found");
|
||||||
|
String addFileUrl = links.get(ZENODO_LINKS_BUCKET) + "/" + cleanFileName(pdfEnvelope.getFilename()) + "?access_token=" + zenodoToken;
|
||||||
|
|
||||||
|
byte[] pdfFileBytes = null;
|
||||||
|
if (this.getConfiguration().isUseSharedStorage() && pdfEnvelope.getFileRef() != null && !pdfEnvelope.getFileRef().isBlank()) {
|
||||||
|
pdfFileBytes = this.storageService.readFile(pdfEnvelope.getFileRef());
|
||||||
|
}
|
||||||
|
if (pdfFileBytes == null || pdfFileBytes.length == 0){
|
||||||
|
pdfFileBytes = pdfEnvelope.getFile();
|
||||||
|
}
|
||||||
|
zenodoClient.put().uri(addFileUrl)
|
||||||
|
.body(BodyInserters
|
||||||
|
.fromResource(new ByteArrayResource(pdfFileBytes)))
|
||||||
|
.retrieve().toEntity(Map.class).block();
|
||||||
|
FileEnvelopeModel rdaJsonEnvelope = planModel.getRdaJsonFile();
|
||||||
|
|
||||||
|
String jsonFileName = cleanFileName(rdaJsonEnvelope.getFilename());
|
||||||
|
addFileUrl = links.get(ZENODO_LINKS_BUCKET) + "/" + jsonFileName + "?access_token=" + zenodoToken;
|
||||||
|
|
||||||
|
byte[] rdaJsonBytes = null;
|
||||||
|
if (this.getConfiguration().isUseSharedStorage() && rdaJsonEnvelope.getFileRef() != null && !rdaJsonEnvelope.getFileRef().isBlank()) {
|
||||||
|
rdaJsonBytes = this.storageService.readFile(rdaJsonEnvelope.getFileRef());
|
||||||
|
}
|
||||||
|
if (rdaJsonBytes == null || rdaJsonBytes.length == 0){
|
||||||
|
rdaJsonBytes = rdaJsonEnvelope.getFile();
|
||||||
|
}
|
||||||
|
zenodoClient.put().uri(addFileUrl).headers(httpHeaders -> httpHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM)).body(BodyInserters.fromResource(new ByteArrayResource(rdaJsonBytes))).retrieve().toEntity(Map.class).block();
|
||||||
|
|
||||||
|
if (planModel.getSupportingFilesZip() != null) {
|
||||||
|
String supportingFilesZipName = cleanFileName(planModel.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(zenodoClient, publishUrl);
|
||||||
|
|
||||||
|
} catch (HttpClientErrorException | HttpServerErrorException ex) {
|
||||||
|
logger.error(ex.getMessage(), ex);
|
||||||
|
Map<String, String> parsedException = objectMapper.readValue(ex.getResponseBodyAsString(), Map.class);
|
||||||
|
throw new IOException(parsedException.get("message"), ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String cleanFileName(String name){
|
||||||
|
if (name == null || name.isEmpty()) return null;
|
||||||
|
|
||||||
|
int extensionIndex = name.lastIndexOf('.');
|
||||||
|
String extension = "";
|
||||||
|
String namePart = "";
|
||||||
|
if (extensionIndex > 0) {
|
||||||
|
extension = name.substring(extensionIndex + 1);
|
||||||
|
namePart = name.substring(0, extensionIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!namePart.isEmpty()) namePart = namePart.replaceAll("[^a-zA-Z0-9_+ ]", "").replace(" ", "_").replace(",", "_");
|
||||||
|
|
||||||
|
return namePart + "." + extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LinkedHashMap<String, String> depositNewVersion(String zenodoToken, String zenodoUrl, String previousDOI, WebClient zenodoClient, ZenodoDeposit deposit) throws Exception {
|
||||||
|
Map<String, Object> 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, Object>) 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_LATEST_DRAFT)) throw new MyApplicationException("previousDOI not found");
|
||||||
|
String newVersionUrl = links.get(ZENODO_LINKS_LATEST_DRAFT) + "/actions/newversion" + "?access_token=" + zenodoToken;
|
||||||
|
logger.debug("new version url: " + newVersionUrl);
|
||||||
|
createResponse = zenodoClient.post().uri(newVersionUrl)
|
||||||
|
.exchangeToMono(mono ->
|
||||||
|
mono.statusCode().isError() ?
|
||||||
|
mono.createException().flatMap(Mono::error) :
|
||||||
|
mono.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {})
|
||||||
|
).block();
|
||||||
|
logger.debug("createResponse-newVersion:");
|
||||||
|
logger.debug(objectMapper.writeValueAsString(createResponse));
|
||||||
|
links = createResponse == null ? new LinkedHashMap<>() : (LinkedHashMap<String, String>) createResponse.getOrDefault(ZENODO_LINKS, new LinkedHashMap<>());
|
||||||
|
|
||||||
|
//Third, get the new deposit
|
||||||
|
if (!links.containsKey(ZENODO_LINKS_LATEST_DRAFT)) throw new MyApplicationException("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, Object>>() {})).block();
|
||||||
|
logger.debug("createResponse-latestDraft:");
|
||||||
|
logger.debug(objectMapper.writeValueAsString(createResponse));
|
||||||
|
links = createResponse == null ? new LinkedHashMap<>() : (LinkedHashMap<String, String>) 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;
|
||||||
|
logger.debug(new MapLogEntry("Deposit New Version")
|
||||||
|
.And("url", updateUrl)
|
||||||
|
.And("body", deposit));
|
||||||
|
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(Void.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);
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
zenodoClient.delete().uri(latestDraftUrl).retrieve().toEntity(Void.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;
|
||||||
|
logger.debug(new MapLogEntry("Deposit")
|
||||||
|
.And("url", createUrl)
|
||||||
|
.And("body", deposit));
|
||||||
|
createResponse = zenodoClient.post().uri(createUrl).headers(httpHeaders -> {
|
||||||
|
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||||
|
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
})
|
||||||
|
.bodyValue(deposit).exchangeToMono(mono ->
|
||||||
|
mono.statusCode().isError() ?
|
||||||
|
mono.createException().flatMap(Mono::error) :
|
||||||
|
mono.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {})).block();
|
||||||
|
return (LinkedHashMap<String, String>) createResponse.getOrDefault(ZENODO_LINKS, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String publish(WebClient webClient, String publishUrl){
|
||||||
|
logger.debug(new MapLogEntry("publish")
|
||||||
|
.And("url", publishUrl));
|
||||||
|
Map<String, Object> publishResponse = webClient.post().uri(publishUrl).bodyValue("").exchangeToMono(mono ->
|
||||||
|
mono.statusCode().isError() ?
|
||||||
|
mono.createException().flatMap(Mono::error) :
|
||||||
|
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 DepositConfiguration getConfiguration() {
|
||||||
|
return this.zenodoServiceProperties.getDepositConfiguration();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String authenticate(String code){
|
||||||
|
|
||||||
|
DepositConfiguration depositConfiguration = this.getConfiguration();
|
||||||
|
|
||||||
|
if(depositConfiguration != null) {
|
||||||
|
|
||||||
|
WebClient client = WebClient.builder().filters(exchangeFilterFunctions -> {
|
||||||
|
exchangeFilterFunctions.add(logRequest());
|
||||||
|
exchangeFilterFunctions.add(logResponse());
|
||||||
|
}).defaultHeaders(httpHeaders -> {
|
||||||
|
httpHeaders.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
||||||
|
httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||||
|
}).build();
|
||||||
|
|
||||||
|
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
|
||||||
|
map.add(CLIENT_ID, depositConfiguration.getRepositoryClientId());
|
||||||
|
map.add(CLIENT_SECRET, depositConfiguration.getRepositoryClientSecret());
|
||||||
|
map.add(GRANT_TYPE, AUTHORIZATION_CODE);
|
||||||
|
map.add(CODE, code);
|
||||||
|
map.add(REDIRECT_URI, depositConfiguration.getRedirectUri());
|
||||||
|
|
||||||
|
try {
|
||||||
|
logger.debug(new MapLogEntry("Get Access Token")
|
||||||
|
.And("url", depositConfiguration.getRepositoryAccessTokenUrl())
|
||||||
|
.And("body", map));
|
||||||
|
|
||||||
|
Map<String, Object> values = client.post().uri(depositConfiguration.getRepositoryAccessTokenUrl()).bodyValue(map).exchangeToMono(mono ->
|
||||||
|
mono.statusCode().isError() ?
|
||||||
|
mono.createException().flatMap(Mono::error) :
|
||||||
|
mono.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {
|
||||||
|
})).block();
|
||||||
|
|
||||||
|
return values != null ? (String) values.getOrDefault(ACCESS_TOKEN, null) : null;
|
||||||
|
} catch (HttpClientErrorException ex) {
|
||||||
|
logger.error(ex.getMessage(), ex);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLogo() {
|
||||||
|
DepositConfiguration zenodoConfig = this.zenodoServiceProperties.getDepositConfiguration();
|
||||||
|
if(zenodoConfig != null && zenodoConfig.isHasLogo() && this.zenodoServiceProperties.getLogo() != null && !this.zenodoServiceProperties.getLogo().isBlank()) {
|
||||||
|
if (this.logo == null) {
|
||||||
|
try {
|
||||||
|
java.io.File logoFile = ResourceUtils.getFile(this.zenodoServiceProperties.getLogo());
|
||||||
|
if (!logoFile.exists()) return null;
|
||||||
|
try(InputStream inputStream = new FileInputStream(logoFile)){
|
||||||
|
this.logo = inputStream.readAllBytes();
|
||||||
|
};
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error(e.getMessage(), e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (this.logo != null && this.logo.length != 0) ? Base64.getEncoder().encodeToString(this.logo) : null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getUnpublishedDOI(WebClient client, String zenodoUrl, String doi, String token, Short version) {
|
||||||
|
try {
|
||||||
|
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.error(e.getMessage(), e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private WebClient getWebClient(){
|
||||||
|
return WebClient.builder().filters(exchangeFilterFunctions -> {
|
||||||
|
exchangeFilterFunctions.add(logRequest());
|
||||||
|
exchangeFilterFunctions.add(logResponse());
|
||||||
|
}).codecs(codecs -> codecs
|
||||||
|
.defaultCodecs()
|
||||||
|
.maxInMemorySize(this.zenodoServiceProperties.getMaxInMemorySizeInBytes())
|
||||||
|
).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ExchangeFilterFunction logRequest() {
|
||||||
|
return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
|
||||||
|
logger.debug(new MapLogEntry("Request").And("method", clientRequest.method().toString()).And("url", clientRequest.url().toString()));
|
||||||
|
return Mono.just(clientRequest);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ExchangeFilterFunction logResponse() {
|
||||||
|
return ExchangeFilterFunction.ofResponseProcessor(response -> {
|
||||||
|
if (response.statusCode().isError()) {
|
||||||
|
return response.mutate().build().bodyToMono(String.class)
|
||||||
|
.flatMap(body -> {
|
||||||
|
logger.error(new MapLogEntry("Response").And("method", response.request().getMethod().toString()).And("url", response.request().getURI()).And("status", response.statusCode().toString()).And("body", body));
|
||||||
|
return Mono.just(response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Mono.just(response);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package org.opencdmp.deposit.zenodorepository.service.zenodo;
|
||||||
|
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableConfigurationProperties({ZenodoServiceProperties.class})
|
||||||
|
public class ZenodoServiceConfiguration {
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
package org.opencdmp.deposit.zenodorepository.service.zenodo;
|
||||||
|
|
||||||
|
import org.opencdmp.depositbase.repository.DepositConfiguration;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
@ConfigurationProperties(prefix = "zenodo")
|
||||||
|
public class ZenodoServiceProperties {
|
||||||
|
private String logo;
|
||||||
|
|
||||||
|
private String community;
|
||||||
|
|
||||||
|
private String domain;
|
||||||
|
|
||||||
|
private String affiliation;
|
||||||
|
|
||||||
|
private DepositConfiguration depositConfiguration;
|
||||||
|
|
||||||
|
private String organizationReferenceCode;
|
||||||
|
private String grantReferenceCode;
|
||||||
|
private String funderReferenceCode;
|
||||||
|
private String researcherReferenceCode;
|
||||||
|
private String licensesReferenceCode;
|
||||||
|
private String openaireGrantSourceCode;
|
||||||
|
private String orcidResearcherSourceCode;
|
||||||
|
private int maxInMemorySizeInBytes;
|
||||||
|
|
||||||
|
public String getLogo() {
|
||||||
|
return logo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLogo(String logo) {
|
||||||
|
this.logo = logo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCommunity() {
|
||||||
|
return community;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCommunity(String community) {
|
||||||
|
this.community = community;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDomain() {
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDomain(String domain) {
|
||||||
|
this.domain = domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAffiliation() {
|
||||||
|
return affiliation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAffiliation(String affiliation) {
|
||||||
|
this.affiliation = affiliation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DepositConfiguration getDepositConfiguration() {
|
||||||
|
return depositConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDepositConfiguration(DepositConfiguration depositConfiguration) {
|
||||||
|
this.depositConfiguration = depositConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOrganizationReferenceCode() {
|
||||||
|
return organizationReferenceCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrganizationReferenceCode(String organizationReferenceCode) {
|
||||||
|
this.organizationReferenceCode = organizationReferenceCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGrantReferenceCode() {
|
||||||
|
return grantReferenceCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGrantReferenceCode(String grantReferenceCode) {
|
||||||
|
this.grantReferenceCode = grantReferenceCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFunderReferenceCode() {
|
||||||
|
return funderReferenceCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFunderReferenceCode(String funderReferenceCode) {
|
||||||
|
this.funderReferenceCode = funderReferenceCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResearcherReferenceCode() {
|
||||||
|
return researcherReferenceCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResearcherReferenceCode(String researcherReferenceCode) {
|
||||||
|
this.researcherReferenceCode = researcherReferenceCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLicensesReferenceCode() {
|
||||||
|
return licensesReferenceCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLicensesReferenceCode(String licensesReferenceCode) {
|
||||||
|
this.licensesReferenceCode = licensesReferenceCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOpenaireGrantSourceCode() {
|
||||||
|
return openaireGrantSourceCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOpenaireGrantSourceCode(String openaireGrantSourceCode) {
|
||||||
|
this.openaireGrantSourceCode = openaireGrantSourceCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOrcidResearcherSourceCode() {
|
||||||
|
return orcidResearcherSourceCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrcidResearcherSourceCode(String orcidResearcherSourceCode) {
|
||||||
|
this.orcidResearcherSourceCode = orcidResearcherSourceCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxInMemorySizeInBytes() {
|
||||||
|
return maxInMemorySizeInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMaxInMemorySizeInBytes(int maxInMemorySizeInBytes) {
|
||||||
|
this.maxInMemorySizeInBytes = maxInMemorySizeInBytes;
|
||||||
|
}
|
||||||
|
}
|
151
pom.xml
151
pom.xml
|
@ -5,114 +5,75 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
<version>2.5.2</version>
|
<version>3.3.3</version>
|
||||||
<relativePath/>
|
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<groupId>gr.cite.opendmp</groupId>
|
<groupId>org.opencdmp</groupId>
|
||||||
<artifactId>repositorydepositzenodo</artifactId>
|
<artifactId>repository-deposit-parent</artifactId>
|
||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
<packaging>jar</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<name>OpenDMP Repository Deposit Zenodo</name>
|
|
||||||
<description>OpenDMP Repository Deposit Zenodo</description>
|
|
||||||
<url>https://code-repo.d4science.org/MaDgiK-CITE/repository-deposit-zenodo</url>
|
|
||||||
<licenses>
|
|
||||||
<license>
|
|
||||||
<name>MIT License</name>
|
|
||||||
<url>https://code-repo.d4science.org/MaDgiK-CITE/repository-deposit-zenodo/src/branch/master/LICENSE.txt</url>
|
|
||||||
<distribution>repo</distribution>
|
|
||||||
</license>
|
|
||||||
</licenses>
|
|
||||||
<developers>
|
|
||||||
<developer>
|
|
||||||
<name>CITE S.A.</name>
|
|
||||||
<email>maven-central@cite.gr</email>
|
|
||||||
<organization>CITE S.A.</organization>
|
|
||||||
<organizationUrl>https://www.cite.gr</organizationUrl>
|
|
||||||
</developer>
|
|
||||||
</developers>
|
|
||||||
<scm>
|
|
||||||
<connection>scm:git:git://code-repo.d4science.org</connection>
|
|
||||||
<developerConnection>scm:git:ssh://code-repo.d4science.org</developerConnection>
|
|
||||||
<url>https://code-repo.d4science.org/MaDgiK-CITE/repository-deposit-zenodo</url>
|
|
||||||
</scm>
|
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
|
<maven.compiler.target>21</maven.compiler.target>
|
||||||
|
<maven.compiler.release>21</maven.compiler.release>
|
||||||
|
<java.version>21</java.version>
|
||||||
|
<log4j.version>1.2.17</log4j.version>
|
||||||
|
<log4j2.version>2.15.0</log4j2.version>
|
||||||
<revision>1.0.0-SNAPSHOT</revision>
|
<revision>1.0.0-SNAPSHOT</revision>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<module>core</module>
|
||||||
|
<module>web</module>
|
||||||
|
</modules>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.opencdmp</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>gr.cite.opendmp</groupId>
|
|
||||||
<artifactId>repositorydepositbase</artifactId>
|
<artifactId>repositorydepositbase</artifactId>
|
||||||
<version>1.0.4</version>
|
<version>2.0.17</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.json</groupId>
|
<groupId>gr.cite</groupId>
|
||||||
<artifactId>json</artifactId>
|
<artifactId>logging</artifactId>
|
||||||
<version>20160810</version>
|
<version>2.2.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>gr.cite</groupId>
|
||||||
|
<artifactId>exceptions</artifactId>
|
||||||
|
<version>2.2.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
<profiles>
|
||||||
<build>
|
<profile>
|
||||||
<plugins>
|
<id>dev</id>
|
||||||
<plugin>
|
<repositories>
|
||||||
<artifactId>maven-assembly-plugin</artifactId>
|
<repository>
|
||||||
<executions>
|
<id>dev</id>
|
||||||
<execution>
|
<name>Dev Profile</name>
|
||||||
<phase>package</phase>
|
<url>${devProfileUrl}</url>
|
||||||
<goals>
|
</repository>
|
||||||
<goal>single</goal>
|
</repositories>
|
||||||
</goals>
|
<distributionManagement>
|
||||||
</execution>
|
<repository>
|
||||||
</executions>
|
<id>dev</id>
|
||||||
<configuration>
|
<name>Dev Profile</name>
|
||||||
<archive>
|
<url>${devProfileUrlDeposit}</url>
|
||||||
<manifest>
|
</repository>
|
||||||
<mainClass>eu.eudat.EuDatApplication</mainClass>
|
</distributionManagement>
|
||||||
</manifest>
|
</profile>
|
||||||
</archive>
|
<profile>
|
||||||
<descriptorRefs>
|
<id>cite-dev</id>
|
||||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
<repositories>
|
||||||
</descriptorRefs>
|
<repository>
|
||||||
</configuration>
|
<id>cite-maven</id>
|
||||||
</plugin>
|
<name>CITE Maven Repository</name>
|
||||||
<plugin>
|
<url>https://crepo.cite.gr/repository/cite-maven/</url>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
</repository>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
</repositories>
|
||||||
<version>3.4.1</version>
|
<activation>
|
||||||
<executions>
|
<activeByDefault>true</activeByDefault>
|
||||||
<execution>
|
</activation>
|
||||||
<phase>package</phase>
|
</profile>
|
||||||
<goals>
|
</profiles>
|
||||||
<goal>shade</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<filters>
|
|
||||||
<filter>
|
|
||||||
<artifact>*:*</artifact>
|
|
||||||
<excludes>
|
|
||||||
<exclude>module-info.class</exclude>
|
|
||||||
</excludes>
|
|
||||||
</filter>
|
|
||||||
</filters>
|
|
||||||
<relocations>
|
|
||||||
<relocation>
|
|
||||||
<pattern>org.json</pattern>
|
|
||||||
<shadedPattern>zenodorepository.shaded.org.json</shadedPattern>
|
|
||||||
</relocation>
|
|
||||||
</relocations>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
</project>
|
</project>
|
||||||
|
|
27
settings.xml
27
settings.xml
|
@ -1,18 +1,33 @@
|
||||||
<settings>
|
<settings>
|
||||||
|
<pluginGroups>
|
||||||
|
<pluginGroup>org.sonarsource.scanner.maven</pluginGroup>
|
||||||
|
</pluginGroups>
|
||||||
<servers>
|
<servers>
|
||||||
<server>
|
<server>
|
||||||
<id>ossrh</id>
|
<id>cite-repo</id>
|
||||||
<username>${server_username}</username>
|
<username>${server_username}</username>
|
||||||
<password>${server_password}</password>
|
<password>${server_password}</password>
|
||||||
</server>
|
</server>
|
||||||
</servers>
|
</servers>
|
||||||
<profiles>
|
<profiles>
|
||||||
<profile>
|
<profile>
|
||||||
<id>ossrh</id>
|
<id>release</id>
|
||||||
<properties>
|
<repositories>
|
||||||
<gpg.passphrase>${gpg_passphrase}</gpg.passphrase>
|
<repository>
|
||||||
<gpg.keyname>${gpg_keyname}</gpg.keyname>
|
<id>central</id>
|
||||||
</properties>
|
<name>Central Repository</name>
|
||||||
|
<url>https://repo.maven.apache.org/maven2</url>
|
||||||
|
<layout>default</layout>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>cite-repo</id>
|
||||||
|
<name>CITE Maven Repo</name>
|
||||||
|
<url>${citeMavenRepoUrl}</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
</profile>
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
</settings>
|
</settings>
|
|
@ -1,13 +0,0 @@
|
||||||
package eu.eudat.depositinterface.zenodorepository.config;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface ConfigLoader {
|
|
||||||
InputStream getStreamFromPath(String filePath);
|
|
||||||
List<String> getRelatedIdentifiers();
|
|
||||||
List<String> getAcceptedPidTypes();
|
|
||||||
PidFieldNames getPidFieldNames();
|
|
||||||
byte[] getLogo(String repositoryId);
|
|
||||||
List<ZenodoConfig> getZenodoConfig();
|
|
||||||
}
|
|
|
@ -1,110 +0,0 @@
|
||||||
package eu.eudat.depositinterface.zenodorepository.config;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.core.env.Environment;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Service("zenodoConfigLoader")
|
|
||||||
public class ConfigLoaderImpl implements ConfigLoader{
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ConfigLoaderImpl.class);
|
|
||||||
private static final ObjectMapper mapper = new ObjectMapper();
|
|
||||||
|
|
||||||
private List<String> relatedIdentifiers = new ArrayList<>();
|
|
||||||
private List<String> acceptedPidTypes = new ArrayList<>();
|
|
||||||
private PidFieldNames pidFieldNames = new PidFieldNames();
|
|
||||||
private List<ZenodoConfig> zenodoConfig = new ArrayList<>();
|
|
||||||
|
|
||||||
private final Environment environment;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public ConfigLoaderImpl(Environment environment){
|
|
||||||
this.environment = environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getRelatedIdentifiers() {
|
|
||||||
if (relatedIdentifiers == null || relatedIdentifiers.isEmpty()) {
|
|
||||||
BufferedReader ids = new BufferedReader(new InputStreamReader(getStreamFromPath("relatedIdentifiers.txt")));
|
|
||||||
relatedIdentifiers = ids.lines().collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
return relatedIdentifiers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getAcceptedPidTypes() {
|
|
||||||
if (acceptedPidTypes == null || acceptedPidTypes.isEmpty()) {
|
|
||||||
BufferedReader ids = new BufferedReader(new InputStreamReader(getStreamFromPath("acceptedPidTypes.txt")));
|
|
||||||
acceptedPidTypes = ids.lines().collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
return acceptedPidTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PidFieldNames getPidFieldNames() {
|
|
||||||
try {
|
|
||||||
pidFieldNames = mapper.readValue(getStreamFromPath("datasetFieldsPid.json"), PidFieldNames.class);
|
|
||||||
}
|
|
||||||
catch (IOException e){
|
|
||||||
logger.error(e.getLocalizedMessage(), e);
|
|
||||||
}
|
|
||||||
return pidFieldNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ZenodoConfig> getZenodoConfig() {
|
|
||||||
if (zenodoConfig == null || zenodoConfig.isEmpty()) {
|
|
||||||
try {
|
|
||||||
zenodoConfig = mapper.readValue(getStreamFromPath(environment.getProperty("zenodo_plugin.configuration.zenodo")), new TypeReference<List<ZenodoConfig>>() {});
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e.getLocalizedMessage(), e);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return zenodoConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getLogo(String repositoryId) {
|
|
||||||
if (!zenodoConfig.isEmpty()) {
|
|
||||||
ZenodoConfig zenodoConfig = getZenodoConfig().stream().filter(x -> x.getRepositoryId().equals(repositoryId)).findFirst().orElse(null);
|
|
||||||
if (zenodoConfig != null) {
|
|
||||||
String logo = zenodoConfig.getLogo();
|
|
||||||
InputStream logoStream;
|
|
||||||
if (logo != null && !logo.isEmpty()) {
|
|
||||||
logoStream = getStreamFromPath(logo);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
logoStream = getClass().getClassLoader().getResourceAsStream("zenodo.jpg");
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return (logoStream != null) ? logoStream.readAllBytes() : null;
|
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InputStream getStreamFromPath(String filePath) {
|
|
||||||
try {
|
|
||||||
return new FileInputStream(filePath);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
logger.info("loading from classpath");
|
|
||||||
return getClass().getClassLoader().getResourceAsStream(filePath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package eu.eudat.depositinterface.zenodorepository.config;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
|
|
||||||
public class DOIFunder {
|
|
||||||
|
|
||||||
@JsonProperty("Funder")
|
|
||||||
private String funder;
|
|
||||||
@JsonProperty("DOI")
|
|
||||||
private String DOI;
|
|
||||||
|
|
||||||
public String getFunder() {
|
|
||||||
return funder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFunder(String funder) {
|
|
||||||
this.funder = funder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDOI() {
|
|
||||||
return DOI;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setDOI(String DOI) {
|
|
||||||
this.DOI = DOI;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
package eu.eudat.depositinterface.zenodorepository.config;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
|
|
||||||
public class PidFieldNames {
|
|
||||||
@JsonProperty("pidName")
|
|
||||||
private String pidName;
|
|
||||||
@JsonProperty("pidTypeName")
|
|
||||||
private String pidTypeName;
|
|
||||||
|
|
||||||
public PidFieldNames() {}
|
|
||||||
|
|
||||||
public PidFieldNames(String pidName, String pidTypeName) {
|
|
||||||
this.pidName = pidName;
|
|
||||||
this.pidTypeName = 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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,195 +0,0 @@
|
||||||
package eu.eudat.depositinterface.zenodorepository.config;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
|
||||||
import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration;
|
|
||||||
|
|
||||||
public class ZenodoConfig {
|
|
||||||
|
|
||||||
private enum DepositType {
|
|
||||||
SystemDeposit(0), UserDeposit(1), BothWaysDeposit(2);
|
|
||||||
|
|
||||||
private final int value;
|
|
||||||
|
|
||||||
DepositType(int value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DepositType fromInteger(int value) {
|
|
||||||
switch (value) {
|
|
||||||
case 0:
|
|
||||||
return SystemDeposit;
|
|
||||||
case 1:
|
|
||||||
return UserDeposit;
|
|
||||||
case 2:
|
|
||||||
return BothWaysDeposit;
|
|
||||||
default:
|
|
||||||
throw new RuntimeException("Unsupported Deposit Type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonProperty("depositType")
|
|
||||||
private int depositType;
|
|
||||||
@JsonProperty("repositoryId")
|
|
||||||
private String repositoryId;
|
|
||||||
@JsonProperty("accessToken")
|
|
||||||
private String accessToken;
|
|
||||||
@JsonProperty("repositoryUrl")
|
|
||||||
private String repositoryUrl;
|
|
||||||
@JsonProperty("repositoryAuthorizationUrl")
|
|
||||||
private String repositoryAuthorizationUrl;
|
|
||||||
@JsonProperty("repositoryRecordUrl")
|
|
||||||
private String repositoryRecordUrl;
|
|
||||||
@JsonProperty("repositoryAccessTokenUrl")
|
|
||||||
private String repositoryAccessTokenUrl;
|
|
||||||
@JsonProperty("repositoryClientId")
|
|
||||||
private String repositoryClientId;
|
|
||||||
@JsonProperty("repositoryClientSecret")
|
|
||||||
private String repositoryClientSecret;
|
|
||||||
@JsonProperty("redirectUri")
|
|
||||||
private String redirectUri;
|
|
||||||
@JsonProperty("hasLogo")
|
|
||||||
private boolean hasLogo;
|
|
||||||
@JsonProperty("logo")
|
|
||||||
private String logo;
|
|
||||||
@JsonProperty("doiFunder")
|
|
||||||
private String doiFunder;
|
|
||||||
@JsonProperty("community")
|
|
||||||
private String community;
|
|
||||||
@JsonProperty("affiliation")
|
|
||||||
private String affiliation;
|
|
||||||
@JsonProperty("domain")
|
|
||||||
private String domain;
|
|
||||||
|
|
||||||
public int getDepositType() {
|
|
||||||
return depositType;
|
|
||||||
}
|
|
||||||
public void setDepositType(int depositType) {
|
|
||||||
this.depositType = depositType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRepositoryId() {
|
|
||||||
return repositoryId;
|
|
||||||
}
|
|
||||||
public void setRepositoryId(String repositoryId) {
|
|
||||||
this.repositoryId = repositoryId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAccessToken() {
|
|
||||||
return accessToken;
|
|
||||||
}
|
|
||||||
public void setAccessToken(String accessToken) {
|
|
||||||
this.accessToken = accessToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRepositoryUrl() {
|
|
||||||
return repositoryUrl;
|
|
||||||
}
|
|
||||||
public void setRepositoryUrl(String repositoryUrl) {
|
|
||||||
this.repositoryUrl = repositoryUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRepositoryAuthorizationUrl() {
|
|
||||||
return repositoryAuthorizationUrl;
|
|
||||||
}
|
|
||||||
public void setRepositoryAuthorizationUrl(String repositoryAuthorizationUrl) {
|
|
||||||
this.repositoryAuthorizationUrl = repositoryAuthorizationUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRepositoryRecordUrl() {
|
|
||||||
return repositoryRecordUrl;
|
|
||||||
}
|
|
||||||
public void setRepositoryRecordUrl(String repositoryRecordUrl) {
|
|
||||||
this.repositoryRecordUrl = repositoryRecordUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRepositoryAccessTokenUrl() {
|
|
||||||
return repositoryAccessTokenUrl;
|
|
||||||
}
|
|
||||||
public void setRepositoryAccessTokenUrl(String repositoryAccessTokenUrl) {
|
|
||||||
this.repositoryAccessTokenUrl = repositoryAccessTokenUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRepositoryClientId() {
|
|
||||||
return repositoryClientId;
|
|
||||||
}
|
|
||||||
public void setRepositoryClientId(String repositoryClientId) {
|
|
||||||
this.repositoryClientId = repositoryClientId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRepositoryClientSecret() {
|
|
||||||
return repositoryClientSecret;
|
|
||||||
}
|
|
||||||
public void setRepositoryClientSecret(String repositoryClientSecret) {
|
|
||||||
this.repositoryClientSecret = repositoryClientSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRedirectUri() {
|
|
||||||
return redirectUri;
|
|
||||||
}
|
|
||||||
public void setRedirectUri(String redirectUri) {
|
|
||||||
this.redirectUri = redirectUri;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isHasLogo() {
|
|
||||||
return hasLogo;
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
config.setRepositoryId(this.repositoryId);
|
|
||||||
config.setAccessToken(this.accessToken);
|
|
||||||
config.setRepositoryUrl(this.repositoryUrl);
|
|
||||||
config.setRepositoryAuthorizationUrl(this.repositoryAuthorizationUrl);
|
|
||||||
config.setRepositoryRecordUrl(this.repositoryRecordUrl);
|
|
||||||
config.setRepositoryAccessTokenUrl(this.repositoryAccessTokenUrl);
|
|
||||||
config.setRepositoryClientId(this.repositoryClientId);
|
|
||||||
config.setRepositoryClientSecret(this.repositoryClientSecret);
|
|
||||||
config.setRedirectUri(this.redirectUri);
|
|
||||||
config.setHasLogo(this.hasLogo);
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,286 +0,0 @@
|
||||||
package eu.eudat.depositinterface.zenodorepository.interfaces;
|
|
||||||
|
|
||||||
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.config.ConfigLoader;
|
|
||||||
import eu.eudat.depositinterface.zenodorepository.config.ZenodoConfig;
|
|
||||||
import eu.eudat.depositinterface.zenodorepository.mapper.DMPToZenodoMapper;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.core.env.Environment;
|
|
||||||
import org.springframework.core.io.FileSystemResource;
|
|
||||||
import org.springframework.http.*;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
|
||||||
import org.springframework.util.MultiValueMap;
|
|
||||||
import org.springframework.web.client.HttpClientErrorException;
|
|
||||||
import org.springframework.web.client.HttpServerErrorException;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class ZenodoDeposit implements RepositoryDeposit {
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ZenodoDeposit.class);
|
|
||||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
|
||||||
|
|
||||||
private final ConfigLoader configLoader;
|
|
||||||
private final Environment environment;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public ZenodoDeposit(ConfigLoader configLoader, Environment environment){
|
|
||||||
this.configLoader = configLoader;
|
|
||||||
this.environment = environment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String deposit(String repositoryId, DMPDepositModel dmpDepositModel, String zenodoToken) throws Exception {
|
|
||||||
|
|
||||||
RepositoryDepositConfiguration conf = this.getConfiguration().stream().filter(x -> x.getRepositoryId().equals(repositoryId)).findFirst().orElse(null);
|
|
||||||
|
|
||||||
if(conf != null) {
|
|
||||||
|
|
||||||
if (zenodoToken == null) {
|
|
||||||
zenodoToken = conf.getAccessToken();
|
|
||||||
}
|
|
||||||
|
|
||||||
String zenodoUrl = conf.getRepositoryUrl();
|
|
||||||
|
|
||||||
// First step, post call to Zenodo, to create the entry.
|
|
||||||
RestTemplate restTemplate = new RestTemplate();
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
|
||||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
|
||||||
|
|
||||||
ZenodoConfig zenodoConfig = this.configLoader.getZenodoConfig().stream().filter(x -> x.getRepositoryId().equals(repositoryId)).findFirst().orElse(null);
|
|
||||||
eu.eudat.depositinterface.zenodorepository.models.ZenodoDeposit deposit = DMPToZenodoMapper.fromDMP(dmpDepositModel, zenodoConfig);
|
|
||||||
|
|
||||||
HttpEntity<eu.eudat.depositinterface.zenodorepository.models.ZenodoDeposit> request = new HttpEntity<>(deposit, headers);
|
|
||||||
Map createResponse;
|
|
||||||
LinkedHashMap<String, String> links;
|
|
||||||
String previousDOI = dmpDepositModel.getPreviousDOI();
|
|
||||||
String unpublishedUrl = null;
|
|
||||||
String publishUrl;
|
|
||||||
String finalDoi;
|
|
||||||
try {
|
|
||||||
|
|
||||||
if (previousDOI == null) {
|
|
||||||
String createUrl = zenodoUrl + "deposit/depositions" + "?access_token=" + zenodoToken;
|
|
||||||
createResponse = restTemplate.postForEntity(createUrl, request, Map.class).getBody();
|
|
||||||
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<Map[]> listResponses = restTemplate.getForEntity(listUrl, Map[].class);
|
|
||||||
createResponse = listResponses.getBody()[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 = restTemplate.postForObject(newVersionUrl, null, Map.class);
|
|
||||||
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 = restTemplate.getForObject(latestDraftUrl, Map.class);
|
|
||||||
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;
|
|
||||||
restTemplate.put(updateUrl, request);
|
|
||||||
//And finally remove pre-existing files from it
|
|
||||||
String fileListUrl = links.get("self") + "/files" + "?access_token=" + zenodoToken;
|
|
||||||
ResponseEntity<Map[]> fileListResponse = restTemplate.getForEntity(fileListUrl, Map[].class);
|
|
||||||
for (Map file : fileListResponse.getBody()) {
|
|
||||||
String fileDeleteUrl = links.get("self") + "/files/" + file.get("id") + "?access_token=" + zenodoToken;
|
|
||||||
restTemplate.delete(fileDeleteUrl);
|
|
||||||
}
|
|
||||||
} 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);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
String listUrl = zenodoUrl + "deposit/depositions" + "?q=conceptdoi:\"" + previousDOI + "\"&access_token=" + zenodoToken;
|
|
||||||
ResponseEntity<Map[]> listResponses = restTemplate.getForEntity(listUrl, Map[].class);
|
|
||||||
createResponse = listResponses.getBody()[0];
|
|
||||||
links = (LinkedHashMap<String, String>) createResponse.get("links");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unpublishedUrl == null) {
|
|
||||||
// Second step, add the file to the entry.
|
|
||||||
FileEnvelope pdfEnvelope = dmpDepositModel.getPdfFile();
|
|
||||||
FileSystemResource fileSystemResource = new FileSystemResource(pdfEnvelope.getFile());
|
|
||||||
HttpEntity<FileSystemResource> addFileMapRequest = new HttpEntity<>(fileSystemResource, null);
|
|
||||||
|
|
||||||
String addFileUrl = links.get("bucket") + "/" + pdfEnvelope.getFilename() + "?access_token=" + zenodoToken;
|
|
||||||
restTemplate.put(addFileUrl, addFileMapRequest);
|
|
||||||
|
|
||||||
FileEnvelope rdaJsonEnvelope = dmpDepositModel.getRdaJsonFile();
|
|
||||||
HttpHeaders responseHeaders = new HttpHeaders();
|
|
||||||
responseHeaders.setContentLength(rdaJsonEnvelope.getFile().length());
|
|
||||||
responseHeaders.setContentType(MediaType.APPLICATION_OCTET_STREAM);
|
|
||||||
responseHeaders.set("Content-Disposition", "attachment;filename=" + rdaJsonEnvelope.getFilename());
|
|
||||||
responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition");
|
|
||||||
responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type");
|
|
||||||
|
|
||||||
byte[] content = Files.readAllBytes(rdaJsonEnvelope.getFile().toPath());
|
|
||||||
|
|
||||||
ResponseEntity<byte[]> jsonFile = new ResponseEntity<>(content, responseHeaders, HttpStatus.OK);
|
|
||||||
|
|
||||||
UUID jsonFileUUID = UUID.randomUUID();
|
|
||||||
File tempJsonFile = new File(this.environment.getProperty("zenodo_plugin.storage.temp") + jsonFileUUID + ".json");
|
|
||||||
try (FileOutputStream jsonFos = new FileOutputStream(tempJsonFile)) {
|
|
||||||
jsonFos.write(jsonFile.getBody());
|
|
||||||
jsonFos.flush();
|
|
||||||
}
|
|
||||||
fileSystemResource = new FileSystemResource(tempJsonFile);
|
|
||||||
HttpHeaders jsonHeaders = new HttpHeaders();
|
|
||||||
jsonHeaders.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
|
||||||
addFileMapRequest = new HttpEntity<>(fileSystemResource, jsonHeaders);
|
|
||||||
String jsonFileName = jsonFile.getHeaders().get("Content-Disposition").get(0).substring(jsonFile.getHeaders().get("Content-Disposition").get(0).lastIndexOf('=') + 1);
|
|
||||||
addFileUrl = links.get("bucket") + "/" + jsonFileName + "?access_token=" + zenodoToken;
|
|
||||||
restTemplate.put(addFileUrl, addFileMapRequest);
|
|
||||||
Files.deleteIfExists(tempJsonFile.toPath());
|
|
||||||
|
|
||||||
if (dmpDepositModel.getSupportingFilesZip() != null) {
|
|
||||||
File supportinFilesZip = dmpDepositModel.getSupportingFilesZip();
|
|
||||||
String supportinFilesZipName = dmpDepositModel.getSupportingFilesZip().getName();
|
|
||||||
fileSystemResource = new FileSystemResource(supportinFilesZip);
|
|
||||||
addFileMapRequest = new HttpEntity<>(fileSystemResource, null);
|
|
||||||
|
|
||||||
addFileUrl = links.get("bucket") + "/" + supportinFilesZipName + "?access_token=" + zenodoToken;
|
|
||||||
restTemplate.put(addFileUrl, addFileMapRequest);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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){
|
|
||||||
RestTemplate restTemplate = new RestTemplate();
|
|
||||||
Map<String, Object> publishResponce = restTemplate.postForObject(publishUrl, "", Map.class);
|
|
||||||
return (String) publishResponce.get("conceptdoi");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<RepositoryDepositConfiguration> getConfiguration() {
|
|
||||||
List<ZenodoConfig> zenodoConfigs = this.configLoader.getZenodoConfig();
|
|
||||||
return (zenodoConfigs != null) ? zenodoConfigs.stream().map(ZenodoConfig::toRepoConfig).collect(Collectors.toList()) : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String authenticate(String repositoryId, String code){
|
|
||||||
|
|
||||||
RepositoryDepositConfiguration conf = this.getConfiguration().stream().filter(x -> x.getRepositoryId().equals(repositoryId)).findFirst().orElse(null);
|
|
||||||
|
|
||||||
if(conf != null) {
|
|
||||||
|
|
||||||
RestTemplate restTemplate = new RestTemplate();
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
|
||||||
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
|
|
||||||
|
|
||||||
MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
|
|
||||||
map.add("client_id", conf.getRepositoryClientId());
|
|
||||||
map.add("client_secret", conf.getRepositoryClientSecret());
|
|
||||||
map.add("grant_type", "authorization_code");
|
|
||||||
map.add("code", code);
|
|
||||||
map.add("redirect_uri", conf.getRedirectUri());
|
|
||||||
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(map, headers);
|
|
||||||
|
|
||||||
try {
|
|
||||||
Map<String, Object> values = restTemplate.postForObject(conf.getRepositoryAccessTokenUrl(), request, Map.class);
|
|
||||||
//ZenodoResponseToken zenodoResponseToken = new ZenodoResponseToken();
|
|
||||||
Map<String, Object> user = (Map<String, Object>) values.get("user");
|
|
||||||
// zenodoResponseToken.setUserId((String) user.get("id"));
|
|
||||||
// zenodoResponseToken.setEmail((String) user.get("email"));
|
|
||||||
// zenodoResponseToken.setExpiresIn((Integer) values.get("expires_in"));
|
|
||||||
// zenodoResponseToken.setAccessToken((String) values.get("access_token"));
|
|
||||||
// zenodoResponseToken.setRefreshToken((String) values.get("refresh_token"));
|
|
||||||
|
|
||||||
//return zenodoResponseToken;
|
|
||||||
return (String) values.get("access_token");
|
|
||||||
} catch (HttpClientErrorException ex) {
|
|
||||||
logger.error(ex.getResponseBodyAsString(), ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getLogo(String repositoryId) {
|
|
||||||
RepositoryDepositConfiguration conf = this.getConfiguration().stream().filter(x -> x.getRepositoryId().equals(repositoryId)).findFirst().orElse(null);
|
|
||||||
if(conf != null) {
|
|
||||||
if(conf.isHasLogo()){
|
|
||||||
byte[] logo = this.configLoader.getLogo(repositoryId);
|
|
||||||
return (logo != null && logo.length != 0) ? Base64.getEncoder().encodeToString(logo) : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getUnpublishedDOI(String zenodoUrl, String DOI, String token, Integer version) {
|
|
||||||
try {
|
|
||||||
RestTemplate restTemplate = new RestTemplate();
|
|
||||||
HttpHeaders headers = new HttpHeaders();
|
|
||||||
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
|
|
||||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
|
||||||
Map createResponse = null;
|
|
||||||
LinkedHashMap<String, String> links = null;
|
|
||||||
LinkedHashMap<String, String> metadata = null;
|
|
||||||
String listUrl = zenodoUrl + "deposit/depositions" + "?q=conceptdoi:\"" + DOI + "\"&access_token=" + token;
|
|
||||||
ResponseEntity<Map[]> listResponses = restTemplate.getForEntity(listUrl, Map[].class);
|
|
||||||
createResponse = listResponses.getBody()[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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,279 +0,0 @@
|
||||||
package eu.eudat.depositinterface.zenodorepository.mapper;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import eu.eudat.depositinterface.enums.FieldType;
|
|
||||||
import eu.eudat.depositinterface.models.*;
|
|
||||||
import eu.eudat.depositinterface.zenodorepository.config.ConfigLoader;
|
|
||||||
import eu.eudat.depositinterface.zenodorepository.config.DOIFunder;
|
|
||||||
import eu.eudat.depositinterface.zenodorepository.config.PidFieldNames;
|
|
||||||
import eu.eudat.depositinterface.zenodorepository.config.ZenodoConfig;
|
|
||||||
import eu.eudat.depositinterface.zenodorepository.models.*;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class DMPToZenodoMapper {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(DMPToZenodoMapper.class);
|
|
||||||
private static final ObjectMapper objectMapper = new ObjectMapper();
|
|
||||||
|
|
||||||
private static ConfigLoader configLoader;
|
|
||||||
private static PidFieldNames pidFieldNames;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public DMPToZenodoMapper(ConfigLoader configL){
|
|
||||||
configLoader = configL;
|
|
||||||
pidFieldNames = configLoader.getPidFieldNames();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<DatasetFieldsDepositModel> findSchemanticValues(String relatedId, List<DatasetFieldsDepositModel> fields){
|
|
||||||
return fields.stream().filter(f -> f.getSchematics().contains(relatedId)).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Set<String> extractSchemanticValues(List<DatasetFieldsDepositModel> fields, List<String> acceptedPidTypes) throws JsonProcessingException{
|
|
||||||
Set<String> values = new HashSet<>();
|
|
||||||
for(DatasetFieldsDepositModel field: fields){
|
|
||||||
String value = (String) field.getValue();
|
|
||||||
if(value != null && !value.isEmpty()) {
|
|
||||||
switch (FieldType.fromName(field.getRenderStyleType())) {
|
|
||||||
case FREE_TEXT:
|
|
||||||
case TEXT_AREA:
|
|
||||||
case RICH_TEXT_AREA:
|
|
||||||
case RADIO_BOX:
|
|
||||||
case DATE_PICKER:
|
|
||||||
values.add(value);
|
|
||||||
break;
|
|
||||||
case COMBO_BOX:
|
|
||||||
if (field.isMultiple()) {
|
|
||||||
List<String> selected = objectMapper.readValue(value, new TypeReference<List<String>>() {});
|
|
||||||
values.addAll(selected);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
values.add(value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case REGISTRIES:
|
|
||||||
case SERVICES:
|
|
||||||
case EXTERNAL_DATASETS:
|
|
||||||
case DATA_REPOSITORIES:
|
|
||||||
case PUB_REPOSITORIES:
|
|
||||||
case JOURNAL_REPOSITORIES:
|
|
||||||
case TAXONOMIES:
|
|
||||||
case PUBLICATIONS:
|
|
||||||
if (field.isMultiple()) {
|
|
||||||
List<String> selected = objectMapper.readValue(value, new TypeReference<List<String>>() {});
|
|
||||||
for (String s : selected) {
|
|
||||||
Map<String, String> valueMap = objectMapper.readValue(s, new TypeReference<Map<String, String>>() {});
|
|
||||||
String pid = valueMap.get(pidFieldNames.getPidName());
|
|
||||||
String pidType = valueMap.get(pidFieldNames.getPidTypeName());
|
|
||||||
if (acceptedPidTypes.contains(pidType)) {
|
|
||||||
values.add(pid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Map<String, String> valueMap = objectMapper.readValue(value, new TypeReference<Map<String, String>>() {});
|
|
||||||
String pid = valueMap.get(pidFieldNames.getPidName());
|
|
||||||
String pidType = valueMap.get(pidFieldNames.getPidTypeName());
|
|
||||||
if (acceptedPidTypes.contains(pidType)) {
|
|
||||||
values.add(pid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ORGANIZATIONS:
|
|
||||||
case RESEARCHERS:
|
|
||||||
if (field.isMultiple()) {
|
|
||||||
List<String> selected = objectMapper.readValue(value, new TypeReference<List<String>>() {});
|
|
||||||
for (String s : selected) {
|
|
||||||
Map<String, String> valueMap = objectMapper.readValue(s, new TypeReference<Map<String, String>>() {});
|
|
||||||
String pid = valueMap.get("reference");
|
|
||||||
if(pid != null) {
|
|
||||||
values.add(pid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Map<String, String> valueMap = objectMapper.readValue(value, new TypeReference<Map<String, String>>() {});
|
|
||||||
String pid = valueMap.get("reference");
|
|
||||||
if(pid != null) {
|
|
||||||
values.add(pid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case DATASET_IDENTIFIER:
|
|
||||||
Map<String, String> valueMap = objectMapper.readValue(value, new TypeReference<Map<String, String>>() {});
|
|
||||||
values.add(valueMap.get("identifier"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ZenodoDeposit fromDMP(DMPDepositModel dmp, ZenodoConfig zenodoConfig) throws JsonProcessingException {
|
|
||||||
Map<String, Object> extraProperties = dmp.getExtraProperties() != null ? new org.json.JSONObject(dmp.getExtraProperties()).toMap() : new HashMap<>();
|
|
||||||
ZenodoDeposit deposit = new ZenodoDeposit();
|
|
||||||
|
|
||||||
Map<String, Object> schematicsMap = new HashMap<>();
|
|
||||||
|
|
||||||
List<ZenodoRelator> relatedIdentifiers = new ArrayList<>();
|
|
||||||
List<ZenodoComunity> communities = new ArrayList<>();
|
|
||||||
List<ZenodoContributor> contributors = new ArrayList<>();
|
|
||||||
List<ZenodoCreator> creators = new ArrayList<>();
|
|
||||||
List<ZenodoGrant> grants = new ArrayList<>();
|
|
||||||
List<String> keywords = new ArrayList<>();
|
|
||||||
List<String> references = new ArrayList<>();
|
|
||||||
|
|
||||||
List<String> acceptedPidTypes = configLoader.getAcceptedPidTypes();
|
|
||||||
|
|
||||||
for(DatasetDepositModel dataset: dmp.getDatasets()){
|
|
||||||
|
|
||||||
for(String relatedId: configLoader.getRelatedIdentifiers()){
|
|
||||||
|
|
||||||
List<DatasetFieldsDepositModel> fields = findSchemanticValues(relatedId, dataset.getFields());
|
|
||||||
Set<String> values = extractSchemanticValues(fields, acceptedPidTypes);
|
|
||||||
for(String value: values){
|
|
||||||
ZenodoRelator relator = new ZenodoRelator();
|
|
||||||
relator.setRelation(relatedId.substring(relatedId.lastIndexOf(".") + 1));
|
|
||||||
relator.setIdentifier(value);
|
|
||||||
relatedIdentifiers.add(relator);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
schematicsMap.put("related_identifiers", relatedIdentifiers);
|
|
||||||
schematicsMap.put("communities", communities);
|
|
||||||
schematicsMap.put("contributors", contributors);
|
|
||||||
schematicsMap.put("creators", creators);
|
|
||||||
schematicsMap.put("grants", grants);
|
|
||||||
schematicsMap.put("keywords", keywords);
|
|
||||||
schematicsMap.put("references", references);
|
|
||||||
|
|
||||||
String schematicsString = objectMapper.writeValueAsString(schematicsMap);
|
|
||||||
objectMapper.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
|
|
||||||
ZenodoDepositMetadata metadata = objectMapper.readValue(schematicsString, new TypeReference<ZenodoDepositMetadata>(){});
|
|
||||||
|
|
||||||
deposit.setMetadata(metadata);
|
|
||||||
deposit.getMetadata().setTitle(dmp.getLabel());
|
|
||||||
deposit.getMetadata().setUploadType("publication");
|
|
||||||
deposit.getMetadata().setPublicationType("datamanagementplan");
|
|
||||||
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();
|
|
||||||
community.setIdentifier(zenodoCommunity);
|
|
||||||
deposit.getMetadata().getCommunities().add(community);
|
|
||||||
}
|
|
||||||
if (extraProperties.get("visible") == null) {
|
|
||||||
deposit.getMetadata().setAccessRight(ZenodoAccessRight.RESTRICTED);
|
|
||||||
deposit.getMetadata().setAccessConditions("");
|
|
||||||
} else {
|
|
||||||
if (((Boolean) extraProperties.get("visible"))) {
|
|
||||||
Instant publicationDate = Instant.parse(extraProperties.get("publicDate").toString());
|
|
||||||
if (publicationDate.isBefore(Instant.now())) {
|
|
||||||
deposit.getMetadata().setAccessRight(ZenodoAccessRight.OPEN);
|
|
||||||
} else {
|
|
||||||
deposit.getMetadata().setAccessRight(ZenodoAccessRight.EMBARGOED);
|
|
||||||
deposit.getMetadata().setEmbargoDate(publicationDate.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extraProperties.get("license") != null) {
|
|
||||||
deposit.getMetadata().setLicense(((Map<?, ?>) extraProperties.get("license")).get("pid").toString());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
deposit.getMetadata().setAccessRight(ZenodoAccessRight.RESTRICTED);
|
|
||||||
deposit.getMetadata().setAccessConditions("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dmp.isPublic()) {
|
|
||||||
ZenodoRelator relator = new ZenodoRelator();
|
|
||||||
relator.setIdentifier(zenodoConfig.getDomain() + "/external/zenodo/" + dmp.getId().toString());
|
|
||||||
relator.setRelation("isIdenticalTo");
|
|
||||||
deposit.getMetadata().getRelatedIdentifiers().add(relator);
|
|
||||||
}
|
|
||||||
String zenodoAffiliation = zenodoConfig.getAffiliation();
|
|
||||||
List<ZenodoContributor> contributors1 = dmp.getUsers().stream().map(userDMP -> {
|
|
||||||
ZenodoContributor contributor = new ZenodoContributor();
|
|
||||||
contributor.setName(userDMP.getUser().getName());
|
|
||||||
contributor.setType("ProjectMember");
|
|
||||||
if (dmp.getOrganisations() != null && !dmp.getOrganisations().isEmpty()) {
|
|
||||||
contributor.setAffiliation(dmp.getOrganisations()
|
|
||||||
.stream().map(OrganisationDepositModel::getLabel).collect(Collectors.joining(", ")));
|
|
||||||
} else {
|
|
||||||
if(zenodoAffiliation != null && !zenodoAffiliation.isEmpty()) {
|
|
||||||
contributor.setAffiliation(zenodoAffiliation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return contributor;
|
|
||||||
}).collect(Collectors.toList());
|
|
||||||
|
|
||||||
List<ZenodoContributor> researchers = dmp.getResearchers().stream().map(researcher -> {
|
|
||||||
ZenodoContributor contributor = new ZenodoContributor();
|
|
||||||
contributor.setName(researcher.getLabel());
|
|
||||||
contributor.setType("Researcher");
|
|
||||||
String referenceHead = researcher.getReference().split(":")[0];
|
|
||||||
String referenceTail = researcher.getReference().replace(referenceHead + ":", "");
|
|
||||||
contributor.setAffiliation(referenceHead);
|
|
||||||
if (referenceHead.equalsIgnoreCase("ORCID")) {
|
|
||||||
contributor.setOrcid(referenceTail);
|
|
||||||
}
|
|
||||||
return contributor;
|
|
||||||
}).collect(Collectors.toList());
|
|
||||||
|
|
||||||
deposit.getMetadata().getContributors().addAll(contributors1);
|
|
||||||
deposit.getMetadata().getContributors().addAll(researchers);
|
|
||||||
|
|
||||||
if (dmp.getGrant() != null) {
|
|
||||||
if (dmp.getGrant().getReference() == null) {
|
|
||||||
dmp.getGrant().setReference("dmp:" + dmp.getGrant().getId());
|
|
||||||
}
|
|
||||||
String grantReferenceHead = dmp.getGrant().getReference().split(":")[0];
|
|
||||||
if (grantReferenceHead.equals("openaire")) {
|
|
||||||
String grantReferenceTail = dmp.getGrant().getReference().split(":")[3];
|
|
||||||
List<DOIFunder> doiFunders = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
List<Map<String, Object>> tempdoiFunders = objectMapper.readValue(configLoader.getStreamFromPath(zenodoConfig.getDoiFunder()), List.class);
|
|
||||||
doiFunders = tempdoiFunders.stream().map(map -> objectMapper.convertValue(map, DOIFunder.class)).collect(Collectors.toList());
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.error(e.getLocalizedMessage(), e);
|
|
||||||
}
|
|
||||||
if (dmp.getGrant().getFunder() != null && dmp.getGrant().getFunder().getLabel() != null) {
|
|
||||||
DOIFunder doiFunder = doiFunders.stream()
|
|
||||||
.filter(doiFunder1 -> dmp.getGrant().getFunder().getLabel().contains(doiFunder1.getFunder()) || doiFunder1.getFunder().contains(dmp.getGrant().getFunder().getLabel()))
|
|
||||||
.findFirst().orElse(null);
|
|
||||||
if (doiFunder != null) {
|
|
||||||
String finalId = doiFunder.getDOI() + "::" + grantReferenceTail;
|
|
||||||
ZenodoGrant grant = new ZenodoGrant();
|
|
||||||
grant.setId(finalId);
|
|
||||||
deposit.getMetadata().getGrants().add(grant);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ZenodoCreator creator = new ZenodoCreator();
|
|
||||||
creator.setName(dmp.getUsers().stream().filter(userDMP -> userDMP.getRole().equals(UserDMPDepositModel.UserDMPRoles.OWNER.getValue())).findFirst().get().getUser().getName());
|
|
||||||
if (dmp.getOrganisations() != null && !dmp.getOrganisations().isEmpty()) {
|
|
||||||
creator.setAffiliation(dmp.getOrganisations()
|
|
||||||
.stream().map(OrganisationDepositModel::getLabel).collect(Collectors.joining(", ")));
|
|
||||||
} else {
|
|
||||||
if(zenodoAffiliation != null && !zenodoAffiliation.isEmpty()) {
|
|
||||||
creator.setAffiliation(zenodoAffiliation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
deposit.getMetadata().getCreators().add(creator);
|
|
||||||
|
|
||||||
return deposit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
package eu.eudat.depositinterface.zenodorepository.models;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonValue;
|
|
||||||
|
|
||||||
public enum ZenodoAccessRight {
|
|
||||||
RESTRICTED("restricted"), EMBARGOED("embargoed"), OPEN("open");
|
|
||||||
|
|
||||||
private final String value;
|
|
||||||
|
|
||||||
ZenodoAccessRight(String value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonValue
|
|
||||||
public String getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
[
|
|
||||||
{
|
|
||||||
"Funder": "Australian Research Council",
|
|
||||||
"DOI": "10.13039/501100000923"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Funder": "Austrian Science Fund",
|
|
||||||
"DOI": "10.13039/501100002428"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Funder": "European Commission",
|
|
||||||
"DOI": "10.13039/501100000780"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Funder": "European Environment Agency",
|
|
||||||
"DOI": "10.13039/501100000806"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Funder": "Academy of Finland",
|
|
||||||
"DOI": "10.13039/501100002341"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Funder": "Hrvatska Zaklada za Znanost",
|
|
||||||
"DOI": "10.13039/501100004488"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Funder": "Fundação para a Ciência e a Tecnologia",
|
|
||||||
"DOI": "10.13039/501100001871"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Funder": "Ministarstvo Prosvete, Nauke i Tehnološkog Razvoja",
|
|
||||||
"DOI": "10.13039/501100004564"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Funder": "Ministarstvo Znanosti, Obrazovanja i Sporta",
|
|
||||||
"DOI": "10.13039/501100006588"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Funder": "National Health and Medical Research Council",
|
|
||||||
"DOI": "10.13039/501100000925"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Funder": "National Institutes of Health",
|
|
||||||
"DOI": "10.13039/100000002"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Funder": "National Science Foundation",
|
|
||||||
"DOI": "10.13039/100000001"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Funder": "Nederlandse Organisatie voor Wetenschappelijk Onderzoek",
|
|
||||||
"DOI": "10.13039/501100003246"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Funder": "Research Councils",
|
|
||||||
"DOI": "10.13039/501100000690"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Funder": "Schweizerischer Nationalfonds zur Förderung der wissenschaftlichen Forschung",
|
|
||||||
"DOI": "10.13039/501100001711"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Funder": "Science Foundation Ireland",
|
|
||||||
"DOI": "10.13039/501100001602"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Funder": "Wellcome Trust",
|
|
||||||
"DOI": "10.13039/100004440"
|
|
||||||
}
|
|
||||||
]
|
|
|
@ -1,43 +0,0 @@
|
||||||
actrn
|
|
||||||
ark
|
|
||||||
bibcode
|
|
||||||
nct
|
|
||||||
drks
|
|
||||||
doi
|
|
||||||
euctr
|
|
||||||
data.europa.eu
|
|
||||||
epo_id
|
|
||||||
GRID
|
|
||||||
gsk
|
|
||||||
GeoPass
|
|
||||||
GBIF
|
|
||||||
hal
|
|
||||||
handle
|
|
||||||
isrctn
|
|
||||||
ichushi
|
|
||||||
ISNI
|
|
||||||
jprn
|
|
||||||
mag_id
|
|
||||||
NAID
|
|
||||||
NCID
|
|
||||||
oai
|
|
||||||
orcid_pending
|
|
||||||
orcid
|
|
||||||
OrgPeg
|
|
||||||
PANGAEA
|
|
||||||
PIC
|
|
||||||
epo_nr_epodoc
|
|
||||||
pdb
|
|
||||||
pmc
|
|
||||||
pmid
|
|
||||||
RNSR
|
|
||||||
ROR
|
|
||||||
RRID
|
|
||||||
UNKNOWN
|
|
||||||
VIAF
|
|
||||||
who
|
|
||||||
arXiv
|
|
||||||
info:eu-repo/dai
|
|
||||||
orcidworkid
|
|
||||||
urn
|
|
||||||
w3id
|
|
|
@ -1,2 +0,0 @@
|
||||||
zenodo_plugin.storage.temp=${STORAGE_TMP_ZENODO}
|
|
||||||
zenodo_plugin.configuration.zenodo=${CONFIGURATION_ZENODO}
|
|
|
@ -1,4 +0,0 @@
|
||||||
{
|
|
||||||
"pidName": "pid",
|
|
||||||
"pidTypeName": "pidTypeField"
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
zenodo.related_identifiers.isCitedBy
|
|
||||||
zenodo.related_identifiers.cites
|
|
||||||
zenodo.related_identifiers.isSupplementTo
|
|
||||||
zenodo.related_identifiers.isSupplementedBy
|
|
||||||
zenodo.related_identifiers.isContinuedBy
|
|
||||||
zenodo.related_identifiers.continues
|
|
||||||
zenodo.related_identifiers.isDescribedBy
|
|
||||||
zenodo.related_identifiers.describes
|
|
||||||
zenodo.related_identifiers.hasMetadata
|
|
||||||
zenodo.related_identifiers.isMetadataFor
|
|
||||||
zenodo.related_identifiers.isNewVersionOf
|
|
||||||
zenodo.related_identifiers.isPreviousVersionOf
|
|
||||||
zenodo.related_identifiers.isPartOf
|
|
||||||
zenodo.related_identifiers.hasPart
|
|
||||||
zenodo.related_identifiers.isReferencedBy
|
|
||||||
zenodo.related_identifiers.references
|
|
||||||
zenodo.related_identifiers.isDocumentedBy
|
|
||||||
zenodo.related_identifiers.documents
|
|
||||||
zenodo.related_identifiers.isCompiledBy
|
|
||||||
zenodo.related_identifiers.compiles
|
|
||||||
zenodo.related_identifiers.isVariantFormOf
|
|
||||||
zenodo.related_identifiers.isOriginalFormof
|
|
||||||
zenodo.related_identifiers.isIdenticalTo
|
|
||||||
zenodo.related_identifiers.isAlternateIdentifier
|
|
||||||
zenodo.related_identifiers.isReviewedBy
|
|
||||||
zenodo.related_identifiers.reviews
|
|
||||||
zenodo.related_identifiers.isDerivedFrom
|
|
||||||
zenodo.related_identifiers.isSourceOf
|
|
||||||
zenodo.related_identifiers.requires
|
|
||||||
zenodo.related_identifiers.isRequiredBy
|
|
||||||
zenodo.related_identifiers.isObsoletedBy
|
|
||||||
zenodo.related_identifiers.obsoletes
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.opencdmp</groupId>
|
||||||
|
<artifactId>repository-deposit-parent</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>repository-deposit-web</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>21</maven.compiler.source>
|
||||||
|
<maven.compiler.target>21</maven.compiler.target>
|
||||||
|
<maven.compiler.release>21</maven.compiler.release>
|
||||||
|
<java.version>21</java.version>
|
||||||
|
<revision>1.0.0-SNAPSHOT</revision>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>gr.cite</groupId>
|
||||||
|
<artifactId>oidc-authn</artifactId>
|
||||||
|
<version>2.2.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>gr.cite</groupId>
|
||||||
|
<artifactId>cache</artifactId>
|
||||||
|
<version>2.1.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>gr.cite</groupId>
|
||||||
|
<artifactId>exceptions-web</artifactId>
|
||||||
|
<version>2.2.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-cache</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.opencdmp</groupId>
|
||||||
|
<artifactId>repositorydepositzenodo</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
<configuration>
|
||||||
|
<source>21</source>
|
||||||
|
<target>21</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,17 @@
|
||||||
|
package org.opencdmp.deposit;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
@SpringBootApplication(scanBasePackages = {
|
||||||
|
"org.opencdmp.deposit.*",
|
||||||
|
"org.opencdmp.depositbase.*",
|
||||||
|
"gr.cite.tools",
|
||||||
|
"gr.cite.commons"
|
||||||
|
})
|
||||||
|
public class DepositApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(DepositApplication.class, args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package org.opencdmp.deposit.config;
|
||||||
|
|
||||||
|
import gr.cite.commons.web.oidc.configuration.WebSecurityProperties;
|
||||||
|
import gr.cite.commons.web.oidc.configuration.filter.ApiKeyFilter;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.authentication.AuthenticationManagerResolver;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
|
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;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableWebSecurity
|
||||||
|
public class SecurityConfiguration {
|
||||||
|
|
||||||
|
private final WebSecurityProperties webSecurityProperties;
|
||||||
|
private final AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public SecurityConfiguration(WebSecurityProperties webSecurityProperties, AuthenticationManagerResolver<HttpServletRequest> authenticationManagerResolver) {
|
||||||
|
this.webSecurityProperties = webSecurityProperties;
|
||||||
|
this.authenticationManagerResolver = authenticationManagerResolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||||
|
http.csrf(AbstractHttpConfigurer::disable)
|
||||||
|
.cors(Customizer.withDefaults())
|
||||||
|
.authorizeHttpRequests(authorizationManagerRequestMatcherRegistry -> authorizationManagerRequestMatcherRegistry
|
||||||
|
.requestMatchers(buildAntPatterns(webSecurityProperties.getAuthorizedEndpoints())).authenticated()
|
||||||
|
.requestMatchers(buildAntPatterns(webSecurityProperties.getAllowedEndpoints())).anonymous())
|
||||||
|
.sessionManagement(httpSecuritySessionManagementConfigurer -> httpSecuritySessionManagementConfigurer.sessionCreationPolicy(SessionCreationPolicy.NEVER))
|
||||||
|
.oauth2ResourceServer(oauth2 -> oauth2.authenticationManagerResolver(authenticationManagerResolver));
|
||||||
|
return http.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] buildAntPatterns(Set<String> endpoints) {
|
||||||
|
if (endpoints == null) {
|
||||||
|
return new String[0];
|
||||||
|
}
|
||||||
|
return endpoints.stream()
|
||||||
|
.filter(endpoint -> endpoint != null && !endpoint.isBlank())
|
||||||
|
.map(endpoint -> "/" + stripUnnecessaryCharacters(endpoint) + "/**")
|
||||||
|
.toArray(String[]::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String stripUnnecessaryCharacters(String endpoint) {
|
||||||
|
endpoint = endpoint.strip();
|
||||||
|
if (endpoint.startsWith("/")) {
|
||||||
|
endpoint = endpoint.substring(1);
|
||||||
|
}
|
||||||
|
if (endpoint.endsWith("/")) {
|
||||||
|
endpoint = endpoint.substring(0, endpoint.length() - 1);
|
||||||
|
}
|
||||||
|
return endpoint;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
package org.opencdmp.deposit.controller;
|
||||||
|
|
||||||
|
import gr.cite.tools.auditing.AuditService;
|
||||||
|
import gr.cite.tools.logging.LoggerService;
|
||||||
|
import gr.cite.tools.logging.MapLogEntry;
|
||||||
|
import org.opencdmp.commonmodels.models.plan.PlanModel;
|
||||||
|
import org.opencdmp.deposit.zenodorepository.audit.AuditableAction;
|
||||||
|
import org.opencdmp.depositbase.repository.DepositConfiguration;
|
||||||
|
import org.opencdmp.deposit.zenodorepository.service.zenodo.ZenodoDepositService;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.AbstractMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/deposit")
|
||||||
|
public class DepositController implements org.opencdmp.depositbase.repository.DepositController {
|
||||||
|
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DepositController.class));
|
||||||
|
|
||||||
|
private final ZenodoDepositService depositClient;
|
||||||
|
|
||||||
|
private final AuditService auditService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public DepositController(ZenodoDepositService depositClient, AuditService auditService) {
|
||||||
|
this.depositClient = depositClient;
|
||||||
|
this.auditService = auditService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String deposit(@RequestBody PlanModel planModel, @RequestParam("authToken")String authToken) throws Exception {
|
||||||
|
logger.debug(new MapLogEntry("deposit " + PlanModel.class.getSimpleName()).And("planModel", planModel));
|
||||||
|
|
||||||
|
String doiId = depositClient.deposit(planModel, authToken);
|
||||||
|
|
||||||
|
this.auditService.track(AuditableAction.Deposit_Deposit, Map.ofEntries(
|
||||||
|
new AbstractMap.SimpleEntry<String, Object>("planModel", planModel)
|
||||||
|
));
|
||||||
|
return doiId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String authenticate(@RequestParam("authToken") String code) {
|
||||||
|
logger.debug(new MapLogEntry("authenticate " + PlanModel.class.getSimpleName()));
|
||||||
|
|
||||||
|
String token = depositClient.authenticate(code);
|
||||||
|
|
||||||
|
this.auditService.track(AuditableAction.Deposit_Authenticate);
|
||||||
|
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DepositConfiguration getConfiguration() {
|
||||||
|
logger.debug(new MapLogEntry("getConfiguration " + PlanModel.class.getSimpleName()));
|
||||||
|
|
||||||
|
DepositConfiguration configuration = depositClient.getConfiguration();
|
||||||
|
|
||||||
|
this.auditService.track(AuditableAction.Deposit_GetConfiguration);
|
||||||
|
|
||||||
|
return configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLogo() {
|
||||||
|
logger.debug(new MapLogEntry("getLogo " + PlanModel.class.getSimpleName()));
|
||||||
|
|
||||||
|
String logo = depositClient.getLogo();
|
||||||
|
|
||||||
|
this.auditService.track(AuditableAction.Deposit_GetLogo);
|
||||||
|
|
||||||
|
return logo;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,202 @@
|
||||||
|
package org.opencdmp.deposit.controller.controllerhandler;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
|
import gr.cite.tools.exception.*;
|
||||||
|
import gr.cite.tools.logging.LoggerService;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
import org.springframework.web.context.request.WebRequest;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@RestControllerAdvice
|
||||||
|
@ControllerAdvice
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(GlobalExceptionHandler.class));
|
||||||
|
|
||||||
|
private final ObjectMapper objectMapper;
|
||||||
|
|
||||||
|
public GlobalExceptionHandler() {
|
||||||
|
this.objectMapper = new ObjectMapper();
|
||||||
|
this.objectMapper.registerModule(new JavaTimeModule());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ExceptionHandler(Exception.class)
|
||||||
|
public ResponseEntity<?> handleUnexpectedErrors(Exception exception, WebRequest request) throws Exception {
|
||||||
|
HandledException handled = this.handleException(exception, request);
|
||||||
|
this.log(handled.getLevel(), exception, MessageFormat.format("returning code {0} and payload {1}", handled.getStatusCode(), handled.getMessage()));
|
||||||
|
return new ResponseEntity<>(handled.getMessage(), handled.getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toJsonSafe(Object item) {
|
||||||
|
if (item == null) return null;
|
||||||
|
try {
|
||||||
|
return this.objectMapper.writeValueAsString(item);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void log(System.Logger.Level level, Exception e, String message) {
|
||||||
|
if (level != null) {
|
||||||
|
switch (level) {
|
||||||
|
case TRACE:
|
||||||
|
logger.trace(message, e);
|
||||||
|
break;
|
||||||
|
case DEBUG:
|
||||||
|
logger.debug(message, e);
|
||||||
|
break;
|
||||||
|
case INFO:
|
||||||
|
logger.info(message, e);
|
||||||
|
break;
|
||||||
|
case WARNING:
|
||||||
|
logger.warn(message, e);
|
||||||
|
break;
|
||||||
|
case ERROR:
|
||||||
|
logger.error(message, e);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logger.error(e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public HandledException handleException(Exception exception, WebRequest request) throws Exception {
|
||||||
|
HttpStatus statusCode;
|
||||||
|
Map<String, Object> result;
|
||||||
|
System.Logger.Level logLevel;
|
||||||
|
|
||||||
|
switch (exception){
|
||||||
|
case MyNotFoundException myNotFoundException -> {
|
||||||
|
logLevel = System.Logger.Level.DEBUG;
|
||||||
|
statusCode = HttpStatus.NOT_FOUND;
|
||||||
|
int code = myNotFoundException.getCode();
|
||||||
|
if (code > 0) {
|
||||||
|
result = Map.ofEntries(
|
||||||
|
Map.entry("code", code),
|
||||||
|
Map.entry("error", myNotFoundException.getMessage())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = Map.ofEntries(
|
||||||
|
Map.entry("error", myNotFoundException.getMessage())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case MyUnauthorizedException myUnauthorizedException -> {
|
||||||
|
logLevel = System.Logger.Level.DEBUG;
|
||||||
|
statusCode = HttpStatus.UNAUTHORIZED;
|
||||||
|
int code = myUnauthorizedException.getCode();
|
||||||
|
if (code > 0) {
|
||||||
|
result = Map.ofEntries(
|
||||||
|
Map.entry("code", code),
|
||||||
|
Map.entry("error", myUnauthorizedException.getMessage())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = Map.ofEntries(
|
||||||
|
Map.entry("error", myUnauthorizedException.getMessage())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case MyForbiddenException myForbiddenException -> {
|
||||||
|
logLevel = System.Logger.Level.DEBUG;
|
||||||
|
statusCode = HttpStatus.FORBIDDEN;
|
||||||
|
int code = myForbiddenException.getCode();
|
||||||
|
if (code > 0) {
|
||||||
|
result = Map.ofEntries(
|
||||||
|
Map.entry("code", code),
|
||||||
|
Map.entry("error", myForbiddenException.getMessage())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = Map.ofEntries(
|
||||||
|
Map.entry("error", myForbiddenException.getMessage())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case MyValidationException myValidationException -> {
|
||||||
|
logLevel = System.Logger.Level.DEBUG;
|
||||||
|
statusCode = HttpStatus.BAD_REQUEST;
|
||||||
|
int code = myValidationException.getCode();
|
||||||
|
|
||||||
|
result = new HashMap<>();
|
||||||
|
if (code > 0) result.put("code", code);
|
||||||
|
if (myValidationException.getMessage() != null) result.put("error", myValidationException.getMessage());
|
||||||
|
if (myValidationException.getErrors() != null) result.put("message", myValidationException.getErrors());
|
||||||
|
}
|
||||||
|
case MyApplicationException myApplicationException -> {
|
||||||
|
logLevel = System.Logger.Level.ERROR;
|
||||||
|
statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
|
||||||
|
int code = myApplicationException.getCode();
|
||||||
|
if (code > 0) {
|
||||||
|
result = Map.ofEntries(
|
||||||
|
Map.entry("code", code),
|
||||||
|
Map.entry("error", myApplicationException.getMessage())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = Map.ofEntries(
|
||||||
|
Map.entry("error", myApplicationException.getMessage())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default -> {
|
||||||
|
logLevel = System.Logger.Level.ERROR;
|
||||||
|
statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
|
||||||
|
result = Map.ofEntries(
|
||||||
|
Map.entry("error", "System error")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
String serialization = this.toJsonSafe(result);
|
||||||
|
return new HandledException(statusCode, serialization, logLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HandledException{
|
||||||
|
public HttpStatus statusCode;
|
||||||
|
public String message;
|
||||||
|
public System.Logger.Level level;
|
||||||
|
|
||||||
|
public HandledException(HttpStatus statusCode, String message, System.Logger.Level level) {
|
||||||
|
this.statusCode = statusCode;
|
||||||
|
this.message = message;
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HttpStatus getStatusCode() {
|
||||||
|
return statusCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatusCode(HttpStatus statusCode) {
|
||||||
|
this.statusCode = statusCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public System.Logger.Level getLevel() {
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLevel(System.Logger.Level level) {
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
spring:
|
||||||
|
jackson:
|
||||||
|
default-property-inclusion: non_null
|
||||||
|
config:
|
||||||
|
import: optional:classpath:config/app.env[.properties], optional:file:../config/app.env[.properties],
|
||||||
|
optional:classpath:config/server.yml[.yml], optional:classpath:config/server-${spring.profiles.active}.yml[.yml], optional:file:../config/server-${spring.profiles.active}.yml[.yml],
|
||||||
|
optional:classpath:config/logging.yml[.yml], optional:classpath:config/logging-${spring.profiles.active}.yml[.yml], optional:file:../config/logging-${spring.profiles.active}.yml[.yml],
|
||||||
|
optional:classpath:config/zenodo.yml[.yml], optional:classpath:config/zenodo-${spring.profiles.active}.yml[.yml], optional:file:../config/zenodo-${spring.profiles.active}.yml[.yml],
|
||||||
|
optional:classpath:config/pid.yml[.yml], optional:classpath:config/pid-${spring.profiles.active}.yml[.yml], optional:file:../config/pid-${spring.profiles.active}.yml[.yml],
|
||||||
|
optional:classpath:config/funder.yml[.yml], optional:classpath:config/funder-${spring.profiles.active}.yml[.yml], optional:file:../config/funder-${spring.profiles.active}.yml[.yml],
|
||||||
|
optional:classpath:config/identifiers.yml[.yml], optional:classpath:config/identifiers-${spring.profiles.active}.yml[.yml], optional:file:../config/identifiers-${spring.profiles.active}.yml[.yml],
|
||||||
|
optional:classpath:config/security.yml[.yml], optional:classpath:config/security-${spring.profiles.active}.yml[.yml], optional:file:../config/security-${spring.profiles.active}.yml[.yml],
|
||||||
|
optional:classpath:config/cache.yml[.yml], optional:classpath:config/cache-${spring.profiles.active}.yml[.yml], optional:file:../config/cache-${spring.profiles.active}.yml[.yml],
|
||||||
|
optional:classpath:config/idpclaims.yml[.yml], optional:classpath:config/idpclaims-${spring.profiles.active}.yml[.yml], optional:file:../config/idpclaims-${spring.profiles.active}.yml[.yml]
|
|
@ -0,0 +1,18 @@
|
||||||
|
cache:
|
||||||
|
manager:
|
||||||
|
fallbackToNoOpCache: true
|
||||||
|
caffeineCaches:
|
||||||
|
- names: [ "logoByRepository" ]
|
||||||
|
allowNullValues: true
|
||||||
|
initialCapacity: 100
|
||||||
|
maximumSize: 500
|
||||||
|
enableRecordStats: false
|
||||||
|
expireAfterWriteMinutes: 10
|
||||||
|
expireAfterAccessMinutes: 10
|
||||||
|
refreshAfterWriteMinutes: 10
|
||||||
|
mapCaches:
|
||||||
|
logoByRepository:
|
||||||
|
name: logoByRepository
|
||||||
|
keyPattern: zenodoplugin_$repo$:v0
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
funder:
|
||||||
|
available:
|
||||||
|
- funder: "Austrian Science Fund"
|
||||||
|
doi: "10.13039/501100002428"
|
||||||
|
- funder: "European Commission"
|
||||||
|
doi: "10.13039/501100000780"
|
||||||
|
- funder: "European Environment Agency"
|
||||||
|
doi: "10.13039/501100000806"
|
||||||
|
- funder: "Academy of Finland"
|
||||||
|
doi: "10.13039/501100002341"
|
||||||
|
- funder: "Hrvatska Zaklada za Znanost"
|
||||||
|
doi: "10.13039/501100004488"
|
||||||
|
- funder: "Fundação para a Ciência e a Tecnologia"
|
||||||
|
doi: "10.13039/501100001871"
|
||||||
|
- funder: "Ministarstvo Prosvete, Nauke i Tehnološkog Razvoja"
|
||||||
|
doi: "10.13039/501100004564"
|
||||||
|
- funder: "Ministarstvo Znanosti, Obrazovanja i Sporta"
|
||||||
|
doi: "10.13039/501100006588"
|
||||||
|
- funder: "National Health and Medical Research Council"
|
||||||
|
doi: "10.13039/501100000925"
|
||||||
|
- funder: "National Institutes of Health"
|
||||||
|
doi: "10.13039/100000002"
|
||||||
|
- funder: "National Science Foundation"
|
||||||
|
doi: "10.13039/100000001"
|
||||||
|
- funder: "Nederlandse Organisatie voor Wetenschappelijk Onderzoek"
|
||||||
|
doi: "10.13039/501100003246"
|
||||||
|
- funder: "Research Councils"
|
||||||
|
doi: "10.13039/501100000690"
|
||||||
|
- funder: "Schweizerischer Nationalfonds zur Förderung der wissenschaftlichen Forschung"
|
||||||
|
doi: "10.13039/501100001711"
|
||||||
|
- funder: "Science Foundation Ireland"
|
||||||
|
doi: "10.13039/501100001602"
|
||||||
|
- funder: "Wellcome Trust"
|
||||||
|
doi: "10.13039/100004440"
|
|
@ -0,0 +1,34 @@
|
||||||
|
identifiers:
|
||||||
|
related:
|
||||||
|
- zenodo.related_identifiers.isCitedBy
|
||||||
|
- zenodo.related_identifiers.cites
|
||||||
|
- zenodo.related_identifiers.isSupplementTo
|
||||||
|
- zenodo.related_identifiers.isSupplementedBy
|
||||||
|
- zenodo.related_identifiers.isContinuedBy
|
||||||
|
- zenodo.related_identifiers.continues
|
||||||
|
- zenodo.related_identifiers.isDescribedBy
|
||||||
|
- zenodo.related_identifiers.describes
|
||||||
|
- zenodo.related_identifiers.hasMetadata
|
||||||
|
- zenodo.related_identifiers.isMetadataFor
|
||||||
|
- zenodo.related_identifiers.isNewVersionOf
|
||||||
|
- zenodo.related_identifiers.isPreviousVersionOf
|
||||||
|
- zenodo.related_identifiers.isPartOf
|
||||||
|
- zenodo.related_identifiers.hasPart
|
||||||
|
- zenodo.related_identifiers.isReferencedBy
|
||||||
|
- zenodo.related_identifiers.references
|
||||||
|
- zenodo.related_identifiers.isDocumentedBy
|
||||||
|
- zenodo.related_identifiers.documents
|
||||||
|
- zenodo.related_identifiers.isCompiledBy
|
||||||
|
- zenodo.related_identifiers.compiles
|
||||||
|
- zenodo.related_identifiers.isVariantFormOf
|
||||||
|
- zenodo.related_identifiers.isOriginalFormof
|
||||||
|
- zenodo.related_identifiers.isIdenticalTo
|
||||||
|
- zenodo.related_identifiers.isAlternateIdentifier
|
||||||
|
- zenodo.related_identifiers.isReviewedBy
|
||||||
|
- zenodo.related_identifiers.reviews
|
||||||
|
- zenodo.related_identifiers.isDerivedFrom
|
||||||
|
- zenodo.related_identifiers.isSourceOf
|
||||||
|
- zenodo.related_identifiers.requires
|
||||||
|
- zenodo.related_identifiers.isRequiredBy
|
||||||
|
- zenodo.related_identifiers.isObsoletedBy
|
||||||
|
- zenodo.related_identifiers.obsoletes
|
|
@ -0,0 +1,41 @@
|
||||||
|
idpclient:
|
||||||
|
claims:
|
||||||
|
mapping:
|
||||||
|
Subject:
|
||||||
|
- type: sub
|
||||||
|
Name:
|
||||||
|
- type: name
|
||||||
|
Client:
|
||||||
|
- type: client_id
|
||||||
|
AuthenticationMethod:
|
||||||
|
- type: amr
|
||||||
|
NotBefore:
|
||||||
|
- type: nbf
|
||||||
|
AuthenticatedAt:
|
||||||
|
- type: auth_time
|
||||||
|
ExpiresAt:
|
||||||
|
- type: exp
|
||||||
|
Email:
|
||||||
|
- type: email
|
||||||
|
Roles:
|
||||||
|
- type: resource_access
|
||||||
|
path: dmp_zenodo_bridge.roles
|
||||||
|
Scope:
|
||||||
|
- type: scope
|
||||||
|
AccessToken:
|
||||||
|
- type: x-access-token
|
||||||
|
visibility: SENSITIVE
|
||||||
|
IssuedAt:
|
||||||
|
- type: iat
|
||||||
|
Issuer:
|
||||||
|
- type: iss
|
||||||
|
Audience:
|
||||||
|
- type: aud
|
||||||
|
TokenType:
|
||||||
|
- type: typ
|
||||||
|
AuthorizedParty:
|
||||||
|
- type: azp
|
||||||
|
Authorities:
|
||||||
|
- type: authorities
|
||||||
|
ExternalProviderName:
|
||||||
|
- type: identity_provider
|
|
@ -0,0 +1,36 @@
|
||||||
|
logging:
|
||||||
|
config: classpath:logging/logback-${spring.profiles.active}.xml
|
||||||
|
context:
|
||||||
|
request:
|
||||||
|
requestIdKey: req.id
|
||||||
|
requestRemoteHostKey: req.remoteHost
|
||||||
|
requestUriKey: req.requestURI
|
||||||
|
requestQueryStringKey: req.queryString
|
||||||
|
requestUrlKey : req.requestURL
|
||||||
|
requestMethodKey: req.method
|
||||||
|
requestUserAgentKey: req.userAgent
|
||||||
|
requestForwardedForKey: req.xForwardedFor
|
||||||
|
requestSchemeKey: req.scheme
|
||||||
|
requestRemoteAddressKey: req.remoteAddr
|
||||||
|
requestRemotePortKey: req.remotePort
|
||||||
|
requestRemoteUserKey: req.remoteUser
|
||||||
|
principal:
|
||||||
|
subjectKey: usr.subject
|
||||||
|
nameKey: usr.name
|
||||||
|
clientKey: usr.client
|
||||||
|
audit:
|
||||||
|
enable: true
|
||||||
|
requestRemoteHostKey: req.remoteHost
|
||||||
|
requestUriKey: req.requestURI
|
||||||
|
requestQueryStringKey: req.queryString
|
||||||
|
requestUrlKey : req.requestURL
|
||||||
|
requestMethodKey: req.method
|
||||||
|
requestUserAgentKey: req.userAgent
|
||||||
|
requestForwardedForKey: req.xForwardedFor
|
||||||
|
requestSchemeKey: req.scheme
|
||||||
|
requestRemoteAddressKey: req.remoteAddr
|
||||||
|
requestRemotePortKey: req.remotePort
|
||||||
|
requestRemoteUserKey: req.remoteUser
|
||||||
|
principalSubjectKey: usr.subject
|
||||||
|
principalNameKey: usr.name
|
||||||
|
principalClientKey: usr.client
|
|
@ -0,0 +1,35 @@
|
||||||
|
logging:
|
||||||
|
context:
|
||||||
|
request:
|
||||||
|
requestIdKey: req.id
|
||||||
|
requestRemoteHostKey: req.remoteHost
|
||||||
|
requestUriKey: req.requestURI
|
||||||
|
requestQueryStringKey: req.queryString
|
||||||
|
requestUrlKey : req.requestURL
|
||||||
|
requestMethodKey: req.method
|
||||||
|
requestUserAgentKey: req.userAgent
|
||||||
|
requestForwardedForKey: req.xForwardedFor
|
||||||
|
requestSchemeKey: req.scheme
|
||||||
|
requestRemoteAddressKey: req.remoteAddr
|
||||||
|
requestRemotePortKey: req.remotePort
|
||||||
|
requestRemoteUserKey: req.remoteUser
|
||||||
|
principal:
|
||||||
|
subjectKey: usr.subject
|
||||||
|
nameKey: usr.name
|
||||||
|
clientKey: usr.client
|
||||||
|
audit:
|
||||||
|
enable: true
|
||||||
|
requestRemoteHostKey: req.remoteHost
|
||||||
|
requestUriKey: req.requestURI
|
||||||
|
requestQueryStringKey: req.queryString
|
||||||
|
requestUrlKey : req.requestURL
|
||||||
|
requestMethodKey: req.method
|
||||||
|
requestUserAgentKey: req.userAgent
|
||||||
|
requestForwardedForKey: req.xForwardedFor
|
||||||
|
requestSchemeKey: req.scheme
|
||||||
|
requestRemoteAddressKey: req.remoteAddr
|
||||||
|
requestRemotePortKey: req.remotePort
|
||||||
|
requestRemoteUserKey: req.remoteUser
|
||||||
|
principalSubjectKey: usr.subject
|
||||||
|
principalNameKey: usr.name
|
||||||
|
principalClientKey: usr.client
|
|
@ -0,0 +1,48 @@
|
||||||
|
pid:
|
||||||
|
fields:
|
||||||
|
pid-name: pid
|
||||||
|
pid-type-name: pidTypeField
|
||||||
|
accepted-types:
|
||||||
|
- actrn
|
||||||
|
- ark
|
||||||
|
- bibcode
|
||||||
|
- nct
|
||||||
|
- drks
|
||||||
|
- doi
|
||||||
|
- euctr
|
||||||
|
- data.europa.eu
|
||||||
|
- epo_id
|
||||||
|
- GRID
|
||||||
|
- gsk
|
||||||
|
- GeoPass
|
||||||
|
- GBIF
|
||||||
|
- hal
|
||||||
|
- handle
|
||||||
|
- isrctn
|
||||||
|
- ichushi
|
||||||
|
- ISNI
|
||||||
|
- jprn
|
||||||
|
- mag_id
|
||||||
|
- NAID
|
||||||
|
- NCID
|
||||||
|
- oai
|
||||||
|
- orcid_pending
|
||||||
|
- orcid
|
||||||
|
- OrgPeg
|
||||||
|
- PANGAEA
|
||||||
|
- PIC
|
||||||
|
- epo_nr_epodoc
|
||||||
|
- pdb
|
||||||
|
- pmc
|
||||||
|
- pmid
|
||||||
|
- RNSR
|
||||||
|
- ROR
|
||||||
|
- RRID
|
||||||
|
- UNKNOWN
|
||||||
|
- VIAF
|
||||||
|
- who
|
||||||
|
- arXiv
|
||||||
|
- info:eu-repo/dai
|
||||||
|
- orcidworkid
|
||||||
|
- urn
|
||||||
|
- w3id
|
|
@ -0,0 +1,6 @@
|
||||||
|
web:
|
||||||
|
security:
|
||||||
|
idp:
|
||||||
|
resource:
|
||||||
|
jwt:
|
||||||
|
audiences: [ "dmp_zenodo_bridge" ]
|
|
@ -0,0 +1,14 @@
|
||||||
|
web:
|
||||||
|
security:
|
||||||
|
enabled: true
|
||||||
|
authorized-endpoints: [ api ]
|
||||||
|
allowed-endpoints: [ health ]
|
||||||
|
idp:
|
||||||
|
api-key:
|
||||||
|
enabled: false
|
||||||
|
resource:
|
||||||
|
token-type: JWT #| opaque
|
||||||
|
jwt:
|
||||||
|
claims: [ role, x-role ]
|
||||||
|
issuer-uri: ${IDP_ISSUER_URI}
|
||||||
|
validIssuer: ${IDP_ISSUER_URI}
|
|
@ -0,0 +1,12 @@
|
||||||
|
server:
|
||||||
|
port: 8082
|
||||||
|
tomcat:
|
||||||
|
threads:
|
||||||
|
max: 20
|
||||||
|
max-connections: 10000
|
||||||
|
|
||||||
|
spring:
|
||||||
|
servlet:
|
||||||
|
multipart:
|
||||||
|
max-file-size: 10MB
|
||||||
|
max-request-size: 10MB
|
|
@ -0,0 +1,4 @@
|
||||||
|
file:
|
||||||
|
storage:
|
||||||
|
temp: ${STORAGE_PATH}/tmp
|
||||||
|
transient-path: ${STORAGE_PATH}/shared
|
|
@ -0,0 +1,8 @@
|
||||||
|
zenodo:
|
||||||
|
community: argos
|
||||||
|
affiliation: ARGOS
|
||||||
|
domain: https://argos.openaire.eu/
|
||||||
|
logo: classpath:zenodo.jpg
|
||||||
|
depositConfiguration:
|
||||||
|
has-logo: true
|
||||||
|
useSharedStorage: false
|
|
@ -0,0 +1,25 @@
|
||||||
|
zenodo:
|
||||||
|
organizationReferenceCode: "organisations"
|
||||||
|
grantReferenceCode: "grants"
|
||||||
|
funderReferenceCode: "funders"
|
||||||
|
researcherReferenceCode: "researchers"
|
||||||
|
licenceReferenceCode: "licenses"
|
||||||
|
projectReferenceCode: "projects"
|
||||||
|
datasetReferenceCode: "datasets"
|
||||||
|
publicationReferenceCode: "publications"
|
||||||
|
openaireGrantSourceCode: "openaire"
|
||||||
|
orcidResearcherSourceCode: "ORCID"
|
||||||
|
maxInMemorySizeInBytes: 6554000
|
||||||
|
depositConfiguration:
|
||||||
|
deposit-type: 2
|
||||||
|
repository-id: zenodo
|
||||||
|
access-token: ${ZENODO_ACCESS_TOKEN}
|
||||||
|
repository-url: ${ZENODO_URL}
|
||||||
|
repository-authorization-url: ${ZENODO_AUTHORIZATION_URL}
|
||||||
|
repository-record-url: ${ZENODO_RECORD_URL}
|
||||||
|
repository-access-token-url: ${ZENODO_ACCESS_TOKEN_URL}
|
||||||
|
repository-client-id: ${ZENODO_CLIENT_ID}
|
||||||
|
repository-client-secret: ${ZENODO_CLIENT_SECRET}
|
||||||
|
redirect-uri: ${REDIRECT_URL}
|
||||||
|
has-logo: true
|
||||||
|
useSharedStorage: false
|
|
@ -0,0 +1,62 @@
|
||||||
|
<configuration debug="true">
|
||||||
|
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||||
|
<Pattern>%date{ISO8601} [%thread] %-5level %logger{36} [%X{req.id}] - %message%n</Pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="TROUBLESHOOTING" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>logs/logging.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>logs/logging.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||||
|
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||||
|
<maxFileSize>100MB</maxFileSize>
|
||||||
|
</timeBasedFileNamingAndTriggeringPolicy>
|
||||||
|
<maxHistory>15</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||||
|
<Pattern>%date{ISO8601} [%thread] %-5level %logger{36} [%X{req.id}] - %message%n</Pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="AUDITING" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>logs/auditing.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<fileNamePattern>logs/auditing.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||||
|
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||||
|
<maxFileSize>100MB</maxFileSize>
|
||||||
|
</timeBasedFileNamingAndTriggeringPolicy>
|
||||||
|
<maxHistory>15</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||||
|
<Pattern>%date{ISO8601} - %X{req.id} - %message%n</Pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
|
||||||
|
<logger name="org.springframework.web" level="INFO" additivity="false">
|
||||||
|
<appender-ref ref="TROUBLESHOOTING"/>
|
||||||
|
<appender-ref ref="STDOUT"/>
|
||||||
|
</logger>
|
||||||
|
<logger name="org.hibernate" level="INFO" additivity="false">
|
||||||
|
<appender-ref ref="TROUBLESHOOTING"/>
|
||||||
|
<appender-ref ref="STDOUT"/>
|
||||||
|
</logger>
|
||||||
|
<logger name="gr.cite" level="DEBUG" additivity="false">
|
||||||
|
<appender-ref ref="TROUBLESHOOTING"/>
|
||||||
|
<appender-ref ref="STDOUT"/>
|
||||||
|
</logger>
|
||||||
|
<logger name="org.opencdmp" level="DEBUG" additivity="false">
|
||||||
|
<appender-ref ref="TROUBLESHOOTING"/>
|
||||||
|
<appender-ref ref="STDOUT"/>
|
||||||
|
</logger>
|
||||||
|
<logger name="audit" level="INFO" additivity="false">
|
||||||
|
<appender-ref ref="AUDITING"/>
|
||||||
|
<appender-ref ref="STDOUT"/>
|
||||||
|
</logger>
|
||||||
|
<root level="info">
|
||||||
|
<appender-ref ref="TROUBLESHOOTING"/>
|
||||||
|
<appender-ref ref="STDOUT"/>
|
||||||
|
</root>
|
||||||
|
</configuration>
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
Loading…
Reference in New Issue