Code development platform for open source projects from the European Union institutions

Skip to content
Snippets Groups Projects
Commit a4b938ef authored by Joze RIHTARSIC's avatar Joze RIHTARSIC
Browse files

Pull request #99: EDELIVERY-12743 implement domain properties configuration for the ui

Merge in EDELIVERY/smp from feature/EDELIVERY-12743-ui-domain-configuration to development

* commit 'c889dc08':
  Fix the PR comments
  fix unit test build
  EDELIVERY-12743 implement domain properties configuration for the ui
parents 3dfe4474 c889dc08
No related branches found
No related tags found
No related merge requests found
Pipeline #173504 failed
Showing
with 906 additions and 316 deletions
......@@ -18,6 +18,7 @@
*/
package eu.europa.ec.edelivery.smp.conversion;
import eu.europa.ec.edelivery.smp.data.enums.MemberOfType;
import eu.europa.ec.edelivery.smp.data.model.user.DBGroupMember;
import eu.europa.ec.edelivery.smp.data.ui.MemberRO;
import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
......@@ -26,7 +27,10 @@ import org.springframework.stereotype.Component;
/**
* Converter for DBGroupMember to MemberRO
*
* @author Joze Rihtarsic
* @since 5.0
*/
@Component
public class DBGroupMemberToMemberROConverter implements Converter<DBGroupMember, MemberRO> {
......@@ -34,12 +38,11 @@ public class DBGroupMemberToMemberROConverter implements Converter<DBGroupMember
@Override
public MemberRO convert(DBGroupMember source) {
MemberRO target = new MemberRO();
target.setMemberOf("GROUP");
target.setMemberOf(MemberOfType.GROUP);
target.setUsername(source.getUser().getUsername());
target.setFullName(source.getUser().getFullName());
target.setRoleType(source.getRole());
target.setMemberId(SessionSecurityUtils.encryptedEntityId(source.getId()));
return target;
}
}
......@@ -18,6 +18,7 @@
*/
package eu.europa.ec.edelivery.smp.conversion;
import eu.europa.ec.edelivery.smp.data.enums.MemberOfType;
import eu.europa.ec.edelivery.smp.data.model.user.DBResourceMember;
import eu.europa.ec.edelivery.smp.data.ui.MemberRO;
import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils;
......@@ -34,7 +35,7 @@ public class DBResourceMemberToMemberROConverter implements Converter<DBResource
@Override
public MemberRO convert(DBResourceMember source) {
MemberRO target = new MemberRO();
target.setMemberOf("RESOURCE");
target.setMemberOf(MemberOfType.RESOURCE);
target.setUsername(source.getUser().getUsername());
target.setFullName(source.getUser().getFullName());
target.setRoleType(source.getRole());
......
......@@ -41,6 +41,7 @@ public class DBSubresourceDefToSubresourceDefinitionROConverter implements Conve
SubresourceDefinitionRO target = new SubresourceDefinitionRO();
try {
org.springframework.beans.BeanUtils.copyProperties(source, target);
BeanUtils.copyProperties(target, source);
} catch (IllegalAccessException | InvocationTargetException e) {
LOG.error("Error occurred while converting DBResourceDef", e);
......
package eu.europa.ec.edelivery.smp.conversion;
import eu.europa.ec.edelivery.smp.config.enums.SMPDomainPropertyEnum;
import eu.europa.ec.edelivery.smp.data.model.DBDomainConfiguration;
import eu.europa.ec.edelivery.smp.data.ui.DomainPropertyRO;
import eu.europa.ec.edelivery.smp.logging.SMPLogger;
import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
import eu.europa.ec.edelivery.smp.services.ConfigurationService;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
/**
* Converts a {@link DBDomainConfiguration} to a {@link DomainPropertyRO}.
*
* @author Joze Rihtars
* @since 5.1
*/
@Component
public class DomainPropEnumToDomainPropROConverter implements Converter<SMPDomainPropertyEnum, DomainPropertyRO> {
protected static final SMPLogger LOG = SMPLoggerFactory.getLogger(DomainPropEnumToDomainPropROConverter.class);
private final ConfigurationService configurationService;
public DomainPropEnumToDomainPropROConverter(ConfigurationService configurationService) {
this.configurationService = configurationService;
}
/**
* Create DomainPropertyRO with system default value for given SMPDomainPropertyEnum.
* Note: The method does not update the database value.
*
* @param property - property to create
* @return DomainPropertyRO with system default value
*/
@Override
public DomainPropertyRO convert(SMPDomainPropertyEnum property) {
DomainPropertyRO domainConfiguration = new DomainPropertyRO();
domainConfiguration.setProperty(property.getProperty());
domainConfiguration.setSystemDefaultValue(configurationService.getDefaultDomainConfiguration(property));
domainConfiguration.setSystemDefault(true);
domainConfiguration.setValuePattern(property.getValuePattern().pattern());
domainConfiguration.setType(property.getPropertyType().name());
domainConfiguration.setDesc(property.getDesc());
return domainConfiguration;
}
}
/*-
* #START_LICENSE#
* smp-webapp
* %%
* Copyright (C) 2017 - 2024 European Commission | eDelivery | DomiSMP
* %%
* Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and limitations under the Licence.
* #END_LICENSE#
*/
package eu.europa.ec.edelivery.smp.conversion;
import eu.europa.ec.dynamicdiscovery.model.identifiers.types.EBCorePartyIdFormatterType;
import eu.europa.ec.edelivery.smp.identifiers.Identifier;
import eu.europa.ec.edelivery.smp.identifiers.IdentifierFormatter;
import eu.europa.ec.edelivery.smp.logging.SMPLogger;
import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
import eu.europa.ec.edelivery.smp.services.ConfigurationService;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.regex.Pattern;
/**
* Class provides tools to parse, format and normalize Document and Participant identifiers.
*
* @author gutowpa
* @since 3.0.0
*/
@Component
public class IdentifierService {
private static final SMPLogger LOG = SMPLoggerFactory.getLogger(IdentifierService.class);
IdentifierFormatter participantIdentifierFormatter = IdentifierFormatter.Builder
.create()
.addFormatterTypes(new EBCorePartyIdFormatterType())
.build();
IdentifierFormatter documentIdentifierFormatter = IdentifierFormatter.Builder.create().build();
ConfigurationService configurationService;
public IdentifierService(ConfigurationService configurationService) {
this.configurationService = configurationService;
}
/**
* Update ParticipantIdentifierFormatter for non null values. Null values are ignored
*
* @param caseInsensitiveSchemas list of schemas for which case insensitivity is required
* @param mandatoryScheme if true, scheme is mandatory
*/
public void configureParticipantIdentifierFormatter(List<String> caseInsensitiveSchemas, Boolean mandatoryScheme, Pattern allowedSchemeRegExp) {
if (caseInsensitiveSchemas != null) {
participantIdentifierFormatter.setCaseSensitiveSchemas(caseInsensitiveSchemas);
} else {
LOG.debug("Skip configure ParticipantIdentifierFormatter.caseInsensitiveSchemas for null value");
}
if (mandatoryScheme != null) {
participantIdentifierFormatter.setSchemeMandatory(mandatoryScheme);
} else {
LOG.debug("Skip configure ParticipantIdentifierFormatter.mandatoryScheme for null value");
}
if (allowedSchemeRegExp != null) {
participantIdentifierFormatter.setSchemeValidationPattern(allowedSchemeRegExp);
} else {
LOG.debug("Skip configure ParticipantIdentifierFormatter.allowedSchemeRegExp for null value");
}
}
/**
* Update DocumentIdentifierFormatter for non null values. Null values are ignored
*
* @param caseInsensitiveSchemas list of schemas for which case insensitivity is required
*/
public void configureDocumentIdentifierFormatter(List<String> caseInsensitiveSchemas) {
if (caseInsensitiveSchemas != null) {
documentIdentifierFormatter.setCaseSensitiveSchemas(caseInsensitiveSchemas);
} else {
LOG.debug("Skip configure DocumentIdentifierFormatter.caseInsensitiveSchemas for null value");
}
}
public Identifier normalizeDocument(final Identifier documentIdentifier) {
return documentIdentifierFormatter.normalize(documentIdentifier);
}
public Identifier normalizeDocument(final String scheme, final String identifier) {
return documentIdentifierFormatter.normalize(scheme, identifier);
}
public Identifier normalizeDocumentIdentifier(String value) {
return documentIdentifierFormatter.normalizeIdentifier(value);
}
public Identifier normalizeParticipant(final String scheme, final String identifier) {
return participantIdentifierFormatter.normalize(scheme, identifier);
}
public Identifier normalizeParticipant(final Identifier participantIdentifier) {
return participantIdentifierFormatter.normalize(participantIdentifier);
}
public Identifier normalizeParticipantIdentifier(final String participantId) {
return participantIdentifierFormatter.normalizeIdentifier(participantId);
}
public String formatParticipant(final Identifier participantIdentifier) {
return participantIdentifierFormatter.format(participantIdentifier);
}
public String urlEncodedFormatParticipant(final Identifier participantIdentifier) {
return participantIdentifierFormatter.urlEncodedFormat(participantIdentifier);
}
public String formatParticipant(final String scheme, final String identifier) {
return participantIdentifierFormatter.format(scheme, identifier);
}
public String formatDocument(final Identifier documentIdentifier) {
return documentIdentifierFormatter.format(documentIdentifier);
}
public String urlEncodedFormatDocument(final Identifier documentIdentifier) {
return documentIdentifierFormatter.urlEncodedFormat(documentIdentifier);
}
public String formatDocument(final String scheme, final String identifier) {
return documentIdentifierFormatter.format(scheme, identifier);
}
}
......@@ -8,9 +8,9 @@
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
*
* [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and limitations under the Licence.
......@@ -19,8 +19,11 @@
package eu.europa.ec.edelivery.smp.data.dao;
import eu.europa.ec.edelivery.smp.config.enums.SMPDomainPropertyEnum;
import eu.europa.ec.edelivery.smp.data.enums.MembershipRoleType;
import eu.europa.ec.edelivery.smp.data.model.DBDomain;
import eu.europa.ec.edelivery.smp.data.model.DBDomainConfiguration;
import eu.europa.ec.edelivery.smp.data.ui.DomainPropertyRO;
import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
import org.apache.commons.lang3.StringUtils;
......@@ -29,14 +32,15 @@ import org.springframework.transaction.annotation.Transactional;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.TransactionRequiredException;
import javax.persistence.TypedQuery;
import java.util.List;
import java.util.Optional;
import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*;
import static eu.europa.ec.edelivery.smp.data.enums.MembershipRoleType.toList;
import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.DOMAIN_NOT_EXISTS;
import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.ILLEGAL_STATE_DOMAIN_MULTIPLE_ENTRY;
import static eu.europa.ec.edelivery.smp.data.enums.MembershipRoleType.toList;
/**
* @author gutowpa
......@@ -107,36 +111,37 @@ public class DomainDao extends BaseDao<DBDomain> {
* @throws IllegalStateException if more than one domain is not configured for the code!
*/
public Optional<DBDomain> getDomainByCode(String domainCode) {
if (StringUtils.isEmpty(domainCode)) {
return Optional.empty();
}
try {
TypedQuery<DBDomain> query = memEManager.createNamedQuery(QUERY_DOMAIN_CODE, DBDomain.class);
query.setParameter(PARAM_DOMAIN_CODE, domainCode);
return Optional.of(query.getSingleResult());
} catch (NoResultException e) {
return Optional.empty();
} catch (NonUniqueResultException e) {
throw new IllegalStateException(ILLEGAL_STATE_DOMAIN_MULTIPLE_ENTRY.getMessage(domainCode));
}
return getDomainByQueryWithParam(domainCode, QUERY_DOMAIN_CODE, PARAM_DOMAIN_CODE);
}
public Optional<DBDomain> getDomainBySmlSmpId(String smlSmpId) {
if (StringUtils.isEmpty(smlSmpId)) {
return getDomainByQueryWithParam(smlSmpId, QUERY_DOMAIN_SMP_SML_ID, PARAM_DOMAIN_SML_SMP_ID);
}
/**
* Returns the Optional DBDomain from database. The domain is searched by domain parameter and queryDomainCode.
*
* @param domainParameter - parameter value to search for
* @param queryName - The named DBDomain query
* @param queryParamName the parameter name in the query
* @return Optional DBDomain
*/
private Optional<DBDomain> getDomainByQueryWithParam(String domainParameter, String queryName, String queryParamName) {
if (StringUtils.isEmpty(domainParameter)) {
return Optional.empty();
}
try {
TypedQuery<DBDomain> query = memEManager.createNamedQuery(QUERY_DOMAIN_SMP_SML_ID, DBDomain.class);
query.setParameter(PARAM_DOMAIN_SML_SMP_ID, smlSmpId);
TypedQuery<DBDomain> query = memEManager.createNamedQuery(queryName, DBDomain.class);
query.setParameter(queryParamName, domainParameter);
return Optional.of(query.getSingleResult());
} catch (NoResultException e) {
return Optional.empty();
} catch (NonUniqueResultException e) {
throw new IllegalStateException(ILLEGAL_STATE_DOMAIN_MULTIPLE_ENTRY.getMessage(smlSmpId));
throw new IllegalStateException(ILLEGAL_STATE_DOMAIN_MULTIPLE_ENTRY.getMessage(domainParameter));
}
}
public Long getResourceCountForDomain(Long domainId) {
TypedQuery<Long> query = memEManager.createNamedQuery(QUERY_RESOURCES_BY_DOMAIN_ID_COUNT, Long.class);
......@@ -144,7 +149,7 @@ public class DomainDao extends BaseDao<DBDomain> {
return query.getSingleResult();
}
public Long getDomainsByUserIdAndDomainRolesCount(Long userId, MembershipRoleType ... roleTypes) {
public Long getDomainsByUserIdAndDomainRolesCount(Long userId, MembershipRoleType... roleTypes) {
TypedQuery<Long> query = memEManager.createNamedQuery(QUERY_DOMAIN_BY_USER_ROLES_COUNT, Long.class);
query.setParameter(PARAM_USER_ID, userId);
......@@ -152,14 +157,14 @@ public class DomainDao extends BaseDao<DBDomain> {
return query.getSingleResult();
}
public List<DBDomain> getDomainsByUserIdAndDomainRoles(Long userId, MembershipRoleType ... roleTypes) {
public List<DBDomain> getDomainsByUserIdAndDomainRoles(Long userId, MembershipRoleType... roleTypes) {
TypedQuery<DBDomain> query = memEManager.createNamedQuery(QUERY_DOMAIN_BY_USER_ROLES, DBDomain.class);
query.setParameter(PARAM_USER_ID, userId);
query.setParameter(PARAM_MEMBERSHIP_ROLES, toList(roleTypes));
return query.getResultList();
}
public Long getDomainsByUserIdAndGroupRolesCount(Long userId, MembershipRoleType ... roleTypes) {
public Long getDomainsByUserIdAndGroupRolesCount(Long userId, MembershipRoleType... roleTypes) {
TypedQuery<Long> query = memEManager.createNamedQuery(QUERY_DOMAIN_BY_USER_GROUP_ROLES_COUNT, Long.class);
query.setParameter(PARAM_USER_ID, userId);
......@@ -167,7 +172,7 @@ public class DomainDao extends BaseDao<DBDomain> {
return query.getSingleResult();
}
public List<DBDomain> getDomainsByUserIdAndGroupRoles(Long userId, MembershipRoleType ... roleTypes) {
public List<DBDomain> getDomainsByUserIdAndGroupRoles(Long userId, MembershipRoleType... roleTypes) {
TypedQuery<DBDomain> query = memEManager.createNamedQuery(QUERY_DOMAIN_BY_USER_GROUP_ROLES, DBDomain.class);
query.setParameter(PARAM_USER_ID, userId);
......@@ -175,7 +180,7 @@ public class DomainDao extends BaseDao<DBDomain> {
return query.getResultList();
}
public Long getDomainsByUserIdAndResourceRolesCount(Long userId, MembershipRoleType ... roleTypes) {
public Long getDomainsByUserIdAndResourceRolesCount(Long userId, MembershipRoleType... roleTypes) {
TypedQuery<Long> query = memEManager.createNamedQuery(QUERY_DOMAIN_BY_USER_RESOURCE_ROLES_COUNT, Long.class);
query.setParameter(PARAM_USER_ID, userId);
......@@ -183,7 +188,7 @@ public class DomainDao extends BaseDao<DBDomain> {
return query.getSingleResult();
}
public List<DBDomain> getDomainsByUserIdAndResourceRoles(Long userId, MembershipRoleType ... roleTypes) {
public List<DBDomain> getDomainsByUserIdAndResourceRoles(Long userId, MembershipRoleType... roleTypes) {
TypedQuery<DBDomain> query = memEManager.createNamedQuery(QUERY_DOMAIN_BY_USER_RESOURCE_ROLES, DBDomain.class);
query.setParameter(PARAM_USER_ID, userId);
......@@ -227,4 +232,70 @@ public class DomainDao extends BaseDao<DBDomain> {
return false;
}
/**
* Returns the domain properties for the given domain.
*
* @param domain - domain for which the properties are requested
* @return - list of domain properties
*/
public List<DBDomainConfiguration> getDomainConfiguration(DBDomain domain) {
TypedQuery<DBDomainConfiguration> query = memEManager.createNamedQuery(QUERY_DOMAIN_CONFIGURATION_ALL,
DBDomainConfiguration.class);
query.setParameter(PARAM_DOMAIN_ID, domain.getId());
return query.getResultList();
}
/**
* Update domain property. If property does not exist in the database, it will be created.
* The method must be called in transactional context, else TransactionRequiredException
* will be thrown from JPA merge method.
*
* @param domain - domain to update. Value is used in case domain configuration does not exist in the database.
* @param domainProp - domain property to update
* @param domainConfiguration - current domain configuration or null if it does not exist in the database.
* The object must be attached to the persistence context.
* @param domainPropertyRO - new domain property value and system default flag
* @return new/updated domain configuration
*/
public DBDomainConfiguration updateDomainProperty(DBDomain domain, SMPDomainPropertyEnum domainProp,
DBDomainConfiguration domainConfiguration, DomainPropertyRO domainPropertyRO) {
if (domainConfiguration == null) {
domainConfiguration = new DBDomainConfiguration();
domainConfiguration.setDomain(domain);
domainConfiguration.setProperty(domainProp.getProperty());
// attach domain configuration to the persistence context
mergeConfiguration(domainConfiguration);
}
if (domainPropertyRO != null) {
domainConfiguration.setValue(domainPropertyRO.getValue());
domainConfiguration.setUseSystemDefault(domainPropertyRO.isSystemDefault());
} else {
domainConfiguration.setValue(domainProp.getDefValue());
domainConfiguration.setUseSystemDefault(true);
}
return domainConfiguration;
}
/**
* The method Merge the state of the given domain configuration into the current
* persistence context. The method must be
* called in existing transaction, and it is used to manage domain properties.
*
* @param entity - domain configuration to be merged
* @return - jpa merged/managed domain configuration
* @throws TransactionRequiredException if there is no transaction when
* invoked on a container-managed entity manager of that is of type
* <code>PersistenceContextType.TRANSACTION</code>
*/
public DBDomainConfiguration mergeConfiguration(DBDomainConfiguration entity) {
return memEManager.merge(entity);
}
public void removeConfiguration(DBDomainConfiguration entity) {
memEManager.remove(entity);
}
}
......@@ -74,15 +74,13 @@ public class QueryNames {
public static final String QUERY_DOMAIN_RESOURCE_DEF_ALL = "DBDomainResourceDef.getAll";
public static final String QUERY_DOMAIN_RESOURCE_DEF_DOMAIN_ALL = "DBDomainResourceDef.getAllForDomain";
public static final String QUERY_DOMAIN_RESOURCE_DEF_DOMAIN_CODE_SEGMENT_URL = "DBDomainResourceDef.getByDomainCodeResDefURL";
public static final String QUERY_DOMAIN_RESOURCE_DEF_DOMAIN_ID_RESDEF_IDENTIFIER = "DBDomainResourceDef.getByDomainIdAdResDefIdentifier";
public static final String QUERY_DOMAIN_RESOURCE_DEF_DOMAIN_RES_DEF = "DBDomainResourceDef.getByDomainResDef";
public static final String QUERY_RESOURCE_BY_IDENTIFIER_RESOURCE_DEF_DOMAIN = "DBResource.getResByIdentifierAndResourceDefAndDomain";
public static final String QUERY_RESOURCES_BY_DOMAIN_ID_COUNT = "DBResource.getResByDomainIdCount";
public static final String QUERY_RESOURCES_BY_DOMAIN_ID_RESOURCE_DEF_ID_COUNT = "DBResource.getResByDomainIdAndResourceDefCount";
public static final String QUERY_DOMAIN_CONFIGURATION_ALL = "DBDomainConfiguration.getAllForDomain";
public static final String QUERY_RESOURCE_ALL_FOR_USER = "DBResource.getPublicSearch";
......
/*-
* #START_LICENSE#
* smp-server-library
* %%
* Copyright (C) 2017 - 2024 European Commission | eDelivery | DomiSMP
* %%
* Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and limitations under the Licence.
* #END_LICENSE#
*/
package eu.europa.ec.edelivery.smp.data.enums;
import java.util.Arrays;
import java.util.List;
/**
* Enum for member of types. At the moment there are following member of types:
* <ul>
* <li>DOMAIN - membership of domain.</li>
* <li>GROUP - membership of domain.</li>
* <li>RESOURCE; - membership of domain.</li>
* </ul>
*
* @author Joze Rihtarsic
* @since 5.1
*/
public enum MemberOfType {
DOMAIN,
GROUP,
RESOURCE;
/**
* Method to convert MembershipRoleType to List<MembershipRoleType>. if roleTypes is null or empty,
* all values are returned as list
*
* @param roleTypes - list of role types
* @return list of role types
*/
public static List<MemberOfType> toList(MemberOfType... roleTypes) {
return Arrays.asList(roleTypes == null || roleTypes.length == 0 ? values() : roleTypes);
}
}
......@@ -147,6 +147,16 @@ public class DBDomain extends BaseEntity {
)
private List<DBDomainResourceDef> domainResourceDefs = new ArrayList<>();
@OneToMany(
mappedBy = "domain",
cascade = CascadeType.ALL,
orphanRemoval = true,
fetch = FetchType.LAZY
)
private List<DBDomainConfiguration> domainConfigurations = new ArrayList<>();
@Override
public Long getId() {
return id;
......@@ -240,6 +250,10 @@ public class DBDomain extends BaseEntity {
return domainResourceDefs;
}
public List<DBDomainConfiguration> getDomainConfigurations() {
return domainConfigurations;
}
public VisibilityType getVisibility() {
return visibility;
}
......
/*-
* #START_LICENSE#
* smp-webapp
* %%
* Copyright (C) 2017 - 2023 European Commission | eDelivery | DomiSMP
* %%
* Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and limitations under the Licence.
* #END_LICENSE#
*/
package eu.europa.ec.edelivery.smp.data.model;
import eu.europa.ec.edelivery.smp.data.dao.QueryNames;
import eu.europa.ec.edelivery.smp.data.dao.utils.ColumnDescription;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.envers.Audited;
import javax.persistence.*;
import java.util.Objects;
/**
* Database configuration entity for DomiSMP Domain specific configuration properties
*
* @author Joze Rihtarsic
* @since 5.1
*/
@Entity
@Audited
@Table(name = "SMP_DOMAIN_CONFIGURATION",
indexes = {
@Index(name = "SMP_DOMAIN_CONF_IDX", columnList = "ID, PROPERTY_NAME, FK_DOMAIN_ID", unique = true),
})
@NamedQuery(name = QueryNames.QUERY_DOMAIN_CONFIGURATION_ALL,
query = "SELECT d FROM DBDomainConfiguration d where d.domain.id = :domain_id")
@org.hibernate.annotations.Table(appliesTo = "SMP_DOMAIN_CONFIGURATION", comment = "SMP domain configuration")
public class DBDomainConfiguration extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SMP_DOMAIN_CONF_SEQ")
@GenericGenerator(name = "SMP_DOMAIN_CONF_SEQ", strategy = "native")
@Column(name = "ID")
@ColumnDescription(comment = "Unique domain configuration id")
Long id;
@Column(name = "PROPERTY_NAME", length = CommonColumnsLengths.MAX_TEXT_LENGTH_512, nullable = false)
@ColumnDescription(comment = "Property name/key")
String property;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "FK_DOMAIN_ID", nullable = false)
private DBDomain domain;
@Column(name = "PROPERTY_VALUE", length = CommonColumnsLengths.MAX_FREE_TEXT_LENGTH)
@ColumnDescription(comment = "Property value")
String value;
@Column(name = "DESCRIPTION", length = CommonColumnsLengths.MAX_FREE_TEXT_LENGTH)
@ColumnDescription(comment = "Property description")
String description;
@Column(name = "USER_SYSTEM_DEFAULT", nullable = false)
@ColumnDescription(comment = "Use system default value")
boolean useSystemDefault = true;
@Override
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public DBDomain getDomain() {
return domain;
}
public void setDomain(DBDomain domain) {
this.domain = domain;
}
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isUseSystemDefault() {
return useSystemDefault;
}
public void setUseSystemDefault(boolean useSystemDefault) {
this.useSystemDefault = useSystemDefault;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
DBDomainConfiguration that = (DBDomainConfiguration) o;
return Objects.equals(property, that.property) && Objects.equals(domain, that.domain);
}
@Override
public int hashCode() {
return Objects.hash(property, domain);
}
}
/*-
* #START_LICENSE#
* smp-server-library
* %%
* Copyright (C) 2017 - 2024 European Commission | eDelivery | DomiSMP
* %%
* Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and limitations under the Licence.
* #END_LICENSE#
*/
package eu.europa.ec.edelivery.smp.data.ui;
/**
* Domain property contains domain configuration property for UI representation.
* Some of the system properties can be overridden by domain administrator.
*
* @author Joze Rihtarsic
* @since 5.1
*/
public class DomainPropertyRO extends BaseRO {
private static final long serialVersionUID = 9008583888835630035L;
private String property;
private String value;
private String type;
private String desc;
private String newValue;
private String systemDefaultValue;
private String valuePattern;
boolean isSystemDefault = true;
public DomainPropertyRO(){}
public DomainPropertyRO(String property, String value) {
this.property = property;
this.value = value;
}
public String getProperty() {
return property;
}
public void setProperty(String property) {
this.property = property;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public boolean isSystemDefault() {
return isSystemDefault;
}
public void setSystemDefault(boolean systemDefault) {
isSystemDefault = systemDefault;
}
public String getSystemDefaultValue() {
return systemDefaultValue;
}
public void setSystemDefaultValue(String systemDefaultValue) {
this.systemDefaultValue = systemDefaultValue;
}
public String getNewValue() {
return newValue;
}
public void setNewValue(String newValue) {
this.newValue = newValue;
}
public String getValuePattern() {
return valuePattern;
}
public void setValuePattern(String valuePattern) {
this.valuePattern = valuePattern;
}
}
......@@ -18,13 +18,14 @@
*/
package eu.europa.ec.edelivery.smp.data.ui;
import eu.europa.ec.edelivery.smp.data.enums.MemberOfType;
import eu.europa.ec.edelivery.smp.data.enums.MembershipRoleType;
public class MemberRO {
String memberId;
String username;
String memberOf;
MemberOfType memberOf;
String fullName;
MembershipRoleType roleType;
......@@ -44,11 +45,11 @@ public class MemberRO {
this.username = username;
}
public String getMemberOf() {
public MemberOfType getMemberOf() {
return memberOf;
}
public void setMemberOf(String memberOf) {
public void setMemberOf(MemberOfType memberOf) {
this.memberOf = memberOf;
}
......
......@@ -19,6 +19,7 @@
package eu.europa.ec.edelivery.smp.services;
import eu.europa.ec.edelivery.smp.auth.enums.SMPUserAuthenticationTypes;
import eu.europa.ec.edelivery.smp.config.enums.SMPDomainPropertyEnum;
import eu.europa.ec.edelivery.smp.config.enums.SMPPropertyEnum;
import eu.europa.ec.edelivery.smp.data.dao.ConfigurationDao;
import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority;
......@@ -62,15 +63,15 @@ public class ConfigurationService {
public Pattern getParticipantIdentifierSchemeRexExp() {
return configurationDAO.getCachedPropertyValue(PARTC_SCH_VALIDATION_REGEXP);
return configurationDAO.getCachedPropertyValue(RESOURCE_SCH_VALIDATION_REGEXP);
}
public String getParticipantIdentifierSchemeRexExpPattern() {
return configurationDAO.getCachedProperty(PARTC_SCH_VALIDATION_REGEXP);
return configurationDAO.getCachedProperty(RESOURCE_SCH_VALIDATION_REGEXP);
}
public String getParticipantIdentifierSchemeRexExpMessage() {
return configurationDAO.getCachedPropertyValue(PARTC_SCH_REGEXP_MSG);
return configurationDAO.getCachedPropertyValue(RESOURCE_SCH_REGEXP_MSG);
}
public Pattern getPasswordPolicyRexExp() {
......@@ -161,26 +162,26 @@ public class ConfigurationService {
}
public List<String> getCaseSensitiveDocumentScheme() {
return configurationDAO.getCachedPropertyValue(CS_DOCUMENTS);
return configurationDAO.getCachedPropertyValue(SUBRESOURCE_CASE_SENSITIVE_SCHEMES);
}
public List<String> getCaseSensitiveParticipantScheme() {
return configurationDAO.getCachedPropertyValue(CS_PARTICIPANTS);
return configurationDAO.getCachedPropertyValue(RESOURCE_CASE_SENSITIVE_SCHEMES);
}
public boolean getParticipantSchemeMandatory() {
// not mandatory by default
Boolean value = configurationDAO.getCachedPropertyValue(PARTC_SCH_MANDATORY);
Boolean value = configurationDAO.getCachedPropertyValue(RESOURCE_SCH_MANDATORY);
return value != null && value;
}
public Pattern getParticipantIdentifierSplitRexExp() {
return configurationDAO.getCachedPropertyValue(PARTC_SCH_SPLIT_REGEXP);
return configurationDAO.getCachedPropertyValue(RESOURCE_SCH_SPLIT_REGEXP);
}
public Pattern getParticipantIdentifierUrnValidationRexExp() {
return configurationDAO.getCachedPropertyValue(PARTC_SCH_URN_REGEXP);
return configurationDAO.getCachedPropertyValue(RESOURCE_SCH_URN_REGEXP);
}
public boolean isProxyEnabled() {
......@@ -409,6 +410,12 @@ public class ConfigurationService {
return configurationDAO.getCachedPropertyValue(SML_CUSTOM_NAPTR_SERVICE_PARAMS);
}
public int getManageMaxSMLRecordCount() {
Integer intVal = configurationDAO.getCachedPropertyValue(SML_MANAGE_MAX_COUNT);
return intVal == null ? 10000 : intVal;
}
public List<String> getCasURLTokenValidationGroups() {
return configurationDAO.getCachedPropertyValue(SSO_CAS_TOKEN_VALIDATION_GROUPS);
}
......@@ -611,4 +618,11 @@ public class ConfigurationService {
return configurationDAO.getCachedPropertyValue(SMP_ALERT_MAIL_FROM);
}
public String getDefaultDomainConfiguration(SMPDomainPropertyEnum property) {
return configurationDAO.getCachedProperty(property.getPropertyEnum());
}
public <T> T getDefaultDomainConfigurationValue(SMPDomainPropertyEnum property) {
return configurationDAO.getCachedPropertyValue(property.getPropertyEnum());
}
}
......@@ -8,9 +8,9 @@
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
*
* [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and limitations under the Licence.
......@@ -27,18 +27,14 @@ import eu.europa.ec.edelivery.smp.data.model.doc.DBResourceFilter;
import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
import eu.europa.ec.edelivery.smp.logging.SMPLogger;
import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.regex.Pattern;
import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.*;
import static eu.europa.ec.edelivery.smp.config.enums.SMPPropertyEnum.SML_MANAGE_MAX_COUNT;
/**
......@@ -49,103 +45,109 @@ import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.*;
*/
@Service
public class DomainService {
public class DomainSMLIntegrationService {
private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DomainService.class);
private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DomainSMLIntegrationService.class);
public static final Pattern DOMAIN_ID_PATTERN = Pattern.compile("[a-zA-Z0-9]{1,50}");
@Autowired
private SMLIntegrationService smlIntegrationService;
@Autowired
private ResourceDao resourceDao;
@Autowired
private DomainDao domainDao;
/**
* Method checks if domain is in right format. Domain must contains only alphanomeric chars and it must
* not be longer than 50 chars.
*
* @param domain
* @return
*/
@NotNull
public DBDomain getDomain(final String domain) {
if (StringUtils.isBlank(domain)) {
Optional<DBDomain> res = domainDao.getTheOnlyDomain();
if (!res.isPresent()) {
throw new SMPRuntimeException(MISSING_DOMAIN);
}
return res.get();
}
// else test if domain is ok.
if (!DOMAIN_ID_PATTERN.matcher(domain).matches()) {
throw new SMPRuntimeException(INVALID_DOMAIN_CODE, domain, DOMAIN_ID_PATTERN);
}
// get domain by code
Optional<DBDomain> domEntity = domainDao.getDomainByCode(domain);
if (!domEntity.isPresent()) {
throw new SMPRuntimeException(DOMAIN_NOT_EXISTS, domain);
}
return domEntity.get();
private final SMLIntegrationService smlIntegrationService;
private final ResourceDao resourceDao;
private final DomainDao domainDao;
private final ConfigurationService configurationService;
public DomainSMLIntegrationService(SMLIntegrationService smlIntegrationService,
ResourceDao resourceDao,
DomainDao domainDao,
ConfigurationService configurationService) {
this.smlIntegrationService = smlIntegrationService;
this.resourceDao = resourceDao;
this.domainDao = domainDao;
this.configurationService = configurationService;
}
/**
* If domain is not yet registered and SML integration is on, it tries to register a domain and all participants
* on that domain. If integration is off, it returns a configuration exception.
* on that domain. If integration is disabled, it returns a configuration exception. The participants are registered
* not registered if count of participants is higher than defined in max bdmsl.participants.manage.max-count.
* In this case they must be registered manually.
* <p>
* Method is not in transaction - but sub-methods are. if registering domain or particular serviceGroup succeed
* then the database flag (SML_REGISTERED) is turned on ( if method fails
* while execution the SML_REGISTERED reflect the real status in SML). Running the method again updates only
* serviceGroup which are not yet registered.
*
* @param domain
* @param domainId domain id
*/
@Transactional
public void registerDomainAndParticipants(DBDomain domain) {
LOG.info("Start registerDomainAndParticipants for domain:" + domain.getDomainCode());
smlIntegrationService.registerDomain(domain);
public void registerDomainAndParticipants(Long domainId) {
DBDomain dbDomain = domainDao.find(domainId);
LOG.info("Start registerDomainAndParticipants for domain: [{}]", dbDomain);
DBResourceFilter filter = DBResourceFilter.createBuilder().domain(dbDomain).build();
smlIntegrationService.registerDomain(dbDomain);
Long resourceCnt = resourceDao.getResourcesForFilterCount(filter);
int maxSMLRecordCount = configurationService.getManageMaxSMLRecordCount();
if (resourceCnt > maxSMLRecordCount) {
LOG.warn("Too many resources to register for the domain [{}]. Count: [{}], max. allowed [{}]!" +
"For details check the configuration option [{}]!",
dbDomain, resourceCnt, maxSMLRecordCount, SML_MANAGE_MAX_COUNT.getProperty());
return;
}
DBResourceFilter filter = DBResourceFilter.createBuilder().domain(domain).build();
List<DBResource> resources = resourceDao.getResourcesForFilter(-1, -1, filter);
List<DBResource> processed = new ArrayList<>();
try {
for (DBResource resource : resources) {
smlIntegrationService.registerParticipant(resource, domain);
smlIntegrationService.registerParticipant(resource, dbDomain);
processed.add(resource);
}
} catch (SMPRuntimeException exc) {
// rollback dns records
for (DBResource resource : processed) {
smlIntegrationService.unregisterParticipant(resource, domain);
smlIntegrationService.unregisterParticipant(resource, dbDomain);
}
throw exc;
}
}
/**
* If domain is registered and SML integration is on, it tries to unregister a domain and all its participants
* The participants are not unregistered if count of participants is higher than defined in max bdmsl.participants.manage.max-count.
* In this case they must be unregistered manually.
*
* @param domainId domain id
*/
@Transactional
public void unregisterDomainAndParticipantsFromSml(DBDomain domain) {
public void unregisterDomainAndParticipantsFromSml(Long domainId) {
DBDomain dbDomain = domainDao.find(domainId);
LOG.info("Start unregisterDomainAndParticipants for domain: [{}]", dbDomain);
DBResourceFilter filter = DBResourceFilter.createBuilder().domain(dbDomain).build();
Long resourceCnt = resourceDao.getResourcesForFilterCount(filter);
int maxSMLRecordCount = configurationService.getManageMaxSMLRecordCount();
if (resourceCnt > maxSMLRecordCount) {
LOG.warn("Too many resources to unregister for the domain [{}]. Count: [{}], max. allowed [{}]!" +
"For details check the configuration option [{}]!",
dbDomain, resourceCnt, maxSMLRecordCount, SML_MANAGE_MAX_COUNT.getProperty());
return;
}
DBResourceFilter filter = DBResourceFilter.createBuilder().domain(domain).build();
List<DBResource> resources = resourceDao.getResourcesForFilter(-1, -1, filter);
List<DBResource> processed = new ArrayList<>();
try {
for (DBResource resource : resources) {
smlIntegrationService.unregisterParticipant(resource, domain);
smlIntegrationService.unregisterParticipant(resource, dbDomain);
processed.add(resource);
}
} catch (SMPRuntimeException exc) {
// rollback dns records
for (DBResource resource : processed) {
smlIntegrationService.registerParticipant(resource, domain);
smlIntegrationService.registerParticipant(resource, dbDomain);
}
throw exc;
}
smlIntegrationService.unRegisterDomain(domain);
smlIntegrationService.unRegisterDomain(dbDomain);
}
}
package eu.europa.ec.edelivery.smp.services;
import eu.europa.ec.dynamicdiscovery.model.identifiers.types.EBCorePartyIdFormatterType;
import eu.europa.ec.edelivery.smp.config.enums.SMPDomainPropertyEnum;
import eu.europa.ec.edelivery.smp.config.enums.SMPPropertyEnum;
import eu.europa.ec.edelivery.smp.config.enums.SMPPropertyTypeEnum;
import eu.europa.ec.edelivery.smp.data.dao.DomainDao;
import eu.europa.ec.edelivery.smp.data.model.DBDomain;
import eu.europa.ec.edelivery.smp.data.model.DBDomainConfiguration;
import eu.europa.ec.edelivery.smp.exceptions.ErrorCode;
import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
import eu.europa.ec.edelivery.smp.identifiers.IdentifierFormatter;
import eu.europa.ec.edelivery.smp.utils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* Spring bean provides Identifier formatters for the domain.
* @since 5.1
*/
@Component
public class IdentifierFormatterService {
public static final String CACHE_NAME_DOMAIN_RESOURCE_IDENTIFIER_FORMATTER = "domain-resource-identifier-formatter";
public static final String CACHE_NAME_DOMAIN_SUBRESOURCE_IDENTIFIER_FORMATTER = "domain-subresource-identifier-formatter";
private static final Logger LOG = LoggerFactory.getLogger(IdentifierFormatterService.class);
private final DomainDao domainDao;
private final ConfigurationService configurationService;
public IdentifierFormatterService(DomainDao domainDao, ConfigurationService configurationService) {
this.domainDao = domainDao;
this.configurationService = configurationService;
}
/**
* Method returns participant identifier formatter for given domain
* @param domainCode domain code to get IdentifierFormatter
*/
@Cacheable(CACHE_NAME_DOMAIN_RESOURCE_IDENTIFIER_FORMATTER)
public IdentifierFormatter getResourceIdentifierFormatter(String domainCode) {
if (StringUtils.isBlank(domainCode)) {
throw new SMPRuntimeException(ErrorCode.DOMAIN_NOT_EXISTS, domainCode);
}
DBDomain domain = domainDao.getDomainByCode(domainCode)
.orElseThrow(() -> new SMPRuntimeException(ErrorCode.DOMAIN_NOT_EXISTS, domainCode));
List<DBDomainConfiguration> listDomainConf = domainDao.getDomainConfiguration(domain);
IdentifierFormatter identifierFormatter = IdentifierFormatter.Builder
.create()
.addFormatterTypes(new EBCorePartyIdFormatterType())
.build();
identifierFormatter.setCaseSensitiveSchemas(getDomainConfigurationValue(listDomainConf, SMPDomainPropertyEnum.RESOURCE_CASE_SENSITIVE_SCHEMES));
identifierFormatter.setSchemeMandatory(getDomainConfigurationValue(listDomainConf, SMPDomainPropertyEnum.RESOURCE_SCH_MANDATORY));
identifierFormatter.setSchemeValidationPattern(getDomainConfigurationValue(listDomainConf, SMPDomainPropertyEnum.RESOURCE_SCH_VALIDATION_REGEXP));
return identifierFormatter;
}
/**
* Method returns participant identifier formatter for given domain
* @param domain
*/
/**
* Method returns participant identifier formatter for given domain
* @param domainCode domain code to get IdentifierFormatter
*/
@Cacheable(CACHE_NAME_DOMAIN_SUBRESOURCE_IDENTIFIER_FORMATTER)
public IdentifierFormatter getSubresourceIdentifierFormatter(String domainCode) {
if (StringUtils.isBlank(domainCode)) {
throw new SMPRuntimeException(ErrorCode.DOMAIN_NOT_EXISTS, domainCode);
}
DBDomain domain = domainDao.getDomainByCode(domainCode)
.orElseThrow(() -> new SMPRuntimeException(ErrorCode.DOMAIN_NOT_EXISTS, domainCode));
List<DBDomainConfiguration> listDomainConf = domainDao.getDomainConfiguration(domain);
IdentifierFormatter identifierFormatter = IdentifierFormatter.Builder
.create()
.build();
identifierFormatter.setCaseSensitiveSchemas(getDomainConfigurationValue(listDomainConf,
SMPDomainPropertyEnum.SUBRESOURCE_CASE_SENSITIVE_SCHEMES));
return identifierFormatter;
}
/**
* Method returns parsed value for property on given domain. If property is not found or use system default,
* system default value is returned.
* @param domain domain to get configuration value
* @param property domain property type
* @return parsed value for property
* @param <T> type of returned value
*/
public <T> T getDomainConfigurationValue(List<DBDomainConfiguration> domain, SMPDomainPropertyEnum property) {
DBDomainConfiguration domainConfiguration = domain.stream()
.filter(dc -> dc.getProperty().equals(property.getProperty()))
.findFirst()
.orElse(null);
if (domainConfiguration == null || domainConfiguration.isUseSystemDefault()) {
LOG.debug("Domain configuration value for property [{}] not found or use system default. Using system default value!", property);
return configurationService.getDefaultDomainConfigurationValue(property);
}
String value = domainConfiguration.getValue();
SMPPropertyEnum sysPropType = getSmpPropertyEnum(property);
return (T) PropertyUtils.parseProperty(sysPropType, value, null);
}
private static SMPPropertyEnum getSmpPropertyEnum(SMPDomainPropertyEnum property) {
SMPPropertyEnum sysPropType = property.getPropertyEnum();
if (sysPropType.isEncrypted()) {
throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Encrypted domain Properties are not supported!. Can not parse ["
+ property + "]!");
}
if (sysPropType.getPropertyType() == SMPPropertyTypeEnum.PATH ||
sysPropType.getPropertyType() == SMPPropertyTypeEnum.FILENAME) {
throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Path or filename domain properties are not supported!. Can not parse ["
+ property + "]!");
}
return sysPropType;
}
}
/*-
* #START_LICENSE#
* smp-webapp
* %%
* Copyright (C) 2017 - 2024 European Commission | eDelivery | DomiSMP
* %%
* Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and limitations under the Licence.
* #END_LICENSE#
*/
package eu.europa.ec.edelivery.smp.services;
import eu.europa.ec.edelivery.smp.identifiers.Identifier;
import eu.europa.ec.edelivery.smp.identifiers.IdentifierFormatter;
import org.springframework.stereotype.Component;
/**
* Class provides tools to parse, format and normalize Document and Participant identifiers.
*
* @author gutowpa
* @since 3.0.0
*/
@Component
public class IdentifierService {
private final IdentifierFormatterService identifierFormatterService;
public IdentifierService(IdentifierFormatterService identifierFormatterService) {
this.identifierFormatterService = identifierFormatterService;
}
public Identifier normalizeParticipant(final String domainCode, final String scheme, final String identifier) {
return getResourceIdentifierFormatter(domainCode).normalize(scheme, identifier);
}
public Identifier normalizeParticipant(final String domainCode, final Identifier participantIdentifier) {
return getResourceIdentifierFormatter(domainCode).normalize(participantIdentifier);
}
public Identifier normalizeParticipantIdentifier(final String domainCode, final String participantId) {
return getResourceIdentifierFormatter(domainCode).normalizeIdentifier(participantId);
}
public String formatParticipant(final String domainCode, final Identifier participantIdentifier) {
return getResourceIdentifierFormatter(domainCode).format(participantIdentifier);
}
public String urlEncodedFormatParticipant(final String domainCode, final Identifier participantIdentifier) {
return getResourceIdentifierFormatter(domainCode).urlEncodedFormat(participantIdentifier);
}
public String formatParticipant(final String domainCode, final String scheme, final String identifier) {
return getResourceIdentifierFormatter(domainCode).format(scheme, identifier);
}
public Identifier normalizeDocument(final String domainCode, final Identifier documentIdentifier) {
return getSubresourceIdentifierFormatter(domainCode)
.normalize(documentIdentifier);
}
public Identifier normalizeDocument(final String domainCode, final String scheme, final String identifier) {
return getSubresourceIdentifierFormatter(domainCode)
.normalize(scheme, identifier);
}
public Identifier normalizeDocumentIdentifier(final String domainCode, String value) {
return getSubresourceIdentifierFormatter(domainCode).normalizeIdentifier(value);
}
public String formatDocument(final String domainCode, final Identifier documentIdentifier) {
return getSubresourceIdentifierFormatter(domainCode).format(documentIdentifier);
}
public String urlEncodedFormatDocument(final String domainCode, final Identifier documentIdentifier) {
return getSubresourceIdentifierFormatter(domainCode).urlEncodedFormat(documentIdentifier);
}
public String formatDocument(final String domainCode, final String scheme, final String identifier) {
return getSubresourceIdentifierFormatter(domainCode).format(scheme, identifier);
}
private IdentifierFormatter getSubresourceIdentifierFormatter(final String domainCode) {
return identifierFormatterService.getSubresourceIdentifierFormatter(domainCode);
}
private IdentifierFormatter getResourceIdentifierFormatter(final String domainCode) {
return identifierFormatterService.getResourceIdentifierFormatter(domainCode);
}
}
......@@ -19,12 +19,10 @@
package eu.europa.ec.edelivery.smp.services;
import eu.europa.ec.edelivery.smp.conversion.IdentifierService;
import eu.europa.ec.edelivery.smp.data.dao.DomainDao;
import eu.europa.ec.edelivery.smp.data.model.DBDomain;
import eu.europa.ec.edelivery.smp.data.model.doc.DBResource;
import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException;
import eu.europa.ec.edelivery.smp.identifiers.Identifier;
import eu.europa.ec.edelivery.smp.logging.SMPLogger;
import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
import eu.europa.ec.edelivery.smp.sml.SmlConnector;
......@@ -55,13 +53,11 @@ public class SMLIntegrationService {
private final ConfigurationService configurationService;
private final SmlConnector smlConnector;
private final DomainDao domainDao;
private final IdentifierService identifierService;
public SMLIntegrationService(ConfigurationService configurationService, SmlConnector smlConnector, DomainDao domainDao, IdentifierService identifierService) {
public SMLIntegrationService(ConfigurationService configurationService, SmlConnector smlConnector, DomainDao domainDao) {
this.configurationService = configurationService;
this.smlConnector = smlConnector;
this.domainDao = domainDao;
this.identifierService = identifierService;
}
/**
......@@ -75,10 +71,7 @@ public class SMLIntegrationService {
if (!isSMLIntegrationEnabled()) {
throw new SMPRuntimeException(CONFIGURATION_ERROR, ERROR_MESSAGE_DNS_NOT_ENABLED);
}
Identifier normalizedParticipantId = identifierService
.normalizeParticipant(resource.getIdentifierScheme(), resource.getIdentifierValue());
return smlConnector.participantExists(normalizedParticipantId, domain);
return smlConnector.participantExists(resource.getIdentifierScheme(), resource.getIdentifierValue(), domain);
}
/**
......@@ -146,14 +139,12 @@ public class SMLIntegrationService {
resource.getIdentifierScheme(), domain.getDomainCode(), ERROR_MESSAGE_DNS_NOT_ENABLED);
return;
}
Identifier normalizedParticipantId = identifierService
.normalizeParticipant(resource.getIdentifierScheme(), resource.getIdentifierValue());
// register only not registered services
if (!resource.isSmlRegistered()) {
// update value
resource.setSmlRegistered(true);
String customNaptrService = getNaptrServiceForResource(resource);
smlConnector.registerInDns(normalizedParticipantId, domain, customNaptrService);
smlConnector.registerInDns(resource.getIdentifierScheme(), resource.getIdentifierValue(), domain, customNaptrService);
LOG.businessDebug(BUS_SML_REGISTER_SERVICE_GROUP, resource.getIdentifierValue(), resource.getIdentifierScheme(), domain.getDomainCode());
} else {
LOG.businessWarn(BUS_SML_REGISTER_SERVICE_GROUP_ALREADY_REGISTERED, resource.getIdentifierValue(), resource.getIdentifierScheme(), domain.getDomainCode());
......@@ -221,11 +212,8 @@ public class SMLIntegrationService {
public boolean unregisterParticipantFromSML(DBResource resource, DBDomain domain) {
LOG.businessDebug(BUS_SML_UNREGISTER_SERVICE_GROUP, resource.getIdentifierValue(), resource.getIdentifierScheme(), domain.getDomainCode());
Identifier normalizedParticipantId = identifierService
.normalizeParticipant(resource.getIdentifierScheme(), resource.getIdentifierValue());
// unregister only registered participants
return smlConnector.unregisterFromDns(normalizedParticipantId, domain);
return smlConnector.unregisterFromDns(resource.getIdentifierScheme(), resource.getIdentifierValue(), domain);
}
public boolean isSMLIntegrationEnabled() {
......
......@@ -19,7 +19,7 @@
package eu.europa.ec.edelivery.smp.services.resource;
import eu.europa.ec.edelivery.smp.auth.SMPUserDetails;
import eu.europa.ec.edelivery.smp.conversion.IdentifierService;
import eu.europa.ec.edelivery.smp.services.IdentifierService;
import eu.europa.ec.edelivery.smp.data.dao.*;
import eu.europa.ec.edelivery.smp.data.model.DBDomain;
import eu.europa.ec.edelivery.smp.data.model.doc.DBDocument;
......@@ -123,7 +123,7 @@ public class ResourceResolverService {
currentParameter = pathParameters.get(iParameterIndex);
}
Identifier resourceId = identifierService.normalizeParticipantIdentifier(currentParameter);
Identifier resourceId = identifierService.normalizeParticipantIdentifier(domain.getDomainCode(), currentParameter);
// validate identifier
validateResourceIdentifier(resourceId);
DBResource resource = resolveResourceIdentifier(domain, resourceDef, resourceId);
......@@ -160,7 +160,9 @@ public class ResourceResolverService {
String subResourceDefUrl = pathParameters.get(iParameterIndex);
// test if subresourceDef exists
DBSubresourceDef subresourceDef = getSubresource(resourceDef, subResourceDefUrl);
Identifier subResourceId = identifierService.normalizeDocumentIdentifier(pathParameters.get(++iParameterIndex));
Identifier subResourceId = identifierService.normalizeDocumentIdentifier(
domain.getDomainCode(),
pathParameters.get(++iParameterIndex));
DBSubresource subresource = resolveSubResourceIdentifier(resource, subResourceDefUrl, subResourceId);
LOG.debug("Got subresource [{}]", subresource);
if (subresource == null) {
......
......@@ -8,9 +8,9 @@
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
*
* [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and limitations under the Licence.
......@@ -18,18 +18,15 @@
*/
package eu.europa.ec.edelivery.smp.services.spi;
import eu.europa.ec.edelivery.smp.conversion.IdentifierService;
import eu.europa.ec.edelivery.smp.identifiers.Identifier;
import eu.europa.ec.edelivery.smp.logging.SMPLogger;
import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory;
import eu.europa.ec.edelivery.smp.services.ConfigurationService;
import eu.europa.ec.edelivery.smp.services.IdentifierService;
import eu.europa.ec.smp.spi.api.SmpIdentifierServiceApi;
import eu.europa.ec.smp.spi.api.model.ResourceIdentifier;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import java.util.regex.Pattern;
/**
* Implementation of the class provides the identifier services for the SPI implementation. The identifier formatting
* is DomiSMP configuration specific!
......@@ -50,63 +47,55 @@ public class SmpIdentifierService implements SmpIdentifierServiceApi {
}
@Override
public ResourceIdentifier normalizeResourceIdentifier(String value, String scheme) {
return toUrlIdentifier(identifierService.normalizeParticipant(scheme, value));
public ResourceIdentifier normalizeResourceIdentifier(final String domainCode, final String value, final String scheme) {
return toUrlIdentifier(identifierService.normalizeParticipant(domainCode, scheme, value));
}
@Override
public ResourceIdentifier normalizeSubresourceIdentifier(String value, String scheme) {
return toUrlIdentifier(identifierService.normalizeDocument(scheme, value));
public ResourceIdentifier normalizeSubresourceIdentifier(final String domainCode, final String value, final String scheme) {
return toUrlIdentifier(identifierService.normalizeDocument(domainCode, scheme, value));
}
@Override
public String formatResourceIdentifier(ResourceIdentifier identifier) {
public String formatResourceIdentifier(final String domainCode, ResourceIdentifier identifier) {
if (identifier == null) {
LOG.debug("formatResourceIdentifier: identifier is null for domain [{}]", domainCode);
return null;
}
Identifier id = toIdentifier(identifier);
return identifierService.formatParticipant(id);
return identifierService.formatParticipant(domainCode, id);
}
@Override
public String formatSubresourceIdentifier(ResourceIdentifier identifier) {
public String formatSubresourceIdentifier(final String domainCode, ResourceIdentifier identifier) {
if (identifier == null) {
LOG.debug("formatSubresourceIdentifier: identifier is null for domain [{}]", domainCode);
return null;
}
Identifier id = toIdentifier(identifier);
return identifierService.formatDocument(id);
return identifierService.formatDocument(domainCode, id);
}
@Override
public String getURLEncodedResourceIdentifier(ResourceIdentifier identifier) {
public String getURLEncodedResourceIdentifier(final String domainCode, ResourceIdentifier identifier) {
if (identifier == null) {
LOG.debug("getURLEncodedResourceIdentifier: identifier is null for domain [{}]", domainCode);
return null;
}
Identifier id = toIdentifier(identifier);
return identifierService.urlEncodedFormatParticipant(id);
return identifierService.urlEncodedFormatParticipant(domainCode, id);
}
@Override
public String getURLEncodedSubresourceIdentifier(ResourceIdentifier identifier) {
public String getURLEncodedSubresourceIdentifier(final String domainCode, ResourceIdentifier identifier) {
if (identifier == null) {
LOG.debug("getURLEncodedSubresourceIdentifier: identifier is null for domain [{}]", domainCode);
return null;
}
Identifier id = toIdentifier(identifier);
return identifierService.urlEncodedFormatDocument(id);
return identifierService.urlEncodedFormatDocument(domainCode, id);
}
@Override
public boolean concatenateResourceIdentifier(ResourceIdentifier identifier) {
Pattern concatenatePartyId = configurationService.getParticipantIdentifierUrnValidationRexExp();
if (identifier == null || StringUtils.isBlank(identifier.getScheme())) {
LOG.debug("Return false for null or empty scheme identifier!");
return false;
}
return concatenatePartyId != null
&& concatenatePartyId.matcher(identifier.getScheme())
.matches();
}
private Identifier toIdentifier(ResourceIdentifier identifier) {
return identifier == null ? null :
......
......@@ -8,9 +8,9 @@
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
*
* [PROJECT_HOME]\license\eupl-1.2\license.txt or https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
*
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and limitations under the Licence.
......@@ -18,14 +18,17 @@
*/
package eu.europa.ec.edelivery.smp.services.ui;
import eu.europa.ec.edelivery.smp.config.enums.SMPDomainPropertyEnum;
import eu.europa.ec.edelivery.smp.data.dao.*;
import eu.europa.ec.edelivery.smp.data.enums.VisibilityType;
import eu.europa.ec.edelivery.smp.data.model.DBDomain;
import eu.europa.ec.edelivery.smp.data.model.DBDomainConfiguration;
import eu.europa.ec.edelivery.smp.data.model.DBDomainResourceDef;
import eu.europa.ec.edelivery.smp.data.model.DBGroup;
import eu.europa.ec.edelivery.smp.data.model.ext.DBResourceDef;
import eu.europa.ec.edelivery.smp.data.model.user.DBDomainMember;
import eu.europa.ec.edelivery.smp.data.model.user.DBGroupMember;
import eu.europa.ec.edelivery.smp.data.ui.DomainPropertyRO;
import eu.europa.ec.edelivery.smp.data.ui.DomainRO;
import eu.europa.ec.edelivery.smp.data.ui.ServiceResult;
import eu.europa.ec.edelivery.smp.data.ui.enums.EntityROStatus;
......@@ -41,21 +44,21 @@ import org.springframework.core.convert.ConversionService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* Bean provides system admin services. The services must always be accessible via
* authenticated UI services allowing only users with System admin to access them.
*
* @author Joze Rihtarsic
* @since 5.0
*/
@Service
public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
private static final SMPLogger LOG = SMPLoggerFactory.getLogger(UIDomainService.class);
public class UIDomainAdminService extends UIServiceBase<DBDomain, DomainRO> {
private static final SMPLogger LOG = SMPLoggerFactory.getLogger(UIDomainAdminService.class);
private final DomainDao domainDao;
private final DomainMemberDao domainMemberDao;
......@@ -67,15 +70,15 @@ public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
private final GroupMemberDao groupMemberDao;
private final SMLIntegrationService smlIntegrationService;
public UIDomainService(ConversionService conversionService,
DomainDao domainDao,
DomainMemberDao domainMemberDao,
ResourceDao resourceDao,
ResourceDefDao resourceDefDao,
DomainResourceDefDao domainResourceDefDao,
GroupDao groupDao,
GroupMemberDao groupMemberDao,
SMLIntegrationService smlIntegrationService) {
public UIDomainAdminService(ConversionService conversionService,
DomainDao domainDao,
DomainMemberDao domainMemberDao,
ResourceDao resourceDao,
ResourceDefDao resourceDefDao,
DomainResourceDefDao domainResourceDefDao,
GroupDao groupDao,
GroupMemberDao groupMemberDao,
SMLIntegrationService smlIntegrationService) {
this.conversionService = conversionService;
this.domainDao = domainDao;
this.resourceDao = resourceDao;
......@@ -121,12 +124,12 @@ public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
@Transactional
public void createDomainData(DomainRO data) {
if (StringUtils.isBlank(data.getDomainCode())){
if (StringUtils.isBlank(data.getDomainCode())) {
throw new SMPRuntimeException(ErrorCode.INVALID_DOMAIN_DATA, "Domain code must not be empty!");
}
if (domainDao.getDomainByCode(data.getDomainCode()).isPresent()){
throw new SMPRuntimeException(ErrorCode.INVALID_DOMAIN_DATA, "Domain with code ["+data.getDomainCode()+"] already exists!");
if (domainDao.getDomainByCode(data.getDomainCode()).isPresent()) {
throw new SMPRuntimeException(ErrorCode.INVALID_DOMAIN_DATA, "Domain with code [" + data.getDomainCode() + "] already exists!");
}
DBDomain domain = new DBDomain();
domain.setDomainCode(data.getDomainCode());
......@@ -148,7 +151,7 @@ public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
public void updateBasicDomainData(Long domainId, DomainRO data) {
DBDomain domain = domainDao.find(domainId);
if (domain == null) {
LOG.warn("Can not delete domain for ID [{}], because it does not exists!", domainId);
LOG.warn("Can not update domain for ID [{}], because it does not exists!", domainId);
throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, "Domain does not exist in database!");
}
domain.setDomainCode(data.getDomainCode());
......@@ -180,7 +183,7 @@ public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
domain.setSmlClientCertAuth(data.isSmlClientCertAuth());
// if registered, validate the updated domain to ensure its SML integration certificate is valid
if(domain.isSmlRegistered() && !smlIntegrationService.isDomainValid(domain)) {
if (domain.isSmlRegistered() && !smlIntegrationService.isDomainValid(domain)) {
String msg = "The SML-SMP certificate for domain [" + domain.getDomainCode() + "] is not valid!";
throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, msg);
}
......@@ -226,6 +229,72 @@ public class UIDomainService extends UIServiceBase<DBDomain, DomainRO> {
return conversionService.convert(domain, DomainRO.class);
}
/**
* Method returns all Domain properties.
*
* @param domainId - domain to get properties
* @return list of domain properties
*/
public List<DomainPropertyRO> getDomainProperties(Long domainId) {
DBDomain domain = domainDao.find(domainId);
if (domain == null) {
throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, "Domain does not exist in database!");
}
List<DBDomainConfiguration> domainConfiguration = domainDao.getDomainConfiguration(domain);
Map<String, DomainPropertyRO> dbList = domainConfiguration.stream()
.map(dc -> conversionService.convert(dc, DomainPropertyRO.class))
.collect(Collectors.toMap(DomainPropertyRO::getProperty, dp -> dp));
return Arrays.stream(SMPDomainPropertyEnum.values()).map(enumType -> {
if (dbList.containsKey(enumType.getProperty())) {
return dbList.get(enumType.getProperty());
}
return conversionService.convert(enumType, DomainPropertyRO.class);
}).filter(Objects::nonNull).collect(Collectors.toList());
}
@Transactional
public List<DomainPropertyRO> updateDomainProperties(Long domainId, List<DomainPropertyRO> domainProperties) {
DBDomain domain = domainDao.find(domainId);
if (domain == null) {
throw new BadRequestException(ErrorBusinessCode.NOT_FOUND, "Domain does not exist in database!");
}
// get current domain configuration
Map<String, DBDomainConfiguration> currentDomainConfiguration = domainDao.getDomainConfiguration(domain)
.stream().collect(Collectors.toMap(DBDomainConfiguration::getProperty, Function.identity()));
Map<String, DomainPropertyRO> newDomainPropertyValues =
domainProperties.stream().collect(Collectors.toMap(DomainPropertyRO::getProperty, dp -> dp));
List<DBDomainConfiguration> listOfDomainConfiguration = new ArrayList<>();
// database domain configuration property list must match SMPDomainPropertyEnum
for (SMPDomainPropertyEnum domainProp : SMPDomainPropertyEnum.values()) {
DBDomainConfiguration domainConfiguration = currentDomainConfiguration.get(domainProp.getProperty());
DomainPropertyRO domainPropertyRO = newDomainPropertyValues.get(domainProp.getProperty());
// if property already exists in the database, update value
DBDomainConfiguration updatedDomainProp = domainDao.updateDomainProperty(domain, domainProp,
domainConfiguration, domainPropertyRO);
listOfDomainConfiguration.add(updatedDomainProp);
// remove updated property from the map
currentDomainConfiguration.remove(domainProp.getProperty());
LOG.debug("Updated domain property [{}]: [{}] for domain [{}]",
domainProp.getProperty(), updatedDomainProp, domain.getDomainCode());
}
// remove properties that are not in the new list
currentDomainConfiguration.values().forEach(domainConfiguration -> {
domainDao.removeConfiguration(domainConfiguration);
LOG.debug("Removed domain property [{}]: [{}] for domain [{}]",
domainConfiguration.getProperty(), domainConfiguration.getValue(),
domain.getDomainCode());
});
// up
return listOfDomainConfiguration.stream().map(dc -> conversionService.convert(dc, DomainPropertyRO.class))
.collect(Collectors.toList());
}
private boolean validateRemoveDomainResourceDef(DBDomain domain, DBResourceDef resourceDef) {
Long count = resourceDao.getResourceCountForDomainIdAndResourceDefId(domain.getId(), resourceDef.getId());
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment