Fix action delete access control - to require only target update (not delete also) (#2767)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -385,14 +385,13 @@ public class JpaRolloutExecutor implements RolloutExecutor {
|
||||
}
|
||||
|
||||
private void deleteScheduledActions(final JpaRollout rollout, final Slice<JpaAction> scheduledActions) {
|
||||
final boolean hasScheduledActions = scheduledActions.getNumberOfElements() > 0;
|
||||
|
||||
if (hasScheduledActions) {
|
||||
if (scheduledActions.getNumberOfElements() > 0) {
|
||||
// has scheduled actions - delete them
|
||||
try {
|
||||
final List<Long> actionIds = StreamSupport.stream(scheduledActions.spliterator(), false)
|
||||
.map(Action::getId)
|
||||
.toList();
|
||||
actionRepository.deleteByIdIn(actionIds);
|
||||
actionRepository.deleteAllById(actionIds);
|
||||
afterCommit.afterCommit(() -> EventPublisherHolder.getInstance().getEventPublisher()
|
||||
.publishEvent(new RolloutUpdatedEvent(rollout)));
|
||||
} catch (final RuntimeException e) {
|
||||
|
||||
@@ -80,7 +80,7 @@ public class AccessControllerConfiguration {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Optional<Specification<JpaAction>> getAccessRules(final Operation operation) {
|
||||
return targetAccessController.getAccessRules(operation).map(targetSpec -> (actionRoot, query, cb) -> {
|
||||
return targetAccessController.getAccessRules(map(operation)).map(targetSpec -> (actionRoot, query, cb) -> {
|
||||
final Join<JpaAction, JpaTarget> targetJoin = actionRoot.join(JpaAction_.target);
|
||||
final EntityType<JpaTarget> targetModel = query.from(JpaTarget.class).getModel();
|
||||
final Root<JpaTarget> targetRoot = (Root<JpaTarget>) Proxy.newProxyInstance(
|
||||
@@ -101,7 +101,15 @@ public class AccessControllerConfiguration {
|
||||
|
||||
@Override
|
||||
public void assertOperationAllowed(final Operation operation, final JpaAction entity) throws InsufficientPermissionException {
|
||||
targetAccessController.assertOperationAllowed(operation, entity.getTarget());
|
||||
targetAccessController.assertOperationAllowed(map(operation), entity.getTarget());
|
||||
}
|
||||
|
||||
// all CREATE/UPDATE/DELETE action operations are mapped to UPDATE_TARGET permissions / actions
|
||||
private static Operation map(final Operation actionOperation) {
|
||||
return switch (actionOperation) {
|
||||
case READ -> Operation.READ;
|
||||
case CREATE, UPDATE, DELETE -> Operation.UPDATE;
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,13 +13,12 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import jakarta.persistence.criteria.JoinType;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.function.TriConsumer;
|
||||
import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||
import org.eclipse.hawkbit.repository.RepositoryConstants;
|
||||
import org.eclipse.hawkbit.repository.RepositoryProperties;
|
||||
@@ -29,6 +28,7 @@ import org.eclipse.hawkbit.repository.event.remote.entity.TargetUpdatedEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
||||
import org.eclipse.hawkbit.repository.jpa.management.JpaDeploymentManagement.MaxAssignmentsExceededInfo;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.AbstractJpaBaseEntity_;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
|
||||
@@ -67,7 +67,7 @@ public abstract class AbstractDsAssignmentStrategy {
|
||||
private final BooleanSupplier multiAssignmentsConfig;
|
||||
private final BooleanSupplier confirmationFlowConfig;
|
||||
private final RepositoryProperties repositoryProperties;
|
||||
private final TriConsumer<Long, Long, AssignmentQuotaExceededException> maxAssignmentExceededHandler;
|
||||
private final Consumer<MaxAssignmentsExceededInfo> maxAssignmentExceededHandler;
|
||||
|
||||
@SuppressWarnings("java:S107")
|
||||
AbstractDsAssignmentStrategy(
|
||||
@@ -76,7 +76,7 @@ public abstract class AbstractDsAssignmentStrategy {
|
||||
final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository,
|
||||
final QuotaManagement quotaManagement, final BooleanSupplier multiAssignmentsConfig,
|
||||
final BooleanSupplier confirmationFlowConfig, final RepositoryProperties repositoryProperties,
|
||||
final TriConsumer<Long, Long, AssignmentQuotaExceededException> maxAssignmentExceededHandler) {
|
||||
final Consumer<MaxAssignmentsExceededInfo> maxAssignmentExceededHandler) {
|
||||
this.targetRepository = targetRepository;
|
||||
this.afterCommit = afterCommit;
|
||||
this.actionRepository = actionRepository;
|
||||
@@ -96,7 +96,7 @@ public abstract class AbstractDsAssignmentStrategy {
|
||||
|
||||
// create the action
|
||||
return optTarget.map(target -> {
|
||||
assertActionsPerTargetQuota(target, 1);
|
||||
assertActionsPerTargetQuota(target);
|
||||
final JpaAction actionForTarget = new JpaAction();
|
||||
actionForTarget.setActionType(targetWithActionType.getActionType());
|
||||
actionForTarget.setForcedTime(targetWithActionType.getForceTime());
|
||||
@@ -144,7 +144,7 @@ public abstract class AbstractDsAssignmentStrategy {
|
||||
*
|
||||
* @param targetsIds to override {@link Action}s
|
||||
*/
|
||||
protected List<Long> overrideObsoleteUpdateActions(final Collection<Long> targetsIds) {
|
||||
protected void overrideObsoleteUpdateActions(final Collection<Long> targetsIds) {
|
||||
// Figure out if there are potential target/action combinations that
|
||||
// need to be considered for cancellation
|
||||
final List<JpaAction> activeActions = actionRepository.findAll((root, query, cb) -> {
|
||||
@@ -157,22 +157,18 @@ public abstract class AbstractDsAssignmentStrategy {
|
||||
);
|
||||
});
|
||||
|
||||
final List<Long> targetIds = activeActions.stream().map(action -> {
|
||||
activeActions.forEach(action -> {
|
||||
action.setStatus(Status.CANCELING);
|
||||
|
||||
// document that the status has been retrieved
|
||||
actionStatusRepository.save(new JpaActionStatus(action, Status.CANCELING, System.currentTimeMillis(),
|
||||
RepositoryConstants.SERVER_MESSAGE_PREFIX + "cancel obsolete action due to new update"));
|
||||
actionRepository.save(action);
|
||||
|
||||
return action.getTarget().getId();
|
||||
}).toList();
|
||||
});
|
||||
|
||||
if (!activeActions.isEmpty()) {
|
||||
cancelAssignDistributionSetEvent(Collections.unmodifiableList(activeActions));
|
||||
}
|
||||
|
||||
return targetIds;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,7 +179,7 @@ public abstract class AbstractDsAssignmentStrategy {
|
||||
*
|
||||
* @param targetsIds to override {@link Action}s
|
||||
*/
|
||||
protected List<Long> closeObsoleteUpdateActions(final Collection<Long> targetsIds) {
|
||||
protected void closeObsoleteUpdateActions(final Collection<Long> targetsIds) {
|
||||
// Figure out if there are potential target/action combinations that
|
||||
// need to be considered for cancellation
|
||||
final List<JpaAction> activeActions = actionRepository.findAll((root, query, cb) -> {
|
||||
@@ -195,7 +191,7 @@ public abstract class AbstractDsAssignmentStrategy {
|
||||
);
|
||||
});
|
||||
|
||||
return activeActions.stream().map(action -> {
|
||||
activeActions.forEach(action -> {
|
||||
action.setStatus(Status.CANCELED);
|
||||
action.setActive(false);
|
||||
|
||||
@@ -203,10 +199,7 @@ public abstract class AbstractDsAssignmentStrategy {
|
||||
actionStatusRepository.save(new JpaActionStatus(action, Status.CANCELED, System.currentTimeMillis(),
|
||||
RepositoryConstants.SERVER_MESSAGE_PREFIX + "close obsolete action due to new update"));
|
||||
actionRepository.save(action);
|
||||
|
||||
return action.getTarget().getId();
|
||||
}).toList();
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,10 +230,6 @@ public abstract class AbstractDsAssignmentStrategy {
|
||||
*/
|
||||
abstract List<JpaTarget> findTargetsForAssignment(final List<String> controllerIDs, final long distributionSetId);
|
||||
|
||||
/**
|
||||
* @param set
|
||||
* @param targets
|
||||
*/
|
||||
abstract void sendTargetUpdatedEvents(final DistributionSet set, final List<JpaTarget> targets);
|
||||
|
||||
/**
|
||||
@@ -260,9 +249,8 @@ public abstract class AbstractDsAssignmentStrategy {
|
||||
* such actions existed.
|
||||
*
|
||||
* @param targetIds to cancel actions for
|
||||
* @return {@link Set} of {@link Target#getId()}s
|
||||
*/
|
||||
abstract Set<Long> cancelActiveActions(List<List<Long>> targetIds);
|
||||
abstract void cancelActiveActions(List<List<Long>> targetIds);
|
||||
|
||||
/**
|
||||
* Cancels actions that can be canceled (i.e.
|
||||
@@ -274,8 +262,6 @@ public abstract class AbstractDsAssignmentStrategy {
|
||||
*/
|
||||
abstract void closeActiveActions(List<List<Long>> targetIds);
|
||||
|
||||
abstract void sendDeploymentEvents(final DistributionSetAssignmentResult assignmentResult);
|
||||
|
||||
abstract void sendDeploymentEvents(final List<DistributionSetAssignmentResult> assignmentResults);
|
||||
|
||||
private static String getActionMessage(final Action action) {
|
||||
@@ -297,12 +283,12 @@ public abstract class AbstractDsAssignmentStrategy {
|
||||
.publishEvent(new CancelTargetAssignmentEvent(tenant, actions)));
|
||||
}
|
||||
|
||||
private void assertActionsPerTargetQuota(final Target target, final long requested) {
|
||||
private void assertActionsPerTargetQuota(final Target target) {
|
||||
final int quota = quotaManagement.getMaxActionsPerTarget();
|
||||
try {
|
||||
QuotaHelper.assertAssignmentQuota(target.getId(), requested, quota, Action.class, Target.class, actionRepository::countByTargetId);
|
||||
} catch (AssignmentQuotaExceededException ex) {
|
||||
maxAssignmentExceededHandler.accept(target.getId(), requested, ex);
|
||||
QuotaHelper.assertAssignmentQuota(target.getId(), 1, quota, Action.class, Target.class, actionRepository::countByTargetId);
|
||||
} catch (AssignmentQuotaExceededException e) {
|
||||
maxAssignmentExceededHandler.accept(new MaxAssignmentsExceededInfo(target.getId(), 1, e));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -37,8 +38,6 @@ import jakarta.persistence.criteria.Root;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.function.TriConsumer;
|
||||
import org.eclipse.hawkbit.repository.ActionFields;
|
||||
import org.eclipse.hawkbit.repository.DeploymentManagement;
|
||||
import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||
@@ -162,6 +161,11 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
this.targetRepository = targetRepository;
|
||||
this.auditorProvider = auditorProvider;
|
||||
this.txManager = txManager;
|
||||
final Consumer<MaxAssignmentsExceededInfo> maxAssignmentsExceededHandler = maxAssignmentsExceededInfo ->
|
||||
handleMaxAssignmentsExceeded(
|
||||
maxAssignmentsExceededInfo.targetId,
|
||||
maxAssignmentsExceededInfo.requested,
|
||||
maxAssignmentsExceededInfo.quotaExceededException);
|
||||
onlineDsAssignmentStrategy = new OnlineDsAssignmentStrategy(targetRepository, afterCommit, actionRepository, actionStatusRepository,
|
||||
quotaManagement, this::isMultiAssignmentsEnabled, this::isConfirmationFlowEnabled, repositoryProperties,
|
||||
maxAssignmentsExceededHandler);
|
||||
@@ -409,14 +413,6 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
@Transactional
|
||||
public void deleteAction(final long actionId) {
|
||||
log.info("Deleting action {}", actionId);
|
||||
actionRepository.getAccessController().ifPresent(accessController -> {
|
||||
// check update access
|
||||
if (ObjectUtils.isEmpty(actionRepository.findAll(accessController.appendAccessRules(
|
||||
AccessController.Operation.UPDATE, ((root, q, cb) -> cb.equal(root.get(AbstractJpaBaseEntity_.id), actionId)))))) {
|
||||
// could be also InsufficientPermissionException but for security reasons we do not reveal that the entity exists
|
||||
throw new EntityNotFoundException(Action.class, actionId);
|
||||
}
|
||||
});
|
||||
actionRepository.deleteById(actionId);
|
||||
}
|
||||
|
||||
@@ -424,56 +420,41 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
@Transactional
|
||||
public void deleteActionsByRsql(final String rsql) {
|
||||
log.info("Deleting actions matching rsql {}", rsql);
|
||||
final Specification<JpaAction> specification = QLSupport.getInstance().buildSpec(rsql, ActionFields.class);
|
||||
actionRepository.delete(
|
||||
actionRepository.getAccessController()
|
||||
.map(accessController -> accessController.appendAccessRules(AccessController.Operation.UPDATE, specification))
|
||||
.orElse(specification));
|
||||
actionRepository.delete(QLSupport.getInstance().buildSpec(rsql, ActionFields.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteActionsByIds(final List<Long> actionIds) {
|
||||
log.info("Deleting actions with ids {}", actionIds);
|
||||
actionRepository.getAccessController().ifPresent(accessController ->
|
||||
actionRepository.findAll(
|
||||
accessController.appendAccessRules(AccessController.Operation.UPDATE, ActionSpecifications.byIdIn(actionIds))));
|
||||
actionRepository.deleteByIdIn(actionIds);
|
||||
actionRepository.deleteAllById(actionIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteTargetActionsByIds(final String target, final List<Long> actionsIds) {
|
||||
log.info("Delete actions for target {} with action ids {}", target, actionsIds);
|
||||
targetRepository.getAccessController()
|
||||
.ifPresent(accessController ->
|
||||
accessController.assertOperationAllowed(AccessController.Operation.UPDATE, targetRepository.getByControllerId(target)));
|
||||
actionRepository.delete(ActionSpecifications.byControllerIdAndIdIn(target, actionsIds));
|
||||
public void deleteTargetActionsByIds(final String controllerId, final List<Long> actionsIds) {
|
||||
log.info("Delete actions for target {} with action ids {}", controllerId, actionsIds);
|
||||
actionRepository.delete(ActionSpecifications.byControllerIdAndIdIn(controllerId, actionsIds));
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void deleteOldestTargetActions(final String target, final int keepLast) {
|
||||
final JpaTarget jpaTarget = targetRepository.findByControllerId(target)
|
||||
.orElseThrow(EntityNotFoundException::new);
|
||||
public void deleteOldestTargetActions(final String controllerId, final int keepLast) {
|
||||
final JpaTarget target = targetRepository.findByControllerId(controllerId).orElseThrow(EntityNotFoundException::new);
|
||||
// check access to target since deletion will be executed via native query
|
||||
targetRepository.getAccessController().ifPresent(accessController ->
|
||||
accessController.assertOperationAllowed(AccessController.Operation.UPDATE, jpaTarget));
|
||||
|
||||
final long targetActions = actionRepository.countByTargetId(jpaTarget.getId());
|
||||
|
||||
long oldestToDelete;
|
||||
accessController.assertOperationAllowed(AccessController.Operation.UPDATE, target));
|
||||
final long targetActions = actionRepository.countByTargetId(target.getId());
|
||||
if (targetActions > keepLast) {
|
||||
oldestToDelete = targetActions - keepLast;
|
||||
} else {
|
||||
return;
|
||||
final long oldestToDelete = targetActions - keepLast;
|
||||
deleteOldestTargetActions(target.getId(), (int) oldestToDelete);
|
||||
}
|
||||
deleteOldestTargetActions(jpaTarget.getId(), (int) oldestToDelete);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(isolation = Isolation.READ_COMMITTED)
|
||||
@Retryable(retryFor = {
|
||||
ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
@Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX,
|
||||
backoff = @Backoff(delay = Constants.TX_RT_DELAY))
|
||||
public void cancelInactiveScheduledActionsForTargets(final List<Long> targetIds) {
|
||||
if (!isMultiAssignmentsEnabled()) {
|
||||
targetRepository.getAccessController().ifPresent(v -> {
|
||||
@@ -598,12 +579,11 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMaxAssignmentsExceeded(final Long targetId, final Long requested, final AssignmentQuotaExceededException ex) {
|
||||
maxAssignmentsExceededHandler.accept(targetId, requested, ex);
|
||||
}
|
||||
public record MaxAssignmentsExceededInfo(long targetId, long requested, AssignmentQuotaExceededException quotaExceededException) {}
|
||||
|
||||
private final TriConsumer<Long, Long, AssignmentQuotaExceededException> maxAssignmentsExceededHandler = (targetId, requested, quotaExceededException) -> {
|
||||
@Override
|
||||
public void handleMaxAssignmentsExceeded(
|
||||
final Long targetId, final Long requested, final AssignmentQuotaExceededException quotaExceededException) {
|
||||
int actionsPurgePercentage = getActionsPurgePercentage();
|
||||
int quota = quotaManagement.getMaxActionsPerTarget();
|
||||
if (actionsPurgePercentage > 0 && actionsPurgePercentage < 100) {
|
||||
@@ -622,7 +602,9 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
} else {
|
||||
throw quotaExceededException;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
/**
|
||||
* Deletes the first n target actions of a target
|
||||
@@ -630,7 +612,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
* @param targetId - target id
|
||||
* @param oldestToDelete - number of oldest actions to be deleted
|
||||
*/
|
||||
public void deleteOldestTargetActions(long targetId, int oldestToDelete) {
|
||||
private void deleteOldestTargetActions(long targetId, int oldestToDelete) {
|
||||
// Workaround for the case where JPQL or Criteria API do not support LIMIT
|
||||
log.info("Deleting last {} actions of target {}", oldestToDelete, targetId);
|
||||
final String SQL = "DELETE FROM sp_action WHERE id IN(" +
|
||||
@@ -641,7 +623,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
" LIMIT " + oldestToDelete
|
||||
+ ") AS sub"
|
||||
+ ")";
|
||||
Query query = entityManager.createNativeQuery(SQL);
|
||||
final Query query = entityManager.createNativeQuery(SQL);
|
||||
query.setParameter("target", targetId);
|
||||
query.executeUpdate();
|
||||
}
|
||||
@@ -912,7 +894,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
|
||||
} catch (final AssignmentQuotaExceededException ex) {
|
||||
targetRepository.findByControllerId(controllerId).ifPresentOrElse(
|
||||
// assume requested are always smaller than int size
|
||||
target -> maxAssignmentsExceededHandler.accept(target.getId(), requested, ex),
|
||||
target -> handleMaxAssignmentsExceeded(target.getId(), requested, ex),
|
||||
() -> {
|
||||
throw new EntityNotFoundException(Target.class, controllerId);
|
||||
});
|
||||
|
||||
@@ -9,25 +9,21 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.management;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.apache.commons.lang3.function.TriConsumer;
|
||||
import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||
import org.eclipse.hawkbit.repository.RepositoryConstants;
|
||||
import org.eclipse.hawkbit.repository.RepositoryProperties;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
|
||||
import org.eclipse.hawkbit.repository.jpa.JpaManagementHelper;
|
||||
import org.eclipse.hawkbit.repository.jpa.acm.AccessController;
|
||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
||||
import org.eclipse.hawkbit.repository.jpa.management.JpaDeploymentManagement.MaxAssignmentsExceededInfo;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
@@ -53,7 +49,7 @@ class OfflineDsAssignmentStrategy extends AbstractDsAssignmentStrategy {
|
||||
final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository,
|
||||
final QuotaManagement quotaManagement, final BooleanSupplier multiAssignmentsConfig,
|
||||
final BooleanSupplier confirmationFlowConfig, final RepositoryProperties repositoryProperties,
|
||||
final TriConsumer<Long, Long, AssignmentQuotaExceededException> maxAssignmentExceededHandler) {
|
||||
final Consumer<MaxAssignmentsExceededInfo> maxAssignmentExceededHandler) {
|
||||
super(targetRepository, afterCommit, actionRepository, actionStatusRepository,
|
||||
quotaManagement, multiAssignmentsConfig, confirmationFlowConfig, repositoryProperties, maxAssignmentExceededHandler);
|
||||
}
|
||||
@@ -128,8 +124,7 @@ class OfflineDsAssignmentStrategy extends AbstractDsAssignmentStrategy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> cancelActiveActions(final List<List<Long>> targetIds) {
|
||||
return Collections.emptySet();
|
||||
public void cancelActiveActions(final List<List<Long>> targetIds) {
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -137,14 +132,8 @@ class OfflineDsAssignmentStrategy extends AbstractDsAssignmentStrategy {
|
||||
// Not supported by offline case
|
||||
}
|
||||
|
||||
@Override
|
||||
void sendDeploymentEvents(final DistributionSetAssignmentResult assignmentResult) {
|
||||
// no need to send deployment events in the offline case
|
||||
}
|
||||
|
||||
@Override
|
||||
void sendDeploymentEvents(final List<DistributionSetAssignmentResult> assignmentResults) {
|
||||
// no need to send deployment events in the offline case
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -9,30 +9,25 @@
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.management;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.commons.collections4.ListUtils;
|
||||
import org.apache.commons.lang3.function.TriConsumer;
|
||||
import org.eclipse.hawkbit.repository.QuotaManagement;
|
||||
import org.eclipse.hawkbit.repository.RepositoryProperties;
|
||||
import org.eclipse.hawkbit.repository.event.EventPublisherHolder;
|
||||
import org.eclipse.hawkbit.repository.event.remote.MultiActionAssignEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.MultiActionCancelEvent;
|
||||
import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent;
|
||||
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
|
||||
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
|
||||
import org.eclipse.hawkbit.repository.jpa.acm.AccessController;
|
||||
import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
|
||||
import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor;
|
||||
import org.eclipse.hawkbit.repository.jpa.management.JpaDeploymentManagement.MaxAssignmentsExceededInfo;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaActionStatus;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
@@ -59,7 +54,7 @@ class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy {
|
||||
final ActionRepository actionRepository, final ActionStatusRepository actionStatusRepository,
|
||||
final QuotaManagement quotaManagement, final BooleanSupplier multiAssignmentsConfig,
|
||||
final BooleanSupplier confirmationFlowConfig, final RepositoryProperties repositoryProperties,
|
||||
final TriConsumer<Long, Long, AssignmentQuotaExceededException> maxAssignmentExceededHandler) {
|
||||
final Consumer<MaxAssignmentsExceededInfo> maxAssignmentExceededHandler) {
|
||||
super(targetRepository, afterCommit, actionRepository, actionStatusRepository,
|
||||
quotaManagement, multiAssignmentsConfig, confirmationFlowConfig, repositoryProperties, maxAssignmentExceededHandler);
|
||||
}
|
||||
@@ -129,7 +124,8 @@ class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAssignedDistributionSetAndTargetStatus(final JpaDistributionSet set, final List<List<Long>> targetIds, final String currentUser) {
|
||||
public void setAssignedDistributionSetAndTargetStatus(final JpaDistributionSet set, final List<List<Long>> targetIds,
|
||||
final String currentUser) {
|
||||
final long now = System.currentTimeMillis();
|
||||
targetIds.forEach(targetIdsChunk -> {
|
||||
if (targetRepository.count(AccessController.Operation.UPDATE,
|
||||
@@ -154,8 +150,8 @@ class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Long> cancelActiveActions(final List<List<Long>> targetIds) {
|
||||
return targetIds.stream().map(this::overrideObsoleteUpdateActions).flatMap(Collection::stream).collect(Collectors.toSet());
|
||||
public void cancelActiveActions(final List<List<Long>> targetIds) {
|
||||
targetIds.forEach(this::overrideObsoleteUpdateActions);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -163,15 +159,6 @@ class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy {
|
||||
targetIds.forEach(this::closeObsoleteUpdateActions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDeploymentEvents(final DistributionSetAssignmentResult assignmentResult) {
|
||||
if (isMultiAssignmentsEnabled()) {
|
||||
sendDeploymentEvents(Collections.singletonList(assignmentResult));
|
||||
} else {
|
||||
sendDistributionSetAssignedEvent(assignmentResult);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendDeploymentEvents(final List<DistributionSetAssignmentResult> assignmentResults) {
|
||||
if (isMultiAssignmentsEnabled()) {
|
||||
@@ -190,7 +177,7 @@ class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy {
|
||||
}
|
||||
|
||||
void sendCancellationMessages(final List<JpaAction> actions, final String tenant) {
|
||||
if(isMultiAssignmentsEnabled()) {
|
||||
if (isMultiAssignmentsEnabled()) {
|
||||
sendMultiActionCancelEvent(tenant, Collections.unmodifiableList(actions));
|
||||
} else {
|
||||
actions.forEach(this::cancelAssignDistributionSetEvent);
|
||||
@@ -224,12 +211,10 @@ class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy {
|
||||
sendMultiActionAssignEvent(tenant, filteredActions);
|
||||
}
|
||||
|
||||
private DistributionSetAssignmentResult sendDistributionSetAssignedEvent(
|
||||
final DistributionSetAssignmentResult assignmentResult) {
|
||||
private void sendDistributionSetAssignedEvent(final DistributionSetAssignmentResult assignmentResult) {
|
||||
final List<Action> filteredActions = filterCancellations(assignmentResult.getAssignedEntity()).toList();
|
||||
final DistributionSet set = assignmentResult.getDistributionSet();
|
||||
sendTargetAssignDistributionSetEvent(set.getTenant(), set.getId(), filteredActions);
|
||||
return assignmentResult;
|
||||
}
|
||||
|
||||
private void sendTargetAssignDistributionSetEvent(final String tenant, final long distributionSetId,
|
||||
|
||||
@@ -320,15 +320,4 @@ public interface ActionRepository extends BaseEntityRepository<JpaAction> {
|
||||
@Transactional
|
||||
@Query("UPDATE JpaAction a SET a.externalRef = :externalRef WHERE a.id = :actionId")
|
||||
void updateExternalRef(@Param("actionId") Long actionId, @Param("externalRef") String externalRef);
|
||||
|
||||
/**
|
||||
* Deletes all actions with the given IDs.
|
||||
*
|
||||
* @param actionIDs the IDs of the actions to be deleted.
|
||||
*/
|
||||
@Modifying
|
||||
@Transactional
|
||||
// Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477
|
||||
@Query("DELETE FROM JpaAction a WHERE a.id IN ?1")
|
||||
void deleteByIdIn(Collection<Long> actionIDs);
|
||||
}
|
||||
@@ -43,11 +43,6 @@ public final class ActionSpecifications {
|
||||
cb.equal(root.get(JpaAction_.active), true));
|
||||
}
|
||||
|
||||
public static Specification<JpaAction> byIdIn(final List<Long> actionIds) {
|
||||
return ((root, query, cb) ->
|
||||
root.get(AbstractJpaBaseEntity_.id).in(actionIds));
|
||||
}
|
||||
|
||||
public static Specification<JpaAction> byTargetControllerId(final String controllerId) {
|
||||
return (root, query, cb) -> cb.equal(root.get(JpaAction_.target).get(JpaTarget_.controllerId), controllerId);
|
||||
}
|
||||
|
||||
@@ -53,12 +53,12 @@ public final class TargetSpecifications {
|
||||
/**
|
||||
* {@link Specification} for retrieving {@link Target}s including {@link TargetTag}s.
|
||||
*
|
||||
* @param controllerIDs to search for
|
||||
* @param controllerIds to search for
|
||||
* @return the {@link Target} {@link Specification}
|
||||
*/
|
||||
public static Specification<JpaTarget> byControllerIdWithTagsInJoin(final Collection<String> controllerIDs) {
|
||||
public static Specification<JpaTarget> byControllerIdWithTagsInJoin(final Collection<String> controllerIds) {
|
||||
return (targetRoot, query, cb) -> {
|
||||
final Predicate predicate = targetRoot.get(JpaTarget_.controllerId).in(controllerIDs);
|
||||
final Predicate predicate = targetRoot.get(JpaTarget_.controllerId).in(controllerIds);
|
||||
targetRoot.fetch(JpaTarget_.tags, JoinType.LEFT);
|
||||
query.distinct(true);
|
||||
return predicate;
|
||||
|
||||
Reference in New Issue
Block a user