Merge branch 'dmp-refactoring' of https://code-repo.d4science.org/MaDgiK-CITE/argos into dmp-refactoring

This commit is contained in:
Sofia Papacharalampous 2024-05-10 15:19:23 +03:00
commit 2b1bc2a5ce
16 changed files with 267 additions and 50 deletions

View File

@ -60,6 +60,9 @@ public class PublicDmp {
private List<PublicEntityDoi> entityDois;
public static final String _entityDois = "entityDois";
private List<PublicDmp> otherDmpVersions;
public static final String _otherDmpVersions = "otherDmpVersions";
public UUID getId() {
return id;
}
@ -171,4 +174,12 @@ public class PublicDmp {
public void setEntityDois(List<PublicEntityDoi> entityDois) {
this.entityDois = entityDois;
}
public List<PublicDmp> getOtherDmpVersions() {
return otherDmpVersions;
}
public void setOtherDmpVersions(List<PublicDmp> otherDmpVersions) {
this.otherDmpVersions = otherDmpVersions;
}
}

View File

@ -9,13 +9,11 @@ import gr.cite.tools.logging.DataLogEntry;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.commons.enums.EntityType;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.DmpEntity;
import org.opencdmp.model.*;
import org.opencdmp.query.DescriptionQuery;
import org.opencdmp.query.DmpReferenceQuery;
import org.opencdmp.query.DmpUserQuery;
import org.opencdmp.query.EntityDoiQuery;
import org.opencdmp.query.*;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@ -70,6 +68,9 @@ public class PublicDmpBuilder extends BaseBuilder<PublicDmp, DmpEntity> {
FieldSet entityDoisFields = fields.extractPrefixed(this.asPrefix(PublicDmp._entityDois));
Map<UUID, List<PublicEntityDoi>> entityDoisMap = this.collectEntityDois(entityDoisFields, data);
FieldSet otherDmpVersionsFields = fields.extractPrefixed(this.asPrefix(PublicDmp._otherDmpVersions));
Map<UUID, List<PublicDmp>> otherDmpVersionsMap = this.collectOtherDmpVersions(otherDmpVersionsFields, data);
for (DmpEntity d : data) {
PublicDmp m = new PublicDmp();
if (fields.hasField(this.asIndexer(PublicDmp._id))) m.setId(d.getId());
@ -87,6 +88,7 @@ public class PublicDmpBuilder extends BaseBuilder<PublicDmp, DmpEntity> {
if (dmpUsersMap != null && !dmpUsersMap.isEmpty() && dmpUsersMap.containsKey(d.getId())) m.setDmpUsers(dmpUsersMap.get(d.getId()));
if (descriptionsMap != null && !descriptionsMap.isEmpty() && descriptionsMap.containsKey(d.getId())) m.setDescriptions(descriptionsMap.get(d.getId()));
if (entityDoisMap != null && !entityDoisMap.isEmpty() && entityDoisMap.containsKey(d.getId())) m.setEntityDois(entityDoisMap.get(d.getId()));
if (otherDmpVersionsMap != null && !otherDmpVersionsMap.isEmpty() && otherDmpVersionsMap.containsKey(d.getGroupId())) m.setOtherDmpVersions(otherDmpVersionsMap.get(d.getGroupId()));
models.add(m);
}
@ -167,4 +169,22 @@ public class PublicDmpBuilder extends BaseBuilder<PublicDmp, DmpEntity> {
return itemMap;
}
private Map<UUID, List<PublicDmp>> collectOtherDmpVersions(FieldSet fields, List<DmpEntity> data) throws MyApplicationException {
if (fields.isEmpty() || data.isEmpty()) return null;
this.logger.debug("checking related - {}", PublicDmp.class.getSimpleName());
Map<UUID, List<PublicDmp>> itemMap;
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(PublicDmp._id);
DmpQuery query = this.queryFactory.query(DmpQuery.class).disableTracking().authorize(this.authorize).groupIds(data.stream().map(DmpEntity::getGroupId).distinct().collect(Collectors.toList())).isActive(IsActive.Active);
itemMap = this.builderFactory.builder(PublicDmpBuilder.class).authorize(this.authorize).asMasterKey(query, clone, x -> x.getGroupId());
if (!fields.hasField(this.asIndexer(PublicDmp._otherDmpVersions, PublicDmp._id))) {
itemMap.values().stream().flatMap(List::stream).filter(x -> x != null).peek(x -> {
x.setId(null);
});
}
return itemMap;
}
}

View File

@ -105,6 +105,9 @@ public class DmpBuilder extends BaseBuilder<Dmp, DmpEntity> {
FieldSet dmpDescriptionTemplatesFields = fields.extractPrefixed(this.asPrefix(Dmp._dmpDescriptionTemplates));
Map<UUID, List<DmpDescriptionTemplate>> dmpDescriptionTemplatesMap = this.collectDmpDescriptionTemplates(dmpDescriptionTemplatesFields, data);
FieldSet otherDmpVersionsFields = fields.extractPrefixed(this.asPrefix(Dmp._otherDmpVersions));
Map<UUID, List<Dmp>> otherDmpVersionsMap = this.collectOtherDmpVersions(otherDmpVersionsFields, data);
Set<String> authorizationFlags = this.extractAuthorizationFlags(fields, Dmp._authorizationFlags, this.authorizationContentResolver.getPermissionNames());
Map<UUID, AffiliatedResource> affiliatedResourceMap = authorizationFlags == null || authorizationFlags.isEmpty() ? null : this.authorizationContentResolver.dmpsAffiliation(data.stream().map(DmpEntity::getId).collect(Collectors.toList()));
@ -134,6 +137,7 @@ public class DmpBuilder extends BaseBuilder<Dmp, DmpEntity> {
if (dmpUsersMap != null && !dmpUsersMap.isEmpty() && dmpUsersMap.containsKey(d.getId())) m.setDmpUsers(dmpUsersMap.get(d.getId()));
if (descriptionsMap != null && !descriptionsMap.isEmpty() && descriptionsMap.containsKey(d.getId())) m.setDescriptions(descriptionsMap.get(d.getId()));
if (dmpDescriptionTemplatesMap != null && !dmpDescriptionTemplatesMap.isEmpty() && dmpDescriptionTemplatesMap.containsKey(d.getId())) m.setDmpDescriptionTemplates(dmpDescriptionTemplatesMap.get(d.getId()));
if (otherDmpVersionsMap != null && !otherDmpVersionsMap.isEmpty() && otherDmpVersionsMap.containsKey(d.getGroupId())) m.setOtherDmpVersions(otherDmpVersionsMap.get(d.getGroupId()));
if (!propertiesFields.isEmpty() && d.getProperties() != null){
DmpPropertiesEntity propertyDefinition = this.jsonHandlingService.fromJsonSafe(DmpPropertiesEntity.class, d.getProperties());
m.setProperties(this.builderFactory.builder(DmpPropertiesBuilder.class).authorize(this.authorize).build(propertiesFields, propertyDefinition));
@ -297,4 +301,22 @@ public class DmpBuilder extends BaseBuilder<Dmp, DmpEntity> {
return itemMap;
}
private Map<UUID, List<Dmp>> collectOtherDmpVersions(FieldSet fields, List<DmpEntity> data) throws MyApplicationException {
if (fields.isEmpty() || data.isEmpty()) return null;
this.logger.debug("checking related - {}", Dmp.class.getSimpleName());
Map<UUID, List<Dmp>> itemMap;
FieldSet clone = new BaseFieldSet(fields.getFields()).ensure(Dmp._id);
DmpQuery query = this.queryFactory.query(DmpQuery.class).disableTracking().authorize(this.authorize).groupIds(data.stream().map(DmpEntity::getGroupId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(DmpBuilder.class).authorize(this.authorize).asMasterKey(query, clone, x -> x.getGroupId());
if (!fields.hasField(this.asIndexer(Dmp._otherDmpVersions, Dmp._id))) {
itemMap.values().stream().flatMap(List::stream).filter(x -> x != null).peek(x -> {
x.setId(null);
});
}
return itemMap;
}
}

View File

@ -44,6 +44,8 @@ public class PublicDmpCensor extends BaseCensor {
this.censorFactory.censor(PublicDmpUserCensor.class).censor(dmpDescriptionsFields);
FieldSet dmpReferencesFields = fields.extractPrefixed(this.asIndexerPrefix(PublicDmp._dmpReferences));
this.censorFactory.censor(PublicDmpReferenceCensor.class).censor(dmpReferencesFields);
FieldSet otherDmpVersionsFields = fields.extractPrefixed(this.asIndexerPrefix(PublicDmp._otherDmpVersions));
this.censorFactory.censor(PublicDmpCensor.class).censor(otherDmpVersionsFields);
}
}

View File

@ -52,5 +52,7 @@ public class DmpCensor extends BaseCensor {
this.censorFactory.censor(EntityDoiCensor.class).censor(doisFields, userId);
FieldSet propertiesFields = fields.extractPrefixed(this.asIndexerPrefix(Dmp._properties));
this.censorFactory.censor(DmpPropertiesCensor.class).censor(propertiesFields, userId);
FieldSet otherDmpVersionsFields = fields.extractPrefixed(this.asIndexerPrefix(Dmp._otherDmpVersions));
this.censorFactory.censor(DmpCensor.class).censor(otherDmpVersionsFields, userId);
}
}

View File

@ -91,6 +91,9 @@ public class Dmp {
private List<String> authorizationFlags;
public static final String _authorizationFlags = "authorizationFlags";
private List<Dmp> otherDmpVersions;
public static final String _otherDmpVersions = "otherDmpVersions";
private Boolean belongsToCurrentTenant;
public static final String _belongsToCurrentTenant = "belongsToCurrentTenant";
@ -302,4 +305,12 @@ public class Dmp {
public void setBelongsToCurrentTenant(Boolean belongsToCurrentTenant) {
this.belongsToCurrentTenant = belongsToCurrentTenant;
}
public List<Dmp> getOtherDmpVersions() {
return otherDmpVersions;
}
public void setOtherDmpVersions(List<Dmp> otherDmpVersions) {
this.otherDmpVersions = otherDmpVersions;
}
}

View File

@ -1,16 +1,12 @@
package org.opencdmp.service.deposit;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import org.opencdmp.commonmodels.models.dmp.DmpModel;
import org.opencdmp.depositbase.repository.DepositClient;
import org.opencdmp.depositbase.repository.DepositConfiguration;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import org.slf4j.LoggerFactory;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@ -26,21 +22,25 @@ public class DepositClientImpl implements DepositClient {
@Override
public String deposit(DmpModel dmpDepositModel, String repositoryAccessToken) throws Exception {
return depositClient.post().uri("", uriBuilder -> uriBuilder.queryParam("authToken", repositoryAccessToken).build()).bodyValue(dmpDepositModel).exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(String.class)).block();
logger.debug(new MapLogEntry("deposit").And("dmpDepositModel", dmpDepositModel));
return this.depositClient.post().uri("", uriBuilder -> uriBuilder.queryParam("authToken", repositoryAccessToken).build()).bodyValue(dmpDepositModel).exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(String.class)).block();
}
@Override
public String authenticate(String code) {
return depositClient.get().uri("/authenticate/", uriBuilder -> uriBuilder.queryParam("authToken", code).build()).exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(String.class)).block();
logger.debug(new MapLogEntry("code"));
return this.depositClient.get().uri("/authenticate/", uriBuilder -> uriBuilder.queryParam("authToken", code).build()).exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(String.class)).block();
}
@Override
public DepositConfiguration getConfiguration() {
return depositClient.get().uri("/configuration").exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(new ParameterizedTypeReference<DepositConfiguration>() {})).block();
logger.debug(new MapLogEntry("getConfiguration"));
return this.depositClient.get().uri("/configuration").exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(new ParameterizedTypeReference<DepositConfiguration>() {})).block();
}
@Override
public String getLogo() {
return depositClient.get().uri("/logo").exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(String.class)).block();
logger.debug(new MapLogEntry("getLogo"));
return this.depositClient.get().uri("/logo").exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(String.class)).block();
}
}

