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_Validate = new EventId(5015, "Plan_Validate");
public static final EventId Plan_GetXml = new EventId(5016, "Plan_GetXml"); 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_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"); public static final EventId Description_Query = new EventId(6000, "Description_Query");
@ -61,6 +63,8 @@ public class AuditableAction {
public static final EventId Description_Validate = new EventId(6009, "Description_Validate"); 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_GetDescriptionSectionPermissions = new EventId(6010, "Description_GetDescriptionSectionPermissions");
public static final EventId Description_UpdateDescriptionTemplate = new EventId(6011, "Description_UpdateDescriptionTemplate"); 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_Query = new EventId(7000, "Reference_Query");

View File

@ -12,13 +12,13 @@ import org.opencdmp.commonmodels.models.descriptiotemplate.DescriptionTemplateMo
import org.opencdmp.commonmodels.models.plan.PlanModel; import org.opencdmp.commonmodels.models.plan.PlanModel;
import org.opencdmp.commons.JsonHandlingService; import org.opencdmp.commons.JsonHandlingService;
import org.opencdmp.commons.XmlHandlingService; 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.description.PropertyDefinitionEntity;
import org.opencdmp.commons.types.descriptiontemplate.DefinitionEntity; import org.opencdmp.commons.types.descriptiontemplate.DefinitionEntity;
import org.opencdmp.convention.ConventionService; import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.DescriptionEntity; import org.opencdmp.data.*;
import org.opencdmp.data.DescriptionTemplateEntity;
import org.opencdmp.data.PlanDescriptionTemplateEntity;
import org.opencdmp.data.PlanEntity;
import org.opencdmp.model.PlanDescriptionTemplate; import org.opencdmp.model.PlanDescriptionTemplate;
import org.opencdmp.model.builder.commonmodels.BaseCommonModelBuilder; import org.opencdmp.model.builder.commonmodels.BaseCommonModelBuilder;
import org.opencdmp.model.builder.commonmodels.CommonModelBuilderItemResponse; 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.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.management.InvalidApplicationException;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.opencdmp.authorization.AuthorizationFlags.Public;
@Component @Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class DescriptionCommonModelBuilder extends BaseCommonModelBuilder<DescriptionModel, DescriptionEntity> { public class DescriptionCommonModelBuilder extends BaseCommonModelBuilder<DescriptionModel, DescriptionEntity> {
@ -48,6 +51,7 @@ public class DescriptionCommonModelBuilder extends BaseCommonModelBuilder<Descri
private final BuilderFactory builderFactory; private final BuilderFactory builderFactory;
private final JsonHandlingService jsonHandlingService; private final JsonHandlingService jsonHandlingService;
private final XmlHandlingService xmlHandlingService; private final XmlHandlingService xmlHandlingService;
private final TenantEntityManager entityManager;
private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None); private EnumSet<AuthorizationFlags> authorize = EnumSet.of(AuthorizationFlags.None);
private String repositoryId; private String repositoryId;
@ -56,12 +60,13 @@ public class DescriptionCommonModelBuilder extends BaseCommonModelBuilder<Descri
public DescriptionCommonModelBuilder( public DescriptionCommonModelBuilder(
ConventionService conventionService, ConventionService conventionService,
QueryFactory queryFactory, QueryFactory queryFactory,
BuilderFactory builderFactory, JsonHandlingService jsonHandlingService, XmlHandlingService xmlHandlingService) { BuilderFactory builderFactory, JsonHandlingService jsonHandlingService, XmlHandlingService xmlHandlingService, TenantEntityManager entityManager) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(DescriptionCommonModelBuilder.class))); super(conventionService, new LoggerService(LoggerFactory.getLogger(DescriptionCommonModelBuilder.class)));
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.builderFactory = builderFactory; this.builderFactory = builderFactory;
this.jsonHandlingService = jsonHandlingService; this.jsonHandlingService = jsonHandlingService;
this.xmlHandlingService = xmlHandlingService; this.xmlHandlingService = xmlHandlingService;
this.entityManager = entityManager;
} }
public DescriptionCommonModelBuilder authorize(EnumSet<AuthorizationFlags> values) { public DescriptionCommonModelBuilder authorize(EnumSet<AuthorizationFlags> values) {
@ -81,6 +86,12 @@ public class DescriptionCommonModelBuilder extends BaseCommonModelBuilder<Descri
return this; return this;
} }
private boolean isPublic;
public DescriptionCommonModelBuilder isPublic(boolean isPublic) {
this.isPublic = isPublic;
return this;
}
@Override @Override
protected List<CommonModelBuilderItemResponse<DescriptionModel, DescriptionEntity>> buildInternal(List<DescriptionEntity> data) throws MyApplicationException { protected List<CommonModelBuilderItemResponse<DescriptionModel, DescriptionEntity>> buildInternal(List<DescriptionEntity> data) throws MyApplicationException {
this.logger.debug("building for {}", Optional.ofNullable(data).map(List::size).orElse(0)); 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()); this.logger.debug("checking related - {}", PlanModel.class.getSimpleName());
Map<UUID, PlanModel> itemMap; 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())); 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); 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; return itemMap;
} }

