Absract metatype impl (#2575)

* Add common "interface" for metadata supporting entities
* Add common metadata implementation for distribution set and software module
* Extract PermissionSupport + extend by TargetManagement
* TargetManagement tags are now protected by Target permissions - as it should be

---------

Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
Avgustin Marinov
2025-08-01 12:41:53 +03:00
committed by GitHub
parent b40de54d83
commit 5d75c9b0cc
22 changed files with 449 additions and 373 deletions

View File

@@ -54,14 +54,13 @@ import org.springframework.security.access.prepost.PreAuthorize;
* Management service for {@link DistributionSet}s.
*/
public interface DistributionSetManagement<T extends DistributionSet>
extends RepositoryManagement<T, DistributionSetManagement.Create, DistributionSetManagement.Update> {
extends RepositoryManagement<T, DistributionSetManagement.Create, DistributionSetManagement.Update>, MetadataSupport<String> {
@Override
default String permissionGroup() {
return "DISTRIBUTION_SET";
}
/**
* Find {@link DistributionSet} based on given ID including (lazy loaded) details, e.g. {@link DistributionSet#getModules()}. <br/>
* For performance reasons it is recommended to use {@link #get(long)} if the details are not required.
@@ -140,49 +139,6 @@ public interface DistributionSetManagement<T extends DistributionSet>
@PreAuthorize(HAS_UPDATE_REPOSITORY)
List<T> unassignTag(@NotEmpty Collection<Long> ids, long tagId);
/**
* Creates a map of distribution set meta-data entries.
*
* @param id if the {@link DistributionSet} the meta-data has to be created for
* @param metadata the meta-data entries to create or update
* @throws EntityNotFoundException if given set does not exist
* @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_UPDATE_REPOSITORY)
void createMetadata(long id, @NotEmpty Map<String, String> metadata);
/**
* Finds all meta-data by the given distribution set id.
*
* @param id the distribution set id to retrieve the meta-data from
* @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_READ_REPOSITORY)
Map<String, String> getMetadata(long id);
/**
* Updates a distribution set meta-data values by adding them.
*
* @param id {@link DistributionSet} of the meta-data entry to be updated
* @param key meta data-entry key to be updated
* @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_UPDATE_REPOSITORY)
void updateMetadata(long id, @NotNull String key, @NotNull String value);
/**
* Deletes a distribution set meta-data entry.
*
* @param id where meta-data has to be deleted
* @param key of the meta-data element
* @throws EntityNotFoundException if given set does not exist
*/
@PreAuthorize(HAS_UPDATE_REPOSITORY)
void deleteMetadata(long id, @NotEmpty String key);
/**
* Locks a distribution set. From then on its functional properties could not be changed, and it could be assigned to targets
*

View File

@@ -0,0 +1,85 @@
/**
* Copyright (c) 2025 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository;
import java.util.Map;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
import org.eclipse.hawkbit.repository.exception.EntityAlreadyExistsException;
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
import org.springframework.security.access.prepost.PreAuthorize;
/**
* Represents interface for managing meta-data of entities. The keys are always Strings, while the values are generic
*
* @param <MV> the type of the meta-data value
*/
@SuppressWarnings("java:S119") // java:S119 - better self explainable
public interface MetadataSupport<MV> {
/**
* Creates or updates a meta-data value.
*
* @param id the entity id which meta-data has to be updated
* @param key the key of the meta-data entry to be updated
* @param value the meta-data value to be updated
* @throws EntityNotFoundException in case the meta-data entry does not exist and cannot be updated
*/
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
void createMetadata(@NotNull Long id, @NotEmpty String key, @NotNull @Valid MV value);
/**
* Creates a list of entity meta-data entries.
*
* @param id the entity id which meta-data has to be created
* @param metadata the meta-data entries to create
* @throws EntityAlreadyExistsException in case one of the meta-data entry already exists for the specific key
* @throws EntityNotFoundException if entity with given ID does not exist
* @throws AssignmentQuotaExceededException if the maximum number of meta-data entries is exceeded for the addressed entity
*/
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
void createMetadata(@NotNull Long id, @NotEmpty @Valid Map<String, ? extends MV> metadata);
/**
* Finds all meta-data by the given entity id and key.
*
* @param id the entity id to retrieve the meta-data from
* @param key the meta-data key to retrieve
* @return a paged result of all meta-data entries for a given entity id
* @throws EntityNotFoundException if entity with given ID does not exist ot the
*/
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
MV getMetadata(@NotNull Long id, @NotEmpty String key);
/**
* Finds all meta-data by the given entity id.
*
* @param id the entity id to retrieve the meta-data from
* @return a paged result of all meta-data entries for a given entity id
* @throws EntityNotFoundException if entity with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Map<String, MV> getMetadata(@NotNull Long id);
/**
* Deletes a entity meta-data entry.
*
* @param id where meta-data has to be deleted
* @param key of the meta-data element
* @throws EntityNotFoundException if entity with given ID does not exist or the key is not found
*/
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
void deleteMetadata(@NotNull Long id, @NotEmpty String key);
}

View File

@@ -0,0 +1,15 @@
/**
* Copyright (c) 2025 Contributors to the Eclipse Foundation
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.hawkbit.repository;
public interface PermissionSupport {
String permissionGroup();
}

View File

@@ -36,7 +36,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
* @param <C> type of the create request
* @param <U> type of the update request
*/
public interface RepositoryManagement<T extends BaseEntity, C, U extends Identifiable<Long>> {
public interface RepositoryManagement<T extends BaseEntity, C, U extends Identifiable<Long>> extends PermissionSupport {
/**
* Creates new {@link BaseEntity}.
@@ -153,6 +153,7 @@ public interface RepositoryManagement<T extends BaseEntity, C, U extends Identif
@PreAuthorize(SpringEvalExpressions.HAS_DELETE_REPOSITORY)
void delete(@NotEmpty Collection<Long> ids);
@Override
default String permissionGroup() {
return "REPOSITORY";
}

View File

@@ -42,66 +42,13 @@ import org.springframework.security.access.prepost.PreAuthorize;
* Service for managing {@link SoftwareModule}s.
*/
public interface SoftwareModuleManagement<T extends SoftwareModule>
extends RepositoryManagement<T, SoftwareModuleManagement.Create, SoftwareModuleManagement.Update> {
extends RepositoryManagement<T, SoftwareModuleManagement.Create, SoftwareModuleManagement.Update>, MetadataSupport<MetadataValue> {
@Override
default String permissionGroup() {
return "SOFTWARE_MODULE";
}
/**
* Creates or updates a distribution set meta-data value.
*
* @param id the software module id which meta-data has to be updated
* @param key the key of the meta-data entry to be updated
* @param value the meta-data value to be updated
* @throws EntityNotFoundException in case the meta-data entry does not exist and cannot be updated
*/
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
void createMetadata(@NotNull Long id, @NotEmpty String key, @NotNull @Valid MetadataValue value);
/**
* Creates a list of software module meta-data entries.
*
* @param metadata the meta-data entries to create
* @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 meta-data entries is exceeded for the addressed {@link SoftwareModule}
*/
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
void createMetadata(@NotNull Long id, @NotEmpty @Valid Map<String, ? extends MetadataValue> metadata);
/**
* Finds all meta-data by the given software module id and key.
*
* @param id the software module id to retrieve the meta-data from
* @param key the meta-data key to retrieve
* @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_READ_REPOSITORY)
MetadataValue getMetadata(@NotNull Long id, @NotEmpty String key);
/**
* Finds all meta-data by the given software module id.
*
* @param id the software module id to retrieve the meta-data from
* @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_READ_REPOSITORY)
Map<String, MetadataValue> getMetadata(@NotNull Long id);
/**
* Deletes a software module meta-data entry.
*
* @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
*/
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
void deleteMetadata(@NotNull Long id, @NotEmpty String key);
@PreAuthorize(SpringEvalExpressions.IS_SYSTEM_CODE)
Map<Long, Map<String, String>> findMetaDataBySoftwareModuleIdsAndTargetVisible(Collection<Long> ids);

View File

@@ -15,12 +15,10 @@ 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_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_UPDATE_REPOSITORY;
import static org.eclipse.hawkbit.im.authentication.SpringEvalExpressions.HAS_AUTH_UPDATE_TARGET;
import java.util.Collection;
@@ -36,6 +34,7 @@ import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import org.eclipse.hawkbit.im.authentication.SpPermission;
import org.eclipse.hawkbit.im.authentication.SpringEvalExpressions;
import org.eclipse.hawkbit.repository.builder.TargetCreate;
import org.eclipse.hawkbit.repository.builder.TargetUpdate;
import org.eclipse.hawkbit.repository.exception.AssignmentQuotaExceededException;
@@ -60,7 +59,7 @@ import org.springframework.security.access.prepost.PreAuthorize;
/**
* Management service for {@link Target}s.
*/
public interface TargetManagement {
public interface TargetManagement extends PermissionSupport {
String DETAILS_BASE = "base";
String DETAILS_AUTO_CONFIRMATION_STATUS = "autoConfirmationStatus";
@@ -72,6 +71,12 @@ public interface TargetManagement {
HAS_AUTH_AND +
HAS_AUTH_PREFIX + SpPermission.READ_TARGET + HAS_AUTH_SUFFIX +
BRACKET_CLOSE;
@Override
default String permissionGroup() {
return "TARGET";
}
/**
* Counts number of targets with the given distribution set assigned.
*
@@ -744,45 +749,56 @@ public interface TargetManagement {
Page<Target> findByControllerAttributesRequested(@NotNull Pageable pageable);
/**
* Creates a list of target meta-data entries.
* Creates or updates a meta-data value.
*
* @param controllerId {@link Target} controller id the meta-data has to be created for
* @param metadata the meta-data entries to create or update
* @throws EntityNotFoundException if given target does not exist
* @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_UPDATE_REPOSITORY)
void createMetadata(@NotEmpty String controllerId, @NotEmpty Map<String, String> metadata);
/**
* Finds a single target meta-data by its id.
*
* @param controllerId of the {@link Target}
* @return the found target meta-data
* @throws EntityNotFoundException if target with given ID does not exist
*/
@PreAuthorize(HAS_READ_REPOSITORY)
Map<String, String> getMetadata(@NotEmpty String controllerId);
/**
* Updates a target meta-data value if corresponding entry exists.
*
* @param controllerId {@link Target} controller id of the meta-data entry to be updated
* @param key meta data-entry key to be updated
* @param value meta data-entry to be new value
* @param controllerId the entity id which meta-data has to be updated
* @param key the key of the meta-data entry to be updated
* @param value the meta-data value to be updated
* @throws EntityNotFoundException in case the meta-data entry does not exist and cannot be updated
*/
@PreAuthorize(HAS_UPDATE_REPOSITORY)
void updateMetadata(@NotEmpty String controllerId, @NotNull String key, @NotNull String value);
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
void createMetadata(@NotNull String controllerId, @NotEmpty String key, @NotNull @Valid String value);
/**
* Deletes a target meta data entry.
* Creates a list of entity meta-data entries.
*
* @param controllerId the entity id which meta-data has to be created
* @param metadata the meta-data entries to create
* @throws EntityAlreadyExistsException in case one of the meta-data entry already exists for the specific key
* @throws EntityNotFoundException if entity with given ID does not exist
* @throws AssignmentQuotaExceededException if the maximum number of meta-data entries is exceeded for the addressed entity
*/
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
void createMetadata(@NotNull String controllerId, @NotEmpty @Valid Map<String, String> metadata);
/**
* Finds all meta-data by the given entity id and key.
*
* @param controllerId the entity id to retrieve the meta-data from
* @param key the meta-data key to retrieve
* @return a paged result of all meta-data entries for a given entity id
* @throws EntityNotFoundException if entity with given ID does not exist ot the
*/
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
String getMetadata(@NotNull String controllerId, @NotEmpty String key);
/**
* Finds all meta-data by the given entity id.
*
* @param controllerId the entity id to retrieve the meta-data from
* @return a paged result of all meta-data entries for a given entity id
* @throws EntityNotFoundException if entity with given ID does not exist
*/
@PreAuthorize(SpringEvalExpressions.HAS_READ_REPOSITORY)
Map<String, String> getMetadata(@NotNull String controllerId);
/**
* Deletes a entity meta-data entry.
*
* @param controllerId where meta-data has to be deleted
* @param key of the meta data element
* @throws EntityNotFoundException if given target does not exist
* @param key of the meta-data element
* @throws EntityNotFoundException if entity with given ID does not exist or the key is not found
*/
@PreAuthorize(HAS_UPDATE_REPOSITORY)
void deleteMetadata(@NotEmpty String controllerId, @NotEmpty String key);
@PreAuthorize(SpringEvalExpressions.HAS_UPDATE_REPOSITORY)
void deleteMetadata(@NotNull String controllerId, @NotEmpty String key);
}