View File

@ -10,6 +10,8 @@ import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import gr.cite.tools.validation.ValidatorFactory;
import org.apache.commons.io.FilenameUtils;
import org.opencdmp.authorization.AuthorizationFlags;
@ -55,14 +57,15 @@ import org.opencdmp.service.filetransformer.FileTransformerService;
import org.opencdmp.service.storage.StorageFileProperties;
import org.opencdmp.service.storage.StorageFileService;
import org.opencdmp.service.tenant.TenantProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.event.EventListener;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
@ -82,7 +85,7 @@ import java.util.stream.Collectors;
@Service
public class DepositServiceImpl implements DepositService {
private static final Logger logger = LoggerFactory.getLogger(DepositServiceImpl.class);
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(DepositServiceImpl.class));
private final DepositProperties depositProperties;
private final Map<String, DepositClient> clients;
@ -150,7 +153,12 @@ public class DepositServiceImpl implements DepositService {
if (source != null) {
TokenExchangeModel tokenExchangeModel = new TokenExchangeModel("deposit:" + repositoryIdByTenant, source.getIssuerUrl(), source.getClientId(), source.getClientSecret(), source.getScope());
TokenExchangeFilterFunction apiKeyExchangeFilterFunction = new TokenExchangeFilterFunction(this.tokenExchangeCacheService, tokenExchangeModel);
WebClient webClient = WebClient.builder().baseUrl(source.getUrl() + "/api/deposit").filters(exchangeFilterFunctions -> exchangeFilterFunctions.add(apiKeyExchangeFilterFunction)).build();
WebClient webClient = WebClient.builder().baseUrl(source.getUrl() + "/api/deposit")
.filters(exchangeFilterFunctions -> {
exchangeFilterFunctions.add(apiKeyExchangeFilterFunction);
exchangeFilterFunctions.add(logRequest());
exchangeFilterFunctions.add(logResponse());
}).build();
DepositClientImpl repository = new DepositClientImpl(webClient);
this.clients.put(repositoryIdByTenant, repository);
return repository;
@ -376,4 +384,25 @@ public class DepositServiceImpl implements DepositService {
return depositClient.authenticate(model.getCode());
}
private static ExchangeFilterFunction logRequest() {
return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
logger.debug(new MapLogEntry("Request").And("method", clientRequest.method().toString()).And("url", clientRequest.url()));
return Mono.just(clientRequest);
});
}
private static ExchangeFilterFunction logResponse() {
return ExchangeFilterFunction.ofResponseProcessor(response -> {
if (response.statusCode().isError()) {
return response.mutate().build().bodyToMono(String.class)
.flatMap(body -> {
logger.error(new MapLogEntry("Response").And("method", response.request().getMethod().toString()).And("url", response.request().getURI()).And("status", response.statusCode().toString()).And("body", body));
return Mono.just(response);
});
}
return Mono.just(response);
});
}
}

