Fine grained repository permissions (#2562)

1. Introduce @PrreAuthorize check based on hasPermission - allowing custom processing (compared with non-modifiable hasAuthority/Role processing)
2. Dedicated permissions could be implemented on management api level. Check is made by plugged in PermissionEvaluator
3. Thus common XXX_REPOSITORY permissions could differ for extending services
4. Change create/update entity builder pattern - not via EntityFactory but via clean static lombok based builders (with fine fluent api).
5. Implement abstract repository management jpa class that handles the boilerplate code from extending classes in single place consistently -> AbsreactJpaRepositoryManagement
6. Register management api-s as **Sevice**-s instead of **Bean**-s in order to make easier maintainable and get away from heavy argument forwading
7. Simplify custom hawkbit repository registration + adding proxy to handle exception mapping at lower level - thus not depending on Aspects for converting exceptions
8. Implemented general purpose 'copy' utility (ObjectCopyUtil) that using getter/setter patterns is able to copy (e.g. Create/Update) objects to other objects (e.g. JPA entity objects)
This commit is contained in:
Avgustin Marinov
2025-07-28 14:57:33 +03:00
committed by GitHub
parent 8cdbe54cbe
commit 2b66449ff1
214 changed files with 3456 additions and 4416 deletions

View File

@@ -11,10 +11,15 @@ package org.eclipse.hawkbit.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* {@link GenericSpServerException} is thrown when a given entity in's actual and cannot be stored within the current session. Reason could be
* that it has been changed within another session.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class GenericSpServerException extends AbstractServerRtException {
@Serial

View File

@@ -0,0 +1,251 @@
/**
* 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.utils;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.UnaryOperator;
import jakarta.validation.constraints.NotNull;
import lombok.NoArgsConstructor;
@NoArgsConstructor(access = lombok.AccessLevel.PRIVATE)
public class ObjectCopyUtil {
private static final Map<FromTo, CopyFunction> FROM_TO_SETTER = new HashMap<>();
// java:S4276 - it is intended to be generic - not specialized
@SuppressWarnings("java:S4276")
public static boolean copy(final Object from, final Object to, boolean setNullValues, final UnaryOperator<Object> propertyProcessor) {
final FromTo fromTo = new FromTo(from.getClass(), to.getClass());
CopyFunction fromToFunction;
synchronized (FROM_TO_SETTER) {
fromToFunction = FROM_TO_SETTER.get(fromTo);
if (fromToFunction == null) {
fromToFunction = fromToFunction(from.getClass(), to.getClass());
FROM_TO_SETTER.put(fromTo, fromToFunction);
}
}
return fromToFunction.apply(from, to, setNullValues, propertyProcessor);
}
// java:S4276 - it is intended to be generic - not specialized
// java:S3776 - complexity is due to reflection and dynamic method invocation
// java:S1141 - better readable that way
// java:S3011 - low-level, reflection utility. intentionally changes the accessibility
@SuppressWarnings({ "java:S4276", "java:S3776", "java:S1141", "java:S3011" })
private static CopyFunction fromToFunction(final Class<?> fromClass, final Class<?> toClass) {
final List<CopyFunction> propertySetters = new ArrayList<>();
for (final Method fromMethod : getMethods(fromClass)) {
if (fromMethod.getParameterCount() == 0 && fromMethod.getReturnType() != void.class) {
final String methodName = fromMethod.getName();
if (methodName.equals("getClass")) {
continue; // skip
}
final boolean isGet = isGet(methodName);
if (isGet || isIs(fromMethod, methodName)) {
final String fieldName = Character.toLowerCase(methodName.charAt(isGet ? 3 : 2)) + methodName.substring(isGet ? 4 : 3);
fromMethod.setAccessible(true); // if needed
final UnaryOperator<Object> toGetter = toGetter(toClass, fromMethod.getName(), fieldName);
final String setterName = "set" + methodName.substring(isGet ? 3 : 2);
final BiConsumer<Object, Object> toSetter = toSetter(toClass, setterName, fieldName, fromMethod.getReturnType());
if (toSetter == null && toGetter == null) {
// we allow toSetter to be null, but in that case the toGetter must not be null and the
// from value shall always match the to value (without setting it)
throw new IllegalStateException("Setter counterpart for " + fromMethod + " is not found in " + toClass.getName());
}
propertySetters.add((from, to, setNullValues, propertyProcessor) -> {
final Object value;
try {
value = fromMethod.invoke(from);
} catch (final IllegalAccessException e) {
throw new IllegalStateException("Failed to get source value", e);
} catch (final InvocationTargetException e) {
throw new IllegalStateException(
"Failed to get source value",
e.getTargetException() == null ? e : e.getTargetException());
}
if (value == null && !setNullValues) { // if !setNullValues null means no change
return false;
}
if (toGetter != null) {
final Object currentValue = toGetter.apply(to);
if (Objects.equals(value, currentValue)) {
return false; // no change
}
}
if (toSetter == null) {
throw new IllegalStateException(
"Setter counterpart for " + fromMethod + " is not found in " + toClass.getName() +
" and the 'from' value is not equal to the 'to' value");
}
toSetter.accept(to, propertyProcessor.apply(value));
return true;
});
}
}
}
return (from, to, setNullValues, entityManager) -> {
boolean updated = false;
for (final CopyFunction fieldSetter : propertySetters) {
updated = fieldSetter.apply(from, to, setNullValues, entityManager) || updated;
}
return updated;
};
}
// java:S3011 - low-level, reflection utility. intentionally changes the accessibility
@SuppressWarnings("java:S3011")
private static BiConsumer<Object, Object> toSetter(
final Class<?> toClass, final String setterName, final String fieldName, final Class<?> type) {
try {
final Method toSetterMethod = getMethod(toClass, setterName, type);
return (to, value) -> {
try {
toSetterMethod.invoke(to, value);
} catch (final InvocationTargetException e) {
throw new IllegalStateException(
"Error invoking " + toSetterMethod,
e.getTargetException() == null ? e : e.getTargetException());
} catch (final IllegalAccessException | IllegalArgumentException e) {
throw new IllegalStateException("Error invoking " + toSetterMethod, e);
}
};
} catch (final NoSuchMethodException nsme) {
final Field field = getField(toClass, fieldName);
if (field == null) {
return null;
} else {
return (to, value) -> {
try {
field.set(to, value);
} catch (final IllegalAccessException | IllegalArgumentException e) {
throw new IllegalStateException("Error setting field " + field, e);
}
};
}
}
}
private static UnaryOperator<Object> toGetter(final Class<?> toClass, final String getterName, final String fieldName) {
try {
final Method toGetterMethod = getMethod(toClass, getterName);
return to -> {
try {
return toGetterMethod.invoke(to);
} catch (final Exception e) {
throw new IllegalStateException("Error invoking " + toGetterMethod, e);
}
};
} catch (final NoSuchMethodException e) {
// no method to get current value of the target field, try with field access
final Field field = getField(toClass, fieldName); // is or get
return field == null ? null : to -> {
try {
return field.get(to);
} catch (final Exception e2) {
throw new IllegalStateException("Error getting field " + field, e2);
}
};
}
}
private static boolean isIs(final Method fromMethod, final String methodName) {
return methodName.startsWith("is") && methodName.length() > 2 && Character.isUpperCase(methodName.charAt(2)) &&
fromMethod.getReturnType() == boolean.class;
}
private static boolean isGet(final String methodName) {
return methodName.startsWith("get") && methodName.length() > 3 && Character.isUpperCase(methodName.charAt(3));
}
@SuppressWarnings("java:S3011") // low-level, reflection utility. intentionally changes the accessibility
private static Field getField(final Class<?> clazz, final String fieldName) {
for (final Field field : clazz.getDeclaredFields()) {
if (fieldName.equals(field.getName())) {
field.setAccessible(true);
return field;
}
}
final Class<?> superClass = clazz.getSuperclass();
if (superClass == null) {
return null;
} else {
return getField(superClass, fieldName);
}
}
@NotNull
private static Method getMethod(final Class<?> clazz, final String methodName, final Class<?>... parameterTypes)
throws NoSuchMethodException {
try {
return getMethod(clazz, clazz, methodName, parameterTypes);
} catch (final NoSuchMethodException e) {
if (parameterTypes.length == 1 && parameterTypes[0] == Boolean.class) {
try {
return getMethod(clazz, methodName, boolean.class);
} catch (final NoSuchMethodException e2) {
throw e;
}
}
throw e;
}
}
@SuppressWarnings("java:S3011") // low-level, reflection utility. intentionally changes the accessibility
private static Method getMethod(final Class<?> target, final Class<?> clazz, final String methodName, final Class<?>... parameterTypes)
throws NoSuchMethodException {
try {
final Method method = clazz.getDeclaredMethod(methodName, parameterTypes);
method.setAccessible(true);
return method;
} catch (final NoSuchMethodException e) {
final Class<?> superClass = clazz.getSuperclass();
if (superClass == null) {
throw new NoSuchMethodException("Method " + methodName + " not found in " + target.getSimpleName());
} else {
return getMethod(target, superClass, methodName, parameterTypes);
}
}
}
private static List<Method> getMethods(final Class<?> clazz) {
final List<Method> methods = new ArrayList<>();
for (final Method method : clazz.getDeclaredMethods()) {
if (!method.isSynthetic() && !method.isBridge()) {
methods.add(method);
}
}
final Class<?> superClass = clazz.getSuperclass();
if (superClass != null) {
methods.addAll(getMethods(superClass));
}
return methods;
}
// key for copy of class to class function
private record FromTo(Class<?> from, Class<?> to) {}
// functional interface to apply the copy operation
private interface CopyFunction {
boolean apply(Object from, Object to, boolean setNullValues, UnaryOperator<Object> propertyProcessor);
}
}

View File

@@ -353,13 +353,13 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
.andExpect(jsonPath(prefix + ".download", equalTo(downloadType)))
.andExpect(jsonPath(prefix + ".update", equalTo(updateType)))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='jvm')].name",
contains(ds.findFirstModuleByType(runtimeType).get().getName())))
contains(findFirstModuleByType(ds, runtimeType).orElseThrow().getName())))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='jvm')].version",
contains(ds.findFirstModuleByType(runtimeType).get().getVersion())))
contains(findFirstModuleByType(ds, runtimeType).orElseThrow().getVersion())))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].name",
contains(ds.findFirstModuleByType(osType).get().getName())))
contains(findFirstModuleByType(ds, osType).orElseThrow().getName())))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].version",
contains(ds.findFirstModuleByType(osType).get().getVersion())))
contains(findFirstModuleByType(ds, osType).orElseThrow().getVersion())))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0].size", contains(ARTIFACT_SIZE)))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='os')].artifacts[0].filename",
contains(artifact.getFilename())))
@@ -391,9 +391,9 @@ public abstract class AbstractDDiApiIntegrationTest extends AbstractRestIntegrat
contains(HTTP_LOCALHOST + tenantAware.getCurrentTenant() + "/controller/v1/" + controllerId +
"/softwaremodules/" + osModuleId + "/artifacts/" + artifactSignature.getFilename() + "/download.MD5SUM")))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].version",
contains(ds.findFirstModuleByType(appType).get().getVersion())))
contains(findFirstModuleByType(ds, appType).orElseThrow().getVersion())))
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].metadata").doesNotExist())
.andExpect(jsonPath(prefix + ".chunks[?(@.part=='bApp')].name")
.value(ds.findFirstModuleByType(appType).get().getName()));
.value(findFirstModuleByType(ds, appType).orElseThrow().getName()));
}
}

View File

@@ -83,7 +83,7 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
final int artifactSize = 5 * 1024;
final byte[] random = nextBytes(artifactSize);
final Artifact artifact = artifactManagement.create(new ArtifactUpload(
new ByteArrayInputStream(random), ds.findFirstModuleByType(osType).get().getId(), "file1", false, artifactSize));
new ByteArrayInputStream(random), findFirstModuleByType(ds, osType).orElseThrow().getId(), "file1", false, artifactSize));
assignDistributionSet(ds, targets);
@@ -178,7 +178,7 @@ class DdiArtifactDownloadTest extends AbstractDDiApiIntegrationTest {
final int artifactSize = (int) quotaManagement.getMaxArtifactSize();
final byte[] random = nextBytes(artifactSize);
final Artifact artifact = artifactManagement.create(new ArtifactUpload(new ByteArrayInputStream(random),
ds.findFirstModuleByType(osType).get().getId(), "file1", false, artifactSize));
findFirstModuleByType(ds, osType).orElseThrow().getId(), "file1", false, artifactSize));
// download fails as artifact is not yet assigned
mvc.perform(get("/controller/v1/{controllerId}/softwaremodules/{softwareModuleId}/artifacts/{filename}",

View File

@@ -123,11 +123,11 @@ class DdiCancelActionTest extends AbstractDDiApiIntegrationTest {
.andExpect(jsonPath("$.deployment.download", equalTo("forced")))
.andExpect(jsonPath("$.deployment.update", equalTo("forced")))
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='jvm')].version",
contains(ds.findFirstModuleByType(runtimeType).get().getVersion())))
contains(findFirstModuleByType(ds, runtimeType).orElseThrow().getVersion())))
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='os')].version",
contains(ds.findFirstModuleByType(osType).get().getVersion())))
contains(findFirstModuleByType(ds, osType).orElseThrow().getVersion())))
.andExpect(jsonPath("$.deployment.chunks[?(@.part=='bApp')].version",
contains(ds.findFirstModuleByType(appType).get().getVersion())));
contains(findFirstModuleByType(ds, appType).orElseThrow().getVersion())));
// and finish it
mvc.perform(post("/{tenant}/controller/v1/" + TestdataFactory.DEFAULT_CONTROLLER_ID + "/deploymentBase/"

View File

@@ -10,7 +10,7 @@
package org.eclipse.hawkbit.ddi.rest.resource;
import static org.assertj.core.api.Assertions.assertThat;
import static org.eclipse.hawkbit.repository.jpa.management.JpaConfirmationManagement.CONFIRMATION_CODE_MSG_PREFIX;
import static org.eclipse.hawkbit.repository.ConfirmationManagement.CONFIRMATION_CODE_MSG_PREFIX;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.hasItem;
@@ -124,7 +124,7 @@ class DdiConfirmationBaseTest extends AbstractDDiApiIntegrationTest {
getAndVerifyConfirmationBasePayload(
DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact,
artifactSignature, action.getId(),
findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", "forced");
findFirstModuleByType(findDistributionSetByAction, osType).orElseThrow().getId(), "forced", "forced");
// Retrieved is reported
final Iterable<ActionStatus> actionStatus = deploymentManagement

View File

@@ -189,7 +189,7 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final DistributionSet findDistributionSetByAction = distributionSetManagement.findByAction(action.getId()).get();
getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact,
artifactSignature, action.getId(),
findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", "forced");
findFirstModuleByType(findDistributionSetByAction, osType).orElseThrow().getId(), "forced", "forced");
// Retrieved is reported
final Iterable<ActionStatus> actionStatusMessages = deploymentManagement
@@ -348,10 +348,10 @@ class DdiDeploymentBaseTest extends AbstractDDiApiIntegrationTest {
final DistributionSet findDistributionSetByAction = distributionSetManagement.findByAction(action.getId()).get();
getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact,
artifactSignature, action.getId(),
findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced", "forced");
findFirstModuleByType(findDistributionSetByAction, osType).orElseThrow().getId(), "forced", "forced");
getAndVerifyDeploymentBasePayload(DEFAULT_CONTROLLER_ID, MediaTypes.HAL_JSON, ds, artifact, artifactSignature,
action.getId(), findDistributionSetByAction.findFirstModuleByType(osType).get().getId(), "forced",
action.getId(), findFirstModuleByType(findDistributionSetByAction, osType).orElseThrow().getId(), "forced",
"forced");
// Retrieved is reported

View File

@@ -160,14 +160,14 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
startsWith(deploymentBaseLink(CONTROLLER_ID, actionId1.toString()))));
getAndVerifyDeploymentBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1,
actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT);
actionId1, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT);
postDeploymentFeedback(target.getControllerId(), actionId1,
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Closed")),
status().isOk());
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1,
actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT);
actionId1, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT);
// Run test with 2nd action
final Long actionId2 = getFirstAssignedActionId(
@@ -180,14 +180,14 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
startsWith(deploymentBaseLink(CONTROLLER_ID, actionId2.toString()))));
getAndVerifyDeploymentBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds2, artifact2, artifactSignature2,
actionId2, ds2.findFirstModuleByType(osType).get().getId(), Action.ActionType.FORCED);
actionId2, findFirstModuleByType(ds2, osType).orElseThrow().getId(), Action.ActionType.FORCED);
postDeploymentFeedback(target.getControllerId(), actionId2,
getJsonActionFeedback(DdiStatus.ExecutionStatus.CLOSED, DdiResult.FinalResult.SUCCESS, Collections.singletonList("Closed")),
status().isOk());
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds2, artifact2, artifactSignature2,
actionId2, ds2.findFirstModuleByType(osType).get().getId(), Action.ActionType.FORCED);
actionId2, findFirstModuleByType(ds2, osType).orElseThrow().getId(), Action.ActionType.FORCED);
performGet(CONTROLLER_BASE, MediaTypes.HAL_JSON, status().isOk(), tenantAware.getCurrentTenant(), CONTROLLER_ID)
.andExpect(jsonPath("$.config.polling.sleep", equalTo("00:01:00")))
@@ -197,7 +197,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
// older installed action is still accessible, although not part of controller base
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1,
actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT);
actionId1, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT);
}
/**
@@ -245,7 +245,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1,
actionId3, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT);
actionId3, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT);
// cancelled action are not accessible
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(),
@@ -304,7 +304,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
.andExpect(jsonPath("$._links.deploymentBase.href").doesNotExist());
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1,
actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT);
actionId1, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT);
// cancelled action are not accessible
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(),
@@ -359,7 +359,7 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
startsWith(deploymentBaseLink(CONTROLLER_ID, actionId3.toString()))));
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds1, artifact1, artifactSignature1,
actionId1, ds1.findFirstModuleByType(osType).get().getId(), Action.ActionType.SOFT);
actionId1, findFirstModuleByType(ds1, osType).orElseThrow().getId(), Action.ActionType.SOFT);
// cancelled action are not accessible
mvc.perform(MockMvcRequestBuilders.get(INSTALLED_BASE, tenantAware.getCurrentTenant(), target.getControllerId(),
@@ -463,10 +463,10 @@ class DdiInstalledBaseTest extends AbstractDDiApiIntegrationTest {
tenantAware.getCurrentTenant(), target.getControllerId(), actionId))));
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaType.APPLICATION_JSON, ds, artifact, artifactSignature,
actionId, ds.findFirstModuleByType(osType).get().getId(), actionType);
actionId, findFirstModuleByType(ds, osType).orElseThrow().getId(), actionType);
getAndVerifyInstalledBasePayload(CONTROLLER_ID, MediaTypes.HAL_JSON, ds, artifact, artifactSignature, actionId,
ds.findFirstModuleByType(osType).get().getId(), actionType);
findFirstModuleByType(ds, osType).orElseThrow().getId(), actionType);
// Action is still finished after calling installedBase
final Iterable<ActionStatus> actionStatusMessages = deploymentManagement

View File

@@ -26,7 +26,6 @@ import org.eclipse.hawkbit.security.controller.GatewayTokenAuthenticator;
import org.eclipse.hawkbit.security.controller.SecurityHeaderAuthenticator;
import org.eclipse.hawkbit.security.controller.SecurityTokenAuthenticator;
import org.eclipse.hawkbit.tenancy.TenantAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
@@ -57,8 +56,8 @@ class ControllerDownloadSecurityConfiguration {
private final HawkbitSecurityProperties securityProperties;
private final SystemSecurityContext systemSecurityContext;
@Autowired
ControllerDownloadSecurityConfiguration(final ControllerManagement controllerManagement,
ControllerDownloadSecurityConfiguration(
final ControllerManagement controllerManagement,
final TenantConfigurationManagement tenantConfigurationManagement, final TenantAware tenantAware,
final DdiSecurityProperties ddiSecurityConfiguration,
final HawkbitSecurityProperties securityProperties, final SystemSecurityContext systemSecurityContext) {

View File

@@ -97,9 +97,9 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
private final SystemManagement systemManagement;
private final TargetManagement targetManagement;
private final ServiceMatcher serviceMatcher;
private final DistributionSetManagement distributionSetManagement;
private final SoftwareModuleManagement<? extends SoftwareModule> softwareModuleManagement;
private final DistributionSetManagement<? extends DistributionSet> distributionSetManagement;
private final DeploymentManagement deploymentManagement;
private final SoftwareModuleManagement softwareModuleManagement;
private final TenantConfigurationManagement tenantConfigurationManagement;
/**
@@ -121,8 +121,8 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
final AmqpMessageSenderService amqpSenderService, final ArtifactUrlHandler artifactUrlHandler,
final SystemSecurityContext systemSecurityContext, final SystemManagement systemManagement,
final TargetManagement targetManagement, final ServiceMatcher serviceMatcher,
final DistributionSetManagement distributionSetManagement,
final SoftwareModuleManagement softwareModuleManagement, final DeploymentManagement deploymentManagement,
final SoftwareModuleManagement<? extends SoftwareModule> softwareModuleManagement, final DistributionSetManagement<? extends DistributionSet> distributionSetManagement,
final DeploymentManagement deploymentManagement,
final TenantConfigurationManagement tenantConfigurationManagement) {
super(rabbitTemplate);
this.artifactUrlHandler = artifactUrlHandler;
@@ -131,8 +131,8 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
this.systemManagement = systemManagement;
this.targetManagement = targetManagement;
this.serviceMatcher = serviceMatcher;
this.distributionSetManagement = distributionSetManagement;
this.softwareModuleManagement = softwareModuleManagement;
this.distributionSetManagement = distributionSetManagement;
this.deploymentManagement = deploymentManagement;
this.tenantConfigurationManagement = tenantConfigurationManagement;
}

View File

@@ -279,8 +279,8 @@ public class DmfApiConfiguration {
final SoftwareModuleManagement softwareModuleManagement, final DeploymentManagement deploymentManagement,
final TenantConfigurationManagement tenantConfigurationManagement) {
return new AmqpMessageDispatcherService(rabbitTemplate, amqpSenderService, artifactUrlHandler,
systemSecurityContext, systemManagement, targetManagement, serviceMatcher, distributionSetManagement,
softwareModuleManagement, deploymentManagement, tenantConfigurationManagement);
systemSecurityContext, systemManagement, targetManagement, serviceMatcher, softwareModuleManagement, distributionSetManagement,
deploymentManagement, tenantConfigurationManagement);
}
private static Map<String, Object> getTTLMaxArgsAuthenticationQueue() {

View File

@@ -109,7 +109,7 @@ class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
amqpMessageDispatcherService = new AmqpMessageDispatcherService(rabbitTemplate, senderService,
artifactUrlHandlerMock, systemSecurityContext, systemManagement, targetManagement, serviceMatcher,
distributionSetManagement, softwareModuleManagement, deploymentManagement, tenantConfigurationManagement);
softwareModuleManagement, distributionSetManagement, deploymentManagement, tenantConfigurationManagement);
}

View File

@@ -51,7 +51,6 @@ import org.eclipse.hawkbit.repository.DeploymentManagement;
import org.eclipse.hawkbit.repository.DistributionSetInvalidationManagement;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.TargetFilterQueryManagement;
@@ -82,49 +81,50 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
private final SoftwareModuleManagement softwareModuleManagement;
private final SoftwareModuleManagement<? extends SoftwareModule> softwareModuleManagement;
private final DistributionSetManagement<? extends DistributionSet> distributionSetManagement;
private final DistributionSetTypeManagement<? extends DistributionSetType> distributionSetTypeManagement;
private final DistributionSetInvalidationManagement distributionSetInvalidationManagement;
private final TargetManagement targetManagement;
private final TargetFilterQueryManagement targetFilterQueryManagement;
private final DeploymentManagement deployManagement;
private final SystemManagement systemManagement;
private final EntityFactory entityFactory;
private final DistributionSetManagement distributionSetManagement;
private final DistributionSetTypeManagement distributionSetTypeManagement;
private final MgmtDistributionSetMapper mgmtDistributionSetMapper;
private final SystemSecurityContext systemSecurityContext;
private final DistributionSetInvalidationManagement distributionSetInvalidationManagement;
private final TenantConfigHelper tenantConfigHelper;
@SuppressWarnings("java:S107")
MgmtDistributionSetResource(
final SoftwareModuleManagement softwareModuleManagement,
final TargetManagement targetManagement, final TargetFilterQueryManagement targetFilterQueryManagement,
final DeploymentManagement deployManagement, final SystemManagement systemManagement,
final EntityFactory entityFactory, final DistributionSetManagement distributionSetManagement,
final DistributionSetTypeManagement distributionSetTypeManagement, final SystemSecurityContext systemSecurityContext,
final SoftwareModuleManagement<? extends SoftwareModule> softwareModuleManagement,
final DistributionSetManagement<? extends DistributionSet> distributionSetManagement,
final DistributionSetTypeManagement<? extends DistributionSetType> distributionSetTypeManagement,
final DistributionSetInvalidationManagement distributionSetInvalidationManagement,
final TenantConfigurationManagement tenantConfigurationManagement) {
final TargetManagement targetManagement, final TargetFilterQueryManagement targetFilterQueryManagement,
final DeploymentManagement deployManagement, final TenantConfigurationManagement tenantConfigurationManagement,
final MgmtDistributionSetMapper mgmtDistributionSetMapper,
final SystemManagement systemManagement, final SystemSecurityContext systemSecurityContext) {
this.softwareModuleManagement = softwareModuleManagement;
this.distributionSetManagement = distributionSetManagement;
this.distributionSetTypeManagement = distributionSetTypeManagement;
this.distributionSetInvalidationManagement = distributionSetInvalidationManagement;
this.targetManagement = targetManagement;
this.targetFilterQueryManagement = targetFilterQueryManagement;
this.deployManagement = deployManagement;
this.systemManagement = systemManagement;
this.entityFactory = entityFactory;
this.distributionSetManagement = distributionSetManagement;
this.distributionSetTypeManagement = distributionSetTypeManagement;
this.systemSecurityContext = systemSecurityContext;
this.distributionSetInvalidationManagement = distributionSetInvalidationManagement;
this.tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
this.mgmtDistributionSetMapper = mgmtDistributionSetMapper;
this.systemManagement = systemManagement;
this.systemSecurityContext = systemSecurityContext;
}
@Override
public ResponseEntity<PagedList<MgmtDistributionSet>> getDistributionSets(
final String rsqlParam, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) {
final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeDistributionSetSortParam(sortParam));
final Slice<DistributionSet> findDsPage;
final Slice<? extends DistributionSet> findDsPage;
final long countModulesAll;
if (rsqlParam != null) {
findDsPage = distributionSetManagement.findByRsql(rsqlParam, pageable);
countModulesAll = ((Page<DistributionSet>) findDsPage).getTotalElements();
countModulesAll = ((Page<? extends DistributionSet>) findDsPage).getTotalElements();
} else {
findDsPage = distributionSetManagement.findAll(pageable);
countModulesAll = distributionSetManagement.count();
@@ -152,8 +152,8 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
sets.stream().filter(ds -> ds.getType() == null).forEach(ds -> ds.setType(defaultDsKey));
//check if there is already deleted DS Type
for (MgmtDistributionSetRequestBodyPost ds : sets) {
final Optional<DistributionSetType> opt = distributionSetTypeManagement.findByKey(ds.getType());
for (final MgmtDistributionSetRequestBodyPost ds : sets) {
final Optional<? extends DistributionSetType> opt = distributionSetTypeManagement.findByKey(ds.getType());
opt.ifPresent(dsType -> {
if (dsType.isDeleted()) {
final String text = "Cannot create Distribution Set from type with key {0}. Distribution Set Type already deleted!";
@@ -163,8 +163,8 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
});
}
final Collection<DistributionSet> createdDSets = distributionSetManagement
.create(MgmtDistributionSetMapper.dsFromRequest(sets, entityFactory));
final Collection<? extends DistributionSet> createdDSets = distributionSetManagement
.create(mgmtDistributionSetMapper.fromRequest(sets));
log.debug("{} distribution sets created, return status {}", sets.size(), HttpStatus.CREATED);
return new ResponseEntity<>(MgmtDistributionSetMapper.toResponseDistributionSets(createdDSets), HttpStatus.CREATED);
@@ -182,10 +182,11 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
public ResponseEntity<MgmtDistributionSet> updateDistributionSet(
final Long distributionSetId,
final MgmtDistributionSetRequestBodyPut toUpdate) {
final DistributionSet updated = distributionSetManagement.update(entityFactory.distributionSet()
.update(distributionSetId).name(toUpdate.getName()).description(toUpdate.getDescription())
final DistributionSet updated = distributionSetManagement.update(DistributionSetManagement.Update.builder()
.id(distributionSetId).name(toUpdate.getName()).description(toUpdate.getDescription())
.version(toUpdate.getVersion()).locked(toUpdate.getLocked())
.requiredMigrationStep(toUpdate.getRequiredMigrationStep()));
.requiredMigrationStep(toUpdate.getRequiredMigrationStep())
.build());
final MgmtDistributionSet response = MgmtDistributionSetMapper.toResponse(updated);
MgmtDistributionSetMapper.addLinks(updated, response);
@@ -247,7 +248,7 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
final List<Entry<String, Long>> offlineAssignments = assignments.stream()
.map(assignment -> new SimpleEntry<>(assignment.getId(), distributionSetId))
.collect(Collectors.toList());
return ResponseEntity.ok(MgmtDistributionSetMapper
return ResponseEntity.ok(mgmtDistributionSetMapper
.toResponse(deployManagement.offlineAssignedDistributionSets(offlineAssignments)));
}
@@ -260,7 +261,7 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
}).toList();
final List<DistributionSetAssignmentResult> assignmentResults = deployManagement.assignDistributionSets(deploymentRequests);
return ResponseEntity.ok(MgmtDistributionSetMapper.toResponse(assignmentResults));
return ResponseEntity.ok(mgmtDistributionSetMapper.toResponse(assignmentResults));
}
@Override
@@ -316,9 +317,8 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
final Long distributionSetId,
final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) {
final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeDistributionSetSortParam(sortParam));
final Page<SoftwareModule> softwareModules = softwareModuleManagement.findByAssignedTo(distributionSetId, pageable);
return ResponseEntity.ok(new PagedList<>(MgmtSoftwareModuleMapper.toResponse(
softwareModules.getContent()), softwareModules.getTotalElements()));
final Page<? extends SoftwareModule> softwareModules = softwareModuleManagement.findByAssignedTo(distributionSetId, pageable);
return ResponseEntity.ok(new PagedList<>(MgmtSoftwareModuleMapper.toResponse(softwareModules.getContent()), softwareModules.getTotalElements()));
}
@Override

View File

@@ -25,7 +25,6 @@ import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtTagMapper;
import org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
@@ -41,31 +40,29 @@ import org.springframework.web.bind.annotation.RestController;
*/
@Slf4j
@RestController
public class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRestApi {
class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRestApi {
private final DistributionSetTagManagement distributionSetTagManagement;
private final DistributionSetManagement distributionSetManagement;
private final EntityFactory entityFactory;
private final DistributionSetManagement<? extends DistributionSet> distributionSetManagement;
private final DistributionSetTagManagement<? extends DistributionSetTag> distributionSetTagManagement;
MgmtDistributionSetTagResource(
final DistributionSetTagManagement distributionSetTagManagement,
final DistributionSetManagement distributionSetManagement, final EntityFactory entityFactory) {
final DistributionSetManagement<? extends DistributionSet> distributionSetManagement,
final DistributionSetTagManagement<? extends DistributionSetTag> distributionSetTagManagement) {
this.distributionSetTagManagement = distributionSetTagManagement;
this.distributionSetManagement = distributionSetManagement;
this.entityFactory = entityFactory;
}
@Override
public ResponseEntity<PagedList<MgmtTag>> getDistributionSetTags(
final String rsqlParam, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) {
final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeTagSortParam(sortParam));
final Slice<DistributionSetTag> distributionSetTags;
final Slice<? extends DistributionSetTag> distributionSetTags;
final long count;
if (rsqlParam == null) {
distributionSetTags = distributionSetTagManagement.findAll(pageable);
count = distributionSetTagManagement.count();
} else {
final Page<DistributionSetTag> page = distributionSetTagManagement.findByRsql(rsqlParam, pageable);
final Page<? extends DistributionSetTag> page = distributionSetTagManagement.findByRsql(rsqlParam, pageable);
distributionSetTags = page;
count = page.getTotalElements();
}
@@ -88,7 +85,7 @@ public class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRes
public ResponseEntity<List<MgmtTag>> createDistributionSetTags(final List<MgmtTagRequestBodyPut> tags) {
log.debug("creating {} ds tags", tags.size());
final List<DistributionSetTag> createdTags = distributionSetTagManagement.create(MgmtTagMapper.mapTagFromRequest(entityFactory, tags));
final List<? extends DistributionSetTag> createdTags = distributionSetTagManagement.create(MgmtDistributionSetMapper.mapTagFromRequest(tags));
return new ResponseEntity<>(MgmtTagMapper.toResponseDistributionSetTag(createdTags), HttpStatus.CREATED);
}
@@ -97,8 +94,8 @@ public class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRes
public ResponseEntity<MgmtTag> updateDistributionSetTag(final Long distributionSetTagId, final MgmtTagRequestBodyPut restDSTagRest) {
final DistributionSetTag distributionSetTag = distributionSetTagManagement
.update(entityFactory.tag().update(distributionSetTagId).name(restDSTagRest.getName())
.description(restDSTagRest.getDescription()).colour(restDSTagRest.getColour()));
.update(DistributionSetTagManagement.Update.builder().id(distributionSetTagId).name(restDSTagRest.getName())
.description(restDSTagRest.getDescription()).colour(restDSTagRest.getColour()).build());
final MgmtTag response = MgmtTagMapper.toResponse(distributionSetTag);
MgmtTagMapper.addLinks(distributionSetTag, response);
@@ -122,7 +119,7 @@ public class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRes
final Long distributionSetTagId, final String rsqlParam,
final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) {
final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeTagSortParam(sortParam));
final Page<DistributionSet> distributionSets;
final Page<? extends DistributionSet> distributionSets;
if (rsqlParam == null) {
distributionSets = distributionSetManagement.findByTag(distributionSetTagId, pageable);
} else {
@@ -143,7 +140,7 @@ public class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRes
@Override
public ResponseEntity<Void> assignDistributionSets(final Long distributionSetTagId, final List<Long> distributionSetIds) {
log.debug("Assign DistributionSet {} for ds tag {}", distributionSetIds.size(), distributionSetTagId);
final List<DistributionSet> assignedDs = this.distributionSetManagement.assignTag(distributionSetIds, distributionSetTagId);
final List<? extends DistributionSet> assignedDs = this.distributionSetManagement.assignTag(distributionSetIds, distributionSetTagId);
log.debug("Assigned DistributionSet {}", assignedDs.size());
return ResponseEntity.ok().build();
}
@@ -160,7 +157,7 @@ public class MgmtDistributionSetTagResource implements MgmtDistributionSetTagRes
@AuditLog(entity = "DistributionSetTag", type = AuditLog.Type.UPDATE, description = "Unassign Distribution Sets From Tag")
public ResponseEntity<Void> unassignDistributionSets(final Long distributionsetTagId, final List<Long> distributionsetIds) {
log.debug("Unassign DistributionSet {} for ds tag {}", distributionsetIds.size(), distributionsetTagId);
final List<DistributionSet> assignedDs = this.distributionSetManagement.unassignTag(distributionsetIds, distributionsetTagId);
final List<? extends DistributionSet> assignedDs = this.distributionSetManagement.unassignTag(distributionsetIds, distributionsetTagId);
log.debug("Unassigned DistributionSet {}", assignedDs.size());
return ResponseEntity.ok().build();
}

View File

@@ -26,7 +26,6 @@ import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtDistributionSetTypeMapp
import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtSoftwareModuleTypeMapper;
import org.eclipse.hawkbit.mgmt.rest.resource.util.PagingUtility;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.SoftwareModuleTypeNotInDistributionSetTypeException;
@@ -45,33 +44,34 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
public class MgmtDistributionSetTypeResource implements MgmtDistributionSetTypeRestApi {
private final SoftwareModuleTypeManagement softwareModuleTypeManagement;
private final DistributionSetTypeManagement distributionSetTypeManagement;
private final EntityFactory entityFactory;
private final SoftwareModuleTypeManagement<? extends SoftwareModuleType> softwareModuleTypeManagement;
private final DistributionSetTypeManagement<? extends DistributionSetType> distributionSetTypeManagement;
private final MgmtDistributionSetTypeMapper mgmtDistributionSetTypeMapper;
MgmtDistributionSetTypeResource(
final SoftwareModuleTypeManagement softwareModuleTypeManagement,
final DistributionSetTypeManagement distributionSetTypeManagement, final EntityFactory entityFactory) {
final SoftwareModuleTypeManagement<? extends SoftwareModuleType> softwareModuleTypeManagement,
final DistributionSetTypeManagement<? extends DistributionSetType> distributionSetTypeManagement,
final MgmtDistributionSetTypeMapper mgmtDistributionSetTypeMapper) {
this.softwareModuleTypeManagement = softwareModuleTypeManagement;
this.distributionSetTypeManagement = distributionSetTypeManagement;
this.entityFactory = entityFactory;
this.mgmtDistributionSetTypeMapper = mgmtDistributionSetTypeMapper;
}
@Override
public ResponseEntity<PagedList<MgmtDistributionSetType>> getDistributionSetTypes(
final String rsqlParam, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) {
final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeDistributionSetTypeSortParam(sortParam));
final Slice<DistributionSetType> findModuleTypessAll;
final Slice<? extends DistributionSetType> findModuleTypesAll;
long countModulesAll;
if (rsqlParam != null) {
findModuleTypessAll = distributionSetTypeManagement.findByRsql(rsqlParam, pageable);
countModulesAll = ((Page<DistributionSetType>) findModuleTypessAll).getTotalElements();
findModuleTypesAll = distributionSetTypeManagement.findByRsql(rsqlParam, pageable);
countModulesAll = ((Page<?>) findModuleTypesAll).getTotalElements();
} else {
findModuleTypessAll = distributionSetTypeManagement.findAll(pageable);
findModuleTypesAll = distributionSetTypeManagement.findAll(pageable);
countModulesAll = distributionSetTypeManagement.count();
}
final List<MgmtDistributionSetType> rest = MgmtDistributionSetTypeMapper.toListResponse(findModuleTypessAll.getContent());
final List<MgmtDistributionSetType> rest = MgmtDistributionSetTypeMapper.toListResponse(findModuleTypesAll.getContent());
return ResponseEntity.ok(new PagedList<>(rest, countModulesAll));
}
@@ -97,9 +97,10 @@ public class MgmtDistributionSetTypeResource implements MgmtDistributionSetTypeR
@AuditLog(entity = "DistributionSetType", type = AuditLog.Type.UPDATE, description = "Update Distribution Set Type")
public ResponseEntity<MgmtDistributionSetType> updateDistributionSetType(
final Long distributionSetTypeId, final MgmtDistributionSetTypeRequestBodyPut restDistributionSetType) {
final DistributionSetType updated = distributionSetTypeManagement.update(entityFactory.distributionSetType()
.update(distributionSetTypeId).description(restDistributionSetType.getDescription())
.colour(restDistributionSetType.getColour()));
final DistributionSetType updated = distributionSetTypeManagement.update(DistributionSetTypeManagement.Update.builder()
.id(distributionSetTypeId).description(restDistributionSetType.getDescription())
.colour(restDistributionSetType.getColour()).
build());
final MgmtDistributionSetType response = MgmtDistributionSetTypeMapper.toResponse(updated);
MgmtDistributionSetTypeMapper.addLinks(response);
@@ -110,11 +111,10 @@ public class MgmtDistributionSetTypeResource implements MgmtDistributionSetTypeR
@Override
public ResponseEntity<List<MgmtDistributionSetType>> createDistributionSetTypes(
final List<MgmtDistributionSetTypeRequestBodyPost> distributionSetTypes) {
final List<DistributionSetType> createdSoftwareModules = distributionSetTypeManagement
.create(MgmtDistributionSetTypeMapper.smFromRequest(entityFactory, distributionSetTypes));
final List<? extends DistributionSetType> createdSoftwareModules = distributionSetTypeManagement
.create(mgmtDistributionSetTypeMapper.smFromRequest(distributionSetTypes));
return ResponseEntity.status(HttpStatus.CREATED)
.body(MgmtDistributionSetTypeMapper.toListResponse(createdSoftwareModules));
return ResponseEntity.status(HttpStatus.CREATED).body(MgmtDistributionSetTypeMapper.toListResponse(createdSoftwareModules));
}
@Override

View File

@@ -36,10 +36,10 @@ import org.springframework.web.context.WebApplicationContext;
@Scope(value = WebApplicationContext.SCOPE_REQUEST)
public class MgmtDownloadArtifactResource implements MgmtDownloadArtifactRestApi {
private final SoftwareModuleManagement softwareModuleManagement;
private final SoftwareModuleManagement<? extends SoftwareModule> softwareModuleManagement;
private final ArtifactManagement artifactManagement;
public MgmtDownloadArtifactResource(final SoftwareModuleManagement softwareModuleManagement, final ArtifactManagement artifactManagement) {
public MgmtDownloadArtifactResource(final SoftwareModuleManagement<? extends SoftwareModule> softwareModuleManagement, final ArtifactManagement artifactManagement) {
this.softwareModuleManagement = softwareModuleManagement;
this.artifactManagement = artifactManagement;
}

View File

@@ -62,21 +62,25 @@ import org.springframework.web.multipart.MultipartFile;
public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi {
private final ArtifactManagement artifactManagement;
private final SoftwareModuleManagement softwareModuleManagement;
private final SoftwareModuleTypeManagement softwareModuleTypeManagement;
private final SoftwareModuleManagement<? extends SoftwareModule> softwareModuleManagement;
private final SoftwareModuleTypeManagement<? extends SoftwareModuleType> softwareModuleTypeManagement;
private final ArtifactUrlHandler artifactUrlHandler;
private final MgmtSoftwareModuleMapper mgmtSoftwareModuleMapper;
private final SystemManagement systemManagement;
private final EntityFactory entityFactory;
MgmtSoftwareModuleResource(
final ArtifactManagement artifactManagement, final SoftwareModuleManagement softwareModuleManagement,
final SoftwareModuleTypeManagement softwareModuleTypeManagement,
final ArtifactUrlHandler artifactUrlHandler, final SystemManagement systemManagement,
final EntityFactory entityFactory) {
final ArtifactManagement artifactManagement,
final SoftwareModuleManagement<? extends SoftwareModule> softwareModuleManagement,
final SoftwareModuleTypeManagement<? extends SoftwareModuleType> softwareModuleTypeManagement,
final ArtifactUrlHandler artifactUrlHandler,
final MgmtSoftwareModuleMapper mgmtSoftwareModuleMapper,
final SystemManagement systemManagement, final EntityFactory entityFactory) {
this.artifactManagement = artifactManagement;
this.softwareModuleManagement = softwareModuleManagement;
this.softwareModuleTypeManagement = softwareModuleTypeManagement;
this.artifactUrlHandler = artifactUrlHandler;
this.mgmtSoftwareModuleMapper = mgmtSoftwareModuleMapper;
this.systemManagement = systemManagement;
this.entityFactory = entityFactory;
}
@@ -159,11 +163,11 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi {
public ResponseEntity<PagedList<MgmtSoftwareModule>> getSoftwareModules(
final String rsqlParam, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) {
final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeSoftwareModuleSortParam(sortParam));
final Slice<SoftwareModule> findModulesAll;
final Slice<? extends SoftwareModule> findModulesAll;
final long countModulesAll;
if (rsqlParam != null) {
findModulesAll = softwareModuleManagement.findByRsql(rsqlParam, pageable);
countModulesAll = ((Page<SoftwareModule>) findModulesAll).getTotalElements();
countModulesAll = ((Page<?>) findModulesAll).getTotalElements();
} else {
findModulesAll = softwareModuleManagement.findAll(pageable);
countModulesAll = softwareModuleManagement.count();
@@ -188,7 +192,7 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi {
log.debug("creating {} softwareModules", softwareModules.size());
for (final MgmtSoftwareModuleRequestBodyPost sm : softwareModules) {
final Optional<SoftwareModuleType> opt = softwareModuleTypeManagement.findByKey(sm.getType());
final Optional<? extends SoftwareModuleType> opt = softwareModuleTypeManagement.findByKey(sm.getType());
opt.ifPresent(smType -> {
if (smType.isDeleted()) {
final String text = "Cannot create Software Module from type with key {0}. Software Module Type already deleted!";
@@ -197,8 +201,8 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi {
}
});
}
final Collection<SoftwareModule> createdSoftwareModules = softwareModuleManagement
.create(MgmtSoftwareModuleMapper.smFromRequest(entityFactory, softwareModules));
final Collection<? extends SoftwareModule> createdSoftwareModules = softwareModuleManagement
.create(mgmtSoftwareModuleMapper.smFromRequest(softwareModules));
log.debug("{} softwareModules created, return status {}", softwareModules.size(), HttpStatus.CREATED);
return ResponseEntity.status(HttpStatus.CREATED).body(MgmtSoftwareModuleMapper.toResponse(createdSoftwareModules));
@@ -208,10 +212,12 @@ public class MgmtSoftwareModuleResource implements MgmtSoftwareModuleRestApi {
public ResponseEntity<MgmtSoftwareModule> updateSoftwareModule(
final Long softwareModuleId, final MgmtSoftwareModuleRequestBodyPut restSoftwareModule) {
final SoftwareModule module = softwareModuleManagement
.update(entityFactory.softwareModule().update(softwareModuleId)
.update(SoftwareModuleManagement.Update.builder()
.id(softwareModuleId)
.description(restSoftwareModule.getDescription())
.vendor(restSoftwareModule.getVendor())
.locked(restSoftwareModule.getLocked()));
.locked(restSoftwareModule.getLocked())
.build());
final MgmtSoftwareModule response = MgmtSoftwareModuleMapper.toResponse(module);
MgmtSoftwareModuleMapper.addLinks(module, response);

View File

@@ -38,23 +38,21 @@ import org.springframework.web.bind.annotation.RestController;
@RestController
public class MgmtSoftwareModuleTypeResource implements MgmtSoftwareModuleTypeRestApi {
private final SoftwareModuleTypeManagement softwareModuleTypeManagement;
private final EntityFactory entityFactory;
private final SoftwareModuleTypeManagement<? extends SoftwareModuleType> softwareModuleTypeManagement;
MgmtSoftwareModuleTypeResource(final SoftwareModuleTypeManagement softwareModuleTypeManagement, final EntityFactory entityFactory) {
MgmtSoftwareModuleTypeResource(final SoftwareModuleTypeManagement<? extends SoftwareModuleType> softwareModuleTypeManagement) {
this.softwareModuleTypeManagement = softwareModuleTypeManagement;
this.entityFactory = entityFactory;
}
@Override
public ResponseEntity<PagedList<MgmtSoftwareModuleType>> getTypes(
final String rsqlParam, final int pagingOffsetParam, final int pagingLimitParam, final String sortParam) {
final Pageable pageable = PagingUtility.toPageable(pagingOffsetParam, pagingLimitParam, sanitizeSoftwareModuleTypeSortParam(sortParam));
final Slice<SoftwareModuleType> findModuleTypessAll;
final Slice<? extends SoftwareModuleType> findModuleTypessAll;
final long countModulesAll;
if (rsqlParam != null) {
findModuleTypessAll = softwareModuleTypeManagement.findByRsql(rsqlParam, pageable);
countModulesAll = ((Page<SoftwareModuleType>) findModuleTypessAll).getTotalElements();
countModulesAll = ((Page<?>) findModuleTypessAll).getTotalElements();
} else {
findModuleTypessAll = softwareModuleTypeManagement.findAll(pageable);
countModulesAll = softwareModuleTypeManagement.count();
@@ -80,9 +78,11 @@ public class MgmtSoftwareModuleTypeResource implements MgmtSoftwareModuleTypeRes
@Override
public ResponseEntity<MgmtSoftwareModuleType> updateSoftwareModuleType(
final Long softwareModuleTypeId, final MgmtSoftwareModuleTypeRequestBodyPut restSoftwareModuleType) {
final SoftwareModuleType updatedSoftwareModuleType = softwareModuleTypeManagement.update(entityFactory
.softwareModuleType().update(softwareModuleTypeId).description(restSoftwareModuleType.getDescription())
.colour(restSoftwareModuleType.getColour()));
final SoftwareModuleType updatedSoftwareModuleType = softwareModuleTypeManagement.update(
SoftwareModuleTypeManagement.Update.builder().id(softwareModuleTypeId)
.description(restSoftwareModuleType.getDescription())
.colour(restSoftwareModuleType.getColour())
.build());
return ResponseEntity.ok(MgmtSoftwareModuleTypeMapper.toResponse(updatedSoftwareModuleType));
}
@@ -90,8 +90,8 @@ public class MgmtSoftwareModuleTypeResource implements MgmtSoftwareModuleTypeRes
@Override
public ResponseEntity<List<MgmtSoftwareModuleType>> createSoftwareModuleTypes(
final List<MgmtSoftwareModuleTypeRequestBodyPost> softwareModuleTypes) {
final List<SoftwareModuleType> createdSoftwareModules = softwareModuleTypeManagement
.create(MgmtSoftwareModuleTypeMapper.smFromRequest(entityFactory, softwareModuleTypes));
final List<? extends SoftwareModuleType> createdSoftwareModules = softwareModuleTypeManagement
.create(MgmtSoftwareModuleTypeMapper.smFromRequest(softwareModuleTypes));
return new ResponseEntity<>(MgmtSoftwareModuleTypeMapper.toTypesResponse(createdSoftwareModules), HttpStatus.CREATED);
}

View File

@@ -86,17 +86,21 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
private final TargetManagement targetManagement;
private final ConfirmationManagement confirmationManagement;
private final DeploymentManagement deploymentManagement;
private final MgmtDistributionSetMapper mgmtDistributionSetMapper;
private final EntityFactory entityFactory;
private final TenantConfigHelper tenantConfigHelper;
MgmtTargetResource(
final TargetManagement targetManagement, final DeploymentManagement deploymentManagement,
final ConfirmationManagement confirmationManagement, final EntityFactory entityFactory,
final ConfirmationManagement confirmationManagement,
final MgmtDistributionSetMapper mgmtDistributionSetMapper,
final EntityFactory entityFactory,
final SystemSecurityContext systemSecurityContext,
final TenantConfigurationManagement tenantConfigurationManagement) {
this.targetManagement = targetManagement;
this.deploymentManagement = deploymentManagement;
this.confirmationManagement = confirmationManagement;
this.mgmtDistributionSetMapper = mgmtDistributionSetMapper;
this.entityFactory = entityFactory;
this.tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
}
@@ -290,7 +294,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
log.debug("updateActionConfirmation with data [targetId={}, actionId={}]: {}", targetId, actionId, actionConfirmation);
return getValidatedAction(targetId, actionId)
.map(action -> {
.<ResponseEntity<Void>>map(action -> {
try {
switch (actionConfirmation.getConfirmation()) {
case CONFIRMED:
@@ -305,18 +309,18 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
confirmationManagement.denyAction(actionId, actionConfirmation.getCode(), actionConfirmation.getDetails());
break;
}
return new ResponseEntity<Void>(HttpStatus.OK);
return new ResponseEntity<>(HttpStatus.OK);
} catch (final InvalidConfirmationFeedbackException e) {
if (e.getReason() == InvalidConfirmationFeedbackException.Reason.ACTION_CLOSED) {
log.warn("Updating action {} with confirmation {} not possible since action not active anymore.",
action.getId(), actionConfirmation.getConfirmation(), e);
return new ResponseEntity<Void>(HttpStatus.GONE);
return new ResponseEntity<>(HttpStatus.GONE);
} else if (e.getReason() == InvalidConfirmationFeedbackException.Reason.NOT_AWAITING_CONFIRMATION) {
log.debug("Action is not waiting for confirmation, deny request.", e);
return new ResponseEntity<Void>(HttpStatus.NOT_FOUND);
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
} else {
log.debug("Action confirmation failed with unknown reason.", e);
return new ResponseEntity<Void>(HttpStatus.BAD_REQUEST);
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
}
})
@@ -371,7 +375,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
final List<Entry<String, Long>> offlineAssignments = dsAssignments.stream()
.map(dsAssignment -> new SimpleEntry<>(targetId, dsAssignment.getId()))
.collect(Collectors.toList());
return ResponseEntity.ok(MgmtDistributionSetMapper
return ResponseEntity.ok(mgmtDistributionSetMapper
.toResponse(deploymentManagement.offlineAssignedDistributionSets(offlineAssignments)));
}
findTargetWithExceptionIfNotFound(targetId);
@@ -386,7 +390,7 @@ public class MgmtTargetResource implements MgmtTargetRestApi {
final List<DistributionSetAssignmentResult> assignmentResults = deploymentManagement
.assignDistributionSets(deploymentRequests);
return ResponseEntity.ok(MgmtDistributionSetMapper.toResponse(assignmentResults));
return ResponseEntity.ok(mgmtDistributionSetMapper.toResponse(assignmentResults));
}
@Override

View File

@@ -92,7 +92,7 @@ public class MgmtTargetTagResource implements MgmtTargetTagRestApi {
@Override
public ResponseEntity<List<MgmtTag>> createTargetTags(final List<MgmtTagRequestBodyPut> tags) {
log.debug("creating {} target tags", tags.size());
final List<TargetTag> createdTargetTags = this.tagManagement.create(MgmtTagMapper.mapTagFromRequest(entityFactory, tags));
final List<TargetTag> createdTargetTags = tagManagement.create(MgmtTagMapper.mapTagFromRequest(entityFactory, tags));
return new ResponseEntity<>(MgmtTagMapper.toResponse(createdTargetTags), HttpStatus.CREATED);
}

View File

@@ -12,45 +12,59 @@ package org.eclipse.hawkbit.mgmt.rest.resource.mapper;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.eclipse.hawkbit.mgmt.json.model.MgmtMetadata;
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtActionId;
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSet;
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtDistributionSetRequestBodyPost;
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtTargetAssignmentResponseBody;
import org.eclipse.hawkbit.mgmt.json.model.tag.MgmtTagRequestBodyPut;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetTypeRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.builder.DistributionSetCreate;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.DistributionSetTagManagement;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetAssignmentResult;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.rest.json.model.ResponseList;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
/**
* A mapper which maps repository model to RESTful model representation and
* back.
* A mapper which maps repository model to RESTful model representation and back.
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class MgmtDistributionSetMapper {
@Service
public class MgmtDistributionSetMapper {
/**
* {@link MgmtDistributionSetRequestBodyPost}s to {@link DistributionSet}s.
*
* @param sets to convert
* @return converted list of {@link DistributionSet}s
*/
public static List<DistributionSetCreate> dsFromRequest(
final Collection<MgmtDistributionSetRequestBodyPost> sets, final EntityFactory entityFactory) {
return sets.stream().map(dsRest -> fromRequest(dsRest, entityFactory)).toList();
private final DistributionSetTypeManagement<? extends DistributionSetType> distributionSetTypeManagement;
private final SoftwareModuleManagement<? extends SoftwareModule> softwareModuleManagement;
private final SystemManagement systemManagement;
MgmtDistributionSetMapper(
final DistributionSetTypeManagement<? extends DistributionSetType> distributionSetTypeManagement,
final SoftwareModuleManagement<? extends SoftwareModule> softwareModuleManagement,
final SystemManagement systemManagement) {
this.distributionSetTypeManagement = distributionSetTypeManagement;
this.softwareModuleManagement = softwareModuleManagement;
this.systemManagement = systemManagement;
}
public List<DistributionSetManagement.Create> fromRequest(final Collection<MgmtDistributionSetRequestBodyPost> sets) {
return sets.stream().map(this::fromRequest).toList();
}
public static MgmtDistributionSet toResponse(final DistributionSet distributionSet) {
@@ -70,13 +84,11 @@ public final class MgmtDistributionSetMapper {
response.setDeleted(distributionSet.isDeleted());
response.setValid(distributionSet.isValid());
distributionSet.getModules()
.forEach(module -> response.getModules().add(MgmtSoftwareModuleMapper.toResponse(module)));
distributionSet.getModules().forEach(module -> response.getModules().add(MgmtSoftwareModuleMapper.toResponse(module)));
response.setRequiredMigrationStep(distributionSet.isRequiredMigrationStep());
response.add(linkTo(methodOn(MgmtDistributionSetRestApi.class).getDistributionSet(response.getId()))
.withSelfRel().expand());
response.add(linkTo(methodOn(MgmtDistributionSetRestApi.class).getDistributionSet(response.getId())).withSelfRel().expand());
return response;
}
@@ -102,7 +114,7 @@ public final class MgmtDistributionSetMapper {
return result;
}
public static MgmtTargetAssignmentResponseBody toResponse(final List<DistributionSetAssignmentResult> dsAssignmentResults) {
public MgmtTargetAssignmentResponseBody toResponse(final List<DistributionSetAssignmentResult> dsAssignmentResults) {
final MgmtTargetAssignmentResponseBody result = new MgmtTargetAssignmentResponseBody();
final int alreadyAssigned = dsAssignmentResults.stream()
.mapToInt(DistributionSetAssignmentResult::getAlreadyAssigned).sum();
@@ -115,7 +127,7 @@ public final class MgmtDistributionSetMapper {
return result;
}
public static List<MgmtDistributionSet> toResponseDistributionSets(final Collection<DistributionSet> sets) {
public static List<MgmtDistributionSet> toResponseDistributionSets(final Collection<? extends DistributionSet> sets) {
if (sets == null) {
return Collections.emptyList();
}
@@ -123,6 +135,16 @@ public final class MgmtDistributionSetMapper {
return new ResponseList<>(sets.stream().map(MgmtDistributionSetMapper::toResponse).toList());
}
public static List<DistributionSetTagManagement.Create> mapTagFromRequest(final Collection<MgmtTagRequestBodyPut> tags) {
return tags.stream()
.map(tagRest -> DistributionSetTagManagement.Create.builder()
.name(tagRest.getName())
.description(tagRest.getDescription()).colour(tagRest.getColour())
.build())
.map(DistributionSetTagManagement.Create.class::cast)
.toList();
}
public static MgmtMetadata toResponseDsMetadata(final String key, String value) {
final MgmtMetadata metadataRest = new MgmtMetadata();
metadataRest.setKey(key);
@@ -140,7 +162,7 @@ public final class MgmtDistributionSetMapper {
return metadata.entrySet().stream().map(e -> toResponseDsMetadata(e.getKey(), e.getValue())).toList();
}
public static List<MgmtDistributionSet> toResponseFromDsList(final List<DistributionSet> sets) {
public static List<MgmtDistributionSet> toResponseFromDsList(final List<? extends DistributionSet> sets) {
if (sets == null) {
return Collections.emptyList();
}
@@ -148,14 +170,8 @@ public final class MgmtDistributionSetMapper {
return sets.stream().map(MgmtDistributionSetMapper::toResponse).toList();
}
/**
* {@link MgmtDistributionSetRequestBodyPost} to {@link DistributionSet}.
*
* @param dsRest to convert
* @return converted {@link DistributionSet}
*/
private static DistributionSetCreate fromRequest(final MgmtDistributionSetRequestBodyPost dsRest, final EntityFactory entityFactory) {
final List<Long> modules = new ArrayList<>();
private DistributionSetManagement.Create fromRequest(final MgmtDistributionSetRequestBodyPost dsRest) {
final Set<Long> modules = new HashSet<>();
if (dsRest.getOs() != null) {
modules.add(dsRest.getOs().getId());
}
@@ -168,8 +184,32 @@ public final class MgmtDistributionSetMapper {
if (dsRest.getModules() != null) {
dsRest.getModules().forEach(module -> modules.add(module.getId()));
}
return entityFactory.distributionSet().create().name(dsRest.getName()).version(dsRest.getVersion())
.description(dsRest.getDescription()).type(dsRest.getType()).modules(modules)
.requiredMigrationStep(dsRest.getRequiredMigrationStep());
return DistributionSetManagement.Create.builder()
.type(Optional.ofNullable(dsRest.getType())
// if the type is supplied the type MUST exist
.map(typeKey -> distributionSetTypeManagement
.findByKey(typeKey)
.orElseThrow(() -> new EntityNotFoundException(DistributionSetType.class, typeKey)))
.map(DistributionSetType.class::cast)
// if here, the type is not supplied, use the default type
.orElseGet(() -> systemManagement.getTenantMetadata().getDefaultDsType()))
.name(dsRest.getName()).version(dsRest.getVersion())
.description(dsRest.getDescription())
.modules(findSoftwareModuleWithExceptionIfNotFound(modules))
.requiredMigrationStep(dsRest.getRequiredMigrationStep())
.build();
}
private Set<? extends SoftwareModule> findSoftwareModuleWithExceptionIfNotFound(final Set<Long> softwareModuleIds) {
if (CollectionUtils.isEmpty(softwareModuleIds)) {
return Collections.emptySet();
}
final List<? extends SoftwareModule> modules = softwareModuleManagement.get(softwareModuleIds);
if (modules.size() < softwareModuleIds.size()) {
throw new EntityNotFoundException(SoftwareModule.class, softwareModuleIds);
}
return new HashSet<>(modules);
}
}

View File

@@ -14,36 +14,47 @@ import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.eclipse.hawkbit.mgmt.json.model.distributionsettype.MgmtDistributionSetType;
import org.eclipse.hawkbit.mgmt.json.model.distributionsettype.MgmtDistributionSetTypeRequestBodyPost;
import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleTypeAssignment;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtDistributionSetTypeRestApi;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.builder.DistributionSetTypeCreate;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.rest.json.model.ResponseList;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
/**
* A mapper which maps repository model to RESTful model representation and back.
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Service
public final class MgmtDistributionSetTypeMapper {
public static List<DistributionSetTypeCreate> smFromRequest(final EntityFactory entityFactory, final Collection<MgmtDistributionSetTypeRequestBodyPost> smTypesRest) {
private final SoftwareModuleTypeManagement<? extends SoftwareModuleType> softwareModuleTypeManagement;
MgmtDistributionSetTypeMapper(final SoftwareModuleTypeManagement<? extends SoftwareModuleType> softwareModuleTypeManagement) {
this.softwareModuleTypeManagement = softwareModuleTypeManagement;
}
public List<DistributionSetTypeManagement.Create> smFromRequest(final Collection<MgmtDistributionSetTypeRequestBodyPost> smTypesRest) {
if (smTypesRest == null) {
return Collections.emptyList();
}
return smTypesRest.stream().map(smRest -> fromRequest(entityFactory, smRest)).toList();
return smTypesRest.stream().map(this::fromRequest).toList();
}
public static List<MgmtDistributionSetType> toListResponse(final Collection<DistributionSetType> types) {
public static List<MgmtDistributionSetType> toListResponse(final Collection<? extends DistributionSetType> types) {
if (types == null) {
return Collections.emptyList();
}
@@ -71,22 +82,32 @@ public final class MgmtDistributionSetTypeMapper {
.withRel(MgmtRestConstants.DISTRIBUTIONSETTYPE_V1_OPTIONAL_MODULES).expand());
}
private static DistributionSetTypeCreate fromRequest(final EntityFactory entityFactory,
final MgmtDistributionSetTypeRequestBodyPost smsRest) {
return entityFactory.distributionSetType().create().key(smsRest.getKey()).name(smsRest.getName())
private DistributionSetTypeManagement.Create fromRequest(final MgmtDistributionSetTypeRequestBodyPost smsRest) {
return DistributionSetTypeManagement.Create.builder()
.key(smsRest.getKey()).name(smsRest.getName())
.description(smsRest.getDescription()).colour(smsRest.getColour())
.mandatory(getMandatoryModules(smsRest)).optional(getOptionalModules(smsRest));
.mandatoryModuleTypes(getModules(smsRest.getMandatorymodules()))
.optionalModuleTypes(getModules(smsRest.getOptionalmodules()))
.build();
}
private static Collection<Long> getMandatoryModules(final MgmtDistributionSetTypeRequestBodyPost smsRest) {
return Optional.ofNullable(smsRest.getMandatorymodules())
.map(modules -> modules.stream().map(MgmtSoftwareModuleTypeAssignment::getId).toList())
.orElse(Collections.emptyList());
private Set<? extends SoftwareModuleType> getModules(final List<MgmtSoftwareModuleTypeAssignment> moduleAssignments) {
return Optional.ofNullable(moduleAssignments)
.map(modules -> modules.stream().map(MgmtSoftwareModuleTypeAssignment::getId).collect(Collectors.toSet()))
.map(this::findSoftwareModuleTypeWithExceptionIfNotFound)
.orElse(Collections.emptySet());
}
private static Collection<Long> getOptionalModules(final MgmtDistributionSetTypeRequestBodyPost smsRest) {
return Optional.ofNullable(smsRest.getOptionalmodules())
.map(modules -> modules.stream().map(MgmtSoftwareModuleTypeAssignment::getId).toList())
.orElse(Collections.emptyList());
private Set<? extends SoftwareModuleType> findSoftwareModuleTypeWithExceptionIfNotFound(final Collection<Long> softwareModuleTypeId) {
if (CollectionUtils.isEmpty(softwareModuleTypeId)) {
return Collections.emptySet();
}
final List<? extends SoftwareModuleType> module = softwareModuleTypeManagement.get(softwareModuleTypeId);
if (module.size() < softwareModuleTypeId.size()) {
throw new EntityNotFoundException(SoftwareModuleType.class, softwareModuleTypeId);
}
return new HashSet<>(module);
}
}

View File

@@ -16,12 +16,8 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.eclipse.hawkbit.repository.artifact.urlhandler.ApiType;
import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrl;
import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandler;
import org.eclipse.hawkbit.repository.artifact.urlhandler.URLPlaceholder;
import jakarta.validation.ValidationException;
import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifact;
import org.eclipse.hawkbit.mgmt.json.model.artifact.MgmtArtifactHash;
import org.eclipse.hawkbit.mgmt.json.model.softwaremodule.MgmtSoftwareModule;
@@ -33,22 +29,36 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtSoftwareModuleTypeRestApi;
import org.eclipse.hawkbit.mgmt.rest.resource.MgmtDownloadArtifactResource;
import org.eclipse.hawkbit.mgmt.rest.resource.MgmtSoftwareModuleResource;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.SystemManagement;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleCreate;
import org.eclipse.hawkbit.repository.artifact.urlhandler.ApiType;
import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrl;
import org.eclipse.hawkbit.repository.artifact.urlhandler.ArtifactUrlHandler;
import org.eclipse.hawkbit.repository.artifact.urlhandler.URLPlaceholder;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.Artifact;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.rest.json.model.ResponseList;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder;
import org.springframework.stereotype.Service;
/**
* A mapper which maps repository model to RESTful model representation and back.
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Service
public final class MgmtSoftwareModuleMapper {
private final SoftwareModuleTypeManagement<? extends SoftwareModuleType> softwareModuleTypeManagement;
MgmtSoftwareModuleMapper(final SoftwareModuleTypeManagement<? extends SoftwareModuleType> softwareModuleTypeManagement) {
this.softwareModuleTypeManagement = softwareModuleTypeManagement;
}
public static List<SoftwareModuleMetadataCreate> fromRequestSwMetadata(
final EntityFactory entityFactory, final Long softwareModuleId, final Collection<MgmtSoftwareModuleMetadata> metadata) {
if (metadata == null) {
@@ -62,16 +72,15 @@ public final class MgmtSoftwareModuleMapper {
.toList();
}
public static List<SoftwareModuleCreate> smFromRequest(
final EntityFactory entityFactory, final Collection<MgmtSoftwareModuleRequestBodyPost> smsRest) {
public List<SoftwareModuleManagement.Create> smFromRequest(final Collection<MgmtSoftwareModuleRequestBodyPost> smsRest) {
if (smsRest == null) {
return Collections.emptyList();
}
return smsRest.stream().map(smRest -> fromRequest(entityFactory, smRest)).toList();
return smsRest.stream().map(this::fromRequest).toList();
}
public static List<MgmtSoftwareModule> toResponse(final Collection<SoftwareModule> softwareModules) {
public static List<MgmtSoftwareModule> toResponse(final Collection<? extends SoftwareModule> softwareModules) {
if (softwareModules == null) {
return Collections.emptyList();
}
@@ -159,10 +168,21 @@ public final class MgmtSoftwareModuleMapper {
urls.forEach(entry -> response.add(Link.of(entry.getRef()).withRel(entry.getRel()).expand()));
}
private static SoftwareModuleCreate fromRequest(final EntityFactory entityFactory,
private SoftwareModuleManagement.Create fromRequest(
final MgmtSoftwareModuleRequestBodyPost smsRest) {
return entityFactory.softwareModule().create().type(smsRest.getType()).name(smsRest.getName())
.version(smsRest.getVersion()).description(smsRest.getDescription()).vendor(smsRest.getVendor())
.encrypted(smsRest.isEncrypted());
return SoftwareModuleManagement.Create.builder()
.type(getSoftwareModuleTypeFromKeyString(smsRest.getType()))
.name(smsRest.getName()).version(smsRest.getVersion()).description(smsRest.getDescription()).vendor(smsRest.getVendor())
.encrypted(smsRest.isEncrypted())
.build();
}
private SoftwareModuleType getSoftwareModuleTypeFromKeyString(final String type) {
if (type == null) {
throw new ValidationException("type cannot be null");
}
return softwareModuleTypeManagement.findByKey(type.trim())
.orElseThrow(() -> new EntityNotFoundException(SoftwareModuleType.class, type.trim()));
}
}

View File

@@ -21,8 +21,7 @@ import lombok.NoArgsConstructor;
import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleType;
import org.eclipse.hawkbit.mgmt.json.model.softwaremoduletype.MgmtSoftwareModuleTypeRequestBodyPost;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtSoftwareModuleTypeRestApi;
import org.eclipse.hawkbit.repository.EntityFactory;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeCreate;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.rest.json.model.ResponseList;
@@ -32,16 +31,16 @@ import org.eclipse.hawkbit.rest.json.model.ResponseList;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class MgmtSoftwareModuleTypeMapper {
public static List<SoftwareModuleTypeCreate> smFromRequest(final EntityFactory entityFactory,
public static List<SoftwareModuleTypeManagement.Create> smFromRequest(
final Collection<MgmtSoftwareModuleTypeRequestBodyPost> smTypesRest) {
if (smTypesRest == null) {
return Collections.emptyList();
}
return smTypesRest.stream().map(smRest -> fromRequest(entityFactory, smRest)).toList();
return smTypesRest.stream().map(MgmtSoftwareModuleTypeMapper::fromRequest).toList();
}
public static List<MgmtSoftwareModuleType> toTypesResponse(final Collection<SoftwareModuleType> types) {
public static List<MgmtSoftwareModuleType> toTypesResponse(final Collection<? extends SoftwareModuleType> types) {
if (types == null) {
return Collections.emptyList();
}
@@ -62,10 +61,11 @@ public final class MgmtSoftwareModuleTypeMapper {
return result;
}
private static SoftwareModuleTypeCreate fromRequest(final EntityFactory entityFactory,
final MgmtSoftwareModuleTypeRequestBodyPost smsRest) {
return entityFactory.softwareModuleType().create().key(smsRest.getKey()).name(smsRest.getName())
private static SoftwareModuleTypeManagement.Create fromRequest(final MgmtSoftwareModuleTypeRequestBodyPost smsRest) {
return SoftwareModuleTypeManagement.Create.builder()
.key(smsRest.getKey()).name(smsRest.getName())
.description(smsRest.getDescription()).colour(smsRest.getColour())
.maxAssignments(smsRest.getMaxAssignments());
.maxAssignments(smsRest.getMaxAssignments())
.build();
}
}

View File

@@ -70,7 +70,7 @@ public final class MgmtTagMapper {
.expand());
}
public static List<MgmtTag> toResponseDistributionSetTag(final List<DistributionSetTag> distributionSetTags) {
public static List<MgmtTag> toResponseDistributionSetTag(final Collection<? extends DistributionSetTag> distributionSetTags) {
final List<MgmtTag> tagsRest = new ArrayList<>();
if (distributionSetTags == null) {
return tagsRest;
@@ -106,7 +106,7 @@ public final class MgmtTagMapper {
.withRel("assignedDistributionSets").expand());
}
public static List<TagCreate> mapTagFromRequest(final EntityFactory entityFactory, final Collection<MgmtTagRequestBodyPut> tags) {
public static List<TagCreate<Tag>> mapTagFromRequest(final EntityFactory entityFactory, final Collection<MgmtTagRequestBodyPut> tags) {
return tags.stream()
.map(tagRest -> entityFactory.tag().create().name(tagRest.getName())
.description(tagRest.getDescription()).colour(tagRest.getColour()))

View File

@@ -19,7 +19,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.
import java.util.Collections;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.rest.util.JsonBuilder;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
import org.junit.jupiter.api.BeforeEach;
@@ -35,22 +35,21 @@ import org.springframework.test.web.servlet.MvcResult;
/**
* With Spring Boot 2.2.x the default charset encoding became deprecated. In hawkBit we want to keep the old behavior for now and still
* return the charset in the response, which is achieved through enabling {@link Encoding} via properties.
*/
@SpringBootTest(properties = { "server.servlet.encoding.charset=UTF-8", "server.servlet.encoding.force=true" })
@Import(HttpEncodingAutoConfiguration.class)
/**
* <p/>
* Feature: Component Tests - Management API<br/>
* Story: Response Content-Type
*/
@SpringBootTest(properties = { "server.servlet.encoding.charset=UTF-8", "server.servlet.encoding.force=true" })
@Import(HttpEncodingAutoConfiguration.class)
@SuppressWarnings("java:S1874") // TODO for compatibility, to be checked if we really want to do that
public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest {
private final String dsName = "DS-ö";
private DistributionSet ds;
private static final String DS_NAME = "DS-ö";
private DistributionSetManagement.Create dsCreate;
@BeforeEach
public void setupBeforeTest() {
ds = testdataFactory.generateDistributionSet(dsName);
dsCreate = DistributionSetManagement.Create.builder().type(defaultDsType()).name(DS_NAME).version("1.0").build();
}
/**
@@ -60,11 +59,11 @@ public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest {
void postDistributionSet_ContentTypeJsonUtf8_woAccept() throws Exception {
final MvcResult result = mvc.perform(
post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING).content(JsonBuilder.distributionSets(
Collections.singletonList(ds)))
Collections.singletonList(dsCreate)))
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isCreated())
.andExpect(jsonPath("[0]name", equalTo(dsName)))
.andExpect(jsonPath("[0]name", equalTo(DS_NAME)))
.andReturn();
assertEquals(MediaTypes.HAL_JSON_VALUE + ";charset=UTF-8", getResponseHeaderContentType(result));
@@ -77,11 +76,11 @@ public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest {
void postDistributionSet_ContentTypeJsonUtf8_wAcceptJson() throws Exception {
final MvcResult result = mvc.perform(
post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING).content(JsonBuilder.distributionSets(
Collections.singletonList(ds)))
Collections.singletonList(dsCreate)))
.contentType(MediaType.APPLICATION_JSON_UTF8).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isCreated())
.andExpect(jsonPath("[0]name", equalTo(dsName)))
.andExpect(jsonPath("[0]name", equalTo(DS_NAME)))
.andReturn();
assertEquals(MediaType.APPLICATION_JSON_UTF8_VALUE, getResponseHeaderContentType(result));
@@ -94,11 +93,11 @@ public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest {
void postDistributionSet_ContentTypeJsonUtf8_wAcceptJsonUtf8() throws Exception {
final MvcResult result = mvc.perform(
post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING).content(JsonBuilder.distributionSets(
Collections.singletonList(ds)))
Collections.singletonList(dsCreate)))
.contentType(MediaType.APPLICATION_JSON_UTF8).accept(MediaType.APPLICATION_JSON_UTF8))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isCreated())
.andExpect(jsonPath("[0]name", equalTo(dsName)))
.andExpect(jsonPath("[0]name", equalTo(DS_NAME)))
.andReturn();
assertEquals(MediaType.APPLICATION_JSON_UTF8_VALUE, getResponseHeaderContentType(result));
@@ -111,11 +110,11 @@ public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest {
void postDistributionSet_ContentTypeJsonUtf8_wAcceptHalJson() throws Exception {
final MvcResult result = mvc.perform(
post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING).content(JsonBuilder.distributionSets(
Collections.singletonList(ds)))
Collections.singletonList(dsCreate)))
.contentType(MediaType.APPLICATION_JSON_UTF8).accept(MediaTypes.HAL_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isCreated())
.andExpect(jsonPath("[0]name", equalTo(dsName)))
.andExpect(jsonPath("[0]name", equalTo(DS_NAME)))
.andReturn();
assertEquals(MediaTypes.HAL_JSON_VALUE + ";charset=UTF-8", getResponseHeaderContentType(result));
@@ -128,11 +127,11 @@ public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest {
void postDistributionSet_ContentTypeJson_woAccept() throws Exception {
final MvcResult result = mvc.perform(
post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING).content(JsonBuilder.distributionSets(
Collections.singletonList(ds)))
Collections.singletonList(dsCreate)))
.contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isCreated())
.andExpect(jsonPath("[0]name", equalTo(dsName)))
.andExpect(jsonPath("[0]name", equalTo(DS_NAME)))
.andReturn();
assertEquals(MediaTypes.HAL_JSON_VALUE + ";charset=UTF-8", getResponseHeaderContentType(result));
@@ -145,11 +144,11 @@ public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest {
void postDistributionSet_ContentTypeJson_wAcceptJson() throws Exception {
final MvcResult result = mvc.perform(
post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING).content(JsonBuilder.distributionSets(
Collections.singletonList(ds)))
Collections.singletonList(dsCreate)))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isCreated())
.andExpect(jsonPath("[0]name", equalTo(dsName)))
.andExpect(jsonPath("[0]name", equalTo(DS_NAME)))
.andReturn();
assertEquals(MediaType.APPLICATION_JSON_UTF8_VALUE, getResponseHeaderContentType(result));
@@ -161,11 +160,11 @@ public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest {
@Test
void postDistributionSet_ContentTypeJson_wAcceptJsonUtf8() throws Exception {
final MvcResult result = mvc.perform(post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING)
.content(JsonBuilder.distributionSets(Collections.singletonList(ds))).contentType(MediaType.APPLICATION_JSON)
.content(JsonBuilder.distributionSets(Collections.singletonList(dsCreate))).contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON_UTF8))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isCreated())
.andExpect(jsonPath("[0]name", equalTo(dsName)))
.andExpect(jsonPath("[0]name", equalTo(DS_NAME)))
.andReturn();
assertEquals(MediaType.APPLICATION_JSON_UTF8_VALUE, getResponseHeaderContentType(result));
@@ -177,11 +176,11 @@ public class MgmtContentTypeTest extends AbstractManagementApiIntegrationTest {
@Test
void postDistributionSet_ContentTypeJson_wAcceptHalJson() throws Exception {
final MvcResult result = mvc.perform(post(MgmtRestConstants.DISTRIBUTIONSET_V1_REQUEST_MAPPING)
.content(JsonBuilder.distributionSets(Collections.singletonList(ds))).contentType(MediaType.APPLICATION_JSON)
.content(JsonBuilder.distributionSets(Collections.singletonList(dsCreate))).contentType(MediaType.APPLICATION_JSON)
.accept(MediaTypes.HAL_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isCreated())
.andExpect(jsonPath("[0]name", equalTo(dsName)))
.andExpect(jsonPath("[0]name", equalTo(DS_NAME)))
.andReturn();
assertEquals(MediaTypes.HAL_JSON_VALUE + ";charset=UTF-8", getResponseHeaderContentType(result));

View File

@@ -41,6 +41,7 @@ import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtActionType;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.mgmt.rest.resource.util.ResourceUtility;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.jpa.repository.ActionRepository;
@@ -359,8 +360,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
void createDsFromAlreadyMarkedAsDeletedType() throws Exception {
final SoftwareModule softwareModule = testdataFactory.createSoftwareModule("exampleKey");
final DistributionSetType type = testdataFactory.findOrCreateDistributionSetType(
"testKey", "testType", Collections.singletonList(softwareModule.getType()),
Collections.singletonList(softwareModule.getType()));
"testKey", "testType", List.of(softwareModule.getType()), List.of());
final DistributionSet ds = testdataFactory.createDistributionSet("dsName", "dsVersion", type,
Collections.singletonList(softwareModule));
final Target target = testdataFactory.createTarget("exampleControllerId");
@@ -371,7 +371,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
distributionSetTypeManagement.delete(type.getId());
// check if the ds type is marked as deleted
final Optional<DistributionSetType> opt = distributionSetTypeManagement.findByKey(type.getKey());
final Optional<? extends DistributionSetType> opt = distributionSetTypeManagement.findByKey(type.getKey());
if (opt.isEmpty()) {
throw new AssertionError("The Optional object of distribution set type should not be empty!");
}
@@ -379,7 +379,7 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
Assert.isTrue(reloaded.isDeleted(), "Distribution Set Type not marked as deleted!");
//request for ds creation of type which is already marked as deleted - should return bad request
final DistributionSet generated = testdataFactory.generateDistributionSet(
final DistributionSetManagement.Create generated = testdataFactory.generateDistributionSet(
"stanTest", "2", reloaded, Collections.singletonList(softwareModule));
final MvcResult mvcResult = mvc
.perform(post("/rest/v1/distributionsets")
@@ -854,8 +854,8 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
assertThat(distributionSetManagement.findByCompleted(true, PAGE)).isEmpty();
DistributionSet set = testdataFactory.createDistributionSet("one");
set = distributionSetManagement.update(entityFactory.distributionSet().update(set.getId())
.version("anotherVersion").requiredMigrationStep(true));
set = distributionSetManagement.update(DistributionSetManagement.Update.builder().id(set.getId())
.version("anotherVersion").requiredMigrationStep(true).build());
// load also lazy stuff
set = distributionSetManagement.getWithDetails(set.getId()).get();
@@ -881,9 +881,9 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
.andExpect(jsonPath("$.content.[0].lastModifiedAt", equalTo(set.getLastModifiedAt())))
.andExpect(jsonPath("$.content.[0].version", equalTo(set.getVersion())))
.andExpect(jsonPath("$.content.[0].modules.[?(@.type=='" + runtimeType.getKey() + "')].id",
contains(set.findFirstModuleByType(runtimeType).get().getId().intValue())))
contains(findFirstModuleByType(set, runtimeType).get().getId().intValue())))
.andExpect(jsonPath("$.content.[0].modules.[?(@.type=='" + appType.getKey() + "')].id",
contains(set.findFirstModuleByType(appType).get().getId().intValue())))
contains(findFirstModuleByType(set, appType).get().getId().intValue())))
.andExpect(jsonPath("$.content.[0].modules.[?(@.type=='" + osType.getKey() + "')].id",
contains(getOsModule(set).intValue())));
}
@@ -916,9 +916,9 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
.andExpect(jsonPath("$.lastModifiedAt", equalTo(set.getLastModifiedAt())))
.andExpect(jsonPath("$.version", equalTo(set.getVersion())))
.andExpect(jsonPath("$.modules.[?(@.type=='" + runtimeType.getKey() + "')].id",
contains(set.findFirstModuleByType(runtimeType).get().getId().intValue())))
contains(findFirstModuleByType(set, runtimeType).get().getId().intValue())))
.andExpect(jsonPath("$.modules.[?(@.type=='" + appType.getKey() + "')].id",
contains(set.findFirstModuleByType(appType).get().getId().intValue())))
contains(findFirstModuleByType(set, appType).get().getId().intValue())))
.andExpect(jsonPath("$.modules.[?(@.type=='" + osType.getKey() + "')].id",
contains(getOsModule(set).intValue())));
@@ -935,26 +935,19 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
final SoftwareModule jvm = testdataFactory.createSoftwareModule(TestdataFactory.SM_TYPE_RT);
final SoftwareModule os = testdataFactory.createSoftwareModule(TestdataFactory.SM_TYPE_OS);
DistributionSet one = testdataFactory.generateDistributionSet("one", "one", standardDsType,
Arrays.asList(os, jvm, ah));
DistributionSet two = testdataFactory.generateDistributionSet("two", "two", standardDsType,
Arrays.asList(os, jvm, ah));
DistributionSet three = testdataFactory.generateDistributionSet("three", "three", standardDsType,
Arrays.asList(os, jvm, ah), true);
final long current = System.currentTimeMillis();
final MvcResult mvcResult = executeMgmtTargetPost(one, two, three);
final MvcResult mvcResult = executeMgmtTargetPost(
testdataFactory.generateDistributionSet("one", "one", standardDsType, Arrays.asList(os, jvm, ah)),
testdataFactory.generateDistributionSet("two", "two", standardDsType, Arrays.asList(os, jvm, ah)),
testdataFactory.generateDistributionSet("three", "three", standardDsType, Arrays.asList(os, jvm, ah), true));
one = distributionSetManagement
.getWithDetails(distributionSetManagement.findByRsql("name==one", PAGE).getContent().get(0).getId())
.get();
two = distributionSetManagement
.getWithDetails(distributionSetManagement.findByRsql("name==two", PAGE).getContent().get(0).getId())
.get();
three = distributionSetManagement
.getWithDetails(distributionSetManagement.findByRsql("name==three", PAGE).getContent().get(0).getId())
.get();
final DistributionSet one = distributionSetManagement
.getWithDetails(distributionSetManagement.findByRsql("name==one", PAGE).getContent().get(0).getId()).orElseThrow();
final DistributionSet two = distributionSetManagement
.getWithDetails(distributionSetManagement.findByRsql("name==two", PAGE).getContent().get(0).getId()).orElseThrow();
final DistributionSet three = distributionSetManagement
.getWithDetails(distributionSetManagement.findByRsql("name==three", PAGE).getContent().get(0).getId()).orElseThrow();
assertThat((Object) JsonPath.compile("[0]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
.hasToString("http://localhost/rest/v1/distributionsets/" + one.getId());
@@ -1058,8 +1051,11 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
final DistributionSet set = testdataFactory.createDistributionSet("one");
assertThat(distributionSetManagement.count()).isEqualTo(1);
final String body = new JSONObject().put("version", "anotherVersion").put("requiredMigrationStep", true)
.put("deleted", true).toString();
final String body = new JSONObject()
.put("version", "anotherVersion")
.put("requiredMigrationStep", true)
.put("deleted", true)
.toString();
mvc.perform(put("/rest/v1/distributionsets/{dsId}", set.getId()).content(body)
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
@@ -1112,8 +1108,12 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
void invalidRequestsOnDistributionSetsResource() throws Exception {
final DistributionSet set = testdataFactory.createDistributionSet("one");
final List<DistributionSet> sets = new ArrayList<>();
sets.add(set);
final List<DistributionSetManagement.Create> sets = new ArrayList<>();
sets.add(DistributionSetManagement.Create.builder()
.type(set.getType())
.name(set.getName())
.version(set.getVersion())
.build());
// SM does not exist
mvc.perform(get("/rest/v1/distributionsets/12345678"))
@@ -1135,13 +1135,14 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
final DistributionSet missingName = entityFactory.distributionSet().create().build();
final DistributionSetManagement.Create missingName = DistributionSetManagement.Create.builder().build();
mvc.perform(post("/rest/v1/distributionsets").content(JsonBuilder.distributionSets(Collections.singletonList(missingName)))
.contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
final DistributionSet toLongName = testdataFactory.generateDistributionSet(randomString(NamedEntity.NAME_MAX_SIZE + 1));
final DistributionSetManagement.Create toLongName =
testdataFactory.generateDistributionSet(randomString(NamedEntity.NAME_MAX_SIZE + 1));
mvc.perform(post("/rest/v1/distributionsets").content(JsonBuilder.distributionSets(Collections.singletonList(toLongName)))
.contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
@@ -1165,7 +1166,6 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
mvc.perform(delete("/rest/v1/distributionsets"))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isMethodNotAllowed());
}
/**
@@ -1349,7 +1349,10 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
final int amount = 10;
testdataFactory.createDistributionSets(amount);
distributionSetManagement
.create(entityFactory.distributionSet().create().name("incomplete").version("2").type("os"));
.create(DistributionSetManagement.Create.builder()
.type(distributionSetTypeManagement.findByKey("os").orElseThrow())
.name("incomplete").version("2")
.build());
final String rsqlFindLikeDs1OrDs2 = "complete==" + Boolean.TRUE;
@@ -1820,8 +1823,10 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
.create(entityFactory.targetFilterQuery().create().name(filterNamePrefix + "c").query("name==y"));
}
private MvcResult executeMgmtTargetPost(final DistributionSet one, final DistributionSet two,
final DistributionSet three) throws Exception {
private MvcResult executeMgmtTargetPost(
final DistributionSetManagement.Create one,
final DistributionSetManagement.Create two,
final DistributionSetManagement.Create three) throws Exception {
return mvc
.perform(post("/rest/v1/distributionsets")
.content(JsonBuilder.distributionSets(Arrays.asList(one, two, three)))
@@ -1835,13 +1840,13 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
.andExpect(jsonPath("[0]createdBy", equalTo("uploadTester")))
.andExpect(jsonPath("[0]version", equalTo(one.getVersion())))
.andExpect(jsonPath("[0]complete", equalTo(Boolean.TRUE)))
.andExpect(jsonPath("[0]requiredMigrationStep", equalTo(one.isRequiredMigrationStep())))
.andExpect(jsonPath("[0]requiredMigrationStep", equalTo(one.getRequiredMigrationStep())))
.andExpect(jsonPath("[0].modules.[?(@.type=='" + runtimeType.getKey() + "')].id",
contains(one.findFirstModuleByType(runtimeType).get().getId().intValue())))
contains(findFirstModuleByType(one, runtimeType).get().getId().intValue())))
.andExpect(jsonPath("[0].modules.[?(@.type=='" + appType.getKey() + "')].id",
contains(one.findFirstModuleByType(appType).get().getId().intValue())))
contains(findFirstModuleByType(one, appType).get().getId().intValue())))
.andExpect(jsonPath("[0].modules.[?(@.type=='" + osType.getKey() + "')].id",
contains(one.findFirstModuleByType(osType).get().getId().intValue())))
contains(findFirstModuleByType(one, osType).get().getId().intValue())))
.andExpect(jsonPath("[1]name", equalTo(two.getName())))
.andExpect(jsonPath("[1]description", equalTo(two.getDescription())))
.andExpect(jsonPath("[1]complete", equalTo(Boolean.TRUE)))
@@ -1849,12 +1854,12 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
.andExpect(jsonPath("[1]createdBy", equalTo("uploadTester")))
.andExpect(jsonPath("[1]version", equalTo(two.getVersion())))
.andExpect(jsonPath("[1].modules.[?(@.type=='" + runtimeType.getKey() + "')].id",
contains(two.findFirstModuleByType(runtimeType).get().getId().intValue())))
contains(findFirstModuleByType(two, runtimeType).get().getId().intValue())))
.andExpect(jsonPath("[1].modules.[?(@.type=='" + appType.getKey() + "')].id",
contains(two.findFirstModuleByType(appType).get().getId().intValue())))
contains(findFirstModuleByType(two, appType).get().getId().intValue())))
.andExpect(jsonPath("[1].modules.[?(@.type=='" + osType.getKey() + "')].id",
contains(two.findFirstModuleByType(osType).get().getId().intValue())))
.andExpect(jsonPath("[1]requiredMigrationStep", equalTo(two.isRequiredMigrationStep())))
contains(findFirstModuleByType(two, osType).get().getId().intValue())))
.andExpect(jsonPath("[1]requiredMigrationStep", equalTo(two.getRequiredMigrationStep())))
.andExpect(jsonPath("[2]name", equalTo(three.getName())))
.andExpect(jsonPath("[2]description", equalTo(three.getDescription())))
.andExpect(jsonPath("[2]complete", equalTo(Boolean.TRUE)))
@@ -1862,12 +1867,12 @@ class MgmtDistributionSetResourceTest extends AbstractManagementApiIntegrationTe
.andExpect(jsonPath("[2]createdBy", equalTo("uploadTester")))
.andExpect(jsonPath("[2]version", equalTo(three.getVersion())))
.andExpect(jsonPath("[2].modules.[?(@.type=='" + runtimeType.getKey() + "')].id",
contains(three.findFirstModuleByType(runtimeType).get().getId().intValue())))
contains(findFirstModuleByType(three, runtimeType).get().getId().intValue())))
.andExpect(jsonPath("[2].modules.[?(@.type=='" + appType.getKey() + "')].id",
contains(three.findFirstModuleByType(appType).get().getId().intValue())))
contains(findFirstModuleByType(three, appType).get().getId().intValue())))
.andExpect(jsonPath("[2].modules.[?(@.type=='" + osType.getKey() + "')].id",
contains(three.findFirstModuleByType(osType).get().getId().intValue())))
.andExpect(jsonPath("[2]requiredMigrationStep", equalTo(three.isRequiredMigrationStep())))
contains(findFirstModuleByType(three, osType).get().getId().intValue())))
.andExpect(jsonPath("[2]requiredMigrationStep", equalTo(three.getRequiredMigrationStep())))
.andReturn();
}

View File

@@ -353,7 +353,7 @@ class MgmtDistributionSetTagResourceTest extends AbstractManagementApiIntegratio
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
final List<DistributionSet> updated = distributionSetManagement.findByTag(tag.getId(), PAGE).getContent();
final List<? extends DistributionSet> updated = distributionSetManagement.findByTag(tag.getId(), PAGE).getContent();
assertThat(updated.stream().map(DistributionSet::getId).toList()).containsOnly(set.getId());
}
@@ -375,7 +375,7 @@ class MgmtDistributionSetTagResourceTest extends AbstractManagementApiIntegratio
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
final List<DistributionSet> updated = distributionSetManagement.findByTag(tag.getId(), PAGE).getContent();
final List<? extends DistributionSet> updated = distributionSetManagement.findByTag(tag.getId(), PAGE).getContent();
assertThat(updated.stream().map(DistributionSet::getId).toList())
.containsAll(sets.stream().map(DistributionSet::getId).toList());
}
@@ -402,7 +402,7 @@ class MgmtDistributionSetTagResourceTest extends AbstractManagementApiIntegratio
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
final List<DistributionSet> updated = distributionSetManagement.findByTag(tag.getId(), PAGE).getContent();
final List<? extends DistributionSet> updated = distributionSetManagement.findByTag(tag.getId(), PAGE).getContent();
assertThat(updated.stream().map(DistributionSet::getId).toList())
.containsOnly(assigned.getId());
}
@@ -430,7 +430,7 @@ class MgmtDistributionSetTagResourceTest extends AbstractManagementApiIntegratio
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk());
final List<DistributionSet> updated = distributionSetManagement.findByTag(tag.getId(), PAGE).getContent();
final List<? extends DistributionSet> updated = distributionSetManagement.findByTag(tag.getId(), PAGE).getContent();
assertThat(updated.stream().map(DistributionSet::getId).toList())
.containsOnly(assigned.getId());
}

View File

@@ -27,11 +27,14 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import com.jayway.jsonpath.JsonPath;
import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeCreate;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.NamedEntity;
@@ -59,12 +62,14 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
@WithUser(principal = "uploadTester", allSpPermissions = true)
void getDistributionSetTypes() throws Exception {
DistributionSetType testType = distributionSetTypeManagement.create(
entityFactory.distributionSetType().create()
DistributionSetTypeManagement.Create.builder()
.key("test123")
.name("TestName123")
.description("Desc123")
.colour("col12"));
testType = distributionSetTypeManagement.update(entityFactory.distributionSetType().update(testType.getId()).description("Desc1234"));
.colour("col12")
.build());
testType = distributionSetTypeManagement.update(
DistributionSetTypeManagement.Update.builder().id(testType.getId()).description("Desc1234").build());
// 4 types overall (2 hawkbit tenant default, 1 test default and 1
// generated in this test)
@@ -99,12 +104,14 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
@WithUser(principal = "uploadTester", allSpPermissions = true)
void getDistributionSetTypesSortedByKey() throws Exception {
DistributionSetType testType = distributionSetTypeManagement.create(
entityFactory.distributionSetType().create()
DistributionSetTypeManagement.Create.builder()
.key("zzzzz")
.name("TestName123")
.description("Desc123")
.colour("col12"));
testType = distributionSetTypeManagement.update(entityFactory.distributionSetType().update(testType.getId()).description("Desc1234"));
.colour("col12")
.build());
testType = distributionSetTypeManagement.update(
DistributionSetTypeManagement.Update.builder().id(testType.getId()).description("Desc1234").build());
// descending
mvc.perform(get("/rest/v1/distributionsettypes")
@@ -160,11 +167,12 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
@WithUser(principal = "uploadTester", allSpPermissions = true)
void addMandatoryModuleToDistributionSetType() throws Exception {
DistributionSetType testType = distributionSetTypeManagement.create(
entityFactory.distributionSetType().create()
DistributionSetTypeManagement.Create.builder()
.key("test123")
.name("TestName123")
.description("Desc123")
.colour("col12"));
.colour("col12")
.build());
mvc.perform(post("/rest/v1/distributionsettypes/{dstID}/mandatorymoduletypes", testType.getId())
.contentType(MediaType.APPLICATION_JSON)
@@ -185,11 +193,12 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
@WithUser(principal = "uploadTester", allSpPermissions = true)
void addOptionalModuleToDistributionSetType() throws Exception {
DistributionSetType testType = distributionSetTypeManagement.create(
entityFactory.distributionSetType().create()
DistributionSetTypeManagement.Create.builder()
.key("test123")
.name("TestName123")
.description("Desc123")
.colour("col12"));
.colour("col12")
.build());
mvc.perform(post("/rest/v1/distributionsettypes/{dstID}/optionalmoduletypes", testType.getId())
.contentType(MediaType.APPLICATION_JSON)
@@ -213,15 +222,16 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
final int maxSoftwareModuleTypes = quotaManagement.getMaxSoftwareModuleTypesPerDistributionSetType();
final List<Long> moduleTypeIds = new ArrayList<>();
for (int i = 0; i < maxSoftwareModuleTypes + 1; ++i) {
final SoftwareModuleTypeCreate smCreate = entityFactory.softwareModuleType().create().name("smType_" + i)
.description("smType_" + i).maxAssignments(1).colour("blue").key("smType_" + i);
final SoftwareModuleTypeManagement.Create smCreate = SoftwareModuleTypeManagement.Create.builder().name("smType_" + i)
.description("smType_" + i).maxAssignments(1).colour("blue").key("smType_" + i).build();
moduleTypeIds.add(softwareModuleTypeManagement.create(smCreate).getId());
}
// verify quota enforcement for optional module types
final DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType()
.create().key("testType").name("testType").description("testType").colour("col12"));
final DistributionSetType testType = distributionSetTypeManagement.create(
DistributionSetTypeManagement.Create.builder()
.key("testType").name("testType").description("testType").colour("col12").build());
assertThat(testType.getOptLockRevision()).isEqualTo(1);
for (int i = 0; i < moduleTypeIds.size() - 1; ++i) {
@@ -241,8 +251,9 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
// verify quota enforcement for mandatory module types
final DistributionSetType testType2 = distributionSetTypeManagement.create(entityFactory.distributionSetType()
.create().key("testType2").name("testType2").description("testType2").colour("col12"));
final DistributionSetType testType2 = distributionSetTypeManagement.create(
DistributionSetTypeManagement.Create.builder()
.key("testType2").name("testType2").description("testType2").colour("col12").build());
assertThat(testType2.getOptLockRevision()).isEqualTo(1);
for (int i = 0; i < moduleTypeIds.size() - 1; ++i) {
@@ -385,10 +396,10 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
@Test
@WithUser(principal = "uploadTester", allSpPermissions = true)
void getDistributionSetType() throws Exception {
DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType().create()
.key("test123").name("TestName123").description("Desc123"));
DistributionSetType testType = distributionSetTypeManagement.create(DistributionSetTypeManagement.Create.builder()
.key("test123").name("TestName123").description("Desc123").build());
testType = distributionSetTypeManagement
.update(entityFactory.distributionSetType().update(testType.getId()).description("Desc1234"));
.update(DistributionSetTypeManagement.Update.builder().id(testType.getId()).description("Desc1234").build());
mvc.perform(get("/rest/v1/distributionsettypes/{dstId}", testType.getId()).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
@@ -420,8 +431,9 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
@Test
@WithUser(principal = "uploadTester", allSpPermissions = true)
void deleteDistributionSetTypeUnused() throws Exception {
final DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType()
.create().key("test123").name("TestName123").description("Desc123").colour("col12"));
final DistributionSetType testType = distributionSetTypeManagement.create(
DistributionSetTypeManagement.Create.builder()
.key("test123").name("TestName123").description("Desc123").colour("col12").build());
assertThat(distributionSetTypeManagement.count()).isEqualTo(DEFAULT_DS_TYPES + 1);
@@ -448,11 +460,14 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
@Test
@WithUser(principal = "uploadTester", allSpPermissions = true)
void deleteDistributionSetTypeUsed() throws Exception {
final DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType()
.create().key("test123").name("TestName123").description("Desc123").colour("col12"));
final DistributionSetType testType = distributionSetTypeManagement.create(
DistributionSetTypeManagement.Create.builder()
.key("test123").name("TestName123").description("Desc123").colour("col12").build());
distributionSetManagement.create(entityFactory.distributionSet().create().name("sdfsd").description("dsfsdf")
.version("1").type(testType));
distributionSetManagement.create(DistributionSetManagement.Create.builder()
.type(distributionSetTypeManagement.findByKey(testType.getKey()).orElseThrow())
.name("sdfsd").version("1").description("dsfsdf")
.build());
assertThat(distributionSetTypeManagement.count()).isEqualTo(DEFAULT_DS_TYPES + 1);
assertThat(distributionSetManagement.count()).isEqualTo(1);
@@ -480,8 +495,9 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
*/
@Test
void updateDistributionSetTypeColourDescriptionAndNameUntouched() throws Exception {
final DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType()
.create().key("test123").name("TestName123").description("Desc123").colour("col"));
final DistributionSetType testType = distributionSetTypeManagement.create(
DistributionSetTypeManagement.Create.builder()
.key("test123").name("TestName123").description("Desc123").colour("col").build());
final String body = new JSONObject().put("id", testType.getId()).put("description", "foobardesc")
.put("colour", "updatedColour")
@@ -503,8 +519,9 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
*/
@Test
void updateDistributionSetTypeDescriptionAndColor() throws Exception {
final DistributionSetType testType = distributionSetTypeManagement.update(entityFactory.distributionSetType()
.update(testdataFactory.createDistributionSet().getType().getId()).description("Desc1234"));
final DistributionSetType testType = distributionSetTypeManagement.update(
DistributionSetTypeManagement.Update.builder()
.id(testdataFactory.createDistributionSet().getType().getId()).description("Desc1234").build());
final String body = new JSONObject()
.put("description", "an updated description")
.put("colour", "rgb(106,178,83)").toString();
@@ -522,7 +539,7 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
@Test
void updateDistributionSetTypeDeletedFlag() throws Exception {
final DistributionSetType testType = distributionSetTypeManagement
.create(entityFactory.distributionSetType().create().key("test123").name("TestName123").colour("col"));
.create(DistributionSetTypeManagement.Create.builder().key("test123").name("TestName123").colour("col").build());
final String body = new JSONObject().put("id", testType.getId()).put("deleted", true).toString();
@@ -591,7 +608,7 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
@Test
void invalidRequestsOnDistributionSetTypesResource() throws Exception {
final SoftwareModuleType testSmType = softwareModuleTypeManagement
.create(entityFactory.softwareModuleType().create().key("test123").name("TestName123"));
.create(SoftwareModuleTypeManagement.Create.builder().key("test123").name("TestName123").build());
// DST does not exist
mvc.perform(get("/rest/v1/distributionsettypes/12345678"))
@@ -645,12 +662,15 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
// Modules types at creation time invalid
final DistributionSetType testNewType = entityFactory.distributionSetType().create().key("test123")
.name("TestName123").description("Desc123").colour("col").mandatory(Collections.singletonList(osType.getId()))
.optional(Collections.emptyList()).build();
final DistributionSetTypeManagement.Create testNewType = DistributionSetTypeManagement.Create.builder()
.key("test123")
.name("TestName123").description("Desc123").colour("col")
.mandatoryModuleTypes(Set.of(osType))
.optionalModuleTypes(Collections.emptySet())
.build();
mvc.perform(post("/rest/v1/distributionsettypes")
.content(JsonBuilder.distributionSetTypes(Collections.singletonList(testNewType)))
.content(JsonBuilder.distributionSetTypes(List.of(testNewType)))
.contentType(MediaType.APPLICATION_OCTET_STREAM))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isUnsupportedMediaType());
@@ -672,12 +692,12 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
final DistributionSetType toLongName = entityFactory.distributionSetType().create()
final DistributionSetTypeManagement.Create toLongName = DistributionSetTypeManagement.Create.builder()
.key("test123")
.name(randomString(NamedEntity.NAME_MAX_SIZE + 1))
.build();
mvc.perform(post("/rest/v1/distributionsettypes")
.content(JsonBuilder.distributionSetTypes(Collections.singletonList(toLongName)))
.content(JsonBuilder.distributionSetTypes(List.of(toLongName)))
.contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
@@ -706,9 +726,9 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
@Test
void searchDistributionSetTypeRsql() throws Exception {
distributionSetTypeManagement
.create(entityFactory.distributionSetType().create().key("test123").name("TestName123"));
.create(DistributionSetTypeManagement.Create.builder().key("test123").name("TestName123").build());
distributionSetTypeManagement
.create(entityFactory.distributionSetType().create().key("test1234").name("TestName1234"));
.create(DistributionSetTypeManagement.Create.builder().key("test1234").name("TestName1234").build());
final String rsqlFindLikeDs1OrDs2 = "name==TestName123,name==TestName1234";
@@ -731,17 +751,17 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
assertThat(created2.getOptionalModuleTypes()).containsOnly(osType, runtimeType, appType);
assertThat(created3.getMandatoryModuleTypes()).containsOnly(osType, runtimeType);
assertThat((Object)JsonPath.compile("[0]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
assertThat((Object) JsonPath.compile("[0]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
.hasToString("http://localhost/rest/v1/distributionsettypes/" + created1.getId());
assertThat((Object)JsonPath.compile("[1]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
assertThat((Object) JsonPath.compile("[1]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
.hasToString("http://localhost/rest/v1/distributionsettypes/" + created2.getId());
assertThat((Object)JsonPath.compile("[2]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
assertThat((Object) JsonPath.compile("[2]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
.hasToString("http://localhost/rest/v1/distributionsettypes/" + created3.getId());
assertThat(distributionSetTypeManagement.count()).isEqualTo(7);
}
private MvcResult runPostDistributionSetType(final List<DistributionSetType> types) throws Exception {
private MvcResult runPostDistributionSetType(final List<DistributionSetTypeManagement.Create> types) throws Exception {
return mvc
.perform(post("/rest/v1/distributionsettypes").content(JsonBuilder.distributionSetTypes(types))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
@@ -765,24 +785,32 @@ class MgmtDistributionSetTypeResourceTest extends AbstractManagementApiIntegrati
.andReturn();
}
private List<DistributionSetType> createTestDistributionSetTestTypes() {
private List<DistributionSetTypeManagement.Create> createTestDistributionSetTestTypes() {
assertThat(distributionSetTypeManagement.count()).isEqualTo(DEFAULT_DS_TYPES);
return Arrays.asList(
entityFactory.distributionSetType().create().key("testKey1").name("TestName1").description("Desc1")
.colour("col").mandatory(Collections.singletonList(osType.getId()))
.optional(Collections.singletonList(runtimeType.getId())).build(),
entityFactory.distributionSetType().create().key("testKey2").name("TestName2").description("Desc2")
.colour("col").optional(Arrays.asList(runtimeType.getId(), osType.getId(), appType.getId()))
DistributionSetTypeManagement.Create.builder()
.key("testKey1").name("TestName1").description("Desc1").colour("col")
.mandatoryModuleTypes(Set.of(osType))
.optionalModuleTypes(Set.of(runtimeType))
.build(),
entityFactory.distributionSetType().create().key("testKey3").name("TestName3").description("Desc3")
.colour("col").mandatory(Arrays.asList(runtimeType.getId(), osType.getId())).build());
DistributionSetTypeManagement.Create.builder()
.key("testKey2").name("TestName2").description("Desc2").colour("col")
.optionalModuleTypes(Set.of(runtimeType, osType, appType))
.build(),
DistributionSetTypeManagement.Create.builder()
.key("testKey3").name("TestName3").description("Desc3").colour("col")
.mandatoryModuleTypes(Set.of(runtimeType, osType))
.build());
}
private DistributionSetType generateTestType() {
final DistributionSetType testType = distributionSetTypeManagement.create(entityFactory.distributionSetType()
.create().key("test123").name("TestName123").description("Desc123").colour("col")
.mandatory(Collections.singletonList(osType.getId())).optional(Collections.singletonList(appType.getId())));
final DistributionSetType testType = distributionSetTypeManagement.create(
DistributionSetTypeManagement.Create.builder()
.key("test123").name("TestName123").description("Desc123").colour("col")
.mandatoryModuleTypes(Set.of(osType))
.optionalModuleTypes(Set.of(appType))
.build());
assertThat(testType.getOptLockRevision()).isEqualTo(1);
assertThat(testType.getOptionalModuleTypes()).containsExactly(appType);
assertThat(testType.getMandatoryModuleTypes()).containsExactly(osType);

View File

@@ -45,6 +45,7 @@ import org.eclipse.hawkbit.mgmt.rest.api.MgmtRepresentationMode;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.mgmt.rest.resource.util.ResourceUtility;
import org.eclipse.hawkbit.repository.Constants;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.FileSizeQuotaExceededException;
@@ -101,9 +102,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
void createSMFromAlreadyMarkedAsDeletedType() throws Exception {
final String SM_TYPE = "someSmType";
final SoftwareModule sm = testdataFactory.createSoftwareModule(SM_TYPE);
testdataFactory.findOrCreateDistributionSetType(
"testKey", "testType", Collections.singletonList(sm.getType()),
Collections.singletonList(sm.getType()));
testdataFactory.findOrCreateDistributionSetType("testKey", "testType", List.of(sm.getType()), List.of());
final DistributionSetType type = testdataFactory.findOrCreateDistributionSetType("testKey", "testType");
final DistributionSet ds = testdataFactory.createDistributionSet("name", "version", type, Collections.singletonList(sm));
final Target target = testdataFactory.createTarget("test");
@@ -113,7 +112,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
softwareModuleTypeManagement.delete(sm.getType().getId());
//check if it is marked as deleted
final Optional<SoftwareModuleType> opt = softwareModuleTypeManagement.findByKey(SM_TYPE);
final Optional<? extends SoftwareModuleType> opt = softwareModuleTypeManagement.findByKey(SM_TYPE);
if (opt.isEmpty()) {
throw new AssertionError("The Optional object of software module type should not be empty!");
}
@@ -160,7 +159,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
final int totalMetadata = 4;
final String knownKeyPrefix = "knownKey";
final String knownValuePrefix = "knownValue";
final SoftwareModule module = testdataFactory.createDistributionSet("one").findFirstModuleByType(osType).get();
final SoftwareModule module = findFirstModuleByType(testdataFactory.createDistributionSet("one"), osType).get();
for (int index = 0; index < totalMetadata; index++) {
softwareModuleManagement.updateMetadata(entityFactory.softwareModuleMetadata().create(module.getId())
@@ -182,7 +181,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
final int totalMetadata = 4;
final String knownKeyPrefix = "knownKey";
final String knownValuePrefix = "knownValue";
final SoftwareModule module = testdataFactory.createDistributionSet("one").findFirstModuleByType(osType).get();
final SoftwareModule module = findFirstModuleByType(testdataFactory.createDistributionSet("one"), osType).orElseThrow();
for (int index = 0; index < totalMetadata; index++) {
softwareModuleManagement.updateMetadata(entityFactory.softwareModuleMetadata().create(module.getId())
@@ -206,7 +205,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
// prepare and create metadata
final String knownKey = "knownKey";
final String knownValue = "knownValue";
final SoftwareModule module = testdataFactory.createDistributionSet("one").findFirstModuleByType(osType).get();
final SoftwareModule module = findFirstModuleByType(testdataFactory.createDistributionSet("one"), osType).orElseThrow();
softwareModuleManagement.updateMetadata(
entityFactory.softwareModuleMetadata().create(module.getId()).key(knownKey).value(knownValue));
@@ -217,7 +216,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
}
/**
* Tests the update of software module metadata. It is verfied that only the selected fields for the update are really updated and the modification values are filled (i.e. updated by and at).
* Tests the update of software module metadata. It is verified that only the selected fields for the update are really updated and the modification values are filled (i.e. updated by and at).
*/
@Test
@WithUser(principal = "smUpdateTester", allSpPermissions = true)
@@ -230,13 +229,13 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
final String updateVendor = "newVendor1";
final String updateDescription = "newDescription1";
final SoftwareModule sm = softwareModuleManagement.create(entityFactory.softwareModule()
.create()
final SoftwareModule sm = softwareModuleManagement.create(SoftwareModuleManagement.Create.builder()
.type(osType)
.name(knownSWName)
.version(knownSWVersion)
.description(knownSWDescription)
.vendor(knownSWVendor));
.vendor(knownSWVendor)
.build());
assertThat(sm.getName()).as("Wrong name of the software module").isEqualTo(knownSWName);
@@ -279,7 +278,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
final String knownSWVersion = "version1";
final SoftwareModule sm = softwareModuleManagement.create(
entityFactory.softwareModule().create().type(osType).name(knownSWName).version(knownSWVersion));
SoftwareModuleManagement.Create.builder().type(osType).name(knownSWName).version(knownSWVersion).build());
assertThat(sm.isDeleted()).as("Created software module should not be deleted").isFalse();
@@ -311,7 +310,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
@WithUser(principal = "smUpdateTester", allSpPermissions = true)
void lockSoftwareModule() throws Exception {
final SoftwareModule sm = softwareModuleManagement.create(
entityFactory.softwareModule().create().type(osType).name("name1").version("version1"));
SoftwareModuleManagement.Create.builder().type(osType).name("name1").version("version1").build());
assertThat(sm.isLocked()).as("Created software module should not be locked").isFalse();
// ensures that we are not to fast so that last modified is not set correctly
await().until(() -> sm.getLastModifiedAt() > 0L && sm.getLastModifiedBy() != null);
@@ -342,7 +341,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
@WithUser(principal = "smUpdateTester", allSpPermissions = true)
void unlockSoftwareModule() throws Exception {
final SoftwareModule sm = softwareModuleManagement.create(
entityFactory.softwareModule().create().type(osType).name("name1").version("version1"));
SoftwareModuleManagement.Create.builder().type(osType).name("name1").version("version1").build());
softwareModuleManagement.lock(sm.getId());
assertThat(softwareModuleManagement.get(sm.getId())
.orElseThrow(() -> new EntityNotFoundException(SoftwareModule.class, sm.getId())).isLocked())
@@ -402,10 +401,10 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
mvcResult.getResponse().getContentAsString());
final Long artId = softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getId();
assertThat(artResult.getId()).as("Wrong artifact id").isEqualTo(artId);
assertThat((Object)JsonPath.compile("$._links.self.href").read(mvcResult.getResponse().getContentAsString()))
assertThat((Object) JsonPath.compile("$._links.self.href").read(mvcResult.getResponse().getContentAsString()))
.as("Link contains no self url")
.hasToString("http://localhost/rest/v1/softwaremodules/" + sm.getId() + "/artifacts/" + artId);
assertThat((Object)JsonPath.compile("$._links.download.href").read(mvcResult.getResponse().getContentAsString()))
assertThat((Object) JsonPath.compile("$._links.download.href").read(mvcResult.getResponse().getContentAsString()))
.as("response contains no download url ")
.hasToString("http://localhost/rest/v1/softwaremodules/" + sm.getId() + "/artifacts/" + artId + "/download");
@@ -772,11 +771,9 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
.andExpect(jsonPath("$.providedFilename", equalTo("file1")))
.andExpect(jsonPath("$._links.download.href", useArtifactUrlHandler
? equalTo("http://download-cdn.com/artifacts/%s/download".formatted(artifact.getFilename()))
: equalTo("http://localhost/rest/v1/softwaremodules/%s/artifacts/%s/download"
.formatted(sm.getId(), artifact.getId()))))
: equalTo("http://localhost/rest/v1/softwaremodules/%s/artifacts/%s/download".formatted(sm.getId(), artifact.getId()))))
.andExpect(jsonPath("$._links.self.href", equalTo(
"http://localhost/rest/v1/softwaremodules/%s/artifacts/%s".formatted(sm.getId(),
artifact.getId()))));
"http://localhost/rest/v1/softwaremodules/%s/artifacts/%s".formatted(sm.getId(), artifact.getId()))));
}
/**
@@ -785,14 +782,16 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
@Test
void getArtifactSoftDeleted() throws Exception {
// prepare data for test
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs("softDeleted");
SoftwareModule sm = testdataFactory.createSoftwareModuleOs("softDeleted");
final Artifact artifact = testdataFactory.createArtifacts(sm.getId()).get(0);
testdataFactory.createDistributionSet(Collections.singletonList(sm));
// the sm is changed by artifact creation, necessary to get the latest version for Hibernate
sm = softwareModuleManagement.get(sm.getId()).orElseThrow();
testdataFactory.createDistributionSet(List.of(sm));
softwareModuleManagement.delete(sm.getId());
// perform test
mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/{artId}", sm.getId(), artifact.getId()).accept(
MediaType.APPLICATION_JSON))
mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/{artId}", sm.getId(), artifact.getId())
.accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isOk())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
@@ -900,18 +899,18 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
*/
@Test
void invalidRequestsOnArtifactResource() throws Exception {
final int artifactSize = 5 * 1024;
final byte[] random = randomBytes(artifactSize);
final MockMultipartFile file = new MockMultipartFile("file", "orig", null, random);
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
final SoftwareModule smSoftDeleted = testdataFactory.createSoftwareModuleOs("softDeleted");
SoftwareModule smSoftDeleted = testdataFactory.createSoftwareModuleOs("softDeleted");
final Artifact artifactSoftDeleted = testdataFactory.createArtifacts(smSoftDeleted.getId()).get(0);
// the smSoftDeleted is changed by artifact creation, necessary to get the latest version for Hibernate
smSoftDeleted = softwareModuleManagement.get(smSoftDeleted.getId()).orElseThrow();
testdataFactory.createDistributionSet(List.of(smSoftDeleted));
softwareModuleManagement.delete(smSoftDeleted.getId());
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
// no artifact available
mvc.perform(get("/rest/v1/softwaremodules/{smId}/artifacts/1234567/download", sm.getId()))
.andDo(MockMvcResultPrinter.print())
@@ -996,8 +995,6 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
void invalidRequestsOnSoftwareModulesResource() throws Exception {
final SoftwareModule sm = testdataFactory.createSoftwareModuleOs();
final List<SoftwareModule> modules = Collections.singletonList(sm);
// SM does not exist
mvc.perform(get("/rest/v1/softwaremodules/12345678"))
.andDo(MockMvcResultPrinter.print())
@@ -1024,7 +1021,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
final SoftwareModule toLongName = entityFactory.softwareModule().create().type(osType)
final SoftwareModuleManagement.Create toLongName = SoftwareModuleManagement.Create.builder().type(osType)
.name(randomString(80)).build();
mvc.perform(post("/rest/v1/softwaremodules").content(JsonBuilder.softwareModules(Collections.singletonList(toLongName)))
.contentType(MediaType.APPLICATION_JSON))
@@ -1032,16 +1029,22 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
.andExpect(status().isBadRequest());
// unsupported media type
mvc.perform(post("/rest/v1/softwaremodules").content(JsonBuilder.softwareModules(modules))
mvc.perform(post("/rest/v1/softwaremodules")
.content(JsonBuilder.softwareModules(List.of(SoftwareModuleManagement.Create.builder()
.type(sm.getType())
.name(sm.getName())
.version(sm.getVersion())
.build())))
.contentType(MediaType.APPLICATION_OCTET_STREAM))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isUnsupportedMediaType());
final SoftwareModule swm = entityFactory.softwareModule().create().name("encryptedModule").type(osType)
final SoftwareModuleManagement.Create swm = SoftwareModuleManagement.Create.builder()
.name("encryptedModule").type(osType)
.version("version").vendor("vendor").description("description").encrypted(true).build();
// artifact decryption is not supported
mvc.perform(
post("/rest/v1/softwaremodules").content(JsonBuilder.softwareModules(Collections.singletonList(swm)))
post("/rest/v1/softwaremodules").content(JsonBuilder.softwareModules(List.of(swm)))
.contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
@@ -1270,16 +1273,14 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
@Test
@WithUser(principal = "uploadTester", allSpPermissions = true)
void createSoftwareModules() throws Exception {
final SoftwareModule os = entityFactory.softwareModule()
.create()
final SoftwareModuleManagement.Create os = SoftwareModuleManagement.Create.builder()
.name("name1")
.type(osType)
.version("version1")
.vendor("vendor1")
.description("description1")
.build();
final SoftwareModule ah = entityFactory.softwareModule()
.create()
final SoftwareModuleManagement.Create ah = SoftwareModuleManagement.Create.builder()
.name("name3")
.type(appType)
.version("version3")
@@ -1287,7 +1288,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
.description("description3")
.build();
final List<SoftwareModule> modules = Arrays.asList(os, ah);
final List<SoftwareModuleManagement.Create> modules = Arrays.asList(os, ah);
final long current = System.currentTimeMillis();
@@ -1375,7 +1376,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
final int artifactSize = 5 * 1024;
final byte[] random = randomBytes(artifactSize);
final Long appTypeSmId = ds1.findFirstModuleByType(appType).get().getId();
final Long appTypeSmId = findFirstModuleByType(ds1, appType).get().getId();
artifactManagement.create(
new ArtifactUpload(new ByteArrayInputStream(random), appTypeSmId, "file1", false, artifactSize));
@@ -1535,7 +1536,7 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
// binary
try (final InputStream fileInputStream = artifactManagement
.loadArtifactBinary(softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getSha1Hash(),
.loadArtifactBinary(softwareModuleManagement.get(sm.getId()).orElseThrow().getArtifacts().get(0).getSha1Hash(),
sm.getId(), sm.isEncrypted())
.get().getFileInputStream()) {
assertTrue(IOUtils.contentEquals(new ByteArrayInputStream(random), fileInputStream),
@@ -1543,17 +1544,17 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
}
// hashes
assertThat(artifactManagement.getByFilename("origFilename").get().getSha1Hash()).as("Wrong sha1 hash")
assertThat(artifactManagement.getByFilename("origFilename").orElseThrow().getSha1Hash()).as("Wrong sha1 hash")
.isEqualTo(HashGeneratorUtils.generateSHA1(random));
assertThat(artifactManagement.getByFilename("origFilename").get().getMd5Hash()).as("Wrong md5 hash")
assertThat(artifactManagement.getByFilename("origFilename").orElseThrow().getMd5Hash()).as("Wrong md5 hash")
.isEqualTo(HashGeneratorUtils.generateMD5(random));
assertThat(artifactManagement.getByFilename("origFilename").get().getSha256Hash()).as("Wrong sha256 hash")
assertThat(artifactManagement.getByFilename("origFilename").orElseThrow().getSha256Hash()).as("Wrong sha256 hash")
.isEqualTo(HashGeneratorUtils.generateSHA256(random));
// metadata
assertThat(softwareModuleManagement.get(sm.getId()).get().getArtifacts().get(0).getFilename())
assertThat(softwareModuleManagement.get(sm.getId()).orElseThrow().getArtifacts().get(0).getFilename())
.as("wrong metadata of the filename").isEqualTo("origFilename");
}
@@ -1574,8 +1575,8 @@ class MgmtSoftwareModuleResourceTest extends AbstractManagementApiIntegrationTes
char character = 'a';
for (int index = 0; index < amount; index++) {
final String str = String.valueOf(character);
softwareModuleManagement.create(entityFactory.softwareModule().create().type(osType).name(str)
.description(str).vendor(str).version(str));
softwareModuleManagement.create(
SoftwareModuleManagement.Create.builder().type(osType).name(str).description(str).vendor(str).version(str).build());
character++;
}
}

View File

@@ -29,6 +29,8 @@ import java.util.List;
import com.jayway.jsonpath.JsonPath;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.SoftwareModuleManagement;
import org.eclipse.hawkbit.repository.SoftwareModuleTypeManagement;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.test.util.WithUser;
@@ -101,7 +103,8 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt
public void getSoftwareModuleTypesWithParameters() throws Exception {
final SoftwareModuleType testType = testdataFactory.findOrCreateSoftwareModuleType("test123");
softwareModuleTypeManagement
.update(entityFactory.softwareModuleType().update(testType.getId()).description("Desc1234").colour("rgb(106,178,83)"));
.update(SoftwareModuleTypeManagement.Update.builder().id(testType.getId()).description("Desc1234").colour("rgb(106,178,83)")
.build());
mvc.perform(get(MgmtRestConstants.SOFTWAREMODULETYPE_V1_REQUEST_MAPPING + "?limit=10&sort=name:ASC&offset=0&q=name==a")
.accept(MediaType.APPLICATION_JSON))
@@ -160,19 +163,18 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt
@WithUser(principal = "uploadTester", allSpPermissions = true)
public void createSoftwareModuleTypesInvalidAssignmentBadRequest() throws Exception {
final List<SoftwareModuleType> types = new ArrayList<>();
types.add(entityFactory.softwareModuleType().create().key("test-1").name("TestName-1").maxAssignments(-1)
.build());
final List<SoftwareModuleTypeManagement.Create> types = new ArrayList<>();
types.add(SoftwareModuleTypeManagement.Create.builder().key("test-1").name("TestName-1").maxAssignments(-1).build());
mvc.perform(post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypes(types))
mvc.perform(post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypeCreates(types))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
types.clear();
types.add(entityFactory.softwareModuleType().create().key("test0").name("TestName0").maxAssignments(0).build());
types.add(SoftwareModuleTypeManagement.Create.builder().key("test0").name("TestName0").maxAssignments(0).build());
mvc.perform(post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypes(types))
mvc.perform(post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypeCreates(types))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
@@ -185,16 +187,16 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt
@WithUser(principal = "uploadTester", allSpPermissions = true)
public void createSoftwareModuleTypes() throws Exception {
final List<SoftwareModuleType> types = Arrays.asList(
entityFactory.softwareModuleType().create().key("test1").name("TestName1").description("Desc1")
final List<SoftwareModuleTypeManagement.Create> types = Arrays.asList(
SoftwareModuleTypeManagement.Create.builder().key("test1").name("TestName1").description("Desc1")
.colour("col1").maxAssignments(1).build(),
entityFactory.softwareModuleType().create().key("test2").name("TestName2").description("Desc2")
SoftwareModuleTypeManagement.Create.builder().key("test2").name("TestName2").description("Desc2")
.colour("col2").maxAssignments(2).build(),
entityFactory.softwareModuleType().create().key("test3").name("TestName3").description("Desc3")
SoftwareModuleTypeManagement.Create.builder().key("test3").name("TestName3").description("Desc3")
.colour("col3").maxAssignments(3).build());
final MvcResult mvcResult = mvc
.perform(post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypes(types))
.perform(post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypeCreates(types))
.contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isCreated())
@@ -223,9 +225,9 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt
assertThat((Object) JsonPath.compile("[0]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
.hasToString("http://localhost/rest/v1/softwaremoduletypes/" + created1.getId());
assertThat((Object)JsonPath.compile("[1]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
assertThat((Object) JsonPath.compile("[1]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
.hasToString("http://localhost/rest/v1/softwaremoduletypes/" + created2.getId());
assertThat((Object)JsonPath.compile("[2]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
assertThat((Object) JsonPath.compile("[2]_links.self.href").read(mvcResult.getResponse().getContentAsString()))
.hasToString("http://localhost/rest/v1/softwaremoduletypes/" + created3.getId());
assertThat(softwareModuleTypeManagement.count()).isEqualTo(6);
@@ -289,7 +291,7 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt
public void deleteSoftwareModuleTypeUsed() throws Exception {
final SoftwareModuleType testType = createTestType();
softwareModuleManagement
.create(entityFactory.softwareModule().create().type(testType).name("name").version("version"));
.create(SoftwareModuleManagement.Create.builder().type(testType).name("name").version("version").build());
assertThat(softwareModuleTypeManagement.count()).isEqualTo(4);
@@ -406,10 +408,13 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt
* Ensures that the server is behaving as expected on invalid requests (wrong media type, wrong ID etc.).
*/
@Test
void invalidRequestsOnSoftwaremoduleTypesResource() throws Exception {
void invalidRequestsOnSoftwareModuleTypesResource() throws Exception {
final SoftwareModuleType testType = createTestType();
final List<SoftwareModuleType> types = Collections.singletonList(testType);
final List<SoftwareModuleTypeManagement.Create> types = List.of(SoftwareModuleTypeManagement.Create.builder()
.key(testType.getKey())
.name(testType.getName())
.build());
// SM does not exist
mvc.perform(get("/rest/v1/softwaremoduletypes/12345678"))
@@ -437,18 +442,18 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
final SoftwareModuleType toLongName = entityFactory.softwareModuleType().create()
final SoftwareModuleTypeManagement.Create toLongName = SoftwareModuleTypeManagement.Create.builder()
.key("test123")
.name(randomString(NamedEntity.NAME_MAX_SIZE + 1))
.build();
mvc.perform(
post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypes(Collections.singletonList(toLongName)))
post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypeCreates(Collections.singletonList(toLongName)))
.contentType(MediaType.APPLICATION_JSON))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isBadRequest());
// unsupported media type
mvc.perform(post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypes(types))
mvc.perform(post("/rest/v1/softwaremoduletypes").content(JsonBuilder.softwareModuleTypeCreates(types))
.contentType(MediaType.APPLICATION_OCTET_STREAM))
.andDo(MockMvcResultPrinter.print())
.andExpect(status().isUnsupportedMediaType());
@@ -469,10 +474,10 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt
*/
@Test
void searchSoftwareModuleTypeRsql() throws Exception {
softwareModuleTypeManagement.create(entityFactory.softwareModuleType().create().key("test123")
.name("TestName123").description("Desc123").maxAssignments(5));
softwareModuleTypeManagement.create(entityFactory.softwareModuleType().create().key("test1234")
.name("TestName1234").description("Desc1234").maxAssignments(5));
softwareModuleTypeManagement.create(SoftwareModuleTypeManagement.Create.builder().key("test123")
.name("TestName123").description("Desc123").maxAssignments(5).build());
softwareModuleTypeManagement.create(SoftwareModuleTypeManagement.Create.builder().key("test1234")
.name("TestName1234").description("Desc1234").maxAssignments(5).build());
final String rsqlFindLikeDs1OrDs2 = "name==TestName123,name==TestName1234";
@@ -487,10 +492,9 @@ public class MgmtSoftwareModuleTypeResourceTest extends AbstractManagementApiInt
}
private SoftwareModuleType createTestType() {
SoftwareModuleType testType = softwareModuleTypeManagement.create(entityFactory.softwareModuleType().create()
.key("test123").name("TestName123").description("Desc123").colour("colour").maxAssignments(5));
testType = softwareModuleTypeManagement
.update(entityFactory.softwareModuleType().update(testType.getId()).description("Desc1234"));
return testType;
final SoftwareModuleType testType = softwareModuleTypeManagement.create(SoftwareModuleTypeManagement.Create.builder()
.key("test123").name("TestName123").description("Desc123").colour("colour").maxAssignments(5).build());
return softwareModuleTypeManagement
.update(SoftwareModuleTypeManagement.Update.builder().id(testType.getId()).description("Desc1234").build());
}
}

View File

@@ -31,6 +31,7 @@ import org.eclipse.hawkbit.mgmt.json.model.distributionset.MgmtActionType;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.mgmt.rest.resource.mapper.MgmtRestModelMapper;
import org.eclipse.hawkbit.mgmt.rest.resource.util.ResourceUtility;
import org.eclipse.hawkbit.repository.DistributionSetManagement;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.DeletedException;
import org.eclipse.hawkbit.repository.exception.IncompleteDistributionSetException;
@@ -774,8 +775,10 @@ public class MgmtTargetFilterQueryResourceTest extends AbstractManagementApiInte
private void verifyAutoAssignmentWithIncompleteDs(final TargetFilterQuery tfq) throws Exception {
final DistributionSet incompleteDistributionSet = distributionSetManagement
.create(entityFactory.distributionSet().create().name("incomplete").version("1")
.type(testdataFactory.findOrCreateDefaultTestDsType()));
.create(DistributionSetManagement.Create.builder()
.type(testdataFactory.findOrCreateDefaultTestDsType())
.name("incomplete").version("1")
.build());
mvc.perform(post(MgmtRestConstants.TARGET_FILTER_V1_REQUEST_MAPPING + "/" + tfq.getId() + "/autoAssignDS")
.content("{\"id\":" + incompleteDistributionSet.getId() + "}").contentType(MediaType.APPLICATION_JSON))

View File

@@ -947,9 +947,9 @@ class MgmtTargetResourceTest extends AbstractManagementApiIntegrationTest {
// test
final SoftwareModule os = ds.findFirstModuleByType(osType).get();
final SoftwareModule jvm = ds.findFirstModuleByType(runtimeType).get();
final SoftwareModule bApp = ds.findFirstModuleByType(appType).get();
final SoftwareModule os = findFirstModuleByType(ds, osType).orElseThrow();
final SoftwareModule jvm = findFirstModuleByType(ds, runtimeType).orElseThrow();
final SoftwareModule bApp = findFirstModuleByType(ds,appType).orElseThrow();
mvc.perform(get(MgmtRestConstants.TARGET_V1_REQUEST_MAPPING + "/" + knownControllerId + "/assignedDS"))
.andExpect(status().isOk())
.andDo(MockMvcResultPrinter.print())

View File

@@ -24,6 +24,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.mgmt.json.model.system.MgmtSystemTenantConfigurationValueRequest;
import org.eclipse.hawkbit.mgmt.rest.api.MgmtRestConstants;
import org.eclipse.hawkbit.repository.DistributionSetTypeManagement;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.rest.util.MockMvcResultPrinter;
import org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties;
@@ -334,10 +335,10 @@ public class MgmtTenantManagementResourceTest extends AbstractManagementApiInteg
}
private Long createTestDistributionSetType() {
DistributionSetType testDefaultDsType = distributionSetTypeManagement.create(entityFactory.distributionSetType().create()
.key("test123").name("TestName123").description("TestDefaultDsType"));
DistributionSetType testDefaultDsType = distributionSetTypeManagement.create(DistributionSetTypeManagement.Create.builder()
.key("test123").name("TestName123").description("TestDefaultDsType").build());
testDefaultDsType = distributionSetTypeManagement
.update(entityFactory.distributionSetType().update(testDefaultDsType.getId()).description("TestDefaultDsType"));
.update(DistributionSetTypeManagement.Update.builder().id(testDefaultDsType.getId()).description("TestDefaultDsType").build());
return testDefaultDsType.getId();
}

View File

@@ -40,7 +40,7 @@ public interface ArtifactManagement {
* @return the total amount of local artifacts stored in the artifact
* management
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
long count();
/**
@@ -56,7 +56,7 @@ public interface ArtifactManagement {
* @throws InvalidSHA1HashException if check against provided SHA1 checksum failed
* @throws ConstraintViolationException if {@link ArtifactUpload} contains invalid values
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_CREATE_REPOSITORY)
Artifact create(@NotNull @Valid ArtifactUpload artifactUpload);
/**
@@ -66,7 +66,7 @@ public interface ArtifactManagement {
* @throws ArtifactDeleteFailedException if deletion failed (MongoDB is not available)
* @throws EntityNotFoundException if artifact with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_DELETE_REPOSITORY)
void delete(long id);
/**
@@ -75,7 +75,7 @@ public interface ArtifactManagement {
* @param id to search for
* @return found {@link Artifact}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.IS_CONTROLLER)
Optional<Artifact> get(long id);
@@ -87,7 +87,7 @@ public interface ArtifactManagement {
* @return found {@link Artifact}
* @throws EntityNotFoundException if software module with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.IS_CONTROLLER)
Optional<Artifact> getByFilenameAndSoftwareModule(@NotNull String filename, long softwareModuleId);
@@ -97,7 +97,7 @@ public interface ArtifactManagement {
* @param sha1 the sha1
* @return the first local artifact
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.IS_CONTROLLER)
Optional<Artifact> findFirstBySHA1(@NotNull String sha1);
@@ -107,7 +107,7 @@ public interface ArtifactManagement {
* @param filename to search for
* @return found List of {@link Artifact}s.
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.IS_CONTROLLER)
Optional<Artifact> getByFilename(@NotNull String filename);
@@ -119,7 +119,7 @@ public interface ArtifactManagement {
* @return Page<Artifact>
* @throws EntityNotFoundException if software module with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Page<Artifact> findBySoftwareModule(long softwareModuleId, @NotNull Pageable pageable);
/**
@@ -129,7 +129,7 @@ public interface ArtifactManagement {
* @return count by software module
* @throws EntityNotFoundException if software module with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
long countBySoftwareModule(long softwareModuleId);
/**

View File

@@ -1,25 +0,0 @@
/**
* Copyright (c) 2021 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;
/**
* Provider that returns a base repository implementation dynamically based on repository type
*/
@FunctionalInterface
public interface BaseRepositoryTypeProvider {
/**
* Return a base repository implementation that shall be used based on provided repository type
*
* @param repositoryType type of repository
* @return base repository implementation class
*/
Class<?> getBaseRepositoryType(final Class<?> repositoryType);
}

View File

@@ -26,6 +26,8 @@ import org.springframework.security.access.prepost.PreAuthorize;
*/
public interface ConfirmationManagement {
String CONFIRMATION_CODE_MSG_PREFIX = "Confirmation status code: %d";
/**
* Activate auto confirmation for a given controller ID. In case auto confirmation is active already, this method will fail with an exception.
*

View File

@@ -121,7 +121,7 @@ public interface DeploymentManagement {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET)
List<DistributionSetAssignmentResult> offlineAssignedDistributionSets(Collection<Entry<String, Long>> assignments, String initiatedBy);
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
List<DistributionSetAssignmentResult> offlineAssignedDistributionSets(Collection<Entry<String, Long>> assignments);
/**

View File

@@ -9,20 +9,25 @@
*/
package org.eclipse.hawkbit.repository;
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_READ_DISTRIBUTION_SET;
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_UPDATE_DISTRIBUTION_SET;
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_READ_REPOSITORY;
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_UPDATE_REPOSITORY;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.builder.DistributionSetCreate;
import org.eclipse.hawkbit.repository.builder.DistributionSetUpdate;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
@@ -35,6 +40,9 @@ import org.eclipse.hawkbit.repository.exception.UnsupportedSoftwareModuleForThis
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetFilter;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.Statistic;
import org.springframework.data.domain.Page;
@@ -45,7 +53,14 @@ import org.springframework.security.access.prepost.PreAuthorize;
/**
* Management service for {@link DistributionSet}s.
*/
public interface DistributionSetManagement extends RepositoryManagement<DistributionSet, DistributionSetCreate, DistributionSetUpdate> {
public interface DistributionSetManagement<T extends DistributionSet>
extends RepositoryManagement<T, DistributionSetManagement.Create, DistributionSetManagement.Update> {
@Override
default String permissionGroup() {
return "DISTRIBUTION_SET";
}
/**
* Find {@link DistributionSet} based on given ID including (lazy loaded) details, e.g. {@link DistributionSet#getModules()}. <br/>
@@ -54,8 +69,8 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @param id to look for.
* @return {@link DistributionSet}
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
Optional<DistributionSet> getWithDetails(long id);
@PreAuthorize(HAS_READ_REPOSITORY)
Optional<T> getWithDetails(long id);
/**
* Find distribution set by id and throw an exception if it is (soft) deleted.
@@ -64,16 +79,16 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @return the found valid {@link DistributionSet}
* @throws EntityNotFoundException if distribution set with given ID does not exist
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
DistributionSet getOrElseThrowException(long id);
@PreAuthorize(HAS_READ_REPOSITORY)
T getOrElseThrowException(long id);
/**
* Sets the specified {@link DistributionSet} as invalidated.
*
* @param distributionSet the ID of the {@link DistributionSet} to be set to invalid
*/
@PreAuthorize(HAS_AUTH_UPDATE_DISTRIBUTION_SET)
void invalidate(DistributionSet distributionSet);
@PreAuthorize(HAS_UPDATE_REPOSITORY)
void invalidate(T distributionSet);
/**
* Assigns {@link SoftwareModule} to existing {@link DistributionSet}.
@@ -88,8 +103,8 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @throws AssignmentQuotaExceededException if the maximum number of {@link SoftwareModule}s is exceeded for the addressed
* {@link DistributionSet}.
*/
@PreAuthorize(HAS_AUTH_UPDATE_DISTRIBUTION_SET)
DistributionSet assignSoftwareModules(long id, @NotEmpty Collection<Long> moduleIds);
@PreAuthorize(HAS_UPDATE_REPOSITORY)
T assignSoftwareModules(long id, @NotEmpty Collection<Long> moduleIds);
/**
* Unassigns a {@link SoftwareModule} form an existing {@link DistributionSet}.
@@ -100,8 +115,8 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @throws EntityNotFoundException if given module or DS does not exist
* @throws EntityReadOnlyException if use tries to change the {@link DistributionSet} s while the DS is already in use.
*/
@PreAuthorize(HAS_AUTH_UPDATE_DISTRIBUTION_SET)
DistributionSet unassignSoftwareModule(long id, long moduleId);
@PreAuthorize(HAS_UPDATE_REPOSITORY)
T unassignSoftwareModule(long id, long moduleId);
/**
* Assign a {@link DistributionSetTag} assignment to given {@link DistributionSet}s.
@@ -111,8 +126,8 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @return list of assigned ds
* @throws EntityNotFoundException if tag with given ID does not exist or (at least one) of the distribution sets.
*/
@PreAuthorize(HAS_AUTH_UPDATE_DISTRIBUTION_SET)
List<DistributionSet> assignTag(@NotEmpty Collection<Long> ids, long tagId);
@PreAuthorize(HAS_UPDATE_REPOSITORY)
List<T> assignTag(@NotEmpty Collection<Long> ids, long tagId);
/**
* Unassign a {@link DistributionSetTag} assignment to given {@link DistributionSet}s.
@@ -122,8 +137,8 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @return list of assigned ds
* @throws EntityNotFoundException if tag with given ID does not exist or (at least one) of the distribution sets.
*/
@PreAuthorize(HAS_AUTH_UPDATE_DISTRIBUTION_SET)
List<DistributionSet> unassignTag(@NotEmpty Collection<Long> ids, long tagId);
@PreAuthorize(HAS_UPDATE_REPOSITORY)
List<T> unassignTag(@NotEmpty Collection<Long> ids, long tagId);
/**
* Creates a map of distribution set meta-data entries.
@@ -134,7 +149,7 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @throws EntityAlreadyExistsException in case one of the meta-data entry already exists for the specific key
* @throws AssignmentQuotaExceededException if the maximum number of meta-data entries is exceeded for the addressed {@link DistributionSet}
*/
@PreAuthorize(HAS_AUTH_UPDATE_DISTRIBUTION_SET)
@PreAuthorize(HAS_UPDATE_REPOSITORY)
void createMetadata(long id, @NotEmpty Map<String, String> metadata);
/**
@@ -144,7 +159,7 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @return a paged result of all meta-data entries for a given distribution set id
* @throws EntityNotFoundException if distribution set with given ID does not exist
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
@PreAuthorize(HAS_READ_REPOSITORY)
Map<String, String> getMetadata(long id);
/**
@@ -155,7 +170,7 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @param value meta data-entry to be new value
* @throws EntityNotFoundException in case the meta-data entry does not exist and cannot be updated
*/
@PreAuthorize(HAS_AUTH_UPDATE_DISTRIBUTION_SET)
@PreAuthorize(HAS_UPDATE_REPOSITORY)
void updateMetadata(long id, @NotNull String key, @NotNull String value);
/**
@@ -165,7 +180,7 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @param key of the meta-data element
* @throws EntityNotFoundException if given set does not exist
*/
@PreAuthorize(HAS_AUTH_UPDATE_DISTRIBUTION_SET)
@PreAuthorize(HAS_UPDATE_REPOSITORY)
void deleteMetadata(long id, @NotEmpty String key);
/**
@@ -174,7 +189,7 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @param id the distribution set id
* @throws EntityNotFoundException if distribution set with given ID does not exist
*/
@PreAuthorize(HAS_AUTH_UPDATE_DISTRIBUTION_SET)
@PreAuthorize(HAS_UPDATE_REPOSITORY)
void lock(final long id);
/**
@@ -185,7 +200,7 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @param id the distribution set id
* @throws EntityNotFoundException if distribution set with given ID does not exist
*/
@PreAuthorize(HAS_AUTH_UPDATE_DISTRIBUTION_SET)
@PreAuthorize(HAS_UPDATE_REPOSITORY)
void unlock(final long id);
/**
@@ -196,8 +211,8 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @throws EntityNotFoundException if distribution set with given ID does not exist
* @throws InvalidDistributionSetException if distribution set with given ID is invalidated
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
DistributionSet getValid(long id);
@PreAuthorize(HAS_READ_REPOSITORY)
T getValid(long id);
/**
* Find distribution set by id and throw an exception if it is deleted, incomplete or invalidated.
@@ -208,8 +223,8 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @throws InvalidDistributionSetException if distribution set with given ID is invalidated
* @throws IncompleteDistributionSetException if distribution set with given ID is incomplete
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
DistributionSet getValidAndComplete(long id);
@PreAuthorize(HAS_READ_REPOSITORY)
T getValidAndComplete(long id);
/**
* Retrieves the distribution set for a given action.
@@ -218,8 +233,8 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @return the distribution set which is associated with the action
* @throws EntityNotFoundException if action with given ID does not exist
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
Optional<DistributionSet> findByAction(long actionId);
@PreAuthorize(HAS_READ_REPOSITORY)
Optional<T> findByAction(long actionId);
/**
* Find distribution set by name and version.
@@ -228,8 +243,8 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @param version version of {@link DistributionSet}
* @return the page with the found {@link DistributionSet}
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
Optional<DistributionSet> findByNameAndVersion(@NotEmpty String distributionName, @NotEmpty String version);
@PreAuthorize(HAS_READ_REPOSITORY)
Optional<T> findByNameAndVersion(@NotEmpty String distributionName, @NotEmpty String version);
/**
* Finds all {@link DistributionSet}s based on completeness.
@@ -239,8 +254,8 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @param pageable the pagination parameter
* @return all found {@link DistributionSet}s
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
Slice<DistributionSet> findByCompleted(Boolean complete, @NotNull Pageable pageable);
@PreAuthorize(HAS_READ_REPOSITORY)
Slice<T> findByCompleted(Boolean complete, @NotNull Pageable pageable);
/**
* Retrieves {@link DistributionSet}s by filtering on the given parameters.
@@ -249,8 +264,8 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @param pageable page parameter
* @return the page of found {@link DistributionSet}
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
Slice<DistributionSet> findByDistributionSetFilter(@NotNull DistributionSetFilter distributionSetFilter, @NotNull Pageable pageable);
@PreAuthorize(HAS_READ_REPOSITORY)
Slice<T> findByDistributionSetFilter(@NotNull DistributionSetFilter distributionSetFilter, @NotNull Pageable pageable);
/**
* Retrieves {@link DistributionSet}s by filtering on the given parameters.
@@ -263,8 +278,8 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @throws RSQLParameterSyntaxException if the RSQL syntax is wrong
* @throws EntityNotFoundException of distribution set tag with given ID does not exist
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
Page<DistributionSet> findByTag(long tagId, @NotNull Pageable pageable);
@PreAuthorize(HAS_READ_REPOSITORY)
Page<T> findByTag(long tagId, @NotNull Pageable pageable);
/**
* Retrieves {@link DistributionSet}s by filtering on the given parameters.
@@ -275,8 +290,8 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @return the page of found {@link DistributionSet}
* @throws EntityNotFoundException of distribution set tag with given ID does not exist
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
Page<DistributionSet> findByRsqlAndTag(@NotNull String rsql, long tagId, @NotNull Pageable pageable);
@PreAuthorize(HAS_READ_REPOSITORY)
Page<T> findByRsqlAndTag(@NotNull String rsql, long tagId, @NotNull Pageable pageable);
/**
* Counts all {@link DistributionSet}s based on completeness.
@@ -285,7 +300,7 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* nor <code>null</code> to count both.
* @return count of all found {@link DistributionSet}s
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
@PreAuthorize(HAS_READ_REPOSITORY)
long countByCompleted(Boolean complete);
/**
@@ -294,7 +309,7 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @param distributionSetFilter has details of filters to be applied.
* @return count of {@link DistributionSet}s
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
@PreAuthorize(HAS_READ_REPOSITORY)
long countByDistributionSetFilter(@NotNull DistributionSetFilter distributionSetFilter);
/**
@@ -305,7 +320,7 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @return number of {@link DistributionSet}s
* @throws EntityNotFoundException if type with given ID does not exist
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
@PreAuthorize(HAS_READ_REPOSITORY)
long countByTypeId(long typeId);
/**
@@ -315,7 +330,7 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @param id to check
* @return <code>true</code> if in use
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
@PreAuthorize(HAS_READ_REPOSITORY)
boolean isInUse(long id);
/**
@@ -325,7 +340,7 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @param id to look for
* @return List of Statistics for {@link org.eclipse.hawkbit.repository.model.Rollout}s status counts
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
@PreAuthorize(HAS_READ_REPOSITORY)
List<Statistic> countRolloutsByStatusForDistributionSet(@NotNull Long id);
/**
@@ -335,7 +350,7 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @param id to look for
* @return List of Statistics for {@link org.eclipse.hawkbit.repository.model.Action}s status counts
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
@PreAuthorize(HAS_READ_REPOSITORY)
List<Statistic> countActionsByStatusForDistributionSet(@NotNull Long id);
/**
@@ -345,6 +360,60 @@ public interface DistributionSetManagement extends RepositoryManagement<Distribu
* @param id to look for
* @return number of {@link org.eclipse.hawkbit.repository.builder.AutoAssignDistributionSetUpdate}s
*/
@PreAuthorize(HAS_AUTH_READ_DISTRIBUTION_SET)
@PreAuthorize(HAS_READ_REPOSITORY)
Long countAutoAssignmentsForDistributionSet(@NotNull Long id);
@SuperBuilder
@Getter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
final class Create extends UpdateCreate {
@NotNull
private DistributionSetType type;
@Builder.Default
private Set<? extends SoftwareModule> modules = Set.of();
public Create setType(@NotEmpty DistributionSetType type) {
this.type = Objects.requireNonNull(type, "type must not be null");
return this;
}
public boolean isValid() {
return true;
}
}
@SuperBuilder
@Getter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
final class Update extends UpdateCreate implements Identifiable<Long> {
@NotNull
private Long id;
@Builder.Default
private Boolean locked = false;
}
@SuperBuilder
@Getter
class UpdateCreate {
@ValidString
@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE)
@NotNull(groups = Create.class)
private String name;
@ValidString
@Size(min = 1, max = NamedVersionedEntity.VERSION_MAX_SIZE)
@NotNull(groups = Create.class)
private String version;
@ValidString
@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE)
private String description;
@Builder.Default
private Boolean requiredMigrationStep = false;
}
}

View File

@@ -13,13 +13,18 @@ import java.util.Optional;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.builder.TagCreate;
import org.eclipse.hawkbit.repository.builder.TagUpdate;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetTag;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.Tag;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.springframework.data.domain.Page;
@@ -29,7 +34,8 @@ import org.springframework.security.access.prepost.PreAuthorize;
/**
* Management service for {@link DistributionSetTag}s.
*/
public interface DistributionSetTagManagement extends RepositoryManagement<DistributionSetTag, TagCreate, TagUpdate> {
public interface DistributionSetTagManagement<T extends DistributionSetTag>
extends RepositoryManagement<T, DistributionSetTagManagement.Create, DistributionSetTagManagement.Update> {
/**
* Find {@link DistributionSet} based on given name.
@@ -37,8 +43,8 @@ public interface DistributionSetTagManagement extends RepositoryManagement<Distr
* @param name to look for.
* @return {@link DistributionSet}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Optional<DistributionSetTag> findByName(@NotEmpty String name);
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Optional<T> findByName(@NotEmpty String name);
/**
* Finds all {@link TargetTag} assigned to given {@link Target}.
@@ -48,8 +54,8 @@ public interface DistributionSetTagManagement extends RepositoryManagement<Distr
* @return page of the found {@link TargetTag}s
* @throws EntityNotFoundException if {@link DistributionSet} with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<DistributionSetTag> findByDistributionSet(long distributionSetId, @NotNull Pageable pageable);
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Page<T> findByDistributionSet(long distributionSetId, @NotNull Pageable pageable);
/**
* Deletes {@link DistributionSetTag} by given
@@ -58,6 +64,40 @@ public interface DistributionSetTagManagement extends RepositoryManagement<Distr
* @param tagName to be deleted
* @throws EntityNotFoundException if tag with given name does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_DELETE_REPOSITORY)
void delete(@NotEmpty String tagName);
@SuperBuilder
@Getter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
final class Create extends UpdateCreate {}
@SuperBuilder
@Getter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
final class Update extends UpdateCreate implements Identifiable<Long> {
@NotNull
private Long id;
}
@SuperBuilder
@Getter
class UpdateCreate {
@ValidString
@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE)
@NotNull(groups = Create.class)
private String name;
@ValidString
@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE)
private String description;
@ValidString
@Size(max = Tag.COLOUR_MAX_SIZE)
private String colour;
}
}

View File

@@ -11,31 +11,39 @@ package org.eclipse.hawkbit.repository;
import java.util.Collection;
import java.util.Optional;
import java.util.Set;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.builder.DistributionSetTypeCreate;
import org.eclipse.hawkbit.repository.builder.DistributionSetTypeUpdate;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.EntityReadOnlyException;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.Type;
import org.springframework.security.access.prepost.PreAuthorize;
/**
* Management service for {@link DistributionSetType}s.
*/
public interface DistributionSetTypeManagement
extends RepositoryManagement<DistributionSetType, DistributionSetTypeCreate, DistributionSetTypeUpdate> {
public interface DistributionSetTypeManagement<T extends DistributionSetType>
extends RepositoryManagement<T, DistributionSetTypeManagement.Create, DistributionSetTypeManagement.Update> {
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Optional<DistributionSetType> findByKey(@NotEmpty String key);
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Optional<T> findByKey(@NotEmpty String key);
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Optional<DistributionSetType> findByName(@NotEmpty String name);
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Optional<T> findByName(@NotEmpty String name);
/**
* Assigns {@link DistributionSetType#getMandatoryModuleTypes()}.
@@ -48,8 +56,8 @@ public interface DistributionSetTypeManagement
* @throws AssignmentQuotaExceededException if the maximum number of {@link SoftwareModuleType}s is exceeded for the addressed
* {@link DistributionSetType}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
DistributionSetType assignOptionalSoftwareModuleTypes(long id, @NotEmpty Collection<Long> softwareModuleTypeIds);
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
T assignOptionalSoftwareModuleTypes(long id, @NotEmpty Collection<Long> softwareModuleTypeIds);
/**
* Assigns {@link DistributionSetType#getOptionalModuleTypes()}.
@@ -62,8 +70,8 @@ public interface DistributionSetTypeManagement
* @throws AssignmentQuotaExceededException if the maximum number of {@link SoftwareModuleType}s is exceeded for the addressed
* {@link DistributionSetType}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
DistributionSetType assignMandatorySoftwareModuleTypes(long id, @NotEmpty Collection<Long> softwareModuleTypeIds);
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
T assignMandatorySoftwareModuleTypes(long id, @NotEmpty Collection<Long> softwareModuleTypeIds);
/**
* Unassigns a {@link SoftwareModuleType} from the {@link DistributionSetType}. Does nothing if {@link SoftwareModuleType}
@@ -75,6 +83,49 @@ public interface DistributionSetTypeManagement
* @throws EntityNotFoundException in case the {@link DistributionSetType} does not exist
* @throws EntityReadOnlyException if the {@link DistributionSetType} while it is already in use by a {@link DistributionSet}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
DistributionSetType unassignSoftwareModuleType(long id, long softwareModuleTypeId);
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
T unassignSoftwareModuleType(long id, long softwareModuleTypeId);
@SuperBuilder
@Getter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
final class Create extends UpdateCreate {
@Size(min = 1, max = Type.KEY_MAX_SIZE)
@NotNull
private String key;
@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE)
@NotNull
private String name;
}
@SuperBuilder
@Getter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
final class Update extends UpdateCreate implements Identifiable<Long> {
@NotNull
private Long id;
}
@SuperBuilder
@Getter
class UpdateCreate {
@ValidString
@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE)
private String description;
@ValidString
@Size(max = Type.COLOUR_MAX_SIZE)
private String colour;
@Builder.Default
private Set<? extends SoftwareModuleType> mandatoryModuleTypes = Set.of();
@Builder.Default
private Set<? extends SoftwareModuleType> optionalModuleTypes = Set.of();
}
}

View File

@@ -10,18 +10,15 @@
package org.eclipse.hawkbit.repository;
import org.eclipse.hawkbit.repository.builder.ActionStatusBuilder;
import org.eclipse.hawkbit.repository.builder.DistributionSetBuilder;
import org.eclipse.hawkbit.repository.builder.DistributionSetTypeBuilder;
import org.eclipse.hawkbit.repository.builder.RolloutBuilder;
import org.eclipse.hawkbit.repository.builder.RolloutGroupBuilder;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleBuilder;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataBuilder;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeBuilder;
import org.eclipse.hawkbit.repository.builder.TagBuilder;
import org.eclipse.hawkbit.repository.builder.TargetBuilder;
import org.eclipse.hawkbit.repository.builder.TargetFilterQueryBuilder;
import org.eclipse.hawkbit.repository.builder.TargetTypeBuilder;
import org.eclipse.hawkbit.repository.model.BaseEntity;
import org.eclipse.hawkbit.repository.model.Tag;
/**
* central {@link BaseEntity} generation service. Objects are created but not
@@ -34,11 +31,6 @@ public interface EntityFactory {
*/
ActionStatusBuilder actionStatus();
/**
* @return {@link DistributionSetBuilder} object
*/
DistributionSetBuilder distributionSet();
/**
* @return {@link SoftwareModuleMetadataBuilder} object
*/
@@ -47,33 +39,18 @@ public interface EntityFactory {
/**
* @return {@link TagBuilder} object
*/
TagBuilder tag();
TagBuilder<Tag> tag();
/**
* @return {@link RolloutGroupBuilder} object
*/
RolloutGroupBuilder rolloutGroup();
/**
* @return {@link DistributionSetTypeBuilder} object
*/
DistributionSetTypeBuilder distributionSetType();
/**
* @return {@link RolloutBuilder} object
*/
RolloutBuilder rollout();
/**
* @return {@link SoftwareModuleBuilder} object
*/
SoftwareModuleBuilder softwareModule();
/**
* @return {@link SoftwareModuleTypeBuilder} object
*/
SoftwareModuleTypeBuilder softwareModuleType();
/**
* @return {@link TargetBuilder} object
*/

View File

@@ -33,70 +33,30 @@ import org.springframework.security.access.prepost.PreAuthorize;
* Generic management methods common to (software) repository content.
*
* @param <T> type of the {@link BaseEntity}
* @param <C> entity create builder
* @param <U> entity update builder
* @param <C> type of the create request
* @param <U> type of the update request
*/
public interface RepositoryManagement<T, C, U> {
/**
* Creates multiple {@link BaseEntity}s.
*
* @param creates to create
* @return created Entity
* @throws ConstraintViolationException if fields are not filled as specified. Check {@link BaseEntity} for field constraints.
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY)
List<T> create(@NotNull @Valid Collection<C> creates);
public interface RepositoryManagement<T extends BaseEntity, C, U extends Identifiable<Long>> {
/**
* Creates new {@link BaseEntity}.
*
* @param create to create
* @param create bean with properties of the object to create
* @return created Entity
* @throws ConstraintViolationException if fields are not filled as specified. Check {@link BaseEntity} for field constraints.
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_CREATE_REPOSITORY)
T create(@NotNull @Valid C create);
/**
* Updates existing {@link BaseEntity}.
* Creates multiple {@link BaseEntity}s.
*
* @param update to update
* @return updated Entity
* @throws EntityReadOnlyException if the {@link BaseEntity} cannot be updated (e.g. is already in use)
* @throws EntityNotFoundException in case the {@link BaseEntity} does not exist and cannot be updated
* @param create beans with properties of the object to create
* @return created Entity
* @throws ConstraintViolationException if fields are not filled as specified. Check {@link BaseEntity} for field constraints.
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
T update(@NotNull @Valid U update);
/**
* Deletes or marks as delete in case the {@link BaseEntity} is in use.
*
* @param id to delete
* @throws EntityNotFoundException BaseEntity with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY)
void delete(long id);
/**
* Delete {@link BaseEntity}s by their IDs. That is either a soft delete of the entities have been linked to another entity before or a hard
* delete if not.
*
* @param ids to be deleted
* @throws EntityNotFoundException if (at least one) given distribution set does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_DELETE_REPOSITORY)
void delete(@NotEmpty Collection<Long> ids);
/**
* Retrieves all {@link BaseEntity}s without details.
*
* @param ids the ids to for
* @return the found {@link BaseEntity}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
List<T> get(@NotEmpty Collection<Long> ids);
@PreAuthorize(SpringEvalExpressions.HAS_CREATE_REPOSITORY)
List<T> create(@NotNull @Valid Collection<C> create);
/**
* Retrieve {@link BaseEntity}
@@ -104,16 +64,25 @@ public interface RepositoryManagement<T, C, U> {
* @param id to search for
* @return {@link BaseEntity} in the repository with given {@link BaseEntity#getId()}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Optional<T> get(long id);
/**
* Retrieves all {@link BaseEntity}s without details.
*
* @param ids the ids to for
* @return the found {@link BaseEntity}s
*/
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
List<T> get(@NotEmpty Collection<Long> ids);
/**
* Retrieves {@link Page} of all {@link BaseEntity} of given type.
*
* @param pageable paging parameter
* @return all {@link BaseEntity}s in the repository.
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Slice<T> findAll(@NotNull Pageable pageable);
/**
@@ -126,7 +95,7 @@ public interface RepositoryManagement<T, C, U> {
* {@code fieldNameProvider}
* @throws RSQLParameterSyntaxException if the RSQL syntax is wrong
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Page<T> findByRsql(@NotNull String rsql, @NotNull Pageable pageable);
/**
@@ -135,12 +104,56 @@ public interface RepositoryManagement<T, C, U> {
* @param id of entity to check existence
* @return <code>true</code> if entity with given ID exists
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
boolean exists(long id);
/**
* @return number of {@link BaseEntity}s in the repository.
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
long count();
/**
* Counts the number of {@link BaseEntity}s matching the given RSQL filter.
*
* @param rsql filter definition in RSQL syntax
* @return number of matching {@link BaseEntity}s in the repository.
*/
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
long countByRsql(String rsql);
/**
* Updates existing {@link BaseEntity}.
*
* @param update bean with properties of the object to update
* @return updated Entity
* @throws EntityReadOnlyException if the {@link BaseEntity} cannot be updated (e.g. is already in use)
* @throws EntityNotFoundException in case the {@link BaseEntity} does not exist and cannot be updated
* @throws ConstraintViolationException if fields are not filled as specified. Check {@link BaseEntity} for field constraints.
*/
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
T update(@NotNull @Valid U update);
/**
* Deletes or marks as delete in case the {@link BaseEntity} is in use.
*
* @param id to delete
* @throws EntityNotFoundException BaseEntity with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_DELETE_REPOSITORY)
void delete(long id);
/**
* Delete {@link BaseEntity}s by their IDs. That is either a soft delete of the entities have been linked to another entity before or a hard
* delete if not.
*
* @param ids to be deleted
* @throws EntityNotFoundException if (at least one) given distribution set does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_DELETE_REPOSITORY)
void delete(@NotEmpty Collection<Long> ids);
default String permissionGroup() {
return "REPOSITORY";
}
}

View File

@@ -17,19 +17,26 @@ import java.util.Optional;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleCreate;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataCreate;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleMetadataUpdate;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleUpdate;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.Type;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
@@ -38,19 +45,24 @@ import org.springframework.security.access.prepost.PreAuthorize;
/**
* Service for managing {@link SoftwareModule}s.
*/
public interface SoftwareModuleManagement extends RepositoryManagement<SoftwareModule, SoftwareModuleCreate, SoftwareModuleUpdate> {
public interface SoftwareModuleManagement<T extends SoftwareModule>
extends RepositoryManagement<T, SoftwareModuleManagement.Create, SoftwareModuleManagement.Update> {
@Override
default String permissionGroup() {
return "SOFTWARE_MODULE";
}
/**
* Creates a list of software module meta-data entries.
*
* @param metadata the meta-data entries to create
* @return the updated or created software module meta-data entries
* @throws EntityAlreadyExistsException in case one of the meta-data entry already exists for the specific key
* @throws EntityNotFoundException if software module with given ID does not exist
* @throws AssignmentQuotaExceededException if the maximum number of {@link SoftwareModuleMetadata} entries is exceeded for the addressed
* {@link SoftwareModule}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
void createMetadata(@NotNull @Valid Collection<SoftwareModuleMetadataCreate> metadata);
/**
@@ -60,7 +72,7 @@ public interface SoftwareModuleManagement extends RepositoryManagement<SoftwareM
* @return a paged result of all meta-data entries for a given software module id
* @throws EntityNotFoundException if software module with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
List<SoftwareModuleMetadata> getMetadata(long id);
/**
@@ -71,7 +83,7 @@ public interface SoftwareModuleManagement extends RepositoryManagement<SoftwareM
* @return a paged result of all meta-data entries for a given software module id
* @throws EntityNotFoundException if software module with given ID does not exist ot the
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
SoftwareModuleMetadata getMetadata(long id, String key);
/**
@@ -82,7 +94,7 @@ public interface SoftwareModuleManagement extends RepositoryManagement<SoftwareM
* @return a paged result of all meta-data entries for a given software module id
* @throws EntityNotFoundException if software module with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Page<SoftwareModuleMetadata> findMetaDataBySoftwareModuleIdAndTargetVisible(long id, @NotNull Pageable pageable);
/**
@@ -95,7 +107,7 @@ public interface SoftwareModuleManagement extends RepositoryManagement<SoftwareM
* @throws AssignmentQuotaExceededException if the maximum number of {@link SoftwareModuleMetadata}
* entries is exceeded for the addressed {@link SoftwareModule}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
SoftwareModuleMetadata updateMetadata(@NotNull @Valid SoftwareModuleMetadataCreate metadata);
/**
@@ -105,7 +117,7 @@ public interface SoftwareModuleManagement extends RepositoryManagement<SoftwareM
* @return the updated meta-data entry
* @throws EntityNotFoundException in case the meta-data entry does not exist and cannot be updated
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
SoftwareModuleMetadata updateMetadata(@NotNull @Valid SoftwareModuleMetadataUpdate update);
/**
@@ -113,10 +125,10 @@ public interface SoftwareModuleManagement extends RepositoryManagement<SoftwareM
*
* @param id where meta-data has to be deleted
* @param key of the meta-data element
* @throws EntityNotFoundException if software module with given ID does not exist or the key is not found
* @return true if really deleted, false if not
* @throws EntityNotFoundException if software module with given ID does not exist or the key is not found
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
void deleteMetadata(long id, @NotEmpty String key);
/**
@@ -125,7 +137,7 @@ public interface SoftwareModuleManagement extends RepositoryManagement<SoftwareM
* @param id the software module id
* @throws EntityNotFoundException if software module with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
void lock(long id);
/**
@@ -136,7 +148,7 @@ public interface SoftwareModuleManagement extends RepositoryManagement<SoftwareM
* @param id the software module id
* @throws EntityNotFoundException if software module with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
void unlock(long id);
/**
@@ -147,8 +159,8 @@ public interface SoftwareModuleManagement extends RepositoryManagement<SoftwareM
* @return all {@link SoftwareModule}s that are assigned to given {@link DistributionSet}.
* @throws EntityNotFoundException if distribution set with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Page<SoftwareModule> findByAssignedTo(long distributionSetId, @NotNull Pageable pageable);
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Page<T> findByAssignedTo(long distributionSetId, @NotNull Pageable pageable);
/**
* Filter {@link SoftwareModule}s with given {@link SoftwareModule#getName()} or {@link SoftwareModule#getVersion()}
@@ -160,8 +172,8 @@ public interface SoftwareModuleManagement extends RepositoryManagement<SoftwareM
* @return the page of found {@link SoftwareModule}
* @throws EntityNotFoundException if given software module type does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Slice<SoftwareModule> findByTextAndType(String searchText, Long typeId, @NotNull Pageable pageable);
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Slice<T> findByTextAndType(String searchText, Long typeId, @NotNull Pageable pageable);
/**
* Retrieves {@link SoftwareModule} by their name AND version AND type.
@@ -172,8 +184,8 @@ public interface SoftwareModuleManagement extends RepositoryManagement<SoftwareM
* @return the found {@link SoftwareModule}
* @throws EntityNotFoundException if software module type with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Optional<SoftwareModule> findByNameAndVersionAndType(@NotEmpty String name, @NotEmpty String version, long typeId);
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Optional<T> findByNameAndVersionAndType(@NotEmpty String name, @NotEmpty String version, long typeId);
/**
* Retrieves the {@link SoftwareModule}s by their {@link SoftwareModuleType}
@@ -183,10 +195,10 @@ public interface SoftwareModuleManagement extends RepositoryManagement<SoftwareM
* @return the found {@link SoftwareModule}s
* @throws EntityNotFoundException if software module type with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Slice<SoftwareModule> findByType(long typeId, @NotNull Pageable pageable);
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Slice<T> findByType(long typeId, @NotNull Pageable pageable);
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Map<Long, List<SoftwareModuleMetadata>> findMetaDataBySoftwareModuleIdsAndTargetVisible(Collection<Long> moduleIds);
/**
@@ -196,6 +208,48 @@ public interface SoftwareModuleManagement extends RepositoryManagement<SoftwareM
* @return count of {@link SoftwareModule}s that are assigned to given {@link DistributionSet}.
* @throws EntityNotFoundException if distribution set with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
long countByAssignedTo(long distributionSetId);
@SuperBuilder
@Getter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
final class Create extends UpdateCreate {
private boolean encrypted;
}
@SuperBuilder
@Getter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
final class Update extends UpdateCreate implements Identifiable<Long> {
@NotNull
private Long id;
@Builder.Default
private Boolean locked = false;
}
@SuperBuilder
@Getter
class UpdateCreate {
@ValidString
@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE)
@NotNull(groups = Create.class)
private String name;
@ValidString
@Size(min = 1, max = NamedVersionedEntity.VERSION_MAX_SIZE)
@NotNull(groups = Create.class)
private String version;
@ValidString
@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE)
private String description;
@ValidString
@Size(max = SoftwareModule.VENDOR_MAX_SIZE)
private String vendor;
private SoftwareModuleType type;
}
}

View File

@@ -12,30 +12,78 @@ package org.eclipse.hawkbit.repository;
import java.util.Optional;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeCreate;
import org.eclipse.hawkbit.repository.builder.SoftwareModuleTypeUpdate;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.Type;
import org.springframework.security.access.prepost.PreAuthorize;
/**
* Service for managing {@link SoftwareModuleType}s.
*/
public interface SoftwareModuleTypeManagement
extends RepositoryManagement<SoftwareModuleType, SoftwareModuleTypeCreate, SoftwareModuleTypeUpdate> {
public interface SoftwareModuleTypeManagement<T extends SoftwareModuleType>
extends RepositoryManagement<T, SoftwareModuleTypeManagement.Create, SoftwareModuleTypeManagement.Update> {
/**
* @param key to search for
* @return {@link SoftwareModuleType} in the repository with given {@link SoftwareModuleType#getKey()}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Optional<SoftwareModuleType> findByKey(@NotEmpty String key);
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Optional<T> findByKey(@NotEmpty String key);
/**
* @param name to search for
* @return all {@link SoftwareModuleType}s in the repository with given {@link SoftwareModuleType#getName()}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY)
Optional<SoftwareModuleType> findByName(@NotEmpty String name);
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Optional<T> findByName(@NotEmpty String name);
@SuperBuilder
@Getter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
final class Create extends UpdateCreate {
@Size(min = 1, max = Type.KEY_MAX_SIZE)
@NotNull
private String key;
@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE)
@NotNull
private String name;
@Builder.Default
private int maxAssignments = 1;
}
@SuperBuilder
@Getter
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
final class Update extends UpdateCreate implements Identifiable<Long> {
@NotNull
private Long id;
}
@SuperBuilder
@Getter
class UpdateCreate {
@ValidString
@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE)
private String description;
@ValidString
@Size(max = Type.COLOUR_MAX_SIZE)
private String colour;
}
}

View File

@@ -76,7 +76,7 @@ public interface SystemManagement {
/**
* @return {@link TenantMetaData} of {@link TenantAware#getCurrentTenant()}
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION_READ + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.IS_CONTROLLER)
@@ -85,7 +85,7 @@ public interface SystemManagement {
/**
* @return {@link TenantMetaData} of {@link TenantAware#getCurrentTenant()} without details ({@link TenantMetaData#getDefaultDsType()})
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION_READ + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.IS_CONTROLLER)

View File

@@ -15,12 +15,12 @@ import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AU
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_CREATE_TARGET;
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_DELETE_TARGET;
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_PREFIX;
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY;
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_READ_REPOSITORY;
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY_AND_UPDATE_TARGET;
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_READ_TARGET;
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_ROLLOUT_MANAGEMENT_READ_AND_TARGET_READ;
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_SUFFIX;
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_UPDATE_REPOSITORY;
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_UPDATE_REPOSITORY;
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET;
import java.util.Collection;
@@ -752,7 +752,7 @@ public interface TargetManagement {
* @throws EntityAlreadyExistsException in case one of the metad-ata entry already exists for the specific key
* @throws AssignmentQuotaExceededException if the maximum number of meta-data entries is exceeded for the addressed {@link Target}
*/
@PreAuthorize(HAS_AUTH_UPDATE_REPOSITORY)
@PreAuthorize(HAS_UPDATE_REPOSITORY)
void createMetadata(@NotEmpty String controllerId, @NotEmpty Map<String, String> metadata);
/**
@@ -762,7 +762,7 @@ public interface TargetManagement {
* @return the found target meta-data
* @throws EntityNotFoundException if target with given ID does not exist
*/
@PreAuthorize(HAS_AUTH_READ_REPOSITORY)
@PreAuthorize(HAS_READ_REPOSITORY)
Map<String, String> getMetadata(@NotEmpty String controllerId);
/**
@@ -773,7 +773,7 @@ public interface TargetManagement {
* @param value meta data-entry to be new value
* @throws EntityNotFoundException in case the meta-data entry does not exist and cannot be updated
*/
@PreAuthorize(HAS_AUTH_UPDATE_REPOSITORY)
@PreAuthorize(HAS_UPDATE_REPOSITORY)
void updateMetadata(@NotEmpty String controllerId, @NotNull String key, @NotNull String value);
/**
@@ -783,6 +783,6 @@ public interface TargetManagement {
* @param key of the meta data element
* @throws EntityNotFoundException if given target does not exist
*/
@PreAuthorize(HAS_AUTH_UPDATE_REPOSITORY)
@PreAuthorize(HAS_UPDATE_REPOSITORY)
void deleteMetadata(@NotEmpty String controllerId, @NotEmpty String key);
}

View File

@@ -25,6 +25,7 @@ import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterSyntaxException;
import org.eclipse.hawkbit.repository.exception.RSQLParameterUnsupportedFieldException;
import org.eclipse.hawkbit.repository.model.Tag;
import org.eclipse.hawkbit.repository.model.Target;
import org.eclipse.hawkbit.repository.model.TargetTag;
import org.springframework.data.domain.Page;
@@ -53,7 +54,7 @@ public interface TargetTagManagement {
* @throws ConstraintViolationException if fields are not filled as specified. Check {@link TagCreate} for field constraints.
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET)
TargetTag create(@NotNull @Valid TagCreate create);
TargetTag create(@NotNull @Valid TagCreate<Tag> create);
/**
* Created multiple {@link TargetTag}s.
@@ -64,7 +65,7 @@ public interface TargetTagManagement {
* @throws ConstraintViolationException if fields are not filled as specified. Check {@link TagCreate} for field constraints.
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_CREATE_TARGET)
List<TargetTag> create(@NotNull @Valid Collection<TagCreate> creates);
List<TargetTag> create(@NotNull @Valid Collection<TagCreate<Tag>> creates);
/**
* Deletes {@link TargetTag} with given name.

View File

@@ -25,7 +25,7 @@ public interface TenantStatsManagement {
* @return collected statistics
*/
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.HAS_AUTH_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.HAS_READ_REPOSITORY + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.HAS_AUTH_READ_TARGET + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.HAS_AUTH_TENANT_CONFIGURATION_READ + SpringEvalExpressions.HAS_AUTH_OR
+ SpringEvalExpressions.IS_SYSTEM_CODE)

View File

@@ -1,29 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations 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.builder;
import org.eclipse.hawkbit.repository.model.DistributionSet;
/**
* Builder for {@link DistributionSet}.
*/
public interface DistributionSetBuilder {
/**
* @param id of the updatable entity
* @return builder instance
*/
DistributionSetUpdate update(long id);
/**
* @return builder instance
*/
DistributionSetCreate create();
}

View File

@@ -1,79 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations 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.builder;
import java.util.Collection;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.eclipse.hawkbit.repository.model.BaseEntity;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
import org.eclipse.hawkbit.repository.model.Type;
/**
* Builder to create a new {@link DistributionSet} entry. Defines all fields
* that can be set at creation time. Other fields are set by the repository
* automatically, e.g. {@link BaseEntity#getCreatedAt()}.
*/
public interface DistributionSetCreate {
/**
* @param name for {@link DistributionSet#getName()}
* @return updated builder instance
*/
DistributionSetCreate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name);
/**
* @param version for {@link DistributionSet#getVersion()}
* @return updated builder instance
*/
DistributionSetCreate version(@Size(min = 1, max = NamedVersionedEntity.VERSION_MAX_SIZE) @NotNull String version);
/**
* @param description for {@link DistributionSet#getDescription()}
* @return updated builder instance
*/
DistributionSetCreate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description);
/**
* @param typeKey for {@link DistributionSet#getType()}
* @return updated builder instance
*/
DistributionSetCreate type(@Size(min = 1, max = Type.KEY_MAX_SIZE) @NotNull String typeKey);
/**
* @param type for {@link DistributionSet#getType()}
* @return updated builder instance
*/
default DistributionSetCreate type(@NotNull final DistributionSetType type) {
return type(type.getKey());
}
/**
* @param modules for {@link DistributionSet#getModules()}
* @return updated builder instance
*/
DistributionSetCreate modules(Collection<Long> modules);
/**
* @param requiredMigrationStep for {@link DistributionSet#isRequiredMigrationStep()}
* @return updated builder instance
*/
DistributionSetCreate requiredMigrationStep(Boolean requiredMigrationStep);
/**
* @return peek on current state of {@link DistributionSet} in the builder
*/
DistributionSet build();
}

View File

@@ -1,29 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations 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.builder;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
/**
* Builder for {@link DistributionSetType}.
*/
public interface DistributionSetTypeBuilder {
/**
* @param id of the updatable entity
* @return builder instance
*/
DistributionSetTypeUpdate update(long id);
/**
* @return builder instance
*/
DistributionSetTypeCreate create();
}

View File

@@ -1,104 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations 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.builder;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.eclipse.hawkbit.repository.model.BaseEntity;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.Type;
/**
* Builder to create a new {@link DistributionSetType} entry. Defines all fields
* that can be set at creation time. Other fields are set by the repository
* automatically, e.g. {@link BaseEntity#getCreatedAt()}.
*/
public interface DistributionSetTypeCreate {
/**
* @param key for {@link DistributionSetType#getKey()}
* @return updated builder instance
*/
DistributionSetTypeCreate key(@Size(min = 1, max = Type.KEY_MAX_SIZE) @NotNull String key);
/**
* @param name for {@link DistributionSetType#getName()}
* @return updated builder instance
*/
DistributionSetTypeCreate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name);
/**
* @param description for {@link DistributionSetType#getDescription()}
* @return updated builder instance
*/
DistributionSetTypeCreate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description);
/**
* @param colour for {@link DistributionSetType#getColour()}
* @return updated builder instance
*/
DistributionSetTypeCreate colour(@Size(max = Type.COLOUR_MAX_SIZE) String colour);
/**
* @param mandatory for {@link DistributionSetType#getMandatoryModuleTypes()}
* @return updated builder instance
*/
DistributionSetTypeCreate mandatory(Collection<Long> mandatory);
/**
* @param mandatory for {@link DistributionSetType#getMandatoryModuleTypes()}
* @return updated builder instance
*/
default DistributionSetTypeCreate mandatory(final Long mandatory) {
return mandatory(Collections.singletonList(mandatory));
}
/**
* @param mandatory for {@link DistributionSetType#getOptionalModuleTypes()}
* @return updated builder instance
*/
default DistributionSetTypeCreate mandatory(final SoftwareModuleType mandatory) {
return mandatory(Optional.ofNullable(mandatory).map(SoftwareModuleType::getId).orElse(null));
}
/**
* @param optional for {@link DistributionSetType#getOptionalModuleTypes()}
* @return updated builder instance
*/
DistributionSetTypeCreate optional(Collection<Long> optional);
/**
* @param optional for {@link DistributionSetType#getOptionalModuleTypes()}
* @return updated builder instance
*/
default DistributionSetTypeCreate optional(final Long optional) {
return optional(Collections.singletonList(optional));
}
/**
* @param optional for {@link DistributionSetType#getOptionalModuleTypes()}
* @return updated builder instance
*/
default DistributionSetTypeCreate optional(final SoftwareModuleType optional) {
return optional(Optional.ofNullable(optional).map(SoftwareModuleType::getId).orElse(null));
}
/**
* @return peek on current state of {@link DistributionSetType} in the builder
*/
DistributionSetType build();
}

View File

@@ -1,49 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations 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.builder;
import java.util.Collection;
import jakarta.validation.constraints.Size;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.Type;
/**
* Builder to update an existing {@link DistributionSetType} entry. Defines all
* fields that can be updated.
*/
public interface DistributionSetTypeUpdate {
/**
* @param description for {@link DistributionSetType#getDescription()}
* @return updated builder instance
*/
DistributionSetTypeUpdate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description);
/**
* @param colour for {@link DistributionSetType#getColour()}
* @return updated builder instance
*/
DistributionSetTypeUpdate colour(@Size(max = Type.COLOUR_MAX_SIZE) String colour);
/**
* @param mandatory for {@link DistributionSetType#getMandatoryModuleTypes()}
* @return updated builder instance
*/
DistributionSetTypeUpdate mandatory(Collection<Long> mandatory);
/**
* @param optional for {@link DistributionSetType#getOptionalModuleTypes()}
* @return updated builder instance
*/
DistributionSetTypeUpdate optional(Collection<Long> optional);
}

View File

@@ -1,54 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations 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.builder;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Null;
import jakarta.validation.constraints.Size;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
/**
* Builder to update an existing {@link DistributionSet} entry. Defines all fields that can be updated.
*/
public interface DistributionSetUpdate {
/**
* @param name for {@link DistributionSet#getName()}
* @return updated builder instance
*/
DistributionSetUpdate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name);
/**
* @param version for {@link DistributionSet#getVersion()}
* @return updated builder instance
*/
DistributionSetUpdate version(@Size(min = 1, max = NamedVersionedEntity.VERSION_MAX_SIZE) @NotNull String version);
/**
* @param description for {@link DistributionSet#getDescription()}
* @return updated builder instance
*/
DistributionSetUpdate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description);
/**
* @param locked update request if any. If not empty shall be <code>true</code>
* @return updated builder instance
*/
DistributionSetUpdate locked(@Null Boolean locked);
/**
* @param requiredMigrationStep for {@link DistributionSet#isRequiredMigrationStep()}
* @return updated builder instance
*/
DistributionSetUpdate requiredMigrationStep(Boolean requiredMigrationStep);
}

View File

@@ -1,29 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations 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.builder;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
/**
* Builder for {@link SoftwareModule}.
*/
public interface SoftwareModuleBuilder {
/**
* @param id of the updatable entity
* @return builder instance
*/
SoftwareModuleUpdate update(long id);
/**
* @return builder instance
*/
SoftwareModuleCreate create();
}

View File

@@ -1,77 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations 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.builder;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.eclipse.hawkbit.repository.model.BaseEntity;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.NamedVersionedEntity;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.Type;
/**
* Builder to create a new {@link SoftwareModule} entry. Defines all fields that
* can be set at creation time. Other fields are set by the repository
* automatically, e.g. {@link BaseEntity#getCreatedAt()}.
*/
public interface SoftwareModuleCreate {
/**
* @param name for {@link SoftwareModule#getName()}
* @return updated builder instance
*/
SoftwareModuleCreate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name);
/**
* @param version for {@link SoftwareModule#getVersion()}
* @return updated builder instance
*/
SoftwareModuleCreate version(@Size(min = 1, max = NamedVersionedEntity.VERSION_MAX_SIZE) @NotNull String version);
/**
* @param description for {@link SoftwareModule#getDescription()}
* @return updated builder instance
*/
SoftwareModuleCreate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description);
/**
* @param vendor for {@link SoftwareModule#getVendor()}
* @return updated builder instance
*/
SoftwareModuleCreate vendor(@Size(max = SoftwareModule.VENDOR_MAX_SIZE) String vendor);
/**
* @param typeKey for {@link SoftwareModule#getType()}
* @return updated builder instance
*/
SoftwareModuleCreate type(@Size(min = 1, max = Type.KEY_MAX_SIZE) @NotNull String typeKey);
/**
* @param type for {@link SoftwareModule#getType()}
* @return updated builder instance
*/
default SoftwareModuleCreate type(@NotNull final SoftwareModuleType type) {
return type(type.getKey());
}
/**
* @param encrypted if should be encrypted
* @return updated builder instance
*/
SoftwareModuleCreate encrypted(boolean encrypted);
/**
* @return peek on current state of {@link SoftwareModule} in the builder
*/
SoftwareModule build();
}

View File

@@ -1,29 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations 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.builder;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
/**
* Builder for {@link SoftwareModuleType}.
*/
public interface SoftwareModuleTypeBuilder {
/**
* @param id of the updatable entity
* @return builder instance
*/
SoftwareModuleTypeUpdate update(long id);
/**
* @return builder instance
*/
SoftwareModuleTypeCreate create();
}

View File

@@ -1,62 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations 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.builder;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import org.eclipse.hawkbit.repository.model.BaseEntity;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.Type;
/**
* Builder to create a new {@link SoftwareModuleType} entry. Defines all fields
* that can be set at creation time. Other fields are set by the repository
* automatically, e.g. {@link BaseEntity#getCreatedAt()}.
*/
public interface SoftwareModuleTypeCreate {
/**
* @param key for {@link SoftwareModuleType#getKey()}
* @return updated builder instance
*/
SoftwareModuleTypeCreate key(@Size(min = 1, max = Type.KEY_MAX_SIZE) @NotNull String key);
/**
* @param name for {@link SoftwareModuleType#getName()}
* @return updated builder instance
*/
SoftwareModuleTypeCreate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name);
/**
* @param description for {@link SoftwareModuleType#getDescription()}
* @return updated builder instance
*/
SoftwareModuleTypeCreate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description);
/**
* @param colour for {@link SoftwareModuleType#getColour()}
* @return updated builder instance
*/
SoftwareModuleTypeCreate colour(@Size(max = Type.COLOUR_MAX_SIZE) String colour);
/**
* @param maxAssignments for {@link SoftwareModuleType#getMaxAssignments()}
* @return updated builder instance
*/
SoftwareModuleTypeCreate maxAssignments(int maxAssignments);
/**
* @return peek on current state of {@link SoftwareModuleType} in the
* builder
*/
SoftwareModuleType build();
}

View File

@@ -1,35 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations 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.builder;
import jakarta.validation.constraints.Size;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
import org.eclipse.hawkbit.repository.model.Type;
/**
* Builder to update an existing {@link SoftwareModuleType} entry. Defines all
* fields that can be updated.
*/
public interface SoftwareModuleTypeUpdate {
/**
* @param description for {@link SoftwareModuleType#getDescription()}
* @return updated builder instance
*/
SoftwareModuleTypeUpdate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description);
/**
* @param colour for {@link SoftwareModuleType#getColour()}
* @return updated builder instance
*/
SoftwareModuleTypeUpdate colour(@Size(max = Type.COLOUR_MAX_SIZE) String colour);
}

View File

@@ -1,41 +0,0 @@
/**
* Copyright (c) 2015 Bosch Software Innovations 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.builder;
import jakarta.validation.constraints.Null;
import jakarta.validation.constraints.Size;
import org.eclipse.hawkbit.repository.model.NamedEntity;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
/**
* Builder to update an existing {@link SoftwareModule} entry. Defines all
* fields that can be updated.
*/
public interface SoftwareModuleUpdate {
/**
* @param description for {@link SoftwareModule#getDescription()}
* @return updated builder instance
*/
SoftwareModuleUpdate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description);
/**
* @param vendor for {@link SoftwareModule#getVendor()}
* @return updated builder instance
*/
SoftwareModuleUpdate vendor(@Size(max = SoftwareModule.VENDOR_MAX_SIZE) String vendor);
/**
* @param locked update request if any. If not empty shall be <code>true</code>
* @return updated builder instance
*/
SoftwareModuleUpdate locked(@Null Boolean locked);
}

View File

@@ -14,7 +14,7 @@ import org.eclipse.hawkbit.repository.model.Tag;
/**
* Builder for {@link Tag}.
*/
public interface TagBuilder {
public interface TagBuilder<T extends Tag> {
/**
* @param id of the updatable entity
@@ -25,5 +25,5 @@ public interface TagBuilder {
/**
* @return builder instance
*/
TagCreate create();
TagCreate<T> create();
}

View File

@@ -21,28 +21,28 @@ import org.eclipse.hawkbit.repository.model.Tag;
* at creation time. Other fields are set by the repository automatically, e.g.
* {@link BaseEntity#getCreatedAt()}.
*/
public interface TagCreate {
public interface TagCreate<T extends Tag> {
/**
* @param name for {@link Tag#getName()}
* @return updated builder instance
*/
TagCreate name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name);
TagCreate<T> name(@Size(min = 1, max = NamedEntity.NAME_MAX_SIZE) @NotNull String name);
/**
* @param description for {@link Tag#getDescription()}
* @return updated builder instance
*/
TagCreate description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description);
TagCreate<T> description(@Size(max = NamedEntity.DESCRIPTION_MAX_SIZE) String description);
/**
* @param colour for {@link Tag#getColour()}
* @return updated builder instance
*/
TagCreate colour(@Size(max = Tag.COLOUR_MAX_SIZE) String colour);
TagCreate<T> colour(@Size(max = Tag.COLOUR_MAX_SIZE) String colour);
/**
* @return peek on current state of {@link Tag} in the builder
*/
Tag build();
T build();
}

View File

@@ -11,6 +11,8 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
@@ -19,6 +21,8 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
* Exception indicating that an artifact's binary does not exist anymore. This
* might be caused due to the soft deletion of a {@link SoftwareModule}.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ArtifactBinaryNoLongerExistsException extends AbstractServerRtException {
@Serial

View File

@@ -11,9 +11,13 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public final class ArtifactBinaryNotFoundException extends AbstractServerRtException {
@Serial

View File

@@ -11,12 +11,16 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* Thrown if artifact deletion failed.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public final class ArtifactDeleteFailedException extends AbstractServerRtException {
@Serial

View File

@@ -11,9 +11,13 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public final class ArtifactUploadFailedException extends AbstractServerRtException {
@Serial

View File

@@ -9,6 +9,8 @@
*/
package org.eclipse.hawkbit.repository.exception;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.repository.model.BaseEntity;
@@ -16,6 +18,8 @@ import org.eclipse.hawkbit.repository.model.BaseEntity;
/**
* Thrown if assignment quota is exceeded
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AssignmentQuotaExceededException extends AbstractServerRtException {
private static final String ASSIGNMENT_QUOTA_EXCEEDED_MESSAGE = "Quota exceeded: Cannot assign %s more %s entities to %s '%s'. The maximum is %s.";

View File

@@ -11,15 +11,17 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* The {@link AutoConfirmationAlreadyActiveException} is thrown when auto
* confirmation is already active for a device but the
* {@link org.eclipse.hawkbit.repository.ConfirmationManagement#activateAutoConfirmation}
* is getting called.
* The {@link AutoConfirmationAlreadyActiveException} is thrown when auto confirmation is already active for a device but the
* {@link org.eclipse.hawkbit.repository.ConfirmationManagement#activateAutoConfirmation} is getting called.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class AutoConfirmationAlreadyActiveException extends AbstractServerRtException {
@Serial

View File

@@ -11,15 +11,17 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* Thrown if cancellation of action is requested where the action cannot be
* cancelled (e.g. the action is not active or is already a canceled action) or
* controller provides cancellation feedback on an action that is actually not
* in canceling state.
* Thrown if cancellation of action is requested where the action cannot be cancelled (e.g. the action is not active or is already a canceled
* action) or controller provides cancellation feedback on an action that is actually not in canceling state.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public final class CancelActionNotAllowedException extends AbstractServerRtException {
@Serial

View File

@@ -11,14 +11,17 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* {@link ConcurrentModificationException} is thrown when a given entity in's
* actual and cannot be stored within the current session. Reason could be that
* it has been changed within another session.
* {@link ConcurrentModificationException} is thrown when a given entity in's actual and cannot be stored within the current session.
* Reason could be that it has been changed within another session.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ConcurrentModificationException extends AbstractServerRtException {
@Serial

View File

@@ -11,6 +11,8 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.repository.model.BaseEntity;
@@ -18,6 +20,8 @@ import org.eclipse.hawkbit.repository.model.BaseEntity;
/**
* Thrown if assignment quota is exceeded
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeletedException extends AbstractServerRtException {
@Serial

View File

@@ -11,15 +11,18 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.repository.model.DistributionSet;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
/**
* Thrown if the user tries to assign modules to a {@link DistributionSet} that
* has to {@link DistributionSetType} defined.
* Thrown if the user tries to assign modules to a {@link DistributionSet} that has to {@link DistributionSetType} defined.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DistributionSetTypeUndefinedException extends AbstractServerRtException {
@Serial

View File

@@ -11,13 +11,17 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* the {@link EntityAlreadyExistsException} is thrown when an entity is tried to
* be saved which already exists or which violates unique key constraints.
* the {@link EntityAlreadyExistsException} is thrown when an entity is tried to be saved which already exists or which violates unique key
* constraints.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class EntityAlreadyExistsException extends AbstractServerRtException {
@Serial

View File

@@ -14,7 +14,10 @@ import java.util.Collection;
import java.util.Map;
import java.util.stream.Collectors;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.repository.model.BaseEntity;
@@ -22,14 +25,18 @@ import org.eclipse.hawkbit.repository.model.BaseEntity;
/**
* the {@link EntityNotFoundException} is thrown when a entity queried but not found.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Getter
public class EntityNotFoundException extends AbstractServerRtException {
@Serial
private static final long serialVersionUID = 1L;
public static final String KEY = "key";
public static final String ENTITY_ID = "entityId";
public static final String TYPE = "type";
@Serial
private static final long serialVersionUID = 1L;
private static final SpServerError THIS_ERROR = SpServerError.SP_REPO_ENTITY_NOT_EXISTS;
private static final int ENTITY_STRING_MAX_LENGTH = 100;

View File

@@ -11,13 +11,16 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* the {@link EntityReadOnlyException} is thrown when a entity is in read only
* mode and a user tries to change it.
* the {@link EntityReadOnlyException} is thrown when a entity is in read only mode and a user tries to change it.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class EntityReadOnlyException extends AbstractServerRtException {
@Serial

View File

@@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.exception;
import static org.eclipse.hawkbit.repository.SizeConversionHelper.byteValueToReadableString;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
@@ -19,6 +20,7 @@ import org.eclipse.hawkbit.exception.SpServerError;
* Thrown if file size quota is exceeded
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class FileSizeQuotaExceededException extends AbstractServerRtException {
private static final String MAX_ARTIFACT_SIZE_EXCEEDED = "Maximum artifact size (%s) exceeded.";

View File

@@ -11,12 +11,16 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* Thrown when force quitting an actions is not allowed. e.g. the action is not active, or it is not canceled before.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public final class ForceQuitActionNotAllowedException extends AbstractServerRtException {
@Serial

View File

@@ -14,6 +14,7 @@ import java.util.Collection;
import java.util.Collections;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.repository.model.DistributionSet;
@@ -24,6 +25,7 @@ import org.eclipse.hawkbit.repository.model.TargetType;
* Thrown if user tries to assign a {@link DistributionSet} to a {@link Target} that has an incompatible {@link TargetType}
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class IncompatibleTargetTypeException extends AbstractServerRtException {
@Serial

View File

@@ -11,13 +11,16 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* Thrown if a distribution set is assigned to a a target that is incomplete
* (i.e. mandatory modules are missing).
* Thrown if a distribution set is assigned to a target that is incomplete (i.e. mandatory modules are missing).
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public final class IncompleteDistributionSetException extends AbstractServerRtException {
@Serial

View File

@@ -11,35 +11,30 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* Exception which is thrown in case the current security context object does
* not hold a required authority/permission.
* Exception which is thrown in case the current security context object does not hold a required authority/permission.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InsufficientPermissionException extends AbstractServerRtException {
@Serial
private static final long serialVersionUID = 1L;
/**
* creates new InsufficientPermissionException.
*
* @param cause the cause of the exception
*/
public InsufficientPermissionException(final Throwable cause) {
super(SpServerError.SP_INSUFFICIENT_PERMISSION, cause);
}
/**
* creates new InsufficientPermissionException.
*/
public InsufficientPermissionException(final String message) {
super(message, SpServerError.SP_INSUFFICIENT_PERMISSION);
}
public InsufficientPermissionException() {
super(SpServerError.SP_INSUFFICIENT_PERMISSION, null);
this((String)null);
}
}

View File

@@ -12,12 +12,16 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* Thrown if an action type for auto-assignment is neither 'forced', nor 'soft'.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InvalidAutoAssignActionTypeException extends AbstractServerRtException {
@Serial

View File

@@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
@@ -20,6 +21,7 @@ import org.eclipse.hawkbit.exception.SpServerError;
* listed as enum {@link Reason}.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InvalidConfirmationFeedbackException extends AbstractServerRtException {
@Serial

View File

@@ -11,9 +11,13 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InvalidDistributionSetException extends AbstractServerRtException {
@Serial

View File

@@ -11,12 +11,16 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* Thrown if MD5 checksum check fails.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InvalidMD5HashException extends AbstractServerRtException {
@Serial

View File

@@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
@@ -21,6 +22,7 @@ import org.eclipse.hawkbit.exception.SpServerError;
* time.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InvalidMaintenanceScheduleException extends AbstractServerRtException {
@Serial

View File

@@ -11,12 +11,16 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* Thrown if SHA1 checksum check fails.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InvalidSHA1HashException extends AbstractServerRtException {
@Serial

View File

@@ -11,12 +11,16 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* Thrown if SHA256 checksum check fails.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InvalidSHA256HashException extends AbstractServerRtException {
@Serial

View File

@@ -11,12 +11,16 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* Exception which is thrown when trying to set an invalid target address.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InvalidTargetAddressException extends AbstractServerRtException {
@Serial

View File

@@ -12,9 +12,13 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InvalidTargetAttributeException extends AbstractServerRtException {
@Serial

View File

@@ -11,13 +11,16 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* The {@link #InvalidTenantConfigurationKeyException} is thrown when an invalid
* configuration key is used.
* The {@link #InvalidTenantConfigurationKeyException} is thrown when an invalid configuration key is used.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class InvalidTenantConfigurationKeyException extends AbstractServerRtException {
@Serial

View File

@@ -11,6 +11,8 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
import org.eclipse.hawkbit.repository.model.BaseEntity;
@@ -18,6 +20,8 @@ import org.eclipse.hawkbit.repository.model.BaseEntity;
/**
* Thrown if there is attempt to functionally modify a locked entity
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class LockedException extends AbstractServerRtException {
@Serial

View File

@@ -11,12 +11,16 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* Thrown if repository operation is no longer supported.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public final class MethodNotSupportedException extends AbstractServerRtException {
@Serial

View File

@@ -11,13 +11,16 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* This exception is thrown if an operation requires multiassignments, but the
* feature is not enabled.
* This exception is thrown if an operation requires multi-assignments, but the feature is not enabled.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class MultiAssignmentIsNotEnabledException extends AbstractServerRtException {
@Serial

View File

@@ -11,13 +11,16 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* This exception is thrown if multi assignments is enabled and an target
* distribution set assignment request does not contain a weight value
* This exception is thrown if multi assignments is enabled and a target distribution set assignment request does not contain a weight value
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class NoWeightProvidedInMultiAssignmentModeException extends AbstractServerRtException {
@Serial

View File

@@ -19,8 +19,8 @@ import org.eclipse.hawkbit.exception.SpServerError;
/**
* Exception used by the REST API in case of RSQL search filter query.
*/
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class RSQLParameterSyntaxException extends AbstractServerRtException {
@Serial

View File

@@ -19,8 +19,8 @@ import org.eclipse.hawkbit.exception.SpServerError;
/**
* Exception used by the REST API in case of invalid field name in the rsql search parameter.
*/
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class RSQLParameterUnsupportedFieldException extends AbstractServerRtException {
@Serial

View File

@@ -11,14 +11,17 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.exception.AbstractServerRtException;
import org.eclipse.hawkbit.exception.SpServerError;
/**
* the {@link RolloutIllegalStateException} is thrown when a rollout is changing
* it's state which is not valid. E.g. trying to start a already running
* rollout, or trying to resume a already finished rollout.
* the {@link RolloutIllegalStateException} is thrown when a rollout is changing it's state which is not valid. E.g. trying to start an already
* running rollout, or trying to resume a already finished rollout.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class RolloutIllegalStateException extends AbstractServerRtException {
@Serial

View File

@@ -12,6 +12,8 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import java.lang.annotation.Target;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.repository.model.Action;
import org.eclipse.hawkbit.repository.model.SoftwareModule;
@@ -19,6 +21,8 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule;
* the {@link SoftwareModuleNotAssignedToTargetException} is thrown when a {@link SoftwareModule} is requested as part of an {@link Action}
* that has however never been assigned to the {@link Target}.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SoftwareModuleNotAssignedToTargetException extends EntityNotFoundException {
@Serial

View File

@@ -11,16 +11,18 @@ package org.eclipse.hawkbit.repository.exception;
import java.io.Serial;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.eclipse.hawkbit.repository.model.DistributionSetType;
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
/**
* the {@link SoftwareModuleTypeNotInDistributionSetTypeException} is thrown
* when a {@link SoftwareModuleType} is requested as part of a
* {@link DistributionSetType} but actually neither
* {@link DistributionSetType#getMandatoryModuleTypes()} or
* The {@link SoftwareModuleTypeNotInDistributionSetTypeException} is thrown when a {@link SoftwareModuleType} is requested as part of a
* {@link DistributionSetType} but actually neither {@link DistributionSetType#getMandatoryModuleTypes()} or
* {@link DistributionSetType#getOptionalModuleTypes()}.
*/
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class SoftwareModuleTypeNotInDistributionSetTypeException extends EntityNotFoundException {
@Serial

Some files were not shown because too many files have changed in this diff Show More