implement public plan, description exports

This commit is contained in:
CITE\amentis 2024-07-31 14:52:47 +03:00
parent 7980579dec
commit 31c2fe2f10
19 changed files with 394 additions and 85 deletions

View File

@ -47,6 +47,8 @@ public class AuditableAction {
public static final EventId Plan_Validate = new EventId(5015, "Plan_Validate");
public static final EventId Plan_GetXml = new EventId(5016, "Plan_GetXml");
public static final EventId Plan_Import = new EventId(5017, "Plan_Import");
public static final EventId Plan_GetPublicXml = new EventId(5017, "Plan_GetPublicXml");
public static final EventId Plan_ExportPublic = new EventId(5018, "Plan_ExportPublic");
public static final EventId Description_Query = new EventId(6000, "Description_Query");
@ -61,8 +63,10 @@ public class AuditableAction {
public static final EventId Description_Validate = new EventId(6009, "Description_Validate");
public static final EventId Description_GetDescriptionSectionPermissions = new EventId(6010, "Description_GetDescriptionSectionPermissions");
public static final EventId Description_UpdateDescriptionTemplate = new EventId(6011, "Description_UpdateDescriptionTemplate");
public static final EventId Description_GetXml = new EventId(6012, "Description_GetXml");
public static final EventId Description_GetPublicXml = new EventId(6013, "Description_GetPublicXml");
public static final EventId Reference_Query = new EventId(7000, "Reference_Query");
public static final EventId Reference_Lookup = new EventId(7001, "Reference_Lookup");
public static final EventId Reference_Persist = new EventId(7002, "Reference_Persist");

View File

@ -12,13 +12,13 @@ import org.opencdmp.commonmodels.models.descriptiotemplate.DescriptionTemplateMo
import org.opencdmp.commonmodels.models.plan.PlanModel;
import org.opencdmp.commons.JsonHandlingService;
import org.opencdmp.commons.XmlHandlingService;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.enums.PlanAccessType;
import org.opencdmp.commons.enums.PlanStatus;
import org.opencdmp.commons.types.description.PropertyDefinitionEntity;
import org.opencdmp.commons.types.descriptiontemplate.DefinitionEntity;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.DescriptionEntity;
import org.opencdmp.data.DescriptionTemplateEntity;
import org.opencdmp.data.PlanDescriptionTemplateEntity;
import org.opencdmp.data.PlanEntity;
import org.opencdmp.data.*;
import org.opencdmp.model.PlanDescriptionTemplate;
import org.opencdmp.model.builder.commonmodels.BaseCommonModelBuilder;
import org.opencdmp.model.builder.commonmodels.CommonModelBuilderItemResponse;
@ -36,9 +36,12 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.management.InvalidApplicationException;
import java.util.*;
import java.util.stream.Collectors;
import static org.opencdmp.authorization.AuthorizationFlags.Public;
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class DescriptionCommonModelBuilder extends BaseCommonModelBuilder<DescriptionModel, DescriptionEntity> {
@ -48,20 +51,22 @@ public class DescriptionCommonModelBuilder extends BaseCommonModelBuilder<Descri
private final BuilderFactory builderFactory;
private final JsonHandlingService jsonHandlingService;
private final XmlHandlingService xmlHandlingService;
private final TenantEntityManager entityManager;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
private String repositoryId;
@Autowired
public DescriptionCommonModelBuilder(
ConventionService conventionService,
QueryFactory queryFactory,
BuilderFactory builderFactory, JsonHandlingService jsonHandlingService, XmlHandlingService xmlHandlingService) {
ConventionService conventionService,
QueryFactory queryFactory,
BuilderFactory builderFactory, JsonHandlingService jsonHandlingService, XmlHandlingService xmlHandlingService, TenantEntityManager entityManager) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(DescriptionCommonModelBuilder.class)));
this.queryFactory = queryFactory;
this.builderFactory = builderFactory;
this.jsonHandlingService = jsonHandlingService;
this.xmlHandlingService = xmlHandlingService;
this.entityManager = entityManager;
}
public DescriptionCommonModelBuilder authorize(EnumSet<AuthorizationFlags> values) {
@ -81,6 +86,12 @@ public class DescriptionCommonModelBuilder extends BaseCommonModelBuilder<Descri
return this;
}
private boolean isPublic;
public DescriptionCommonModelBuilder isPublic(boolean isPublic) {
this.isPublic = isPublic;
return this;
}
@Override
protected List<CommonModelBuilderItemResponse<DescriptionModel, DescriptionEntity>> buildInternal(List<DescriptionEntity> data) throws MyApplicationException {
this.logger.debug("building for {}", Optional.ofNullable(data).map(List::size).orElse(0));
@ -161,8 +172,28 @@ public class DescriptionCommonModelBuilder extends BaseCommonModelBuilder<Descri
this.logger.debug("checking related - {}", PlanModel.class.getSimpleName());
Map<UUID, PlanModel> itemMap;
PlanQuery q = this.queryFactory.query(PlanQuery.class).authorize(this.authorize).disableTracking().ids(data.stream().map(DescriptionEntity::getPlanId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(PlanCommonModelBuilder.class).setRepositoryId(this.repositoryId).useSharedStorage(this.useSharedStorage).setDisableDescriptions(true).authorize(this.authorize).asForeignKey(q, PlanEntity::getId);
PlanQuery q = null;
if (this.isPublic) {
try {
this.entityManager.disableTenantFilters();
q = this.queryFactory.query(PlanQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(data.stream().map(DescriptionEntity::getPlanId).distinct().collect(Collectors.toList())).isActive(IsActive.Active).statuses(PlanStatus.Finalized).accessTypes(PlanAccessType.Public);
itemMap = this.builderFactory.builder(PlanCommonModelBuilder.class).setRepositoryId(this.repositoryId).useSharedStorage(this.useSharedStorage).setDisableDescriptions(true).authorize(this.authorize).asForeignKey(q, PlanEntity::getId);
try {
this.entityManager.reloadTenantFilters();
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
} finally {
try {
this.entityManager.reloadTenantFilters();
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
}
} else {
q = this.queryFactory.query(PlanQuery.class).authorize(this.authorize).disableTracking().ids(data.stream().map(DescriptionEntity::getPlanId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(PlanCommonModelBuilder.class).setRepositoryId(this.repositoryId).useSharedStorage(this.useSharedStorage).setDisableDescriptions(true).authorize(this.authorize).asForeignKey(q, PlanEntity::getId);
}
return itemMap;
}

View File

@ -41,9 +41,12 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.management.InvalidApplicationException;
import java.util.*;
import java.util.stream.Collectors;
import static org.opencdmp.authorization.AuthorizationFlags.Public;
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, PlanEntity> {
@ -53,6 +56,7 @@ public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, Pl
private final BuilderFactory builderFactory;
private final JsonHandlingService jsonHandlingService;
private final XmlHandlingService xmlHandlingService;
private final TenantEntityManager entityManager;
private FileEnvelopeModel pdfFile;
private FileEnvelopeModel rdaJsonFile;
private String repositoryId;
@ -62,12 +66,13 @@ public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, Pl
@Autowired
public PlanCommonModelBuilder(ConventionService conventionService,
QueryFactory queryFactory,
BuilderFactory builderFactory, JsonHandlingService jsonHandlingService, XmlHandlingService xmlHandlingService) {
BuilderFactory builderFactory, JsonHandlingService jsonHandlingService, XmlHandlingService xmlHandlingService, TenantEntityManager entityManager) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(PlanCommonModelBuilder.class)));
this.queryFactory = queryFactory;
this.builderFactory = builderFactory;
this.jsonHandlingService = jsonHandlingService;
this.xmlHandlingService = xmlHandlingService;
this.entityManager = entityManager;
}
public PlanCommonModelBuilder authorize(EnumSet<AuthorizationFlags> values) {
@ -102,6 +107,12 @@ public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, Pl
return this;
}
private boolean isPublic;
public PlanCommonModelBuilder isPublic(boolean isPublic) {
this.isPublic = isPublic;
return this;
}
@Override
protected List<CommonModelBuilderItemResponse<PlanModel, PlanEntity>> buildInternal(List<PlanEntity> data) throws MyApplicationException {
this.logger.debug("building for {}", Optional.ofNullable(data).map(List::size).orElse(0));
@ -204,8 +215,28 @@ public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, Pl
this.logger.debug("checking related - {}", Description.class.getSimpleName());
Map<UUID, List<DescriptionModel>> itemMap;
DescriptionQuery query = this.queryFactory.query(DescriptionQuery.class).disableTracking().isActive(IsActive.Active).authorize(this.authorize).planIds(data.stream().map(PlanEntity::getId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(DescriptionCommonModelBuilder.class).setRepositoryId(this.repositoryId).useSharedStorage(this.useSharedStorage).authorize(this.authorize).asMasterKey(query, DescriptionEntity::getPlanId);
DescriptionQuery query = null;
if (this.isPublic) {
try {
this.entityManager.disableTenantFilters();
query = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(EnumSet.of(Public)).planIds(data.stream().map(PlanEntity::getId).distinct().collect(Collectors.toList())).planSubQuery(this.queryFactory.query(PlanQuery.class).isActive(IsActive.Active).statuses(org.opencdmp.commons.enums.PlanStatus.Finalized).accessTypes(org.opencdmp.commons.enums.PlanAccessType.Public));
itemMap = this.builderFactory.builder(DescriptionCommonModelBuilder.class).setRepositoryId(this.repositoryId).useSharedStorage(this.useSharedStorage).isPublic(this.isPublic).authorize(this.authorize).asMasterKey(query, DescriptionEntity::getPlanId);
try {
this.entityManager.reloadTenantFilters();
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
} finally {
try {
this.entityManager.reloadTenantFilters();
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
}
} else {
query = this.queryFactory.query(DescriptionQuery.class).disableTracking().isActive(IsActive.Active).authorize(this.authorize).planIds(data.stream().map(PlanEntity::getId).distinct().collect(Collectors.toList()));
itemMap = this.builderFactory.builder(DescriptionCommonModelBuilder.class).setRepositoryId(this.repositoryId).useSharedStorage(this.useSharedStorage).isPublic(this.isPublic).authorize(this.authorize).asMasterKey(query, DescriptionEntity::getPlanId);
}
return itemMap;
}
@ -248,7 +279,7 @@ public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, Pl
return null;
this.logger.debug("checking related - {}", DefinitionEntity.class.getSimpleName());
Map<java.util.UUID, DefinitionEntity> itemMap = new HashMap<>();
Map<UUID, DefinitionEntity> itemMap = new HashMap<>();
PlanBlueprintQuery q = this.queryFactory.query(PlanBlueprintQuery.class).disableTracking().authorize(this.authorize).ids(data.stream().map(PlanEntity::getBlueprintId).distinct().collect(Collectors.toList()));
List<PlanBlueprintEntity> items = q.collectAs(new BaseFieldSet().ensure(PlanBlueprint._id).ensure(PlanBlueprint._definition));
for (PlanBlueprintEntity item : items){

View File

@ -296,8 +296,8 @@ public class DepositServiceImpl implements DepositService {
accessToken = this.authenticate(authenticateRequest);
}
org.opencdmp.model.file.FileEnvelope pdfFile = this.fileTransformerService.exportPlan(planEntity.getId(), source.getPdfTransformerId(),"pdf");
org.opencdmp.model.file.FileEnvelope rda = this.fileTransformerService.exportPlan(planEntity.getId(), source.getRdaTransformerId(),"json");
org.opencdmp.model.file.FileEnvelope pdfFile = this.fileTransformerService.exportPlan(planEntity.getId(), source.getPdfTransformerId(),"pdf", false);
org.opencdmp.model.file.FileEnvelope rda = this.fileTransformerService.exportPlan(planEntity.getId(), source.getRdaTransformerId(),"json", false);
FileEnvelopeModel pdfEnvelope = new FileEnvelopeModel();
FileEnvelopeModel jsonEnvelope = new FileEnvelopeModel();

View File

@ -42,16 +42,18 @@ public interface DescriptionService {
List<DescriptionValidationResult> validate(List<UUID> descriptionIds) throws InvalidApplicationException;
ResponseEntity<byte[]> export(UUID id, String exportType) throws InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException;
ResponseEntity<byte[]> export(UUID id, String exportType, boolean isPublic) throws InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException;
StorageFile uploadFieldFile(DescriptionFieldFilePersist model, MultipartFile file, FieldSet fields) throws IOException;
StorageFileEntity getFieldFile(UUID descriptionId, UUID storageFileId);
void updateDescriptionTemplate(UpdateDescriptionTemplatePersist model) throws InvalidApplicationException, IOException, JAXBException;
DescriptionImportExport exportXmlEntity(UUID id, boolean ignoreAuthorize) throws MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException;
DescriptionImportExport exportXmlEntity(UUID id, boolean ignoreAuthorize, boolean isPublic) throws MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException;
ResponseEntity<byte[]> exportXml(UUID id) throws MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException;
ResponseEntity<byte[]> exportPublicXml(UUID id) throws MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException;
Description importXml(DescriptionImportExport descriptionXml, UUID planId, FieldSet fields) throws MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, TransformerException, InvalidApplicationException, IOException, InstantiationException, IllegalAccessException, SAXException;
Description importCommonModel(DescriptionModel model, UUID planId, FieldSet fields) throws MyForbiddenException, MyNotFoundException, InvalidApplicationException, IOException, JAXBException, ParserConfigurationException, TransformerException, InstantiationException, IllegalAccessException, SAXException;

View File

@ -50,10 +50,7 @@ import org.opencdmp.integrationevent.outbox.annotationentityremoval.AnnotationEn
import org.opencdmp.integrationevent.outbox.annotationentitytouch.AnnotationEntityTouchedIntegrationEventHandler;
import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEvent;
import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEventHandler;
import org.opencdmp.model.DescriptionValidationResult;
import org.opencdmp.model.PlanDescriptionTemplate;
import org.opencdmp.model.StorageFile;
import org.opencdmp.model.Tag;
import org.opencdmp.model.*;
import org.opencdmp.model.builder.description.DescriptionBuilder;
import org.opencdmp.model.deleter.DescriptionDeleter;
import org.opencdmp.model.deleter.DescriptionReferenceDeleter;
@ -110,6 +107,8 @@ import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
import static org.opencdmp.authorization.AuthorizationFlags.Public;
@Service
public class DescriptionServiceImpl implements DescriptionService {
@ -912,10 +911,10 @@ public class DescriptionServiceImpl implements DescriptionService {
//region file export
@Override
public ResponseEntity<byte[]> export(UUID id, String exportType) throws InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
public ResponseEntity<byte[]> export(UUID id, String exportType, boolean isPublic) throws InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
HttpHeaders headers = new HttpHeaders();
FileEnvelope fileEnvelope = this.fileTransformerService.exportDescription(id, null, exportType); //TODO get repo from config
FileEnvelope fileEnvelope = this.fileTransformerService.exportDescription(id, null, exportType, isPublic); //TODO get repo from config
headers.add("Content-Disposition", "attachment;filename=" + fileEnvelope.getFilename());
byte[] data = fileEnvelope.getFile();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
@ -1164,11 +1163,22 @@ public class DescriptionServiceImpl implements DescriptionService {
//region Export
@Override
public DescriptionImportExport exportXmlEntity(UUID id, boolean ignoreAuthorize) throws MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException {
public DescriptionImportExport exportXmlEntity(UUID id, boolean ignoreAuthorize, boolean isPublic) throws MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException {
logger.debug(new MapLogEntry("export xml").And("id", id));
if (!ignoreAuthorize) this.authorizationService.authorizeForce(Permission.ExportDescription);
DescriptionEntity data = this.queryFactory.query(DescriptionQuery.class).disableTracking().ids(id).authorize(AuthorizationFlags.All).isActive(IsActive.Active).first();
DescriptionEntity data = null;
if (!isPublic) {
data = this.queryFactory.query(DescriptionQuery.class).disableTracking().ids(id).authorize(AuthorizationFlags.All).isActive(IsActive.Active).first();
} else {
try {
this.entityManager.disableTenantFilters();
data = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(id).planSubQuery(this.queryFactory.query(PlanQuery.class).isActive(IsActive.Active).statuses(PlanStatus.Finalized).accessTypes(PlanAccessType.Public)).first();
this.entityManager.reloadTenantFilters();
} finally {
this.entityManager.reloadTenantFilters();
}
}
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
PropertyDefinitionEntity definition = this.jsonHandlingService.fromJson(PropertyDefinitionEntity.class, data.getProperties());
@ -1183,7 +1193,28 @@ public class DescriptionServiceImpl implements DescriptionService {
DescriptionEntity data = this.queryFactory.query(DescriptionQuery.class).disableTracking().ids(id).authorize(AuthorizationFlags.All).isActive(IsActive.Active).first();
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
String xml = this.xmlHandlingService.toXml(this.exportXmlEntity(data.getId(), false));
String xml = this.xmlHandlingService.toXml(this.exportXmlEntity(data.getId(), false, false));
this.accountingService.increase(UsageLimitTargetMetric.EXPORT_DESCRIPTION_XML_EXECUTION_COUNT.getValue());
return this.responseUtilsService.buildResponseFileFromText(xml, data.getLabel() + ".xml");
}
@Override
public ResponseEntity<byte[]> exportPublicXml(UUID id) throws MyForbiddenException, MyNotFoundException, JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException {
logger.debug(new MapLogEntry("export xml").And("id", id));
this.authorizationService.authorizeForce(Permission.ExportDescription);
DescriptionEntity data = null;
try {
this.entityManager.disableTenantFilters();
data = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(id).planSubQuery(this.queryFactory.query(PlanQuery.class).isActive(IsActive.Active).statuses(PlanStatus.Finalized).accessTypes(PlanAccessType.Public)).first();
this.entityManager.reloadTenantFilters();
} finally {
this.entityManager.reloadTenantFilters();
}
if (data == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{id, PublicDescription.class.getSimpleName()}, LocaleContextHolder.getLocale()));
String xml = this.xmlHandlingService.toXml(this.exportXmlEntity(data.getId(), false, true));
this.accountingService.increase(UsageLimitTargetMetric.EXPORT_DESCRIPTION_XML_EXECUTION_COUNT.getValue());
return this.responseUtilsService.buildResponseFileFromText(xml, data.getLabel() + ".xml");
}

View File

@ -20,9 +20,9 @@ import java.util.UUID;
public interface FileTransformerService {
List<RepositoryFileFormat> getAvailableExportFileFormats() throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException;
org.opencdmp.model.file.FileEnvelope exportPlan(UUID planId, String repositoryId, String format) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException;
org.opencdmp.model.file.FileEnvelope exportPlan(UUID planId, String repositoryId, String format, boolean isPublic) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException;
org.opencdmp.model.file.FileEnvelope exportDescription(UUID descriptionId, String repositoryId, String format) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException;
org.opencdmp.model.file.FileEnvelope exportDescription(UUID descriptionId, String repositoryId, String format, boolean isPublic) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException;
PlanModel importPlan(PlanCommonModelConfig planCommonModelConfig) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException, IOException, JAXBException;

View File

@ -22,23 +22,19 @@ import org.opencdmp.commonmodels.models.descriptiotemplate.DescriptionTemplateMo
import org.opencdmp.commonmodels.models.plan.PlanModel;
import org.opencdmp.commonmodels.models.planblueprint.PlanBlueprintModel;
import org.opencdmp.commons.JsonHandlingService;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.enums.StorageType;
import org.opencdmp.commons.enums.TenantConfigurationType;
import org.opencdmp.commons.enums.UsageLimitTargetMetric;
import org.opencdmp.commons.enums.*;
import org.opencdmp.commons.scope.tenant.TenantScope;
import org.opencdmp.commons.scope.user.UserScope;
import org.opencdmp.commons.types.filetransformer.FileTransformerSourceEntity;
import org.opencdmp.commons.types.tenantconfiguration.FileTransformerTenantConfigurationEntity;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.DescriptionTemplateEntity;
import org.opencdmp.data.StorageFileEntity;
import org.opencdmp.data.TenantConfigurationEntity;
import org.opencdmp.data.*;
import org.opencdmp.event.TenantConfigurationTouchedEvent;
import org.opencdmp.filetransformerbase.interfaces.FileTransformerConfiguration;
import org.opencdmp.filetransformerbase.models.misc.DescriptionImportModel;
import org.opencdmp.filetransformerbase.models.misc.PlanImportModel;
import org.opencdmp.filetransformerbase.models.misc.PreprocessingPlanModel;
import org.opencdmp.model.PublicPlan;
import org.opencdmp.model.StorageFile;
import org.opencdmp.model.builder.commonmodels.description.DescriptionCommonModelBuilder;
import org.opencdmp.model.builder.commonmodels.descriptiontemplate.DescriptionTemplateCommonModelBuilder;
@ -82,6 +78,8 @@ import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.stream.Collectors;
import static org.opencdmp.authorization.AuthorizationFlags.Public;
@Service
public class FileTransformerServiceImpl implements FileTransformerService {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(FileTransformerServiceImpl.class));
@ -102,10 +100,11 @@ public class FileTransformerServiceImpl implements FileTransformerService {
private final FileTransformerSourcesCacheService fileTransformerSourcesCacheService;
private final UserScope userScope;
private final AccountingService accountingService;
private final TenantEntityManager entityManager;
@Autowired
public FileTransformerServiceImpl(FileTransformerProperties fileTransformerProperties, TokenExchangeCacheService tokenExchangeCacheService, FileTransformerConfigurationCacheService fileTransformerConfigurationCacheService, AuthorizationService authorizationService,
QueryFactory queryFactory, BuilderFactory builderFactory, StorageFileService storageFileService, MessageSource messageSource, ConventionService conventionService, TenantScope tenantScope, EncryptionService encryptionService, TenantProperties tenantProperties, JsonHandlingService jsonHandlingService, FileTransformerSourcesCacheService fileTransformerSourcesCacheService, UserScope userScope, AccountingService accountingService) {
QueryFactory queryFactory, BuilderFactory builderFactory, StorageFileService storageFileService, MessageSource messageSource, ConventionService conventionService, TenantScope tenantScope, EncryptionService encryptionService, TenantProperties tenantProperties, JsonHandlingService jsonHandlingService, FileTransformerSourcesCacheService fileTransformerSourcesCacheService, UserScope userScope, AccountingService accountingService, TenantEntityManager entityManager) {
this.fileTransformerProperties = fileTransformerProperties;
this.tokenExchangeCacheService = tokenExchangeCacheService;
this.fileTransformerConfigurationCacheService = fileTransformerConfigurationCacheService;
@ -122,6 +121,7 @@ public class FileTransformerServiceImpl implements FileTransformerService {
this.fileTransformerSourcesCacheService = fileTransformerSourcesCacheService;
this.userScope = userScope;
this.accountingService = accountingService;
this.entityManager = entityManager;
this.clients = new HashMap<>();
}
@ -256,14 +256,28 @@ public class FileTransformerServiceImpl implements FileTransformerService {
}
@Override
public org.opencdmp.model.file.FileEnvelope exportPlan(UUID planId, String repositoryId, String format) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
public org.opencdmp.model.file.FileEnvelope exportPlan(UUID planId, String repositoryId, String format, boolean isPublic) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
this.authorizationService.authorizeForce(Permission.ExportPlan);
//GK: First get the right client
FileTransformerRepository repository = this.getRepository(repositoryId);
if (repository == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{format, FileTransformerRepository.class.getSimpleName()}, LocaleContextHolder.getLocale()));
//GK: Second get the Target Data Management Plan
PlanQuery query = this.queryFactory.query(PlanQuery.class).disableTracking().authorize(AuthorizationFlags.All).ids(planId);
PlanModel planFileTransformerModel = this.builderFactory.builder(PlanCommonModelBuilder.class).useSharedStorage(repository.getConfiguration().isUseSharedStorage()).setRepositoryId(repository.getConfiguration().getFileTransformerId()).authorize(AuthorizationFlags.All).build(query.first());
PlanEntity entity = null;
if (!isPublic) {
entity = this.queryFactory.query(PlanQuery.class).disableTracking().authorize(AuthorizationFlags.All).ids(planId).first();
} else {
try {
this.entityManager.disableTenantFilters();
entity = this.queryFactory.query(PlanQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(planId).isActive(IsActive.Active).statuses(PlanStatus.Finalized).accessTypes(PlanAccessType.Public).first();
this.entityManager.reloadTenantFilters();
} finally {
this.entityManager.reloadTenantFilters();
}
}
if (entity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{planId, Plan.class.getSimpleName()}, LocaleContextHolder.getLocale()));
PlanModel planFileTransformerModel = this.builderFactory.builder(PlanCommonModelBuilder.class).useSharedStorage(repository.getConfiguration().isUseSharedStorage()).setRepositoryId(repository.getConfiguration().getFileTransformerId()).isPublic(isPublic).authorize(AuthorizationFlags.All).build(entity);
if (planFileTransformerModel == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{planId, Plan.class.getSimpleName()}, LocaleContextHolder.getLocale()));
FileEnvelopeModel fileEnvelope = repository.exportPlan(planFileTransformerModel, format);
@ -280,15 +294,29 @@ public class FileTransformerServiceImpl implements FileTransformerService {
}
@Override
public org.opencdmp.model.file.FileEnvelope exportDescription(UUID descriptionId, String repositoryId, String format) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
public org.opencdmp.model.file.FileEnvelope exportDescription(UUID descriptionId, String repositoryId, String format, boolean isPublic) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
this.authorizationService.authorizeForce(Permission.ExportDescription);
//GK: First get the right client
FileTransformerRepository repository = this.getRepository(repositoryId);
if (repository == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{format, FileTransformerRepository.class.getSimpleName()}, LocaleContextHolder.getLocale()));
//GK: Second get the Target Data Management Plan
DescriptionQuery query = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(AuthorizationFlags.All).ids(descriptionId);
DescriptionModel descriptionFileTransformerModel = this.builderFactory.builder(DescriptionCommonModelBuilder.class).setRepositoryId(repository.getConfiguration().getFileTransformerId()).useSharedStorage(repository.getConfiguration().isUseSharedStorage()).authorize(AuthorizationFlags.All).build(query.first());
DescriptionEntity entity = null;
if (!isPublic){
entity = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(AuthorizationFlags.All).ids(descriptionId).first();
} else {
try {
this.entityManager.disableTenantFilters();
entity = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(EnumSet.of(Public)).ids(descriptionId).planSubQuery(this.queryFactory.query(PlanQuery.class).isActive(IsActive.Active).statuses(PlanStatus.Finalized).accessTypes(PlanAccessType.Public)).first();
this.entityManager.reloadTenantFilters();
} finally {
this.entityManager.reloadTenantFilters();
}
}
if (entity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{descriptionId, Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
DescriptionModel descriptionFileTransformerModel = this.builderFactory.builder(DescriptionCommonModelBuilder.class).setRepositoryId(repository.getConfiguration().getFileTransformerId()).useSharedStorage(repository.getConfiguration().isUseSharedStorage()).isPublic(isPublic).authorize(AuthorizationFlags.All).build(entity);
if (descriptionFileTransformerModel == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{descriptionId, Description.class.getSimpleName()}, LocaleContextHolder.getLocale()));
FileEnvelopeModel fileEnvelope = repository.exportDescription(descriptionFileTransformerModel, format);

View File

@ -336,7 +336,20 @@ public class DescriptionController {
) throws InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
logger.debug(new MapLogEntry("exporting description"));
return this.descriptionService.export(id, exportType);
return this.descriptionService.export(id, exportType, true);
}
@GetMapping("{id}/export-public/{type}")
@OperationWithTenantHeader(summary = "Export a public description in various formats by id", description = "",
responses = @ApiResponse(description = "OK", responseCode = "200"))
@Swagger404
public ResponseEntity<byte[]> exportPublic(
@Parameter(name = "id", description = "The id of a public description to export", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID id,
@Parameter(name = "type", description = "The type of the export", example = "rda", required = true) @PathVariable("type") String exportType
) throws InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
logger.debug(new MapLogEntry("exporting description"));
return this.descriptionService.export(id, exportType, false);
}
@PostMapping("field-file/upload")
@ -423,11 +436,28 @@ public class DescriptionController {
public @ResponseBody ResponseEntity<byte[]> getXml(
@Parameter(name = "id", description = "The id of a description to export", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable UUID id
) throws JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException {
logger.debug(new MapLogEntry("export" + PlanBlueprint.class.getSimpleName()).And("id", id));
logger.debug(new MapLogEntry("export" + Description.class.getSimpleName()).And("id", id));
ResponseEntity<byte[]> response = this.descriptionService.exportXml(id);
this.auditService.track(AuditableAction.PlanBlueprint_GetXml, Map.ofEntries(
this.auditService.track(AuditableAction.Description_GetXml, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("id", id)
));
return response;
}
@RequestMapping(method = RequestMethod.GET, value = "/xml/export-public/{id}", produces = "application/xml")
@OperationWithTenantHeader(summary = "Export a public description in xml format by id", description = "",
responses = @ApiResponse(description = "OK", responseCode = "200"))
@Swagger404
public @ResponseBody ResponseEntity<byte[]> getPublicXml(
@Parameter(name = "id", description = "The id of a public description to export", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable UUID id
) throws JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException {
logger.debug(new MapLogEntry("export public" + PublicDescription.class.getSimpleName()).And("id", id));
ResponseEntity<byte[]> response = this.descriptionService.exportPublicXml(id);
this.auditService.track(AuditableAction.Description_GetPublicXml, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("id", id)
));
return response;

View File

@ -77,7 +77,21 @@ public class FileTransformerController {
logger.debug(new MapLogEntry("exporting plan"));
HttpHeaders headers = new HttpHeaders();
FileEnvelope fileEnvelope = this.fileTransformerService.exportPlan(requestModel.getId(), requestModel.getRepositoryId(), requestModel.getFormat());
FileEnvelope fileEnvelope = this.fileTransformerService.exportPlan(requestModel.getId(), requestModel.getRepositoryId(), requestModel.getFormat(), false);
headers.add("Content-Disposition", "attachment;filename=" + fileEnvelope.getFilename());
byte[] data = fileEnvelope.getFile();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity<>(data, headers, HttpStatus.OK);
}
@PostMapping("/export-public-plan")
@OperationWithTenantHeader(summary = "Export a public published plan", description = SwaggerHelpers.FileTransformer.endpoint_export_plans,
responses = @ApiResponse(description = "OK", responseCode = "200"))
public ResponseEntity<byte[]> exportPublicPlan(@RequestBody ExportRequestModel requestModel) throws InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
logger.debug(new MapLogEntry("exporting plan"));
HttpHeaders headers = new HttpHeaders();
FileEnvelope fileEnvelope = this.fileTransformerService.exportPlan(requestModel.getId(), requestModel.getRepositoryId(), requestModel.getFormat(), true);
headers.add("Content-Disposition", "attachment;filename=" + fileEnvelope.getFilename());
byte[] data = fileEnvelope.getFile();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
@ -91,7 +105,21 @@ public class FileTransformerController {
logger.debug(new MapLogEntry("exporting description"));
HttpHeaders headers = new HttpHeaders();
FileEnvelope fileEnvelope = this.fileTransformerService.exportDescription(requestModel.getId(), requestModel.getRepositoryId(), requestModel.getFormat());
FileEnvelope fileEnvelope = this.fileTransformerService.exportDescription(requestModel.getId(), requestModel.getRepositoryId(), requestModel.getFormat(), false);
headers.add("Content-Disposition", "attachment;filename=" + fileEnvelope.getFilename());
byte[] data = fileEnvelope.getFile();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
return new ResponseEntity<>(data, headers, HttpStatus.OK);
}
@PostMapping("/export-public-description")
@OperationWithTenantHeader(summary = "Export a public description", description = SwaggerHelpers.FileTransformer.endpoint_export_descriptions,
responses = @ApiResponse(description = "OK", responseCode = "200"))
public ResponseEntity<byte[]> exportPublicDescription(@RequestBody ExportRequestModel requestModel) throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
logger.debug(new MapLogEntry("exporting description"));
HttpHeaders headers = new HttpHeaders();
FileEnvelope fileEnvelope = this.fileTransformerService.exportDescription(requestModel.getId(), requestModel.getRepositoryId(), requestModel.getFormat(), true);
headers.add("Content-Disposition", "attachment;filename=" + fileEnvelope.getFilename());
byte[] data = fileEnvelope.getFile();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

View File

@ -408,7 +408,7 @@ public class PlanController {
) throws InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
logger.debug(new MapLogEntry("exporting plan").And("id", id).And("transformerId", transformerId).And("exportType", exportType));
ResponseEntity<byte[]> bytes = this.planService.export(id, transformerId, exportType);
ResponseEntity<byte[]> bytes = this.planService.export(id, transformerId, exportType, false);
this.auditService.track(AuditableAction.Plan_Export, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("id", id),
new AbstractMap.SimpleEntry<String, Object>("transformerId", transformerId),
@ -417,6 +417,26 @@ public class PlanController {
return bytes;
}
@GetMapping("{id}/export-public/{transformerId}/{type}")
@OperationWithTenantHeader(summary = "Export a public published plan in various formats by id", description = "",
responses = @ApiResponse(description = "OK", responseCode = "200"))
@Swagger404
public ResponseEntity<byte[]> exportPublic(
@Parameter(name = "id", description = "The id of a public published plan to export", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable("id") UUID id,
@PathVariable("transformerId") String transformerId,
@PathVariable("type") String exportType
) throws InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
logger.debug(new MapLogEntry("exporting plan").And("id", id).And("transformerId", transformerId).And("exportType", exportType));
ResponseEntity<byte[]> bytes = this.planService.export(id, transformerId, exportType, true);
this.auditService.track(AuditableAction.Plan_ExportPublic, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("id", id),
new AbstractMap.SimpleEntry<String, Object>("transformerId", transformerId),
new AbstractMap.SimpleEntry<String, Object>("exportType", exportType)
));
return bytes;
}
@PostMapping("{id}/invite-users")
@OperationWithTenantHeader(summary = "Send user invitations for the plan by id")
@Transactional
@ -467,6 +487,23 @@ public class PlanController {
return response;
}
@RequestMapping(method = RequestMethod.GET, value = "/xml/export-public/{id}", produces = "application/xml")
@OperationWithTenantHeader(summary = "Export a public published plan in xml format by id", description = "",
responses = @ApiResponse(description = "OK", responseCode = "200"))
@Swagger404
public @ResponseBody ResponseEntity<byte[]> getPublicXml(
@Parameter(name = "id", description = "The id of a public published plan to export", example = "c0c163dc-2965-45a5-9608-f76030578609", required = true) @PathVariable UUID id
) throws JAXBException, ParserConfigurationException, IOException, InstantiationException, IllegalAccessException, SAXException, InvalidApplicationException {
logger.debug(new MapLogEntry("export public" + PublicPlan.class.getSimpleName()).And("id", id));
ResponseEntity<byte[]> response = this.planService.exportPublicXml(id);
this.auditService.track(AuditableAction.Plan_GetPublicXml, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("id", id)
));
return response;
}
@RequestMapping(method = RequestMethod.POST, value = "/xml/import")
@OperationWithTenantHeader(summary = "Import a plan from an xml file", description = "",
responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content(

View File

@ -117,6 +117,17 @@ export class DescriptionService {
return this.httpClient.get(url, { params: params, responseType: 'blob', observe: 'response', headers: headerXml });
}
downloadPublicXML(id: Guid): Observable<HttpResponse<Blob>> {
const url = `${this.apiBase}/xml/export-public/${id}`;
let headerXml: HttpHeaders = this.headers.set('Content-Type', 'application/xml');
const params = new BaseHttpParams();
params.interceptorContext = {
excludedInterceptors: [InterceptorType.JSONContentType]
};
return this.httpClient.get(url, { params: params, responseType: 'blob', observe: 'response', headers: headerXml });
}
public updateDescriptionTemplate(item: UpdateDescriptionTemplatePersist): Observable<boolean> {
const url = `${this.apiBase}/update-description-template`;

View File

@ -30,8 +30,18 @@ export class FileTransformerHttpService extends BaseService {
return this.http.post<any>(url, {id: planId, repositoryId: repositoryId, format: format}, {responseType: 'blob', observe: 'response'}).pipe(catchError((error: any) => throwError(error)));
}
exportPublicPlan(planId: Guid, repositoryId: string, format: string): Observable<any> {
const url = `${this.apiBase}/export-public-plan`;
return this.http.post<any>(url, {id: planId, repositoryId: repositoryId, format: format}, {responseType: 'blob', observe: 'response'}).pipe(catchError((error: any) => throwError(error)));
}
exportDescription(id: Guid, repositoryId: string, format: string): Observable<any> {
const url = `${this.apiBase}/export-description`;
return this.http.post<any>(url, {id: id, repositoryId: repositoryId, format: format}, {responseType: 'blob', observe: 'response'}).pipe(catchError((error: any) => throwError(error)));
}
exportPublicDescription(id: Guid, repositoryId: string, format: string): Observable<any> {
const url = `${this.apiBase}/export-public-description`;
return this.http.post<any>(url, {id: id, repositoryId: repositoryId, format: format}, {responseType: 'blob', observe: 'response'}).pipe(catchError((error: any) => throwError(error)));
}
}

View File

@ -67,10 +67,11 @@ export class FileTransformerService extends BaseService {
});
}
exportPlan(id: Guid, repositoryId: string, format: string) {
exportPlan(id: Guid, repositoryId: string, format: string, isPublic: boolean = false) {
this._loading = true;
if (repositoryId == this.xmlExportRepo.repositoryId) {
this.planService.downloadXML(id)
if (!isPublic) {
this.planService.downloadXML(id)
.pipe(takeUntil(this._destroyed))
.subscribe(response => {
const blob = new Blob([response.body], { type: 'application/xml' });
@ -78,28 +79,56 @@ export class FileTransformerService extends BaseService {
FileSaver.saveAs(blob, filename);
},
error => this.httpErrorHandlingService.handleBackedRequestError(error));
} else {
this.fileTransformerHttpService.exportPlan(id, repositoryId, format).pipe(takeUntil(this._destroyed), catchError((error) => {
this._loading = false;
return null;
}))
.subscribe(result => {
if (result !== null) {
const blob = new Blob([result.body], { type: 'application/octet-stream' });
const filename = this.fileUtils.getFilenameFromContentDispositionHeader(result.headers.get('Content-Disposition'));
} else {
this.planService.downloadPublicXML(id)
.pipe(takeUntil(this._destroyed))
.subscribe(response => {
const blob = new Blob([response.body], { type: 'application/xml' });
const filename = this.fileUtils.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.analyticsService.trackDownload(AnalyticsService.trackPlan, format, id.toString());
}
},
error => this.httpErrorHandlingService.handleBackedRequestError(error));
},
error => this.httpErrorHandlingService.handleBackedRequestError(error));
}
} else {
if (!isPublic) {
this.fileTransformerHttpService.exportPlan(id, repositoryId, format).pipe(takeUntil(this._destroyed), catchError((error) => {
this._loading = false;
return null;
}))
.subscribe(result => {
if (result !== null) {
const blob = new Blob([result.body], { type: 'application/octet-stream' });
const filename = this.fileUtils.getFilenameFromContentDispositionHeader(result.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.analyticsService.trackDownload(AnalyticsService.trackPlan, format, id.toString());
}
},
error => this.httpErrorHandlingService.handleBackedRequestError(error));
} else {
this.fileTransformerHttpService.exportPublicPlan(id, repositoryId, format).pipe(takeUntil(this._destroyed), catchError((error) => {
this._loading = false;
return null;
}))
.subscribe(result => {
if (result !== null) {
const blob = new Blob([result.body], { type: 'application/octet-stream' });
const filename = this.fileUtils.getFilenameFromContentDispositionHeader(result.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.analyticsService.trackDownload(AnalyticsService.trackPlan, format, id.toString());
}
},
error => this.httpErrorHandlingService.handleBackedRequestError(error));
}
}
}
exportDescription(id: Guid, repositoryId: string, format: string) {
exportDescription(id: Guid, repositoryId: string, format: string, isPublic: boolean = false) {
this._loading = true;
if (repositoryId == this.xmlExportRepo.repositoryId) {
this.descriptionService.downloadXML(id)
if (!isPublic) {
this.descriptionService.downloadXML(id)
.pipe(takeUntil(this._destroyed))
.subscribe(response => {
const blob = new Blob([response.body], { type: 'application/xml' });
@ -107,21 +136,48 @@ export class FileTransformerService extends BaseService {
FileSaver.saveAs(blob, filename);
},
error => this.httpErrorHandlingService.handleBackedRequestError(error));
} else {
this.fileTransformerHttpService.exportDescription(id, repositoryId, format).pipe(takeUntil(this._destroyed), catchError((error) => {
this._loading = false;
return null;
}))
.subscribe(result => {
if (result !== null) {
const blob = new Blob([result.body], { type: 'application/octet-stream' });
const filename = this.fileUtils.getFilenameFromContentDispositionHeader(result.headers.get('Content-Disposition'));
} else {
this.descriptionService.downloadPublicXML(id)
.pipe(takeUntil(this._destroyed))
.subscribe(response => {
const blob = new Blob([response.body], { type: 'application/xml' });
const filename = this.fileUtils.getFilenameFromContentDispositionHeader(response.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.analyticsService.trackDownload(AnalyticsService.trackDescriptions, format, id.toString());
}
},
error => this.httpErrorHandlingService.handleBackedRequestError(error));
},
error => this.httpErrorHandlingService.handleBackedRequestError(error));
}
} else {
if (!isPublic) {
this.fileTransformerHttpService.exportDescription(id, repositoryId, format).pipe(takeUntil(this._destroyed), catchError((error) => {
this._loading = false;
return null;
}))
.subscribe(result => {
if (result !== null) {
const blob = new Blob([result.body], { type: 'application/octet-stream' });
const filename = this.fileUtils.getFilenameFromContentDispositionHeader(result.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.analyticsService.trackDownload(AnalyticsService.trackDescriptions, format, id.toString());
}
},
error => this.httpErrorHandlingService.handleBackedRequestError(error));
} else {
this.fileTransformerHttpService.exportPublicDescription(id, repositoryId, format).pipe(takeUntil(this._destroyed), catchError((error) => {
this._loading = false;
return null;
}))
.subscribe(result => {
if (result !== null) {
const blob = new Blob([result.body], { type: 'application/octet-stream' });
const filename = this.fileUtils.getFilenameFromContentDispositionHeader(result.headers.get('Content-Disposition'));
FileSaver.saveAs(blob, filename);
this.analyticsService.trackDownload(AnalyticsService.trackDescriptions, format, id.toString());
}
},
error => this.httpErrorHandlingService.handleBackedRequestError(error));
}
}
}
}

View File

@ -179,6 +179,16 @@ export class PlanService {
return this.httpClient.get(url, { params: params, responseType: 'blob', observe: 'response', headers: headerXml });
}
downloadPublicXML(id: Guid): Observable<HttpResponse<Blob>> {
const url = `${this.apiBase}/xml/export-public/${id}`;
let headerXml: HttpHeaders = this.headers.set('Content-Type', 'application/xml');
const params = new BaseHttpParams();
params.interceptorContext = {
excludedInterceptors: [InterceptorType.JSONContentType]
};
return this.httpClient.get(url, { params: params, responseType: 'blob', observe: 'response', headers: headerXml });
}
uploadXml(file: File, label: string, reqFields: string[] = []): Observable<Plan> {
const url = `${this.apiBase}/xml/import`;
const params = new BaseHttpParams();

View File

@ -47,7 +47,7 @@
</button>
</mat-menu>
<mat-menu #exportMenu="matMenu" xPosition="before">
<button mat-menu-item *ngFor='let fileTransformer of fileTransformerService.availableFormatsFor(fileTransformerEntityTypeEnum.Description)' (click)="fileTransformerService.exportDescription(description.id, fileTransformer.repositoryId, fileTransformer.format)">
<button mat-menu-item *ngFor='let fileTransformer of fileTransformerService.availableFormatsFor(fileTransformerEntityTypeEnum.Description)' (click)="fileTransformerService.exportDescription(description.id, fileTransformer.repositoryId, fileTransformer.format, isPublic)">
<i class="fa pr-2" [ngClass]="fileTransformer.icon ? fileTransformer.icon : 'fa-file-o'"></i>
<span>{{'GENERAL.FILE-TRANSFORMER.' + fileTransformer.format.toUpperCase() | translate}}</span>
</button>

View File

@ -174,7 +174,7 @@
</div>
</ng-container>
<mat-menu #exportMenu="matMenu" xPosition="before">
<button mat-menu-item *ngFor='let fileTransformer of fileTransformerService.availableFormatsFor(fileTransformerEntityTypeEnum.Description)' (click)="fileTransformerService.exportDescription(description.id, fileTransformer.repositoryId, fileTransformer.format)">
<button mat-menu-item *ngFor='let fileTransformer of fileTransformerService.availableFormatsFor(fileTransformerEntityTypeEnum.Description)' (click)="fileTransformerService.exportDescription(description.id, fileTransformer.repositoryId, fileTransformer.format, isPublicView)">
<i class="fa pr-2" [ngClass]="fileTransformer.icon ? fileTransformer.icon : 'fa-file-o'"></i>
<span>{{'GENERAL.FILE-TRANSFORMER.' + fileTransformer.format.toUpperCase() | translate}}</span>
</button>

View File

@ -51,7 +51,7 @@
<a class="col-auto pointer" *ngIf="isAuthenticated()" [matMenuTriggerFor]="actionsMenu"><span class="material-icons icon-align pl-2">more_horiz</span></a>
</div>
<mat-menu #exportMenu="matMenu" xPosition="before">
<button mat-menu-item *ngFor='let fileTransformer of fileTransformerService.availableFormatsFor(fileTransformerEntityTypeEnum.Plan)' (click)="fileTransformerService.exportPlan(plan.id, fileTransformer.repositoryId, fileTransformer.format)">
<button mat-menu-item *ngFor='let fileTransformer of fileTransformerService.availableFormatsFor(fileTransformerEntityTypeEnum.Plan)' (click)="fileTransformerService.exportPlan(plan.id, fileTransformer.repositoryId, fileTransformer.format, isPublic)">
<i class="fa pr-2" [ngClass]="fileTransformer.hasLogo ? fileTransformer.icon : 'fa-file-o'"></i>
<span>{{'GENERAL.FILE-TRANSFORMER.' + fileTransformer.format.toUpperCase() | translate}}</span>
</button>

View File

@ -228,7 +228,7 @@
</div>
</ng-container>
<mat-menu #exportMenu="matMenu" xPosition="before">
<button mat-menu-item *ngFor='let fileTransformer of fileTransformerService.availableFormatsFor(fileTransformerEntityTypeEnum.Plan)' (click)="fileTransformerService.exportPlan(plan.id, fileTransformer.repositoryId, fileTransformer.format)">
<button mat-menu-item *ngFor='let fileTransformer of fileTransformerService.availableFormatsFor(fileTransformerEntityTypeEnum.Plan)' (click)="fileTransformerService.exportPlan(plan.id, fileTransformer.repositoryId, fileTransformer.format, isPublicView)">
<i class="fa pr-2" [ngClass]="fileTransformer.icon ? fileTransformer.icon : 'fa-file-o'"></i>
<span>{{'GENERAL.FILE-TRANSFORMER.' + fileTransformer?.format?.toUpperCase() | translate}}</span>
</button>