View File

@ -6,18 +6,19 @@ import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
import com.jayway.jsonpath.PathNotFoundException;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import net.minidev.json.JSONArray;
import org.opencdmp.commons.JsonHandlingService;
import org.opencdmp.commons.enums.ExternalFetcherSourceType;
import org.opencdmp.commons.types.externalfetcher.StaticOptionEntity;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.ReferenceEntity;
import org.opencdmp.model.reference.Reference;
import org.opencdmp.model.reference.Field;
import org.opencdmp.model.reference.Reference;
import org.opencdmp.service.externalfetcher.config.entities.*;
import org.opencdmp.service.externalfetcher.criteria.ExternalReferenceCriteria;
import org.opencdmp.service.externalfetcher.models.ExternalDataResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
@ -28,7 +29,9 @@ import org.springframework.http.ResponseEntity;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.http.codec.json.Jackson2JsonDecoder;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;
import java.util.*;
@ -38,7 +41,7 @@ import java.util.stream.Collectors;
@Service
public class ExternalFetcherServiceImpl implements ExternalFetcherService {
private static final Logger logger = LoggerFactory.getLogger(ExternalFetcherServiceImpl.class);
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(ExternalFetcherServiceImpl.class));
private WebClient webClient;
private final ConventionService conventionService;
@ -51,10 +54,13 @@ public class ExternalFetcherServiceImpl implements ExternalFetcherService {
private WebClient getWebClient() {
if (this.webClient == null) {
this.webClient = WebClient.builder().codecs(clientCodecConfigurer -> {
clientCodecConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(new ObjectMapper(), MediaType.APPLICATION_JSON));
clientCodecConfigurer.defaultCodecs().maxInMemorySize(2 * ((int) Math.pow(1024, 3))); //GK: Why here???
}
this.webClient = WebClient.builder().filters(exchangeFilterFunctions -> {
exchangeFilterFunctions.add(logRequest());
exchangeFilterFunctions.add(logResponse());
}).codecs(clientCodecConfigurer -> {
clientCodecConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(new ObjectMapper(), MediaType.APPLICATION_JSON));
clientCodecConfigurer.defaultCodecs().maxInMemorySize(2 * ((int) Math.pow(1024, 3))); //GK: Why here???
}
).clientConnector(new ReactorClientHttpConnector(HttpClient.create().followRedirect(true))).build();
}
return this.webClient;
@ -147,12 +153,14 @@ public class ExternalFetcherServiceImpl implements ExternalFetcherService {
case POST -> method =HttpMethod.POST;
default -> throw new MyApplicationException("unrecognized type " + authenticationConfiguration.getAuthMethod());
}
logger.debug(new MapLogEntry("Authentication").And("url", authenticationConfiguration.getAuthUrl()));
Map<String, Object> response = this.getWebClient().method(method).uri(authenticationConfiguration.getAuthUrl())
.contentType(MediaType.APPLICATION_JSON)
.bodyValue(this.parseBodyString(authenticationConfiguration.getAuthRequestBody()))
.exchangeToMono(mono -> mono.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {
})).block();
.exchangeToMono(mono -> mono.statusCode().isError() ?
mono.createException().flatMap(Mono::error) : mono.bodyToMono(new ParameterizedTypeReference<Map<String, Object>>() {}))
.block();
if (response == null) throw new MyApplicationException("Authentication " + authenticationConfiguration.getAuthUrl() + " failed");
return authenticationConfiguration.getType() + " " + response.getOrDefault(authenticationConfiguration.getAuthTokenPath(), null);
@ -259,7 +267,10 @@ public class ExternalFetcherServiceImpl implements ExternalFetcherService {
case POST -> method =HttpMethod.POST;
default -> throw new MyApplicationException("unrecognized type " + apiSource.getHttpMethod());
}
logger.debug(new MapLogEntry("Fetch data")
.And("url", urlString)
.And("body", jsonBody));
ResponseEntity<String> response = this.getWebClient().method(method).uri(urlString).headers(httpHeaders -> {
if (this.conventionService.isNullOrEmpty(apiSource.getContentType())) {
httpHeaders.setAccept(Collections.singletonList(MediaType.valueOf(apiSource.getContentType())));
@ -374,4 +385,25 @@ public class ExternalFetcherServiceImpl implements ExternalFetcherService {
return finalBodyString;
}
private static ExchangeFilterFunction logRequest() {
return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
logger.debug(new MapLogEntry("Request").And("method", clientRequest.method().toString()).And("url", clientRequest.url()));
return Mono.just(clientRequest);
});
}
private static ExchangeFilterFunction logResponse() {
return ExchangeFilterFunction.ofResponseProcessor(response -> {
if (response.statusCode().isError()) {
return response.mutate().build().bodyToMono(String.class)
.flatMap(body -> {
logger.error(new MapLogEntry("Response").And("method", response.request().getMethod().toString()).And("url", response.request().getURI()).And("status", response.statusCode().toString()).And("body", body));
return Mono.just(response);
});
}
return Mono.just(response);
});
}
}

