chore: Convert non-reactive methods consuming @FeatureFlagged to reactive (#39594)

## Description
PR to convert non-reactive methods consuming @FeatureFlagged to reactive.


Fixes #`Issue Number`  
_or_  
Fixes `Issue URL`
> [!WARNING]  
> _If no issue exists, please create an issue first, and check with the
maintainers if the issue is valid._

/test All

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/13698576435>
> Commit: d8ade4daa88bcbe0d794626820201ab01860ed3a
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=13698576435&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.All`
> Spec:
> <hr>Thu, 06 Mar 2025 13:34:00 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Refactor**
- Migrated key permission checks and resource operations to a reactive,
asynchronous model that boosts system responsiveness and scalability.
- **Tests**
- Updated the testing suite to align with reactive patterns, ensuring
enhanced reliability and robustness.
- Adjusted assertions to handle reactive types appropriately, improving
clarity and specificity in test outcomes.
- **Chores**
- Streamlined internal workflows and error handling, leading to improved
performance and maintainability.

These internal improvements help achieve smoother and more efficient
operations without altering the user-facing experience.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Abhijeet 2025-03-07 11:10:27 +05:30 committed by GitHub
parent 022581f320
commit 6e25f51a4f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
73 changed files with 731 additions and 549 deletions

View File

@ -280,13 +280,16 @@ public class ActionCollectionServiceCEImpl extends BaseService<ActionCollectionR
@Override
public Mono<ActionCollectionDTO> deleteWithoutPermissionUnpublishedActionCollection(String id) {
return deleteUnpublishedActionCollection(id, null, actionPermission.getDeletePermission());
return actionPermission
.getDeletePermission()
.flatMap(permission -> deleteUnpublishedActionCollection(id, null, permission));
}
@Override
public Mono<ActionCollectionDTO> deleteUnpublishedActionCollection(String id) {
return deleteUnpublishedActionCollection(
id, actionPermission.getDeletePermission(), actionPermission.getDeletePermission());
return actionPermission
.getDeletePermission()
.flatMap(permission -> deleteUnpublishedActionCollection(id, permission, permission));
}
@Override
@ -418,10 +421,12 @@ public class ActionCollectionServiceCEImpl extends BaseService<ActionCollectionR
}
protected Mono<ActionCollection> archiveGivenActionCollection(ActionCollection actionCollection) {
Flux<NewAction> unpublishedJsActionsFlux = newActionService.findByCollectionIdAndViewMode(
actionCollection.getId(), false, actionPermission.getDeletePermission());
Flux<NewAction> publishedJsActionsFlux = newActionService.findByCollectionIdAndViewMode(
actionCollection.getId(), true, actionPermission.getDeletePermission());
Mono<AclPermission> deleteActionPermissionMono =
actionPermission.getDeletePermission().cache();
Flux<NewAction> unpublishedJsActionsFlux = deleteActionPermissionMono.flatMapMany(permission ->
newActionService.findByCollectionIdAndViewMode(actionCollection.getId(), false, permission));
Flux<NewAction> publishedJsActionsFlux = deleteActionPermissionMono.flatMapMany(permission ->
newActionService.findByCollectionIdAndViewMode(actionCollection.getId(), true, permission));
return unpublishedJsActionsFlux
.mergeWith(publishedJsActionsFlux)
.flatMap(toArchive -> newActionService

View File

@ -20,6 +20,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.ArrayList;
@ -172,84 +173,102 @@ public class ActionCollectionImportableServiceCEImpl implements ImportableServic
// collections
resultDTO.setExistingActionCollections(actionsCollectionsInCurrentArtifact.values());
List<ActionCollection> newActionCollections = new ArrayList<>();
List<ActionCollection> existingActionCollections = new ArrayList<>();
// Use a synchronised list to avoid concurrent modification exception
List<ActionCollection> newActionCollections =
Collections.synchronizedList(new ArrayList<>());
List<ActionCollection> existingActionCollections =
Collections.synchronizedList(new ArrayList<>());
for (ActionCollection actionCollection : importedActionCollectionList) {
final ActionCollectionDTO unpublishedCollection =
actionCollection.getUnpublishedCollection();
if (unpublishedCollection == null
|| StringUtils.isEmpty(unpublishedCollection.calculateContextId())) {
continue; // invalid action collection, skip it
}
return Flux.fromIterable(importedActionCollectionList)
.flatMap(actionCollection -> {
final ActionCollectionDTO unpublishedCollection =
actionCollection.getUnpublishedCollection();
if (unpublishedCollection == null
|| StringUtils.isEmpty(
unpublishedCollection.calculateContextId())) {
return Mono.empty(); // invalid action collection, skip it
}
String idFromJsonFile = actionCollection.getId();
String idFromJsonFile = actionCollection.getId();
ActionCollection branchedActionCollection = null;
ActionCollection branchedActionCollection = null;
if (actionsCollectionsInBranches.containsKey(actionCollection.getGitSyncId())) {
branchedActionCollection =
artifactBasedImportableService
.getExistingEntityInOtherBranchForImportedEntity(
mappedImportableResourcesDTO,
actionsCollectionsInBranches,
actionCollection);
}
if (actionsCollectionsInBranches.containsKey(
actionCollection.getGitSyncId())) {
branchedActionCollection =
artifactBasedImportableService
.getExistingEntityInOtherBranchForImportedEntity(
mappedImportableResourcesDTO,
actionsCollectionsInBranches,
actionCollection);
}
Context baseContext = populateIdReferencesAndReturnBaseContext(
importingMetaDTO,
mappedImportableResourcesDTO,
artifact,
branchedActionCollection,
actionCollection);
Context baseContext = populateIdReferencesAndReturnBaseContext(
importingMetaDTO,
mappedImportableResourcesDTO,
artifact,
branchedActionCollection,
actionCollection);
// Check if the action has gitSyncId and if it's already in DB
if (existingArtifactContainsCollection(
actionsCollectionsInCurrentArtifact, actionCollection)) {
// Check if the action has gitSyncId and if it's already in DB
if (existingArtifactContainsCollection(
actionsCollectionsInCurrentArtifact, actionCollection)) {
// Since the resource is already present in DB, just update resource
ActionCollection existingActionCollection =
artifactBasedImportableService
.getExistingEntityInCurrentBranchForImportedEntity(
mappedImportableResourcesDTO,
actionsCollectionsInCurrentArtifact,
actionCollection);
// Since the resource is already present in DB, just update resource
ActionCollection existingActionCollection =
artifactBasedImportableService
.getExistingEntityInCurrentBranchForImportedEntity(
mappedImportableResourcesDTO,
actionsCollectionsInCurrentArtifact,
actionCollection);
updateExistingCollection(
importingMetaDTO,
mappedImportableResourcesDTO,
actionCollection,
existingActionCollection);
updateExistingCollection(
importingMetaDTO,
mappedImportableResourcesDTO,
actionCollection,
existingActionCollection);
existingActionCollections.add(existingActionCollection);
resultDTO.getSavedActionCollectionIds().add(existingActionCollection.getId());
resultDTO
.getSavedActionCollectionMap()
.put(idFromJsonFile, existingActionCollection);
} else {
artifactBasedImportableService.createNewResource(
importingMetaDTO, actionCollection, baseContext);
existingActionCollections.add(existingActionCollection);
resultDTO
.getSavedActionCollectionIds()
.add(existingActionCollection.getId());
resultDTO
.getSavedActionCollectionMap()
.put(idFromJsonFile, existingActionCollection);
return Mono.just(existingActionCollection);
}
return artifactBasedImportableService
.createNewResource(importingMetaDTO, actionCollection, baseContext)
.flatMap(updatedActionCollection -> {
// populate the domain mapped references
populateDomainMappedReferences(
mappedImportableResourcesDTO, updatedActionCollection);
populateDomainMappedReferences(mappedImportableResourcesDTO, actionCollection);
// it's new actionCollection
newActionCollections.add(actionCollection);
resultDTO.getSavedActionCollectionIds().add(actionCollection.getId());
resultDTO.getSavedActionCollectionMap().put(idFromJsonFile, actionCollection);
}
}
log.info(
"Saving action collections in bulk. New: {}, Updated: {}",
newActionCollections.size(),
existingActionCollections.size());
return Mono.when(
actionCollectionService
.bulkValidateAndInsertActionCollectionInRepository(
newActionCollections),
actionCollectionService
.bulkValidateAndUpdateActionCollectionInRepository(
existingActionCollections))
.thenReturn(resultDTO);
// it's new actionCollection
newActionCollections.add(updatedActionCollection);
resultDTO
.getSavedActionCollectionIds()
.add(updatedActionCollection.getId());
resultDTO
.getSavedActionCollectionMap()
.put(idFromJsonFile, updatedActionCollection);
return Mono.just(updatedActionCollection);
});
})
.then(Mono.defer(() -> {
log.info(
"Saving action collections in bulk. New: {}, Updated: {}",
newActionCollections.size(),
existingActionCollections.size());
return Mono.when(
actionCollectionService
.bulkValidateAndInsertActionCollectionInRepository(
newActionCollections),
actionCollectionService
.bulkValidateAndUpdateActionCollectionInRepository(
existingActionCollections))
.thenReturn(resultDTO);
}));
});
})
.onErrorResume(e -> {

View File

@ -18,6 +18,7 @@ import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.List;
import java.util.Map;
@ -88,26 +89,31 @@ public class ActionCollectionApplicationImportableServiceCEImpl
}
@Override
public void createNewResource(
public Mono<ActionCollection> createNewResource(
ImportingMetaDTO importingMetaDTO, ActionCollection actionCollection, Context baseContext) {
if (!importingMetaDTO.getPermissionProvider().canCreateAction((NewPage) baseContext)) {
throw new AppsmithException(
AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.PAGE, ((NewPage) baseContext).getId());
}
Mono<Boolean> canCreateAction = importingMetaDTO.getPermissionProvider().canCreateAction((NewPage) baseContext);
return canCreateAction.flatMap(canCreate -> {
if (!canCreate) {
return Mono.error(new AppsmithException(
AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.PAGE, ((NewPage) baseContext).getId()));
}
// this will generate the id and other auto generated fields e.g. createdAt
actionCollection.updateForBulkWriteOperation();
actionCollectionService.generateAndSetPolicies((NewPage) baseContext, actionCollection);
// this will generate the id and other auto generated fields e.g. createdAt
actionCollection.updateForBulkWriteOperation();
actionCollectionService.generateAndSetPolicies((NewPage) baseContext, actionCollection);
// create or update base id for the action
// values already set to base id are kept unchanged
actionCollection.setBaseId(actionCollection.getBaseIdOrFallback());
actionCollection.setRefType(importingMetaDTO.getRefType());
actionCollection.setRefName(importingMetaDTO.getRefName());
// create or update base id for the action
// values already set to base id are kept unchanged
actionCollection.setBaseId(actionCollection.getBaseIdOrFallback());
actionCollection.setRefType(importingMetaDTO.getRefType());
actionCollection.setRefName(importingMetaDTO.getRefName());
// generate gitSyncId if it's not present
if (actionCollection.getGitSyncId() == null) {
actionCollection.setGitSyncId(actionCollection.getApplicationId() + "_" + UUID.randomUUID());
}
// generate gitSyncId if it's not present
if (actionCollection.getGitSyncId() == null) {
actionCollection.setGitSyncId(actionCollection.getApplicationId() + "_" + UUID.randomUUID());
}
return Mono.just(actionCollection);
});
}
}

View File

@ -593,10 +593,9 @@ public class ApplicationServiceCEImpl extends BaseService<ApplicationRepository,
// the same level in the hierarchy. A user may have permission to change view on application, but
// may not have explicit permissions on the datasource.
Mono<Void> updatedDatasourcesMono = datasourceIdsMono
.flatMapMany(datasourceIds -> {
return policySolution.updateWithNewPoliciesToDatasourcesByDatasourceIdsWithoutPermission(
datasourceIds, datasourcePolicyMap, addViewAccess);
})
.flatMapMany(datasourceIds ->
policySolution.updateWithNewPoliciesToDatasourcesByDatasourceIdsWithoutPermission(
datasourceIds, datasourcePolicyMap, addViewAccess))
.then();
list.add(updatedDatasourcesMono);

View File

@ -90,19 +90,21 @@ public class ApplicationImportServiceCEImpl
Map.of(FieldName.ARTIFACT_CONTEXT, FieldName.APPLICATION, FieldName.ID, FieldName.APPLICATION_ID);
@Override
public ImportArtifactPermissionProvider getImportArtifactPermissionProviderForImportingArtifact(
public Mono<ImportArtifactPermissionProvider> getImportArtifactPermissionProviderForImportingArtifact(
Set<String> userPermissionGroups) {
return ImportArtifactPermissionProvider.builder(
applicationPermission,
pagePermission,
actionPermission,
datasourcePermission,
workspacePermission)
.requiredPermissionOnTargetWorkspace(workspacePermission.getApplicationCreatePermission())
.permissionRequiredToCreateDatasource(true)
.permissionRequiredToEditDatasource(true)
.currentUserPermissionGroups(userPermissionGroups)
.build();
return workspacePermission
.getApplicationCreatePermission()
.map(appCreatePermission -> ImportArtifactPermissionProvider.builder(
applicationPermission,
pagePermission,
actionPermission,
datasourcePermission,
workspacePermission)
.requiredPermissionOnTargetWorkspace(appCreatePermission)
.permissionRequiredToCreateDatasource(true)
.permissionRequiredToEditDatasource(true)
.currentUserPermissionGroups(userPermissionGroups)
.build());
}
@Override

View File

@ -1,12 +1,13 @@
package com.appsmith.server.artifacts.permissions;
import com.appsmith.server.acl.AclPermission;
import reactor.core.publisher.Mono;
public interface ArtifactPermissionCE {
AclPermission getEditPermission();
AclPermission getDeletePermission();
Mono<AclPermission> getDeletePermission();
AclPermission getGitConnectPermission();

View File

@ -152,7 +152,9 @@ public class DatasourceServiceCEImpl implements DatasourceServiceCE {
@Override
public Mono<Datasource> create(Datasource datasource) {
return createEx(datasource, workspacePermission.getDatasourceCreatePermission(), false, null);
return workspacePermission
.getDatasourceCreatePermission()
.flatMap(permission -> createEx(datasource, permission, false, null));
}
// TODO: Check usage
@ -880,8 +882,9 @@ public class DatasourceServiceCEImpl implements DatasourceServiceCE {
@Override
public Mono<Datasource> archiveById(String id) {
return repository
.findById(id, datasourcePermission.getDeletePermission())
return datasourcePermission
.getDeletePermission()
.flatMap(permission -> repository.findById(id, permission))
.switchIfEmpty(
Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.DATASOURCE, id)))
.zipWhen(datasource -> newActionRepository.countByDatasourceId(datasource.getId()))

View File

@ -301,43 +301,47 @@ public class DatasourceImportableServiceCEImpl implements ImportableServiceCE<Da
.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()));
}
.switchIfEmpty(Mono.defer(
() -> permissionProvider.canCreateDatasource(workspace).flatMap(canCreateDatasource -> {
// check if user has permission to create datasource
if (!canCreateDatasource) {
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);
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
.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()));
}))
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);

View File

@ -433,8 +433,9 @@ public class ApplicationForkingServiceCEImpl implements ApplicationForkingServic
.switchIfEmpty(Mono.error(new AppsmithException(
AppsmithError.NO_RESOURCE_FOUND, FieldName.APPLICATION, srcApplicationId)));
final Mono<Workspace> targetWorkspaceMono = workspaceService
.findById(targetWorkspaceId, workspacePermission.getApplicationCreatePermission())
final Mono<Workspace> targetWorkspaceMono = workspacePermission
.getApplicationCreatePermission()
.flatMap(permission -> workspaceService.findById(targetWorkspaceId, permission))
.switchIfEmpty(Mono.error(new AppsmithException(
AppsmithError.NO_RESOURCE_FOUND, FieldName.WORKSPACE, targetWorkspaceId)));
@ -636,20 +637,22 @@ public class ApplicationForkingServiceCEImpl implements ApplicationForkingServic
permissionGroupIdsMono,
actionPermission.getEditPermission(),
AppsmithError.APPLICATION_NOT_FORKED_MISSING_PERMISSIONS);
Mono<Boolean> workspaceValidatedForCreateApplicationPermission =
UserPermissionUtils.validateDomainObjectPermissionsOrError(
Mono<Boolean> workspaceValidatedForCreateApplicationPermission = workspacePermission
.getApplicationCreatePermission()
.flatMap(permission -> UserPermissionUtils.validateDomainObjectPermissionsOrError(
workspaceFlux,
FieldName.WORKSPACE,
permissionGroupIdsMono,
workspacePermission.getApplicationCreatePermission(),
AppsmithError.APPLICATION_NOT_FORKED_MISSING_PERMISSIONS);
Mono<Boolean> workspaceValidatedForCreateDatasourcePermission =
UserPermissionUtils.validateDomainObjectPermissionsOrError(
permission,
AppsmithError.APPLICATION_NOT_FORKED_MISSING_PERMISSIONS));
Mono<Boolean> workspaceValidatedForCreateDatasourcePermission = workspacePermission
.getDatasourceCreatePermission()
.flatMap(permission -> UserPermissionUtils.validateDomainObjectPermissionsOrError(
workspaceFlux,
FieldName.WORKSPACE,
permissionGroupIdsMono,
workspacePermission.getDatasourceCreatePermission(),
AppsmithError.APPLICATION_NOT_FORKED_MISSING_PERMISSIONS);
permission,
AppsmithError.APPLICATION_NOT_FORKED_MISSING_PERMISSIONS));
return Mono.when(
pagesValidatedForPermission,

View File

@ -7,17 +7,17 @@ import java.util.Map;
public interface EmailServiceHelperCE {
Mono<Map<String, String>> enrichWithBrandParams(Map<String, String> params, String origin);
String getForgotPasswordTemplate();
Mono<String> getForgotPasswordTemplate();
String getWorkspaceInviteTemplate(boolean isNewUser);
Mono<String> getWorkspaceInviteTemplate(boolean isNewUser);
String getEmailVerificationTemplate();
Mono<String> getEmailVerificationTemplate();
String getAdminInstanceInviteTemplate();
Mono<String> getAdminInstanceInviteTemplate();
String getJoinInstanceCtaPrimaryText();
Mono<String> getJoinInstanceCtaPrimaryText();
String getSubjectJoinInstanceAsAdmin(String instanceName);
Mono<String> getSubjectJoinInstanceAsAdmin(String instanceName);
String getSubjectJoinWorkspace(String workspaceName);
Mono<String> getSubjectJoinWorkspace(String workspaceName);
}

View File

@ -36,39 +36,39 @@ public class EmailServiceHelperCEImpl implements EmailServiceHelperCE {
}
@Override
public String getForgotPasswordTemplate() {
return FORGOT_PASSWORD_TEMPLATE_CE;
public Mono<String> getForgotPasswordTemplate() {
return Mono.just(FORGOT_PASSWORD_TEMPLATE_CE);
}
@Override
public String getWorkspaceInviteTemplate(boolean isNewUser) {
if (isNewUser) return INVITE_WORKSPACE_TEMPLATE_NEW_USER_CE;
public Mono<String> getWorkspaceInviteTemplate(boolean isNewUser) {
if (isNewUser) return Mono.just(INVITE_WORKSPACE_TEMPLATE_NEW_USER_CE);
return INVITE_WORKSPACE_TEMPLATE_EXISTING_USER_CE;
return Mono.just(INVITE_WORKSPACE_TEMPLATE_EXISTING_USER_CE);
}
@Override
public String getEmailVerificationTemplate() {
return EMAIL_VERIFICATION_EMAIL_TEMPLATE_CE;
public Mono<String> getEmailVerificationTemplate() {
return Mono.just(EMAIL_VERIFICATION_EMAIL_TEMPLATE_CE);
}
@Override
public String getAdminInstanceInviteTemplate() {
return INSTANCE_ADMIN_INVITE_EMAIL_TEMPLATE;
public Mono<String> getAdminInstanceInviteTemplate() {
return Mono.just(INSTANCE_ADMIN_INVITE_EMAIL_TEMPLATE);
}
@Override
public String getJoinInstanceCtaPrimaryText() {
return PRIMARY_LINK_TEXT_INVITE_TO_INSTANCE_CE;
public Mono<String> getJoinInstanceCtaPrimaryText() {
return Mono.just(PRIMARY_LINK_TEXT_INVITE_TO_INSTANCE_CE);
}
@Override
public String getSubjectJoinInstanceAsAdmin(String instanceName) {
return INSTANCE_ADMIN_INVITE_EMAIL_SUBJECT;
public Mono<String> getSubjectJoinInstanceAsAdmin(String instanceName) {
return Mono.just(INSTANCE_ADMIN_INVITE_EMAIL_SUBJECT);
}
@Override
public String getSubjectJoinWorkspace(String workspaceName) {
return INVITE_TO_WORKSPACE_EMAIL_SUBJECT_CE;
public Mono<String> getSubjectJoinWorkspace(String workspaceName) {
return Mono.just(INVITE_TO_WORKSPACE_EMAIL_SUBJECT_CE);
}
}

View File

@ -16,6 +16,7 @@ import com.appsmith.server.solutions.WorkspacePermission;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import reactor.core.publisher.Mono;
import java.util.Set;
@ -116,24 +117,28 @@ public class ImportArtifactPermissionProviderCE {
return hasPermission(datasourcePermission.getEditPermission(), datasource);
}
public boolean canCreatePage(Application application) {
public Mono<Boolean> canCreatePage(Application application) {
if (!permissionRequiredToCreatePage) {
return true;
return Mono.just(true);
}
return hasPermission(((ApplicationPermission) artifactPermission).getPageCreatePermission(), application);
return ((ApplicationPermission) artifactPermission)
.getPageCreatePermission()
.map(permission -> hasPermission(permission, application));
}
public boolean canCreateAction(NewPage page) {
public Mono<Boolean> canCreateAction(NewPage page) {
if (!permissionRequiredToCreateAction) {
return true;
return Mono.just(true);
}
return hasPermission(contextPermission.getActionCreatePermission(), page);
return contextPermission.getActionCreatePermission().map(permission -> hasPermission(permission, page));
}
public boolean canCreateDatasource(Workspace workspace) {
public Mono<Boolean> canCreateDatasource(Workspace workspace) {
if (!permissionRequiredToCreateDatasource) {
return true;
return Mono.just(true);
}
return hasPermission(workspacePermission.getDatasourceCreatePermission(), workspace);
return workspacePermission
.getDatasourceCreatePermission()
.map(permission -> hasPermission(permission, workspace));
}
}

View File

@ -8,6 +8,7 @@ import com.appsmith.server.domains.Context;
import com.appsmith.server.dtos.ImportingMetaDTO;
import com.appsmith.server.dtos.MappedImportableResourcesDTO;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.List;
import java.util.Map;
@ -40,7 +41,7 @@ public interface ArtifactBasedImportableServiceCE<T extends BaseDomain, U extend
}
}
void createNewResource(ImportingMetaDTO importingMetaDTO, T actionCollection, Context baseContext);
Mono<T> createNewResource(ImportingMetaDTO importingMetaDTO, T entity, Context baseContext);
default T getExistingEntityInCurrentBranchForImportedEntity(
MappedImportableResourcesDTO mappedImportableResourcesDTO,

View File

@ -193,10 +193,7 @@ public class ImportServiceCEImpl implements ImportServiceCE {
getArtifactBasedImportService(artifactExchangeJson);
return permissionGroupRepository
.getCurrentUserPermissionGroups()
.zipWhen(userPermissionGroup -> {
return Mono.just(contextBasedImportService.getImportArtifactPermissionProviderForImportingArtifact(
userPermissionGroup));
})
.zipWhen(contextBasedImportService::getImportArtifactPermissionProviderForImportingArtifact)
.flatMap(tuple2 -> {
Set<String> userPermissionGroup = tuple2.getT1();
ImportArtifactPermissionProvider permissionProvider = tuple2.getT2();

View File

@ -19,7 +19,7 @@ import java.util.Set;
public interface ArtifactBasedImportServiceCE<
T extends Artifact, U extends ArtifactImportDTO, V extends ArtifactExchangeJson> {
ImportArtifactPermissionProvider getImportArtifactPermissionProviderForImportingArtifact(
Mono<ImportArtifactPermissionProvider> getImportArtifactPermissionProviderForImportingArtifact(
Set<String> userPermissions);
ImportArtifactPermissionProvider getImportArtifactPermissionProviderForUpdatingArtifact(

View File

@ -795,7 +795,7 @@ public class NewActionServiceCEImpl extends BaseService<NewActionRepository, New
@Override
public Mono<ActionDTO> deleteUnpublishedAction(String id) {
return deleteUnpublishedAction(id, actionPermission.getDeletePermission());
return actionPermission.getDeletePermission().flatMap(permission -> deleteUnpublishedAction(id, permission));
}
@Override

View File

@ -315,82 +315,95 @@ public class NewActionImportableServiceCEImpl implements ImportableServiceCE<New
// this will be required in next phases when we'll delete the outdated actions
importActionResultDTO.setExistingActions(actionsInCurrentArtifact.values());
List<NewAction> newNewActionList = new ArrayList<>();
List<NewAction> existingNewActionList = new ArrayList<>();
// Use synchronised lists to avoid concurrent modification exceptions
List<NewAction> newNewActionList = Collections.synchronizedList(new ArrayList<>());
List<NewAction> existingNewActionList = Collections.synchronizedList(new ArrayList<>());
for (NewAction newAction : importedNewActionList) {
ActionDTO unpublishedAction = newAction.getUnpublishedAction();
if (unpublishedAction == null
|| !StringUtils.hasLength(unpublishedAction.calculateContextId())) {
continue; // invalid action, skip it
}
return Flux.fromIterable(importedNewActionList)
.flatMap(newAction -> {
ActionDTO unpublishedAction = newAction.getUnpublishedAction();
if (unpublishedAction == null
|| !StringUtils.hasLength(unpublishedAction.calculateContextId())) {
return Mono.empty(); // invalid action, skip it
}
NewAction branchedNewAction = null;
NewAction branchedNewAction = null;
if (actionsInBranches.containsKey(newAction.getGitSyncId())) {
branchedNewAction =
artifactBasedImportableService.getExistingEntityInOtherBranchForImportedEntity(
mappedImportableResourcesDTO, actionsInBranches, newAction);
}
if (actionsInBranches.containsKey(newAction.getGitSyncId())) {
branchedNewAction =
artifactBasedImportableService
.getExistingEntityInOtherBranchForImportedEntity(
mappedImportableResourcesDTO,
actionsInBranches,
newAction);
}
Context baseContext = populateIdReferencesAndReturnBaseContext(
importingMetaDTO,
mappedImportableResourcesDTO,
artifact,
branchedNewAction,
newAction);
Context baseContext = populateIdReferencesAndReturnBaseContext(
importingMetaDTO,
mappedImportableResourcesDTO,
artifact,
branchedNewAction,
newAction);
// Check if the action has datasource is present and contains pluginId
Datasource datasource =
newAction.getUnpublishedAction().getDatasource();
if (datasource != null) {
// Since the datasource are not yet saved to db, if we don't update the action with
// correct datasource,
// the action ave will fail due to validation
updateDatasourceInAction(newAction, mappedImportableResourcesDTO, datasource);
}
// Check if the action has datasource is present and contains pluginId
Datasource datasource =
newAction.getUnpublishedAction().getDatasource();
if (datasource != null) {
// Since the datasource are not yet saved to db, if we don't update the action
// with
// correct datasource,
// the action ave will fail due to validation
updateDatasourceInAction(newAction, mappedImportableResourcesDTO, datasource);
}
// Check if the action has gitSyncId and if it's already in DB
if (existingArtifactContainsAction(actionsInCurrentArtifact, newAction)) {
// Check if the action has gitSyncId and if it's already in DB
if (existingArtifactContainsAction(actionsInCurrentArtifact, newAction)) {
// Since the resource is already present in DB, just update resource
NewAction existingAction =
artifactBasedImportableService
.getExistingEntityInCurrentBranchForImportedEntity(
mappedImportableResourcesDTO,
actionsInCurrentArtifact,
newAction);
// Since the resource is already present in DB, just update resource
NewAction existingAction =
artifactBasedImportableService
.getExistingEntityInCurrentBranchForImportedEntity(
mappedImportableResourcesDTO,
actionsInCurrentArtifact,
newAction);
updateExistingAction(existingAction, newAction, importingMetaDTO);
updateExistingAction(existingAction, newAction, importingMetaDTO);
// Add it to actions list that'll be updated in bulk
existingNewActionList.add(existingAction);
importActionResultDTO.getImportedActionIds().add(existingAction.getId());
putActionIdInMap(existingAction, importActionResultDTO);
} else {
// Add it to actions list that'll be updated in bulk
existingNewActionList.add(existingAction);
importActionResultDTO
.getImportedActionIds()
.add(existingAction.getId());
putActionIdInMap(existingAction, importActionResultDTO);
return Mono.just(existingAction);
}
return artifactBasedImportableService
.createNewResource(importingMetaDTO, newAction, baseContext)
.flatMap(updatedAction -> {
populateDomainMappedReferences(
mappedImportableResourcesDTO, updatedAction);
artifactBasedImportableService.createNewResource(
importingMetaDTO, newAction, baseContext);
// Add it to actions list that'll be inserted or updated in bulk
newNewActionList.add(updatedAction);
populateDomainMappedReferences(mappedImportableResourcesDTO, newAction);
// Add it to actions list that'll be inserted or updated in bulk
newNewActionList.add(newAction);
importActionResultDTO.getImportedActionIds().add(newAction.getId());
putActionIdInMap(newAction, importActionResultDTO);
}
}
log.info(
"Saving actions in bulk. New: {}, Updated: {}",
newNewActionList.size(),
existingNewActionList.size());
// Save all the new actions in bulk
return Mono.when(
newActionService.bulkValidateAndInsertActionInRepository(newNewActionList),
newActionService.bulkValidateAndUpdateActionInRepository(existingNewActionList))
importActionResultDTO
.getImportedActionIds()
.add(updatedAction.getId());
putActionIdInMap(updatedAction, importActionResultDTO);
return Mono.just(updatedAction);
});
})
.then(Mono.defer(() -> {
log.info(
"Saving actions in bulk. New: {}, Updated: {}",
newNewActionList.size(),
existingNewActionList.size());
// Save all the new actions in bulk
return Mono.when(
newActionService.bulkValidateAndInsertActionInRepository(newNewActionList),
newActionService.bulkValidateAndUpdateActionInRepository(
existingNewActionList));
}))
.thenReturn(importActionResultDTO);
});
});

View File

@ -18,6 +18,7 @@ import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.List;
import java.util.Map;
@ -89,25 +90,31 @@ public class NewActionApplicationImportableServiceCEImpl
}
@Override
public void createNewResource(ImportingMetaDTO importingMetaDTO, NewAction newAction, Context baseContext) {
if (!importingMetaDTO.getPermissionProvider().canCreateAction((NewPage) baseContext)) {
throw new AppsmithException(
AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.PAGE, ((NewPage) baseContext).getId());
}
public Mono<NewAction> createNewResource(
ImportingMetaDTO importingMetaDTO, NewAction newAction, Context baseContext) {
Mono<Boolean> canCreateActionMono =
importingMetaDTO.getPermissionProvider().canCreateAction((NewPage) baseContext);
return canCreateActionMono.flatMap(canCreateAction -> {
if (!canCreateAction) {
return Mono.error(new AppsmithException(
AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.PAGE, ((NewPage) baseContext).getId()));
}
// this will generate the id and other auto generated fields e.g. createdAt
newAction.updateForBulkWriteOperation();
newActionService.generateAndSetActionPolicies((NewPage) baseContext, newAction);
// this will generate the id and other auto generated fields e.g. createdAt
newAction.updateForBulkWriteOperation();
newActionService.generateAndSetActionPolicies((NewPage) baseContext, newAction);
// create or update base id for the action
// values already set to base id are kept unchanged
newAction.setBaseId(newAction.getBaseIdOrFallback());
newAction.setRefType(importingMetaDTO.getRefType());
newAction.setRefName(importingMetaDTO.getRefName());
// create or update base id for the action
// values already set to base id are kept unchanged
newAction.setBaseId(newAction.getBaseIdOrFallback());
newAction.setRefType(importingMetaDTO.getRefType());
newAction.setRefName(importingMetaDTO.getRefName());
// generate gitSyncId if it's not present
if (newAction.getGitSyncId() == null) {
newAction.setGitSyncId(newAction.getApplicationId() + "_" + UUID.randomUUID());
}
// generate gitSyncId if it's not present
if (newAction.getGitSyncId() == null) {
newAction.setGitSyncId(newAction.getApplicationId() + "_" + UUID.randomUUID());
}
return Mono.just(newAction);
});
}
}

View File

@ -477,7 +477,7 @@ public class NewPageServiceCEImpl extends BaseService<NewPageRepository, NewPage
@Override
public Mono<NewPage> archiveById(String id) {
return archiveByIdEx(id, pagePermission.getDeletePermission());
return pagePermission.getDeletePermission().flatMap(permission -> archiveByIdEx(id, permission));
}
@Override

View File

@ -462,38 +462,42 @@ public class NewPageImportableServiceCEImpl implements ImportableServiceCE<NewPa
existingPage.setDeletedAt(newPage.getDeletedAt());
existingPage.setPolicies(existingPagePolicy);
return newPageService.save(existingPage);
} else {
// check if user has permission to add new page to the application
if (!importingMetaDTO.getPermissionProvider().canCreatePage(application)) {
log.error(
"User does not have permission to create page in application with id: {}",
application.getId());
return Mono.error(new AppsmithException(
AppsmithError.ACL_NO_RESOURCE_FOUND,
FieldName.APPLICATION,
application.getId()));
}
if (application.getGitApplicationMetadata() != null) {
if (!pagesFromOtherBranches.containsKey(newPage.getGitSyncId())) {
return saveNewPageAndUpdateBaseId(newPage, importingMetaDTO);
}
NewPage branchedPage = pagesFromOtherBranches.get(newPage.getGitSyncId());
newPage.setBaseId(branchedPage.getBaseId());
newPage.setRefType(importingMetaDTO.getRefType());
newPage.setRefName(importingMetaDTO.getRefName());
newPage.getUnpublishedPage()
.setDeletedAt(branchedPage
.getUnpublishedPage()
.getDeletedAt());
newPage.setDeletedAt(branchedPage.getDeletedAt());
// Set policies from existing branch object
newPage.setPolicies(branchedPage.getPolicies());
return newPageService.save(newPage);
}
return saveNewPageAndUpdateBaseId(newPage, importingMetaDTO);
}
// check if user has permission to add new page to the application
return importingMetaDTO
.getPermissionProvider()
.canCreatePage(application)
.flatMap(canCreatePage -> {
if (!canCreatePage) {
log.error(
"User does not have permission to create page in application with id: {}",
application.getId());
return Mono.error(new AppsmithException(
AppsmithError.ACL_NO_RESOURCE_FOUND,
FieldName.APPLICATION,
application.getId()));
}
if (application.getGitApplicationMetadata() != null) {
if (!pagesFromOtherBranches.containsKey(newPage.getGitSyncId())) {
return saveNewPageAndUpdateBaseId(newPage, importingMetaDTO);
}
NewPage branchedPage = pagesFromOtherBranches.get(newPage.getGitSyncId());
newPage.setBaseId(branchedPage.getBaseId());
newPage.setRefType(importingMetaDTO.getRefType());
newPage.setRefName(importingMetaDTO.getRefName());
newPage.getUnpublishedPage()
.setDeletedAt(branchedPage
.getUnpublishedPage()
.getDeletedAt());
newPage.setDeletedAt(branchedPage.getDeletedAt());
// Set policies from existing branch object
newPage.setPolicies(branchedPage.getPolicies());
return newPageService.save(newPage);
}
return saveNewPageAndUpdateBaseId(newPage, importingMetaDTO);
});
});
})
.onErrorResume(error -> {

View File

@ -158,8 +158,9 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE {
}
}
Mono<Application> applicationMono = applicationService
.findById(page.getApplicationId(), applicationPermission.getPageCreatePermission())
Mono<Application> applicationMono = applicationPermission
.getPageCreatePermission()
.flatMap(permission -> applicationService.findById(page.getApplicationId(), permission))
.switchIfEmpty(Mono.error(new AppsmithException(
AppsmithError.NO_RESOURCE_FOUND, FieldName.APPLICATION, page.getApplicationId())))
.cache();
@ -475,8 +476,9 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE {
@Override
public Mono<Application> setApplicationPolicies(Mono<User> userMono, String workspaceId, Application application) {
return userMono.flatMap(user -> {
Mono<Workspace> workspaceMono = workspaceRepository
.findById(workspaceId, workspacePermission.getApplicationCreatePermission())
Mono<Workspace> workspaceMono = workspacePermission
.getApplicationCreatePermission()
.flatMap(permission -> workspaceRepository.findById(workspaceId, permission))
.switchIfEmpty(Mono.error(
new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.WORKSPACE, workspaceId)));
@ -506,8 +508,9 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE {
public Mono<Application> deleteApplication(String id) {
log.debug("Archiving application with id: {}", id);
Mono<Application> applicationMono = applicationRepository
.findById(id, applicationPermission.getDeletePermission())
Mono<Application> applicationMono = applicationPermission
.getDeletePermission()
.flatMap(permission -> applicationRepository.findById(id, permission))
.switchIfEmpty(
Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.APPLICATION, id)))
.cache();
@ -521,8 +524,10 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE {
.flatMapMany(application -> {
GitArtifactMetadata gitData = application.getGitApplicationMetadata();
if (GitUtils.isArtifactConnectedToGit(application.getGitArtifactMetadata())) {
return applicationService.findAllApplicationsByBaseApplicationId(
gitData.getDefaultArtifactId(), applicationPermission.getDeletePermission());
return applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findAllApplicationsByBaseApplicationId(
gitData.getDefaultArtifactId(), permission));
}
return Flux.fromIterable(List.of(application));
})
@ -554,12 +559,16 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE {
}
protected Mono<Application> 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<AclPermission> actionPermissionMono =
actionPermission.getDeletePermission().cache();
Mono<AclPermission> pagePermissionMono = pagePermission.getDeletePermission();
return actionPermissionMono
.flatMap(actionDeletePermission -> actionCollectionService.archiveActionCollectionByApplicationId(
application.getId(), actionDeletePermission))
.then(actionPermissionMono.flatMap(actionDeletePermission ->
newActionService.archiveActionsByApplicationId(application.getId(), actionDeletePermission)))
.then(pagePermissionMono.flatMap(pageDeletePermission ->
newPageService.archivePagesByApplicationId(application.getId(), pageDeletePermission)))
.then(themeService.archiveApplicationThemes(application))
.flatMap(applicationService::archive);
}
@ -904,12 +913,19 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE {
@Override
public Mono<PageDTO> deleteUnpublishedPage(String id) {
return deleteUnpublishedPageEx(
id,
pagePermission.getDeletePermission(),
applicationPermission.getReadPermission(),
actionPermission.getDeletePermission(),
actionPermission.getDeletePermission());
return pagePermission
.getDeletePermission()
.zipWith(actionPermission.getDeletePermission())
.flatMap(tuple -> {
AclPermission pageDeletePermission = tuple.getT1();
AclPermission actionDeletePermission = tuple.getT2();
return deleteUnpublishedPageEx(
id,
pageDeletePermission,
applicationPermission.getReadPermission(),
actionDeletePermission,
actionDeletePermission);
});
}
private Mono<PageDTO> deleteUnpublishedPageEx(
@ -1478,12 +1494,14 @@ public class ApplicationPageServiceCEImpl implements ApplicationPageServiceCE {
return datasourceRepository.setUserPermissionsInObject(datasource);
}));
return UserPermissionUtils.validateDomainObjectPermissionsOrError(
return datasourcePermission
.getActionCreatePermission()
.flatMap(actionCreatePermission -> UserPermissionUtils.validateDomainObjectPermissionsOrError(
datasourceFlux,
FieldName.DATASOURCE,
permissionGroupService.getSessionUserPermissionGroupIds(),
datasourcePermission.getActionCreatePermission(),
AppsmithError.APPLICATION_NOT_CLONED_MISSING_PERMISSIONS)
actionCreatePermission,
AppsmithError.APPLICATION_NOT_CLONED_MISSING_PERMISSIONS))
.thenReturn(Boolean.TRUE);
}
}

View File

@ -34,11 +34,16 @@ public class EmailServiceCEImpl implements EmailServiceCE {
params.put(RESET_URL, resetUrl);
return emailServiceHelper
.enrichWithBrandParams(params, originHeader)
.flatMap(updatedParams -> emailSender.sendMail(
email,
String.format(FORGOT_PASSWORD_EMAIL_SUBJECT, updatedParams.get(INSTANCE_NAME)),
emailServiceHelper.getForgotPasswordTemplate(),
updatedParams));
.zipWith(emailServiceHelper.getForgotPasswordTemplate())
.flatMap(tuple2 -> {
Map<String, String> updatedParams = tuple2.getT1();
String forgotPasswordTemplate = tuple2.getT2();
return emailSender.sendMail(
email,
String.format(FORGOT_PASSWORD_EMAIL_SUBJECT, updatedParams.get(INSTANCE_NAME)),
forgotPasswordTemplate,
updatedParams);
});
}
@Override
@ -55,16 +60,20 @@ public class EmailServiceCEImpl implements EmailServiceCE {
originHeader,
URLEncoder.encode(invitedUser.getUsername().toLowerCase(), StandardCharsets.UTF_8))
: originHeader;
String emailSubject = emailServiceHelper.getSubjectJoinWorkspace(workspaceInvitedTo.getName());
Mono<String> emailSubjectMono = emailServiceHelper.getSubjectJoinWorkspace(workspaceInvitedTo.getName());
Mono<String> workspaceInviteTemplateMono = emailServiceHelper.getWorkspaceInviteTemplate(isNewUser);
Map<String, String> 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(Mono.zip(emailSubjectMono, workspaceInviteTemplateMono))
.flatMap(objects -> {
Map<String, String> updatedParams = objects.getT1();
String emailSubject = objects.getT2().getT1();
String workspaceInviteTemplate = objects.getT2().getT2();
return emailSender.sendMail(
invitedUser.getEmail(), emailSubject, workspaceInviteTemplate, updatedParams);
});
}
@Override
@ -73,11 +82,16 @@ public class EmailServiceCEImpl implements EmailServiceCE {
params.put(EMAIL_VERIFICATION_URL, verificationURL);
return emailServiceHelper
.enrichWithBrandParams(params, originHeader)
.flatMap(updatedParams -> emailSender.sendMail(
user.getEmail(),
EMAIL_VERIFICATION_EMAIL_SUBJECT,
emailServiceHelper.getEmailVerificationTemplate(),
updatedParams));
.zipWith(emailServiceHelper.getEmailVerificationTemplate())
.flatMap(tuple2 -> {
Map<String, String> updatedParams = tuple2.getT1();
String emailVerificationTemplate = tuple2.getT2();
return emailSender.sendMail(
user.getEmail(),
EMAIL_VERIFICATION_EMAIL_SUBJECT,
emailVerificationTemplate,
updatedParams);
});
}
@Override
@ -92,21 +106,28 @@ public class EmailServiceCEImpl implements EmailServiceCE {
: originHeader;
params.put(PRIMARY_LINK_URL, inviteUrl);
String primaryLinkText = emailServiceHelper.getJoinInstanceCtaPrimaryText();
params.put(PRIMARY_LINK_TEXT, primaryLinkText);
Mono<String> primaryLinkTextMono = emailServiceHelper.getJoinInstanceCtaPrimaryText();
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 primaryLinkTextMono
.flatMap(primaryLinkText -> {
params.put(PRIMARY_LINK_TEXT, primaryLinkText);
return emailServiceHelper.enrichWithBrandParams(params, originHeader);
})
.zipWhen(updatedParams -> {
return Mono.zip(
emailServiceHelper.getSubjectJoinInstanceAsAdmin(updatedParams.get(INSTANCE_NAME)),
emailServiceHelper.getAdminInstanceInviteTemplate());
})
.flatMap(objects -> {
Map<String, String> updatedParams = objects.getT1();
String subject = objects.getT2().getT1();
String adminInstanceInviteTemplate = objects.getT2().getT2();
return emailSender.sendMail(
invitedUser.getEmail(), subject, adminInstanceInviteTemplate, updatedParams);
});
}
private Map<String, String> getInviteToWorkspaceEmailParams(

View File

@ -145,8 +145,9 @@ public class LayoutActionServiceCEImpl implements LayoutActionServiceCE {
final String destinationPageId = actionMoveDTO.getDestinationPageId();
action.setPageId(destinationPageId);
Mono<NewPage> destinationPageMono = newPageService
.findById(destinationPageId, pagePermission.getActionCreatePermission())
Mono<NewPage> destinationPageMono = pagePermission
.getActionCreatePermission()
.flatMap(permission -> newPageService.findById(destinationPageId, permission))
.switchIfEmpty(Mono.error(
new AppsmithException(AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.PAGE, destinationPageId)));
@ -186,10 +187,10 @@ public class LayoutActionServiceCEImpl implements LayoutActionServiceCE {
.collect(toSet());
})
// fetch the unpublished destination page
.then(newPageService.findPageById(
actionMoveDTO.getDestinationPageId(),
pagePermission.getActionCreatePermission(),
false))
.then(pagePermission
.getActionCreatePermission()
.flatMap(permission -> newPageService.findPageById(
actionMoveDTO.getDestinationPageId(), permission, false)))
.flatMap(page -> {
if (page.getLayouts() == null) {
return Mono.empty();
@ -339,11 +340,11 @@ public class LayoutActionServiceCEImpl implements LayoutActionServiceCE {
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.PAGE_ID));
}
AclPermission aclPermission =
isJsAction ? pagePermission.getReadPermission() : pagePermission.getActionCreatePermission();
Mono<AclPermission> aclPermissionMono =
isJsAction ? Mono.just(pagePermission.getReadPermission()) : pagePermission.getActionCreatePermission();
return newPageService
.findById(actionDTO.getPageId(), aclPermission)
return aclPermissionMono
.flatMap(permission -> newPageService.findById(actionDTO.getPageId(), permission))
.switchIfEmpty(Mono.error(
new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.PAGE, actionDTO.getPageId())))
.flatMap(newPage -> {
@ -427,13 +428,13 @@ public class LayoutActionServiceCEImpl implements LayoutActionServiceCE {
}
// 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<AclPermission> aclPermissionMono =
isJsAction ? Mono.just(pagePermission.getReadPermission()) : pagePermission.getActionCreatePermission();
Mono<NewPage> pageMono = newPage != null
? Mono.just(newPage)
: newPageService
.findById(action.getPageId(), aclPermission)
: aclPermissionMono
.flatMap(permission -> newPageService.findById(action.getPageId(), permission))
.name(GET_PAGE_BY_ID)
.tap(Micrometer.observation(observationRegistry))
.switchIfEmpty(Mono.error(new AppsmithException(

View File

@ -118,8 +118,9 @@ public class LayoutCollectionServiceCEImpl implements LayoutCollectionServiceCE
protected Mono<Boolean> checkIfNameAllowedBasedOnContext(ActionCollectionDTO collectionDTO) {
final String pageId = collectionDTO.getPageId();
Mono<NewPage> pageMono = newPageService
.findById(pageId, pagePermission.getActionCreatePermission())
Mono<NewPage> pageMono = pagePermission
.getActionCreatePermission()
.flatMap(permission -> newPageService.findById(pageId, permission))
.switchIfEmpty(
Mono.error(new AppsmithException(AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.PAGE, pageId)))
.cache();
@ -156,8 +157,9 @@ public class LayoutCollectionServiceCEImpl implements LayoutCollectionServiceCE
ActionCollection actionCollection = new ActionCollection();
actionCollection.setUnpublishedCollection(collectionDTO);
return newPageService
.findById(collectionDTO.getPageId(), pagePermission.getActionCreatePermission())
return pagePermission
.getActionCreatePermission()
.flatMap(permission -> newPageService.findById(collectionDTO.getPageId(), permission))
.map(branchedPage -> {
actionCollection.setRefType(branchedPage.getRefType());
actionCollection.setRefName(branchedPage.getRefName());
@ -180,8 +182,10 @@ public class LayoutCollectionServiceCEImpl implements LayoutCollectionServiceCE
final String collectionId = actionCollectionMoveDTO.getCollectionId();
final String destinationPageId = actionCollectionMoveDTO.getDestinationPageId();
Mono<NewPage> destinationPageMono = newPageService
.findById(actionCollectionMoveDTO.getDestinationPageId(), pagePermission.getActionCreatePermission())
Mono<NewPage> destinationPageMono = pagePermission
.getActionCreatePermission()
.flatMap(permission ->
newPageService.findById(actionCollectionMoveDTO.getDestinationPageId(), permission))
.switchIfEmpty(Mono.error(
new AppsmithException(AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.PAGE, destinationPageId)))
.cache();
@ -242,10 +246,10 @@ public class LayoutCollectionServiceCEImpl implements LayoutCollectionServiceCE
.collect(toSet());
})
// fetch the unpublished destination page
.then(newPageService.findPageById(
actionCollectionMoveDTO.getDestinationPageId(),
pagePermission.getActionCreatePermission(),
false))
.then(pagePermission
.getActionCreatePermission()
.flatMap(permission -> newPageService.findPageById(
actionCollectionMoveDTO.getDestinationPageId(), permission, false)))
.flatMap(page -> {
if (page.getLayouts() == null) {
return Mono.empty();

View File

@ -22,7 +22,7 @@ public interface UserWorkspaceServiceCE {
Mono<Map<String, List<MemberInfoDTO>>> getWorkspaceMembers(Set<String> workspaceIds);
Boolean isLastAdminRoleEntity(PermissionGroup permissionGroup);
Mono<Boolean> isLastAdminRoleEntity(PermissionGroup permissionGroup);
Mono<List<Workspace>> getUserWorkspacesByRecentlyUsedOrder(String hostname);
}

View File

@ -41,6 +41,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.appsmith.server.helpers.ce.DomainSorter.sortDomainsBasedOnOrderedDomainIds;
import static java.lang.Boolean.TRUE;
@Slf4j
@Service
@ -165,8 +166,11 @@ public class UserWorkspaceServiceCEImpl implements UserWorkspaceServiceCE {
.switchIfEmpty(Mono.error(new AppsmithException(
AppsmithError.ACTION_IS_NOT_AUTHORIZED, "Change permissionGroup of a member")))
.single()
.flatMap(permissionGroup -> {
if (this.isLastAdminRoleEntity(permissionGroup)) {
.zipWhen(permissionGroup -> isLastAdminRoleEntity(permissionGroup))
.flatMap(tuple2 -> {
PermissionGroup permissionGroup = tuple2.getT1();
Boolean isLastAdminRoleEntity = tuple2.getT2();
if (TRUE.equals(isLastAdminRoleEntity)) {
return Mono.error(new AppsmithException(AppsmithError.REMOVE_LAST_WORKSPACE_ADMIN_ERROR));
}
return Mono.just(permissionGroup);
@ -383,9 +387,9 @@ public class UserWorkspaceServiceCEImpl implements UserWorkspaceServiceCE {
}
@Override
public Boolean isLastAdminRoleEntity(PermissionGroup permissionGroup) {
return permissionGroup.getName().startsWith(FieldName.ADMINISTRATOR)
&& permissionGroup.getAssignedToUserIds().size() == 1;
public Mono<Boolean> isLastAdminRoleEntity(PermissionGroup permissionGroup) {
return Mono.just(permissionGroup.getName().startsWith(FieldName.ADMINISTRATOR)
&& permissionGroup.getAssignedToUserIds().size() == 1);
}
/**

View File

@ -571,8 +571,9 @@ public class WorkspaceServiceCEImpl extends BaseService<WorkspaceRepository, Wor
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 workspacePermission
.getDeletePermission()
.flatMap(permission -> repository.findById(workspaceId, permission))
.switchIfEmpty(Mono.error(new AppsmithException(
AppsmithError.NO_RESOURCE_FOUND, FieldName.WORKSPACE, workspaceId)))
.flatMap(workspace -> {

View File

@ -1,9 +1,10 @@
package com.appsmith.server.solutions.ce;
import com.appsmith.server.acl.AclPermission;
import reactor.core.publisher.Mono;
public interface ActionPermissionCE {
AclPermission getDeletePermission();
Mono<AclPermission> getDeletePermission();
AclPermission getExecutePermission();
}

View File

@ -2,6 +2,7 @@ package com.appsmith.server.solutions.ce;
import com.appsmith.server.acl.AclPermission;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import static java.lang.Boolean.TRUE;
@ -28,7 +29,7 @@ public class ActionPermissionCEImpl implements ActionPermissionCE, DomainPermiss
}
@Override
public AclPermission getDeletePermission() {
return AclPermission.MANAGE_ACTIONS;
public Mono<AclPermission> getDeletePermission() {
return Mono.just(AclPermission.MANAGE_ACTIONS);
}
}

View File

@ -2,6 +2,7 @@ package com.appsmith.server.solutions.ce;
import com.appsmith.server.acl.AclPermission;
import com.appsmith.server.artifacts.permissions.ArtifactPermission;
import reactor.core.publisher.Mono;
public interface ApplicationPermissionCE extends ArtifactPermission {
@ -9,7 +10,7 @@ public interface ApplicationPermissionCE extends ArtifactPermission {
AclPermission getCanCommentPermission();
AclPermission getPageCreatePermission();
Mono<AclPermission> getPageCreatePermission();
AclPermission getManageProtectedBranchPermission();

View File

@ -2,6 +2,7 @@ package com.appsmith.server.solutions.ce;
import com.appsmith.server.acl.AclPermission;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
@Component
public class ApplicationPermissionCEImpl implements ApplicationPermissionCE, DomainPermissionCE {
@ -32,8 +33,8 @@ public class ApplicationPermissionCEImpl implements ApplicationPermissionCE, Dom
}
@Override
public AclPermission getDeletePermission() {
return AclPermission.MANAGE_APPLICATIONS;
public Mono<AclPermission> getDeletePermission() {
return Mono.just(AclPermission.MANAGE_APPLICATIONS);
}
@Override
@ -47,8 +48,8 @@ public class ApplicationPermissionCEImpl implements ApplicationPermissionCE, Dom
}
@Override
public AclPermission getPageCreatePermission() {
return AclPermission.MANAGE_APPLICATIONS;
public Mono<AclPermission> getPageCreatePermission() {
return Mono.just(AclPermission.MANAGE_APPLICATIONS);
}
@Override

View File

@ -1,14 +1,15 @@
package com.appsmith.server.solutions.ce;
import com.appsmith.server.acl.AclPermission;
import reactor.core.publisher.Mono;
public interface ContextPermissionCE {
AclPermission getDeletePermission();
Mono<AclPermission> getDeletePermission();
AclPermission getEditPermission();
default AclPermission getActionCreatePermission() {
return null;
default Mono<AclPermission> getActionCreatePermission() {
return Mono.empty();
}
}

View File

@ -228,8 +228,9 @@ public class CreateDBTablePageSolutionCEImpl implements CreateDBTablePageSolutio
// Fetch branched applicationId if connected to git
Mono<NewPage> pageMono = getOrCreatePage(branchedApplicationId, branchedPageId, tableName);
Mono<DatasourceStorage> datasourceStorageMono = datasourceService
.findById(datasourceId, datasourcePermission.getActionCreatePermission())
Mono<DatasourceStorage> datasourceStorageMono = datasourcePermission
.getActionCreatePermission()
.flatMap(permission -> datasourceService.findById(datasourceId, permission))
.switchIfEmpty(Mono.error(
new AppsmithException(AppsmithError.ACL_NO_RESOURCE_FOUND, FieldName.DATASOURCE, datasourceId)))
.flatMap(datasource -> datasourceStorageService.findByDatasourceAndEnvironmentIdForExecution(
@ -500,8 +501,9 @@ public class CreateDBTablePageSolutionCEImpl implements CreateDBTablePageSolutio
});
}
return applicationService
.findById(branchedApplicationId, applicationPermission.getPageCreatePermission())
return applicationPermission
.getPageCreatePermission()
.flatMap(permission -> applicationService.findById(branchedApplicationId, permission))
.switchIfEmpty(Mono.error(new AppsmithException(
AppsmithError.NO_RESOURCE_FOUND, FieldName.APPLICATION, branchedApplicationId)))
.flatMap(branchedApplication -> newPageService

View File

@ -1,11 +1,12 @@
package com.appsmith.server.solutions.ce;
import com.appsmith.server.acl.AclPermission;
import reactor.core.publisher.Mono;
public interface DatasourcePermissionCE {
AclPermission getDeletePermission();
Mono<AclPermission> getDeletePermission();
AclPermission getExecutePermission();
AclPermission getActionCreatePermission();
Mono<AclPermission> getActionCreatePermission();
}

View File

@ -2,6 +2,7 @@ package com.appsmith.server.solutions.ce;
import com.appsmith.server.acl.AclPermission;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import static java.lang.Boolean.TRUE;
@ -18,8 +19,8 @@ public class DatasourcePermissionCEImpl implements DatasourcePermissionCE, Domai
}
@Override
public AclPermission getDeletePermission() {
return AclPermission.MANAGE_DATASOURCES;
public Mono<AclPermission> getDeletePermission() {
return Mono.just(AclPermission.MANAGE_DATASOURCES);
}
@Override
@ -33,7 +34,7 @@ public class DatasourcePermissionCEImpl implements DatasourcePermissionCE, Domai
}
@Override
public AclPermission getActionCreatePermission() {
return AclPermission.MANAGE_DATASOURCES;
public Mono<AclPermission> getActionCreatePermission() {
return Mono.just(AclPermission.MANAGE_DATASOURCES);
}
}

View File

@ -182,8 +182,9 @@ public class DatasourceStructureSolutionCEImpl implements DatasourceStructureSol
@Override
public Mono<ActionExecutionResult> getSchemaPreviewData(
String datasourceId, String environmentId, Template queryTemplate) {
return datasourceService
.findById(datasourceId, datasourcePermission.getActionCreatePermission())
return datasourcePermission
.getActionCreatePermission()
.flatMap(permission -> datasourceService.findById(datasourceId, permission))
.zipWhen(datasource -> datasourceService.getTrueEnvironmentId(
datasource.getWorkspaceId(),
environmentId,

View File

@ -2,6 +2,7 @@ package com.appsmith.server.solutions.ce;
import com.appsmith.server.acl.AclPermission;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import static java.lang.Boolean.TRUE;
@ -23,12 +24,12 @@ public class PagePermissionCEImpl implements PagePermissionCE, DomainPermissionC
}
@Override
public AclPermission getDeletePermission() {
return AclPermission.MANAGE_PAGES;
public Mono<AclPermission> getDeletePermission() {
return Mono.just(AclPermission.MANAGE_PAGES);
}
@Override
public AclPermission getActionCreatePermission() {
return AclPermission.MANAGE_PAGES;
public Mono<AclPermission> getActionCreatePermission() {
return Mono.just(AclPermission.MANAGE_PAGES);
}
}

View File

@ -1,11 +1,12 @@
package com.appsmith.server.solutions.ce;
import com.appsmith.server.acl.AclPermission;
import reactor.core.publisher.Mono;
public interface WorkspacePermissionCE {
AclPermission getDeletePermission();
Mono<AclPermission> getDeletePermission();
AclPermission getApplicationCreatePermission();
Mono<AclPermission> getApplicationCreatePermission();
AclPermission getDatasourceCreatePermission();
Mono<AclPermission> getDatasourceCreatePermission();
}

View File

@ -2,6 +2,7 @@ package com.appsmith.server.solutions.ce;
import com.appsmith.server.acl.AclPermission;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
@Component
public class WorkspacePermissionCEImpl implements WorkspacePermissionCE, DomainPermissionCE {
@ -21,17 +22,17 @@ public class WorkspacePermissionCEImpl implements WorkspacePermissionCE, DomainP
}
@Override
public AclPermission getDeletePermission() {
return AclPermission.MANAGE_WORKSPACES;
public Mono<AclPermission> getDeletePermission() {
return Mono.just(AclPermission.MANAGE_WORKSPACES);
}
@Override
public AclPermission getApplicationCreatePermission() {
return AclPermission.WORKSPACE_MANAGE_APPLICATIONS;
public Mono<AclPermission> getApplicationCreatePermission() {
return Mono.just(AclPermission.WORKSPACE_MANAGE_APPLICATIONS);
}
@Override
public AclPermission getDatasourceCreatePermission() {
return AclPermission.WORKSPACE_MANAGE_DATASOURCES;
public Mono<AclPermission> getDatasourceCreatePermission() {
return Mono.just(AclPermission.WORKSPACE_MANAGE_DATASOURCES);
}
}

View File

@ -19,7 +19,6 @@ import reactor.test.StepVerifier;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.eq;
@SpringBootTest
@ -108,42 +107,39 @@ class FeatureFlaggedMethodInvokerAspectTest {
@Test
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_");
assertEquals("arg_ee_impl_method", result);
Mockito.when(featureFlagService.check(eq(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE)))
.thenReturn(Mono.just(true));
StepVerifier.create(testComponent.ceEeSyncMethod("arg_"))
.assertNext(result -> assertEquals("arg_ee_impl_method", result))
.verifyComplete();
}
@Test
void ceEeSyncMethod_ceImplTest() {
String result = testComponent.ceEeSyncMethod("arg_");
assertEquals("arg_ce_impl_method", result);
StepVerifier.create(testComponent.ceEeSyncMethod("arg_"))
.assertNext(result -> assertEquals("arg_ce_impl_method", result))
.verifyComplete();
}
@Test
void ceEeThrowAppsmithException_eeImplTest() {
CachedFeatures cachedFeatures = new CachedFeatures();
cachedFeatures.setFeatures(Map.of(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE.name(), Boolean.TRUE));
Mockito.when(featureFlagService.getCachedOrganizationFeatureFlags()).thenReturn(cachedFeatures);
assertThrows(
AppsmithException.class,
() -> testComponent.ceEeThrowAppsmithException("arg_"),
AppsmithError.GENERIC_BAD_REQUEST.getMessage("This is a test exception"));
Mockito.when(featureFlagService.check(eq(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE)))
.thenReturn(Mono.just(true));
StepVerifier.create(testComponent.ceEeThrowAppsmithException("arg_"))
.expectErrorMatches(throwable -> throwable instanceof AppsmithException
&& throwable
.getMessage()
.equals(AppsmithError.GENERIC_BAD_REQUEST.getMessage("This is a test exception")))
.verify();
}
@Test
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);
assertThrows(
AppsmithException.class,
() -> testComponent.ceEeThrowNonAppsmithException("arg_"),
AppsmithError.INVALID_METHOD_LEVEL_ANNOTATION_USAGE.getMessage(
"FeatureFlagged",
"TestComponentImpl",
"ceEeThrowNonAppsmithException",
"Exception while invoking super class method"));
Mockito.when(featureFlagService.check(eq(FeatureFlagEnum.ORGANIZATION_TEST_FEATURE)))
.thenReturn(Mono.just(true));
StepVerifier.create(testComponent.ceEeThrowNonAppsmithException("arg_"))
.expectErrorMatches(throwable -> throwable instanceof RuntimeException
&& throwable.getMessage().equals("This is a test exception"))
.verify();
}
}

View File

@ -40,19 +40,19 @@ public class TestComponentImpl extends TestComponentCECompatibleImpl implements
@Override
@FeatureFlagged(featureFlagName = FeatureFlagEnum.ORGANIZATION_TEST_FEATURE)
public String ceEeSyncMethod(String arg) {
return arg + "ee_impl_method";
public Mono<String> ceEeSyncMethod(String arg) {
return Mono.just(arg + "ee_impl_method");
}
@Override
@FeatureFlagged(featureFlagName = FeatureFlagEnum.ORGANIZATION_TEST_FEATURE)
public void ceEeThrowAppsmithException(String arg) {
throw new AppsmithException(AppsmithError.GENERIC_BAD_REQUEST, "This is a test exception");
public Mono<Void> ceEeThrowAppsmithException(String arg) {
return Mono.error(new AppsmithException(AppsmithError.GENERIC_BAD_REQUEST, "This is a test exception"));
}
@Override
@FeatureFlagged(featureFlagName = FeatureFlagEnum.ORGANIZATION_TEST_FEATURE)
public void ceEeThrowNonAppsmithException(String arg) {
throw new RuntimeException("This is a test exception");
public Mono<Void> ceEeThrowNonAppsmithException(String arg) {
return Mono.error(new RuntimeException("This is a test exception"));
}
}

View File

@ -13,9 +13,9 @@ public interface TestComponentCE {
Flux<String> ceEeDiffMethodReturnsFlux();
String ceEeSyncMethod(String arg);
Mono<String> ceEeSyncMethod(String arg);
void ceEeThrowAppsmithException(String arg);
Mono<Void> ceEeThrowAppsmithException(String arg);
void ceEeThrowNonAppsmithException(String arg);
Mono<Void> ceEeThrowNonAppsmithException(String arg);
}

View File

@ -27,13 +27,17 @@ public class TestComponentCEImpl implements TestComponentCE {
}
@Override
public String ceEeSyncMethod(String arg) {
return arg + "ce_impl_method";
public Mono<String> ceEeSyncMethod(String arg) {
return Mono.just(arg + "ce_impl_method");
}
@Override
public void ceEeThrowAppsmithException(String arg) {}
public Mono<Void> ceEeThrowAppsmithException(String arg) {
return Mono.empty();
}
@Override
public void ceEeThrowNonAppsmithException(String arg) {}
public Mono<Void> ceEeThrowNonAppsmithException(String arg) {
return Mono.empty();
}
}

View File

@ -610,6 +610,7 @@ public class ApplicationForkingServiceTests {
.filter(policy -> !policy.getPermission()
.equals(workspacePermission
.getDatasourceCreatePermission()
.block()
.getValue()))
.collect(Collectors.toSet());
targetWorkspace.setPolicies(newPoliciesWithoutCreateDatasource);

View File

@ -266,8 +266,9 @@ public class CommonGitServiceCETest {
@AfterEach
public void cleanup() {
Mockito.when(commonGitFileUtils.deleteLocalRepo(any(Path.class))).thenReturn(Mono.just(true));
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -46,25 +46,28 @@ class EmailServiceHelperCETest {
@Test
void testGetForgotPasswordTemplate() {
assertThat(emailServiceHelperCE.getForgotPasswordTemplate()).isEqualTo(FORGOT_PASSWORD_TEMPLATE_CE);
assertThat(emailServiceHelperCE.getForgotPasswordTemplate().block()).isEqualTo(FORGOT_PASSWORD_TEMPLATE_CE);
}
@Test
void testGetWorkspaceInviteTemplate() {
assertThat(emailServiceHelperCE.getWorkspaceInviteTemplate(Boolean.TRUE))
assertThat(emailServiceHelperCE.getWorkspaceInviteTemplate(Boolean.TRUE).block())
.isEqualTo(INVITE_WORKSPACE_TEMPLATE_NEW_USER_CE);
assertThat(emailServiceHelperCE.getWorkspaceInviteTemplate(Boolean.FALSE))
assertThat(emailServiceHelperCE
.getWorkspaceInviteTemplate(Boolean.FALSE)
.block())
.isEqualTo(INVITE_WORKSPACE_TEMPLATE_EXISTING_USER_CE);
}
@Test
void testGetEmailVerificationTemplate() {
assertThat(emailServiceHelperCE.getEmailVerificationTemplate()).isEqualTo(EMAIL_VERIFICATION_EMAIL_TEMPLATE_CE);
assertThat(emailServiceHelperCE.getEmailVerificationTemplate().block())
.isEqualTo(EMAIL_VERIFICATION_EMAIL_TEMPLATE_CE);
}
@Test
void testGetAdminInstanceInviteTemplate() {
assertThat(emailServiceHelperCE.getAdminInstanceInviteTemplate())
assertThat(emailServiceHelperCE.getAdminInstanceInviteTemplate().block())
.isEqualTo(INSTANCE_ADMIN_INVITE_EMAIL_TEMPLATE);
}
}

View File

@ -16,6 +16,7 @@ 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.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@ -27,6 +28,7 @@ import java.util.List;
import java.util.Set;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -61,9 +63,15 @@ class ImportArtifactPermissionProviderTest {
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()));
assertEquals(
Boolean.TRUE,
importArtifactPermissionProvider
.canCreateDatasource(new Workspace())
.block());
assertEquals(
Boolean.TRUE,
importArtifactPermissionProvider.canCreateAction(new NewPage()).block());
importArtifactPermissionProvider.canCreatePage(new Application()).subscribe(Assertions::assertTrue);
}
@Test
@ -101,9 +109,14 @@ class ImportArtifactPermissionProviderTest {
// we'll create a permission provider for each domain and check if the create permission is false
List<Tuple2<BaseDomain, AclPermission>> 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().block()));
domainAndPermissionList.add(Tuples.of(
new NewPage(), pagePermission.getActionCreatePermission().block()));
domainAndPermissionList.add(Tuples.of(
new Workspace(),
workspacePermission.getDatasourceCreatePermission().block()));
for (Tuple2<BaseDomain, AclPermission> domainAndPermission : domainAndPermissionList) {
BaseDomain domain = domainAndPermission.getT1();
@ -112,11 +125,11 @@ class ImportArtifactPermissionProviderTest {
createPermissionProviderForDomainCreatePermission(domain, domainAndPermission.getT2());
if (domain instanceof Application) {
assertFalse(provider.canCreatePage((Application) domain));
provider.canCreatePage((Application) domain).subscribe(Assertions::assertFalse);
} else if (domain instanceof NewPage) {
assertFalse(provider.canCreateAction((NewPage) domain));
assertFalse(provider.canCreateAction((NewPage) domain).block());
} else if (domain instanceof Workspace) {
assertFalse(provider.canCreateDatasource((Workspace) domain));
provider.canCreateDatasource((Workspace) domain).subscribe(Assertions::assertFalse);
}
}
}

View File

@ -4940,6 +4940,7 @@ public class ImportServiceTests {
.filter(policy -> !policy.getPermission()
.equals(applicationPermission
.getPageCreatePermission()
.block()
.getValue()))
.collect(Collectors.toUnmodifiableSet()));
return applicationRepository.save(application);
@ -4984,6 +4985,7 @@ public class ImportServiceTests {
.filter(policy -> !policy.getPermission()
.equals(applicationPermission
.getPageCreatePermission()
.block()
.getValue()))
.collect(Collectors.toUnmodifiableSet()));
return applicationRepository.save(application);

View File

@ -248,8 +248,9 @@ class RefactoringServiceCETest {
@AfterEach
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -229,8 +229,9 @@ public class RefactoringServiceTest {
@AfterEach
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -216,8 +216,9 @@ public class ActionCollectionServiceTest {
@AfterEach
@WithUserDetails(value = "api_user")
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -86,8 +86,9 @@ public class ApplicationPageServiceTest {
@AfterEach
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspace.getId(), applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspace.getId(), permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -77,8 +77,9 @@ public class ApplicationSnapshotServiceTest {
// Since no setup is done, hence no cleanup should happen.
return;
}
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspace.getId(), applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspace.getId(), permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -207,8 +207,9 @@ public class CurlImporterServiceTest {
// Since, no setup was done if the user context is missing. Hence, no cleanup required.
return;
}
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -138,8 +138,9 @@ public class DatasourceContextServiceTest {
@AfterEach
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();
@ -188,7 +189,7 @@ public class DatasourceContextServiceTest {
doReturn(Mono.just(datasource))
.when(datasourceRepository)
.findById("id1", datasourcePermission.getDeletePermission());
.findById("id1", datasourcePermission.getDeletePermission().block());
doReturn(Mono.just(datasource))
.when(datasourceRepository)
.findById("id1", datasourcePermission.getExecutePermission());

View File

@ -143,8 +143,9 @@ public class DatasourceServiceTest {
@AfterEach
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -78,8 +78,9 @@ public class DatasourceStorageServiceTest {
@AfterEach
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspace.getId(), applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspace.getId(), permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -255,8 +255,9 @@ class LayoutActionServiceTest {
@AfterEach
void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();
@ -476,13 +477,17 @@ class LayoutActionServiceTest {
})
.verifyComplete();
StepVerifier.create(newActionService.findById(createdAction1.getId())).assertNext(newAction -> assertThat(
newAction.getUnpublishedAction().getExecuteOnLoad())
.isTrue());
StepVerifier.create(newActionService.findById(createdAction1.getId()))
.assertNext(
newAction -> assertThat(newAction.getUnpublishedAction().getExecuteOnLoad())
.isTrue())
.verifyComplete();
StepVerifier.create(newActionService.findById(createdAction2.getId())).assertNext(newAction -> assertThat(
newAction.getUnpublishedAction().getExecuteOnLoad())
.isFalse());
StepVerifier.create(newActionService.findById(createdAction2.getId()))
.assertNext(
newAction -> assertThat(newAction.getUnpublishedAction().getExecuteOnLoad())
.isFalse())
.verifyComplete();
dsl = new JSONObject();
dsl.put("widgetName", "firstWidget");

View File

@ -153,8 +153,9 @@ public class LayoutServiceTest {
@AfterEach
public void cleanup() {
applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();
@ -524,16 +525,16 @@ public class LayoutServiceTest {
"some dynamic {{\"anIgnoredAction.data:\" + aGetAction.data}}",
"dynamicPost",
"""
some dynamic {{
(function(ignoredAction1){
\tlet a = ignoredAction1.data
\tlet ignoredAction2 = { data: "nothing" }
\tlet b = ignoredAction2.data
\tlet c = "ignoredAction3.data"
\t// ignoredAction4.data
\treturn aPostAction.data
})(anotherPostAction.data)}}
""",
some dynamic {{
(function(ignoredAction1){
\tlet a = ignoredAction1.data
\tlet ignoredAction2 = { data: "nothing" }
\tlet b = ignoredAction2.data
\tlet c = "ignoredAction3.data"
\t// ignoredAction4.data
\treturn aPostAction.data
})(anotherPostAction.data)}}
""",
"dynamicPostWithAutoExec",
"some dynamic {{aPostActionWithAutoExec.data}}",
"dynamicDelete",

View File

@ -131,8 +131,9 @@ public class MockDataServiceTest {
@AfterEach
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -85,8 +85,9 @@ public class NewPageServiceTest {
@AfterEach
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -155,8 +155,9 @@ public class PageServiceTest {
@AfterEach
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -107,8 +107,9 @@ public class ThemeServiceTest {
@AfterEach
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspace.getId(), applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspace.getId(), permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -118,8 +118,9 @@ public class UserWorkspaceServiceUnitTest {
// Do not proceed with cleanup, because user context doesn't exist.
return;
}
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspace.getId(), applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspace.getId(), permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -284,8 +284,9 @@ public class ActionServiceCE_Test {
@AfterEach
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -415,8 +415,9 @@ public class ApplicationServiceCETest {
// Since no setup was done, hence no cleanup needs to happen
return;
}
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();
@ -4171,7 +4172,10 @@ public class ApplicationServiceCETest {
*/
Set<Policy> newPoliciesWithoutEdit = existingPolicies.stream()
.filter(policy -> !policy.getPermission()
.equals(datasourcePermission.getActionCreatePermission().getValue()))
.equals(datasourcePermission
.getActionCreatePermission()
.block()
.getValue()))
.collect(Collectors.toSet());
testDatasource1.setPolicies(newPoliciesWithoutEdit);
Datasource updatedTestDatasource =

View File

@ -88,8 +88,9 @@ public class ThemeImportableServiceCETest {
@AfterEach
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspace.getId(), applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspace.getId(), permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -101,8 +101,9 @@ public class AuthenticationServiceTest {
@AfterEach
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspace.getId(), applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspace.getId(), permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -241,8 +241,9 @@ public class CreateDBTablePageSolutionTests {
@AfterEach
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(testWorkspace.getId(), applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(testWorkspace.getId(), permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -126,8 +126,9 @@ public class DatasourceStructureSolutionTest {
@AfterEach
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -121,8 +121,9 @@ public class DatasourceTriggerSolutionTest {
@AfterEach
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -292,8 +292,9 @@ public class ActionExecutionSolutionCETest {
@AfterEach
public void cleanup() {
List<Application> deletedApplications = applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
List<Application> deletedApplications = applicationPermission
.getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();

View File

@ -94,8 +94,8 @@ public class ArtifactBuilderExtension implements AfterEachCallback, BeforeEachCa
// Because right now we only have checks for apps
// Move this to artifact based model when we fix that
applicationService
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission())
applicationPermission.getDeletePermission().flatMapMany(permission -> applicationService
.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList()
.block();