JPA Refactoring (3) (#2109)

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2024-12-02 13:50:06 +02:00
committed by GitHub
parent 794f26bea2
commit a9f3d1491a
37 changed files with 151 additions and 246 deletions

View File

@@ -146,8 +146,7 @@ class DdiRootControllerTest extends AbstractDDiApiIntegrationTest {
@Test @Test
@Description("Ensures that server returns a not found response in case of empty controller ID.") @Description("Ensures that server returns a not found response in case of empty controller ID.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
@Expect(type = TargetCreatedEvent.class, count = 0) })
void rootRsWithoutId() throws Exception { void rootRsWithoutId() throws Exception {
mvc.perform(get("/controller/v1/")) mvc.perform(get("/controller/v1/"))
.andDo(MockMvcResultPrinter.print()) .andDo(MockMvcResultPrinter.print())

View File

@@ -28,20 +28,17 @@ public class PreAuthorizeEnabledTest extends AbstractSecurityTest {
@Test @Test
@Description("Tests whether request fail if a role is forbidden for the user") @Description("Tests whether request fail if a role is forbidden for the user")
@WithUser(authorities = { SpPermission.READ_TARGET }) @WithUser(authorities = { SpPermission.READ_TARGET }, autoCreateTenant = false)
public void failIfNoRole() throws Exception { public void failIfNoRole() throws Exception {
mvc.perform(get("/DEFAULT/controller/v1/controllerId")) mvc.perform(get("/DEFAULT/controller/v1/controllerId"))
.andExpect(result -> .andExpect(result -> assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.FORBIDDEN.value()));
assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.FORBIDDEN.value()));
} }
@Test @Test
@Description("Tests whether request succeed if a role is granted for the user") @Description("Tests whether request succeed if a role is granted for the user")
@WithUser(authorities = { SpPermission.SpringEvalExpressions.CONTROLLER_ROLE }) @WithUser(authorities = { SpPermission.SpringEvalExpressions.CONTROLLER_ROLE }, autoCreateTenant = false)
public void successIfHasRole() throws Exception { public void successIfHasRole() throws Exception {
mvc.perform(get("/DEFAULT/controller/v1/controllerId")) mvc.perform(get("/DEFAULT/controller/v1/controllerId"))
.andExpect(result -> { .andExpect(result -> assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value()));
assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value());
});
} }
} }

View File

