diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutExecutor.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutExecutor.java
index e027b742f..3f386e013 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutExecutor.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/RolloutExecutor.java
@@ -22,6 +22,9 @@ import org.springframework.security.access.prepost.PreAuthorize;
public interface RolloutExecutor {
/**
+ * This execution should only be triggered by the system as a background job and
+ * not available via API.
+ *
* Process rollout based on its current {@link Rollout#getStatus()}.
*
* For {@link RolloutStatus#CREATING} that means creating the
@@ -29,9 +32,9 @@ public interface RolloutExecutor {
* {@link RolloutStatus#READY}.
*
* For {@link RolloutStatus#READY} that means switching to
- * {@link RolloutStatus#STARTING} if the {@link Rollout#getStartAt()} is set
- * and time of calling this method is beyond this point in time. This auto
- * start mechanism is optional. Call {@link #start(Long)} otherwise.
+ * {@link RolloutStatus#STARTING} if the {@link Rollout#getStartAt()} is set and
+ * time of calling this method is beyond this point in time. This auto start
+ * mechanism is optional. Call {@link #start(Long)} otherwise.
*
* For {@link RolloutStatus#STARTING} that means starting the first
* {@link RolloutGroup}s in line and when finished switch to
@@ -45,8 +48,7 @@ public interface RolloutExecutor {
* rollout was already {@link RolloutStatus#RUNNING} which results in status
* change {@link RolloutStatus#DELETED} or hard delete from the persistence
* otherwise.
- *
*/
- @PreAuthorize(SpringEvalExpressions.IS_SYSTEM_CODE)
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_CREATE)
void execute(Rollout rollout);
}
diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java
index 7b1de49f3..ecde4b63d 100644
--- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java
+++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TargetManagement.java
@@ -69,9 +69,11 @@ public interface TargetManagement {
/**
* Counts number of targets with the given distribution set assigned.
*
- * @param distributionSetId to search for
+ * @param distributionSetId
+ * to search for
* @return number of found {@link Target}s.
- * @throws EntityNotFoundException if distribution set with given ID does not exist
+ * @throws EntityNotFoundException
+ * if distribution set with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
@@ -81,8 +83,8 @@ public interface TargetManagement {
* Count {@link Target}s for all the given filter parameters.
*
* @param filterParams
- * the filters to apply; only filters are enabled that have
- * non-null value; filters are AND-gated
+ * the filters to apply; only filters are enabled that have non-null
+ * value; filters are AND-gated
*
* @return the found number {@link Target}s
*
@@ -95,21 +97,25 @@ public interface TargetManagement {
/**
* Get the count of targets with the given distribution set id.
*
- * @param distributionSetId to search for
+ * @param distributionSetId
+ * to search for
* @return number of found {@link Target}s.
- * @throws EntityNotFoundException if distribution set with given ID does not exist
+ * @throws EntityNotFoundException
+ * if distribution set with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
long countByInstalledDistributionSet(long distributionSetId);
/**
- * Checks if there is already a {@link Target} that has the given
- * distribution set Id assigned or installed.
+ * Checks if there is already a {@link Target} that has the given distribution
+ * set Id assigned or installed.
*
- * @param distributionSetId to search for
+ * @param distributionSetId
+ * to search for
* @return true if a {@link Target} exists.
- * @throws EntityNotFoundException if distribution set with given ID does not exist
+ * @throws EntityNotFoundException
+ * if distribution set with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
@@ -126,23 +132,47 @@ public interface TargetManagement {
long countByRsql(@NotEmpty String rsqlParam);
/**
- * Count all targets for given {@link TargetFilterQuery} and that are
- * compatible with the passed {@link DistributionSetType}.
+ * Count {@link TargetFilterQuery}s for given target filter query with UPDATE permission.
*
* @param rsqlParam
* filter definition in RSQL syntax
- * @param distributionSetId
+ * @return the found number of {@link Target}s
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
+ long countByRsqlAndUpdatable(@NotEmpty String rsqlParam);
+
+ /**
+ * Count all targets for given {@link TargetFilterQuery} and that are compatible
+ * with the passed {@link DistributionSetType}.
+ *
+ * @param rsqlParam
+ * filter definition in RSQL syntax
+ * @param distributionSetIdTypeId
* ID of the {@link DistributionSetType} the targets need to be
* compatible with
* @return the found number of{@link Target}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
- long countByRsqlAndCompatible(@NotEmpty String rsqlParam, @NotNull Long distributionSetId);
+ long countByRsqlAndCompatible(@NotEmpty String rsqlParam, @NotNull Long distributionSetIdTypeId);
/**
- * Count all targets with failed actions for specific Rollout
- * and that are compatible with the passed {@link DistributionSetType}
- * and created after given timestamp
+ * Count all targets for given {@link TargetFilterQuery} and that are compatible
+ * with the passed {@link DistributionSetType} and UPDATE permission.
+ *
+ * @param rsqlParam
+ * filter definition in RSQL syntax
+ * @param distributionSetIdTypeId
+ * ID of the {@link DistributionSetType} the targets need to be
+ * compatible with
+ * @return the found number of{@link Target}s
+ */
+ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
+ long countByRsqlAndCompatibleAndUpdatable(@NotEmpty String rsqlParam, @NotNull Long distributionSetIdTypeId);
+
+ /**
+ * Count all targets with failed actions for specific Rollout and that are
+ * compatible with the passed {@link DistributionSetType} and created after
+ * given timestamp
*
* @param rolloutId
* rolloutId of the rollout to be retried.
@@ -185,18 +215,17 @@ public interface TargetManagement {
* @throws EntityAlreadyExistsException
* given target already exists.
* @throws ConstraintViolationException
- * if fields are not filled as specified. Check
- * {@link TargetCreate} for field constraints.
+ * if fields are not filled as specified. Check {@link TargetCreate}
+ * for field constraints.
*
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET)
Target create(@NotNull @Valid TargetCreate create);
/**
- * creates multiple {@link Target}s. If the given {@link Target}s
- * already exists in the DB an {@link EntityAlreadyExistsException} is
- * thrown. {@link Target}s contain all objects of the parameter targets,
- * including duplicates.
+ * creates multiple {@link Target}s. If the given {@link Target}s already exists
+ * in the DB an {@link EntityAlreadyExistsException} is thrown. {@link Target}s
+ * contain all objects of the parameter targets, including duplicates.
*
* @param creates
* to be created.
@@ -205,8 +234,8 @@ public interface TargetManagement {
* @throws EntityAlreadyExistsException
* of one of the given targets already exist.
* @throws ConstraintViolationException
- * if fields are not filled as specified. Check
- * {@link TargetCreate} for field constraints.
+ * if fields are not filled as specified. Check {@link TargetCreate}
+ * for field constraints.
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET)
List create(@NotNull @Valid Collection creates);
@@ -253,12 +282,12 @@ public interface TargetManagement {
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
Slice findByTargetFilterQueryAndNonDSAndCompatibleAndUpdatable(@NotNull Pageable pageRequest,
- long distributionSetId, @NotNull String rsqlParam);
+ long distributionSetId, @NotNull String rsqlParam);
/**
- * Counts all targets for all the given parameter {@link TargetFilterQuery}
- * and that don't have the specified distribution set in their action
- * history and are compatible with the passed {@link DistributionSetType}.
+ * Counts all targets for all the given parameter {@link TargetFilterQuery} and
+ * that don't have the specified distribution set in their action history and
+ * are compatible with the passed {@link DistributionSetType}.
*
* @param distributionSetId
* id of the {@link DistributionSet}
@@ -273,9 +302,9 @@ public interface TargetManagement {
long countByRsqlAndNonDSAndCompatibleAndUpdatable(long distributionSetId, @NotNull String rsqlParam);
/**
- * Finds all targets for all the given parameter {@link TargetFilterQuery}
- * and that are not assigned to one of the {@link RolloutGroup}s and are
- * compatible with the passed {@link DistributionSetType}.
+ * Finds all targets for all the given parameter {@link TargetFilterQuery} and
+ * that are not assigned to one of the {@link RolloutGroup}s and are compatible
+ * with the passed {@link DistributionSetType}.
*
* @param pageRequest
* the pageRequest to enhance the query for paging and sorting
@@ -284,8 +313,8 @@ public interface TargetManagement {
* @param rsqlParam
* filter definition in RSQL syntax
* @param distributionSetType
- * type of the {@link DistributionSet} the targets must be
- * compatible withs
+ * type of the {@link DistributionSet} the targets must be compatible
+ * withs
* @return a page of the found {@link Target}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
@@ -294,9 +323,9 @@ public interface TargetManagement {
@NotNull DistributionSetType distributionSetType);
/**
- * Finds all targets with failed actions for specific Rollout
- * and that are not assigned to one of the retried {@link RolloutGroup}s and are
- * compatible with the passed {@link DistributionSetType}.
+ * Finds all targets with failed actions for specific Rollout and that are not
+ * assigned to one of the retried {@link RolloutGroup}s and are compatible with
+ * the passed {@link DistributionSetType}.
*
* @param pageRequest
* the pageRequest to enhance the query for paging and sorting
@@ -308,12 +337,12 @@ public interface TargetManagement {
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET)
Slice findByFailedRolloutAndNotInRolloutGroups(@NotNull Pageable pageRequest,
- @NotEmpty Collection groups, @NotNull String rolloutId);
+ @NotEmpty Collection groups, @NotNull String rolloutId);
/**
- * Counts all targets for all the given parameter {@link TargetFilterQuery}
- * and that are not assigned to one of the {@link RolloutGroup}s and are
- * compatible with the passed {@link DistributionSetType}.
+ * Counts all targets for all the given parameter {@link TargetFilterQuery} and
+ * that are not assigned to one of the {@link RolloutGroup}s and are compatible
+ * with the passed {@link DistributionSetType}.
*
* @param groups
* the list of {@link RolloutGroup}s
@@ -329,9 +358,9 @@ public interface TargetManagement {
@NotNull String rsqlParam, @NotNull DistributionSetType distributionSetType);
/**
- * Counts all targets with failed actions for specific Rollout
- * and that are not assigned to one of the {@link RolloutGroup}s and are
- * compatible with the passed {@link DistributionSetType}.
+ * Counts all targets with failed actions for specific Rollout and that are not
+ * assigned to one of the {@link RolloutGroup}s and are compatible with the
+ * passed {@link DistributionSetType}.
*
* @param groups
* the list of {@link RolloutGroup}s
@@ -343,8 +372,8 @@ public interface TargetManagement {
long countByFailedRolloutAndNotInRolloutGroups(@NotEmpty Collection groups, @NotNull String rolloutId);
/**
- * Finds all targets of the provided {@link RolloutGroup} that have no
- * Action for the RolloutGroup.
+ * Finds all targets of the provided {@link RolloutGroup} that have no Action
+ * for the RolloutGroup.
*
* @param pageRequest
* the pageRequest to enhance the query for paging and sorting
@@ -376,8 +405,8 @@ public interface TargetManagement {
Page findByAssignedDistributionSet(@NotNull Pageable pageReq, long distributionSetId);
/**
- * Retrieves {@link Target}s by the assigned {@link DistributionSet}
- * possible including additional filtering based on the given {@code spec}.
+ * Retrieves {@link Target}s by the assigned {@link DistributionSet} possible
+ * including additional filtering based on the given {@code spec}.
*
* @param pageReq
* page parameter
@@ -420,14 +449,14 @@ public interface TargetManagement {
Optional getByControllerID(@NotEmpty String controllerId);
/**
- * Filter {@link Target}s for all the given parameters. If all parameters
- * except pageable are null, all available {@link Target}s are returned.
+ * Filter {@link Target}s for all the given parameters. If all parameters except
+ * pageable are null, all available {@link Target}s are returned.
*
* @param pageable
* page parameters
* @param filterParams
- * the filters to apply; only filters are enabled that have
- * non-null value; filters are AND-gated
+ * the filters to apply; only filters are enabled that have non-null
+ * value; filters are AND-gated
*
* @return the found {@link Target}s
*
@@ -454,8 +483,8 @@ public interface TargetManagement {
Page findByInstalledDistributionSet(@NotNull Pageable pageReq, long distributionSetId);
/**
- * retrieves {@link Target}s by the installed {@link DistributionSet}
- * including additional filtering based on the given {@code spec}.
+ * retrieves {@link Target}s by the installed {@link DistributionSet} including
+ * additional filtering based on the given {@code spec}.
*
* @param pageReq
* page parameter
@@ -480,8 +509,7 @@ public interface TargetManagement {
@NotNull String rsqlParam);
/**
- * Retrieves the {@link Target} which have a certain
- * {@link TargetUpdateStatus}.
+ * Retrieves the {@link Target} which have a certain {@link TargetUpdateStatus}.
*
* @param pageable
* page parameter
@@ -629,9 +657,9 @@ public interface TargetManagement {
/**
* Initiates {@link TargetType} assignment to given {@link Target}s. If some
- * targets in the list have the {@link TargetType} not yet assigned, they
- * will get assigned. If all targets are already of that type, there will be
- * no un-assignment.
+ * targets in the list have the {@link TargetType} not yet assigned, they will
+ * get assigned. If all targets are already of that type, there will be no
+ * un-assignment.
*
* @param controllerIds
* to set the type to
@@ -647,8 +675,8 @@ public interface TargetManagement {
TargetTypeAssignmentResult assignType(@NotEmpty Collection controllerIds, @NotNull Long typeId);
/**
- * Initiates {@link TargetType} un-assignment to given {@link Target}s. The
- * type of the targets will be set to {@code null}
+ * Initiates {@link TargetType} un-assignment to given {@link Target}s. The type
+ * of the targets will be set to {@code null}
*
* @param controllerIds
* to remove the type from
@@ -710,8 +738,8 @@ public interface TargetManagement {
* @throws EntityNotFoundException
* if given target does not exist
* @throws ConstraintViolationException
- * if fields are not filled as specified. Check
- * {@link TargetUpdate} for field constraints.
+ * if fields are not filled as specified. Check {@link TargetUpdate}
+ * for field constraints.
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET)
Target update(@NotNull @Valid TargetUpdate update);
@@ -797,30 +825,29 @@ public interface TargetManagement {
boolean existsByControllerId(@NotEmpty String controllerId);
/**
- * Verify if a target matches a specific target filter query, does not have
- * a specific DS already assigned and is compatible with it.
+ * Verify if a target matches a specific target filter query, does not have a
+ * specific DS already assigned and is compatible with it.
*
* @param controllerId
* of the {@link org.eclipse.hawkbit.repository.model.Target} to
* check
* @param distributionSetId
* of the
- * {@link org.eclipse.hawkbit.repository.model.DistributionSet}
- * to consider
+ * {@link org.eclipse.hawkbit.repository.model.DistributionSet} to
+ * consider
* @param targetFilterQuery
* to execute
* @return true if it matches
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET)
- boolean isTargetMatchingQueryAndDSNotAssignedAndCompatible(@NotNull String controllerId, long distributionSetId,
- @NotNull String targetFilterQuery);
+ boolean isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(@NotNull String controllerId,
+ long distributionSetId, @NotNull String targetFilterQuery);
/**
* Creates a list of target meta data entries.
*
* @param controllerId
- * {@link Target} controller id the metadata has to be created
- * for
+ * {@link Target} controller id the metadata has to be created for
* @param metadata
* the meta data entries to create or update
* @return the updated or created target metadata entries
@@ -829,12 +856,12 @@ public interface TargetManagement {
* if given target does not exist
*
* @throws EntityAlreadyExistsException
- * in case one of the metadata entry already exists for the
- * specific key
+ * in case one of the metadata entry already exists for the specific
+ * key
*
* @throws AssignmentQuotaExceededException
- * if the maximum number of {@link MetaData} entries is exceeded
- * for the addressed {@link Target}
+ * if the maximum number of {@link MetaData} entries is exceeded for
+ * the addressed {@link Target}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
List createMetaData(@NotEmpty String controllerId, @NotEmpty Collection metadata);
@@ -928,15 +955,13 @@ public interface TargetManagement {
* Updates a target meta data value if corresponding entry exists.
*
* @param controllerId
- * {@link Target} controller id of the metadata entry to be
- * updated
+ * {@link Target} controller id of the metadata entry to be updated
* @param metadata
* meta data entry to be updated
* @return the updated meta data entry
*
* @throws EntityNotFoundException
- * in case the metadata entry does not exist and cannot be
- * updated
+ * in case the metadata entry does not exist and cannot be updated
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
TargetMetadata updateMetadata(@NotEmpty String controllerId, @NotNull MetaData metadata);
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaManagementHelper.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaManagementHelper.java
index 63fffd5f6..a2b6d6548 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaManagementHelper.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaManagementHelper.java
@@ -15,7 +15,10 @@ import java.util.Optional;
import javax.persistence.EntityManager;
+import org.eclipse.hawkbit.repository.jpa.acm.AccessController;
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity;
+import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaTenantAwareBaseEntity;
+import org.eclipse.hawkbit.repository.jpa.repository.BaseEntityRepository;
import org.eclipse.hawkbit.repository.jpa.repository.NoCountSliceRepository;
import org.eclipse.hawkbit.repository.jpa.specifications.SpecificationsBuilder;
import org.springframework.data.domain.Page;
@@ -26,6 +29,7 @@ import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.CrudRepository;
import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
@@ -54,6 +58,9 @@ public final class JpaManagementHelper {
}
public static Specification combineWithAnd(final List> specList) {
+ if (ObjectUtils.isEmpty(specList)) {
+ return Specification.where(null);
+ }
return specList.size() == 1 ? specList.get(0) : SpecificationsBuilder.combineWithAnd(specList);
}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java
index 5f6ab6bb3..168527308 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaRolloutExecutor.java
@@ -520,10 +520,10 @@ public class JpaRolloutExecutor implements RolloutExecutor {
final String baseFilter = RolloutHelper.getTargetFilterQuery(rollout);
final String groupTargetFilter;
- if (StringUtils.isEmpty(group.getTargetFilterQuery())) {
- groupTargetFilter = baseFilter;
- } else {
+ if (StringUtils.hasText(group.getTargetFilterQuery())) {
groupTargetFilter = baseFilter + ";" + group.getTargetFilterQuery();
+ } else {
+ groupTargetFilter = baseFilter;
}
final List readyGroups = RolloutHelper.getGroupsByStatusIncludingGroup(rollout.getRolloutGroups(),
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java
index 06a9e01ba..cd5ce9836 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/RepositoryApplicationConfiguration.java
@@ -101,6 +101,7 @@ import org.eclipse.hawkbit.repository.jpa.management.JpaTargetTagManagement;
import org.eclipse.hawkbit.repository.jpa.management.JpaTargetTypeManagement;
import org.eclipse.hawkbit.repository.jpa.management.JpaTenantConfigurationManagement;
import org.eclipse.hawkbit.repository.jpa.management.JpaTenantStatsManagement;
+import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
import org.eclipse.hawkbit.repository.jpa.model.JpaArtifact;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
@@ -1038,13 +1039,12 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
final DistributionSetManagement distributionSetManagement, final RolloutManagement rolloutManagement,
final DeploymentManagement deploymentManagement,
final TargetFilterQueryManagement targetFilterQueryManagement, final ActionRepository actionRepository,
- final PlatformTransactionManager txManager,
- final RepositoryProperties repositoryProperties, final TenantAware tenantAware,
- final LockRegistry lockRegistry) {
+ final PlatformTransactionManager txManager, final RepositoryProperties repositoryProperties,
+ final TenantAware tenantAware, final LockRegistry lockRegistry,
+ final SystemSecurityContext systemSecurityContext) {
return new JpaDistributionSetInvalidationManagement(distributionSetManagement, rolloutManagement,
- deploymentManagement, targetFilterQueryManagement, actionRepository,
- txManager, repositoryProperties, tenantAware,
- lockRegistry);
+ deploymentManagement, targetFilterQueryManagement, actionRepository, txManager, repositoryProperties,
+ tenantAware, lockRegistry, systemSecurityContext);
}
/**
@@ -1080,10 +1080,12 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
@Autowired(required = false) final AccessController distributionSetTypeAccessController,
@Autowired(required = false) final AccessController distributionSetAccessController,
@Autowired(required = false) final AccessController targetTypeAccessControlManager,
- @Autowired(required = false) final AccessController targetAccessControlManager) {
+ @Autowired(required = false) final AccessController targetAccessControlManager,
+ @Autowired(required = false) final AccessController actionAccessController) {
return new BeanPostProcessor() {
@Override
- public Object postProcessAfterInitialization(@NonNull final Object bean, @NonNull final String beanName) throws BeansException {
+ public Object postProcessAfterInitialization(@NonNull final Object bean, @NonNull final String beanName)
+ throws BeansException {
if (bean instanceof LocalArtifactRepository repo) {
return repo.withACM(artifactAccessController);
} else if (bean instanceof SoftwareModuleTypeRepository repo) {
@@ -1098,6 +1100,8 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
return repo.withACM(targetTypeAccessControlManager);
} else if (bean instanceof TargetRepository repo) {
return repo.withACM(targetAccessControlManager);
+ } else if (bean instanceof ActionRepository repo) {
+ return repo.withACM(actionAccessController);
}
return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignChecker.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignChecker.java
index 0293666d6..7b3c0c746 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignChecker.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignChecker.java
@@ -119,7 +119,7 @@ public class AutoAssignChecker extends AbstractAutoAssignExecutor {
LOGGER.debug("Auto assign check call for tenant {} and target filter query id {} for device {} started",
getContextAware().getCurrentTenant(), targetFilterQuery.getId(), controllerId);
try {
- final boolean controllerIdMatches = targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatible(
+ final boolean controllerIdMatches = targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(
controllerId, targetFilterQuery.getAutoAssignDistributionSet().getId(),
targetFilterQuery.getQuery());
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java
index 7aa1c6f47..0cc67fd99 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaControllerManagement.java
@@ -308,7 +308,6 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont
throwExceptionIfTargetDoesNotExist(controllerId);
throwExceptionIfSoftwareModuleDoesNotExist(moduleId);
- // TODO AC - REVIEW
// it used to perform 3-table join query
// @Query("Select a from JpaAction a join a.distributionSet ds join ds.modules modul where a.target.controllerId = :target and modul.id = :module order by a.id desc")
// final List actions = actionRepository.findActionByTargetAndSoftwareModule(controllerId, moduleId);
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java
index 5fcc2e5bd..eca4eb209 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDeploymentManagement.java
@@ -158,14 +158,14 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
private final RetryTemplate retryTemplate;
public JpaDeploymentManagement(final EntityManager entityManager, final ActionRepository actionRepository,
- final DistributionSetManagement distributionSetManagement,
- final DistributionSetRepository distributionSetRepository, final TargetRepository targetRepository,
- final ActionStatusRepository actionStatusRepository, final AuditorAware auditorProvider,
- final EventPublisherHolder eventPublisherHolder, final AfterTransactionCommitExecutor afterCommit,
- final VirtualPropertyReplacer virtualPropertyReplacer, final PlatformTransactionManager txManager,
- final TenantConfigurationManagement tenantConfigurationManagement, final QuotaManagement quotaManagement,
- final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware, final Database database,
- final RepositoryProperties repositoryProperties) {
+ final DistributionSetManagement distributionSetManagement,
+ final DistributionSetRepository distributionSetRepository, final TargetRepository targetRepository,
+ final ActionStatusRepository actionStatusRepository, final AuditorAware auditorProvider,
+ final EventPublisherHolder eventPublisherHolder, final AfterTransactionCommitExecutor afterCommit,
+ final VirtualPropertyReplacer virtualPropertyReplacer, final PlatformTransactionManager txManager,
+ final TenantConfigurationManagement tenantConfigurationManagement, final QuotaManagement quotaManagement,
+ final SystemSecurityContext systemSecurityContext, final TenantAware tenantAware, final Database database,
+ final RepositoryProperties repositoryProperties) {
super(actionRepository, actionStatusRepository, quotaManagement, repositoryProperties);
this.entityManager = entityManager;
this.distributionSetRepository = distributionSetRepository;
@@ -240,10 +240,10 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
deploymentRequests = deploymentRequests.stream().distinct().toList();
checkForMultiAssignment(deploymentRequests);
checkQuotaForAssignment(deploymentRequests);
- // validates READ access to deployment sets, throws exception if deployment set is not accessible
+ // validates READ access to deployment sets, throws exception if deployment set
+ // is not accessible
checkForTargetTypeCompatibility(deploymentRequests);
// filters only targets that are updatable
- // TODO - should assignments that contain non-existing/allowed devices be allowed anyway?
return filterByTargetUpdatable(deploymentRequests);
}
@@ -313,16 +313,12 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
}
private List filterByTargetUpdatable(final List deploymentRequests) {
- final List controllerIds =
- deploymentRequests.stream()
- .map(DeploymentRequest::getControllerId)
- .distinct()
- .toList();
+ final List controllerIds = deploymentRequests.stream().map(DeploymentRequest::getControllerId)
+ .distinct().toList();
- final List found = targetRepository.findAll(
- AccessController.Operation.UPDATE,
- TargetSpecifications.hasControllerIdIn(controllerIds)
- ).stream().map(JpaTarget::getControllerId).toList();
+ final List found = targetRepository
+ .findAll(AccessController.Operation.UPDATE, TargetSpecifications.hasControllerIdIn(controllerIds))
+ .stream().map(JpaTarget::getControllerId).toList();
if (found.size() != controllerIds.size()) {
return deploymentRequests.stream()
.filter(deploymentRequest -> found.contains(deploymentRequest.getControllerId())).toList();
@@ -384,8 +380,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
final List existingTargetIds = Lists.partition(providedTargetIds, Constants.MAX_ENTRIES_IN_STATEMENT)
.stream()
- .map(ids -> targetRepository.findAll(
- AccessController.Operation.UPDATE, TargetSpecifications.hasControllerIdIn(ids)))
+ .map(ids -> targetRepository.findAll(AccessController.Operation.UPDATE,
+ TargetSpecifications.hasControllerIdIn(ids)))
.flatMap(List::stream).map(JpaTarget::getControllerId).toList();
final List targetEntities = assignmentStrategy.findTargetsForAssignment(existingTargetIds,
@@ -490,9 +486,10 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
public void cancelInactiveScheduledActionsForTargets(final List targetIds) {
if (!isMultiAssignmentsEnabled()) {
targetRepository.getAccessController().ifPresent(v -> {
- if (targetRepository.count(AccessController.Operation.UPDATE, TargetSpecifications.hasIdIn(targetIds)) != targetIds.size()) {
- throw new EntityNotFoundException(Target.class, targetIds);
- }
+ if (targetRepository.count(AccessController.Operation.UPDATE,
+ TargetSpecifications.hasIdIn(targetIds)) != targetIds.size()) {
+ throw new EntityNotFoundException(Target.class, targetIds);
+ }
});
actionRepository.switchStatus(Status.CANCELED, targetIds, false, Status.SCHEDULED);
} else {
@@ -776,24 +773,21 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override
public Optional findAction(final long actionId) {
- return actionRepository
- .findById(actionId)
+ return actionRepository.findById(actionId)
.filter(action -> targetRepository.exists(TargetSpecifications.hasId(action.getTarget().getId())))
.map(JpaAction.class::cast);
}
@Override
public Optional findActionWithDetails(final long actionId) {
- return actionRepository
- .findWithDetailsById(actionId)
+ return actionRepository.findWithDetailsById(actionId)
.filter(action -> targetRepository.exists(TargetSpecifications.hasId(action.getTarget().getId())));
}
@Override
public Slice findActionsByTarget(final String controllerId, final Pageable pageable) {
assertTargetReadAllowed(controllerId);
- return actionRepository
- .findAll(ActionSpecifications.byTargetControllerId(controllerId), pageable)
+ return actionRepository.findAll(ActionSpecifications.byTargetControllerId(controllerId), pageable)
.map(Action.class::cast);
}
@@ -853,8 +847,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Retryable(include = {
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public Action forceTargetAction(final long actionId) {
- final JpaAction action = actionRepository.findById(actionId)
- .map(this::assertTargetUpdateAllowed)
+ final JpaAction action = actionRepository.findById(actionId).map(this::assertTargetUpdateAllowed)
.orElseThrow(() -> new EntityNotFoundException(Action.class, actionId));
if (!action.isForcedOrTimeForced()) {
@@ -878,7 +871,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
return actionStatusRepository.countByActionId(actionId);
}
- // action is already got and there are checked read permissions - do not check permissions
+ // action is already got and there are checked read permissions - do not check
+ // permissions
// and UI which is to be removed
@Override
public Page findMessagesByActionStatusId(final Pageable pageable, final long actionStatusId) {
@@ -921,15 +915,11 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
return JpaManagementHelper.countBySpec(actionRepository, specList);
}
- // TODO - return via Mgmt API all actions (event for targets the use has no access - check if should and could
- // be limited
@Override
public Slice findActionsAll(final Pageable pageable) {
return JpaManagementHelper.findAllWithoutCountBySpec(actionRepository, pageable, null);
}
- // TODO - return via Mgmt API all actions (event for targets the use has no access - check if should and could
- // be limited
@Override
public Slice findActions(final String rsqlParam, final Pageable pageable) {
final List> specList = List.of(
@@ -983,8 +973,8 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
public boolean hasPendingCancellations(final Long targetId) {
// target access checked in assertTargetReadAllowed
assertTargetReadAllowed(targetId);
- return actionRepository.exists(
- ActionSpecifications.byTargetIdAndIsActiveAndStatus(targetId, Action.Status.CANCELING));
+ return actionRepository
+ .exists(ActionSpecifications.byTargetIdAndIsActiveAndStatus(targetId, Action.Status.CANCELING));
}
private static String getQueryForDeleteActionsByStatusAndLastModifiedBeforeString(final Database database) {
@@ -1039,29 +1029,33 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override
@Transactional
- public void cancelActionsForDistributionSet(
- final CancelationType cancelationType, final DistributionSet distributionSet) {
- actionRepository
- .findAll(ActionSpecifications.byDistributionSetIdAndActiveAndStatusIsNot(distributionSet.getId(), Status.CANCELING))
+ public void cancelActionsForDistributionSet(final CancelationType cancelationType,
+ final DistributionSet distributionSet) {
+ actionRepository.findAll(ActionSpecifications
+ .byDistributionSetIdAndActiveAndStatusIsNot(distributionSet.getId(), Status.CANCELING))
.forEach(action -> {
try {
assertTargetUpdateAllowed(action);
cancelAction(action.getId());
LOG.debug("Action {} canceled", action.getId());
} catch (final InsufficientPermissionException e) {
- // no access - skip it
+ LOG.trace("Could not cancel action {} due to insufficient permissions.", action.getId(), e);
+ } catch (final EntityNotFoundException e) {
+ LOG.trace("Could not cancel action {} due to entity not found exception.", action.getId(), e);
}
});
if (cancelationType == CancelationType.FORCE) {
- actionRepository
- .findAll(ActionSpecifications.byDistributionSetIdAndActive(distributionSet.getId()))
+ actionRepository.findAll(ActionSpecifications.byDistributionSetIdAndActive(distributionSet.getId()))
.forEach(action -> {
try {
assertTargetUpdateAllowed(action);
forceQuitAction(action.getId());
LOG.debug("Action {} force canceled", action.getId());
} catch (final InsufficientPermissionException e) {
- // no access - skip it
+ LOG.trace("Could not cancel action {} due to insufficient permissions.", action.getId(), e);
+ } catch (final EntityNotFoundException e) {
+ LOG.trace("Could not cancel action {} due to entity not found exception.", action.getId(),
+ e);
}
});
}
@@ -1080,9 +1074,12 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
}
private JpaAction assertTargetUpdateAllowed(final JpaAction action) {
- if (!targetRepository.exists(TargetSpecifications.hasId(action.getTarget().getId()))) {
+ targetRepository.findOne(TargetSpecifications.hasId(action.getTarget().getId())).ifPresentOrElse(target -> {
+ targetRepository.getAccessController()
+ .ifPresent(acm -> acm.assertOperationAllowed(AccessController.Operation.UPDATE, target));
+ }, () -> {
throw new EntityNotFoundException(Action.class, action);
- }
+ });
return action;
}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetInvalidationManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetInvalidationManagement.java
index 53af6acb0..36511c81b 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetInvalidationManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetInvalidationManagement.java
@@ -27,6 +27,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation;
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation.CancelationType;
import org.eclipse.hawkbit.repository.model.DistributionSetInvalidationCount;
+import org.eclipse.hawkbit.security.SystemSecurityContext;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -50,13 +51,14 @@ public class JpaDistributionSetInvalidationManagement implements DistributionSet
private final RepositoryProperties repositoryProperties;
private final TenantAware tenantAware;
private final LockRegistry lockRegistry;
+ private final SystemSecurityContext systemSecurityContext;
public JpaDistributionSetInvalidationManagement(final DistributionSetManagement distributionSetManagement,
final RolloutManagement rolloutManagement, final DeploymentManagement deploymentManagement,
final TargetFilterQueryManagement targetFilterQueryManagement, final ActionRepository actionRepository,
- final PlatformTransactionManager txManager,
- final RepositoryProperties repositoryProperties, final TenantAware tenantAware,
- final LockRegistry lockRegistry) {
+ final PlatformTransactionManager txManager, final RepositoryProperties repositoryProperties,
+ final TenantAware tenantAware, final LockRegistry lockRegistry,
+ final SystemSecurityContext systemSecurityContext) {
this.distributionSetManagement = distributionSetManagement;
this.rolloutManagement = rolloutManagement;
this.deploymentManagement = deploymentManagement;
@@ -66,13 +68,13 @@ public class JpaDistributionSetInvalidationManagement implements DistributionSet
this.repositoryProperties = repositoryProperties;
this.tenantAware = tenantAware;
this.lockRegistry = lockRegistry;
+ this.systemSecurityContext = systemSecurityContext;
}
@Override
public void invalidateDistributionSet(final DistributionSetInvalidation distributionSetInvalidation) {
LOG.debug("Invalidate distribution sets {}", distributionSetInvalidation.getDistributionSetIds());
final String tenant = tenantAware.getCurrentTenant();
-
if (shouldRolloutsBeCanceled(distributionSetInvalidation.getCancelationType(),
distributionSetInvalidation.isCancelRollouts())) {
final String handlerId = JpaRolloutManagement.createRolloutLockKey(tenant);
@@ -95,6 +97,7 @@ public class JpaDistributionSetInvalidationManagement implements DistributionSet
// no lock is needed as no rollout will be stopped
invalidateDistributionSetsInTransaction(distributionSetInvalidation, tenant);
}
+
}
private void invalidateDistributionSetsInTransaction(final DistributionSetInvalidation distributionSetInvalidation,
@@ -110,17 +113,25 @@ public class JpaDistributionSetInvalidationManagement implements DistributionSet
final boolean cancelRollouts) {
final DistributionSet set = distributionSetManagement.getValidAndComplete(setId);
distributionSetManagement.invalidate(set);
- LOG.debug("Distribution set {} set to invalid", setId);
+ LOG.debug("Distribution set {} marked as invalid.", setId);
+ // rollout cancellation should only be permitted with UPDATE_ROLLOUT permission
if (shouldRolloutsBeCanceled(cancelationType, cancelRollouts)) {
+ LOG.debug("Cancel rollouts after ds invalidation. ID: {}", setId);
rolloutManagement.cancelRolloutsForDistributionSet(set);
}
- if (cancelationType != CancelationType.NONE) {
- deploymentManagement.cancelActionsForDistributionSet(cancelationType, set);
- }
+ // Do run as system to ensure all actions (even invisible) are canceled due to invalidation.
+ systemSecurityContext.runAsSystem(() -> {
+ if (cancelationType != CancelationType.NONE) {
+ LOG.debug("Cancel actions after ds invalidation. ID: {}", setId);
+ deploymentManagement.cancelActionsForDistributionSet(cancelationType, set);
+ }
- targetFilterQueryManagement.cancelAutoAssignmentForDistributionSet(setId);
+ LOG.debug("Cancel auto assignments after ds invalidation. ID: {}", setId);
+ targetFilterQueryManagement.cancelAutoAssignmentForDistributionSet(setId);
+ return null;
+ });
}
private static boolean shouldRolloutsBeCanceled(final CancelationType cancelationType,
@@ -131,13 +142,16 @@ public class JpaDistributionSetInvalidationManagement implements DistributionSet
@Override
public DistributionSetInvalidationCount countEntitiesForInvalidation(
final DistributionSetInvalidation distributionSetInvalidation) {
- final Collection setIds = distributionSetInvalidation.getDistributionSetIds();
- final long rolloutsCount = shouldRolloutsBeCanceled(distributionSetInvalidation.getCancelationType(),
- distributionSetInvalidation.isCancelRollouts()) ? countRolloutsForInvalidation(setIds) : 0;
- final long autoAssignmentsCount = countAutoAssignmentsForInvalidation(setIds);
- final long actionsCount = countActionsForInvalidation(setIds, distributionSetInvalidation.getCancelationType());
+ return systemSecurityContext.runAsSystem(() -> {
+ final Collection setIds = distributionSetInvalidation.getDistributionSetIds();
+ final long rolloutsCount = shouldRolloutsBeCanceled(distributionSetInvalidation.getCancelationType(),
+ distributionSetInvalidation.isCancelRollouts()) ? countRolloutsForInvalidation(setIds) : 0;
+ final long autoAssignmentsCount = countAutoAssignmentsForInvalidation(setIds);
+ final long actionsCount = countActionsForInvalidation(setIds,
+ distributionSetInvalidation.getCancelationType());
- return new DistributionSetInvalidationCount(rolloutsCount, autoAssignmentsCount, actionsCount);
+ return new DistributionSetInvalidationCount(rolloutsCount, autoAssignmentsCount, actionsCount);
+ });
}
private long countRolloutsForInvalidation(final Collection setIds) {
@@ -163,7 +177,9 @@ public class JpaDistributionSetInvalidationManagement implements DistributionSet
}
private long countActionsForSoftInvalidation(final Collection setIds) {
- return setIds.stream().mapToLong(distributionSet -> actionRepository
- .countByDistributionSetIdAndActiveIsTrueAndStatusIsNot(distributionSet, Status.CANCELING)).sum();
+ return setIds.stream()
+ .mapToLong(distributionSet -> actionRepository
+ .countByDistributionSetIdAndActiveIsTrueAndStatusIsNot(distributionSet, Status.CANCELING))
+ .sum();
}
}
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java
index f501affd0..ba23f485f 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java
@@ -786,7 +786,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
public void invalidate(final DistributionSet distributionSet) {
final JpaDistributionSet jpaSet = (JpaDistributionSet) distributionSet;
jpaSet.invalidate();
- distributionSetRepository.save(AccessController.Operation.DELETE, jpaSet);
+ distributionSetRepository.save(jpaSet);
}
private JpaDistributionSet getById(final long id) {
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java
index 96fcfdc92..4ff027df1 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTargetManagement.java
@@ -96,6 +96,8 @@ import org.springframework.validation.annotation.Validated;
import com.google.common.collect.Lists;
+import static org.eclipse.hawkbit.repository.jpa.JpaManagementHelper.combineWithAnd;
+
/**
* JPA implementation of {@link TargetManagement}.
*
@@ -130,7 +132,6 @@ public class JpaTargetManagement implements TargetManagement {
private final Database database;
-
public JpaTargetManagement(final EntityManager entityManager,
final DistributionSetManagement distributionSetManagement, final QuotaManagement quotaManagement,
final TargetRepository targetRepository, final TargetTypeRepository targetTypeRepository,
@@ -138,8 +139,8 @@ public class JpaTargetManagement implements TargetManagement {
final RolloutGroupRepository rolloutGroupRepository,
final TargetFilterQueryRepository targetFilterQueryRepository,
final TargetTagRepository targetTagRepository, final EventPublisherHolder eventPublisherHolder,
- final TenantAware tenantAware,
- final VirtualPropertyReplacer virtualPropertyReplacer, final Database database) {
+ final TenantAware tenantAware, final VirtualPropertyReplacer virtualPropertyReplacer,
+ final Database database) {
this.entityManager = entityManager;
this.distributionSetManagement = distributionSetManagement;
this.quotaManagement = quotaManagement;
@@ -161,8 +162,7 @@ public class JpaTargetManagement implements TargetManagement {
}
private JpaTarget getByControllerIdAndThrowIfNotFound(final String controllerId) {
- return targetRepository
- .findOne(TargetSpecifications.hasControllerId(controllerId))
+ return targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId))
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
}
@@ -255,6 +255,9 @@ public class JpaTargetManagement implements TargetManagement {
final JpaTarget target = JpaManagementHelper.touch(entityManager, targetRepository,
getByControllerIdAndThrowIfNotFound(controllerId));
+ targetRepository.getAccessController()
+ .ifPresent(acm -> acm.assertOperationAllowed(AccessController.Operation.UPDATE, target));
+
targetMetadataRepository.deleteById(metadata.getId());
// target update event is set to ignore "lastModifiedAt" field, so it is
// not send automatically within the touch() method
@@ -312,17 +315,14 @@ public class JpaTargetManagement implements TargetManagement {
.orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId));
return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable,
- List.of(
- RSQLUtility.buildRsqlSpecification(targetFilterQuery.getQuery(), TargetFields.class,
- virtualPropertyReplacer, database)));
+ List.of(RSQLUtility.buildRsqlSpecification(targetFilterQuery.getQuery(), TargetFields.class,
+ virtualPropertyReplacer, database)));
}
@Override
public Slice findByRsql(final Pageable pageable, final String targetFilterQuery) {
- return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable,
- List.of(
- RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class,
- virtualPropertyReplacer, database)));
+ return JpaManagementHelper.findAllWithoutCountBySpec(targetRepository, pageable, List.of(RSQLUtility
+ .buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database)));
}
@Override
@@ -481,7 +481,7 @@ public class JpaTargetManagement implements TargetManagement {
final TargetTag tag = targetTagRepository.findByNameEquals(tagName)
.orElseThrow(() -> new EntityNotFoundException(TargetTag.class, tagName));
final List allTargets = targetRepository
- .findAll(AccessController.Operation.UPDATE, TargetSpecifications.byControllerIdWithTagsInJoin(controllerIds));
+ .findAll(TargetSpecifications.byControllerIdWithTagsInJoin(controllerIds));
if (allTargets.size() < controllerIds.size()) {
throw new EntityNotFoundException(Target.class, controllerIds,
allTargets.stream().map(Target::getControllerId).toList());
@@ -492,6 +492,7 @@ public class JpaTargetManagement implements TargetManagement {
// all are already assigned -> unassign
if (alreadyAssignedTargets.size() == allTargets.size()) {
+
alreadyAssignedTargets.forEach(target -> target.removeTag(tag));
return new TargetTagAssignmentResult(0, Collections.emptyList(),
Collections.unmodifiableList(alreadyAssignedTargets), tag);
@@ -501,9 +502,7 @@ public class JpaTargetManagement implements TargetManagement {
// some or none are assigned -> assign
allTargets.forEach(target -> target.addTag(tag));
final TargetTagAssignmentResult result = new TargetTagAssignmentResult(alreadyAssignedTargets.size(),
- Collections
- .unmodifiableList(allTargets.stream().map(targetRepository::save).collect(Collectors.toList())),
- Collections.emptyList(), tag);
+ targetRepository.saveAll(allTargets), Collections.emptyList(), tag);
// no reason to persist the tag
entityManager.detach(tag);
@@ -528,7 +527,7 @@ public class JpaTargetManagement implements TargetManagement {
targetsWithoutSameType.forEach(target -> target.setTargetType(type));
final TargetTypeAssignmentResult result = new TargetTypeAssignmentResult(targetsWithSameType.size(),
- targetsWithoutSameType.stream().map(targetRepository::save).toList(), Collections.emptyList(), type);
+ targetRepository.saveAll(targetsWithoutSameType), Collections.emptyList(), type);
// no reason to persist the type
entityManager.detach(type);
@@ -566,12 +565,15 @@ public class JpaTargetManagement implements TargetManagement {
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public List assignTag(final Collection controllerIds, final long tagId) {
final List allTargets = targetRepository
- .findAll(AccessController.Operation.UPDATE, TargetSpecifications.byControllerIdWithTagsInJoin(controllerIds));
+ .findAll(TargetSpecifications.byControllerIdWithTagsInJoin(controllerIds));
if (allTargets.size() < controllerIds.size()) {
throw new EntityNotFoundException(Target.class, controllerIds,
allTargets.stream().map(Target::getControllerId).toList());
}
+ targetRepository.getAccessController()
+ .ifPresent(acm -> acm.assertOperationAllowed(AccessController.Operation.UPDATE, allTargets));
+
final JpaTargetTag tag = targetTagRepository.findById(tagId)
.orElseThrow(() -> new EntityNotFoundException(TargetTag.class, tagId));
@@ -619,6 +621,11 @@ public class JpaTargetManagement implements TargetManagement {
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
public Target assignType(final String controllerId, final Long targetTypeId) {
final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId);
+
+ targetRepository.getAccessController().ifPresent(acm -> {
+ acm.assertOperationAllowed(AccessController.Operation.UPDATE, target);
+ });
+
final JpaTargetType targetType = getTargetTypeByIdAndThrowIfNotFound(targetTypeId);
target.setTargetType(targetType);
return targetRepository.save(target);
@@ -626,7 +633,7 @@ public class JpaTargetManagement implements TargetManagement {
@Override
public Slice findByFilterOrderByLinkedDistributionSet(final Pageable pageable,
- final long orderByDistributionSetId, final FilterParams filterParams) {
+ final long orderByDistributionSetId, final FilterParams filterParams) {
// remove default sort from pageable to not overwrite sorted spec
final OffsetBasedPageRequest unsortedPage = new OffsetBasedPageRequest(pageable.getOffset(),
pageable.getPageSize(), Sort.unsorted());
@@ -661,41 +668,42 @@ public class JpaTargetManagement implements TargetManagement {
@Override
public Slice findByTargetFilterQueryAndNonDSAndCompatibleAndUpdatable(final Pageable pageRequest,
- final long distributionSetId, final String targetFilterQuery) {
+ final long distributionSetId, final String targetFilterQuery) {
final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
final Long distSetTypeId = jpaDistributionSet.getType().getId();
- return targetRepository.findAllWithoutCount(
- AccessController.Operation.UPDATE,
- JpaManagementHelper.combineWithAnd(List.of(
- RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer,
- database),
- TargetSpecifications.hasNotDistributionSetInActions(distributionSetId),
- TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId))),
- pageRequest).map(Target.class::cast);
+ return targetRepository
+ .findAllWithoutCount(AccessController.Operation.UPDATE,
+ combineWithAnd(List.of(
+ RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class,
+ virtualPropertyReplacer, database),
+ TargetSpecifications.hasNotDistributionSetInActions(distributionSetId),
+ TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId))),
+ pageRequest)
+ .map(Target.class::cast);
}
@Override
public Slice findByTargetFilterQueryAndNotInRolloutGroupsAndCompatibleAndUpdatable(
final Pageable pageRequest, final Collection groups, final String targetFilterQuery,
final DistributionSetType dsType) {
- return targetRepository.findAllWithoutCount(
- AccessController.Operation.UPDATE,
- JpaManagementHelper.combineWithAnd(List.of(
- RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer,
- database),
- TargetSpecifications.isNotInRolloutGroups(groups),
- TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()))),
- pageRequest).map(Target.class::cast);
+ return targetRepository
+ .findAllWithoutCount(AccessController.Operation.UPDATE,
+ combineWithAnd(List.of(
+ RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class,
+ virtualPropertyReplacer, database),
+ TargetSpecifications.isNotInRolloutGroups(groups),
+ TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()))),
+ pageRequest)
+ .map(Target.class::cast);
}
@Override
public Slice findByFailedRolloutAndNotInRolloutGroups(Pageable pageRequest, Collection groups,
- String rolloutId) {
+ String rolloutId) {
final List> specList = Arrays.asList(
- TargetSpecifications.failedActionsForRollout(rolloutId),
- TargetSpecifications.isNotInRolloutGroups(groups)
- );
+ TargetSpecifications.failedActionsForRollout(rolloutId),
+ TargetSpecifications.isNotInRolloutGroups(groups));
return JpaManagementHelper.findAllWithCountBySpec(targetRepository, pageRequest, specList);
}
@@ -712,34 +720,34 @@ public class JpaTargetManagement implements TargetManagement {
@Override
public long countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(final Collection groups,
- final String targetFilterQuery, final DistributionSetType dsType) {
- return targetRepository.count(AccessController.Operation.UPDATE, JpaManagementHelper.combineWithAnd(
- List.of(
- RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer,
- database),
- TargetSpecifications.isNotInRolloutGroups(groups),
- TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()))));
+ final String targetFilterQuery, final DistributionSetType dsType) {
+ return targetRepository.count(AccessController.Operation.UPDATE,
+ combineWithAnd(List.of(
+ RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class,
+ virtualPropertyReplacer, database),
+ TargetSpecifications.isNotInRolloutGroups(groups),
+ TargetSpecifications.isCompatibleWithDistributionSetType(dsType.getId()))));
}
@Override
public long countByFailedRolloutAndNotInRolloutGroups(Collection groups, String rolloutId) {
final List> specList = Arrays.asList(
- TargetSpecifications.failedActionsForRollout(rolloutId),
- TargetSpecifications.isNotInRolloutGroups(groups));
+ TargetSpecifications.failedActionsForRollout(rolloutId),
+ TargetSpecifications.isNotInRolloutGroups(groups));
return JpaManagementHelper.countBySpec(targetRepository, specList);
}
@Override
public long countByRsqlAndNonDSAndCompatibleAndUpdatable(final long distributionSetId,
- final String targetFilterQuery) {
+ final String targetFilterQuery) {
final DistributionSet jpaDistributionSet = distributionSetManagement.getOrElseThrowException(distributionSetId);
final Long distSetTypeId = jpaDistributionSet.getType().getId();
- return targetRepository.count(AccessController.Operation.UPDATE, JpaManagementHelper.combineWithAnd(
- List.of(
- RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer,
- database),
+ return targetRepository.count(AccessController.Operation.UPDATE,
+ combineWithAnd(List.of(
+ RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class,
+ virtualPropertyReplacer, database),
TargetSpecifications.hasNotDistributionSetInActions(distributionSetId),
TargetSpecifications.isCompatibleWithDistributionSetType(distSetTypeId))));
}
@@ -798,27 +806,38 @@ public class JpaTargetManagement implements TargetManagement {
@Override
public long countByRsql(final String targetFilterQuery) {
- return JpaManagementHelper.countBySpec(
- targetRepository,
- List.of(
- RSQLUtility.buildRsqlSpecification(
- targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database)));
+ return JpaManagementHelper.countBySpec(targetRepository, List.of(RSQLUtility
+ .buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer, database)));
}
@Override
- public long countByRsqlAndCompatible(final String targetFilterQuery, final Long distributionSetId) {
- final List> specList = List.of(
- RSQLUtility.buildRsqlSpecification(targetFilterQuery, TargetFields.class, virtualPropertyReplacer,
- database),
- TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetId));
+ public long countByRsqlAndUpdatable(String targetFilterQuery) {
+ final List> specList = List.of(RSQLUtility.buildRsqlSpecification(targetFilterQuery,
+ TargetFields.class, virtualPropertyReplacer, database));
+ return targetRepository.count(AccessController.Operation.UPDATE, combineWithAnd(specList));
+ }
+
+ @Override
+ public long countByRsqlAndCompatible(final String targetFilterQuery, final Long distributionSetIdTypeId) {
+ final List> specList = List.of(RSQLUtility.buildRsqlSpecification(targetFilterQuery,
+ TargetFields.class, virtualPropertyReplacer, database),
+ TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetIdTypeId));
return JpaManagementHelper.countBySpec(targetRepository, specList);
}
+ @Override
+ public long countByRsqlAndCompatibleAndUpdatable(String targetFilterQuery, Long distributionSetIdTypeId) {
+ final List> specList = List.of(RSQLUtility.buildRsqlSpecification(targetFilterQuery,
+ TargetFields.class, virtualPropertyReplacer, database),
+ TargetSpecifications.isCompatibleWithDistributionSetType(distributionSetIdTypeId));
+ return targetRepository.count(AccessController.Operation.UPDATE, combineWithAnd(specList));
+ }
+
@Override
public long countByFailedInRollout(final String rolloutId, final Long dsTypeId) {
- final List> specList = List.of(
- TargetSpecifications.failedActionsForRollout(rolloutId));
+ final List> specList = List
+ .of(TargetSpecifications.failedActionsForRollout(rolloutId));
return JpaManagementHelper.countBySpec(targetRepository, specList);
}
@@ -856,6 +875,8 @@ public class JpaTargetManagement implements TargetManagement {
@Override
public void requestControllerAttributes(final String controllerId) {
final JpaTarget target = getByControllerIdAndThrowIfNotFound(controllerId);
+ targetRepository.getAccessController()
+ .ifPresent(acm -> acm.assertOperationAllowed(AccessController.Operation.UPDATE, target));
target.setRequestControllerAttributes(true);
eventPublisherHolder.getEventPublisher()
.publishEvent(new TargetAttributesRequestedEvent(tenantAware.getCurrentTenant(), target.getId(),
@@ -876,7 +897,7 @@ public class JpaTargetManagement implements TargetManagement {
}
@Override
- public boolean isTargetMatchingQueryAndDSNotAssignedAndCompatible(final String controllerId,
+ public boolean isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(final String controllerId,
final long distributionSetId, final String targetFilterQuery) {
RSQLUtility.validateRsqlFor(targetFilterQuery, TargetFields.class);
final DistributionSet ds = distributionSetManagement.get(distributionSetId)
@@ -891,7 +912,7 @@ public class JpaTargetManagement implements TargetManagement {
final Specification combinedSpecification = Objects
.requireNonNull(SpecificationsBuilder.combineWithAnd(specList));
- return targetRepository.exists(combinedSpecification);
+ return targetRepository.exists(AccessController.Operation.UPDATE, combinedSpecification);
}
@Override
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepositoryACM.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepositoryACM.java
index c5547b79e..5aef2becc 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepositoryACM.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/BaseEntityRepositoryACM.java
@@ -27,7 +27,6 @@ import javax.transaction.Transactional;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
-import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
@@ -70,13 +69,18 @@ public class BaseEntityRepositoryACM
if (method.getName().startsWith("find") || method.getName().startsWith("get")) {
final Object result = method.invoke(repository, args);
if (Iterable.class.isAssignableFrom(method.getReturnType())) {
- for (final T e : ((Iterable) result)) {
- accessController.assertOperationAllowed(AccessController.Operation.READ, e);
+ for (final Object e : (Iterable>) result) {
+ if (repository.getDomainClass().isAssignableFrom(e.getClass())) {
+ accessController.assertOperationAllowed(AccessController.Operation.READ, (T) e);
+ }
}
- } else if (Optional.class.isAssignableFrom(method.getReturnType())) {
- return ((Optional)result).filter(t -> isOperationAllowed(AccessController.Operation.READ, t, accessController));
+ } else if (Optional.class.isAssignableFrom(method.getReturnType()) && ((Optional>) result)
+ .filter(value -> repository.getDomainClass().isAssignableFrom(value.getClass()))
+ .isPresent()) {
+ return ((Optional) result).filter(
+ t -> isOperationAllowed(AccessController.Operation.READ, t, accessController));
} else if (repository.getDomainClass().isAssignableFrom(method.getReturnType())) {
- accessController.assertOperationAllowed(AccessController.Operation.READ, (T)result);
+ accessController.assertOperationAllowed(AccessController.Operation.READ, (T) result);
}
return result;
} else if ("toString".equals(method.getName()) && method.getParameterCount() == 0) {
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerTest.java
index a02d94277..9f755b18d 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerTest.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/autoassign/AutoAssignCheckerTest.java
@@ -74,9 +74,9 @@ class AutoAssignCheckerTest {
when(targetFilterQueryManagement.findWithAutoAssignDS(any()))
.thenReturn(new SliceImpl<>(Arrays.asList(notMatching, matching)));
- when(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatible(target, ds, matching.getQuery()))
+ when(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(target, ds, matching.getQuery()))
.thenReturn(true);
- when(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatible(target, ds, notMatching.getQuery()))
+ when(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(target, ds, notMatching.getQuery()))
.thenReturn(false);
sut.checkSingleTarget(target);
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetInvalidationManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetInvalidationManagementTest.java
index 3eca57e94..147481e70 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetInvalidationManagementTest.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetInvalidationManagementTest.java
@@ -203,18 +203,18 @@ class DistributionSetInvalidationManagementTest extends AbstractJpaIntegrationTe
}
@Test
- @Description("Verify that a user that has authority READ_REPOSITORY and UPDATE_REPOSITORY is not allowed to invalidate a distribution set")
+ @Description("Verify that a user that has authority READ_REPOSITORY and UPDATE_REPOSITORY is allowed to invalidate a distribution set")
@WithUser(authorities = { "READ_REPOSITORY", "UPDATE_REPOSITORY" })
void verifyInvalidateWithReadAndUpdateRepoAuthority() {
final InvalidationTestData invalidationTestData = systemSecurityContext
.runAsSystem(() -> createInvalidationTestData("verifyInvalidateWithUpdateRepoAuthority"));
- assertThatExceptionOfType(InsufficientPermissionException.class)
- .as("Insufficient permission exception expected")
- .isThrownBy(() -> distributionSetInvalidationManagement
- .invalidateDistributionSet(new DistributionSetInvalidation(
- Collections.singletonList(invalidationTestData.getDistributionSet().getId()),
- CancelationType.NONE, false)));
+ distributionSetInvalidationManagement.invalidateDistributionSet(new DistributionSetInvalidation(
+ Collections.singletonList(invalidationTestData.getDistributionSet().getId()), CancelationType.NONE,
+ false));
+ assertThat(
+ distributionSetRepository.findById(invalidationTestData.getDistributionSet().getId()).get().isValid())
+ .isFalse();
}
@Test
diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java
index 0514007d8..94c97ce49 100644
--- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java
+++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/TargetManagementTest.java
@@ -1267,7 +1267,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
final DistributionSet ds = testdataFactory.createDistributionSet();
final String filter = "metadata.key1==target1-value1";
- assertThat(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatible(target.getControllerId(),
+ assertThat(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(target.getControllerId(),
ds.getId(), filter)).isTrue();
}
@@ -1278,7 +1278,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
final DistributionSet ds = testdataFactory.createDistributionSet();
final String filter = "metadata.key==not_existing";
- assertThat(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatible(target.getControllerId(),
+ assertThat(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(target.getControllerId(),
ds.getId(), filter)).isFalse();
}
@@ -1292,7 +1292,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
assignDistributionSet(ds2, target);
final String filter = "name==*";
- assertThat(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatible(target.getControllerId(),
+ assertThat(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(target.getControllerId(),
ds1.getId(), filter)).isFalse();
}
@@ -1303,7 +1303,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
final Target target = testdataFactory.createTarget("target", "target", type.getId());
final DistributionSet ds = testdataFactory.createDistributionSet();
- assertThat(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatible(target.getControllerId(),
+ assertThat(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(target.getControllerId(),
ds.getId(), "name==*")).isFalse();
}
@@ -1314,9 +1314,9 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
final Long ds = testdataFactory.createDistributionSet().getId();
assertThatExceptionOfType(RSQLParameterSyntaxException.class).isThrownBy(() -> targetManagement
- .isTargetMatchingQueryAndDSNotAssignedAndCompatible(target, ds, "invalid_syntax"));
+ .isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(target, ds, "invalid_syntax"));
assertThatExceptionOfType(RSQLParameterUnsupportedFieldException.class).isThrownBy(() -> targetManagement
- .isTargetMatchingQueryAndDSNotAssignedAndCompatible(target, ds, "invalid_field==1"));
+ .isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(target, ds, "invalid_field==1"));
}
@Test
@@ -1324,7 +1324,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
void matchesFilterTargetNotExists() {
final DistributionSet ds = testdataFactory.createDistributionSet();
- assertThat(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatible("notExisting", ds.getId(),
+ assertThat(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable("notExisting", ds.getId(),
"name==*")).isFalse();
}
@@ -1334,7 +1334,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
final String target = testdataFactory.createTarget().getControllerId();
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(
- () -> targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatible(target, 123, "name==*"));
+ () -> targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(target, 123, "name==*"));
}
private void validateFoundTargetsByRsql(final String rsqlFilter, final String... controllerIds) {
diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/window/layouts/AddRolloutWindowLayout.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/window/layouts/AddRolloutWindowLayout.java
index 29a962e0b..ce7118e0d 100644
--- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/window/layouts/AddRolloutWindowLayout.java
+++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/rollout/window/layouts/AddRolloutWindowLayout.java
@@ -134,14 +134,13 @@ public class AddRolloutWindowLayout extends AbstractRolloutWindowLayout {
}
private Long getTotalTargets(final String filterQuery, final Long distSetTypeId) {
- // TODO AC - Check for updatable targets only
if (StringUtils.isEmpty(filterQuery)) {
return null;
}
if (distSetTypeId == null) {
- return targetManagement.countByRsql(filterQuery);
+ return targetManagement.countByRsqlAndUpdatable(filterQuery);
}
- return targetManagement.countByRsqlAndCompatible(filterQuery, distSetTypeId);
+ return targetManagement.countByRsqlAndCompatibleAndUpdatable(filterQuery, distSetTypeId);
}
private boolean isSimpleGroupsTabSelected() {