diff --git a/code/api/api/pom.xml b/code/api/api/pom.xml
index a0bda9795..0f1ad9caa 100644
--- a/code/api/api/pom.xml
+++ b/code/api/api/pom.xml
@@ -66,6 +66,18 @@
io.micrometer
micrometer-registry-influx
+
+
+
+ org.springframework.boot
+ spring-boot-starter-cache
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
@@ -96,6 +108,13 @@
spring-boot-devtools
true
+
+
+ com.github.tomakehurst
+ wiremock
+ 2.32.0
+ test
+
diff --git a/code/api/api/src/main/java/com/decathlon/ara/Messages.java b/code/api/api/src/main/java/com/decathlon/ara/Messages.java
index b9db452a4..4758d4532 100644
--- a/code/api/api/src/main/java/com/decathlon/ara/Messages.java
+++ b/code/api/api/src/main/java/com/decathlon/ara/Messages.java
@@ -22,9 +22,12 @@ public final class Messages {
private Messages() {
}
+ public static final String ALREADY_EXIST = "The %s already exist";
+
public static final String PARAMETER_IS_MISSING = "One or more parameters is missing or null";
public static final String PARAMETER_HAS_ONE_OR_MORE_MISSING_FIELDS = "A parameter has one or more missing field";
+ public static final String NOT_FOUND = "The %s does not exist: it has perhaps been removed.";
public static final String NOT_FOUND_COMMUNICATION = "The communication does not exist: it has perhaps been removed.";
public static final String NOT_FOUND_COUNTRY = "The country does not exist: it has perhaps been removed.";
public static final String NOT_FOUND_CYCLE_DEFINITION = "The cycle definition does not exist: it has perhaps been removed.";
diff --git a/code/api/api/src/main/java/com/decathlon/ara/cache/CacheService.java b/code/api/api/src/main/java/com/decathlon/ara/cache/CacheService.java
new file mode 100644
index 000000000..2f5d8143f
--- /dev/null
+++ b/code/api/api/src/main/java/com/decathlon/ara/cache/CacheService.java
@@ -0,0 +1,104 @@
+package com.decathlon.ara.cache;
+
+import java.util.function.Predicate;
+
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.ehcache.EhCacheCache;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.support.TransactionSynchronization;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+import com.decathlon.ara.domain.Project;
+
+@Service
+public class CacheService {
+
+ private static final String USER_PROJECTS_CACHE_NAME = "security.user.projects";
+ private static final String USER_PROJECT_ROLES_CACHE_NAME = "security.user.project.roles";
+
+ private CacheManager cacheManager;
+
+ public CacheService(CacheManager cacheManager) {
+ this.cacheManager = cacheManager;
+ }
+
+ public void evictCaches(Project project) {
+ evictCacheAfterCommit(() -> {
+ evictCache(USER_PROJECT_ROLES_CACHE_NAME, key -> key.toString().startsWith(project.getCode()));
+
+ Cache cache = cacheManager.getCache(USER_PROJECTS_CACHE_NAME);
+ if (cache != null) {
+ cache.clear();
+ }
+ });
+ }
+
+ public void evictCaches(Project project, String userName) {
+ evictsUserProjectRolesCache(project, userName);
+ evictsUserProjectsCache(userName);
+ }
+
+ public void evictsUserProjectRolesCache(Project project, String userName) {
+ evictCacheAfterCommit(() -> {
+ Cache cache = cacheManager.getCache(USER_PROJECT_ROLES_CACHE_NAME);
+ if (cache != null) {
+ cache.evict(project.getCode().concat(userName));
+ }
+ });
+ }
+
+ public void evictsUserProjectRolesCache(String userName) {
+ evictCacheAfterCommit(() -> evictCache(USER_PROJECT_ROLES_CACHE_NAME, key -> key.toString().endsWith(userName)));
+ }
+
+ public void evictsUserProjectsCache(String userName) {
+ evictCacheAfterCommit(() -> {
+ Cache cache = cacheManager.getCache(USER_PROJECTS_CACHE_NAME);
+ if (cache != null) {
+ cache.evict(userName);
+ }
+ });
+ }
+
+ public void evictCaches(String userName) {
+ evictsUserProjectRolesCache(userName);
+ evictsUserProjectsCache(userName);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void evictCache(String cacheName, Predicate