View File

@ -41,9 +41,12 @@ 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 javax.management.InvalidApplicationException;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.opencdmp.authorization.AuthorizationFlags.Public;
@Component @Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, PlanEntity> { public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, PlanEntity> {
@ -53,6 +56,7 @@ public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, Pl
private final BuilderFactory builderFactory; private final BuilderFactory builderFactory;
private final JsonHandlingService jsonHandlingService; private final JsonHandlingService jsonHandlingService;
private final XmlHandlingService xmlHandlingService; private final XmlHandlingService xmlHandlingService;
private final TenantEntityManager entityManager;
private FileEnvelopeModel pdfFile; private FileEnvelopeModel pdfFile;
private FileEnvelopeModel rdaJsonFile; private FileEnvelopeModel rdaJsonFile;
private String repositoryId; private String repositoryId;
@ -62,12 +66,13 @@ public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, Pl
@Autowired @Autowired
public PlanCommonModelBuilder(ConventionService conventionService, public PlanCommonModelBuilder(ConventionService conventionService,
QueryFactory queryFactory, QueryFactory queryFactory,
BuilderFactory builderFactory, JsonHandlingService jsonHandlingService, XmlHandlingService xmlHandlingService) { BuilderFactory builderFactory, JsonHandlingService jsonHandlingService, XmlHandlingService xmlHandlingService, TenantEntityManager entityManager) {
super(conventionService, new LoggerService(LoggerFactory.getLogger(PlanCommonModelBuilder.class))); super(conventionService, new LoggerService(LoggerFactory.getLogger(PlanCommonModelBuilder.class)));
this.queryFactory = queryFactory; this.queryFactory = queryFactory;
this.builderFactory = builderFactory; this.builderFactory = builderFactory;
this.jsonHandlingService = jsonHandlingService; this.jsonHandlingService = jsonHandlingService;
this.xmlHandlingService = xmlHandlingService; this.xmlHandlingService = xmlHandlingService;
this.entityManager = entityManager;
} }
public PlanCommonModelBuilder authorize(EnumSet<AuthorizationFlags> values) { public PlanCommonModelBuilder authorize(EnumSet<AuthorizationFlags> values) {
@ -102,6 +107,12 @@ public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, Pl
return this; return this;
} }
private boolean isPublic;
public PlanCommonModelBuilder isPublic(boolean isPublic) {
this.isPublic = isPublic;
return this;
}
@Override @Override
protected List<CommonModelBuilderItemResponse<PlanModel, PlanEntity>> buildInternal(List<PlanEntity> data) throws MyApplicationException { protected List<CommonModelBuilderItemResponse<PlanModel, PlanEntity>> buildInternal(List<PlanEntity> data) throws MyApplicationException {
this.logger.debug("building for {}", Optional.ofNullable(data).map(List::size).orElse(0)); 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()); this.logger.debug("checking related - {}", Description.class.getSimpleName());
Map<UUID, List<DescriptionModel>> itemMap; 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())); DescriptionQuery query = null;
itemMap = this.builderFactory.builder(DescriptionCommonModelBuilder.class).setRepositoryId(this.repositoryId).useSharedStorage(this.useSharedStorage).authorize(this.authorize).asMasterKey(query, DescriptionEntity::getPlanId); 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; return itemMap;
} }
@ -248,7 +279,7 @@ public class PlanCommonModelBuilder extends BaseCommonModelBuilder<PlanModel, Pl
return null; return null;
this.logger.debug("checking related - {}", DefinitionEntity.class.getSimpleName()); 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())); 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)); List<PlanBlueprintEntity> items = q.collectAs(new BaseFieldSet().ensure(PlanBlueprint._id).ensure(PlanBlueprint._definition));
for (PlanBlueprintEntity item : items){ for (PlanBlueprintEntity item : items){

View File

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

View File

@ -42,16 +42,18 @@ public interface DescriptionService {
List<DescriptionValidationResult> validate(List<UUID> descriptionIds) throws InvalidApplicationException; 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; StorageFile uploadFieldFile(DescriptionFieldFilePersist model, MultipartFile file, FieldSet fields) throws IOException;
StorageFileEntity getFieldFile(UUID descriptionId, UUID storageFileId); StorageFileEntity getFieldFile(UUID descriptionId, UUID storageFileId);
void updateDescriptionTemplate(UpdateDescriptionTemplatePersist model) throws InvalidApplicationException, IOException, JAXBException; 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[]> 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 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; 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.annotationentitytouch.AnnotationEntityTouchedIntegrationEventHandler;
import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEvent; import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEvent;
import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEventHandler; import org.opencdmp.integrationevent.outbox.notification.NotifyIntegrationEventHandler;
import org.opencdmp.model.DescriptionValidationResult; import org.opencdmp.model.*;
import org.opencdmp.model.PlanDescriptionTemplate;
import org.opencdmp.model.StorageFile;
import org.opencdmp.model.Tag;
import org.opencdmp.model.builder.description.DescriptionBuilder; import org.opencdmp.model.builder.description.DescriptionBuilder;
import org.opencdmp.model.deleter.DescriptionDeleter; import org.opencdmp.model.deleter.DescriptionDeleter;
import org.opencdmp.model.deleter.DescriptionReferenceDeleter; import org.opencdmp.model.deleter.DescriptionReferenceDeleter;
@ -110,6 +107,8 @@ import java.time.Instant;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.opencdmp.authorization.AuthorizationFlags.Public;
@Service @Service
public class DescriptionServiceImpl implements DescriptionService { public class DescriptionServiceImpl implements DescriptionService {
@ -912,10 +911,10 @@ public class DescriptionServiceImpl implements DescriptionService {
//region file export //region file export
@Override @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(); 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()); headers.add("Content-Disposition", "attachment;filename=" + fileEnvelope.getFilename());
byte[] data = fileEnvelope.getFile(); byte[] data = fileEnvelope.getFile();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
@ -1164,11 +1163,22 @@ public class DescriptionServiceImpl implements DescriptionService {
//region Export //region Export
@Override @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)); logger.debug(new MapLogEntry("export xml").And("id", id));
if (!ignoreAuthorize) this.authorizationService.authorizeForce(Permission.ExportDescription); 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())); 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()); 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(); 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())); 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()); this.accountingService.increase(UsageLimitTargetMetric.EXPORT_DESCRIPTION_XML_EXECUTION_COUNT.getValue());
return this.responseUtilsService.buildResponseFileFromText(xml, data.getLabel() + ".xml"); return this.responseUtilsService.buildResponseFileFromText(xml, data.getLabel() + ".xml");
} }

