support default tenant as null
This commit is contained in:
parent
77d2dcdc39
commit
cc407c202a
|
@ -5,6 +5,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
|
|||
@ConfigurationProperties(prefix = "tenant.multitenancy")
|
||||
public class MultitenancyProperties {
|
||||
private boolean isMultitenant;
|
||||
private String defaultTenantCode;
|
||||
|
||||
public boolean isMultitenant() {
|
||||
return isMultitenant;
|
||||
|
@ -13,4 +14,12 @@ public class MultitenancyProperties {
|
|||
public void setIsMultitenant(boolean multitenant) {
|
||||
isMultitenant = multitenant;
|
||||
}
|
||||
|
||||
public String getDefaultTenantCode() {
|
||||
return defaultTenantCode;
|
||||
}
|
||||
|
||||
public void setDefaultTenantCode(String defaultTenantCode) {
|
||||
this.defaultTenantCode = defaultTenantCode;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
package eu.eudat.commons.scope.tenant;
|
||||
|
||||
import eu.eudat.data.tenant.TenantScopedBaseEntity;
|
||||
import gr.cite.tools.logging.LoggerService;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import org.hibernate.Session;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.context.annotation.RequestScope;
|
||||
|
@ -22,7 +20,6 @@ public class TenantScope {
|
|||
public static final String TenantClaimName = "x-tenant";
|
||||
|
||||
private final MultitenancyProperties multitenancy;
|
||||
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(TenantScope.class));
|
||||
private final AtomicReference<UUID> tenant = new AtomicReference<>();
|
||||
private final AtomicReference<String> tenantCode = new AtomicReference<>();
|
||||
private final AtomicReference<UUID> initialTenant = new AtomicReference<>();
|
||||
|
@ -37,45 +34,70 @@ public class TenantScope {
|
|||
return multitenancy.isMultitenant();
|
||||
}
|
||||
|
||||
public String getDefaultTenantCode() {
|
||||
return multitenancy.getDefaultTenantCode();
|
||||
}
|
||||
|
||||
public Boolean isSet() {
|
||||
if (!this.isMultitenant())
|
||||
return Boolean.TRUE;
|
||||
return this.tenant.get() != null;
|
||||
return this.tenant.get() != null || this.isDefaultTenant();
|
||||
}
|
||||
|
||||
public Boolean isDefaultTenant() {
|
||||
if (!this.isMultitenant())
|
||||
return Boolean.TRUE;
|
||||
return this.multitenancy.getDefaultTenantCode().equalsIgnoreCase(this.tenantCode.get());
|
||||
}
|
||||
|
||||
public UUID getTenant() throws InvalidApplicationException {
|
||||
if (!this.isMultitenant())
|
||||
return null;
|
||||
if (this.tenant.get() == null)
|
||||
if (this.tenant.get() == null && !this.isDefaultTenant())
|
||||
throw new InvalidApplicationException("tenant not set");
|
||||
return this.tenant.get();
|
||||
return this.isDefaultTenant() ? null : this.tenant.get();
|
||||
}
|
||||
|
||||
public String getTenantCode() throws InvalidApplicationException {
|
||||
if (!this.isMultitenant())
|
||||
return null;
|
||||
if (this.tenant.get() == null)
|
||||
if (this.tenantCode.get() == null)
|
||||
throw new InvalidApplicationException("tenant not set");
|
||||
return this.tenantCode.get();
|
||||
}
|
||||
|
||||
public void setTempTenant(EntityManager entityManager, UUID tenant) {
|
||||
public void setTempTenant(EntityManager entityManager, UUID tenant, String tenantCode) {
|
||||
this.tenant.set(tenant);
|
||||
this.tenantCode.set(tenantCode);
|
||||
|
||||
if (this.tenant.get() != null) {
|
||||
entityManager
|
||||
.unwrap(Session.class)
|
||||
.enableFilter(TenantScopedBaseEntity.tenantFilter).setParameter(TenantScopedBaseEntity.tenantFilterTenantParam, this.tenant.get().toString());
|
||||
if (this.tenant.get() != null && !this.isDefaultTenant()) {
|
||||
if(!this.isDefaultTenant()) {
|
||||
entityManager
|
||||
.unwrap(Session.class)
|
||||
.enableFilter(TenantScopedBaseEntity.TENANT_FILTER)
|
||||
.setParameter(TenantScopedBaseEntity.TENANT_FILTER_TENANT_PARAM, this.tenant.get().toString());
|
||||
} else {
|
||||
entityManager
|
||||
.unwrap(Session.class)
|
||||
.enableFilter(TenantScopedBaseEntity.DEFAULT_TENANT_FILTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void removeTempTenant(EntityManager entityManager) {
|
||||
this.tenant.set(this.initialTenant.get());
|
||||
this.tenantCode.set(this.initialTenantCode.get());
|
||||
if (this.initialTenant.get() != null) {
|
||||
entityManager
|
||||
.unwrap(Session.class)
|
||||
.enableFilter(TenantScopedBaseEntity.tenantFilter).setParameter(TenantScopedBaseEntity.tenantFilterTenantParam, this.initialTenant.get().toString());
|
||||
if (this.initialTenant.get() != null && !this.isDefaultTenant()) {
|
||||
if(!this.isDefaultTenant()) {
|
||||
entityManager
|
||||
.unwrap(Session.class)
|
||||
.enableFilter(TenantScopedBaseEntity.TENANT_FILTER)
|
||||
.setParameter(TenantScopedBaseEntity.TENANT_FILTER_TENANT_PARAM, this.tenant.get().toString());
|
||||
} else {
|
||||
entityManager
|
||||
.unwrap(Session.class)
|
||||
.enableFilter(TenantScopedBaseEntity.DEFAULT_TENANT_FILTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ public class TenantEntityManager {
|
|||
// this.claimExtractor.subjectUUID(this.currentPrincipalResolver.currentPrincipal());
|
||||
// boolean isAllowedNoTenant = authorizationService.authorize(Permission.AllowNoTenant);
|
||||
|
||||
boolean isAllowedNoTenant = ((TenantScoped) entity).allowNullTenant();
|
||||
boolean isAllowedNoTenant = ((TenantScoped) entity).allowNullTenant() || this.tenantScope.isDefaultTenant();
|
||||
final UUID tenantId = !isAllowedNoTenant ? tenantScope.getTenant() : null;
|
||||
if (!isAllowedNoTenant && !tenantId.equals(((TenantScoped) entity).getTenantId())) throw new MyForbiddenException("tenant tampering");
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ public class TenantEntityManager {
|
|||
|
||||
public void remove(Object entity) throws InvalidApplicationException {
|
||||
if (tenantScope.isMultitenant() && (entity instanceof TenantScoped)) {
|
||||
boolean isAllowedNoTenant = ((TenantScoped) entity).allowNullTenant();
|
||||
boolean isAllowedNoTenant = ((TenantScoped) entity).allowNullTenant() || this.tenantScope.isDefaultTenant();
|
||||
final UUID tenantId = !isAllowedNoTenant ? tenantScope.getTenant() : null;
|
||||
if (!isAllowedNoTenant && !tenantId.equals(((TenantScoped) entity).getTenantId())) throw new MyForbiddenException("tenant tampering");
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ public class TenantEntityManager {
|
|||
// this.claimExtractor.subjectUUID(this.currentPrincipalResolver.currentPrincipal());
|
||||
// boolean isAllowedNoTenant = authorizationService.authorize(Permission.AllowNoTenant);
|
||||
|
||||
boolean isAllowedNoTenant = ((TenantScoped) entity).allowNullTenant();
|
||||
boolean isAllowedNoTenant = ((TenantScoped) entity).allowNullTenant() || this.tenantScope.isDefaultTenant();
|
||||
final UUID tenantId = !isAllowedNoTenant ? tenantScope.getTenant() : null;
|
||||
if (!isAllowedNoTenant && !tenantId.equals(((TenantScoped) entity).getTenantId())) return null;
|
||||
}
|
||||
|
|
|
@ -29,11 +29,16 @@ public class TenantFilterAspect {
|
|||
pointcut = "bean(entityManagerFactory) && execution(* createEntityManager(..))",
|
||||
returning = "retVal")
|
||||
public void getSessionAfter(JoinPoint joinPoint, Object retVal) throws InvalidApplicationException {
|
||||
if (retVal != null && retVal instanceof EntityManager && tenantScope.isSet()) {
|
||||
if (retVal instanceof EntityManager && tenantScope.isSet()) {
|
||||
Session session = ((EntityManager) retVal).unwrap(Session.class);
|
||||
session
|
||||
.enableFilter(TenantScopedBaseEntity.tenantFilter)
|
||||
.setParameter(TenantScopedBaseEntity.tenantFilterTenantParam, tenantScope.getTenant().toString());
|
||||
if(!tenantScope.isDefaultTenant()) {
|
||||
session
|
||||
.enableFilter(TenantScopedBaseEntity.TENANT_FILTER)
|
||||
.setParameter(TenantScopedBaseEntity.TENANT_FILTER_TENANT_PARAM, tenantScope.getTenant().toString());
|
||||
} else {
|
||||
session
|
||||
.enableFilter(TenantScopedBaseEntity.DEFAULT_TENANT_FILTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,11 +29,11 @@ public class TenantListener {
|
|||
@PrePersist
|
||||
public void setTenantOnCreate(TenantScoped entity) throws InvalidApplicationException {
|
||||
if (tenantScope.isMultitenant()) {
|
||||
if (entity.getTenantId() != null && entity.getTenantId().compareTo(tenantScope.getTenant()) != 0) {
|
||||
logger.error("somebody tried to set not login tenat");
|
||||
if (entity.getTenantId() != null && (this.tenantScope.isDefaultTenant() || entity.getTenantId().compareTo(tenantScope.getTenant()) != 0)) {
|
||||
logger.error("somebody tried to set not login tenant");
|
||||
throw new MyForbiddenException("tenant tampering");
|
||||
}
|
||||
if (!entity.allowNullTenant()) {
|
||||
if (!entity.allowNullTenant() && !tenantScope.isDefaultTenant()) {
|
||||
final UUID tenantId = tenantScope.getTenant();
|
||||
entity.setTenantId(tenantId);
|
||||
}
|
||||
|
@ -47,19 +47,26 @@ public class TenantListener {
|
|||
public void setTenantOnUpdate(TenantScoped entity) throws InvalidApplicationException {
|
||||
if (tenantScope.isMultitenant()) {
|
||||
if (!entity.allowNullTenant()){
|
||||
if (entity.getTenantId() == null) {
|
||||
logger.error("somebody tried to set null tenant");
|
||||
throw new MyForbiddenException("tenant tampering");
|
||||
}
|
||||
if (entity.getTenantId().compareTo(tenantScope.getTenant()) != 0) {
|
||||
logger.error("somebody tried to change an entries tenant");
|
||||
throw new MyForbiddenException("tenant tampering");
|
||||
}
|
||||
if (!tenantScope.isDefaultTenant()) {
|
||||
if (entity.getTenantId() == null) {
|
||||
logger.error("somebody tried to set null tenant");
|
||||
throw new MyForbiddenException("tenant tampering");
|
||||
}
|
||||
if (entity.getTenantId().compareTo(tenantScope.getTenant()) != 0) {
|
||||
logger.error("somebody tried to change an entries tenant");
|
||||
throw new MyForbiddenException("tenant tampering");
|
||||
}
|
||||
|
||||
final UUID tenantId = tenantScope.getTenant();
|
||||
entity.setTenantId(tenantId);
|
||||
final UUID tenantId = tenantScope.getTenant();
|
||||
entity.setTenantId(tenantId);
|
||||
} else {
|
||||
if (entity.getTenantId() != null) {
|
||||
logger.error("somebody tried to set null tenant");
|
||||
throw new MyForbiddenException("tenant tampering");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (entity.getTenantId() != null && entity.getTenantId().compareTo(tenantScope.getTenant()) != 0) {
|
||||
if (entity.getTenantId() != null && (!this.tenantScope.isDefaultTenant() ||entity.getTenantId().compareTo(tenantScope.getTenant()) != 0)) {
|
||||
logger.error("somebody tried to change an entries tenant");
|
||||
throw new MyForbiddenException("tenant tampering");
|
||||
}
|
||||
|
|
|
@ -14,13 +14,16 @@ import java.util.UUID;
|
|||
//@Getter
|
||||
//@Setter
|
||||
//@NoArgsConstructor
|
||||
@FilterDef(name = TenantScopedBaseEntity.tenantFilter, parameters = {@ParamDef(name = TenantScopedBaseEntity.tenantFilterTenantParam, type = String.class)})
|
||||
@Filter(name = "tenantFilter", condition = "(tenant = (cast(:tenantId as uuid)) or tenant is null)")
|
||||
@FilterDef(name = TenantScopedBaseEntity.TENANT_FILTER, parameters = {@ParamDef(name = TenantScopedBaseEntity.TENANT_FILTER_TENANT_PARAM, type = String.class)})
|
||||
@FilterDef(name = TenantScopedBaseEntity.DEFAULT_TENANT_FILTER)
|
||||
@Filter(name = TenantScopedBaseEntity.DEFAULT_TENANT_FILTER, condition = "(tenant = tenant is null)")
|
||||
@Filter(name = TenantScopedBaseEntity.TENANT_FILTER, condition = "(tenant = (cast(:tenantId as uuid)) or tenant is null)")
|
||||
@EntityListeners(TenantListener.class)
|
||||
public abstract class TenantScopedBaseEntity implements TenantScoped, Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
public static final String tenantFilter = "tenantFilter";
|
||||
public static final String tenantFilterTenantParam = "tenantId";
|
||||
public static final String TENANT_FILTER = "tenantFilter";
|
||||
public static final String DEFAULT_TENANT_FILTER = "defaultTenantFilter";
|
||||
public static final String TENANT_FILTER_TENANT_PARAM = "tenantId";
|
||||
|
||||
@Column(name = "tenant", columnDefinition = "uuid", nullable = true)
|
||||
private UUID tenantId;
|
||||
|
|
|
@ -38,15 +38,6 @@ public class DescriptionTemplateTypePersist {
|
|||
private DescriptionTemplateTypeStatus status;
|
||||
|
||||
private Map<UUID, DescriptionTemplateTypePersist> test;
|
||||
public final static String _test = "test";
|
||||
|
||||
public Map<UUID, DescriptionTemplateTypePersist> getTest() {
|
||||
return test;
|
||||
}
|
||||
|
||||
public void setTest(Map<UUID, DescriptionTemplateTypePersist> test) {
|
||||
this.test = test;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
|
@ -86,12 +77,10 @@ public class DescriptionTemplateTypePersist {
|
|||
public static final String ValidatorName = "DescriptionTemplateTypePersistValidator";
|
||||
|
||||
private final MessageSource messageSource;
|
||||
private final ValidatorFactory validatorFactory;
|
||||
|
||||
public DescriptionTemplateTypePersistValidator(MessageSource messageSource, ConventionService conventionService, ErrorThesaurusProperties errors, ValidatorFactory validatorFactory) {
|
||||
public DescriptionTemplateTypePersistValidator(MessageSource messageSource, ConventionService conventionService, ErrorThesaurusProperties errors) {
|
||||
super(conventionService, errors);
|
||||
this.messageSource = messageSource;
|
||||
this.validatorFactory = validatorFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -3,10 +3,9 @@ package eu.eudat.interceptors.tenant;
|
|||
|
||||
import eu.eudat.authorization.Permission;
|
||||
import eu.eudat.commons.enums.IsActive;
|
||||
import eu.eudat.commons.lock.LockByKeyManager;
|
||||
import eu.eudat.commons.scope.tenant.TenantScope;
|
||||
import eu.eudat.commons.scope.user.UserScope;
|
||||
import eu.eudat.data.DmpReferenceEntity;
|
||||
import eu.eudat.data.ReferenceEntity;
|
||||
import eu.eudat.data.TenantUserEntity;
|
||||
import eu.eudat.data.UserEntity;
|
||||
import eu.eudat.data.tenant.TenantScopedBaseEntity;
|
||||
|
@ -24,7 +23,6 @@ import jakarta.persistence.Tuple;
|
|||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import jakarta.persistence.criteria.Subquery;
|
||||
import org.hibernate.Session;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -46,6 +44,7 @@ import java.time.Instant;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Component
|
||||
public class TenantInterceptor implements WebRequestInterceptor {
|
||||
|
@ -61,6 +60,7 @@ public class TenantInterceptor implements WebRequestInterceptor {
|
|||
private final PlatformTransactionManager transactionManager;
|
||||
private final ErrorThesaurusProperties errors;
|
||||
private final QueryUtilsService queryUtilsService;
|
||||
private final LockByKeyManager lockByKeyManager;
|
||||
@PersistenceContext
|
||||
public EntityManager entityManager;
|
||||
|
||||
|
@ -74,7 +74,7 @@ public class TenantInterceptor implements WebRequestInterceptor {
|
|||
TenantScopeProperties tenantScopeProperties,
|
||||
UserAllowedTenantCacheService userAllowedTenantCacheService,
|
||||
PlatformTransactionManager transactionManager,
|
||||
ErrorThesaurusProperties errors, QueryUtilsService queryUtilsService) {
|
||||
ErrorThesaurusProperties errors, QueryUtilsService queryUtilsService, LockByKeyManager lockByKeyManager) {
|
||||
this.tenantScope = tenantScope;
|
||||
this.userScope = userScope;
|
||||
this.currentPrincipalResolver = currentPrincipalResolver;
|
||||
|
@ -85,10 +85,11 @@ public class TenantInterceptor implements WebRequestInterceptor {
|
|||
this.transactionManager = transactionManager;
|
||||
this.errors = errors;
|
||||
this.queryUtilsService = queryUtilsService;
|
||||
this.lockByKeyManager = lockByKeyManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preHandle(@NotNull WebRequest request) throws InvalidApplicationException {
|
||||
public void preHandle(@NotNull WebRequest request) throws InvalidApplicationException, InterruptedException {
|
||||
if (!this.currentPrincipalResolver.currentPrincipal().isAuthenticated()) return;
|
||||
if (!this.tenantScope.isMultitenant()) return;
|
||||
|
||||
|
@ -101,18 +102,29 @@ public class TenantInterceptor implements WebRequestInterceptor {
|
|||
}
|
||||
|
||||
boolean isUserAllowedTenant = false;
|
||||
UserAllowedTenantCacheService.UserAllowedTenantCacheValue cacheValue = this.userAllowedTenantCacheService.lookup(this.userAllowedTenantCacheService.buildKey(this.userScope.getUserId(), this.tenantScope.getTenant()));
|
||||
if (cacheValue != null) {
|
||||
isUserAllowedTenant = cacheValue.isAllowed();
|
||||
if (this.tenantScope.isDefaultTenant()){
|
||||
isUserAllowedTenant = true;
|
||||
} else {
|
||||
isUserAllowedTenant = this.isUserAllowedTenant();
|
||||
this.userAllowedTenantCacheService.put(new UserAllowedTenantCacheService.UserAllowedTenantCacheValue(this.userScope.getUserId(), this.tenantScope.getTenant(), isUserAllowedTenant));
|
||||
UserAllowedTenantCacheService.UserAllowedTenantCacheValue cacheValue = this.userAllowedTenantCacheService.lookup(this.userAllowedTenantCacheService.buildKey(this.userScope.getUserId(), this.tenantScope.getTenant()));
|
||||
if (cacheValue != null) {
|
||||
isUserAllowedTenant = cacheValue.isAllowed();
|
||||
} else {
|
||||
isUserAllowedTenant = this.isUserAllowedTenant();
|
||||
this.userAllowedTenantCacheService.put(new UserAllowedTenantCacheService.UserAllowedTenantCacheValue(this.userScope.getUserId(), this.tenantScope.getTenant(), isUserAllowedTenant));
|
||||
}
|
||||
}
|
||||
|
||||
if (isUserAllowedTenant) {
|
||||
this.entityManager
|
||||
.unwrap(Session.class)
|
||||
.enableFilter(TenantScopedBaseEntity.tenantFilter).setParameter(TenantScopedBaseEntity.tenantFilterTenantParam, tenantScope.getTenant().toString());
|
||||
if(!tenantScope.isDefaultTenant()) {
|
||||
this.entityManager
|
||||
.unwrap(Session.class)
|
||||
.enableFilter(TenantScopedBaseEntity.TENANT_FILTER)
|
||||
.setParameter(TenantScopedBaseEntity.TENANT_FILTER_TENANT_PARAM, tenantScope.getTenant().toString());
|
||||
} else {
|
||||
this.entityManager
|
||||
.unwrap(Session.class)
|
||||
.enableFilter(TenantScopedBaseEntity.DEFAULT_TENANT_FILTER);
|
||||
}
|
||||
} else {
|
||||
if (isAllowedNoTenant || this.isWhiteListedEndpoint(request)) {
|
||||
tenantScope.setTenant(null, null);
|
||||
|
@ -143,40 +155,47 @@ public class TenantInterceptor implements WebRequestInterceptor {
|
|||
return false;
|
||||
}
|
||||
|
||||
private boolean isUserAllowedTenant() throws InvalidApplicationException {
|
||||
private boolean isUserAllowedTenant() throws InvalidApplicationException, InterruptedException {
|
||||
if (userScope.isSet()) {
|
||||
|
||||
CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Tuple> query = criteriaBuilder.createQuery(Tuple.class);
|
||||
Root<UserEntity> root = query.from(UserEntity.class);
|
||||
query.where(criteriaBuilder.and(
|
||||
criteriaBuilder.equal(root.get(UserEntity._isActive), IsActive.Active),
|
||||
criteriaBuilder.in(root.get(UserEntity._id)).value(queryUtilsService.buildSubQuery(new BuildSubQueryInput<>(new BuildSubQueryInput.Builder<>(TenantUserEntity.class, UUID.class)
|
||||
.query(query)
|
||||
.criteriaBuilder(criteriaBuilder)
|
||||
.keyPathFunc((subQueryRoot) -> subQueryRoot.get(TenantUserEntity._userId))
|
||||
.filterFunc((subQueryRoot, cb) ->
|
||||
{
|
||||
try {
|
||||
return cb.and(
|
||||
criteriaBuilder.equal(subQueryRoot.get(TenantUserEntity._tenantId), this.tenantScope.getTenant()),
|
||||
criteriaBuilder.equal(subQueryRoot.get(TenantUserEntity._userId), this.userScope.getUserId()),
|
||||
criteriaBuilder.equal(subQueryRoot.get(TenantUserEntity._isActive), IsActive.Active)
|
||||
);
|
||||
} catch (InvalidApplicationException e) {
|
||||
throw new RuntimeException(e);
|
||||
boolean usedResource = false;
|
||||
String lockId = userScope.getUserId().toString().toLowerCase(Locale.ROOT);
|
||||
try {
|
||||
if (this.tenantScopeProperties.getAutoCreateTenantUser()) usedResource = this.lockByKeyManager.tryLock(lockId, 5000, TimeUnit.MILLISECONDS);
|
||||
|
||||
CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
|
||||
CriteriaQuery<Tuple> query = criteriaBuilder.createQuery(Tuple.class);
|
||||
Root<UserEntity> root = query.from(UserEntity.class);
|
||||
query.where(criteriaBuilder.and(
|
||||
criteriaBuilder.equal(root.get(UserEntity._isActive), IsActive.Active),
|
||||
criteriaBuilder.in(root.get(UserEntity._id)).value(queryUtilsService.buildSubQuery(new BuildSubQueryInput<>(new BuildSubQueryInput.Builder<>(TenantUserEntity.class, UUID.class)
|
||||
.query(query)
|
||||
.criteriaBuilder(criteriaBuilder)
|
||||
.keyPathFunc((subQueryRoot) -> subQueryRoot.get(TenantUserEntity._userId))
|
||||
.filterFunc((subQueryRoot, cb) ->
|
||||
{
|
||||
try {
|
||||
return cb.and(
|
||||
criteriaBuilder.equal(subQueryRoot.get(TenantUserEntity._tenantId), this.tenantScope.getTenant()),
|
||||
criteriaBuilder.equal(subQueryRoot.get(TenantUserEntity._userId), this.userScope.getUserId()),
|
||||
criteriaBuilder.equal(subQueryRoot.get(TenantUserEntity._isActive), IsActive.Active)
|
||||
);
|
||||
} catch (InvalidApplicationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
))
|
||||
)
|
||||
));
|
||||
query.multiselect(root.get(UserEntity._id).alias(UserEntity._id));
|
||||
List<Tuple> results = this.entityManager.createQuery(query).getResultList();
|
||||
if (results.isEmpty() && this.tenantScopeProperties.getAutoCreateTenantUser()) {
|
||||
return this.createTenantUser();
|
||||
} else {
|
||||
return !results.isEmpty();
|
||||
)
|
||||
))
|
||||
)
|
||||
));
|
||||
query.multiselect(root.get(UserEntity._id).alias(UserEntity._id));
|
||||
List<Tuple> results = this.entityManager.createQuery(query).getResultList();
|
||||
if (results.isEmpty() && this.tenantScopeProperties.getAutoCreateTenantUser()) {
|
||||
return this.createTenantUser();
|
||||
} else {
|
||||
return !results.isEmpty();
|
||||
}
|
||||
} finally {
|
||||
if (usedResource) this.lockByKeyManager.unlock(lockId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,21 +78,26 @@ public class TenantScopeClaimInterceptor implements WebRequestInterceptor {
|
|||
|
||||
MyPrincipal principal = this.currentPrincipalResolver.currentPrincipal();
|
||||
if (principal != null && principal.isAuthenticated() /* principal.Claims.Any() */) {
|
||||
Boolean scoped = this.scopeByPrincipal(this.tenantScope, principal);
|
||||
if (!scoped) scoped = this.scopeByClient(this.tenantScope, principal);
|
||||
boolean scoped = this.scopeByPrincipal(principal);
|
||||
if (!scoped) scoped = this.scopeByClient(principal);
|
||||
if (!scoped && this.tenantScope.isSet() && this.tenantScopeProperties.getEnforceTrustedTenant())
|
||||
throw new MyForbiddenException(this.errorThesaurusProperties.getMissingTenant().getCode(), this.errorThesaurusProperties.getMissingTenant().getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Boolean scopeByPrincipal(TenantScope scope, MyPrincipal principal) {
|
||||
private boolean scopeByPrincipal(MyPrincipal principal) {
|
||||
String tenantCode = this.claimExtractor.tenantString(principal);
|
||||
if (tenantCode == null || tenantCode.isBlank())
|
||||
tenantCode = this.claimExtractor.asString(principal, this.clientTenantClaimName);
|
||||
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())){
|
||||
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 && tenantCode == null)
|
||||
return Boolean.FALSE;
|
||||
if (tenantId == null) {
|
||||
TenantByCodeCacheService.TenantByCodeCacheValue cacheValue = this.tenantByCodeCacheService.lookup(this.tenantByCodeCacheService.buildKey(tenantCode));
|
||||
if (cacheValue != null) {
|
||||
|
@ -115,21 +120,22 @@ public class TenantScopeClaimInterceptor implements WebRequestInterceptor {
|
|||
}
|
||||
}
|
||||
|
||||
if (tenantId != null && tenantCode != null && !tenantCode.isBlank()) {
|
||||
if (tenantId != null) {
|
||||
logger.debug("parsed tenant header and set tenant id to {}", tenantId);
|
||||
this.tenantScope.setTenant(tenantId, tenantCode);
|
||||
this.claimExtractorContext.putReplaceParameter(TenantScope.TenantReplaceParameter, tenantCode);
|
||||
return true;
|
||||
}
|
||||
return tenantId != null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private Boolean scopeByClient(TenantScope scope, MyPrincipal principal) throws InvalidApplicationException {
|
||||
private boolean scopeByClient(MyPrincipal principal) throws InvalidApplicationException {
|
||||
String client = this.claimExtractor.client(principal);
|
||||
|
||||
Boolean isWhiteListed = this.tenantScopeProperties.getWhiteListedClients() != null && !this.conventionService.isNullOrEmpty(client) && this.tenantScopeProperties.getWhiteListedClients().contains(client);
|
||||
logger.debug("client is whitelisted : {}, scope is set: {}, with value {}", isWhiteListed, scope.isSet(), (scope.isSet() ? scope.getTenant() : null));
|
||||
logger.debug("client is whitelisted : {}, scope is set: {}, with value {}", isWhiteListed, this.tenantScope.isSet(), (this.tenantScope.isSet() ? this.tenantScope.getTenant() : null));
|
||||
|
||||
return isWhiteListed && scope.isSet();
|
||||
return isWhiteListed && this.tenantScope.isSet();
|
||||
}
|
||||
|
||||
private UUID getTenantIdFromDatabase(String tenantCode) {
|
||||
|
|
|
@ -62,10 +62,16 @@ public class TenantScopeHeaderInterceptor implements WebRequestInterceptor {
|
|||
|
||||
String tenantCode = request.getHeader(TenantScope.TenantClaimName);
|
||||
logger.debug("retrieved request tenant header is: {}", tenantCode);
|
||||
if (this.conventionService.isNullOrEmpty(tenantCode)) return;
|
||||
if (tenantCode == null || this.conventionService.isNullOrEmpty(tenantCode)) return;
|
||||
|
||||
if (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;
|
||||
}
|
||||
|
||||
UUID tenantId = this.conventionService.parseUUIDSafe(tenantCode);
|
||||
if (tenantId == null && tenantCode == null) return;
|
||||
if (tenantId == null) {
|
||||
TenantByCodeCacheService.TenantByCodeCacheValue cacheValue = this.tenantByCodeCacheService.lookup(this.tenantByCodeCacheService.buildKey(tenantCode));
|
||||
if (cacheValue != null) {
|
||||
|
@ -86,7 +92,7 @@ public class TenantScopeHeaderInterceptor implements WebRequestInterceptor {
|
|||
}
|
||||
}
|
||||
|
||||
if (tenantId != null && tenantCode != null && !tenantCode.isBlank()) {
|
||||
if (tenantId != null) {
|
||||
logger.debug("parsed tenant header and set tenant id to {}", tenantId);
|
||||
this.tenantScope.setTenant(tenantId, tenantCode);
|
||||
this.claimExtractorContext.putReplaceParameter(TenantScope.TenantReplaceParameter, tenantCode);
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
tenant:
|
||||
configEncryptionAesKey: rmpTvZnRWzyisUtFADBcZCn0q7Z75Xdz
|
||||
configEncryptionAesIv: ec05d521a23f80ad
|
||||
multitenancy:
|
||||
is-multitenant: true
|
||||
default-tenant-code: default
|
||||
interceptor:
|
||||
client-claims-prefix: client_
|
||||
enforce-trusted-tenant: false
|
||||
auto-create-tenant-user: true
|
|
@ -1,11 +1,8 @@
|
|||
tenant:
|
||||
configEncryptionAesKey: rmpTvZnRWzyisUtFADBcZCn0q7Z75Xdz
|
||||
configEncryptionAesIv: ec05d521a23f80ad
|
||||
multitenancy:
|
||||
is-multitenant: true
|
||||
is-multitenant: false
|
||||
interceptor:
|
||||
client-claims-prefix: client_
|
||||
white-listed-clients: [ ]
|
||||
enforce-trusted-tenant: false
|
||||
auto-create-tenant-user: true
|
||||
auto-create-tenant-user: false
|
||||
white-listed-endpoints: [ '/api/principal/my-tenants', '/api/principal/me' ]
|
Loading…
Reference in New Issue