diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java index 213e244b39..1e5bbdad80 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DeploymentManagement.java @@ -403,6 +403,7 @@ Slice findActionsByTarget(@NotNull String rsqlParam, @NotEmpty String co * @return assigned {@link DistributionSet} * @throws EntityNotFoundException if target with given ID does not exist */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) Optional getAssignedDistributionSet(@NotEmpty String controllerId); /** @@ -413,6 +414,7 @@ Slice findActionsByTarget(@NotNull String rsqlParam, @NotEmpty String co * @return installed {@link DistributionSet} * @throws EntityNotFoundException if target with given ID does not exist */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) Optional getInstalledDistributionSet(@NotEmpty String controllerId); /** diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetInvalidationManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetInvalidationManagement.java index a6646208b9..2a92efce07 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetInvalidationManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/DistributionSetInvalidationManagement.java @@ -12,6 +12,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSet; import org.eclipse.hawkbit.repository.model.DistributionSetInvalidation; import org.eclipse.hawkbit.repository.model.DistributionSetInvalidationCount; +import org.springframework.security.access.prepost.PreAuthorize; /** * A DistributionSetInvalidationManagement service provides operations to @@ -24,6 +25,8 @@ public interface DistributionSetInvalidationManagement { * cancels all auto assignments referring this {@link DistributionSet} and * can not be undone. Optionally, all rollouts and actions referring this * {@link DistributionSet} can be canceled. + *

+ * {@link PreAuthorize} missing intentionally as it relies on the permission set defined in the management api methods that it calls internally. * * @param distributionSetInvalidation defines the {@link DistributionSet} and options what should be * canceled @@ -33,6 +36,8 @@ public interface DistributionSetInvalidationManagement { /** * Counts all entities for a list of {@link DistributionSet}s that will be * canceled when invalidation is called for those {@link DistributionSet}s. + *

+ * {@link PreAuthorize} missing intentionally as it relies on the permission set defined in the management api methods that it calls internally. * * @param distributionSetInvalidation defines the {@link DistributionSet} and options what should be * canceled 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 67c9516fe2..dde94197ad 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 @@ -59,8 +59,7 @@ public interface TargetManagement { * @return number of found {@link Target}s. * @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) + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET) long countByAssignedDistributionSet(long distributionSetId); /** @@ -81,8 +80,7 @@ public interface TargetManagement { * @return number of found {@link Target}s. * @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) + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET) long countByInstalledDistributionSet(long distributionSetId); /** @@ -93,8 +91,7 @@ public interface TargetManagement { * @return true if a {@link Target} exists. * @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) + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET) boolean existsByInstalledOrAssignedDistributionSet(long distributionSetId); /** @@ -225,7 +222,7 @@ public interface TargetManagement { * @return a page of the found {@link Target}s * @throws EntityNotFoundException if distribution set with given ID does not exist */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET) + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET) Slice findByTargetFilterQueryAndNonDSAndCompatibleAndUpdatable(@NotNull Pageable pageRequest, long distributionSetId, @NotNull String rsqlParam); @@ -239,7 +236,7 @@ Slice findByTargetFilterQueryAndNonDSAndCompatibleAndUpdatable(@NotNull * @return the count of found {@link Target}s * @throws EntityNotFoundException if distribution set with given ID does not exist */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET) + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_READ_TARGET) long countByRsqlAndNonDSAndCompatibleAndUpdatable(long distributionSetId, @NotNull String rsqlParam); /** @@ -254,17 +251,17 @@ Slice findByTargetFilterQueryAndNonDSAndCompatibleAndUpdatable(@NotNull * withs * @return a page of the found {@link Target}s */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET) + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ) Slice findByTargetFilterQueryAndNotInRolloutGroupsAndCompatibleAndUpdatable(@NotNull Pageable pageRequest, @NotEmpty Collection groups, @NotNull String targetFilterQuery, @NotNull DistributionSetType distributionSetType); - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET) + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ) Slice findByNotInGEGroupAndNotInActiveActionGEWeightOrInRolloutAndTargetFilterQueryAndCompatibleAndUpdatable( @NotNull Pageable pageRequest, final long rolloutId, final int weight, final long firstGroupId, @NotNull String targetFilterQuery, @NotNull DistributionSetType distributionSetType); - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ) long countByActionsInRolloutGroup(final long rolloutGroupId); /** @@ -277,7 +274,7 @@ Slice findByNotInGEGroupAndNotInActiveActionGEWeightOrInRolloutAndTarget * @param rolloutId rolloutId of the rollout to be retried. * @return a page of the found {@link Target}s */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ) Slice findByFailedRolloutAndNotInRolloutGroups(@NotNull Pageable pageRequest, @NotEmpty Collection groups, @NotNull String rolloutId); @@ -292,7 +289,7 @@ Slice findByFailedRolloutAndNotInRolloutGroups(@NotNull Pageable pageReq * with * @return count of the found {@link Target}s */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET) + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ) long countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(@NotEmpty Collection groups, @NotNull String rsqlParam, @NotNull DistributionSetType distributionSetType); @@ -305,7 +302,7 @@ long countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(@NotEmpty Collect * @param rolloutId rolloutId of the rollout to be retried. * @return count of the found {@link Target}s */ - @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_TARGET) + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ) long countByFailedRolloutAndNotInRolloutGroups(@NotEmpty Collection groups, @NotNull String rolloutId); /** @@ -526,9 +523,7 @@ Page findByInstalledDistributionSetAndRsql(@NotNull Pageable pageReq, lo * @throws EntityNotFoundException if given targetTagId or at least one of the targets do not exist */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET) - default List assignTag(@NotEmpty Collection controllerIds, long targetTagId) { - return assignTag(controllerIds, targetTagId, null); - } + List assignTag(@NotEmpty Collection controllerIds, long targetTagId); /** * Un-assign a {@link TargetTag} assignment to given {@link Target}s. @@ -551,9 +546,7 @@ default List assignTag(@NotEmpty Collection controllerIds, long * @throws EntityNotFoundException if given targetTagId or at least one of the targets do not exist */ @PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET) - default List unassignTag(@NotEmpty Collection controllerIds, long targetTagId) { - return unassignTag(controllerIds, targetTagId, null); - } + List unassignTag(@NotEmpty Collection controllerIds, long targetTagId); /** * Un-assign a {@link TargetType} assignment to given {@link Target}. diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantConfigurationManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantConfigurationManagement.java index 5390e7287e..c3c9bd8146 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantConfigurationManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/TenantConfigurationManagement.java @@ -10,10 +10,6 @@ package org.eclipse.hawkbit.repository; import java.io.Serializable; -import java.time.Duration; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; import java.util.Map; import java.util.function.Function; @@ -22,8 +18,6 @@ import org.eclipse.hawkbit.repository.model.PollStatus; import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; -import org.eclipse.hawkbit.tenancy.configuration.DurationHelper; -import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.env.Environment; import org.springframework.security.access.prepost.PreAuthorize; @@ -126,25 +120,6 @@ TenantConfigurationValue getConfigurationValue(Strin @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION_READ) T getGlobalConfigurationValue(String configurationKeyName, Class propertyType); - // PreAuthorize for TENANT_CONFIGURATION_READ won't be applied but actually we want just read target @PreAuthorize(value = SpringEvalExpressions.HAS_AUTH_READ_TARGET) - default Function pollStatusResolver() { - final Duration pollTime = DurationHelper.formattedStringToDuration( - getConfigurationValue(TenantConfigurationKey.POLLING_TIME_INTERVAL, String.class).getValue()); - final Duration overdueTime = DurationHelper.formattedStringToDuration( - getConfigurationValue(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL, String.class) - .getValue()); - return target -> { - final Long lastTargetQuery = target.getLastTargetQuery(); - if (lastTargetQuery == null) { - return null; - } - final LocalDateTime currentDate = LocalDateTime.now(); - final LocalDateTime lastPollDate = LocalDateTime.ofInstant(Instant.ofEpochMilli(lastTargetQuery), - ZoneId.systemDefault()); - final LocalDateTime nextPollDate = lastPollDate.plus(pollTime); - final LocalDateTime overdueDate = nextPollDate.plus(overdueTime); - return new PollStatus(lastPollDate, nextPollDate, overdueDate, currentDate); - }; - } + Function pollStatusResolver(); } 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 a3847b5b8c..dee3f8d157 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 @@ -530,6 +530,19 @@ public TargetTypeAssignmentResult unassignType(final Collection controll backoff = @Backoff(delay = Constants.TX_RT_DELAY)) public List assignTag(final Collection controllerIds, final long targetTagId, final Consumer> notFoundHandler) { + return assignTag0(controllerIds, targetTagId, notFoundHandler); + } + + @Override + @Transactional + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, + backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public List assignTag(final Collection controllerIds, final long targetTagId) { + return assignTag0(controllerIds, targetTagId, null); + } + + private List assignTag0(final Collection controllerIds, final long targetTagId, + final Consumer> notFoundHandler) { return updateTag(controllerIds, targetTagId, notFoundHandler, (tag, target) -> { if (target.getTags().contains(tag)) { return target; @@ -546,6 +559,19 @@ public List assignTag(final Collection controllerIds, final long backoff = @Backoff(delay = Constants.TX_RT_DELAY)) public List unassignTag(final Collection controllerIds, final long targetTagId, final Consumer> notFoundHandler) { + return unassignTag0(controllerIds, targetTagId, notFoundHandler); + } + + @Override + @Transactional + @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, + backoff = @Backoff(delay = Constants.TX_RT_DELAY)) + public List unassignTag(final Collection controllerIds, final long targetTagId) { + return unassignTag0(controllerIds, targetTagId, null); + } + + private List unassignTag0(final Collection controllerIds, final long targetTagId, + final Consumer> notFoundHandler) { return updateTag(controllerIds, targetTagId, notFoundHandler, (tag, target) -> { if (target.getTags().contains(tag)) { target.removeTag(tag); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java index 19a778d9b1..aa522c6894 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaTenantConfigurationManagement.java @@ -14,10 +14,15 @@ import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED; import java.io.Serializable; +import java.time.Duration; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; @@ -30,10 +35,13 @@ import org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor; import org.eclipse.hawkbit.repository.jpa.model.JpaTenantConfiguration; import org.eclipse.hawkbit.repository.jpa.repository.TenantConfigurationRepository; +import org.eclipse.hawkbit.repository.model.PollStatus; +import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TenantConfiguration; import org.eclipse.hawkbit.repository.model.TenantConfigurationValue; import org.eclipse.hawkbit.repository.model.helper.SystemSecurityContextHolder; import org.eclipse.hawkbit.security.SystemSecurityContext; +import org.eclipse.hawkbit.tenancy.configuration.DurationHelper; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; import org.springframework.beans.factory.annotation.Autowired; @@ -146,6 +154,27 @@ public T getGlobalConfigurationValue(final String configurationKeyName, fina return CONVERSION_SERVICE.convert(key.getDefaultValue(), propertyType); } + @Override + public Function pollStatusResolver() { + final Duration pollTime = DurationHelper.formattedStringToDuration( + getConfigurationValue(TenantConfigurationKey.POLLING_TIME_INTERVAL, String.class).getValue()); + final Duration overdueTime = DurationHelper.formattedStringToDuration( + getConfigurationValue(TenantConfigurationKey.POLLING_OVERDUE_TIME_INTERVAL, String.class) + .getValue()); + return target -> { + final Long lastTargetQuery = target.getLastTargetQuery(); + if (lastTargetQuery == null) { + return null; + } + final LocalDateTime currentDate = LocalDateTime.now(); + final LocalDateTime lastPollDate = LocalDateTime.ofInstant(Instant.ofEpochMilli(lastTargetQuery), + ZoneId.systemDefault()); + final LocalDateTime nextPollDate = lastPollDate.plus(pollTime); + final LocalDateTime overdueDate = nextPollDate.plus(overdueTime); + return new PollStatus(lastPollDate, nextPollDate, overdueDate, currentDate); + }; + } + /** * Validates the data type of the tenant configuration. If it is possible to * cast to the given data type.