SystemManagement getTenantMetadata - fetch details, added method getTenantMetadataWithoutDetails (#2194)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -36,6 +36,7 @@ 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.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 @@ public final class DataConversionHelper {
|
||||
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()));
|
||||
|
||||
@@ -585,12 +585,13 @@ public class AmqpMessageDispatcherService extends BaseAmqpService {
|
||||
private DmfArtifact convertArtifact(final Target target, final Artifact localArtifact) {
|
||||
final DmfArtifact artifact = new DmfArtifact();
|
||||
|
||||
final TenantMetaData metaData = systemManagement.getTenantMetadata();
|
||||
final TenantMetaData tenantMetadata = systemManagement.getTenantMetadataWithoutDetails();
|
||||
artifact.setUrls(artifactUrlHandler
|
||||
.getUrls(new URLPlaceholder(metaData.getTenant(),
|
||||
metaData.getId(), target.getControllerId(), target.getId(),
|
||||
new SoftwareData(localArtifact.getSoftwareModule().getId(), localArtifact.getFilename(),
|
||||
localArtifact.getId(), localArtifact.getSha1Hash())),
|
||||
.getUrls(new URLPlaceholder(
|
||||
tenantMetadata.getTenant(), tenantMetadata.getId(), target.getControllerId(), target.getId(),
|
||||
new SoftwareData(
|
||||
localArtifact.getSoftwareModule().getId(), localArtifact.getFilename(), localArtifact.getId(),
|
||||
localArtifact.getSha1Hash())),
|
||||
ApiType.DMF)
|
||||
.stream()
|
||||
.collect(Collectors.toMap(ArtifactUrl::getProtocol, ArtifactUrl::getRef)));
|
||||
|
||||
@@ -102,6 +102,7 @@ class AmqpMessageDispatcherServiceTest extends AbstractIntegrationTest {
|
||||
when(tenantMetaData.getTenant()).thenReturn(TENANT);
|
||||
|
||||
when(systemManagement.getTenantMetadata()).thenReturn(tenantMetaData);
|
||||
when(systemManagement.getTenantMetadataWithoutDetails()).thenReturn(tenantMetaData);
|
||||
|
||||
amqpMessageDispatcherService = new AmqpMessageDispatcherService(rabbitTemplate, senderService,
|
||||
artifactUrlHandlerMock, systemSecurityContext, systemManagement, targetManagement, serviceMatcher,
|
||||
|
||||
@@ -144,8 +144,7 @@ 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 = 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
|
||||
|
||||
@@ -115,8 +115,7 @@ public class MgmtTenantManagementResource implements MgmtTenantManagementRestApi
|
||||
}
|
||||
|
||||
//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 @@ public class MgmtTenantManagementResource implements MgmtTenantManagementRestApi
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -361,5 +361,4 @@ public class MgmtTenantManagementResourceTest extends AbstractManagementApiInteg
|
||||
private Long getActualDefaultDsType() {
|
||||
return systemManagement.getTenantMetadata().getDefaultDsType().getId();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -103,7 +103,7 @@ public class MgmtSecurityConfiguration {
|
||||
(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);
|
||||
},
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -12,30 +12,31 @@ package org.eclipse.hawkbit.repository.model;
|
||||
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<SoftwareModuleType> 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<SoftwareModuleType> getOptionalModuleTypes();
|
||||
|
||||
/**
|
||||
* Checks if the given {@link SoftwareModuleType} is in this
|
||||
* {@link DistributionSetType}.
|
||||
* @param distributionSet to check for completeness
|
||||
* @return <code>true</code> if the all mandatory software module types are in the system.
|
||||
*/
|
||||
boolean checkComplete(DistributionSet distributionSet);
|
||||
|
||||
/**
|
||||
* Checks if the given {@link SoftwareModuleType} is in this {@link DistributionSetType}.
|
||||
*
|
||||
* @param softwareModuleType search for
|
||||
* @return <code>true</code> if found
|
||||
@@ -45,64 +46,22 @@ public interface DistributionSetType extends Type {
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given {@link SoftwareModuleType} is in this
|
||||
* {@link DistributionSetType}.
|
||||
*
|
||||
* @param softwareModuleTypeId search for by {@link SoftwareModuleType#getId()}
|
||||
* @return <code>true</code> if found
|
||||
*/
|
||||
default boolean containsModuleType(final Long softwareModuleTypeId) {
|
||||
return containsMandatoryModuleType(softwareModuleTypeId) || containsOptionalModuleType(softwareModuleTypeId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 <code>true</code> if found
|
||||
*/
|
||||
default boolean containsMandatoryModuleType(final SoftwareModuleType softwareModuleType) {
|
||||
return containsMandatoryModuleType(softwareModuleType.getId());
|
||||
return getMandatoryModuleTypes().stream().anyMatch(element -> element.getId().equals(softwareModuleType.getId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given {@link SoftwareModuleType} is in
|
||||
* {@link #getMandatoryModuleTypes()}.
|
||||
*
|
||||
* @param softwareModuleTypeId search for by {@link SoftwareModuleType#getId()}
|
||||
* @return <code>true</code> if found
|
||||
*/
|
||||
default boolean containsMandatoryModuleType(final Long softwareModuleTypeId) {
|
||||
return getMandatoryModuleTypes().stream().anyMatch(element -> element.getId().equals(softwareModuleTypeId));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 <code>true</code> if found
|
||||
*/
|
||||
default boolean containsOptionalModuleType(final SoftwareModuleType softwareModuleType) {
|
||||
return containsOptionalModuleType(softwareModuleType.getId());
|
||||
return getOptionalModuleTypes().stream().anyMatch(element -> element.getId().equals(softwareModuleType.getId()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the given {@link SoftwareModuleType} is in
|
||||
* {@link #getOptionalModuleTypes()}.
|
||||
*
|
||||
* @param softwareModuleTypeId search by {@link SoftwareModuleType#getId()}
|
||||
* @return <code>true</code> if found
|
||||
*/
|
||||
default boolean containsOptionalModuleType(final Long softwareModuleTypeId) {
|
||||
return getOptionalModuleTypes().stream().anyMatch(element -> element.getId().equals(softwareModuleTypeId));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param distributionSet to check for completeness
|
||||
* @return <code>true</code> if the all mandatory software module types are
|
||||
* in the system.
|
||||
*/
|
||||
boolean checkComplete(DistributionSet distributionSet);
|
||||
}
|
||||
@@ -623,7 +623,7 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
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 @@ public class JpaDistributionSetManagement implements DistributionSetManagement {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -173,8 +173,7 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
||||
|
||||
@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<String> consumer) {
|
||||
Page<String> tenants;
|
||||
@@ -207,7 +206,6 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
||||
|
||||
@Override
|
||||
public SystemUsageReport getSystemUsageStatistics() {
|
||||
|
||||
final Number count = (Number) entityManager.createNativeQuery(countSoftwareModulesQuery).getSingleResult();
|
||||
|
||||
long sumOfArtifacts = 0;
|
||||
@@ -232,22 +230,12 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
||||
|
||||
@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 class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
||||
@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 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
||||
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()));
|
||||
}
|
||||
|
||||
@@ -35,7 +35,6 @@ import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||
* {@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;
|
||||
|
||||
|
||||
@@ -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<DistributionSetTypeElement> elements = new HashSet<>();
|
||||
|
||||
@@ -118,10 +119,6 @@ public class JpaDistributionSetType extends AbstractJpaTypeEntity implements Dis
|
||||
return this;
|
||||
}
|
||||
|
||||
public Set<DistributionSetTypeElement> getElements() {
|
||||
return Collections.unmodifiableSet(elements);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DistributionSetType [key=" + getKey() + ", isDeleted()=" + isDeleted() + ", getId()=" + getId() + "]";
|
||||
|
||||
@@ -19,6 +19,8 @@ import jakarta.persistence.FetchType;
|
||||
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 @@ import org.eclipse.hawkbit.repository.model.TenantMetaData;
|
||||
@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")
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.eclipse.hawkbit.repository.jpa.model.JpaTenantMetaData;
|
||||
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 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
@Transactional(readOnly = true)
|
||||
public interface TenantMetaDataRepository extends PagingAndSortingRepository<JpaTenantMetaData, Long>, CrudRepository<JpaTenantMetaData, Long> {
|
||||
|
||||
/**
|
||||
* Search {@link TenantMetaData} by tenant name.
|
||||
*
|
||||
* @param tenant to search for
|
||||
* @return found {@link TenantMetaData} or <code>null</code>
|
||||
*/
|
||||
// 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<String> findTenants(final Pageable pageable);
|
||||
|
||||
/**
|
||||
* @param tenant
|
||||
*/
|
||||
@Transactional
|
||||
@Modifying
|
||||
@Query("DELETE FROM JpaTenantMetaData t WHERE UPPER(t.tenant) = UPPER(:tenant)")
|
||||
|
||||
@@ -212,7 +212,8 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
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 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@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<DistributionSetTag> skipTags = distributionSetTagManagement.create(
|
||||
repositoryProperties.getSkipImplicitLockForTags().stream()
|
||||
.map(String::toLowerCase)
|
||||
@@ -733,13 +733,12 @@ class DistributionSetManagementTest extends AbstractJpaIntegrationTest {
|
||||
@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();
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,15 @@ public class SystemManagementSecurityTest extends AbstractJpaIntegrationTest {
|
||||
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() {
|
||||
|
||||
@@ -130,7 +130,7 @@ class SystemManagementTest extends AbstractJpaIntegrationTest {
|
||||
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);
|
||||
|
||||
@@ -112,11 +112,10 @@ public class MultiTenancyEntityTest extends AbstractJpaIntegrationTest {
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user