Resolving migration tool startup issues due to core module changes, change on handling of license json objects
This commit is contained in:
parent
fd1d6c9b1a
commit
a9eb2ff8a7
|
@ -2,11 +2,15 @@ package eu.eudat.commons;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectReader;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||||
import org.springframework.context.annotation.Scope;
|
import org.springframework.context.annotation.Scope;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
|
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)
|
||||||
public class JsonHandlingService {
|
public class JsonHandlingService {
|
||||||
|
@ -36,6 +40,11 @@ public class JsonHandlingService {
|
||||||
return objectMapper.readValue(json, type);
|
return objectMapper.readValue(json, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public HashMap<String, String> mapFromJson(String json) throws JsonProcessingException {
|
||||||
|
ObjectReader reader = objectMapper.readerFor(Map.class);
|
||||||
|
return reader.readValue(json);
|
||||||
|
}
|
||||||
|
|
||||||
public <T> T fromJsonSafe(Class<T> type, String json) {
|
public <T> T fromJsonSafe(Class<T> type, String json) {
|
||||||
if (json == null) return null;
|
if (json == null) return null;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -16,7 +16,7 @@ import java.util.UUID;
|
||||||
//@NoArgsConstructor
|
//@NoArgsConstructor
|
||||||
@FilterDef(name = TenantScopedBaseEntity.tenantFilter, parameters = {@ParamDef(name = TenantScopedBaseEntity.tenantFilterTenantParam, type = String.class)})
|
@FilterDef(name = TenantScopedBaseEntity.tenantFilter, parameters = {@ParamDef(name = TenantScopedBaseEntity.tenantFilterTenantParam, type = String.class)})
|
||||||
@Filter(name = "tenantFilter", condition = "tenant = (cast(:tenantId as uuid))")
|
@Filter(name = "tenantFilter", condition = "tenant = (cast(:tenantId as uuid))")
|
||||||
@EntityListeners(TenantListener.class)
|
//@EntityListeners(TenantListener.class)
|
||||||
public abstract class TenantScopedBaseEntity implements TenantScoped, Serializable {
|
public abstract class TenantScopedBaseEntity implements TenantScoped, Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
public static final String tenantFilter = "tenantFilter";
|
public static final String tenantFilter = "tenantFilter";
|
||||||
|
|
|
@ -1 +1,5 @@
|
||||||
web/target
|
web/target
|
||||||
|
data/target
|
||||||
|
elastic/target
|
||||||
|
queryable/target
|
||||||
|
web/src/main/resources/certificates
|
||||||
|
|
|
@ -356,6 +356,19 @@
|
||||||
</property>
|
</property>
|
||||||
</activation>
|
</activation>
|
||||||
</profile>
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>cite-dev</id>
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>cite-maven</id>
|
||||||
|
<name>CITE Maven Repository</name>
|
||||||
|
<url>https://crepo.cite.gr/repository/cite-maven/</url>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -1,84 +0,0 @@
|
||||||
package eu.old.eudat.controllers;
|
|
||||||
|
|
||||||
import eu.old.eudat.logic.managers.DepositManager;
|
|
||||||
import eu.old.eudat.logic.security.claims.ClaimedAuthorities;
|
|
||||||
import eu.old.eudat.logic.services.ApiContext;
|
|
||||||
import eu.old.eudat.models.data.doi.DepositCode;
|
|
||||||
import eu.old.eudat.models.data.doi.DepositRequest;
|
|
||||||
import eu.old.eudat.models.data.doi.Doi;
|
|
||||||
import eu.old.eudat.models.data.doi.RepositoryConfig;
|
|
||||||
import eu.old.eudat.models.data.helpers.responses.ResponseItem;
|
|
||||||
import eu.old.eudat.models.data.security.Principal;
|
|
||||||
import eu.old.eudat.types.ApiMessageCode;
|
|
||||||
import eu.old.eudat.types.Authorities;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@CrossOrigin
|
|
||||||
@RequestMapping(value = {"/api/deposit/"})
|
|
||||||
public class DepositController extends BaseController {
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(DepositController.class);
|
|
||||||
|
|
||||||
private DepositManager depositManager;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public DepositController(ApiContext apiContext, DepositManager depositManager){
|
|
||||||
super(apiContext);
|
|
||||||
this.depositManager = depositManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = {"/repos"})
|
|
||||||
public @ResponseBody
|
|
||||||
ResponseEntity<ResponseItem<List<RepositoryConfig>>> getAvailableRepos(@ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) {
|
|
||||||
List<RepositoryConfig> ids = this.depositManager.getAvailableRepos();
|
|
||||||
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<List<RepositoryConfig>>().status(ApiMessageCode.NO_MESSAGE).payload(ids));
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.POST, value = {"/getAccessToken"})
|
|
||||||
public @ResponseBody
|
|
||||||
ResponseEntity<ResponseItem<String>> getAccessToken(@RequestBody DepositCode depositCode, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) throws Exception {
|
|
||||||
String accessToken = this.depositManager.authenticate(depositCode.getRepositoryId(), depositCode.getCode());
|
|
||||||
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<String>().status(ApiMessageCode.NO_MESSAGE).payload(accessToken));
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.POST, value = {"/createDoi"})
|
|
||||||
public @ResponseBody
|
|
||||||
ResponseEntity<ResponseItem<Doi>> createDoi(@RequestBody DepositRequest depositRequest, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) {
|
|
||||||
try {
|
|
||||||
Doi doi = this.depositManager.deposit(depositRequest, principal);
|
|
||||||
if(doi != null){
|
|
||||||
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<Doi>().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully created DOI for Data Datamanagement Plan in question.").payload(doi));
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<Doi>().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to create DOI for the Data Management Plan"));
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<Doi>().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to create DOI for the Data Management Plan: " + e.getMessage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping(method = RequestMethod.GET, value = {"/logo/{repositoryId}"})
|
|
||||||
public @ResponseBody
|
|
||||||
ResponseEntity<ResponseItem<String>> getLogo(@PathVariable("repositoryId") String repositoryId, @ClaimedAuthorities(claims = {Authorities.ADMIN, Authorities.MANAGER, Authorities.USER, Authorities.ANONYMOUS}) Principal principal) {
|
|
||||||
try {
|
|
||||||
String encodedLogo = this.depositManager.getRepositoryLogo(repositoryId);
|
|
||||||
if(encodedLogo != null){
|
|
||||||
return ResponseEntity.status(HttpStatus.OK).body(new ResponseItem<String>().status(ApiMessageCode.SUCCESS_MESSAGE).message("Successfully loaded " + repositoryId + "'s logo.").payload(encodedLogo));
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ResponseItem<String>().status(ApiMessageCode.ERROR_MESSAGE).message(repositoryId + " has no logo").payload(null));
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(new ResponseItem<String>().status(ApiMessageCode.ERROR_MESSAGE).message("Failed to load " + repositoryId + "'s logo: " + e.getMessage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +1,6 @@
|
||||||
package eu.old.eudat.logic.managers;
|
package eu.old.eudat.logic.managers;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import eu.eudat.depositinterface.models.DMPDepositModel;
|
|
||||||
import eu.eudat.depositinterface.repository.RepositoryDeposit;
|
|
||||||
import eu.old.eudat.elastic.criteria.DmpCriteria;
|
|
||||||
import eu.old.eudat.elastic.entities.Collaborator;
|
|
||||||
import eu.old.eudat.elastic.entities.Dmp;
|
|
||||||
import eu.old.eudat.elastic.entities.Organization;
|
|
||||||
import eu.old.eudat.elastic.entities.Tag;
|
|
||||||
import eu.old.eudat.configurations.dynamicgrant.DynamicGrantConfiguration;
|
import eu.old.eudat.configurations.dynamicgrant.DynamicGrantConfiguration;
|
||||||
import eu.old.eudat.configurations.dynamicgrant.entities.Property;
|
import eu.old.eudat.configurations.dynamicgrant.entities.Property;
|
||||||
import eu.old.eudat.data.dao.criteria.*;
|
import eu.old.eudat.data.dao.criteria.*;
|
||||||
|
@ -23,6 +16,11 @@ import eu.old.eudat.data.enumeration.notification.NotifyState;
|
||||||
import eu.old.eudat.data.query.items.table.dataset.DatasetTableRequest;
|
import eu.old.eudat.data.query.items.table.dataset.DatasetTableRequest;
|
||||||
import eu.old.eudat.data.query.items.table.datasetprofile.DatasetProfileTableRequestItem;
|
import eu.old.eudat.data.query.items.table.datasetprofile.DatasetProfileTableRequestItem;
|
||||||
import eu.old.eudat.data.query.items.table.dmp.DataManagementPlanTableRequest;
|
import eu.old.eudat.data.query.items.table.dmp.DataManagementPlanTableRequest;
|
||||||
|
import eu.old.eudat.elastic.criteria.DmpCriteria;
|
||||||
|
import eu.old.eudat.elastic.entities.Collaborator;
|
||||||
|
import eu.old.eudat.elastic.entities.Dmp;
|
||||||
|
import eu.old.eudat.elastic.entities.Organization;
|
||||||
|
import eu.old.eudat.elastic.entities.Tag;
|
||||||
import eu.old.eudat.exceptions.datamanagementplan.DMPNewVersionException;
|
import eu.old.eudat.exceptions.datamanagementplan.DMPNewVersionException;
|
||||||
import eu.old.eudat.exceptions.datamanagementplan.DMPWithDatasetsDeleteException;
|
import eu.old.eudat.exceptions.datamanagementplan.DMPWithDatasetsDeleteException;
|
||||||
import eu.old.eudat.exceptions.security.ForbiddenException;
|
import eu.old.eudat.exceptions.security.ForbiddenException;
|
||||||
|
@ -31,14 +29,12 @@ import eu.old.eudat.logic.builders.entity.UserInfoBuilder;
|
||||||
import eu.old.eudat.logic.mapper.elastic.DmpMapper;
|
import eu.old.eudat.logic.mapper.elastic.DmpMapper;
|
||||||
import eu.old.eudat.logic.mapper.elastic.criteria.DmpCriteriaMapper;
|
import eu.old.eudat.logic.mapper.elastic.criteria.DmpCriteriaMapper;
|
||||||
import eu.old.eudat.logic.proxy.config.configloaders.ConfigLoader;
|
import eu.old.eudat.logic.proxy.config.configloaders.ConfigLoader;
|
||||||
import eu.old.eudat.logic.security.repositorydeposit.mapper.DMPToDepositMapper;
|
|
||||||
import eu.old.eudat.logic.services.ApiContext;
|
import eu.old.eudat.logic.services.ApiContext;
|
||||||
import eu.old.eudat.logic.services.forms.VisibilityRuleService;
|
import eu.old.eudat.logic.services.forms.VisibilityRuleService;
|
||||||
import eu.old.eudat.logic.services.forms.VisibilityRuleServiceImpl;
|
import eu.old.eudat.logic.services.forms.VisibilityRuleServiceImpl;
|
||||||
import eu.old.eudat.logic.services.operations.DatabaseRepository;
|
import eu.old.eudat.logic.services.operations.DatabaseRepository;
|
||||||
import eu.old.eudat.logic.utilities.builders.XmlBuilder;
|
import eu.old.eudat.logic.utilities.builders.XmlBuilder;
|
||||||
import eu.old.eudat.logic.utilities.documents.helpers.FileEnvelope;
|
import eu.old.eudat.logic.utilities.documents.helpers.FileEnvelope;
|
||||||
import eu.old.eudat.logic.utilities.documents.pdf.PDFUtils;
|
|
||||||
import eu.old.eudat.logic.utilities.documents.types.ParagraphStyle;
|
import eu.old.eudat.logic.utilities.documents.types.ParagraphStyle;
|
||||||
import eu.old.eudat.logic.utilities.documents.word.WordBuilder;
|
import eu.old.eudat.logic.utilities.documents.word.WordBuilder;
|
||||||
import eu.old.eudat.logic.utilities.documents.xml.ExportXmlBuilder;
|
import eu.old.eudat.logic.utilities.documents.xml.ExportXmlBuilder;
|
||||||
|
@ -118,11 +114,10 @@ public class DataManagementPlanManager {
|
||||||
private UserManager userManager;
|
private UserManager userManager;
|
||||||
private final MetricsManager metricsManager;
|
private final MetricsManager metricsManager;
|
||||||
private final ConfigLoader configLoader;
|
private final ConfigLoader configLoader;
|
||||||
private List<RepositoryDeposit> repositoriesDeposit;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
public DataManagementPlanManager(ApiContext apiContext, DatasetManager datasetManager, DataManagementProfileManager dataManagementProfileManager, Environment environment, RDAManager rdaManager, UserManager userManager,
|
public DataManagementPlanManager(ApiContext apiContext, DatasetManager datasetManager, DataManagementProfileManager dataManagementProfileManager, Environment environment, RDAManager rdaManager, UserManager userManager,
|
||||||
MetricsManager metricsManager, ConfigLoader configLoader, List<RepositoryDeposit> repositoriesDeposit) {
|
MetricsManager metricsManager, ConfigLoader configLoader) {
|
||||||
this.apiContext = apiContext;
|
this.apiContext = apiContext;
|
||||||
this.datasetManager = datasetManager;
|
this.datasetManager = datasetManager;
|
||||||
this.dataManagementProfileManager = dataManagementProfileManager;
|
this.dataManagementProfileManager = dataManagementProfileManager;
|
||||||
|
@ -133,7 +128,6 @@ public class DataManagementPlanManager {
|
||||||
this.metricsManager = metricsManager;
|
this.metricsManager = metricsManager;
|
||||||
this.configLoader = configLoader;
|
this.configLoader = configLoader;
|
||||||
this.objectMapper = new ObjectMapper();
|
this.objectMapper = new ObjectMapper();
|
||||||
this.repositoriesDeposit = repositoriesDeposit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2378,74 +2372,73 @@ public class DataManagementPlanManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Doi createDoi(DepositRequest depositRequest, Principal principal) throws Exception {
|
public Doi createDoi(DepositRequest depositRequest, Principal principal) throws Exception {
|
||||||
DMP dmp = this.apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(UUID.fromString(depositRequest.getDmpId()));
|
// DMP dmp = this.apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().find(UUID.fromString(depositRequest.getDmpId()));
|
||||||
if (!isUserOwnerOfDmp(dmp, principal))
|
// if (!isUserOwnerOfDmp(dmp, principal))
|
||||||
throw new Exception("User is not authorized to invoke this action");
|
// throw new Exception("User is not authorized to invoke this action");
|
||||||
if (!dmp.getStatus().equals(DMP.DMPStatus.FINALISED.getValue()))
|
// if (!dmp.getStatus().equals(DMP.DMPStatus.FINALISED.getValue()))
|
||||||
throw new Exception("DMP is not finalized");
|
// throw new Exception("DMP is not finalized");
|
||||||
/*if (dmp.getDoi() != null)
|
// /*if (dmp.getDoi() != null)
|
||||||
throw new Exception("DMP already has a DOI");*/
|
// throw new Exception("DMP already has a DOI");*/
|
||||||
|
//
|
||||||
FileEnvelope file = getWordDocument(depositRequest.getDmpId(), principal, configLoader);
|
// FileEnvelope file = getWordDocument(depositRequest.getDmpId(), principal, configLoader);
|
||||||
String name = file.getFilename().substring(0, file.getFilename().length() - 5).replaceAll("[^a-zA-Z0-9_+ ]", "").replace(" ", "_").replace(",", "_");
|
// String name = file.getFilename().substring(0, file.getFilename().length() - 5).replaceAll("[^a-zA-Z0-9_+ ]", "").replace(" ", "_").replace(",", "_");
|
||||||
File pdfFile = PDFUtils.convertToPDF(file, environment);
|
// File pdfFile = PDFUtils.convertToPDF(file, environment);
|
||||||
eu.eudat.depositinterface.models.FileEnvelope pdfEnvelope = new eu.eudat.depositinterface.models.FileEnvelope();
|
// eu.eudat.depositinterface.models.FileEnvelope pdfEnvelope = new eu.eudat.depositinterface.models.FileEnvelope();
|
||||||
pdfEnvelope.setFile(pdfFile);
|
//// pdfEnvelope.setFile(pdfFile);
|
||||||
pdfEnvelope.setFilename(name + ".pdf");
|
// pdfEnvelope.setFilename(name + ".pdf");
|
||||||
eu.eudat.depositinterface.models.FileEnvelope rdaJsonFile = new eu.eudat.depositinterface.models.FileEnvelope();
|
// eu.eudat.depositinterface.models.FileEnvelope rdaJsonFile = new eu.eudat.depositinterface.models.FileEnvelope();
|
||||||
try {
|
// try {
|
||||||
FileEnvelope rdaJsonDocument = getRDAJsonDocument(depositRequest.getDmpId(), principal);
|
// FileEnvelope rdaJsonDocument = getRDAJsonDocument(depositRequest.getDmpId(), principal);
|
||||||
rdaJsonFile.setFile(rdaJsonDocument.getFile());
|
//// rdaJsonFile.setFile(rdaJsonDocument.getFile());
|
||||||
rdaJsonFile.setFilename(rdaJsonDocument.getFilename());
|
// rdaJsonFile.setFilename(rdaJsonDocument.getFilename());
|
||||||
} catch (Exception e) {
|
// } catch (Exception e) {
|
||||||
logger.error(e.getMessage(), e);
|
// logger.error(e.getMessage(), e);
|
||||||
}
|
// }
|
||||||
String previousDOI = this.getPreviousDOI(dmp.getGroupId(), dmp.getId(), depositRequest.getRepositoryId());
|
// String previousDOI = this.getPreviousDOI(dmp.getGroupId(), dmp.getId(), depositRequest.getRepositoryId());
|
||||||
|
//
|
||||||
File supportingFilesZip = this.createSupportingFilesZip(dmp);
|
// File supportingFilesZip = this.createSupportingFilesZip(dmp);
|
||||||
|
//
|
||||||
DMPDepositModel dmpDepositModel = DMPToDepositMapper.fromDMP(dmp, pdfEnvelope, rdaJsonFile, supportingFilesZip, previousDOI);
|
//// DMPDepositModel dmpDepositModel = DMPToDepositMapper.fromDMP(dmp, pdfEnvelope, rdaJsonFile, supportingFilesZip, previousDOI);
|
||||||
|
//
|
||||||
String finalDoi = null;
|
// String finalDoi = null;
|
||||||
for(RepositoryDeposit repo: this.repositoriesDeposit){
|
//// for(RepositoryDeposit repo: this.repositoriesDeposit){
|
||||||
if(repo.getConfiguration().stream().anyMatch(x-> x.getRepositoryId().equals(depositRequest.getRepositoryId()))){
|
//// if(repo.getConfiguration().stream().anyMatch(x-> x.getRepositoryId().equals(depositRequest.getRepositoryId()))){
|
||||||
try {
|
// try {
|
||||||
finalDoi = repo.deposit(depositRequest.getRepositoryId(), dmpDepositModel, depositRequest.getAccessToken());
|
//// finalDoi = repo.deposit(depositRequest.getRepositoryId(), dmpDepositModel, depositRequest.getAccessToken());
|
||||||
} catch (Exception e) {
|
// } catch (Exception e) {
|
||||||
logger.error(e.getMessage(), e);
|
// logger.error(e.getMessage(), e);
|
||||||
return null;
|
// return null;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
Doi doiModel = null;
|
// Doi doiModel = null;
|
||||||
if (finalDoi != null) {
|
// if (finalDoi != null) {
|
||||||
|
//
|
||||||
EntityDoi doiEntity = new EntityDoi();
|
// EntityDoi doiEntity = new EntityDoi();
|
||||||
doiEntity.setId(UUID.randomUUID());
|
// doiEntity.setId(UUID.randomUUID());
|
||||||
doiEntity.setEntityType(EntityDoi.EntityType.DMP);
|
// doiEntity.setEntityType(EntityDoi.EntityType.DMP);
|
||||||
doiEntity.setDoi(finalDoi);
|
// doiEntity.setDoi(finalDoi);
|
||||||
doiEntity.setRepositoryId(depositRequest.getRepositoryId());
|
// doiEntity.setRepositoryId(depositRequest.getRepositoryId());
|
||||||
Date now = new Date();
|
// Date now = new Date();
|
||||||
doiEntity.setCreatedAt(now);
|
// doiEntity.setCreatedAt(now);
|
||||||
doiEntity.setUpdatedAt(now);
|
// doiEntity.setUpdatedAt(now);
|
||||||
doiEntity.setEntityId(dmp);
|
// doiEntity.setEntityId(dmp);
|
||||||
apiContext.getOperationsContext().getDatabaseRepository().getEntityDoiDao().createOrUpdate(doiEntity);
|
// apiContext.getOperationsContext().getDatabaseRepository().getEntityDoiDao().createOrUpdate(doiEntity);
|
||||||
|
//
|
||||||
dmp.getDois().add(doiEntity);
|
// dmp.getDois().add(doiEntity);
|
||||||
apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp);
|
// apiContext.getOperationsContext().getDatabaseRepository().getDmpDao().createOrUpdate(dmp);
|
||||||
|
//
|
||||||
doiModel = new Doi().fromDataModel(doiEntity);
|
// doiModel = new Doi().fromDataModel(doiEntity);
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
if(supportingFilesZip != null) {
|
// if(supportingFilesZip != null) {
|
||||||
Files.deleteIfExists(supportingFilesZip.toPath());
|
// Files.deleteIfExists(supportingFilesZip.toPath());
|
||||||
}
|
// }
|
||||||
Files.deleteIfExists(rdaJsonFile.getFile().toPath());
|
// Files.deleteIfExists(rdaJsonFile.getFile().toPath());
|
||||||
Files.deleteIfExists(pdfFile.toPath());
|
// Files.deleteIfExists(pdfFile.toPath());
|
||||||
Files.deleteIfExists(file.getFile().toPath());
|
// Files.deleteIfExists(file.getFile().toPath());
|
||||||
|
|
||||||
return doiModel;
|
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private File createSupportingFilesZip(DMP dmp) throws IOException {
|
private File createSupportingFilesZip(DMP dmp) throws IOException {
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
package eu.old.eudat.logic.managers;
|
|
||||||
|
|
||||||
import eu.eudat.depositinterface.repository.RepositoryDeposit;
|
|
||||||
import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration;
|
|
||||||
import eu.old.eudat.models.data.doi.DepositRequest;
|
|
||||||
import eu.old.eudat.models.data.doi.Doi;
|
|
||||||
import eu.old.eudat.models.data.doi.RepositoryConfig;
|
|
||||||
import eu.old.eudat.models.data.security.Principal;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
@Component
|
|
||||||
public class DepositManager {
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(DepositManager.class);
|
|
||||||
|
|
||||||
private List<RepositoryDeposit> repositories;
|
|
||||||
private DataManagementPlanManager dataManagementPlanManager;
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public DepositManager(List<RepositoryDeposit> repositories, DataManagementPlanManager dataManagementPlanManager){
|
|
||||||
this.repositories = repositories;
|
|
||||||
this.dataManagementPlanManager = dataManagementPlanManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<RepositoryConfig> getAvailableRepos() {
|
|
||||||
List<RepositoryConfig> reposConfigModel = new ArrayList<>();
|
|
||||||
for (RepositoryDeposit r: this.repositories) {
|
|
||||||
List<RepositoryDepositConfiguration> repoConf = r.getConfiguration();
|
|
||||||
if(repoConf != null) {
|
|
||||||
for(RepositoryDepositConfiguration cf: repoConf){
|
|
||||||
RepositoryConfig repoModel = new RepositoryConfig();
|
|
||||||
reposConfigModel.add(repoModel.toModel(cf));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return reposConfigModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String authenticate(String id, String code) {
|
|
||||||
for(RepositoryDeposit r: this.repositories){
|
|
||||||
if(r.getConfiguration().stream().anyMatch(x -> x.getRepositoryId().equals(id))){
|
|
||||||
return r.authenticate(id, code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Doi deposit(DepositRequest depositRequest, Principal principal) throws Exception {
|
|
||||||
return this.dataManagementPlanManager.createDoi(depositRequest, principal);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRepositoryLogo(String repositoryId){
|
|
||||||
for(RepositoryDeposit r: this.repositories){
|
|
||||||
Optional<RepositoryDepositConfiguration> cf = r.getConfiguration().stream().filter(x -> x.getRepositoryId().equals(repositoryId)).findFirst();
|
|
||||||
if(cf.isPresent()){
|
|
||||||
return cf.get().isHasLogo() ? r.getLogo(repositoryId) : null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,156 +0,0 @@
|
||||||
package eu.old.eudat.logic.security.repositorydeposit.mapper;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import eu.eudat.depositinterface.models.*;
|
|
||||||
import eu.old.eudat.data.entities.*;
|
|
||||||
import eu.old.eudat.logic.utilities.builders.XmlBuilder;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.w3c.dom.Document;
|
|
||||||
import org.w3c.dom.Element;
|
|
||||||
import org.w3c.dom.Node;
|
|
||||||
import org.w3c.dom.NodeList;
|
|
||||||
|
|
||||||
import javax.xml.xpath.*;
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class DMPToDepositMapper {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(DMPToDepositMapper.class);
|
|
||||||
private static final ObjectMapper mapper = new ObjectMapper();
|
|
||||||
|
|
||||||
public static DMPDepositModel fromDMP(DMP entity, FileEnvelope pdfFile, FileEnvelope jsonFile, File supportingFilesZip, String previousDOI) {
|
|
||||||
DMPDepositModel deposit = new DMPDepositModel();
|
|
||||||
deposit.setId(entity.getId());
|
|
||||||
deposit.setVersion(entity.getVersion());
|
|
||||||
deposit.setLabel(entity.getLabel());
|
|
||||||
deposit.setDescription(entity.getDescription());
|
|
||||||
deposit.setPublic(entity.isPublic());
|
|
||||||
deposit.setDatasets(entity.getDataset().stream().map(DMPToDepositMapper::fromDataset).collect(Collectors.toList()));
|
|
||||||
deposit.setUsers(entity.getUsers().stream().map(DMPToDepositMapper::fromUserDMP).collect(Collectors.toSet()));
|
|
||||||
deposit.setOrganisations(entity.getOrganisations().stream().map(DMPToDepositMapper::fromOrganisation).collect(Collectors.toSet()));
|
|
||||||
deposit.setResearchers(entity.getResearchers().stream().map(DMPToDepositMapper::fromResearcher).collect(Collectors.toSet()));
|
|
||||||
if (entity.getGrant() != null) {
|
|
||||||
deposit.setGrant(fromGrant(entity.getGrant()));
|
|
||||||
}
|
|
||||||
|
|
||||||
deposit.setPdfFile(pdfFile);
|
|
||||||
deposit.setRdaJsonFile(jsonFile);
|
|
||||||
deposit.setSupportingFilesZip(supportingFilesZip);
|
|
||||||
deposit.setPreviousDOI(previousDOI);
|
|
||||||
|
|
||||||
deposit.setExtraProperties(entity.getExtraProperties());
|
|
||||||
return deposit;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static DatasetDepositModel fromDataset(Dataset entity){
|
|
||||||
DatasetDepositModel deposit = new DatasetDepositModel();
|
|
||||||
deposit.setLabel(entity.getLabel());
|
|
||||||
deposit.setDescription(entity.getDescription());
|
|
||||||
deposit.setProfileDefinition(entity.getProfile().getDefinition());
|
|
||||||
deposit.setProperties(entity.getProperties());
|
|
||||||
deposit.setFields(fromDefinitionAndProperties(deposit.getProfileDefinition(), deposit.getProperties()));
|
|
||||||
return deposit;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<DatasetFieldsDepositModel> fromDefinitionAndProperties(String definition, String properties){
|
|
||||||
List<DatasetFieldsDepositModel> deposit = new ArrayList<>();
|
|
||||||
try {
|
|
||||||
|
|
||||||
Map<String, Object> datasetAnswers = mapper.readValue(properties, HashMap.class);
|
|
||||||
|
|
||||||
Document document = XmlBuilder.fromXml(definition);
|
|
||||||
XPathFactory xpathFactory = XPathFactory.newInstance();
|
|
||||||
XPath xpath = xpathFactory.newXPath();
|
|
||||||
XPathExpression expr = xpath.compile("//schematics");
|
|
||||||
NodeList schematics = (NodeList) expr.evaluate(document, XPathConstants.NODESET);
|
|
||||||
for (int i = 0; i < schematics.getLength(); i++) {
|
|
||||||
Node schematicsNode = schematics.item(i);
|
|
||||||
NodeList schematicsList = schematicsNode.getChildNodes();
|
|
||||||
DatasetFieldsDepositModel fieldDeposit = new DatasetFieldsDepositModel();
|
|
||||||
List<String> schematicsDeposit = new ArrayList<>();
|
|
||||||
if(schematicsList != null){
|
|
||||||
for(int j = 0; j < schematicsList.getLength(); j++){
|
|
||||||
Node schematic = schematicsList.item(j);
|
|
||||||
if(schematic.getTextContent().matches(".*\\w+.*")) {
|
|
||||||
schematicsDeposit.add(schematic.getTextContent());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fieldDeposit.setSchematics(schematicsDeposit);
|
|
||||||
String fieldId = schematicsNode.getParentNode().getAttributes().getNamedItem("id").getNodeValue();
|
|
||||||
Object value = datasetAnswers.get(fieldId);
|
|
||||||
fieldDeposit.setValue(value);
|
|
||||||
Element field = (Element) schematicsNode.getParentNode();
|
|
||||||
Element viewStyle = (Element) field.getElementsByTagName("viewStyle").item(0);
|
|
||||||
String renderStyle = viewStyle.getAttribute("renderstyle");
|
|
||||||
fieldDeposit.setRenderStyleType(renderStyle);
|
|
||||||
Element data = (Element) field.getElementsByTagName("data").item(0);
|
|
||||||
String multipleSelection = data.getAttribute("multiList");
|
|
||||||
String multipleAutoComplete = data.getAttribute("multiAutoComplete");
|
|
||||||
if(!multipleSelection.isEmpty()){
|
|
||||||
fieldDeposit.setMultiple(Boolean.parseBoolean(multipleSelection));
|
|
||||||
}
|
|
||||||
else if(!multipleAutoComplete.isEmpty()){
|
|
||||||
fieldDeposit.setMultiple(Boolean.parseBoolean(multipleAutoComplete));
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
fieldDeposit.setMultiple(false);
|
|
||||||
}
|
|
||||||
deposit.add(fieldDeposit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (XPathExpressionException | JsonProcessingException ex){
|
|
||||||
logger.error(ex.getMessage(), ex);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return deposit;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static UserDMPDepositModel fromUserDMP(UserDMP entity){
|
|
||||||
UserDMPDepositModel deposit = new UserDMPDepositModel();
|
|
||||||
deposit.setUser(fromUserInfo(entity.getUser()));
|
|
||||||
deposit.setRole(entity.getRole());
|
|
||||||
return deposit;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static UserInfoDepositModel fromUserInfo(UserInfo entity){
|
|
||||||
UserInfoDepositModel deposit = new UserInfoDepositModel();
|
|
||||||
deposit.setName(entity.getName());
|
|
||||||
deposit.setEmail(entity.getEmail());
|
|
||||||
return deposit;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static OrganisationDepositModel fromOrganisation(Organisation entity){
|
|
||||||
OrganisationDepositModel deposit = new OrganisationDepositModel();
|
|
||||||
deposit.setLabel(entity.getLabel());
|
|
||||||
return deposit;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static ResearcherDepositModel fromResearcher(Researcher entity){
|
|
||||||
ResearcherDepositModel deposit = new ResearcherDepositModel();
|
|
||||||
deposit.setLabel(entity.getLabel());
|
|
||||||
deposit.setReference(entity.getReference());
|
|
||||||
return deposit;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static GrantDepositModel fromGrant(Grant entity){
|
|
||||||
GrantDepositModel deposit = new GrantDepositModel();
|
|
||||||
deposit.setId(entity.getId());
|
|
||||||
deposit.setReference(entity.getReference());
|
|
||||||
deposit.setFunder(fromFunder(entity.getFunder()));
|
|
||||||
return deposit;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static FunderDepositModel fromFunder(Funder entity){
|
|
||||||
FunderDepositModel deposit = new FunderDepositModel();
|
|
||||||
deposit.setLabel(entity.getLabel());
|
|
||||||
return deposit;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,10 @@
|
||||||
package eu.old.eudat.migration;
|
package eu.old.eudat.migration;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.type.MapType;
|
||||||
|
import com.fasterxml.jackson.databind.type.TypeFactory;
|
||||||
import eu.eudat.commons.JsonHandlingService;
|
import eu.eudat.commons.JsonHandlingService;
|
||||||
import eu.eudat.commons.enums.*;
|
import eu.eudat.commons.enums.*;
|
||||||
import eu.eudat.commons.types.dmp.DmpBlueprintValueEntity;
|
import eu.eudat.commons.types.dmp.DmpBlueprintValueEntity;
|
||||||
|
@ -116,9 +120,10 @@ public class DmpMigrationService {
|
||||||
}
|
}
|
||||||
if (model.getExtraProperties().containsKey("license") && model.getExtraProperties().get("license") != null) {
|
if (model.getExtraProperties().containsKey("license") && model.getExtraProperties().get("license") != null) {
|
||||||
Object license = model.getExtraProperties().get("license");
|
Object license = model.getExtraProperties().get("license");
|
||||||
|
HashMap<String, String> licenseMap = jsonHandlingService.mapFromJson(jsonHandlingService.toJson(license));
|
||||||
ReferenceEntity referenceEntity = new ReferenceEntity();
|
ReferenceEntity referenceEntity = new ReferenceEntity();
|
||||||
if (Arrays.stream(license.getClass().getFields()).map(Field::getName).toList().contains("pid")) {
|
if (licenseMap.containsKey("pid")) {
|
||||||
referenceEntity.setReference(String.valueOf(license.getClass().getField("pid").get(license)));
|
referenceEntity.setReference(licenseMap.get("pid"));
|
||||||
}
|
}
|
||||||
ReferenceQuery referenceQuery = queryFactory.query(ReferenceQuery.class)
|
ReferenceQuery referenceQuery = queryFactory.query(ReferenceQuery.class)
|
||||||
.references(referenceEntity.getReference())
|
.references(referenceEntity.getReference())
|
||||||
|
@ -127,14 +132,14 @@ public class DmpMigrationService {
|
||||||
List<ReferenceEntity> foundReferences = referenceQuery.collect();
|
List<ReferenceEntity> foundReferences = referenceQuery.collect();
|
||||||
boolean licenseExists = foundReferences != null && !foundReferences.isEmpty();
|
boolean licenseExists = foundReferences != null && !foundReferences.isEmpty();
|
||||||
if (!licenseExists) {
|
if (!licenseExists) {
|
||||||
if (Arrays.stream(license.getClass().getFields()).map(Field::getName).toList().contains("name")) {
|
if (licenseMap.containsKey("name")) {
|
||||||
referenceEntity.setLabel(String.valueOf(license.getClass().getField("name").get(license)));
|
referenceEntity.setLabel(licenseMap.get("name"));
|
||||||
}
|
}
|
||||||
if (Arrays.stream(license.getClass().getFields()).map(Field::getName).toList().contains("uri")) {
|
if (licenseMap.containsKey("uri")) {
|
||||||
referenceEntity.setSource(String.valueOf(license.getClass().getField("uri").get(license)));
|
referenceEntity.setSource(licenseMap.get("uri"));
|
||||||
}
|
}
|
||||||
if (Arrays.stream(license.getClass().getFields()).map(Field::getName).toList().contains("abbreviation")) {
|
if (licenseMap.containsKey("abbreviation")) {
|
||||||
referenceEntity.setAbbreviation(String.valueOf(license.getClass().getField("abbreviation").get(license)));
|
referenceEntity.setAbbreviation(licenseMap.get("abbreviation"));
|
||||||
}
|
}
|
||||||
referenceEntity.setId(UUID.randomUUID());
|
referenceEntity.setId(UUID.randomUUID());
|
||||||
referenceEntity.setSourceType(ReferenceSourceType.External);
|
referenceEntity.setSourceType(ReferenceSourceType.External);
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package eu.old.eudat.models.data.doi;
|
package eu.old.eudat.models.data.doi;
|
||||||
|
|
||||||
import eu.eudat.depositinterface.repository.RepositoryDepositConfiguration;
|
|
||||||
|
|
||||||
public class RepositoryConfig {
|
public class RepositoryConfig {
|
||||||
|
|
||||||
private int depositType;
|
private int depositType;
|
||||||
|
@ -60,15 +58,4 @@ public class RepositoryConfig {
|
||||||
public void setHasLogo(boolean hasLogo) {
|
public void setHasLogo(boolean hasLogo) {
|
||||||
this.hasLogo = hasLogo;
|
this.hasLogo = hasLogo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RepositoryConfig toModel(RepositoryDepositConfiguration r){
|
|
||||||
this.setDepositType(r.getDepositType());
|
|
||||||
this.setRepositoryId(r.getRepositoryId());
|
|
||||||
this.setRepositoryAuthorizationUrl(r.getRepositoryAuthorizationUrl());
|
|
||||||
this.setRepositoryRecordUrl(r.getRepositoryRecordUrl());
|
|
||||||
this.setRepositoryClientId(r.getRepositoryClientId());
|
|
||||||
this.setRedirectUri(r.getRedirectUri());
|
|
||||||
this.setHasLogo(r.isHasLogo());
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,4 +112,63 @@ cache:
|
||||||
keyPattern: reference_$type$_$criteria$:v0
|
keyPattern: reference_$type$_$criteria$:v0
|
||||||
deposit:
|
deposit:
|
||||||
name: deposit
|
name: deposit
|
||||||
keyPattern: base:v0
|
keyPattern: base:v0
|
||||||
|
|
||||||
|
spring:
|
||||||
|
rabbitmq:
|
||||||
|
host: ${RABBIT_HOST}
|
||||||
|
port: ${RABBIT_PORT}
|
||||||
|
username: ${RABBIT_USER}
|
||||||
|
password: ${RABBIT_PASS}
|
||||||
|
ssl:
|
||||||
|
enabled: false
|
||||||
|
queue:
|
||||||
|
rabbitmq:
|
||||||
|
enable: true
|
||||||
|
app-id: ${THE_API_ID}
|
||||||
|
durable: true
|
||||||
|
queue: cite_dmp_devel_web_inbox_queue
|
||||||
|
exchange: cite_dmp_devel_queue
|
||||||
|
listenerEnabled: true
|
||||||
|
publisherEnabled: true
|
||||||
|
#TODO
|
||||||
|
connection-recovery:
|
||||||
|
enable: true
|
||||||
|
network-recovery-interval: 5000
|
||||||
|
unreachable-recovery-interval: 5000
|
||||||
|
task:
|
||||||
|
publisher:
|
||||||
|
enable: true
|
||||||
|
options:
|
||||||
|
exchange: cite_dmp_devel_queue
|
||||||
|
forget-me-completed-topic: forgetme.completed
|
||||||
|
notify-topic: notification.notify
|
||||||
|
tenant-reactivation-topic: tenant.reactivated
|
||||||
|
tenant-removal-topic: tenant.remove
|
||||||
|
tenant-touch-topic: tenant.touch
|
||||||
|
tenant-user-invite-topic: tenant.invite
|
||||||
|
what-you-know-about-me-completed-topic: whatyouknowaboutme.completed
|
||||||
|
generate-file-topic: generate.file
|
||||||
|
rabbitmq:
|
||||||
|
enable: true
|
||||||
|
interval-seconds: 30000
|
||||||
|
options:
|
||||||
|
retry-threashold: 100
|
||||||
|
retry-delay-step-seconds: 300
|
||||||
|
max-retry-delay-seconds: 10800
|
||||||
|
too-old-to-send-seconds: 604800
|
||||||
|
confirm-timeout-seconds: 30
|
||||||
|
listener:
|
||||||
|
enable: true
|
||||||
|
options:
|
||||||
|
exchange: cite_dmp_devel_queue
|
||||||
|
user-removal-topic: [ "user.remove" ]
|
||||||
|
user-touched-topic: [ "user.touch" ]
|
||||||
|
rabbitmq:
|
||||||
|
enable: true
|
||||||
|
interval-seconds: 30000
|
||||||
|
options:
|
||||||
|
retry-threashold: 100
|
||||||
|
retry-delay-step-seconds: 300
|
||||||
|
max-retry-delay-seconds: 10800
|
||||||
|
too-old-to-send-seconds: 604800
|
Loading…
Reference in New Issue