View File

@ -1,16 +1,20 @@
package org.opencdmp.service.filetransformer;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import org.opencdmp.commonmodels.models.FileEnvelopeModel;
import org.opencdmp.commonmodels.models.description.DescriptionModel;
import org.opencdmp.commonmodels.models.dmp.DmpModel;
import org.opencdmp.filetransformerbase.interfaces.FileTransformerClient;
import org.opencdmp.filetransformerbase.interfaces.FileTransformerConfiguration;
import org.slf4j.LoggerFactory;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
public class FileTransformerRepository implements FileTransformerClient {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(FileTransformerRepository.class));
private final WebClient transformerClient;
@ -20,30 +24,35 @@ public class FileTransformerRepository implements FileTransformerClient {
@Override
public FileEnvelopeModel exportDmp(DmpModel dmpModel, String format) {
logger.debug(new MapLogEntry("exportDmp").And("format", format).And("dmpModel", dmpModel));
return this.transformerClient.post().uri("/export/dmp", uriBuilder -> uriBuilder.queryParam("format", format).build()).bodyValue(dmpModel)
.exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(FileEnvelopeModel.class)).block();
}
@Override
public DmpModel importDmp(FileEnvelopeModel fileEnvelope) {
logger.debug(new MapLogEntry("importDmp").And("fileEnvelope", fileEnvelope));
return this.transformerClient.post().uri("/import/dmp").bodyValue(fileEnvelope)
.exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(DmpModel.class)).block();
}
@Override
public FileEnvelopeModel exportDescription(DescriptionModel descriptionModel, String format) {
logger.debug(new MapLogEntry("exportDescription").And("format", format).And("descriptionModel", descriptionModel));
return this.transformerClient.post().uri("/export/description", uriBuilder -> uriBuilder.queryParam("format", format).build()).bodyValue(descriptionModel)
.exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(FileEnvelopeModel.class)).block();
}
@Override
public DescriptionModel importDescription(FileEnvelopeModel fileEnvelope) {
logger.debug(new MapLogEntry("importDescription").And("fileEnvelope", fileEnvelope));
return this.transformerClient.post().uri("/import/description").bodyValue(fileEnvelope)
.exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(DescriptionModel.class)).block();
}
@Override
public FileTransformerConfiguration getConfiguration() {
logger.debug(new MapLogEntry("getConfiguration"));
return this.transformerClient.get().uri("/formats")
.exchangeToMono(mono -> mono.statusCode().isError() ? mono.createException().flatMap(Mono::error) : mono.bodyToMono(new ParameterizedTypeReference<FileTransformerConfiguration>() {})).block();
}

View File

@ -8,6 +8,8 @@ import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.authorization.Permission;
import org.opencdmp.commonmodels.models.FileEnvelopeModel;
@ -36,7 +38,6 @@ import org.opencdmp.query.TenantConfigurationQuery;
import org.opencdmp.service.encryption.EncryptionService;
import org.opencdmp.service.storage.StorageFileService;
import org.opencdmp.service.tenant.TenantProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
@ -58,8 +59,7 @@ import java.util.*;
@Service
public class FileTransformerServiceImpl implements FileTransformerService {
private static final Logger logger = LoggerFactory.getLogger(FileTransformerServiceImpl.class);
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(FileTransformerServiceImpl.class));
private final FileTransformerProperties fileTransformerProperties;
private final Map<String, FileTransformerRepository> clients;
private final TokenExchangeCacheService tokenExchangeCacheService;
@ -108,6 +108,7 @@ public class FileTransformerServiceImpl implements FileTransformerService {
FileTransformerRepository repository = new FileTransformerRepository(WebClient.builder().baseUrl(source.getUrl() + "/api/file-transformer").filters(exchangeFilterFunctions -> {
exchangeFilterFunctions.add(tokenExchangeFilterFunction);
exchangeFilterFunctions.add(logRequest());
exchangeFilterFunctions.add(logResponse());
}).build());
this.clients.put(repositoryIdByTenant, repository);
return repository;
@ -259,12 +260,24 @@ public class FileTransformerServiceImpl implements FileTransformerService {
return result;
}
// This method returns filter function which will log request data
private static ExchangeFilterFunction logRequest() {
return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
logger.info("Request: {} {}", clientRequest.method(), clientRequest.url());
clientRequest.headers().forEach((name, values) -> values.forEach(value -> logger.info("{}={}", name, value)));
logger.debug(new MapLogEntry("Request").And("method", clientRequest.method().toString()).And("url", clientRequest.url()));
return Mono.just(clientRequest);
});
}
private static ExchangeFilterFunction logResponse() {
return ExchangeFilterFunction.ofResponseProcessor(response -> {
if (response.statusCode().isError()) {
return response.mutate().build().bodyToMono(String.class)
.flatMap(body -> {
logger.error(new MapLogEntry("Response").And("method", response.request().getMethod().toString()).And("url", response.request().getURI()).And("status", response.statusCode().toString()).And("body", body));
return Mono.just(response);
});
}
return Mono.just(response);
});
}
}