@@ -63,8 +63,7 @@ public class BaseAmqpServiceTest {
@Test @Test
@Description("Tests invalid null message content") @Description("Tests invalid null message content")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
@Expect(type = TargetCreatedEvent.class, count = 0) })
public void convertMessageWithNullContent() { public void convertMessageWithNullContent() {
final Message message = createMessage("".getBytes()); final Message message = createMessage("".getBytes());
assertThatExceptionOfType(MessageConversionException.class) assertThatExceptionOfType(MessageConversionException.class)
@@ -74,8 +73,7 @@ public class BaseAmqpServiceTest {
@Test @Test
@Description("Tests invalid empty message content") @Description("Tests invalid empty message content")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
@Expect(type = TargetCreatedEvent.class, count = 0) })
public void updateActionStatusWithEmptyContent() { public void updateActionStatusWithEmptyContent() {
final Message message = createMessage("".getBytes()); final Message message = createMessage("".getBytes());
assertThatExceptionOfType(MessageConversionException.class) assertThatExceptionOfType(MessageConversionException.class)
@@ -85,8 +83,7 @@ public class BaseAmqpServiceTest {
@Test @Test
@Description("Tests invalid json message content") @Description("Tests invalid json message content")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
@Expect(type = TargetCreatedEvent.class, count = 0) })
public void updateActionStatusWithInvalidJsonContent() { public void updateActionStatusWithInvalidJsonContent() {
final Message message = createMessage("Invalid Json".getBytes()); final Message message = createMessage("Invalid Json".getBytes());
when(rabbitTemplate.getMessageConverter()).thenReturn(new Jackson2JsonMessageConverter()); when(rabbitTemplate.getMessageConverter()).thenReturn(new Jackson2JsonMessageConverter());

View File

@@ -187,8 +187,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
@ValueSource(strings = { "", "Invalid Invalid" }) @ValueSource(strings = { "", "Invalid Invalid" })
@NullSource @NullSource
@Description("Tests register invalid target with empty controller id.") @Description("Tests register invalid target with empty controller id.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
@Expect(type = TargetCreatedEvent.class) })
void shouldNotRegisterTargetsWithInvalidControllerIds(String controllerId) { void shouldNotRegisterTargetsWithInvalidControllerIds(String controllerId) {
createAndSendThingCreated(controllerId); createAndSendThingCreated(controllerId);
assertAllTargetsCount(0); assertAllTargetsCount(0);
@@ -197,8 +196,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
@Test @Test
@Description("Tests register invalid target with too long controller id") @Description("Tests register invalid target with too long controller id")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
@Expect(type = TargetCreatedEvent.class) })
void registerInvalidTargetWithTooLongControllerId() { void registerInvalidTargetWithTooLongControllerId() {
createAndSendThingCreated(RandomStringUtils.randomAlphabetic(Target.CONTROLLER_ID_MAX_SIZE + 1)); createAndSendThingCreated(RandomStringUtils.randomAlphabetic(Target.CONTROLLER_ID_MAX_SIZE + 1));
assertAllTargetsCount(0); assertAllTargetsCount(0);
@@ -207,8 +205,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
@Test @Test
@Description("Tests null reply to property in message header. This message should forwarded to the deadletter queue") @Description("Tests null reply to property in message header. This message should forwarded to the deadletter queue")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
@Expect(type = TargetCreatedEvent.class) })
void missingReplyToProperty() { void missingReplyToProperty() {
final String controllerId = TARGET_PREFIX + "missingReplyToProperty"; final String controllerId = TARGET_PREFIX + "missingReplyToProperty";
final Message createTargetMessage = createTargetMessage(controllerId, TENANT_EXIST); final Message createTargetMessage = createTargetMessage(controllerId, TENANT_EXIST);
@@ -221,8 +218,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
@Test @Test
@Description("Tests missing reply to property in message header. This message should forwarded to the deadletter queue") @Description("Tests missing reply to property in message header. This message should forwarded to the deadletter queue")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
@Expect(type = TargetCreatedEvent.class) })
void emptyReplyToProperty() { void emptyReplyToProperty() {
final String controllerId = TARGET_PREFIX + "emptyReplyToProperty"; final String controllerId = TARGET_PREFIX + "emptyReplyToProperty";
final Message createTargetMessage = createTargetMessage(controllerId, TENANT_EXIST); final Message createTargetMessage = createTargetMessage(controllerId, TENANT_EXIST);
@@ -235,8 +231,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
@Test @Test
@Description("Tests missing thing id property in message. This message should forwarded to the deadletter queue") @Description("Tests missing thing id property in message. This message should forwarded to the deadletter queue")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
@Expect(type = TargetCreatedEvent.class) })
void missingThingIdProperty() { void missingThingIdProperty() {
final Message createTargetMessage = createTargetMessage(null, TENANT_EXIST); final Message createTargetMessage = createTargetMessage(null, TENANT_EXIST);
createTargetMessage.getMessageProperties().getHeaders().remove(MessageHeaderKey.THING_ID); createTargetMessage.getMessageProperties().getHeaders().remove(MessageHeaderKey.THING_ID);
@@ -248,8 +243,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
@Test @Test
@Description("Tests null thing id property in message. This message should forwarded to the deadletter queue") @Description("Tests null thing id property in message. This message should forwarded to the deadletter queue")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
@Expect(type = TargetCreatedEvent.class) })
void nullThingIdProperty() { void nullThingIdProperty() {
final Message createTargetMessage = createTargetMessage(null, TENANT_EXIST); final Message createTargetMessage = createTargetMessage(null, TENANT_EXIST);
getDmfClient().send(createTargetMessage); getDmfClient().send(createTargetMessage);
@@ -260,8 +254,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
@Test @Test
@Description("Tests missing tenant message header. This message should forwarded to the deadletter queue") @Description("Tests missing tenant message header. This message should forwarded to the deadletter queue")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
@Expect(type = TargetCreatedEvent.class) })
void missingTenantHeader() { void missingTenantHeader() {
final String controllerId = TARGET_PREFIX + "missingTenantHeader"; final String controllerId = TARGET_PREFIX + "missingTenantHeader";
final Message createTargetMessage = createTargetMessage(controllerId, TENANT_EXIST); final Message createTargetMessage = createTargetMessage(controllerId, TENANT_EXIST);
@@ -274,8 +267,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
@Test @Test
@Description("Tests null tenant message header. This message should forwarded to the deadletter queue") @Description("Tests null tenant message header. This message should forwarded to the deadletter queue")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
@Expect(type = TargetCreatedEvent.class) })
void nullTenantHeader() { void nullTenantHeader() {
final String controllerId = TARGET_PREFIX + "nullTenantHeader"; final String controllerId = TARGET_PREFIX + "nullTenantHeader";
final Message createTargetMessage = createTargetMessage(controllerId, null); final Message createTargetMessage = createTargetMessage(controllerId, null);
@@ -287,8 +279,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
@Test @Test
@Description("Tests empty tenant message header. This message should forwarded to the deadletter queue") @Description("Tests empty tenant message header. This message should forwarded to the deadletter queue")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
@Expect(type = TargetCreatedEvent.class) })
void emptyTenantHeader() { void emptyTenantHeader() {
final String controllerId = TARGET_PREFIX + "emptyTenantHeader"; final String controllerId = TARGET_PREFIX + "emptyTenantHeader";
final Message createTargetMessage = createTargetMessage(controllerId, ""); final Message createTargetMessage = createTargetMessage(controllerId, "");
@@ -300,8 +291,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
@Test @Test
@Description("Tests missing type message header. This message should forwarded to the deadletter queue") @Description("Tests missing type message header. This message should forwarded to the deadletter queue")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
@Expect(type = TargetCreatedEvent.class) })
void missingTypeHeader() { void missingTypeHeader() {
final Message createTargetMessage = createTargetMessage(null, TENANT_EXIST); final Message createTargetMessage = createTargetMessage(null, TENANT_EXIST);
createTargetMessage.getMessageProperties().getHeaders().remove(MessageHeaderKey.TYPE); createTargetMessage.getMessageProperties().getHeaders().remove(MessageHeaderKey.TYPE);
@@ -315,8 +305,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
@ValueSource(strings = { "", "NotExist" }) @ValueSource(strings = { "", "NotExist" })
@NullSource @NullSource
@Description("Tests null type message header. This message should forwarded to the deadletter queue") @Description("Tests null type message header. This message should forwarded to the deadletter queue")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
@Expect(type = TargetCreatedEvent.class) })
void shouldNotCreateTargetsWithInvalidTypeInHeader(String type) { void shouldNotCreateTargetsWithInvalidTypeInHeader(String type) {
final Message createTargetMessage = createTargetMessage(null, TENANT_EXIST); final Message createTargetMessage = createTargetMessage(null, TENANT_EXIST);
createTargetMessage.getMessageProperties().getHeaders().put(MessageHeaderKey.TYPE, type); createTargetMessage.getMessageProperties().getHeaders().put(MessageHeaderKey.TYPE, type);
@@ -330,8 +319,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
@ValueSource(strings = { "", "NotExist" }) @ValueSource(strings = { "", "NotExist" })
@NullSource @NullSource
@Description("Tests null topic message header. This message should forwarded to the deadletter queue") @Description("Tests null topic message header. This message should forwarded to the deadletter queue")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
@Expect(type = TargetCreatedEvent.class) })
void shouldNotSendMessagesWithInvalidTopic(String topic) { void shouldNotSendMessagesWithInvalidTopic(String topic) {
final Message eventMessage = createUpdateActionEventMessage(""); final Message eventMessage = createUpdateActionEventMessage("");
eventMessage.getMessageProperties().getHeaders().put(MessageHeaderKey.TOPIC, topic); eventMessage.getMessageProperties().getHeaders().put(MessageHeaderKey.TOPIC, topic);
@@ -342,8 +330,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
@Test @Test
@Description("Tests missing topic message header. This message should forwarded to the deadletter queue") @Description("Tests missing topic message header. This message should forwarded to the deadletter queue")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
@Expect(type = TargetCreatedEvent.class) })
void missingTopicHeader() { void missingTopicHeader() {
final Message eventMessage = createUpdateActionEventMessage(""); final Message eventMessage = createUpdateActionEventMessage("");
eventMessage.getMessageProperties().getHeaders().remove(MessageHeaderKey.TOPIC); eventMessage.getMessageProperties().getHeaders().remove(MessageHeaderKey.TOPIC);
@@ -356,8 +343,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
@ValueSource(strings = { "", "Invalid Content" }) @ValueSource(strings = { "", "Invalid Content" })
@NullSource @NullSource
@Description("Tests invalid null message content. This message should forwarded to the deadletter queue") @Description("Tests invalid null message content. This message should forwarded to the deadletter queue")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
@Expect(type = TargetCreatedEvent.class) })
void shouldMoveUpdateActionStatusWithInvalidPayloadIntoDeadLetter(String payload) { void shouldMoveUpdateActionStatusWithInvalidPayloadIntoDeadLetter(String payload) {
final Message eventMessage = createUpdateActionEventMessage(payload); final Message eventMessage = createUpdateActionEventMessage(payload);
getDmfClient().send(eventMessage); getDmfClient().send(eventMessage);
@@ -366,8 +352,7 @@ class AmqpMessageHandlerServiceIntegrationTest extends AbstractAmqpServiceIntegr
@Test @Test
@Description("Tests invalid topic message header. This message should forwarded to the deadletter queue") @Description("Tests invalid topic message header. This message should forwarded to the deadletter queue")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
@Expect(type = TargetCreatedEvent.class) })
void updateActionStatusWithInvalidActionId() { void updateActionStatusWithInvalidActionId() {
final DmfActionUpdateStatus actionUpdateStatus = new DmfActionUpdateStatus(1L, DmfActionStatus.RUNNING); final DmfActionUpdateStatus actionUpdateStatus = new DmfActionUpdateStatus(1L, DmfActionStatus.RUNNING);
final Message eventMessage = createUpdateActionEventMessage(actionUpdateStatus); final Message eventMessage = createUpdateActionEventMessage(actionUpdateStatus);

View File

@@ -34,5 +34,4 @@ public abstract class AbstractSecurityTest {
.apply(SecurityMockMvcConfigurers.springSecurity()).dispatchOptions(true); .apply(SecurityMockMvcConfigurers.springSecurity()).dispatchOptions(true);
mvc = builder.build(); mvc = builder.build();
} }
} }

View File

@@ -46,7 +46,7 @@ public class CorsTest extends AbstractSecurityTest {
@Test @Test
@Description("Ensures that Cors is working.") @Description("Ensures that Cors is working.")
@WithUser(authorities = SpRole.TENANT_ADMIN) @WithUser(authorities = SpRole.TENANT_ADMIN, autoCreateTenant = false)
public void validateCorsRequest() throws Exception { public void validateCorsRequest() throws Exception {
performOptionsRequestToRestWithOrigin(ALLOWED_ORIGIN_FIRST).andExpect(status().isOk()) performOptionsRequestToRestWithOrigin(ALLOWED_ORIGIN_FIRST).andExpect(status().isOk())
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, ALLOWED_ORIGIN_FIRST)); .andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, ALLOWED_ORIGIN_FIRST));

View File

@@ -30,7 +30,7 @@ public class PreAuthorizeEnabledTest extends AbstractSecurityTest {
@Test @Test
@Description("Tests whether request fail if a role is forbidden for the user") @Description("Tests whether request fail if a role is forbidden for the user")
@WithUser(authorities = { SpPermission.READ_TARGET }) @WithUser(authorities = { SpPermission.READ_TARGET }, autoCreateTenant = false)
public void failIfNoRole() throws Exception { public void failIfNoRole() throws Exception {
mvc.perform(get("/rest/v1/distributionsets")).andExpect(result -> mvc.perform(get("/rest/v1/distributionsets")).andExpect(result ->
assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.FORBIDDEN.value())); assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.FORBIDDEN.value()));
@@ -38,41 +38,36 @@ public class PreAuthorizeEnabledTest extends AbstractSecurityTest {
@Test @Test
@Description("Tests whether request succeed if a role is granted for the user") @Description("Tests whether request succeed if a role is granted for the user")
@WithUser(authorities = { SpPermission.READ_REPOSITORY }) @WithUser(authorities = { SpPermission.READ_REPOSITORY }, autoCreateTenant = false)
public void successIfHasRole() throws Exception { public void successIfHasRole() throws Exception {
mvc.perform(get("/rest/v1/distributionsets")).andExpect(result -> { mvc.perform(get("/rest/v1/distributionsets")).andExpect(result ->
assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value()); assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value()));
});
} }
@Test @Test
@Description("Tests whether request succeed if a role is granted for the user") @Description("Tests whether request succeed if a role is granted for the user")
@WithUser(authorities = { SpRole.TENANT_ADMIN }) @WithUser(authorities = { SpRole.TENANT_ADMIN }, autoCreateTenant = false)
public void successIfHasTenantAdminRole() throws Exception { public void successIfHasTenantAdminRole() throws Exception {
mvc.perform(get("/rest/v1/distributionsets")).andExpect(result -> { mvc.perform(get("/rest/v1/distributionsets")).andExpect(result ->
assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value()); assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value()));
});
} }
@Test @Test
@Description("Tests whether read tenant config request fail if a tenant config (or read read) is not " + @Description("Tests whether read tenant config request fail if a tenant config (or read read) is not granted for the user")
"granted for the user") @WithUser(authorities = { SpPermission.READ_TARGET }, autoCreateTenant = false)
@WithUser(authorities = { SpPermission.READ_TARGET })
public void onlyDSIfNoTenantConfig() throws Exception { public void onlyDSIfNoTenantConfig() throws Exception {
mvc.perform(get("/rest/v1/system/configs")).andExpect(result -> { mvc.perform(get("/rest/v1/system/configs")).andExpect(result -> {
// returns default DS type because of READ_TARGET // returns default DS type because of READ_TARGET
assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value()); assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value());
assertThat( assertThat(
new ObjectMapper().reader().readValue(result.getResponse().getContentAsString(), HashMap.class) new ObjectMapper().reader().readValue(result.getResponse().getContentAsString(), HashMap.class).size())
.size())
.isEqualTo(1); .isEqualTo(1);
}); });
} }
@Test @Test
@Description("Tests whether read tenant config request succeed if a tenant config (not read explicitly) is " + @Description("Tests whether read tenant config request succeed if a tenant config (not read explicitly) is granted for the user")
"granted for the user") @WithUser(authorities = { SpPermission.TENANT_CONFIGURATION }, autoCreateTenant = false)
@WithUser(authorities = { SpPermission.TENANT_CONFIGURATION })
public void successIfHasTenantConfig() throws Exception { public void successIfHasTenantConfig() throws Exception {
mvc.perform(get("/rest/v1/system/configs")).andExpect(result -> mvc.perform(get("/rest/v1/system/configs")).andExpect(result ->
assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value())); assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value()));

