JpaDistributionSet#metadata made Map (#2411)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -26,7 +26,6 @@ import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusBuilder;
|
||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaRolloutGroupBuilder;
|
||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaSoftwareModuleTypeBuilder;
|
||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaTagBuilder;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
@@ -71,11 +70,6 @@ public class JpaEntityFactory implements EntityFactory {
|
||||
return distributionSetBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MetaData generateDsMetadata(final String key, final String value) {
|
||||
return new JpaDistributionSetMetadata(key, value == null ? null : value.strip());
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoftwareModuleMetadataBuilder softwareModuleMetadata() {
|
||||
return softwareModuleMetadataBuilder;
|
||||
|
||||
@@ -119,7 +119,6 @@ import org.eclipse.hawkbit.repository.jpa.model.helper.SecurityTokenGeneratorHol
|
||||
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantAwareHolder;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetMetadataRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTagRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTypeRepository;
|
||||
@@ -536,7 +535,6 @@ public class RepositoryApplicationConfiguration {
|
||||
final DistributionSetRepository distributionSetRepository,
|
||||
final DistributionSetTagManagement distributionSetTagManagement, final SystemManagement systemManagement,
|
||||
final DistributionSetTypeManagement distributionSetTypeManagement, final QuotaManagement quotaManagement,
|
||||
final DistributionSetMetadataRepository distributionSetMetadataRepository,
|
||||
final TargetRepository targetRepository,
|
||||
final TargetFilterQueryRepository targetFilterQueryRepository, final ActionRepository actionRepository,
|
||||
final SystemSecurityContext systemSecurityContext, final TenantConfigurationManagement tenantConfigurationManagement,
|
||||
@@ -544,7 +542,7 @@ public class RepositoryApplicationConfiguration {
|
||||
final DistributionSetTagRepository distributionSetTagRepository,
|
||||
final JpaProperties properties, final RepositoryProperties repositoryProperties) {
|
||||
return new JpaDistributionSetManagement(entityManager, distributionSetRepository, distributionSetTagManagement,
|
||||
systemManagement, distributionSetTypeManagement, quotaManagement, distributionSetMetadataRepository,
|
||||
systemManagement, distributionSetTypeManagement, quotaManagement,
|
||||
targetRepository, targetFilterQueryRepository, actionRepository,
|
||||
TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement),
|
||||
virtualPropertyReplacer, softwareModuleRepository, distributionSetTagRepository,
|
||||
|
||||
@@ -12,9 +12,9 @@ package org.eclipse.hawkbit.repository.jpa.management;
|
||||
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.IMPLICIT_LOCK_ENABLED;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
@@ -24,11 +24,15 @@ import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.MapJoin;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import jakarta.persistence.metamodel.MapAttribute;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import org.eclipse.hawkbit.repository.DistributionSetFields;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetMetadataFields;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
|
||||
import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||
@@ -49,14 +53,10 @@ import org.eclipse.hawkbit.repository.jpa.acm.AccessController;
|
||||
import org.eclipse.hawkbit.repository.jpa.builder.JpaDistributionSetCreate;
|
||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.DsMetadataCompositeKey;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetMetadataRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.DistributionSetTagRepository;
|
||||
import org.eclipse.hawkbit.repository.jpa.repository.SoftwareModuleRepository;
|
||||
@@ -69,10 +69,8 @@ import org.eclipse.hawkbit.repository.jpa.utils.QuotaHelper;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetFilter;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.Statistic;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
@@ -103,7 +101,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
private final SystemManagement systemManagement;
|
||||
private final DistributionSetTypeManagement distributionSetTypeManagement;
|
||||
private final QuotaManagement quotaManagement;
|
||||
private final DistributionSetMetadataRepository distributionSetMetadataRepository;
|
||||
private final TargetRepository targetRepository;
|
||||
private final TargetFilterQueryRepository targetFilterQueryRepository;
|
||||
private final ActionRepository actionRepository;
|
||||
@@ -120,7 +117,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
final DistributionSetRepository distributionSetRepository,
|
||||
final DistributionSetTagManagement distributionSetTagManagement, final SystemManagement systemManagement,
|
||||
final DistributionSetTypeManagement distributionSetTypeManagement, final QuotaManagement quotaManagement,
|
||||
final DistributionSetMetadataRepository distributionSetMetadataRepository,
|
||||
final TargetRepository targetRepository,
|
||||
final TargetFilterQueryRepository targetFilterQueryRepository, final ActionRepository actionRepository,
|
||||
final TenantConfigHelper tenantConfigHelper,
|
||||
@@ -135,7 +131,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
this.systemManagement = systemManagement;
|
||||
this.distributionSetTypeManagement = distributionSetTypeManagement;
|
||||
this.quotaManagement = quotaManagement;
|
||||
this.distributionSetMetadataRepository = distributionSetMetadataRepository;
|
||||
this.targetRepository = targetRepository;
|
||||
this.targetFilterQueryRepository = targetFilterQueryRepository;
|
||||
this.actionRepository = actionRepository;
|
||||
@@ -360,21 +355,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public DistributionSetMetadata updateMetaData(final long id, final MetaData md) {
|
||||
// check if exists otherwise throw entity not found exception
|
||||
final JpaDistributionSetMetadata toUpdate = (JpaDistributionSetMetadata) findMetaDataByDistributionSetId(id, md.getKey())
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSetMetadata.class, id, md.getKey()));
|
||||
toUpdate.setValue(md.getValue());
|
||||
|
||||
// touch it to update the lock revision because we are modifying the DS indirectly, it will, also check UPDATE access
|
||||
JpaManagementHelper.touch(entityManager, distributionSetRepository, (JpaDistributionSet) getValid(id));
|
||||
return distributionSetMetadataRepository.save(toUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
@@ -394,34 +374,60 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public List<DistributionSetMetadata> putMetaData(final long id, final Collection<MetaData> md) {
|
||||
public void createMetadata(final long id, final Map<String, String> md) {
|
||||
final JpaDistributionSet distributionSet = (JpaDistributionSet) getValid(id);
|
||||
assertMetaDataQuota(id, md.size());
|
||||
|
||||
md.forEach(meta -> checkAndThrowIfDistributionSetMetadataAlreadyExists(
|
||||
new DsMetadataCompositeKey(id, meta.getKey())));
|
||||
// get the modifiable metadata map
|
||||
final Map<String, String> metadata = distributionSet.getMetadata();
|
||||
md.keySet().forEach(key -> {
|
||||
if (metadata.containsKey(key)) {
|
||||
throw new EntityAlreadyExistsException("Metadata entry with key '" + key + "' already exists");
|
||||
}
|
||||
});
|
||||
metadata.putAll(md);
|
||||
|
||||
JpaManagementHelper.touch(entityManager, distributionSetRepository, distributionSet);
|
||||
assertMetaDataQuota(id, metadata.size());
|
||||
|
||||
return md.stream()
|
||||
.map(meta -> distributionSetMetadataRepository
|
||||
.save(new JpaDistributionSetMetadata(meta.getKey(), distributionSet, meta.getValue())))
|
||||
.collect(Collectors.toUnmodifiableList());
|
||||
distributionSetRepository.save(distributionSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getMetadata(final long id) {
|
||||
assertDistributionSetExists(id);
|
||||
return getMap(id, JpaDistributionSet_.metadata);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public void deleteMetaData(final long id, final String key) {
|
||||
final JpaDistributionSetMetadata metadata = (JpaDistributionSetMetadata) findMetaDataByDistributionSetId(
|
||||
id, key)
|
||||
.orElseThrow(() -> new EntityNotFoundException(DistributionSetMetadata.class, id, key));
|
||||
public void updateMetadata(final long id, final String key, final String value) {
|
||||
final JpaDistributionSet distributionSet = (JpaDistributionSet) getValid(id);
|
||||
|
||||
// touch it to update the lock revision because we are modifying the
|
||||
// DS indirectly, it will, also check UPDATE access
|
||||
JpaManagementHelper.touch(entityManager, distributionSetRepository, metadata.getDistributionSet());
|
||||
distributionSetMetadataRepository.deleteById(metadata.getId());
|
||||
// get the modifiable metadata map
|
||||
final Map<String, String> metadata = distributionSet.getMetadata();
|
||||
if (!metadata.containsKey(key)) {
|
||||
throw new EntityNotFoundException("DistributionSet metadata", id + ":" + key);
|
||||
}
|
||||
metadata.put(key, value);
|
||||
|
||||
distributionSetRepository.save(distributionSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public void deleteMetadata(final long id, final String key) {
|
||||
final JpaDistributionSet distributionSet = (JpaDistributionSet) getValid(id);
|
||||
|
||||
// get the modifiable metadata map
|
||||
final Map<String, String> metadata = distributionSet.getMetadata();
|
||||
if (metadata.remove(key) == null) {
|
||||
throw new EntityNotFoundException("DistributionSet metadata", id + ":" + key);
|
||||
}
|
||||
|
||||
distributionSetRepository.save(distributionSet);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -504,33 +510,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
return distributionSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<DistributionSetMetadata> findMetaDataByDistributionSetId(final long id, final Pageable pageable) {
|
||||
assertDistributionSetExists(id);
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(distributionSetMetadataRepository, Collections.singletonList(byDsIdSpec(id)), pageable
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countMetaDataByDistributionSetId(final long id) {
|
||||
assertDistributionSetExists(id);
|
||||
|
||||
return distributionSetMetadataRepository.countByDistributionSetId(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<DistributionSetMetadata> findMetaDataByDistributionSetIdAndRsql(final long id, final String rsqlParam,
|
||||
final Pageable pageable) {
|
||||
assertDistributionSetExists(id);
|
||||
|
||||
final List<Specification<JpaDistributionSetMetadata>> specList = Arrays
|
||||
.asList(RSQLUtility.buildRsqlSpecification(rsqlParam, DistributionSetMetadataFields.class,
|
||||
virtualPropertyReplacer, database), byDsIdSpec(id));
|
||||
|
||||
return JpaManagementHelper.findAllWithCountBySpec(distributionSetMetadataRepository, specList, pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Slice<DistributionSet> findByCompleted(final Pageable pageReq, final Boolean complete) {
|
||||
final List<Specification<JpaDistributionSet>> specifications = buildSpecsByComplete(complete);
|
||||
@@ -577,15 +556,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
DistributionSetSpecification.hasTag(tagId), DistributionSetSpecification.isNotDeleted()), pageable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<DistributionSetMetadata> findMetaDataByDistributionSetId(final long id, final String key) {
|
||||
assertDistributionSetExists(id);
|
||||
|
||||
return distributionSetMetadataRepository
|
||||
.findById(new DsMetadataCompositeKey(id, key))
|
||||
.map(DistributionSetMetadata.class::cast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long countByTypeId(final long typeId) {
|
||||
if (!distributionSetTypeManagement.exists(typeId)) {
|
||||
@@ -732,6 +702,24 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> getMap(final long id, final MapAttribute<JpaDistributionSet, String, String> mapAttribute) {
|
||||
final CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
||||
final CriteriaQuery<Object[]> query = cb.createQuery(Object[].class);
|
||||
|
||||
final Root<JpaDistributionSet> targetRoot = query.from(JpaDistributionSet.class);
|
||||
query.where(cb.equal(targetRoot.get(AbstractJpaBaseEntity_.ID), id));
|
||||
|
||||
final MapJoin<JpaDistributionSet, String, String> mapJoin = targetRoot.join(mapAttribute);
|
||||
query.multiselect(mapJoin.key(), mapJoin.value());
|
||||
query.orderBy(cb.asc(mapJoin.key()));
|
||||
|
||||
return entityManager
|
||||
.createQuery(query)
|
||||
.getResultList()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(entry -> (String) entry[0], entry -> (String) entry[1], (v1, v2) -> v1, LinkedHashMap::new));
|
||||
}
|
||||
|
||||
private JpaSoftwareModule findSoftwareModuleAndThrowExceptionIfNotFound(final Long softwareModuleId) {
|
||||
return softwareModuleRepository.findById(softwareModuleId)
|
||||
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, softwareModuleId));
|
||||
@@ -754,9 +742,8 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
}
|
||||
|
||||
private void assertMetaDataQuota(final Long dsId, final int requested) {
|
||||
QuotaHelper.assertAssignmentQuota(dsId, requested, quotaManagement.getMaxMetaDataEntriesPerDistributionSet(),
|
||||
DistributionSetMetadata.class, DistributionSet.class,
|
||||
distributionSetMetadataRepository::countByDistributionSetId);
|
||||
final int limit = quotaManagement.getMaxMetaDataEntriesPerDistributionSet();
|
||||
QuotaHelper.assertAssignmentQuota(dsId, requested, limit, "Metadata", DistributionSet.class.getSimpleName(), null);
|
||||
}
|
||||
|
||||
private void assertSoftwareModuleQuota(final Long id, final int requested) {
|
||||
@@ -764,11 +751,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
SoftwareModule.class, DistributionSet.class, softwareModuleRepository::countByAssignedToId);
|
||||
}
|
||||
|
||||
private Specification<JpaDistributionSetMetadata> byDsIdSpec(final long dsId) {
|
||||
return (root, query, cb) -> cb
|
||||
.equal(root.get(JpaDistributionSetMetadata_.distributionSet).get(AbstractJpaBaseEntity_.id), dsId);
|
||||
}
|
||||
|
||||
private void assertDistributionSetIsNotAssignedToTargets(final Long distributionSet) {
|
||||
if (actionRepository.countByDistributionSetId(distributionSet) > 0) {
|
||||
throw new EntityReadOnlyException(String.format(
|
||||
@@ -776,13 +758,6 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkAndThrowIfDistributionSetMetadataAlreadyExists(final DsMetadataCompositeKey metadataId) {
|
||||
if (distributionSetMetadataRepository.existsById(metadataId)) {
|
||||
throw new EntityAlreadyExistsException(
|
||||
"Metadata entry with key '" + metadataId.getKey() + "' already exists");
|
||||
}
|
||||
}
|
||||
|
||||
private List<JpaDistributionSet> getDistributionSets(final Collection<Long> ids) {
|
||||
final List<JpaDistributionSet> foundDs = distributionSetRepository.findAllById(ids);
|
||||
if (foundDs.size() != ids.size()) {
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.model;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
/**
|
||||
* The DistributionSet Metadata composite key which contains the meta-data key and the ID of the DistributionSet itself.
|
||||
*/
|
||||
@NoArgsConstructor // Default constructor for JPA
|
||||
@Setter
|
||||
@Getter
|
||||
public final class DsMetadataCompositeKey implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String key;
|
||||
private Long distributionSet;
|
||||
|
||||
/**
|
||||
* @param distributionSet the distribution set for this meta data
|
||||
* @param key the key of the meta data
|
||||
*/
|
||||
public DsMetadataCompositeKey(final Long distributionSet, final String key) {
|
||||
this.distributionSet = distributionSet;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (distributionSet == null ? 0 : distributionSet.hashCode());
|
||||
result = prime * result + (key == null ? 0 : key.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final DsMetadataCompositeKey other = (DsMetadataCompositeKey) obj;
|
||||
if (distributionSet == null) {
|
||||
if (other.distributionSet != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!distributionSet.equals(other.distributionSet)) {
|
||||
return false;
|
||||
}
|
||||
if (key == null) {
|
||||
return other.key == null;
|
||||
} else {
|
||||
return key.equals(other.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,13 +13,14 @@ import java.io.Serial;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.CollectionTable;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.ConstraintMode;
|
||||
import jakarta.persistence.ElementCollection;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ForeignKey;
|
||||
@@ -28,9 +29,9 @@ import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinTable;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.MapKeyColumn;
|
||||
import jakarta.persistence.NamedAttributeNode;
|
||||
import jakarta.persistence.NamedEntityGraph;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
@@ -47,7 +48,6 @@ import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetExcepti
|
||||
import org.eclipse.hawkbit.repository.exception.LockedException;
|
||||
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
@@ -109,11 +109,16 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_tag_tag")) })
|
||||
private Set<DistributionSetTag> tags = new HashSet<>();
|
||||
|
||||
@ToString.Exclude
|
||||
@OneToMany(mappedBy = "distributionSet", fetch = FetchType.LAZY,
|
||||
cascade = { CascadeType.REMOVE },
|
||||
targetEntity = JpaDistributionSetMetadata.class)
|
||||
private List<DistributionSetMetadata> metadata;
|
||||
// no cascade option on an ElementCollection, the target objects are always persisted, merged, removed with their parent
|
||||
@Getter
|
||||
@ElementCollection
|
||||
@CollectionTable(
|
||||
name = "sp_ds_metadata",
|
||||
joinColumns = { @JoinColumn(name = "ds", nullable = false) },
|
||||
foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_metadata_ds"))
|
||||
@MapKeyColumn(name = "meta_key", length = DistributionSet.METADATA_KEY_SIZE)
|
||||
@Column(name = "meta_value", length = DistributionSet.METADATA_VALUE_SIZE)
|
||||
private Map<String, String> metadata;
|
||||
|
||||
@Column(name = "complete")
|
||||
private boolean complete;
|
||||
@@ -217,14 +222,6 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen
|
||||
return tags.remove(tag);
|
||||
}
|
||||
|
||||
public List<DistributionSetMetadata> getMetadata() {
|
||||
if (metadata == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(metadata);
|
||||
}
|
||||
|
||||
public void lock() {
|
||||
if (!isComplete()) {
|
||||
throw new IncompleteDistributionSetException("Could not be locked while incomplete!");
|
||||
|
||||
@@ -1,86 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.model;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
import jakarta.persistence.ConstraintMode;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.ForeignKey;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.IdClass;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
|
||||
/**
|
||||
* Meta data for {@link DistributionSet}.
|
||||
*/
|
||||
@NoArgsConstructor // Default constructor needed for JPA entities.
|
||||
@Getter
|
||||
@IdClass(DsMetadataCompositeKey.class)
|
||||
@Entity
|
||||
@Table(name = "sp_ds_metadata")
|
||||
public class JpaDistributionSetMetadata extends AbstractJpaMetaData implements DistributionSetMetadata {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@ManyToOne(fetch = FetchType.LAZY, optional = false)
|
||||
@JoinColumn(name = "ds", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_metadata_ds"))
|
||||
private JpaDistributionSet distributionSet;
|
||||
|
||||
public JpaDistributionSetMetadata(final String key, final String value) {
|
||||
super(key, value);
|
||||
}
|
||||
|
||||
public JpaDistributionSetMetadata(final String key, final DistributionSet distributionSet, final String value) {
|
||||
super(key, value);
|
||||
this.distributionSet = (JpaDistributionSet) distributionSet;
|
||||
}
|
||||
|
||||
public DsMetadataCompositeKey getId() {
|
||||
return new DsMetadataCompositeKey(distributionSet.getId(), getKey());
|
||||
}
|
||||
|
||||
public void setDistributionSet(final DistributionSet distributionSet) {
|
||||
this.distributionSet = (JpaDistributionSet) distributionSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = super.hashCode();
|
||||
result = prime * result + ((distributionSet == null) ? 0 : distributionSet.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
// exception squid:S2259 - obj is checked for null in super
|
||||
@SuppressWarnings("squid:S2259")
|
||||
public boolean equals(final Object obj) {
|
||||
if (!super.equals(obj)) {
|
||||
return false;
|
||||
}
|
||||
final JpaDistributionSetMetadata other = (JpaDistributionSetMetadata) obj;
|
||||
if (distributionSet == null) {
|
||||
return other.distributionSet == null;
|
||||
} else {
|
||||
return distributionSet.equals(other.distributionSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.repository;
|
||||
|
||||
import org.eclipse.hawkbit.repository.jpa.model.DsMetadataCompositeKey;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* {@link DistributionSetMetadata} repository.
|
||||
*/
|
||||
@Transactional(readOnly = true)
|
||||
public interface DistributionSetMetadataRepository
|
||||
extends PagingAndSortingRepository<JpaDistributionSetMetadata, DsMetadataCompositeKey>,
|
||||
CrudRepository<JpaDistributionSetMetadata, DsMetadataCompositeKey>,
|
||||
JpaSpecificationExecutor<JpaDistributionSetMetadata> {
|
||||
|
||||
/**
|
||||
* Counts the meta data entries that match the given distribution set ID.
|
||||
* <p/>
|
||||
* No access control applied
|
||||
*
|
||||
* @param id of the distribution set.
|
||||
* @return The number of matching meta data entries.
|
||||
*/
|
||||
long countByDistributionSetId(@Param("id") Long id);
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
|
||||
@@ -28,14 +29,12 @@ import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
|
||||
import org.eclipse.hawkbit.repository.jpa.acm.AccessController;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetFilter;
|
||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -121,12 +120,18 @@ class DistributionSetAccessControllerTest extends AbstractAccessControllerTest {
|
||||
@Description("Verifies read access rules for distribution sets")
|
||||
void verifyDistributionSetUpdates() {
|
||||
// permit all operations first to prepare test setup
|
||||
permitAllOperations(AccessController.Operation.READ);
|
||||
permitAllOperations(AccessController.Operation.CREATE);
|
||||
permitAllOperations(AccessController.Operation.UPDATE);
|
||||
|
||||
final DistributionSet permitted = testdataFactory.createDistributionSet();
|
||||
final String mdPresetKey = "metadata.preset";
|
||||
final String mdPresetValue = "presetValue";
|
||||
distributionSetManagement.createMetadata(permitted.getId(), Map.of(mdPresetKey, mdPresetValue));
|
||||
final DistributionSet readOnly = testdataFactory.createDistributionSet();
|
||||
distributionSetManagement.createMetadata(readOnly.getId(), Map.of(mdPresetKey, mdPresetValue));
|
||||
final DistributionSet hidden = testdataFactory.createDistributionSet();
|
||||
distributionSetManagement.createMetadata(hidden.getId(), Map.of(mdPresetKey, mdPresetValue));
|
||||
|
||||
final SoftwareModule swModule = testdataFactory.createSoftwareModuleOs();
|
||||
|
||||
@@ -134,52 +139,49 @@ class DistributionSetAccessControllerTest extends AbstractAccessControllerTest {
|
||||
testAccessControlManger.deleteAllRules();
|
||||
// define access controlling rule
|
||||
defineAccess(AccessController.Operation.READ, permitted, readOnly);
|
||||
|
||||
// allow updating the permitted distributionSet
|
||||
defineAccess(AccessController.Operation.READ, permitted);
|
||||
defineAccess(AccessController.Operation.UPDATE, permitted);
|
||||
|
||||
// verify distributionSetManagement#assignSoftwareModules
|
||||
final var singleModuleIdList = Collections.singletonList(swModule.getId());
|
||||
final List<Long> singleModuleIdList = Collections.singletonList(swModule.getId());
|
||||
assertThat(distributionSetManagement.assignSoftwareModules(permitted.getId(), singleModuleIdList))
|
||||
.satisfies(ds -> assertThat(ds.getModules().stream().map(Identifiable::getId).toList()).contains(swModule.getId()));
|
||||
final Long readOnlyId = readOnly.getId();
|
||||
assertThatThrownBy(() -> distributionSetManagement.assignSoftwareModules(readOnlyId, singleModuleIdList))
|
||||
.as("Distribution set not allowed to me modified.")
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
final Long hiddenId = hidden.getId();
|
||||
assertThatThrownBy(() -> distributionSetManagement.assignSoftwareModules(hiddenId, singleModuleIdList))
|
||||
.as("Distribution set should not be visible.")
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
|
||||
final JpaDistributionSetMetadata metadata = new JpaDistributionSetMetadata("test", "test");
|
||||
final Map<String, String> metadata = Map.of("test.create", mdPresetValue);
|
||||
|
||||
// verify distributionSetManagement#createMetaData
|
||||
final List<MetaData> metadataList = Collections.singletonList(metadata);
|
||||
distributionSetManagement.putMetaData(permitted.getId(), metadataList);
|
||||
assertThatThrownBy(() -> distributionSetManagement.putMetaData(readOnlyId, metadataList))
|
||||
.as("Distribution set not allowed to me modified.")
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
assertThatThrownBy(() -> distributionSetManagement.putMetaData(hiddenId, metadataList))
|
||||
distributionSetManagement.createMetadata(permitted.getId(), metadata);
|
||||
assertThatThrownBy(() -> distributionSetManagement.createMetadata(readOnlyId, metadata))
|
||||
.as("Distribution set not allowed to be modified.")
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
assertThatThrownBy(() -> distributionSetManagement.createMetadata(hiddenId, metadata))
|
||||
.as("Distribution set should not be visible.")
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
|
||||
// verify distributionSetManagement#updateMetaData
|
||||
distributionSetManagement.updateMetaData(permitted.getId(), metadata);
|
||||
assertThatThrownBy(() -> distributionSetManagement.updateMetaData(readOnlyId, metadata))
|
||||
final String newValue = "newValue";
|
||||
distributionSetManagement.updateMetadata(permitted.getId(), mdPresetKey, newValue);
|
||||
assertThatThrownBy(() -> distributionSetManagement.updateMetadata(readOnlyId, mdPresetKey, newValue))
|
||||
.as("Distribution set not allowed to me modified.")
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
assertThatThrownBy(() -> distributionSetManagement.updateMetaData(hiddenId, metadata))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
assertThatThrownBy(() -> distributionSetManagement.updateMetadata(hiddenId, mdPresetKey, newValue))
|
||||
.as("Distribution set should not be visible.")
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
|
||||
// verify distributionSetManagement#deleteMetaData
|
||||
final String metadataKey = metadata.getKey();
|
||||
distributionSetManagement.deleteMetaData(permitted.getId(), metadataKey);
|
||||
assertThatThrownBy(() -> distributionSetManagement.deleteMetaData(readOnlyId, metadataKey))
|
||||
final String metadataKey = metadata.entrySet().stream().findAny().get().getKey();
|
||||
distributionSetManagement.deleteMetadata(permitted.getId(), metadataKey);
|
||||
assertThatThrownBy(() -> distributionSetManagement.deleteMetadata(readOnlyId, mdPresetKey))
|
||||
.as("Distribution set not allowed to me modified.")
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
assertThatThrownBy(() -> distributionSetManagement.deleteMetaData(hiddenId, metadataKey))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
assertThatThrownBy(() -> distributionSetManagement.deleteMetadata(hiddenId, mdPresetKey))
|
||||
.as("Distribution set should not be visible.")
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
}
|
||||
|
||||
@@ -220,13 +220,12 @@ class TargetAccessControllerTest extends AbstractAccessControllerTest {
|
||||
|
||||
final Target permittedTarget = targetManagement
|
||||
.create(entityFactory.target().create().controllerId("device01").status(TargetUpdateStatus.REGISTERED));
|
||||
|
||||
final String hiddenTargetControllerId = targetManagement
|
||||
.create(entityFactory.target().create().controllerId("device02").status(TargetUpdateStatus.REGISTERED))
|
||||
.getControllerId();
|
||||
|
||||
// define access controlling rule
|
||||
defineAccess(AccessController.Operation.READ, permittedTarget);
|
||||
overwriteAccess(AccessController.Operation.READ, permittedTarget);
|
||||
|
||||
// verify targetManagement#findByUpdateStatus before assignment
|
||||
assertThat(targetManagement.findByUpdateStatus(Pageable.unpaged(), TargetUpdateStatus.REGISTERED).get()
|
||||
@@ -269,18 +268,15 @@ class TargetAccessControllerTest extends AbstractAccessControllerTest {
|
||||
|
||||
final Target manageableTarget = targetManagement
|
||||
.create(entityFactory.target().create().controllerId("device01").status(TargetUpdateStatus.REGISTERED));
|
||||
|
||||
final Target readOnlyTarget = targetManagement
|
||||
.create(entityFactory.target().create().controllerId("device02").status(TargetUpdateStatus.REGISTERED));
|
||||
|
||||
// define access controlling rule
|
||||
defineAccess(AccessController.Operation.READ, manageableTarget, readOnlyTarget);
|
||||
|
||||
defineAccess(AccessController.Operation.UPDATE, manageableTarget);
|
||||
// overwriting full access controlling rule
|
||||
overwriteAccess(AccessController.Operation.READ, manageableTarget, readOnlyTarget);
|
||||
overwriteAccess(AccessController.Operation.UPDATE, manageableTarget);
|
||||
|
||||
// assignment is permitted for manageableTarget
|
||||
assertThat(assignDistributionSet(firstDsId, manageableTarget.getControllerId()).getAssigned())
|
||||
.isEqualTo(1);
|
||||
assertThat(assignDistributionSet(firstDsId, manageableTarget.getControllerId()).getAssigned()).isEqualTo(1);
|
||||
|
||||
// assignment is denied for readOnlyTarget (read, but no update permissions)
|
||||
final var readOnlyTargetControllerId = readOnlyTarget.getControllerId();
|
||||
@@ -309,19 +305,17 @@ class TargetAccessControllerTest extends AbstractAccessControllerTest {
|
||||
|
||||
final List<Target> updateTargets = testdataFactory.createTargets("update1", "update2", "update3");
|
||||
final List<Target> readTargets = testdataFactory.createTargets("read1", "read2", "read3", "read4");
|
||||
final List<Target> hiddenTargets = testdataFactory.createTargets(
|
||||
"hidden1", "hidden2", "hidden3", "hidden4", "hidden5");
|
||||
final List<Target> hiddenTargets = testdataFactory.createTargets("hidden1", "hidden2", "hidden3", "hidden4", "hidden5");
|
||||
|
||||
defineAccess(AccessController.Operation.UPDATE, updateTargets);
|
||||
defineAccess(AccessController.Operation.READ, merge(readTargets, updateTargets));
|
||||
overwriteAccess(AccessController.Operation.READ, merge(readTargets, updateTargets));
|
||||
|
||||
final Rollout rollout = testdataFactory.createRolloutByVariables("testRollout", "description",
|
||||
updateTargets.size(), "id==*", ds, "50", "5");
|
||||
final Rollout rollout = testdataFactory.createRolloutByVariables(
|
||||
"testRollout", "description", updateTargets.size(), "id==*", ds, "50", "5");
|
||||
|
||||
assertThat(rollout.getTotalTargets()).isEqualTo(updateTargets.size());
|
||||
|
||||
final List<RolloutGroup> content = rolloutGroupManagement.findByRollout(rollout.getId(), Pageable.unpaged())
|
||||
.getContent();
|
||||
final List<RolloutGroup> content = rolloutGroupManagement.findByRollout(rollout.getId(), Pageable.unpaged()).getContent();
|
||||
assertThat(content).hasSize(updateTargets.size());
|
||||
|
||||
final List<Target> rolloutTargets = content.stream().flatMap(
|
||||
@@ -393,6 +387,18 @@ class TargetAccessControllerTest extends AbstractAccessControllerTest {
|
||||
target -> ids.contains(target.getId()));
|
||||
}
|
||||
|
||||
private void overwriteAccess(final AccessController.Operation operation, final Target... target) {
|
||||
overwriteAccess(operation, List.of(target));
|
||||
}
|
||||
|
||||
private void overwriteAccess(final AccessController.Operation operation, final List<Target> targets) {
|
||||
final List<Long> ids = targets.stream().map(Target::getId).toList();
|
||||
testAccessControlManger.overwriteAccessRule(
|
||||
JpaTarget.class, operation,
|
||||
TargetSpecifications.hasIdIn(ids),
|
||||
target -> ids.contains(target.getId()));
|
||||
}
|
||||
|
||||
private static Specification<JpaDistributionSet> dsById(final Long distid) {
|
||||
return (dsRoot, query, cb) -> {
|
||||
final Predicate predicate = cb.equal(dsRoot.get(JpaDistributionSet_.id), distid);
|
||||
|
||||
@@ -14,6 +14,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
@@ -37,14 +38,9 @@ class TargetTypeAccessControllerTest extends AbstractAccessControllerTest {
|
||||
@Test
|
||||
@Description("Verifies read access rules for target types")
|
||||
void verifyTargetTypeReadOperations() {
|
||||
permitAllOperations(AccessController.Operation.READ);
|
||||
permitAllOperations(AccessController.Operation.CREATE);
|
||||
|
||||
final TargetType permittedTargetType = targetTypeManagement
|
||||
.create(entityFactory.targetType().create().name("type1"));
|
||||
|
||||
final TargetType hiddenTargetType = targetTypeManagement
|
||||
.create(entityFactory.targetType().create().name("type2"));
|
||||
final TargetType permittedTargetType = targetTypeManagement.create(entityFactory.targetType().create().name("type1"));
|
||||
final TargetType hiddenTargetType = targetTypeManagement.create(entityFactory.targetType().create().name("type2"));
|
||||
|
||||
// define access controlling rule
|
||||
defineAccess(AccessController.Operation.READ, permittedTargetType);
|
||||
@@ -67,12 +63,12 @@ class TargetTypeAccessControllerTest extends AbstractAccessControllerTest {
|
||||
assertThat(targetTypeManagement.count()).isEqualTo(1);
|
||||
|
||||
// verify targetTypeManagement#countByName
|
||||
// assertThat(targetTypeManagement.countByName(permittedTargetType.getName())).isEqualTo(1);
|
||||
// assertThat(targetTypeManagement.countByName(hiddenTargetType.getName())).isZero();
|
||||
assertThat(targetTypeManagement.countByName(permittedTargetType.getName())).isEqualTo(1);
|
||||
assertThat(targetTypeManagement.countByName(hiddenTargetType.getName())).isZero();
|
||||
|
||||
// verify targetTypeManagement#countByName
|
||||
// assertThat(targetTypeManagement.countByName(permittedTargetType.getName())).isEqualTo(1);
|
||||
// assertThat(targetTypeManagement.countByName(hiddenTargetType.getName())).isZero();
|
||||
assertThat(targetTypeManagement.countByName(permittedTargetType.getName())).isEqualTo(1);
|
||||
assertThat(targetTypeManagement.countByName(hiddenTargetType.getName())).isZero();
|
||||
|
||||
// verify targetTypeManagement#get by id
|
||||
assertThat(targetTypeManagement.get(permittedTargetType.getId())).isPresent();
|
||||
@@ -161,15 +157,11 @@ class TargetTypeAccessControllerTest extends AbstractAccessControllerTest {
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
}
|
||||
|
||||
private void defineAccess(final AccessController.Operation operation, final TargetType... targetType) {
|
||||
defineAccess(operation, List.of(targetType));
|
||||
}
|
||||
|
||||
private void defineAccess(final AccessController.Operation operation, final List<TargetType> targetTypes) {
|
||||
final List<Long> ids = targetTypes.stream().map(TargetType::getId).toList();
|
||||
private void defineAccess(final AccessController.Operation operation, final TargetType... targetTypes) {
|
||||
final List<Long> ids = Stream.of(targetTypes).map(TargetType::getId).toList();
|
||||
testAccessControlManger.defineAccessRule(
|
||||
JpaTargetType.class, operation,
|
||||
TargetTypeSpecification.hasIdIn(ids),
|
||||
targetType -> ids.contains(targetType.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,23 @@ public class TestAccessControlManger {
|
||||
public <T> void defineAccessRule(
|
||||
final Class<T> ruleClass, final AccessController.Operation operation,
|
||||
final Specification<T> specification, final Predicate<T> check) {
|
||||
accessRules.put(new AccessRuleId<>(ruleClass, operation), new AccessRule<>(specification, check));
|
||||
defineAccessRule(ruleClass, operation, specification, check, false);
|
||||
}
|
||||
|
||||
public <T> void overwriteAccessRule(
|
||||
final Class<T> ruleClass, final AccessController.Operation operation,
|
||||
final Specification<T> specification, final Predicate<T> check) {
|
||||
defineAccessRule(ruleClass, operation, specification, check, true);
|
||||
}
|
||||
|
||||
private <T> void defineAccessRule(
|
||||
final Class<T> ruleClass, final AccessController.Operation operation,
|
||||
final Specification<T> specification, final Predicate<T> check, final boolean overwrite) {
|
||||
final AccessRuleId<T> ruleId = new AccessRuleId<>(ruleClass, operation);
|
||||
if (!overwrite && accessRules.containsKey(ruleId)) {
|
||||
throw new IllegalStateException("Access rule already defined for " + ruleId + "! You should explicitly set overwrite to true.");
|
||||
}
|
||||
accessRules.put(ruleId, new AccessRule<>(specification, check));
|
||||
}
|
||||
|
||||
public <T extends AbstractJpaBaseEntity> Specification<T> getAccessRule(final Class<T> ruleClass,
|
||||
@@ -53,8 +69,7 @@ public class TestAccessControlManger {
|
||||
} else {
|
||||
for (final T entity : entities) {
|
||||
if (!accessRule.checker.test(entity)) {
|
||||
throw new InsufficientPermissionException(
|
||||
"Access to " + ruleClass.getName() + "/" + entity + " not allowed by checker!");
|
||||
throw new InsufficientPermissionException("Access to " + ruleClass.getName() + "/" + entity + " not allowed by checker!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,4 +82,4 @@ public class TestAccessControlManger {
|
||||
private record AccessRuleId<T>(Class<T> ruleClass, AccessController.Operation operation) {}
|
||||
|
||||
private record AccessRule<T>(Specification<T> specification, Predicate<T> checker) {}
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@
|
||||
package org.eclipse.hawkbit.repository.jpa.management;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
@@ -66,17 +67,36 @@ class DistributionSetManagementSecurityTest
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void createMetaDataPermissionsCheck() {
|
||||
void createMetadataPermissionsCheck() {
|
||||
assertPermissions(
|
||||
() -> distributionSetManagement.putMetaData(1L, List.of(entityFactory.generateDsMetadata("key", "value"))),
|
||||
() -> {
|
||||
distributionSetManagement.createMetadata(1L, Map.of("key", "value"));
|
||||
return null;
|
||||
},
|
||||
List.of(SpPermission.UPDATE_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void deleteMetaDataPermissionsCheck() {
|
||||
void getMetadataPermissiosCheck() {
|
||||
assertPermissions(() -> distributionSetManagement.getMetadata(1L), List.of(SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void updateMetadataPermissionsCheck() {
|
||||
assertPermissions(() -> {
|
||||
distributionSetManagement.deleteMetaData(1L, "key");
|
||||
distributionSetManagement.updateMetadata(1L,"key", "value");
|
||||
return null;
|
||||
},
|
||||
List.of(SpPermission.UPDATE_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void deleteMetadataPermissionsCheck() {
|
||||
assertPermissions(() -> {
|
||||
distributionSetManagement.deleteMetadata(1L, "key");
|
||||
return null;
|
||||
}, List.of(SpPermission.UPDATE_REPOSITORY));
|
||||
}
|
||||
@@ -135,25 +155,6 @@ class DistributionSetManagementSecurityTest
|
||||
assertPermissions(() -> distributionSetManagement.getOrElseThrowException(1L), List.of(SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void findMetaDataByDistributionSetIdPermissionsCheck() {
|
||||
assertPermissions(() -> distributionSetManagement.findMetaDataByDistributionSetId(1L, PAGE), List.of(SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void countMetaDataByDistributionSetIdPermissionsCheck() {
|
||||
assertPermissions(() -> distributionSetManagement.countMetaDataByDistributionSetId(1L), List.of(SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void findMetaDataByDistributionSetIdAndRsqlPermissionsCheck() {
|
||||
assertPermissions(() -> distributionSetManagement.findMetaDataByDistributionSetIdAndRsql(1L, "rsql", PAGE),
|
||||
List.of(SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void findByCompletedPermissionsCheck() {
|
||||
@@ -192,12 +193,6 @@ class DistributionSetManagementSecurityTest
|
||||
assertPermissions(() -> distributionSetManagement.findByRsqlAndTag("rsql", 1L, PAGE), List.of(SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void getMetaDataByDistributionSetIdPermissionsCheck() {
|
||||
assertPermissions(() -> distributionSetManagement.findMetaDataByDistributionSetId(1L, "key"), List.of(SpPermission.READ_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void isInUsePermissionsCheck() {
|
||||
@@ -210,13 +205,6 @@ class DistributionSetManagementSecurityTest
|
||||
assertPermissions(() -> distributionSetManagement.unassignSoftwareModule(1L, 1L), List.of(SpPermission.UPDATE_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void updateMetaDataPermissionsCheck() {
|
||||
assertPermissions(() -> distributionSetManagement.updateMetaData(1L, entityFactory.generateDsMetadata("key", "value")),
|
||||
List.of(SpPermission.UPDATE_REPOSITORY));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.")
|
||||
void countByTypeIdPermissionsCheck() {
|
||||
|
||||
@@ -18,7 +18,9 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@@ -49,17 +51,14 @@ import org.eclipse.hawkbit.repository.exception.LockedException;
|
||||
import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThisDistributionSetException;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.Action.Status;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetFilter;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetFilter.DistributionSetFilterBuilder;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.CancelationType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
import org.eclipse.hawkbit.repository.model.NamedEntity;
|
||||
import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
@@ -71,8 +70,6 @@ import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
|
||||
/**
|
||||
* {@link DistributionSetManagement} tests.
|
||||
@@ -96,7 +93,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
assertThat(distributionSetManagement.get(NOT_EXIST_IDL)).isNotPresent();
|
||||
assertThat(distributionSetManagement.getWithDetails(NOT_EXIST_IDL)).isNotPresent();
|
||||
assertThat(distributionSetManagement.findByNameAndVersion(NOT_EXIST_ID, NOT_EXIST_ID)).isNotPresent();
|
||||
assertThat(distributionSetManagement.findMetaDataByDistributionSetId(set.getId(), NOT_EXIST_ID)).isNotPresent();
|
||||
assertThat(distributionSetManagement.getMetadata(set.getId()).get(NOT_EXIST_ID)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -138,44 +135,30 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.create(
|
||||
entityFactory.distributionSet().create().name("xxx").type(NOT_EXIST_ID)), "DistributionSetType");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.putMetaData(
|
||||
NOT_EXIST_IDL, singletonList(entityFactory.generateDsMetadata("123", "123"))), "DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.createMetadata(NOT_EXIST_IDL, Map.of("123", "123")), "DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.delete(singletonList(NOT_EXIST_IDL)), "DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.delete(NOT_EXIST_IDL), "DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.deleteMetaData(NOT_EXIST_IDL, "xxx"),
|
||||
"DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.deleteMetaData(set.getId(), NOT_EXIST_ID),
|
||||
"DistributionSetMetadata");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.deleteMetadata(NOT_EXIST_IDL, "xxx"), "DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.deleteMetadata(set.getId(), NOT_EXIST_ID), "DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.findByAction(NOT_EXIST_IDL), "Action");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.findMetaDataByDistributionSetId(NOT_EXIST_IDL, "xxx"),
|
||||
"DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.getMetadata(NOT_EXIST_IDL).get("xxx"), "DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.findMetaDataByDistributionSetId(NOT_EXIST_IDL, PAGE),
|
||||
"DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(
|
||||
() -> distributionSetManagement.findMetaDataByDistributionSetIdAndRsql(NOT_EXIST_IDL, "name==*", PAGE),
|
||||
"DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.getMetadata(NOT_EXIST_IDL).get(PAGE), "DistributionSet");
|
||||
|
||||
assertThatThrownBy(() -> distributionSetManagement.isInUse(NOT_EXIST_IDL))
|
||||
.isInstanceOf(EntityNotFoundException.class).hasMessageContaining(NOT_EXIST_ID)
|
||||
.hasMessageContaining("DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(
|
||||
() -> distributionSetManagement.update(entityFactory.distributionSet().update(NOT_EXIST_IDL)),
|
||||
"DistributionSet");
|
||||
() -> distributionSetManagement.update(entityFactory.distributionSet().update(NOT_EXIST_IDL)), "DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.updateMetaData(NOT_EXIST_IDL,
|
||||
entityFactory.generateDsMetadata("xxx", "xxx")), "DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.updateMetadata(NOT_EXIST_IDL,"xxx", "xxx"), "DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.updateMetadata(set.getId(),NOT_EXIST_ID, "xxx"), "DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.updateMetaData(set.getId(),
|
||||
entityFactory.generateDsMetadata(NOT_EXIST_ID, "xxx")), "DistributionSetMetadata");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.getOrElseThrowException(NOT_EXIST_IDL),
|
||||
"DistributionSet");
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.getOrElseThrowException(NOT_EXIST_IDL), "DistributionSet");
|
||||
|
||||
verifyThrownExceptionBy(() -> distributionSetManagement.getValidAndComplete(NOT_EXIST_IDL), "DistributionSet");
|
||||
|
||||
@@ -247,68 +230,57 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Test
|
||||
@Description("Checks that metadata for a distribution set can be created.")
|
||||
void createDistributionSetMetadata() {
|
||||
void createMetadata() {
|
||||
final String knownKey = "dsMetaKnownKey";
|
||||
final String knownValue = "dsMetaKnownValue";
|
||||
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("testDs");
|
||||
|
||||
final DistributionSetMetadata metadata = new JpaDistributionSetMetadata(knownKey, ds, knownValue);
|
||||
final JpaDistributionSetMetadata createdMetadata = (JpaDistributionSetMetadata) createDistributionSetMetadata(
|
||||
ds.getId(), metadata);
|
||||
|
||||
assertThat(createdMetadata).isNotNull();
|
||||
assertThat(createdMetadata.getId().getKey()).isEqualTo(knownKey);
|
||||
assertThat(createdMetadata.getDistributionSet().getId()).isEqualTo(ds.getId());
|
||||
assertThat(createdMetadata.getValue()).isEqualTo(knownValue);
|
||||
insertMetadata(knownKey, knownValue, ds); // and validate
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Verifies the enforcement of the metadata quota per distribution set.")
|
||||
void createDistributionSetMetadataUntilQuotaIsExceeded() {
|
||||
void createMetadataUntilQuotaIsExceeded() {
|
||||
|
||||
// add meta data one by one
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("ds1");
|
||||
final int maxMetaData = quotaManagement.getMaxMetaDataEntriesPerDistributionSet();
|
||||
for (int i = 0; i < maxMetaData; ++i) {
|
||||
assertThat((JpaDistributionSetMetadata) createDistributionSetMetadata(ds1.getId(),
|
||||
new JpaDistributionSetMetadata("k" + i, ds1, "v" + i))).isNotNull();
|
||||
insertMetadata("k" + i, "v" + i, ds1);
|
||||
}
|
||||
|
||||
// quota exceeded
|
||||
final Long ds1Id = ds1.getId();
|
||||
final JpaDistributionSetMetadata jpaMaxMetaData = new JpaDistributionSetMetadata("k" + maxMetaData, ds1, "v" + maxMetaData);
|
||||
assertThatExceptionOfType(AssignmentQuotaExceededException.class)
|
||||
.isThrownBy(() -> createDistributionSetMetadata(ds1Id, jpaMaxMetaData));
|
||||
.isThrownBy(() -> insertMetadata("k" + maxMetaData, "v" + maxMetaData, ds1));
|
||||
|
||||
// add multiple meta data entries at once
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("ds2");
|
||||
final List<MetaData> metaData2 = new ArrayList<>();
|
||||
final Map<String, String> metaData2 = new HashMap<>();
|
||||
for (int i = 0; i < maxMetaData + 1; ++i) {
|
||||
metaData2.add(new JpaDistributionSetMetadata("k" + i, ds2, "v" + i));
|
||||
metaData2.put("k" + i, "v" + i);
|
||||
}
|
||||
// verify quota is exceeded
|
||||
final Long ds2Id = ds2.getId();
|
||||
assertThatExceptionOfType(AssignmentQuotaExceededException.class)
|
||||
.isThrownBy(() -> createDistributionSetMetadata(ds2Id, metaData2));
|
||||
.isThrownBy(() -> distributionSetManagement.createMetadata(ds2Id, metaData2));
|
||||
|
||||
// add some meta data entries
|
||||
final DistributionSet ds3 = testdataFactory.createDistributionSet("ds3");
|
||||
final int firstHalf = Math.round((maxMetaData) / 2.f);
|
||||
final Long ds3Id = ds3.getId();
|
||||
for (int i = 0; i < firstHalf; ++i) {
|
||||
createDistributionSetMetadata(ds3Id, new JpaDistributionSetMetadata("k" + i, ds3, "v" + i));
|
||||
insertMetadata("k" + i, "v" + i, ds3);
|
||||
}
|
||||
// add too many data entries
|
||||
final int secondHalf = maxMetaData - firstHalf;
|
||||
final List<MetaData> metaData3 = new ArrayList<>();
|
||||
final Map<String, String> metaData3 = new HashMap<>();
|
||||
for (int i = 0; i < secondHalf + 1; ++i) {
|
||||
metaData3.add(new JpaDistributionSetMetadata("kk" + i, ds3, "vv" + i));
|
||||
metaData3.put("kk" + i, "vv" + i);
|
||||
}
|
||||
// verify quota is exceeded
|
||||
assertThatExceptionOfType(AssignmentQuotaExceededException.class)
|
||||
.isThrownBy(() -> createDistributionSetMetadata(ds3Id, metaData3));
|
||||
|
||||
.isThrownBy(() -> distributionSetManagement.createMetadata(ds3Id, metaData3));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -507,7 +479,7 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@Test
|
||||
@WithUser(allSpPermissions = true)
|
||||
@Description("Checks that metadata for a distribution set can be updated.")
|
||||
void updateDistributionSetMetadata() {
|
||||
void updateMetadata() {
|
||||
final String knownKey = "myKnownKey";
|
||||
final String knownValue = "myKnownValue";
|
||||
final String knownUpdateValue = "myNewUpdatedValue";
|
||||
@@ -519,26 +491,22 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
waitNextMillis();
|
||||
// create an DS meta data entry
|
||||
createDistributionSetMetadata(ds.getId(), new JpaDistributionSetMetadata(knownKey, ds, knownValue));
|
||||
insertMetadata(knownKey, knownValue, ds);
|
||||
|
||||
final DistributionSet changedLockRevisionDS = getOrThrow(distributionSetManagement.get(ds.getId()));
|
||||
assertThat(changedLockRevisionDS.getOptLockRevision()).isEqualTo(2);
|
||||
|
||||
waitNextMillis();
|
||||
// update the DS metadata
|
||||
final JpaDistributionSetMetadata updated = (JpaDistributionSetMetadata) distributionSetManagement
|
||||
.updateMetaData(ds.getId(), entityFactory.generateDsMetadata(knownKey, knownUpdateValue));
|
||||
distributionSetManagement.updateMetadata(ds.getId(), knownKey, knownUpdateValue);
|
||||
// we are updating the sw metadata so also modifying the base software
|
||||
// module so opt lock revision must be three
|
||||
final DistributionSet reloadedDS = getOrThrow(distributionSetManagement.get(ds.getId()));
|
||||
assertThat(reloadedDS.getOptLockRevision()).isEqualTo(3);
|
||||
assertThat(reloadedDS.getLastModifiedAt()).isPositive();
|
||||
|
||||
// verify updated meta data contains the updated value
|
||||
assertThat(updated).isNotNull();
|
||||
assertThat(updated.getValue()).isEqualTo(knownUpdateValue);
|
||||
assertThat(updated.getId().getKey()).isEqualTo(knownKey);
|
||||
assertThat(updated.getDistributionSet().getId()).isEqualTo(ds.getId());
|
||||
// verify updated meta data is the updated value
|
||||
assertThat(distributionSetManagement.getMetadata(ds.getId()).get(knownKey)).isEqualTo(knownUpdateValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -783,37 +751,22 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Queries and loads the metadata related to a given software module.")
|
||||
void findAllDistributionSetMetadataByDsId() {
|
||||
@Description("Queries and loads the metadata related to a given distribution set.")
|
||||
void getMetadata() {
|
||||
// create a DS
|
||||
final DistributionSet ds1 = testdataFactory.createDistributionSet("testDs1");
|
||||
final DistributionSet ds2 = testdataFactory.createDistributionSet("testDs2");
|
||||
|
||||
for (int index = 0; index < quotaManagement.getMaxMetaDataEntriesPerDistributionSet(); index++) {
|
||||
createDistributionSetMetadata(ds1.getId(),
|
||||
new JpaDistributionSetMetadata("key" + index, ds1, "value" + index));
|
||||
insertMetadata("key" + index, "value" + index, ds1);
|
||||
}
|
||||
|
||||
for (int index = 0; index <= quotaManagement.getMaxMetaDataEntriesPerDistributionSet() - 2; index++) {
|
||||
createDistributionSetMetadata(ds2.getId(),
|
||||
new JpaDistributionSetMetadata("key" + index, ds2, "value" + index));
|
||||
insertMetadata("key" + index, "value" + index, ds2);
|
||||
}
|
||||
|
||||
final Page<DistributionSetMetadata> metadataOfDs1 = distributionSetManagement
|
||||
.findMetaDataByDistributionSetId(ds1.getId(), PageRequest.of(0, 100));
|
||||
|
||||
final Page<DistributionSetMetadata> metadataOfDs2 = distributionSetManagement
|
||||
.findMetaDataByDistributionSetId(ds2.getId(), PageRequest.of(0, 100));
|
||||
|
||||
assertThat(metadataOfDs1.getNumberOfElements())
|
||||
.isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet());
|
||||
assertThat(metadataOfDs1.getTotalElements())
|
||||
.isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet());
|
||||
|
||||
assertThat(metadataOfDs2.getNumberOfElements())
|
||||
.isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet() - 1);
|
||||
assertThat(metadataOfDs2.getTotalElements())
|
||||
.isEqualTo(quotaManagement.getMaxMetaDataEntriesPerDistributionSet() - 1);
|
||||
assertThat(distributionSetManagement.getMetadata(ds1.getId())).hasSize(quotaManagement.getMaxMetaDataEntriesPerDistributionSet());
|
||||
assertThat(distributionSetManagement.getMetadata(ds2.getId())).hasSize(quotaManagement.getMaxMetaDataEntriesPerDistributionSet() - 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -897,23 +850,20 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
final String knownUpdateValue = "knownUpdateValue";
|
||||
|
||||
final Long dsId = testdataFactory.createDistributionSet().getId();
|
||||
distributionSetManagement.putMetaData(dsId,
|
||||
singletonList(entityFactory.generateDsMetadata(knownKey1, knownValue)));
|
||||
distributionSetManagement.createMetadata(dsId, Map.of(knownKey1, knownValue));
|
||||
|
||||
distributionSetInvalidationManagement.invalidateDistributionSet(
|
||||
new DistributionSetInvalidation(singletonList(dsId), CancelationType.NONE, false));
|
||||
|
||||
// assert that no new metadata can be created
|
||||
final List<MetaData> metadata = singletonList(entityFactory.generateDsMetadata(knownKey2, knownValue));
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception")
|
||||
.isThrownBy(() -> distributionSetManagement.putMetaData(dsId, metadata));
|
||||
.isThrownBy(() -> distributionSetManagement.createMetadata(dsId, Map.of(knownKey2, knownValue)));
|
||||
|
||||
// assert that an existing metadata can not be updated
|
||||
final MetaData metadata2 = entityFactory.generateDsMetadata(knownKey1, knownUpdateValue);
|
||||
assertThatExceptionOfType(InvalidDistributionSetException.class)
|
||||
.as("Invalid distributionSet should throw an exception")
|
||||
.isThrownBy(() -> distributionSetManagement.updateMetaData(dsId, metadata2));
|
||||
.isThrownBy(() -> distributionSetManagement.updateMetadata(dsId, knownKey1, knownUpdateValue));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1265,6 +1215,11 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
.isComplete(Boolean.FALSE).isDeleted(Boolean.FALSE));
|
||||
}
|
||||
|
||||
private void insertMetadata(final String knownKey, final String knownValue, final DistributionSet distributionSet) {
|
||||
distributionSetManagement.createMetadata(distributionSet.getId(), Map.of(knownKey, knownValue));
|
||||
assertThat(distributionSetManagement.getMetadata(distributionSet.getId()).get(knownKey)).isEqualTo(knownValue);
|
||||
}
|
||||
|
||||
private void assertThatFilterContainsOnlyGivenDistributionSets(final DistributionSetFilterBuilder filterBuilder,
|
||||
final List<DistributionSet> distributionSets) {
|
||||
final int expectedDsSize = distributionSets.size();
|
||||
|
||||
@@ -1,234 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetFields;
|
||||
import org.eclipse.hawkbit.repository.SoftwareModuleFields;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
|
||||
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
|
||||
import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.orm.jpa.vendor.Database;
|
||||
|
||||
@Feature("Component Tests - Repository")
|
||||
@Story("RSQL filter distribution set")
|
||||
@SuppressWarnings("java:S6813") // constructor injects are not possible for test classes
|
||||
class RSQLDistributionSetFieldTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
protected VirtualPropertyReplacer virtualPropertyReplacer;
|
||||
@Autowired
|
||||
protected EntityManager entityManager;
|
||||
|
||||
private DistributionSet ds;
|
||||
private SoftwareModule sm;
|
||||
|
||||
@BeforeEach
|
||||
void setupBeforeTest() {
|
||||
|
||||
sm = testdataFactory.createSoftwareModuleApp("SM");
|
||||
|
||||
ds = testdataFactory.createDistributionSet(Collections.singletonList(sm), "DS");
|
||||
ds = distributionSetManagement.update(entityFactory.distributionSet().update(ds.getId()).description("DS"));
|
||||
createDistributionSetMetadata(ds.getId(), entityFactory.generateDsMetadata("metaKey", "metaValue"));
|
||||
|
||||
DistributionSet ds2 = testdataFactory.createDistributionSets("NewDS", 3).get(0);
|
||||
|
||||
ds2 = distributionSetManagement.update(entityFactory.distributionSet().update(ds2.getId()).description("DS%"));
|
||||
createDistributionSetMetadata(ds2.getId(), entityFactory.generateDsMetadata("metaKey", "value"));
|
||||
|
||||
final DistributionSetTag distSetTag = distributionSetTagManagement
|
||||
.create(entityFactory.tag().create().name("Tag1"));
|
||||
distributionSetTagManagement.create(entityFactory.tag().create().name("Tag2"));
|
||||
distributionSetTagManagement.create(entityFactory.tag().create().name("Tag3"));
|
||||
distributionSetTagManagement.create(entityFactory.tag().create().name("Tag4"));
|
||||
|
||||
distributionSetManagement.assignTag(Arrays.asList(ds.getId(), ds2.getId()), distSetTag.getId());
|
||||
|
||||
final DistributionSet ds3 = distributionSetManagement
|
||||
.create(entityFactory.distributionSet().create().name("test123").version("noDescription"));
|
||||
distributionSetManagement.invalidate(ds3);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by id")
|
||||
void testFilterByParameterId() {
|
||||
assertRSQLQuery(DistributionSetFields.ID.name() + "==" + ds.getId(), 1);
|
||||
assertRSQLQuery(DistributionSetFields.ID.name() + "!=" + ds.getId(), 4);
|
||||
assertRSQLQuery(DistributionSetFields.ID.name() + "==" + -1, 0);
|
||||
assertRSQLQuery(DistributionSetFields.ID.name() + "!=" + -1, 5);
|
||||
|
||||
// Not supported for numbers
|
||||
if (Database.POSTGRESQL.equals(getDatabase())) {
|
||||
return;
|
||||
}
|
||||
|
||||
assertRSQLQuery(DistributionSetFields.ID.name() + "=in=(" + ds.getId() + ",10000000)", 1);
|
||||
assertRSQLQuery(DistributionSetFields.ID.name() + "=out=(" + ds.getId() + ",10000000)", 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by name")
|
||||
void testFilterByParameterName() {
|
||||
assertRSQLQuery(DistributionSetFields.NAME.name() + "==DS", 1);
|
||||
assertRSQLQuery(DistributionSetFields.NAME.name() + "!=DS", 4);
|
||||
assertRSQLQuery(DistributionSetFields.NAME.name() + "==*DS", 4);
|
||||
assertRSQLQuery(DistributionSetFields.NAME.name() + "==noExist*", 0);
|
||||
assertRSQLQuery(DistributionSetFields.NAME.name() + "=in=(DS,notexist)", 1);
|
||||
assertRSQLQuery(DistributionSetFields.NAME.name() + "=out=(DS,notexist)", 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by assigned software module")
|
||||
void testFilterBySoftwareModule() {
|
||||
assertRSQLQuery(DistributionSetFields.MODULE.name() + "." + SoftwareModuleFields.NAME.name() + "==" + sm.getName(), 1);
|
||||
assertRSQLQuery(DistributionSetFields.MODULE.name() + "." + SoftwareModuleFields.ID.name() + "==" + sm.getId(), 1);
|
||||
assertRSQLQuery(DistributionSetFields.MODULE.name() + "." + SoftwareModuleFields.NAME.name() + "==noExist", 0);
|
||||
assertRSQLQuery(DistributionSetFields.MODULE.name() + "." + SoftwareModuleFields.ID.name() + "=in=(" + sm.getId() + ", -1)", 1);
|
||||
assertRSQLQuery(DistributionSetFields.MODULE.name() + "." + SoftwareModuleFields.ID.name() + "=out=(" + sm.getId() + ", -1)", 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by description")
|
||||
void testFilterByParameterDescription() {
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "==''", 1);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "!=''", 4);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "==DS", 1);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "!=DS*", 3);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "!=DS", 4);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "==DS*", 2);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "==DS%", 1);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "==noExist*", 0);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "=in=(DS,notexist)", 1);
|
||||
assertRSQLQuery(DistributionSetFields.DESCRIPTION.name() + "=out=(DS,notexist)", 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by version")
|
||||
void testFilterByParameterVersion() {
|
||||
assertRSQLQuery(DistributionSetFields.VERSION.name() + "==" + TestdataFactory.DEFAULT_VERSION, 1);
|
||||
assertRSQLQuery(DistributionSetFields.VERSION.name() + "!=" + TestdataFactory.DEFAULT_VERSION, 4);
|
||||
assertRSQLQuery(DistributionSetFields.VERSION.name() + "=in=(" + TestdataFactory.DEFAULT_VERSION + ",1.0.0,1.0.1)", 3);
|
||||
assertRSQLQuery(DistributionSetFields.VERSION.name() + "=out=(" + TestdataFactory.DEFAULT_VERSION + ",error)", 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by complete property")
|
||||
void testFilterByAttributeComplete() {
|
||||
assertRSQLQuery(DistributionSetFields.COMPLETE.name() + "==true", 3);
|
||||
final String noExistStar = DistributionSetFields.COMPLETE.name() + "==noExist*";
|
||||
assertThatExceptionOfType(RSQLParameterSyntaxException.class)
|
||||
.isThrownBy(() -> assertRSQLQuery(noExistStar, 0));
|
||||
assertRSQLQuery(DistributionSetFields.COMPLETE.name() + "=in=(true)", 3);
|
||||
assertRSQLQuery(DistributionSetFields.COMPLETE.name() + "=out=(true)", 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by valid property")
|
||||
void testFilterByAttributeValid() {
|
||||
assertRSQLQuery(DistributionSetFields.VALID.name() + "==true", 4);
|
||||
assertRSQLQuery(DistributionSetFields.VALID.name() + "==false", 1);
|
||||
final String rsqlNoExistStar = DistributionSetFields.VALID.name() + "==noExist*";
|
||||
assertThatExceptionOfType(RSQLParameterSyntaxException.class)
|
||||
.isThrownBy(() -> assertRSQLQuery(rsqlNoExistStar, 0));
|
||||
assertRSQLQuery(DistributionSetFields.VALID.name() + "=in=(true)", 4);
|
||||
assertRSQLQuery(DistributionSetFields.VALID.name() + "=out=(true)", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by tag name")
|
||||
void testFilterByTag() {
|
||||
assertRSQLQuery(DistributionSetFields.TAG.name() + "==Tag1", 2);
|
||||
assertRSQLQuery(DistributionSetFields.TAG.name() + "!=Tag1", 3);
|
||||
assertRSQLQuery(DistributionSetFields.TAG.name() + "==T*", 2);
|
||||
assertRSQLQuery(DistributionSetFields.TAG.name() + "==noExist*", 0);
|
||||
assertRSQLQuery(DistributionSetFields.TAG.name() + "=in=(Tag1,notexist)", 2);
|
||||
assertRSQLQuery(DistributionSetFields.TAG.name() + "=out=(null)", 5);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by type key")
|
||||
void testFilterByType() {
|
||||
assertRSQLQuery(DistributionSetFields.TYPE.name() + "==" + TestdataFactory.DS_TYPE_DEFAULT, 4);
|
||||
assertRSQLQuery(DistributionSetFields.TYPE.name() + "==noExist*", 0);
|
||||
assertRSQLQuery(DistributionSetFields.TYPE.name() + "=in=(" + TestdataFactory.DS_TYPE_DEFAULT + ",ecl)", 4);
|
||||
assertRSQLQuery(DistributionSetFields.TYPE.name() + "=out=(" + TestdataFactory.DS_TYPE_DEFAULT + ")", 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set by metadata")
|
||||
void testFilterByMetadata() {
|
||||
createDistributionSetWithMetadata("key.dot", "value.dot");
|
||||
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey==metaValue", 1);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey==*v*", 2);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey==noExist*", 0);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey=in=(metaValue,notexist)", 1);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".metaKey=out=(metaValue,notexist)", 1);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".notExist==metaValue", 0);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".key.dot==value.dot", 1);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".key.dot*==value.dot", 0);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".key.*==value.dot", 0);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".key.==value.dot", 0);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".key*==value.dot", 0);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + ".*==value.dot", 0);
|
||||
assertRSQLQuery(DistributionSetFields.METADATA.name() + "..==value.dot", 0);
|
||||
assertRSQLQueryThrowsException(
|
||||
DistributionSetFields.METADATA.name() + ".==value.dot",
|
||||
RSQLParameterUnsupportedFieldException.class);
|
||||
assertRSQLQueryThrowsException(
|
||||
DistributionSetFields.METADATA.name() + "*==value.dot",
|
||||
RSQLParameterUnsupportedFieldException.class);
|
||||
assertRSQLQueryThrowsException(
|
||||
DistributionSetFields.METADATA.name() + "==value.dot",
|
||||
RSQLParameterUnsupportedFieldException.class);
|
||||
|
||||
}
|
||||
|
||||
private void assertRSQLQuery(final String rsqlParam, final long expectedEntity) {
|
||||
final Page<DistributionSet> find = distributionSetManagement.findByRsql(rsqlParam, PageRequest.of(0, 100));
|
||||
final long countAll = find.getTotalElements();
|
||||
assertThat(find).as("Found entity is should not be null").isNotNull();
|
||||
assertThat(countAll).as("Found entity size is wrong").isEqualTo(expectedEntity);
|
||||
}
|
||||
|
||||
private <T extends Throwable> void assertRSQLQueryThrowsException(final String rsqlParam, final Class<T> expectedException) {
|
||||
assertThatExceptionOfType(expectedException)
|
||||
.isThrownBy(() -> RSQLUtility.validateRsqlFor(
|
||||
rsqlParam, DistributionSetFields.class, JpaDistributionSet.class, virtualPropertyReplacer, entityManager));
|
||||
}
|
||||
|
||||
private DistributionSet createDistributionSetWithMetadata(final String metadataKeyName, final String metadataValue) {
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
|
||||
createDistributionSetMetadata(distributionSet.getId(), entityFactory.generateDsMetadata(metadataKeyName, metadataValue));
|
||||
return distributionSet;
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2015 Bosch Software Innovations GmbH and others
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.rsql;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import io.qameta.allure.Description;
|
||||
import io.qameta.allure.Feature;
|
||||
import io.qameta.allure.Story;
|
||||
import org.eclipse.hawkbit.repository.DistributionSetMetadataFields;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSetMetadata;
|
||||
import org.eclipse.hawkbit.repository.model.MetaData;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
|
||||
@Feature("Component Tests - Repository")
|
||||
@Story("RSQL filter distribution set metadata")
|
||||
class RSQLDistributionSetMetadataFieldsTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
private Long distributionSetId;
|
||||
|
||||
@BeforeEach
|
||||
void setupBeforeTest() {
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet("DS");
|
||||
distributionSetId = distributionSet.getId();
|
||||
|
||||
final List<MetaData> metadata = new ArrayList<>(5);
|
||||
for (int i = 0; i < 5; i++) {
|
||||
metadata.add(entityFactory.generateDsMetadata("" + i, "" + i));
|
||||
}
|
||||
|
||||
distributionSetManagement.putMetaData(distributionSetId, metadata);
|
||||
|
||||
distributionSetManagement.putMetaData(distributionSetId,
|
||||
Arrays.asList(entityFactory.generateDsMetadata("emptyValueTest", null)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set metadata by key")
|
||||
void testFilterByParameterKey() {
|
||||
assertRSQLQuery(DistributionSetMetadataFields.KEY.name() + "==1", 1);
|
||||
assertRSQLQuery(DistributionSetMetadataFields.KEY.name() + "!=1", 5);
|
||||
assertRSQLQuery(DistributionSetMetadataFields.KEY.name() + "=in=(1,2)", 2);
|
||||
assertRSQLQuery(DistributionSetMetadataFields.KEY.name() + "=out=(1,2)", 4);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Description("Test filter distribution set metadata by value")
|
||||
void testFilterByParameterValue() {
|
||||
assertRSQLQuery(DistributionSetMetadataFields.VALUE.name() + "==''", 1);
|
||||
assertRSQLQuery(DistributionSetMetadataFields.VALUE.name() + "!=''", 5);
|
||||
assertRSQLQuery(DistributionSetMetadataFields.VALUE.name() + "==1", 1);
|
||||
assertRSQLQuery(DistributionSetMetadataFields.VALUE.name() + "!=1", 5);
|
||||
assertRSQLQuery(DistributionSetMetadataFields.VALUE.name() + "=in=(1,2)", 2);
|
||||
assertRSQLQuery(DistributionSetMetadataFields.VALUE.name() + "=out=(1,2)", 4);
|
||||
}
|
||||
|
||||
private void assertRSQLQuery(final String rsqlParam, final long expectedEntities) {
|
||||
|
||||
final Page<DistributionSetMetadata> findEnitity = distributionSetManagement
|
||||
.findMetaDataByDistributionSetIdAndRsql(distributionSetId, rsqlParam, PageRequest.of(0, 100));
|
||||
final long countAllEntities = findEnitity.getTotalElements();
|
||||
assertThat(findEnitity).isNotNull();
|
||||
assertThat(countAllEntities).isEqualTo(expectedEntities);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user