View File

@ -20,9 +20,9 @@ import java.util.UUID;
public interface FileTransformerService { public interface FileTransformerService {
List<RepositoryFileFormat> getAvailableExportFileFormats() throws InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, InvalidApplicationException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException; 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; 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.plan.PlanModel;
import org.opencdmp.commonmodels.models.planblueprint.PlanBlueprintModel; import org.opencdmp.commonmodels.models.planblueprint.PlanBlueprintModel;
import org.opencdmp.commons.JsonHandlingService; import org.opencdmp.commons.JsonHandlingService;
import org.opencdmp.commons.enums.IsActive; import org.opencdmp.commons.enums.*;
import org.opencdmp.commons.enums.StorageType;
import org.opencdmp.commons.enums.TenantConfigurationType;
import org.opencdmp.commons.enums.UsageLimitTargetMetric;
import org.opencdmp.commons.scope.tenant.TenantScope; import org.opencdmp.commons.scope.tenant.TenantScope;
import org.opencdmp.commons.scope.user.UserScope; import org.opencdmp.commons.scope.user.UserScope;
import org.opencdmp.commons.types.filetransformer.FileTransformerSourceEntity; import org.opencdmp.commons.types.filetransformer.FileTransformerSourceEntity;
import org.opencdmp.commons.types.tenantconfiguration.FileTransformerTenantConfigurationEntity; import org.opencdmp.commons.types.tenantconfiguration.FileTransformerTenantConfigurationEntity;
import org.opencdmp.convention.ConventionService; import org.opencdmp.convention.ConventionService;
import org.opencdmp.data.DescriptionTemplateEntity; import org.opencdmp.data.*;
import org.opencdmp.data.StorageFileEntity;
import org.opencdmp.data.TenantConfigurationEntity;
import org.opencdmp.event.TenantConfigurationTouchedEvent; import org.opencdmp.event.TenantConfigurationTouchedEvent;
import org.opencdmp.filetransformerbase.interfaces.FileTransformerConfiguration; import org.opencdmp.filetransformerbase.interfaces.FileTransformerConfiguration;
import org.opencdmp.filetransformerbase.models.misc.DescriptionImportModel; import org.opencdmp.filetransformerbase.models.misc.DescriptionImportModel;
import org.opencdmp.filetransformerbase.models.misc.PlanImportModel; import org.opencdmp.filetransformerbase.models.misc.PlanImportModel;
import org.opencdmp.filetransformerbase.models.misc.PreprocessingPlanModel; import org.opencdmp.filetransformerbase.models.misc.PreprocessingPlanModel;
import org.opencdmp.model.PublicPlan;
import org.opencdmp.model.StorageFile; import org.opencdmp.model.StorageFile;
import org.opencdmp.model.builder.commonmodels.description.DescriptionCommonModelBuilder; import org.opencdmp.model.builder.commonmodels.description.DescriptionCommonModelBuilder;
import org.opencdmp.model.builder.commonmodels.descriptiontemplate.DescriptionTemplateCommonModelBuilder; import org.opencdmp.model.builder.commonmodels.descriptiontemplate.DescriptionTemplateCommonModelBuilder;
@ -82,6 +78,8 @@ import java.security.NoSuchAlgorithmException;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import static org.opencdmp.authorization.AuthorizationFlags.Public;
@Service @Service
public class FileTransformerServiceImpl implements FileTransformerService { public class FileTransformerServiceImpl implements FileTransformerService {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(FileTransformerServiceImpl.class)); 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 FileTransformerSourcesCacheService fileTransformerSourcesCacheService;
private final UserScope userScope; private final UserScope userScope;
private final AccountingService accountingService; private final AccountingService accountingService;
private final TenantEntityManager entityManager;
@Autowired @Autowired
public FileTransformerServiceImpl(FileTransformerProperties fileTransformerProperties, TokenExchangeCacheService tokenExchangeCacheService, FileTransformerConfigurationCacheService fileTransformerConfigurationCacheService, AuthorizationService authorizationService, 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.fileTransformerProperties = fileTransformerProperties;
this.tokenExchangeCacheService = tokenExchangeCacheService; this.tokenExchangeCacheService = tokenExchangeCacheService;
this.fileTransformerConfigurationCacheService = fileTransformerConfigurationCacheService; this.fileTransformerConfigurationCacheService = fileTransformerConfigurationCacheService;
@ -122,6 +121,7 @@ public class FileTransformerServiceImpl implements FileTransformerService {
this.fileTransformerSourcesCacheService = fileTransformerSourcesCacheService; this.fileTransformerSourcesCacheService = fileTransformerSourcesCacheService;
this.userScope = userScope; this.userScope = userScope;
this.accountingService = accountingService; this.accountingService = accountingService;
this.entityManager = entityManager;
this.clients = new HashMap<>(); this.clients = new HashMap<>();
} }
@ -256,14 +256,28 @@ public class FileTransformerServiceImpl implements FileTransformerService {
} }
@Override @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); this.authorizationService.authorizeForce(Permission.ExportPlan);
//GK: First get the right client //GK: First get the right client
FileTransformerRepository repository = this.getRepository(repositoryId); FileTransformerRepository repository = this.getRepository(repositoryId);
if (repository == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{format, FileTransformerRepository.class.getSimpleName()}, LocaleContextHolder.getLocale())); 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 //GK: Second get the Target Data Management Plan
PlanQuery query = this.queryFactory.query(PlanQuery.class).disableTracking().authorize(AuthorizationFlags.All).ids(planId); PlanEntity entity = null;
PlanModel planFileTransformerModel = this.builderFactory.builder(PlanCommonModelBuilder.class).useSharedStorage(repository.getConfiguration().isUseSharedStorage()).setRepositoryId(repository.getConfiguration().getFileTransformerId()).authorize(AuthorizationFlags.All).build(query.first()); 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())); 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); FileEnvelopeModel fileEnvelope = repository.exportPlan(planFileTransformerModel, format);
@ -280,15 +294,29 @@ public class FileTransformerServiceImpl implements FileTransformerService {
} }
@Override @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); this.authorizationService.authorizeForce(Permission.ExportDescription);
//GK: First get the right client //GK: First get the right client
FileTransformerRepository repository = this.getRepository(repositoryId); FileTransformerRepository repository = this.getRepository(repositoryId);
if (repository == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{format, FileTransformerRepository.class.getSimpleName()}, LocaleContextHolder.getLocale())); 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 //GK: Second get the Target Data Management Plan
DescriptionQuery query = this.queryFactory.query(DescriptionQuery.class).disableTracking().authorize(AuthorizationFlags.All).ids(descriptionId); DescriptionEntity entity = null;
DescriptionModel descriptionFileTransformerModel = this.builderFactory.builder(DescriptionCommonModelBuilder.class).setRepositoryId(repository.getConfiguration().getFileTransformerId()).useSharedStorage(repository.getConfiguration().isUseSharedStorage()).authorize(AuthorizationFlags.All).build(query.first()); 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())); 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); FileEnvelopeModel fileEnvelope = repository.exportDescription(descriptionFileTransformerModel, format);

