diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/InstanceConfig.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/InstanceConfig.java index 0ef9d81a6d..411a03dfe6 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/InstanceConfig.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/configurations/InstanceConfig.java @@ -5,6 +5,7 @@ import com.appsmith.server.domains.Config; import com.appsmith.server.dtos.ResponseDTO; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; +import com.appsmith.server.repositories.CacheableRepositoryHelper; import com.appsmith.server.services.ConfigService; import com.appsmith.util.WebClientUtils; import io.sentry.Sentry; @@ -38,8 +39,11 @@ public class InstanceConfig implements ApplicationListener registrationAndRtsCheckMono) + // Prefill the server cache with anonymous user permission group ids. + .then(cacheableRepositoryHelper.preFillAnonymousUserPermissionGroupIdsCache()) .subscribe(null, e -> { log.debug("Application start up encountered an error: {}", e.getMessage()); Sentry.captureException(e); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java index 065d7fbfa1..ce75097b4a 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/exceptions/AppsmithError.java @@ -152,7 +152,9 @@ public enum AppsmithError { PUBLIC_APP_NO_PERMISSION_GROUP(500, 5020, "Invalid state. Public application does not have the required roles set for public access. Please reach out to Appsmith customer support to resolve this.", AppsmithErrorAction.LOG_EXTERNALLY, null, ErrorType.INTERNAL_ERROR, null), RTS_SERVER_ERROR(500, 5021, "RTS server error while processing request: {0}", AppsmithErrorAction.LOG_EXTERNALLY, null, ErrorType.INTERNAL_ERROR, null), SCHEMA_MISMATCH_ERROR(500, 5022, "Looks like you skipped some required update(s), please go back to the mandatory upgrade path {0}, or refer to ''https://docs.appsmith.com/'' for more info", AppsmithErrorAction.LOG_EXTERNALLY, null, ErrorType.INTERNAL_ERROR, null), - SCHEMA_VERSION_NOT_FOUND_ERROR(500, 5023, "Could not find mandatory instance schema version config. Please reach out to Appsmith customer support to resolve this.", AppsmithErrorAction.LOG_EXTERNALLY, null, ErrorType.INTERNAL_ERROR, null) + SCHEMA_VERSION_NOT_FOUND_ERROR(500, 5023, "Could not find mandatory instance schema version config. Please reach out to Appsmith customer support to resolve this.", AppsmithErrorAction.LOG_EXTERNALLY, null, ErrorType.INTERNAL_ERROR, null), + SERVER_NOT_READY(500, 5024, "Appsmith server is not ready. Please try again in some time.", AppsmithErrorAction.LOG_EXTERNALLY, null, ErrorType.INTERNAL_ERROR, null), + SESSION_BAD_STATE(500, 5025, "User session is invalid. Please log out and log in again.", AppsmithErrorAction.LOG_EXTERNALLY, null, ErrorType.INTERNAL_ERROR, null) ; private final Integer httpErrorCode; diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCE.java index 4a6a08121e..b5e780f293 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCE.java @@ -9,6 +9,8 @@ public interface CacheableRepositoryHelperCE { Mono> getPermissionGroupsOfUser(User user); + Mono> preFillAnonymousUserPermissionGroupIdsCache(); + Mono> getPermissionGroupsOfAnonymousUser(); Mono evictPermissionGroupsUser(String email, String tenantId); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCEImpl.java index 91870eda3e..413d43281d 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/ce/CacheableRepositoryHelperCEImpl.java @@ -11,6 +11,8 @@ import com.appsmith.server.domains.QTenant; import com.appsmith.server.domains.QUser; import com.appsmith.server.domains.Tenant; import com.appsmith.server.domains.User; +import com.appsmith.server.exceptions.AppsmithError; +import com.appsmith.server.exceptions.AppsmithException; import lombok.extern.slf4j.Slf4j; import org.springframework.data.mongodb.core.ReactiveMongoOperations; import org.springframework.data.mongodb.core.query.Criteria; @@ -23,6 +25,7 @@ import java.util.Set; import java.util.stream.Collectors; import static com.appsmith.server.constants.FieldName.PERMISSION_GROUP_ID; +import static com.appsmith.server.constants.ce.FieldNameCE.ANONYMOUS_USER; import static com.appsmith.server.repositories.BaseAppsmithRepositoryImpl.fieldName; import static com.appsmith.server.repositories.ce.BaseAppsmithRepositoryCEImpl.notDeleted; @@ -45,6 +48,18 @@ public class CacheableRepositoryHelperCEImpl implements CacheableRepositoryHelpe @Cache(cacheName = "permissionGroupsForUser", key = "{#user.email + #user.tenantId}") @Override public Mono> getPermissionGroupsOfUser(User user) { + + // If the user is anonymous, then we don't need to fetch the permission groups from the database. We can just + // return the cached permission group ids. + if (ANONYMOUS_USER.equals(user.getUsername())) { + return getPermissionGroupsOfAnonymousUser(); + } + + if (user.getEmail() == null || user.getEmail().isEmpty() || user.getId() == null || user.getId().isEmpty()) { + return Mono.error(new AppsmithException(AppsmithError.SESSION_BAD_STATE)); + } + + Criteria assignedToUserIdsCriteria = Criteria.where(fieldName(QPermissionGroup.permissionGroup.assignedToUserIds)).is(user.getId()); Criteria notDeletedCriteria = notDeleted(); @@ -60,9 +75,9 @@ public class CacheableRepositoryHelperCEImpl implements CacheableRepositoryHelpe } @Override - public Mono> getPermissionGroupsOfAnonymousUser() { + public Mono> preFillAnonymousUserPermissionGroupIdsCache() { - if (anonymousUserPermissionGroupIds != null) { + if (anonymousUserPermissionGroupIds != null && !anonymousUserPermissionGroupIds.isEmpty()) { return Mono.just(anonymousUserPermissionGroupIds); } @@ -74,6 +89,19 @@ public class CacheableRepositoryHelperCEImpl implements CacheableRepositoryHelpe .doOnSuccess(permissionGroupIds -> anonymousUserPermissionGroupIds = permissionGroupIds); } + @Override + public Mono> getPermissionGroupsOfAnonymousUser() { + + if (anonymousUserPermissionGroupIds != null) { + return Mono.just(anonymousUserPermissionGroupIds); + } + + // If we have reached this state, then the cache is not populated. We need to wait for this to get populated + // Anonymous user cache is getting populated at #InstanceConfig.onApplicationEvent + // Return an error to the user so that the user can re-try in some time + return Mono.error(new AppsmithException(AppsmithError.SERVER_NOT_READY)); + } + @CacheEvict(cacheName = "permissionGroupsForUser", key = "{#email + #tenantId}") @Override public Mono evictPermissionGroupsUser(String email, String tenantId) {