View File

@@ -46,7 +46,7 @@ public class CorsTest extends AbstractSecurityTest {
@Test @Test
@Description("Ensures that Cors is working.") @Description("Ensures that Cors is working.")
@WithUser(authorities = SpRole.TENANT_ADMIN) @WithUser(authorities = SpRole.TENANT_ADMIN, autoCreateTenant = false)
public void validateCorsRequest() throws Exception { public void validateCorsRequest() throws Exception {
performOptionsRequestToRestWithOrigin(ALLOWED_ORIGIN_FIRST).andExpect(status().isOk()) performOptionsRequestToRestWithOrigin(ALLOWED_ORIGIN_FIRST).andExpect(status().isOk())
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, ALLOWED_ORIGIN_FIRST)); .andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, ALLOWED_ORIGIN_FIRST));

View File

@@ -30,56 +30,46 @@ public class PreAuthorizeEnabledTest extends AbstractSecurityTest {
@Test @Test
@Description("Tests whether request fail if a role is forbidden for the user") @Description("Tests whether request fail if a role is forbidden for the user")
@WithUser(authorities = { SpPermission.READ_TARGET }) @WithUser(authorities = { SpPermission.READ_TARGET }, autoCreateTenant = false)
public void failIfNoRole() throws Exception { public void failIfNoRole() throws Exception {
mvc.perform(get("/rest/v1/distributionsets")) mvc.perform(get("/rest/v1/distributionsets"))
.andExpect(result -> .andExpect(result -> assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.FORBIDDEN.value()));
assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.FORBIDDEN.value()));
} }
@Test @Test
@Description("Tests whether request succeed if a role is granted for the user") @Description("Tests whether request succeed if a role is granted for the user")
@WithUser(authorities = { SpPermission.READ_REPOSITORY }) @WithUser(authorities = { SpPermission.READ_REPOSITORY }, autoCreateTenant = false)
public void successIfHasRole() throws Exception { public void successIfHasRole() throws Exception {
mvc.perform(get("/rest/v1/distributionsets")) mvc.perform(get("/rest/v1/distributionsets"))
.andExpect(result -> { .andExpect(result -> assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value()));
assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value());
});
} }
@Test @Test
@Description("Tests whether request succeed if a role is granted for the user") @Description("Tests whether request succeed if a role is granted for the user")
@WithUser(authorities = { SpRole.TENANT_ADMIN }) @WithUser(authorities = { SpRole.TENANT_ADMIN }, autoCreateTenant = false)
public void successIfHasTenantAdminRole() throws Exception { public void successIfHasTenantAdminRole() throws Exception {
mvc.perform(get("/rest/v1/distributionsets")) mvc.perform(get("/rest/v1/distributionsets"))
.andExpect(result -> { .andExpect(result -> assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value()));
assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value());
});
} }
@Test @Test
@Description("Tests whether read tenant config request fail if a tenant config (or read read) is not " + @Description("Tests whether read tenant config request fail if a tenant config (or read read) is not granted for the user")
"granted for the user") @WithUser(authorities = { SpPermission.READ_TARGET }, autoCreateTenant = false)
@WithUser(authorities = { SpPermission.READ_TARGET })
public void onlyDSIfNoTenantConfig() throws Exception { public void onlyDSIfNoTenantConfig() throws Exception {
mvc.perform(get("/rest/v1/system/configs")) mvc.perform(get("/rest/v1/system/configs"))
.andExpect(result -> { .andExpect(result -> {
// returns default DS type because of READ_TARGET // returns default DS type because of READ_TARGET
assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value()); assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value());
assertThat( assertThat(new ObjectMapper().reader().readValue(result.getResponse().getContentAsString(), HashMap.class).size())
new ObjectMapper().reader().readValue(result.getResponse().getContentAsString(), HashMap.class)
.size())
.isEqualTo(1); .isEqualTo(1);
}); });
} }
@Test @Test
@Description("Tests whether read tenant config request succeed if a tenant config (not read explicitly) is " + @Description("Tests whether read tenant config request succeed if a tenant config (not read explicitly) is granted for the user")
"granted for the user") @WithUser(authorities = { SpPermission.TENANT_CONFIGURATION }, autoCreateTenant = false)
@WithUser(authorities = { SpPermission.TENANT_CONFIGURATION })
public void successIfHasTenantConfig() throws Exception { public void successIfHasTenantConfig() throws Exception {
mvc.perform(get("/rest/v1/system/configs")) mvc.perform(get("/rest/v1/system/configs"))
.andExpect(result -> .andExpect(result -> assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value()));
assertThat(result.getResponse().getStatus()).isEqualTo(HttpStatus.OK.value()));
} }
} }

View File

@@ -109,7 +109,4 @@ public interface SystemManagement {
@PreAuthorize(SpringEvalExpressions.IS_SYSTEM_CODE) @PreAuthorize(SpringEvalExpressions.IS_SYSTEM_CODE)
TenantMetaData getTenantMetadata(long tenantId); TenantMetaData getTenantMetadata(long tenantId);
@PreAuthorize(SpringEvalExpressions.IS_SYSTEM_CODE)
boolean tenantExists(String tenant);
} }

View File

@@ -154,7 +154,6 @@ import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetFilterQuery; import org.eclipse.hawkbit.repository.model.TargetFilterQuery;
import org.eclipse.hawkbit.repository.model.TargetType; import org.eclipse.hawkbit.repository.model.TargetType;
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder; import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
import org.eclipse.hawkbit.repository.model.helper.SystemManagementHolder;
import org.eclipse.hawkbit.repository.model.helper.SystemSecurityContextHolder; import org.eclipse.hawkbit.repository.model.helper.SystemSecurityContextHolder;
import org.eclipse.hawkbit.repository.model.helper.TenantConfigurationManagementHolder; import org.eclipse.hawkbit.repository.model.helper.TenantConfigurationManagementHolder;
import org.eclipse.hawkbit.repository.rsql.RsqlConfigHolder; import org.eclipse.hawkbit.repository.rsql.RsqlConfigHolder;
@@ -488,16 +487,6 @@ public class RepositoryApplicationConfiguration extends JpaBaseConfiguration {
return TenantConfigurationManagementHolder.getInstance(); return TenantConfigurationManagementHolder.getInstance();
} }
/**
* @return the {@link SystemManagementHolder} singleton bean which holds the
* current {@link SystemManagement} service and make it accessible in
* beans which cannot access the service directly, e.g. JPA entities.
*/
@Bean
SystemManagementHolder systemManagementHolder() {
return SystemManagementHolder.getInstance();
}
/** /**
* @return the {@link TenantAwareHolder} singleton bean which holds the current * @return the {@link TenantAwareHolder} singleton bean which holds the current
* {@link TenantAware} service and make it accessible in beans which * {@link TenantAware} service and make it accessible in beans which

View File

@@ -24,7 +24,6 @@ import org.eclipse.hawkbit.repository.RepositoryConstants;
import org.eclipse.hawkbit.repository.RepositoryProperties; import org.eclipse.hawkbit.repository.RepositoryProperties;
import org.eclipse.hawkbit.repository.builder.ActionStatusCreate; import org.eclipse.hawkbit.repository.builder.ActionStatusCreate;
import org.eclipse.hawkbit.repository.exception.AutoConfirmationAlreadyActiveException; import org.eclipse.hawkbit.repository.exception.AutoConfirmationAlreadyActiveException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.InvalidConfirmationFeedbackException; import org.eclipse.hawkbit.repository.exception.InvalidConfirmationFeedbackException;
import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusCreate; import org.eclipse.hawkbit.repository.jpa.builder.JpaActionStatusCreate;
import org.eclipse.hawkbit.repository.jpa.configuration.Constants; import org.eclipse.hawkbit.repository.jpa.configuration.Constants;
@@ -35,7 +34,6 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository; import org.eclipse.hawkbit.repository.jpa.repository.ActionStatusRepository;
import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository; import org.eclipse.hawkbit.repository.jpa.repository.TargetRepository;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
import org.eclipse.hawkbit.repository.model.Action; import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.Action.Status; import org.eclipse.hawkbit.repository.model.Action.Status;
import org.eclipse.hawkbit.repository.model.AutoConfirmationStatus; import org.eclipse.hawkbit.repository.model.AutoConfirmationStatus;
@@ -81,7 +79,7 @@ public class JpaConfirmationManagement extends JpaActionManagement implements Co
public AutoConfirmationStatus activateAutoConfirmation(final String controllerId, final String initiator, final String remark) { public AutoConfirmationStatus activateAutoConfirmation(final String controllerId, final String initiator, final String remark) {
log.trace( log.trace(
"'activateAutoConfirmation' was called with values: controllerId={}; initiator={}; remark={}", controllerId, initiator, remark); "'activateAutoConfirmation' was called with values: controllerId={}; initiator={}; remark={}", controllerId, initiator, remark);
final JpaTarget target = getTargetByControllerIdAndThrowIfNotFound(controllerId); final JpaTarget target = targetRepository.getByControllerId(controllerId);
if (target.getAutoConfirmationStatus() != null) { if (target.getAutoConfirmationStatus() != null) {
log.debug("'activateAutoConfirmation' was called for an controller id {} with active auto confirmation.", controllerId); log.debug("'activateAutoConfirmation' was called for an controller id {} with active auto confirmation.", controllerId);
throw new AutoConfirmationAlreadyActiveException(controllerId); throw new AutoConfirmationAlreadyActiveException(controllerId);
@@ -104,13 +102,13 @@ public class JpaConfirmationManagement extends JpaActionManagement implements Co
@Override @Override
public Optional<AutoConfirmationStatus> getStatus(final String controllerId) { public Optional<AutoConfirmationStatus> getStatus(final String controllerId) {
return Optional.of(getTargetByControllerIdAndThrowIfNotFound(controllerId)).map(JpaTarget::getAutoConfirmationStatus); return Optional.of(targetRepository.getByControllerId(controllerId)).map(JpaTarget::getAutoConfirmationStatus);
} }
@Override @Override
@Transactional @Transactional
public List<Action> autoConfirmActiveActions(final String controllerId) { public List<Action> autoConfirmActiveActions(final String controllerId) {
final JpaTarget target = getTargetByControllerIdAndThrowIfNotFound(controllerId); final JpaTarget target = targetRepository.getByControllerId(controllerId);
if (target.getAutoConfirmationStatus() == null) { if (target.getAutoConfirmationStatus() == null) {
// auto-confirmation is not active // auto-confirmation is not active
return Collections.emptyList(); return Collections.emptyList();
@@ -159,7 +157,7 @@ public class JpaConfirmationManagement extends JpaActionManagement implements Co
@Transactional @Transactional
public void deactivateAutoConfirmation(String controllerId) { public void deactivateAutoConfirmation(String controllerId) {
log.debug("Deactivate auto confirmation for controllerId '{}'", controllerId); log.debug("Deactivate auto confirmation for controllerId '{}'", controllerId);
final JpaTarget target = getTargetByControllerIdAndThrowIfNotFound(controllerId); final JpaTarget target = targetRepository.getByControllerId(controllerId);
target.setAutoConfirmationStatus(null); target.setAutoConfirmationStatus(null);
targetRepository.save(target); targetRepository.save(target);
} }
@@ -220,19 +218,12 @@ public class JpaConfirmationManagement extends JpaActionManagement implements Co
"Automatically confirm actionId '{}' due to active auto-confirmation initiated by '{}' and rollouts system user '{}'", "Automatically confirm actionId '{}' due to active auto-confirmation initiated by '{}' and rollouts system user '{}'",
action.getId(), autoConfirmationStatus.getInitiator(), autoConfirmationStatus.getCreatedBy()); action.getId(), autoConfirmationStatus.getInitiator(), autoConfirmationStatus.getCreatedBy());
// do not make use of // do not make use of org.eclipse.hawkbit.repository.jpa.management.JpaActionManagement.handleAddUpdateActionStatus
// org.eclipse.hawkbit.repository.jpa.management.JpaActionManagement.handleAddUpdateActionStatus // to bypass the quota check. Otherwise, the action will not be confirmed in case of exceeded action status quota.
// to bypass the quota check. Otherwise, the action will not be confirmed in case
// of exceeded action status quota.
action.setStatus(Status.RUNNING); action.setStatus(Status.RUNNING);
actionStatus.setAction(action); actionStatus.setAction(action);
actionStatusRepository.save(actionStatus); actionStatusRepository.save(actionStatus);
return actionRepository.save(action); return actionRepository.save(action);
} }
private JpaTarget getTargetByControllerIdAndThrowIfNotFound(final String controllerId) {
return targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId))
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
}
} }

View File

@@ -414,8 +414,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont
throw new InvalidTargetAttributeException(); throw new InvalidTargetAttributeException();
} }
final JpaTarget target = targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)) final JpaTarget target = targetRepository.getByControllerId(controllerId);
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
// get the modifiable attribute map // get the modifiable attribute map
final Map<String, String> controllerAttributes = target.getControllerAttributes(); final Map<String, String> controllerAttributes = target.getControllerAttributes();
@@ -447,7 +446,7 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont
@Override @Override
public Optional<Target> getByControllerId(final String controllerId) { public Optional<Target> getByControllerId(final String controllerId) {
return targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)).map(Target.class::cast); return targetRepository.findByControllerId(controllerId).map(Target.class::cast);
} }
@Override @Override
@@ -541,20 +540,16 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont
@Override @Override
public void deleteExistingTarget(@NotEmpty final String controllerId) { public void deleteExistingTarget(@NotEmpty final String controllerId) {
final Target target = targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)) targetRepository.deleteById(targetRepository.getByControllerId(controllerId).getId());
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
targetRepository.deleteById(target.getId());
} }
@Override @Override
public Optional<Action> getInstalledActionByTarget(final String controllerId) { public Optional<Action> getInstalledActionByTarget(final String controllerId) {
final JpaTarget jpaTarget = targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)) final JpaDistributionSet installedDistributionSet = targetRepository.getByControllerId(controllerId).getInstalledDistributionSet();
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId)); if (installedDistributionSet != null) {
final JpaTarget jpaTarget = targetRepository.getByControllerId(controllerId);
final JpaDistributionSet installedDistributionSet = jpaTarget.getInstalledDistributionSet(); return actionRepository.findFirstByTargetIdAndDistributionSetIdAndStatusOrderByIdDesc(
if (null != installedDistributionSet) { jpaTarget.getId(), installedDistributionSet.getId(), FINISHED);
return actionRepository.findFirstByTargetIdAndDistributionSetIdAndStatusOrderByIdDesc(jpaTarget.getId(),
installedDistributionSet.getId(), FINISHED);
} else { } else {
return Optional.empty(); return Optional.empty();
} }

View File

@@ -486,16 +486,12 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
@Override @Override
public Optional<DistributionSet> getAssignedDistributionSet(final String controllerId) { public Optional<DistributionSet> getAssignedDistributionSet(final String controllerId) {
return targetRepository return targetRepository.findByControllerId(controllerId).map(JpaTarget::getAssignedDistributionSet);
.findOne(TargetSpecifications.hasControllerId(controllerId))
.map(JpaTarget::getAssignedDistributionSet);
} }
@Override @Override
public Optional<DistributionSet> getInstalledDistributionSet(final String controllerId) { public Optional<DistributionSet> getInstalledDistributionSet(final String controllerId) {
return targetRepository return targetRepository.findByControllerId(controllerId).map(JpaTarget::getInstalledDistributionSet);
.findOne(TargetSpecifications.hasControllerId(controllerId))
.map(JpaTarget::getInstalledDistributionSet);
} }
@Override @Override
@@ -710,8 +706,7 @@ public class JpaDeploymentManagement extends JpaActionManagement implements Depl
} }
private void checkCompatibilityForMultiDsAssignment(final String controllerId, final List<Long> distSetIds) { private void checkCompatibilityForMultiDsAssignment(final String controllerId, final List<Long> distSetIds) {
final Target target = targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)) final Target target = targetRepository.getByControllerId(controllerId);
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
if (target.getTargetType() != null) { if (target.getTargetType() != null) {
// we assume that list of assigned DS is less than // we assume that list of assigned DS is less than

View File

@@ -73,8 +73,10 @@ import org.springframework.validation.annotation.Validated;
public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, SystemManagement { public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, SystemManagement {
private static final int MAX_TENANTS_QUERY = 1000; private static final int MAX_TENANTS_QUERY = 1000;
private final String countArtifactQuery; private final String countArtifactQuery;
private final String countSoftwareModulesQuery; private final String countSoftwareModulesQuery;
@Autowired @Autowired
private EntityManager entityManager; private EntityManager entityManager;
@Autowired @Autowired
@@ -284,12 +286,6 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
.orElseThrow(() -> new EntityNotFoundException(TenantMetaData.class, tenantId)); .orElseThrow(() -> new EntityNotFoundException(TenantMetaData.class, tenantId));
} }
@Override
@Cacheable(value = "currentTenant", keyGenerator = "currentTenantKeyGenerator", cacheManager = "directCacheManager", unless = "#result == null")
public boolean tenantExists(final String tenant) {
return tenantMetaDataRepository.findByTenantIgnoreCase(tenant) != null;
}
private static boolean isPostgreSql(final JpaProperties properties) { private static boolean isPostgreSql(final JpaProperties properties) {
return Database.POSTGRESQL == properties.getDatabase(); return Database.POSTGRESQL == properties.getDatabase();
} }

View File

@@ -410,7 +410,7 @@ public class JpaTargetManagement implements TargetManagement {
@Override @Override
public Optional<Target> getByControllerID(final String controllerId) { public Optional<Target> getByControllerID(final String controllerId) {
return targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)).map(Target.class::cast); return targetRepository.findByControllerId(controllerId).map(Target.class::cast);
} }
@Override @Override
@@ -892,8 +892,7 @@ public class JpaTargetManagement implements TargetManagement {
} }
private JpaTarget getByControllerIdAndThrowIfNotFound(final String controllerId) { private JpaTarget getByControllerIdAndThrowIfNotFound(final String controllerId) {
return targetRepository.findOne(TargetSpecifications.hasControllerId(controllerId)) return targetRepository.getByControllerId(controllerId);
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
} }
private JpaTargetType getTargetTypeByIdAndThrowIfNotFound(final long id) { private JpaTargetType getTargetTypeByIdAndThrowIfNotFound(final long id) {
@@ -960,7 +959,7 @@ public class JpaTargetManagement implements TargetManagement {
final JpaTargetTag tag = targetTagRepository.findById(targetTagId) final JpaTargetTag tag = targetTagRepository.findById(targetTagId)
.orElseThrow(() -> new EntityNotFoundException(TargetTag.class, targetTagId)); .orElseThrow(() -> new EntityNotFoundException(TargetTag.class, targetTagId));
final List<JpaTarget> targets = controllerIds.size() == 1 ? final List<JpaTarget> targets = controllerIds.size() == 1 ?
targetRepository.findOne(TargetSpecifications.hasControllerId(controllerIds.iterator().next())) targetRepository.findByControllerId(controllerIds.iterator().next())
.map(List::of) .map(List::of)
.orElseGet(Collections::emptyList) : .orElseGet(Collections::emptyList) :
targetRepository targetRepository

View File

@@ -24,11 +24,9 @@ import lombok.Setter;
import org.eclipse.hawkbit.repository.exception.TenantNotExistException; import org.eclipse.hawkbit.repository.exception.TenantNotExistException;
import org.eclipse.hawkbit.repository.jpa.model.helper.TenantAwareHolder; import org.eclipse.hawkbit.repository.jpa.model.helper.TenantAwareHolder;
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
import org.eclipse.hawkbit.repository.model.helper.SystemManagementHolder;
import org.eclipse.persistence.annotations.Multitenant; import org.eclipse.persistence.annotations.Multitenant;
import org.eclipse.persistence.annotations.MultitenantType; import org.eclipse.persistence.annotations.MultitenantType;
import org.eclipse.persistence.annotations.TenantDiscriminatorColumn; import org.eclipse.persistence.annotations.TenantDiscriminatorColumn;
import org.hibernate.annotations.TenantId;
/** /**
* Holder of the base attributes common to all tenant aware entities. * Holder of the base attributes common to all tenant aware entities.

View File

@@ -37,15 +37,13 @@ import org.springframework.transaction.annotation.Transactional;
@NoRepositoryBean @NoRepositoryBean
@Transactional(readOnly = true) @Transactional(readOnly = true)
public interface BaseEntityRepository<T extends AbstractJpaTenantAwareBaseEntity> public interface BaseEntityRepository<T extends AbstractJpaTenantAwareBaseEntity>
extends PagingAndSortingRepository<T, Long>, CrudRepository<T, Long>, JpaSpecificationExecutor<T>, extends PagingAndSortingRepository<T, Long>, CrudRepository<T, Long>, JpaSpecificationExecutor<T>, NoCountSliceRepository<T>,
NoCountSliceRepository<T>, ACMRepository<T> { ACMRepository<T> {
/** /**
* Overrides * Overrides {@link org.springframework.data.repository.CrudRepository#saveAll(Iterable)} to return a list of created entities instead
* {@link org.springframework.data.repository.CrudRepository#saveAll(Iterable)} * of an instance of {@link Iterable} to be able to work with it directly in further code processing instead of converting the
* to return a list of created entities instead of an instance of * {@link Iterable}.
* {@link Iterable} to be able to work with it directly in further code
* processing instead of converting the {@link Iterable}.
* *
* @param entities to persist in the database * @param entities to persist in the database
* @return the created entities * @return the created entities
@@ -55,11 +53,9 @@ public interface BaseEntityRepository<T extends AbstractJpaTenantAwareBaseEntity
<S extends T> List<S> saveAll(Iterable<S> entities); <S extends T> List<S> saveAll(Iterable<S> entities);
/** /**
* Overrides * Overrides {@link org.springframework.data.repository.CrudRepository#findAll()} to return a list of found entities instead of
* {@link org.springframework.data.repository.CrudRepository#findAll()} * an instance of {@link Iterable} to be able to work with it directly in further code processing instead of converting the
* to return a list of found entities instead of an instance of * {@link Iterable}.
* {@link Iterable} to be able to work with it directly in further code
* processing instead of converting the {@link Iterable}.
* *
* @return the found entities * @return the found entities
*/ */
@@ -67,22 +63,9 @@ public interface BaseEntityRepository<T extends AbstractJpaTenantAwareBaseEntity
List<T> findAll(); List<T> findAll();
/** /**
* Gets by id requiring entity to exists * Overrides {@link org.springframework.data.repository.CrudRepository#findAllById(Iterable)} to return a list of found entities instead
* * of an instance of {@link Iterable} to be able to work with it directly in further code processing instead of converting the
* @param id the entity id * {@link Iterable}.
* @return the existing entity.
* @throws EntityNotFoundException if the entity doesn't exist
*/
default T getById(final Long id) {
return findById(id).orElseThrow(() -> new EntityNotFoundException(getDomainClass(), id));
}
/**
* Overrides
* {@link org.springframework.data.repository.CrudRepository#findAllById(Iterable)}
* to return a list of found entities instead of an instance of
* {@link Iterable} to be able to work with it directly in further code
* processing instead of converting the {@link Iterable}.
* *
* @param ids to search in the database for * @param ids to search in the database for
* @return the found entities * @return the found entities
@@ -92,10 +75,8 @@ public interface BaseEntityRepository<T extends AbstractJpaTenantAwareBaseEntity
// TODO To be considered if this method is needed at all // TODO To be considered if this method is needed at all
/** /**
* Deletes all entities of a given tenant from this repository. For safety * Deletes all entities of a given tenant from this repository. For safety reasons (this is a "delete everything" query after all) we add
* reasons (this is a "delete everything" query after all) we add the tenant * the tenant manually to query even if this will be done by {@link EntityManager} anyhow. The DB should take care of optimizing this away.
* manually to query even if this will be done by {@link EntityManager}
* anyhow. The DB should take care of optimizing this away.
* <p/> * <p/>
* *
* @param tenant to delete data from * @param tenant to delete data from
@@ -103,11 +84,9 @@ public interface BaseEntityRepository<T extends AbstractJpaTenantAwareBaseEntity
void deleteByTenant(String tenant); void deleteByTenant(String tenant);
/** /**
* Returns a wrapper (or the same instance if access controller is <code>null</code> of this repository that * Returns a wrapper (or the same instance if access controller is <code>null</code> of this repository that supports ACM.
* supports ACM.
* <p/> * <p/>
* Note: To use ACM support the returned object shall be used! <code>this</code> object will not achieve ACM * Note: To use ACM support the returned object shall be used! <code>this</code> object will not achieve ACM support!
* support!
* <p/> * <p/>
* Notes on ACM support (if enabled, i.e. <code>accessController</code> is not <code>null</code>): * Notes on ACM support (if enabled, i.e. <code>accessController</code> is not <code>null</code>):
* <ul> * <ul>
@@ -123,7 +102,6 @@ public interface BaseEntityRepository<T extends AbstractJpaTenantAwareBaseEntity
* </ul> * </ul>
* *
* @param accessController access controller to be applied to the result * @param accessController access controller to be applied to the result
* @param entityType the entity type of the repository
* @return a repository that supports ACM. * @return a repository that supports ACM.
*/ */
default BaseEntityRepository<T> withACM(@Nullable final AccessController<T> accessController) { default BaseEntityRepository<T> withACM(@Nullable final AccessController<T> accessController) {

View File

@@ -322,7 +322,11 @@ public class BaseEntityRepositoryACM<T extends AbstractJpaTenantAwareBaseEntity>
.filter(value -> repository.getDomainClass().isAssignableFrom(value.getClass())) .filter(value -> repository.getDomainClass().isAssignableFrom(value.getClass()))
.isPresent()) { .isPresent()) {
return ((Optional<T>) result).filter( return ((Optional<T>) result).filter(
t -> isOperationAllowed(AccessController.Operation.READ, t, accessController)); t -> {
// if not accessible - throws exception (as for iterables or single entities)
accessController.assertOperationAllowed(AccessController.Operation.READ, t);
return true;
});
} else if (repository.getDomainClass().isAssignableFrom(method.getReturnType())) { } else if (repository.getDomainClass().isAssignableFrom(method.getReturnType())) {
accessController.assertOperationAllowed(AccessController.Operation.READ, (T) result); accessController.assertOperationAllowed(AccessController.Operation.READ, (T) result);
} }

