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

This commit is contained in:
Sofia Papacharalampous 2024-05-17 12:47:37 +03:00
commit 3323e40aea
20 changed files with 190 additions and 121 deletions

View File

@ -8,7 +8,7 @@ public class ErrorThesaurusProperties {
private ErrorDescription systemError;
public ErrorDescription getSystemError() {
return systemError;
return this.systemError;
}
public void setSystemError(ErrorDescription systemError) {
@ -18,7 +18,7 @@ public class ErrorThesaurusProperties {
private ErrorDescription forbidden;
public ErrorDescription getForbidden() {
return forbidden;
return this.forbidden;
}
public void setForbidden(ErrorDescription forbidden) {
@ -28,7 +28,7 @@ public class ErrorThesaurusProperties {
private ErrorDescription hashConflict;
public ErrorDescription getHashConflict() {
return hashConflict;
return this.hashConflict;
}
public void setHashConflict(ErrorDescription hashConflict) {
@ -38,7 +38,7 @@ public class ErrorThesaurusProperties {
private ErrorDescription modelValidation;
public ErrorDescription getModelValidation() {
return modelValidation;
return this.modelValidation;
}
public void setModelValidation(ErrorDescription modelValidation) {
@ -48,7 +48,7 @@ public class ErrorThesaurusProperties {
private ErrorDescription descriptionTemplateNewVersionConflict;
public ErrorDescription getDescriptionTemplateNewVersionConflict() {
return descriptionTemplateNewVersionConflict;
return this.descriptionTemplateNewVersionConflict;
}
public void setDescriptionTemplateNewVersionConflict(ErrorDescription descriptionTemplateNewVersionConflict) {
@ -58,7 +58,7 @@ public class ErrorThesaurusProperties {
private ErrorDescription dmpNewVersionConflict;
public ErrorDescription getDmpNewVersionConflict() {
return dmpNewVersionConflict;
return this.dmpNewVersionConflict;
}
public void setDmpNewVersionConflict(ErrorDescription dmpNewVersionConflict) {
@ -68,7 +68,7 @@ public class ErrorThesaurusProperties {
public ErrorDescription dmpBlueprintNewVersionConflict;
public ErrorDescription getDmpBlueprintNewVersionConflict() {
return dmpBlueprintNewVersionConflict;
return this.dmpBlueprintNewVersionConflict;
}
public void setDmpBlueprintNewVersionConflict(ErrorDescription dmpBlueprintNewVersionConflict) {
@ -78,7 +78,7 @@ public class ErrorThesaurusProperties {
private ErrorDescription dmpIsFinalized;
public ErrorDescription getDmpIsFinalized() {
return dmpIsFinalized;
return this.dmpIsFinalized;
}
public void setDmpIsFinalized(ErrorDescription dmpIsFinalized) {
@ -88,7 +88,7 @@ public class ErrorThesaurusProperties {
private ErrorDescription dmpCanNotChange;
public ErrorDescription getDmpCanNotChange() {
return dmpCanNotChange;
return this.dmpCanNotChange;
}
public void setDmpCanNotChange(ErrorDescription dmpCanNotChange) {
@ -98,7 +98,7 @@ public class ErrorThesaurusProperties {
private ErrorDescription dmpDescriptionTemplateCanNotChange;
public ErrorDescription getDmpDescriptionTemplateCanNotChange() {
return dmpDescriptionTemplateCanNotChange;
return this.dmpDescriptionTemplateCanNotChange;
}
public void setDmpDescriptionTemplateCanNotChange(ErrorDescription dmpDescriptionTemplateCanNotChange) {
@ -108,7 +108,7 @@ public class ErrorThesaurusProperties {
private ErrorDescription invalidDescriptionTemplate;
public ErrorDescription getInvalidDescriptionTemplate() {
return invalidDescriptionTemplate;
return this.invalidDescriptionTemplate;
}
public void setInvalidDescriptionTemplate(ErrorDescription invalidDescriptionTemplate) {
@ -118,7 +118,7 @@ public class ErrorThesaurusProperties {
private ErrorDescription descriptionIsFinalized;
public ErrorDescription getDescriptionIsFinalized() {
return descriptionIsFinalized;
return this.descriptionIsFinalized;
}
public void setDescriptionIsFinalized(ErrorDescription descriptionIsFinalized) {
@ -128,7 +128,7 @@ public class ErrorThesaurusProperties {
private ErrorDescription dmpBlueprintHasNoDescriptionTemplates;
public ErrorDescription getDmpBlueprintHasNoDescriptionTemplates() {
return dmpBlueprintHasNoDescriptionTemplates;
return this.dmpBlueprintHasNoDescriptionTemplates;
}
public void setDmpBlueprintHasNoDescriptionTemplates(ErrorDescription dmpBlueprintHasNoDescriptionTemplates) {
@ -138,7 +138,7 @@ public class ErrorThesaurusProperties {
private ErrorDescription dmpDescriptionTemplateCanNotRemove;
public ErrorDescription getDmpDescriptionTemplateCanNotRemove() {
return dmpDescriptionTemplateCanNotRemove;
return this.dmpDescriptionTemplateCanNotRemove;
}
public void setDmpDescriptionTemplateCanNotRemove(ErrorDescription dmpDescriptionTemplateCanNotRemove) {
@ -148,7 +148,7 @@ public class ErrorThesaurusProperties {
private ErrorDescription missingTenant;
public ErrorDescription getMissingTenant() {
return missingTenant;
return this.missingTenant;
}
public void setMissingTenant(ErrorDescription missingTenant) {
@ -158,7 +158,7 @@ public class ErrorThesaurusProperties {
private ErrorDescription tenantNotAllowed;
public ErrorDescription getTenantNotAllowed() {
return tenantNotAllowed;
return this.tenantNotAllowed;
}
public void setTenantNotAllowed(ErrorDescription tenantNotAllowed) {
@ -168,7 +168,7 @@ public class ErrorThesaurusProperties {
private ErrorDescription tenantTampering;
public ErrorDescription getTenantTampering() {
return tenantTampering;
return this.tenantTampering;
}
public void setTenantTampering(ErrorDescription tenantTampering) {
@ -178,7 +178,7 @@ public class ErrorThesaurusProperties {
private ErrorDescription tenantConfigurationTypeCanNotChange;
public ErrorDescription getTenantConfigurationTypeCanNotChange() {
return tenantConfigurationTypeCanNotChange;
return this.tenantConfigurationTypeCanNotChange;
}
public void setTenantConfigurationTypeCanNotChange(ErrorDescription tenantConfigurationTypeCanNotChange) {
@ -188,10 +188,20 @@ public class ErrorThesaurusProperties {
private ErrorDescription multipleTenantConfigurationTypeNotAllowed;
public ErrorDescription getMultipleTenantConfigurationTypeNotAllowed() {
return multipleTenantConfigurationTypeNotAllowed;
return this.multipleTenantConfigurationTypeNotAllowed;
}
public void setMultipleTenantConfigurationTypeNotAllowed(ErrorDescription multipleTenantConfigurationTypeNotAllowed) {
this.multipleTenantConfigurationTypeNotAllowed = multipleTenantConfigurationTypeNotAllowed;
}
private ErrorDescription tenantCodeExists;
public ErrorDescription getTenantCodeExists() {
return this.tenantCodeExists;
}
public void setTenantCodeExists(ErrorDescription tenantCodeExists) {
this.tenantCodeExists = tenantCodeExists;
}
}

View File

@ -1,12 +1,12 @@
package org.opencdmp.model.persist;
import org.opencdmp.commons.validation.BaseValidator;
import org.opencdmp.model.persist.descriptionreference.DescriptionReferenceDataPersist;
import org.opencdmp.model.persist.dmpreference.DmpReferenceDataPersist;
import gr.cite.tools.validation.ValidatorFactory;
import gr.cite.tools.validation.specification.Specification;
import org.opencdmp.commons.validation.BaseValidator;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.opencdmp.model.persist.descriptionreference.DescriptionReferenceDataPersist;
import org.opencdmp.model.persist.dmpreference.DmpReferenceDataPersist;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Scope;
@ -15,12 +15,11 @@ import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
public class DescriptionReferencePersist {
private ReferencePersist reference = null;
private ReferencePersist reference;
public static final String _reference = "reference";
@ -30,7 +29,7 @@ public class DescriptionReferencePersist {
public static final String _data = "data";
public ReferencePersist getReference() {
return reference;
return this.reference;
}
public void setReference(ReferencePersist reference) {
@ -38,7 +37,7 @@ public class DescriptionReferencePersist {
}
public DescriptionReferenceDataPersist getData() {
return data;
return this.data;
}
public void setData(DescriptionReferenceDataPersist data) {
@ -71,7 +70,7 @@ public class DescriptionReferencePersist {
return Arrays.asList(
this.spec()
.must(() -> !this.isNull(item.getReference()))
.failOn(DescriptionReferencePersist._reference).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionReferencePersist._reference}, LocaleContextHolder.getLocale())),
.failOn(DescriptionReferencePersist._reference).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionReferencePersist._reference}, LocaleContextHolder.getLocale())),
this.refSpec()
.iff(() -> !this.isNull(item.getReference()))
.on(DescriptionReferencePersist._reference)
@ -79,7 +78,7 @@ public class DescriptionReferencePersist {
.using(() -> this.validatorFactory.validator(ReferencePersist.ReferencePersistValidator.class)),
this.spec()
.must(() -> !this.isNull(item.getData()))
.failOn(DescriptionReferencePersist._data).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionReferencePersist._data}, LocaleContextHolder.getLocale())),
.failOn(DescriptionReferencePersist._data).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionReferencePersist._data}, LocaleContextHolder.getLocale())),
this.refSpec()
.iff(() -> !this.isNull(item.getData()))
.on(DescriptionReferencePersist._data)

View File

@ -1,5 +1,7 @@
package org.opencdmp.model.persist.descriptionproperties;
import gr.cite.tools.validation.ValidatorFactory;
import gr.cite.tools.validation.specification.Specification;
import org.opencdmp.commons.enums.DescriptionStatus;
import org.opencdmp.commons.enums.FieldValidationType;
import org.opencdmp.commons.types.descriptiontemplate.DefinitionEntity;
@ -11,15 +13,16 @@ import org.opencdmp.errorcode.ErrorThesaurusProperties;
import org.opencdmp.model.persist.validation.StatusAware;
import org.opencdmp.service.visibility.VisibilityService;
import org.opencdmp.service.visibility.VisibilityServiceImpl;
import gr.cite.tools.validation.ValidatorFactory;
import gr.cite.tools.validation.specification.Specification;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Scope;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class PropertyDefinitionPersist {
@ -29,7 +32,7 @@ public class PropertyDefinitionPersist {
private Map<String, PropertyDefinitionFieldSetPersist> fieldSets;
public Map<String, PropertyDefinitionFieldSetPersist> getFieldSets() {
return fieldSets;
return this.fieldSets;
}
public void setFieldSets(Map<String, PropertyDefinitionFieldSetPersist> fieldSets) {
@ -67,21 +70,21 @@ public class PropertyDefinitionPersist {
this.spec()
.iff(() -> this.status == DescriptionStatus.Finalized)
.must(() -> !this.isNull(item.getFieldSets()) && !item.getFieldSets().isEmpty())
.failOn(PropertyDefinitionPersist._fieldSets).failWith(messageSource.getMessage("Validation_Required", new Object[]{PropertyDefinitionPersist._fieldSets}, LocaleContextHolder.getLocale())),
.failOn(PropertyDefinitionPersist._fieldSets).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{PropertyDefinitionPersist._fieldSets}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> this.isListNullOrEmpty(this.getMissingFieldSetEntity(item)))
.failOn(PropertyDefinitionPersist._fieldSets).failWith(messageSource.getMessage("Validation.MissingFields", new Object[]{this.serializeMissingFieldSets(this.getMissingFieldSetEntity(item))}, LocaleContextHolder.getLocale())),
.failOn(PropertyDefinitionPersist._fieldSets).failWith(this.messageSource.getMessage("Validation.MissingFields", new Object[]{this.serializeMissingFieldSets(this.getMissingFieldSetEntity(item))}, LocaleContextHolder.getLocale())),
this.spec()
.must(() -> this.isListNullOrEmpty(this.getMissingFieldsEntity(item)))
.failOn(PropertyDefinitionPersist._fieldSets).failWith(messageSource.getMessage("Validation.MissingFields", new Object[]{this.serializeMissingFields(this.getMissingFieldsEntity(item))}, LocaleContextHolder.getLocale())),
.failOn(PropertyDefinitionPersist._fieldSets).failWith(this.messageSource.getMessage("Validation.MissingFields", new Object[]{this.serializeMissingFields(this.getMissingFieldsEntity(item))}, LocaleContextHolder.getLocale())),
this.mapSpec()
.iff(() -> !this.isNull(item.getFieldSets()))
.on(PropertyDefinitionPersist._fieldSets)
.over(item.getFieldSets())
.mapKey((k) -> ((String)k))
.using((itm) -> {
FieldSetEntity fieldSetEntity = definition != null ? definition.getFieldSetById((String)itm.getKey()).stream().findFirst().orElse(null) : null;
return this.validatorFactory.validator(PropertyDefinitionFieldSetPersist.PersistValidator.class).withFieldSetEntity(fieldSetEntity).withVisibilityService(visibilityService).setStatus(this.status);
FieldSetEntity fieldSetEntity = this.definition != null ? this.definition.getFieldSetById((String)itm.getKey()).stream().findFirst().orElse(null) : null;
return this.validatorFactory.validator(PropertyDefinitionFieldSetPersist.PersistValidator.class).withFieldSetEntity(fieldSetEntity).withVisibilityService(this.visibilityService).setStatus(this.status);
})
);
}
@ -105,8 +108,8 @@ public class PropertyDefinitionPersist {
private List<FieldSetEntity> getMissingFieldSetEntity(PropertyDefinitionPersist item){
List<FieldSetEntity> missingMultipleFieldSets = new ArrayList<>();
if (definition == null || definition.getAllFieldSets() == null) return missingMultipleFieldSets;
for (FieldSetEntity fieldSet: definition.getAllFieldSets()) {
if (this.definition == null || this.definition.getAllFieldSets() == null) return missingMultipleFieldSets;
for (FieldSetEntity fieldSet: this.definition.getAllFieldSets()) {
boolean requiredAtLeastOneFieldSet = fieldSet.getMultiplicity() != null && fieldSet.getHasMultiplicity() && fieldSet.getMultiplicity().getMin() > 0;
if (requiredAtLeastOneFieldSet) {
@ -124,8 +127,8 @@ public class PropertyDefinitionPersist {
private List<FieldEntity> getMissingFieldsEntity(PropertyDefinitionPersist item){
List<FieldEntity> missingFields = new ArrayList<>();
if (definition == null || definition.getAllFieldSets() == null) return missingFields;
for (FieldSetEntity fieldSet: definition.getAllFieldSets()) {
if (this.definition == null || this.definition.getAllFieldSets() == null) return missingFields;
for (FieldSetEntity fieldSet: this.definition.getAllFieldSets()) {
if (fieldSet.getFields() == null) continue;
@ -163,12 +166,12 @@ public class PropertyDefinitionPersist {
private String serializeMissingFieldSets (List<FieldSetEntity> missingFieldSets){
if (missingFieldSets == null) return "";
return missingFieldSets.stream().map(x -> x.getId()).collect(Collectors.joining(", "));
return missingFieldSets.stream().map(FieldSetEntity::getId).collect(Collectors.joining(", "));
}
private String serializeMissingFields (List<FieldEntity> missingFields){
if (missingFields == null) return "";
return missingFields.stream().map(x -> x.getId()).collect(Collectors.joining(", "));
return missingFields.stream().map(FieldEntity::getId).collect(Collectors.joining(", "));
}
}

View File

@ -1,9 +1,9 @@
package org.opencdmp.model.persist.descriptionreference;
import gr.cite.tools.validation.specification.Specification;
import org.opencdmp.commons.validation.BaseValidator;
import org.opencdmp.convention.ConventionService;
import org.opencdmp.errorcode.ErrorThesaurusProperties;
import gr.cite.tools.validation.specification.Specification;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Scope;
@ -12,7 +12,6 @@ import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
public class DescriptionReferenceDataPersist {
@ -21,7 +20,7 @@ public class DescriptionReferenceDataPersist {
public static final String _fieldId = "fieldId";
public String getFieldId() {
return fieldId;
return this.fieldId;
}
public void setFieldId(String fieldId) {
@ -50,7 +49,7 @@ public class DescriptionReferenceDataPersist {
return Arrays.asList(
this.spec()
.must(() -> !this.isNull(item.getFieldId()))
.failOn(DescriptionReferenceDataPersist._fieldId).failWith(messageSource.getMessage("Validation_Required", new Object[]{DescriptionReferenceDataPersist._fieldId}, LocaleContextHolder.getLocale()))
.failOn(DescriptionReferenceDataPersist._fieldId).failWith(this.messageSource.getMessage("Validation_Required", new Object[]{DescriptionReferenceDataPersist._fieldId}, LocaleContextHolder.getLocale()))
);
}
}

View File

@ -66,6 +66,8 @@ import org.opencdmp.service.filetransformer.FileTransformerService;
import org.opencdmp.service.responseutils.ResponseUtilsService;
import org.opencdmp.service.storage.StorageFileProperties;
import org.opencdmp.service.storage.StorageFileService;
import org.opencdmp.service.visibility.VisibilityService;
import org.opencdmp.service.visibility.VisibilityServiceImpl;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
@ -237,11 +239,12 @@ public class DescriptionServiceImpl implements DescriptionService {
this.entityManager.flush();
org.opencdmp.commons.types.descriptiontemplate.DefinitionEntity definition = this.xmlHandlingService.fromXmlSafe(org.opencdmp.commons.types.descriptiontemplate.DefinitionEntity.class, descriptionTemplateEntity.getDefinition());
Map<String, List<UUID>> fieldToReferenceMap = this.patchAndSaveReferences(this.buildDescriptionReferencePersists(model.getProperties()), data.getId(), definition);
VisibilityService visibilityService = new VisibilityServiceImpl(definition, model.getProperties());
Map<String, List<UUID>> fieldToReferenceMap = this.patchAndSaveReferences(this.buildDescriptionReferencePersists(visibilityService, model.getProperties()), data.getId(), definition);
this.entityManager.flush();
data.setProperties(this.jsonHandlingService.toJson(this.buildPropertyDefinitionEntity(model.getProperties(), definition, fieldToReferenceMap)));
data.setProperties(this.jsonHandlingService.toJson(this.buildPropertyDefinitionEntity(visibilityService, model.getProperties(), definition, fieldToReferenceMap)));
this.entityManager.merge(data);
@ -262,7 +265,7 @@ public class DescriptionServiceImpl implements DescriptionService {
return this.builderFactory.builder(DescriptionBuilder.class).authorize(AuthorizationFlags.OwnerOrDmpAssociatedOrPermission).build(BaseFieldSet.build(fields, Description._id), data);
}
@Override
public void updateDescriptionTemplate(UpdateDescriptionTemplatePersist model) throws InvalidApplicationException, IOException, JAXBException {
public void updateDescriptionTemplate(UpdateDescriptionTemplatePersist model) throws InvalidApplicationException, IOException {
logger.debug(new MapLogEntry("update description template").And("model", model));
this.authorizationService.authorizeAtLeastOneForce(List.of(this.authorizationContentResolver.descriptionAffiliation(model.getId())), Permission.EditDescription);
@ -399,7 +402,7 @@ public class DescriptionServiceImpl implements DescriptionService {
this.eventHandler.handle(event);
}
private NotifyIntegrationEvent applyNotificationType(DescriptionStatus status, NotifyIntegrationEvent event) {
private void applyNotificationType(DescriptionStatus status, NotifyIntegrationEvent event) {
switch (status) {
case Draft:
event.setNotificationType(this.notificationProperties.getDescriptionModifiedType());
@ -410,7 +413,7 @@ public class DescriptionServiceImpl implements DescriptionService {
default:
throw new MyApplicationException("Unsupported Description Status.");
}
return event;
return;
}
@Override
@ -460,38 +463,39 @@ public class DescriptionServiceImpl implements DescriptionService {
DescriptionPersist.DescriptionPersistValidator validator = this.validatorFactory.validator(DescriptionPersist.DescriptionPersistValidator.class);
validator.validate(this.buildDescriptionPersist(description));
if (validator.result().isValid()) descriptionValidationResult.setResult(DescriptionValidationOutput.Valid);
descriptionValidationResults.add(descriptionValidationResult);
descriptionValidationResults.add(descriptionValidationResult);
}
return descriptionValidationResults;
}
private @NotNull PropertyDefinitionEntity buildPropertyDefinitionEntity(PropertyDefinitionPersist persist, org.opencdmp.commons.types.descriptiontemplate.DefinitionEntity definition, Map<String, List<UUID>> fieldToReferenceMap) throws InvalidApplicationException {
private @NotNull PropertyDefinitionEntity buildPropertyDefinitionEntity(VisibilityService visibilityService, PropertyDefinitionPersist persist, org.opencdmp.commons.types.descriptiontemplate.DefinitionEntity definition, Map<String, List<UUID>> fieldToReferenceMap) throws InvalidApplicationException {
PropertyDefinitionEntity data = new PropertyDefinitionEntity();
if (persist == null) return data;
if (persist.getFieldSets() != null && !persist.getFieldSets().isEmpty()){
data.setFieldSets(new HashMap<>());
for (String key: persist.getFieldSets().keySet()) {
FieldSetEntity fieldSetEntity = definition != null ? definition.getFieldSetById(key).stream().findFirst().orElse(null) : null;
data.getFieldSets().put(key, this.buildPropertyDefinitionFieldSetEntity(persist.getFieldSets().get(key), fieldSetEntity, fieldToReferenceMap));
data.getFieldSets().put(key, this.buildPropertyDefinitionFieldSetEntity(persist.getFieldSets().get(key), fieldSetEntity, fieldToReferenceMap, visibilityService));
}
}
return data;
}
private @NotNull PropertyDefinitionFieldSetEntity buildPropertyDefinitionFieldSetEntity(PropertyDefinitionFieldSetPersist persist, FieldSetEntity fieldSetEntity, Map<String, List<UUID>> fieldToReferenceMap) throws InvalidApplicationException {
private @NotNull PropertyDefinitionFieldSetEntity buildPropertyDefinitionFieldSetEntity(PropertyDefinitionFieldSetPersist persist, FieldSetEntity fieldSetEntity, Map<String, List<UUID>> fieldToReferenceMap, VisibilityService visibilityService) throws InvalidApplicationException {
PropertyDefinitionFieldSetEntity data = new PropertyDefinitionFieldSetEntity();
if (persist == null) return data;
if (!this.conventionService.isListNullOrEmpty(persist.getItems())){
data.setItems(new ArrayList<>());
for (PropertyDefinitionFieldSetItemPersist itemsPersist: persist.getItems()) {
data.getItems().add(this.buildPropertyDefinitionFieldSetItemEntity(itemsPersist, fieldSetEntity, fieldToReferenceMap));
data.getItems().add(this.buildPropertyDefinitionFieldSetItemEntity(itemsPersist, fieldSetEntity, fieldToReferenceMap, visibilityService));
}
}
return data;
}
private @NotNull PropertyDefinitionFieldSetItemEntity buildPropertyDefinitionFieldSetItemEntity(PropertyDefinitionFieldSetItemPersist persist, FieldSetEntity fieldSetEntity, Map<String, List<UUID>> fieldToReferenceMap) throws InvalidApplicationException {
private @NotNull PropertyDefinitionFieldSetItemEntity buildPropertyDefinitionFieldSetItemEntity(PropertyDefinitionFieldSetItemPersist persist, FieldSetEntity fieldSetEntity, Map<String, List<UUID>> fieldToReferenceMap, VisibilityService visibilityService) throws InvalidApplicationException {
PropertyDefinitionFieldSetItemEntity data = new PropertyDefinitionFieldSetItemEntity();
if (persist == null) return data;
if (persist.getFields() != null && !persist.getFields().isEmpty()){
@ -500,16 +504,17 @@ public class DescriptionServiceImpl implements DescriptionService {
data.setFields(new HashMap<>());
for (String key: persist.getFields().keySet()) {
org.opencdmp.commons.types.descriptiontemplate.FieldEntity fieldEntity = fieldSetEntity != null ? fieldSetEntity.getFieldById(key).stream().findFirst().orElse(null) : null;
data.getFields().put(key, this.buildFieldEntity(persist.getFields().get(key), fieldEntity, fieldToReferenceMap));
boolean isVisible = fieldEntity != null ? visibilityService.isVisible(fieldEntity.getId(), persist.getOrdinal()) : false;
data.getFields().put(key, this.buildFieldEntity(persist.getFields().get(key), fieldEntity, fieldToReferenceMap, isVisible));
}
}
return data;
}
private @NotNull FieldEntity buildFieldEntity(FieldPersist persist, org.opencdmp.commons.types.descriptiontemplate.FieldEntity fieldEntity, Map<String, List<UUID>> fieldToReferenceMap) throws InvalidApplicationException {
private @NotNull FieldEntity buildFieldEntity(FieldPersist persist, org.opencdmp.commons.types.descriptiontemplate.FieldEntity fieldEntity, Map<String, List<UUID>> fieldToReferenceMap, boolean isVisible) throws InvalidApplicationException {
FieldType fieldType = fieldEntity != null && fieldEntity.getData() != null ? fieldEntity.getData().getFieldType() : FieldType.FREE_TEXT;
FieldEntity data = new FieldEntity();
if (persist == null) return data;
if (persist == null || !isVisible) return data;
if (FieldType.isTextType(fieldType)) {
if (FieldType.UPLOAD.equals(fieldType)){
@ -537,7 +542,7 @@ public class DescriptionServiceImpl implements DescriptionService {
else if (FieldType.isTextListType(fieldType)) {
List<UUID> ids = new ArrayList<>();
if (FieldType.INTERNAL_ENTRIES_DMPS.equals(fieldType)) {
if (!this.conventionService.isListNullOrEmpty(persist.getTextListValue())) persist.getTextListValue().stream().map(UUID::fromString).toList();
if (!this.conventionService.isListNullOrEmpty(persist.getTextListValue())) ids = persist.getTextListValue().stream().map(UUID::fromString).toList();
else if (!this.conventionService.isNullOrEmpty(persist.getTextValue())) ids.add(UUID.fromString(persist.getTextValue()));
if (!ids.isEmpty()){
@ -590,7 +595,7 @@ public class DescriptionServiceImpl implements DescriptionService {
return data;
}
private @NotNull List<DescriptionReferencePersist> buildDescriptionReferencePersists(PropertyDefinitionPersist persist){
private @NotNull List<DescriptionReferencePersist> buildDescriptionReferencePersists(VisibilityService visibilityService, PropertyDefinitionPersist persist){
List<DescriptionReferencePersist> descriptionReferencePersists = new ArrayList<>();
if (persist.getFieldSets() != null && !persist.getFieldSets().isEmpty()){
for (PropertyDefinitionFieldSetPersist propertyDefinitionFieldSetPersist: persist.getFieldSets().values()) {
@ -599,7 +604,8 @@ public class DescriptionServiceImpl implements DescriptionService {
if (definitionFieldSetItemPersist.getFields() != null && !definitionFieldSetItemPersist.getFields().isEmpty()) {
for (String key : definitionFieldSetItemPersist.getFields().keySet()) {
FieldPersist fieldPersist = definitionFieldSetItemPersist.getFields().get(key);
this.BuildDescriptionReferencePersist(key, fieldPersist, descriptionReferencePersists);
boolean isVisible = visibilityService.isVisible(key, definitionFieldSetItemPersist.getOrdinal());
if (isVisible) this.BuildDescriptionReferencePersist(key, fieldPersist, descriptionReferencePersists);
}
}
}
@ -649,7 +655,7 @@ public class DescriptionServiceImpl implements DescriptionService {
List<UUID> updatedCreatedIds = new ArrayList<>();
for (DescriptionReferencePersist model : models) {
ReferencePersist referencePersist = model.getReference();
ReferenceEntity referenceEntity = null;
ReferenceEntity referenceEntity;
if (this.conventionService.isValidGuid(referencePersist.getId())){
referenceEntity = this.entityManager.find(ReferenceEntity.class, referencePersist.getId());
if (referenceEntity == null) throw new MyNotFoundException(this.messageSource.getMessage("General_ItemNotFound", new Object[]{referencePersist.getId(), Reference.class.getSimpleName()}, LocaleContextHolder.getLocale()));

View File

@ -1,18 +1,16 @@
package org.opencdmp.service.tenant;
import org.opencdmp.model.Tenant;
import org.opencdmp.model.persist.TenantPersist;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
import gr.cite.tools.exception.MyNotFoundException;
import gr.cite.tools.exception.MyValidationException;
import gr.cite.tools.fieldset.FieldSet;
import org.opencdmp.model.Tenant;
import org.opencdmp.model.persist.TenantPersist;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.management.InvalidApplicationException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
@ -26,4 +24,6 @@ public interface TenantService {
InvalidAlgorithmParameterException, NoSuchPaddingException, IllegalBlockSizeException, NoSuchAlgorithmException, BadPaddingException, InvalidKeyException;
void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException;
List<Tenant> myTenants(FieldSet fieldSet) throws MyForbiddenException;
}

View File

@ -1,8 +1,12 @@
package org.opencdmp.service.tenant;
import gr.cite.commons.web.authz.service.AuthorizationService;
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
import gr.cite.commons.web.oidc.principal.MyPrincipal;
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
import gr.cite.tools.data.builder.BuilderFactory;
import gr.cite.tools.data.deleter.DeleterFactory;
import gr.cite.tools.data.query.Ordering;
import gr.cite.tools.data.query.QueryFactory;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyForbiddenException;
@ -14,6 +18,7 @@ import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import org.opencdmp.authorization.AuthorizationFlags;
import org.opencdmp.authorization.AuthorizationProperties;
import org.opencdmp.authorization.ClaimNames;
import org.opencdmp.authorization.Permission;
import org.opencdmp.commons.enums.IsActive;
import org.opencdmp.commons.scope.tenant.TenantScope;
@ -31,6 +36,7 @@ import org.opencdmp.model.Tenant;
import org.opencdmp.model.builder.TenantBuilder;
import org.opencdmp.model.deleter.TenantDeleter;
import org.opencdmp.model.persist.TenantPersist;
import org.opencdmp.query.TenantQuery;
import org.opencdmp.query.UserCredentialQuery;
import org.opencdmp.query.UserRoleQuery;
import org.opencdmp.service.keycloak.KeycloakService;
@ -48,6 +54,7 @@ import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@ -73,6 +80,8 @@ public class TenantServiceImpl implements TenantService {
private final AuthorizationProperties authorizationProperties;
private final TenantScope tenantScope;
private final QueryFactory queryFactory;
private final CurrentPrincipalResolver currentPrincipalResolver;
private final ClaimExtractor claimExtractor;
@Autowired
@ -83,7 +92,7 @@ public class TenantServiceImpl implements TenantService {
BuilderFactory builderFactory,
ConventionService conventionService,
MessageSource messageSource,
ErrorThesaurusProperties errors, TenantTouchedIntegrationEventHandler tenantTouchedIntegrationEventHandler, TenantRemovalIntegrationEventHandler tenantRemovalIntegrationEventHandler, KeycloakService keycloakService, AuthorizationProperties authorizationProperties, TenantScope tenantScope, QueryFactory queryFactory) {
ErrorThesaurusProperties errors, TenantTouchedIntegrationEventHandler tenantTouchedIntegrationEventHandler, TenantRemovalIntegrationEventHandler tenantRemovalIntegrationEventHandler, KeycloakService keycloakService, AuthorizationProperties authorizationProperties, TenantScope tenantScope, QueryFactory queryFactory, CurrentPrincipalResolver currentPrincipalResolver, ClaimExtractor claimExtractor) {
this.entityManager = entityManager;
this.authorizationService = authorizationService;
this.deleterFactory = deleterFactory;
@ -97,6 +106,8 @@ public class TenantServiceImpl implements TenantService {
this.authorizationProperties = authorizationProperties;
this.tenantScope = tenantScope;
this.queryFactory = queryFactory;
this.currentPrincipalResolver = currentPrincipalResolver;
this.claimExtractor = claimExtractor;
}
@Override
@ -131,6 +142,9 @@ public class TenantServiceImpl implements TenantService {
this.entityManager.flush();
Long tenantsWithThisCode = this.queryFactory.query(TenantQuery.class).codes(data.getCode()).count();
if (tenantsWithThisCode > 1) throw new MyValidationException(this.errors.getTenantCodeExists().getCode(), this.errors.getTenantCodeExists().getMessage());
if (!isUpdate) {
this.keycloakService.createTenantGroups(data.getCode());
this.autoAssignGlobalAdminsToNewTenant(data);
@ -177,8 +191,6 @@ public class TenantServiceImpl implements TenantService {
}
@Override
public void deleteAndSave(UUID id) throws MyForbiddenException, InvalidApplicationException {
logger.debug("deleting : {}", id);
@ -192,5 +204,38 @@ public class TenantServiceImpl implements TenantService {
this.tenantRemovalIntegrationEventHandler.handle(tenantRemovalIntegrationEvent);
}
@Override
public List<Tenant> myTenants(FieldSet fieldSet) throws MyForbiddenException {
logger.debug("my tenants");
MyPrincipal principal = this.currentPrincipalResolver.currentPrincipal();
List<String> tenants = this.claimExtractor.asStrings(principal, ClaimNames.TenantCodesClaimName);
List<Tenant> models = new ArrayList<>();
if (tenants != null && !tenants.isEmpty()) {
if (fieldSet == null || fieldSet.isEmpty()) {
fieldSet = new BaseFieldSet(
Tenant._id,
Tenant._code,
Tenant._name);
}
TenantQuery query = this.queryFactory.query(TenantQuery.class).codes(tenants).isActive(IsActive.Active);
query.setOrder(new Ordering().addAscending(Tenant._name));
List<TenantEntity> data = query.collectAs(fieldSet);
models.addAll(this.builderFactory.builder(TenantBuilder.class).build(fieldSet, data));
if (tenants.contains(this.tenantScope.getDefaultTenantCode())){
Tenant tenant = new Tenant();
tenant.setCode(this.tenantScope.getDefaultTenantCode());
tenant.setName(this.messageSource.getMessage("DefaultTenant_Name", new Object[]{}, LocaleContextHolder.getLocale()));
models.addFirst(tenant);
}
}
return models;
}
}

View File

@ -1,17 +1,16 @@
package org.opencdmp.controllers;
import org.opencdmp.audit.AuditableAction;
import org.opencdmp.authorization.ClaimNames;
import org.opencdmp.commons.scope.tenant.TenantScope;
import org.opencdmp.models.Account;
import org.opencdmp.models.AccountBuilder;
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
import gr.cite.commons.web.oidc.principal.MyPrincipal;
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
import gr.cite.tools.auditing.AuditService;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.fieldset.FieldSet;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.audit.AuditableAction;
import org.opencdmp.model.Tenant;
import org.opencdmp.models.Account;
import org.opencdmp.models.AccountBuilder;
import org.opencdmp.service.tenant.TenantService;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
@ -21,27 +20,26 @@ import org.springframework.web.bind.annotation.RestController;
import javax.management.InvalidApplicationException;
import java.util.List;
import java.util.stream.Collectors;
@RestController
@RequestMapping(value = { "/api/principal/" })
@RequestMapping("/api/principal/")
public class PrincipalController {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(PrincipalController.class));
private final AuditService auditService;
private final CurrentPrincipalResolver currentPrincipalResolver;
private final AccountBuilder accountBuilder;
private final ClaimExtractor claimExtractor;
private final TenantService tenantService;
@Autowired
public PrincipalController(
CurrentPrincipalResolver currentPrincipalResolver,
AccountBuilder accountBuilder,
AuditService auditService, ClaimExtractor claimExtractor) {
AuditService auditService, TenantService tenantService) {
this.currentPrincipalResolver = currentPrincipalResolver;
this.accountBuilder = accountBuilder;
this.auditService = auditService;
this.claimExtractor = claimExtractor;
this.tenantService = tenantService;
}
@RequestMapping(path = "me", method = RequestMethod.GET )
@ -80,16 +78,15 @@ public class PrincipalController {
}
@GetMapping("my-tenants")
public List<String> myTenants() {
public List<Tenant> myTenants(FieldSet fieldSet) {
logger.debug("my-tenants");
MyPrincipal principal = this.currentPrincipalResolver.currentPrincipal();
List<String> tenants = this.claimExtractor.asStrings(principal, ClaimNames.TenantCodesClaimName);
List<Tenant> models = this.tenantService.myTenants(fieldSet);
this.auditService.track(AuditableAction.Principal_MyTenants);
//auditService.trackIdentity(AuditableAction.IdentityTracking_Action);
return tenants == null ? null : tenants.stream().distinct().collect(Collectors.toList());
return models;
}
}

View File

@ -1,10 +1,5 @@
package org.opencdmp.models;
import org.opencdmp.commons.JsonHandlingService;
import org.opencdmp.commons.scope.user.UserScope;
import org.opencdmp.commons.types.user.AdditionalInfoEntity;
import org.opencdmp.data.TenantEntityManager;
import org.opencdmp.data.UserEntity;
import gr.cite.commons.web.authz.configuration.AuthorizationConfiguration;
import gr.cite.commons.web.authz.configuration.Permission;
import gr.cite.commons.web.oidc.principal.CurrentPrincipalResolver;
@ -13,6 +8,11 @@ import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractor;
import gr.cite.commons.web.oidc.principal.extractor.ClaimExtractorKeys;
import gr.cite.tools.fieldset.BaseFieldSet;
import gr.cite.tools.fieldset.FieldSet;
import org.opencdmp.commons.JsonHandlingService;
import org.opencdmp.commons.scope.user.UserScope;
import org.opencdmp.commons.types.user.AdditionalInfoEntity;
import org.opencdmp.data.TenantEntityManager;
import org.opencdmp.data.UserEntity;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@ -21,7 +21,7 @@ import javax.management.InvalidApplicationException;
import java.util.*;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class AccountBuilder {
private final ClaimExtractor claimExtractor;
@ -91,13 +91,13 @@ public class AccountBuilder {
}
}
if (fields.hasField(Account._roles)) {
List<String> roles = claimExtractor.roles(currentPrincipalResolver.currentPrincipal());
List<String> roles = this.claimExtractor.roles(this.currentPrincipalResolver.currentPrincipal());
model.setRoles(roles);
}
if (fields.hasField(Account._permissions)) {
List<String> roles = claimExtractor.roles(currentPrincipalResolver.currentPrincipal());
Set<String> permissions = authorizationConfiguration.permissionsOfRoles(roles);
for (Map.Entry<String, Permission> permissionEntry : authorizationConfiguration.getRawPolicies().entrySet()){
List<String> roles = this.claimExtractor.roles(this.currentPrincipalResolver.currentPrincipal());
Set<String> permissions = this.authorizationConfiguration.permissionsOfRoles(roles);
for (Map.Entry<String, Permission> permissionEntry : this.authorizationConfiguration.getRawPolicies().entrySet()){
if (permissionEntry.getValue().getAllowAuthenticated()){
permissions.add(permissionEntry.getKey());
}

View File

@ -65,4 +65,6 @@ error-thesaurus:
multiple-tenant-configuration-type-not-allowed:
code: 125
message: Multiple Tenant Configuration Type Not Allowed
tenant-code-exists:
code: 126
message: Tenant code exists

View File

@ -28,3 +28,5 @@ Validation.MissingFields= missing fields: {0}
Validation.InvalidDescriptionTemplateMultiplicity= {0} can not be used
Validation.InvalidDescriptionTemplateMultiplicityOnDMP= Description Templates has multiplicity errors
Validation_UrlRequired={0} is not valid url
DefaultTenant_Name=Default

View File

@ -16,5 +16,5 @@ export enum ResponseErrorCode {
TenantTampering = 123,
TenantConfigurationTypeCanNotChange = 124,
MultipleTenantConfigurationTypeNotAllowed = 125,
TenantCodeExists = 126,
}

View File

@ -4,6 +4,7 @@ import { Observable } from 'rxjs';
import { ConfigurationService } from '../configuration/configuration.service';
import { BaseHttpV2Service } from '../http/base-http-v2.service';
import { map } from 'rxjs/operators';
import { Tenant } from '@app/core/model/tenant/tenant';
@Injectable()
export class PrincipalService {
@ -20,8 +21,8 @@ export class PrincipalService {
return this.http.get<AppAccount>(url, options);
}
public myTenants(options?: Object): Observable<Array<string>> {
public myTenants(options?: Object): Observable<Array<Tenant>> {
const url = `${this.apiBase}/my-tenants`;
return this.http.get<Array<string>>(url, options);
return this.http.get<Array<Tenant>>(url, options);
}
}

View File

@ -64,9 +64,9 @@ export class PostLoginComponent extends BaseComponent implements OnInit {
this.principalService.myTenants({ params: params }).subscribe(myTenants => {
if (myTenants) {
if (myTenants.length > 1) {
this.tenants = myTenants.map(function (code) { return { 'code': code }; });
this.tenants = myTenants;
} else if (myTenants.length === 1) {
this.authService.selectedTenant(myTenants[0]);
this.authService.selectedTenant(myTenants[0]?.code);
this.loadUser();
} else {
this.authService.selectedTenant(null);

View File

@ -19,7 +19,7 @@
<div class="col-auto description-to-dmp">{{'DESCRIPTION-EDITOR.TO-DMP' | translate}}</div>
<div class="dmp-title p-0">:&nbsp;{{ item?.dmp?.label }}</div>
<div class="col-auto d-flex align-items-center">
<a [routerLink]="['/overview/' + item.dmp.id]" target="_blank" class="pointer open-in-new-icon">
<a [routerLink]="['/plans/overview/' + item.dmp.id]" target="_blank" class="pointer open-in-new-icon">
<mat-icon class="size-18">open_in_new</mat-icon>
</a>
</div>

View File

@ -1,5 +1,5 @@
<mat-button-toggle-group class="tenant-menu" vertical (change)="onTenantSelected($event)" [value]="this.currentTenant">
<div *ngFor="let tenant of tenants | async">
<mat-button-toggle class="tenant-button" [value]="tenant">{{ tenant }}</mat-button-toggle>
<mat-button-toggle class="tenant-button" [value]="tenant.code">{{ tenant.name }}</mat-button-toggle>
</div>
</mat-button-toggle-group>

View File

@ -1,6 +1,7 @@
import { Component, EventEmitter, OnInit, Output } from "@angular/core";
import { MatButtonToggleChange } from "@angular/material/button-toggle";
import { Router } from "@angular/router";
import { Tenant } from "@app/core/model/tenant/tenant";
import { AuthService } from "@app/core/services/auth/auth.service";
import { PrincipalService } from "@app/core/services/http/principal.service";
import { BaseComponent } from "@common/base/base.component";
@ -16,7 +17,7 @@ import { takeUntil } from "rxjs/operators";
styleUrls: ['tenant-switch.component.scss']
})
export class TenantSwitchComponent extends BaseComponent implements OnInit {
tenants: Observable<Array<string>>;
tenants: Observable<Array<Tenant>>;
constructor(
private router: Router,
@ -36,7 +37,7 @@ export class TenantSwitchComponent extends BaseComponent implements OnInit {
//this.tenantChange.emit(this.getCurrentLanguage())
}
loadUserTenants(): Observable<Array<string>> {
loadUserTenants(): Observable<Array<Tenant>> {
const params = new BaseHttpParams();
params.interceptorContext = {
excludedInterceptors: [InterceptorType.TenantHeaderInterceptor]

View File

@ -15,7 +15,7 @@
<mat-label>Tenant</mat-label>
<mat-select placeholder="Tenant" [formControl]="this.tenantFormGroup.get('tenantCode')">
<ng-container *ngFor="let tenant of tenants | async">
<mat-option [value]="tenant">{{ tenant }}</mat-option>
<mat-option [value]="tenant.code">{{ tenant.name }}</mat-option>
</ng-container>
</mat-select>
</mat-form-field>

View File

@ -38,6 +38,7 @@ import { ReferenceTypeService } from '@app/core/services/reference-type/referenc
import { SingleAutoCompleteConfiguration } from '@app/library/auto-complete/single/single-auto-complete-configuration';
import { ReferenceSourceType } from '@app/core/common/enum/reference-source-type';
import { ReferenceType } from '@app/core/model/reference-type/reference-type';
import { Tenant } from '@app/core/model/tenant/tenant';
@Component({
selector: 'app-user-profile',
@ -61,7 +62,7 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
errorMessages = [];
nestedCount = [];
nestedIndex = 0;
tenants: Observable<Array<string>>;
tenants: Observable<Array<Tenant>>;
expandedPreferences: boolean = false;
organisationsSingleAutoCompleteConfiguration: SingleAutoCompleteConfiguration;
@ -438,7 +439,7 @@ export class UserProfileComponent extends BaseComponent implements OnInit, OnDes
}
// Switch Tenant
loadUserTenants(): Observable<Array<string>> {
loadUserTenants(): Observable<Array<Tenant>> {
const params = new BaseHttpParams();
params.interceptorContext = {
excludedInterceptors: [InterceptorType.TenantHeaderInterceptor]

View File

@ -139,6 +139,9 @@ export abstract class BaseEditor<EditorModelType extends BaseEditorModel, Entity
this.uiNotificationService.snackBarNotification(errorResponse.error.error, SnackBarNotificationLevel.Error);
this.refreshOnNavigateToData(null);
}
if(errorResponse.error.code === ResponseErrorCode.TenantCodeExists){
this.uiNotificationService.snackBarNotification(errorResponse.error.error, SnackBarNotificationLevel.Error);
}
else {
this.uiNotificationService.snackBarNotification(error.getMessagesString(), SnackBarNotificationLevel.Warning);
}