feat: Adding cache eviction for users whose permissions change due to super user changes (#16362)

Adding cache eviction for users whose permissions change due to super user changes
This commit is contained in:
Trisha Anand 2022-08-29 13:21:24 +05:30 committed by GitHub
parent b893cb5216
commit 8d9e071648
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 1 deletions

View File

@ -2,10 +2,12 @@ package com.appsmith.server.helpers;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class CollectionUtils {
@ -65,4 +67,29 @@ public class CollectionUtils {
list.addAll(set);
}
/**
* Finds all the elements which do not exist in the intersection between the two sets
* @param set1
* @param set2
* @return
* @param <T>
*/
public static <T> Set<T> findSymmetricDiff(Set<T> set1, Set<T> set2) {
Map<T, Integer> map = new HashMap<>();
set1.forEach(e -> putKeyForFindingSymmetricDiff(map, e));
set2.forEach(e -> putKeyForFindingSymmetricDiff(map, e));
return map.entrySet().stream()
.filter(e -> e.getValue() == 1)
.map(Map.Entry::getKey)
.collect(Collectors.toSet());
}
private static <T> void putKeyForFindingSymmetricDiff(Map<T, Integer> map, T key) {
if (map.containsKey(key)) {
map.replace(key, Integer.MAX_VALUE);
} else {
map.put(key, 1);
}
}
}

View File

@ -52,6 +52,7 @@ import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.helpers.PolicyUtils;
import com.appsmith.server.helpers.TextUtils;
import com.appsmith.server.repositories.CacheableRepositoryHelper;
import com.appsmith.server.repositories.NewPageRepository;
import com.appsmith.server.repositories.UserRepository;
import com.appsmith.server.services.WorkspaceService;
@ -109,10 +110,12 @@ import static com.appsmith.server.acl.AclPermission.RESET_PASSWORD_USERS;
import static com.appsmith.server.constants.EnvVariables.APPSMITH_ADMIN_EMAILS;
import static com.appsmith.server.constants.FieldName.DEFAULT_PERMISSION_GROUP;
import static com.appsmith.server.constants.FieldName.PERMISSION_GROUP_ID;
import static com.appsmith.server.helpers.CollectionUtils.findSymmetricDiff;
import static com.appsmith.server.migrations.DatabaseChangelog.dropIndexIfExists;
import static com.appsmith.server.migrations.DatabaseChangelog.ensureIndexes;
import static com.appsmith.server.migrations.DatabaseChangelog.getUpdatedDynamicBindingPathList;
import static com.appsmith.server.migrations.DatabaseChangelog.makeIndex;
import static com.appsmith.server.migrations.MigrationHelperMethods.evictPermissionCacheForUsers;
import static com.appsmith.server.repositories.BaseAppsmithRepositoryImpl.fieldName;
import static java.lang.Boolean.TRUE;
import static org.springframework.data.mongodb.core.query.Criteria.where;
@ -2288,7 +2291,7 @@ public class DatabaseChangelog2 {
}
@ChangeSet(order = "033", id = "update-super-users", author = "", runAlways = true)
public void updateSuperUsers(MongockTemplate mongockTemplate) {
public void updateSuperUsers(MongockTemplate mongockTemplate, CacheableRepositoryHelper cacheableRepositoryHelper) {
// Read the admin emails from the environment and update the super users accordingly
String adminEmailsStr = System.getenv(String.valueOf(APPSMITH_ADMIN_EMAILS));
@ -2325,6 +2328,9 @@ public class DatabaseChangelog2 {
})
.collect(Collectors.toSet());
Set<String> oldSuperUsers = instanceAdminPG.getAssignedToUserIds();
Set<String> updatedUserIds = findSymmetricDiff(oldSuperUsers, userIds);
evictPermissionCacheForUsers(updatedUserIds, mongockTemplate, cacheableRepositoryHelper);
instanceAdminPG.setAssignedToUserIds(userIds);
mongockTemplate.save(instanceAdminPG);
}
@ -2334,6 +2340,7 @@ public class DatabaseChangelog2 {
user.setEmail(email);
user.setIsEnabled(false);
user.setTenantId(tenantId);
user.setCreatedAt(Instant.now());
user = mongockTemplate.save(user);
// Assign the user to the default permissions

View File

@ -4,10 +4,16 @@ import com.appsmith.external.models.InvisibleActionFields;
import com.appsmith.server.constants.ResourceModes;
import com.appsmith.server.domains.ApplicationPage;
import com.appsmith.server.domains.NewAction;
import com.appsmith.server.domains.QUser;
import com.appsmith.server.domains.User;
import com.appsmith.server.dtos.ActionDTO;
import com.appsmith.server.dtos.ApplicationJson;
import com.appsmith.server.helpers.CollectionUtils;
import com.appsmith.server.repositories.CacheableRepositoryHelper;
import com.github.cloudyrock.mongock.driver.mongodb.springdata.v3.decorator.impl.MongockTemplate;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import java.time.Instant;
import java.util.ArrayList;
@ -19,6 +25,7 @@ import java.util.stream.Collectors;
import static com.appsmith.server.constants.ResourceModes.EDIT;
import static com.appsmith.server.constants.ResourceModes.VIEW;
import static com.appsmith.server.repositories.BaseAppsmithRepositoryImpl.fieldName;
public class MigrationHelperMethods {
// Migration for deprecating archivedAt field in ActionDTO
@ -165,4 +172,22 @@ public class MigrationHelperMethods {
});
}
}
public static void evictPermissionCacheForUsers(Set<String> userIds,
MongockTemplate mongockTemplate,
CacheableRepositoryHelper cacheableRepositoryHelper) {
if (userIds == null || userIds.isEmpty()) {
// Nothing to do here.
return;
}
userIds.forEach(userId -> {
Query query = new Query(new Criteria(fieldName(QUser.user.id)).is(userId));
User user = mongockTemplate.findOne(query, User.class);
// blocking call for cache eviction to ensure its subscribed immediately before proceeding further.
cacheableRepositoryHelper.evictPermissionGroupsUser(user.getEmail(), user.getTenantId())
.block();
});
}
}