View File

@@ -10,11 +10,14 @@
package org.eclipse.hawkbit.repository.jpa.repository; package org.eclipse.hawkbit.repository.jpa.repository;
import java.util.Collection; import java.util.Collection;
import java.util.Optional;
import jakarta.persistence.EntityManager; import jakarta.persistence.EntityManager;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet; import org.eclipse.hawkbit.repository.jpa.model.JpaDistributionSet;
import org.eclipse.hawkbit.repository.jpa.model.JpaTarget; import org.eclipse.hawkbit.repository.jpa.model.JpaTarget;
import org.eclipse.hawkbit.repository.jpa.specifications.TargetSpecifications;
import org.eclipse.hawkbit.repository.model.Target; import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetUpdateStatus; import org.eclipse.hawkbit.repository.model.TargetUpdateStatus;
import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity; import org.eclipse.hawkbit.repository.model.TenantAwareBaseEntity;
@@ -29,6 +32,15 @@ import org.springframework.transaction.annotation.Transactional;
@Transactional(readOnly = true) @Transactional(readOnly = true)
public interface TargetRepository extends BaseEntityRepository<JpaTarget> { public interface TargetRepository extends BaseEntityRepository<JpaTarget> {
default Optional<JpaTarget> findByControllerId(final String controllerId) {
return findOne(TargetSpecifications.hasControllerId(controllerId));
}
default JpaTarget getByControllerId(final String controllerId) {
return findOne(TargetSpecifications.hasControllerId(controllerId))
.orElseThrow(() -> new EntityNotFoundException(Target.class, controllerId));
}
// TODO AC - remove it and use specification // TODO AC - remove it and use specification
/** /**

View File

@@ -21,7 +21,6 @@ import io.qameta.allure.Feature;
import io.qameta.allure.Story; import io.qameta.allure.Story;
import org.eclipse.hawkbit.repository.FilterParams; import org.eclipse.hawkbit.repository.FilterParams;
import org.eclipse.hawkbit.repository.Identifiable; import org.eclipse.hawkbit.repository.Identifiable;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException; import org.eclipse.hawkbit.repository.exception.InsufficientPermissionException;
import org.eclipse.hawkbit.repository.jpa.acm.AccessController; import org.eclipse.hawkbit.repository.jpa.acm.AccessController;
import org.eclipse.hawkbit.repository.jpa.autoassign.AutoAssignChecker; import org.eclipse.hawkbit.repository.jpa.autoassign.AutoAssignChecker;
@@ -76,7 +75,9 @@ class TargetAccessControllerTest extends AbstractAccessControllerTest {
// verify targetManagement#getByControllerID // verify targetManagement#getByControllerID
assertThat(targetManagement.getByControllerID(permittedTarget.getControllerId())).isPresent(); assertThat(targetManagement.getByControllerID(permittedTarget.getControllerId())).isPresent();
assertThat(targetManagement.getByControllerID(hiddenTarget.getControllerId())).isEmpty(); assertThatThrownBy(() -> targetManagement.getByControllerID(hiddenTarget.getControllerId()))
.as("Missing read permissions for hidden target.")
.isInstanceOf(InsufficientPermissionException.class);
// verify targetManagement#getByControllerID // verify targetManagement#getByControllerID
assertThat(targetManagement assertThat(targetManagement
@@ -95,7 +96,7 @@ class TargetAccessControllerTest extends AbstractAccessControllerTest {
assertThat(targetManagement.getControllerAttributes(permittedTarget.getControllerId())).isEmpty(); assertThat(targetManagement.getControllerAttributes(permittedTarget.getControllerId())).isEmpty();
assertThatThrownBy(() -> { assertThatThrownBy(() -> {
assertThat(targetManagement.getControllerAttributes(hiddenTarget.getControllerId())).isEmpty(); assertThat(targetManagement.getControllerAttributes(hiddenTarget.getControllerId())).isEmpty();
}).as("Target should not be found.").isInstanceOf(EntityNotFoundException.class); }).as("Target should not be found.").isInstanceOf(InsufficientPermissionException.class);
final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement final TargetFilterQuery targetFilterQuery = targetFilterQueryManagement
.create(entityFactory.targetFilterQuery().create().name("test").query("id==*")); .create(entityFactory.targetFilterQuery().create().name("test").query("id==*"));
@@ -176,7 +177,7 @@ class TargetAccessControllerTest extends AbstractAccessControllerTest {
assertThatThrownBy(() -> { assertThatThrownBy(() -> {
targetManagement.assignTag(Collections.singletonList(readOnlyTarget.getControllerId()), myTag.getId()); targetManagement.assignTag(Collections.singletonList(readOnlyTarget.getControllerId()), myTag.getId());
}).as("Missing update permissions for target to toggle tag assignment.") }).as("Missing update permissions for target to toggle tag assignment.")
.isInstanceOfAny(InsufficientPermissionException.class, EntityNotFoundException.class); .isInstanceOfAny(InsufficientPermissionException.class);
// assignment is denied for readOnlyTarget (read, but no update permissions) // assignment is denied for readOnlyTarget (read, but no update permissions)
assertThatThrownBy(() -> { assertThatThrownBy(() -> {
@@ -190,19 +191,18 @@ class TargetAccessControllerTest extends AbstractAccessControllerTest {
.assignTag(Collections.singletonList(hiddenTarget.getControllerId()), myTag.getId()) .assignTag(Collections.singletonList(hiddenTarget.getControllerId()), myTag.getId())
.size(); .size();
}).as("Missing update permissions for target to toggle tag assignment.") }).as("Missing update permissions for target to toggle tag assignment.")
.isInstanceOf(EntityNotFoundException.class); .isInstanceOf(InsufficientPermissionException.class);
// assignment is denied for hiddenTarget since it's hidden // assignment is denied for hiddenTarget since it's hidden
assertThatThrownBy(() -> { assertThatThrownBy(() -> {
targetManagement.assignTag(Collections.singletonList(hiddenTarget.getControllerId()), myTag.getId()); targetManagement.assignTag(Collections.singletonList(hiddenTarget.getControllerId()), myTag.getId());
}).as("Missing update permissions for target to toggle tag assignment.") }).as("Missing update permissions for target to toggle tag assignment.")
.isInstanceOf(EntityNotFoundException.class); .isInstanceOf(InsufficientPermissionException.class);
// assignment is denied for hiddenTarget since it's hidden // assignment is denied for hiddenTarget since it's hidden
assertThatThrownBy(() -> { assertThatThrownBy(() -> targetManagement.unassignTag(hiddenTarget.getControllerId(), myTag.getId()))
targetManagement.unassignTag(hiddenTarget.getControllerId(), myTag.getId()); .as("Missing update permissions for target to toggle tag assignment.")
}).as("Missing update permissions for target to toggle tag assignment.") .isInstanceOf(InsufficientPermissionException.class);
.isInstanceOf(EntityNotFoundException.class);
} }
@Test @Test

View File

@@ -57,7 +57,6 @@ public class TestAccessControlManger {
"Access to " + ruleClass.getName() + "/" + entity + " not allowed by checker!"); "Access to " + ruleClass.getName() + "/" + entity + " not allowed by checker!");
} }
} }
return;
} }
} }

View File

@@ -68,8 +68,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verifies that management get access react as specfied on calls for non existing entities by means of Optional not present.") @Description("Verifies that management get access react as specfied on calls for non existing entities by means of Optional not present.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = SoftwareModuleCreatedEvent.class, count = 1) })
@Expect(type = SoftwareModuleCreatedEvent.class, count = 1) })
public void nonExistingEntityAccessReturnsNotPresent() { public void nonExistingEntityAccessReturnsNotPresent() {
final SoftwareModule module = testdataFactory.createSoftwareModuleOs(); final SoftwareModule module = testdataFactory.createSoftwareModuleOs();
@@ -85,8 +84,7 @@ public class ArtifactManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verifies that management queries react as specfied on calls for non existing entities " @Description("Verifies that management queries react as specfied on calls for non existing entities "
+ " by means of throwing EntityNotFoundException.") + " by means of throwing EntityNotFoundException.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = SoftwareModuleDeletedEvent.class, count = 0) })
@Expect(type = SoftwareModuleDeletedEvent.class, count = 0) })
public void entityQueriesReferringToNotExistingEntitiesThrowsException() throws URISyntaxException { public void entityQueriesReferringToNotExistingEntitiesThrowsException() throws URISyntaxException {
final String artifactData = "test"; final String artifactData = "test";

View File

@@ -146,8 +146,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verifies that management get access react as specified on calls for non existing entities by means " + @Description("Verifies that management get access react as specified on calls for non existing entities by means " +
"of Optional not present.") "of Optional not present.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
@Expect(type = TargetCreatedEvent.class, count = 0) })
void nonExistingEntityAccessReturnsNotPresent() { void nonExistingEntityAccessReturnsNotPresent() {
assertThat(deploymentManagement.findAction(1234L)).isNotPresent(); assertThat(deploymentManagement.findAction(1234L)).isNotPresent();
assertThat(deploymentManagement.findActionWithDetails(NOT_EXIST_IDL)).isNotPresent(); assertThat(deploymentManagement.findActionWithDetails(NOT_EXIST_IDL)).isNotPresent();
@@ -156,8 +155,7 @@ class DeploymentManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verifies that management queries react as specified on calls for non existing entities " + @Description("Verifies that management queries react as specified on calls for non existing entities " +
" by means of throwing EntityNotFoundException.") " by means of throwing EntityNotFoundException.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1) })
@Expect(type = TargetCreatedEvent.class, count = 1) })
void entityQueriesReferringToNotExistingEntitiesThrowsException() { void entityQueriesReferringToNotExistingEntitiesThrowsException() {
final Target target = testdataFactory.createTarget(); final Target target = testdataFactory.createTarget();
final String dsName = "DistributionSet"; final String dsName = "DistributionSet";

View File

@@ -54,8 +54,7 @@ class DistributionSetTagManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verifies that management get access reacts as specified on calls for non existing entities by means of Optional not present.") @Description("Verifies that management get access reacts as specified on calls for non existing entities by means of Optional not present.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
@Expect(type = TargetCreatedEvent.class, count = 0) })
void nonExistingEntityAccessReturnsNotPresent() { void nonExistingEntityAccessReturnsNotPresent() {
assertThat(distributionSetTagManagement.getByName(NOT_EXIST_ID)).isNotPresent(); assertThat(distributionSetTagManagement.getByName(NOT_EXIST_ID)).isNotPresent();
assertThat(distributionSetTagManagement.get(NOT_EXIST_IDL)).isNotPresent(); assertThat(distributionSetTagManagement.get(NOT_EXIST_IDL)).isNotPresent();

View File

@@ -55,8 +55,7 @@ public class DistributionSetTypeManagementTest extends AbstractJpaIntegrationTes
@Test @Test
@Description("Verifies that management get access react as specfied on calls for non existing entities by means " @Description("Verifies that management get access react as specfied on calls for non existing entities by means "
+ "of Optional not present.") + "of Optional not present.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = DistributionSetCreatedEvent.class, count = 0) })
@Expect(type = DistributionSetCreatedEvent.class, count = 0) })
public void nonExistingEntityAccessReturnsNotPresent() { public void nonExistingEntityAccessReturnsNotPresent() {
assertThat(distributionSetTypeManagement.get(NOT_EXIST_IDL)).isNotPresent(); assertThat(distributionSetTypeManagement.get(NOT_EXIST_IDL)).isNotPresent();
assertThat(distributionSetTypeManagement.getByKey(NOT_EXIST_ID)).isNotPresent(); assertThat(distributionSetTypeManagement.getByKey(NOT_EXIST_ID)).isNotPresent();

View File

@@ -49,8 +49,7 @@ class RolloutGroupManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verifies that management get access reacts as specified on calls for non existing entities by means " + @Description("Verifies that management get access reacts as specified on calls for non existing entities by means " +
"of Optional not present.") "of Optional not present.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
@Expect(type = TargetCreatedEvent.class, count = 0) })
void nonExistingEntityAccessReturnsNotPresent() { void nonExistingEntityAccessReturnsNotPresent() {
assertThat(rolloutGroupManagement.get(NOT_EXIST_IDL)).isNotPresent(); assertThat(rolloutGroupManagement.get(NOT_EXIST_IDL)).isNotPresent();
assertThat(rolloutGroupManagement.getWithDetailedStatus(NOT_EXIST_IDL)).isNotPresent(); assertThat(rolloutGroupManagement.getWithDetailedStatus(NOT_EXIST_IDL)).isNotPresent();

View File

@@ -283,8 +283,7 @@ class RolloutManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verifies that management get access reacts as specified on calls for non existing entities by means " @Description("Verifies that management get access reacts as specified on calls for non existing entities by means "
+ "of Optional not present.") + "of Optional not present.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
@Expect(type = TargetCreatedEvent.class) })
void nonExistingEntityAccessReturnsNotPresent() { void nonExistingEntityAccessReturnsNotPresent() {
assertThat(rolloutManagement.get(NOT_EXIST_IDL)).isNotPresent(); assertThat(rolloutManagement.get(NOT_EXIST_IDL)).isNotPresent();
assertThat(rolloutManagement.getByName(NOT_EXIST_ID)).isNotPresent(); assertThat(rolloutManagement.getByName(NOT_EXIST_ID)).isNotPresent();

View File

@@ -62,8 +62,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verifies that management get access reacts as specified on calls for non existing entities by means " @Description("Verifies that management get access reacts as specified on calls for non existing entities by means "
+ "of Optional not present.") + "of Optional not present.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = SoftwareModuleCreatedEvent.class, count = 1) })
@Expect(type = SoftwareModuleCreatedEvent.class, count = 1) })
public void nonExistingEntityAccessReturnsNotPresent() { public void nonExistingEntityAccessReturnsNotPresent() {
final SoftwareModule module = testdataFactory.createSoftwareModuleApp(); final SoftwareModule module = testdataFactory.createSoftwareModuleApp();
@@ -78,8 +77,7 @@ public class SoftwareModuleManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verifies that management queries react as specfied on calls for non existing entities " @Description("Verifies that management queries react as specfied on calls for non existing entities "
+ " by means of throwing EntityNotFoundException.") + " by means of throwing EntityNotFoundException.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = SoftwareModuleCreatedEvent.class, count = 1) })
@Expect(type = SoftwareModuleCreatedEvent.class, count = 1) })
public void entityQueriesReferringToNotExistingEntitiesThrowsException() { public void entityQueriesReferringToNotExistingEntitiesThrowsException() {
final SoftwareModule module = testdataFactory.createSoftwareModuleApp(); final SoftwareModule module = testdataFactory.createSoftwareModuleApp();

View File

@@ -37,8 +37,7 @@ public class SoftwareModuleTypeManagementTest extends AbstractJpaIntegrationTest
@Test @Test
@Description("Verifies that management get access reacts as specfied on calls for non existing entities by means " @Description("Verifies that management get access reacts as specfied on calls for non existing entities by means "
+ "of Optional not present.") + "of Optional not present.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = SoftwareModuleCreatedEvent.class, count = 0) })
@Expect(type = SoftwareModuleCreatedEvent.class, count = 0) })
public void nonExistingEntityAccessReturnsNotPresent() { public void nonExistingEntityAccessReturnsNotPresent() {
assertThat(softwareModuleTypeManagement.get(NOT_EXIST_IDL)).isNotPresent(); assertThat(softwareModuleTypeManagement.get(NOT_EXIST_IDL)).isNotPresent();
@@ -49,8 +48,7 @@ public class SoftwareModuleTypeManagementTest extends AbstractJpaIntegrationTest
@Test @Test
@Description("Verifies that management queries react as specfied on calls for non existing entities " @Description("Verifies that management queries react as specfied on calls for non existing entities "
+ " by means of throwing EntityNotFoundException.") + " by means of throwing EntityNotFoundException.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = SoftwareModuleCreatedEvent.class, count = 0) })
@Expect(type = SoftwareModuleCreatedEvent.class, count = 0) })
public void entityQueriesReferringToNotExistingEntitiesThrowsException() { public void entityQueriesReferringToNotExistingEntitiesThrowsException() {
verifyThrownExceptionBy(() -> softwareModuleTypeManagement.delete(NOT_EXIST_IDL), "SoftwareModuleType"); verifyThrownExceptionBy(() -> softwareModuleTypeManagement.delete(NOT_EXIST_IDL), "SoftwareModuleType");

View File

@@ -66,8 +66,7 @@ public class TargetFilterQueryManagementTest extends AbstractJpaIntegrationTest
@Test @Test
@Description("Verifies that management get access reacts as specfied on calls for non existing entities by means " @Description("Verifies that management get access reacts as specfied on calls for non existing entities by means "
+ "of Optional not present.") + "of Optional not present.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 0) })
@Expect(type = TargetCreatedEvent.class, count = 0) })
public void nonExistingEntityAccessReturnsNotPresent() { public void nonExistingEntityAccessReturnsNotPresent() {
assertThat(targetFilterQueryManagement.get(NOT_EXIST_IDL)).isNotPresent(); assertThat(targetFilterQueryManagement.get(NOT_EXIST_IDL)).isNotPresent();
assertThat(targetFilterQueryManagement.getByName(NOT_EXIST_ID)).isNotPresent(); assertThat(targetFilterQueryManagement.getByName(NOT_EXIST_ID)).isNotPresent();

View File

@@ -96,8 +96,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verifies that management get access react as specified on calls for non existing entities by means " @Description("Verifies that management get access react as specified on calls for non existing entities by means "
+ "of Optional not present.") + "of Optional not present.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1) })
@Expect(type = TargetCreatedEvent.class, count = 1) })
void nonExistingEntityAccessReturnsNotPresent() { void nonExistingEntityAccessReturnsNotPresent() {
final Target target = testdataFactory.createTarget(); final Target target = testdataFactory.createTarget();
assertThat(targetManagement.getByControllerID(NOT_EXIST_ID)).isNotPresent(); assertThat(targetManagement.getByControllerID(NOT_EXIST_ID)).isNotPresent();
@@ -184,8 +183,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Ensures that retrieving the target security is only permitted with the necessary permissions.") @Description("Ensures that retrieving the target security is only permitted with the necessary permissions.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1) })
@Expect(type = TargetCreatedEvent.class, count = 1) })
void getTargetSecurityTokenOnlyWithCorrectPermission() throws Exception { void getTargetSecurityTokenOnlyWithCorrectPermission() throws Exception {
final Target createdTarget = targetManagement final Target createdTarget = targetManagement
.create(entityFactory.target().create().controllerId("targetWithSecurityToken").securityToken("token")); .create(entityFactory.target().create().controllerId("targetWithSecurityToken").securityToken("token"));
@@ -221,8 +219,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verify that a target with same controller ID than another device cannot be created.") @Description("Verify that a target with same controller ID than another device cannot be created.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1) })
@Expect(type = TargetCreatedEvent.class, count = 1) })
void createTargetThatViolatesUniqueConstraintFails() { void createTargetThatViolatesUniqueConstraintFails() {
targetManagement.create(entityFactory.target().create().controllerId("123")); targetManagement.create(entityFactory.target().create().controllerId("123"));
@@ -388,8 +385,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Checks if the EntityAlreadyExistsException is thrown if the targets with the same controller ID are created twice.") @Description("Checks if the EntityAlreadyExistsException is thrown if the targets with the same controller ID are created twice.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 5) })
@Expect(type = TargetCreatedEvent.class, count = 5) })
void createMultipleTargetsDuplicate() { void createMultipleTargetsDuplicate() {
testdataFactory.createTargets(5, "mySimpleTargs", "my simple targets"); testdataFactory.createTargets(5, "mySimpleTargs", "my simple targets");
try { try {
@@ -402,8 +398,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Checks if the EntityAlreadyExistsException is thrown if a single target with the same controller ID are created twice.") @Description("Checks if the EntityAlreadyExistsException is thrown if a single target with the same controller ID are created twice.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 1) })
@Expect(type = TargetCreatedEvent.class, count = 1) })
void createTargetDuplicate() { void createTargetDuplicate() {
targetManagement.create(entityFactory.target().create().controllerId("4711")); targetManagement.create(entityFactory.target().create().controllerId("4711"));
try { try {
@@ -743,8 +738,7 @@ class TargetManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verify that the find all targets by ids method contains the entities that we are looking for") @Description("Verify that the find all targets by ids method contains the entities that we are looking for")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class, count = 12) })
@Expect(type = TargetCreatedEvent.class, count = 12) })
void verifyFindTargetAllById() { void verifyFindTargetAllById() {
final List<Long> searchIds = Arrays.asList(testdataFactory.createTarget("target-4").getId(), final List<Long> searchIds = Arrays.asList(testdataFactory.createTarget("target-4").getId(),
testdataFactory.createTarget("target-5").getId(), testdataFactory.createTarget("target-6").getId()); testdataFactory.createTarget("target-5").getId(), testdataFactory.createTarget("target-6").getId());

View File

@@ -90,8 +90,7 @@ class TargetTagManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verifies that management get access reacts as specfied on calls for non existing entities by means " + @Description("Verifies that management get access reacts as specfied on calls for non existing entities by means " +
"of Optional not present.") "of Optional not present.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetCreatedEvent.class) })
@Expect(type = TargetCreatedEvent.class) })
void nonExistingEntityAccessReturnsNotPresent() { void nonExistingEntityAccessReturnsNotPresent() {
assertThat(targetTagManagement.getByName(NOT_EXIST_ID)).isNotPresent(); assertThat(targetTagManagement.getByName(NOT_EXIST_ID)).isNotPresent();
assertThat(targetTagManagement.get(NOT_EXIST_IDL)).isNotPresent(); assertThat(targetTagManagement.get(NOT_EXIST_IDL)).isNotPresent();

View File

@@ -43,8 +43,7 @@ class TargetTypeManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verifies that management get access react as specified on calls for non existing entities by means " @Description("Verifies that management get access react as specified on calls for non existing entities by means "
+ "of Optional not present.") + "of Optional not present.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetTypeCreatedEvent.class) })
@Expect(type = TargetTypeCreatedEvent.class) })
void nonExistingEntityAccessReturnsNotPresent() { void nonExistingEntityAccessReturnsNotPresent() {
assertThat(targetTypeManagement.get(NOT_EXIST_IDL)).isNotPresent(); assertThat(targetTypeManagement.get(NOT_EXIST_IDL)).isNotPresent();
assertThat(targetTypeManagement.getByName(NOT_EXIST_ID)).isNotPresent(); assertThat(targetTypeManagement.getByName(NOT_EXIST_ID)).isNotPresent();
@@ -53,8 +52,7 @@ class TargetTypeManagementTest extends AbstractJpaIntegrationTest {
@Test @Test
@Description("Verifies that management queries react as specified on calls for non existing entities " @Description("Verifies that management queries react as specified on calls for non existing entities "
+ " by means of throwing EntityNotFoundException.") + " by means of throwing EntityNotFoundException.")
@ExpectEvents({ @ExpectEvents({ @Expect(type = TargetTypeUpdatedEvent.class) })
@Expect(type = TargetTypeUpdatedEvent.class) })
void entityQueriesReferringToNotExistingEntitiesThrowsException() { void entityQueriesReferringToNotExistingEntitiesThrowsException() {
verifyThrownExceptionBy(() -> targetTypeManagement.delete(NOT_EXIST_IDL), "TargetType"); verifyThrownExceptionBy(() -> targetTypeManagement.delete(NOT_EXIST_IDL), "TargetType");
verifyThrownExceptionBy(() -> targetTypeManagement.update(entityFactory.targetType().update(NOT_EXIST_IDL)), verifyThrownExceptionBy(() -> targetTypeManagement.update(entityFactory.targetType().update(NOT_EXIST_IDL)),

View File

@@ -27,11 +27,13 @@ import org.eclipse.hawkbit.event.BusProtoStuffMessageConverter;
import org.eclipse.hawkbit.im.authentication.SpRole; import org.eclipse.hawkbit.im.authentication.SpRole;
import org.eclipse.hawkbit.repository.RolloutApprovalStrategy; import org.eclipse.hawkbit.repository.RolloutApprovalStrategy;
import org.eclipse.hawkbit.repository.RolloutStatusCache; import org.eclipse.hawkbit.repository.RolloutStatusCache;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.event.ApplicationEventFilter; import org.eclipse.hawkbit.repository.event.ApplicationEventFilter;
import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder; import org.eclipse.hawkbit.repository.model.helper.EventPublisherHolder;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyReplacer;
import org.eclipse.hawkbit.repository.rsql.VirtualPropertyResolver; import org.eclipse.hawkbit.repository.rsql.VirtualPropertyResolver;
import org.eclipse.hawkbit.repository.test.util.RolloutTestApprovalStrategy; import org.eclipse.hawkbit.repository.test.util.RolloutTestApprovalStrategy;
import org.eclipse.hawkbit.repository.test.util.SystemManagementHolder;
import org.eclipse.hawkbit.repository.test.util.TestdataFactory; import org.eclipse.hawkbit.repository.test.util.TestdataFactory;
import org.eclipse.hawkbit.security.DdiSecurityProperties; import org.eclipse.hawkbit.security.DdiSecurityProperties;
import org.eclipse.hawkbit.security.HawkbitSecurityProperties; import org.eclipse.hawkbit.security.HawkbitSecurityProperties;
@@ -131,6 +133,16 @@ public class TestConfiguration implements AsyncConfigurer {
return new ArtifactFilesystemRepository(artifactFilesystemProperties); return new ArtifactFilesystemRepository(artifactFilesystemProperties);
} }
/**
* @return the {@link org.eclipse.hawkbit.repository.test.util.SystemManagementHolder} singleton bean which holds the
* current {@link SystemManagement} service and make it accessible in
* beans which cannot access the service directly, e.g. JPA entities.
*/
@Bean
SystemManagementHolder systemManagementHolder() {
return SystemManagementHolder.getInstance();
}
@Bean @Bean
TestdataFactory testdataFactory() { TestdataFactory testdataFactory() {
return new TestdataFactory(); return new TestdataFactory();

View File

@@ -18,7 +18,6 @@ import java.util.Objects;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import org.eclipse.hawkbit.im.authentication.SpPermission; import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.repository.model.helper.SystemManagementHolder;
import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails; import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails;
import org.eclipse.hawkbit.tenancy.TenantAwareUser; import org.eclipse.hawkbit.tenancy.TenantAwareUser;
import org.springframework.security.authentication.TestingAuthenticationToken; import org.springframework.security.authentication.TestingAuthenticationToken;
@@ -29,6 +28,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
public class SecurityContextSwitch { public class SecurityContextSwitch {
public static final String DEFAULT_TENANT = "DEFAULT"; public static final String DEFAULT_TENANT = "DEFAULT";
private static final WithUser PRIVILEDGED_USER = private static final WithUser PRIVILEDGED_USER =
createWithUser("bumlux", DEFAULT_TENANT, false, true, false, "ROLE_CONTROLLER", "ROLE_SYSTEM_CODE"); createWithUser("bumlux", DEFAULT_TENANT, false, true, false, "ROLE_CONTROLLER", "ROLE_SYSTEM_CODE");

View File

@@ -7,7 +7,7 @@
* *
* SPDX-License-Identifier: EPL-2.0 * SPDX-License-Identifier: EPL-2.0
*/ */
package org.eclipse.hawkbit.repository.model.helper; package org.eclipse.hawkbit.repository.test.util;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;