View File

@ -35,6 +35,7 @@ export interface Dmp extends BaseEntity {
descriptions?: Description[];
dmpDescriptionTemplates?: DmpDescriptionTemplate[];
entityDois?: EntityDoi[];
otherDmpVersions?: Dmp[];
authorizationFlags?: AppPermission[];
}
@ -169,6 +170,7 @@ export interface PublicDmp extends BaseEntity {
dmpUsers: PublicDmpUser[];
descriptions: PublicDescription[];
entityDois: PublicEntityDoi[];
otherDmpVersions?: PublicDmp[];
}
export interface PublicDmpReference {

View File

@ -34,8 +34,8 @@
</div>
<div class="col-auto">
<mat-form-field appearance="outline" subscriptSizing="dynamic" class="dense-3 versions-select">
<mat-select placeholder="{{'DMP-OVERVIEW.VERSION' | translate}} {{dmp.version}}" [(ngModel)]="version" (ngModelChange)="versionChanged(version.id)">
<mat-option *ngFor="let version of pastVersions" [value]="version">
<mat-select placeholder="{{'DMP-OVERVIEW.VERSION' | translate}} {{dmp.version}}" [(ngModel)]="selectedDmpVersion" (selectionChange)="versionChanged(selectedDmpVersion.id)">
<mat-option *ngFor="let version of dmp?.otherDmpVersions" [value]="version">
{{'DMP-OVERVIEW.VERSION' | translate}} {{version.version}}</mat-option>
</mat-select>
</mat-form-field>

View File

@ -58,6 +58,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
dmp: any;
selectedBlueprint: DmpBlueprint;
selectedDmpVersion: any;
researchers: DmpReference[] = [];
isNew = true;
isFinalized = false;
@ -67,7 +68,6 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
// isUserOwner: boolean;
isLocked: Boolean;
textMessage: any;
pastVersions: Dmp[]; //TODO: get these from the backend
selectedModel: EntityDoi;
fileTransformerEntityTypeEnum = FileTransformerEntityType;
@ -121,6 +121,7 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
.subscribe(data => {
this.dmp = data;
this.dmp.dmpUsers = data.dmpUsers.filter(x => x.isActive === IsActive.Active);
this.dmp.otherDmpVersions = data.otherDmpVersions?.filter(x => x.isActive === IsActive.Active) || null;
if (this.dmp.descriptions) {
if (this.dmp.status == DmpStatus.Finalized) {
this.dmp.descriptions = data.descriptions.filter(x => x.isActive === IsActive.Active && x.status === DescriptionStatus.Finalized);
@ -134,9 +135,9 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
if (!this.hasDoi()) {
this.selectedModel = this.dmp.entityDois[0];
}
this.selectedDmpVersion = this.dmp;
this.checkLockStatus(this.dmp.id);
// this.setIsUserOwner();
this.getAllVersions(this.dmp);
// const breadCrumbs = [];
// breadCrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.MY-DMPS'), url: "/plans" });
// breadCrumbs.push({ parentComponentName: 'DmpListingComponent', label: this.dmp.label, url: '/plans/overview/' + this.dmp.id });
@ -162,8 +163,8 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
if (!this.hasDoi()) {
this.selectedModel = this.dmp.entityDois[0];
}
this.selectedDmpVersion = this.dmp;
// this.checkLockStatus(this.dmp.id);
this.getAllVersions(this.dmp);
// const breadCrumbs = [];
// breadCrumbs.push({ parentComponentName: null, label: this.language.instant('NAV-BAR.PUBLIC-DMPS'), url: "/explore-plans" });
// breadCrumbs.push({ parentComponentName: 'DmpListingComponent', label: this.dmp.label, url: '/plans/overview/public/' + this.dmp.id });
@ -476,15 +477,6 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
return (this.dmp.entityDois == null || this.dmp.entityDois.length == 0);
}
getAllVersions(dmp: Dmp) {
//TODO: add this
// this.dmpService.getAllVersions(dmp.groupId, this.isPublicView)
// .pipe(takeUntil(this._destroyed))
// .subscribe(items => {
// this.versions = items;
// });
}
afterDeposit(result: EntityDoi[]) {
if (result.length > 0) {
this.dmp.entityDois = result;
@ -771,6 +763,11 @@ export class DmpOverviewComponent extends BaseComponent implements OnInit {
[nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.id)].join('.'),
[nameof<Dmp>(x => x.blueprint), nameof<DmpBlueprint>(x => x.definition), nameof<DmpBlueprintDefinition>(x => x.sections), nameof<DmpBlueprintDefinitionSection>(x => x.label)].join('.'),
[nameof<Dmp>(x => x.otherDmpVersions), nameof<Dmp>(x => x.id)].join('.'),
[nameof<Dmp>(x => x.otherDmpVersions), nameof<Dmp>(x => x.groupId)].join('.'),
[nameof<Dmp>(x => x.otherDmpVersions), nameof<Dmp>(x => x.version)].join('.'),
[nameof<Dmp>(x => x.otherDmpVersions), nameof<Dmp>(x => x.isActive)].join('.'),
nameof<Dmp>(x => x.hash),
]
}

View File

@ -348,7 +348,7 @@
"LANGUAGE": "Language",
"PRIMARY-COLOR": "Primary Color",
"PRIMARY-COLOR-2": "Primary Color 2",
"PRIMARY-COLOR-3": "Primary Color 2",
"PRIMARY-COLOR-3": "Primary Color 3",
"SECONDARY-COLOR": "Secondary Color",
"DISABLE-SYSTEM-SOURCES": "Disable System Sources",
"DEPOSIT-PLUGINS": "Plugin",

View File

@ -5,4 +5,71 @@ description: Configure the tenant you are logged in with
# Tenant Configuration
TODO: thgiannos
On this page, we can configure the tenant we are logged in with. The configuration options are separated in the following sections.
:::info
Only tenant administrators can access this page.
:::
<details>
<summary>Default Tenant Locale</summary>
Here we specify the locale configuration, which will be applied by default to the users of this tenant.
- **Timezone**
- **Culture**
- **Language**
</details>
<details>
<summary>App Colors</summary>
Here we specify the color accents, which will be applied to the UI when this tenant is selected. Every tenant can have a different theme.
- **Primary Color**
- **Primary Color 2**
- **Primary Color 3**
- **Secondary Color**
</details>
<details>
<summary>Deposit Plugins</summary>
Here we specify the deposit plugins, which will be available for this tenant. We can add plugins by pressing the `Add Source` button. For every plugin, we have to specify the following.
- **Repository Id**: An identifier for the deposit plugin.
- **Url**: The url of the endpoint the deposit listens to.
- **Issuer Url**: The authentication token issuer url.
- **Client Id**: The authentication client.
- **Client Secret**: The authentication client secret.
- **Scope**: The authentication token scope.
- **Pdf Transformer Id**: The id of the file transformer plugin used for pdf files, if configured and available.<br/>*Please refer to the next section.*
- **Rda Transformer Id**: The id of the file transformer plugin used for rda files, if configured and available.<br/>*Please refer to the next section.*
</details>
<details>
<summary>File Transformer Plugins</summary>
Here we specify the file transformer plugins, which will be available for this tenant. We can add plugins by pressing the `Add Source` button. For every plugin, we have to specify the following.
- **Transformer Id**: An identifier for the transformer plugin.<br/>*This id can be added on deposit plugin configurations.*
- **Url**: The url of the endpoint the deposit listens to.
- **Issuer Url**: The authentication token issuer url.
- **Client Id**: The authentication client.
- **Client Secret**: The authentication client secret.
- **Scope**: The authentication token scope.
</details>
<details>
<summary>Extra Logo</summary>
Here we can upload an extra logo, which will be displayed next to the platform logo. It is a great way for tenant branding.
</details>
<details>
<summary>Notification Preferences</summary>
Here we specify the notification preferences, which will be applied by default to the users of this tenant. For every notification case, we can specify the channels which will be used and their priority.
</details>