View File

@ -336,7 +336,20 @@ public class DescriptionController {
) throws InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { ) throws InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
logger.debug(new MapLogEntry("exporting description")); 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") @PostMapping("field-file/upload")
@ -423,11 +436,28 @@ public class DescriptionController {
public @ResponseBody ResponseEntity<byte[]> getXml( 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 @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 { ) 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); 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) new AbstractMap.SimpleEntry<String, Object>("id", id)
)); ));
return response; return response;

View File

@ -77,7 +77,21 @@ public class FileTransformerController {
logger.debug(new MapLogEntry("exporting plan")); logger.debug(new MapLogEntry("exporting plan"));
HttpHeaders headers = new HttpHeaders(); 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()); headers.add("Content-Disposition", "attachment;filename=" + fileEnvelope.getFilename());
byte[] data = fileEnvelope.getFile(); byte[] data = fileEnvelope.getFile();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
@ -91,7 +105,21 @@ public class FileTransformerController {
logger.debug(new MapLogEntry("exporting description")); logger.debug(new MapLogEntry("exporting description"));
HttpHeaders headers = new HttpHeaders(); 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()); headers.add("Content-Disposition", "attachment;filename=" + fileEnvelope.getFilename());
byte[] data = fileEnvelope.getFile(); byte[] data = fileEnvelope.getFile();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);

