diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/actioncollections/base/ActionCollectionServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/actioncollections/base/ActionCollectionServiceCEImpl.java index 3c4dcf1788db..3dd16fa6a41d 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/actioncollections/base/ActionCollectionServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/actioncollections/base/ActionCollectionServiceCEImpl.java @@ -11,10 +11,12 @@ import com.appsmith.server.domains.ActionCollection; import com.appsmith.server.domains.NewAction; import com.appsmith.server.domains.NewPage; +import com.appsmith.server.domains.User; import com.appsmith.server.dtos.ActionCollectionDTO; import com.appsmith.server.dtos.ActionCollectionViewDTO; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.newactions.base.NewActionService; import com.appsmith.server.repositories.ActionCollectionRepository; import com.appsmith.server.services.AnalyticsService; @@ -280,13 +282,18 @@ public Mono update(String id, ActionCollectionDTO actionCol @Override public Mono deleteWithoutPermissionUnpublishedActionCollection(String id) { - return deleteUnpublishedActionCollection(id, null, actionPermission.getDeletePermission()); + return ReactiveContextUtils.getCurrentUser() + .flatMap(user -> deleteUnpublishedActionCollection( + id, null, actionPermission.getDeletePermission(user.getOrganizationId()))); } @Override public Mono deleteUnpublishedActionCollection(String id) { - return deleteUnpublishedActionCollection( - id, actionPermission.getDeletePermission(), actionPermission.getDeletePermission()); + return ReactiveContextUtils.getCurrentUser() + .flatMap(user -> deleteUnpublishedActionCollection( + id, + actionPermission.getDeletePermission(user.getOrganizationId()), + actionPermission.getDeletePermission(user.getOrganizationId()))); } @Override @@ -418,10 +425,17 @@ public Mono archiveById(String id) { } protected Mono archiveGivenActionCollection(ActionCollection actionCollection) { - Flux unpublishedJsActionsFlux = newActionService.findByCollectionIdAndViewMode( - actionCollection.getId(), false, actionPermission.getDeletePermission()); - Flux publishedJsActionsFlux = newActionService.findByCollectionIdAndViewMode( - actionCollection.getId(), true, actionPermission.getDeletePermission()); + Mono currentUserMono = ReactiveContextUtils.getCurrentUser().cache(); + Flux unpublishedJsActionsFlux = + currentUserMono.flatMapMany(user -> newActionService.findByCollectionIdAndViewMode( + actionCollection.getId(), + false, + actionPermission.getDeletePermission(user.getOrganizationId()))); + Flux publishedJsActionsFlux = + currentUserMono.flatMapMany(user -> newActionService.findByCollectionIdAndViewMode( + actionCollection.getId(), + true, + actionPermission.getDeletePermission(user.getOrganizationId()))); return unpublishedJsActionsFlux .mergeWith(publishedJsActionsFlux) .flatMap(toArchive -> newActionService diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/actioncollections/importable/ActionCollectionImportableServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/actioncollections/importable/ActionCollectionImportableServiceCEImpl.java index 0fb942013c19..81e3c09c3f64 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/actioncollections/importable/ActionCollectionImportableServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/actioncollections/importable/ActionCollectionImportableServiceCEImpl.java @@ -12,6 +12,7 @@ import com.appsmith.server.dtos.ImportActionCollectionResultDTO; import com.appsmith.server.dtos.ImportingMetaDTO; import com.appsmith.server.dtos.MappedImportableResourcesDTO; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.imports.importable.ImportableServiceCE; import com.appsmith.server.imports.importable.artifactbased.ArtifactBasedImportableService; import com.appsmith.server.repositories.ActionCollectionRepository; @@ -162,10 +163,14 @@ private Mono importActionCollections( importedActionCollectionList, mappedImportableResourcesDTO); } - return Mono.zip(actionCollectionsInCurrentArtifactMono, actionCollectionsInBranchesMono) + return Mono.zip( + actionCollectionsInCurrentArtifactMono, + actionCollectionsInBranchesMono, + ReactiveContextUtils.getCurrentUser()) .flatMap(objects -> { Map actionsCollectionsInCurrentArtifact = objects.getT1(); Map actionsCollectionsInBranches = objects.getT2(); + String currentUserOrgId = objects.getT3().getOrganizationId(); // set the existing action collections in the result DTO, // this will be required in next phases when we'll delete the outdated action @@ -228,7 +233,7 @@ private Mono importActionCollections( .put(idFromJsonFile, existingActionCollection); } else { artifactBasedImportableService.createNewResource( - importingMetaDTO, actionCollection, baseContext); + importingMetaDTO, actionCollection, baseContext, currentUserOrgId); populateDomainMappedReferences(mappedImportableResourcesDTO, actionCollection); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/actioncollections/importable/applications/ActionCollectionApplicationImportableServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/actioncollections/importable/applications/ActionCollectionApplicationImportableServiceCEImpl.java index 0595b5abee0e..0d2708aa12d9 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/actioncollections/importable/applications/ActionCollectionApplicationImportableServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/actioncollections/importable/applications/ActionCollectionApplicationImportableServiceCEImpl.java @@ -89,8 +89,11 @@ public Context updateContextInResource( @Override public void createNewResource( - ImportingMetaDTO importingMetaDTO, ActionCollection actionCollection, Context baseContext) { - if (!importingMetaDTO.getPermissionProvider().canCreateAction((NewPage) baseContext)) { + ImportingMetaDTO importingMetaDTO, + ActionCollection actionCollection, + Context baseContext, + String organizationId) { + if (!importingMetaDTO.getPermissionProvider().canCreateAction((NewPage) baseContext, organizationId)) { throw new AppsmithException( AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.PAGE, ((NewPage) baseContext).getId()); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/applications/base/ApplicationServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/applications/base/ApplicationServiceCEImpl.java index 580596aa51ec..4d0de38cda78 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/applications/base/ApplicationServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/applications/base/ApplicationServiceCEImpl.java @@ -501,12 +501,13 @@ private Mono generateAndSetPoliciesForPublicView( .filter(applicationId -> !application.getId().equals(applicationId)) .cache(); - List> updateInheritedDomainsList = + Mono>> updateInheritedDomainsListMono = updatePoliciesForInheritingDomains(application, applicationPolicyMap, addViewAccess); List> updateIndependentDomainsList = updatePoliciesForIndependentDomains( application, permissionGroupId, addViewAccess, otherApplicationsForThisRoleFlux); - return Flux.fromIterable(updateInheritedDomainsList) + return updateInheritedDomainsListMono + .flatMapMany(Flux::fromIterable) .flatMap(voidMono -> voidMono) .thenMany(Flux.fromIterable(updateIndependentDomainsList)) .flatMap(voidMono -> voidMono) @@ -604,7 +605,7 @@ protected List> updatePoliciesForIndependentDomains( return list; } - protected List> updatePoliciesForInheritingDomains( + protected Mono>> updatePoliciesForInheritingDomains( Application application, Map applicationPolicyMap, Boolean addViewAccess) { List> list = new ArrayList<>(); @@ -635,7 +636,7 @@ protected List> updatePoliciesForInheritingDomains( .then(); list.add(updatedThemesMono); - return list; + return Mono.just(list); } public Mono setTransientFields(Application application) { diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/applications/imports/ApplicationImportServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/applications/imports/ApplicationImportServiceCEImpl.java index 94c29a24331c..88fd8a5c345c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/applications/imports/ApplicationImportServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/applications/imports/ApplicationImportServiceCEImpl.java @@ -24,6 +24,7 @@ import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.helpers.ImportArtifactPermissionProvider; import com.appsmith.server.helpers.ImportExportUtils; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.imports.importable.ImportableService; import com.appsmith.server.imports.internal.artifactbased.ArtifactBasedImportServiceCE; import com.appsmith.server.layouts.UpdateLayoutService; @@ -90,19 +91,23 @@ public class ApplicationImportServiceCEImpl Map.of(FieldName.ARTIFACT_CONTEXT, FieldName.APPLICATION, FieldName.ID, FieldName.APPLICATION_ID); @Override - public ImportArtifactPermissionProvider getImportArtifactPermissionProviderForImportingArtifact( + public Mono getImportArtifactPermissionProviderForImportingArtifact( Set userPermissionGroups) { - return ImportArtifactPermissionProvider.builder( - applicationPermission, - pagePermission, - actionPermission, - datasourcePermission, - workspacePermission) - .requiredPermissionOnTargetWorkspace(workspacePermission.getApplicationCreatePermission()) - .permissionRequiredToCreateDatasource(true) - .permissionRequiredToEditDatasource(true) - .currentUserPermissionGroups(userPermissionGroups) - .build(); + + return ReactiveContextUtils.getCurrentUser().map(currentUser -> { + String userOrgId = currentUser.getOrganizationId(); + return ImportArtifactPermissionProvider.builder( + applicationPermission, + pagePermission, + actionPermission, + datasourcePermission, + workspacePermission) + .requiredPermissionOnTargetWorkspace(workspacePermission.getApplicationCreatePermission(userOrgId)) + .permissionRequiredToCreateDatasource(true) + .permissionRequiredToEditDatasource(true) + .currentUserPermissionGroups(userPermissionGroups) + .build(); + }); } @Override diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/artifacts/permissions/ArtifactPermissionCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/artifacts/permissions/ArtifactPermissionCE.java index 78423dd64cfb..fbd173bc20a8 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/artifacts/permissions/ArtifactPermissionCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/artifacts/permissions/ArtifactPermissionCE.java @@ -6,7 +6,7 @@ public interface ArtifactPermissionCE { AclPermission getEditPermission(); - AclPermission getDeletePermission(); + AclPermission getDeletePermission(String organizationId); AclPermission getGitConnectPermission(); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java index 40659e939ea7..94e895f57b3c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspect.java @@ -15,11 +15,13 @@ import org.aspectj.lang.reflect.MethodSignature; import org.springframework.context.ApplicationContext; import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.beans.Introspector; import java.lang.reflect.Method; +import java.lang.reflect.Parameter; @RequiredArgsConstructor @Aspect @@ -42,7 +44,7 @@ public class FeatureFlaggedMethodInvokerAspect { * @see FeatureFlagged */ @Around("execution(public * *(..)) && @annotation(com.appsmith.external.annotations.FeatureFlagged)") - public Object invokeMethodAtMethodLevelAnnotation(ProceedingJoinPoint joinPoint) throws IllegalAccessException { + public Object invokeMethodAtMethodLevelAnnotation(ProceedingJoinPoint joinPoint) { Method method = ((MethodSignature) joinPoint.getSignature()).getMethod(); FeatureFlagged annotation = method.getAnnotation(FeatureFlagged.class); if (annotation.featureFlagName() == null) { @@ -64,9 +66,19 @@ private Object invokeMethod(ProceedingJoinPoint joinPoint, FeatureFlagged annota } else if (Flux.class.isAssignableFrom(returnType)) { return featureFlagMono.flatMapMany(isSupported -> (Flux) invokeMethod(isSupported, joinPoint, method)); } + // Extract organizationId from method arguments + String organizationId = extractOrganizationId(joinPoint.getArgs(), method.getParameters()); + + if (!StringUtils.hasLength(organizationId)) { + String errorMessage = + "Add missing organizationId parameter and enforce non-null value for orgnization-specific feature flags retrieval in non-reactive methods"; + AppsmithException exception = getInvalidAnnotationUsageException(method, errorMessage); + log.error(exception.getMessage()); + throw exception; + } // For non-reactive methods with feature flagging annotation we will be using the in memory feature flag cache // which is getting updated whenever the organization feature flags are updated. - return invokeMethod(isFeatureFlagEnabled(flagName), joinPoint, method); + return invokeMethod(isFeatureFlagEnabled(flagName, organizationId), joinPoint, method); } private Object invokeMethod(Boolean isFeatureSupported, ProceedingJoinPoint joinPoint, Method method) { @@ -106,10 +118,26 @@ AppsmithException getInvalidAnnotationUsageException(Method method, String error error); } - boolean isFeatureFlagEnabled(FeatureFlagEnum flagName) { - CachedFeatures cachedFeatures = featureFlagService.getCachedOrganizationFeatureFlags(); + boolean isFeatureFlagEnabled(FeatureFlagEnum flagName, String organizationId) { + CachedFeatures cachedFeatures = featureFlagService.getCachedOrganizationFeatureFlags(organizationId); return cachedFeatures != null && !CollectionUtils.isNullOrEmpty(cachedFeatures.getFeatures()) && Boolean.TRUE.equals(cachedFeatures.getFeatures().get(flagName.name())); } + + private String extractOrganizationId(Object[] args, Parameter[] parameters) { + if (args == null || parameters == null || args.length != parameters.length) { + return null; + } + + // First try to find parameter named exactly "organizationId" or "orgId" + for (int i = 0; i < parameters.length; i++) { + String paramName = parameters[i].getName(); + if ((paramName.equals("organizationId") || paramName.equals("orgId")) && args[i] instanceof String) { + return (String) args[i]; + } + } + + return null; + } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/base/DatasourceServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/base/DatasourceServiceCEImpl.java index 591ea758900d..5c4fc1f6dad9 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/base/DatasourceServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/base/DatasourceServiceCEImpl.java @@ -23,6 +23,7 @@ import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.helpers.PluginExecutorHelper; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.plugins.base.PluginService; import com.appsmith.server.ratelimiting.RateLimitService; import com.appsmith.server.repositories.DatasourceRepository; @@ -152,7 +153,12 @@ public DatasourceServiceCEImpl( @Override public Mono create(Datasource datasource) { - return createEx(datasource, workspacePermission.getDatasourceCreatePermission(), false, null); + return ReactiveContextUtils.getCurrentUser() + .flatMap(user -> createEx( + datasource, + workspacePermission.getDatasourceCreatePermission(user.getOrganizationId()), + false, + null)); } // TODO: Check usage @@ -880,8 +886,9 @@ public Flux getAllByWorkspaceIdWithStorages(String workspaceId, AclP @Override public Mono archiveById(String id) { - return repository - .findById(id, datasourcePermission.getDeletePermission()) + return ReactiveContextUtils.getCurrentUser() + .flatMap(user -> + repository.findById(id, datasourcePermission.getDeletePermission(user.getOrganizationId()))) .switchIfEmpty( Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.DATASOURCE, id))) .zipWhen(datasource -> newActionRepository.countByDatasourceId(datasource.getId())) diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/importable/DatasourceImportableServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/importable/DatasourceImportableServiceCEImpl.java index 83489d22a359..1f1e8d91cce5 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/importable/DatasourceImportableServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/datasources/importable/DatasourceImportableServiceCEImpl.java @@ -21,6 +21,7 @@ import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.helpers.ImportArtifactPermissionProvider; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.imports.importable.ImportableServiceCE; import com.appsmith.server.imports.importable.artifactbased.ArtifactBasedImportableService; import com.appsmith.server.services.SequenceService; @@ -301,43 +302,47 @@ private Mono createUniqueDatasourceIfNotPresent( .filter(ds -> ds.getName().equals(datasourceStorage.getName()) && datasourceStorage.getPluginId().equals(ds.getPluginId())) .next() // Get the first matching datasource, we don't need more than one here. - .switchIfEmpty(Mono.defer(() -> { - // check if user has permission to create datasource - if (!permissionProvider.canCreateDatasource(workspace)) { - log.error( - "Unauthorized to create datasource: {} in workspace: {}", - datasourceStorage.getName(), - workspace.getName()); - return Mono.error(new AppsmithException( - AppsmithError.ACL_NO_RESOURCE_FOUND, - FieldName.DATASOURCE, - datasourceStorage.getName())); - } - - if (datasourceConfig != null && datasourceConfig.getAuthentication() != null) { - datasourceConfig.getAuthentication().setAuthenticationResponse(authResponse); - } - // No matching existing datasource found, so create a new one. - datasourceStorage.setIsConfigured( - datasourceConfig != null && datasourceConfig.getAuthentication() != null); - datasourceStorage.setEnvironmentId(environmentId); - - return datasourceService - .findByNameAndWorkspaceId(datasourceStorage.getName(), workspace.getId(), null) - .flatMap(duplicateNameDatasource -> - getUniqueSuffixForDuplicateNameEntity(duplicateNameDatasource, workspace.getId())) - .map(dsName -> { - datasourceStorage.setName(datasourceStorage.getName() + dsName); - - return datasourceService.createDatasourceFromDatasourceStorage(datasourceStorage); - }) - .switchIfEmpty(Mono.just( - datasourceService.createDatasourceFromDatasourceStorage(datasourceStorage))) - // DRY RUN queries are not saved, so we need to create them separately at the import service - // solution - .flatMap(datasource -> datasourceService.createWithoutPermissions( - datasource, mappedImportableResourcesDTO.getDatasourceStorageDryRunQueries())); - })) + .switchIfEmpty( + Mono.defer(() -> ReactiveContextUtils.getCurrentUser().flatMap(user -> { + // check if user has permission to create datasource + if (!permissionProvider.canCreateDatasource(workspace, user.getOrganizationId())) { + log.error( + "Unauthorized to create datasource: {} in workspace: {}", + datasourceStorage.getName(), + workspace.getName()); + return Mono.error(new AppsmithException( + AppsmithError.ACL_NO_RESOURCE_FOUND, + FieldName.DATASOURCE, + datasourceStorage.getName())); + } + + if (datasourceConfig != null && datasourceConfig.getAuthentication() != null) { + datasourceConfig.getAuthentication().setAuthenticationResponse(authResponse); + } + // No matching existing datasource found, so create a new one. + datasourceStorage.setIsConfigured( + datasourceConfig != null && datasourceConfig.getAuthentication() != null); + datasourceStorage.setEnvironmentId(environmentId); + + return datasourceService + .findByNameAndWorkspaceId(datasourceStorage.getName(), workspace.getId(), null) + .flatMap(duplicateNameDatasource -> getUniqueSuffixForDuplicateNameEntity( + duplicateNameDatasource, workspace.getId())) + .map(dsName -> { + datasourceStorage.setName(datasourceStorage.getName() + dsName); + + return datasourceService.createDatasourceFromDatasourceStorage( + datasourceStorage); + }) + .switchIfEmpty(Mono.just( + datasourceService.createDatasourceFromDatasourceStorage(datasourceStorage))) + // DRY RUN queries are not saved, so we need to create them separately at the import + // service + // solution + .flatMap(datasource -> datasourceService.createWithoutPermissions( + datasource, + mappedImportableResourcesDTO.getDatasourceStorageDryRunQueries())); + }))) .onErrorResume(throwable -> { log.error("failed to import datasource", throwable); return Mono.error(throwable); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/fork/internal/ApplicationForkingServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/fork/internal/ApplicationForkingServiceCEImpl.java index 62fc9d9bdec4..488331f4b661 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/fork/internal/ApplicationForkingServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/fork/internal/ApplicationForkingServiceCEImpl.java @@ -65,6 +65,7 @@ import java.util.concurrent.ConcurrentHashMap; import static com.appsmith.server.helpers.ce.PolicyUtil.policyMapToSet; +import static java.lang.Boolean.TRUE; @RequiredArgsConstructor @Slf4j @@ -132,8 +133,8 @@ public Mono> forkApplications( // Extracting forkWithConfiguration to use below before resetting it for newly forked app // forkWithConfig by default remains FALSE for datasources used in an application Boolean forkWithConfig; - if (Boolean.TRUE.equals(application.getForkWithConfiguration())) { - forkWithConfig = Boolean.TRUE; + if (TRUE.equals(application.getForkWithConfiguration())) { + forkWithConfig = TRUE; } else { forkWithConfig = Boolean.FALSE; } @@ -433,13 +434,14 @@ public Mono forkApplicationToWorkspaceWithEnvironment( .switchIfEmpty(Mono.error(new AppsmithException( AppsmithError.NO_RESOURCE_FOUND, FieldName.APPLICATION, srcApplicationId))); - final Mono targetWorkspaceMono = workspaceService - .findById(targetWorkspaceId, workspacePermission.getApplicationCreatePermission()) + Mono userMono = sessionUserService.getCurrentUser().cache(); + + final Mono targetWorkspaceMono = userMono.flatMap(user -> workspaceService.findById( + targetWorkspaceId, + workspacePermission.getApplicationCreatePermission(user.getOrganizationId()))) .switchIfEmpty(Mono.error(new AppsmithException( AppsmithError.NO_RESOURCE_FOUND, FieldName.WORKSPACE, targetWorkspaceId))); - Mono userMono = sessionUserService.getCurrentUser(); - // For collecting all the possible event data Map eventData = new HashMap<>(); @@ -463,7 +465,7 @@ public Mono forkApplicationToWorkspaceWithEnvironment( .contains(applicationPermission .getEditPermission() .getValue())) - || Boolean.TRUE.equals(application.getForkingEnabled()); + || TRUE.equals(application.getForkingEnabled()); if (!allowFork) { return Mono.error(new AppsmithException(AppsmithError.APPLICATION_FORKING_NOT_ALLOWED)); @@ -568,102 +570,112 @@ private Mono checkPermissionsForForking(String branchedApplicationId1, AppsmithError.NO_RESOURCE_FOUND, FieldName.APPLICATION, branchedApplicationId1))) .cache(); + Mono currentUserMono = sessionUserService.getCurrentUser(); + // For sample apps that are marked as forked, we allow forking to any workspace without any permission checks - return isForkingEnabled(applicationMonoWithOutPermission).flatMap(isForkingEnabled -> { - if (isForkingEnabled) { - return Mono.just(Boolean.TRUE); - } - - // Normal Application forking with developer/edit access - Flux pageFlux = applicationMonoWithOutPermission.flatMapMany(application -> newPageRepository - .findIdsAndPolicyMapByApplicationIdIn(List.of(application.getId())) - .map(idPoliciesOnly -> { - NewPage newPage = new NewPage(); - newPage.setId(idPoliciesOnly.getId()); - Set policies = policyMapToSet(idPoliciesOnly.getPolicyMap()); - newPage.setPolicies(policies); - return newPage; - }) - .flatMap(newPageRepository::setUserPermissionsInObject)); - - Flux actionFlux = - applicationMonoWithOutPermission.flatMapMany(application -> newActionRepository - .findIdsAndPolicyMapByApplicationIdIn(List.of(application.getId())) - .map(idPoliciesOnly -> { - NewAction newAction = new NewAction(); - newAction.setId(idPoliciesOnly.getId()); - Set policies = policyMapToSet(idPoliciesOnly.getPolicyMap()); - newAction.setPolicies(policies); - return newAction; - }) - .flatMap(newActionRepository::setUserPermissionsInObject)); - - Flux actionCollectionFlux = - applicationMonoWithOutPermission.flatMapMany(application -> actionCollectionRepository - .findIdsAndPolicyMapByApplicationIdIn(List.of(application.getId())) - .map(idPoliciesOnly -> { - ActionCollection actionCollection = new ActionCollection(); - actionCollection.setId(idPoliciesOnly.getId()); - Set policies = policyMapToSet(idPoliciesOnly.getPolicyMap()); - actionCollection.setPolicies(policies); - return actionCollection; - }) - .flatMap(actionCollectionRepository::setUserPermissionsInObject)); - - Flux workspaceFlux = Flux.from(workspaceRepository - .findById(targetWorkspaceId) - .flatMap(workspaceRepository::setUserPermissionsInObject)); - - Mono> permissionGroupIdsMono = - permissionGroupService.getSessionUserPermissionGroupIds().cache(); - - Mono pagesValidatedForPermission = UserPermissionUtils.validateDomainObjectPermissionsOrError( - pageFlux, - FieldName.PAGE, - permissionGroupIdsMono, - pagePermission.getEditPermission(), - AppsmithError.APPLICATION_NOT_FORKED_MISSING_PERMISSIONS); - Mono actionsValidatedForPermission = UserPermissionUtils.validateDomainObjectPermissionsOrError( - actionFlux, - FieldName.ACTION, - permissionGroupIdsMono, - actionPermission.getEditPermission(), - AppsmithError.APPLICATION_NOT_FORKED_MISSING_PERMISSIONS); - Mono actionCollectionsValidatedForPermission = - UserPermissionUtils.validateDomainObjectPermissionsOrError( - actionCollectionFlux, - FieldName.ACTION, - permissionGroupIdsMono, - actionPermission.getEditPermission(), - AppsmithError.APPLICATION_NOT_FORKED_MISSING_PERMISSIONS); - Mono workspaceValidatedForCreateApplicationPermission = - UserPermissionUtils.validateDomainObjectPermissionsOrError( - workspaceFlux, - FieldName.WORKSPACE, - permissionGroupIdsMono, - workspacePermission.getApplicationCreatePermission(), - AppsmithError.APPLICATION_NOT_FORKED_MISSING_PERMISSIONS); - Mono workspaceValidatedForCreateDatasourcePermission = - UserPermissionUtils.validateDomainObjectPermissionsOrError( - workspaceFlux, - FieldName.WORKSPACE, - permissionGroupIdsMono, - workspacePermission.getDatasourceCreatePermission(), - AppsmithError.APPLICATION_NOT_FORKED_MISSING_PERMISSIONS); - - return Mono.when( - pagesValidatedForPermission, - actionsValidatedForPermission, - actionCollectionsValidatedForPermission, - workspaceValidatedForCreateApplicationPermission, - workspaceValidatedForCreateDatasourcePermission) - .thenReturn(Boolean.TRUE); - }); + return isForkingEnabled(applicationMonoWithOutPermission) + .zipWith(currentUserMono) + .flatMap(tuple2 -> { + boolean isForkingEnabled = TRUE.equals(tuple2.getT1()); + User currentUser = tuple2.getT2(); + if (isForkingEnabled) { + return Mono.just(TRUE); + } + + // Normal Application forking with developer/edit access + Flux pageFlux = + applicationMonoWithOutPermission.flatMapMany(application -> newPageRepository + .findIdsAndPolicyMapByApplicationIdIn(List.of(application.getId())) + .map(idPoliciesOnly -> { + NewPage newPage = new NewPage(); + newPage.setId(idPoliciesOnly.getId()); + Set policies = policyMapToSet(idPoliciesOnly.getPolicyMap()); + newPage.setPolicies(policies); + return newPage; + }) + .flatMap(newPageRepository::setUserPermissionsInObject)); + + Flux actionFlux = + applicationMonoWithOutPermission.flatMapMany(application -> newActionRepository + .findIdsAndPolicyMapByApplicationIdIn(List.of(application.getId())) + .map(idPoliciesOnly -> { + NewAction newAction = new NewAction(); + newAction.setId(idPoliciesOnly.getId()); + Set policies = policyMapToSet(idPoliciesOnly.getPolicyMap()); + newAction.setPolicies(policies); + return newAction; + }) + .flatMap(newActionRepository::setUserPermissionsInObject)); + + Flux actionCollectionFlux = + applicationMonoWithOutPermission.flatMapMany(application -> actionCollectionRepository + .findIdsAndPolicyMapByApplicationIdIn(List.of(application.getId())) + .map(idPoliciesOnly -> { + ActionCollection actionCollection = new ActionCollection(); + actionCollection.setId(idPoliciesOnly.getId()); + Set policies = policyMapToSet(idPoliciesOnly.getPolicyMap()); + actionCollection.setPolicies(policies); + return actionCollection; + }) + .flatMap(actionCollectionRepository::setUserPermissionsInObject)); + + Flux workspaceFlux = Flux.from(workspaceRepository + .findById(targetWorkspaceId) + .flatMap(workspaceRepository::setUserPermissionsInObject)); + + Mono> permissionGroupIdsMono = permissionGroupService + .getSessionUserPermissionGroupIds() + .cache(); + + Mono pagesValidatedForPermission = + UserPermissionUtils.validateDomainObjectPermissionsOrError( + pageFlux, + FieldName.PAGE, + permissionGroupIdsMono, + pagePermission.getEditPermission(), + AppsmithError.APPLICATION_NOT_FORKED_MISSING_PERMISSIONS); + Mono actionsValidatedForPermission = + UserPermissionUtils.validateDomainObjectPermissionsOrError( + actionFlux, + FieldName.ACTION, + permissionGroupIdsMono, + actionPermission.getEditPermission(), + AppsmithError.APPLICATION_NOT_FORKED_MISSING_PERMISSIONS); + Mono actionCollectionsValidatedForPermission = + UserPermissionUtils.validateDomainObjectPermissionsOrError( + actionCollectionFlux, + FieldName.ACTION, + permissionGroupIdsMono, + actionPermission.getEditPermission(), + AppsmithError.APPLICATION_NOT_FORKED_MISSING_PERMISSIONS); + Mono workspaceValidatedForCreateApplicationPermission = + UserPermissionUtils.validateDomainObjectPermissionsOrError( + workspaceFlux, + FieldName.WORKSPACE, + permissionGroupIdsMono, + workspacePermission.getApplicationCreatePermission(currentUser.getOrganizationId()), + AppsmithError.APPLICATION_NOT_FORKED_MISSING_PERMISSIONS); + Mono workspaceValidatedForCreateDatasourcePermission = + UserPermissionUtils.validateDomainObjectPermissionsOrError( + workspaceFlux, + FieldName.WORKSPACE, + permissionGroupIdsMono, + workspacePermission.getDatasourceCreatePermission(currentUser.getOrganizationId()), + AppsmithError.APPLICATION_NOT_FORKED_MISSING_PERMISSIONS); + + return Mono.when( + pagesValidatedForPermission, + actionsValidatedForPermission, + actionCollectionsValidatedForPermission, + workspaceValidatedForCreateApplicationPermission, + workspaceValidatedForCreateDatasourcePermission) + .thenReturn(TRUE); + }); } protected Mono isForkingEnabled(Mono applicationMono) { return applicationMono - .map(application -> Boolean.TRUE.equals(application.getForkingEnabled())) + .map(application -> TRUE.equals(application.getForkingEnabled())) .defaultIfEmpty(Boolean.FALSE); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ReactiveContextUtils.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ReactiveContextUtils.java new file mode 100644 index 000000000000..1f7db5cfaac1 --- /dev/null +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ReactiveContextUtils.java @@ -0,0 +1,20 @@ +package com.appsmith.server.helpers; + +import com.appsmith.server.domains.User; +import lombok.extern.slf4j.Slf4j; +import org.springframework.security.core.context.ReactiveSecurityContextHolder; +import org.springframework.security.core.context.SecurityContext; +import reactor.core.publisher.Mono; + +@Slf4j +public class ReactiveContextUtils { + public static Mono getCurrentUser() { + return ReactiveSecurityContextHolder.getContext() + .map(SecurityContext::getAuthentication) + .map(auth -> (User) auth.getPrincipal()) + .switchIfEmpty(Mono.defer(() -> { + log.error("No user found in the security context"); + return Mono.empty(); + })); + } +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCE.java index db905304a4a4..e22f2fa6fed6 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCE.java @@ -7,17 +7,17 @@ public interface EmailServiceHelperCE { Mono> enrichWithBrandParams(Map params, String origin); - String getForgotPasswordTemplate(); + String getForgotPasswordTemplate(String organizationId); - String getWorkspaceInviteTemplate(boolean isNewUser); + String getWorkspaceInviteTemplate(boolean isNewUser, String organizationId); - String getEmailVerificationTemplate(); + String getEmailVerificationTemplate(String organizationId); - String getAdminInstanceInviteTemplate(); + String getAdminInstanceInviteTemplate(String organizationId); - String getJoinInstanceCtaPrimaryText(); + String getJoinInstanceCtaPrimaryText(String organizationId); - String getSubjectJoinInstanceAsAdmin(String instanceName); + String getSubjectJoinInstanceAsAdmin(String instanceName, String organizationId); - String getSubjectJoinWorkspace(String workspaceName); + String getSubjectJoinWorkspace(String workspaceName, String organizationId); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCEImpl.java index 239be2322bc7..f97e6078000d 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/EmailServiceHelperCEImpl.java @@ -36,39 +36,39 @@ public Mono> enrichWithBrandParams(Map param } @Override - public String getForgotPasswordTemplate() { + public String getForgotPasswordTemplate(String organizationId) { return FORGOT_PASSWORD_TEMPLATE_CE; } @Override - public String getWorkspaceInviteTemplate(boolean isNewUser) { + public String getWorkspaceInviteTemplate(boolean isNewUser, String organizationId) { if (isNewUser) return INVITE_WORKSPACE_TEMPLATE_NEW_USER_CE; return INVITE_WORKSPACE_TEMPLATE_EXISTING_USER_CE; } @Override - public String getEmailVerificationTemplate() { + public String getEmailVerificationTemplate(String organizationId) { return EMAIL_VERIFICATION_EMAIL_TEMPLATE_CE; } @Override - public String getAdminInstanceInviteTemplate() { + public String getAdminInstanceInviteTemplate(String organizationId) { return INSTANCE_ADMIN_INVITE_EMAIL_TEMPLATE; } @Override - public String getJoinInstanceCtaPrimaryText() { + public String getJoinInstanceCtaPrimaryText(String organizationId) { return PRIMARY_LINK_TEXT_INVITE_TO_INSTANCE_CE; } @Override - public String getSubjectJoinInstanceAsAdmin(String instanceName) { + public String getSubjectJoinInstanceAsAdmin(String instanceName, String organizationId) { return INSTANCE_ADMIN_INVITE_EMAIL_SUBJECT; } @Override - public String getSubjectJoinWorkspace(String workspaceName) { + public String getSubjectJoinWorkspace(String workspaceName, String organizationId) { return INVITE_TO_WORKSPACE_EMAIL_SUBJECT_CE; } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/ImportArtifactPermissionProviderCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/ImportArtifactPermissionProviderCE.java index b5422273ff85..e27d49d38303 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/ImportArtifactPermissionProviderCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/ImportArtifactPermissionProviderCE.java @@ -116,24 +116,25 @@ public boolean hasEditPermission(Datasource datasource) { return hasPermission(datasourcePermission.getEditPermission(), datasource); } - public boolean canCreatePage(Application application) { + public boolean canCreatePage(Application application, String organizationId) { if (!permissionRequiredToCreatePage) { return true; } - return hasPermission(((ApplicationPermission) artifactPermission).getPageCreatePermission(), application); + return hasPermission( + ((ApplicationPermission) artifactPermission).getPageCreatePermission(organizationId), application); } - public boolean canCreateAction(NewPage page) { + public boolean canCreateAction(NewPage page, String organizationId) { if (!permissionRequiredToCreateAction) { return true; } - return hasPermission(contextPermission.getActionCreatePermission(), page); + return hasPermission(contextPermission.getActionCreatePermission(organizationId), page); } - public boolean canCreateDatasource(Workspace workspace) { + public boolean canCreateDatasource(Workspace workspace, String organizationId) { if (!permissionRequiredToCreateDatasource) { return true; } - return hasPermission(workspacePermission.getDatasourceCreatePermission(), workspace); + return hasPermission(workspacePermission.getDatasourceCreatePermission(organizationId), workspace); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/importable/artifactbased/ArtifactBasedImportableServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/importable/artifactbased/ArtifactBasedImportableServiceCE.java index 663fe760ca62..50cc6c5b37b1 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/importable/artifactbased/ArtifactBasedImportableServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/importable/artifactbased/ArtifactBasedImportableServiceCE.java @@ -40,7 +40,8 @@ default void populateBaseId(ImportingMetaDTO importingMetaDTO, Artifact artifact } } - void createNewResource(ImportingMetaDTO importingMetaDTO, T actionCollection, Context baseContext); + void createNewResource( + ImportingMetaDTO importingMetaDTO, T actionCollection, Context baseContext, String organizationId); default T getExistingEntityInCurrentBranchForImportedEntity( MappedImportableResourcesDTO mappedImportableResourcesDTO, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCEImpl.java index c0794040dd11..65c47e3a0f2b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/ImportServiceCEImpl.java @@ -193,10 +193,7 @@ public Mono importNewArtifactInWorkspaceFromJson( getArtifactBasedImportService(artifactExchangeJson); return permissionGroupRepository .getCurrentUserPermissionGroups() - .zipWhen(userPermissionGroup -> { - return Mono.just(contextBasedImportService.getImportArtifactPermissionProviderForImportingArtifact( - userPermissionGroup)); - }) + .zipWhen(contextBasedImportService::getImportArtifactPermissionProviderForImportingArtifact) .flatMap(tuple2 -> { Set userPermissionGroup = tuple2.getT1(); ImportArtifactPermissionProvider permissionProvider = tuple2.getT2(); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/artifactbased/ArtifactBasedImportServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/artifactbased/ArtifactBasedImportServiceCE.java index 7fd0e80d67b0..0ddb8743f8e9 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/artifactbased/ArtifactBasedImportServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/imports/internal/artifactbased/ArtifactBasedImportServiceCE.java @@ -19,7 +19,7 @@ public interface ArtifactBasedImportServiceCE< T extends Artifact, U extends ArtifactImportDTO, V extends ArtifactExchangeJson> { - ImportArtifactPermissionProvider getImportArtifactPermissionProviderForImportingArtifact( + Mono getImportArtifactPermissionProviderForImportingArtifact( Set userPermissions); ImportArtifactPermissionProvider getImportArtifactPermissionProviderForUpdatingArtifact( diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/newactions/base/NewActionServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/newactions/base/NewActionServiceCEImpl.java index fabbf4691a5b..862f554f5539 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/newactions/base/NewActionServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/newactions/base/NewActionServiceCEImpl.java @@ -35,6 +35,7 @@ import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.helpers.PluginExecutorHelper; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.newactions.helpers.NewActionHelper; import com.appsmith.server.newpages.base.NewPageService; import com.appsmith.server.plugins.base.PluginService; @@ -795,7 +796,9 @@ public ActionViewDTO generateActionViewDTO(NewAction action, ActionDTO actionDTO @Override public Mono deleteUnpublishedAction(String id) { - return deleteUnpublishedAction(id, actionPermission.getDeletePermission()); + return ReactiveContextUtils.getCurrentUser() + .flatMap(user -> + deleteUnpublishedAction(id, actionPermission.getDeletePermission(user.getOrganizationId()))); } @Override diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/newactions/importable/NewActionImportableServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/newactions/importable/NewActionImportableServiceCEImpl.java index f96d0200e0fc..65ad18c832f4 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/newactions/importable/NewActionImportableServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/newactions/importable/NewActionImportableServiceCEImpl.java @@ -11,6 +11,7 @@ import com.appsmith.server.domains.Artifact; import com.appsmith.server.domains.Context; import com.appsmith.server.domains.NewAction; +import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; import com.appsmith.server.dtos.ArtifactExchangeJson; import com.appsmith.server.dtos.ImportActionCollectionResultDTO; @@ -20,6 +21,7 @@ import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.helpers.ImportArtifactPermissionProvider; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.imports.importable.ImportableServiceCE; import com.appsmith.server.imports.importable.artifactbased.ArtifactBasedImportableService; import com.appsmith.server.newactions.base.NewActionService; @@ -305,11 +307,12 @@ private Mono createImportNewActionsMono( && mappedImportableResourcesDTO.getRefactoringNameReference() != null) { updateActionNameBeforeMerge(importedNewActionList, mappedImportableResourcesDTO); } - - return Mono.zip(actionsInCurrentArtifactMono, actionsInOtherBranchesMono) + Mono currentUserMono = ReactiveContextUtils.getCurrentUser(); + return Mono.zip(actionsInCurrentArtifactMono, actionsInOtherBranchesMono, currentUserMono) .flatMap(objects -> { Map actionsInCurrentArtifact = objects.getT1(); Map actionsInBranches = objects.getT2(); + String currentUserOrgId = objects.getT3().getOrganizationId(); // set the existing actions in the result DTO, // this will be required in next phases when we'll delete the outdated actions @@ -370,7 +373,7 @@ private Mono createImportNewActionsMono( } else { artifactBasedImportableService.createNewResource( - importingMetaDTO, newAction, baseContext); + importingMetaDTO, newAction, baseContext, currentUserOrgId); populateDomainMappedReferences(mappedImportableResourcesDTO, newAction); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/newactions/importable/applications/NewActionApplicationImportableServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/newactions/importable/applications/NewActionApplicationImportableServiceCEImpl.java index 5a36460e3510..57fb1ebfc948 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/newactions/importable/applications/NewActionApplicationImportableServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/newactions/importable/applications/NewActionApplicationImportableServiceCEImpl.java @@ -89,8 +89,9 @@ public Context updateContextInResource( } @Override - public void createNewResource(ImportingMetaDTO importingMetaDTO, NewAction newAction, Context baseContext) { - if (!importingMetaDTO.getPermissionProvider().canCreateAction((NewPage) baseContext)) { + public void createNewResource( + ImportingMetaDTO importingMetaDTO, NewAction newAction, Context baseContext, String organizationId) { + if (!importingMetaDTO.getPermissionProvider().canCreateAction((NewPage) baseContext, organizationId)) { throw new AppsmithException( AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.PAGE, ((NewPage) baseContext).getId()); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/newpages/base/NewPageServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/newpages/base/NewPageServiceCEImpl.java index 28a291853f2e..99529e6dcb7e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/newpages/base/NewPageServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/newpages/base/NewPageServiceCEImpl.java @@ -16,6 +16,7 @@ import com.appsmith.server.dtos.PageNameIdDTO; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.helpers.TextUtils; import com.appsmith.server.repositories.NewPageRepository; import com.appsmith.server.services.AnalyticsService; @@ -477,7 +478,8 @@ public Mono archiveByIdWithoutPermission(String id) { @Override public Mono archiveById(String id) { - return archiveByIdEx(id, pagePermission.getDeletePermission()); + return ReactiveContextUtils.getCurrentUser() + .flatMap(user -> archiveByIdEx(id, pagePermission.getDeletePermission(user.getOrganizationId()))); } @Override diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/newpages/importable/NewPageImportableServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/newpages/importable/NewPageImportableServiceCEImpl.java index eef9bbfe748a..6ca0b35be103 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/newpages/importable/NewPageImportableServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/newpages/importable/NewPageImportableServiceCEImpl.java @@ -7,6 +7,7 @@ import com.appsmith.server.domains.ApplicationPage; import com.appsmith.server.domains.Artifact; import com.appsmith.server.domains.NewPage; +import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; import com.appsmith.server.dtos.ApplicationJson; import com.appsmith.server.dtos.ArtifactExchangeJson; @@ -16,6 +17,7 @@ import com.appsmith.server.dtos.MappedImportableResourcesDTO; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.helpers.TextUtils; import com.appsmith.server.imports.importable.ImportableServiceCE; import com.appsmith.server.imports.importable.artifactbased.ArtifactBasedImportableService; @@ -434,8 +436,11 @@ private Flux importAndSavePages( existingSavedPages.stream() .filter(newPage -> !StringUtils.isEmpty(newPage.getGitSyncId())) .forEach(newPage -> savedPagesGitIdToPageMap.put(newPage.getGitSyncId(), newPage)); - - return Flux.fromIterable(pages).flatMap(newPage -> { + Flux currentUserFlux = + ReactiveContextUtils.getCurrentUser().cache().repeat(); + return Flux.fromIterable(pages).zipWith(currentUserFlux).flatMap(tuple -> { + NewPage newPage = tuple.getT1(); + User currentUser = tuple.getT2(); log.debug( "Importing page: {}", newPage.getUnpublishedPage().getName()); @@ -464,7 +469,9 @@ private Flux importAndSavePages( return newPageService.save(existingPage); } else { // check if user has permission to add new page to the application - if (!importingMetaDTO.getPermissionProvider().canCreatePage(application)) { + if (!importingMetaDTO + .getPermissionProvider() + .canCreatePage(application, currentUser.getOrganizationId())) { log.error( "User does not have permission to create page in application with id: {}", application.getId()); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionCEImpl.java index bfa29a1b8b75..8da537ced59c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/plugins/solutions/PluginTriggerSolutionCEImpl.java @@ -78,11 +78,6 @@ public Mono trigger( Mono pluginExecutorMono = pluginMono.flatMap(plugin -> pluginExecutorHelper.getPluginExecutor(Mono.just(plugin))); - // TODO: Flags are needed here for google sheets integration to support shared drive behind a flag - // Once thoroughly tested, this flag can be removed - Map featureFlagMap = - featureFlagService.getCachedOrganizationFeatureFlags().getFeatures(); - /* * Since there is no datasource provided, we are passing the Datasource Context connection and datasourceConfiguration as null. * We will leave the execution to respective plugin executor. @@ -91,9 +86,15 @@ public Mono trigger( Plugin plugin = pair.getT1(); PluginExecutor pluginExecutor = pair.getT2(); setHeadersToTriggerRequest(plugin, httpHeaders, triggerRequestDTO); - return setOrganizationAndInstanceId(triggerRequestDTO) - .flatMap(updatedTriggerRequestDTO -> ((PluginExecutor) pluginExecutor) - .triggerWithFlags(null, null, updatedTriggerRequestDTO, featureFlagMap)); + return setOrganizationAndInstanceId(triggerRequestDTO).flatMap(updatedTriggerRequestDTO -> { + // TODO: Flags are needed here for google sheets integration to support shared drive behind a + // flag once thoroughly tested, this flag can be removed + Map featureFlags = featureFlagService + .getCachedOrganizationFeatureFlags(updatedTriggerRequestDTO.getOrganizationId()) + .getFeatures(); + return ((PluginExecutor) pluginExecutor) + .triggerWithFlags(null, null, updatedTriggerRequestDTO, featureFlags); + }); }); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/EmailServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/EmailServiceImpl.java index 7e4d440d3ac2..ba8329a49a57 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/EmailServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/EmailServiceImpl.java @@ -7,7 +7,8 @@ @Service public class EmailServiceImpl extends EmailServiceCEImpl implements EmailService { - public EmailServiceImpl(EmailSender emailSender, EmailServiceHelper emailServiceHelper) { - super(emailSender, emailServiceHelper); + public EmailServiceImpl( + EmailSender emailSender, EmailServiceHelper emailServiceHelper, OrganizationService organizationService) { + super(emailSender, emailServiceHelper, organizationService); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationPageServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationPageServiceCEImpl.java index 3aa4688bd8f5..c9aca7715869 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationPageServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/ApplicationPageServiceCEImpl.java @@ -37,6 +37,7 @@ import com.appsmith.server.helpers.CommonGitFileUtils; import com.appsmith.server.helpers.DSLMigrationUtils; import com.appsmith.server.helpers.GitUtils; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.helpers.UserPermissionUtils; import com.appsmith.server.layouts.UpdateLayoutService; import com.appsmith.server.migrations.ApplicationVersion; @@ -158,8 +159,11 @@ public Mono createPage(PageDTO page) { } } - Mono applicationMono = applicationService - .findById(page.getApplicationId(), applicationPermission.getPageCreatePermission()) + Mono userMono = sessionUserService.getCurrentUser(); + + Mono applicationMono = userMono.flatMap(user -> applicationService.findById( + page.getApplicationId(), + applicationPermission.getPageCreatePermission(user.getOrganizationId()))) .switchIfEmpty(Mono.error(new AppsmithException( AppsmithError.NO_RESOURCE_FOUND, FieldName.APPLICATION, page.getApplicationId()))) .cache(); @@ -476,7 +480,7 @@ public Mono createApplication(Application application, String works public Mono setApplicationPolicies(Mono userMono, String workspaceId, Application application) { return userMono.flatMap(user -> { Mono workspaceMono = workspaceRepository - .findById(workspaceId, workspacePermission.getApplicationCreatePermission()) + .findById(workspaceId, workspacePermission.getApplicationCreatePermission(user.getOrganizationId())) .switchIfEmpty(Mono.error( new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.WORKSPACE, workspaceId))); @@ -506,8 +510,10 @@ public void generateAndSetPagePolicies(Application application, PageDTO page) { public Mono deleteApplication(String id) { log.debug("Archiving application with id: {}", id); - Mono applicationMono = applicationRepository - .findById(id, applicationPermission.getDeletePermission()) + Mono currentUserMono = ReactiveContextUtils.getCurrentUser().cache(); + Mono applicationMono = currentUserMono + .flatMap(currentUser -> applicationRepository.findById( + id, applicationPermission.getDeletePermission(currentUser.getOrganizationId()))) .switchIfEmpty( Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.APPLICATION, id))) .cache(); @@ -518,11 +524,15 @@ public Mono deleteApplication(String id) { * GitApplicationMetadata has a field called defaultApplicationId which refers to the main application * */ return applicationMono - .flatMapMany(application -> { + .zipWith(currentUserMono) + .flatMapMany(tuple2 -> { + Application application = tuple2.getT1(); GitArtifactMetadata gitData = application.getGitApplicationMetadata(); + User user = tuple2.getT2(); if (GitUtils.isArtifactConnectedToGit(application.getGitArtifactMetadata())) { return applicationService.findAllApplicationsByBaseApplicationId( - gitData.getDefaultArtifactId(), applicationPermission.getDeletePermission()); + gitData.getDefaultArtifactId(), + applicationPermission.getDeletePermission(user.getOrganizationId())); } return Flux.fromIterable(List.of(application)); }) @@ -554,12 +564,18 @@ public Mono deleteApplicationByResource(Application application) { } protected Mono deleteApplicationResources(Application application) { - return actionCollectionService - .archiveActionCollectionByApplicationId(application.getId(), actionPermission.getDeletePermission()) - .then(newActionService.archiveActionsByApplicationId( - application.getId(), actionPermission.getDeletePermission())) - .then(newPageService.archivePagesByApplicationId( - application.getId(), pagePermission.getDeletePermission())) + Mono currentUserOrgIdMono = ReactiveContextUtils.getCurrentUser() + .map(User::getOrganizationId) + .cache(); + return currentUserOrgIdMono + .flatMap(orgId -> actionCollectionService.archiveActionCollectionByApplicationId( + application.getId(), actionPermission.getDeletePermission(orgId))) + .then(currentUserOrgIdMono) + .flatMap(orgId -> newActionService.archiveActionsByApplicationId( + application.getId(), actionPermission.getDeletePermission(orgId))) + .then(currentUserOrgIdMono) + .flatMap(orgId -> newPageService.archivePagesByApplicationId( + application.getId(), pagePermission.getDeletePermission(orgId))) .then(themeService.archiveApplicationThemes(application)) .flatMap(applicationService::archive); } @@ -904,12 +920,15 @@ public Mono deleteUnpublishedPage( @Override public Mono deleteUnpublishedPage(String id) { - return deleteUnpublishedPageEx( - id, - pagePermission.getDeletePermission(), - applicationPermission.getReadPermission(), - actionPermission.getDeletePermission(), - actionPermission.getDeletePermission()); + return ReactiveContextUtils.getCurrentUser().flatMap(user -> { + String organizationId = user.getOrganizationId(); + return deleteUnpublishedPageEx( + id, + pagePermission.getDeletePermission(organizationId), + applicationPermission.getReadPermission(), + actionPermission.getDeletePermission(organizationId), + actionPermission.getDeletePermission(organizationId)); + }); } private Mono deleteUnpublishedPageEx( @@ -1478,12 +1497,13 @@ private Mono validateDatasourcesForCreatePermission(Mono a return datasourceRepository.setUserPermissionsInObject(datasource); })); - return UserPermissionUtils.validateDomainObjectPermissionsOrError( + return ReactiveContextUtils.getCurrentUser() + .flatMap(user -> UserPermissionUtils.validateDomainObjectPermissionsOrError( datasourceFlux, FieldName.DATASOURCE, permissionGroupService.getSessionUserPermissionGroupIds(), - datasourcePermission.getActionCreatePermission(), - AppsmithError.APPLICATION_NOT_CLONED_MISSING_PERMISSIONS) + datasourcePermission.getActionCreatePermission(user.getOrganizationId()), + AppsmithError.APPLICATION_NOT_CLONED_MISSING_PERMISSIONS)) .thenReturn(Boolean.TRUE); } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/EmailServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/EmailServiceCEImpl.java index dddb54db6656..f2fbf61c0dd6 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/EmailServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/EmailServiceCEImpl.java @@ -5,7 +5,9 @@ import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; import com.appsmith.server.helpers.EmailServiceHelper; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.notifications.EmailSender; +import com.appsmith.server.services.OrganizationService; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; @@ -20,25 +22,35 @@ @Component public class EmailServiceCEImpl implements EmailServiceCE { private final EmailSender emailSender; - private final EmailServiceHelper emailServiceHelper; + private final OrganizationService organizationService; - public EmailServiceCEImpl(EmailSender emailSender, EmailServiceHelper emailServiceHelper) { + public EmailServiceCEImpl( + EmailSender emailSender, EmailServiceHelper emailServiceHelper, OrganizationService organizationService) { this.emailSender = emailSender; this.emailServiceHelper = emailServiceHelper; + this.organizationService = organizationService; } @Override public Mono sendForgotPasswordEmail(String email, String resetUrl, String originHeader) { Map params = new HashMap<>(); params.put(RESET_URL, resetUrl); + // TODO @CloudBilling: Considering there won't be a active session for the user, we can't get the + // organizationId from the session. We need to get the orgId based on the hostname, for now resorting to + // default org id till then. return emailServiceHelper .enrichWithBrandParams(params, originHeader) - .flatMap(updatedParams -> emailSender.sendMail( - email, - String.format(FORGOT_PASSWORD_EMAIL_SUBJECT, updatedParams.get(INSTANCE_NAME)), - emailServiceHelper.getForgotPasswordTemplate(), - updatedParams)); + .zipWith(organizationService.getDefaultOrganizationId()) + .flatMap(tuple2 -> { + Map updatedParams = tuple2.getT1(); + String organizationId = tuple2.getT2(); + return emailSender.sendMail( + email, + String.format(FORGOT_PASSWORD_EMAIL_SUBJECT, updatedParams.get(INSTANCE_NAME)), + emailServiceHelper.getForgotPasswordTemplate(organizationId), + updatedParams); + }); } @Override @@ -55,16 +67,22 @@ public Mono sendInviteUserToWorkspaceEmail( originHeader, URLEncoder.encode(invitedUser.getUsername().toLowerCase(), StandardCharsets.UTF_8)) : originHeader; - String emailSubject = emailServiceHelper.getSubjectJoinWorkspace(workspaceInvitedTo.getName()); Map params = getInviteToWorkspaceEmailParams( workspaceInvitedTo, invitingUser, inviteUrl, assignedPermissionGroup.getName(), isNewUser); return emailServiceHelper .enrichWithBrandParams(params, originHeader) - .flatMap(updatedParams -> emailSender.sendMail( - invitedUser.getEmail(), - emailSubject, - emailServiceHelper.getWorkspaceInviteTemplate(isNewUser), - updatedParams)); + .zipWith(ReactiveContextUtils.getCurrentUser()) + .flatMap(tuple2 -> { + Map updatedParams = tuple2.getT1(); + String organizationId = tuple2.getT2().getOrganizationId(); + String emailSubject = + emailServiceHelper.getSubjectJoinWorkspace(workspaceInvitedTo.getName(), organizationId); + return emailSender.sendMail( + invitedUser.getEmail(), + emailSubject, + emailServiceHelper.getWorkspaceInviteTemplate(isNewUser, organizationId), + updatedParams); + }); } @Override @@ -76,7 +94,7 @@ public Mono sendEmailVerificationEmail(User user, String verificationUR .flatMap(updatedParams -> emailSender.sendMail( user.getEmail(), EMAIL_VERIFICATION_EMAIL_SUBJECT, - emailServiceHelper.getEmailVerificationTemplate(), + emailServiceHelper.getEmailVerificationTemplate(user.getOrganizationId()), updatedParams)); } @@ -92,21 +110,26 @@ public Mono sendInstanceAdminInviteEmail( : originHeader; params.put(PRIMARY_LINK_URL, inviteUrl); - String primaryLinkText = emailServiceHelper.getJoinInstanceCtaPrimaryText(); - params.put(PRIMARY_LINK_TEXT, primaryLinkText); - + // In what scenario will the inviting user be null? if (invitingUser != null) { params.put(INVITER_FIRST_NAME, StringUtils.defaultIfEmpty(invitingUser.getName(), invitingUser.getEmail())); } - return emailServiceHelper.enrichWithBrandParams(params, originHeader).flatMap(updatedParams -> { - String instanceName = updatedParams.get(INSTANCE_NAME); - String subject = emailServiceHelper.getSubjectJoinInstanceAsAdmin(instanceName); - return emailSender.sendMail( - invitedUser.getEmail(), - subject, - emailServiceHelper.getAdminInstanceInviteTemplate(), - updatedParams); - }); + return emailServiceHelper + .enrichWithBrandParams(params, originHeader) + .zipWith(ReactiveContextUtils.getCurrentUser()) + .flatMap(tuple2 -> { + Map updatedParams = tuple2.getT1(); + String organizationId = tuple2.getT2().getOrganizationId(); + String instanceName = updatedParams.get(INSTANCE_NAME); + String subject = emailServiceHelper.getSubjectJoinInstanceAsAdmin(instanceName, organizationId); + String primaryLinkText = emailServiceHelper.getJoinInstanceCtaPrimaryText(organizationId); + params.put(PRIMARY_LINK_TEXT, primaryLinkText); + return emailSender.sendMail( + invitedUser.getEmail(), + subject, + emailServiceHelper.getAdminInstanceInviteTemplate(organizationId), + updatedParams); + }); } private Map getInviteToWorkspaceEmailParams( @@ -115,6 +138,7 @@ private Map getInviteToWorkspaceEmailParams( if (workspace != null) { params.put(INVITER_WORKSPACE_NAME, workspace.getName()); } + // In what scenario will the inviter be null? if (inviter != null) { params.put(INVITER_FIRST_NAME, StringUtils.defaultIfEmpty(inviter.getName(), inviter.getEmail())); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java index cce3d3402deb..4b8ea2bb4cce 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCE.java @@ -42,5 +42,5 @@ Mono getAllRemoteFeaturesForOrganizationAndUpdateFeatureFlagsWithP Mono checkAndExecuteMigrationsForOrganizationFeatureFlags(Organization organization); - CachedFeatures getCachedOrganizationFeatureFlags(); + CachedFeatures getCachedOrganizationFeatureFlags(String organizationId); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java index b8362f034293..fa6750b6debc 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/FeatureFlagServiceCEImpl.java @@ -13,7 +13,6 @@ import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.SessionUserService; import com.appsmith.server.services.UserIdentifierService; -import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.util.StringUtils; @@ -40,9 +39,7 @@ public class FeatureFlagServiceCEImpl implements FeatureFlagServiceCE { private final FeatureFlagMigrationHelper featureFlagMigrationHelper; private static final long FEATURE_FLAG_CACHE_TIME_MIN = 120; - // TODO @CloudBilling: Remove once all the helper methods consuming @FeatureFlagged are converted to reactive - @Getter - private CachedFeatures cachedOrganizationFeatureFlags; + private Map cachedOrganizationFeatureFlags = new HashMap<>(); /** * This function checks if the feature is enabled for the current user. In case the user object is not present, @@ -185,7 +182,7 @@ public Mono> getOrganizationFeatures(String organizationId) return cacheableFeatureFlagHelper .fetchCachedOrganizationFeatures(organizationId) .map(cachedFeatures -> { - cachedOrganizationFeatureFlags = cachedFeatures; + cachedOrganizationFeatureFlags.put(organizationId, cachedFeatures); return cachedFeatures.getFeatures(); }) .switchIfEmpty(Mono.just(new HashMap<>())); @@ -200,4 +197,8 @@ public Mono> getOrganizationFeatures(String organizationId) public Mono checkAndExecuteMigrationsForOrganizationFeatureFlags(Organization organization) { return organizationService.checkAndExecuteMigrationsForOrganizationFeatureFlags(organization); } + + public CachedFeatures getCachedOrganizationFeatureFlags(String organizationId) { + return this.cachedOrganizationFeatureFlags.getOrDefault(organizationId, new CachedFeatures()); + } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/LayoutActionServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/LayoutActionServiceCEImpl.java index 0539352ff1fc..e843e9aa3e3f 100755 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/LayoutActionServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/LayoutActionServiceCEImpl.java @@ -12,11 +12,13 @@ import com.appsmith.server.domains.Layout; import com.appsmith.server.domains.NewAction; import com.appsmith.server.domains.NewPage; +import com.appsmith.server.domains.User; import com.appsmith.server.dtos.ActionMoveDTO; import com.appsmith.server.dtos.CreateActionMetaDTO; import com.appsmith.server.dtos.PageDTO; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.layouts.UpdateLayoutService; import com.appsmith.server.newactions.base.NewActionService; import com.appsmith.server.newpages.base.NewPageService; @@ -145,8 +147,11 @@ public Mono moveAction(ActionMoveDTO actionMoveDTO) { final String destinationPageId = actionMoveDTO.getDestinationPageId(); action.setPageId(destinationPageId); - Mono destinationPageMono = newPageService - .findById(destinationPageId, pagePermission.getActionCreatePermission()) + Mono currentUserMono = ReactiveContextUtils.getCurrentUser().cache(); + + Mono destinationPageMono = currentUserMono + .flatMap(user -> newPageService.findById( + destinationPageId, pagePermission.getActionCreatePermission(user.getOrganizationId()))) .switchIfEmpty(Mono.error( new AppsmithException(AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.PAGE, destinationPageId))); @@ -186,9 +191,10 @@ public Mono moveAction(ActionMoveDTO actionMoveDTO) { .collect(toSet()); }) // fetch the unpublished destination page - .then(newPageService.findPageById( + .then(currentUserMono) + .flatMap(user -> newPageService.findPageById( actionMoveDTO.getDestinationPageId(), - pagePermission.getActionCreatePermission(), + pagePermission.getActionCreatePermission(user.getOrganizationId()), false)) .flatMap(page -> { if (page.getLayouts() == null) { @@ -339,11 +345,13 @@ public Mono createSingleAction(ActionDTO actionDTO, Boolean isJsActio return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.PAGE_ID)); } - AclPermission aclPermission = - isJsAction ? pagePermission.getReadPermission() : pagePermission.getActionCreatePermission(); - - return newPageService - .findById(actionDTO.getPageId(), aclPermission) + return ReactiveContextUtils.getCurrentUser() + .flatMap(currentUser -> { + AclPermission aclPermission = isJsAction + ? pagePermission.getReadPermission() + : pagePermission.getActionCreatePermission(currentUser.getOrganizationId()); + return newPageService.findById(actionDTO.getPageId(), aclPermission); + }) .switchIfEmpty(Mono.error( new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.PAGE, actionDTO.getPageId()))) .flatMap(newPage -> { @@ -425,15 +433,20 @@ protected Mono validateAndGenerateActionDomainBasedOnContext( if (!StringUtils.hasLength(action.getPageId())) { return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.PAGE_ID)); } - // If the action is a JS action, then we don't need to validate the page. Fetch the page with read. - // Else fetch the page with create action permission to ensure that the user has the right to create an action - AclPermission aclPermission = - isJsAction ? pagePermission.getReadPermission() : pagePermission.getActionCreatePermission(); Mono pageMono = newPage != null ? Mono.just(newPage) - : newPageService - .findById(action.getPageId(), aclPermission) + : ReactiveContextUtils.getCurrentUser() + .flatMap(currentUser -> { + // If the action is a JS action, then we don't need to validate the page. Fetch the page + // with read. + // Else fetch the page with create action permission to ensure that the user has the right + // to create an action + AclPermission aclPermission = isJsAction + ? pagePermission.getReadPermission() + : pagePermission.getActionCreatePermission(currentUser.getOrganizationId()); + return newPageService.findById(action.getPageId(), aclPermission); + }) .name(GET_PAGE_BY_ID) .tap(Micrometer.observation(observationRegistry)) .switchIfEmpty(Mono.error(new AppsmithException( diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/LayoutCollectionServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/LayoutCollectionServiceCEImpl.java index 5a31f5197d6d..1c97798cfe07 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/LayoutCollectionServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/LayoutCollectionServiceCEImpl.java @@ -8,11 +8,13 @@ import com.appsmith.server.domains.ActionCollection.Fields; import com.appsmith.server.domains.Layout; import com.appsmith.server.domains.NewPage; +import com.appsmith.server.domains.User; import com.appsmith.server.dtos.ActionCollectionDTO; import com.appsmith.server.dtos.ActionCollectionMoveDTO; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.helpers.ContextTypeUtils; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.helpers.ce.bridge.Bridge; import com.appsmith.server.helpers.ce.bridge.BridgeUpdate; import com.appsmith.server.layouts.UpdateLayoutService; @@ -118,8 +120,9 @@ private void validateApplicationId(ActionCollectionDTO collectionDTO) { protected Mono checkIfNameAllowedBasedOnContext(ActionCollectionDTO collectionDTO) { final String pageId = collectionDTO.getPageId(); - Mono pageMono = newPageService - .findById(pageId, pagePermission.getActionCreatePermission()) + Mono pageMono = ReactiveContextUtils.getCurrentUser() + .flatMap(user -> newPageService.findById( + pageId, pagePermission.getActionCreatePermission(user.getOrganizationId()))) .switchIfEmpty( Mono.error(new AppsmithException(AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.PAGE, pageId))) .cache(); @@ -156,8 +159,9 @@ protected Mono validateAndCreateActionCollectionDomain(ActionC ActionCollection actionCollection = new ActionCollection(); actionCollection.setUnpublishedCollection(collectionDTO); - return newPageService - .findById(collectionDTO.getPageId(), pagePermission.getActionCreatePermission()) + return ReactiveContextUtils.getCurrentUser() + .flatMap(user -> newPageService.findById( + collectionDTO.getPageId(), pagePermission.getActionCreatePermission(user.getOrganizationId()))) .map(branchedPage -> { actionCollection.setRefType(branchedPage.getRefType()); actionCollection.setRefName(branchedPage.getRefName()); @@ -179,9 +183,12 @@ protected Mono validateAndCreateActionCollectionDomain(ActionC public Mono moveCollection(ActionCollectionMoveDTO actionCollectionMoveDTO) { final String collectionId = actionCollectionMoveDTO.getCollectionId(); final String destinationPageId = actionCollectionMoveDTO.getDestinationPageId(); + Mono currentUserMono = ReactiveContextUtils.getCurrentUser().cache(); - Mono destinationPageMono = newPageService - .findById(actionCollectionMoveDTO.getDestinationPageId(), pagePermission.getActionCreatePermission()) + Mono destinationPageMono = currentUserMono + .flatMap(user -> newPageService.findById( + actionCollectionMoveDTO.getDestinationPageId(), + pagePermission.getActionCreatePermission(user.getOrganizationId()))) .switchIfEmpty(Mono.error( new AppsmithException(AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.PAGE, destinationPageId))) .cache(); @@ -241,27 +248,35 @@ public Mono moveCollection(ActionCollectionMoveDTO actionCo }) .collect(toSet()); }) - // fetch the unpublished destination page - .then(newPageService.findPageById( - actionCollectionMoveDTO.getDestinationPageId(), - pagePermission.getActionCreatePermission(), - false)) - .flatMap(page -> { - if (page.getLayouts() == null) { - return Mono.empty(); - } - - // 3. Run updateLayout on the new page. - return Flux.fromIterable(page.getLayouts()) - .flatMap(layout -> { - layout.setDsl(updateLayoutService.unescapeMongoSpecialCharacters(layout)); - return updateLayoutService.updateLayout( - page.getId(), page.getApplicationId(), layout.getId(), layout); - }) - .collect(toSet()); - }) - // 4. Return the saved action. - .thenReturn(savedCollection); + .then(currentUserMono) + .flatMap(user -> + // fetch the unpublished destination page + newPageService + .findPageById( + actionCollectionMoveDTO.getDestinationPageId(), + pagePermission.getActionCreatePermission(user.getOrganizationId()), + false) + .flatMap(page -> { + if (page.getLayouts() == null) { + return Mono.empty(); + } + + // 3. Run updateLayout on the new page. + return Flux.fromIterable(page.getLayouts()) + .flatMap(layout -> { + layout.setDsl( + updateLayoutService.unescapeMongoSpecialCharacters( + layout)); + return updateLayoutService.updateLayout( + page.getId(), + page.getApplicationId(), + layout.getId(), + layout); + }) + .collect(toSet()); + }) + // 4. Return the saved action. + .thenReturn(savedCollection)); }); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCE.java index ad976da77ee0..e3e44ea8e48c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCE.java @@ -22,7 +22,7 @@ Mono updatePermissionGroupForMember( Mono>> getWorkspaceMembers(Set workspaceIds); - Boolean isLastAdminRoleEntity(PermissionGroup permissionGroup); + Mono isLastAdminRoleEntity(PermissionGroup permissionGroup); Mono> getUserWorkspacesByRecentlyUsedOrder(String hostname); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCEImpl.java index 239aae4c7da8..e7fdc15d5649 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/UserWorkspaceServiceCEImpl.java @@ -165,11 +165,14 @@ public Mono updatePermissionGroupForMember( .switchIfEmpty(Mono.error(new AppsmithException( AppsmithError.ACTION_IS_NOT_AUTHORIZED, "Change permissionGroup of a member"))) .single() - .flatMap(permissionGroup -> { - if (this.isLastAdminRoleEntity(permissionGroup)) { - return Mono.error(new AppsmithException(AppsmithError.REMOVE_LAST_WORKSPACE_ADMIN_ERROR)); + .zipWhen(this::isLastAdminRoleEntity) + .map(tuple2 -> { + PermissionGroup permissionGroup = tuple2.getT1(); + boolean isLastAdminRoleEntity = tuple2.getT2(); + if (isLastAdminRoleEntity) { + throw new AppsmithException(AppsmithError.REMOVE_LAST_WORKSPACE_ADMIN_ERROR); } - return Mono.just(permissionGroup); + return permissionGroup; }); /* @@ -383,9 +386,9 @@ protected Flux getPermissionGroupsForWorkspace(String workspace } @Override - public Boolean isLastAdminRoleEntity(PermissionGroup permissionGroup) { - return permissionGroup.getName().startsWith(FieldName.ADMINISTRATOR) - && permissionGroup.getAssignedToUserIds().size() == 1; + public Mono isLastAdminRoleEntity(PermissionGroup permissionGroup) { + return Mono.just(permissionGroup.getName().startsWith(FieldName.ADMINISTRATOR) + && permissionGroup.getAssignedToUserIds().size() == 1); } /** diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCEImpl.java index cdcd6187a86f..92112b0d25ea 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/WorkspaceServiceCEImpl.java @@ -16,6 +16,7 @@ import com.appsmith.server.dtos.WorkspacePluginStatus; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.helpers.TextUtils; import com.appsmith.server.helpers.WorkspaceServiceHelper; import com.appsmith.server.repositories.ApplicationRepository; @@ -166,14 +167,14 @@ public Mono create(Workspace workspace, User user, Boolean isDefault) Not using it right now because of circular dependency b/w workspaceService and pluginService Also, since all our deployments are single node, this logic will still work */ - .flatMap(org -> pluginRepository + .flatMap(validatedWorkspace -> pluginRepository .findByDefaultInstall(true) .filter(plugin -> plugin.getId() != null) .map(obj -> new WorkspacePlugin(obj.getId(), WorkspacePluginStatus.FREE)) .collect(Collectors.toSet()) .map(pluginList -> { - org.setPlugins(pluginList); - return org; + validatedWorkspace.setPlugins(pluginList); + return validatedWorkspace; })) // Save the workspace in the db .flatMap(repository::save) @@ -571,8 +572,9 @@ public Mono archiveById(String workspaceId) { return applicationRepository.countByWorkspaceId(workspaceId).flatMap(appCount -> { if (appCount == 0) { // no application found under this workspace // fetching the workspace first to make sure user has permission to archive - return repository - .findById(workspaceId, workspacePermission.getDeletePermission()) + return ReactiveContextUtils.getCurrentUser() + .flatMap(user -> repository.findById( + workspaceId, workspacePermission.getDeletePermission(user.getOrganizationId()))) .switchIfEmpty(Mono.error(new AppsmithException( AppsmithError.NO_RESOURCE_FOUND, FieldName.WORKSPACE, workspaceId))) .flatMap(workspace -> { diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java index 16d63cd7188b..a712ab29ced0 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCEImpl.java @@ -38,6 +38,7 @@ import com.appsmith.server.helpers.DatasourceAnalyticsUtils; import com.appsmith.server.helpers.DateUtils; import com.appsmith.server.helpers.PluginExecutorHelper; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.newactions.base.NewActionService; import com.appsmith.server.newpages.base.NewPageService; import com.appsmith.server.plugins.base.PluginService; @@ -254,7 +255,6 @@ private Mono getTrueEnvironmentId( private Mono populateExecuteActionDTO(ExecuteActionDTO executeActionDTO, NewAction newAction) { Mono instanceIdMono = configService.getInstanceId(); Mono defaultOrganizationIdMono = organizationService.getDefaultOrganizationId(); - Mono systemInfoPopulatedExecuteActionDTOMono = actionExecutionSolutionHelper.populateExecuteActionDTOWithSystemInfo(executeActionDTO); @@ -755,17 +755,20 @@ protected Mono verifyDatasourceAndMakeRequest( .tag("plugin", plugin.getPackageName()) .name(ACTION_EXECUTION_DATASOURCE_CONTEXT) .tap(Micrometer.observation(observationRegistry))) - .flatMap(tuple2 -> { - DatasourceStorage datasourceStorage1 = tuple2.getT1(); - DatasourceContext resourceContext = tuple2.getT2(); + .zipWith(ReactiveContextUtils.getCurrentUser()) + .flatMap(objects -> { + DatasourceStorage datasourceStorage1 = objects.getT1().getT1(); + DatasourceContext resourceContext = objects.getT1().getT2(); + String organizationId = objects.getT2().getOrganizationId(); // Now that we have the context (connection details), execute the action. Instant requestedAt = Instant.now(); - Map features = featureFlagService.getCachedOrganizationFeatureFlags() != null - ? featureFlagService - .getCachedOrganizationFeatureFlags() - .getFeatures() - : Collections.emptyMap(); + Map features = + featureFlagService.getCachedOrganizationFeatureFlags(organizationId) != null + ? featureFlagService + .getCachedOrganizationFeatureFlags(organizationId) + .getFeatures() + : Collections.emptyMap(); // TODO: Flags are needed here for google sheets integration to support shared drive behind a flag // Once thoroughly tested, this flag can be removed diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionPermissionCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionPermissionCE.java index 216e1b4c3923..5aba47b623f7 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionPermissionCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionPermissionCE.java @@ -3,7 +3,7 @@ import com.appsmith.server.acl.AclPermission; public interface ActionPermissionCE { - AclPermission getDeletePermission(); + AclPermission getDeletePermission(String organizationId); AclPermission getExecutePermission(); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionPermissionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionPermissionCEImpl.java index aeb1b9900f4f..154a987d5e8d 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionPermissionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ActionPermissionCEImpl.java @@ -1,6 +1,7 @@ package com.appsmith.server.solutions.ce; import com.appsmith.server.acl.AclPermission; +import org.jetbrains.annotations.NotNull; import org.springframework.stereotype.Component; import static java.lang.Boolean.TRUE; @@ -28,7 +29,7 @@ public AclPermission getExecutePermission() { } @Override - public AclPermission getDeletePermission() { + public AclPermission getDeletePermission(@NotNull String organizationId) { return AclPermission.MANAGE_ACTIONS; } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ApplicationPermissionCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ApplicationPermissionCE.java index 2b1620ed4d13..7f526e0b984f 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ApplicationPermissionCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ApplicationPermissionCE.java @@ -9,7 +9,7 @@ public interface ApplicationPermissionCE extends ArtifactPermission { AclPermission getCanCommentPermission(); - AclPermission getPageCreatePermission(); + AclPermission getPageCreatePermission(String organizationId); AclPermission getManageProtectedBranchPermission(); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ApplicationPermissionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ApplicationPermissionCEImpl.java index e0363cf739b7..890132daf05b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ApplicationPermissionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ApplicationPermissionCEImpl.java @@ -32,7 +32,7 @@ public AclPermission getExportPermission() { } @Override - public AclPermission getDeletePermission() { + public AclPermission getDeletePermission(String organizationId) { return AclPermission.MANAGE_APPLICATIONS; } @@ -47,7 +47,7 @@ public AclPermission getCanCommentPermission() { } @Override - public AclPermission getPageCreatePermission() { + public AclPermission getPageCreatePermission(String organizationId) { return AclPermission.MANAGE_APPLICATIONS; } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/AuthenticationServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/AuthenticationServiceCEImpl.java index 8d4909cc4b8f..e8a9dc3d0962 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/AuthenticationServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/AuthenticationServiceCEImpl.java @@ -26,6 +26,7 @@ import com.appsmith.server.domains.Config; import com.appsmith.server.domains.NewPage; import com.appsmith.server.domains.Plugin; +import com.appsmith.server.domains.User; import com.appsmith.server.dtos.AuthorizationCodeCallbackDTO; import com.appsmith.server.dtos.IntegrationDTO; import com.appsmith.server.dtos.RequestAppsmithTokenDTO; @@ -33,6 +34,7 @@ import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.helpers.InstanceConfigHelper; import com.appsmith.server.helpers.PluginExecutorHelper; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.helpers.RedirectHelper; import com.appsmith.server.newpages.base.NewPageService; import com.appsmith.server.plugins.base.PluginService; @@ -422,10 +424,13 @@ public Mono getAppsmithToken( new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.DATASOURCE, datasourceId))) .flatMap(this::validateRequiredFieldsForGenericOAuth2) .flatMap(datasource -> Mono.zip( - configService.getInstanceId(), pluginService.findById(datasource.getPluginId())) + configService.getInstanceId(), + pluginService.findById(datasource.getPluginId()), + ReactiveContextUtils.getCurrentUser()) .flatMap(tuple -> { String instanceId = tuple.getT1(); Plugin plugin = tuple.getT2(); + User currentUser = tuple.getT3(); IntegrationDTO integrationDTO = new IntegrationDTO(); integrationDTO.setInstallationKey(instanceId); integrationDTO.setImportForGit(importForGit); @@ -444,7 +449,10 @@ public Mono getAppsmithToken( requestAppsmithTokenDTO.getContextId(), requestAppsmithTokenDTO.getContextType()) .map(context -> associateIntegrationDTOWithContext( - integrationDTO, context, requestAppsmithTokenDTO.getContextType())); + integrationDTO, + context, + requestAppsmithTokenDTO.getContextType(), + currentUser.getOrganizationId())); })) .flatMap(integrationDTO -> { Mono clientResponseMono = WebClientUtils.create( @@ -562,7 +570,10 @@ protected Mono getContext(String branchedContextId, Creato } protected IntegrationDTO associateIntegrationDTOWithContext( - IntegrationDTO integrationDTO, BaseDomain baseDomain, CreatorContextType contextType) { + IntegrationDTO integrationDTO, + BaseDomain baseDomain, + CreatorContextType contextType, + String organizationId) { NewPage pageRedirectionDTO = (NewPage) baseDomain; integrationDTO.setPageId(pageRedirectionDTO.getBaseIdOrFallback()); integrationDTO.setApplicationId(pageRedirectionDTO.getApplicationId()); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ContextPermissionCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ContextPermissionCE.java index 8539e4053895..fdc3f322b18a 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ContextPermissionCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/ContextPermissionCE.java @@ -4,11 +4,9 @@ public interface ContextPermissionCE { - AclPermission getDeletePermission(); - AclPermission getEditPermission(); - default AclPermission getActionCreatePermission() { + default AclPermission getActionCreatePermission(String organizationId) { return null; } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/CreateDBTablePageSolutionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/CreateDBTablePageSolutionCEImpl.java index dbee3a087a03..dc01febde672 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/CreateDBTablePageSolutionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/CreateDBTablePageSolutionCEImpl.java @@ -32,6 +32,7 @@ import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.helpers.PluginExecutorHelper; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.layouts.UpdateLayoutService; import com.appsmith.server.migrations.JsonSchemaMigration; import com.appsmith.server.newpages.base.NewPageService; @@ -228,8 +229,9 @@ public Mono createPageFromDBTable( // Fetch branched applicationId if connected to git Mono pageMono = getOrCreatePage(branchedApplicationId, branchedPageId, tableName); - Mono datasourceStorageMono = datasourceService - .findById(datasourceId, datasourcePermission.getActionCreatePermission()) + Mono datasourceStorageMono = ReactiveContextUtils.getCurrentUser() + .flatMap(user -> datasourceService.findById( + datasourceId, datasourcePermission.getActionCreatePermission(user.getOrganizationId()))) .switchIfEmpty(Mono.error( new AppsmithException(AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.DATASOURCE, datasourceId))) .flatMap(datasource -> datasourceStorageService.findByDatasourceAndEnvironmentIdForExecution( @@ -500,8 +502,9 @@ private Mono getOrCreatePage(String branchedApplicationId, String branc }); } - return applicationService - .findById(branchedApplicationId, applicationPermission.getPageCreatePermission()) + return ReactiveContextUtils.getCurrentUser() + .flatMap(user -> applicationService.findById( + branchedApplicationId, applicationPermission.getPageCreatePermission(user.getOrganizationId()))) .switchIfEmpty(Mono.error(new AppsmithException( AppsmithError.NO_RESOURCE_FOUND, FieldName.APPLICATION, branchedApplicationId))) .flatMap(branchedApplication -> newPageService diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourcePermissionCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourcePermissionCE.java index 317baaa97c43..ccc05674c85b 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourcePermissionCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourcePermissionCE.java @@ -3,9 +3,9 @@ import com.appsmith.server.acl.AclPermission; public interface DatasourcePermissionCE { - AclPermission getDeletePermission(); + AclPermission getDeletePermission(String organizationId); AclPermission getExecutePermission(); - AclPermission getActionCreatePermission(); + AclPermission getActionCreatePermission(String organizationId); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourcePermissionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourcePermissionCEImpl.java index 519ca8029a85..f57382a9075d 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourcePermissionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourcePermissionCEImpl.java @@ -18,7 +18,7 @@ public AclPermission getExportPermission(boolean isGitSync, boolean exportWithCo } @Override - public AclPermission getDeletePermission() { + public AclPermission getDeletePermission(String organizationId) { return AclPermission.MANAGE_DATASOURCES; } @@ -33,7 +33,7 @@ public AclPermission getExecutePermission() { } @Override - public AclPermission getActionCreatePermission() { + public AclPermission getActionCreatePermission(String organizationId) { return AclPermission.MANAGE_DATASOURCES; } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceStructureSolutionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceStructureSolutionCEImpl.java index 19fec9feea6e..d726400d5e14 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceStructureSolutionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceStructureSolutionCEImpl.java @@ -18,6 +18,7 @@ import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.helpers.PluginExecutorHelper; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.plugins.base.PluginService; import com.appsmith.server.services.AnalyticsService; import com.appsmith.server.services.DatasourceContextService; @@ -182,8 +183,9 @@ public Mono getStructure(DatasourceStorage datasourceStorag @Override public Mono getSchemaPreviewData( String datasourceId, String environmentId, Template queryTemplate) { - return datasourceService - .findById(datasourceId, datasourcePermission.getActionCreatePermission()) + return ReactiveContextUtils.getCurrentUser() + .flatMap(user -> datasourceService.findById( + datasourceId, datasourcePermission.getActionCreatePermission(user.getOrganizationId()))) .zipWhen(datasource -> datasourceService.getTrueEnvironmentId( datasource.getWorkspaceId(), environmentId, diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceTriggerSolutionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceTriggerSolutionCEImpl.java index b934b4d0841b..de24bd474291 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceTriggerSolutionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/DatasourceTriggerSolutionCEImpl.java @@ -108,26 +108,32 @@ public Mono trigger( final PluginExecutor pluginExecutor = tuple.getT3(); final Datasource datasource = tuple.getT4(); - // TODO: Flags are needed here for google sheets integration to support shared drive behind a flag - // Once thoroughly tested, this flag can be removed - Map featureFlagMap = featureFlagService.getCachedOrganizationFeatureFlags() != null - ? featureFlagService - .getCachedOrganizationFeatureFlags() - .getFeatures() - : Collections.emptyMap(); - return datasourceContextService .getDatasourceContext(datasourceStorage, plugin) // Now that we have the context (connection details), execute the action. // datasource remains unevaluated for datasource of DBAuth Type Authentication, // However the context comes from evaluated datasource. .flatMap(resourceContext -> populateTriggerRequestDto(triggerRequestDTO, datasource) - .flatMap(updatedTriggerRequestDTO -> ((PluginExecutor) pluginExecutor) - .triggerWithFlags( - resourceContext.getConnection(), - datasourceStorage.getDatasourceConfiguration(), - updatedTriggerRequestDTO, - featureFlagMap))); + .flatMap(updatedTriggerRequestDTO -> { + String organizationId = updatedTriggerRequestDTO.getOrganizationId(); + // TODO: Flags are needed here for google sheets integration to support shared + // drive behind a flag + // Once thoroughly tested, this flag can be removed + Map featureFlagMap = + featureFlagService.getCachedOrganizationFeatureFlags(organizationId) + != null + ? featureFlagService + .getCachedOrganizationFeatureFlags(organizationId) + .getFeatures() + : Collections.emptyMap(); + + return ((PluginExecutor) pluginExecutor) + .triggerWithFlags( + resourceContext.getConnection(), + datasourceStorage.getDatasourceConfiguration(), + updatedTriggerRequestDTO, + featureFlagMap); + })); }); // If the plugin hasn't implemented the trigger function, go for the default implementation diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/PagePermissionCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/PagePermissionCE.java index 0919462c75c1..c44c5485c602 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/PagePermissionCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/PagePermissionCE.java @@ -1,3 +1,7 @@ package com.appsmith.server.solutions.ce; -public interface PagePermissionCE extends ContextPermissionCE {} +import com.appsmith.server.acl.AclPermission; + +public interface PagePermissionCE extends ContextPermissionCE { + AclPermission getDeletePermission(String organizationId); +} diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/PagePermissionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/PagePermissionCEImpl.java index 51d26f72c779..5a13ff5d77d3 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/PagePermissionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/PagePermissionCEImpl.java @@ -23,12 +23,12 @@ public AclPermission getExportPermission(boolean isGitSync, boolean exportWithCo } @Override - public AclPermission getDeletePermission() { + public AclPermission getDeletePermission(String organizationId) { return AclPermission.MANAGE_PAGES; } @Override - public AclPermission getActionCreatePermission() { + public AclPermission getActionCreatePermission(String organizationId) { return AclPermission.MANAGE_PAGES; } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/WorkspacePermissionCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/WorkspacePermissionCE.java index bae21a41fb75..d6e6ac1b5fba 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/WorkspacePermissionCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/WorkspacePermissionCE.java @@ -3,9 +3,9 @@ import com.appsmith.server.acl.AclPermission; public interface WorkspacePermissionCE { - AclPermission getDeletePermission(); + AclPermission getDeletePermission(String organizationId); - AclPermission getApplicationCreatePermission(); + AclPermission getApplicationCreatePermission(String organizationId); - AclPermission getDatasourceCreatePermission(); + AclPermission getDatasourceCreatePermission(String organizationId); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/WorkspacePermissionCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/WorkspacePermissionCEImpl.java index 9c09aa09864e..007efafeb9b6 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/WorkspacePermissionCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ce/WorkspacePermissionCEImpl.java @@ -21,17 +21,17 @@ public AclPermission getExportPermission(boolean isGitSync, boolean exportWithCo } @Override - public AclPermission getDeletePermission() { + public AclPermission getDeletePermission(String organizationId) { return AclPermission.MANAGE_WORKSPACES; } @Override - public AclPermission getApplicationCreatePermission() { + public AclPermission getApplicationCreatePermission(String organizationId) { return AclPermission.WORKSPACE_MANAGE_APPLICATIONS; } @Override - public AclPermission getDatasourceCreatePermission() { + public AclPermission getDatasourceCreatePermission(String organizationId) { return AclPermission.WORKSPACE_MANAGE_DATASOURCES; } } diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java index 49c8607bc577..525b3096205a 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/FeatureFlaggedMethodInvokerAspectTest.java @@ -2,9 +2,11 @@ import com.appsmith.external.enums.FeatureFlagEnum; import com.appsmith.server.aspect.component.TestComponent; +import com.appsmith.server.domains.User; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.featureflags.CachedFeatures; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.services.FeatureFlagService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -12,6 +14,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.security.test.context.support.WithUserDetails; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; @@ -20,6 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @SpringBootTest @@ -35,6 +39,8 @@ class FeatureFlaggedMethodInvokerAspectTest { private static final String CE_COMPATIBLE_RESPONSE = "ce_compatible_impl_method"; private static final String CE_RESPONSE = "ce_impl_method"; + private static String organizationId; + @BeforeEach void setUp() { Mockito.when(featureFlagService.check(eq(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE))) @@ -42,7 +48,11 @@ void setUp() { CachedFeatures cachedFeatures = new CachedFeatures(); cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE.name(), Boolean.FALSE)); - Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags()).thenReturn(cachedFeatures); + Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags(any())) + .thenReturn(cachedFeatures); + organizationId = ReactiveContextUtils.getCurrentUser() + .map(User::getOrganizationId) + .block(); } @Test @@ -107,43 +117,69 @@ void ceEeDiffMethodReturnsFlux_ceImplTest() { } @Test + @WithUserDetails(value = "api_user") void ceEeSyncMethod_eeImplTest() { CachedFeatures cachedFeatures = new CachedFeatures(); cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE.name(), Boolean.TRUE)); - Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags()).thenReturn(cachedFeatures); - String result = testComponent.ceEeSyncMethod("arg_"); + Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags(any())) + .thenReturn(cachedFeatures); + String result = testComponent.ceEeSyncMethod("arg_", organizationId); assertEquals("arg_ee_impl_method", result); } @Test + @WithUserDetails(value = "api_user") void ceEeSyncMethod_ceImplTest() { - String result = testComponent.ceEeSyncMethod("arg_"); + String result = testComponent.ceEeSyncMethod("arg_", organizationId); assertEquals("arg_ce_impl_method", result); } @Test + @WithUserDetails(value = "api_user") void ceEeThrowAppsmithException_eeImplTest() { CachedFeatures cachedFeatures = new CachedFeatures(); cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE.name(), Boolean.TRUE)); - Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags()).thenReturn(cachedFeatures); + Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags(any())) + .thenReturn(cachedFeatures); + String result = testComponent.ceEeSyncMethod("arg_", organizationId); assertThrows( AppsmithException.class, - () -> testComponent.ceEeThrowAppsmithException("arg_"), + () -> testComponent.ceEeThrowAppsmithException("arg_", organizationId), AppsmithError.GENERIC_BAD_REQUEST.getMessage("This is a test exception")); } @Test + @WithUserDetails(value = "api_user") void ceEeThrowNonAppsmithException_eeImplTest_throwExceptionFromAspect() { CachedFeatures cachedFeatures = new CachedFeatures(); cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE.name(), Boolean.TRUE)); - Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags()).thenReturn(cachedFeatures); + Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags(any())) + .thenReturn(cachedFeatures); assertThrows( AppsmithException.class, - () -> testComponent.ceEeThrowNonAppsmithException("arg_"), + () -> testComponent.ceEeThrowNonAppsmithException("arg_", organizationId), AppsmithError.INVALID_METHOD_LEVEL_ANNOTATION_USAGE.getMessage( "FeatureFlagged", "TestComponentImpl", "ceEeThrowNonAppsmithException", "Exception while invoking super class method")); } + + @Test + @WithUserDetails(value = "api_user") + void ceEeSyncMethodWOOrgId_eeImplTest() { + try { + testComponent.ceEeSyncMethodWithoutOrgId("arg_"); + } catch (AppsmithException e) { + assertEquals( + AppsmithError.INVALID_METHOD_LEVEL_ANNOTATION_USAGE.getMessage( + "FeatureFlagged", + "TestComponentImpl", + "ceEeSyncMethodWithoutOrgId", + "Add missing organizationId parameter and enforce non-null value for orgnization-specific feature flags retrieval in non-reactive methods"), + e.getMessage()); + } catch (Exception e) { + assert false; + } + } } diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/TestComponentImpl.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/TestComponentImpl.java index 373e0eabf195..c6f5cecd27af 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/TestComponentImpl.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/TestComponentImpl.java @@ -40,19 +40,25 @@ public Flux ceEeDiffMethodReturnsFlux() { @Override @FeatureFlagged(featureFlagName = FeatureFlagEnum.ORGANIZATION_TEST_FEATURE) - public String ceEeSyncMethod(String arg) { + public String ceEeSyncMethod(String arg, String organizationId) { return arg + "ee_impl_method"; } @Override @FeatureFlagged(featureFlagName = FeatureFlagEnum.ORGANIZATION_TEST_FEATURE) - public void ceEeThrowAppsmithException(String arg) { + public void ceEeThrowAppsmithException(String arg, String organizationId) { throw new AppsmithException(AppsmithError.GENERIC_BAD_REQUEST, "This is a test exception"); } @Override @FeatureFlagged(featureFlagName = FeatureFlagEnum.ORGANIZATION_TEST_FEATURE) - public void ceEeThrowNonAppsmithException(String arg) { + public void ceEeThrowNonAppsmithException(String arg, String organizationId) { throw new RuntimeException("This is a test exception"); } + + @Override + @FeatureFlagged(featureFlagName = FeatureFlagEnum.ORGANIZATION_TEST_FEATURE) + public String ceEeSyncMethodWithoutOrgId(String arg) { + return arg + "ee_impl_method"; + } } diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/ce/TestComponentCE.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/ce/TestComponentCE.java index a0e5fa62f6a1..135a47eb82a9 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/ce/TestComponentCE.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/ce/TestComponentCE.java @@ -13,9 +13,11 @@ public interface TestComponentCE { Flux ceEeDiffMethodReturnsFlux(); - String ceEeSyncMethod(String arg); + String ceEeSyncMethod(String arg, String organizationId); - void ceEeThrowAppsmithException(String arg); + void ceEeThrowAppsmithException(String arg, String organizationId); - void ceEeThrowNonAppsmithException(String arg); + void ceEeThrowNonAppsmithException(String arg, String organizationId); + + String ceEeSyncMethodWithoutOrgId(String arg); } diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/ce/TestComponentCEImpl.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/ce/TestComponentCEImpl.java index 86755f406afc..f8ca7e1c546f 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/ce/TestComponentCEImpl.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/aspect/component/ce/TestComponentCEImpl.java @@ -27,13 +27,18 @@ public Flux ceEeDiffMethodReturnsFlux() { } @Override - public String ceEeSyncMethod(String arg) { + public String ceEeSyncMethod(String arg, String organizationId) { return arg + "ce_impl_method"; } @Override - public void ceEeThrowAppsmithException(String arg) {} + public void ceEeThrowAppsmithException(String arg, String organizationId) {} @Override - public void ceEeThrowNonAppsmithException(String arg) {} + public void ceEeThrowNonAppsmithException(String arg, String organizationId) {} + + @Override + public String ceEeSyncMethodWithoutOrgId(String arg) { + return arg + "ce_impl_method"; + } } diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/fork/ApplicationForkingServiceTests.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/fork/ApplicationForkingServiceTests.java index fb84d7ea6cb1..ed2e550ff144 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/fork/ApplicationForkingServiceTests.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/fork/ApplicationForkingServiceTests.java @@ -600,6 +600,7 @@ public void test6_failForkApplication_noDatasourceCreatePermission() { targetWorkspace.setName("Target Workspace"); targetWorkspace = workspaceService.create(targetWorkspace).block(); final String workspaceId = targetWorkspace.getId(); + final String orgId = targetWorkspace.getOrganizationId(); Set existingPolicies = targetWorkspace.getPolicies(); /* @@ -609,7 +610,7 @@ public void test6_failForkApplication_noDatasourceCreatePermission() { Set newPoliciesWithoutCreateDatasource = existingPolicies.stream() .filter(policy -> !policy.getPermission() .equals(workspacePermission - .getDatasourceCreatePermission() + .getDatasourceCreatePermission(orgId) .getValue())) .collect(Collectors.toSet()); targetWorkspace.setPolicies(newPoliciesWithoutCreateDatasource); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/git/CommonGitServiceCETest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/git/CommonGitServiceCETest.java index 8ce36a1fc29c..cb0fced558c8 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/git/CommonGitServiceCETest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/git/CommonGitServiceCETest.java @@ -235,6 +235,8 @@ public class CommonGitServiceCETest { @SpyBean AnalyticsService analyticsService; + private static String organizationId; + @BeforeEach public void setup() throws IOException, GitAPIException { User currentUser = sessionUserService.getCurrentUser().block(); @@ -248,6 +250,7 @@ public void setup() throws IOException, GitAPIException { Workspace workspace = workspaceService.create(toCreate, apiUser, Boolean.FALSE).block(); workspaceId = workspace.getId(); + organizationId = workspace.getOrganizationId(); defaultEnvironmentId = workspaceService .getDefaultEnvironmentId(workspaceId, environmentPermission.getExecutePermission()) .block(); @@ -267,7 +270,7 @@ public void setup() throws IOException, GitAPIException { public void cleanup() { Mockito.when(commonGitFileUtils.deleteLocalRepo(any(Path.class))).thenReturn(Mono.just(true)); List deletedApplications = applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission(organizationId)) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/EmailServiceHelperCETest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/EmailServiceHelperCETest.java index e10befb4c39a..90444015a9e9 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/EmailServiceHelperCETest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/EmailServiceHelperCETest.java @@ -29,6 +29,8 @@ class EmailServiceHelperCETest { @Autowired OrganizationService organizationService; + private static String organizationId; + @Test @WithUserDetails(value = "api_user") public void testEnrichWithBrandParams() { @@ -42,29 +44,32 @@ public void testEnrichWithBrandParams() { assertThat(map.get(INSTANCE_NAME)).isEqualTo(instanceName); }) .verifyComplete(); + organizationId = defautOrganization.getId(); } @Test void testGetForgotPasswordTemplate() { - assertThat(emailServiceHelperCE.getForgotPasswordTemplate()).isEqualTo(FORGOT_PASSWORD_TEMPLATE_CE); + assertThat(emailServiceHelperCE.getForgotPasswordTemplate(organizationId)) + .isEqualTo(FORGOT_PASSWORD_TEMPLATE_CE); } @Test void testGetWorkspaceInviteTemplate() { - assertThat(emailServiceHelperCE.getWorkspaceInviteTemplate(Boolean.TRUE)) + assertThat(emailServiceHelperCE.getWorkspaceInviteTemplate(Boolean.TRUE, organizationId)) .isEqualTo(INVITE_WORKSPACE_TEMPLATE_NEW_USER_CE); - assertThat(emailServiceHelperCE.getWorkspaceInviteTemplate(Boolean.FALSE)) + assertThat(emailServiceHelperCE.getWorkspaceInviteTemplate(Boolean.FALSE, organizationId)) .isEqualTo(INVITE_WORKSPACE_TEMPLATE_EXISTING_USER_CE); } @Test void testGetEmailVerificationTemplate() { - assertThat(emailServiceHelperCE.getEmailVerificationTemplate()).isEqualTo(EMAIL_VERIFICATION_EMAIL_TEMPLATE_CE); + assertThat(emailServiceHelperCE.getEmailVerificationTemplate(organizationId)) + .isEqualTo(EMAIL_VERIFICATION_EMAIL_TEMPLATE_CE); } @Test void testGetAdminInstanceInviteTemplate() { - assertThat(emailServiceHelperCE.getAdminInstanceInviteTemplate()) + assertThat(emailServiceHelperCE.getAdminInstanceInviteTemplate(organizationId)) .isEqualTo(INSTANCE_ADMIN_INVITE_EMAIL_TEMPLATE); } } diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/ImportArtifactPermissionProviderTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/ImportArtifactPermissionProviderTest.java index bb85f57382fe..d064694d0c80 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/ImportArtifactPermissionProviderTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/helpers/ce/ImportArtifactPermissionProviderTest.java @@ -8,14 +8,17 @@ import com.appsmith.server.domains.Application; import com.appsmith.server.domains.NewAction; import com.appsmith.server.domains.NewPage; +import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; import com.appsmith.server.helpers.ImportArtifactPermissionProvider; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.solutions.ActionPermission; import com.appsmith.server.solutions.ApplicationPermission; import com.appsmith.server.solutions.DatasourcePermission; import com.appsmith.server.solutions.DomainPermission; import com.appsmith.server.solutions.PagePermission; import com.appsmith.server.solutions.WorkspacePermission; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @@ -47,6 +50,15 @@ class ImportArtifactPermissionProviderTest { @Autowired WorkspacePermission workspacePermission; + private static String organizationId; + + @BeforeEach + public void setup() { + organizationId = ReactiveContextUtils.getCurrentUser() + .map(User::getOrganizationId) + .block(); + } + @Test public void testCheckPermissionMethods_WhenNoPermissionProvided_ReturnsTrue() { ImportArtifactPermissionProvider importArtifactPermissionProvider = ImportArtifactPermissionProvider.builder( @@ -61,9 +73,9 @@ public void testCheckPermissionMethods_WhenNoPermissionProvided_ReturnsTrue() { assertTrue(importArtifactPermissionProvider.hasEditPermission(new NewAction())); assertTrue(importArtifactPermissionProvider.hasEditPermission(new Datasource())); - assertTrue(importArtifactPermissionProvider.canCreateDatasource(new Workspace())); - assertTrue(importArtifactPermissionProvider.canCreateAction(new NewPage())); - assertTrue(importArtifactPermissionProvider.canCreatePage(new Application())); + assertTrue(importArtifactPermissionProvider.canCreateDatasource(new Workspace(), organizationId)); + assertTrue(importArtifactPermissionProvider.canCreateAction(new NewPage(), organizationId)); + assertTrue(importArtifactPermissionProvider.canCreatePage(new Application(), organizationId)); } @Test @@ -101,9 +113,11 @@ public void tesHasCreatePermissionOnDomains_WhenPermissionGroupDoesNotMatch_Retu // we'll create a permission provider for each domain and check if the create permission is false List> domainAndPermissionList = new ArrayList<>(); - domainAndPermissionList.add(Tuples.of(new Application(), applicationPermission.getPageCreatePermission())); - domainAndPermissionList.add(Tuples.of(new NewPage(), pagePermission.getActionCreatePermission())); - domainAndPermissionList.add(Tuples.of(new Workspace(), workspacePermission.getDatasourceCreatePermission())); + domainAndPermissionList.add( + Tuples.of(new Application(), applicationPermission.getPageCreatePermission(organizationId))); + domainAndPermissionList.add(Tuples.of(new NewPage(), pagePermission.getActionCreatePermission(organizationId))); + domainAndPermissionList.add( + Tuples.of(new Workspace(), workspacePermission.getDatasourceCreatePermission(organizationId))); for (Tuple2 domainAndPermission : domainAndPermissionList) { BaseDomain domain = domainAndPermission.getT1(); @@ -112,11 +126,11 @@ public void tesHasCreatePermissionOnDomains_WhenPermissionGroupDoesNotMatch_Retu createPermissionProviderForDomainCreatePermission(domain, domainAndPermission.getT2()); if (domain instanceof Application) { - assertFalse(provider.canCreatePage((Application) domain)); + assertFalse(provider.canCreatePage((Application) domain, organizationId)); } else if (domain instanceof NewPage) { - assertFalse(provider.canCreateAction((NewPage) domain)); + assertFalse(provider.canCreateAction((NewPage) domain, organizationId)); } else if (domain instanceof Workspace) { - assertFalse(provider.canCreateDatasource((Workspace) domain)); + assertFalse(provider.canCreateDatasource((Workspace) domain, organizationId)); } } } diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/imports/internal/ImportServiceTests.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/imports/internal/ImportServiceTests.java index 317f121db519..2dc9409cbdba 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/imports/internal/ImportServiceTests.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/imports/internal/ImportServiceTests.java @@ -153,6 +153,7 @@ public class ImportServiceTests { private static final Map datasourceMap = new HashMap<>(); private static Plugin installedPlugin; private static String workspaceId; + private static String organizationId; private static String defaultEnvironmentId; private static String testAppId; private static Datasource jsDatasource; @@ -258,6 +259,7 @@ public void setup() { workspace.setName("Import-Export-Test-Workspace"); Workspace savedWorkspace = workspaceService.create(workspace).block(); workspaceId = savedWorkspace.getId(); + organizationId = savedWorkspace.getOrganizationId(); defaultEnvironmentId = workspaceService .getDefaultEnvironmentId(workspaceId, environmentPermission.getExecutePermission()) .block(); @@ -4939,7 +4941,7 @@ public void mergeApplicationJsonWithApplication_WhenNoPermissionToCreatePage_Fai application.setPolicies(application.getPolicies().stream() .filter(policy -> !policy.getPermission() .equals(applicationPermission - .getPageCreatePermission() + .getPageCreatePermission(organizationId) .getValue())) .collect(Collectors.toUnmodifiableSet())); return applicationRepository.save(application); @@ -4983,7 +4985,7 @@ public void extractFileAndUpdateNonGitConnectedApplication_WhenNoPermissionToCre application.setPolicies(application.getPolicies().stream() .filter(policy -> !policy.getPermission() .equals(applicationPermission - .getPageCreatePermission() + .getPageCreatePermission(organizationId) .getValue())) .collect(Collectors.toUnmodifiableSet())); return applicationRepository.save(application); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/refactors/ce/RefactoringServiceCETest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/refactors/ce/RefactoringServiceCETest.java index 6570ca2da9ac..0160ddba8f58 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/refactors/ce/RefactoringServiceCETest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/refactors/ce/RefactoringServiceCETest.java @@ -145,6 +145,7 @@ class RefactoringServiceCETest { Datasource datasource; String workspaceId; + private static String organizationId; String branchName; @@ -154,6 +155,7 @@ class RefactoringServiceCETest { public void setup() { newPageService.deleteAll().block(); User currentUser = sessionUserService.getCurrentUser().block(); + organizationId = currentUser.getOrganizationId(); Workspace toCreate = new Workspace(); toCreate.setName("LayoutActionServiceTest"); @@ -249,7 +251,7 @@ public void setup() { @AfterEach public void cleanup() { List deletedApplications = applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission(organizationId)) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/refactors/ce/RefactoringServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/refactors/ce/RefactoringServiceTest.java index 9010de1a0e58..f63fbf3bb03a 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/refactors/ce/RefactoringServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/refactors/ce/RefactoringServiceTest.java @@ -121,6 +121,7 @@ public class RefactoringServiceTest { Datasource datasource; String workspaceId; + private static String organizationId; String branchName; @@ -134,6 +135,7 @@ public class RefactoringServiceTest { public void setup() { newPageService.deleteAll().block(); User apiUser = userService.findByEmail("api_user").block(); + organizationId = apiUser.getOrganizationId(); Workspace toCreate = new Workspace(); toCreate.setName("LayoutActionServiceTest"); @@ -230,7 +232,7 @@ public void setup() { @AfterEach public void cleanup() { List deletedApplications = applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission(organizationId)) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ActionCollectionServiceImplTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ActionCollectionServiceImplTest.java index 41b452a91bce..d9034ba353c7 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ActionCollectionServiceImplTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ActionCollectionServiceImplTest.java @@ -12,9 +12,11 @@ import com.appsmith.server.domains.ActionCollection; import com.appsmith.server.domains.NewAction; import com.appsmith.server.domains.NewPage; +import com.appsmith.server.domains.User; import com.appsmith.server.dtos.ActionCollectionDTO; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.layouts.UpdateLayoutService; import com.appsmith.server.newactions.base.NewActionService; import com.appsmith.server.newpages.base.NewPageService; @@ -32,9 +34,11 @@ import jakarta.validation.Validator; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.MockedStatic; import org.mockito.Mockito; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -100,6 +104,17 @@ public class ActionCollectionServiceImplTest { @MockBean private PolicyGenerator policyGenerator; + @BeforeAll + public static void beforeAll() { + User mockUser = new User(); + mockUser.setOrganizationId("testOrgId"); + MockedStatic reactiveContextUtilsMockedStatic = + Mockito.mockStatic(ReactiveContextUtils.class); + reactiveContextUtilsMockedStatic + .when(ReactiveContextUtils::getCurrentUser) + .thenReturn(Mono.just(mockUser)); + } + @BeforeEach public void setUp() { applicationPermission = new ApplicationPermissionImpl(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ActionCollectionServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ActionCollectionServiceTest.java index b31038346352..05274ea15daf 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ActionCollectionServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ActionCollectionServiceTest.java @@ -152,12 +152,14 @@ public class ActionCollectionServiceTest { Datasource datasource; String workspaceId; + private static String organizationId; @BeforeEach @WithUserDetails(value = "api_user") public void setup() { User apiUser = userService.findByEmail("api_user").block(); assert apiUser != null; + organizationId = apiUser.getOrganizationId(); Workspace toCreate = new Workspace(); toCreate.setName("ActionCollectionServiceTest"); @@ -217,7 +219,7 @@ public void setup() { @WithUserDetails(value = "api_user") public void cleanup() { List deletedApplications = applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission(organizationId)) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ApplicationPageServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ApplicationPageServiceTest.java index 364e3ee7209c..80ad28cb6a63 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ApplicationPageServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ApplicationPageServiceTest.java @@ -87,7 +87,8 @@ public void setup() { @AfterEach public void cleanup() { List deletedApplications = applicationService - .findByWorkspaceId(workspace.getId(), applicationPermission.getDeletePermission()) + .findByWorkspaceId( + workspace.getId(), applicationPermission.getDeletePermission(workspace.getOrganizationId())) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ApplicationSnapshotServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ApplicationSnapshotServiceTest.java index 6538471c394e..c55c5730d23c 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ApplicationSnapshotServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ApplicationSnapshotServiceTest.java @@ -78,7 +78,8 @@ public void cleanup() { return; } List deletedApplications = applicationService - .findByWorkspaceId(workspace.getId(), applicationPermission.getDeletePermission()) + .findByWorkspaceId( + workspace.getId(), applicationPermission.getDeletePermission(user.getOrganizationId())) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/CurlImporterServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/CurlImporterServiceTest.java index bacca9f82e67..f9a9512ffcac 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/CurlImporterServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/CurlImporterServiceTest.java @@ -208,7 +208,8 @@ public void cleanup() { return; } List deletedApplications = applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + .findByWorkspaceId( + workspaceId, applicationPermission.getDeletePermission(currentUser.getOrganizationId())) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/DatasourceContextServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/DatasourceContextServiceTest.java index e2dbb66a3a99..6324b3d29b2a 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/DatasourceContextServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/DatasourceContextServiceTest.java @@ -121,6 +121,7 @@ public class DatasourceContextServiceTest { String defaultEnvironmentId; String workspaceId; + private static String organizationId; @BeforeEach public void setup() { @@ -131,6 +132,7 @@ public void setup() { Workspace workspace = workspaceService.create(toCreate, apiUser, Boolean.FALSE).block(); workspaceId = workspace.getId(); + organizationId = workspace.getOrganizationId(); defaultEnvironmentId = workspaceService .getDefaultEnvironmentId(workspaceId, environmentPermission.getExecutePermission()) .block(); @@ -139,7 +141,7 @@ public void setup() { @AfterEach public void cleanup() { List deletedApplications = applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission(organizationId)) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); @@ -188,7 +190,7 @@ public void testDatasourceCache_afterDatasourceDeleted_doesNotReturnOldConnectio doReturn(Mono.just(datasource)) .when(datasourceRepository) - .findById("id1", datasourcePermission.getDeletePermission()); + .findById("id1", datasourcePermission.getDeletePermission(organizationId)); doReturn(Mono.just(datasource)) .when(datasourceRepository) .findById("id1", datasourcePermission.getExecutePermission()); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/DatasourceServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/DatasourceServiceTest.java index f7739d72e422..91c64b36ceb9 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/DatasourceServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/DatasourceServiceTest.java @@ -125,6 +125,7 @@ public class DatasourceServiceTest { ApplicationPermission applicationPermission; String workspaceId = ""; + private static String organizationId; private String defaultEnvironmentId; @BeforeEach @@ -136,6 +137,7 @@ public void setup() { Workspace workspace = workspaceService.create(toCreate, apiUser, Boolean.FALSE).block(); workspaceId = workspace.getId(); + organizationId = workspace.getOrganizationId(); defaultEnvironmentId = workspaceService .getDefaultEnvironmentId(workspaceId, environmentPermission.getExecutePermission()) .block(); @@ -144,7 +146,7 @@ public void setup() { @AfterEach public void cleanup() { List deletedApplications = applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission(organizationId)) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/DatasourceStorageServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/DatasourceStorageServiceTest.java index 194181ab43c1..440d4f9f34e2 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/DatasourceStorageServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/DatasourceStorageServiceTest.java @@ -79,7 +79,8 @@ public void setup() { @AfterEach public void cleanup() { List deletedApplications = applicationService - .findByWorkspaceId(workspace.getId(), applicationPermission.getDeletePermission()) + .findByWorkspaceId( + workspace.getId(), applicationPermission.getDeletePermission(workspace.getOrganizationId())) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/LayoutActionServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/LayoutActionServiceTest.java index 4ad9cf33c936..91555cc1327e 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/LayoutActionServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/LayoutActionServiceTest.java @@ -255,8 +255,10 @@ public void setup() { @AfterEach void cleanup() { - List deletedApplications = applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + List deletedApplications = workspaceService + .getById(workspaceId) + .flatMapMany(workspace -> applicationService.findByWorkspaceId( + workspaceId, applicationPermission.getDeletePermission(workspace.getOrganizationId()))) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/LayoutServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/LayoutServiceTest.java index 8bfc73e2f441..2c2e3f362cdd 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/LayoutServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/LayoutServiceTest.java @@ -153,8 +153,10 @@ public void setup() { @AfterEach public void cleanup() { + String orgId = + sessionUserService.getCurrentUser().map(User::getOrganizationId).block(); applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission(orgId)) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/MockDataServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/MockDataServiceTest.java index e3b1d4523c0a..ee586bcfcf97 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/MockDataServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/MockDataServiceTest.java @@ -103,6 +103,7 @@ public class MockDataServiceTest { ApplicationPermission applicationPermission; String workspaceId = ""; + String organizationId; Application testApp = null; @@ -118,6 +119,7 @@ public void setup() { Workspace workspace = workspaceService.create(toCreate, apiUser, Boolean.FALSE).block(); workspaceId = workspace.getId(); + organizationId = workspace.getOrganizationId(); // Create application and page which will be used by the tests to create actions for. Application application = new Application(); @@ -132,7 +134,7 @@ public void setup() { @AfterEach public void cleanup() { List deletedApplications = applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission(organizationId)) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/NewPageServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/NewPageServiceTest.java index b89277c7012a..2f9008207342 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/NewPageServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/NewPageServiceTest.java @@ -74,19 +74,22 @@ public class NewPageServiceTest { ApplicationPermission applicationPermission; String workspaceId = null; + String organizationId; @BeforeEach public void setup() { String randomId = UUID.randomUUID().toString(); Workspace workspace = new Workspace(); workspace.setName("org_" + randomId); - workspaceId = workspaceService.create(workspace).map(Workspace::getId).block(); + workspace = workspaceService.create(workspace).block(); + workspaceId = workspace.getId(); + organizationId = workspace.getOrganizationId(); } @AfterEach public void cleanup() { List deletedApplications = applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission(organizationId)) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/PageServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/PageServiceTest.java index 0822fc81098c..5988b5b71bac 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/PageServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/PageServiceTest.java @@ -35,6 +35,7 @@ import com.appsmith.server.exports.internal.ExportService; import com.appsmith.server.helpers.MockPluginExecutor; import com.appsmith.server.helpers.PluginExecutorHelper; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.helpers.TextUtils; import com.appsmith.server.imports.internal.ImportService; import com.appsmith.server.layouts.UpdateLayoutService; @@ -155,8 +156,13 @@ public void setup() { @AfterEach public void cleanup() { + User currentUser = ReactiveContextUtils.getCurrentUser().block(); + if (currentUser == null) { + return; + } List deletedApplications = applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + .findByWorkspaceId( + workspaceId, applicationPermission.getDeletePermission(currentUser.getOrganizationId())) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ThemeServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ThemeServiceTest.java index 0e7e7ce8bb6b..962f32d6f583 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ThemeServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ThemeServiceTest.java @@ -13,6 +13,7 @@ import com.appsmith.server.dtos.UpdatePermissionGroupDTO; import com.appsmith.server.exceptions.AppsmithError; import com.appsmith.server.exceptions.AppsmithException; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.repositories.ApplicationRepository; import com.appsmith.server.repositories.CacheableRepositoryHelper; import com.appsmith.server.repositories.PermissionGroupRepository; @@ -107,8 +108,13 @@ public void setup() { @AfterEach public void cleanup() { + User currentUser = ReactiveContextUtils.getCurrentUser().block(); + if (currentUser == null) { + return; + } List deletedApplications = applicationService - .findByWorkspaceId(workspace.getId(), applicationPermission.getDeletePermission()) + .findByWorkspaceId( + workspace.getId(), applicationPermission.getDeletePermission(currentUser.getOrganizationId())) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UserWorkspaceServiceUnitTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UserWorkspaceServiceUnitTest.java index f7ca9468321a..79279e9c64f2 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UserWorkspaceServiceUnitTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/UserWorkspaceServiceUnitTest.java @@ -119,7 +119,8 @@ public void cleanup() { return; } List deletedApplications = applicationService - .findByWorkspaceId(workspace.getId(), applicationPermission.getDeletePermission()) + .findByWorkspaceId( + workspace.getId(), applicationPermission.getDeletePermission(currentUser.getOrganizationId())) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ActionServiceCE_Test.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ActionServiceCE_Test.java index ee5934ede490..26eb1e35d14f 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ActionServiceCE_Test.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ActionServiceCE_Test.java @@ -284,8 +284,13 @@ public void setup() { @AfterEach public void cleanup() { + User currentUser = sessionUserService.getCurrentUser().block(); + if (currentUser == null) { + return; + } List deletedApplications = applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + .findByWorkspaceId( + workspaceId, applicationPermission.getDeletePermission(currentUser.getOrganizationId())) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ApplicationServiceCETest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ApplicationServiceCETest.java index 6093222abbb7..5939dc0122c4 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ApplicationServiceCETest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ApplicationServiceCETest.java @@ -50,6 +50,7 @@ import com.appsmith.server.exports.internal.ExportService; import com.appsmith.server.helpers.MockPluginExecutor; import com.appsmith.server.helpers.PluginExecutorHelper; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.helpers.TextUtils; import com.appsmith.server.imports.internal.ImportService; import com.appsmith.server.jslibs.base.CustomJSLibService; @@ -416,7 +417,8 @@ public void cleanup() { return; } List deletedApplications = applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + .findByWorkspaceId( + workspaceId, applicationPermission.getDeletePermission(currentUser.getOrganizationId())) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); @@ -4169,9 +4171,14 @@ public void cloneApplication_noDatasourceCreateActionPermissions() { /* * The created Workspace has a Datasource. And we will remove the Create Datasource Action permisison. */ + String orgId = ReactiveContextUtils.getCurrentUser() + .map(User::getOrganizationId) + .block(); Set newPoliciesWithoutEdit = existingPolicies.stream() .filter(policy -> !policy.getPermission() - .equals(datasourcePermission.getActionCreatePermission().getValue())) + .equals(datasourcePermission + .getActionCreatePermission(orgId) + .getValue())) .collect(Collectors.toSet()); testDatasource1.setPolicies(newPoliciesWithoutEdit); Datasource updatedTestDatasource = diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java index d615089f7ad4..9adb458c7ab6 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/FeatureFlagServiceCETest.java @@ -7,6 +7,7 @@ import com.appsmith.server.featureflags.CachedFeatures; import com.appsmith.server.featureflags.CachedFlags; import com.appsmith.server.helpers.FeatureFlagMigrationHelper; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.services.CacheableFeatureFlagHelper; import com.appsmith.server.services.FeatureFlagService; import com.appsmith.server.services.OrganizationService; @@ -288,8 +289,11 @@ public void getOrganizationFeatureFlags_withDefaultOrganization_fetchLatestFlags @WithUserDetails(value = "api_user") public void getCachedOrganizationFeatureFlags_withDefaultOrganization_organizationFeatureFlagsAreCached() { + String orgId = ReactiveContextUtils.getCurrentUser() + .map(User::getOrganizationId) + .block(); // Assert that the cached feature flags are empty before the remote fetch - CachedFeatures cachedFeaturesBeforeRemoteCall = featureFlagService.getCachedOrganizationFeatureFlags(); + CachedFeatures cachedFeaturesBeforeRemoteCall = featureFlagService.getCachedOrganizationFeatureFlags(orgId); assertThat(cachedFeaturesBeforeRemoteCall.getFeatures()).hasSize(1); assertTrue(cachedFeaturesBeforeRemoteCall.getFeatures().get(ORGANIZATION_TEST_FEATURE.name())); @@ -305,7 +309,7 @@ public void getCachedOrganizationFeatureFlags_withDefaultOrganization_organizati // Check if the cached feature flags are updated after the remote fetch CachedFeatures cachedFeaturesAfterRemoteCall = - featureFlagService.getCachedOrganizationFeatureFlags(); + featureFlagService.getCachedOrganizationFeatureFlags(orgId); assertFalse(cachedFeaturesAfterRemoteCall.getFeatures().get(ORGANIZATION_TEST_FEATURE.name())); }) .verifyComplete(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ThemeImportableServiceCETest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ThemeImportableServiceCETest.java index 63d8a7b58a61..56f0f9d8b743 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ThemeImportableServiceCETest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/ce/ThemeImportableServiceCETest.java @@ -3,10 +3,12 @@ import com.appsmith.server.applications.base.ApplicationService; import com.appsmith.server.domains.Application; import com.appsmith.server.domains.Theme; +import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; import com.appsmith.server.dtos.ApplicationJson; import com.appsmith.server.dtos.ImportingMetaDTO; import com.appsmith.server.dtos.MappedImportableResourcesDTO; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.imports.importable.ImportableService; import com.appsmith.server.repositories.ApplicationRepository; import com.appsmith.server.repositories.PermissionGroupRepository; @@ -88,8 +90,13 @@ public void setup() { @AfterEach public void cleanup() { + User currentUser = ReactiveContextUtils.getCurrentUser().block(); + if (currentUser == null) { + return; + } List deletedApplications = applicationService - .findByWorkspaceId(workspace.getId(), applicationPermission.getDeletePermission()) + .findByWorkspaceId( + workspace.getId(), applicationPermission.getDeletePermission(currentUser.getOrganizationId())) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/AuthenticationServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/AuthenticationServiceTest.java index 7e2eb4825594..77311c2e06b1 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/AuthenticationServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/AuthenticationServiceTest.java @@ -14,6 +14,7 @@ import com.appsmith.server.domains.Application; import com.appsmith.server.domains.NewPage; import com.appsmith.server.domains.Plugin; +import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; import com.appsmith.server.dtos.PageDTO; import com.appsmith.server.dtos.PluginWorkspaceDTO; @@ -22,6 +23,7 @@ import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.helpers.MockPluginExecutor; import com.appsmith.server.helpers.PluginExecutorHelper; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.newpages.base.NewPageService; import com.appsmith.server.plugins.base.PluginService; import com.appsmith.server.repositories.WorkspaceRepository; @@ -101,8 +103,13 @@ public void setup() { @AfterEach public void cleanup() { + User currentUser = ReactiveContextUtils.getCurrentUser().block(); + if (currentUser == null) { + return; + } List deletedApplications = applicationService - .findByWorkspaceId(workspace.getId(), applicationPermission.getDeletePermission()) + .findByWorkspaceId( + workspace.getId(), applicationPermission.getDeletePermission(currentUser.getOrganizationId())) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/CreateDBTablePageSolutionTests.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/CreateDBTablePageSolutionTests.java index f409d5e809f9..7dd32f602a17 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/CreateDBTablePageSolutionTests.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/CreateDBTablePageSolutionTests.java @@ -23,6 +23,7 @@ import com.appsmith.server.domains.NewAction; import com.appsmith.server.domains.NewPage; import com.appsmith.server.domains.Plugin; +import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; import com.appsmith.server.dtos.ApplicationJson; import com.appsmith.server.dtos.CRUDPageResourceDTO; @@ -33,6 +34,7 @@ import com.appsmith.server.exports.internal.ExportService; import com.appsmith.server.helpers.MockPluginExecutor; import com.appsmith.server.helpers.PluginExecutorHelper; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.imports.internal.ImportService; import com.appsmith.server.newactions.base.NewActionService; import com.appsmith.server.newpages.base.NewPageService; @@ -241,8 +243,14 @@ public void setup() { @AfterEach public void cleanup() { - List deletedApplications = applicationService - .findByWorkspaceId(testWorkspace.getId(), applicationPermission.getDeletePermission()) + User currentUser = ReactiveContextUtils.getCurrentUser().block(); + if (currentUser == null) { + return; + } + applicationService + .findByWorkspaceId( + testWorkspace.getId(), + applicationPermission.getDeletePermission(currentUser.getOrganizationId())) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/DatasourceStructureSolutionTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/DatasourceStructureSolutionTest.java index 342f4783f95f..59c43a95af7d 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/DatasourceStructureSolutionTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/DatasourceStructureSolutionTest.java @@ -19,6 +19,7 @@ import com.appsmith.server.domains.Workspace; import com.appsmith.server.helpers.MockPluginExecutor; import com.appsmith.server.helpers.PluginExecutorHelper; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.plugins.base.PluginService; import com.appsmith.server.services.ApplicationPageService; import com.appsmith.server.services.DatasourceContextService; @@ -126,8 +127,13 @@ public void setup() { @AfterEach public void cleanup() { + User currentUser = ReactiveContextUtils.getCurrentUser().block(); + if (currentUser == null) { + return; + } List deletedApplications = applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + .findByWorkspaceId( + workspaceId, applicationPermission.getDeletePermission(currentUser.getOrganizationId())) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/DatasourceTriggerSolutionTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/DatasourceTriggerSolutionTest.java index 6ad83290dcd3..30f05a5be4dd 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/DatasourceTriggerSolutionTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/DatasourceTriggerSolutionTest.java @@ -12,9 +12,11 @@ import com.appsmith.server.datasources.base.DatasourceService; import com.appsmith.server.domains.Application; import com.appsmith.server.domains.Plugin; +import com.appsmith.server.domains.User; import com.appsmith.server.domains.Workspace; import com.appsmith.server.helpers.MockPluginExecutor; import com.appsmith.server.helpers.PluginExecutorHelper; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.plugins.base.PluginService; import com.appsmith.server.services.ApplicationPageService; import com.appsmith.server.services.FeatureFlagService; @@ -121,8 +123,13 @@ public void setup() { @AfterEach public void cleanup() { + User currentUser = ReactiveContextUtils.getCurrentUser().block(); + if (currentUser == null) { + return; + } + String orgId = currentUser.getOrganizationId(); List deletedApplications = applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission(orgId)) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCETest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCETest.java index 43cf663f943c..cddea0a8b3a0 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCETest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ce/ActionExecutionSolutionCETest.java @@ -36,6 +36,7 @@ import com.appsmith.server.exports.internal.ExportService; import com.appsmith.server.helpers.MockPluginExecutor; import com.appsmith.server.helpers.PluginExecutorHelper; +import com.appsmith.server.helpers.ReactiveContextUtils; import com.appsmith.server.helpers.WidgetSuggestionHelper; import com.appsmith.server.imports.internal.ImportService; import com.appsmith.server.newpages.base.NewPageService; @@ -292,8 +293,13 @@ public void setup() { @AfterEach public void cleanup() { + User currentUser = ReactiveContextUtils.getCurrentUser().block(); + if (currentUser == null) { + return; + } List deletedApplications = applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + .findByWorkspaceId( + workspaceId, applicationPermission.getDeletePermission(currentUser.getOrganizationId())) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block(); diff --git a/app/server/appsmith-server/src/test/utils/com/appsmith/server/git/ArtifactBuilderExtension.java b/app/server/appsmith-server/src/test/utils/com/appsmith/server/git/ArtifactBuilderExtension.java index 123664de18e6..426a92c9e9d7 100644 --- a/app/server/appsmith-server/src/test/utils/com/appsmith/server/git/ArtifactBuilderExtension.java +++ b/app/server/appsmith-server/src/test/utils/com/appsmith/server/git/ArtifactBuilderExtension.java @@ -83,6 +83,7 @@ public void beforeEach(ExtensionContext extensionContext) throws Exception { contextStore.put(FieldName.WORKSPACE_ID, (workspace.getId())); contextStore.put(FieldName.ARTIFACT_ID, (artifact.getId())); + contextStore.put(FieldName.ORGANIZATION_ID, (workspace.getOrganizationId())); } @@ -91,11 +92,12 @@ public void afterEach(ExtensionContext extensionContext) { ExtensionContext.Store contextStore = extensionContext.getStore(ExtensionContext.Namespace.create(ArtifactBuilderExtension.class)); String workspaceId = contextStore.get(FieldName.WORKSPACE_ID, String.class); + String organizationId = contextStore.get(FieldName.ORGANIZATION_ID, String.class); // Because right now we only have checks for apps // Move this to artifact based model when we fix that applicationService - .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) + .findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission(organizationId)) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .collectList() .block();