From 7dd2030eb3bcc59876c6f415c210c8008781a08d Mon Sep 17 00:00:00 2001 From: Aldo Mihasi Date: Mon, 24 Oct 2022 09:35:49 +0300 Subject: [PATCH 01/26] [WIP] create deposit interface and implement multiple deposit repositories --- dmp-backend/depositinterface/pom.xml | 23 +++ .../models/DMPDepositModel.java | 122 ++++++++++++++ .../models/FunderDepositModel.java | 12 ++ .../models/GrantDepositModel.java | 30 ++++ .../models/OrganisationDepositModel.java | 12 ++ .../models/ResearcherDepositModel.java | 20 +++ .../models/UserDMPDepositModel.java | 47 ++++++ .../models/UserInfoDepositModel.java | 12 ++ .../repository/RepositoryDeposit.java | 13 ++ .../RepositoryDepositConfiguration.java | 96 +++++++++++ .../target/maven-archiver/pom.properties | 3 + dmp-backend/pom.xml | 1 + dmp-backend/web/pom.xml | 10 +- .../main/java/eu/eudat/EuDatApplication.java | 2 +- .../eudat/controllers/DepositController.java | 39 +++++ .../managers/DataManagementPlanManager.java | 157 +++-------------- .../eudat/logic/managers/DepositManager.java | 40 +++++ .../eudat/logic/proxy/config/DOIFunder.java | 27 --- .../config/configloaders/ConfigLoader.java | 2 - .../configloaders/DefaultConfigLoader.java | 14 -- .../mapper/DMPToDepositMapper.java | 72 ++++++++ .../deposit/zenodo/ZenodoAccessRight.java | 18 -- .../models/deposit/zenodo/ZenodoComunity.java | 19 --- .../deposit/zenodo/ZenodoContributor.java | 45 ----- .../models/deposit/zenodo/ZenodoDeposit.java | 19 --- .../deposit/zenodo/ZenodoDepositMetadata.java | 159 ------------------ .../models/deposit/zenodo/ZenodoGrant.java | 18 -- .../models/deposit/zenodo/ZenodoRelator.java | 28 --- .../zenodo/mapper/DMPToZenodoMapper.java | 115 ------------- .../src/app/core/core-service.module.ts | 2 + .../deposit-repositories.service.ts | 20 +++ dmp-frontend/src/app/ui/dmp/dmp.module.ts | 7 +- .../dmp-deposit-dialog.component.html | 25 +++ .../dmp-deposit-dialog.component.scss | 0 .../dmp-deposit-dialog.component.ts | 35 ++++ .../dmp/overview/dmp-overview.component.html | 2 +- .../ui/dmp/overview/dmp-overview.component.ts | 25 +++ 37 files changed, 691 insertions(+), 600 deletions(-) create mode 100644 dmp-backend/depositinterface/pom.xml create mode 100644 dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/DMPDepositModel.java create mode 100644 dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/FunderDepositModel.java create mode 100644 dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/GrantDepositModel.java create mode 100644 dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/OrganisationDepositModel.java create mode 100644 dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/ResearcherDepositModel.java create mode 100644 dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/UserDMPDepositModel.java create mode 100644 dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/UserInfoDepositModel.java create mode 100644 dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/repository/RepositoryDeposit.java create mode 100644 dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/repository/RepositoryDepositConfiguration.java create mode 100644 dmp-backend/depositinterface/target/maven-archiver/pom.properties create mode 100644 dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java delete mode 100644 dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/DOIFunder.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/logic/security/repositorydeposit/mapper/DMPToDepositMapper.java delete mode 100644 dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoAccessRight.java delete mode 100644 dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoComunity.java delete mode 100644 dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoContributor.java delete mode 100644 dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoDeposit.java delete mode 100644 dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoDepositMetadata.java delete mode 100644 dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoGrant.java delete mode 100644 dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoRelator.java delete mode 100644 dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/mapper/DMPToZenodoMapper.java create mode 100644 dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts create mode 100644 dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.html create mode 100644 dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.scss create mode 100644 dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts diff --git a/dmp-backend/depositinterface/pom.xml b/dmp-backend/depositinterface/pom.xml new file mode 100644 index 000000000..8899237cf --- /dev/null +++ b/dmp-backend/depositinterface/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + + eu.eudat + dmp-backend + 1.0.0-SNAPSHOT + + + depositinterface + 1.0-SNAPSHOT + jar + + + + org.springframework.boot + spring-boot-starter-web + + + + diff --git a/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/DMPDepositModel.java b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/DMPDepositModel.java new file mode 100644 index 000000000..15fdd8e24 --- /dev/null +++ b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/DMPDepositModel.java @@ -0,0 +1,122 @@ +package eu.eudat.depositinterface.models; + +import org.springframework.http.ResponseEntity; + +import java.io.File; +import java.util.Set; +import java.util.UUID; + +public class DMPDepositModel { + private UUID id; + private int version; + private String label; + private String description; + private boolean isPublic; + private Set users; + private Set organisations; + private Set researchers; + private GrantDepositModel grant; + private File pdfFile; + private String pdfFileName; + private ResponseEntity rdaJson; + private String previousDOI; + private String extraProperties; + + public UUID getId() { + return id; + } + public void setId(UUID id) { + this.id = id; + } + + public int getVersion() { + return version; + } + public void setVersion(int version) { + this.version = version; + } + + public String getLabel() { + return label; + } + public void setLabel(String label) { + this.label = label; + } + + public String getDescription() { + return description; + } + public void setDescription(String description) { + this.description = description; + } + + public boolean isPublic() { + return isPublic; + } + public void setPublic(boolean aPublic) { + isPublic = aPublic; + } + + public Set getUsers() { + return users; + } + public void setUsers(Set users) { + this.users = users; + } + + public Set getOrganisations() { + return organisations; + } + public void setOrganisations(Set organisations) { + this.organisations = organisations; + } + + public Set getResearchers() { + return researchers; + } + public void setResearchers(Set researchers) { + this.researchers = researchers; + } + + public GrantDepositModel getGrant() { + return grant; + } + public void setGrant(GrantDepositModel grant) { + this.grant = grant; + } + + public File getPdfFile() { + return pdfFile; + } + public void setPdfFile(File pdfFile) { + this.pdfFile = pdfFile; + } + + public String getPdfFileName() { + return pdfFileName; + } + public void setPdfFileName(String pdfFileName) { + this.pdfFileName = pdfFileName; + } + + public ResponseEntity getRdaJson() { + return rdaJson; + } + public void setRdaJson(ResponseEntity rdaJson) { + this.rdaJson = rdaJson; + } + + public String getPreviousDOI() { + return previousDOI; + } + public void setPreviousDOI(String previousDOI) { + this.previousDOI = previousDOI; + } + + public String getExtraProperties() { + return extraProperties; + } + public void setExtraProperties(String extraProperties) { + this.extraProperties = extraProperties; + } +} diff --git a/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/FunderDepositModel.java b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/FunderDepositModel.java new file mode 100644 index 000000000..a7b505c1f --- /dev/null +++ b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/FunderDepositModel.java @@ -0,0 +1,12 @@ +package eu.eudat.depositinterface.models; + +public class FunderDepositModel { + private String label; + + public String getLabel() { + return label; + } + public void setLabel(String label) { + this.label = label; + } +} diff --git a/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/GrantDepositModel.java b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/GrantDepositModel.java new file mode 100644 index 000000000..fc7cffd7c --- /dev/null +++ b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/GrantDepositModel.java @@ -0,0 +1,30 @@ +package eu.eudat.depositinterface.models; + +import java.util.UUID; + +public class GrantDepositModel { + private UUID id; + private String reference; + private FunderDepositModel funder; + + public UUID getId() { + return id; + } + public void setId(UUID id) { + this.id = id; + } + + public String getReference() { + return reference; + } + public void setReference(String reference) { + this.reference = reference; + } + + public FunderDepositModel getFunder() { + return funder; + } + public void setFunder(FunderDepositModel funder) { + this.funder = funder; + } +} diff --git a/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/OrganisationDepositModel.java b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/OrganisationDepositModel.java new file mode 100644 index 000000000..86ea84cb5 --- /dev/null +++ b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/OrganisationDepositModel.java @@ -0,0 +1,12 @@ +package eu.eudat.depositinterface.models; + +public class OrganisationDepositModel { + private String label; + + public String getLabel() { + return label; + } + public void setLabel(String label) { + this.label = label; + } +} diff --git a/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/ResearcherDepositModel.java b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/ResearcherDepositModel.java new file mode 100644 index 000000000..f6aa0378d --- /dev/null +++ b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/ResearcherDepositModel.java @@ -0,0 +1,20 @@ +package eu.eudat.depositinterface.models; + +public class ResearcherDepositModel { + private String label; + private String reference; + + public String getLabel() { + return label; + } + public void setLabel(String label) { + this.label = label; + } + + public String getReference() { + return reference; + } + public void setReference(String reference) { + this.reference = reference; + } +} diff --git a/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/UserDMPDepositModel.java b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/UserDMPDepositModel.java new file mode 100644 index 000000000..e7dae22b7 --- /dev/null +++ b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/UserDMPDepositModel.java @@ -0,0 +1,47 @@ +package eu.eudat.depositinterface.models; + +public class UserDMPDepositModel { + + public enum UserDMPRoles { + OWNER(0), USER(1); + + private int value; + + UserDMPRoles(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + + public static UserDMPRoles fromInteger(int value) { + switch (value) { + case 0: + return OWNER; + case 1: + return USER; + default: + throw new RuntimeException("Unsupported User Dmp Role Message Code"); + } + } + } + + private UserInfoDepositModel user; + private Integer role; + + public UserInfoDepositModel getUser() { + return user; + } + public void setUser(UserInfoDepositModel user) { + this.user = user; + } + + public Integer getRole() { + return role; + } + public void setRole(Integer role) { + this.role = role; + } +} diff --git a/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/UserInfoDepositModel.java b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/UserInfoDepositModel.java new file mode 100644 index 000000000..2b8cec04e --- /dev/null +++ b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/UserInfoDepositModel.java @@ -0,0 +1,12 @@ +package eu.eudat.depositinterface.models; + +public class UserInfoDepositModel { + private String name; + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } +} diff --git a/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/repository/RepositoryDeposit.java b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/repository/RepositoryDeposit.java new file mode 100644 index 000000000..59f6b43c2 --- /dev/null +++ b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/repository/RepositoryDeposit.java @@ -0,0 +1,13 @@ +package eu.eudat.depositinterface.repository; + +import eu.eudat.depositinterface.models.DMPDepositModel; + +public interface RepositoryDeposit { + + String deposit(DMPDepositModel dmpDepositModel, boolean update, String repositoryAccessToken) throws Exception; + + //authenticate(); + + RepositoryDepositConfiguration getConfiguration(); + +} diff --git a/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/repository/RepositoryDepositConfiguration.java b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/repository/RepositoryDepositConfiguration.java new file mode 100644 index 000000000..5504ad25b --- /dev/null +++ b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/repository/RepositoryDepositConfiguration.java @@ -0,0 +1,96 @@ +package eu.eudat.depositinterface.repository; + +public class RepositoryDepositConfiguration { + + public enum DepositAccountStatus { + SystemDeposit(0), UserDeposit(1), BothWaysDeposit(2); + + private int value; + + DepositAccountStatus(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static DepositAccountStatus fromInteger(int value) { + switch (value) { + case 0: + return SystemDeposit; + case 1: + return UserDeposit; + case 2: + return BothWaysDeposit; + default: + throw new RuntimeException("Unsupported Deposit Account Status"); + } + } + } + + private int depositAccountStatus; + private String repositoryId; + private String accessToken; + private String repositoryUrl; + private String repositoryLoginAccessTokenUrl; + private String repositoryLoginClientId; + private String repositoryLoginClientSecret; + private String repositoryLoginRedirectUri; // + + public int getDepositAccountStatus() { + return depositAccountStatus; + } + public void setDepositAccountStatus(int depositAccountStatus) { + this.depositAccountStatus = depositAccountStatus; + } + + 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 getRepositoryLoginAccessTokenUrl() { + return repositoryLoginAccessTokenUrl; + } + public void setRepositoryLoginAccessTokenUrl(String repositoryLoginAccessTokenUrl) { + this.repositoryLoginAccessTokenUrl = repositoryLoginAccessTokenUrl; + } + + public String getRepositoryLoginClientId() { + return repositoryLoginClientId; + } + public void setRepositoryLoginClientId(String repositoryLoginClientId) { + this.repositoryLoginClientId = repositoryLoginClientId; + } + + public String getRepositoryLoginClientSecret() { + return repositoryLoginClientSecret; + } + public void setRepositoryLoginClientSecret(String repositoryLoginClientSecret) { + this.repositoryLoginClientSecret = repositoryLoginClientSecret; + } + + public String getRepositoryLoginRedirectUri() { + return repositoryLoginRedirectUri; + } + public void setRepositoryLoginRedirectUri(String repositoryLoginRedirectUri) { + this.repositoryLoginRedirectUri = repositoryLoginRedirectUri; + } +} diff --git a/dmp-backend/depositinterface/target/maven-archiver/pom.properties b/dmp-backend/depositinterface/target/maven-archiver/pom.properties new file mode 100644 index 000000000..20bd9443f --- /dev/null +++ b/dmp-backend/depositinterface/target/maven-archiver/pom.properties @@ -0,0 +1,3 @@ +artifactId=depositinterface +groupId=eu.eudat +version=1.0-SNAPSHOT diff --git a/dmp-backend/pom.xml b/dmp-backend/pom.xml index daf645f04..27be888d0 100644 --- a/dmp-backend/pom.xml +++ b/dmp-backend/pom.xml @@ -18,6 +18,7 @@ web data elastic + depositinterface diff --git a/dmp-backend/web/pom.xml b/dmp-backend/web/pom.xml index 6d05bdeb8..8170c8cee 100644 --- a/dmp-backend/web/pom.xml +++ b/dmp-backend/web/pom.xml @@ -26,13 +26,16 @@ queryable 1.0-SNAPSHOT - eu.eudat elastic 1.0.0-SNAPSHOT - + + eu.eudat + depositinterface + 1.0-SNAPSHOT + @@ -219,6 +222,9 @@ org.springframework.boot spring-boot-maven-plugin + + ZIP + diff --git a/dmp-backend/web/src/main/java/eu/eudat/EuDatApplication.java b/dmp-backend/web/src/main/java/eu/eudat/EuDatApplication.java index 31e87ddf5..5ed228762 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/EuDatApplication.java +++ b/dmp-backend/web/src/main/java/eu/eudat/EuDatApplication.java @@ -8,7 +8,7 @@ import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.scheduling.annotation.EnableAsync; -@SpringBootApplication +@SpringBootApplication(scanBasePackages = {"eu.eudat", "eu.eudat.depositinterface"}) @EnableAsync public class EuDatApplication extends SpringBootServletInitializer { private static final Logger logger = LoggerFactory.getLogger(EuDatApplication.class); diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java new file mode 100644 index 000000000..599871b01 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java @@ -0,0 +1,39 @@ +package eu.eudat.controllers; + +import eu.eudat.logic.managers.DepositManager; +import eu.eudat.logic.security.claims.ClaimedAuthorities; +import eu.eudat.logic.services.ApiContext; +import eu.eudat.models.data.helpers.responses.ResponseItem; +import eu.eudat.models.data.security.Principal; +import eu.eudat.types.ApiMessageCode; +import eu.eudat.types.Authorities; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@CrossOrigin +@RequestMapping(value = {"/api/deposit/"}) +public class DepositController extends BaseController { + private static final Logger logger = LoggerFactory.getLogger(DepositController.class); + + private DepositManager depositManager; + + @Autowired + public DepositController(ApiContext apiContext, DepositManager depositManager){ + super(apiContext); + this.depositManager = depositManager; + } + + @RequestMapping(method = RequestMethod.GET, value = {"/repos"}) + public @ResponseBody + ResponseEntity>> getAvailableRepos(@ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws Exception { + List ids = this.depositManager.getAvailableRepos(); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(ids)); + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java index f492e2a9d..7bc65f570 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java @@ -15,6 +15,8 @@ import eu.eudat.data.enumeration.notification.NotifyState; import eu.eudat.data.query.items.table.dataset.DatasetTableRequest; import eu.eudat.data.query.items.table.datasetprofile.DatasetProfileTableRequestItem; import eu.eudat.data.query.items.table.dmp.DataManagementPlanTableRequest; +import eu.eudat.depositinterface.models.DMPDepositModel; +import eu.eudat.depositinterface.repository.RepositoryDeposit; import eu.eudat.elastic.criteria.DmpCriteria; import eu.eudat.elastic.entities.Collaborator; import eu.eudat.elastic.entities.Dmp; @@ -29,6 +31,7 @@ import eu.eudat.logic.builders.entity.UserInfoBuilder; import eu.eudat.logic.mapper.elastic.DmpMapper; import eu.eudat.logic.mapper.elastic.criteria.DmpCriteriaMapper; import eu.eudat.logic.proxy.config.configloaders.ConfigLoader; +import eu.eudat.logic.security.repositorydeposit.mapper.DMPToDepositMapper; import eu.eudat.logic.services.ApiContext; import eu.eudat.logic.services.forms.VisibilityRuleService; import eu.eudat.logic.services.forms.VisibilityRuleServiceImpl; @@ -57,8 +60,6 @@ import eu.eudat.models.data.project.ProjectDMPEditorModel; import eu.eudat.models.data.security.Principal; import eu.eudat.models.data.user.composite.PagedDatasetProfile; import eu.eudat.models.data.userinfo.UserListingModel; -import eu.eudat.models.deposit.zenodo.ZenodoDeposit; -import eu.eudat.models.deposit.zenodo.mapper.DMPToZenodoMapper; import eu.eudat.queryable.QueryableList; import eu.eudat.types.Authorities; import eu.eudat.types.MetricNames; @@ -70,11 +71,8 @@ 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.web.client.HttpClientErrorException; -import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.RestTemplate; import org.springframework.web.multipart.MultipartFile; import org.w3c.dom.Document; @@ -114,9 +112,11 @@ public class DataManagementPlanManager { private UserManager userManager; private final MetricsManager metricsManager; private final ConfigLoader configLoader; + private List repositoriesDeposit; @Autowired - public DataManagementPlanManager(ApiContext apiContext, DatasetManager datasetManager, Environment environment, RDAManager rdaManager, UserManager userManager, MetricsManager metricsManager, ConfigLoader configLoader) { + public DataManagementPlanManager(ApiContext apiContext, DatasetManager datasetManager, Environment environment, RDAManager rdaManager, UserManager userManager, + MetricsManager metricsManager, ConfigLoader configLoader, List repositoriesDeposit) { this.apiContext = apiContext; this.datasetManager = datasetManager; this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository(); @@ -126,6 +126,7 @@ public class DataManagementPlanManager { this.metricsManager = metricsManager; this.configLoader = configLoader; this.objectMapper = new ObjectMapper(); + this.repositoriesDeposit = repositoriesDeposit; } /* @@ -2064,6 +2065,20 @@ public class DataManagementPlanManager { /*if (dmp.getDoi() != null) throw new Exception("DMP already has a DOI");*/ + FileEnvelope file = getWordDocument(id.toString(), principal, configLoader); + String name = file.getFilename().substring(0, file.getFilename().length() - 5); + File pdfFile = PDFUtils.convertToPDF(file, environment); + String fileName = name + ".pdf"; + ResponseEntity jsonFile; + try { + jsonFile = getRDAJsonDocument(id.toString(), principal); + } catch (Exception e) { + throw e; + } + String previousDOI = this.getPreviousDOI(dmp.getGroupId(), dmp.getId()); + + DMPDepositModel dmpDepositModel = DMPToDepositMapper.fromDMP(dmp, pdfFile, fileName, jsonFile, previousDOI); + String zenodoToken = ""; try { if (this.userManager.isDOITokenValid(principal)) { @@ -2072,136 +2087,18 @@ public class DataManagementPlanManager { } catch (NonValidTokenException e) { zenodoToken = this.environment.getProperty("zenodo.access_token"); } - // 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); - ZenodoDeposit deposit = DMPToZenodoMapper.fromDMP(dmp, environment, configLoader); - //if (Objects.requireNonNull(environment.getProperty("spring.profiles.active")).contains("devel")) { - String json = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(deposit); - logger.info(json); - //} - HttpEntity request = new HttpEntity<>(deposit, headers); - Map createResponse; - LinkedHashMap links; - String previousDOI = this.getPreviousDOI(dmp.getGroupId(), dmp.getId()); - String unpublishedUrl = null; - String publishUrl; - String finalDoi; - try { - - if (previousDOI == null) { - String createUrl = this.environment.getProperty("zenodo.url") + "deposit/depositions" + "?access_token=" + zenodoToken; - createResponse = restTemplate.postForEntity(createUrl, request, Map.class).getBody(); - links = (LinkedHashMap) createResponse.get("links"); - finalDoi = (String) createResponse.get("conceptdoi"); - } else { - unpublishedUrl = this.getUnpublishedDOI(previousDOI, zenodoToken, dmp.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 = this.environment.getProperty("zenodo.url") + "deposit/depositions" + "?q=conceptdoi:\"" + previousDOI + "\"&access_token=" + zenodoToken; - ResponseEntity listResponses = restTemplate.getForEntity(listUrl, Map[].class); - createResponse = listResponses.getBody()[0]; - links = (LinkedHashMap) createResponse.get("links"); - //Second, make the new version (not in the links?) - String newVersionUrl = links.get("self") + "/actions/newversion" + "?access_token=" + zenodoToken; - createResponse = restTemplate.postForObject(newVersionUrl, null, Map.class); - links = (LinkedHashMap) createResponse.get("links"); - //Third, get the new deposit - String latestDraftUrl = links.get("latest_draft") + "?access_token=" + zenodoToken; - createResponse = restTemplate.getForObject(latestDraftUrl, Map.class); - links = (LinkedHashMap) createResponse.get("links"); - finalDoi = (String) createResponse.get("conceptdoi"); - //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 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 = this.environment.getProperty("zenodo.url") + "deposit/depositions" + "?q=conceptdoi:\"" + previousDOI + "\"&access_token=" + zenodoToken; - ResponseEntity listResponses = restTemplate.getForEntity(listUrl, Map[].class); - createResponse = listResponses.getBody()[0]; - links = (LinkedHashMap) createResponse.get("links"); - } - } - - if (!update) { - if (unpublishedUrl == null) { - // Second step, add the file to the entry. - FileEnvelope file = getWordDocument(id.toString(), principal, configLoader); - String name = file.getFilename().substring(0, file.getFilename().length() - 5); - File pdfFile = PDFUtils.convertToPDF(file, environment); - String fileName = name + ".pdf"; - FileSystemResource fileSystemResource = new FileSystemResource(pdfFile); - HttpEntity addFileMapRequest = new HttpEntity<>(fileSystemResource, null); - - String addFileUrl = links.get("bucket") + "/" + fileName + "?access_token=" + zenodoToken; - restTemplate.put(addFileUrl, addFileMapRequest); - Files.deleteIfExists(file.getFile().toPath()); - - ResponseEntity jsonFile; - try { - jsonFile = getRDAJsonDocument(id.toString(), principal); - } catch (Exception e) { - throw e; - } - UUID jsonFileUUID = UUID.randomUUID(); - File tempJsonFile = new File(this.environment.getProperty("temp.temp") + jsonFileUUID.toString() + ".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()); - - - // 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; - } -// if (dmp.isPublic()) { - Map publishResponce = restTemplate.postForObject(publishUrl, "", Map.class); - finalDoi = (String) publishResponce.get("conceptdoi"); -// } - } else { - Map editResponce = restTemplate.postForObject(links.get("edit") + "?access_token=" + zenodoToken, "", Map.class); - restTemplate.put(links.get("self") + "?access_token=" + zenodoToken, request); - Map publishResponce = restTemplate.postForObject(links.get("publish") + "?access_token=" + zenodoToken, "", Map.class); - finalDoi = (String) publishResponce.get("conceptdoi"); - } + String finalDoi = null; + for(RepositoryDeposit repo: this.repositoriesDeposit) { //temp + finalDoi = repo.deposit(dmpDepositModel, update, zenodoToken); if (finalDoi != null) { dmp.setDoi(finalDoi); apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); } - return finalDoi; - } catch (HttpClientErrorException | HttpServerErrorException ex) { - //ObjectMapper ob = new ObjectMapper(); - Map parsedException = objectMapper.readValue(ex.getResponseBodyAsString(), HashMap.class); - throw new IOException(parsedException.get("message"), ex); } + Files.deleteIfExists(file.getFile().toPath()); + + return finalDoi; } /* diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java new file mode 100644 index 000000000..80c4cf472 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java @@ -0,0 +1,40 @@ +package eu.eudat.logic.managers; + +import eu.eudat.depositinterface.repository.RepositoryDeposit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +@Component +public class DepositManager { + private static final Logger logger = LoggerFactory.getLogger(DepositManager.class); + + private List repositories; + + @Autowired + public DepositManager(List repositories){ + this.repositories = repositories; + } + + public List getAvailableRepos() { + List repos = new ArrayList<>(); + +// logger.info("\n\n-------REPOS------\n"); +// for (RepositoryDeposit r: this.repositories) { +// logger.info("...Loaded Class: " +// + r.getClass()); +// } +// logger.info("\n-------------------------------"); + for (RepositoryDeposit r: this.repositories) { + repos.add(r.getConfiguration().getRepositoryId()); + } + + //repos.add("dummyId"); + return repos; + } + +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/DOIFunder.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/DOIFunder.java deleted file mode 100644 index 68803e021..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/DOIFunder.java +++ /dev/null @@ -1,27 +0,0 @@ -package eu.eudat.logic.proxy.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; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ConfigLoader.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ConfigLoader.java index 08dc4062c..175442eda 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ConfigLoader.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/ConfigLoader.java @@ -1,6 +1,5 @@ package eu.eudat.logic.proxy.config.configloaders; -import eu.eudat.logic.proxy.config.DOIFunder; import eu.eudat.logic.proxy.config.ExternalUrls; import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.ConfigurableProviders; import org.apache.poi.xwpf.usermodel.XWPFDocument; @@ -15,5 +14,4 @@ public interface ConfigLoader { XWPFDocument getDatasetDocument(); ConfigurableProviders getConfigurableProviders(); Map getKeyToSourceMap(); - List getDOIFunders(); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DefaultConfigLoader.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DefaultConfigLoader.java index 15c04e898..2a7f4b74d 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DefaultConfigLoader.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/configloaders/DefaultConfigLoader.java @@ -2,7 +2,6 @@ package eu.eudat.logic.proxy.config.configloaders; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; -import eu.eudat.logic.proxy.config.DOIFunder; import eu.eudat.logic.proxy.config.ExternalUrls; import eu.eudat.logic.security.customproviders.ConfigurableProvider.entities.ConfigurableProviders; import org.apache.poi.xwpf.usermodel.XWPFDocument; @@ -41,7 +40,6 @@ public class DefaultConfigLoader implements ConfigLoader { private XWPFDocument datasetDocument; private ConfigurableProviders configurableProviders; private Map keyToSourceMap; - private List doiFunders = new ArrayList<>(); @Autowired private Environment environment; @@ -239,18 +237,6 @@ public class DefaultConfigLoader implements ConfigLoader { return keyToSourceMap; } - @Override - public List getDOIFunders() { - if (doiFunders == null || doiFunders.isEmpty()) { - try { - List> tempdoiFunders = mapper.readValue(getStreamFromPath(environment.getProperty("configuration.doi_funder")), List.class); - doiFunders = tempdoiFunders.stream().map(map -> mapper.convertValue(map, DOIFunder.class) ).collect(Collectors.toList()); - } catch (IOException e) { - logger.error(e.getLocalizedMessage(), e); - } - } - return doiFunders; - } private Document getXmlDocumentFromFilePath(String filePath) { InputStream is = null; diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/security/repositorydeposit/mapper/DMPToDepositMapper.java b/dmp-backend/web/src/main/java/eu/eudat/logic/security/repositorydeposit/mapper/DMPToDepositMapper.java new file mode 100644 index 000000000..052c13607 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/security/repositorydeposit/mapper/DMPToDepositMapper.java @@ -0,0 +1,72 @@ +package eu.eudat.logic.security.repositorydeposit.mapper; + +import eu.eudat.data.entities.*; +import eu.eudat.depositinterface.models.*; +import org.springframework.http.ResponseEntity; + +import java.io.File; +import java.util.stream.Collectors; + +public class DMPToDepositMapper { + + public static DMPDepositModel fromDMP(DMP entity, File pdfFile, String fileName, ResponseEntity jsonFile, String previousDOI) { + DMPDepositModel deposit = new DMPDepositModel(); + deposit.setId(entity.getId()); + deposit.setVersion(entity.getVersion()); + deposit.setLabel(entity.getLabel()); + deposit.setDescription(entity.getDescription()); + deposit.setPublic(entity.isPublic()); + deposit.setUsers(entity.getUsers().stream().map(DMPToDepositMapper::fromUserDMP).collect(Collectors.toSet())); + deposit.setOrganisations(entity.getOrganisations().stream().map(DMPToDepositMapper::fromOrganisation).collect(Collectors.toSet())); + deposit.setResearchers(entity.getResearchers().stream().map(DMPToDepositMapper::fromResearcher).collect(Collectors.toSet())); + deposit.setGrant(fromGrant(entity.getGrant())); + + deposit.setPdfFile(pdfFile); + deposit.setPdfFileName(fileName); + deposit.setRdaJson(jsonFile); + deposit.setPreviousDOI(previousDOI); + + deposit.setExtraProperties(entity.getExtraProperties()); + return deposit; + } + + private static UserDMPDepositModel fromUserDMP(UserDMP entity){ + UserDMPDepositModel deposit = new UserDMPDepositModel(); + deposit.setUser(fromUserInfo(entity.getUser())); + deposit.setRole(entity.getRole()); + return deposit; + } + + private static UserInfoDepositModel fromUserInfo(UserInfo entity){ + UserInfoDepositModel deposit = new UserInfoDepositModel(); + deposit.setName(entity.getName()); + return deposit; + } + + private static OrganisationDepositModel fromOrganisation(Organisation entity){ + OrganisationDepositModel deposit = new OrganisationDepositModel(); + deposit.setLabel(entity.getLabel()); + return deposit; + } + + private static ResearcherDepositModel fromResearcher(Researcher entity){ + ResearcherDepositModel deposit = new ResearcherDepositModel(); + deposit.setLabel(entity.getLabel()); + deposit.setReference(entity.getReference()); + return deposit; + } + + private static GrantDepositModel fromGrant(Grant entity){ + GrantDepositModel deposit = new GrantDepositModel(); + deposit.setId(entity.getId()); + deposit.setReference(entity.getReference()); + deposit.setFunder(fromFunder(entity.getFunder())); + return deposit; + } + + private static FunderDepositModel fromFunder(Funder entity){ + FunderDepositModel deposit = new FunderDepositModel(); + deposit.setLabel(entity.getLabel()); + return deposit; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoAccessRight.java b/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoAccessRight.java deleted file mode 100644 index b143338fc..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoAccessRight.java +++ /dev/null @@ -1,18 +0,0 @@ -package eu.eudat.models.deposit.zenodo; - -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; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoComunity.java b/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoComunity.java deleted file mode 100644 index f644d3144..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoComunity.java +++ /dev/null @@ -1,19 +0,0 @@ -package eu.eudat.models.deposit.zenodo; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(JsonInclude.Include.NON_NULL) -public class ZenodoComunity { - - private String identifier; - - public String getIdentifier() { - return identifier; - } - - public void setIdentifier(String identifier) { - this.identifier = identifier; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoContributor.java b/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoContributor.java deleted file mode 100644 index 55ca86ed7..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoContributor.java +++ /dev/null @@ -1,45 +0,0 @@ -package eu.eudat.models.deposit.zenodo; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(JsonInclude.Include.NON_NULL) -public class ZenodoContributor { - private String name; - private String type; - private String affiliation; - private String orcid; - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getAffiliation() { - return affiliation; - } - - public void setAffiliation(String affiliation) { - this.affiliation = affiliation; - } - - public String getOrcid() { - return orcid; - } - - public void setOrcid(String orcid) { - this.orcid = orcid; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoDeposit.java b/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoDeposit.java deleted file mode 100644 index c80a167c9..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoDeposit.java +++ /dev/null @@ -1,19 +0,0 @@ -package eu.eudat.models.deposit.zenodo; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(JsonInclude.Include.NON_NULL) -public class ZenodoDeposit { - - private ZenodoDepositMetadata metadata; - - public ZenodoDepositMetadata getMetadata() { - return metadata; - } - - public void setMetadata(ZenodoDepositMetadata metadata) { - this.metadata = metadata; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoDepositMetadata.java b/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoDepositMetadata.java deleted file mode 100644 index 014239f69..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoDepositMetadata.java +++ /dev/null @@ -1,159 +0,0 @@ -package eu.eudat.models.deposit.zenodo; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; - -import java.time.Instant; -import java.util.List; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(JsonInclude.Include.NON_NULL) -public class ZenodoDepositMetadata { - - private String title; - - @JsonProperty("upload_type") - private String uploadType; - - @JsonProperty("publication_type") - private String publicationType; - - private String description; - - private String version; - - private List communities; - - @JsonProperty("access_right") - private ZenodoAccessRight accessRight; - - @JsonProperty("access_conditions") - private String accessConditions; - - @JsonProperty("embargo_date") - private String embargoDate; - - private String license; - - @JsonProperty("related_identifiers") - private List relatedIdentifiers; - - private List contributors; - - private List grants; - - private List creators; - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getUploadType() { - return uploadType; - } - - public void setUploadType(String uploadType) { - this.uploadType = uploadType; - } - - public String getPublicationType() { - return publicationType; - } - - public void setPublicationType(String publicationType) { - this.publicationType = publicationType; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public List getCommunities() { - return communities; - } - - public void setCommunities(List communities) { - this.communities = communities; - } - - public ZenodoAccessRight getAccessRight() { - return accessRight; - } - - public void setAccessRight(ZenodoAccessRight accessRight) { - this.accessRight = accessRight; - } - - public String getAccessConditions() { - return accessConditions; - } - - public void setAccessConditions(String accessConditions) { - this.accessConditions = accessConditions; - } - - public String getEmbargoDate() { - return embargoDate; - } - - public void setEmbargoDate(String embargoDate) { - this.embargoDate = embargoDate; - } - - public String getLicense() { - return license; - } - - public void setLicense(String license) { - this.license = license; - } - - public List getRelatedIdentifiers() { - return relatedIdentifiers; - } - - public void setRelatedIdentifiers(List relatedIdentifiers) { - this.relatedIdentifiers = relatedIdentifiers; - } - - public List getContributors() { - return contributors; - } - - public void setContributors(List contributors) { - this.contributors = contributors; - } - - public List getGrants() { - return grants; - } - - public void setGrants(List grants) { - this.grants = grants; - } - - public List getCreators() { - return creators; - } - - public void setCreators(List creators) { - this.creators = creators; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoGrant.java b/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoGrant.java deleted file mode 100644 index 292322a30..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoGrant.java +++ /dev/null @@ -1,18 +0,0 @@ -package eu.eudat.models.deposit.zenodo; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(JsonInclude.Include.NON_NULL) -public class ZenodoGrant { - private String id; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoRelator.java b/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoRelator.java deleted file mode 100644 index e5389602e..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/ZenodoRelator.java +++ /dev/null @@ -1,28 +0,0 @@ -package eu.eudat.models.deposit.zenodo; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; - -@JsonIgnoreProperties(ignoreUnknown = true) -@JsonInclude(JsonInclude.Include.NON_NULL) -public class ZenodoRelator { - - private String identifier; - private String relation; - - public String getIdentifier() { - return identifier; - } - - public void setIdentifier(String identifier) { - this.identifier = identifier; - } - - public String getRelation() { - return relation; - } - - public void setRelation(String relation) { - this.relation = relation; - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/mapper/DMPToZenodoMapper.java b/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/mapper/DMPToZenodoMapper.java deleted file mode 100644 index f4a399f49..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/models/deposit/zenodo/mapper/DMPToZenodoMapper.java +++ /dev/null @@ -1,115 +0,0 @@ -package eu.eudat.models.deposit.zenodo.mapper; - -import eu.eudat.data.entities.DMP; -import eu.eudat.data.entities.Organisation; -import eu.eudat.data.entities.UserDMP; -import eu.eudat.logic.proxy.config.DOIFunder; -import eu.eudat.logic.proxy.config.configloaders.ConfigLoader; -import eu.eudat.models.deposit.zenodo.*; -import org.springframework.core.env.Environment; - -import java.time.Instant; -import java.util.*; -import java.util.stream.Collectors; - -public class DMPToZenodoMapper { - - public static ZenodoDeposit fromDMP(DMP dmp, Environment environment, ConfigLoader configLoader) { - Map extraProperties = dmp.getExtraProperties() != null ? new org.json.JSONObject(dmp.getExtraProperties()).toMap() : new HashMap<>(); - ZenodoDeposit deposit = new ZenodoDeposit(); - deposit.setMetadata(new ZenodoDepositMetadata()); - deposit.getMetadata().setTitle(dmp.getLabel()); - deposit.getMetadata().setUploadType("publication"); - deposit.getMetadata().setPublicationType("datamanagementplan"); - deposit.getMetadata().setDescription((dmp.getDescription() != null && !dmp.getDescription().isEmpty() ? dmp.getDescription() : "

")); - deposit.getMetadata().setVersion(dmp.getVersion().toString()); - ZenodoComunity community = new ZenodoComunity(); - community.setIdentifier(environment.getProperty("zenodo.community")); - deposit.getMetadata().setCommunities(Collections.singletonList(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((environment.getProperty("dmp.domain") + "/external/zenodo/" + dmp.getId().toString())); - relator.setRelation("isIdenticalTo"); - deposit.getMetadata().setRelatedIdentifiers(Collections.singletonList(relator)); - } - deposit.getMetadata().setContributors(new LinkedList<>()); - List contributors = 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(Organisation::getLabel).collect(Collectors.joining(", "))); - } else { - contributor.setAffiliation(environment.getProperty("zenodo.affiliation")); - } - return contributor; - }).collect(Collectors.toList()); - - List 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(contributors); - deposit.getMetadata().getContributors().addAll(researchers); - - 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]; - DOIFunder doiFunder = configLoader.getDOIFunders().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().setGrants(Collections.singletonList(grant)); - } - } - ZenodoContributor creator = new ZenodoContributor(); - creator.setName(dmp.getUsers().stream().filter(userDMP -> userDMP.getRole().equals(UserDMP.UserDMPRoles.OWNER.getValue())).findFirst().get().getUser().getName()); - if (dmp.getOrganisations() != null && !dmp.getOrganisations().isEmpty()) { - creator.setAffiliation(dmp.getOrganisations() - .stream().map(Organisation::getLabel).collect(Collectors.joining(", "))); - } else { - creator.setAffiliation(environment.getProperty("zenodo.affiliation")); - } - deposit.getMetadata().setCreators(Collections.singletonList(creator)); - - return deposit; - } -} - diff --git a/dmp-frontend/src/app/core/core-service.module.ts b/dmp-frontend/src/app/core/core-service.module.ts index 6f81f1095..b36cf42f8 100644 --- a/dmp-frontend/src/app/core/core-service.module.ts +++ b/dmp-frontend/src/app/core/core-service.module.ts @@ -46,6 +46,7 @@ import { CollectionUtils } from './services/utilities/collection-utils.service'; import { TypeUtils } from './services/utilities/type-utils.service'; import { SpecialAuthGuard } from './special-auth-guard.service'; import {PrefillingService} from "@app/core/services/prefilling.service"; +import { DepositRepositoriesService } from './services/deposit-repositories/deposit-repositories.service'; // // // This is shared module that provides all the services. Its imported only once on the AppModule. @@ -89,6 +90,7 @@ export class CoreServiceModule { FunderService, GrantFileUploadService, DmpService, + DepositRepositoriesService, DmpProfileService, ExternalSourcesService, ExternalSourcesConfigurationService, diff --git a/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts b/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts new file mode 100644 index 000000000..dd6ebfde2 --- /dev/null +++ b/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts @@ -0,0 +1,20 @@ +import { HttpClient, HttpHeaders } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; +import { ConfigurationService } from '../configuration/configuration.service'; +import { BaseHttpService } from '../http/base-http.service'; + +@Injectable() +export class DepositRepositoriesService { + + private actionUrl: string; + private headers = new HttpHeaders(); + + constructor(private http: BaseHttpService, private httpClient: HttpClient, private configurationService: ConfigurationService) { + this.actionUrl = configurationService.server + 'deposit/'; + } + + getAvailableRepos(): Observable { + return this.http.get(this.actionUrl + 'repos/', { headers: this.headers }); + } +} diff --git a/dmp-frontend/src/app/ui/dmp/dmp.module.ts b/dmp-frontend/src/app/ui/dmp/dmp.module.ts index 01f0355b6..16867c162 100644 --- a/dmp-frontend/src/app/ui/dmp/dmp.module.ts +++ b/dmp-frontend/src/app/ui/dmp/dmp.module.ts @@ -50,6 +50,7 @@ import { FormProgressIndicationComponent } from '../misc/dataset-description-for import { FormProgressIndicationModule } from '../misc/dataset-description-form/components/form-progress-indication/form-progress-indication.module'; import { DatasetPreviewDialogComponent } from './dataset-preview/dataset-preview-dialog.component'; import {RichTextEditorModule} from "@app/library/rich-text-editor/rich-text-editor.module"; +import { DmpDepositDialogComponent } from './editor/dmp-deposit-dialog/dmp-deposit-dialog.component'; @NgModule({ imports: [ @@ -103,7 +104,8 @@ import {RichTextEditorModule} from "@app/library/rich-text-editor/rich-text-edit FundingInfoComponent, DatasetInfoComponent, LicenseInfoComponent, - DatasetPreviewDialogComponent + DatasetPreviewDialogComponent, + DmpDepositDialogComponent ], entryComponents: [ DmpInvitationDialogComponent, @@ -119,7 +121,8 @@ import {RichTextEditorModule} from "@app/library/rich-text-editor/rich-text-edit StartNewDmpDialogComponent, StartNewDatasetDialogComponent, DatasetEditorDetailsComponent, - DatasetPreviewDialogComponent + DatasetPreviewDialogComponent, + DmpDepositDialogComponent ] }) export class DmpModule { } diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.html b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.html new file mode 100644 index 000000000..8dbb6dcd3 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.html @@ -0,0 +1,25 @@ +
+
{{ data.message }}
+
+ close +
+
+
+ + + + {{ repo }} + + + +
+
{{ 'DMP-FINALISE-DIALOG.EMPTY' | translate }}
+ +
+
+ +
+
+ +
+
\ No newline at end of file diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.scss b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.scss new file mode 100644 index 000000000..e69de29bb diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts new file mode 100644 index 000000000..04247b533 --- /dev/null +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts @@ -0,0 +1,35 @@ +import { Component, Inject, OnInit } from '@angular/core'; +import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { BaseComponent } from '@common/base/base.component'; + +@Component({ + selector: 'app-dmp-deposit-dialog', + templateUrl: './dmp-deposit-dialog.component.html', + styleUrls: ['./dmp-deposit-dialog.component.scss'] +}) +export class DmpDepositDialogComponent extends BaseComponent implements OnInit { + + inputRepos: string[]; + outputRepos: string[]; + + constructor( + public dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any + ) { + super(); + this.inputRepos = data['depositRepos']; + this.outputRepos = []; + } + + ngOnInit(): void { + } + + onSubmit() { + this.dialogRef.close(this.outputRepos); + } + + close() { + this.dialogRef.close(this.outputRepos); + } + +} diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html index c0efb9577..15284e00b 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html @@ -141,7 +141,7 @@
-
+
diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts index 8a75001ee..63c3a8231 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts @@ -41,6 +41,8 @@ import { StartNewDmpDialogComponent } from '../start-new-dmp-dialogue/start-new- import { HttpClient } from '@angular/common/http'; import { MatomoService } from '@app/core/services/matomo/matomo-service'; import { PopupNotificationDialogComponent } from '@app/library/notification/popup/popup-notification.component'; +import { DepositRepositoriesService } from '@app/core/services/deposit-repositories/deposit-repositories.service'; +import { DmpDepositDialogComponent } from '../editor/dmp-deposit-dialog/dmp-deposit-dialog.component'; @Component({ selector: 'app-dmp-overview', @@ -68,12 +70,15 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { @ViewChild('doi') doi: ElementRef; + depositRepos: String[]; + formGroup: FormGroup; constructor( private route: ActivatedRoute, private router: Router, private dmpService: DmpService, + private depositRepositoriesService: DepositRepositoriesService, private translate: TranslateService, private authentication: AuthService, private dialog: MatDialog, @@ -578,6 +583,26 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { }); } + deposit(){ + this.depositRepositoriesService.getAvailableRepos() + .pipe(takeUntil(this._destroyed)) + .subscribe( + repos => { + this.depositRepos = repos; + } + ); + const dialogRef = this.dialog.open(DmpDepositDialogComponent, { + restoreFocus: false, + autoFocus: false, + data: { + depositRepos: this.depositRepos, + message: "Select repositories to deposit",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.FINALIZE-ITEM'), + confirmButton: "Proceed to authentication",//this.language.instant('DMP-FINALISE-DIALOG.SUBMIT'), + cancelButton: "Cancel",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), + } + }); + } + finalize(dmp: DmpOverviewModel) { const dialogInputModel: DmpFinalizeDialogInput = { From ab66a5f1dafd4bb9e926626b0efb869163376bfa Mon Sep 17 00:00:00 2001 From: Aldo Mihasi Date: Wed, 26 Oct 2022 13:50:01 +0300 Subject: [PATCH 02/26] [WIP] implement zenodo repository deposit, add authentication for depositions --- dmp-backend/depositinterface/pom.xml | 8 +- .../repository/RepositoryDeposit.java | 2 +- dmp-backend/pom.xml | 1 - dmp-backend/web/pom.xml | 7 + .../eudat/controllers/DepositController.java | 26 +- .../managers/DataManagementPlanManager.java | 58 +++++ .../eudat/logic/managers/DepositManager.java | 36 ++- .../eudat/models/data/doi/DepositRequest.java | 29 +++ dmp-backend/zenodoRepository/pom.xml | 39 +++ .../dummyrepository/TestDummy.java | 29 +++ .../zenodorepository/config/ConfigLoader.java | 7 + .../config/ConfigLoaderImpl.java | 50 ++++ .../zenodorepository/config/DOIFunder.java | 27 ++ .../interfaces/ZenodoDeposit.java | 244 ++++++++++++++++++ .../mapper/DMPToZenodoMapper.java | 119 +++++++++ .../models/ZenodoAccessRight.java | 18 ++ .../models/ZenodoComunity.java | 19 ++ .../models/ZenodoContributor.java | 45 ++++ .../models/ZenodoDeposit.java | 19 ++ .../models/ZenodoDepositMetadata.java | 158 ++++++++++++ .../zenodorepository/models/ZenodoGrant.java | 18 ++ .../models/ZenodoRelator.java | 28 ++ .../src/main/resources/DOI_Funder.json | 70 +++++ .../src/main/resources/application.properties | 1 + .../enum/deposit-configuration-status.ts | 5 + .../model/deposit/deposit-configuration.ts | 11 + .../app/core/model/deposit/deposit-request.ts | 5 + .../deposit-repositories.service.ts | 18 +- .../dmp-deposit-dialog.component.html | 16 +- .../dmp-deposit-dialog.component.ts | 94 ++++++- .../ui/dmp/overview/dmp-overview.component.ts | 29 ++- 31 files changed, 1196 insertions(+), 40 deletions(-) create mode 100644 dmp-backend/web/src/main/java/eu/eudat/models/data/doi/DepositRequest.java create mode 100644 dmp-backend/zenodoRepository/pom.xml create mode 100644 dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/dummyrepository/TestDummy.java create mode 100644 dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/config/ConfigLoader.java create mode 100644 dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/config/ConfigLoaderImpl.java create mode 100644 dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/config/DOIFunder.java create mode 100644 dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/interfaces/ZenodoDeposit.java create mode 100644 dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/mapper/DMPToZenodoMapper.java create mode 100644 dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoAccessRight.java create mode 100644 dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoComunity.java create mode 100644 dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoContributor.java create mode 100644 dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoDeposit.java create mode 100644 dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoDepositMetadata.java create mode 100644 dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoGrant.java create mode 100644 dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoRelator.java create mode 100644 dmp-backend/zenodoRepository/src/main/resources/DOI_Funder.json create mode 100644 dmp-backend/zenodoRepository/src/main/resources/application.properties create mode 100644 dmp-frontend/src/app/core/common/enum/deposit-configuration-status.ts create mode 100644 dmp-frontend/src/app/core/model/deposit/deposit-configuration.ts create mode 100644 dmp-frontend/src/app/core/model/deposit/deposit-request.ts diff --git a/dmp-backend/depositinterface/pom.xml b/dmp-backend/depositinterface/pom.xml index 8899237cf..bfdd74f3a 100644 --- a/dmp-backend/depositinterface/pom.xml +++ b/dmp-backend/depositinterface/pom.xml @@ -4,11 +4,13 @@ 4.0.0 - eu.eudat - dmp-backend - 1.0.0-SNAPSHOT + org.springframework.boot + spring-boot-starter-parent + 2.7.4 + + eu.eudat depositinterface 1.0-SNAPSHOT jar diff --git a/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/repository/RepositoryDeposit.java b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/repository/RepositoryDeposit.java index 59f6b43c2..7563a9595 100644 --- a/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/repository/RepositoryDeposit.java +++ b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/repository/RepositoryDeposit.java @@ -6,7 +6,7 @@ public interface RepositoryDeposit { String deposit(DMPDepositModel dmpDepositModel, boolean update, String repositoryAccessToken) throws Exception; - //authenticate(); + String authenticate(String code); RepositoryDepositConfiguration getConfiguration(); diff --git a/dmp-backend/pom.xml b/dmp-backend/pom.xml index 27be888d0..daf645f04 100644 --- a/dmp-backend/pom.xml +++ b/dmp-backend/pom.xml @@ -18,7 +18,6 @@ web data elastic - depositinterface diff --git a/dmp-backend/web/pom.xml b/dmp-backend/web/pom.xml index 8170c8cee..4295c6b12 100644 --- a/dmp-backend/web/pom.xml +++ b/dmp-backend/web/pom.xml @@ -225,6 +225,13 @@ ZIP + + + + repackage + + + diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java index 599871b01..1687f560f 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java @@ -1,8 +1,10 @@ package eu.eudat.controllers; +import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration; import eu.eudat.logic.managers.DepositManager; import eu.eudat.logic.security.claims.ClaimedAuthorities; import eu.eudat.logic.services.ApiContext; +import eu.eudat.models.data.doi.DepositRequest; import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.models.data.security.Principal; import eu.eudat.types.ApiMessageCode; @@ -32,8 +34,26 @@ public class DepositController extends BaseController { @RequestMapping(method = RequestMethod.GET, value = {"/repos"}) public @ResponseBody - ResponseEntity>> getAvailableRepos(@ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws Exception { - List ids = this.depositManager.getAvailableRepos(); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(ids)); + ResponseEntity>> getAvailableRepos(@ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) { + List ids = this.depositManager.getAvailableRepos(); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(ids)); + } + + @RequestMapping(method = RequestMethod.GET, value = {"/getAccessToken"}) + public @ResponseBody + ResponseEntity> getAccessToken(@RequestParam("repository") String repository, @RequestParam("code") String code, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws Exception { + String accessToken = this.depositManager.authenticate(repository, code); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(accessToken)); + } + + @RequestMapping(method = RequestMethod.POST, value = {"/createDoi"}) + public ResponseEntity> createDoi(@RequestBody DepositRequest depositRequest, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) { + try { + String doi = this.depositManager.deposit(depositRequest, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully created DOI for Data Datamanagement Plan in question.").payload(doi)); + } catch (Exception e) { + logger.error(e.getMessage(), e); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to create DOI for the Data Management Plan: " + e.getMessage())); + } } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java index 7bc65f570..b6d734eb4 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java @@ -48,6 +48,7 @@ import eu.eudat.models.data.datasetprofile.DatasetProfileListingModel; import eu.eudat.models.data.datasetwizard.DatasetWizardModel; import eu.eudat.models.data.datasetwizard.DatasetsToBeFinalized; import eu.eudat.models.data.dmp.*; +import eu.eudat.models.data.doi.DepositRequest; import eu.eudat.models.data.dynamicfields.DynamicFieldWithValue; import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.DataManagementPlanProfile; import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.Field; @@ -63,6 +64,7 @@ import eu.eudat.models.data.userinfo.UserListingModel; import eu.eudat.queryable.QueryableList; import eu.eudat.types.Authorities; import eu.eudat.types.MetricNames; +import org.apache.commons.io.IOUtils; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; @@ -84,6 +86,7 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import java.io.*; import java.math.BigInteger; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.time.Instant; import java.time.temporal.ChronoUnit; @@ -2101,6 +2104,61 @@ public class DataManagementPlanManager { return finalDoi; } + public String createDoi(DepositRequest depositRequest, Principal principal) throws Exception { + DMP dmp = this.apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(UUID.fromString(depositRequest.getDmpId())); + if (!isUserOwnerOfDmp(dmp, principal)) + throw new Exception("User is not authorized to invoke this action"); + if (!dmp.getStatus().equals(DMP.DMPStatus.FINALISED.getValue())) + throw new Exception("DMP is not finalized"); + /*if (dmp.getDoi() != null) + throw new Exception("DMP already has a DOI");*/ + + FileEnvelope file = getWordDocument(depositRequest.getDmpId(), principal, configLoader); + String name = file.getFilename().substring(0, file.getFilename().length() - 5); + //File pdfFile = PDFUtils.convertToPDF(file, environment); + String uuid = UUID.randomUUID().toString(); + File pdfFile = new File(environment.getProperty("temp.temp") + uuid + ".pdf"); + FileOutputStream output = new FileOutputStream(pdfFile); + IOUtils.write("testing".getBytes(StandardCharsets.UTF_8), output); + String fileName = name + ".pdf"; + output.close(); + ResponseEntity jsonFile; + try { + jsonFile = getRDAJsonDocument(depositRequest.getDmpId(), principal); + } catch (Exception e) { + throw e; + } + String previousDOI = this.getPreviousDOI(dmp.getGroupId(), dmp.getId()); + + DMPDepositModel dmpDepositModel = DMPToDepositMapper.fromDMP(dmp, pdfFile, fileName, jsonFile, previousDOI); + +// String zenodoToken = ""; +// try { +// if (this.userManager.isDOITokenValid(principal)) { +// zenodoToken = principal.getZenodoToken(); +// } +// } catch (NonValidTokenException e) { +// zenodoToken = this.environment.getProperty("zenodo.access_token"); +// } + + Optional repo = this.repositoriesDeposit.stream().filter(x -> x.getConfiguration().getRepositoryId().equals(depositRequest.getRepositoryId())).findFirst(); + String finalDoi = repo.map(r -> { + try { + return r.deposit(dmpDepositModel, false, depositRequest.getAccessToken()); + } catch (Exception e) { + logger.error(e.getMessage(), e); + return null; + } + }).orElse(null); + if (finalDoi != null) { + //dmp.setDoi(finalDoi); + //apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); + } + Files.deleteIfExists(file.getFile().toPath()); + + return finalDoi; + } + /* * Misc * */ diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java index 80c4cf472..978c27db7 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java @@ -1,40 +1,62 @@ package eu.eudat.logic.managers; +import eu.eudat.data.entities.DMP; +import eu.eudat.depositinterface.models.DMPDepositModel; import eu.eudat.depositinterface.repository.RepositoryDeposit; +import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration; +import eu.eudat.exceptions.security.NonValidTokenException; +import eu.eudat.logic.security.repositorydeposit.mapper.DMPToDepositMapper; +import eu.eudat.logic.utilities.documents.helpers.FileEnvelope; +import eu.eudat.logic.utilities.documents.pdf.PDFUtils; +import eu.eudat.models.data.doi.DepositRequest; +import eu.eudat.models.data.security.Principal; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; +import java.io.File; +import java.nio.file.Files; import java.util.ArrayList; import java.util.List; +import java.util.Optional; @Component public class DepositManager { private static final Logger logger = LoggerFactory.getLogger(DepositManager.class); private List repositories; + private DataManagementPlanManager dataManagementPlanManager; @Autowired - public DepositManager(List repositories){ + public DepositManager(List repositories, DataManagementPlanManager dataManagementPlanManager){ this.repositories = repositories; + this.dataManagementPlanManager = dataManagementPlanManager; } - public List getAvailableRepos() { - List repos = new ArrayList<>(); + public List getAvailableRepos() { + List repos = new ArrayList<>(); -// logger.info("\n\n-------REPOS------\n"); +// logger.info("-------------REPOS------------"); // for (RepositoryDeposit r: this.repositories) { // logger.info("...Loaded Class: " // + r.getClass()); // } -// logger.info("\n-------------------------------"); +// logger.info("-------------------------------"); for (RepositoryDeposit r: this.repositories) { - repos.add(r.getConfiguration().getRepositoryId()); + repos.add(r.getConfiguration()); } - //repos.add("dummyId"); return repos; } + public String authenticate(String id, String code) { + Optional repo = repositories.stream().filter(x -> x.getConfiguration().getRepositoryId().equals(id)).findFirst(); + return repo.map(repositoryDeposit -> repositoryDeposit.authenticate(code)).orElse(null); + } + + public String deposit(DepositRequest depositRequest, Principal principal) throws Exception { + return this.dataManagementPlanManager.createDoi(depositRequest, principal); + } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/DepositRequest.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/DepositRequest.java new file mode 100644 index 000000000..b6ee1f4a3 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/DepositRequest.java @@ -0,0 +1,29 @@ +package eu.eudat.models.data.doi; + +public class DepositRequest { + + private String repositoryId; + private String dmpId; + private String accessToken; + + public String getRepositoryId() { + return repositoryId; + } + public void setRepositoryId(String repositoryId) { + this.repositoryId = repositoryId; + } + + public String getDmpId() { + return dmpId; + } + public void setDmpId(String dmpId) { + this.dmpId = dmpId; + } + + public String getAccessToken() { + return accessToken; + } + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } +} diff --git a/dmp-backend/zenodoRepository/pom.xml b/dmp-backend/zenodoRepository/pom.xml new file mode 100644 index 000000000..9acabc826 --- /dev/null +++ b/dmp-backend/zenodoRepository/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.4 + + + eu.eudat.depositinterface + zenodoRepository + 0.0.1-SNAPSHOT + zenodoRepository + + + 11 + + + + + org.springframework.boot + spring-boot-starter-web + + + + eu.eudat + depositinterface + 1.0-SNAPSHOT + + + + org.json + json + 20160810 + + + + diff --git a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/dummyrepository/TestDummy.java b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/dummyrepository/TestDummy.java new file mode 100644 index 000000000..cc9087d61 --- /dev/null +++ b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/dummyrepository/TestDummy.java @@ -0,0 +1,29 @@ +package eu.eudat.depositinterface.dummyrepository; + +import eu.eudat.depositinterface.models.DMPDepositModel; +import eu.eudat.depositinterface.repository.RepositoryDeposit; +import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration; +import org.springframework.stereotype.Component; + +import static eu.eudat.depositinterface.repository.RepositoryDepositConfiguration.DepositAccountStatus.BothWaysDeposit; + +@Component +public class TestDummy implements RepositoryDeposit { + @Override + public String deposit(DMPDepositModel dmpDepositModel, boolean update, String repositoryAccessToken) throws Exception { + return "test2"; + } + + @Override + public RepositoryDepositConfiguration getConfiguration() { + RepositoryDepositConfiguration conf = new RepositoryDepositConfiguration(); + conf.setRepositoryId("Dummy"); + conf.setDepositAccountStatus(BothWaysDeposit.getValue()); + return conf; + } + + @Override + public String authenticate(String code) { + return "accessToken"; + } +} \ No newline at end of file diff --git a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/config/ConfigLoader.java b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/config/ConfigLoader.java new file mode 100644 index 000000000..100f94d06 --- /dev/null +++ b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/config/ConfigLoader.java @@ -0,0 +1,7 @@ +package eu.eudat.depositinterface.zenodorepository.config; + +import java.util.List; + +public interface ConfigLoader { + List getDOIFunders(); +} diff --git a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/config/ConfigLoaderImpl.java b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/config/ConfigLoaderImpl.java new file mode 100644 index 000000000..52514bda2 --- /dev/null +++ b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/config/ConfigLoaderImpl.java @@ -0,0 +1,50 @@ +package eu.eudat.depositinterface.zenodorepository.config; + +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.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +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 doiFunders = new ArrayList<>(); + + @Autowired + private Environment environment; + + @Override + public List getDOIFunders() { + if (doiFunders == null || doiFunders.isEmpty()) { + try { + List> tempdoiFunders = mapper.readValue(getStreamFromPath(environment.getProperty("configuration.doi_funder")), List.class); + doiFunders = tempdoiFunders.stream().map(map -> mapper.convertValue(map, DOIFunder.class) ).collect(Collectors.toList()); + } catch (IOException e) { + logger.error(e.getLocalizedMessage(), e); + } + } + return doiFunders; + } + + private InputStream getStreamFromPath(String filePath) { + try { + return new FileInputStream(filePath); + } catch (FileNotFoundException e) { + logger.info("loading from classpath"); + return getClass().getClassLoader().getResourceAsStream(filePath); + } + } +} diff --git a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/config/DOIFunder.java b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/config/DOIFunder.java new file mode 100644 index 000000000..88c7090a4 --- /dev/null +++ b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/config/DOIFunder.java @@ -0,0 +1,27 @@ +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; + } +} diff --git a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/interfaces/ZenodoDeposit.java b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/interfaces/ZenodoDeposit.java new file mode 100644 index 000000000..c3bdef1ad --- /dev/null +++ b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/interfaces/ZenodoDeposit.java @@ -0,0 +1,244 @@ +package eu.eudat.depositinterface.zenodorepository.interfaces; + +import com.fasterxml.jackson.databind.ObjectMapper; +import eu.eudat.depositinterface.models.DMPDepositModel; +import eu.eudat.depositinterface.repository.RepositoryDeposit; +import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration; +import eu.eudat.depositinterface.zenodorepository.config.ConfigLoader; +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.io.FileSystemResource; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +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.web.client.HttpClientErrorException; +import org.springframework.web.client.HttpServerErrorException; +import org.springframework.web.client.RestTemplate; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.util.*; + +import static eu.eudat.depositinterface.repository.RepositoryDepositConfiguration.DepositAccountStatus.BothWaysDeposit; + +@Component +public class ZenodoDeposit implements RepositoryDeposit { + private static final Logger logger = LoggerFactory.getLogger(ZenodoDeposit.class); + private static final ObjectMapper objectMapper = new ObjectMapper(); + + private ConfigLoader configLoader; + + @Autowired + public ZenodoDeposit(ConfigLoader configLoader){ + this.configLoader = configLoader; + } + + @Override + public String deposit(DMPDepositModel dmpDepositModel, boolean update, String zenodoToken) throws Exception { + + RepositoryDepositConfiguration conf = this.getConfiguration(); + 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); + eu.eudat.depositinterface.zenodorepository.models.ZenodoDeposit deposit = DMPToZenodoMapper.fromDMP(dmpDepositModel, "argos", "ARGOS", "https://argos.openaire.eu/", this.configLoader.getDOIFunders()); + + HttpEntity request = new HttpEntity<>(deposit, headers); + Map createResponse; + LinkedHashMap 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) createResponse.get("links"); + finalDoi = (String) createResponse.get("conceptdoi"); + } 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; + ResponseEntity listResponses = restTemplate.getForEntity(listUrl, Map[].class); + createResponse = listResponses.getBody()[0]; + links = (LinkedHashMap) createResponse.get("links"); + //Second, make the new version (not in the links?) + String newVersionUrl = links.get("self") + "/actions/newversion" + "?access_token=" + zenodoToken; + createResponse = restTemplate.postForObject(newVersionUrl, null, Map.class); + links = (LinkedHashMap) createResponse.get("links"); + //Third, get the new deposit + String latestDraftUrl = links.get("latest_draft") + "?access_token=" + zenodoToken; + createResponse = restTemplate.getForObject(latestDraftUrl, Map.class); + links = (LinkedHashMap) createResponse.get("links"); + finalDoi = (String) createResponse.get("conceptdoi"); + //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 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 listResponses = restTemplate.getForEntity(listUrl, Map[].class); + createResponse = listResponses.getBody()[0]; + links = (LinkedHashMap) createResponse.get("links"); + } + } + + if (!update) { + if (unpublishedUrl == null) { + // Second step, add the file to the entry. + File pdfFile = dmpDepositModel.getPdfFile(); + String name = dmpDepositModel.getPdfFileName(); + String fileName = name + ".pdf"; + FileSystemResource fileSystemResource = new FileSystemResource(pdfFile); + HttpEntity addFileMapRequest = new HttpEntity<>(fileSystemResource, null); + + String addFileUrl = links.get("bucket") + "/" + fileName + "?access_token=" + zenodoToken; + restTemplate.put(addFileUrl, addFileMapRequest); + + ResponseEntity jsonFile = dmpDepositModel.getRdaJson(); + UUID jsonFileUUID = UUID.randomUUID(); + File tempJsonFile = new File(jsonFileUUID + ".json"); // temp storage?? + 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()); + + + // 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; + } +// if (dmp.isPublic()) { + Map publishResponce = restTemplate.postForObject(publishUrl, "", Map.class); + finalDoi = (String) publishResponce.get("conceptdoi"); +// } + } else { + Map editResponce = restTemplate.postForObject(links.get("edit") + "?access_token=" + zenodoToken, "", Map.class); + restTemplate.put(links.get("self") + "?access_token=" + zenodoToken, request); + Map publishResponce = restTemplate.postForObject(links.get("publish") + "?access_token=" + zenodoToken, "", Map.class); + finalDoi = (String) publishResponce.get("conceptdoi"); + } + + return finalDoi; + } catch (HttpClientErrorException | HttpServerErrorException ex) { + Map parsedException = objectMapper.readValue(ex.getResponseBodyAsString(), HashMap.class); + throw new IOException(parsedException.get("message"), ex); + } + + } + + @Override + public RepositoryDepositConfiguration getConfiguration() { + RepositoryDepositConfiguration conf = new RepositoryDepositConfiguration(); + conf.setDepositAccountStatus(BothWaysDeposit.getValue()); + conf.setRepositoryId("Zenodo"); + conf.setAccessToken("pcqw4LGLrhp17FF5GoXNCXakkEi82ThchZw7Tk4qh74VrDE3EmliG3UlhYtd"); + conf.setRepositoryUrl("https://sandbox.zenodo.org/api/"); + conf.setRepositoryLoginAccessTokenUrl("https://sandbox.zenodo.org/oauth/token"); + conf.setRepositoryLoginClientId("hEmVRNc1OzRmWyi2GDR3XVKbhG3OtfJXLXkkOGXx"); + conf.setRepositoryLoginClientSecret("7VSU0NjiAg0P3mv14wemMYy2XhvlmV6F7xoszxPH4ZDx98v8FdMpBbxlncqr"); + conf.setRepositoryLoginRedirectUri("http://localhost:4200/login/external/zenodo"); + return conf; + } + + @Override + public String authenticate(String code){ + + RepositoryDepositConfiguration conf = this.getConfiguration(); + + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = new HttpHeaders(); + headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + + MultiValueMap map = new LinkedMultiValueMap<>(); + map.add("client_id", conf.getRepositoryLoginClientId()); + map.add("client_secret", conf.getRepositoryLoginClientSecret()); + map.add("grant_type", "authorization_code"); + map.add("code", code); + map.add("redirect_uri", conf.getRepositoryLoginRedirectUri()); + HttpEntity> request = new HttpEntity<>(map, headers); + + try { + Map values = restTemplate.postForObject(conf.getRepositoryLoginAccessTokenUrl(), request, Map.class); + //ZenodoResponseToken zenodoResponseToken = new ZenodoResponseToken(); + Map user = (Map) 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; + } + + 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 links = null; + LinkedHashMap metadata = null; + String listUrl = zenodoUrl + "deposit/depositions" + "?q=conceptdoi:\"" + DOI + "\"&access_token=" + token; + ResponseEntity listResponses = restTemplate.getForEntity(listUrl, Map[].class); + createResponse = listResponses.getBody()[0]; + metadata = (LinkedHashMap) createResponse.get("metadata"); + links = (LinkedHashMap) 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; + } + } +} diff --git a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/mapper/DMPToZenodoMapper.java b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/mapper/DMPToZenodoMapper.java new file mode 100644 index 000000000..efc037599 --- /dev/null +++ b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/mapper/DMPToZenodoMapper.java @@ -0,0 +1,119 @@ +package eu.eudat.depositinterface.zenodorepository.mapper; + +import eu.eudat.depositinterface.models.DMPDepositModel; +import eu.eudat.depositinterface.models.OrganisationDepositModel; +import eu.eudat.depositinterface.models.UserDMPDepositModel; +import eu.eudat.depositinterface.zenodorepository.config.DOIFunder; +import eu.eudat.depositinterface.zenodorepository.models.*; + +import java.time.Instant; +import java.util.*; +import java.util.stream.Collectors; + +public class DMPToZenodoMapper { + + public static ZenodoDeposit fromDMP(DMPDepositModel dmp, String zenodoCommunity, String zenodoAffiliation, String domain, List doiFunders) { + Map extraProperties = dmp.getExtraProperties() != null ? new org.json.JSONObject(dmp.getExtraProperties()).toMap() : new HashMap<>(); + ZenodoDeposit deposit = new ZenodoDeposit(); + deposit.setMetadata(new ZenodoDepositMetadata()); + deposit.getMetadata().setTitle(dmp.getLabel()); + deposit.getMetadata().setUploadType("publication"); + deposit.getMetadata().setPublicationType("datamanagementplan"); + deposit.getMetadata().setDescription((dmp.getDescription() != null && !dmp.getDescription().isEmpty() ? dmp.getDescription() : "

