Add AccessContext.asTenant and use where possible (#2838)
Signed-off-by: Avgustin Marinov <Avgustin.Marinov@bosch.com>
This commit is contained in:
@@ -12,6 +12,7 @@ package org.eclipse.hawkbit.context;
|
|||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -78,10 +79,7 @@ public class AccessContext {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sometimes 'system' need to override the auditor when do create/modify actions in context of a tenant and user.
|
// Sometimes 'system' need to override the auditor when do create/modify actions in context of an actor
|
||||||
// Though this could be made using runAsTenantAsUser sometimes (as in transaction) this override is needed
|
|
||||||
// after runAsTenantAsUser (because it seems that auditor is got in commit time).
|
|
||||||
// So this thread local variable provides option to override explicitly the auditor.
|
|
||||||
private static final ThreadLocal<String> ACTOR_OVERRIDE = new ThreadLocal<>();
|
private static final ThreadLocal<String> ACTOR_OVERRIDE = new ThreadLocal<>();
|
||||||
|
|
||||||
// Return the current actor / auditor / principal name. It could be a user (person), technical user, device, etc.
|
// Return the current actor / auditor / principal name. It could be a user (person), technical user, device, etc.
|
||||||
@@ -143,6 +141,34 @@ public class AccessContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs a given {@link Runnable} within a current authorities with set tenant in the context.
|
||||||
|
*
|
||||||
|
* @param tenant the tenant to be set in context.
|
||||||
|
* @param runnable the runnable to call within the tenant context
|
||||||
|
*/
|
||||||
|
public static void asTenant(final String tenant, final Runnable runnable) {
|
||||||
|
asTenant(tenant, () -> {
|
||||||
|
runnable.run();
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs a given {@link Supplier} within a current authorities with set tenant in the context.
|
||||||
|
*
|
||||||
|
* @param tenant the tenant to be set in context.
|
||||||
|
* @param supplier the supplier to call within the tenant context
|
||||||
|
* @return the return value of the {@link Supplier#get()} method.
|
||||||
|
*/
|
||||||
|
public static <T> T asTenant(final String tenant, final Supplier<T> supplier) {
|
||||||
|
final SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||||
|
securityContext.setAuthentication(new AuthenticationDelegate(
|
||||||
|
tenant, Optional.ofNullable(actor()).orElse(SYSTEM_ACTOR),
|
||||||
|
SecurityContextHolder.getContext().getAuthentication()));
|
||||||
|
return withSecurityContext(securityContext, supplier);
|
||||||
|
}
|
||||||
|
|
||||||
public static void asActor(final String actor, final Runnable runnable) {
|
public static void asActor(final String actor, final Runnable runnable) {
|
||||||
asActor(actor, () -> {
|
asActor(actor, () -> {
|
||||||
runnable.run();
|
runnable.run();
|
||||||
@@ -219,14 +245,12 @@ public class AccessContext {
|
|||||||
* @return the return value of the {@link Supplier#get()} method.
|
* @return the return value of the {@link Supplier#get()} method.
|
||||||
*/
|
*/
|
||||||
public static <T> T asSystemAsTenant(final String tenant, final Supplier<T> supplier) {
|
public static <T> T asSystemAsTenant(final String tenant, final Supplier<T> supplier) {
|
||||||
final SecurityContext currentContext = SecurityContextHolder.getContext();
|
log.debug("Entering system code execution");
|
||||||
try {
|
try {
|
||||||
log.debug("Entering system code execution");
|
|
||||||
final SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
final SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||||
securityContext.setAuthentication(new SystemCodeAuthentication(tenant));
|
securityContext.setAuthentication(new SystemCodeAuthentication(tenant));
|
||||||
return withSecurityContext(securityContext, supplier);
|
return withSecurityContext(securityContext, supplier);
|
||||||
} finally {
|
} finally {
|
||||||
SecurityContextHolder.setContext(currentContext);
|
|
||||||
log.debug("Leaving system code execution");
|
log.debug("Leaving system code execution");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -446,4 +470,83 @@ public class AccessContext {
|
|||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An {@link Authentication} implementation to delegate to an existing {@link Authentication} object except setting the details
|
||||||
|
* specifically for a specific tenant and user.
|
||||||
|
*/
|
||||||
|
private static final class AuthenticationDelegate implements Authentication {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final Authentication delegate;
|
||||||
|
private final TenantAwareUser principal;
|
||||||
|
private final TenantAwareAuthenticationDetails tenantAwareAuthenticationDetails;
|
||||||
|
|
||||||
|
private AuthenticationDelegate(final String tenant, final String username, final Authentication delegate) {
|
||||||
|
this.delegate = delegate;
|
||||||
|
principal = new TenantAwareUser(username, username, delegate != null ? delegate.getAuthorities() : Collections.emptyList(), tenant);
|
||||||
|
tenantAwareAuthenticationDetails = new TenantAwareAuthenticationDetails(tenant, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return delegate != null ? delegate.hashCode() : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object another) {
|
||||||
|
if (another instanceof Authentication anotherAuthentication) {
|
||||||
|
return Objects.equals(delegate, anotherAuthentication) &&
|
||||||
|
Objects.equals(principal, anotherAuthentication.getPrincipal()) &&
|
||||||
|
Objects.equals(tenantAwareAuthenticationDetails, anotherAuthentication.getDetails());
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return delegate != null ? delegate.toString() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return delegate != null ? delegate.getName() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||||
|
return principal.getAuthorities();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getCredentials() {
|
||||||
|
return delegate != null ? delegate.getCredentials() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getDetails() {
|
||||||
|
return tenantAwareAuthenticationDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getPrincipal() {
|
||||||
|
return principal;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAuthenticated() {
|
||||||
|
return delegate == null || delegate.isAuthenticated();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAuthenticated(final boolean isAuthenticated) {
|
||||||
|
if (delegate == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
delegate.setAuthenticated(isAuthenticated);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -9,11 +9,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.context;
|
package org.eclipse.hawkbit.context;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.eclipse.hawkbit.context.AccessContext.asSystemAsTenant;
|
import static org.eclipse.hawkbit.context.AccessContext.asSystemAsTenant;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.assertj.core.api.Assertions;
|
|
||||||
import org.eclipse.hawkbit.auth.SpRole;
|
import org.eclipse.hawkbit.auth.SpRole;
|
||||||
import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails;
|
import org.eclipse.hawkbit.tenancy.TenantAwareAuthenticationDetails;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@@ -23,32 +23,36 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
|||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
|
||||||
class SystemSecurityContextTest {
|
class AccessContextAsSystemTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void test() {
|
void test() {
|
||||||
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("test", "pass", List.of(new SimpleGrantedAuthority("anonymous")));
|
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
|
||||||
|
"test", "pass", List.of(new SimpleGrantedAuthority("anonymous")));
|
||||||
auth.setDetails("string details");
|
auth.setDetails("string details");
|
||||||
test(auth);
|
test(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testWithNullPrincipal() {
|
void testWithNullPrincipal() {
|
||||||
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(null, "pass", List.of(new SimpleGrantedAuthority("anonymous")));
|
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
|
||||||
|
null, "pass", List.of(new SimpleGrantedAuthority("anonymous")));
|
||||||
auth.setDetails("string details");
|
auth.setDetails("string details");
|
||||||
test(auth);
|
test(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testWithNullCredentials() {
|
void testWithNullCredentials() {
|
||||||
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken("test", null, List.of(new SimpleGrantedAuthority("anonymous")));
|
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
|
||||||
|
"test", null, List.of(new SimpleGrantedAuthority("anonymous")));
|
||||||
auth.setDetails("string details");
|
auth.setDetails("string details");
|
||||||
test(auth);
|
test(auth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testWitAllNull() {
|
void testWitAllNull() {
|
||||||
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(null, null, List.of(new SimpleGrantedAuthority("anonymous")));
|
final UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
|
||||||
|
null, null, List.of(new SimpleGrantedAuthority("anonymous")));
|
||||||
auth.setDetails(null);
|
auth.setDetails(null);
|
||||||
test(auth);
|
test(auth);
|
||||||
}
|
}
|
||||||
@@ -59,10 +63,10 @@ class SystemSecurityContextTest {
|
|||||||
SecurityContextHolder.setContext(sc);
|
SecurityContextHolder.setContext(sc);
|
||||||
asSystemAsTenant("tenant", () -> {
|
asSystemAsTenant("tenant", () -> {
|
||||||
final Authentication currentAuth = SecurityContextHolder.getContext().getAuthentication();
|
final Authentication currentAuth = SecurityContextHolder.getContext().getAuthentication();
|
||||||
Assertions.assertThat(currentAuth.getClass().getSimpleName()).isEqualTo("SystemCodeAuthentication");
|
assertThat(currentAuth.getClass().getSimpleName()).isEqualTo("SystemCodeAuthentication");
|
||||||
Assertions.assertThat(currentAuth.getCredentials()).isNull();
|
assertThat(currentAuth.getCredentials()).isNull();
|
||||||
Assertions.assertThat(currentAuth.getAuthorities()).isEqualTo(List.of(new SimpleGrantedAuthority(SpRole.SYSTEM_ROLE)));
|
assertThat(currentAuth.getAuthorities()).isEqualTo(List.of(new SimpleGrantedAuthority(SpRole.SYSTEM_ROLE)));
|
||||||
Assertions.assertThat(currentAuth.getDetails()).isEqualTo(new TenantAwareAuthenticationDetails("tenant", false));
|
assertThat(currentAuth.getDetails()).isEqualTo(new TenantAwareAuthenticationDetails("tenant", false));
|
||||||
});
|
});
|
||||||
SecurityContextHolder.clearContext();
|
SecurityContextHolder.clearContext();
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.security.controller;
|
package org.eclipse.hawkbit.security.controller;
|
||||||
|
|
||||||
import static org.eclipse.hawkbit.context.AccessContext.asSystemAsTenant;
|
import static org.eclipse.hawkbit.context.AccessContext.asTenant;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -47,9 +47,7 @@ public interface Authenticator {
|
|||||||
abstract class AbstractAuthenticator implements Authenticator {
|
abstract class AbstractAuthenticator implements Authenticator {
|
||||||
|
|
||||||
protected boolean isEnabled(final ControllerSecurityToken securityToken) {
|
protected boolean isEnabled(final ControllerSecurityToken securityToken) {
|
||||||
return asSystemAsTenant(
|
return asTenant(securityToken.getTenant(), () -> TenantConfigHelper.getAsSystem(getTenantConfigurationKey(), Boolean.class));
|
||||||
securityToken.getTenant(),
|
|
||||||
() -> TenantConfigHelper.getAsSystem(getTenantConfigurationKey(), Boolean.class));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract String getTenantConfigurationKey();
|
protected abstract String getTenantConfigurationKey();
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.security.controller;
|
package org.eclipse.hawkbit.security.controller;
|
||||||
|
|
||||||
import static org.eclipse.hawkbit.context.AccessContext.asSystemAsTenant;
|
import static org.eclipse.hawkbit.context.AccessContext.asTenant;
|
||||||
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_ENABLED;
|
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_ENABLED;
|
||||||
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY;
|
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY;
|
||||||
|
|
||||||
@@ -51,14 +51,10 @@ public class GatewayTokenAuthenticator extends Authenticator.AbstractAuthenticat
|
|||||||
final String presentedToken = authHeader.substring(OFFSET_GATEWAY_TOKEN);
|
final String presentedToken = authHeader.substring(OFFSET_GATEWAY_TOKEN);
|
||||||
|
|
||||||
// validate if the presented token is the same as the gateway token
|
// validate if the presented token is the same as the gateway token
|
||||||
return presentedToken.equals(asSystemAsTenant(
|
return presentedToken.equals(asTenant(controllerSecurityToken.getTenant(), () -> {
|
||||||
controllerSecurityToken.getTenant(),
|
log.trace("retrieving configuration value for configuration key {}", AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY);
|
||||||
() -> {
|
return TenantConfigHelper.getAsSystem(AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class);
|
||||||
log.trace("retrieving configuration value for configuration key {}", AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY);
|
})) ? authenticatedController(controllerSecurityToken.getTenant(), controllerSecurityToken.getControllerId()) : null;
|
||||||
return TenantConfigHelper.getAsSystem(AUTHENTICATION_GATEWAY_SECURITY_TOKEN_KEY, String.class);
|
|
||||||
}))
|
|
||||||
? authenticatedController(controllerSecurityToken.getTenant(), controllerSecurityToken.getControllerId())
|
|
||||||
: null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.security.controller;
|
package org.eclipse.hawkbit.security.controller;
|
||||||
|
|
||||||
import static org.eclipse.hawkbit.context.AccessContext.asSystemAsTenant;
|
import static org.eclipse.hawkbit.context.AccessContext.asTenant;
|
||||||
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_HEADER_AUTHORITY_NAME;
|
import static org.eclipse.hawkbit.tenancy.configuration.TenantConfigurationProperties.TenantConfigurationKey.AUTHENTICATION_HEADER_AUTHORITY_NAME;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -73,7 +73,7 @@ public class SecurityHeaderAuthenticator extends Authenticator.AbstractAuthentic
|
|||||||
|
|
||||||
final String sslIssuerHashValue = getIssuerHashHeader(
|
final String sslIssuerHashValue = getIssuerHashHeader(
|
||||||
controllerSecurityToken,
|
controllerSecurityToken,
|
||||||
asSystemAsTenant(
|
asTenant(
|
||||||
controllerSecurityToken.getTenant(),
|
controllerSecurityToken.getTenant(),
|
||||||
() -> TenantConfigHelper.getAsSystem(AUTHENTICATION_HEADER_AUTHORITY_NAME, String.class)));
|
() -> TenantConfigHelper.getAsSystem(AUTHENTICATION_HEADER_AUTHORITY_NAME, String.class)));
|
||||||
if (sslIssuerHashValue == null) {
|
if (sslIssuerHashValue == null) {
|
||||||
|
|||||||
@@ -19,8 +19,6 @@ import org.eclipse.hawkbit.context.AccessContext;
|
|||||||
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
import org.eclipse.hawkbit.repository.model.DistributionSetType;
|
||||||
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
import org.eclipse.hawkbit.repository.model.SoftwareModuleType;
|
||||||
import org.eclipse.hawkbit.repository.model.TenantMetaData;
|
import org.eclipse.hawkbit.repository.model.TenantMetaData;
|
||||||
import org.springframework.data.domain.Page;
|
|
||||||
import org.springframework.data.domain.Pageable;
|
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,22 +26,15 @@ import org.springframework.security.access.prepost.PreAuthorize;
|
|||||||
*/
|
*/
|
||||||
public interface SystemManagement {
|
public interface SystemManagement {
|
||||||
|
|
||||||
/**
|
|
||||||
* @param pageable for paging information
|
|
||||||
* @return list of all tenant names in the system.
|
|
||||||
*/
|
|
||||||
@PreAuthorize(SpringEvalExpressions.HAS_AUTH_SYSTEM_ADMIN)
|
|
||||||
Page<String> findTenants(@NotNull Pageable pageable);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs consumer for each tenant as
|
* Runs consumer for each tenant as
|
||||||
* {@link AccessContext#asSystemAsTenant(String, java.util.concurrent.Callable)}
|
* {@link AccessContext#asSystemAsTenant(String, Runnable)}
|
||||||
* silently (i.e. exceptions will be logged but operations will continue for further tenants).
|
* silently (i.e. exceptions will be logged but operations will continue for further tenants).
|
||||||
*
|
*
|
||||||
* @param consumer to run as tenant
|
* @param consumer to run as tenant
|
||||||
*/
|
*/
|
||||||
@PreAuthorize(SpringEvalExpressions.IS_SYSTEM_CODE)
|
@PreAuthorize(SpringEvalExpressions.IS_SYSTEM_CODE)
|
||||||
void forEachTenant(Consumer<String> consumer);
|
void forEachTenantAsSystem(Consumer<String> consumer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {@link TenantMetaData} of {@link AccessContext#tenant()}
|
* @return {@link TenantMetaData} of {@link AccessContext#tenant()}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository;
|
package org.eclipse.hawkbit.repository;
|
||||||
|
|
||||||
import static org.eclipse.hawkbit.context.AccessContext.asSystemAsTenant;
|
import static org.eclipse.hawkbit.context.AccessContext.asTenant;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -54,7 +54,6 @@ public class RolloutStatusCache {
|
|||||||
* Retrieves cached list of {@link TotalTargetCountActionStatus} of {@link Rollout}s.
|
* Retrieves cached list of {@link TotalTargetCountActionStatus} of {@link Rollout}s.
|
||||||
*
|
*
|
||||||
* @param rolloutId to retrieve cache entries for
|
* @param rolloutId to retrieve cache entries for
|
||||||
* @return map of cached entries
|
|
||||||
*/
|
*/
|
||||||
public static List<TotalTargetCountActionStatus> getRolloutStatus(final Long rolloutId) {
|
public static List<TotalTargetCountActionStatus> getRolloutStatus(final Long rolloutId) {
|
||||||
return retrieveFromCache(rolloutId, getRolloutStatusCache());
|
return retrieveFromCache(rolloutId, getRolloutStatusCache());
|
||||||
@@ -74,7 +73,6 @@ public class RolloutStatusCache {
|
|||||||
* Retrieves cached list of {@link TotalTargetCountActionStatus} of {@link RolloutGroup}.
|
* Retrieves cached list of {@link TotalTargetCountActionStatus} of {@link RolloutGroup}.
|
||||||
*
|
*
|
||||||
* @param groupId to retrieve cache entries for
|
* @param groupId to retrieve cache entries for
|
||||||
* @return map of cached entries
|
|
||||||
*/
|
*/
|
||||||
public static List<TotalTargetCountActionStatus> getRolloutGroupStatus(final Long groupId) {
|
public static List<TotalTargetCountActionStatus> getRolloutGroupStatus(final Long groupId) {
|
||||||
return retrieveFromCache(groupId, getGroupStatusCache());
|
return retrieveFromCache(groupId, getGroupStatusCache());
|
||||||
@@ -122,34 +120,29 @@ public class RolloutStatusCache {
|
|||||||
@EventListener(classes = AbstractActionEvent.class)
|
@EventListener(classes = AbstractActionEvent.class)
|
||||||
public void invalidateCachedTotalTargetCountActionStatus(final AbstractActionEvent event) {
|
public void invalidateCachedTotalTargetCountActionStatus(final AbstractActionEvent event) {
|
||||||
if (event.getRolloutId() != null) {
|
if (event.getRolloutId() != null) {
|
||||||
final Cache cache = asSystemAsTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_RO_NAME));
|
asTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_RO_NAME)).evict(event.getRolloutId());
|
||||||
cache.evict(event.getRolloutId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.getRolloutGroupId() != null) {
|
if (event.getRolloutGroupId() != null) {
|
||||||
final Cache cache = asSystemAsTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_GR_NAME));
|
asTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_GR_NAME)).evict(event.getRolloutGroupId());
|
||||||
cache.evict(event.getRolloutGroupId());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventListener(classes = RolloutDeletedEvent.class)
|
@EventListener(classes = RolloutDeletedEvent.class)
|
||||||
public void invalidateCachedTotalTargetCountOnRolloutDelete(final RolloutDeletedEvent event) {
|
public void invalidateCachedTotalTargetCountOnRolloutDelete(final RolloutDeletedEvent event) {
|
||||||
final Cache cache = asSystemAsTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_RO_NAME));
|
asTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_RO_NAME)).evict(event.getEntityId());
|
||||||
cache.evict(event.getEntityId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventListener(classes = RolloutGroupDeletedEvent.class)
|
@EventListener(classes = RolloutGroupDeletedEvent.class)
|
||||||
public void invalidateCachedTotalTargetCountOnRolloutGroupDelete(final RolloutGroupDeletedEvent event) {
|
public void invalidateCachedTotalTargetCountOnRolloutGroupDelete(final RolloutGroupDeletedEvent event) {
|
||||||
final Cache cache = asSystemAsTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_GR_NAME));
|
asTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_GR_NAME)).evict(event.getEntityId());
|
||||||
cache.evict(event.getEntityId());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventListener(classes = RolloutStoppedEvent.class)
|
@EventListener(classes = RolloutStoppedEvent.class)
|
||||||
public void invalidateCachedTotalTargetCountOnRolloutStopped(final RolloutStoppedEvent event) {
|
public void invalidateCachedTotalTargetCountOnRolloutStopped(final RolloutStoppedEvent event) {
|
||||||
final Cache cache = asSystemAsTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_RO_NAME));
|
final Cache cache = asTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_RO_NAME));
|
||||||
cache.evict(event.getRolloutId());
|
cache.evict(event.getRolloutId());
|
||||||
event.getRolloutGroupIds().forEach(
|
event.getRolloutGroupIds().forEach(groupId -> asTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_GR_NAME)).evict(groupId));
|
||||||
groupId -> asSystemAsTenant(event.getTenant(), () -> CACHE_MANAGER.getCache(CACHE_GR_NAME)).evict(groupId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static @NotNull Map<Long, List<TotalTargetCountActionStatus>> retrieveFromCache(final List<Long> ids, @NotNull final Cache cache) {
|
private static @NotNull Map<Long, List<TotalTargetCountActionStatus>> retrieveFromCache(final List<Long> ids, @NotNull final Cache cache) {
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public class AutoCleanupScheduler {
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("squid:S3516")
|
@SuppressWarnings("squid:S3516")
|
||||||
private Void executeAutoCleanup() {
|
private Void executeAutoCleanup() {
|
||||||
systemManagement.forEachTenant(tenant -> cleanupTasks.forEach(task -> {
|
systemManagement.forEachTenantAsSystem(tenant -> cleanupTasks.forEach(task -> {
|
||||||
final Lock lock = lockRegistry.obtain(AUTO_CLEANUP + SEP + task.getId() + SEP + tenant);
|
final Lock lock = lockRegistry.obtain(AUTO_CLEANUP + SEP + task.getId() + SEP + tenant);
|
||||||
if (!lock.tryLock()) {
|
if (!lock.tryLock()) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.eclipse.hawkbit.repository.jpa.event;
|
package org.eclipse.hawkbit.repository.jpa.event;
|
||||||
|
|
||||||
import static org.eclipse.hawkbit.context.AccessContext.asSystemAsTenant;
|
import static org.eclipse.hawkbit.context.AccessContext.asTenant;
|
||||||
|
|
||||||
import jakarta.persistence.EntityManager;
|
import jakarta.persistence.EntityManager;
|
||||||
|
|
||||||
@@ -36,6 +36,6 @@ public class JpaEventEntityManager implements EventEntityManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <E extends TenantAwareBaseEntity> E findEntity(final String tenant, final Long id, final Class<E> entityType) {
|
public <E extends TenantAwareBaseEntity> E findEntity(final String tenant, final Long id, final Class<E> entityType) {
|
||||||
return asSystemAsTenant(tenant, () -> entityManager.find(entityType, id));
|
return asTenant(tenant, () -> entityManager.find(entityType, id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,6 @@ package org.eclipse.hawkbit.repository.jpa.management;
|
|||||||
|
|
||||||
import static org.eclipse.hawkbit.context.AccessContext.asActor;
|
import static org.eclipse.hawkbit.context.AccessContext.asActor;
|
||||||
import static org.eclipse.hawkbit.context.AccessContext.asSystem;
|
import static org.eclipse.hawkbit.context.AccessContext.asSystem;
|
||||||
import static org.eclipse.hawkbit.context.AccessContext.asSystemAsTenant;
|
|
||||||
import static org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor.afterCommit;
|
import static org.eclipse.hawkbit.repository.jpa.executor.AfterTransactionCommitExecutor.afterCommit;
|
||||||
import static org.eclipse.hawkbit.repository.model.Action.Status.DOWNLOADED;
|
import static org.eclipse.hawkbit.repository.model.Action.Status.DOWNLOADED;
|
||||||
import static org.eclipse.hawkbit.repository.model.Action.Status.FINISHED;
|
import static org.eclipse.hawkbit.repository.model.Action.Status.FINISHED;
|
||||||
@@ -125,7 +124,6 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.transaction.PlatformTransactionManager;
|
import org.springframework.transaction.PlatformTransactionManager;
|
||||||
import org.springframework.transaction.annotation.Isolation;
|
import org.springframework.transaction.annotation.Isolation;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.transaction.support.TransactionCallback;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
@@ -694,11 +692,10 @@ public class JpaControllerManagement extends JpaActionManagement implements Cont
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
events.stream().collect(Collectors.groupingBy(TargetPoll::getTenant)).forEach((tenant, polls) -> {
|
events.stream().collect(Collectors.groupingBy(TargetPoll::getTenant))
|
||||||
final TransactionCallback<Void> createTransaction = status -> updateLastTargetQueries(tenant, polls);
|
.forEach((tenant, polls) -> DeploymentHelper.runInNewTransaction(
|
||||||
asSystemAsTenant(
|
txManager, "flushUpdateQueue",
|
||||||
tenant, () -> DeploymentHelper.runInNewTransaction(txManager, "flushUpdateQueue", createTransaction));
|
status -> updateLastTargetQueries(tenant, polls)));
|
||||||
});
|
|
||||||
} catch (final RuntimeException ex) {
|
} catch (final RuntimeException ex) {
|
||||||
log.error("Failed to persist UpdateQueue content.", ex);
|
log.error("Failed to persist UpdateQueue content.", ex);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
package org.eclipse.hawkbit.repository.jpa.management;
|
package org.eclipse.hawkbit.repository.jpa.management;
|
||||||
|
|
||||||
import static org.eclipse.hawkbit.context.AccessContext.asSystemAsTenant;
|
import static org.eclipse.hawkbit.context.AccessContext.asSystemAsTenant;
|
||||||
|
import static org.eclipse.hawkbit.context.AccessContext.asTenant;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
@@ -136,20 +137,15 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
|||||||
return currentTenantCacheKeyGenerator.currentTenantKeyGenerator();
|
return currentTenantCacheKeyGenerator.currentTenantKeyGenerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Page<String> findTenants(final Pageable pageable) {
|
|
||||||
return tenantMetaDataRepository.findTenants(pageable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(propagation = Propagation.NOT_SUPPORTED)
|
@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")
|
@SuppressWarnings("squid:S2229")
|
||||||
public void forEachTenant(final Consumer<String> consumer) {
|
public void forEachTenantAsSystem(final Consumer<String> consumer) {
|
||||||
Page<String> tenants;
|
Page<String> tenants;
|
||||||
Pageable query = PageRequest.of(0, MAX_TENANTS_QUERY);
|
Pageable query = PageRequest.of(0, MAX_TENANTS_QUERY);
|
||||||
do {
|
do {
|
||||||
tenants = findTenants(query); // with IS_SYSTEM_CODE so we could find all tenants
|
tenants = tenantMetaDataRepository.findTenants(query); // with IS_SYSTEM_CODE so we could find all tenants
|
||||||
tenants.forEach(tenant -> asSystemAsTenant(tenant, () -> {
|
tenants.forEach(tenant -> asSystemAsTenant(tenant, () -> {
|
||||||
try {
|
try {
|
||||||
consumer.accept(tenant);
|
consumer.accept(tenant);
|
||||||
@@ -200,7 +196,7 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
|||||||
}
|
}
|
||||||
|
|
||||||
final String tenant = t.toUpperCase();
|
final String tenant = t.toUpperCase();
|
||||||
asSystemAsTenant(tenant, () -> DeploymentHelper.runInNewTransaction(txManager, "deleteTenant", status -> {
|
asTenant(tenant, () -> DeploymentHelper.runInNewTransaction(txManager, "deleteTenant", status -> {
|
||||||
tenantMetaDataRepository.deleteByTenantIgnoreCase(tenant);
|
tenantMetaDataRepository.deleteByTenantIgnoreCase(tenant);
|
||||||
tenantConfigurationRepository.deleteByTenant(tenant);
|
tenantConfigurationRepository.deleteByTenant(tenant);
|
||||||
targetRepository.deleteByTenant(tenant);
|
targetRepository.deleteByTenant(tenant);
|
||||||
@@ -293,10 +289,9 @@ public class JpaSystemManagement implements CurrentTenantCacheKeyGenerator, Syst
|
|||||||
* @return the initial created {@link TenantMetaData}
|
* @return the initial created {@link TenantMetaData}
|
||||||
*/
|
*/
|
||||||
private TenantMetaData createInitialTenantMetaData(final String tenant) {
|
private TenantMetaData createInitialTenantMetaData(final String tenant) {
|
||||||
return asSystemAsTenant(
|
return asSystemAsTenant(tenant, () -> DeploymentHelper.runInNewTransaction(txManager, "initial-tenant-creation", status -> {
|
||||||
tenant, () -> DeploymentHelper.runInNewTransaction(txManager, "initial-tenant-creation", status -> {
|
final DistributionSetType defaultDsType = createStandardSoftwareDataSetup();
|
||||||
final DistributionSetType defaultDsType = createStandardSoftwareDataSetup();
|
return tenantMetaDataRepository.save(new JpaTenantMetaData(defaultDsType, tenant));
|
||||||
return tenantMetaDataRepository.save(new JpaTenantMetaData(defaultDsType, tenant));
|
}));
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@ public class AutoAssignScheduler {
|
|||||||
final long startNano = java.lang.System.nanoTime();
|
final long startNano = java.lang.System.nanoTime();
|
||||||
try {
|
try {
|
||||||
log.debug("Auto assign scheduled execution has acquired lock and started for each tenant.");
|
log.debug("Auto assign scheduled execution has acquired lock and started for each tenant.");
|
||||||
systemManagement.forEachTenant(tenant -> {
|
systemManagement.forEachTenantAsSystem(tenant -> {
|
||||||
final long startNanoT = java.lang.System.nanoTime();
|
final long startNanoT = java.lang.System.nanoTime();
|
||||||
|
|
||||||
autoAssignExecutor.checkAllTargets();
|
autoAssignExecutor.checkAllTargets();
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public class RolloutScheduler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scheduler method called by the spring-async mechanism. For all tenants, using {@link SystemManagement#forEachTenant},
|
* Scheduler method called by the spring-async mechanism. For all tenants, using {@link SystemManagement#forEachTenantAsSystem},
|
||||||
* runs the {@link RolloutHandler#handleAll()} scoped to permission of access control context or unscoped (with {@link System}) if null
|
* runs the {@link RolloutHandler#handleAll()} scoped to permission of access control context or unscoped (with {@link System}) if null
|
||||||
*/
|
*/
|
||||||
@Scheduled(initialDelayString = PROP_SCHEDULER_DELAY_PLACEHOLDER, fixedDelayString = PROP_SCHEDULER_DELAY_PLACEHOLDER)
|
@Scheduled(initialDelayString = PROP_SCHEDULER_DELAY_PLACEHOLDER, fixedDelayString = PROP_SCHEDULER_DELAY_PLACEHOLDER)
|
||||||
@@ -63,7 +63,7 @@ public class RolloutScheduler {
|
|||||||
// workaround eclipselink that is currently not possible to execute a query without multi-tenancy if MultiTenant
|
// workaround eclipselink that is currently not possible to execute a query without multi-tenancy if MultiTenant
|
||||||
// annotation is used. https://bugs.eclipse.org/bugs/show_bug.cgi?id=355458. So
|
// annotation is used. https://bugs.eclipse.org/bugs/show_bug.cgi?id=355458. So
|
||||||
// iterate through all tenants and execute the rollout check for each tenant separately.
|
// iterate through all tenants and execute the rollout check for each tenant separately.
|
||||||
systemManagement.forEachTenant(tenant -> {
|
systemManagement.forEachTenantAsSystem(tenant -> {
|
||||||
if (rolloutTaskExecutor == null) {
|
if (rolloutTaskExecutor == null) {
|
||||||
handleAll(tenant);
|
handleAll(tenant);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import static org.mockito.Mockito.doAnswer;
|
|||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.util.Collections;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.awaitility.Awaitility;
|
import org.awaitility.Awaitility;
|
||||||
@@ -63,8 +63,7 @@ class ConcurrentDistributionSetInvalidationTest extends AbstractJpaIntegrationTe
|
|||||||
final Rollout rollout = createRollout(distributionSet);
|
final Rollout rollout = createRollout(distributionSet);
|
||||||
final String tenant = AccessContext.tenant();
|
final String tenant = AccessContext.tenant();
|
||||||
|
|
||||||
// run in new Thread so that the invalidation can be executed in
|
// run in new Thread so that the invalidation can be executed in parallel
|
||||||
// parallel
|
|
||||||
new Thread(() -> asSystemAsTenant(tenant, rolloutHandler::handleAll)).start();
|
new Thread(() -> asSystemAsTenant(tenant, rolloutHandler::handleAll)).start();
|
||||||
|
|
||||||
// wait until at least one RolloutGroup is created, as this means that the thread has started and has acquired the lock
|
// wait until at least one RolloutGroup is created, as this means that the thread has started and has acquired the lock
|
||||||
@@ -74,7 +73,7 @@ class ConcurrentDistributionSetInvalidationTest extends AbstractJpaIntegrationTe
|
|||||||
.until(() -> asSystemAsTenant(tenant, () -> rolloutGroupManagement.findByRollout(rollout.getId(), PAGE).getSize() > 0));
|
.until(() -> asSystemAsTenant(tenant, () -> rolloutGroupManagement.findByRollout(rollout.getId(), PAGE).getSize() > 0));
|
||||||
|
|
||||||
final DistributionSetInvalidation distributionSetInvalidation = new DistributionSetInvalidation(
|
final DistributionSetInvalidation distributionSetInvalidation = new DistributionSetInvalidation(
|
||||||
Collections.singletonList(distributionSet.getId()), ActionCancellationType.SOFT);
|
List.of(distributionSet.getId()), ActionCancellationType.SOFT);
|
||||||
assertThatExceptionOfType(StopRolloutException.class)
|
assertThatExceptionOfType(StopRolloutException.class)
|
||||||
.as("Invalidation of distributionSet should throw an exception")
|
.as("Invalidation of distributionSet should throw an exception")
|
||||||
.isThrownBy(() -> distributionSetInvalidationManagement.invalidateDistributionSet(distributionSetInvalidation));
|
.isThrownBy(() -> distributionSetInvalidationManagement.invalidateDistributionSet(distributionSetInvalidation));
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ package org.eclipse.hawkbit.repository.jpa.management;
|
|||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.hawkbit.auth.SpRole;
|
import org.eclipse.hawkbit.auth.SpRole;
|
||||||
@@ -37,11 +38,15 @@ class SystemManagementTest extends AbstractJpaIntegrationTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
void findTenantsReturnsAllTenantsNotOnlyWhichLoggedIn() {
|
void findTenantsReturnsAllTenantsNotOnlyWhichLoggedIn() {
|
||||||
assertThat(systemManagement.findTenants(PAGE).getContent()).hasSize(1);
|
assertThat(listTenants()).hasSize(1);
|
||||||
|
|
||||||
createTestTenantsForSystemStatistics(2, 0, 0, 0);
|
createTestTenantsForSystemStatistics(2, 0, 0, 0);
|
||||||
|
assertThat(listTenants()).hasSize(3);
|
||||||
|
}
|
||||||
|
|
||||||
assertThat(systemManagement.findTenants(PAGE).getContent()).hasSize(3);
|
private List<String> listTenants() {
|
||||||
|
final List<String> tenants = new ArrayList<>();
|
||||||
|
systemManagement.forEachTenantAsSystem(tenants::add);
|
||||||
|
return tenants;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createTestTenantsForSystemStatistics(final int tenants, final int artifactSize, final int targets, final int updates) {
|
private void createTestTenantsForSystemStatistics(final int tenants, final int artifactSize, final int targets, final int updates) {
|
||||||
|
|||||||
@@ -11,11 +11,14 @@ package org.eclipse.hawkbit.repository.jpa.tenancy;
|
|||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.fail;
|
import static org.assertj.core.api.Assertions.fail;
|
||||||
|
import static org.eclipse.hawkbit.context.AccessContext.asSystem;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
|
import org.eclipse.hawkbit.context.AccessContext;
|
||||||
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
import org.eclipse.hawkbit.repository.exception.EntityNotFoundException;
|
||||||
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
import org.eclipse.hawkbit.repository.jpa.AbstractJpaIntegrationTest;
|
||||||
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
import org.eclipse.hawkbit.repository.model.DistributionSet;
|
||||||
@@ -59,8 +62,7 @@ class MultiTenancyEntityTest extends AbstractJpaIntegrationTest {
|
|||||||
assertThat(findTargetsForTenant.getContent().get(0).getTenant().toUpperCase()).isEqualTo(tenant.toUpperCase());
|
assertThat(findTargetsForTenant.getContent().get(0).getTenant().toUpperCase()).isEqualTo(tenant.toUpperCase());
|
||||||
final Page<? extends Target> findTargetsForAnotherTenant = findTargetsForTenant(anotherTenant);
|
final Page<? extends Target> findTargetsForAnotherTenant = findTargetsForTenant(anotherTenant);
|
||||||
assertThat(findTargetsForAnotherTenant).hasSize(1);
|
assertThat(findTargetsForAnotherTenant).hasSize(1);
|
||||||
assertThat(findTargetsForAnotherTenant.getContent().get(0).getTenant().toUpperCase())
|
assertThat(findTargetsForAnotherTenant.getContent().get(0).getTenant().toUpperCase()).isEqualTo(anotherTenant.toUpperCase());
|
||||||
.isEqualTo(anotherTenant.toUpperCase());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,11 +98,9 @@ class MultiTenancyEntityTest extends AbstractJpaIntegrationTest {
|
|||||||
final String controllerAnotherTenant = "anotherController";
|
final String controllerAnotherTenant = "anotherController";
|
||||||
createTargetForTenant(controllerAnotherTenant, anotherTenant);
|
createTargetForTenant(controllerAnotherTenant, anotherTenant);
|
||||||
|
|
||||||
assertThat(systemManagement.findTenants(PAGE)).as("Expected number if tenants before deletion is").hasSize(3);
|
assertThat(listTenants()).as("Expected number if tenants before deletion is").hasSize(3);
|
||||||
|
|
||||||
systemManagement.deleteTenant(anotherTenant);
|
systemManagement.deleteTenant(anotherTenant);
|
||||||
|
assertThat(listTenants()).as("Expected number if tenants after deletion is").hasSize(2);
|
||||||
assertThat(systemManagement.findTenants(PAGE)).as("Expected number if tenants after deletion is").hasSize(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -202,4 +202,10 @@ class MultiTenancyEntityTest extends AbstractJpaIntegrationTest {
|
|||||||
private Slice<? extends DistributionSet> findDistributionSetForTenant(final String tenant) throws Exception {
|
private Slice<? extends DistributionSet> findDistributionSetForTenant(final String tenant) throws Exception {
|
||||||
return runAsTenant(tenant, () -> distributionSetManagement.findAll(PAGE));
|
return runAsTenant(tenant, () -> distributionSetManagement.findAll(PAGE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<String> listTenants() {
|
||||||
|
final List<String> tenants = new ArrayList<>();
|
||||||
|
asSystem(() -> systemManagement.forEachTenantAsSystem(tenants::add));
|
||||||
|
return tenants;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ public class CleanupTestExecutionListener extends AbstractTestExecutionListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void clearTestRepository(final SystemManagement systemManagement) {
|
private void clearTestRepository(final SystemManagement systemManagement) {
|
||||||
asSystem(() -> systemManagement.forEachTenant(tenant -> {
|
asSystem(() -> systemManagement.forEachTenantAsSystem(tenant -> {
|
||||||
try {
|
try {
|
||||||
asSystem(() -> systemManagement.deleteTenant(tenant));
|
asSystem(() -> systemManagement.deleteTenant(tenant));
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user