diff --git a/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DataConversionHelper.java b/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DataConversionHelper.java index f96e41a81d..00c8542287 100644 --- a/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DataConversionHelper.java +++ b/hawkbit-ddi/hawkbit-ddi-resource/src/main/java/org/eclipse/hawkbit/ddi/rest/resource/DataConversionHelper.java @@ -36,6 +36,7 @@ import org.eclipse.hawkbit.repository.model.SoftwareModule; import org.eclipse.hawkbit.repository.model.SoftwareModuleMetadata; import org.eclipse.hawkbit.repository.model.Target; +import org.eclipse.hawkbit.repository.model.TenantMetaData; import org.eclipse.hawkbit.rest.json.model.ResponseList; import org.eclipse.hawkbit.tenancy.TenantAware; import org.springframework.hateoas.Link; @@ -179,10 +180,12 @@ private static DdiArtifact createArtifact( file.setFilename(artifact.getFilename()); file.setSize(artifact.getSize()); + final TenantMetaData tenantMetadata = systemManagement.getTenantMetadataWithoutDetails(); artifactUrlHandler - .getUrls(new URLPlaceholder(systemManagement.getTenantMetadata().getTenant(), - systemManagement.getTenantMetadata().getId(), target.getControllerId(), target.getId(), - new SoftwareData(artifact.getSoftwareModule().getId(), artifact.getFilename(), artifact.getId(), + .getUrls(new URLPlaceholder( + tenantMetadata.getTenant(), tenantMetadata.getId(), target.getControllerId(), target.getId(), + new SoftwareData( + artifact.getSoftwareModule().getId(), artifact.getFilename(), artifact.getId(), artifact.getSha1Hash())), ApiType.DDI, request.getURI()) .forEach(entry -> file.add(Link.of(entry.getRef()).withRel(entry.getRel()).expand())); diff --git a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java index 9cdf914219..1869d31107 100644 --- a/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java +++ b/hawkbit-dmf/hawkbit-dmf-amqp/src/main/java/org/eclipse/hawkbit/amqp/AmqpMessageDispatcherService.java @@ -585,12 +585,13 @@ private List convertArtifacts(final Target target, final List getDistributionSet(final Long distrib public ResponseEntity> createDistributionSets(final List 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 = systemSecurityContext.runAsSystem(systemManagement.getTenantMetadata().getDefaultDsType()::getKey); sets.stream().filter(ds -> ds.getType() == null).forEach(ds -> ds.setType(defaultDsKey)); //check if there is already deleted DS Type diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResource.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResource.java index a2183b7b51..90a9744ef5 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResource.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/main/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResource.java @@ -115,8 +115,7 @@ public ResponseEntity> updateTenantConf } //Try update TenantMetadata first - final Serializable defaultDsTypeValueUpdate = configurationValueMap.remove( - MgmtTenantManagementMapper.DEFAULT_DISTRIBUTION_SET_TYPE_KEY); + final Serializable defaultDsTypeValueUpdate = configurationValueMap.remove(MgmtTenantManagementMapper.DEFAULT_DISTRIBUTION_SET_TYPE_KEY); Long oldDefaultDsType = null; MgmtSystemTenantConfigurationValue updatedDefaultDsType = null; if (defaultDsTypeValueUpdate != null) { @@ -150,14 +149,14 @@ private static boolean isDefaultDistributionSetTypeKey(String keyName) { return MgmtTenantManagementMapper.DEFAULT_DISTRIBUTION_SET_TYPE_KEY.equals(keyName); } - private MgmtSystemTenantConfigurationValue loadTenantConfigurationValueBy(String keyName) { + private MgmtSystemTenantConfigurationValue loadTenantConfigurationValueBy(final String keyName) { //Check if requested key is TenantConfiguration or TenantMetadata, load it and return it as rest response final MgmtSystemTenantConfigurationValue response; if (isDefaultDistributionSetTypeKey(keyName)) { response = MgmtTenantManagementMapper.toResponseDefaultDsType(systemManagement.getTenantMetadata().getDefaultDsType().getId()); } else { - response = MgmtTenantManagementMapper.toResponseTenantConfigurationValue(keyName, - tenantConfigurationManagement.getConfigurationValue(keyName)); + response = MgmtTenantManagementMapper.toResponseTenantConfigurationValue( + keyName, tenantConfigurationManagement.getConfigurationValue(keyName)); } return response; } diff --git a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResourceTest.java b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResourceTest.java index af8bdee0b8..c373b62c48 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResourceTest.java +++ b/hawkbit-mgmt/hawkbit-mgmt-resource/src/test/java/org/eclipse/hawkbit/mgmt/rest/resource/MgmtTenantManagementResourceTest.java @@ -361,5 +361,4 @@ private void assertBatchConfigurationFails(Object newRolloutApprovalEnabled, Obj private Long getActualDefaultDsType() { return systemManagement.getTenantMetadata().getDefaultDsType().getId(); } - -} +} \ No newline at end of file diff --git a/hawkbit-mgmt/hawkbit-mgmt-starter/src/main/java/org/eclipse/hawkbit/autoconfigure/mgmt/MgmtSecurityConfiguration.java b/hawkbit-mgmt/hawkbit-mgmt-starter/src/main/java/org/eclipse/hawkbit/autoconfigure/mgmt/MgmtSecurityConfiguration.java index a99e4ff8d6..80e4f89c7f 100644 --- a/hawkbit-mgmt/hawkbit-mgmt-starter/src/main/java/org/eclipse/hawkbit/autoconfigure/mgmt/MgmtSecurityConfiguration.java +++ b/hawkbit-mgmt/hawkbit-mgmt-starter/src/main/java/org/eclipse/hawkbit/autoconfigure/mgmt/MgmtSecurityConfiguration.java @@ -103,7 +103,7 @@ SecurityFilterChain filterChainREST( (request, response, chain) -> { final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication != null && authentication.isAuthenticated()) { - systemSecurityContext.runAsSystem(systemManagement::getTenantMetadata); + systemSecurityContext.runAsSystem(systemManagement::getTenantMetadataWithoutDetails); } chain.doFilter(request, response); }, diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java index bcd2395b24..ce61da0e4c 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/SystemManagement.java @@ -82,6 +82,15 @@ public interface SystemManagement { + SpringEvalExpressions.IS_CONTROLLER) TenantMetaData getTenantMetadata(); + /** + * @return {@link TenantMetaData} of {@link TenantAware#getCurrentTenant()} without details ({@link TenantMetaData#getDefaultDsType()}) + */ + @PreAuthorize(SpringEvalExpressions.HAS_AUTH_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) + TenantMetaData getTenantMetadataWithoutDetails(); + /** * Returns {@link TenantMetaData} of given and current tenant. Creates for * new tenants also two {@link SoftwareModuleType} (os and app) and diff --git a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetType.java b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetType.java index 7ab6edf7c4..2bbff226cf 100644 --- a/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetType.java +++ b/hawkbit-repository/hawkbit-repository-api/src/main/java/org/eclipse/hawkbit/repository/model/DistributionSetType.java @@ -12,97 +12,56 @@ import java.util.Set; /** - * A {@link DistributionSetType} is an abstract definition for - * {@link DistributionSet} that defines what {@link SoftwareModule}s can be - * added (optional) to {@link DistributionSet} of that type or have to added - * (mandatory) in order to be considered complete. Only complete DS can be - * assigned to a {@link Target}. + * A {@link DistributionSetType} is an abstract definition for {@link DistributionSet} that defines what {@link SoftwareModule}s can be + * added (optional) to {@link DistributionSet} of that type or have to added (mandatory) in order to be considered complete. Only complete DS + * can be assigned to a {@link Target}. */ public interface DistributionSetType extends Type { /** - * @return immutable set of {@link SoftwareModuleType}s that need to be in a - * {@link DistributionSet} of this type to be + * @return immutable set of {@link SoftwareModuleType}s that need to be in a {@link DistributionSet} of this type to be * {@link DistributionSet#isComplete()}. */ Set getMandatoryModuleTypes(); /** - * @return immutable set of optional {@link SoftwareModuleType}s that can be - * in a {@link DistributionSet} of this type. + * @return immutable set of optional {@link SoftwareModuleType}s that can be in a {@link DistributionSet} of this type. */ Set getOptionalModuleTypes(); /** - * Checks if the given {@link SoftwareModuleType} is in this - * {@link DistributionSetType}. - * - * @param softwareModuleType search for - * @return true if found + * @param distributionSet to check for completeness + * @return true if the all mandatory software module types are in the system. */ - default boolean containsModuleType(final SoftwareModuleType softwareModuleType) { - return containsMandatoryModuleType(softwareModuleType) || containsOptionalModuleType(softwareModuleType); - } + boolean checkComplete(DistributionSet distributionSet); /** - * Checks if the given {@link SoftwareModuleType} is in this - * {@link DistributionSetType}. + * Checks if the given {@link SoftwareModuleType} is in this {@link DistributionSetType}. * - * @param softwareModuleTypeId search for by {@link SoftwareModuleType#getId()} + * @param softwareModuleType search for * @return true if found */ - default boolean containsModuleType(final Long softwareModuleTypeId) { - return containsMandatoryModuleType(softwareModuleTypeId) || containsOptionalModuleType(softwareModuleTypeId); + default boolean containsModuleType(final SoftwareModuleType softwareModuleType) { + return containsMandatoryModuleType(softwareModuleType) || containsOptionalModuleType(softwareModuleType); } /** - * Checks if the given {@link SoftwareModuleType} is in - * {@link #getMandatoryModuleTypes()}. + * Checks if the given {@link SoftwareModuleType} is in {@link #getMandatoryModuleTypes()}. * * @param softwareModuleType search for * @return true if found */ default boolean containsMandatoryModuleType(final SoftwareModuleType softwareModuleType) { - return containsMandatoryModuleType(softwareModuleType.getId()); - } - - /** - * Checks if the given {@link SoftwareModuleType} is in - * {@link #getMandatoryModuleTypes()}. - * - * @param softwareModuleTypeId search for by {@link SoftwareModuleType#getId()} - * @return true if found - */ - default boolean containsMandatoryModuleType(final Long softwareModuleTypeId) { - return getMandatoryModuleTypes().stream().anyMatch(element -> element.getId().equals(softwareModuleTypeId)); + return getMandatoryModuleTypes().stream().anyMatch(element -> element.getId().equals(softwareModuleType.getId())); } /** - * Checks if the given {@link SoftwareModuleType} is in - * {@link #getOptionalModuleTypes()}. + * Checks if the given {@link SoftwareModuleType} is in {@link #getOptionalModuleTypes()}. * * @param softwareModuleType search for * @return true if found */ default boolean containsOptionalModuleType(final SoftwareModuleType softwareModuleType) { - return containsOptionalModuleType(softwareModuleType.getId()); - } - - /** - * Checks if the given {@link SoftwareModuleType} is in - * {@link #getOptionalModuleTypes()}. - * - * @param softwareModuleTypeId search by {@link SoftwareModuleType#getId()} - * @return true if found - */ - default boolean containsOptionalModuleType(final Long softwareModuleTypeId) { - return getOptionalModuleTypes().stream().anyMatch(element -> element.getId().equals(softwareModuleTypeId)); + return getOptionalModuleTypes().stream().anyMatch(element -> element.getId().equals(softwareModuleType.getId())); } - - /** - * @param distributionSet to check for completeness - * @return true if the all mandatory software module types are - * in the system. - */ - boolean checkComplete(DistributionSet distributionSet); } \ No newline at end of file diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java index 80137490d2..f150e972e1 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaDistributionSetManagement.java @@ -623,7 +623,7 @@ public Long countAutoAssignmentsForDistributionSet(final Long id) { return distributionSetRepository.countAutoAssignmentsForDistributionSet(id); } - // check if shall implicitly lock a distribution set + // check if it shall implicitly lock a distribution set boolean isImplicitLockApplicable(final DistributionSet distributionSet) { final JpaDistributionSet jpaDistributionSet = (JpaDistributionSet) distributionSet; if (jpaDistributionSet.isLocked()) { @@ -631,7 +631,7 @@ boolean isImplicitLockApplicable(final DistributionSet distributionSet) { return false; } - if (!tenantConfigHelper.getConfigValue(IMPLICIT_LOCK_ENABLED, Boolean.class)) { + if (Boolean.FALSE.equals(tenantConfigHelper.getConfigValue(IMPLICIT_LOCK_ENABLED, Boolean.class))) { // implicit lock disabled return false; } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java index 4eb40e22c9..0f97b30088 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/management/JpaSystemManagement.java @@ -173,8 +173,7 @@ public Page findTenants(final Pageable pageable) { @Override @Transactional(propagation = Propagation.NOT_SUPPORTED) - // Exception squid:S2229 - calling findTenants without transaction is - // intended in this case + // Exception squid:S2229 - calling findTenants without transaction is intended in this case @SuppressWarnings("squid:S2229") public void forEachTenant(final Consumer consumer) { Page tenants; @@ -207,7 +206,6 @@ public SystemUsageReportWithTenants getSystemUsageStatisticsWithTenants() { @Override public SystemUsageReport getSystemUsageStatistics() { - final Number count = (Number) entityManager.createNativeQuery(countSoftwareModulesQuery).getSingleResult(); long sumOfArtifacts = 0; @@ -232,22 +230,12 @@ public SystemUsageReport getSystemUsageStatistics() { @Override public TenantMetaData getTenantMetadata() { - final String tenant = tenantAware.getCurrentTenant(); - if (tenant == null) { - throw new IllegalStateException("Tenant not set"); - } + return getTenantMetadata0(true); + } - final TenantMetaData metaData = tenantMetaDataRepository.findByTenantIgnoreCase(tenant); - if (metaData == null) { - if (repositoryProperties.isImplicitTenantCreateAllowed()) { - log.info("Tenant {} doesn't exist create metadata", tenant, new Exception("Thread dump")); - return createTenantMetadata0(tenant); - } else { - throw new EntityNotFoundException(TenantMetaData.class, tenant); - } - } else { - return metaData; - } + @Override + public TenantMetaData getTenantMetadataWithoutDetails() { + return getTenantMetadata0(false); } @Override @@ -265,11 +253,9 @@ public TenantMetaData createTenantMetadata(final String tenant) { @Retryable(retryFor = { ConcurrencyFailureException.class }, maxAttempts = Constants.TX_RT_MAX, backoff = @Backoff(delay = Constants.TX_RT_DELAY)) public TenantMetaData updateTenantMetadata(final long defaultDsType) { - final JpaTenantMetaData data = (JpaTenantMetaData) getTenantMetadata(); - + final JpaTenantMetaData data = (JpaTenantMetaData) getTenantMetadataWithoutDetails(); data.setDefaultDsType(distributionSetTypeRepository.findById(defaultDsType) .orElseThrow(() -> new EntityNotFoundException(DistributionSetType.class, defaultDsType))); - return tenantMetaDataRepository.save(data); } @@ -283,6 +269,28 @@ private static boolean isPostgreSql(final JpaProperties properties) { return Database.POSTGRESQL == properties.getDatabase(); } + private TenantMetaData getTenantMetadata0(final boolean withDetails) { + final String tenant = tenantAware.getCurrentTenant(); + if (tenant == null) { + throw new IllegalStateException("Tenant not set"); + } + + final TenantMetaData metaData = + withDetails ? + tenantMetaDataRepository.findWitDetailsByTenantIgnoreCase(tenant) : + tenantMetaDataRepository.findByTenantIgnoreCase(tenant); + if (metaData == null) { + if (repositoryProperties.isImplicitTenantCreateAllowed()) { + log.info("Tenant {} doesn't exist create metadata", tenant, new Exception("Thread dump")); + return createTenantMetadata0(tenant); + } else { + throw new EntityNotFoundException(TenantMetaData.class, tenant); + } + } else { + return metaData; + } + } + private void usageStatsPerTenant(final SystemUsageReportWithTenants report) { forEachTenant(tenant -> report.addTenantData(systemStatsManagement.getStatsOfTenant())); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElement.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElement.java index e2561462e3..4644c7a9a6 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElement.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/DistributionSetTypeElement.java @@ -35,7 +35,6 @@ * {@link SoftwareModuleType} elements. */ @NoArgsConstructor // Default constructor for JPA -@Getter @Entity @Table(name = "sp_ds_type_element") public class DistributionSetTypeElement implements Serializable { @@ -47,16 +46,22 @@ public class DistributionSetTypeElement implements Serializable { private DistributionSetTypeElementCompositeKey key; @MapsId("dsType") - @ManyToOne(optional = false, fetch = FetchType.LAZY) - @JoinColumn(name = "distribution_set_type", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_type_element_element")) + @ManyToOne(optional = false) + @JoinColumn( + name = "distribution_set_type", nullable = false, updatable = false, + foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_type_element_element")) private JpaDistributionSetType dsType; + @Getter @MapsId("smType") - @ManyToOne(optional = false, fetch = FetchType.LAZY) - @JoinColumn(name = "software_module_type", nullable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_type_element_smtype")) + @ManyToOne(optional = false) + @JoinColumn( + name = "software_module_type", nullable = false, updatable = false, + foreignKey = @ForeignKey(value = ConstraintMode.CONSTRAINT, name = "fk_ds_type_element_smtype")) private JpaSoftwareModuleType smType; @Setter + @Getter @Column(name = "mandatory") private boolean mandatory; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetType.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetType.java index 5964b1a4fc..bfa45484f0 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetType.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaDistributionSetType.java @@ -60,6 +60,7 @@ public class JpaDistributionSetType extends AbstractJpaTypeEntity implements Dis @OneToMany( mappedBy = "dsType", targetEntity = DistributionSetTypeElement.class, + fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE }, orphanRemoval = true) private Set elements = new HashSet<>(); @@ -118,10 +119,6 @@ public JpaDistributionSetType removeModuleType(final Long smTypeId) { return this; } - public Set getElements() { - return Collections.unmodifiableSet(elements); - } - @Override public String toString() { return "DistributionSetType [key=" + getKey() + ", isDeleted()=" + isDeleted() + ", getId()=" + getId() + "]"; diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTenantMetaData.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTenantMetaData.java index 3a5dafa16c..1cc1b3009b 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTenantMetaData.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/model/JpaTenantMetaData.java @@ -19,6 +19,8 @@ import jakarta.persistence.ForeignKey; import jakarta.persistence.Index; import jakarta.persistence.JoinColumn; +import jakarta.persistence.NamedAttributeNode; +import jakarta.persistence.NamedEntityGraph; import jakarta.persistence.OneToOne; import jakarta.persistence.Table; import jakarta.persistence.UniqueConstraint; @@ -45,6 +47,7 @@ @Table(name = "sp_tenant", indexes = { @Index(name = "sp_idx_tenant_prim", columnList = "tenant,id") }, uniqueConstraints = { @UniqueConstraint(columnNames = { "tenant" }, name = "uk_tenantmd_tenant") }) +@NamedEntityGraph(name = "TenantMetaData.withDetails", attributeNodes = { @NamedAttributeNode("defaultDsType") }) @Entity // exception squid:S2160 - BaseEntity equals/hashcode is handling correctly for sub entities @SuppressWarnings("squid:S2160") diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TenantMetaDataRepository.java b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TenantMetaDataRepository.java index a5143f8c03..bda5746084 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TenantMetaDataRepository.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/main/java/org/eclipse/hawkbit/repository/jpa/repository/TenantMetaDataRepository.java @@ -13,6 +13,7 @@ import org.eclipse.hawkbit.repository.model.TenantMetaData; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.CrudRepository; @@ -26,21 +27,16 @@ @Transactional(readOnly = true) public interface TenantMetaDataRepository extends PagingAndSortingRepository, CrudRepository { - /** - * Search {@link TenantMetaData} by tenant name. - * - * @param tenant to search for - * @return found {@link TenantMetaData} or null - */ + // find without details TenantMetaData findByTenantIgnoreCase(String tenant); - @Transactional + // find with details + @EntityGraph(value = "TenantMetaData.withDetails", type = EntityGraph.EntityGraphType.LOAD) + TenantMetaData findWitDetailsByTenantIgnoreCase(String tenant); + @Query("SELECT t.tenant FROM JpaTenantMetaData t") Page findTenants(final Pageable pageable); - /** - * @param tenant - */ @Transactional @Modifying @Query("DELETE FROM JpaTenantMetaData t WHERE UPPER(t.tenant) = UPPER(:tenant)") diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementTest.java index 239370af22..66556d81a7 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/DistributionSetManagementTest.java @@ -212,7 +212,8 @@ void createDistributionSetWithImplicitType() { final DistributionSet set = distributionSetManagement .create(entityFactory.distributionSet().create().name("newtypesoft").version("1")); - assertThat(set.getType()).as("Type should be equal to default type of tenant") + assertThat(set.getType()) + .as("Type should be equal to default type of tenant") .isEqualTo(systemManagement.getTenantMetadata().getDefaultDsType()); } @@ -705,13 +706,12 @@ void lockDistributionSetApplied() { @Test @Description("Test implicit locks for a DS and skip tags.") void isImplicitLockApplicableForDistributionSet() { - final JpaDistributionSetManagement distributionSetManagement = - (JpaDistributionSetManagement) this.distributionSetManagement; + final JpaDistributionSetManagement distributionSetManagement = (JpaDistributionSetManagement) this.distributionSetManagement; final DistributionSet distributionSet = testdataFactory.createDistributionSet("ds-non-skip"); // assert that implicit lock is applicable for non skip tags assertThat(distributionSetManagement.isImplicitLockApplicable(distributionSet)).isTrue(); - assertThat(repositoryProperties.getSkipImplicitLockForTags().size()).isNotEqualTo(0); + assertThat(repositoryProperties.getSkipImplicitLockForTags().size()).isNotZero(); final List skipTags = distributionSetTagManagement.create( repositoryProperties.getSkipImplicitLockForTags().stream() .map(String::toLowerCase) @@ -733,13 +733,12 @@ void isImplicitLockApplicableForDistributionSet() { @Test @Description("Locks an incomplete DS. Expected behaviour is to throw an exception and to do not lock it.") void lockIncompleteDistributionSetFails() { - final DistributionSet incompleteDistributionSet = testdataFactory.createIncompleteDistributionSet(); + final long incompleteDistributionSetId = testdataFactory.createIncompleteDistributionSet().getId(); assertThatExceptionOfType(IncompleteDistributionSetException.class) .as("Locking an incomplete distribution set should throw an exception") - .isThrownBy(() -> distributionSetManagement.lock(incompleteDistributionSet.getId())); + .isThrownBy(() -> distributionSetManagement.lock(incompleteDistributionSetId)); assertThat( - distributionSetManagement.get(incompleteDistributionSet.getId()).map(DistributionSet::isLocked) - .orElse(true)) + distributionSetManagement.get(incompleteDistributionSetId).map(DistributionSet::isLocked).orElse(true)) .isFalse(); } diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementSecurityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementSecurityTest.java index 448b532bdd..b4827fb47f 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementSecurityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementSecurityTest.java @@ -69,6 +69,15 @@ void getTenantMetadataPermissionsCheck() { assertPermissions(() -> systemManagement.getTenantMetadata(), List.of(SpPermission.SpringEvalExpressions.CONTROLLER_ROLE), List.of(SpPermission.CREATE_REPOSITORY)); } + @Test + @Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.") + void getTenantMetadataWithoutDetailsPermissionsCheck() { + assertPermissions(() -> systemManagement.getTenantMetadataWithoutDetails(), List.of(SpPermission.READ_REPOSITORY), List.of(SpPermission.CREATE_REPOSITORY)); + assertPermissions(() -> systemManagement.getTenantMetadataWithoutDetails(), List.of(SpPermission.READ_TARGET), List.of(SpPermission.CREATE_REPOSITORY)); + assertPermissions(() -> systemManagement.getTenantMetadataWithoutDetails(), List.of(SpPermission.READ_TENANT_CONFIGURATION), List.of(SpPermission.CREATE_REPOSITORY)); + assertPermissions(() -> systemManagement.getTenantMetadataWithoutDetails(), List.of(SpPermission.SpringEvalExpressions.CONTROLLER_ROLE), List.of(SpPermission.CREATE_REPOSITORY)); + } + @Test @Description("Tests ManagementAPI PreAuthorized method with correct and insufficient permissions.") void getTenantMetadataByTenantPermissionsCheck() { diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementTest.java index 29798f70a4..5aac39bedb 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/management/SystemManagementTest.java @@ -130,7 +130,7 @@ private byte[] createTestTenantsForSystemStatistics(final int tenants, final int final String tenantname = "TENANT" + i; SecurityContextSwitch.runAs(SecurityContextSwitch.withUserAndTenant("bumlux", tenantname, true, true, false, SpringEvalExpressions.SYSTEM_ROLE), () -> { - systemManagement.getTenantMetadata(); + systemManagement.getTenantMetadataWithoutDetails(); if (artifactSize > 0) { createTestArtifact(random); createDeletedTestArtifact(random); diff --git a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java index d31453932f..38bd7544e2 100644 --- a/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java +++ b/hawkbit-repository/hawkbit-repository-jpa/src/test/java/org/eclipse/hawkbit/repository/jpa/tenancy/MultiTenancyEntityTest.java @@ -112,11 +112,10 @@ public void getTenanatMetdata() throws Exception { assertThat(distributionSetTypeManagement.findAll(PAGE)).isNotEmpty(); - // check that the cache is not getting in the way, i.e. "bumlux" results - // in bumlux and not - // mytenant - assertThat(SecurityContextSwitch.runAs(SecurityContextSwitch.withUserAndTenantAllSpPermissions("user", "bumlux"), - () -> systemManagement.getTenantMetadata().getTenant().toUpperCase())) + // check that the cache is not getting in the way, i.e. "bumlux" results in bumlux and not mytenant + assertThat(SecurityContextSwitch.runAs( + SecurityContextSwitch.withUserAndTenantAllSpPermissions("user", "bumlux"), + () -> systemManagement.getTenantMetadataWithoutDetails().getTenant().toUpperCase())) .isEqualTo("bumlux".toUpperCase()); }