From 8e890424c03867b574da7622d9fadfd2ce6ca8a1 Mon Sep 17 00:00:00 2001 From: Kai Zimmermann Date: Tue, 10 Oct 2017 17:26:43 +0200 Subject: [PATCH] Optional support for autoclose of deprecated actions (#585) * Introduce action autoclose into repository. Signed-off-by: kaizimmerm * Extended test. Signed-off-by: kaizimmerm * Fix typo. Signed-off-by: kaizimmerm * Added checkbox to management ui. Signed-off-by: kaizimmerm * Fix Ui allignment. Signed-off-by: kaizimmerm * Fix item ID. Signed-off-by: kaizimmerm * Fix sonar issues. Signed-off-by: kaizimmerm * readibility. Signed-off-by: kaizimmerm --- .../ddi/rest/resource/DdiRootController.java | 4 +- .../resource/DdiArtifactDownloadTest.java | 10 +- .../TenantConfigurationProperties.java | 6 + .../hawkbit-repository-defaults.properties | 5 + .../jpa/AbstractDsAssignmentStrategy.java | 48 ++++++- .../repository/jpa/ActionRepository.java | 15 ++- .../jpa/JpaDeploymentManagement.java | 22 ++- .../jpa/JpaTargetFilterQueryManagement.java | 5 +- .../jpa/JpaTenantStatsManagement.java | 2 +- .../jpa/OfflineDsAssignmentStrategy.java | 7 +- .../jpa/OnlineDsAssignmentStrategy.java | 7 +- .../RepositoryApplicationConfiguration.java | 6 +- .../jpa/model/JpaDistributionSet.java | 2 +- .../jpa/DeploymentManagementTest.java | 47 +++++++ .../AuthenticationConfigurationView.java | 9 +- .../RepositoryConfigurationView.java | 125 ++++++++++++++++++ .../TenantConfigurationDashboardView.java | 6 + ...wnloadAuthenticationConfigurationItem.java | 3 +- ...ficateAuthenticationConfigurationItem.java | 3 +- ...yTokenAuthenticationConfigurationItem.java | 3 +- ...yTokenAuthenticationConfigurationItem.java | 3 +- ...stractBooleanTenantConfigurationItem.java} | 8 +- .../BooleanConfigurationItem.java} | 22 +-- .../ActionAutocloseConfigurationItem.java | 65 +++++++++ .../ui/utils/UIComponentIdProvider.java | 8 ++ .../src/main/resources/messages.properties | 2 + 26 files changed, 392 insertions(+), 51 deletions(-) create mode 100644 hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/RepositoryConfigurationView.java rename hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/{authentication/AbstractAuthenticationTenantConfigurationItem.java => generic/AbstractBooleanTenantConfigurationItem.java} (91%) rename hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/{authentication/AuthenticationConfigurationItem.java => generic/BooleanConfigurationItem.java} (63%) create mode 100644 hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/repository/ActionAutocloseConfigurationItem.java diff --git a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java b/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java index 7edf70c73..71c955149 100644 --- a/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java +++ b/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DdiRootController.java @@ -221,7 +221,7 @@ public class DdiRootController implements DdiRootControllerRestApi { @PathVariable("controllerId") final String controllerId, @PathVariable("softwareModuleId") final Long softwareModuleId, @PathVariable("fileName") final String fileName) { - controllerManagement.getByControllerId(controllerId) + final Target target = controllerManagement.getByControllerId(controllerId) .orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); final SoftwareModule module = controllerManagement.getSoftwareModule(softwareModuleId) @@ -235,6 +235,8 @@ public class DdiRootController implements DdiRootControllerRestApi { final Artifact artifact = module.getArtifactByFilename(fileName) .orElseThrow(() -> new EntityNotFoundException(Artifact.class, fileName)); + checkAndLogDownload(requestResponseContextHolder.getHttpServletRequest(), target, module.getId()); + try { FileStreamingUtil.writeMD5FileResponse(requestResponseContextHolder.getHttpServletResponse(), artifact.getMd5Hash(), fileName); diff --git a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java index 982d1547d..948991263 100644 --- a/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java +++ b/hawkbit-ddi-resource/src/test/java/org/eclipse/hawkbit/ddi/rest/resource/DdiArtifactDownloadTest.java @@ -208,10 +208,12 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest { // create ds final DistributionSet ds = testdataFactory.createDistributionSet(""); + assignDistributionSet(ds, target); + // create artifact final byte random[] = RandomUtils.nextBytes(5 * 1024); - final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), - "file1", false); + final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), "file1", + false); // download final MvcResult result = mvc @@ -242,8 +244,8 @@ public class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest { // create artifact final byte random[] = RandomUtils.nextBytes(resultLength); - final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), - "file1", false); + final Artifact artifact = artifactManagement.create(new ByteArrayInputStream(random), getOsModule(ds), "file1", + false); assertThat(random.length).isEqualTo(resultLength); diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/tenancy/configuration/TenantConfigurationProperties.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/tenancy/configuration/TenantConfigurationProperties.java index c5800e4c2..acae2d49f 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/tenancy/configuration/TenantConfigurationProperties.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/tenancy/configuration/TenantConfigurationProperties.java @@ -102,6 +102,12 @@ public class TenantConfigurationProperties { */ public static final String ANONYMOUS_DOWNLOAD_MODE_ENABLED = "anonymous.download.enabled"; + /** + * Repository on autoclose mode instead of canceling in case of new DS + * assignment over active actions. + */ + public static final String REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED = "repository.actions.autoclose.enabled"; + private String keyName; private String defaultValue = ""; private Class dataType = String.class; diff --git a/hawkbit-repository/hawkbit-repository-core/src/main/resources/hawkbit-repository-defaults.properties b/hawkbit-repository/hawkbit-repository-core/src/main/resources/hawkbit-repository-defaults.properties index 287df0101..6576d4a77 100644 --- a/hawkbit-repository/hawkbit-repository-core/src/main/resources/hawkbit-repository-defaults.properties +++ b/hawkbit-repository/hawkbit-repository-core/src/main/resources/hawkbit-repository-defaults.properties @@ -20,6 +20,11 @@ hawkbit.server.tenant.configuration.authentication-header-enabled.defaultValue=$ hawkbit.server.tenant.configuration.authentication-header-enabled.dataType=java.lang.Boolean hawkbit.server.tenant.configuration.authentication-header-enabled.validator=org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationBooleanValidator +hawkbit.server.tenant.configuration.repository-actions-autoclose-enabled.keyName=repository.actions.autoclose.enabled +hawkbit.server.tenant.configuration.repository-actions-autoclose-enabled.defaultValue=false +hawkbit.server.tenant.configuration.repository-actions-autoclose-enabled.dataType=java.lang.Boolean +hawkbit.server.tenant.configuration.repository-actions-autoclose-enabled.validator=org.eclipse.hawkbit.tenancy.configuration.validator.TenantConfigurationBooleanValidator + hawkbit.server.tenant.configuration.authentication-header-authority.keyName=authentication.header.authority hawkbit.server.tenant.configuration.authentication-header-authority.defaultValue=${hawkbit.server.ddi.security.authentication.header.authority} diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/AbstractDsAssignmentStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/AbstractDsAssignmentStrategy.java index 66b50500a..bd52a5f5d 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/AbstractDsAssignmentStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/AbstractDsAssignmentStrategy.java @@ -92,7 +92,19 @@ public abstract class AbstractDsAssignmentStrategy { * to cancel actions for * @return {@link Set} of {@link Target#getId()}s */ - abstract Set findTargetIdsToCancel(List> targetIds); + abstract Set cancelActiveActions(List> targetIds); + + /** + * Cancels actions that can be canceled (i.e. + * {@link DistributionSet#isRequiredMigrationStep() is false}) + * as a result of the new assignment and returns all {@link Target}s where + * such actions existed. + * + * @param targetIds + * to cancel actions for + * @return {@link Set} of {@link Target#getId()}s + */ + abstract void closeActiveActions(List> targetIds); /** * Handles event sending related to the assignment. @@ -119,7 +131,7 @@ public abstract class AbstractDsAssignmentStrategy { } /** - * Removes {@link Action}s that are no longer necessary and sends + * Cancels {@link Action}s that are no longer necessary and sends * cancellations to the controller. * * @param targetsIds @@ -130,8 +142,8 @@ public abstract class AbstractDsAssignmentStrategy { // Figure out if there are potential target/action combinations that // need to be considered for cancellation final List activeActions = actionRepository - .findByActiveAndTargetIdInAndActionStatusNotEqualToAndDistributionSetRequiredMigrationStep(targetsIds, - Action.Status.CANCELING); + .findByActiveAndTargetIdInAndActionStatusNotEqualToAndDistributionSetNotRequiredMigrationStep( + targetsIds, Action.Status.CANCELING); return activeActions.stream().map(action -> { action.setStatus(Status.CANCELING); @@ -148,6 +160,34 @@ public abstract class AbstractDsAssignmentStrategy { } + /** + * Closes {@link Action}s that are no longer necessary without sending a + * hint to the controller. + * + * @param targetsIds + * to override {@link Action}s + */ + protected List closeObsoleteUpdateActions(final Collection targetsIds) { + + // Figure out if there are potential target/action combinations that + // need to be considered for cancellation + final List activeActions = actionRepository + .findByActiveAndTargetIdInAndDistributionSetNotRequiredMigrationStep(targetsIds); + + return activeActions.stream().map(action -> { + action.setStatus(Status.CANCELED); + action.setActive(false); + + // document that the status has been retrieved + 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(); + }).collect(Collectors.toList()); + + } + /** * Sends the {@link CancelTargetAssignmentEvent} for a specific target to * the eventPublisher. diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/ActionRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/ActionRepository.java index d6879b6c5..2c0a9efa8 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/ActionRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/ActionRepository.java @@ -219,9 +219,22 @@ public interface ActionRepository extends BaseEntityRepository, */ @EntityGraph(attributePaths = { "target" }, type = EntityGraphType.LOAD) @Query("SELECT a FROM JpaAction a WHERE a.active = true AND a.distributionSet.requiredMigrationStep = false AND a.target IN ?1 AND a.status != ?2") - List findByActiveAndTargetIdInAndActionStatusNotEqualToAndDistributionSetRequiredMigrationStep( + List findByActiveAndTargetIdInAndActionStatusNotEqualToAndDistributionSetNotRequiredMigrationStep( Collection targetIds, Action.Status notStatus); + /** + * + * Retrieves all {@link Action}s which are active and referring to the given + * target Ids and distribution set required migration step. + * + * @param targetIds + * the IDs of targets for the actions + * @return the found list of {@link Action}s + */ + @EntityGraph(attributePaths = { "target" }, type = EntityGraphType.LOAD) + @Query("SELECT a FROM JpaAction a WHERE a.active = true AND a.distributionSet.requiredMigrationStep = false AND a.target IN ?1") + List findByActiveAndTargetIdInAndDistributionSetNotRequiredMigrationStep(Collection targetIds); + /** * Counts all {@link Action}s referring to the given target. * diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java index 406847596..d2ed67bcf 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaDeploymentManagement.java @@ -30,6 +30,7 @@ import org.eclipse.hawkbit.repository.ActionFields; import org.eclipse.hawkbit.repository.DeploymentManagement; import org.eclipse.hawkbit.repository.RepositoryConstants; import org.eclipse.hawkbit.repository.TargetManagement; +import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.repository.event.remote.TargetAssignDistributionSetEvent; import org.eclipse.hawkbit.repository.exception.CancelActionNotAllowedException; import org.eclipse.hawkbit.repository.exception.EntityNotFoundException; @@ -57,6 +58,8 @@ import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetWithActionType; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; +import org.eclipse.hawkbit.security.SystemSecurityContext; +import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationContext; @@ -109,13 +112,17 @@ public class JpaDeploymentManagement implements DeploymentManagement { private final PlatformTransactionManager txManager; private final OnlineDsAssignmentStrategy onlineDsAssignmentStrategy; private final OfflineDsAssignmentStrategy offlineDsAssignmentStrategy; + private final TenantConfigurationManagement tenantConfigurationManagement; + private final SystemSecurityContext systemSecurityContext; JpaDeploymentManagement(final EntityManager entityManager, final ActionRepository actionRepository, final DistributionSetRepository distributionSetRepository, final TargetRepository targetRepository, final ActionStatusRepository actionStatusRepository, final TargetManagement targetManagement, final AuditorAware auditorProvider, final ApplicationEventPublisher eventPublisher, final ApplicationContext applicationContext, final AfterTransactionCommitExecutor afterCommit, - final VirtualPropertyReplacer virtualPropertyReplacer, final PlatformTransactionManager txManager) { + final VirtualPropertyReplacer virtualPropertyReplacer, final PlatformTransactionManager txManager, + final TenantConfigurationManagement tenantConfigurationManagement, + final SystemSecurityContext systemSecurityContext) { this.entityManager = entityManager; this.actionRepository = actionRepository; this.distributionSetRepository = distributionSetRepository; @@ -132,6 +139,8 @@ public class JpaDeploymentManagement implements DeploymentManagement { applicationContext, actionRepository, actionStatusRepository); offlineDsAssignmentStrategy = new OfflineDsAssignmentStrategy(targetRepository, afterCommit, eventPublisher, applicationContext, actionRepository, actionStatusRepository); + this.tenantConfigurationManagement = tenantConfigurationManagement; + this.systemSecurityContext = systemSecurityContext; } @Override @@ -254,7 +263,16 @@ public class JpaDeploymentManagement implements DeploymentManagement { // need to remember which one we have been switched to canceling state // because for targets which we have changed to canceling we don't want // to publish the new action update event. - final Set targetIdsCancellList = assignmentStrategy.findTargetIdsToCancel(targetIds); + final Set targetIdsCancellList; + + if (systemSecurityContext.runAsSystem(() -> tenantConfigurationManagement + .getConfigurationValue(TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, Boolean.class) + .getValue())) { + targetIdsCancellList = Collections.emptySet(); + assignmentStrategy.closeActiveActions(targetIds); + } else { + targetIdsCancellList = assignmentStrategy.cancelActiveActions(targetIds); + } // cancel all scheduled actions which are in-active, these actions were // not active before and the manual assignment which has been done diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java index 883ca63ac..d302f3d38 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTargetFilterQueryManagement.java @@ -85,8 +85,9 @@ public class JpaTargetFilterQueryManagement implements TargetFilterQueryManageme @Retryable(include = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) public void delete(final Long targetFilterQueryId) { - get(targetFilterQueryId) - .orElseThrow(() -> new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId)); + if (!targetFilterQueryRepository.exists(targetFilterQueryId)) { + throw new EntityNotFoundException(TargetFilterQuery.class, targetFilterQueryId); + } targetFilterQueryRepository.delete(targetFilterQueryId); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTenantStatsManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTenantStatsManagement.java index 321dcdb3c..b5f4b1ec4 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTenantStatsManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/JpaTenantStatsManagement.java @@ -44,7 +44,7 @@ public class JpaTenantStatsManagement implements TenantStatsManagement { result.setTargets(targetRepository.count()); result.setArtifacts(artifactRepository.countBySoftwareModuleDeleted(false)); - artifactRepository.getSumOfUndeletedArtifactSize().map(result::setOverallArtifactVolumeInBytes); + artifactRepository.getSumOfUndeletedArtifactSize().ifPresent(result::setOverallArtifactVolumeInBytes); result.setActions(actionRepository.count()); return result; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/OfflineDsAssignmentStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/OfflineDsAssignmentStrategy.java index 671eecf44..1fb831718 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/OfflineDsAssignmentStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/OfflineDsAssignmentStrategy.java @@ -67,10 +67,15 @@ public class OfflineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { } @Override - public Set findTargetIdsToCancel(final List> targetIds) { + public Set cancelActiveActions(final List> targetIds) { return Collections.emptySet(); } + @Override + void closeActiveActions(final List> targetIds) { + // Not supported by offline case + } + @Override void updateTargetStatus(final JpaDistributionSet set, final List> targetIds, final String currentUser) { targetIds.forEach(tIds -> targetRepository.setAssignedAndInstalledDistributionSetAndUpdateStatus( diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/OnlineDsAssignmentStrategy.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/OnlineDsAssignmentStrategy.java index 3f6b0d3d0..4f42987bf 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/OnlineDsAssignmentStrategy.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/OnlineDsAssignmentStrategy.java @@ -67,11 +67,16 @@ public class OnlineDsAssignmentStrategy extends AbstractDsAssignmentStrategy { } @Override - Set findTargetIdsToCancel(final List> targetIds) { + Set cancelActiveActions(final List> targetIds) { return targetIds.stream().map(this::overrideObsoleteUpdateActions).flatMap(Collection::stream) .collect(Collectors.toSet()); } + @Override + void closeActiveActions(final List> targetIds) { + targetIds.forEach(this::closeObsoleteUpdateActions); + } + @Override void updateTargetStatus(final JpaDistributionSet set, final List> targetIds, final String currentUser) { targetIds.forEach(tIds -> targetRepository.setAssignedDistributionSetAndUpdateStatus(TargetUpdateStatus.PENDING, 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 b6684e39a..b70a6acbb 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 @@ -531,10 +531,12 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration { final TargetManagement targetManagement, final AuditorAware auditorProvider, final ApplicationEventPublisher eventPublisher, final ApplicationContext applicationContext, final AfterTransactionCommitExecutor afterCommit, final VirtualPropertyReplacer virtualPropertyReplacer, - final PlatformTransactionManager txManager) { + final PlatformTransactionManager txManager, + final TenantConfigurationManagement tenantConfigurationManagement, + final SystemSecurityContext systemSecurityContext) { return new JpaDeploymentManagement(entityManager, actionRepository, distributionSetRepository, targetRepository, actionStatusRepository, targetManagement, auditorProvider, eventPublisher, applicationContext, - afterCommit, virtualPropertyReplacer, txManager); + afterCommit, virtualPropertyReplacer, txManager, tenantConfigurationManagement, systemSecurityContext); } /** diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java index 9ff4962f3..16349fea4 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSet.java @@ -272,7 +272,7 @@ public class JpaDistributionSet extends AbstractJpaNamedVersionedEntity implemen if (allready >= softwareModule.getType().getMaxAssignments()) { modules.stream().filter(module -> module.getType().getKey().equals(softwareModule.getType().getKey())) - .findAny().map(modules::remove); + .findAny().ifPresent(modules::remove); } if (modules.add(softwareModule)) { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DeploymentManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DeploymentManagementTest.java index 7c09b4d6b..3a7f21016 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DeploymentManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/DeploymentManagementTest.java @@ -55,6 +55,7 @@ import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetWithActionType; import org.eclipse.hawkbit.repository.test.matcher.Expect; import org.eclipse.hawkbit.repository.test.matcher.ExpectEvents; +import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; import org.junit.Before; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -460,6 +461,52 @@ public class DeploymentManagementTest extends AbstractJpaIntegrationTest { .allMatch(target -> target.getLastModifiedAt().equals(target.getInstallationDate())); } + @Test + @Description("Verifies that if an account is set to action autoclose running actions in case of a new assigned set get closed and set to CANCELED.") + @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 10), + @Expect(type = TargetUpdatedEvent.class, count = 20), @Expect(type = ActionCreatedEvent.class, count = 20), + @Expect(type = ActionUpdatedEvent.class, count = 10), + @Expect(type = DistributionSetCreatedEvent.class, count = 2), + @Expect(type = SoftwareModuleCreatedEvent.class, count = 6), + @Expect(type = TargetAssignDistributionSetEvent.class, count = 20) }) + public void assigneDistributionSetAndAutoCloseActiveActions() { + tenantConfigurationManagement + .addOrUpdateConfiguration(TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, true); + + try { + final List targets = testdataFactory.createTargets(10); + + // First assignment + final DistributionSet ds1 = testdataFactory.createDistributionSet("1"); + assignDistributionSet(ds1, targets); + + List assignmentOne = actionRepository.findByDistributionSetId(PAGE, ds1.getId()).getContent(); + assertThat(assignmentOne).hasSize(10).as("Is active").allMatch(Action::isActive).as("Is assigned DS") + .allMatch(action -> action.getDistributionSet().getId() == ds1.getId()).as("Is running") + .allMatch(action -> action.getStatus() == Status.RUNNING); + + // Second assignment + final DistributionSet ds2 = testdataFactory.createDistributionSet("2"); + assignDistributionSet(ds2, targets); + + final List assignmentTwo = actionRepository.findByDistributionSetId(PAGE, ds2.getId()).getContent(); + assignmentOne = actionRepository.findByDistributionSetId(PAGE, ds1.getId()).getContent(); + assertThat(assignmentTwo).hasSize(10).as("Is active").allMatch(Action::isActive).as("Is assigned DS") + .allMatch(action -> action.getDistributionSet().getId() == ds2.getId()).as("Is running") + .allMatch(action -> action.getStatus() == Status.RUNNING); + assertThat(assignmentOne).hasSize(10).as("Is active").allMatch(action -> !action.isActive()) + .as("Is assigned to DS").allMatch(action -> action.getDistributionSet().getId() == ds1.getId()) + .as("Is cancelled").allMatch(action -> action.getStatus() == Status.CANCELED); + + assertThat(targetManagement.findByAssignedDistributionSet(PAGE, ds2.getId()).getContent()).hasSize(10) + .as("InstallationDate not set").allMatch(target -> (target.getInstallationDate() == null)); + + } finally { + tenantConfigurationManagement + .addOrUpdateConfiguration(TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, false); + } + } + /** * test a simple deployment by calling the * {@link TargetRepository#assignDistributionSet(DistributionSet, Iterable)} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/AuthenticationConfigurationView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/AuthenticationConfigurationView.java index 6add8fa05..d9aafa9f3 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/AuthenticationConfigurationView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/AuthenticationConfigurationView.java @@ -12,10 +12,10 @@ import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.security.SecurityTokenGenerator; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.tenantconfiguration.authentication.AnonymousDownloadAuthenticationConfigurationItem; -import org.eclipse.hawkbit.ui.tenantconfiguration.authentication.AuthenticationConfigurationItem; import org.eclipse.hawkbit.ui.tenantconfiguration.authentication.CertificateAuthenticationConfigurationItem; import org.eclipse.hawkbit.ui.tenantconfiguration.authentication.GatewaySecurityTokenAuthenticationConfigurationItem; import org.eclipse.hawkbit.ui.tenantconfiguration.authentication.TargetSecurityTokenAuthenticationConfigurationItem; +import org.eclipse.hawkbit.ui.tenantconfiguration.generic.BooleanConfigurationItem; import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; @@ -31,7 +31,7 @@ import com.vaadin.ui.VerticalLayout; * View to configure the authentication mode. */ public class AuthenticationConfigurationView extends BaseConfigurationView - implements ConfigurationGroup, ConfigurationItem.ConfigurationItemChangeListener, ValueChangeListener { + implements ConfigurationItem.ConfigurationItemChangeListener, ValueChangeListener { private static final String DIST_CHECKBOX_STYLE = "dist-checkbox-style"; @@ -55,7 +55,8 @@ public class AuthenticationConfigurationView extends BaseConfigurationView private CheckBox downloadAnonymousCheckBox; - AuthenticationConfigurationView(final VaadinMessageSource i18n, final TenantConfigurationManagement tenantConfigurationManagement, + AuthenticationConfigurationView(final VaadinMessageSource i18n, + final TenantConfigurationManagement tenantConfigurationManagement, final SecurityTokenGenerator securityTokenGenerator) { this.i18n = i18n; this.certificateAuthenticationConfigurationItem = new CertificateAuthenticationConfigurationItem( @@ -161,7 +162,7 @@ public class AuthenticationConfigurationView extends BaseConfigurationView notifyConfigurationChanged(); final CheckBox checkBox = (CheckBox) event.getProperty(); - AuthenticationConfigurationItem configurationItem; + BooleanConfigurationItem configurationItem; if (gatewaySecTokenCheckBox.equals(checkBox)) { configurationItem = gatewaySecurityTokenAuthenticationConfigurationItem; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/RepositoryConfigurationView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/RepositoryConfigurationView.java new file mode 100644 index 000000000..de4c0a0d3 --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/RepositoryConfigurationView.java @@ -0,0 +1,125 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.ui.tenantconfiguration; + +import org.eclipse.hawkbit.repository.TenantConfigurationManagement; +import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; +import org.eclipse.hawkbit.ui.tenantconfiguration.generic.BooleanConfigurationItem; +import org.eclipse.hawkbit.ui.tenantconfiguration.repository.ActionAutocloseConfigurationItem; +import org.eclipse.hawkbit.ui.utils.UIComponentIdProvider; +import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; + +import com.vaadin.data.Property.ValueChangeEvent; +import com.vaadin.data.Property.ValueChangeListener; +import com.vaadin.ui.CheckBox; +import com.vaadin.ui.GridLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.Panel; +import com.vaadin.ui.VerticalLayout; + +/** + * View to configure the authentication mode. + */ +public class RepositoryConfigurationView extends BaseConfigurationView + implements ConfigurationGroup, ConfigurationItem.ConfigurationItemChangeListener, ValueChangeListener { + + private static final String DIST_CHECKBOX_STYLE = "dist-checkbox-style"; + + private static final long serialVersionUID = 1L; + + private final VaadinMessageSource i18n; + + private final ActionAutocloseConfigurationItem actionAutocloseConfigurationItem; + + private CheckBox actionAutocloseCheckBox; + + RepositoryConfigurationView(final VaadinMessageSource i18n, + final TenantConfigurationManagement tenantConfigurationManagement) { + this.i18n = i18n; + this.actionAutocloseConfigurationItem = new ActionAutocloseConfigurationItem(tenantConfigurationManagement, + i18n); + + init(); + } + + private void init() { + + final Panel rootPanel = new Panel(); + rootPanel.setSizeFull(); + + rootPanel.addStyleName("config-panel"); + + final VerticalLayout vLayout = new VerticalLayout(); + vLayout.setMargin(true); + vLayout.setSizeFull(); + + final Label headerDisSetType = new Label(i18n.getMessage("configuration.repository.title")); + headerDisSetType.addStyleName("config-panel-header"); + vLayout.addComponent(headerDisSetType); + + final GridLayout gridLayout = new GridLayout(2, 1); + gridLayout.setSpacing(true); + gridLayout.setImmediate(true); + gridLayout.setColumnExpandRatio(1, 1.0F); + gridLayout.setSizeFull(); + + actionAutocloseCheckBox = SPUIComponentProvider.getCheckBox("", DIST_CHECKBOX_STYLE, null, false, ""); + actionAutocloseCheckBox.setId(UIComponentIdProvider.REPOSITORY_ACTIONS_AUTOCLOSE_CHECKBOX); + actionAutocloseCheckBox.setValue(actionAutocloseConfigurationItem.isConfigEnabled()); + actionAutocloseCheckBox.addValueChangeListener(this); + actionAutocloseConfigurationItem.addChangeListener(this); + gridLayout.addComponent(actionAutocloseCheckBox, 0, 0); + gridLayout.addComponent(actionAutocloseConfigurationItem, 1, 0); + + vLayout.addComponent(gridLayout); + rootPanel.setContent(vLayout); + setCompositionRoot(rootPanel); + } + + @Override + public void save() { + actionAutocloseConfigurationItem.save(); + } + + @Override + public void undo() { + actionAutocloseConfigurationItem.undo(); + actionAutocloseCheckBox.setValue(actionAutocloseConfigurationItem.isConfigEnabled()); + } + + @Override + public void configurationHasChanged() { + notifyConfigurationChanged(); + } + + @Override + public void valueChange(final ValueChangeEvent event) { + + if (!(event.getProperty() instanceof CheckBox)) { + return; + } + + notifyConfigurationChanged(); + + final CheckBox checkBox = (CheckBox) event.getProperty(); + BooleanConfigurationItem configurationItem; + + if (actionAutocloseCheckBox.equals(checkBox)) { + configurationItem = actionAutocloseConfigurationItem; + } else { + return; + } + + if (checkBox.getValue()) { + configurationItem.configEnable(); + } else { + configurationItem.configDisable(); + } + } +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/TenantConfigurationDashboardView.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/TenantConfigurationDashboardView.java index 2617cddb3..d5f1300bc 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/TenantConfigurationDashboardView.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/TenantConfigurationDashboardView.java @@ -56,6 +56,8 @@ public class TenantConfigurationDashboardView extends CustomComponent implements private final DefaultDistributionSetTypeLayout defaultDistributionSetTypeLayout; + private final RepositoryConfigurationView repositoryConfigurationView; + private final AuthenticationConfigurationView authenticationConfigurationView; private final PollingConfigurationView pollingConfigurationView; @@ -87,6 +89,8 @@ public class TenantConfigurationDashboardView extends CustomComponent implements securityTokenGenerator); this.pollingConfigurationView = new PollingConfigurationView(i18n, controllerPollProperties, tenantConfigurationManagement); + this.repositoryConfigurationView = new RepositoryConfigurationView(i18n, tenantConfigurationManagement); + this.i18n = i18n; this.uiProperties = uiProperties; this.uINotification = uINotification; @@ -100,6 +104,8 @@ public class TenantConfigurationDashboardView extends CustomComponent implements if (defaultDistributionSetTypeLayout.getComponentCount() > 0) { configurationViews.add(defaultDistributionSetTypeLayout); } + configurationViews.add(repositoryConfigurationView); + configurationViews.add(authenticationConfigurationView); configurationViews.add(pollingConfigurationView); if (customConfigurationViews != null) { diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/AnonymousDownloadAuthenticationConfigurationItem.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/AnonymousDownloadAuthenticationConfigurationItem.java index 30c7e9c91..33d10111d 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/AnonymousDownloadAuthenticationConfigurationItem.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/AnonymousDownloadAuthenticationConfigurationItem.java @@ -10,13 +10,14 @@ package org.eclipse.hawkbit.ui.tenantconfiguration.authentication; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; +import org.eclipse.hawkbit.ui.tenantconfiguration.generic.AbstractBooleanTenantConfigurationItem; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; /** * This class represents the UI item for the anonymous download by in the * authentication configuration view. */ -public class AnonymousDownloadAuthenticationConfigurationItem extends AbstractAuthenticationTenantConfigurationItem { +public class AnonymousDownloadAuthenticationConfigurationItem extends AbstractBooleanTenantConfigurationItem { private static final long serialVersionUID = 1L; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/CertificateAuthenticationConfigurationItem.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/CertificateAuthenticationConfigurationItem.java index 819e24579..00c7502dc 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/CertificateAuthenticationConfigurationItem.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/CertificateAuthenticationConfigurationItem.java @@ -12,6 +12,7 @@ import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; import org.eclipse.hawkbit.ui.common.builder.LabelBuilder; import org.eclipse.hawkbit.ui.common.builder.TextFieldBuilder; +import org.eclipse.hawkbit.ui.tenantconfiguration.generic.AbstractBooleanTenantConfigurationItem; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import com.vaadin.ui.HorizontalLayout; @@ -23,7 +24,7 @@ import com.vaadin.ui.VerticalLayout; * This class represents the UI item for the certificate authenticated by an * reverse proxy in the authentication configuration view. */ -public class CertificateAuthenticationConfigurationItem extends AbstractAuthenticationTenantConfigurationItem { +public class CertificateAuthenticationConfigurationItem extends AbstractBooleanTenantConfigurationItem { private static final long serialVersionUID = 1L; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/GatewaySecurityTokenAuthenticationConfigurationItem.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/GatewaySecurityTokenAuthenticationConfigurationItem.java index 4a728fb34..fcdbcd794 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/GatewaySecurityTokenAuthenticationConfigurationItem.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/GatewaySecurityTokenAuthenticationConfigurationItem.java @@ -15,6 +15,7 @@ import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.T import org.eclipse.hawkbit.ui.common.builder.LabelBuilder; import org.eclipse.hawkbit.ui.components.SPUIComponentProvider; import org.eclipse.hawkbit.ui.decorators.SPUIButtonStyleSmall; +import org.eclipse.hawkbit.ui.tenantconfiguration.generic.AbstractBooleanTenantConfigurationItem; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; import com.vaadin.server.FontAwesome; @@ -28,7 +29,7 @@ import com.vaadin.ui.themes.ValoTheme; * This class represents the UI item for the gateway security token section in * the authentication configuration view. */ -public class GatewaySecurityTokenAuthenticationConfigurationItem extends AbstractAuthenticationTenantConfigurationItem { +public class GatewaySecurityTokenAuthenticationConfigurationItem extends AbstractBooleanTenantConfigurationItem { private static final long serialVersionUID = 1L; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/TargetSecurityTokenAuthenticationConfigurationItem.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/TargetSecurityTokenAuthenticationConfigurationItem.java index e6bf25991..26bf039a6 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/TargetSecurityTokenAuthenticationConfigurationItem.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/TargetSecurityTokenAuthenticationConfigurationItem.java @@ -10,13 +10,14 @@ package org.eclipse.hawkbit.ui.tenantconfiguration.authentication; import org.eclipse.hawkbit.repository.TenantConfigurationManagement; import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; +import org.eclipse.hawkbit.ui.tenantconfiguration.generic.AbstractBooleanTenantConfigurationItem; import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; /** * This class represents the UI item for the target security token section in * the authentication configuration view. */ -public class TargetSecurityTokenAuthenticationConfigurationItem extends AbstractAuthenticationTenantConfigurationItem { +public class TargetSecurityTokenAuthenticationConfigurationItem extends AbstractBooleanTenantConfigurationItem { private static final long serialVersionUID = 1L; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/AbstractAuthenticationTenantConfigurationItem.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/generic/AbstractBooleanTenantConfigurationItem.java similarity index 91% rename from hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/AbstractAuthenticationTenantConfigurationItem.java rename to hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/generic/AbstractBooleanTenantConfigurationItem.java index 60b7f634d..689219a45 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/AbstractAuthenticationTenantConfigurationItem.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/generic/AbstractBooleanTenantConfigurationItem.java @@ -6,7 +6,7 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ -package org.eclipse.hawkbit.ui.tenantconfiguration.authentication; +package org.eclipse.hawkbit.ui.tenantconfiguration.generic; import java.util.ArrayList; import java.util.List; @@ -21,8 +21,8 @@ import com.vaadin.ui.VerticalLayout; /** * abstract authentication configuration item. */ -abstract class AbstractAuthenticationTenantConfigurationItem extends VerticalLayout - implements AuthenticationConfigurationItem { +public abstract class AbstractBooleanTenantConfigurationItem extends VerticalLayout + implements BooleanConfigurationItem { private static final long serialVersionUID = 1L; @@ -40,7 +40,7 @@ abstract class AbstractAuthenticationTenantConfigurationItem extends VerticalLay * the tenant configuration management to retrieve the * configuration value */ - public AbstractAuthenticationTenantConfigurationItem(final String configurationKey, + protected AbstractBooleanTenantConfigurationItem(final String configurationKey, final TenantConfigurationManagement tenantConfigurationManagement, final VaadinMessageSource i18n) { this.configurationKey = configurationKey; this.tenantConfigurationManagement = tenantConfigurationManagement; diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/AuthenticationConfigurationItem.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/generic/BooleanConfigurationItem.java similarity index 63% rename from hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/AuthenticationConfigurationItem.java rename to hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/generic/BooleanConfigurationItem.java index b6b045e1b..953441d34 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/authentication/AuthenticationConfigurationItem.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/generic/BooleanConfigurationItem.java @@ -6,21 +6,15 @@ * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ -package org.eclipse.hawkbit.ui.tenantconfiguration.authentication; +package org.eclipse.hawkbit.ui.tenantconfiguration.generic; -import org.eclipse.hawkbit.ui.tenantconfiguration.ConfigurationItem; - -import com.vaadin.ui.Component; +import org.eclipse.hawkbit.ui.tenantconfiguration.ConfigurationGroup; /** * Interface to be implemented by any tenant specific configuration to show on * the UI. - * - * - * - * */ -public interface AuthenticationConfigurationItem extends Component, ConfigurationItem { +public interface BooleanConfigurationItem extends ConfigurationGroup { /** * @return {@code true} if configuration is enabled, otherwise {@code false} @@ -37,14 +31,4 @@ public interface AuthenticationConfigurationItem extends Component, Configuratio */ void configDisable(); - /** - * called to save the configuration. - */ - void save(); - - /** - * called to rollback made changes. - */ - void undo(); - } diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/repository/ActionAutocloseConfigurationItem.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/repository/ActionAutocloseConfigurationItem.java new file mode 100644 index 000000000..5591d3d1c --- /dev/null +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/tenantconfiguration/repository/ActionAutocloseConfigurationItem.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2015 Bosch Software Innovations GmbH and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + */ +package org.eclipse.hawkbit.ui.tenantconfiguration.repository; + +import org.eclipse.hawkbit.repository.TenantConfigurationManagement; +import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; +import org.eclipse.hawkbit.ui.tenantconfiguration.generic.AbstractBooleanTenantConfigurationItem; +import org.eclipse.hawkbit.ui.utils.VaadinMessageSource; + +/** + * This class represents the UI item for the target security token section in + * the authentication configuration view. + */ +public class ActionAutocloseConfigurationItem extends AbstractBooleanTenantConfigurationItem { + + private static final long serialVersionUID = 1L; + + private boolean configurationEnabled; + private boolean configurationEnabledChange; + + public ActionAutocloseConfigurationItem(final TenantConfigurationManagement tenantConfigurationManagement, + final VaadinMessageSource i18n) { + super(TenantConfigurationKey.REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED, tenantConfigurationManagement, i18n); + + super.init("label.configuration.repository.autoclose.action"); + configurationEnabled = isConfigEnabled(); + } + + @Override + public void configEnable() { + if (!configurationEnabled) { + configurationEnabledChange = true; + } + configurationEnabled = true; + } + + @Override + public void configDisable() { + if (configurationEnabled) { + configurationEnabledChange = true; + } + configurationEnabled = false; + } + + @Override + public void save() { + if (!configurationEnabledChange) { + return; + } + getTenantConfigurationManagement().addOrUpdateConfiguration(getConfigurationKey(), configurationEnabled); + } + + @Override + public void undo() { + configurationEnabledChange = false; + configurationEnabled = getTenantConfigurationManagement() + .getConfigurationValue(getConfigurationKey(), Boolean.class).getValue(); + } +} diff --git a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIComponentIdProvider.java b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIComponentIdProvider.java index e0ab14ae9..9a653f6ed 100644 --- a/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIComponentIdProvider.java +++ b/hawkbit-ui/src/main/java/org/eclipse/hawkbit/ui/utils/UIComponentIdProvider.java @@ -9,6 +9,8 @@ package org.eclipse.hawkbit.ui.utils; +import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey; + /** * Interface to provide the unchanged constants. */ @@ -1039,6 +1041,12 @@ public final class UIComponentIdProvider { */ public static final String ARTIFACT_DETAILS_HEADER_LABEL_ID = "artifact.details.header.caption"; + /** + * Configuration checkbox for + * {@link TenantConfigurationKey#REPOSITORY_ACTIONS_AUTOCLOSE_ENABLED}. + */ + public static final String REPOSITORY_ACTIONS_AUTOCLOSE_CHECKBOX = "repositoryactionsautoclosecheckbox"; + /** * /* Private Constructor. */ diff --git a/hawkbit-ui/src/main/resources/messages.properties b/hawkbit-ui/src/main/resources/messages.properties index fbf11f882..c1d45fc4d 100644 --- a/hawkbit-ui/src/main/resources/messages.properties +++ b/hawkbit-ui/src/main/resources/messages.properties @@ -194,6 +194,7 @@ label.tag.name = Tag name label.configuration.auth.header = Allow targets to authenticate via a certificate authenticated by an reverse proxy label.configuration.auth.gatewaytoken = Allow a gateway to authenticate and manage multiple targets through a gateway security token label.configuration.auth.targettoken = Allow targets to authenticate directly with their target security token +label.configuration.repository.autoclose.action = Autoclose running actions with new Distribution Set assignment label.configuration.anonymous.download = Allow targets to download artifacts without security credentials label.unsupported.browser.ie=Sorry! current browser is not supported. Please use Internet Explorer 11 and above label.auto.assign.description=When an auto assign distribution set is selected, it will be automatically assigned to all targets that match the target filter. @@ -450,6 +451,7 @@ configuration.defaultdistributionset.select.label=Select the default Distributio configuration.savebutton.tooltip=Save Configurations configuration.cancellbutton.tooltip=Cancel Configurations configuration.authentication.title=Authentication Configuration +configuration.repository.title=Repository Configuration configuration.polling.title=Polling Configuration configuration.polling.time=Polling Time configuration.polling.overduetime=Polling Overdue Time