add cache to tenant interceptor

This commit is contained in:
Efstratios Giannopoulos 2024-04-03 10:15:28 +03:00
parent fcc3dd7609
commit a5f31ab880
6 changed files with 130 additions and 3 deletions

View File

@ -69,6 +69,7 @@ public class TenantInterceptor implements WebRequestInterceptor {
private final ConventionService conventionService;
private final UserTouchedIntegrationEventHandler userTouchedIntegrationEventHandler;
private final AuthorizationProperties authorizationProperties;
private final UserTenantRolesCacheService userTenantRolesCacheService;
@PersistenceContext
public EntityManager entityManager;
@ -82,7 +83,7 @@ public class TenantInterceptor implements WebRequestInterceptor {
TenantScopeProperties tenantScopeProperties,
UserAllowedTenantCacheService userAllowedTenantCacheService,
PlatformTransactionManager transactionManager,
ErrorThesaurusProperties errors, QueryUtilsService queryUtilsService, LockByKeyManager lockByKeyManager, ConventionService conventionService, UserTouchedIntegrationEventHandler userTouchedIntegrationEventHandler, AuthorizationProperties authorizationProperties) {
ErrorThesaurusProperties errors, QueryUtilsService queryUtilsService, LockByKeyManager lockByKeyManager, ConventionService conventionService, UserTouchedIntegrationEventHandler userTouchedIntegrationEventHandler, AuthorizationProperties authorizationProperties, UserTenantRolesCacheService userTenantRolesCacheService) {
this.tenantScope = tenantScope;
this.userScope = userScope;
this.currentPrincipalResolver = currentPrincipalResolver;
@ -97,6 +98,7 @@ public class TenantInterceptor implements WebRequestInterceptor {
this.conventionService = conventionService;
this.userTouchedIntegrationEventHandler = userTouchedIntegrationEventHandler;
this.authorizationProperties = authorizationProperties;
this.userTenantRolesCacheService = userTenantRolesCacheService;
}
@Override
@ -145,7 +147,10 @@ public class TenantInterceptor implements WebRequestInterceptor {
}
}
this.syncUserWithClaims();
UserTenantRolesCacheService.UserTenantRolesCacheValue cacheValue = this.userTenantRolesCacheService.lookup(this.userTenantRolesCacheService.buildKey(this.userScope.getUserId(), this.tenantScope.isDefaultTenant() ? UUID.fromString("00000000-0000-0000-0000-000000000000") : this.tenantScope.getTenant()));
if (cacheValue == null || !this.userRolesSynced(cacheValue.getRoles())) {
this.syncUserWithClaims();
}
} else {
if (!isAllowedNoTenant) {
if (!this.isWhiteListedEndpoint(request)) {
@ -244,6 +249,8 @@ public class TenantInterceptor implements WebRequestInterceptor {
}
private void syncUserWithClaims() throws InvalidApplicationException, InterruptedException {
boolean usedResource = false;
String lockId = userScope.getUserId().toString().toLowerCase(Locale.ROOT);
boolean hasChanges = false;
@ -258,7 +265,14 @@ public class TenantInterceptor implements WebRequestInterceptor {
try {
status = transactionManager.getTransaction(definition);
List<String> existingUserRoles = this.collectUserRoles();
UserTenantRolesCacheService.UserTenantRolesCacheValue cacheValue = this.userTenantRolesCacheService.lookup(this.userTenantRolesCacheService.buildKey(this.userScope.getUserId(), this.tenantScope.isDefaultTenant() ? UUID.fromString("00000000-0000-0000-0000-000000000000") : this.tenantScope.getTenant()));
List<String> existingUserRoles;
if (cacheValue != null) {
existingUserRoles = cacheValue.getRoles();
} else {
existingUserRoles = this.collectUserRoles();
this.userTenantRolesCacheService.put(new UserTenantRolesCacheService.UserTenantRolesCacheValue(this.userScope.getUserId(), this.tenantScope.isDefaultTenant() ? UUID.fromString("00000000-0000-0000-0000-000000000000") : this.tenantScope.getTenant(), existingUserRoles));
}
if (!this.userRolesSynced(existingUserRoles)) {
this.syncRoles();
hasChanges = true;

View File

@ -8,3 +8,5 @@ import org.springframework.context.annotation.Configuration;
@ConfigurationProperties(prefix = "cache.user-allowed-tenant")
public class UserAllowedTenantCacheOptions extends CacheOptions {
}

View File

@ -88,3 +88,4 @@ public class UserAllowedTenantCacheService extends CacheService<UserAllowedTenan
return this.generateKey(keyParts);
}
}

View File

@ -0,0 +1,10 @@
package eu.eudat.interceptors.tenant;
import gr.cite.tools.cache.CacheOptions;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Configuration
@ConfigurationProperties(prefix = "cache.user-tenant-roles")
public class UserTenantRolesCacheOptions extends CacheOptions {
}

View File

@ -0,0 +1,91 @@
package eu.eudat.interceptors.tenant;
import eu.eudat.event.UserAddedToTenantEvent;
import eu.eudat.event.UserRemovedFromTenantEvent;
import gr.cite.tools.cache.CacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
@Service
public class UserTenantRolesCacheService extends CacheService<UserTenantRolesCacheService.UserTenantRolesCacheValue> {
public static class UserTenantRolesCacheValue {
public UserTenantRolesCacheValue() {
}
public UserTenantRolesCacheValue(UUID userId, UUID tenantId, List<String> roles) {
this.userId = userId;
this.tenantId = tenantId;
this.roles = roles;
}
private UUID userId;
public UUID getUserId() {
return userId;
}
public void setUserId(UUID userId) {
this.userId = userId;
}
private UUID tenantId;
public UUID getTenantId() {
return tenantId;
}
public void setTenantId(UUID tenantId) {
this.tenantId = tenantId;
}
private List<String> roles;
public List<String> getRoles() {
return roles;
}
public void setRoles(List<String> roles) {
this.roles = roles;
}
}
@Autowired
public UserTenantRolesCacheService(UserTenantRolesCacheOptions options) {
super(options);
}
@EventListener
public void handleUserRemovedFromTenantEvent(UserRemovedFromTenantEvent event) {
this.evict(this.buildKey(event.getUserId(), event.getTenantId()));
}
@EventListener
public void handleUserAddedToTenantEvent(UserAddedToTenantEvent event) {
this.evict(this.buildKey(event.getUserId(), event.getTenantId()));
}
@Override
protected Class<UserTenantRolesCacheValue> valueClass() {
return UserTenantRolesCacheValue.class;
}
@Override
public String keyOf(UserTenantRolesCacheValue value) {
return this.buildKey(value.getUserId(), value.getTenantId());
}
public String buildKey(UUID userId, UUID tenantId) {
HashMap<String, String> keyParts = new HashMap<>();
keyParts.put("$user_id$", userId.toString().toLowerCase(Locale.ROOT));
keyParts.put("$tenant_id$", tenantId.toString().toLowerCase(Locale.ROOT));
return this.generateKey(keyParts);
}
}

View File

@ -68,6 +68,12 @@ cache:
maximumSize: 500
enableRecordStats: false
expireAfterWriteSeconds: 60
- names: [ userTenantRoles ]
allowNullValues: true
initialCapacity: 100
maximumSize: 500
enableRecordStats: false
expireAfterWriteSeconds: 60
mapCaches:
userBySubjectId:
name: userBySubjectId
@ -81,6 +87,9 @@ cache:
userAllowedTenant:
name: userAllowedTenant
keyPattern: user_allowed_tenant$tenant_id$_$user_id$:v0
userTenantRoles:
name: userTenantRoles
keyPattern: user_tenant_roles$tenant_id$_$user_id$:v0
supportiveMaterial:
name: supportiveMaterial
keyPattern: supportive_material_$type$_$lang$:v0