add supportExpansionTenant
This commit is contained in:
parent
cdaf9d43d5
commit
cae4003af5
|
@ -6,4 +6,14 @@ import org.springframework.context.annotation.Configuration;
|
|||
@Configuration
|
||||
@EnableConfigurationProperties(MultitenancyProperties.class)
|
||||
public class MultitenancyConfiguration {
|
||||
private final MultitenancyProperties config;
|
||||
|
||||
|
||||
public MultitenancyConfiguration(MultitenancyProperties config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public MultitenancyProperties getConfig() {
|
||||
return this.config;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||
@ConfigurationProperties(prefix = "tenant.multitenancy")
|
||||
public class MultitenancyProperties {
|
||||
private boolean isMultitenant;
|
||||
private boolean supportExpansionTenant;
|
||||
private String defaultTenantCode;
|
||||
|
||||
public boolean isMultitenant() {
|
||||
|
@ -15,6 +16,10 @@ public class MultitenancyProperties {
|
|||
this.isMultitenant = multitenant;
|
||||
}
|
||||
|
||||
public void setMultitenant(boolean multitenant) {
|
||||
this.isMultitenant = multitenant;
|
||||
}
|
||||
|
||||
public String getDefaultTenantCode() {
|
||||
return this.defaultTenantCode;
|
||||
}
|
||||
|
@ -22,4 +27,13 @@ public class MultitenancyProperties {
|
|||
public void setDefaultTenantCode(String defaultTenantCode) {
|
||||
this.defaultTenantCode = defaultTenantCode;
|
||||
}
|
||||
|
||||
public boolean getSupportExpansionTenant() {
|
||||
return this.supportExpansionTenant;
|
||||
}
|
||||
|
||||
public void setSupportExpansionTenant(boolean supportExpansionTenant) {
|
||||
this.supportExpansionTenant = supportExpansionTenant;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,23 +13,27 @@ import java.util.concurrent.atomic.AtomicReference;
|
|||
@RequestScope
|
||||
public class TenantScope {
|
||||
public static final String TenantReplaceParameter = "::TenantCode::";
|
||||
private final MultitenancyProperties multitenancy;
|
||||
private final MultitenancyConfiguration multitenancyConfiguration;
|
||||
private final AtomicReference<UUID> tenant = new AtomicReference<>();
|
||||
private final AtomicReference<String> tenantCode = new AtomicReference<>();
|
||||
private final AtomicReference<UUID> initialTenant = new AtomicReference<>();
|
||||
private final AtomicReference<String> initialTenantCode = new AtomicReference<>();
|
||||
|
||||
@Autowired
|
||||
public TenantScope(MultitenancyProperties multitenancy) {
|
||||
this.multitenancy = multitenancy;
|
||||
public TenantScope(MultitenancyConfiguration multitenancyConfiguration) {
|
||||
this.multitenancyConfiguration = multitenancyConfiguration;
|
||||
}
|
||||
|
||||
public Boolean isMultitenant() {
|
||||
return this.multitenancy.isMultitenant();
|
||||
return this.multitenancyConfiguration.getConfig().isMultitenant();
|
||||
}
|
||||
|
||||
public Boolean supportExpansionTenant() {
|
||||
return this.multitenancyConfiguration.getConfig().getSupportExpansionTenant();
|
||||
}
|
||||
|
||||
public String getDefaultTenantCode() {
|
||||
return this.multitenancy.getDefaultTenantCode();
|
||||
return this.multitenancyConfiguration.getConfig().getDefaultTenantCode();
|
||||
}
|
||||
|
||||
public Boolean isSet() {
|
||||
|
@ -40,8 +44,8 @@ public class TenantScope {
|
|||
|
||||
public Boolean isDefaultTenant() {
|
||||
if (!this.isMultitenant())
|
||||
return Boolean.TRUE;
|
||||
return this.multitenancy.getDefaultTenantCode().equalsIgnoreCase(this.tenantCode.get());
|
||||
return Boolean.FALSE;
|
||||
return this.supportExpansionTenant() && this.multitenancyConfiguration.getConfig().getDefaultTenantCode().equalsIgnoreCase(this.tenantCode.get());
|
||||
}
|
||||
|
||||
public UUID getTenant() throws InvalidApplicationException {
|
||||
|
|
|
@ -72,7 +72,7 @@ public class TenantEntityManager {
|
|||
if (!this.tenantFiltersDisabled && this.tenantScope.isMultitenant() && (entity instanceof TenantScoped tenantScopedEntity)) {
|
||||
if (tenantScopedEntity.getTenantId() != null && !tenantScopedEntity.getTenantId().equals(this.tenantScope.getTenant())) return null;
|
||||
}
|
||||
if (disableTracking && entity != null) this.entityManager.detach(entity);
|
||||
if (disableTracking) this.entityManager.detach(entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
@ -95,8 +95,10 @@ public class TenantEntityManager {
|
|||
}
|
||||
|
||||
public void reloadTenantFilters() throws InvalidApplicationException {
|
||||
if (!this.entityManager.isOpen()) return;
|
||||
|
||||
if (!this.entityManager.isOpen()) {
|
||||
this.tenantFiltersDisabled = false;
|
||||
return;
|
||||
}
|
||||
this.disableTenantFilters();
|
||||
|
||||
if (!this.tenantScope.isSet()) return;
|
||||
|
@ -115,8 +117,10 @@ public class TenantEntityManager {
|
|||
}
|
||||
|
||||
public void loadExplicitTenantFilters() throws InvalidApplicationException {
|
||||
if (!this.entityManager.isOpen()) return;
|
||||
|
||||
if (!this.entityManager.isOpen()) {
|
||||
this.tenantFiltersDisabled = false;
|
||||
return;
|
||||
}
|
||||
this.disableTenantFilters();
|
||||
|
||||
if (!this.tenantScope.isSet()) return;
|
||||
|
@ -135,8 +139,10 @@ public class TenantEntityManager {
|
|||
}
|
||||
|
||||
public void disableTenantFilters() {
|
||||
if (!this.entityManager.isOpen()) return;
|
||||
|
||||
if (!this.entityManager.isOpen()) {
|
||||
this.tenantFiltersDisabled = true;
|
||||
return;
|
||||
}
|
||||
this.entityManager
|
||||
.unwrap(Session.class)
|
||||
.disableFilter(TenantScopedBaseEntity.TENANT_FILTER);
|
||||
|
|
|
@ -74,7 +74,7 @@ public class TenantListener {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (entity.getTenantId() != null && (!this.tenantScope.isDefaultTenant() ||entity.getTenantId().compareTo(this.tenantScope.getTenant()) != 0)) {
|
||||
if (entity.getTenantId() != null) {
|
||||
logger.error("somebody tried to change an entries tenant");
|
||||
throw new MyForbiddenException(this.errors.getTenantTampering().getCode(), this.errors.getTenantTampering().getMessage());
|
||||
}
|
||||
|
|
|
@ -90,15 +90,20 @@ public class AnnotationEntityCreatedIntegrationEventHandlerImpl implements Annot
|
|||
EventProcessingStatus status = EventProcessingStatus.Success;
|
||||
try {
|
||||
|
||||
if (this.tenantScope.isMultitenant() && properties.getTenantId() != null) {
|
||||
TenantEntity tenant = this.queryFactory.query(TenantQuery.class).disableTracking().ids(properties.getTenantId()).firstAs(new BaseFieldSet().ensure(Tenant._id).ensure(Tenant._code));
|
||||
if (tenant == null) {
|
||||
if (this.tenantScope.isMultitenant()) {
|
||||
if (properties.getTenantId() != null) {
|
||||
TenantEntity tenant = this.queryFactory.query(TenantQuery.class).disableTracking().ids(properties.getTenantId()).firstAs(new BaseFieldSet().ensure(Tenant._id).ensure(Tenant._code));
|
||||
if (tenant == null) {
|
||||
logger.error("missing tenant from event message");
|
||||
return EventProcessingStatus.Error;
|
||||
}
|
||||
this.tenantScope.setTempTenant(this.tenantEntityManager, properties.getTenantId(), tenant.getCode());
|
||||
} else if (this.tenantScope.supportExpansionTenant()) {
|
||||
this.tenantScope.setTempTenant(this.tenantEntityManager, null, this.tenantScope.getDefaultTenantCode());
|
||||
} else {
|
||||
logger.error("missing tenant from event message");
|
||||
return EventProcessingStatus.Error;
|
||||
}
|
||||
this.tenantScope.setTempTenant(this.tenantEntityManager, properties.getTenantId(), tenant.getCode());
|
||||
} else if (this.tenantScope.isMultitenant()) {
|
||||
this.tenantScope.setTempTenant(this.tenantEntityManager, null, this.tenantScope.getDefaultTenantCode());
|
||||
}
|
||||
|
||||
this.currentPrincipalResolver.push(InboxPrincipal.build(properties, this.claimExtractorProperties));
|
||||
|
|
|
@ -90,15 +90,20 @@ public class AnnotationStatusEntityChangedIntegrationEventHandlerImpl implements
|
|||
EventProcessingStatus status = EventProcessingStatus.Success;
|
||||
try {
|
||||
|
||||
if (this.tenantScope.isMultitenant() && properties.getTenantId() != null) {
|
||||
TenantEntity tenant = this.queryFactory.query(TenantQuery.class).disableTracking().ids(properties.getTenantId()).firstAs(new BaseFieldSet().ensure(Tenant._id).ensure(Tenant._code));
|
||||
if (tenant == null) {
|
||||
if (this.tenantScope.isMultitenant()) {
|
||||
if (properties.getTenantId() != null) {
|
||||
TenantEntity tenant = this.queryFactory.query(TenantQuery.class).disableTracking().ids(properties.getTenantId()).firstAs(new BaseFieldSet().ensure(Tenant._id).ensure(Tenant._code));
|
||||
if (tenant == null) {
|
||||
logger.error("missing tenant from event message");
|
||||
return EventProcessingStatus.Error;
|
||||
}
|
||||
this.tenantScope.setTempTenant(this.tenantEntityManager, properties.getTenantId(), tenant.getCode());
|
||||
} else if (this.tenantScope.supportExpansionTenant()) {
|
||||
this.tenantScope.setTempTenant(this.tenantEntityManager, null, this.tenantScope.getDefaultTenantCode());
|
||||
} else {
|
||||
logger.error("missing tenant from event message");
|
||||
return EventProcessingStatus.Error;
|
||||
}
|
||||
this.tenantScope.setTempTenant(this.tenantEntityManager, properties.getTenantId(), tenant.getCode());
|
||||
} else if (this.tenantScope.isMultitenant()) {
|
||||
this.tenantScope.setTempTenant(this.tenantEntityManager, null, this.tenantScope.getDefaultTenantCode());
|
||||
}
|
||||
|
||||
this.currentPrincipalResolver.push(InboxPrincipal.build(properties, this.claimExtractorProperties));
|
||||
|
|
|
@ -181,8 +181,13 @@ public class TenantServiceImpl implements TenantService {
|
|||
|
||||
existingItems = this.queryFactory.query(UserRoleQuery.class).disableTracking().tenantIsSet(false).roles(this.authorizationConfiguration.getAuthorizationProperties().getGlobalAdminRoles()).collect();
|
||||
userCredentialEntities = this.queryFactory.query(UserCredentialQuery.class).disableTracking().userIds(existingItems.stream().map(UserRoleEntity::getUserId).distinct().toList()).collect();
|
||||
|
||||
List<String> keycloakIdsToAddToTenantGroup = new ArrayList<>();
|
||||
} finally {
|
||||
this.entityManager.reloadTenantFilters();
|
||||
}
|
||||
|
||||
List<String> keycloakIdsToAddToTenantGroup = new ArrayList<>();
|
||||
try {
|
||||
this.tenantScope.setTempTenant(this.entityManager, tenant.getId(), tenant.getCode());
|
||||
for (UUID userId : existingItems.stream().map(UserRoleEntity::getUserId).distinct().toList()) {
|
||||
this.usageLimitService.checkIncrease(UsageLimitTargetMetric.USER_COUNT);
|
||||
TenantUserEntity tenantUserEntity = new TenantUserEntity();
|
||||
|
@ -196,13 +201,13 @@ public class TenantServiceImpl implements TenantService {
|
|||
this.eventBroker.emit(new UserAddedToTenantEvent(tenantUserEntity.getUserId(), tenantUserEntity.getTenantId()));
|
||||
this.accountingService.increase(UsageLimitTargetMetric.USER_COUNT.getValue());
|
||||
|
||||
UserCredentialEntity userCredential = userCredentialEntities.stream().filter(x-> !this.conventionService.isNullOrEmpty(x.getExternalId()) && x.getUserId().equals(userId)).findFirst().orElse(null);
|
||||
UserCredentialEntity userCredential = userCredentialEntities.stream().filter(x -> !this.conventionService.isNullOrEmpty(x.getExternalId()) && x.getUserId().equals(userId)).findFirst().orElse(null);
|
||||
if (userCredential == null) continue;
|
||||
UserRoleEntity item = new UserRoleEntity();
|
||||
item.setId(UUID.randomUUID());
|
||||
item.setUserId(userId);
|
||||
item.setTenantId(tenant.getId());
|
||||
if (existingItems.stream().filter(x -> x.getUserId().equals(userId) && x.getRole().equals(this.authorizationConfiguration.getAuthorizationProperties().getAdminRole())).findFirst().orElse(null) != null){
|
||||
if (existingItems.stream().filter(x -> x.getUserId().equals(userId) && x.getRole().equals(this.authorizationConfiguration.getAuthorizationProperties().getAdminRole())).findFirst().orElse(null) != null) {
|
||||
item.setRole(this.authorizationConfiguration.getAuthorizationProperties().getTenantAdminRole()); // admin
|
||||
} else {
|
||||
item.setRole(this.authorizationConfiguration.getAuthorizationProperties().getTenantUserRole()); // installation admin
|
||||
|
@ -215,21 +220,22 @@ public class TenantServiceImpl implements TenantService {
|
|||
}
|
||||
|
||||
this.entityManager.flush();
|
||||
|
||||
|
||||
for (UUID userId : existingItems.stream().map(UserRoleEntity::getUserId).distinct().toList()) {
|
||||
this.userTouchedIntegrationEventHandler.handle(userId);
|
||||
this.eventBroker.emit(new UserTouchedEvent(userId));
|
||||
|
||||
}
|
||||
|
||||
this.entityManager.flush();
|
||||
|
||||
for (String externalId : keycloakIdsToAddToTenantGroup) {
|
||||
this.keycloakService.addUserToTenantRoleGroup(externalId, tenant.getCode(), this.authorizationConfiguration.getAuthorizationProperties().getTenantAdminRole());
|
||||
}
|
||||
|
||||
this.entityManager.flush();
|
||||
} finally {
|
||||
this.entityManager.reloadTenantFilters();
|
||||
this.tenantScope.removeTempTenant(this.entityManager);
|
||||
}
|
||||
|
||||
for (String externalId : keycloakIdsToAddToTenantGroup) {
|
||||
this.keycloakService.addUserToTenantRoleGroup(externalId, tenant.getCode(), this.authorizationConfiguration.getAuthorizationProperties().getTenantAdminRole());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -117,7 +117,7 @@ public class TenantInterceptor implements WebRequestInterceptor {
|
|||
}
|
||||
|
||||
boolean isUserAllowedTenant = false;
|
||||
if (this.tenantScope.isDefaultTenant()){
|
||||
if (this.tenantScope.supportExpansionTenant() && this.tenantScope.isDefaultTenant()){
|
||||
isUserAllowedTenant = true;
|
||||
} else {
|
||||
UserAllowedTenantCacheService.UserAllowedTenantCacheValue cacheValue = this.userAllowedTenantCacheService.lookup(this.userAllowedTenantCacheService.buildKey(this.userScope.getUserId(), this.tenantScope.getTenant()));
|
||||
|
|
|
@ -90,13 +90,13 @@ public class TenantScopeClaimInterceptor implements WebRequestInterceptor {
|
|||
if (this.conventionService.isNullOrEmpty(tenantCode)) tenantCode = this.claimExtractor.asString(principal, this.clientTenantClaimName);
|
||||
if (tenantCode == null || this.conventionService.isNullOrEmpty(tenantCode)) return false;
|
||||
|
||||
if (tenantCode.equalsIgnoreCase(this.tenantScope.getDefaultTenantCode())){
|
||||
if (this.tenantScope.supportExpansionTenant() && tenantCode.equalsIgnoreCase(this.tenantScope.getDefaultTenantCode())) {
|
||||
logger.debug("parsed tenant header and set tenant to default tenant");
|
||||
this.tenantScope.setTenant(null, tenantCode);
|
||||
this.claimExtractorContext.putReplaceParameter(TenantScope.TenantReplaceParameter, tenantCode);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
UUID tenantId = this.conventionService.parseUUIDSafe(tenantCode);
|
||||
if (tenantId == null) {
|
||||
TenantByCodeCacheService.TenantByCodeCacheValue cacheValue = this.tenantByCodeCacheService.lookup(this.tenantByCodeCacheService.buildKey(tenantCode));
|
||||
|
|
|
@ -56,15 +56,15 @@ public class TenantScopeHeaderInterceptor implements WebRequestInterceptor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void preHandle(@NotNull WebRequest request) {
|
||||
public void preHandle(@NotNull WebRequest request) {
|
||||
if (!this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) return;
|
||||
if (!this.tenantScope.isMultitenant()) return;
|
||||
|
||||
String tenantCode = request.getHeader(ClaimNames.TenantClaimName);
|
||||
logger.debug("retrieved request tenant header is: {}", tenantCode);
|
||||
if (tenantCode == null || this.conventionService.isNullOrEmpty(tenantCode)) return;
|
||||
|
||||
if (tenantCode.equalsIgnoreCase(this.tenantScope.getDefaultTenantCode())){
|
||||
|
||||
if (this.tenantScope.supportExpansionTenant() && tenantCode.equalsIgnoreCase(this.tenantScope.getDefaultTenantCode())) {
|
||||
logger.debug("parsed tenant header and set tenant to default tenant");
|
||||
this.tenantScope.setTenant(null, tenantCode);
|
||||
this.claimExtractorContext.putReplaceParameter(TenantScope.TenantReplaceParameter, tenantCode);
|
||||
|
@ -144,3 +144,4 @@ public class TenantScopeHeaderInterceptor implements WebRequestInterceptor {
|
|||
public void afterCompletion(@NonNull WebRequest request, Exception ex) {
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ tenant:
|
|||
multitenancy:
|
||||
is-multitenant: true
|
||||
default-tenant-code: default
|
||||
support-expansion-tenant: true
|
||||
interceptor:
|
||||
client-claims-prefix: client_
|
||||
enforce-trusted-tenant: false
|
||||
|
|
Loading…
Reference in New Issue