")); + deposit.getMetadata().setVersion(String.valueOf(dmp.getVersion())); + if(zenodoCommunity != null && !zenodoAffiliation.isEmpty()) { + ZenodoComunity community = new ZenodoComunity(); + community.setIdentifier(zenodoCommunity); + deposit.getMetadata().setCommunities(Collections.singletonList(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(domain + "/external/zenodo/" + dmp.getId().toString()); + relator.setRelation("isIdenticalTo"); + deposit.getMetadata().setRelatedIdentifiers(Collections.singletonList(relator)); + } + deposit.getMetadata().setContributors(new LinkedList<>()); + List contributors = 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 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(contributors); + deposit.getMetadata().getContributors().addAll(researchers); + + 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]; + 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().setGrants(Collections.singletonList(grant)); + } + } + ZenodoContributor creator = new ZenodoContributor(); + 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().setCreators(Collections.singletonList(creator)); + + return deposit; + } +} + diff --git a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoAccessRight.java b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoAccessRight.java new file mode 100644 index 000000000..0cf6cd4b6 --- /dev/null +++ b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoAccessRight.java @@ -0,0 +1,18 @@ +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; + } +} diff --git a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoComunity.java b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoComunity.java new file mode 100644 index 000000000..a04a19c17 --- /dev/null +++ b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoComunity.java @@ -0,0 +1,19 @@ +package eu.eudat.depositinterface.zenodorepository.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ZenodoComunity { + + private String identifier; + + public String getIdentifier() { + return identifier; + } + + public void setIdentifier(String identifier) { + this.identifier = identifier; + } +} diff --git a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoContributor.java b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoContributor.java new file mode 100644 index 000000000..c172d5220 --- /dev/null +++ b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoContributor.java @@ -0,0 +1,45 @@ +package eu.eudat.depositinterface.zenodorepository.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ZenodoContributor { + private String name; + private String type; + private String affiliation; + private String orcid; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getAffiliation() { + return affiliation; + } + + public void setAffiliation(String affiliation) { + this.affiliation = affiliation; + } + + public String getOrcid() { + return orcid; + } + + public void setOrcid(String orcid) { + this.orcid = orcid; + } +} diff --git a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoDeposit.java b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoDeposit.java new file mode 100644 index 000000000..c27c2530f --- /dev/null +++ b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoDeposit.java @@ -0,0 +1,19 @@ +package eu.eudat.depositinterface.zenodorepository.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ZenodoDeposit { + + private ZenodoDepositMetadata metadata; + + public ZenodoDepositMetadata getMetadata() { + return metadata; + } + + public void setMetadata(ZenodoDepositMetadata metadata) { + this.metadata = metadata; + } +} diff --git a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoDepositMetadata.java b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoDepositMetadata.java new file mode 100644 index 000000000..041f9623e --- /dev/null +++ b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoDepositMetadata.java @@ -0,0 +1,158 @@ +package eu.eudat.depositinterface.zenodorepository.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +import java.util.List; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ZenodoDepositMetadata { + + private String title; + + @JsonProperty("upload_type") + private String uploadType; + + @JsonProperty("publication_type") + private String publicationType; + + private String description; + + private String version; + + private List communities; + + @JsonProperty("access_right") + private ZenodoAccessRight accessRight; + + @JsonProperty("access_conditions") + private String accessConditions; + + @JsonProperty("embargo_date") + private String embargoDate; + + private String license; + + @JsonProperty("related_identifiers") + private List relatedIdentifiers; + + private List contributors; + + private List grants; + + private List creators; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getUploadType() { + return uploadType; + } + + public void setUploadType(String uploadType) { + this.uploadType = uploadType; + } + + public String getPublicationType() { + return publicationType; + } + + public void setPublicationType(String publicationType) { + this.publicationType = publicationType; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public List getCommunities() { + return communities; + } + + public void setCommunities(List communities) { + this.communities = communities; + } + + public ZenodoAccessRight getAccessRight() { + return accessRight; + } + + public void setAccessRight(ZenodoAccessRight accessRight) { + this.accessRight = accessRight; + } + + public String getAccessConditions() { + return accessConditions; + } + + public void setAccessConditions(String accessConditions) { + this.accessConditions = accessConditions; + } + + public String getEmbargoDate() { + return embargoDate; + } + + public void setEmbargoDate(String embargoDate) { + this.embargoDate = embargoDate; + } + + public String getLicense() { + return license; + } + + public void setLicense(String license) { + this.license = license; + } + + public List getRelatedIdentifiers() { + return relatedIdentifiers; + } + + public void setRelatedIdentifiers(List relatedIdentifiers) { + this.relatedIdentifiers = relatedIdentifiers; + } + + public List getContributors() { + return contributors; + } + + public void setContributors(List contributors) { + this.contributors = contributors; + } + + public List getGrants() { + return grants; + } + + public void setGrants(List grants) { + this.grants = grants; + } + + public List getCreators() { + return creators; + } + + public void setCreators(List creators) { + this.creators = creators; + } +} diff --git a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoGrant.java b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoGrant.java new file mode 100644 index 000000000..d37c6575e --- /dev/null +++ b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoGrant.java @@ -0,0 +1,18 @@ +package eu.eudat.depositinterface.zenodorepository.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ZenodoGrant { + private String id; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } +} diff --git a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoRelator.java b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoRelator.java new file mode 100644 index 000000000..8196f63a3 --- /dev/null +++ b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/models/ZenodoRelator.java @@ -0,0 +1,28 @@ +package eu.eudat.depositinterface.zenodorepository.models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; +import com.fasterxml.jackson.annotation.JsonInclude; + +@JsonIgnoreProperties(ignoreUnknown = true) +@JsonInclude(JsonInclude.Include.NON_NULL) +public class ZenodoRelator { + + private String identifier; + private String relation; + + public String getIdentifier() { + return identifier; + } + + public void setIdentifier(String identifier) { + this.identifier = identifier; + } + + public String getRelation() { + return relation; + } + + public void setRelation(String relation) { + this.relation = relation; + } +} diff --git a/dmp-backend/zenodoRepository/src/main/resources/DOI_Funder.json b/dmp-backend/zenodoRepository/src/main/resources/DOI_Funder.json new file mode 100644 index 000000000..9f1c4856d --- /dev/null +++ b/dmp-backend/zenodoRepository/src/main/resources/DOI_Funder.json @@ -0,0 +1,70 @@ +[ + { + "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" + } +] \ No newline at end of file diff --git a/dmp-backend/zenodoRepository/src/main/resources/application.properties b/dmp-backend/zenodoRepository/src/main/resources/application.properties new file mode 100644 index 000000000..51594e272 --- /dev/null +++ b/dmp-backend/zenodoRepository/src/main/resources/application.properties @@ -0,0 +1 @@ +configuration.doi_funder=DOI_Funder.json diff --git a/dmp-frontend/src/app/core/common/enum/deposit-configuration-status.ts b/dmp-frontend/src/app/core/common/enum/deposit-configuration-status.ts new file mode 100644 index 000000000..fc5787572 --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/deposit-configuration-status.ts @@ -0,0 +1,5 @@ +export enum DepositConfigurationStatus { + System = 0, + User = 1, + BothSystemAndUser = 2 +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/model/deposit/deposit-configuration.ts b/dmp-frontend/src/app/core/model/deposit/deposit-configuration.ts new file mode 100644 index 000000000..1e2ef02e1 --- /dev/null +++ b/dmp-frontend/src/app/core/model/deposit/deposit-configuration.ts @@ -0,0 +1,11 @@ +import { DepositConfigurationStatus } from "@app/core/common/enum/deposit-configuration-status"; + +export class DepositConfigurationModel { + depositAccountStatus: DepositConfigurationStatus; + repositoryId: string; + accessToken: string; + repositoryUrl: string; + repositoryLoginAccessTokenUrl: string; + repositoryLoginClientId: string; + repositoryLoginClientSecret: string; +} diff --git a/dmp-frontend/src/app/core/model/deposit/deposit-request.ts b/dmp-frontend/src/app/core/model/deposit/deposit-request.ts new file mode 100644 index 000000000..daf62d32c --- /dev/null +++ b/dmp-frontend/src/app/core/model/deposit/deposit-request.ts @@ -0,0 +1,5 @@ +export class DepositRequest { + repositoryId: string; + dmpId: string; + accessToken: string; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts b/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts index dd6ebfde2..2c9becc6c 100644 --- a/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts +++ b/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts @@ -1,5 +1,7 @@ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; +import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration'; +import { DepositRequest } from '@app/core/model/deposit/deposit-request'; import { Observable } from 'rxjs'; import { ConfigurationService } from '../configuration/configuration.service'; import { BaseHttpService } from '../http/base-http.service'; @@ -14,7 +16,19 @@ export class DepositRepositoriesService { this.actionUrl = configurationService.server + 'deposit/'; } - getAvailableRepos(): Observable { - return this.http.get(this.actionUrl + 'repos/', { headers: this.headers }); + getAvailableRepos(): Observable { + return this.http.get(this.actionUrl + 'repos', { headers: this.headers }); + } + + getAccessToken(repository: string, code: string): Observable { + return this.http.get(this.actionUrl + 'getAccessToken?repository=' + repository + '&code=' + code, { headers: this.headers }); + } + + createDoi(repositoryId: string, dmpId: string, accessToken: string): Observable { + const depositRequest = new DepositRequest(); + depositRequest.repositoryId = repositoryId; + depositRequest.dmpId = dmpId; + depositRequest.accessToken = accessToken; + return this.http.post(this.actionUrl + 'createDoi', depositRequest, { headers: this.headers }); } } diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.html b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.html index 8dbb6dcd3..407452047 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.html @@ -5,21 +5,17 @@
- - - - {{ repo }} - - - + + +
-
{{ 'DMP-FINALISE-DIALOG.EMPTY' | translate }}
+
No publishing repositories so far
-
+
\ No newline at end of file diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts index 04247b533..2fb0eac2d 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts @@ -1,6 +1,17 @@ import { Component, Inject, OnInit } from '@angular/core'; import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; +import { DepositConfigurationStatus } from '@app/core/common/enum/deposit-configuration-status'; +import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration'; +import { DmpOverviewModel } from '@app/core/model/dmp/dmp-overview'; +import { DepositRepositoriesService } from '@app/core/services/deposit-repositories/deposit-repositories.service'; +import { DmpService } from '@app/core/services/dmp/dmp.service'; +import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; +import { Oauth2DialogService } from '@app/ui/misc/oauth2-dialog/service/oauth2-dialog.service'; import { BaseComponent } from '@common/base/base.component'; +import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; +import { MultipleChoiceDialogComponent } from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.component'; +import { TranslateService } from '@ngx-translate/core'; +import { takeUntil } from 'rxjs/operators'; @Component({ selector: 'app-dmp-deposit-dialog', @@ -9,15 +20,23 @@ import { BaseComponent } from '@common/base/base.component'; }) export class DmpDepositDialogComponent extends BaseComponent implements OnInit { - inputRepos: string[]; + inputRepos: DepositConfigurationModel[]; outputRepos: string[]; + dmp: DmpOverviewModel; constructor( + private dmpService: DmpService, + private depositRepositoriesService: DepositRepositoriesService, public dialogRef: MatDialogRef, + private dialog: MatDialog, + private language: TranslateService, + private uiNotificationService: UiNotificationService, + private oauth2DialogService: Oauth2DialogService, @Inject(MAT_DIALOG_DATA) public data: any ) { super(); - this.inputRepos = data['depositRepos']; + this.inputRepos = data['depositRepos'][0]; + this.dmp = data['depositRepos'][1]; this.outputRepos = []; } @@ -32,4 +51,75 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit { this.dialogRef.close(this.outputRepos); } + deposit(repo: DepositConfigurationModel) { + + if(repo.depositAccountStatus == DepositConfigurationStatus.BothSystemAndUser){ + + const dialogRef = this.dialog.open(MultipleChoiceDialogComponent, { + maxWidth: '600px', + restoreFocus: false, + data: { + message: 'Which account would you like to use?',//this.language.instant('GENERAL.ERRORS.HTTP-REQUEST-ERROR'), + titles: ['Login with ' + repo.repositoryId/*this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.ZENODO-LOGIN')*/, this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.USE-DEFAULT')] + } + }); + dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { + switch (result) { + case 0: + this.showOauth2Dialog('https://sandbox.zenodo.org/oauth/authorize'+ '?client_id=' + repo.repositoryLoginClientId + + '&response_type=code&scope=deposit:write+deposit:actions+user:email&state=astate&redirect_uri=' + + 'http://localhost:4200/login/external/zenodo', repo, this.dmp); + break; + case 1: + // this.dmpService.getDoi(dmp.id) + // .pipe(takeUntil(this._destroyed)) + // .subscribe( + // complete => { + // this.onDOICallbackSuccess(); + // this.dmp.doi = complete; + // }, + // error => this.onDeleteCallbackError(error) + // ); + break; + } + }); + + } + } + + onDOICallbackSuccess(): void { + this.uiNotificationService.snackBarNotification(this.language.instant('DMP-EDITOR.SNACK-BAR.SUCCESSFUL-DOI'), SnackBarNotificationLevel.Success); + } + + onDeleteCallbackError(error) { + this.uiNotificationService.snackBarNotification(error.error.message ? this.language.instant(error.error.message) : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error); + } + + showOauth2Dialog(url: string, repo: DepositConfigurationModel, dmp: DmpOverviewModel) { + this.oauth2DialogService.login(url) + .pipe(takeUntil(this._destroyed)) + .subscribe(result => { + if (result !== undefined) { + if (result.oauthCode !== undefined && result.oauthCode !== null) { + this.depositRepositoriesService.getAccessToken(repo.repositoryId, result.oauthCode) + .pipe(takeUntil(this._destroyed)) + .subscribe(token => { + console.log(token); + this.depositRepositoriesService.createDoi(repo.repositoryId, dmp.id, token) + .pipe(takeUntil(this._destroyed)) + .subscribe(doi =>{ + console.log(doi); + }); + }); + // this.userService.registerDOIToken(result.oauthCode, this.configurationService.app + 'oauth2') + // .pipe(takeUntil(this._destroyed)) + // .subscribe(() => { + // this.hasDOIToken = true; + // this.showConfirmationDOIDialog(dmp); + // }); + } + } + }); + } + } diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts index 63c3a8231..bf561abbc 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts @@ -43,6 +43,7 @@ import { MatomoService } from '@app/core/services/matomo/matomo-service'; import { PopupNotificationDialogComponent } from '@app/library/notification/popup/popup-notification.component'; import { DepositRepositoriesService } from '@app/core/services/deposit-repositories/deposit-repositories.service'; import { DmpDepositDialogComponent } from '../editor/dmp-deposit-dialog/dmp-deposit-dialog.component'; +import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration'; @Component({ selector: 'app-dmp-overview', @@ -70,7 +71,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { @ViewChild('doi') doi: ElementRef; - depositRepos: String[]; + depositRepos: DepositConfigurationModel[]; formGroup: FormGroup; @@ -589,18 +590,24 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { .subscribe( repos => { this.depositRepos = repos; + const dialogRef = this.dialog.open(DmpDepositDialogComponent, { + maxWidth: '600px', + restoreFocus: false, + autoFocus: false, + data: { + depositRepos: [this.depositRepos, this.dmp], + message: "Select repositories to deposit",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.FINALIZE-ITEM'), + confirmButton: "Proceed to authentication",//this.language.instant('DMP-FINALISE-DIALOG.SUBMIT'), + cancelButton: "Cancel",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), + } + }); + dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe((result: string[]) => { + if (result) { + this.dmp.doi = result[0]; + } + }); } ); - const dialogRef = this.dialog.open(DmpDepositDialogComponent, { - restoreFocus: false, - autoFocus: false, - data: { - depositRepos: this.depositRepos, - message: "Select repositories to deposit",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.FINALIZE-ITEM'), - confirmButton: "Proceed to authentication",//this.language.instant('DMP-FINALISE-DIALOG.SUBMIT'), - cancelButton: "Cancel",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), - } - }); } finalize(dmp: DmpOverviewModel) { From 7d624a2daa346a075d6a9514134f615508baa02a Mon Sep 17 00:00:00 2001 From: Aldo Mihasi Date: Thu, 27 Oct 2022 09:32:26 +0300 Subject: [PATCH 03/26] [WIP] system deposit authentication, using default repo token --- .../eudat/controllers/DepositController.java | 10 +++++---- .../managers/DataManagementPlanManager.java | 4 ++-- .../eu/eudat/models/data/doi/DepositCode.java | 21 +++++++++++++++++++ .../interfaces/ZenodoDeposit.java | 7 ++++++- .../app/core/model/deposit/deposit-request.ts | 5 +++++ .../deposit-repositories.service.ts | 11 ++++++---- .../dmp-deposit-dialog.component.ts | 21 ++++++++----------- .../ui/dmp/overview/dmp-overview.component.ts | 1 + 8 files changed, 57 insertions(+), 23 deletions(-) create mode 100644 dmp-backend/web/src/main/java/eu/eudat/models/data/doi/DepositCode.java diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java index 1687f560f..c0d603dba 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java @@ -4,6 +4,7 @@ import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration; import eu.eudat.logic.managers.DepositManager; import eu.eudat.logic.security.claims.ClaimedAuthorities; import eu.eudat.logic.services.ApiContext; +import eu.eudat.models.data.doi.DepositCode; import eu.eudat.models.data.doi.DepositRequest; import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.models.data.security.Principal; @@ -39,15 +40,16 @@ public class DepositController extends BaseController { return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(ids)); } - @RequestMapping(method = RequestMethod.GET, value = {"/getAccessToken"}) + @RequestMapping(method = RequestMethod.POST, value = {"/getAccessToken"}) public @ResponseBody - ResponseEntity> getAccessToken(@RequestParam("repository") String repository, @RequestParam("code") String code, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws Exception { - String accessToken = this.depositManager.authenticate(repository, code); + ResponseEntity> getAccessToken(@RequestBody DepositCode depositCode, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws Exception { + String accessToken = this.depositManager.authenticate(depositCode.getRepositoryId(), depositCode.getCode()); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.NO_MESSAGE).payload(accessToken)); } @RequestMapping(method = RequestMethod.POST, value = {"/createDoi"}) - public ResponseEntity> createDoi(@RequestBody DepositRequest depositRequest, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) { + public @ResponseBody + ResponseEntity> createDoi(@RequestBody DepositRequest depositRequest, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) { try { String doi = this.depositManager.deposit(depositRequest, principal); return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully created DOI for Data Datamanagement Plan in question.").payload(doi)); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java index b6d734eb4..fff2b168a 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java @@ -2151,8 +2151,8 @@ public class DataManagementPlanManager { } }).orElse(null); if (finalDoi != null) { - //dmp.setDoi(finalDoi); - //apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); + dmp.setDoi(finalDoi); + apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); } Files.deleteIfExists(file.getFile().toPath()); diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/DepositCode.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/DepositCode.java new file mode 100644 index 000000000..a567dc9da --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/DepositCode.java @@ -0,0 +1,21 @@ +package eu.eudat.models.data.doi; + +public class DepositCode { + + private String repositoryId; + private String code; + + public String getRepositoryId() { + return repositoryId; + } + public void setRepositoryId(String repositoryId) { + this.repositoryId = repositoryId; + } + + public String getCode() { + return code; + } + public void setCode(String code) { + this.code = code; + } +} diff --git a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/interfaces/ZenodoDeposit.java b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/interfaces/ZenodoDeposit.java index c3bdef1ad..b8696885f 100644 --- a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/interfaces/ZenodoDeposit.java +++ b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/interfaces/ZenodoDeposit.java @@ -27,7 +27,7 @@ import java.io.IOException; import java.nio.file.Files; import java.util.*; -import static eu.eudat.depositinterface.repository.RepositoryDepositConfiguration.DepositAccountStatus.BothWaysDeposit; +import static eu.eudat.depositinterface.repository.RepositoryDepositConfiguration.DepositAccountStatus.*; @Component public class ZenodoDeposit implements RepositoryDeposit { @@ -45,6 +45,11 @@ public class ZenodoDeposit implements RepositoryDeposit { public String deposit(DMPDepositModel dmpDepositModel, boolean update, String zenodoToken) throws Exception { RepositoryDepositConfiguration conf = this.getConfiguration(); + + if(zenodoToken == null){ + zenodoToken = conf.getAccessToken(); + } + String zenodoUrl = conf.getRepositoryUrl(); // First step, post call to Zenodo, to create the entry. diff --git a/dmp-frontend/src/app/core/model/deposit/deposit-request.ts b/dmp-frontend/src/app/core/model/deposit/deposit-request.ts index daf62d32c..10ee13980 100644 --- a/dmp-frontend/src/app/core/model/deposit/deposit-request.ts +++ b/dmp-frontend/src/app/core/model/deposit/deposit-request.ts @@ -2,4 +2,9 @@ export class DepositRequest { repositoryId: string; dmpId: string; accessToken: string; +} + +export class DepositCode { + repositoryId: string; + code: string; } \ No newline at end of file diff --git a/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts b/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts index 2c9becc6c..d4cee9ada 100644 --- a/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts +++ b/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts @@ -1,7 +1,7 @@ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration'; -import { DepositRequest } from '@app/core/model/deposit/deposit-request'; +import { DepositCode, DepositRequest } from '@app/core/model/deposit/deposit-request'; import { Observable } from 'rxjs'; import { ConfigurationService } from '../configuration/configuration.service'; import { BaseHttpService } from '../http/base-http.service'; @@ -20,11 +20,14 @@ export class DepositRepositoriesService { return this.http.get(this.actionUrl + 'repos', { headers: this.headers }); } - getAccessToken(repository: string, code: string): Observable { - return this.http.get(this.actionUrl + 'getAccessToken?repository=' + repository + '&code=' + code, { headers: this.headers }); + getAccessToken(repositoryId: string, code: string): Observable { + const depositCode = new DepositCode(); + depositCode.repositoryId = repositoryId; + depositCode.code = code; + return this.http.post(this.actionUrl + 'getAccessToken', depositCode, { headers: this.headers }); } - createDoi(repositoryId: string, dmpId: string, accessToken: string): Observable { + createDoi(repositoryId: string, dmpId: string, accessToken: string | null): Observable { const depositRequest = new DepositRequest(); depositRequest.repositoryId = repositoryId; depositRequest.dmpId = dmpId; diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts index 2fb0eac2d..acd7dec11 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts @@ -71,15 +71,12 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit { + 'http://localhost:4200/login/external/zenodo', repo, this.dmp); break; case 1: - // this.dmpService.getDoi(dmp.id) - // .pipe(takeUntil(this._destroyed)) - // .subscribe( - // complete => { - // this.onDOICallbackSuccess(); - // this.dmp.doi = complete; - // }, - // error => this.onDeleteCallbackError(error) - // ); + this.depositRepositoriesService.createDoi(repo.repositoryId, this.dmp.id, null) + .pipe(takeUntil(this._destroyed)) + .subscribe(doi =>{ + this.onDOICallbackSuccess(); + this.outputRepos.push(doi); + }, error => this.onDeleteCallbackError(error)); break; } }); @@ -104,12 +101,12 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit { this.depositRepositoriesService.getAccessToken(repo.repositoryId, result.oauthCode) .pipe(takeUntil(this._destroyed)) .subscribe(token => { - console.log(token); this.depositRepositoriesService.createDoi(repo.repositoryId, dmp.id, token) .pipe(takeUntil(this._destroyed)) .subscribe(doi =>{ - console.log(doi); - }); + this.onDOICallbackSuccess(); + this.outputRepos.push(doi); + }, error => this.onDeleteCallbackError(error)); }); // this.userService.registerDOIToken(result.oauthCode, this.configurationService.app + 'oauth2') // .pipe(takeUntil(this._destroyed)) diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts index bf561abbc..eb89f320d 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts @@ -604,6 +604,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe((result: string[]) => { if (result) { this.dmp.doi = result[0]; + this.hasDOIToken = true; } }); } From 59e26dbb8de840df6a991b270723243d1409fb87 Mon Sep 17 00:00:00 2001 From: Aldo Mihasi Date: Wed, 2 Nov 2022 09:41:40 +0200 Subject: [PATCH 04/26] [WIP] EntityDoi table --- .../eudat/data/dao/entities/EntityDoiDao.java | 9 ++ .../data/dao/entities/EntityDoiDaoImpl.java | 51 ++++++++ .../main/java/eu/eudat/data/entities/DMP.java | 11 ++ .../eu/eudat/data/entities/EntityDoi.java | 121 ++++++++++++++++++ .../eudat/controllers/DepositController.java | 9 +- .../managers/DataManagementPlanManager.java | 23 +++- .../eudat/logic/managers/DepositManager.java | 3 +- .../operations/DatabaseRepository.java | 2 + .../operations/DatabaseRepositoryImpl.java | 10 ++ .../models/data/dmp/DataManagementPlan.java | 11 ++ .../java/eu/eudat/models/data/doi/Doi.java | 85 ++++++++++++ .../DataManagementPlanOverviewModel.java | 13 ++ dmp-db-scema/main/dmp-dump.sql | 21 +++ .../updates/00.00.010_Add_EntityDoi_table.sql | 26 ++++ ...Migrate_data_from_dmp_doi_to_entitydoi.sql | 14 ++ .../00.00.012.Delete_doi_from_dmp_table.sql | 11 ++ .../src/app/core/model/dmp/dmp-overview.ts | 2 + dmp-frontend/src/app/core/model/doi/doi.ts | 7 + .../deposit-repositories.service.ts | 5 +- .../dmp-deposit-dialog.component.ts | 18 ++- .../dmp/overview/dmp-overview.component.html | 32 ++++- .../ui/dmp/overview/dmp-overview.component.ts | 57 +++++---- 22 files changed, 498 insertions(+), 43 deletions(-) create mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDao.java create mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDaoImpl.java create mode 100644 dmp-backend/data/src/main/java/eu/eudat/data/entities/EntityDoi.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/models/data/doi/Doi.java create mode 100644 dmp-db-scema/updates/00.00.010_Add_EntityDoi_table.sql create mode 100644 dmp-db-scema/updates/00.00.011.Migrate_data_from_dmp_doi_to_entitydoi.sql create mode 100644 dmp-db-scema/updates/00.00.012.Delete_doi_from_dmp_table.sql create mode 100644 dmp-frontend/src/app/core/model/doi/doi.ts diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDao.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDao.java new file mode 100644 index 000000000..d6629f598 --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDao.java @@ -0,0 +1,9 @@ +package eu.eudat.data.dao.entities; + +import eu.eudat.data.dao.DatabaseAccessLayer; +import eu.eudat.data.entities.EntityDoi; + +import java.util.UUID; + +public interface EntityDoiDao extends DatabaseAccessLayer { +} diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDaoImpl.java b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDaoImpl.java new file mode 100644 index 000000000..ead4e2a5c --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/dao/entities/EntityDoiDaoImpl.java @@ -0,0 +1,51 @@ +package eu.eudat.data.dao.entities; + +import eu.eudat.data.dao.DatabaseAccess; +import eu.eudat.data.dao.databaselayer.service.DatabaseService; +import eu.eudat.data.entities.EntityDoi; +import eu.eudat.queryable.QueryableList; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.UUID; +import java.util.concurrent.CompletableFuture; + +@Component("EntityDoiDao") +public class EntityDoiDaoImpl extends DatabaseAccess implements EntityDoiDao { + + @Autowired + public EntityDoiDaoImpl(DatabaseService databaseService){ + super(databaseService); + } + + + @Override + public EntityDoi createOrUpdate(EntityDoi item) { + return this.getDatabaseService().createOrUpdate(item, EntityDoi.class); + } + + @Override + public CompletableFuture createOrUpdateAsync(EntityDoi item) { + return CompletableFuture.supplyAsync(() -> this.createOrUpdate(item)); + } + + @Override + public EntityDoi find(UUID id) { + return this.getDatabaseService().getQueryable(EntityDoi.class).where((builder, root) -> builder.equal(root.get("id"), id)).getSingle(); + } + + @Override + public EntityDoi find(UUID id, String hint) { + return null; + } + + @Override + public void delete(EntityDoi item) { + this.getDatabaseService().delete(item); + } + + @Override + public QueryableList asQueryable() { + return this.getDatabaseService().getQueryable(EntityDoi.class); + } +} diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java index b4f212210..14c55dee8 100644 --- a/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/DMP.java @@ -184,6 +184,9 @@ public class DMP implements DataEntity { @Column(name = "\"DOI\"") private String doi; + @OneToMany(mappedBy = "entityId", fetch = FetchType.LAZY) + private Set dois; + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "\"Project\"") private Project project; @@ -346,6 +349,13 @@ public class DMP implements DataEntity { this.doi = doi; } + public Set getDois() { + return dois; + } + public void setDois(Set dois) { + this.dois = dois; + } + public Project getProject() { return project; } @@ -381,6 +391,7 @@ public class DMP implements DataEntity { if (entity.isPublic) this.setPublishedAt(new Date()); if (entity.getUsers() != null) this.users = entity.getUsers(); if (entity.getDoi() != null && entity.getDoi().trim().isEmpty()) this.doi = entity.doi; + this.dois = entity.getDois(); this.extraProperties = entity.getExtraProperties(); } diff --git a/dmp-backend/data/src/main/java/eu/eudat/data/entities/EntityDoi.java b/dmp-backend/data/src/main/java/eu/eudat/data/entities/EntityDoi.java new file mode 100644 index 000000000..a0b86c6c5 --- /dev/null +++ b/dmp-backend/data/src/main/java/eu/eudat/data/entities/EntityDoi.java @@ -0,0 +1,121 @@ +package eu.eudat.data.entities; + +import eu.eudat.data.converters.DateToUTCConverter; +import eu.eudat.data.entities.helpers.EntityBinder; +import eu.eudat.queryable.queryableentity.DataEntity; +import org.hibernate.annotations.Type; + +import javax.persistence.*; +import java.util.Arrays; +import java.util.Date; +import java.util.List; +import java.util.UUID; +import java.util.stream.Collectors; + +@Entity +@Table(name = "\"EntityDoi\"") +public class EntityDoi implements DataEntity { + public enum EntityType { + DMP + } + + @Id + @Column(name = "\"ID\"", updatable = false, nullable = false, columnDefinition = "BINARY(16)") + private UUID id; + + @Enumerated(EnumType.STRING) + @Type(type = "eu.eudat.configurations.typedefinition.PostgreSQLEnumType") + @Column(name = "\"EntityType\"", nullable = false) + private EntityType entityType; + + @Column(name = "\"RepositoryId\"", nullable = false) + private String repositoryId; + + @Column(name = "\"Doi\"", nullable = false) + private String doi; + + @Column(name = "\"CreatedAt\"", nullable = false) + @Convert(converter = DateToUTCConverter.class) + private Date createdAt; + + @Column(name = "\"UpdatedAt\"", nullable = false) + @Convert(converter = DateToUTCConverter.class) + private Date updatedAt; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "\"EntityId\"", nullable = false) + private DMP entityId; + + public UUID getId() { + return id; + } + public void setId(UUID id) { + this.id = id; + } + + public EntityType getEntityType() { + return entityType; + } + public void setEntityType(EntityType entityType) { + this.entityType = entityType; + } + + public String getRepositoryId() { + return repositoryId; + } + public void setRepositoryId(String repositoryId) { + this.repositoryId = repositoryId; + } + + public String getDoi() { + return doi; + } + public void setDoi(String doi) { + this.doi = doi; + } + + public Date getCreatedAt() { + return createdAt; + } + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public Date getUpdatedAt() { + return updatedAt; + } + public void setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + } + + public DMP getEntityId() { + return entityId; + } + public void setEntityId(DMP entityId) { + this.entityId = entityId; + } + + @Override + public void update(EntityDoi doi) { + this.entityType = doi.getEntityType(); + this.repositoryId = doi.getRepositoryId(); + this.doi = doi.getDoi(); + this.createdAt = doi.getCreatedAt(); + this.updatedAt = doi.getUpdatedAt(); + this.entityId = doi.getEntityId(); + } + + @Override + public UUID getKeys() { + return this.id; + } + + @Override + public EntityDoi buildFromTuple(List tuple, List fields, String base) { + String currentBase = base.isEmpty() ? "" : base + "."; + if (fields.contains(currentBase + "id")) this.id = EntityBinder.fromTuple(tuple, currentBase + "id"); + if (fields.contains(currentBase + "entityId")) + this.entityId = tuple.stream().map(x -> new DMP().buildFromTuple(Arrays.asList(x), fields , base.isEmpty() ? "entityId" : base + "." + "entityId")).collect(Collectors.toList()).get(0); + return this; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java index c0d603dba..f579394d8 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/DepositController.java @@ -6,6 +6,7 @@ import eu.eudat.logic.security.claims.ClaimedAuthorities; import eu.eudat.logic.services.ApiContext; import eu.eudat.models.data.doi.DepositCode; import eu.eudat.models.data.doi.DepositRequest; +import eu.eudat.models.data.doi.Doi; import eu.eudat.models.data.helpers.responses.ResponseItem; import eu.eudat.models.data.security.Principal; import eu.eudat.types.ApiMessageCode; @@ -49,13 +50,13 @@ public class DepositController extends BaseController { @RequestMapping(method = RequestMethod.POST, value = {"/createDoi"}) public @ResponseBody - ResponseEntity> createDoi(@RequestBody DepositRequest depositRequest, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) { + ResponseEntity> createDoi(@RequestBody DepositRequest depositRequest, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) { try { - String doi = this.depositManager.deposit(depositRequest, principal); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully created DOI for Data Datamanagement Plan in question.").payload(doi)); + Doi doi = this.depositManager.deposit(depositRequest, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully created DOI for Data Datamanagement Plan in question.").payload(doi)); } catch (Exception e) { logger.error(e.getMessage(), e); - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to create DOI for the Data Management Plan: " + e.getMessage())); + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to create DOI for the Data Management Plan: " + e.getMessage())); } } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java index fff2b168a..a2a8ccc5c 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java @@ -49,6 +49,7 @@ import eu.eudat.models.data.datasetwizard.DatasetWizardModel; import eu.eudat.models.data.datasetwizard.DatasetsToBeFinalized; import eu.eudat.models.data.dmp.*; import eu.eudat.models.data.doi.DepositRequest; +import eu.eudat.models.data.doi.Doi; import eu.eudat.models.data.dynamicfields.DynamicFieldWithValue; import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.DataManagementPlanProfile; import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.Field; @@ -2104,7 +2105,7 @@ public class DataManagementPlanManager { return finalDoi; } - public String createDoi(DepositRequest depositRequest, Principal principal) throws Exception { + public Doi createDoi(DepositRequest depositRequest, Principal principal) throws Exception { DMP dmp = this.apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(UUID.fromString(depositRequest.getDmpId())); if (!isUserOwnerOfDmp(dmp, principal)) throw new Exception("User is not authorized to invoke this action"); @@ -2150,13 +2151,29 @@ public class DataManagementPlanManager { return null; } }).orElse(null); + Doi doiModel = null; if (finalDoi != null) { - dmp.setDoi(finalDoi); + + EntityDoi doiEntity = new EntityDoi(); + doiEntity.setId(UUID.randomUUID()); + doiEntity.setEntityType(EntityDoi.EntityType.DMP); + doiEntity.setDoi(finalDoi); + doiEntity.setRepositoryId(depositRequest.getRepositoryId()); + Date now = new Date(); + doiEntity.setCreatedAt(now); + doiEntity.setUpdatedAt(now); + doiEntity.setEntityId(dmp); + apiContext.getOperationsContext().getDatabaseRepository().getEntityDoiDao().createOrUpdate(doiEntity); + + dmp.getDois().add(doiEntity); apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp); + + doiModel = new Doi().fromDataModel(doiEntity); + } Files.deleteIfExists(file.getFile().toPath()); - return finalDoi; + return doiModel; } /* diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java index 978c27db7..49fceab84 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java @@ -9,6 +9,7 @@ import eu.eudat.logic.security.repositorydeposit.mapper.DMPToDepositMapper; import eu.eudat.logic.utilities.documents.helpers.FileEnvelope; import eu.eudat.logic.utilities.documents.pdf.PDFUtils; import eu.eudat.models.data.doi.DepositRequest; +import eu.eudat.models.data.doi.Doi; import eu.eudat.models.data.security.Principal; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -56,7 +57,7 @@ public class DepositManager { return repo.map(repositoryDeposit -> repositoryDeposit.authenticate(code)).orElse(null); } - public String deposit(DepositRequest depositRequest, Principal principal) throws Exception { + public Doi deposit(DepositRequest depositRequest, Principal principal) throws Exception { return this.dataManagementPlanManager.createDoi(depositRequest, principal); } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java index 67225a76d..99e088a1c 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepository.java @@ -60,5 +60,7 @@ public interface DatabaseRepository { FileUploadDao getFileUploadDao(); + EntityDoiDao getEntityDoiDao(); + void detachEntity(T entity); } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java index 7228b5b2f..2e2dd4c63 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/services/operations/DatabaseRepositoryImpl.java @@ -39,6 +39,7 @@ public class DatabaseRepositoryImpl implements DatabaseRepository { private LockDao lockDao; private NotificationDao notificationDao; private FileUploadDao fileUploadDao; + private EntityDoiDao entityDoiDao; private EntityManager entityManager; @@ -317,6 +318,15 @@ public class DatabaseRepositoryImpl implements DatabaseRepository { this.fileUploadDao = fileUploadDao; } + @Override + public EntityDoiDao getEntityDoiDao() { + return entityDoiDao; + } + + @Autowired + public void setEntityDoiDao(EntityDoiDao entityDoiDao) { + this.entityDoiDao = entityDoiDao; + } public void detachEntity(T entity) { this.entityManager.detach(entity); diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlan.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlan.java index cc2dcd4fb..f0fba6c80 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlan.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/dmp/DataManagementPlan.java @@ -4,6 +4,7 @@ import eu.eudat.data.entities.*; import eu.eudat.logic.utilities.builders.XmlBuilder; import eu.eudat.models.DataModel; import eu.eudat.models.data.datasetwizard.DatasetWizardModel; +import eu.eudat.models.data.doi.Doi; import eu.eudat.models.data.dynamicfields.DynamicFieldWithValue; import eu.eudat.models.data.entities.xmlmodels.dmpprofiledefinition.DataManagementPlanProfile; import eu.eudat.models.data.funder.Funder; @@ -41,6 +42,7 @@ public class DataManagementPlan implements DataModel { private Map properties; private List users; private String doi; + private List dois; private Project project; private Funder funder; private Boolean isPublic; @@ -201,6 +203,13 @@ public class DataManagementPlan implements DataModel { this.doi = doi; } + public List getDois() { + return dois; + } + public void setDois(List dois) { + this.dois = dois; + } + public Project getProject() { return project; } @@ -281,6 +290,7 @@ public class DataManagementPlan implements DataModel { this.associatedUsers = entity.getUsers() != null ? entity.getUsers().stream().map(item -> new UserListingModel().fromDataModel(item.getUser())).collect(Collectors.toList()) : new ArrayList<>(); this.users = entity.getUsers() != null ? entity.getUsers().stream().map(item -> new UserInfoListingModel().fromDataModel(item)).collect(Collectors.toList()) : new ArrayList<>(); this.doi = entity.getDoi(); + this.dois = entity.getDois() != null ? entity.getDois().stream().map(item -> new Doi().fromDataModel(item)).collect(Collectors.toList()): new ArrayList<>(); if (entity.getProject() != null) { this.project = new Project(); @@ -377,6 +387,7 @@ public class DataManagementPlan implements DataModel { this.associatedUsers = entity.getUsers() != null ? entity.getUsers().stream().map(item -> new UserListingModel().fromDataModel(item.getUser())).collect(Collectors.toList()) : new ArrayList<>(); this.users = entity.getUsers() != null ? entity.getUsers().stream().map(item -> new UserInfoListingModel().fromDataModel(item)).collect(Collectors.toList()) : new ArrayList<>(); this.doi = entity.getDoi(); + this.dois = entity.getDois() != null ? entity.getDois().stream().map(item -> new Doi().fromDataModel(item)).collect(Collectors.toList()): new ArrayList<>(); this.grant.fromDataModel(entity.getGrant()); if (entity.getProject() != null) { diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/Doi.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/Doi.java new file mode 100644 index 000000000..9a877dc4d --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/doi/Doi.java @@ -0,0 +1,85 @@ +package eu.eudat.models.data.doi; + +import eu.eudat.data.entities.EntityDoi; +import eu.eudat.models.DataModel; +import eu.eudat.models.data.dmp.DataManagementPlan; + +import java.util.Date; +import java.util.UUID; + +public class Doi implements DataModel { + private UUID id; + private String repositoryId; + private String doi; + private Date createdAt; + private Date updatedAt; + private DataManagementPlan dmp; + + public UUID getId() { + return id; + } + public void setId(UUID id) { + this.id = id; + } + + public String getRepositoryId() { + return repositoryId; + } + public void setRepositoryId(String repositoryId) { + this.repositoryId = repositoryId; + } + + public String getDoi() { + return doi; + } + public void setDoi(String doi) { + this.doi = doi; + } + + public Date getCreatedAt() { + return createdAt; + } + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + + public Date getUpdatedAt() { + return updatedAt; + } + public void setUpdatedAt(Date updatedAt) { + this.updatedAt = updatedAt; + } + + public DataManagementPlan getDmp() { + return dmp; + } + public void setDmp(DataManagementPlan dmp) { + this.dmp = dmp; + } + + @Override + public Doi fromDataModel(EntityDoi entity) { + this.id = entity.getId(); + this.repositoryId = entity.getRepositoryId(); + this.doi = entity.getDoi(); + this.createdAt = entity.getCreatedAt(); + this.updatedAt = entity.getUpdatedAt(); + return this; + } + + @Override + public EntityDoi toDataModel() throws Exception { + EntityDoi entityDoi = new EntityDoi(); + entityDoi.setId(this.id); + entityDoi.setRepositoryId(this.repositoryId); + entityDoi.setDoi(this.doi); + entityDoi.setCreatedAt(this.createdAt); + entityDoi.setUpdatedAt(this.updatedAt); + return entityDoi; + } + + @Override + public String getHint() { + return null; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanOverviewModel.java b/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanOverviewModel.java index e90d044c1..9aeac8e0f 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanOverviewModel.java +++ b/dmp-backend/web/src/main/java/eu/eudat/models/data/listingmodels/DataManagementPlanOverviewModel.java @@ -8,6 +8,7 @@ import eu.eudat.models.data.dataset.DatasetOverviewModel; import eu.eudat.models.data.dmp.AssociatedProfile; import eu.eudat.models.data.dmp.Organisation; import eu.eudat.models.data.dmp.Researcher; +import eu.eudat.models.data.doi.Doi; import eu.eudat.models.data.grant.GrantOverviewModel; import java.util.Date; @@ -36,6 +37,7 @@ public class DataManagementPlanOverviewModel implements DataModel dois; public String getId() { @@ -171,6 +173,13 @@ public class DataManagementPlanOverviewModel implements DataModel getDois() { + return dois; + } + public void setDois(List dois) { + this.dois = dois; + } + @Override public DataManagementPlanOverviewModel fromDataModel(DMP entity) { this.id = entity.getId().toString(); @@ -180,6 +189,9 @@ public class DataManagementPlanOverviewModel implements DataModel new Researcher().fromDataModel(item)).collect(Collectors.toList()); } + if(entity.getDois() != null){ + this.dois = entity.getDois().stream().map(item -> new Doi().fromDataModel(item)).collect(Collectors.toList()); + } return this; } @@ -209,6 +221,7 @@ public class DataManagementPlanOverviewModel implements DataModel new Doi().fromDataModel(item)).collect(Collectors.toList()); return this; } diff --git a/dmp-db-scema/main/dmp-dump.sql b/dmp-db-scema/main/dmp-dump.sql index 1a63a0774..470447770 100644 --- a/dmp-db-scema/main/dmp-dump.sql +++ b/dmp-db-scema/main/dmp-dump.sql @@ -926,6 +926,27 @@ CREATE TABLE public."FileUpload" ALTER TABLE public."FileUpload" OWNER TO :POSTGRES_USER; +-- +-- Name: EntityDoi; Type: TABLE; Schema: public; Owner: :POSTGRES_USER +-- + +CREATE TYPE DoiEntityType AS ENUM ('DMP'); + +CREATE TABLE public."EntityDoi" +( + "ID" uuid NOT NULL, + "EntityType" DoiEntityType NOT NULL, + "RepositoryId" character varying(150) NOT NULL, + "Doi" character varying(50) NOt NULL, + "CreatedAt" timestamp(6) with time zone DEFAULT now() NOT NULL, + "UpdatedAt" timestamp(6) with time zone DEFAULT now() NOT NULL, + "EntityId" uuid NOT NULL, + CONSTRAINT "Doi_pkey" PRIMARY KEY ("ID"), + CONSTRAINT fk_doi_entityId FOREIGN KEY ("EntityId") REFERENCES public."DMP"("ID") +); + +ALTER TABLE public."EntityDoi" OWNER TO :POSTGRES_USER; + -- -- Name: Content Content_pkey; Type: CONSTRAINT; Schema: public; Owner: :POSTGRES_USER -- diff --git a/dmp-db-scema/updates/00.00.010_Add_EntityDoi_table.sql b/dmp-db-scema/updates/00.00.010_Add_EntityDoi_table.sql new file mode 100644 index 000000000..d92e9d1d8 --- /dev/null +++ b/dmp-db-scema/updates/00.00.010_Add_EntityDoi_table.sql @@ -0,0 +1,26 @@ +DO $$DECLARE + this_version CONSTANT varchar := '00.00.010'; +BEGIN + PERFORM * FROM "DBVersion" WHERE version = this_version; + IF FOUND THEN RETURN; END IF; + +CREATE TYPE DoiEntityType AS ENUM ('DMP'); + +CREATE TABLE public."EntityDoi" +( + "ID" uuid NOT NULL, + "EntityType" DoiEntityType NOT NULL, + "RepositoryId" character varying(150) NOT NULL, + "Doi" character varying(50) NOt NULL, + "CreatedAt" timestamp(6) with time zone DEFAULT now() NOT NULL, + "UpdatedAt" timestamp(6) with time zone DEFAULT now() NOT NULL, + "EntityId" uuid NOT NULL, + CONSTRAINT "Doi_pkey" PRIMARY KEY ("ID"), + CONSTRAINT fk_doi_entityId FOREIGN KEY ("EntityId") REFERENCES public."DMP"("ID") +); + +/*ALTER TABLE public."EntityDoi" OWNER TO :POSTGRES_USER;*/ + +INSERT INTO public."DBVersion" VALUES ('DMPDB', '00.00.010', '2022-10-27 10:50:00.000000+02', now(), 'Add Doi Table for depositions'); + +END$$; \ No newline at end of file diff --git a/dmp-db-scema/updates/00.00.011.Migrate_data_from_dmp_doi_to_entitydoi.sql b/dmp-db-scema/updates/00.00.011.Migrate_data_from_dmp_doi_to_entitydoi.sql new file mode 100644 index 000000000..6189fe51a --- /dev/null +++ b/dmp-db-scema/updates/00.00.011.Migrate_data_from_dmp_doi_to_entitydoi.sql @@ -0,0 +1,14 @@ +DO $$DECLARE + this_version CONSTANT varchar := '00.00.011'; +BEGIN + PERFORM * FROM "DBVersion" WHERE version = this_version; + IF FOUND THEN RETURN; END IF; + +INSERT INTO public."EntityDoi" ("ID", "EntityType", "RepositoryId", "Doi", "CreatedAt", "UpdatedAt", "EntityId") +SELECT uuid_generate_v4(), 'DMP', 'Zenodo', public."DMP"."DOI", now(), now(), public."DMP"."ID" +FROM public."DMP" +WHERE public."DMP"."DOI" IS NOT NULL; + +INSERT INTO public."DBVersion" VALUES ('DMPDB', '00.00.011', '2022-10-27 10:50:00.000000+02', now(), 'Migrate DMP.DOI to EntityDoi table'); + +END$$; \ No newline at end of file diff --git a/dmp-db-scema/updates/00.00.012.Delete_doi_from_dmp_table.sql b/dmp-db-scema/updates/00.00.012.Delete_doi_from_dmp_table.sql new file mode 100644 index 000000000..25219abd0 --- /dev/null +++ b/dmp-db-scema/updates/00.00.012.Delete_doi_from_dmp_table.sql @@ -0,0 +1,11 @@ +DO $$DECLARE + this_version CONSTANT varchar := '00.00.012'; +BEGIN + PERFORM * FROM "DBVersion" WHERE version = this_version; + IF FOUND THEN RETURN; END IF; + +ALTER TABLE public."DMP" DROP COLUMN 'DOI'; + +INSERT INTO public."DBVersion" VALUES ('DMPDB', '00.00.012', '2022-10-27 10:50:00.000000+02', now(), 'Delete doi column from dmp table'); + +END$$; \ No newline at end of file diff --git a/dmp-frontend/src/app/core/model/dmp/dmp-overview.ts b/dmp-frontend/src/app/core/model/dmp/dmp-overview.ts index da5802817..a5171ad61 100644 --- a/dmp-frontend/src/app/core/model/dmp/dmp-overview.ts +++ b/dmp-frontend/src/app/core/model/dmp/dmp-overview.ts @@ -4,6 +4,7 @@ import { DmpAssociatedProfileModel } from "../dmp-profile/dmp-associated-profile import { ResearcherModel } from "../researcher/researcher"; import { GrantOverviewModel } from "../grant/grant-overview"; import { DatasetOverviewModel } from "../dataset/dataset-overview"; +import { DoiModel } from "../doi/doi"; export interface DmpOverviewModel { id: string; @@ -26,4 +27,5 @@ export interface DmpOverviewModel { finalizedAt: Date; publishedAt: Date; doi: string; + dois: DoiModel[]; } diff --git a/dmp-frontend/src/app/core/model/doi/doi.ts b/dmp-frontend/src/app/core/model/doi/doi.ts new file mode 100644 index 000000000..c72ba0023 --- /dev/null +++ b/dmp-frontend/src/app/core/model/doi/doi.ts @@ -0,0 +1,7 @@ +export interface DoiModel { + id: string; + repositoryId: string; + doi: string; + createdAt: Date; + updatedAt: Date; +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts b/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts index d4cee9ada..235f766a8 100644 --- a/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts +++ b/dmp-frontend/src/app/core/services/deposit-repositories/deposit-repositories.service.ts @@ -2,6 +2,7 @@ import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration'; import { DepositCode, DepositRequest } from '@app/core/model/deposit/deposit-request'; +import { DoiModel } from '@app/core/model/doi/doi'; import { Observable } from 'rxjs'; import { ConfigurationService } from '../configuration/configuration.service'; import { BaseHttpService } from '../http/base-http.service'; @@ -27,11 +28,11 @@ export class DepositRepositoriesService { return this.http.post(this.actionUrl + 'getAccessToken', depositCode, { headers: this.headers }); } - createDoi(repositoryId: string, dmpId: string, accessToken: string | null): Observable { + createDoi(repositoryId: string, dmpId: string, accessToken: string | null): Observable { const depositRequest = new DepositRequest(); depositRequest.repositoryId = repositoryId; depositRequest.dmpId = dmpId; depositRequest.accessToken = accessToken; - return this.http.post(this.actionUrl + 'createDoi', depositRequest, { headers: this.headers }); + return this.http.post(this.actionUrl + 'createDoi', depositRequest, { headers: this.headers }); } } diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts index acd7dec11..0f5133e47 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts @@ -3,6 +3,7 @@ import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dial import { DepositConfigurationStatus } from '@app/core/common/enum/deposit-configuration-status'; import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration'; import { DmpOverviewModel } from '@app/core/model/dmp/dmp-overview'; +import { DoiModel } from '@app/core/model/doi/doi'; import { DepositRepositoriesService } from '@app/core/services/deposit-repositories/deposit-repositories.service'; import { DmpService } from '@app/core/services/dmp/dmp.service'; import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; @@ -21,7 +22,7 @@ import { takeUntil } from 'rxjs/operators'; export class DmpDepositDialogComponent extends BaseComponent implements OnInit { inputRepos: DepositConfigurationModel[]; - outputRepos: string[]; + outputRepos: DoiModel[]; dmp: DmpOverviewModel; constructor( @@ -37,9 +38,16 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit { super(); this.inputRepos = data['depositRepos'][0]; this.dmp = data['depositRepos'][1]; + for(var i = 0; i < this.dmp.dois.length; i++){ + this.inputRepos = this.inputRepos.filter(r => this.hasDoi(r, this.dmp.dois, i)); + } this.outputRepos = []; } + hasDoi(repo, dois, i){ + return repo.repositoryId !== dois[i].repositoryId; + } + ngOnInit(): void { } @@ -76,6 +84,10 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit { .subscribe(doi =>{ this.onDOICallbackSuccess(); this.outputRepos.push(doi); + this.inputRepos = this.inputRepos.filter(function(x) { return x.repositoryId !== repo.repositoryId; }); + if(this.inputRepos.length == 0){ + this.close(); + } }, error => this.onDeleteCallbackError(error)); break; } @@ -106,6 +118,10 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit { .subscribe(doi =>{ this.onDOICallbackSuccess(); this.outputRepos.push(doi); + this.inputRepos = this.inputRepos.filter(function(x) { return x.repositoryId !== repo.repositoryId; }); + if(this.inputRepos.length == 0){ + this.close(); + } }, error => this.onDeleteCallbackError(error)); }); // this.userService.registerDOIToken(result.oauthCode, this.configurationService.app + 'oauth2') diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html index 15284e00b..60d21ea68 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html @@ -114,21 +114,41 @@

{{'DMP-EDITOR.TITLE.SUBTITLE' | translate}}

-

- -

-
+ + + {{x.repositoryId}} + + +
+
@@ -141,7 +161,7 @@
-
+
diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts index eb89f320d..c01ecf706 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts @@ -44,6 +44,7 @@ import { PopupNotificationDialogComponent } from '@app/library/notification/popu import { DepositRepositoriesService } from '@app/core/services/deposit-repositories/deposit-repositories.service'; import { DmpDepositDialogComponent } from '../editor/dmp-deposit-dialog/dmp-deposit-dialog.component'; import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-configuration'; +import { DoiModel } from '@app/core/model/doi/doi'; @Component({ selector: 'app-dmp-overview', @@ -71,7 +72,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { @ViewChild('doi') doi: ElementRef; - depositRepos: DepositConfigurationModel[]; + depositRepos: DepositConfigurationModel[] = []; formGroup: FormGroup; @@ -151,6 +152,12 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { }); } }); + this.depositRepositoriesService.getAvailableRepos() + .pipe(takeUntil(this._destroyed)) + .subscribe( + repos => { + this.depositRepos = repos; + }); } onFetchingDeletedCallbackError(redirectRoot: string) { @@ -450,7 +457,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { } hasDoi(dmp: DmpOverviewModel) { - return dmp.doi == null ? true : false; + return (this.dmp.dois == null || this.dmp.dois.length == 0) ? true : false; } getAccessUrl(): string { @@ -585,30 +592,28 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { } deposit(){ - this.depositRepositoriesService.getAvailableRepos() - .pipe(takeUntil(this._destroyed)) - .subscribe( - repos => { - this.depositRepos = repos; - const dialogRef = this.dialog.open(DmpDepositDialogComponent, { - maxWidth: '600px', - restoreFocus: false, - autoFocus: false, - data: { - depositRepos: [this.depositRepos, this.dmp], - message: "Select repositories to deposit",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.FINALIZE-ITEM'), - confirmButton: "Proceed to authentication",//this.language.instant('DMP-FINALISE-DIALOG.SUBMIT'), - cancelButton: "Cancel",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), - } - }); - dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe((result: string[]) => { - if (result) { - this.dmp.doi = result[0]; - this.hasDOIToken = true; - } - }); - } - ); + const dialogRef = this.dialog.open(DmpDepositDialogComponent, { + maxWidth: '600px', + disableClose: true, + restoreFocus: false, + autoFocus: false, + data: { + depositRepos: [this.depositRepos, this.dmp], + message: "Select repositories to deposit",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.FINALIZE-ITEM'), + confirmButton: "Proceed to authentication",//this.language.instant('DMP-FINALISE-DIALOG.SUBMIT'), + cancelButton: "Cancel",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), + } + }); + dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe((result: DoiModel[]) => { + if (result.length > 0) { + this.dmp.dois.push(...result); + this.hasDOIToken = true; + } + }); + } + + moreDeposit(){ + return (this.dmp.dois.length < this.depositRepos.length) ? true : false; } finalize(dmp: DmpOverviewModel) { From 6b2bc3c1e0bb22eb03c7b20cc1ba3b4188e4d6d3 Mon Sep 17 00:00:00 2001 From: Aldo Mihasi Date: Wed, 2 Nov 2022 13:31:42 +0200 Subject: [PATCH 05/26] cleanup code, add authorizationUrl and recordUrl in repositories config --- .../RepositoryDepositConfiguration.java | 18 +- .../eudat/logic/managers/DepositManager.java | 8 - .../interfaces/ZenodoDeposit.java | 2 + .../model/deposit/deposit-configuration.ts | 3 + .../configuration/configuration.service.ts | 6 - .../dmp-deposit-dialog.component.html | 2 +- .../dmp-deposit-dialog.component.ts | 33 ++- .../dmp/overview/dmp-overview.component.html | 6 +- .../ui/dmp/overview/dmp-overview.component.ts | 210 +++++++++--------- dmp-frontend/src/assets/config/config.json | 1 - dmp-frontend/src/assets/i18n/de.json | 8 + dmp-frontend/src/assets/i18n/en.json | 8 + dmp-frontend/src/assets/i18n/es.json | 8 + dmp-frontend/src/assets/i18n/gr.json | 8 + dmp-frontend/src/assets/i18n/hr.json | 8 + dmp-frontend/src/assets/i18n/pl.json | 8 + dmp-frontend/src/assets/i18n/pt.json | 8 + dmp-frontend/src/assets/i18n/sk.json | 8 + dmp-frontend/src/assets/i18n/sr.json | 8 + dmp-frontend/src/assets/i18n/tr.json | 8 + 20 files changed, 223 insertions(+), 146 deletions(-) diff --git a/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/repository/RepositoryDepositConfiguration.java b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/repository/RepositoryDepositConfiguration.java index 5504ad25b..937e5182a 100644 --- a/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/repository/RepositoryDepositConfiguration.java +++ b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/repository/RepositoryDepositConfiguration.java @@ -33,10 +33,12 @@ public class RepositoryDepositConfiguration { private String repositoryId; private String accessToken; private String repositoryUrl; + private String repositoryAuthorizationUrl; + private String repositoryRecordUrl; private String repositoryLoginAccessTokenUrl; private String repositoryLoginClientId; private String repositoryLoginClientSecret; - private String repositoryLoginRedirectUri; // + private String repositoryLoginRedirectUri; public int getDepositAccountStatus() { return depositAccountStatus; @@ -66,6 +68,20 @@ public class RepositoryDepositConfiguration { 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 getRepositoryLoginAccessTokenUrl() { return repositoryLoginAccessTokenUrl; } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java index 49fceab84..d5ec7ff88 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DepositManager.java @@ -38,17 +38,9 @@ public class DepositManager { public List getAvailableRepos() { List repos = new ArrayList<>(); - -// logger.info("-------------REPOS------------"); -// for (RepositoryDeposit r: this.repositories) { -// logger.info("...Loaded Class: " -// + r.getClass()); -// } -// logger.info("-------------------------------"); for (RepositoryDeposit r: this.repositories) { repos.add(r.getConfiguration()); } - return repos; } diff --git a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/interfaces/ZenodoDeposit.java b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/interfaces/ZenodoDeposit.java index b8696885f..012076af7 100644 --- a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/interfaces/ZenodoDeposit.java +++ b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/zenodorepository/interfaces/ZenodoDeposit.java @@ -177,6 +177,8 @@ public class ZenodoDeposit implements RepositoryDeposit { conf.setRepositoryId("Zenodo"); conf.setAccessToken("pcqw4LGLrhp17FF5GoXNCXakkEi82ThchZw7Tk4qh74VrDE3EmliG3UlhYtd"); conf.setRepositoryUrl("https://sandbox.zenodo.org/api/"); + conf.setRepositoryAuthorizationUrl("https://sandbox.zenodo.org/oauth/authorize"); + conf.setRepositoryRecordUrl("https://sandbox.zenodo.org/record/"); conf.setRepositoryLoginAccessTokenUrl("https://sandbox.zenodo.org/oauth/token"); conf.setRepositoryLoginClientId("hEmVRNc1OzRmWyi2GDR3XVKbhG3OtfJXLXkkOGXx"); conf.setRepositoryLoginClientSecret("7VSU0NjiAg0P3mv14wemMYy2XhvlmV6F7xoszxPH4ZDx98v8FdMpBbxlncqr"); diff --git a/dmp-frontend/src/app/core/model/deposit/deposit-configuration.ts b/dmp-frontend/src/app/core/model/deposit/deposit-configuration.ts index 1e2ef02e1..97840d578 100644 --- a/dmp-frontend/src/app/core/model/deposit/deposit-configuration.ts +++ b/dmp-frontend/src/app/core/model/deposit/deposit-configuration.ts @@ -5,7 +5,10 @@ export class DepositConfigurationModel { repositoryId: string; accessToken: string; repositoryUrl: string; + repositoryAuthorizationUrl: string; + repositoryRecordUrl: string; repositoryLoginAccessTokenUrl: string; repositoryLoginClientId: string; repositoryLoginClientSecret: string; + repositoryLoginRedirectUri: string; } diff --git a/dmp-frontend/src/app/core/services/configuration/configuration.service.ts b/dmp-frontend/src/app/core/services/configuration/configuration.service.ts index 9b92ad064..64082cb55 100644 --- a/dmp-frontend/src/app/core/services/configuration/configuration.service.ts +++ b/dmp-frontend/src/app/core/services/configuration/configuration.service.ts @@ -66,11 +66,6 @@ export class ConfigurationService extends BaseComponent { return this._allowOrganizationCreator; } - private _doiLink: string; - get doiLink(): string { - return this._doiLink; - } - private _useSplash: string; get useSplash(): string { return this._useSplash; @@ -137,7 +132,6 @@ export class ConfigurationService extends BaseComponent { this._lockInterval = config.lockInterval; this._guideAssets = config.guideAssets; this._allowOrganizationCreator = config.allowOrganizationCreator; - this._doiLink = config.doiLink; this._useSplash = config.useSplash; this._orcidPath = config.orcidPath; if (config.matomo) { diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.html b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.html index 407452047..1ab72528e 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.html +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.html @@ -9,7 +9,7 @@
-
No publishing repositories so far
+
{{'DMP-OVERVIEW.DEPOSIT.NO-REPOSITORIES' | translate}}
diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts index 0f5133e47..88364d012 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts @@ -5,11 +5,9 @@ import { DepositConfigurationModel } from '@app/core/model/deposit/deposit-confi import { DmpOverviewModel } from '@app/core/model/dmp/dmp-overview'; import { DoiModel } from '@app/core/model/doi/doi'; import { DepositRepositoriesService } from '@app/core/services/deposit-repositories/deposit-repositories.service'; -import { DmpService } from '@app/core/services/dmp/dmp.service'; import { SnackBarNotificationLevel, UiNotificationService } from '@app/core/services/notification/ui-notification-service'; import { Oauth2DialogService } from '@app/ui/misc/oauth2-dialog/service/oauth2-dialog.service'; import { BaseComponent } from '@common/base/base.component'; -import { ConfirmationDialogComponent } from '@common/modules/confirmation-dialog/confirmation-dialog.component'; import { MultipleChoiceDialogComponent } from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.component'; import { TranslateService } from '@ngx-translate/core'; import { takeUntil } from 'rxjs/operators'; @@ -24,13 +22,14 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit { inputRepos: DepositConfigurationModel[]; outputRepos: DoiModel[]; dmp: DmpOverviewModel; + private oauthLock: boolean; constructor( - private dmpService: DmpService, private depositRepositoriesService: DepositRepositoriesService, public dialogRef: MatDialogRef, private dialog: MatDialog, private language: TranslateService, + private translate: TranslateService, private uiNotificationService: UiNotificationService, private oauth2DialogService: Oauth2DialogService, @Inject(MAT_DIALOG_DATA) public data: any @@ -67,16 +66,16 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit { maxWidth: '600px', restoreFocus: false, data: { - message: 'Which account would you like to use?',//this.language.instant('GENERAL.ERRORS.HTTP-REQUEST-ERROR'), - titles: ['Login with ' + repo.repositoryId/*this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.ZENODO-LOGIN')*/, this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.USE-DEFAULT')] + message: this.language.instant('DMP-OVERVIEW.DEPOSIT.ACCOUNT-LOGIN'), + titles: [this.language.instant('DMP-OVERVIEW.DEPOSIT.LOGIN', { 'repository': repo.repositoryId }), this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.USE-DEFAULT')] } }); dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { switch (result) { case 0: - this.showOauth2Dialog('https://sandbox.zenodo.org/oauth/authorize'+ '?client_id=' + repo.repositoryLoginClientId + this.showOauth2Dialog(repo.repositoryAuthorizationUrl + '?client_id=' + repo.repositoryLoginClientId + '&response_type=code&scope=deposit:write+deposit:actions+user:email&state=astate&redirect_uri=' - + 'http://localhost:4200/login/external/zenodo', repo, this.dmp); + + repo.repositoryLoginRedirectUri, repo, this.dmp); break; case 1: this.depositRepositoriesService.createDoi(repo.repositoryId, this.dmp.id, null) @@ -88,7 +87,7 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit { if(this.inputRepos.length == 0){ this.close(); } - }, error => this.onDeleteCallbackError(error)); + }, error => this.onDOICallbackError(error)); break; } }); @@ -100,8 +99,8 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit { this.uiNotificationService.snackBarNotification(this.language.instant('DMP-EDITOR.SNACK-BAR.SUCCESSFUL-DOI'), SnackBarNotificationLevel.Success); } - onDeleteCallbackError(error) { - this.uiNotificationService.snackBarNotification(error.error.message ? this.language.instant(error.error.message) : this.language.instant('GENERAL.SNACK-BAR.UNSUCCESSFUL-DELETE'), SnackBarNotificationLevel.Error); + onDOICallbackError(error) { + this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('DMP-EDITOR.SNACK-BAR.UNSUCCESSFUL-DOI'), SnackBarNotificationLevel.Error); } showOauth2Dialog(url: string, repo: DepositConfigurationModel, dmp: DmpOverviewModel) { @@ -109,7 +108,7 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit { .pipe(takeUntil(this._destroyed)) .subscribe(result => { if (result !== undefined) { - if (result.oauthCode !== undefined && result.oauthCode !== null) { + if (result.oauthCode !== undefined && result.oauthCode !== null && !this.oauthLock) { this.depositRepositoriesService.getAccessToken(repo.repositoryId, result.oauthCode) .pipe(takeUntil(this._destroyed)) .subscribe(token => { @@ -122,16 +121,14 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit { if(this.inputRepos.length == 0){ this.close(); } - }, error => this.onDeleteCallbackError(error)); + }, error => this.onDOICallbackError(error)); }); - // this.userService.registerDOIToken(result.oauthCode, this.configurationService.app + 'oauth2') - // .pipe(takeUntil(this._destroyed)) - // .subscribe(() => { - // this.hasDOIToken = true; - // this.showConfirmationDOIDialog(dmp); - // }); + this.oauthLock = true; } } + else{ + this.oauthLock = false; + } }); } diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html index 60d21ea68..602935ded 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html @@ -115,8 +115,8 @@

{{'DMP-EDITOR.TITLE.SUBTITLE' | translate}}

- - {{x.repositoryId}} + + {{doi.repositoryId}}
@@ -124,7 +124,7 @@ content_copy diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts index c01ecf706..eaf84437d 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.ts @@ -18,16 +18,15 @@ import { BreadcrumbItem } from '@app/ui/misc/breadcrumb/definition/breadcrumb-it import { BaseComponent } from '@common/base/base.component'; import { TranslateService } from '@ngx-translate/core'; import * as FileSaver from 'file-saver'; -import { Observable, of as observableOf, interval } from 'rxjs'; +import { Observable, of as observableOf } from 'rxjs'; import { takeUntil, map } from 'rxjs/operators'; import { Role } from "@app/core/common/enum/role"; import { DmpInvitationDialogComponent } from '../invitation/dmp-invitation-dialog.component'; -import { MultipleChoiceDialogComponent } from '@common/modules/multiple-choice-dialog/multiple-choice-dialog.component'; import { ConfigurationService } from '@app/core/services/configuration/configuration.service'; import { Oauth2DialogService } from '@app/ui/misc/oauth2-dialog/service/oauth2-dialog.service'; import { UserService } from '@app/core/services/user/user.service'; import { Location } from '@angular/common'; -import { FormGroup, FormArray, FormControl } from '@angular/forms'; +import { FormGroup } from '@angular/forms'; import { LockService } from '@app/core/services/lock/lock.service'; import { VersionListingModel } from '@app/core/model/version/version-listing.model'; import { CloneDialogComponent } from '../clone/clone-dialog/clone-dialog.component'; @@ -67,7 +66,6 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { textMessage: any; versions: VersionListingModel[]; version: VersionListingModel; - private oauthLock: boolean; @ViewChild('doi') doi: ElementRef; @@ -87,11 +85,8 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { private language: TranslateService, private uiNotificationService: UiNotificationService, private configurationService: ConfigurationService, - private oauth2DialogService: Oauth2DialogService, - private userService: UserService, private location: Location, private lockService: LockService, - private httpClient: HttpClient, private matomoService: MatomoService ) { super(); @@ -460,25 +455,6 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { return (this.dmp.dois == null || this.dmp.dois.length == 0) ? true : false; } - getAccessUrl(): string { - const redirectUri = this.configurationService.app + 'oauth2'; - const url = this.configurationService.loginProviders.zenodoConfiguration.oauthUrl - + '?client_id=' + this.configurationService.loginProviders.zenodoConfiguration.clientId - + '&response_type=code&scope=deposit:write+deposit:actions+user:email&state=astate&redirect_uri=' - + redirectUri; - return url; - } - - getDoi(dmp: DmpOverviewModel) { - this.userService.hasDOIToken().subscribe(response => { - this.hasDOIToken = true; - this.showConfirmationDOIDialog(dmp); - }, error => { - this.hasDOIToken = false; - this.showErrorConfirmationDOIDialog(error.error.message, dmp); - }); - } - getAllVersions(dmp: DmpOverviewModel) { this.dmpService.getAllVersions(dmp.groupId, this.isPublicView) .pipe(takeUntil(this._destroyed)) @@ -487,82 +463,6 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { }); } - showConfirmationDOIDialog(dmp: DmpOverviewModel) { - const dialogRef = this.dialog.open(ConfirmationDialogComponent, { - maxWidth: '600px', - restoreFocus: false, - data: { - message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ZENODO-DOI', { 'username': this.hasDOIToken ? this.authentication.current().zenodoEmail : 'default' }), - confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'), - cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), - } - }); - dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { - if (result) { - this.dmpService.getDoi(dmp.id) - .pipe(takeUntil(this._destroyed)) - .subscribe( - complete => { - this.onDOICallbackSuccess(); - this.dmp.doi = complete; - }, - error => this.onDeleteCallbackError(error) - ); - } - }); - } - - showErrorConfirmationDOIDialog(message: string, dmp: DmpOverviewModel) { - const dialogRef = this.dialog.open(MultipleChoiceDialogComponent, { - maxWidth: '600px', - restoreFocus: false, - data: { - message: message ? this.language.instant(message) : this.language.instant('GENERAL.ERRORS.HTTP-REQUEST-ERROR'), - titles: [this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.ZENODO-LOGIN'), this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.USE-DEFAULT')] - } - }); - dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { - switch (result) { - case 0: - // this.authentication.logout(); - // this.router.navigate(['/login/external/zenodo']); - this.showOauth2Dialog(this.getAccessUrl(), dmp); - break; - case 1: - this.showConfirmationDOIDialog(dmp); - break; - } - }); - } - - showOauth2Dialog(url: string, dmp: DmpOverviewModel) { - this.oauth2DialogService.login(url) - .pipe(takeUntil(this._destroyed)) - .subscribe(result => { - if (result !== undefined) { - if (result.oauthCode !== undefined && result.oauthCode !== null && !this.oauthLock) { - this.userService.registerDOIToken(result.oauthCode, this.configurationService.app + 'oauth2') - .pipe(takeUntil(this._destroyed)) - .subscribe(() => { - this.hasDOIToken = true; - this.showConfirmationDOIDialog(dmp); - }); - this.oauthLock = true; - } - } else { - this.oauthLock = false; - } - }); - } - - onDOICallbackSuccess(): void { - this.uiNotificationService.snackBarNotification(this.language.instant('DMP-EDITOR.SNACK-BAR.SUCCESSFUL-DOI'), SnackBarNotificationLevel.Success); - } - - onDOICallbackError(error) { - this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('DMP-EDITOR.SNACK-BAR.UNSUCCESSFUL-DOI'), SnackBarNotificationLevel.Error); - } - showPublishButton(dmp: DmpOverviewModel) { return this.isFinalizedDmp(dmp) && !dmp.isPublic && this.hasPublishButton; } @@ -599,9 +499,9 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { autoFocus: false, data: { depositRepos: [this.depositRepos, this.dmp], - message: "Select repositories to deposit",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.FINALIZE-ITEM'), - confirmButton: "Proceed to authentication",//this.language.instant('DMP-FINALISE-DIALOG.SUBMIT'), - cancelButton: "Cancel",//this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), + message: this.language.instant('DMP-OVERVIEW.DEPOSIT.SELECT-REPOSITORIES'), + confirmButton: this.language.instant('DMP-OVERVIEW.DEPOSIT.AUTHORIZE'), + cancelButton: this.language.instant('DMP-OVERVIEW.DEPOSIT.CANCEL'), } }); dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe((result: DoiModel[]) => { @@ -715,10 +615,10 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { this.router.navigate(['/datasets', 'new', this.dmp.id]); } - createDoiLink(doi: string): string { - const doiarr = doi.split('.'); + createDoiLink(doiModel: DoiModel): string { + const doiarr = doiModel.doi.split('.'); const id = doiarr[doiarr.length - 1]; - return this.configurationService.doiLink + id; + return this.depositRepos.find(r => r.repositoryId == doiModel.repositoryId).repositoryRecordUrl + id; } reverse() { @@ -876,5 +776,99 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit { // }); // } + // getAccessUrl(): string { + // const redirectUri = this.configurationService.app + 'oauth2'; + // const url = this.configurationService.loginProviders.zenodoConfiguration.oauthUrl + // + '?client_id=' + this.configurationService.loginProviders.zenodoConfiguration.clientId + // + '&response_type=code&scope=deposit:write+deposit:actions+user:email&state=astate&redirect_uri=' + // + redirectUri; + // return url; + // } + + // getDoi(dmp: DmpOverviewModel) { + // this.userService.hasDOIToken().subscribe(response => { + // this.hasDOIToken = true; + // this.showConfirmationDOIDialog(dmp); + // }, error => { + // this.hasDOIToken = false; + // this.showErrorConfirmationDOIDialog(error.error.message, dmp); + // }); + // } + + // showConfirmationDOIDialog(dmp: DmpOverviewModel) { + // const dialogRef = this.dialog.open(ConfirmationDialogComponent, { + // maxWidth: '600px', + // restoreFocus: false, + // data: { + // message: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ZENODO-DOI', { 'username': this.hasDOIToken ? this.authentication.current().zenodoEmail : 'default' }), + // confirmButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CONFIRM'), + // cancelButton: this.language.instant('GENERAL.CONFIRMATION-DIALOG.ACTIONS.CANCEL'), + // } + // }); + // dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { + // if (result) { + // this.dmpService.getDoi(dmp.id) + // .pipe(takeUntil(this._destroyed)) + // .subscribe( + // complete => { + // this.onDOICallbackSuccess(); + // this.dmp.doi = complete; + // }, + // error => this.onDeleteCallbackError(error) + // ); + // } + // }); + // } + + // showErrorConfirmationDOIDialog(message: string, dmp: DmpOverviewModel) { + // const dialogRef = this.dialog.open(MultipleChoiceDialogComponent, { + // maxWidth: '600px', + // restoreFocus: false, + // data: { + // message: message ? this.language.instant(message) : this.language.instant('GENERAL.ERRORS.HTTP-REQUEST-ERROR'), + // titles: [this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.ZENODO-LOGIN'), this.language.instant('DMP-OVERVIEW.MULTIPLE-DIALOG.USE-DEFAULT')] + // } + // }); + // dialogRef.afterClosed().pipe(takeUntil(this._destroyed)).subscribe(result => { + // switch (result) { + // case 0: + // // this.authentication.logout(); + // // this.router.navigate(['/login/external/zenodo']); + // this.showOauth2Dialog(this.getAccessUrl(), dmp); + // break; + // case 1: + // this.showConfirmationDOIDialog(dmp); + // break; + // } + // }); + // } + + // showOauth2Dialog(url: string, dmp: DmpOverviewModel) { + // this.oauth2DialogService.login(url) + // .pipe(takeUntil(this._destroyed)) + // .subscribe(result => { + // if (result !== undefined) { + // if (result.oauthCode !== undefined && result.oauthCode !== null && !this.oauthLock) { + // this.userService.registerDOIToken(result.oauthCode, this.configurationService.app + 'oauth2') + // .pipe(takeUntil(this._destroyed)) + // .subscribe(() => { + // this.hasDOIToken = true; + // this.showConfirmationDOIDialog(dmp); + // }); + // this.oauthLock = true; + // } + // } else { + // this.oauthLock = false; + // } + // }); + // } + + // onDOICallbackSuccess(): void { + // this.uiNotificationService.snackBarNotification(this.language.instant('DMP-EDITOR.SNACK-BAR.SUCCESSFUL-DOI'), SnackBarNotificationLevel.Success); + // } + + // onDOICallbackError(error) { + // this.uiNotificationService.snackBarNotification(error.error.message ? error.error.message : this.language.instant('DMP-EDITOR.SNACK-BAR.UNSUCCESSFUL-DOI'), SnackBarNotificationLevel.Error); + // } } diff --git a/dmp-frontend/src/assets/config/config.json b/dmp-frontend/src/assets/config/config.json index 7b0bbad3d..72c5d8a10 100644 --- a/dmp-frontend/src/assets/config/config.json +++ b/dmp-frontend/src/assets/config/config.json @@ -57,7 +57,6 @@ "lockInterval": 60000, "guideAssets": "assets/images/guide", "allowOrganizationCreator": true, - "doiLink": "https://sandbox.zenodo.org/record/", "useSplash": false, "orcidPath": "https://orcid.org/", "maxFileSizeInMB": 10 diff --git a/dmp-frontend/src/assets/i18n/de.json b/dmp-frontend/src/assets/i18n/de.json index 9e0e2ed4e..97770fb97 100644 --- a/dmp-frontend/src/assets/i18n/de.json +++ b/dmp-frontend/src/assets/i18n/de.json @@ -803,6 +803,14 @@ "ZENODO-LOGIN": "Login with Zenodo", "USE-DEFAULT": "Use Default Token" }, + "DEPOSIT": { + "ACCOUNT-LOGIN": "Which account would you like to use?", + "LOGIN": "Login with {{repository}}", + "NO-REPOSITORIES": "No publishing repositories", + "SELECT-REPOSITORIES": "Select repositories to deposit", + "AUTHORIZE": "Proceed to authorization", + "CANCEL": "Cancel" + }, "LOCKED-DIALOG":{ "TITLE": "DMP is locked", "MESSAGE":"Somebody else is modifying the DMP at this moment. If you would like to modify or view it, please come back later." diff --git a/dmp-frontend/src/assets/i18n/en.json b/dmp-frontend/src/assets/i18n/en.json index 6f563ad38..ceca83d40 100644 --- a/dmp-frontend/src/assets/i18n/en.json +++ b/dmp-frontend/src/assets/i18n/en.json @@ -803,6 +803,14 @@ "ZENODO-LOGIN": "Login with Zenodo", "USE-DEFAULT": "Use Default Token" }, + "DEPOSIT": { + "ACCOUNT-LOGIN": "Which account would you like to use?", + "LOGIN": "Login with {{repository}}", + "NO-REPOSITORIES": "No publishing repositories", + "SELECT-REPOSITORIES": "Select repositories to deposit", + "AUTHORIZE": "Proceed to authorization", + "CANCEL": "Cancel" + }, "LOCKED-DIALOG":{ "TITLE": "DMP is locked", "MESSAGE":"Somebody else is modifying the DMP at this moment. If you would like to modify or view it, please come back later." diff --git a/dmp-frontend/src/assets/i18n/es.json b/dmp-frontend/src/assets/i18n/es.json index 1c1d11e2d..acb90f104 100644 --- a/dmp-frontend/src/assets/i18n/es.json +++ b/dmp-frontend/src/assets/i18n/es.json @@ -803,6 +803,14 @@ "ZENODO-LOGIN": "Identificarse con Zenodo", "USE-DEFAULT": "Usar el token por defecto" }, + "DEPOSIT": { + "ACCOUNT-LOGIN": "Which account would you like to use?", + "LOGIN": "Login with {{repository}}", + "NO-REPOSITORIES": "No publishing repositories", + "SELECT-REPOSITORIES": "Select repositories to deposit", + "AUTHORIZE": "Proceed to authorization", + "CANCEL": "Cancel" + }, "LOCKED-DIALOG":{ "TITLE": "PGD bloqeuado", "MESSAGE":"Alguien más está modificando el PGD. Si quiere modificarlo o visualizarlo, por favor, inténtelo más tarde." diff --git a/dmp-frontend/src/assets/i18n/gr.json b/dmp-frontend/src/assets/i18n/gr.json index 9cf4eca81..9399e919e 100644 --- a/dmp-frontend/src/assets/i18n/gr.json +++ b/dmp-frontend/src/assets/i18n/gr.json @@ -803,6 +803,14 @@ "ZENODO-LOGIN": "Σύνδεση με Zenodo", "USE-DEFAULT": "Χρήση Προκαθορισμένου Token" }, + "DEPOSIT": { + "ACCOUNT-LOGIN": "Which account would you like to use?", + "LOGIN": "Login with {{repository}}", + "NO-REPOSITORIES": "No publishing repositories", + "SELECT-REPOSITORIES": "Select repositories to deposit", + "AUTHORIZE": "Proceed to authorization", + "CANCEL": "Cancel" + }, "LOCKED-DIALOG":{ "TITLE": "DMP is locked", "MESSAGE":"Somebody else is modifying the DMP at this moment. If you would like to modify or view it, please come back later." diff --git a/dmp-frontend/src/assets/i18n/hr.json b/dmp-frontend/src/assets/i18n/hr.json index 69b1ab7d2..9e8186572 100644 --- a/dmp-frontend/src/assets/i18n/hr.json +++ b/dmp-frontend/src/assets/i18n/hr.json @@ -803,6 +803,14 @@ "ZENODO-LOGIN": "Prijavite se pomoću Zenodo korisničkog računa", "USE-DEFAULT": "Koristite zadanu opciju" }, + "DEPOSIT": { + "ACCOUNT-LOGIN": "Which account would you like to use?", + "LOGIN": "Login with {{repository}}", + "NO-REPOSITORIES": "No publishing repositories", + "SELECT-REPOSITORIES": "Select repositories to deposit", + "AUTHORIZE": "Proceed to authorization", + "CANCEL": "Cancel" + }, "LOCKED-DIALOG": { "TITLE": "PUP je zaključan", "MESSAGE": "U ovom trenutku netko drugi uređuje informacije o skupu podataka. Ako želite pregledati zapis ili napraviti izmjenu, pričekajte i pokušajte ponovo kasnije." diff --git a/dmp-frontend/src/assets/i18n/pl.json b/dmp-frontend/src/assets/i18n/pl.json index 4dba630af..824765d35 100644 --- a/dmp-frontend/src/assets/i18n/pl.json +++ b/dmp-frontend/src/assets/i18n/pl.json @@ -803,6 +803,14 @@ "ZENODO-LOGIN": "Zaloguj się za pomocą Zenodo", "USE-DEFAULT": "Użyj domyślnego tokena" }, + "DEPOSIT": { + "ACCOUNT-LOGIN": "Which account would you like to use?", + "LOGIN": "Login with {{repository}}", + "NO-REPOSITORIES": "No publishing repositories", + "SELECT-REPOSITORIES": "Select repositories to deposit", + "AUTHORIZE": "Proceed to authorization", + "CANCEL": "Cancel" + }, "LOCKED-DIALOG": { "TITLE": "DMP jest zablokowany", "MESSAGE": "W tej chwili ktoś inny modyfikuje ten zbiór danych. Możesz przeglądać ten zbiór danych, ale nie możesz wprowadzać żadnych zmian. Jeśli chcesz go zmodyfikować, wróć później." diff --git a/dmp-frontend/src/assets/i18n/pt.json b/dmp-frontend/src/assets/i18n/pt.json index 8123b7bca..5d9d81d68 100644 --- a/dmp-frontend/src/assets/i18n/pt.json +++ b/dmp-frontend/src/assets/i18n/pt.json @@ -808,6 +808,14 @@ "ZENODO-LOGIN": "Entre com o Zenodo", "USE-DEFAULT": "Use o Token" }, + "DEPOSIT": { + "ACCOUNT-LOGIN": "Which account would you like to use?", + "LOGIN": "Login with {{repository}}", + "NO-REPOSITORIES": "No publishing repositories", + "SELECT-REPOSITORIES": "Select repositories to deposit", + "AUTHORIZE": "Proceed to authorization", + "CANCEL": "Cancel" + }, "LOCKED-DIALOG":{ "TITLE": "DMP is locked", "MESSAGE":"Somebody else is modifying the DMP at this moment. If you would like to modify or view it, please come back later." diff --git a/dmp-frontend/src/assets/i18n/sk.json b/dmp-frontend/src/assets/i18n/sk.json index 06032b3d8..2a2344c54 100644 --- a/dmp-frontend/src/assets/i18n/sk.json +++ b/dmp-frontend/src/assets/i18n/sk.json @@ -803,6 +803,14 @@ "ZENODO-LOGIN": "Prihlásiť sa do Zenodo", "USE-DEFAULT": "Použite predvolený token" }, + "DEPOSIT": { + "ACCOUNT-LOGIN": "Which account would you like to use?", + "LOGIN": "Login with {{repository}}", + "NO-REPOSITORIES": "No publishing repositories", + "SELECT-REPOSITORIES": "Select repositories to deposit", + "AUTHORIZE": "Proceed to authorization", + "CANCEL": "Cancel" + }, "LOCKED-DIALOG":{ "TITLE": "DMP is locked", "MESSAGE":"Somebody else is modifying the DMP at this moment. If you would like to modify or view it, please come back later." diff --git a/dmp-frontend/src/assets/i18n/sr.json b/dmp-frontend/src/assets/i18n/sr.json index bd4751501..d06447a20 100644 --- a/dmp-frontend/src/assets/i18n/sr.json +++ b/dmp-frontend/src/assets/i18n/sr.json @@ -803,6 +803,14 @@ "ZENODO-LOGIN": "Prijavite se pomoću Zenodo naloga", "USE-DEFAULT": "Koristite podrazumevani znak" }, + "DEPOSIT": { + "ACCOUNT-LOGIN": "Which account would you like to use?", + "LOGIN": "Login with {{repository}}", + "NO-REPOSITORIES": "No publishing repositories", + "SELECT-REPOSITORIES": "Select repositories to deposit", + "AUTHORIZE": "Proceed to authorization", + "CANCEL": "Cancel" + }, "LOCKED-DIALOG":{ "TITLE": "DMP is locked", "MESSAGE":"Somebody else is modifying the DMP at this moment. If you would like to modify or view it, please come back later." diff --git a/dmp-frontend/src/assets/i18n/tr.json b/dmp-frontend/src/assets/i18n/tr.json index a99da8a5b..d4d070c60 100644 --- a/dmp-frontend/src/assets/i18n/tr.json +++ b/dmp-frontend/src/assets/i18n/tr.json @@ -803,6 +803,14 @@ "ZENODO-LOGIN": "Zenodo ile oturum aç", "USE-DEFAULT": "Mevcut Jetonu Kullan" }, + "DEPOSIT": { + "ACCOUNT-LOGIN": "Which account would you like to use?", + "LOGIN": "Login with {{repository}}", + "NO-REPOSITORIES": "No publishing repositories", + "SELECT-REPOSITORIES": "Select repositories to deposit", + "AUTHORIZE": "Proceed to authorization", + "CANCEL": "Cancel" + }, "LOCKED-DIALOG":{ "TITLE": "DMP is locked", "MESSAGE":"Somebody else is modifying the DMP at this moment. If you would like to modify or view it, please come back later." From b4490cb0f334649137883d247b1b8463d6116369 Mon Sep 17 00:00:00 2001 From: Aldo Mihasi Date: Thu, 10 Nov 2022 10:12:11 +0200 Subject: [PATCH 06/26] [WIP] implement dataverse repository deposit --- dmp-backend/dataverseRepository/pom.xml | 46 +++++ .../interfaces/DataverseDeposit.java | 159 ++++++++++++++++++ .../src/main/resources/application.properties | 1 + .../models/UserInfoDepositModel.java | 8 + .../managers/DataManagementPlanManager.java | 9 +- .../mapper/DMPToDepositMapper.java | 1 + .../dummyrepository/TestDummy.java | 29 ---- .../dmp-deposit-dialog.component.ts | 12 ++ 8 files changed, 229 insertions(+), 36 deletions(-) create mode 100644 dmp-backend/dataverseRepository/pom.xml create mode 100644 dmp-backend/dataverseRepository/src/main/java/eu/eudat/depositinterface/dataverserepository/interfaces/DataverseDeposit.java create mode 100644 dmp-backend/dataverseRepository/src/main/resources/application.properties delete mode 100644 dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/dummyrepository/TestDummy.java diff --git a/dmp-backend/dataverseRepository/pom.xml b/dmp-backend/dataverseRepository/pom.xml new file mode 100644 index 000000000..1772a86c1 --- /dev/null +++ b/dmp-backend/dataverseRepository/pom.xml @@ -0,0 +1,46 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 2.7.4 + + + eu.eudat.depositinterface + dataverseRepository + 0.0.1-SNAPSHOT + dataverseRepository + + + 11 + + + + + jitpack.io + https://jitpack.io + + + + + + org.springframework.boot + spring-boot-starter-web + + + + eu.eudat + depositinterface + 1.0-SNAPSHOT + + + + com.github.IQSS + dataverse-client-java + master-dv14-12-compatible-ge2dc343-7 + + + + diff --git a/dmp-backend/dataverseRepository/src/main/java/eu/eudat/depositinterface/dataverserepository/interfaces/DataverseDeposit.java b/dmp-backend/dataverseRepository/src/main/java/eu/eudat/depositinterface/dataverserepository/interfaces/DataverseDeposit.java new file mode 100644 index 000000000..52f0f1802 --- /dev/null +++ b/dmp-backend/dataverseRepository/src/main/java/eu/eudat/depositinterface/dataverserepository/interfaces/DataverseDeposit.java @@ -0,0 +1,159 @@ +package eu.eudat.depositinterface.dataverserepository.interfaces; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.researchspace.dataverse.api.v1.DataverseAPI; +import com.researchspace.dataverse.api.v1.DataverseConfig; +import com.researchspace.dataverse.entities.DataverseContacts; +import com.researchspace.dataverse.entities.DataversePost; +import com.researchspace.dataverse.entities.DataverseResponse; +import com.researchspace.dataverse.entities.Identifier; +import com.researchspace.dataverse.entities.facade.DatasetAuthor; +import com.researchspace.dataverse.entities.facade.DatasetContact; +import com.researchspace.dataverse.entities.facade.DatasetDescription; +import com.researchspace.dataverse.entities.facade.DatasetFacade; +import com.researchspace.dataverse.http.DataverseAPIImpl; +import eu.eudat.depositinterface.models.DMPDepositModel; +import eu.eudat.depositinterface.repository.RepositoryDeposit; +import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.http.*; +import org.springframework.stereotype.Component; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.client.RestTemplate; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.Objects; +import java.util.stream.Collectors; + +import static eu.eudat.depositinterface.repository.RepositoryDepositConfiguration.DepositAccountStatus.SystemDeposit; + +@Component +public class DataverseDeposit implements RepositoryDeposit { + private static final Logger logger = LoggerFactory.getLogger(DataverseDeposit.class); + private static final ObjectMapper objectMapper = new ObjectMapper(); + + private static final String API_TOKEN = ""; + private static final String SYSTEM_PARENT_DATAVERSE_ALIAS = ""; + private static final String SERVER = ""; + private static final String SYSTEM_EMAIL = ""; + + private DataverseAPI api; + private boolean isApiSet; + + private Environment environment; + + @Autowired + public DataverseDeposit(Environment environment){ + this.environment = environment; + this.isApiSet = false; + } + + private void setDataverseApi() throws MalformedURLException { + if(!this.isApiSet) { + this.api = new DataverseAPIImpl(); + DataverseConfig config = new DataverseConfig(new URL(SERVER), API_TOKEN, SYSTEM_PARENT_DATAVERSE_ALIAS); + api.configure(config); + this.isApiSet = true; + } + } + + @Override + public String deposit(DMPDepositModel dmpDepositModel, boolean update, String repositoryAccessToken) throws Exception { + + if(!this.isApiSet) + this.setDataverseApi(); + + DataversePost entity = new DataversePost(); + entity.setName(dmpDepositModel.getLabel()); + entity.setAlias(dmpDepositModel.getLabel().replace(" ", "_")); + entity.setDescription(dmpDepositModel.getDescription()); + entity.setCreationDate(new Date()); + entity.setDataverseContacts(Collections.singletonList(new DataverseContacts(SYSTEM_EMAIL))); + DataverseResponse response = this.api.getDataverseOperations().createNewDataverse(SYSTEM_PARENT_DATAVERSE_ALIAS, entity); + + DatasetFacade dataset = DatasetFacade.builder() + .title(dmpDepositModel.getLabel()) + .authors(dmpDepositModel.getUsers().stream().map(x -> DatasetAuthor.builder().authorName(x.getUser().getName()).build()).collect(Collectors.toList())) + .contacts(dmpDepositModel.getUsers().stream().map(x -> DatasetContact.builder().datasetContactEmail(x.getUser().getEmail()).build()).collect(Collectors.toList())) + .subject("Other") + .description(DatasetDescription.builder().description(dmpDepositModel.getDescription()).build()) + .languages(new ArrayList<>()) + .depositor("") + .build(); + Identifier id = this.api.getDataverseOperations().createDataset(dataset, entity.getAlias()); + + String doi = this.api.getDatasetOperations().getDataset(id).getDoiId().orElse(null); + + this.uploadFile(dmpDepositModel.getPdfFileName(), dmpDepositModel.getPdfFile(), doi); + + String contentDisposition = dmpDepositModel.getRdaJson().getHeaders().get("Content-Disposition").get(0); + String jsonFileName = contentDisposition.substring(contentDisposition.lastIndexOf('=') + 1); + File rdaJson = new File(this.environment.getProperty("storage.temp") + jsonFileName); + OutputStream output = new FileOutputStream(rdaJson); + try { + output.write(Objects.requireNonNull(dmpDepositModel.getRdaJson().getBody())); + output.flush(); + output.close(); + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + this.uploadFile(jsonFileName, rdaJson, doi); + Files.deleteIfExists(rdaJson.toPath()); + + return doi; + + } + + private void uploadFile(String filename, File file, String doi) throws IOException { + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + headers.set("X-Dataverse-key", API_TOKEN); + MultiValueMap fileMap = new LinkedMultiValueMap<>(); + ContentDisposition contentDisposition = ContentDisposition + .builder("form-data") + .name("file") + .filename(filename) + .build(); + fileMap.add(HttpHeaders.CONTENT_DISPOSITION, contentDisposition.toString()); + HttpEntity fileEntity = new HttpEntity<>(Files.readAllBytes(file.toPath()), fileMap); + MultiValueMap body = new LinkedMultiValueMap<>(); + body.add("file", fileEntity); + body.add("jsonData", "{\"restrict\":\"true\", \"tabIngest\":\"false\"}"); + HttpEntity> requestEntity + = new HttpEntity<>(body, headers); + + String serverUrl = SERVER + "/api/datasets/:persistentId/add?persistentId=doi:" + doi; + + RestTemplate restTemplate = new RestTemplate(); + ResponseEntity resp = restTemplate.postForEntity(serverUrl, requestEntity, Object.class); + } + + @Override + public RepositoryDepositConfiguration getConfiguration() { + RepositoryDepositConfiguration conf = new RepositoryDepositConfiguration(); + conf.setRepositoryId("Dataverse"); + conf.setDepositAccountStatus(SystemDeposit.getValue()); + conf.setAccessToken(API_TOKEN); + conf.setRepositoryUrl(SERVER + "/api/"); + conf.setRepositoryRecordUrl(SERVER + "/dataverse/"); + return conf; + } + + @Override + public String authenticate(String code) { + return null; + } +} diff --git a/dmp-backend/dataverseRepository/src/main/resources/application.properties b/dmp-backend/dataverseRepository/src/main/resources/application.properties new file mode 100644 index 000000000..0ef26534a --- /dev/null +++ b/dmp-backend/dataverseRepository/src/main/resources/application.properties @@ -0,0 +1 @@ +storage.temp= diff --git a/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/UserInfoDepositModel.java b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/UserInfoDepositModel.java index 2b8cec04e..aeb6d5f19 100644 --- a/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/UserInfoDepositModel.java +++ b/dmp-backend/depositinterface/src/main/java/eu/eudat/depositinterface/models/UserInfoDepositModel.java @@ -2,6 +2,7 @@ package eu.eudat.depositinterface.models; public class UserInfoDepositModel { private String name; + private String email; public String getName() { return name; @@ -9,4 +10,11 @@ public class UserInfoDepositModel { public void setName(String name) { this.name = name; } + + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java index a2a8ccc5c..825592d16 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/managers/DataManagementPlanManager.java @@ -2115,14 +2115,9 @@ public class DataManagementPlanManager { throw new Exception("DMP already has a DOI");*/ FileEnvelope file = getWordDocument(depositRequest.getDmpId(), principal, configLoader); - String name = file.getFilename().substring(0, file.getFilename().length() - 5); - //File pdfFile = PDFUtils.convertToPDF(file, environment); - String uuid = UUID.randomUUID().toString(); - File pdfFile = new File(environment.getProperty("temp.temp") + uuid + ".pdf"); - FileOutputStream output = new FileOutputStream(pdfFile); - IOUtils.write("testing".getBytes(StandardCharsets.UTF_8), output); + String name = file.getFilename().substring(0, file.getFilename().length() - 5).replace(" ", "_").replace(",", "_"); + File pdfFile = PDFUtils.convertToPDF(file, environment); String fileName = name + ".pdf"; - output.close(); ResponseEntity jsonFile; try { jsonFile = getRDAJsonDocument(depositRequest.getDmpId(), principal); diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/security/repositorydeposit/mapper/DMPToDepositMapper.java b/dmp-backend/web/src/main/java/eu/eudat/logic/security/repositorydeposit/mapper/DMPToDepositMapper.java index 052c13607..2cbe5e20b 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/security/repositorydeposit/mapper/DMPToDepositMapper.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/security/repositorydeposit/mapper/DMPToDepositMapper.java @@ -40,6 +40,7 @@ public class DMPToDepositMapper { private static UserInfoDepositModel fromUserInfo(UserInfo entity){ UserInfoDepositModel deposit = new UserInfoDepositModel(); deposit.setName(entity.getName()); + deposit.setEmail(entity.getEmail()); return deposit; } diff --git a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/dummyrepository/TestDummy.java b/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/dummyrepository/TestDummy.java deleted file mode 100644 index cc9087d61..000000000 --- a/dmp-backend/zenodoRepository/src/main/java/eu/eudat/depositinterface/dummyrepository/TestDummy.java +++ /dev/null @@ -1,29 +0,0 @@ -package eu.eudat.depositinterface.dummyrepository; - -import eu.eudat.depositinterface.models.DMPDepositModel; -import eu.eudat.depositinterface.repository.RepositoryDeposit; -import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration; -import org.springframework.stereotype.Component; - -import static eu.eudat.depositinterface.repository.RepositoryDepositConfiguration.DepositAccountStatus.BothWaysDeposit; - -@Component -public class TestDummy implements RepositoryDeposit { - @Override - public String deposit(DMPDepositModel dmpDepositModel, boolean update, String repositoryAccessToken) throws Exception { - return "test2"; - } - - @Override - public RepositoryDepositConfiguration getConfiguration() { - RepositoryDepositConfiguration conf = new RepositoryDepositConfiguration(); - conf.setRepositoryId("Dummy"); - conf.setDepositAccountStatus(BothWaysDeposit.getValue()); - return conf; - } - - @Override - public String authenticate(String code) { - return "accessToken"; - } -} \ No newline at end of file diff --git a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts index 88364d012..005eba99d 100644 --- a/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts +++ b/dmp-frontend/src/app/ui/dmp/editor/dmp-deposit-dialog/dmp-deposit-dialog.component.ts @@ -93,6 +93,18 @@ export class DmpDepositDialogComponent extends BaseComponent implements OnInit { }); } + else if(repo.depositAccountStatus == DepositConfigurationStatus.System){ + this.depositRepositoriesService.createDoi(repo.repositoryId, this.dmp.id, null) + .pipe(takeUntil(this._destroyed)) + .subscribe(doi =>{ + this.onDOICallbackSuccess(); + this.outputRepos.push(doi); + this.inputRepos = this.inputRepos.filter(function(x) { return x.repositoryId !== repo.repositoryId; }); + if(this.inputRepos.length == 0){ + this.close(); + } + }, error => this.onDOICallbackError(error)); + } } onDOICallbackSuccess(): void { From 6c13d3b68fedbe338d64750871bd128a9f605194 Mon Sep 17 00:00:00 2001 From: Aldo Mihasi Date: Mon, 14 Nov 2022 09:34:49 +0200 Subject: [PATCH 07/26] when new version is deposited, create dataset in existing dataverse --- .../interfaces/DataverseDeposit.java | 27 +++++++++-------- .../dmp/overview/dmp-overview.component.html | 6 ++-- .../ui/dmp/overview/dmp-overview.component.ts | 30 +++++++++++++++---- 3 files changed, 41 insertions(+), 22 deletions(-) diff --git a/dmp-backend/dataverseRepository/src/main/java/eu/eudat/depositinterface/dataverserepository/interfaces/DataverseDeposit.java b/dmp-backend/dataverseRepository/src/main/java/eu/eudat/depositinterface/dataverserepository/interfaces/DataverseDeposit.java index 52f0f1802..9a63460c5 100644 --- a/dmp-backend/dataverseRepository/src/main/java/eu/eudat/depositinterface/dataverserepository/interfaces/DataverseDeposit.java +++ b/dmp-backend/dataverseRepository/src/main/java/eu/eudat/depositinterface/dataverserepository/interfaces/DataverseDeposit.java @@ -3,10 +3,7 @@ package eu.eudat.depositinterface.dataverserepository.interfaces; import com.fasterxml.jackson.databind.ObjectMapper; import com.researchspace.dataverse.api.v1.DataverseAPI; import com.researchspace.dataverse.api.v1.DataverseConfig; -import com.researchspace.dataverse.entities.DataverseContacts; -import com.researchspace.dataverse.entities.DataversePost; -import com.researchspace.dataverse.entities.DataverseResponse; -import com.researchspace.dataverse.entities.Identifier; +import com.researchspace.dataverse.entities.*; import com.researchspace.dataverse.entities.facade.DatasetAuthor; import com.researchspace.dataverse.entities.facade.DatasetContact; import com.researchspace.dataverse.entities.facade.DatasetDescription; @@ -76,13 +73,17 @@ public class DataverseDeposit implements RepositoryDeposit { if(!this.isApiSet) this.setDataverseApi(); - DataversePost entity = new DataversePost(); - entity.setName(dmpDepositModel.getLabel()); - entity.setAlias(dmpDepositModel.getLabel().replace(" ", "_")); - entity.setDescription(dmpDepositModel.getDescription()); - entity.setCreationDate(new Date()); - entity.setDataverseContacts(Collections.singletonList(new DataverseContacts(SYSTEM_EMAIL))); - DataverseResponse response = this.api.getDataverseOperations().createNewDataverse(SYSTEM_PARENT_DATAVERSE_ALIAS, entity); + String alias = dmpDepositModel.getLabel().replace(" ", "_"); + DataverseGet dataverse = this.api.getDataverseOperations().getDataverseById(alias); + if(dataverse == null) { + DataversePost entity = new DataversePost(); + entity.setName(dmpDepositModel.getLabel()); + entity.setAlias(alias); + entity.setDescription(dmpDepositModel.getDescription()); + entity.setCreationDate(new Date()); + entity.setDataverseContacts(Collections.singletonList(new DataverseContacts(SYSTEM_EMAIL))); + DataverseResponse response = this.api.getDataverseOperations().createNewDataverse(SYSTEM_PARENT_DATAVERSE_ALIAS, entity); + } DatasetFacade dataset = DatasetFacade.builder() .title(dmpDepositModel.getLabel()) @@ -93,7 +94,7 @@ public class DataverseDeposit implements RepositoryDeposit { .languages(new ArrayList<>()) .depositor("") .build(); - Identifier id = this.api.getDataverseOperations().createDataset(dataset, entity.getAlias()); + Identifier id = this.api.getDataverseOperations().createDataset(dataset, alias); String doi = this.api.getDatasetOperations().getDataset(id).getDoiId().orElse(null); @@ -148,7 +149,7 @@ public class DataverseDeposit implements RepositoryDeposit { conf.setDepositAccountStatus(SystemDeposit.getValue()); conf.setAccessToken(API_TOKEN); conf.setRepositoryUrl(SERVER + "/api/"); - conf.setRepositoryRecordUrl(SERVER + "/dataverse/"); + conf.setRepositoryRecordUrl(SERVER + "/dataset.xhtml?persistentId=doi:"); return conf; } diff --git a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html index 602935ded..bec9d1720 100644 --- a/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html +++ b/dmp-frontend/src/app/ui/dmp/overview/dmp-overview.component.html @@ -114,13 +114,13 @@

{{'DMP-EDITOR.TITLE.SUBTITLE' | translate}}

- - + + {{doi.repositoryId}}
-