View File

@ -408,7 +408,7 @@ public class PlanController {
) throws InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException { ) throws InvalidApplicationException, IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException {
logger.debug(new MapLogEntry("exporting plan").And("id", id).And("transformerId", transformerId).And("exportType", exportType)); 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( this.auditService.track(AuditableAction.Plan_Export, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("id", id), new AbstractMap.SimpleEntry<String, Object>("id", id),
new AbstractMap.SimpleEntry<String, Object>("transformerId", transformerId), new AbstractMap.SimpleEntry<String, Object>("transformerId", transformerId),
@ -417,6 +417,26 @@ public class PlanController {
return bytes; 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") @PostMapping("{id}/invite-users")
@OperationWithTenantHeader(summary = "Send user invitations for the plan by id") @OperationWithTenantHeader(summary = "Send user invitations for the plan by id")
@Transactional @Transactional
@ -467,6 +487,23 @@ public class PlanController {
return response; 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") @RequestMapping(method = RequestMethod.POST, value = "/xml/import")
@OperationWithTenantHeader(summary = "Import a plan from an xml file", description = "", @OperationWithTenantHeader(summary = "Import a plan from an xml file", description = "",
responses = @ApiResponse(description = "OK", responseCode = "200", content = @Content( 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 }); 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> { public updateDescriptionTemplate(item: UpdateDescriptionTemplatePersist): Observable<boolean> {
const url = `${this.apiBase}/update-description-template`; 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))); 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> { exportDescription(id: Guid, repositoryId: string, format: string): Observable<any> {
const url = `${this.apiBase}/export-description`; 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))); 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,9 +67,10 @@ 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; this._loading = true;
if (repositoryId == this.xmlExportRepo.repositoryId) { if (repositoryId == this.xmlExportRepo.repositoryId) {
if (!isPublic) {
this.planService.downloadXML(id) this.planService.downloadXML(id)
.pipe(takeUntil(this._destroyed)) .pipe(takeUntil(this._destroyed))
.subscribe(response => { .subscribe(response => {
@ -79,6 +80,17 @@ export class FileTransformerService extends BaseService {
}, },
error => this.httpErrorHandlingService.handleBackedRequestError(error)); error => this.httpErrorHandlingService.handleBackedRequestError(error));
} else { } 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);
},
error => this.httpErrorHandlingService.handleBackedRequestError(error));
}
} else {
if (!isPublic) {
this.fileTransformerHttpService.exportPlan(id, repositoryId, format).pipe(takeUntil(this._destroyed), catchError((error) => { this.fileTransformerHttpService.exportPlan(id, repositoryId, format).pipe(takeUntil(this._destroyed), catchError((error) => {
this._loading = false; this._loading = false;
return null; return null;
@ -93,12 +105,29 @@ export class FileTransformerService extends BaseService {
} }
}, },
error => this.httpErrorHandlingService.handleBackedRequestError(error)); 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; this._loading = true;
if (repositoryId == this.xmlExportRepo.repositoryId) { if (repositoryId == this.xmlExportRepo.repositoryId) {
if (!isPublic) {
this.descriptionService.downloadXML(id) this.descriptionService.downloadXML(id)
.pipe(takeUntil(this._destroyed)) .pipe(takeUntil(this._destroyed))
.subscribe(response => { .subscribe(response => {
@ -108,6 +137,17 @@ export class FileTransformerService extends BaseService {
}, },
error => this.httpErrorHandlingService.handleBackedRequestError(error)); error => this.httpErrorHandlingService.handleBackedRequestError(error));
} else { } 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);
},
error => this.httpErrorHandlingService.handleBackedRequestError(error));
}
} else {
if (!isPublic) {
this.fileTransformerHttpService.exportDescription(id, repositoryId, format).pipe(takeUntil(this._destroyed), catchError((error) => { this.fileTransformerHttpService.exportDescription(id, repositoryId, format).pipe(takeUntil(this._destroyed), catchError((error) => {
this._loading = false; this._loading = false;
return null; return null;
@ -122,6 +162,22 @@ export class FileTransformerService extends BaseService {
} }
}, },
error => this.httpErrorHandlingService.handleBackedRequestError(error)); 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 }); 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> { uploadXml(file: File, label: string, reqFields: string[] = []): Observable<Plan> {
const url = `${this.apiBase}/xml/import`; const url = `${this.apiBase}/xml/import`;
const params = new BaseHttpParams(); const params = new BaseHttpParams();

View File

@ -47,7 +47,7 @@
</button> </button>
</mat-menu> </mat-menu>
<mat-menu #exportMenu="matMenu" xPosition="before"> <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> <i class="fa pr-2" [ngClass]="fileTransformer.icon ? fileTransformer.icon : 'fa-file-o'"></i>
<span>{{'GENERAL.FILE-TRANSFORMER.' + fileTransformer.format.toUpperCase() | translate}}</span> <span>{{'GENERAL.FILE-TRANSFORMER.' + fileTransformer.format.toUpperCase() | translate}}</span>
</button> </button>

View File

@ -174,7 +174,7 @@
</div> </div>
</ng-container> </ng-container>
<mat-menu #exportMenu="matMenu" xPosition="before"> <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> <i class="fa pr-2" [ngClass]="fileTransformer.icon ? fileTransformer.icon : 'fa-file-o'"></i>
<span>{{'GENERAL.FILE-TRANSFORMER.' + fileTransformer.format.toUpperCase() | translate}}</span> <span>{{'GENERAL.FILE-TRANSFORMER.' + fileTransformer.format.toUpperCase() | translate}}</span>
</button> </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> <a class="col-auto pointer" *ngIf="isAuthenticated()" [matMenuTriggerFor]="actionsMenu"><span class="material-icons icon-align pl-2">more_horiz</span></a>
</div> </div>
<mat-menu #exportMenu="matMenu" xPosition="before"> <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> <i class="fa pr-2" [ngClass]="fileTransformer.hasLogo ? fileTransformer.icon : 'fa-file-o'"></i>
<span>{{'GENERAL.FILE-TRANSFORMER.' + fileTransformer.format.toUpperCase() | translate}}</span> <span>{{'GENERAL.FILE-TRANSFORMER.' + fileTransformer.format.toUpperCase() | translate}}</span>
</button> </button>

View File

@ -228,7 +228,7 @@
</div> </div>
</ng-container> </ng-container>
<mat-menu #exportMenu="matMenu" xPosition="before"> <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> <i class="fa pr-2" [ngClass]="fileTransformer.icon ? fileTransformer.icon : 'fa-file-o'"></i>
<span>{{'GENERAL.FILE-TRANSFORMER.' + fileTransformer?.format?.toUpperCase() | translate}}</span> <span>{{'GENERAL.FILE-TRANSFORMER.' + fileTransformer?.format?.toUpperCase() | translate}}</span>
</button> </button>