diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/enums/ExternalReferencesType.java b/dmp-backend/core/src/main/java/eu/eudat/commons/enums/ExternalReferencesType.java new file mode 100644 index 000000000..c3dccae5d --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/enums/ExternalReferencesType.java @@ -0,0 +1,11 @@ +package eu.eudat.commons.enums; + +public enum ExternalReferencesType { + + taxonomies, + licenses, + publications, + journals, + pubRepositories, + dataRepositories +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/commons/enums/SupportiveMaterialFieldType.java b/dmp-backend/core/src/main/java/eu/eudat/commons/enums/SupportiveMaterialFieldType.java new file mode 100644 index 000000000..ce3854316 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/commons/enums/SupportiveMaterialFieldType.java @@ -0,0 +1,10 @@ +package eu.eudat.commons.enums; + +public enum SupportiveMaterialFieldType { + + faq, + about, + glossary, + termsofservice, + userguide +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/ExternalReference.java b/dmp-backend/core/src/main/java/eu/eudat/model/ExternalReference.java new file mode 100644 index 000000000..3361db6a5 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/ExternalReference.java @@ -0,0 +1,124 @@ +package eu.eudat.model; + +import eu.eudat.data.entities.DataRepository; +import eu.eudat.data.entities.UserInfo; + +import java.util.Date; +import java.util.UUID; + +public class ExternalReference { + private UUID id; + private String name; + private String pid; + private String abbreviation; + private String uri; + private Date created; + private Date modified; + private String tag; // Api fetching the data + private String source; // Actual harvested source + + public UUID getId() { + return id; + } + public void setId(UUID id) { + this.id = id; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public String getPid() { + return pid; + } + public void setPid(String pid) { + this.pid = pid; + } + + public String getAbbreviation() { + return abbreviation; + } + public void setAbbreviation(String abbreviation) { + this.abbreviation = abbreviation; + } + + public String getUri() { + return uri; + } + public void setUri(String uri) { + this.uri = uri; + } + + public Date getCreated() { + return created; + } + public void setCreated(Date created) { + this.created = created; + } + + public Date getModified() { + return modified; + } + public void setModified(Date modified) { + this.modified = modified; + } + + public String getTag() { + return tag; + } + public void setTag(String tag) { + this.tag = tag; + } + + public String getSource() { + return source; + } + public void setSource(String source) { + this.source = source; + } + + + public ExternalReference fromDataModel(DataRepository entity) { + this.setAbbreviation(entity.getAbbreviation()); + this.setName(entity.getLabel()); + this.setUri(entity.getUri()); + this.setId(entity.getId()); + this.setPid(entity.getReference()); + String source1 = entity.getReference().substring(0, entity.getReference().indexOf(":")); + if (source1.equals("dmp")) { + this.source = "Internal"; + } else { + this.source = source1; + } + return this; + } + + public DataRepository toDataModel() throws Exception { + DataRepository dataRepository = new DataRepository(); + dataRepository.setId(this.id != null ? this.id : UUID.randomUUID()); + dataRepository.setAbbreviation(this.abbreviation); + dataRepository.setCreated(this.created != null ? this.created : new Date()); + dataRepository.setModified(new Date()); + dataRepository.setLabel(this.name); + if (this.source != null) { + if (this.source.equals("Internal") || this.source.equals(this.id.toString().substring(0, this.source.length()))) { + dataRepository.setReference(this.id.toString()); + } else { + dataRepository.setReference(this.source + ":" + dataRepository.getId()); + } + } else { + dataRepository.setReference("dmp:" + dataRepository.getId()); + } + dataRepository.setUri(this.uri); + dataRepository.setStatus((short) 0); + dataRepository.setCreationUser(new UserInfo()); + return dataRepository; + } + + public String getHint() { + return null; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/ExternalReference2.java b/dmp-backend/core/src/main/java/eu/eudat/model/ExternalReference2.java new file mode 100644 index 000000000..60b7a66f5 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/ExternalReference2.java @@ -0,0 +1,178 @@ +package eu.eudat.model; + +import eu.eudat.data.entities.Registry; +import eu.eudat.data.entities.Service; +import eu.eudat.data.entities.UserInfo; + +import java.util.Date; +import java.util.UUID; + +public class ExternalReference2 { + private UUID id; + private String label; + private String name; + private String pid; + private String abbreviation; + private String uri; + private Date created; + private Date modified; + private String reference; + private String tag; + private String source; + + public UUID getId() { + return id; + } + public void setId(UUID id) { + this.id = id; + } + + public String getLabel() { + return label; + } + public void setLabel(String label) { + this.label = label; + } + + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + public String getPid() { + return pid; + } + public void setPid(String pid) { + this.pid = pid; + } + + public String getAbbreviation() { + return abbreviation; + } + public void setAbbreviation(String abbreviation) { + this.abbreviation = abbreviation; + } + + public String getUri() { + return uri; + } + public void setUri(String uri) { + this.uri = uri; + } + + public Date getCreated() { + return created; + } + public void setCreated(Date created) { + this.created = created; + } + + public Date getModified() { + return modified; + } + public void setModified(Date modified) { + this.modified = modified; + } + + public String getReference() { + return reference; + } + public void setReference(String reference) { + this.reference = reference; + } + + public String getTag() { + return tag; + } + public void setTag(String tag) { + this.tag = tag; + } + + public String getSource() { + return source; + } + public void setSource(String source) { + this.source = source; + } + + public ExternalReference2 fromDataModel(Service entity) { + this.abbreviation = entity.getAbbreviation(); + this.created = entity.getCreated(); + this.id = entity.getId(); + this.label = entity.getLabel(); + this.name = entity.getLabel(); + this.modified = entity.getModified(); + this.uri = entity.getUri(); + String source = entity.getReference().substring(0, entity.getReference().indexOf(":")); + if (source.equals("dmp")) { + this.source = "Internal"; + } else { + this.source = source; + } + return this; + } + + public ExternalReference2 fromDataModel(Registry entity) { + this.id = entity.getId(); + this.abbreviation = entity.getAbbreviation(); + this.created = entity.getCreated(); + this.label = entity.getLabel(); + this.name = entity.getLabel(); + this.modified = entity.getModified(); + this.uri = entity.getUri(); + String source1 = entity.getReference().substring(0, entity.getReference().indexOf(":")); + if (source1.equals("dmp")) { + this.source = "Internal"; + } else { + this.source = source1; + } + this.reference = entity.getReference(); + return this; + } + + public Service toDataModelService() throws Exception { + Service service = new Service(); + service.setId(this.id != null ? this.id : UUID.randomUUID()); + service.setAbbreviation(this.abbreviation); + service.setCreated(this.created != null ? this.created : new Date()); + service.setLabel(this.label != null ? this.label : this.name); + service.setModified(new Date()); + service.setUri(this.uri); + if (this.source == null) this.source = "dmp"; + if (this.reference == null) this.reference = service.getId().toString(); + if (this.source.equals(this.reference.substring(0, this.source.length()))) { + service.setReference(this.reference); + } else { + service.setReference(this.source + ":" + this.reference); + } + service.setModified(new Date()); + service.setStatus((short) 0); + service.setCreationUser(new UserInfo()); + return service; + } + + public Registry toDataModelRegistry() throws Exception { + Registry registry = new Registry(); + registry.setAbbreviation(this.abbreviation); + registry.setCreated(this.created != null ? this.created : new Date()); + registry.setId(this.id != null ? this.id : UUID.randomUUID()); + registry.setLabel(this.label != null ? this.label : this.name); + registry.setUri(this.uri); + registry.setModified(new Date()); + if (this.source == null) this.source = "dmp"; + if (this.source.equals(registry.getId().toString().substring(0, this.source.length()))) { + registry.setReference(registry.getId().toString()); + } else { + registry.setReference(this.source + ":" + registry.getId()); + } + registry.setStatus((short)0); + registry.setCreationUser(new UserInfo()); + return registry; + } + + public String getHint() { + return null; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/model/persist/UserGuidePersist.java b/dmp-backend/core/src/main/java/eu/eudat/model/persist/UserGuidePersist.java new file mode 100644 index 000000000..6707ba919 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/model/persist/UserGuidePersist.java @@ -0,0 +1,30 @@ +package eu.eudat.model.persist; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; + +public class UserGuidePersist { + + @NotNull(message = "{validation.empty}") + @NotEmpty(message = "{validation.empty}") + private String name; + @NotNull(message = "{validation.empty}") + @NotEmpty(message = "{validation.empty}") + private String html; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getHtml() { + return html; + } + + public void setHtml(String html) { + this.html = html; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/ValidationService.java b/dmp-backend/core/src/main/java/eu/eudat/service/ValidationService.java new file mode 100644 index 000000000..b736a2018 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/service/ValidationService.java @@ -0,0 +1,30 @@ +package eu.eudat.service; + +import eu.eudat.logic.proxy.config.ExternalUrlCriteria; +import eu.eudat.logic.proxy.config.exceptions.HugeResultSet; +import eu.eudat.logic.proxy.config.exceptions.NoURLFound; +import eu.eudat.logic.proxy.fetching.RemoteFetcher; +import eu.eudat.models.data.security.Principal; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class ValidationService { + + private RemoteFetcher remoteFetcher; + + @Autowired + public ValidationService(RemoteFetcher remoteFetcher) { + super(); + this.remoteFetcher = remoteFetcher; + } + + public Boolean validateIdentifier(String identifier, String type, Principal principal) throws NoURLFound, HugeResultSet { + ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(identifier); + Integer count = this.remoteFetcher.findEntries(externalUrlCriteria, type); + return principal != null && count > 0; + } + + + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/ExternalReferencesCacheOptions.java b/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/ExternalReferencesCacheOptions.java new file mode 100644 index 000000000..d224ee815 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/ExternalReferencesCacheOptions.java @@ -0,0 +1,10 @@ +package eu.eudat.service.externalreferences; + +import gr.cite.tools.cache.CacheOptions; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "cache.external-reference") +public class ExternalReferencesCacheOptions extends CacheOptions { +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/ExternalReferencesCacheService.java b/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/ExternalReferencesCacheService.java new file mode 100644 index 000000000..18d82d1b5 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/ExternalReferencesCacheService.java @@ -0,0 +1,67 @@ +package eu.eudat.service.externalreferences; + +import eu.eudat.proxy.config.ExternalUrlCriteria; +import gr.cite.tools.cache.CacheService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.Locale; + +@Service +public class ExternalReferencesCacheService extends CacheService { + + public static class ExternalReferencesCacheValue { + + public ExternalReferencesCacheValue() {} + + public ExternalReferencesCacheValue(String externalType, ExternalUrlCriteria externalUrlCriteria) { + this.externalType = externalType; + this.externalUrlCriteria = externalUrlCriteria; + } + + private String externalType; + + private ExternalUrlCriteria externalUrlCriteria; + + public String getExternalType() { + return externalType; + } + + public void setExternalType(String externalType) { + this.externalType = externalType; + } + + public ExternalUrlCriteria getExternalUrlCriteria() { + return externalUrlCriteria; + } + + public void setExternalUrlCriteria(ExternalUrlCriteria externalUrlCriteria) { + this.externalUrlCriteria = externalUrlCriteria; + } + } + + @Autowired + public ExternalReferencesCacheService(ExternalReferencesCacheOptions options) { + super(options); + } + + @Override + protected Class valueClass() {return ExternalReferencesCacheService.ExternalReferencesCacheValue.class;} + + public String keyOf(ExternalReferencesCacheService.ExternalReferencesCacheValue value) { + return this.buildKey(value.getExternalType(), value.getExternalUrlCriteria()); + } + + public String buildKey(String externalType, ExternalUrlCriteria externalUrlCriteria) { + HashMap keyParts = new HashMap<>(); + + keyParts.put("$type$", externalType.toLowerCase(Locale.ROOT)); + + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append(externalUrlCriteria); + keyParts.put("$criteria$", stringBuffer.toString().toLowerCase(Locale.ROOT)); + + return this.generateKey(keyParts); + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/ExternalReferencesService.java b/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/ExternalReferencesService.java new file mode 100644 index 000000000..ff50260d1 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/ExternalReferencesService.java @@ -0,0 +1,22 @@ +package eu.eudat.service.externalreferences; + +import eu.eudat.data.entities.DataRepository; +import eu.eudat.logic.proxy.config.exceptions.HugeResultSet; +import eu.eudat.logic.proxy.config.exceptions.NoURLFound; +import eu.eudat.model.ExternalReference2; + +import eu.eudat.model.ExternalReference; +import eu.eudat.models.data.security.Principal; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public interface ExternalReferencesService { + + DataRepository create(ExternalReference externalReference, Principal principal) throws Exception; + + List getExternal(String externalType, String query, String type, Principal principal) throws HugeResultSet, NoURLFound; + + List getExternal2(String externalType, String query, String type, Principal principal) throws HugeResultSet,NoURLFound; +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/ExternalReferencesServiceImpl.java b/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/ExternalReferencesServiceImpl.java new file mode 100644 index 000000000..41f2c0331 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/ExternalReferencesServiceImpl.java @@ -0,0 +1,97 @@ +package eu.eudat.service.externalreferences; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import eu.eudat.data.dao.criteria.DataRepositoryCriteria; +import eu.eudat.data.dao.criteria.RegistryCriteria; +import eu.eudat.data.dao.criteria.ServiceCriteria; +import eu.eudat.data.entities.DataRepository; +import eu.eudat.data.entities.Registry; +import eu.eudat.data.entities.Service; +import eu.eudat.logic.proxy.config.ExternalUrlCriteria; +import eu.eudat.logic.proxy.config.exceptions.HugeResultSet; +import eu.eudat.logic.proxy.config.exceptions.NoURLFound; +import eu.eudat.logic.services.ApiContext; +import eu.eudat.model.ExternalReference2; +import eu.eudat.model.ExternalReference; +import eu.eudat.models.data.security.Principal; + +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class ExternalReferencesServiceImpl implements ExternalReferencesService{ + + private final ApiContext apiContext; + + public ExternalReferencesServiceImpl(ApiContext apiContext) { + this.apiContext = apiContext; + } + + @Override + public DataRepository create(ExternalReference externalReference, Principal principal) throws Exception { + // only dataRepositories, pubRepositories, journals + DataRepository dataRepository = externalReference.toDataModel(); + dataRepository.getCreationUser().setId(principal.getId()); + return apiContext.getOperationsContext().getDatabaseRepository().getDataRepositoryDao().createOrUpdate(dataRepository); + } + + @Override + public List getExternal(String externalType, String query, String type, Principal principal) throws HugeResultSet, NoURLFound { + ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(query); + List> remoteRepos = this.apiContext.getOperationsContext().getRemoteFetcher().get(externalType, externalUrlCriteria, type); + + DataRepositoryCriteria criteria = new DataRepositoryCriteria(); + if (!query.isEmpty()) criteria.setLike(query); + + List list = new LinkedList<>(); + if((externalType.equals("dataRepositories") || externalType.equals("pubRepositories") || externalType.equals("journals"))){ + criteria.setCreationUserId(principal.getId()); + if (type.equals("")) { + List dataRepositoryList = (this.apiContext.getOperationsContext().getDatabaseRepository().getDataRepositoryDao().getWithCriteria(criteria)).toList(); + list = dataRepositoryList.stream().map(item -> new ExternalReference().fromDataModel(item)).collect(Collectors.toList()); + } + } + + ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + list.addAll(remoteRepos.stream().map(item -> mapper.convertValue(item, ExternalReference.class)).collect(Collectors.toList())); + list = list.stream().filter(licenseModel -> licenseModel.getName().toLowerCase().contains(query.toLowerCase())).collect(Collectors.toList()); + return list; + } + + public List getExternal2(String externalType, String query, String type, Principal principal) throws HugeResultSet,NoURLFound { + ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(query); + List> remoteRepos = this.apiContext.getOperationsContext().getRemoteFetcher().get(externalType,externalUrlCriteria, type); + + List list = new LinkedList<>(); + + if (externalType.equals("registries")){ + RegistryCriteria criteria = new RegistryCriteria(); + + if (!query.isEmpty()) criteria.setLike(query); + criteria.setCreationUserId(principal.getId()); + + if (type.equals("")) { + List registryList = (this.apiContext.getOperationsContext().getDatabaseRepository().getRegistryDao().getWithCriteria(criteria)).toList(); + list = registryList.stream().map(item -> new ExternalReference2().fromDataModel(item)).collect(Collectors.toList()); + } + } else if (externalType.equals("services")) { + ServiceCriteria criteria = new ServiceCriteria(); + + if (!query.isEmpty()) criteria.setLike(query); + criteria.setCreationUserId(principal.getId()); + + if (type.equals("")) { + List serviceList = (this.apiContext.getOperationsContext().getDatabaseRepository().getServiceDao().getWithCriteria(criteria)).toList(); + list = serviceList.stream().map(item -> new ExternalReference2().fromDataModel(item)).collect(Collectors.toList()); + } + } + + ObjectMapper mapper = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + list.addAll(remoteRepos.stream().map(item -> mapper.convertValue(item, ExternalReference2.class)).collect(Collectors.toList())); + + return list; + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/FunderService.java b/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/FunderService.java new file mode 100644 index 000000000..6596e0d53 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/FunderService.java @@ -0,0 +1,64 @@ +package eu.eudat.service.externalreferences; + +import eu.eudat.data.query.items.item.funder.FunderCriteriaRequest; +import eu.eudat.logic.builders.model.models.FunderBuilder; +import eu.eudat.proxy.config.ExternalUrlCriteria; +import eu.eudat.proxy.config.exceptions.HugeResultSet; +import eu.eudat.proxy.config.exceptions.NoURLFound; +import eu.eudat.proxy.fetching.RemoteFetcher; +import eu.eudat.logic.utilities.helpers.ListHelper; +import eu.eudat.models.data.external.ExternalSourcesItemModel; +import eu.eudat.models.data.external.FundersExternalSourcesModel; +import eu.eudat.models.data.funder.Funder; +import eu.eudat.models.data.security.Principal; +import eu.eudat.queryable.QueryableList; +import org.springframework.stereotype.Service; + +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +public class FunderService { + + private ApiContext apiContext; + private RemoteFetcher remoteFetcher; + private ListHelper listHelper; + + public FunderService(ApiContext apiContext, RemoteFetcher remoteFetcher, ListHelper listHelper) { + this.apiContext = apiContext; + this.remoteFetcher = remoteFetcher; + this.listHelper = listHelper; + } + + public List getCriteriaWithExternal(FunderCriteriaRequest funderCriteria, Principal principal) throws HugeResultSet, NoURLFound { + eu.eudat.data.entities.UserInfo userInfo = new eu.eudat.data.entities.UserInfo(); + userInfo.setId(principal.getId()); + funderCriteria.getCriteria().setReference("dmp:"); + QueryableList items = apiContext.getOperationsContext().getDatabaseRepository().getFunderDao().getWithCritetia(funderCriteria.getCriteria()); + QueryableList authItems = apiContext.getOperationsContext().getDatabaseRepository().getFunderDao().getAuthenticated(items, userInfo); + List funders = authItems.select(item -> new Funder().fromDataModel(item)); + ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(funderCriteria.getCriteria().getLike()); + List> remoteRepos = remoteFetcher.getFunders(externalUrlCriteria); + FundersExternalSourcesModel fundersExternalSourcesModel = new FundersExternalSourcesModel().fromExternalItem(remoteRepos); + for (ExternalSourcesItemModel externalListingItem : fundersExternalSourcesModel) { + Funder funder = apiContext.getOperationsContext().getBuilderFactory().getBuilder(FunderBuilder.class) + .reference(externalListingItem.getRemoteId()).label(externalListingItem.getName()) + .status(eu.eudat.data.entities.Funder.Status.fromInteger(0)) + .key(externalListingItem.getKey()) + .source(externalListingItem.getTag()) + .build(); + if (externalListingItem.getSource() != null) { + funder.setSource(externalListingItem.getSource()); + } else { + funder.setSource(externalListingItem.getTag()); + } + + funders.add(funder); + } + funders.sort(Comparator.comparing(Funder::getLabel)); + funders = funders.stream().filter(listHelper.distinctByKey(Funder::getLabel)).collect(Collectors.toList()); + return funders; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/ProjectService.java b/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/ProjectService.java new file mode 100644 index 000000000..48f7bd910 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/service/externalreferences/ProjectService.java @@ -0,0 +1,60 @@ +package eu.eudat.service.externalreferences; + +import eu.eudat.data.query.items.item.project.ProjectCriteriaRequest; +import eu.eudat.logic.builders.model.models.ProjectBuilder; +import eu.eudat.proxy.config.ExternalUrlCriteria; +import eu.eudat.proxy.config.exceptions.HugeResultSet; +import eu.eudat.proxy.config.exceptions.NoURLFound; +import eu.eudat.proxy.fetching.RemoteFetcher; +import eu.eudat.logic.utilities.helpers.ListHelper; +import eu.eudat.models.data.external.ExternalSourcesItemModel; +import eu.eudat.models.data.external.ProjectsExternalSourcesModel; +import eu.eudat.models.data.project.Project; +import eu.eudat.models.data.security.Principal; +import eu.eudat.queryable.QueryableList; +import org.springframework.stereotype.Service; + +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Service +public class ProjectService { + + private ApiContext apiContext; + private RemoteFetcher remoteFetcher; + private ListHelper listHelper; + + public ProjectService(ApiContext apiContext, ListHelper listHelper) { + this.apiContext = apiContext; + this.remoteFetcher = apiContext.getOperationsContext().getRemoteFetcher(); + this.listHelper = listHelper; + } + + public List getCriteriaWithExternal(ProjectCriteriaRequest projectCriteria, Principal principal) throws HugeResultSet, NoURLFound { + eu.eudat.data.entities.UserInfo userInfo = new eu.eudat.data.entities.UserInfo(); + userInfo.setId(principal.getId()); + projectCriteria.getCriteria().setReference("dmp:"); + QueryableList items = apiContext.getOperationsContext().getDatabaseRepository().getProjectDao().getWithCritetia(projectCriteria.getCriteria()); + QueryableList authItems = apiContext.getOperationsContext().getDatabaseRepository().getProjectDao().getAuthenticated(items, userInfo); + List projects = authItems.select(item -> new Project().fromDataModel(item)); + ExternalUrlCriteria externalUrlCriteria = new ExternalUrlCriteria(projectCriteria.getCriteria().getLike()); + List> remoteRepos = remoteFetcher.getProjects(externalUrlCriteria); + ProjectsExternalSourcesModel projectsExternalSourcesModel = new ProjectsExternalSourcesModel().fromExternalItem(remoteRepos); + for (ExternalSourcesItemModel externalListingItem : projectsExternalSourcesModel) { + Project project = apiContext.getOperationsContext().getBuilderFactory().getBuilder(ProjectBuilder.class) + .reference(externalListingItem.getRemoteId()).label(externalListingItem.getName()) + .description(externalListingItem.getDescription()).uri(externalListingItem.getUri()) + .abbreviation(externalListingItem.getAbbreviation()).status(eu.eudat.data.entities.Project.Status.fromInteger(0)) + .key(externalListingItem.getKey()) + .source(externalListingItem.getTag()) + .build(); + + projects.add(project); + } + projects.sort(Comparator.comparing(Project::getLabel)); + projects = projects.stream().filter(listHelper.distinctByKey(Project::getLabel)).collect(Collectors.toList()); + return projects; + } +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/supportivematerial/SupportiveMaterialCacheOptions.java b/dmp-backend/core/src/main/java/eu/eudat/service/supportivematerial/SupportiveMaterialCacheOptions.java new file mode 100644 index 000000000..f415c524b --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/service/supportivematerial/SupportiveMaterialCacheOptions.java @@ -0,0 +1,11 @@ +package eu.eudat.service.supportivematerial; + + +import gr.cite.tools.cache.CacheOptions; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConfigurationProperties(prefix = "cache.supportive-material") +public class SupportiveMaterialCacheOptions extends CacheOptions { +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/supportivematerial/SupportiveMaterialCacheService.java b/dmp-backend/core/src/main/java/eu/eudat/service/supportivematerial/SupportiveMaterialCacheService.java new file mode 100644 index 000000000..c12c5d99a --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/service/supportivematerial/SupportiveMaterialCacheService.java @@ -0,0 +1,67 @@ +package eu.eudat.service.supportivematerial; + + +import gr.cite.tools.cache.CacheService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Locale; + +@Service +public class SupportiveMaterialCacheService extends CacheService { + + public static class SupportiveMaterialCacheValue { + + public SupportiveMaterialCacheValue() {} + + public SupportiveMaterialCacheValue(String name, byte[] content) { + this.name = name; + this.content = content; + } + + private String name; + + private byte[] content; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public byte[] getContent() { + return content; + } + + public void setContent(byte[] content) { + this.content = content; + } + } + + @Autowired + public SupportiveMaterialCacheService(SupportiveMaterialCacheOptions options) { + super(options); + } + + @Override + protected Class valueClass() {return SupportiveMaterialCacheValue.class;} + + + public String keyOf(SupportiveMaterialCacheValue value) { + return this.buildKey(value.getName()); + } + + public String buildKey(String name) { + HashMap keyParts = new HashMap<>(); + + keyParts.put("$material$", name.toLowerCase(Locale.ROOT)); + //keyParts.put("$material_content$", new String(content, StandardCharsets.UTF_8).toLowerCase(Locale.ROOT)); + + return this.generateKey(keyParts); + } + +} diff --git a/dmp-backend/core/src/main/java/eu/eudat/service/supportivematerial/SupportiveMaterialService.java b/dmp-backend/core/src/main/java/eu/eudat/service/supportivematerial/SupportiveMaterialService.java new file mode 100644 index 000000000..b5cf20223 --- /dev/null +++ b/dmp-backend/core/src/main/java/eu/eudat/service/supportivematerial/SupportiveMaterialService.java @@ -0,0 +1,71 @@ +package eu.eudat.service.supportivematerial; + +import eu.eudat.model.persist.UserGuidePersist; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + + +@Service +public class SupportiveMaterialService { + + private final SupportiveMaterialCacheService supportiveMaterialCacheService; + + public SupportiveMaterialService( + SupportiveMaterialCacheService supportiveMaterialCacheService + ) { + this.supportiveMaterialCacheService = supportiveMaterialCacheService; + } + + public ResponseEntity getResponseEntity(String lang, Stream paths) throws IOException { + List result = paths.filter(Files::isRegularFile) + .map(Path::toString).collect(Collectors.toList()); + + String fileName = result.stream().filter(about -> about.contains("_" + lang)).findFirst().orElse(null); + + if (fileName == null) { + fileName = result.stream().filter(about -> about.contains("_en")).findFirst().get(); + } + + SupportiveMaterialCacheService.SupportiveMaterialCacheValue supportiveMaterialCacheItem = this.supportiveMaterialCacheService.lookup(this.supportiveMaterialCacheService.buildKey(fileName)); + + if(supportiveMaterialCacheItem == null){ + InputStream is = new FileInputStream(fileName); + + // Path path = Paths.get(fileName); + + byte[] content = new byte[is.available()]; + is.read(content); + is.close(); + + supportiveMaterialCacheItem = new SupportiveMaterialCacheService.SupportiveMaterialCacheValue(fileName, content); + this.supportiveMaterialCacheService.put(supportiveMaterialCacheItem); + } + + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.setContentLength(supportiveMaterialCacheItem.getContent().length); + responseHeaders.setContentType(MediaType.TEXT_HTML); + responseHeaders.set("Content-Disposition", "attachment;filename=" + fileName); + responseHeaders.set("Access-Control-Expose-Headers", "Content-Disposition"); + responseHeaders.get("Access-Control-Expose-Headers").add("Content-Type"); + + return new ResponseEntity<>(supportiveMaterialCacheItem.getContent(), responseHeaders, HttpStatus.OK); + } + + public void persist(UserGuidePersist userGuidePersist, String fileName) throws IOException { + this.supportiveMaterialCacheService.evict(fileName); + OutputStream os = new FileOutputStream(fileName); + os.write(userGuidePersist.getHtml().getBytes()); + os.close(); + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/AboutController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/AboutController.java deleted file mode 100644 index 729c8cd05..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/AboutController.java +++ /dev/null @@ -1,39 +0,0 @@ -package eu.eudat.controllers; - -import eu.eudat.logic.managers.MaterialManager; -import eu.eudat.logic.managers.MetricsManager; -import eu.eudat.types.MetricNames; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.Environment; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Objects; -import java.util.stream.Stream; - -@RestController -@CrossOrigin -@RequestMapping(value = {"/api/material/about/"}) -public class AboutController { - - private Environment environment; - private MaterialManager materialManager; - - @Autowired - public AboutController(Environment environment, MaterialManager materialManager, MetricsManager metricsManager) { - this.environment = environment; - this.materialManager = materialManager; - } - - @RequestMapping(path = "{lang}", method = RequestMethod.GET ) - public ResponseEntity getAbout(@PathVariable(name = "lang") String lang) throws IOException { - try (Stream paths = Files.walk(Paths.get(Objects.requireNonNull(this.environment.getProperty("about.path"))))) { - return this.materialManager.getResponseEntity(lang, paths); - } - } - -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/FaqController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/FaqController.java deleted file mode 100644 index 5badd7959..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/FaqController.java +++ /dev/null @@ -1,38 +0,0 @@ -package eu.eudat.controllers; - -import eu.eudat.logic.managers.MaterialManager; -import eu.eudat.logic.managers.MetricsManager; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.Environment; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Objects; -import java.util.stream.Stream; - -@RestController -@CrossOrigin -@RequestMapping(value = {"/api/material/faq/"}) -public class FaqController { - - private Environment environment; - private MaterialManager materialManager; - - @Autowired - public FaqController(Environment environment, MaterialManager materialManager, MetricsManager metricsManager) { - this.environment = environment; - this.materialManager = materialManager; - } - - @RequestMapping(path = "{lang}", method = RequestMethod.GET ) - public ResponseEntity getFaq(@PathVariable(name = "lang") String lang) throws IOException { - try (Stream paths = Files.walk(Paths.get(Objects.requireNonNull(this.environment.getProperty("faq.path"))))) { - return this.materialManager.getResponseEntity(lang, paths); - } - } - -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/GlossaryController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/GlossaryController.java deleted file mode 100644 index 5e6a783bd..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/GlossaryController.java +++ /dev/null @@ -1,38 +0,0 @@ -package eu.eudat.controllers; - -import eu.eudat.logic.managers.MaterialManager; -import eu.eudat.logic.managers.MetricsManager; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.Environment; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Objects; -import java.util.stream.Stream; - -@RestController -@CrossOrigin -@RequestMapping(value = {"/api/material/glossary/"}) -public class GlossaryController { - - private Environment environment; - private MaterialManager materialManager; - - @Autowired - public GlossaryController(Environment environment, MaterialManager materialManager, MetricsManager metricsManager) { - this.environment = environment; - this.materialManager = materialManager; - } - - @RequestMapping(path = "{lang}", method = RequestMethod.GET ) - public ResponseEntity getGlossary(@PathVariable(name = "lang") String lang) throws IOException { - try (Stream paths = Files.walk(Paths.get(Objects.requireNonNull(this.environment.getProperty("glossary.path"))))) { - return this.materialManager.getResponseEntity(lang, paths); - } - } - -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/TermsOfServiceController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/TermsOfServiceController.java deleted file mode 100644 index 2875f6c07..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/TermsOfServiceController.java +++ /dev/null @@ -1,38 +0,0 @@ -package eu.eudat.controllers; - -import eu.eudat.logic.managers.MaterialManager; -import eu.eudat.logic.managers.MetricsManager; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.Environment; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Objects; -import java.util.stream.Stream; - -@RestController -@CrossOrigin -@RequestMapping(value = {"/api/material/termsofservice/"}) -public class TermsOfServiceController { - - private Environment environment; - private MaterialManager materialManager; - - @Autowired - public TermsOfServiceController(Environment environment, MaterialManager materialManager, MetricsManager metricsManager) { - this.environment = environment; - this.materialManager = materialManager; - } - - @RequestMapping(path = "{lang}", method = RequestMethod.GET ) - public ResponseEntity getTermsOfService(@PathVariable(name = "lang") String lang) throws IOException { - try (Stream paths = Files.walk(Paths.get(Objects.requireNonNull(this.environment.getProperty("termsofservice.path"))))) { - return this.materialManager.getResponseEntity(lang, paths); - } - } - -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/UserGuideController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/UserGuideController.java deleted file mode 100644 index cd7cb9dae..000000000 --- a/dmp-backend/web/src/main/java/eu/eudat/controllers/UserGuideController.java +++ /dev/null @@ -1,60 +0,0 @@ -package eu.eudat.controllers; - -import eu.eudat.logic.managers.MaterialManager; -import eu.eudat.logic.managers.MetricsManager; -import eu.eudat.logic.security.claims.ClaimedAuthorities; -import eu.eudat.models.data.helpers.responses.ResponseItem; -import eu.eudat.models.data.security.Principal; -import eu.eudat.models.data.userguide.UserGuide; -import eu.eudat.types.ApiMessageCode; -import eu.eudat.types.MetricNames; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.env.Environment; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.io.*; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static eu.eudat.types.Authorities.ADMIN; - -@RestController -@CrossOrigin -@RequestMapping(value = {"/api/userguide/"}) -public class UserGuideController { - - private Environment environment; - private MaterialManager materialManager; - - @Autowired - public UserGuideController(Environment environment, MaterialManager materialManager, MetricsManager metricsManager) { - this.environment = environment; - this.materialManager = materialManager; - } - - @RequestMapping(path = "{lang}", method = RequestMethod.GET ) - public ResponseEntity getUserGuide(@PathVariable(name = "lang") String lang) throws IOException { - try (Stream paths = Files.walk(Paths.get(Objects.requireNonNull(this.environment.getProperty("userguide.path"))))) { - return this.materialManager.getResponseEntity(lang, paths); - } - } - - @RequestMapping(value = "current", method = RequestMethod.POST) - public @ResponseBody - ResponseEntity> updateGuide(@RequestBody UserGuide guide, @ClaimedAuthorities(claims = {ADMIN}) Principal principal) throws Exception { - String fileName = this.environment.getProperty("userguide.path") + guide.getName(); - OutputStream os = new FileOutputStream(fileName); - os.write(guide.getHtml().getBytes()); - os.close(); - return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Updated").payload("Updated")); - } -} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ExternalReferencesController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ExternalReferencesController.java new file mode 100644 index 000000000..4c3b6ae37 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ExternalReferencesController.java @@ -0,0 +1,66 @@ +package eu.eudat.controllers.v2; + +import eu.eudat.controllers.BaseController; +import eu.eudat.data.query.items.item.funder.FunderCriteriaRequest; +import eu.eudat.data.query.items.item.project.ProjectCriteriaRequest; +import eu.eudat.logic.proxy.config.exceptions.HugeResultSet; +import eu.eudat.logic.proxy.config.exceptions.NoURLFound; +import eu.eudat.logic.services.ApiContext; +import eu.eudat.model.ExternalReference; +import eu.eudat.models.data.funder.Funder; +import eu.eudat.models.data.helpers.responses.ResponseItem; +import eu.eudat.models.data.project.Project; +import eu.eudat.models.data.security.Principal; +import eu.eudat.service.externalreferences.*; +import eu.eudat.types.ApiMessageCode; +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(path = {"/api/external-references"}) +public class ExternalReferencesController extends BaseController { + + private final FunderService funderService; + private final ExternalReferencesService externalReferencesService; + private final ProjectService projectService; + + @Autowired + public ExternalReferencesController( + ApiContext apiContext, + FunderService funderService, + ExternalReferencesService externalReferencesService, + ProjectService projectService + ) { + super(apiContext); + this.funderService = funderService; + this.externalReferencesService = externalReferencesService; + this.projectService = projectService; + } + + @PostMapping(path = {"funders"}, consumes = "application/json", produces = "application/json") + public @ResponseBody ResponseEntity>> getWithExternal(@RequestBody FunderCriteriaRequest funderCriteria, Principal principal) throws NoURLFound, InstantiationException, HugeResultSet, IllegalAccessException { + List dataTable = this.funderService.getCriteriaWithExternal(funderCriteria, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().payload(dataTable).status(ApiMessageCode.NO_MESSAGE)); + } + + @PostMapping(path = {"projects"}, consumes = "application/json", produces = "application/json") + public @ResponseBody + ResponseEntity>> getWithExternal(@RequestBody ProjectCriteriaRequest projectCriteria, Principal principal) throws NoURLFound, InstantiationException, HugeResultSet, IllegalAccessException { + List dataTable = this.projectService.getCriteriaWithExternal(projectCriteria, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().payload(dataTable).status(ApiMessageCode.NO_MESSAGE)); + } + + @GetMapping(path = {"{externalType"}, produces = "application/json") + public @ResponseBody ResponseEntity>> listExternalReferecnes(@RequestParam(value = "externalType") String externalType, @RequestParam(value = "query", required = false) String query, + @RequestParam(value = "type", required = false) String type, Principal principal + ) throws HugeResultSet, NoURLFound { + List externalReferences = this.externalReferencesService.getExternal(externalType, query, type, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem>().status(ApiMessageCode.NO_MESSAGE).payload(externalReferences)); + } + +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ExternalValidationController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ExternalValidationController.java new file mode 100644 index 000000000..6f5a288e3 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/ExternalValidationController.java @@ -0,0 +1,37 @@ +package eu.eudat.controllers.v2; + +import eu.eudat.controllers.BaseController; +import eu.eudat.logic.proxy.config.exceptions.HugeResultSet; +import eu.eudat.logic.proxy.config.exceptions.NoURLFound; +import eu.eudat.logic.services.ApiContext; +import eu.eudat.models.data.helpers.responses.ResponseItem; +import eu.eudat.models.data.security.Principal; +import eu.eudat.service.ValidationService; +import eu.eudat.types.ApiMessageCode; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@CrossOrigin +@RequestMapping(path = {"api/validation"}) +public class ExternalValidationController extends BaseController { + + private ValidationService validationService; + + @Autowired + public ExternalValidationController(ApiContext apiContext, ValidationService validationService) { + super(apiContext); + this.validationService = validationService; + } + + @GetMapping(path = {""}, produces = "application/json") + public @ResponseBody + ResponseEntity> validate( + @RequestParam(value = "query", required = false) String query, @RequestParam(value = "type", required = false) String type, Principal principal + ) throws HugeResultSet, NoURLFound { + Boolean isValid = this.validationService.validateIdentifier(query, type, principal); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().payload(isValid).status(ApiMessageCode.NO_MESSAGE)); + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/SupportiveMaterialController.java b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/SupportiveMaterialController.java new file mode 100644 index 000000000..0e060b594 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/controllers/v2/SupportiveMaterialController.java @@ -0,0 +1,71 @@ +package eu.eudat.controllers.v2; + +import eu.eudat.commons.enums.SupportiveMaterialFieldType; +import eu.eudat.logic.managers.MetricsManager; +import eu.eudat.logic.security.claims.ClaimedAuthorities; +import eu.eudat.model.persist.UserGuidePersist; +import eu.eudat.models.data.helpers.responses.ResponseItem; +import eu.eudat.models.data.security.Principal; +import eu.eudat.service.supportivematerial.SupportiveMaterialService; +import eu.eudat.types.ApiMessageCode; +import org.apache.commons.lang3.EnumUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Objects; +import java.util.stream.Stream; + +import static eu.eudat.types.Authorities.ADMIN; + +@RestController +@CrossOrigin +@RequestMapping(path = {"/api/material"}) +public class SupportiveMaterialController { + + private Environment environment; + private SupportiveMaterialService supportiveMaterialService; + + @Autowired + public SupportiveMaterialController(Environment environment, SupportiveMaterialService supportiveMaterialService, MetricsManager metricsManager) { + this.environment = environment; + this.supportiveMaterialService = supportiveMaterialService; + } + + @GetMapping("{lang}") + public ResponseEntity getMaterial(@PathVariable(name = "lang") String lang, String field) throws IOException { + if( !EnumUtils.isValidEnum(SupportiveMaterialFieldType.class, field)){ + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + try (Stream paths = Files.walk(Paths.get(Objects.requireNonNull(this.environment.getProperty(field +".path"))))) { + return this.supportiveMaterialService.getResponseEntity(lang, paths); + } + } + +// @PostMapping("userguide/current") +// public @ResponseBody +// ResponseEntity> updateGuide(@RequestBody UserGuidePersist guide, @ClaimedAuthorities(claims = {ADMIN}) Principal principal) throws IOException { +// String fileName = this.environment.getProperty("userguide.path") + guide.getName(); +// this.supportiveMaterialService.persist(guide, fileName); +// return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Updated").payload("Updated")); +// } + + @PostMapping("current") + public @ResponseBody + ResponseEntity> persist(@RequestBody UserGuidePersist guide, String field, @ClaimedAuthorities(claims = {ADMIN}) Principal principal) throws IOException { + if( !EnumUtils.isValidEnum(SupportiveMaterialFieldType.class, field)){ + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + String fileName = this.environment.getProperty(field+ ".path") + guide.getName(); + this.supportiveMaterialService.persist(guide, fileName); + return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem().status(ApiMessageCode.SUCCESS_MESSAGE).message("Updated").payload("Updated")); + } + + +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/DataRepositoryUrls.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/DataRepositoryUrls.java new file mode 100644 index 000000000..1ede1feaf --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/DataRepositoryUrls.java @@ -0,0 +1,41 @@ +package eu.eudat.logic.proxy.config.entitiesV2; + +import eu.eudat.proxy.config.FetchStrategy; +import eu.eudat.proxy.config.UrlConfiguration; +import eu.eudat.proxy.config.entities.GenericUrls; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlElementWrapper; +import jakarta.xml.bind.annotation.XmlRootElement; + +import java.io.Serializable; +import java.util.List; + +@XmlRootElement(name = "repositories") +public class DataRepositoryUrls extends GenericUrls implements Serializable { + + private static final long serialVersionUID = -5076364662014107275L; + + List urls; + FetchStrategy fetchMode; + + @Override + public List getUrls() { + return urls; + } + + @XmlElementWrapper + @XmlElement(name = "urlConfig") + public void setUrls(List urls) { + this.urls = urls; + } + + @Override + public FetchStrategy getFetchMode() { + return fetchMode; + } + + @XmlElement(name = "fetchMode") + public void setFetchMode(FetchStrategy fetchMode) { + this.fetchMode = fetchMode; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/ExternalUrlsBase.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/ExternalUrlsBase.java new file mode 100644 index 000000000..589efd336 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/ExternalUrlsBase.java @@ -0,0 +1,67 @@ +package eu.eudat.logic.proxy.config.entitiesV2; + + +public class ExternalUrlsBase { + + TaxonomyUrls taxonomyUrls; + + DataRepositoryUrls dataRepositoryUrls; + + JournalUrls journalUrls; + + LicenseUrls licenseUrls; + + PublicationUrls publicationUrls; + + PubRepositoryUrls pubRepositoryUrls; + + public TaxonomyUrls getTaxonomyUrls() { + return taxonomyUrls; + } + + public void setTaxonomyUrls(TaxonomyUrls taxonomyUrls) { + this.taxonomyUrls = taxonomyUrls; + } + + public DataRepositoryUrls getDataRepositoryUrls() { + return dataRepositoryUrls; + } + + public void setDataRepositoryUrls(DataRepositoryUrls dataRepositoryUrls) { + this.dataRepositoryUrls = dataRepositoryUrls; + } + + public JournalUrls getJournalUrls() { + return journalUrls; + } + + public void setJournalUrls(JournalUrls journalUrls) { + this.journalUrls = journalUrls; + } + + public LicenseUrls getLicenseUrls() { + return licenseUrls; + } + + public void setLicenseUrls(LicenseUrls licenseUrls) { + this.licenseUrls = licenseUrls; + } + + public PublicationUrls getPublicationUrls() { + return publicationUrls; + } + + public void setPublicationUrls(PublicationUrls publicationUrls) { + this.publicationUrls = publicationUrls; + } + + public PubRepositoryUrls getPubRepositoryUrls() { + return pubRepositoryUrls; + } + + public void setPubRepositoryUrls(PubRepositoryUrls pubRepositoryUrls) { + this.pubRepositoryUrls = pubRepositoryUrls; + } +} + + diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/JournalUrls.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/JournalUrls.java new file mode 100644 index 000000000..bfc3ac854 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/JournalUrls.java @@ -0,0 +1,41 @@ +package eu.eudat.logic.proxy.config.entitiesV2; + +import eu.eudat.proxy.config.FetchStrategy; +import eu.eudat.proxy.config.UrlConfiguration; +import eu.eudat.proxy.config.entities.GenericUrls; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlElementWrapper; +import jakarta.xml.bind.annotation.XmlRootElement; + +import java.io.Serializable; +import java.util.List; + +@XmlRootElement(name = "journal") +public class JournalUrls extends GenericUrls implements Serializable { + + private static final long serialVersionUID = -5076364662014107275L; + + List urls; + FetchStrategy fetchMode; + + @Override + public List getUrls() { + return urls; + } + + @XmlElementWrapper + @XmlElement(name = "urlConfig") + public void setUrls(List urls) { + this.urls = urls; + } + + @Override + public FetchStrategy getFetchMode() { + return fetchMode; + } + + @XmlElement(name = "fetchMode") + public void setFetchMode(FetchStrategy fetchMode) { + this.fetchMode = fetchMode; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/LicenseUrls.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/LicenseUrls.java new file mode 100644 index 000000000..32f7b1ec6 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/LicenseUrls.java @@ -0,0 +1,41 @@ +package eu.eudat.logic.proxy.config.entitiesV2; + +import eu.eudat.proxy.config.FetchStrategy; +import eu.eudat.proxy.config.UrlConfiguration; +import eu.eudat.proxy.config.entities.GenericUrls; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlElementWrapper; +import jakarta.xml.bind.annotation.XmlRootElement; + +import java.io.Serializable; +import java.util.List; + +@XmlRootElement(name = "licenses") +public class LicenseUrls extends GenericUrls implements Serializable { + + private static final long serialVersionUID = -5076364662014107275L; + + List urls; + FetchStrategy fetchMode; + + @Override + public List getUrls() { + return urls; + } + + @XmlElementWrapper + @XmlElement(name = "urlConfig") + public void setUrls(List urls) { + this.urls = urls; + } + + @Override + public FetchStrategy getFetchMode() { + return fetchMode; + } + + @XmlElement(name = "fetchMode") + public void setFetchMode(FetchStrategy fetchMode) { + this.fetchMode = fetchMode; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/PubRepositoryUrls.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/PubRepositoryUrls.java new file mode 100644 index 000000000..a0506d208 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/PubRepositoryUrls.java @@ -0,0 +1,41 @@ +package eu.eudat.logic.proxy.config.entitiesV2; + +import eu.eudat.proxy.config.FetchStrategy; +import eu.eudat.proxy.config.UrlConfiguration; +import eu.eudat.proxy.config.entities.GenericUrls; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlElementWrapper; +import jakarta.xml.bind.annotation.XmlRootElement; + +import java.io.Serializable; +import java.util.List; + +@XmlRootElement(name = "pubRepositories") +public class PubRepositoryUrls extends GenericUrls implements Serializable { + + private static final long serialVersionUID = -5076364662014107275L; + + List urls; + FetchStrategy fetchMode; + + @Override + public List getUrls() { + return urls; + } + + @XmlElementWrapper + @XmlElement(name = "urlConfig") + public void setUrls(List urls) { + this.urls = urls; + } + + @Override + public FetchStrategy getFetchMode() { + return fetchMode; + } + + @XmlElement(name = "fetchMode") + public void setFetchMode(FetchStrategy fetchMode) { + this.fetchMode = fetchMode; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/PublicationUrls.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/PublicationUrls.java new file mode 100644 index 000000000..c9209af9d --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/PublicationUrls.java @@ -0,0 +1,41 @@ +package eu.eudat.logic.proxy.config.entitiesV2; + +import eu.eudat.proxy.config.FetchStrategy; +import eu.eudat.proxy.config.UrlConfiguration; +import eu.eudat.proxy.config.entities.GenericUrls; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlElementWrapper; +import jakarta.xml.bind.annotation.XmlRootElement; + +import java.io.Serializable; +import java.util.List; + +@XmlRootElement(name = "publications") +public class PublicationUrls extends GenericUrls implements Serializable { + + private static final long serialVersionUID = -5076364662014107275L; + + List urls; + FetchStrategy fetchMode; + + @Override + public List getUrls() { + return urls; + } + + @XmlElementWrapper + @XmlElement(name = "urlConfig") + public void setUrls(List urls) { + this.urls = urls; + } + + @Override + public FetchStrategy getFetchMode() { + return fetchMode; + } + + @XmlElement(name = "fetchMode") + public void setFetchMode(FetchStrategy fetchMode) { + this.fetchMode = fetchMode; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/TaxonomyUrls.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/TaxonomyUrls.java new file mode 100644 index 000000000..d0e2cf03d --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/config/entitiesV2/TaxonomyUrls.java @@ -0,0 +1,41 @@ +package eu.eudat.logic.proxy.config.entitiesV2; + +import eu.eudat.proxy.config.FetchStrategy; +import eu.eudat.proxy.config.UrlConfiguration; +import eu.eudat.proxy.config.entities.GenericUrls; +import jakarta.xml.bind.annotation.XmlElement; +import jakarta.xml.bind.annotation.XmlElementWrapper; +import jakarta.xml.bind.annotation.XmlRootElement; + +import java.io.Serializable; +import java.util.List; + +@XmlRootElement(name = "taxonomies") +public class TaxonomyUrls extends GenericUrls implements Serializable { + + private static final long serialVersionUID = -5076364662014107275L; + + List urls; + FetchStrategy fetchMode; + + @Override + public List getUrls() { + return urls; + } + + @XmlElementWrapper + @XmlElement(name = "urlConfig") + public void setUrls(List urls) { + this.urls = urls; + } + + @Override + public FetchStrategy getFetchMode() { + return fetchMode; + } + + @XmlElement(name = "fetchMode") + public void setFetchMode(FetchStrategy fetchMode) { + this.fetchMode = fetchMode; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/fetching/RemoteFetcher.java b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/fetching/RemoteFetcher.java index 86a9742f9..212d8f4ad 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/fetching/RemoteFetcher.java +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/proxy/fetching/RemoteFetcher.java @@ -50,6 +50,56 @@ public class RemoteFetcher { ).clientConnector(new ReactorClientHttpConnector(HttpClient.create().followRedirect(true))).build(); } + //@Cacheable(value = "tempexternalType", keyGenerator = "externalUrlsKeyGenerator") + public List> get(String externalType, ExternalUrlCriteria externalUrlCriteria, String key) throws eu.eudat.proxy.config.exceptions.NoURLFound, eu.eudat.proxy.config.exceptions.HugeResultSet { + List urlConfigs = null; + FetchStrategy fetchStrategy = null; + switch (externalType){ + case "taxonomies": + urlConfigs = key != null && !key.isEmpty() ? configLoader.getExternalUrls().getTaxonomies().getUrls().stream().filter(item -> item.getKey().equals(key)).collect(Collectors.toList()) + : configLoader.getExternalUrls().getTaxonomies().getUrls(); + fetchStrategy = configLoader.getExternalUrls().getTaxonomies().getFetchMode(); + break; + case "licenses": + urlConfigs = key != null && !key.isEmpty() ? configLoader.getExternalUrls().getLicenses().getUrls().stream().filter(item -> item.getKey().equals(key)).collect(Collectors.toList()) + : configLoader.getExternalUrls().getLicenses().getUrls(); + fetchStrategy = configLoader.getExternalUrls().getLicenses().getFetchMode(); + break; + case "publications": + urlConfigs = key != null && !key.isEmpty() ? configLoader.getExternalUrls().getPublications().getUrls().stream().filter(item -> item.getKey().equals(key)).collect(Collectors.toList()) + : configLoader.getExternalUrls().getPublications().getUrls(); + fetchStrategy = configLoader.getExternalUrls().getPublications().getFetchMode(); + break; + case "journals": + urlConfigs = key != null && !key.isEmpty() ? configLoader.getExternalUrls().getJournals().getUrls().stream().filter(item -> item.getKey().equals(key)).collect(Collectors.toList()) + : configLoader.getExternalUrls().getJournals().getUrls(); + fetchStrategy = configLoader.getExternalUrls().getJournals().getFetchMode(); + break; + case "pubRepositories": + urlConfigs = key != null && !key.isEmpty() ? configLoader.getExternalUrls().getPubRepositories().getUrls().stream().filter(item -> item.getKey().equals(key)).collect(Collectors.toList()) + : configLoader.getExternalUrls().getPubRepositories().getUrls(); + fetchStrategy = configLoader.getExternalUrls().getPubRepositories().getFetchMode(); + break; + case "dataRepositories": + urlConfigs = key != null && !key.isEmpty() ? configLoader.getExternalUrls().getRepositories().getUrls().stream().filter(item -> item.getKey().equals(key)).collect(Collectors.toList()) + : configLoader.getExternalUrls().getRepositories().getUrls(); + fetchStrategy = configLoader.getExternalUrls().getRepositories().getFetchMode(); + break; + case "registries": + urlConfigs = key != null && !key.isEmpty() ? configLoader.getExternalUrls().getRegistries().getUrls().stream().filter(item -> item.getKey().equals(key)).collect(Collectors.toList()) + : configLoader.getExternalUrls().getRegistries().getUrls(); + fetchStrategy = configLoader.getExternalUrls().getRegistries().getFetchMode(); + break; + case "services": + urlConfigs = key != null && !key.isEmpty() ? configLoader.getExternalUrls().getServices().getUrls().stream().filter(item -> item.getKey().equals(key)).collect(Collectors.toList()) + : configLoader.getExternalUrls().getServices().getUrls(); + fetchStrategy = configLoader.getExternalUrls().getServices().getFetchMode(); + break; + } + + return getAll(urlConfigs, fetchStrategy, externalUrlCriteria); + } + @Cacheable(value = "repositories", keyGenerator = "externalUrlsKeyGenerator") public List> getRepositories(ExternalUrlCriteria externalUrlCriteria, String key) throws NoURLFound, HugeResultSet { List urlConfigs = diff --git a/dmp-backend/web/src/main/java/eu/eudat/publicapi/configurations/SwaggerConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/publicapi/configurations/SwaggerConfiguration.java index f3284dfb4..232794013 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/publicapi/configurations/SwaggerConfiguration.java +++ b/dmp-backend/web/src/main/java/eu/eudat/publicapi/configurations/SwaggerConfiguration.java @@ -1,32 +1,32 @@ package eu.eudat.publicapi.configurations; -import io.swagger.v3.oas.models.OpenAPI; -import io.swagger.v3.oas.models.info.Contact; -import io.swagger.v3.oas.models.info.Info; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.env.Environment; - -@Configuration -public class SwaggerConfiguration { - - // private static final TypeResolver resolver = new TypeResolver(); - - @Autowired - private Environment environment; - - @Bean - public OpenAPI ArgosOpenApi() { - return new OpenAPI().info(apiInfo()); - } - - private Info apiInfo() { - return new Info() - .title("OpenDMP public API") - .description("Argos public API.") - .version("1.0") - .termsOfService("https://argos.openaire.eu/terms-and-conditions") - .contact(new Contact().name("Argos").url("https://argos.openaire.eu/").email("argos@openaire.eu ")); - } -} +//import io.swagger.v3.oas.models.OpenAPI; +//import io.swagger.v3.oas.models.info.Contact; +//import io.swagger.v3.oas.models.info.Info; +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.context.annotation.Bean; +//import org.springframework.context.annotation.Configuration; +//import org.springframework.core.env.Environment; +// +//@Configuration +//public class SwaggerConfiguration { +// +// // private static final TypeResolver resolver = new TypeResolver(); +// +// @Autowired +// private Environment environment; +// +// @Bean +// public OpenAPI ArgosOpenApi() { +// return new OpenAPI().info(apiInfo()); +// } +// +// private Info apiInfo() { +// return new Info() +// .title("OpenDMP public API") +// .description("Argos public API.") +// .version("1.0") +// .termsOfService("https://argos.openaire.eu/terms-and-conditions") +// .contact(new Contact().name("Argos").url("https://argos.openaire.eu/").email("argos@openaire.eu ")); +// } +//} diff --git a/dmp-backend/web/src/main/resources/config/cache.yml b/dmp-backend/web/src/main/resources/config/cache.yml index 25a8f2c1f..0d331706c 100644 --- a/dmp-backend/web/src/main/resources/config/cache.yml +++ b/dmp-backend/web/src/main/resources/config/cache.yml @@ -26,6 +26,14 @@ cache: expireAfterWriteMinutes: 10 expireAfterAccessMinutes: 10 refreshAfterWriteMinutes: 10 + - names: [ "externalReference" ] + allowNullValues: true + initialCapacity: 100 + maximumSize: 500 + enableRecordStats: false + expireAfterWriteMinutes: 10 + expireAfterAccessMinutes: 10 + refreshAfterWriteMinutes: 10 mapCaches: apiKey: name: apikey @@ -35,4 +43,7 @@ cache: keyPattern: user_by_subject_$subject$:v0 supportiveMaterial: name: supportiveMaterial - keyPattern: supportive_material_$material$:v0 \ No newline at end of file + keyPattern: supportive_material_$material$:v0 + externalReference: + name: externalReference + keyPattern: external_reference_$type$_$criteria$:v0 \ No newline at end of file diff --git a/dmp-backend/web/src/main/resources/externalUrls/funders.xml b/dmp-backend/web/src/main/resources/externalUrls/funders.xml new file mode 100644 index 000000000..f7b1873c7 --- /dev/null +++ b/dmp-backend/web/src/main/resources/externalUrls/funders.xml @@ -0,0 +1,215 @@ + + + + + + openaire + + 1 + External + https://services.openaire.eu/search/v2/api/publications?&refine=true&fields=relfunder&page={page}&size=0&format=json + 0 + application/json; charset=utf-8 + + $['refineResults']['relfunder'][*] + + 'name' + 'id' + 'count' + + + local + + + + + cristin + + 1 + External + https://eestore.paas2.uninett.no/api/projectrepo/?search={like}&page={page}&size={pageSize} + 1 + application/vnd.api+json; charset=utf-8 + + $['data'][*]['attributes'] + + 'pid' + 'name' + 'uri' + 'description' + + + $['meta']['pagination']['page','pages','count'] + + + crossref + + 1 + External + https://api.crossref.org/funders?query={like}&rows={pageSize} + application/json; charset=utf-8 + + $['message']['items'][*] + + 'name' + 'id' + 'count' + + + + + + + FIRST + diff --git a/dmp-backend/web/src/main/resources/externalUrls/journals.xml b/dmp-backend/web/src/main/resources/externalUrls/journals.xml new file mode 100644 index 000000000..7bf785abd --- /dev/null +++ b/dmp-backend/web/src/main/resources/externalUrls/journals.xml @@ -0,0 +1,27 @@ + + + + + + openaire + + 1 + External + POST + https://services.openaire.eu/openaire/ds/searchdetails/{page}/{pageSize}?requestSortBy=id&order=ASCENDING + 0 + application/json + {"officialname": "{like}", "typology":"journal"} + + $['datasourceInfo'][*] + + 'id' + 'officialname' + 'count' + + + $['meta']['pagination']['page','pages','count'] + + + FIRST + \ No newline at end of file diff --git a/dmp-backend/web/src/main/resources/externalUrls/licenses.xml b/dmp-backend/web/src/main/resources/externalUrls/licenses.xml new file mode 100644 index 000000000..3af20a4d4 --- /dev/null +++ b/dmp-backend/web/src/main/resources/externalUrls/licenses.xml @@ -0,0 +1,25 @@ + + + + + + opendefinition + + 1 + External + https://licenses.opendefinition.org/licenses/groups/all.json + 1 + application/vnd.api+json; charset=utf-8 + + $[*] + + 'id' + 'title' + 'url' + 'maintainer' + + + + + FIRST + \ No newline at end of file diff --git a/dmp-backend/web/src/main/resources/externalUrls/projects.xml b/dmp-backend/web/src/main/resources/externalUrls/projects.xml new file mode 100644 index 000000000..d5bf6d090 --- /dev/null +++ b/dmp-backend/web/src/main/resources/externalUrls/projects.xml @@ -0,0 +1,80 @@ + + + + + + + FIRST + \ No newline at end of file diff --git a/dmp-backend/web/src/main/resources/externalUrls/pub-repositories.xml b/dmp-backend/web/src/main/resources/externalUrls/pub-repositories.xml new file mode 100644 index 000000000..64caea2df --- /dev/null +++ b/dmp-backend/web/src/main/resources/externalUrls/pub-repositories.xml @@ -0,0 +1,67 @@ + + + + + + openaire + + 1 + External + POST + https://services.openaire.eu/openaire/ds/searchdetails/{page}/{pageSize}?requestSortBy=id&order=ASCENDING + 0 + application/json + {"officialname": "{like}", "typology":"pubsrepository::institutional"} + + $['datasourceInfo'][*] + + 'id' + 'officialname' + 'count' + + + $['meta']['pagination']['page','pages','count'] + + + openaire + + 1 + External + POST + https://services.openaire.eu/openaire/ds/searchdetails/{page}/{pageSize}?requestSortBy=id&order=ASCENDING + 0 + application/json + {"officialname": "{like}", "typology":"pubsrepository::thematic"} + + $['datasourceInfo'][*] + + 'id' + 'officialname' + 'count' + + + $['meta']['pagination']['page','pages','count'] + + + openaire + + 1 + External + POST + https://services.openaire.eu/openaire/ds/searchdetails/{page}/{pageSize}?requestSortBy=id&order=ASCENDING + 0 + application/json + {"officialname": "{like}", "typology":"pubsrepository::unknown"} + + $['datasourceInfo'][*] + + 'id' + 'officialname' + 'count' + + + $['meta']['pagination']['page','pages','count'] + + + FIRST + \ No newline at end of file diff --git a/dmp-backend/web/src/main/resources/externalUrls/publications.xml b/dmp-backend/web/src/main/resources/externalUrls/publications.xml new file mode 100644 index 000000000..b4c679490 --- /dev/null +++ b/dmp-backend/web/src/main/resources/externalUrls/publications.xml @@ -0,0 +1,44 @@ + + + + + + openaire + + 1 + External + https://services.openaire.eu/search/v2/api/resources?query=oaftype exact result and {query}&page={page}&size={pageSize}&format=json + 0 + application/json;charset=UTF-8 + + + 0 + (10[.][0-9]{4,}(?:[.][0-9]+)*\/(?:(?!["&\'<>])[[:graph:]])+) + (pidclassid exact "doi" and pid="{like}") + + + 1 + (10[.][0-9]{4,}(?:[.][0-9]+)*\/(?:(?!["&\'<>])\S)+) + (pidclassid exact "doi" and pid="{like}") + + + 2 + .+ + {like} + + + + $['results'][*]['result']['metadata']['oaf:entity']['oaf:result'] + + 'originalId' + pid.content + pid.classid + 'title' + 'count' + + + $['meta']['pagination']['page','pages','count'] + + + FIRST + \ No newline at end of file diff --git a/dmp-backend/web/src/main/resources/externalUrls/repositories.xml b/dmp-backend/web/src/main/resources/externalUrls/repositories.xml new file mode 100644 index 000000000..10ac938d9 --- /dev/null +++ b/dmp-backend/web/src/main/resources/externalUrls/repositories.xml @@ -0,0 +1,124 @@ + + + + + + + openairealt2 + + 1 + External + POST + https://services.openaire.eu/openaire/ds/searchdetails/{page}/{pageSize}?requestSortBy=id&order=ASCENDING + + 0 + application/json + {"officialname": "{like}", "typology":"data"} + + $['datasourceInfo'][*] + + 'id' + 'officialname' + 'count' + + + $['meta']['pagination']['page','pages','count'] + + + + + + FIRST + \ No newline at end of file diff --git a/dmp-backend/web/src/main/resources/externalUrls/taxonomies.xml b/dmp-backend/web/src/main/resources/externalUrls/taxonomies.xml new file mode 100644 index 000000000..735c9f661 --- /dev/null +++ b/dmp-backend/web/src/main/resources/externalUrls/taxonomies.xml @@ -0,0 +1,25 @@ + + + + + + taxonomy + + 1 + External + https://eestore.paas2.uninett.no/api/taxonomy/ + 0 + application/vnd.api+json + + $['data'][*]['attributes'] + + 'pid' + 'name' + 'count' + + + + + + ALL + \ No newline at end of file diff --git a/dmp-backend/web/src/main/resources/externalUrls/validators.xml b/dmp-backend/web/src/main/resources/externalUrls/validators.xml new file mode 100644 index 000000000..6e52a39b6 --- /dev/null +++ b/dmp-backend/web/src/main/resources/externalUrls/validators.xml @@ -0,0 +1,26 @@ + + + + + + zenodo + + 1 + External + https://sandbox.zenodo.org/api/records/?page={page}&size={pageSize}&q="{like}" + 1 + application/json + + $[*] + + 'conceptrecid' + 'conceptdoi' + 'doi' + 'created' + + + $['hits']['total'] + + + FIRST + \ No newline at end of file diff --git a/dmp-frontend/src/app/core/common/enum/supportive-material-field-type.ts b/dmp-frontend/src/app/core/common/enum/supportive-material-field-type.ts new file mode 100644 index 000000000..8385c9380 --- /dev/null +++ b/dmp-frontend/src/app/core/common/enum/supportive-material-field-type.ts @@ -0,0 +1,7 @@ +export enum SupportiveMaterialFieldType { + faq = 'faq', + about = 'about', + glossary = 'glossary', + termsofservice = 'termsofservice', + userguide = 'userguide' +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/core-service.module.ts b/dmp-frontend/src/app/core/core-service.module.ts index 727b40702..59beab191 100644 --- a/dmp-frontend/src/app/core/core-service.module.ts +++ b/dmp-frontend/src/app/core/core-service.module.ts @@ -54,11 +54,12 @@ import { TermsOfServiceService } from './services/terms-of-service/terms-of-serv import { UnlinkAccountEmailConfirmationService } from './services/unlink-account-email-confirmation/unlink-account-email-confirmation.service'; import { DescriptionTemplateTypeService } from './services/description-template-type/description-template-type.service'; import { BaseHttpV2Service } from './services/http/base-http-v2.service'; -import { KeycloakService } from 'keycloak-angular'; +//import { KeycloakService } from 'keycloak-angular'; import { PrincipalService } from './services/http/principal.service'; import { InterceptorType } from '@common/http/interceptors/interceptor-type'; import { BaseHttpParams } from '@common/http/base-http-params'; import { from } from 'rxjs'; +import { SupportiveMaterialService } from './services/supportive-material/supportive-material.service'; // // // This is shared module that provides all the services. Its imported only once on the AppModule. @@ -126,6 +127,7 @@ export class CoreServiceModule { FaqService, GlossaryService, TermsOfServiceService, + SupportiveMaterialService, CurrencyService, MergeEmailConfirmationService, UnlinkAccountEmailConfirmationService, diff --git a/dmp-frontend/src/app/core/services/faq/faq.service.ts b/dmp-frontend/src/app/core/services/faq/faq.service.ts index c59cfe9cd..f5408871c 100644 --- a/dmp-frontend/src/app/core/services/faq/faq.service.ts +++ b/dmp-frontend/src/app/core/services/faq/faq.service.ts @@ -11,11 +11,11 @@ export class FaqService { private http: HttpClient, private configurationService: ConfigurationService ) { - this.faqUrl = `${configurationService.server}material/faq`; + this.faqUrl = `${configurationService.server}material`; } - public getFaq(lang: string): Observable> { - return this.http.get(`${this.faqUrl}/${lang}`, { responseType: 'blob', observe: 'response', headers: {'Content-type': 'text/html', + public getFaq(lang: string, field: string): Observable> { + return this.http.get(`${this.faqUrl}/${lang}`, {params: {field}, responseType: 'blob', observe: 'response', headers: {'Content-type': 'text/html', 'Accept': 'text/html', 'Access-Control-Allow-Origin': this.configurationService.app, 'Access-Control-Allow-Credentials': 'true'} }); diff --git a/dmp-frontend/src/app/core/services/supportive-material/supportive-material.service.ts b/dmp-frontend/src/app/core/services/supportive-material/supportive-material.service.ts new file mode 100644 index 000000000..803e0e1a9 --- /dev/null +++ b/dmp-frontend/src/app/core/services/supportive-material/supportive-material.service.ts @@ -0,0 +1,27 @@ +import { Injectable } from "@angular/core"; +import { ConfigurationService } from "../configuration/configuration.service"; +import { HttpClient, HttpResponse } from "@angular/common/http"; +import { Observable } from "rxjs"; + +@Injectable() +export class SupportiveMaterialService{ + private baseUrl : string; + + constructor( + private http: HttpClient, + private configurationService: ConfigurationService + ) { + this.baseUrl = `${configurationService.server}material`; + } + + public getMaterial(lang: string, field: string): Observable> { + return this.http.get(`${this.baseUrl}/${lang}`, {params: {field}, responseType: 'blob', observe: 'response', headers: {'Content-type': 'text/html', + 'Accept': 'text/html', + 'Access-Control-Allow-Origin': this.configurationService.app, + 'Access-Control-Allow-Credentials': 'true'} }); + } + + public persist(data: any, field: string): Observable { + return this.http.post(`${this.baseUrl}/current`, data, {params: {field}}); + } +} \ No newline at end of file diff --git a/dmp-frontend/src/app/core/services/user-guide/user-guide.service.ts b/dmp-frontend/src/app/core/services/user-guide/user-guide.service.ts index 206e2a70d..4ad254f71 100644 --- a/dmp-frontend/src/app/core/services/user-guide/user-guide.service.ts +++ b/dmp-frontend/src/app/core/services/user-guide/user-guide.service.ts @@ -16,7 +16,7 @@ export class UserGuideService { private baseHttp: BaseHttpService, private configurationService: ConfigurationService ) { - this.userGuideUrl = `${configurationService.server}userguide`; + this.userGuideUrl = `${configurationService.server}material/userguide`; } public getUserGuide(lang: string): Observable> { diff --git a/dmp-frontend/src/app/ui/about/about.component.ts b/dmp-frontend/src/app/ui/about/about.component.ts index ff9740a7b..b89c0ae40 100644 --- a/dmp-frontend/src/app/ui/about/about.component.ts +++ b/dmp-frontend/src/app/ui/about/about.component.ts @@ -1,9 +1,10 @@ import { Component, OnInit } from '@angular/core'; import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; import { Router } from '@angular/router'; -import { AboutService } from '@app/core/services/about/about.service'; +import { SupportiveMaterialFieldType } from '@app/core/common/enum/supportive-material-field-type'; import { LanguageService } from '@app/core/services/language/language.service'; import { MatomoService } from '@app/core/services/matomo/matomo-service'; +import { SupportiveMaterialService } from '@app/core/services/supportive-material/supportive-material.service'; import { BaseComponent } from '@common/base/base.component'; import { TranslateService, LangChangeEvent } from '@ngx-translate/core'; import { takeUntil } from 'rxjs/operators'; @@ -19,7 +20,7 @@ export class AboutComponent extends BaseComponent implements OnInit { sanitizedGuideUrl: any; constructor( - private aboutService: AboutService, + private supportiveMaterialService: SupportiveMaterialService, private sanitizer: DomSanitizer, private languageService: LanguageService, private matomoService: MatomoService, @@ -32,7 +33,7 @@ export class AboutComponent extends BaseComponent implements OnInit { this.translate.onLangChange.subscribe((event: LangChangeEvent) => { this.router.navigate(['/reload'], { skipLocationChange: true }).then(() => this.router.navigate(['/about'])); }); - this.aboutService.getAbout(this.languageService.getCurrentLanguage()) + this.supportiveMaterialService.getMaterial(this.languageService.getCurrentLanguage(), SupportiveMaterialFieldType.about) .pipe(takeUntil(this._destroyed)) .subscribe(response => { const blob = new Blob([response.body], { type: 'text/html' }); diff --git a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/auto-complete-single-data.ts b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/auto-complete-single-data.ts index 4923a0752..e84fd4e1d 100644 --- a/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/auto-complete-single-data.ts +++ b/dmp-frontend/src/app/ui/admin/dataset-profile/admin/field-data/auto-complete-single-data.ts @@ -3,7 +3,7 @@ import { DatasetProfileComboBoxType } from '@app/core/common/enum/dataset-profil import { FieldDataOptionEditorModel } from './field-data-option-editor-model'; import { UntypedFormGroup, Validators } from '@angular/forms'; import { AutoCompleteFieldData, AutoCompleteSingleData } from '@app/core/model/dataset-profile-definition/field-data/field-data'; -import { AuthFieldEditorModel } from './auto-complete-auth-field-data.model'; +//import { AuthFieldEditorModel } from './auto-complete-auth-field-data.model'; export class AutoCompleteSingleDataEditorModel extends FieldDataEditorModel { @@ -14,7 +14,7 @@ export class AutoCompleteSingleDataEditorModel extends FieldDataEditorModel = []): UntypedFormGroup { @@ -27,7 +27,7 @@ export class AutoCompleteSingleDataEditorModel extends FieldDataEditorModel { const blob = new Blob([response.body], { type: 'text/html' }); diff --git a/dmp-frontend/src/app/ui/glossary/glossary-content/glossary-content.component.ts b/dmp-frontend/src/app/ui/glossary/glossary-content/glossary-content.component.ts index e4deba043..ba753ecb7 100644 --- a/dmp-frontend/src/app/ui/glossary/glossary-content/glossary-content.component.ts +++ b/dmp-frontend/src/app/ui/glossary/glossary-content/glossary-content.component.ts @@ -1,9 +1,10 @@ import { Component, OnInit, Input } from '@angular/core'; import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; import { Router } from '@angular/router'; -import { GlossaryService } from '@app/core/services/glossary/glossary.service'; +import { SupportiveMaterialFieldType } from '@app/core/common/enum/supportive-material-field-type'; import { LanguageService } from '@app/core/services/language/language.service'; import { MatomoService } from '@app/core/services/matomo/matomo-service'; +import { SupportiveMaterialService } from '@app/core/services/supportive-material/supportive-material.service'; import { BaseComponent } from '@common/base/base.component'; import { LangChangeEvent, TranslateService } from '@ngx-translate/core'; import { takeUntil } from 'rxjs/operators'; @@ -21,7 +22,7 @@ export class GlossaryContentComponent extends BaseComponent implements OnInit { sanitizedGuideUrl: any; constructor( - private glossaryService: GlossaryService, + private supportiveMaterialService: SupportiveMaterialService, private sanitizer: DomSanitizer, private languageService: LanguageService, private matomoService: MatomoService, @@ -35,7 +36,7 @@ export class GlossaryContentComponent extends BaseComponent implements OnInit { this.router.navigate(['/reload'], { skipLocationChange: true }).then(() => this.router.navigate(['/glossary'])); }); - this.glossaryService.getGlossary(this.languageService.getCurrentLanguage()) + this.supportiveMaterialService.getMaterial(this.languageService.getCurrentLanguage(), SupportiveMaterialFieldType.glossary) .pipe(takeUntil(this._destroyed)) .subscribe(response => { const blob = new Blob([response.body], { type: 'text/html' }); diff --git a/dmp-frontend/src/app/ui/sidebar/sidebar-footer/terms/terms.component.ts b/dmp-frontend/src/app/ui/sidebar/sidebar-footer/terms/terms.component.ts index ee83c5e10..b022de297 100644 --- a/dmp-frontend/src/app/ui/sidebar/sidebar-footer/terms/terms.component.ts +++ b/dmp-frontend/src/app/ui/sidebar/sidebar-footer/terms/terms.component.ts @@ -1,9 +1,10 @@ import { Component, OnInit } from '@angular/core'; import { SafeResourceUrl, DomSanitizer } from '@angular/platform-browser'; import { Router } from '@angular/router'; +import { SupportiveMaterialFieldType } from '@app/core/common/enum/supportive-material-field-type'; import { LanguageService } from '@app/core/services/language/language.service'; import { MatomoService } from '@app/core/services/matomo/matomo-service'; -import { TermsOfServiceService } from '@app/core/services/terms-of-service/terms-of-service.service'; +import { SupportiveMaterialService } from '@app/core/services/supportive-material/supportive-material.service'; import { BaseComponent } from '@common/base/base.component'; import { TranslateService, LangChangeEvent } from '@ngx-translate/core'; import { takeUntil } from 'rxjs/operators'; @@ -19,7 +20,7 @@ export class TermsComponent extends BaseComponent implements OnInit { sanitizedGuideUrl: any; constructor( - private termsService: TermsOfServiceService, + private supportiveMaterialService: SupportiveMaterialService, private sanitizer: DomSanitizer, private languageService: LanguageService, private matomoService: MatomoService, @@ -32,7 +33,7 @@ export class TermsComponent extends BaseComponent implements OnInit { this.translate.onLangChange.subscribe((event: LangChangeEvent) => { this.router.navigate(['/reload'], { skipLocationChange: true }).then(() => this.router.navigate(['/terms-and-conditions'])); }); - this.termsService.getTermsOfService(this.languageService.getCurrentLanguage()) + this.supportiveMaterialService.getMaterial(this.languageService.getCurrentLanguage(), SupportiveMaterialFieldType.termsofservice) .pipe(takeUntil(this._destroyed)) .subscribe(response => { const blob = new Blob([response.body], { type: 'text/html' }); diff --git a/dmp-frontend/src/app/ui/user-guide-editor/user-guide-editor.component.ts b/dmp-frontend/src/app/ui/user-guide-editor/user-guide-editor.component.ts index 88ac72ce1..3d50a7caf 100644 --- a/dmp-frontend/src/app/ui/user-guide-editor/user-guide-editor.component.ts +++ b/dmp-frontend/src/app/ui/user-guide-editor/user-guide-editor.component.ts @@ -1,7 +1,6 @@ import { Component, OnInit } from '@angular/core'; import { UntypedFormGroup, UntypedFormBuilder } from '@angular/forms'; import { BaseComponent } from '@common/base/base.component'; -import { UserGuideService } from '@app/core/services/user-guide/user-guide.service'; import { takeUntil } from 'rxjs/operators'; import { UiNotificationService, SnackBarNotificationLevel } from '@app/core/services/notification/ui-notification-service'; import { TranslateService } from '@ngx-translate/core'; @@ -13,6 +12,8 @@ import { AuthService } from '@app/core/services/auth/auth.service'; import { LanguageService } from '@app/core/services/language/language.service'; import { MatomoService } from '@app/core/services/matomo/matomo-service'; import { HttpClient } from '@angular/common/http'; +import { SupportiveMaterialService } from '@app/core/services/supportive-material/supportive-material.service'; +import { SupportiveMaterialFieldType } from '@app/core/common/enum/supportive-material-field-type'; @Component({ selector: 'app-user-guide-editor', @@ -23,7 +24,7 @@ export class UserGuideEditorComponent extends BaseComponent implements OnInit { public formGroup: UntypedFormGroup; private formBuilder: UntypedFormBuilder; - constructor(private userGuideService: UserGuideService, + constructor(private supportiveMaterialService: SupportiveMaterialService, private uiNotificationService: UiNotificationService, private translate: TranslateService, private router: Router, @@ -40,7 +41,7 @@ export class UserGuideEditorComponent extends BaseComponent implements OnInit { name: [''], html: [''] }); - this.userGuideService.getUserGuide(this.languageService.getCurrentLanguage()).pipe(takeUntil(this._destroyed)).subscribe(data => { + this.supportiveMaterialService.getMaterial(this.languageService.getCurrentLanguage(), SupportiveMaterialFieldType.userguide).pipe(takeUntil(this._destroyed)).subscribe(data => { const contentDispositionHeader = data.headers.get('Content-Disposition'); const filename = contentDispositionHeader.split(';')[1].trim().split('=')[1].replace(/"/g, ''); @@ -76,7 +77,7 @@ export class UserGuideEditorComponent extends BaseComponent implements OnInit { let result = this.parseText(this.formGroup.get('html').value); //result = result.replace(/href="#/g, 'class="href" path="'); this.formGroup.get('html').patchValue(result); - this.userGuideService.updateUserGuide(this.formGroup.value).pipe(takeUntil(this._destroyed)) + this.supportiveMaterialService.persist(this.formGroup.value, "userguide").pipe(takeUntil(this._destroyed)) .subscribe( complete => { this.onCallbackSuccess(complete); diff --git a/dmp-frontend/src/app/ui/user-guide/user-guide-content/user-guide-content.component.ts b/dmp-frontend/src/app/ui/user-guide/user-guide-content/user-guide-content.component.ts index 5555a9f42..1b21b1092 100644 --- a/dmp-frontend/src/app/ui/user-guide/user-guide-content/user-guide-content.component.ts +++ b/dmp-frontend/src/app/ui/user-guide/user-guide-content/user-guide-content.component.ts @@ -2,10 +2,11 @@ import { HttpClient } from '@angular/common/http'; import { Component, ElementRef, OnInit, ViewChild } from '@angular/core'; import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'; import { Router } from '@angular/router'; +import { SupportiveMaterialFieldType } from '@app/core/common/enum/supportive-material-field-type'; import { ConfigurationService } from '@app/core/services/configuration/configuration.service'; import { LanguageService } from '@app/core/services/language/language.service'; import { MatomoService } from '@app/core/services/matomo/matomo-service'; -import { UserGuideService } from '@app/core/services/user-guide/user-guide.service'; +import { SupportiveMaterialService } from '@app/core/services/supportive-material/supportive-material.service'; import { BaseComponent } from '@common/base/base.component'; import { LangChangeEvent, TranslateService } from '@ngx-translate/core'; import { interval, Subject } from 'rxjs'; @@ -30,7 +31,7 @@ export class UserGuideContentComponent extends BaseComponent implements OnInit { @ViewChild('guide') guide: ElementRef; constructor( - private userGuideService: UserGuideService, + private supportiveMaterialService: SupportiveMaterialService, private sanitizer: DomSanitizer, private languageService: LanguageService, private httpClient: HttpClient, @@ -50,7 +51,7 @@ export class UserGuideContentComponent extends BaseComponent implements OnInit { this.translate.onLangChange.subscribe((event: LangChangeEvent) => { this.router.navigate(['/reload'], { skipLocationChange: true }).then(() => this.router.navigate(['/user-guide'])); }); - this.userGuideService.getUserGuide(this.languageService.getCurrentLanguage()) + this.supportiveMaterialService.getMaterial(this.languageService.getCurrentLanguage(), SupportiveMaterialFieldType.userguide) .pipe(takeUntil(this._destroyed)) .subscribe(response => { const blob = new Blob([response.body], { type: 'text/html' }); diff --git a/dmp-frontend/src/assets/config/config.json b/dmp-frontend/src/assets/config/config.json index aa1530c15..1f88e12a3 100644 --- a/dmp-frontend/src/assets/config/config.json +++ b/dmp-frontend/src/assets/config/config.json @@ -52,19 +52,51 @@ ], "keycloak": { "enabled": true, - "address": null, - "realm": null, + "address": "http://dev03.local.cite.gr:60201/auth", + "realm": "dmp-development", "flow": "standard", - "clientId": null, + "clientId": "dmp_webapp", "silentCheckSsoRedirectUri": "http://localhost:4200/assets/silent-check-sso.html", - "scope": "openid profile email address phone", + "scope": "openid profile email address phone dmp_web", "clientSecret": null, "grantType": "code" }, - "zenodoConfiguration": { - "clientId": "", - "oauthUrl": "https://sandbox.zenodo.org/oauth/authorize", - "redirectUri": "http://localhost:4200/login/external/zenodo" + "loginProviders": { + "enabled": [1, 2, 3, 4, 5, 6, 7, 8], + "facebookConfiguration": { "clientId": "" }, + "googleConfiguration": { "clientId": "524432312250-sc9qsmtmbvlv05r44onl6l93ia3k9deo.apps.googleusercontent.com" }, + "linkedInConfiguration": { + "clientId": "", + "oauthUrl": "https://www.linkedin.com/oauth/v2/authorization", + "redirectUri": "http://localhost:4200/login/linkedin", + "state": "987654321" + }, + "twitterConfiguration": { + "clientId": "", + "oauthUrl": "https://api.twitter.com/oauth/authenticate" + }, + "b2accessConfiguration": { + "clientId": "", + "oauthUrl": "https://b2access-integration.fz-juelich.de:443/oauth2-as/oauth2-authz", + "redirectUri": "http://localhost:4200/api/oauth/authorized/b2access", + "state": "" + }, + "orcidConfiguration": { + "clientId": "", + "oauthUrl": "https://orcid.org/oauth/authorize", + "redirectUri": "http://localhost:4200/login/external/orcid" + }, + "openAireConfiguration": { + "clientId": "", + "oauthUrl": "", + "redirectUri": "", + "state": "987654321" + }, + "zenodoConfiguration": { + "clientId": "", + "oauthUrl": "https://sandbox.zenodo.org/oauth/authorize", + "redirectUri": "http://localhost:4200/login/external/zenodo" + } }, "logging": { "enabled": true,