Add Target(Type)Management tests (#2735)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -19,6 +19,7 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch;
|
||||
import org.eclipse.hawkbit.repository.test.util.WithUser;
|
||||
@@ -26,7 +27,7 @@ import org.junit.jupiter.api.BeforeEach;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
@TestPropertySource(properties = "hawkbit.acm.access-controller.enabled=true")
|
||||
abstract class AbstractAccessControllerTest extends AbstractJpaIntegrationTest {
|
||||
abstract class AbstractAccessControllerManagementTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
protected SoftwareModuleType smType1;
|
||||
protected SoftwareModuleType smType2;
|
||||
@@ -44,10 +45,13 @@ abstract class AbstractAccessControllerTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
protected TargetType targetType1;
|
||||
protected TargetType targetType2;
|
||||
protected TargetTag targetTag1;
|
||||
protected TargetTag targetTag2;
|
||||
protected Target target1Type1;
|
||||
protected Target target2Type2;
|
||||
protected Target target3Type2;
|
||||
|
||||
@SuppressWarnings("java:S1117") // java:S1117 - intentional hiding of fiends - they are the same
|
||||
@BeforeEach
|
||||
@Override
|
||||
public void beforeAll() throws Exception {
|
||||
@@ -61,9 +65,9 @@ abstract class AbstractAccessControllerTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
dsType1 = testdataFactory.findOrCreateDistributionSetType("DsType1", "DistributionSetType-1", List.of(smType1), List.of());
|
||||
dsType2 = testdataFactory.findOrCreateDistributionSetType("DsType2", "DistributionSetType-2", List.of(smType2), List.of(smType1));
|
||||
final List<DistributionSetTag> tags = testdataFactory.createDistributionSetTags(2);
|
||||
dsTag1 = tags.get(0);
|
||||
dsTag2 = tags.get(1);
|
||||
final List<DistributionSetTag> dsTags = testdataFactory.createDistributionSetTags(2);
|
||||
dsTag1 = dsTags.get(0);
|
||||
dsTag2 = dsTags.get(1);
|
||||
ds1Type1 = distributionSetManagement.lock(
|
||||
distributionSetManagement.assignTag(
|
||||
List.of(testdataFactory.createDistributionSet("Ds1Type1", "1.0", dsType1, List.of(sm1Type1)).getId()),
|
||||
@@ -79,9 +83,18 @@ abstract class AbstractAccessControllerTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
targetType1 = testdataFactory.createTargetType("TargetType1", Set.of(dsType1, dsType2));
|
||||
targetType2 = testdataFactory.createTargetType("TargetType2", Set.of(dsType2));
|
||||
target1Type1 = testdataFactory.createTarget("controller_1", "Controller-1", targetType1);
|
||||
target2Type2 = testdataFactory.createTarget("controller_2", "Controller-2", targetType2);
|
||||
target3Type2 = testdataFactory.createTarget("controller_3", "Controller-3", targetType2);
|
||||
final List<? extends TargetTag> targetTags = testdataFactory.createTargetTags(2, "acm_");
|
||||
targetTag1 = targetTags.get(0);
|
||||
targetTag2 = targetTags.get(1);
|
||||
final Target target1Type1 = testdataFactory.createTarget("controller_1", "Controller-1", targetType1);
|
||||
final Target target2Type2 = testdataFactory.createTarget("controller_2", "Controller-2", targetType2);
|
||||
final Target target3Type2 = testdataFactory.createTarget("controller_3", "Controller-3", targetType2);
|
||||
targetManagement.assignTag(List.of(target1Type1.getControllerId(), target2Type2.getControllerId()), targetTag1.getId());
|
||||
targetManagement.assignTag(
|
||||
List.of(target1Type1.getControllerId(), target2Type2.getControllerId(), target3Type2.getControllerId()), targetTag2.getId());
|
||||
this.target1Type1 = targetManagement.get(target1Type1.getId());
|
||||
this.target2Type2 = targetManagement.get(target2Type2.getId());
|
||||
this.target3Type2 = targetManagement.get(target3Type2.getId());
|
||||
}
|
||||
|
||||
protected static WithUser withAuthorities(final String... authorities) {
|
||||
@@ -30,7 +30,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.integration.support.locks.LockRegistry;
|
||||
|
||||
class AutoAssignTest extends AbstractAccessControllerTest {
|
||||
class AutoAssignTest extends AbstractAccessControllerManagementTest {
|
||||
|
||||
@Autowired
|
||||
AutoAssignExecutor autoAssignExecutor;
|
||||
|
||||
@@ -27,7 +27,7 @@ import org.eclipse.hawkbit.repository.model.DeploymentRequest;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class DeploymentManagementTest extends AbstractAccessControllerTest {
|
||||
class DeploymentManagementTest extends AbstractAccessControllerManagementTest {
|
||||
|
||||
@Test
|
||||
void verifyAssignments() {
|
||||
|
||||
@@ -32,7 +32,7 @@ import org.eclipse.hawkbit.repository.model.NamedEntity;
|
||||
import org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class DistributionSetManagementTest extends AbstractAccessControllerTest {
|
||||
class DistributionSetManagementTest extends AbstractAccessControllerManagementTest {
|
||||
|
||||
@Test
|
||||
void verifyCreate() {
|
||||
|
||||
@@ -30,11 +30,11 @@ import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.model.NamedEntity;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class DistributionSetTypeManagementTest extends AbstractAccessControllerTest {
|
||||
class DistributionSetTypeManagementTest extends AbstractAccessControllerManagementTest {
|
||||
|
||||
@Test
|
||||
void verifyCreate() {
|
||||
// permissions to read only type1 ds types and create new type with name 'permitted'
|
||||
// permissions to read all and create new type with name 'permitted'
|
||||
runAs(withAuthorities(READ_PREFIX + DISTRIBUTION_SET_TYPE, CREATE_PREFIX + DISTRIBUTION_SET_TYPE + "/name==permitted"), () -> {
|
||||
assertThat(testdataFactory.findOrCreateDistributionSetType("newType", "permitted")).isNotNull();
|
||||
assertThatThrownBy(() -> testdataFactory.findOrCreateDistributionSetType("newType_2", "not_permitted_2"))
|
||||
|
||||
@@ -18,14 +18,16 @@ import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_TARGET;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.UPDATE_TARGET;
|
||||
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.runAs;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.hawkbit.repository.Identifiable;
|
||||
import org.eclipse.hawkbit.repository.jpa.rollout.RolloutScheduler;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class RolloutExecutionTest extends AbstractAccessControllerTest {
|
||||
class RolloutExecutionTest extends AbstractAccessControllerManagementTest {
|
||||
|
||||
@Test
|
||||
void verifyOnlyUpdatableTargetsArePartOfRolloutExecutedByScheduler() {
|
||||
@@ -66,7 +68,8 @@ class RolloutExecutionTest extends AbstractAccessControllerTest {
|
||||
|
||||
assertThat(rolloutGroupManagement.findByRollout(rollout.getId(), UNPAGED).getContent().stream()
|
||||
.flatMap(rolloutGroup -> rolloutGroupManagement.findTargetsOfRolloutGroup(rolloutGroup.getId(), UNPAGED).stream()))
|
||||
.extracting(Identifiable::getId)
|
||||
.as("Only updatable targets should be part of the rollout")
|
||||
.containsExactly(expectedTargets);
|
||||
.containsExactly(Arrays.stream(expectedTargets).map(Identifiable::getId).toArray(Long[]::new));
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ import org.eclipse.hawkbit.repository.Identifiable;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class RolloutManagementTest extends AbstractAccessControllerTest {
|
||||
class RolloutManagementTest extends AbstractAccessControllerManagementTest {
|
||||
|
||||
/**
|
||||
* Test is verifying that rollout details are showing details without restrictions
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModule.MetadataValueCreate;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class SoftwareModuleManagementTest extends AbstractAccessControllerTest {
|
||||
class SoftwareModuleManagementTest extends AbstractAccessControllerManagementTest {
|
||||
|
||||
@Test
|
||||
void verifyRead() {
|
||||
|
||||
@@ -29,11 +29,11 @@ import org.eclipse.hawkbit.repository.model.NamedEntity;
|
||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class SoftwareModuleTypeManagementTest extends AbstractAccessControllerTest {
|
||||
class SoftwareModuleTypeManagementTest extends AbstractAccessControllerManagementTest {
|
||||
|
||||
@Test
|
||||
void verifyCreate() {
|
||||
// permissions to read only type1 sm types and create new type with name 'permitted'
|
||||
// permissions to read all and create new type with name 'permitted'
|
||||
runAs(withAuthorities(READ_PREFIX + SOFTWARE_MODULE_TYPE, CREATE_PREFIX + SOFTWARE_MODULE_TYPE + "/key==permitted"), () -> {
|
||||
assertThat(testdataFactory.findOrCreateSoftwareModuleType("permitted")).isNotNull();
|
||||
assertThatThrownBy(() -> testdataFactory.findOrCreateSoftwareModuleType("not_permitted_2"))
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Contributors to the Eclipse Foundation
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.acm;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.CREATE_PREFIX;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.CREATE_TARGET;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.DELETE_PREFIX;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.DELETE_TARGET;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.DISTRIBUTION_SET;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.DISTRIBUTION_SET_TYPE;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_DISTRIBUTION_SET;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_PREFIX;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_TARGET;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.SOFTWARE_MODULE;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.SOFTWARE_MODULE_TYPE;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.TARGET_TYPE;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.UPDATE_PREFIX;
|
||||
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.runAs;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.repository.jpa.acm.AccessController.Operation;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaAction;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSetType;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModule;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaSoftwareModuleType;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
|
||||
import org.eclipse.hawkbit.repository.jpa.model.JpaTargetType;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.jpa.domain.Specification;
|
||||
|
||||
class SystemExecutionTest extends AbstractAccessControllerManagementTest {
|
||||
|
||||
@Autowired
|
||||
protected AccessController<JpaSoftwareModule> softwareModuleAccessController;
|
||||
@Autowired
|
||||
protected AccessController<JpaSoftwareModuleType> softwareModuleTypeAccessController;
|
||||
@Autowired
|
||||
protected AccessController<JpaDistributionSet> distributionSetAccessController;
|
||||
@Autowired
|
||||
protected AccessController<JpaDistributionSetType> distributionSetTypeAccessController;
|
||||
@Autowired
|
||||
protected AccessController<JpaTarget> targetAccessController;
|
||||
@Autowired
|
||||
protected AccessController<JpaTargetType> targetTypeAccessController;
|
||||
@Autowired
|
||||
protected AccessController<JpaAction> actionAccessController;
|
||||
|
||||
@Autowired
|
||||
List<AccessController<?>> allAccessControllers;
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Test
|
||||
void verifyWithoutScopes() {
|
||||
allAccessControllers.forEach(accessController -> {
|
||||
for (final Operation operation : Operation.values()) {
|
||||
assertThat(accessController.getAccessRules(operation)).isEmpty();
|
||||
}
|
||||
final Specification specificationMock = mock(Specification.class);
|
||||
for (final Operation operation : Operation.values()) {
|
||||
accessController.appendAccessRules(operation, specificationMock);
|
||||
verifyNoInteractions(specificationMock);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
void verifyWithScope() {
|
||||
runAs(withAuthorities(READ_PREFIX + SOFTWARE_MODULE + "/type.id==1", UPDATE_PREFIX + SOFTWARE_MODULE),
|
||||
() -> verifyAccessController(softwareModuleAccessController));
|
||||
runAs(withAuthorities(READ_PREFIX + SOFTWARE_MODULE_TYPE + "/id==1", UPDATE_PREFIX + SOFTWARE_MODULE_TYPE),
|
||||
() -> verifyAccessController(softwareModuleTypeAccessController));
|
||||
runAs(withAuthorities(READ_DISTRIBUTION_SET + "/type.id==1", CREATE_PREFIX + DISTRIBUTION_SET),
|
||||
() -> verifyAccessController(distributionSetAccessController));
|
||||
runAs(withAuthorities(READ_PREFIX + DISTRIBUTION_SET_TYPE + "/id==1", DELETE_PREFIX + DISTRIBUTION_SET_TYPE),
|
||||
() -> verifyAccessController(distributionSetTypeAccessController));
|
||||
runAs(withAuthorities(READ_TARGET, DELETE_TARGET + "/type.id==1"),
|
||||
() -> verifyAccessController(targetAccessController));
|
||||
runAs(withAuthorities(UPDATE_PREFIX + TARGET_TYPE + "/id==1"), () -> verifyAccessController(targetTypeAccessController));
|
||||
runAs(withAuthorities(CREATE_TARGET + "/type.id==1"), () -> verifyAccessController(actionAccessController));
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private void verifyAccessController(final AccessController<?> accessController) {
|
||||
final Specification mock = mock(Specification.class);
|
||||
for (final Operation operation : Operation.values()) {
|
||||
accessController.appendAccessRules(operation, mock);
|
||||
}
|
||||
verify(mock, times(1)).and(any()); // once for every access controller is scoped only
|
||||
|
||||
final Specification mockAsSystem = mock(Specification.class);
|
||||
for (Operation operation : Operation.values()) {
|
||||
systemSecurityContext.runAsSystem(() -> {
|
||||
accessController.appendAccessRules(operation, mockAsSystem);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
verifyNoInteractions(mockAsSystem);
|
||||
}
|
||||
}
|
||||
@@ -1,319 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Contributors to the Eclipse Foundation
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.acm;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.CREATE_ROLLOUT;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_DISTRIBUTION_SET;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_ROLLOUT;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_TARGET;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.UPDATE_TARGET;
|
||||
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.runAs;
|
||||
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.withUser;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.repository.Identifiable;
|
||||
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement.AutoAssignDistributionSetUpdate;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement.Create;
|
||||
import org.eclipse.hawkbit.repository.TargetTagManagement;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.jpa.autoassign.AutoAssignChecker;
|
||||
import org.eclipse.hawkbit.repository.model.Action.ActionType;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
|
||||
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
/**
|
||||
* Feature: Component Tests - Access Control<br/>
|
||||
* Story: Test Target Access Controller
|
||||
*/
|
||||
@TestPropertySource(properties = "hawkbit.acm.access-controller.enabled=true")
|
||||
class TargetAccessControllerTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
AutoAssignChecker autoAssignChecker;
|
||||
|
||||
/**
|
||||
* Verifies read access rules for targets
|
||||
*/
|
||||
@Test
|
||||
void verifyTargetReadOperations() {
|
||||
final Target permittedTarget = targetManagement
|
||||
.create(Create.builder().controllerId("device01").updateStatus(TargetUpdateStatus.REGISTERED).build());
|
||||
|
||||
final Target hiddenTarget = targetManagement
|
||||
.create(Create.builder().controllerId("device02").updateStatus(TargetUpdateStatus.REGISTERED).build());
|
||||
|
||||
runAs(withUser("user", READ_TARGET + "/controllerId==" + permittedTarget.getControllerId()), () -> {
|
||||
// verify targetManagement#findAll
|
||||
assertThat(targetManagement.findAll(Pageable.unpaged()).get().map(Identifiable::getId).toList())
|
||||
.containsExactly(permittedTarget.getId());
|
||||
|
||||
// verify targetManagement#findByRsql
|
||||
assertThat(targetManagement.findByRsql("id==*", Pageable.unpaged()).get().map(Identifiable::getId).toList())
|
||||
.containsExactly(permittedTarget.getId());
|
||||
|
||||
// verify targetManagement#getByControllerID
|
||||
assertThat(targetManagement.getByControllerId(permittedTarget.getControllerId())).isNotNull();
|
||||
final String hiddenTargetControllerId = hiddenTarget.getControllerId();
|
||||
assertThatThrownBy(() -> targetManagement.getByControllerId(hiddenTargetControllerId))
|
||||
.as("Missing read permissions for hidden target.")
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
assertThatThrownBy(() -> targetManagement.findByControllerId(hiddenTargetControllerId))
|
||||
.as("Missing read permissions for hidden target.")
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
|
||||
// verify targetManagement#getByControllerId
|
||||
assertThat(targetManagement
|
||||
.findByControllerId(List.of(permittedTarget.getControllerId(), hiddenTargetControllerId))
|
||||
.stream().map(Identifiable::getId).toList()).containsExactly(permittedTarget.getId());
|
||||
|
||||
// verify targetManagement#get
|
||||
assertThat(targetManagement.find(permittedTarget.getId())).isPresent();
|
||||
assertThat(targetManagement.find(hiddenTarget.getId())).isEmpty();
|
||||
|
||||
// verify targetManagement#get
|
||||
final List<Long> withHidden = List.of(permittedTarget.getId(), hiddenTarget.getId());
|
||||
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> targetManagement.get(withHidden));
|
||||
|
||||
// verify targetManagement#getControllerAttributes
|
||||
assertThat(targetManagement.getControllerAttributes(permittedTarget.getControllerId())).isEmpty();
|
||||
assertThatThrownBy(() -> targetManagement.getControllerAttributes(hiddenTargetControllerId))
|
||||
.as("Target should not be found.")
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void verifyTagFilteringAndManagement() {
|
||||
final Target permittedTarget = targetManagement
|
||||
.create(Create.builder().controllerId("device01").updateStatus(TargetUpdateStatus.REGISTERED).build());
|
||||
|
||||
final Target readOnlyTarget = targetManagement
|
||||
.create(Create.builder().controllerId("device02").updateStatus(TargetUpdateStatus.REGISTERED).build());
|
||||
final String readOnlyTargetControllerId = readOnlyTarget.getControllerId();
|
||||
|
||||
final Target hiddenTarget = targetManagement
|
||||
.create(Create.builder().controllerId("device03").updateStatus(TargetUpdateStatus.REGISTERED).build());
|
||||
|
||||
final Long myTagId = targetTagManagement.create(TargetTagManagement.Create.builder().name("myTag").build()).getId();
|
||||
|
||||
// perform tag assignment before setting access rules
|
||||
targetManagement.assignTag(
|
||||
List.of(permittedTarget.getControllerId(), readOnlyTargetControllerId, hiddenTarget.getControllerId()), myTagId);
|
||||
|
||||
runAs(withUser("user",
|
||||
READ_TARGET + "/controllerId==" + permittedTarget.getControllerId() + " or controllerId==" + readOnlyTargetControllerId,
|
||||
UPDATE_TARGET + "/controllerId==" + permittedTarget.getControllerId()),
|
||||
() -> {
|
||||
// verify targetManagement#findByTag
|
||||
assertThat(
|
||||
targetManagement.findByTag(myTagId, Pageable.unpaged()).get().map(Identifiable::getId).toList())
|
||||
.containsExactlyInAnyOrder(permittedTarget.getId(), readOnlyTarget.getId());
|
||||
|
||||
// verify targetManagement#findByRsqlAndTag
|
||||
assertThat(targetManagement.findByRsqlAndTag("id==*", myTagId, Pageable.unpaged()).get()
|
||||
.map(Identifiable::getId).toList()).containsExactlyInAnyOrder(permittedTarget.getId(), readOnlyTarget.getId());
|
||||
|
||||
// verify targetManagement#assignTag on permitted target
|
||||
assertThat(targetManagement.assignTag(Collections.singletonList(permittedTarget.getControllerId()), myTagId)).hasSize(1);
|
||||
// verify targetManagement#unassignTag on permitted target
|
||||
assertThat(targetManagement.unassignTag(Collections.singletonList(permittedTarget.getControllerId()), myTagId)).hasSize(1);
|
||||
// verify targetManagement#assignTag on permitted target
|
||||
assertThat(targetManagement.assignTag(Collections.singletonList(permittedTarget.getControllerId()), myTagId))
|
||||
.hasSize(1);
|
||||
// verify targetManagement#unAssignTag on permitted target
|
||||
assertThat(targetManagement.unassignTag(List.of(permittedTarget.getControllerId()), myTagId).get(0).getControllerId())
|
||||
.isEqualTo(permittedTarget.getControllerId());
|
||||
|
||||
// assignment is denied for readOnlyTarget (read, but no update permissions)
|
||||
final List<String> readTargetControllerIdList = Collections.singletonList(readOnlyTargetControllerId);
|
||||
assertThatThrownBy(() -> targetManagement.assignTag(readTargetControllerIdList, myTagId))
|
||||
.as("Missing update permissions for target to toggle tag assignment.")
|
||||
.isInstanceOfAny(InsufficientPermissionException.class);
|
||||
|
||||
// assignment is denied for readOnlyTarget (read, but no update permissions)
|
||||
final List<String> readOnlyTargetControllerIdList = List.of(readOnlyTargetControllerId);
|
||||
assertThatThrownBy(() -> targetManagement.unassignTag(readOnlyTargetControllerIdList, myTagId))
|
||||
.as("Missing update permissions for target to toggle tag assignment.")
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
|
||||
// assignment is denied for hiddenTarget since it's hidden
|
||||
final List<String> hiddenTargetControllerIdList = Collections.singletonList(hiddenTarget.getControllerId());
|
||||
assertThatThrownBy(() -> targetManagement.assignTag(hiddenTargetControllerIdList, myTagId))
|
||||
.as("Missing update permissions for target to toggle tag assignment.")
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
|
||||
// assignment is denied for hiddenTarget since it's hidden
|
||||
assertThatThrownBy(() -> targetManagement.assignTag(hiddenTargetControllerIdList, myTagId))
|
||||
.as("Missing update permissions for target to toggle tag assignment.")
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
|
||||
// assignment is denied for hiddenTarget since it's hidden
|
||||
assertThatThrownBy(() -> targetManagement.unassignTag(hiddenTargetControllerIdList, myTagId))
|
||||
.as("Missing update permissions for target to toggle tag assignment.")
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies rules for target assignment
|
||||
*/
|
||||
@Test
|
||||
void verifyTargetAssignment() {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("myDs");
|
||||
distributionSetManagement.lock(ds);
|
||||
|
||||
final Target permittedTarget = targetManagement
|
||||
.create(Create.builder().controllerId("device01").updateStatus(TargetUpdateStatus.REGISTERED).build());
|
||||
final String hiddenTargetControllerId = targetManagement
|
||||
.create(Create.builder().controllerId("device02").updateStatus(TargetUpdateStatus.REGISTERED).build())
|
||||
.getControllerId();
|
||||
|
||||
runAs(withUser("user",
|
||||
READ_DISTRIBUTION_SET,
|
||||
READ_TARGET + "/controllerId==" + permittedTarget.getControllerId(),
|
||||
UPDATE_TARGET + "/controllerId==" + permittedTarget.getControllerId()), () -> {
|
||||
final Long dsId = ds.getId();
|
||||
assertThat(assignDistributionSet(dsId, permittedTarget.getControllerId()).getAssigned()).isEqualTo(1);
|
||||
// assigning of not allowed target behaves as not found
|
||||
assertThatThrownBy(() -> assignDistributionSet(dsId, hiddenTargetControllerId)).isInstanceOf(AssertionError.class);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies rules for target assignment
|
||||
*/
|
||||
@Test
|
||||
void verifyTargetAssignmentOnNonUpdatableTarget() {
|
||||
final DistributionSet firstDs = testdataFactory.createDistributionSet("myDs");
|
||||
distributionSetManagement.lock(firstDs);
|
||||
final DistributionSet secondDs = testdataFactory.createDistributionSet("anotherDs");
|
||||
distributionSetManagement.lock(secondDs);
|
||||
|
||||
final Target manageableTarget = targetManagement
|
||||
.create(Create.builder().controllerId("device01").updateStatus(TargetUpdateStatus.REGISTERED).build());
|
||||
final Target readOnlyTarget = targetManagement
|
||||
.create(Create.builder().controllerId("device02").updateStatus(TargetUpdateStatus.REGISTERED).build());
|
||||
|
||||
runAs(withUser("user",
|
||||
READ_DISTRIBUTION_SET,
|
||||
READ_TARGET + "/controllerId==" + manageableTarget.getControllerId() + " or controllerId==" + readOnlyTarget.getControllerId(),
|
||||
UPDATE_TARGET + "/controllerId==" + manageableTarget.getControllerId()), () -> {
|
||||
final Long firstDsId = firstDs.getId();
|
||||
// assignment is permitted for manageableTarget
|
||||
assertThat(assignDistributionSet(firstDsId, manageableTarget.getControllerId()).getAssigned()).isEqualTo(1);
|
||||
|
||||
// assignment is denied for readOnlyTarget (read, but no update permissions)
|
||||
final var readOnlyTargetControllerId = readOnlyTarget.getControllerId();
|
||||
assertThatThrownBy(() -> assignDistributionSet(firstDsId, readOnlyTargetControllerId)).isInstanceOf(AssertionError.class);
|
||||
|
||||
// bunch assignment skips denied since at least one target without update permissions is present
|
||||
assertThat(assignDistributionSet(secondDs.getId(),
|
||||
Arrays.asList(readOnlyTargetControllerId, manageableTarget.getControllerId()),
|
||||
ActionType.FORCED).getAssigned()).isEqualTo(1);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies only manageable targets are part of the rollout
|
||||
*/
|
||||
@Test
|
||||
void verifyRolloutTargetScope() {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("myDs");
|
||||
distributionSetManagement.lock(ds);
|
||||
|
||||
final String[] updateTargetControllerIds = { "update1", "update2", "update3" };
|
||||
final List<Target> updateTargets = testdataFactory.createTargets(updateTargetControllerIds);
|
||||
final String[] readTargetControllerIds = { "read1", "read2", "read3", "read4" };
|
||||
final List<Target> readTargets = testdataFactory.createTargets(readTargetControllerIds);
|
||||
final List<Target> hiddenTargets = testdataFactory.createTargets("hidden1", "hidden2", "hidden3", "hidden4", "hidden5");
|
||||
|
||||
runAs(withUser("user",
|
||||
READ_DISTRIBUTION_SET,
|
||||
READ_TARGET + "/controllerId=in=(" + String.join(", ", List.of(updateTargetControllerIds)) + ")" +
|
||||
" or controllerId=in=(" + String.join(", ", List.of(readTargetControllerIds)) + ")",
|
||||
UPDATE_TARGET + "/controllerId=in=(" + String.join(", ", List.of(updateTargetControllerIds)) + ")",
|
||||
CREATE_ROLLOUT, READ_ROLLOUT), () -> {
|
||||
final Rollout rollout = testdataFactory.createRolloutByVariables(
|
||||
"testRollout", "description", updateTargets.size(), "id==*", ds, "50", "5");
|
||||
assertThat(rollout.getTotalTargets()).isEqualTo(updateTargets.size());
|
||||
|
||||
final List<RolloutGroup> content = rolloutGroupManagement.findByRollout(rollout.getId(), Pageable.unpaged()).getContent();
|
||||
assertThat(content).hasSize(updateTargets.size());
|
||||
|
||||
final List<Target> rolloutTargets = content.stream().flatMap(
|
||||
group -> rolloutGroupManagement.findTargetsOfRolloutGroup(group.getId(), Pageable.unpaged()).get())
|
||||
.toList();
|
||||
|
||||
assertThat(rolloutTargets).hasSize(updateTargets.size()).allMatch(
|
||||
target -> updateTargets.stream().anyMatch(readTarget -> readTarget.getId().equals(target.getId())))
|
||||
.noneMatch(target -> readTargets.stream()
|
||||
.anyMatch(readTarget -> readTarget.getId().equals(target.getId())))
|
||||
.noneMatch(target -> hiddenTargets.stream()
|
||||
.anyMatch(readTarget -> readTarget.getId().equals(target.getId())));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies only manageable targets are part of an auto assignment.
|
||||
*/
|
||||
@Test
|
||||
void verifyAutoAssignmentTargetScope() {
|
||||
final DistributionSet distributionSet = testdataFactory.createDistributionSet();
|
||||
distributionSetManagement.lock(distributionSet);
|
||||
|
||||
final String[] updateTargetControllerIds = { "update1", "update2", "update3" };
|
||||
final List<Target> updateTargets = testdataFactory.createTargets(updateTargetControllerIds);
|
||||
final String[] readTargetControllerIds = { "read1", "read2", "read3", "read4" };
|
||||
final List<Target> readTargets = testdataFactory.createTargets(readTargetControllerIds);
|
||||
final List<Target> hiddenTargets = testdataFactory.createTargets("hidden1", "hidden2", "hidden3", "hidden4", "hidden5");
|
||||
|
||||
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
|
||||
.create(TargetFilterQueryManagement.Create.builder().name("testName").query("id==*").build());
|
||||
|
||||
runAs(withUser("user",
|
||||
READ_TARGET + "/controllerId=in=(" + String.join(", ", List.of(updateTargetControllerIds)) + ")" +
|
||||
" or controllerId=in=(" + String.join(", ", List.of(readTargetControllerIds)) + ")",
|
||||
UPDATE_TARGET + "/controllerId=in=(" + String.join(", ", List.of(updateTargetControllerIds)) + ")",
|
||||
READ_DISTRIBUTION_SET + "/id==" + distributionSet.getId()), () -> {
|
||||
|
||||
targetFilterQueryManagement.updateAutoAssignDS(
|
||||
new AutoAssignDistributionSetUpdate(targetFilterQuery.getId()).ds(distributionSet.getId()));
|
||||
|
||||
autoAssignChecker.checkAllTargets();
|
||||
|
||||
assertThat(targetManagement.findByAssignedDistributionSet(distributionSet.getId(), Pageable.unpaged())
|
||||
.getContent())
|
||||
.hasSize(updateTargets.size())
|
||||
.allMatch(assignedTarget -> updateTargets.stream()
|
||||
.anyMatch(updateTarget -> updateTarget.getId().equals(assignedTarget.getId())))
|
||||
.noneMatch(assignedTarget -> readTargets.stream()
|
||||
.anyMatch(updateTarget -> updateTarget.getId().equals(assignedTarget.getId())))
|
||||
.noneMatch(assignedTarget -> hiddenTargets.stream()
|
||||
.anyMatch(updateTarget -> updateTarget.getId().equals(assignedTarget.getId())));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,331 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Contributors to the Eclipse Foundation
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.acm;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.CREATE_ROLLOUT;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.CREATE_TARGET;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.DELETE_TARGET;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.HANDLE_ROLLOUT;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_DISTRIBUTION_SET;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_ROLLOUT;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_TARGET;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.UPDATE_TARGET;
|
||||
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.runAs;
|
||||
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.withUser;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.eclipse.hawkbit.repository.Identifiable;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement;
|
||||
import org.eclipse.hawkbit.repository.TargetManagement.Update;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
|
||||
import org.eclipse.hawkbit.repository.model.Action;
|
||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||
import org.eclipse.hawkbit.repository.model.NamedEntity;
|
||||
import org.eclipse.hawkbit.repository.model.Rollout;
|
||||
import org.eclipse.hawkbit.repository.model.RolloutGroup;
|
||||
import org.eclipse.hawkbit.repository.model.Target;
|
||||
import org.eclipse.hawkbit.repository.model.TargetTag;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
class TargetManagementTest extends AbstractAccessControllerManagementTest {
|
||||
|
||||
@Test
|
||||
void verifyCreation() {
|
||||
// permissions to read all and create only type1 targets
|
||||
runAs(withAuthorities(READ_TARGET, CREATE_TARGET + "/type.id==" + targetType1.getId()), () -> {
|
||||
testdataFactory.createTarget("controller_1_create", "Controller-1_create", targetType1);
|
||||
assertThatThrownBy(() -> testdataFactory.createTarget("controller_2_create", "Controller-2_create", targetType2))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Test
|
||||
void verifyRead() {
|
||||
assertThat(assignDistributionSet(ds2Type2, List.of(target1Type1, target2Type2, target3Type2)).getAssigned()).isEqualTo(3);
|
||||
final Target target1Type1 = targetManagement.get(super.target1Type1.getId());
|
||||
final Target target2Type2 = targetManagement.get(super.target2Type2.getId());
|
||||
runAs(withAuthorities(READ_TARGET + "/type.id==" + targetType1.getId(), READ_DISTRIBUTION_SET), () -> {
|
||||
Assertions.<Target> assertThat(targetManagement.findAll(UNPAGED)).containsExactly(target1Type1);
|
||||
assertThat(targetManagement.count()).isEqualTo(1);
|
||||
|
||||
Assertions.<Target> assertThat(targetManagement.get(List.of(target1Type1.getId()))).containsExactly(target1Type1);
|
||||
final List<Long> allTargetIds = List.of(target1Type1.getId(), target2Type2.getId());
|
||||
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> targetManagement.get(allTargetIds));
|
||||
|
||||
assertThat(((TargetManagement) targetManagement).find(target1Type1.getId())).hasValue(target1Type1);
|
||||
assertThat(targetManagement.find(target2Type2.getId())).isEmpty();
|
||||
|
||||
assertThat(targetManagement.findByControllerId(List.of(target1Type1.getControllerId()))).containsExactly(target1Type1);
|
||||
|
||||
assertThat(targetManagement.getByControllerId(target1Type1.getControllerId())).isEqualTo(target1Type1);
|
||||
assertThat(targetManagement.findByControllerId(target1Type1.getControllerId())).hasValue(target1Type1);
|
||||
final String target2Type2ControllerId = target2Type2.getControllerId();
|
||||
assertThatThrownBy(() -> targetManagement.getByControllerId(target2Type2ControllerId))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
assertThatThrownBy(() -> targetManagement.findByControllerId(target2Type2ControllerId))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
|
||||
assertThat(targetManagement.getControllerAttributes(target1Type1.getControllerId())).isEmpty();
|
||||
assertThatThrownBy(() -> targetManagement.getControllerAttributes(target2Type2ControllerId))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
|
||||
assertThat(targetManagement.getByControllerId(target1Type1.getControllerId())).isEqualTo(target1Type1);
|
||||
assertThat(targetManagement.findByControllerId(target1Type1.getControllerId())).hasValue(target1Type1);
|
||||
assertThatThrownBy(() -> targetManagement.getByControllerId(target2Type2ControllerId))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
assertThatThrownBy(() -> targetManagement.findByControllerId(target2Type2ControllerId))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
|
||||
assertThat(targetManagement.countByRsql("id==*")).isEqualTo(1);
|
||||
assertThat(targetManagement.countByRsql("id==%s".formatted(target1Type1.getControllerId()))).isEqualTo(1);
|
||||
assertThat(targetManagement.countByRsql("id==%s".formatted(target2Type2.getControllerId()))).isZero();
|
||||
Assertions.<Target> assertThat(targetManagement.findByRsql("id==*", UNPAGED))
|
||||
.hasSize(1)
|
||||
.containsExactly(target1Type1)
|
||||
.doesNotContain(target2Type2);
|
||||
Assertions.<Target> assertThat(
|
||||
targetManagement.findByRsql("id==%s".formatted(target1Type1.getControllerId()), UNPAGED))
|
||||
.hasSize(1)
|
||||
.containsExactly(target1Type1)
|
||||
.doesNotContain(target2Type2);
|
||||
assertThat(targetManagement.findByRsql("id==%s".formatted(target2Type2.getControllerId()), UNPAGED)).isEmpty();
|
||||
|
||||
assertThat(targetManagement.findByAssignedDistributionSet(ds2Type2.getId(), UNPAGED))
|
||||
.extracting(Identifiable::getId).containsExactly(target1Type1.getId());
|
||||
assertThat(targetManagement.findByAssignedDistributionSetAndRsql(ds2Type2.getId(), "id==*", UNPAGED))
|
||||
.extracting(Identifiable::getId).containsExactly(target1Type1.getId());
|
||||
|
||||
assertThat(targetManagement.countByRsqlAndCompatible("id==*", ds2Type2.getType().getId())).isEqualTo(1);
|
||||
|
||||
assertThat(targetManagement.getMetadata(target1Type1.getControllerId())).isEmpty();
|
||||
final String target2Type2ControllerId1 = target2Type2.getControllerId();
|
||||
assertThatThrownBy(() -> targetManagement.getMetadata(target2Type2ControllerId1))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
|
||||
// find by tags
|
||||
assertThat(targetManagement.findByTag(targetType2.getId(), UNPAGED))
|
||||
.extracting(Identifiable::getId)
|
||||
.containsOnly(target1Type1.getId());
|
||||
assertThat(targetManagement.findByRsqlAndTag("id==*", targetType2.getId(), UNPAGED))
|
||||
.extracting(Identifiable::getId)
|
||||
.containsOnly(target1Type1.getId());
|
||||
});
|
||||
}
|
||||
|
||||
@Disabled
|
||||
@Test
|
||||
void verifyReadRolloutRelated() {
|
||||
assertThat(assignDistributionSet(ds2Type2, List.of(target1Type1, target2Type2, target3Type2)).getAssigned()).isEqualTo(3);
|
||||
prepareFinishedUpdates(ds2Type2, target1Type1, target2Type2);
|
||||
final Target target1Type1 = targetManagement.get(super.target1Type1.getId());
|
||||
runAs(withAuthorities(
|
||||
READ_TARGET + "/type.id==" + targetType1.getId(),
|
||||
READ_DISTRIBUTION_SET,
|
||||
CREATE_ROLLOUT, READ_ROLLOUT, HANDLE_ROLLOUT), () -> {
|
||||
assertThat(targetManagement.findByInstalledDistributionSet(ds2Type2.getId(), UNPAGED))
|
||||
.extracting(Identifiable::getId).containsExactly(target1Type1.getId());
|
||||
assertThat(targetManagement.findByInstalledDistributionSetAndRsql(ds2Type2.getId(), "id==*", UNPAGED))
|
||||
.extracting(Identifiable::getId).containsExactly(target1Type1.getId());
|
||||
|
||||
assertThat(targetManagement.findByTargetFilterQueryAndNonDSAndCompatibleAndUpdatable(
|
||||
ds2Type2.getId(), "id==*", UNPAGED))
|
||||
.hasSize(1)
|
||||
.extracting(Identifiable::getId).containsOnly(target1Type1.getId());
|
||||
|
||||
assertThat(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(
|
||||
target1Type1.getControllerId(), ds2Type2.getId(), "id==*")).isTrue();
|
||||
assertThat(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(
|
||||
target2Type2.getControllerId(), ds2Type2.getId(), "id==*")).isFalse();
|
||||
|
||||
assertThat(targetManagement.findByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
||||
List.of(1L), "id==*", ds2Type2.getType(), UNPAGED))
|
||||
.hasSize(1)
|
||||
.extracting(Identifiable::getId).containsOnly(target1Type1.getId());
|
||||
assertThat(targetManagement.countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable("id==*", List.of(1L),
|
||||
ds2Type2.getType())).isEqualTo(1);
|
||||
|
||||
final Rollout rollout = testdataFactory.createRolloutByVariables(
|
||||
"testRollout", "testDescription", 3, "id==*", ds2Type2, "50", "5");
|
||||
|
||||
final List<Long> foundTargetIds = rolloutGroupManagement.findByRollout(rollout.getId(), UNPAGED).getContent().stream()
|
||||
.flatMap(rolloutGroup -> targetManagement.findByInRolloutGroupWithoutAction(rolloutGroup.getId(), UNPAGED)
|
||||
.getContent().stream()).map(Identifiable::getId).toList();
|
||||
assertThat(foundTargetIds).hasSize(1).contains(target1Type1.getId());
|
||||
|
||||
assertThat(targetManagement.findByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable(
|
||||
List.of(1L), "id==*", ds2Type2.getType(), UNPAGED))
|
||||
.hasSize(1)
|
||||
.extracting(Identifiable::getId).containsOnly(target1Type1.getId());
|
||||
assertThat(targetManagement.countByRsqlAndNotInRolloutGroupsAndCompatibleAndUpdatable("id==*", List.of(1L), ds2Type2.getType()))
|
||||
.isEqualTo(1);
|
||||
final Rollout runAsSystem = systemSecurityContext.runAsSystem(
|
||||
() -> testdataFactory.createRolloutByVariables("testRollout", "testDescription", 3, "id==*", ds2Type2, "50", "5"));
|
||||
assertThat(rolloutGroupManagement.findByRollout(runAsSystem.getId(), UNPAGED).getContent().stream()
|
||||
.flatMap(rolloutGroup -> targetManagement.findByInRolloutGroupWithoutAction(rolloutGroup.getId(), UNPAGED)
|
||||
.getContent().stream()).map(Identifiable::getId).toList())
|
||||
.hasSize(3);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void verifyUpdate() {
|
||||
final TargetTag testTag = testdataFactory.createTargetTags(1, "testTag").get(0);
|
||||
final Long testTagId = testTag.getId();
|
||||
runAs(withAuthorities(
|
||||
READ_TARGET, UPDATE_TARGET + "/type.id==" + targetType1.getId(),
|
||||
READ_DISTRIBUTION_SET),
|
||||
() -> {
|
||||
assertThat(targetManagement.update(
|
||||
Update.builder().id(target1Type1.getId()).name("myNewName").build()))
|
||||
.extracting(NamedEntity::getName).isEqualTo("myNewName");
|
||||
|
||||
final Update targetUpdate = Update.builder().id(target2Type2.getId()).name("myNewName").build();
|
||||
assertThatThrownBy(() -> targetManagement.update(targetUpdate)).isInstanceOf(InsufficientPermissionException.class);
|
||||
|
||||
final String metadataKey = "key.dot";
|
||||
final Map<String, String> metadata = Map.of(metadataKey, "value.dot");
|
||||
final String target1Type1ControllerId = target1Type1.getControllerId();
|
||||
targetManagement.createMetadata(target1Type1ControllerId, metadata);
|
||||
final String target2Type2ControllerId = target2Type2.getControllerId();
|
||||
assertThatThrownBy(() -> targetManagement.createMetadata(target2Type2ControllerId, metadata))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
final String newValue = "newValue";
|
||||
targetManagement.createMetadata(target1Type1ControllerId, metadataKey, newValue);
|
||||
assertThat(targetManagement.getMetadata(target1Type1ControllerId)).containsEntry(metadataKey, newValue);
|
||||
assertThatThrownBy(() -> targetManagement.createMetadata(target2Type2ControllerId, metadataKey, newValue))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
targetManagement.deleteMetadata(target1Type1ControllerId, metadataKey);
|
||||
assertThatThrownBy(() -> targetManagement.deleteMetadata(target2Type2ControllerId, metadataKey))
|
||||
.isInstanceOf(EntityNotFoundException.class);
|
||||
|
||||
// tag assignments
|
||||
assertThat(targetManagement.assignTag(List.of(target1Type1.getControllerId()), testTagId))
|
||||
.extracting(Identifiable::getId).containsExactly(target1Type1.getId());
|
||||
final List<String> target2Type2ControllerIdList = List.of(target2Type2.getControllerId());
|
||||
assertThatThrownBy(() -> targetManagement.assignTag(target2Type2ControllerIdList, testTagId))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
assertThatThrownBy(() -> targetManagement.assignTag(target2Type2ControllerIdList, testTagId))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
|
||||
assertThat(targetManagement.unassignTag(List.of(target1Type1.getControllerId()), testTagId)).element(0)
|
||||
.extracting(Identifiable::getId).isEqualTo(target1Type1.getId());
|
||||
assertThatThrownBy(() -> targetManagement.unassignTag(target2Type2ControllerIdList, testTagId))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
assertThatThrownBy(() -> targetManagement.unassignTag(target2Type2ControllerIdList, testTagId))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
|
||||
// type
|
||||
final Long targetType2Id = targetType2.getId();
|
||||
assertThatThrownBy(() -> targetManagement.assignType(target2Type2ControllerId, targetType2Id))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
assertThatThrownBy(() -> targetManagement.unassignType(target2Type2ControllerId))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
final String noPermissionsTestDataControllerId = target2Type2.getControllerId();
|
||||
assertThatThrownBy(() -> targetManagement.unassignType(noPermissionsTestDataControllerId))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
|
||||
assertThat(assignDistributionSet(ds2Type2.getId(), target1Type1.getControllerId()).getAssigned()).isEqualTo(1);
|
||||
assertThatThrownBy(() -> assignDistributionSet(ds2Type2.getId(), target2Type2ControllerId)).isInstanceOf(
|
||||
AssertionError.class);
|
||||
// bunch assignment skips denied since at least one target without update permissions is present
|
||||
assertThat(assignDistributionSet(
|
||||
ds3Type2.getId(), List.of(target1Type1.getControllerId(), target2Type2ControllerId), Action.ActionType.FORCED)
|
||||
.getAssigned()).isEqualTo(1);
|
||||
|
||||
assertThat(targetManagement.findByTargetFilterQueryAndNonDSAndCompatibleAndUpdatable(ds1Type1.getId(), "id==*", UNPAGED))
|
||||
.extracting(Identifiable::getId).containsExactly(target1Type1.getId());
|
||||
assertThat(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(
|
||||
target1Type1.getControllerId(), ds1Type1.getId(), "id==*")).isTrue();
|
||||
assertThat(targetManagement.isTargetMatchingQueryAndDSNotAssignedAndCompatibleAndUpdatable(
|
||||
target2Type2.getControllerId(), ds1Type1.getId(), "id==*")).isFalse();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void verifyDeletion() {
|
||||
runAs(withAuthorities(READ_TARGET, DELETE_TARGET + "/type.id==" + targetType1.getId()), () -> {
|
||||
final List<Long> allTargetIds = List.of(target1Type1.getId(), target2Type2.getId());
|
||||
assertThatThrownBy(() -> targetManagement.delete(allTargetIds)).isInstanceOf(InsufficientPermissionException.class);
|
||||
final List<Long> target2Type2IdList = List.of(target2Type2.getId());
|
||||
assertThatThrownBy(() -> targetManagement.delete(target2Type2IdList)).isInstanceOf(InsufficientPermissionException.class);
|
||||
|
||||
targetManagement.delete(List.of(target1Type1.getId()));
|
||||
});
|
||||
}
|
||||
|
||||
private void prepareFinishedUpdates(final DistributionSet ds, final Target... targets) {
|
||||
final List<String> controllerIds = Arrays.stream(targets).map(Target::getControllerId).toList();
|
||||
getFirstAssignedTarget(assignDistributionSet(ds.getId(), controllerIds, Action.ActionType.FORCED));
|
||||
|
||||
controllerIds.stream().map(controllerId -> deploymentManagement.findActiveActionsByTarget(controllerId, PAGE).getContent().get(0))
|
||||
.forEach(action -> {
|
||||
if (action.getStatus() == Action.Status.WAIT_FOR_CONFIRMATION) {
|
||||
confirmationManagement.confirmAction(action.getId(), null, null);
|
||||
}
|
||||
|
||||
action = controllerManagement.addUpdateActionStatus(
|
||||
Action.ActionStatusCreate.builder().actionId(action.getId()).status(Action.Status.RUNNING).build());
|
||||
|
||||
controllerManagement.addUpdateActionStatus(
|
||||
Action.ActionStatusCreate.builder().actionId(action.getId()).status(Action.Status.FINISHED).build());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies only manageable targets are part of the rollout
|
||||
*/
|
||||
@Test
|
||||
void verifyRolloutTargetScope() {
|
||||
final DistributionSet ds = testdataFactory.createDistributionSet("myDs");
|
||||
distributionSetManagement.lock(ds);
|
||||
|
||||
final String[] updateTargetControllerIds = { "update1", "update2", "update3" };
|
||||
final List<Target> updateTargets = testdataFactory.createTargets(updateTargetControllerIds);
|
||||
final String[] readTargetControllerIds = { "read1", "read2", "read3", "read4" };
|
||||
final List<Target> readTargets = testdataFactory.createTargets(readTargetControllerIds);
|
||||
final List<Target> hiddenTargets = testdataFactory.createTargets("hidden1", "hidden2", "hidden3", "hidden4", "hidden5");
|
||||
|
||||
runAs(withUser("user",
|
||||
READ_DISTRIBUTION_SET,
|
||||
READ_TARGET + "/controllerId=in=(" + String.join(", ", List.of(updateTargetControllerIds)) + ")" +
|
||||
" or controllerId=in=(" + String.join(", ", List.of(readTargetControllerIds)) + ")",
|
||||
UPDATE_TARGET + "/controllerId=in=(" + String.join(", ", List.of(updateTargetControllerIds)) + ")",
|
||||
CREATE_ROLLOUT, READ_ROLLOUT), () -> {
|
||||
final Rollout rollout = testdataFactory.createRolloutByVariables(
|
||||
"testRollout", "description", updateTargets.size(), "id==*", ds, "50", "5");
|
||||
assertThat(rollout.getTotalTargets()).isEqualTo(updateTargets.size());
|
||||
|
||||
final List<RolloutGroup> content = rolloutGroupManagement.findByRollout(rollout.getId(), Pageable.unpaged()).getContent();
|
||||
assertThat(content).hasSize(updateTargets.size());
|
||||
|
||||
final List<Target> rolloutTargets = content.stream().flatMap(
|
||||
group -> rolloutGroupManagement.findTargetsOfRolloutGroup(group.getId(), Pageable.unpaged()).get())
|
||||
.toList();
|
||||
|
||||
assertThat(rolloutTargets).hasSize(updateTargets.size()).allMatch(
|
||||
target -> updateTargets.stream().anyMatch(readTarget -> readTarget.getId().equals(target.getId())))
|
||||
.noneMatch(target -> readTargets.stream()
|
||||
.anyMatch(readTarget -> readTarget.getId().equals(target.getId())))
|
||||
.noneMatch(target -> hiddenTargets.stream()
|
||||
.anyMatch(readTarget -> readTarget.getId().equals(target.getId())));
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2023 Bosch.IO GmbH and others
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.acm;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.DELETE_TARGET_TYPE;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_TARGET_TYPE;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.UPDATE_TARGET_TYPE;
|
||||
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.runAs;
|
||||
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.withUser;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.hawkbit.repository.Identifiable;
|
||||
import org.eclipse.hawkbit.repository.TargetTypeManagement.Create;
|
||||
import org.eclipse.hawkbit.repository.TargetTypeManagement.Update;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
|
||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||
import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
/**
|
||||
* Feature: Component Tests - Access Control<br/>
|
||||
* Story: Test Target Type Access Controller
|
||||
*/
|
||||
@TestPropertySource(properties = "hawkbit.acm.access-controller.enabled=true")
|
||||
class TargetTypeAccessControllerTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
/**
|
||||
* Verifies read access rules for target types
|
||||
*/
|
||||
@Test
|
||||
void verifyTargetTypeReadOperations() {
|
||||
final TargetType permittedTargetType = targetTypeManagement.create(Create.builder().name("type1").build());
|
||||
final TargetType hiddenTargetType = targetTypeManagement.create(Create.builder().name("type2").build());
|
||||
|
||||
runAs(withUser("user", READ_TARGET_TYPE + "/id==" + permittedTargetType.getId()), () -> {
|
||||
// verify targetTypeManagement#findAll
|
||||
assertThat(targetTypeManagement.findAll(Pageable.unpaged()).get().map(Identifiable::getId).toList())
|
||||
.containsExactly(permittedTargetType.getId());
|
||||
|
||||
// verify targetTypeManagement#findByRsql
|
||||
assertThat(targetTypeManagement.findByRsql("name==*", Pageable.unpaged()).get().map(Identifiable::getId).toList())
|
||||
.containsExactly(permittedTargetType.getId());
|
||||
|
||||
// verify targetTypeManagement#count
|
||||
assertThat(targetTypeManagement.count()).isEqualTo(1);
|
||||
|
||||
// verify targetTypeManagement#get by id
|
||||
assertThat(targetTypeManagement.find(permittedTargetType.getId())).isPresent();
|
||||
final Long hiddenTargetTypeId = hiddenTargetType.getId();
|
||||
assertThat(targetTypeManagement.find(hiddenTargetTypeId)).isEmpty();
|
||||
|
||||
// verify targetTypeManagement#get by ids
|
||||
final List<Long> allEntityIds = Arrays.asList(permittedTargetType.getId(), hiddenTargetTypeId);
|
||||
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> targetTypeManagement.get(allEntityIds));
|
||||
|
||||
// verify targetTypeManagement#update is not possible. Assert exception thrown.
|
||||
final Update targetTypeUpdate = Update.builder()
|
||||
.id(hiddenTargetTypeId).name(hiddenTargetType.getName() + "/new").description("newDesc")
|
||||
.build();
|
||||
assertThatThrownBy(() -> targetTypeManagement.update(targetTypeUpdate))
|
||||
.as("Target type update shouldn't be allowed since the target type is not visible.")
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
|
||||
// verify targetTypeManagement#delete is not possible. Assert exception thrown.
|
||||
assertThatThrownBy(() -> targetTypeManagement.delete(hiddenTargetTypeId))
|
||||
.as("Target type delete shouldn't be allowed since the target type is not visible.")
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies delete access rules for target types
|
||||
*/
|
||||
@Test
|
||||
void verifyTargetTypeDeleteOperations() {
|
||||
final TargetType manageableTargetType = targetTypeManagement.create(Create.builder().name("type1").build());
|
||||
final TargetType readOnlyTargetType = targetTypeManagement.create(Create.builder().name("type2").build());
|
||||
|
||||
runAs(withUser("user",
|
||||
READ_TARGET_TYPE + "/id==" + manageableTargetType.getId() + " or id==" + readOnlyTargetType.getId(),
|
||||
DELETE_TARGET_TYPE + "/id==" + manageableTargetType.getId()), () -> {
|
||||
// delete the manageableTargetType
|
||||
targetTypeManagement.delete(manageableTargetType.getId());
|
||||
|
||||
// verify targetTypeManagement#delete for readOnlyTargetType is not possible
|
||||
final Long readOnlyTargetTypeId = readOnlyTargetType.getId();
|
||||
assertThatThrownBy(() -> targetTypeManagement.delete(readOnlyTargetTypeId))
|
||||
.isInstanceOfAny(InsufficientPermissionException.class, EntityNotFoundException.class);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies update operation for target types
|
||||
*/
|
||||
@Test
|
||||
void verifyTargetTypeUpdateOperations() {
|
||||
final TargetType manageableTargetType = targetTypeManagement.create(Create.builder().name("type1").build());
|
||||
final TargetType readOnlyTargetType = targetTypeManagement.create(Create.builder().name("type2").build());
|
||||
|
||||
runAs(withUser("user",
|
||||
READ_TARGET_TYPE + "/id==" + manageableTargetType.getId() + " or id==" + readOnlyTargetType.getId(),
|
||||
UPDATE_TARGET_TYPE + "/id==" + manageableTargetType.getId()), () -> {
|
||||
// update the manageableTargetType
|
||||
targetTypeManagement.update(Update.builder().id(manageableTargetType.getId())
|
||||
.name(manageableTargetType.getName() + "/new").description("newDesc").build());
|
||||
|
||||
// verify targetTypeManagement#update for readOnlyTargetType is not possible
|
||||
final Update targetTypeUpdate = Update.builder()
|
||||
.id(readOnlyTargetType.getId()).name(readOnlyTargetType.getName() + "/new").description("newDesc")
|
||||
.build();
|
||||
assertThatThrownBy(() -> targetTypeManagement.update(targetTypeUpdate)).isInstanceOf(InsufficientPermissionException.class);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies create operation blocked by controller
|
||||
*/
|
||||
@Test
|
||||
void verifyTargetTypeCreationBlockedByAccessController() {
|
||||
runAs(withUser("user", READ_TARGET_TYPE, UPDATE_TARGET_TYPE), () -> {
|
||||
// verify targetTypeManagement#create for any type
|
||||
final Create targetTypeCreate = Create.builder().name("type1").build();
|
||||
assertThatThrownBy(() -> targetTypeManagement.create(targetTypeCreate))
|
||||
.as("Target type create shouldn't be allowed since the target type is not visible.")
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Copyright (c) 2025 Contributors to the Eclipse Foundation
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
package org.eclipse.hawkbit.repository.jpa.acm;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.CREATE_PREFIX;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.DELETE_TARGET_TYPE;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.DISTRIBUTION_SET_TYPE;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_PREFIX;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.READ_TARGET_TYPE;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.TARGET_TYPE;
|
||||
import static org.eclipse.hawkbit.im.authentication.SpPermission.UPDATE_TARGET_TYPE;
|
||||
import static org.eclipse.hawkbit.repository.test.util.SecurityContextSwitch.runAs;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.eclipse.hawkbit.repository.TargetTypeManagement.Update;
|
||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
|
||||
import org.eclipse.hawkbit.repository.model.NamedEntity;
|
||||
import org.eclipse.hawkbit.repository.model.TargetType;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class TargetTypeManagementTest extends AbstractAccessControllerManagementTest {
|
||||
|
||||
@Test
|
||||
void verifyCreate() {
|
||||
// permissions to read all and create new type with name 'permitted'
|
||||
runAs(withAuthorities(READ_TARGET_TYPE, CREATE_PREFIX + TARGET_TYPE + "/name==permitted"), () -> {
|
||||
assertThat(testdataFactory.findOrCreateTargetType("permitted")).isNotNull();
|
||||
assertThatThrownBy(() -> testdataFactory.findOrCreateTargetType("not_permitted_2"))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void verifyRead() {
|
||||
// permissions to read only type1 target types
|
||||
runAs(withAuthorities(READ_TARGET_TYPE + "/id==" + targetType1.getId()), () -> {
|
||||
Assertions.<TargetType> assertThat(targetTypeManagement.findAll(UNPAGED)).containsExactly(targetType1);
|
||||
assertThat(targetTypeManagement.count()).isEqualTo(1);
|
||||
|
||||
Assertions.<TargetType> assertThat(targetTypeManagement.findByRsql("name==*", UNPAGED))
|
||||
.contains(targetType1).doesNotContain(targetType2);
|
||||
|
||||
assertThat((Optional) targetTypeManagement.find(targetType1.getId())).hasValue(targetType1);
|
||||
assertThat(targetTypeManagement.find(targetType2.getId())).isEmpty();
|
||||
|
||||
Assertions.<TargetType> assertThat(targetTypeManagement.get(Collections.singletonList(targetType1.getId())))
|
||||
.contains(targetType1).doesNotContain(targetType2);
|
||||
final List<Long> noPermissionsEntitiesIds = Collections.singletonList(targetType2.getId());
|
||||
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> targetTypeManagement.get(noPermissionsEntitiesIds));
|
||||
final List<Long> allEntitiesIds = List.of(targetType1.getId(), targetType2.getId());
|
||||
assertThatExceptionOfType(EntityNotFoundException.class).isThrownBy(() -> targetTypeManagement.get(allEntitiesIds));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void verifyUpdate() {
|
||||
runAs(withAuthorities(READ_TARGET_TYPE, UPDATE_TARGET_TYPE + "/id==" + targetType1.getId(), READ_PREFIX + DISTRIBUTION_SET_TYPE),
|
||||
() -> {
|
||||
assertThat(targetTypeManagement.update(Update.builder().id(targetType1.getId()).description("anotherDesc").build()))
|
||||
.extracting(NamedEntity::getDescription).isEqualTo("anotherDesc");
|
||||
final Update targetTypeUpdate = Update.builder().id(targetType2.getId()).description("anotherDesc").build();
|
||||
assertThatThrownBy(() -> targetTypeManagement.update(targetTypeUpdate)).isInstanceOf(InsufficientPermissionException.class);
|
||||
|
||||
targetTypeManagement.assignCompatibleDistributionSetTypes(targetType1.getId(), List.of(dsType2.getId()));
|
||||
final Long targetType2Id = targetType2.getId();
|
||||
assertThatThrownBy(
|
||||
() -> targetTypeManagement.assignCompatibleDistributionSetTypes(targetType2Id, List.of(dsType2.getId())))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
|
||||
targetTypeManagement.unassignDistributionSetType(targetType1.getId(), dsType2.getId());
|
||||
assertThatThrownBy(() -> targetTypeManagement.unassignDistributionSetType(targetType2Id, dsType2.getId()))
|
||||
.isInstanceOf(InsufficientPermissionException.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void verifyDelete() {
|
||||
// assigned type can't be deleted, so create dedicated ones
|
||||
final TargetType targetType4 = testdataFactory.findOrCreateTargetType("toBeDeleted");
|
||||
final Long targetType5Id = testdataFactory.findOrCreateTargetType("toBeDeleted2").getId();
|
||||
runAs(withAuthorities(READ_TARGET_TYPE, DELETE_TARGET_TYPE + "/id==" + targetType4.getId()), () -> {
|
||||
targetTypeManagement.delete(targetType4.getId());
|
||||
assertThatThrownBy(() -> targetTypeManagement.delete(targetType5Id)).isInstanceOf(InsufficientPermissionException.class);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ import org.junit.jupiter.api.Test;
|
||||
* Feature: Component Tests - Access Control<br/>
|
||||
* Story: Test Distribution Set Access Controller
|
||||
*/
|
||||
class TargetTypeQueryManagementTest extends AbstractAccessControllerTest {
|
||||
class TargetTypeQueryManagementTest extends AbstractAccessControllerManagementTest {
|
||||
|
||||
@Test
|
||||
void verifyAutoAssignmentRestrictionByDs() {
|
||||
|
||||
Reference in New Issue
Block a user