Finalize and polish fine-grained permission (#2660)
* Remove _REPOSITORY_ permissions -> replaced with _SOFTWARE_MODULE_, _SOFTWARE_MODULE_TYPE_, _DISTRIBUTION_SET_, _DISTRIBUTION_SET_TYPE_ permissions * Still kept _ROLE_REPOSITORY_ADMIN_ role granting all repository fine-graned permissions * Added dedicated _TARGET_TYPE_ permission set - the _TARGET_ permissions just grant _READ_TARGET_TYPE_ (analogically _SOFTWARE_MODULE_ permissions grant _READ_SOFTWARE_MODULE_TYPE_ and _DISTRIBUTION_SET_ grants _READ_DISTRIBUTON_SET_TYPE_ * Hierarcy is not configurable - could be completely replaced by setting spring application property org.eclipse.hawkbit.hierarchy or could be extended by adding rules using org.eclipse.hawkbit.hierarchy.ext Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -17,7 +17,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jakarta.validation.ValidationException;
|
||||
@@ -88,7 +88,6 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
|
||||
private final DeploymentManagement deployManagement;
|
||||
private final SystemManagement systemManagement;
|
||||
private final MgmtDistributionSetMapper mgmtDistributionSetMapper;
|
||||
private final SystemSecurityContext systemSecurityContext;
|
||||
private final TenantConfigHelper tenantConfigHelper;
|
||||
|
||||
@SuppressWarnings("java:S107")
|
||||
@@ -112,7 +111,6 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
|
||||
this.tenantConfigHelper = TenantConfigHelper.usingContext(systemSecurityContext, tenantConfigurationManagement);
|
||||
this.mgmtDistributionSetMapper = mgmtDistributionSetMapper;
|
||||
this.systemManagement = systemManagement;
|
||||
this.systemSecurityContext = systemSecurityContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -144,23 +142,27 @@ public class MgmtDistributionSetResource implements MgmtDistributionSetRestApi {
|
||||
public ResponseEntity<List<MgmtDistributionSet>> createDistributionSets(final List<MgmtDistributionSetRequestBodyPost> sets) {
|
||||
log.debug("creating {} distribution sets", sets.size());
|
||||
// set default Ds type if ds type is null
|
||||
final String defaultDsKey = systemSecurityContext.runAsSystem(systemManagement.getTenantMetadata().getDefaultDsType()::getKey);
|
||||
final String defaultDsKey = systemManagement.getTenantMetadata().getDefaultDsType().getKey();
|
||||
sets.stream().filter(ds -> ds.getType() == null).forEach(ds -> ds.setType(defaultDsKey));
|
||||
|
||||
//check if there is already deleted DS Type
|
||||
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!";
|
||||
final String message = MessageFormat.format(text, dsType.getKey());
|
||||
throw new ValidationException(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
// check if target ds types exist and are not deleted, also caches them
|
||||
final Map<String, DistributionSetType> dsTypeKeyToDsType = sets.stream()
|
||||
.map(MgmtDistributionSetRequestBodyPost::getType)
|
||||
.distinct()
|
||||
.collect(Collectors.toMap(
|
||||
Function.identity(),
|
||||
dsTypeKey ->
|
||||
distributionSetTypeManagement.findByKey(dsTypeKey).map(dsType -> {
|
||||
if (dsType.isDeleted()) {
|
||||
throw new ValidationException(MessageFormat.format(
|
||||
"Cannot create Distribution Set from type with key {0}. Distribution Set Type already deleted!",
|
||||
dsTypeKey));
|
||||
}
|
||||
return dsType;
|
||||
}).orElseThrow(() -> new EntityNotFoundException(DistributionSetType.class, dsTypeKey))));
|
||||
|
||||
final Collection<? extends DistributionSet> createdDSets = distributionSetManagement
|
||||
.create(mgmtDistributionSetMapper.fromRequest(sets));
|
||||
final Collection<? extends DistributionSet> createdDSets =
|
||||
distributionSetManagement.create(mgmtDistributionSetMapper.fromRequest(sets, defaultDsKey, dsTypeKeyToDsType));
|
||||
|
||||
log.debug("{} distribution sets created, return status {}", sets.size(), HttpStatus.CREATED);
|
||||
return new ResponseEntity<>(MgmtDistributionSetMapper.toResponseDistributionSets(createdDSets), HttpStatus.CREATED);
|
||||
|
||||
@@ -17,6 +17,7 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -63,8 +64,38 @@ public class MgmtDistributionSetMapper {
|
||||
this.systemManagement = systemManagement;
|
||||
}
|
||||
|
||||
public List<DistributionSetManagement.Create> fromRequest(final Collection<MgmtDistributionSetRequestBodyPost> sets) {
|
||||
return sets.stream().map(this::fromRequest).toList();
|
||||
public List<DistributionSetManagement.Create> fromRequest(
|
||||
final Collection<MgmtDistributionSetRequestBodyPost> sets,
|
||||
final String defaultDsKey, final Map<String, DistributionSetType> dsTypeKeyToDsType) {
|
||||
return sets.stream().<DistributionSetManagement.Create>map(dsRest -> {
|
||||
final Set<Long> modules = new HashSet<>();
|
||||
if (dsRest.getOs() != null) {
|
||||
modules.add(dsRest.getOs().getId());
|
||||
}
|
||||
if (dsRest.getApplication() != null) {
|
||||
modules.add(dsRest.getApplication().getId());
|
||||
}
|
||||
if (dsRest.getRuntime() != null) {
|
||||
modules.add(dsRest.getRuntime().getId());
|
||||
}
|
||||
if (dsRest.getModules() != null) {
|
||||
dsRest.getModules().forEach(module -> modules.add(module.getId()));
|
||||
}
|
||||
// distribution set type, if null by the REST call shall be replaced with the default tenant DS type
|
||||
final String dsTypeKey = Objects.requireNonNull(dsRest.getType(), "Distribution set type must not be null");
|
||||
final DistributionSetType dsType = dsTypeKeyToDsType.get(dsTypeKey);
|
||||
if (dsType == null) {
|
||||
// type should never null, cache is prefilled with all types
|
||||
throw new EntityNotFoundException(DistributionSetType.class, defaultDsKey);
|
||||
}
|
||||
return DistributionSetManagement.Create.builder()
|
||||
.type(dsType)
|
||||
.name(dsRest.getName()).version(dsRest.getVersion())
|
||||
.description(dsRest.getDescription())
|
||||
.modules(findSoftwareModuleWithExceptionIfNotFound(modules))
|
||||
.requiredMigrationStep(dsRest.getRequiredMigrationStep())
|
||||
.build();
|
||||
}).toList();
|
||||
}
|
||||
|
||||
public static MgmtDistributionSet toResponse(final DistributionSet distributionSet) {
|
||||
@@ -170,36 +201,6 @@ public class MgmtDistributionSetMapper {
|
||||
return sets.stream().map(MgmtDistributionSetMapper::toResponse).toList();
|
||||
}
|
||||
|
||||
private DistributionSetManagement.Create fromRequest(final MgmtDistributionSetRequestBodyPost dsRest) {
|
||||
final Set<Long> modules = new HashSet<>();
|
||||
if (dsRest.getOs() != null) {
|
||||
modules.add(dsRest.getOs().getId());
|
||||
}
|
||||
if (dsRest.getApplication() != null) {
|
||||
modules.add(dsRest.getApplication().getId());
|
||||
}
|
||||
if (dsRest.getRuntime() != null) {
|
||||
modules.add(dsRest.getRuntime().getId());
|
||||
}
|
||||
if (dsRest.getModules() != null) {
|
||||
dsRest.getModules().forEach(module -> modules.add(module.getId()));
|
||||
}
|
||||
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();
|
||||
|
||||
@@ -73,7 +73,6 @@ class MgmtTargetTypeResourceTest extends AbstractManagementApiIntegrationTest {
|
||||
principal = "targetTypeTester", allSpPermissions = true,
|
||||
removeFromAllPermission = {
|
||||
SpPermission.CREATE_TARGET, SpPermission.READ_TARGET, SpPermission.UPDATE_TARGET, SpPermission.DELETE_TARGET,
|
||||
SpPermission.CREATE_REPOSITORY, SpPermission.READ_REPOSITORY, SpPermission.UPDATE_REPOSITORY, SpPermission.DELETE_REPOSITORY,
|
||||
SpPermission.READ_TARGET_TYPE })
|
||||
void getTargetTypesWithoutPermission() throws Exception {
|
||||
mvc.perform(get(TARGETTYPES_ENDPOINT).accept(MediaType.APPLICATION_JSON))
|
||||
|
||||
Reference in New Issue
Block a user