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

View File

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

View File

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

View File

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

View File

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

View File

@ -152,7 +152,9 @@ public class DatasourceServiceCEImpl implements DatasourceServiceCE {
@Override @Override
public Mono<Datasource> create(Datasource datasource) { 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 // TODO: Check usage
@ -880,8 +882,9 @@ public class DatasourceServiceCEImpl implements DatasourceServiceCE {
@Override @Override
public Mono<Datasource> archiveById(String id) { public Mono<Datasource> archiveById(String id) {
return repository return datasourcePermission
.findById(id, datasourcePermission.getDeletePermission()) .getDeletePermission()
.flatMap(permission -> repository.findById(id, permission))
.switchIfEmpty( .switchIfEmpty(
Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.DATASOURCE, id))) Mono.error(new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.DATASOURCE, id)))
.zipWhen(datasource -> newActionRepository.countByDatasourceId(datasource.getId())) .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()) .filter(ds -> ds.getName().equals(datasourceStorage.getName())
&& datasourceStorage.getPluginId().equals(ds.getPluginId())) && datasourceStorage.getPluginId().equals(ds.getPluginId()))
.next() // Get the first matching datasource, we don't need more than one here. .next() // Get the first matching datasource, we don't need more than one here.
.switchIfEmpty(Mono.defer(() -> { .switchIfEmpty(Mono.defer(
// check if user has permission to create datasource () -> permissionProvider.canCreateDatasource(workspace).flatMap(canCreateDatasource -> {
if (!permissionProvider.canCreateDatasource(workspace)) { // check if user has permission to create datasource
log.error( if (!canCreateDatasource) {
"Unauthorized to create datasource: {} in workspace: {}", log.error(
datasourceStorage.getName(), "Unauthorized to create datasource: {} in workspace: {}",
workspace.getName()); datasourceStorage.getName(),
return Mono.error(new AppsmithException( workspace.getName());
AppsmithError.ACL_NO_RESOURCE_FOUND, return Mono.error(new AppsmithException(
FieldName.DATASOURCE, AppsmithError.ACL_NO_RESOURCE_FOUND,
datasourceStorage.getName())); FieldName.DATASOURCE,
} datasourceStorage.getName()));
}
if (datasourceConfig != null && datasourceConfig.getAuthentication() != null) { if (datasourceConfig != null && datasourceConfig.getAuthentication() != null) {
datasourceConfig.getAuthentication().setAuthenticationResponse(authResponse); datasourceConfig.getAuthentication().setAuthenticationResponse(authResponse);
} }
// No matching existing datasource found, so create a new one. // No matching existing datasource found, so create a new one.
datasourceStorage.setIsConfigured( datasourceStorage.setIsConfigured(
datasourceConfig != null && datasourceConfig.getAuthentication() != null); datasourceConfig != null && datasourceConfig.getAuthentication() != null);
datasourceStorage.setEnvironmentId(environmentId); datasourceStorage.setEnvironmentId(environmentId);
return datasourceService return datasourceService
.findByNameAndWorkspaceId(datasourceStorage.getName(), workspace.getId(), null) .findByNameAndWorkspaceId(datasourceStorage.getName(), workspace.getId(), null)
.flatMap(duplicateNameDatasource -> .flatMap(duplicateNameDatasource -> getUniqueSuffixForDuplicateNameEntity(
getUniqueSuffixForDuplicateNameEntity(duplicateNameDatasource, workspace.getId())) duplicateNameDatasource, workspace.getId()))
.map(dsName -> { .map(dsName -> {
datasourceStorage.setName(datasourceStorage.getName() + dsName); datasourceStorage.setName(datasourceStorage.getName() + dsName);
return datasourceService.createDatasourceFromDatasourceStorage(datasourceStorage); return datasourceService.createDatasourceFromDatasourceStorage(
}) datasourceStorage);
.switchIfEmpty(Mono.just( })
datasourceService.createDatasourceFromDatasourceStorage(datasourceStorage))) .switchIfEmpty(Mono.just(
// DRY RUN queries are not saved, so we need to create them separately at the import service datasourceService.createDatasourceFromDatasourceStorage(datasourceStorage)))
// solution // DRY RUN queries are not saved, so we need to create them separately at the import
.flatMap(datasource -> datasourceService.createWithoutPermissions( // service
datasource, mappedImportableResourcesDTO.getDatasourceStorageDryRunQueries())); // solution
})) .flatMap(datasource -> datasourceService.createWithoutPermissions(
datasource,
mappedImportableResourcesDTO.getDatasourceStorageDryRunQueries()));
})))
.onErrorResume(throwable -> { .onErrorResume(throwable -> {
log.error("failed to import datasource", throwable); log.error("failed to import datasource", throwable);
return Mono.error(throwable); return Mono.error(throwable);

View File

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

View File

@ -7,17 +7,17 @@ import java.util.Map;
public interface EmailServiceHelperCE { public interface EmailServiceHelperCE {
Mono<Map<String, String>> enrichWithBrandParams(Map<String, String> params, String origin); 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 @Override
public String getForgotPasswordTemplate() { public Mono<String> getForgotPasswordTemplate() {
return FORGOT_PASSWORD_TEMPLATE_CE; return Mono.just(FORGOT_PASSWORD_TEMPLATE_CE);
} }
@Override @Override
public String getWorkspaceInviteTemplate(boolean isNewUser) { public Mono<String> getWorkspaceInviteTemplate(boolean isNewUser) {
if (isNewUser) return INVITE_WORKSPACE_TEMPLATE_NEW_USER_CE; 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 @Override
public String getEmailVerificationTemplate() { public Mono<String> getEmailVerificationTemplate() {
return EMAIL_VERIFICATION_EMAIL_TEMPLATE_CE; return Mono.just(EMAIL_VERIFICATION_EMAIL_TEMPLATE_CE);
} }
@Override @Override
public String getAdminInstanceInviteTemplate() { public Mono<String> getAdminInstanceInviteTemplate() {
return INSTANCE_ADMIN_INVITE_EMAIL_TEMPLATE; return Mono.just(INSTANCE_ADMIN_INVITE_EMAIL_TEMPLATE);
} }
@Override @Override
public String getJoinInstanceCtaPrimaryText() { public Mono<String> getJoinInstanceCtaPrimaryText() {
return PRIMARY_LINK_TEXT_INVITE_TO_INSTANCE_CE; return Mono.just(PRIMARY_LINK_TEXT_INVITE_TO_INSTANCE_CE);
} }
@Override @Override
public String getSubjectJoinInstanceAsAdmin(String instanceName) { public Mono<String> getSubjectJoinInstanceAsAdmin(String instanceName) {
return INSTANCE_ADMIN_INVITE_EMAIL_SUBJECT; return Mono.just(INSTANCE_ADMIN_INVITE_EMAIL_SUBJECT);
} }
@Override @Override
public String getSubjectJoinWorkspace(String workspaceName) { public Mono<String> getSubjectJoinWorkspace(String workspaceName) {
return INVITE_TO_WORKSPACE_EMAIL_SUBJECT_CE; 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.AccessLevel;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
import reactor.core.publisher.Mono;
import java.util.Set; import java.util.Set;
@ -116,24 +117,28 @@ public class ImportArtifactPermissionProviderCE {
return hasPermission(datasourcePermission.getEditPermission(), datasource); return hasPermission(datasourcePermission.getEditPermission(), datasource);
} }
public boolean canCreatePage(Application application) { public Mono<Boolean> canCreatePage(Application application) {
if (!permissionRequiredToCreatePage) { 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) { 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) { 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.ImportingMetaDTO;
import com.appsmith.server.dtos.MappedImportableResourcesDTO; import com.appsmith.server.dtos.MappedImportableResourcesDTO;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.util.List; import java.util.List;
import java.util.Map; 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( default T getExistingEntityInCurrentBranchForImportedEntity(
MappedImportableResourcesDTO mappedImportableResourcesDTO, MappedImportableResourcesDTO mappedImportableResourcesDTO,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -462,38 +462,42 @@ public class NewPageImportableServiceCEImpl implements ImportableServiceCE<NewPa
existingPage.setDeletedAt(newPage.getDeletedAt()); existingPage.setDeletedAt(newPage.getDeletedAt());
existingPage.setPolicies(existingPagePolicy); existingPage.setPolicies(existingPagePolicy);
return newPageService.save(existingPage); 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 -> { .onErrorResume(error -> {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -571,8 +571,9 @@ public class WorkspaceServiceCEImpl extends BaseService<WorkspaceRepository, Wor
return applicationRepository.countByWorkspaceId(workspaceId).flatMap(appCount -> { return applicationRepository.countByWorkspaceId(workspaceId).flatMap(appCount -> {
if (appCount == 0) { // no application found under this workspace if (appCount == 0) { // no application found under this workspace
// fetching the workspace first to make sure user has permission to archive // fetching the workspace first to make sure user has permission to archive
return repository return workspacePermission
.findById(workspaceId, workspacePermission.getDeletePermission()) .getDeletePermission()
.flatMap(permission -> repository.findById(workspaceId, permission))
.switchIfEmpty(Mono.error(new AppsmithException( .switchIfEmpty(Mono.error(new AppsmithException(
AppsmithError.NO_RESOURCE_FOUND, FieldName.WORKSPACE, workspaceId))) AppsmithError.NO_RESOURCE_FOUND, FieldName.WORKSPACE, workspaceId)))
.flatMap(workspace -> { .flatMap(workspace -> {

View File

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

View File

@ -2,6 +2,7 @@ package com.appsmith.server.solutions.ce;
import com.appsmith.server.acl.AclPermission; import com.appsmith.server.acl.AclPermission;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import static java.lang.Boolean.TRUE; import static java.lang.Boolean.TRUE;
@ -28,7 +29,7 @@ public class ActionPermissionCEImpl implements ActionPermissionCE, DomainPermiss
} }
@Override @Override
public AclPermission getDeletePermission() { public Mono<AclPermission> getDeletePermission() {
return AclPermission.MANAGE_ACTIONS; 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.acl.AclPermission;
import com.appsmith.server.artifacts.permissions.ArtifactPermission; import com.appsmith.server.artifacts.permissions.ArtifactPermission;
import reactor.core.publisher.Mono;
public interface ApplicationPermissionCE extends ArtifactPermission { public interface ApplicationPermissionCE extends ArtifactPermission {
@ -9,7 +10,7 @@ public interface ApplicationPermissionCE extends ArtifactPermission {
AclPermission getCanCommentPermission(); AclPermission getCanCommentPermission();
AclPermission getPageCreatePermission(); Mono<AclPermission> getPageCreatePermission();
AclPermission getManageProtectedBranchPermission(); AclPermission getManageProtectedBranchPermission();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -13,9 +13,9 @@ public interface TestComponentCE {
Flux<String> ceEeDiffMethodReturnsFlux(); 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 @Override
public String ceEeSyncMethod(String arg) { public Mono<String> ceEeSyncMethod(String arg) {
return arg + "ce_impl_method"; return Mono.just(arg + "ce_impl_method");
} }
@Override @Override
public void ceEeThrowAppsmithException(String arg) {} public Mono<Void> ceEeThrowAppsmithException(String arg) {
return Mono.empty();
}
@Override @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() .filter(policy -> !policy.getPermission()
.equals(workspacePermission .equals(workspacePermission
.getDatasourceCreatePermission() .getDatasourceCreatePermission()
.block()
.getValue())) .getValue()))
.collect(Collectors.toSet()); .collect(Collectors.toSet());
targetWorkspace.setPolicies(newPoliciesWithoutCreateDatasource); targetWorkspace.setPolicies(newPoliciesWithoutCreateDatasource);

View File

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

View File

@ -46,25 +46,28 @@ class EmailServiceHelperCETest {
@Test @Test
void testGetForgotPasswordTemplate() { void testGetForgotPasswordTemplate() {
assertThat(emailServiceHelperCE.getForgotPasswordTemplate()).isEqualTo(FORGOT_PASSWORD_TEMPLATE_CE); assertThat(emailServiceHelperCE.getForgotPasswordTemplate().block()).isEqualTo(FORGOT_PASSWORD_TEMPLATE_CE);
} }
@Test @Test
void testGetWorkspaceInviteTemplate() { void testGetWorkspaceInviteTemplate() {
assertThat(emailServiceHelperCE.getWorkspaceInviteTemplate(Boolean.TRUE)) assertThat(emailServiceHelperCE.getWorkspaceInviteTemplate(Boolean.TRUE).block())
.isEqualTo(INVITE_WORKSPACE_TEMPLATE_NEW_USER_CE); .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); .isEqualTo(INVITE_WORKSPACE_TEMPLATE_EXISTING_USER_CE);
} }
@Test @Test
void testGetEmailVerificationTemplate() { void testGetEmailVerificationTemplate() {
assertThat(emailServiceHelperCE.getEmailVerificationTemplate()).isEqualTo(EMAIL_VERIFICATION_EMAIL_TEMPLATE_CE); assertThat(emailServiceHelperCE.getEmailVerificationTemplate().block())
.isEqualTo(EMAIL_VERIFICATION_EMAIL_TEMPLATE_CE);
} }
@Test @Test
void testGetAdminInstanceInviteTemplate() { void testGetAdminInstanceInviteTemplate() {
assertThat(emailServiceHelperCE.getAdminInstanceInviteTemplate()) assertThat(emailServiceHelperCE.getAdminInstanceInviteTemplate().block())
.isEqualTo(INSTANCE_ADMIN_INVITE_EMAIL_TEMPLATE); .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.DomainPermission;
import com.appsmith.server.solutions.PagePermission; import com.appsmith.server.solutions.PagePermission;
import com.appsmith.server.solutions.WorkspacePermission; import com.appsmith.server.solutions.WorkspacePermission;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
@ -27,6 +28,7 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import static org.assertj.core.api.Assertions.assertThat; 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.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
@ -61,9 +63,15 @@ class ImportArtifactPermissionProviderTest {
assertTrue(importArtifactPermissionProvider.hasEditPermission(new NewAction())); assertTrue(importArtifactPermissionProvider.hasEditPermission(new NewAction()));
assertTrue(importArtifactPermissionProvider.hasEditPermission(new Datasource())); assertTrue(importArtifactPermissionProvider.hasEditPermission(new Datasource()));
assertTrue(importArtifactPermissionProvider.canCreateDatasource(new Workspace())); assertEquals(
assertTrue(importArtifactPermissionProvider.canCreateAction(new NewPage())); Boolean.TRUE,
assertTrue(importArtifactPermissionProvider.canCreatePage(new Application())); importArtifactPermissionProvider
.canCreateDatasource(new Workspace())
.block());
assertEquals(
Boolean.TRUE,
importArtifactPermissionProvider.canCreateAction(new NewPage()).block());
importArtifactPermissionProvider.canCreatePage(new Application()).subscribe(Assertions::assertTrue);
} }
@Test @Test
@ -101,9 +109,14 @@ class ImportArtifactPermissionProviderTest {
// we'll create a permission provider for each domain and check if the create permission is false // we'll create a permission provider for each domain and check if the create permission is false
List<Tuple2<BaseDomain, AclPermission>> domainAndPermissionList = new ArrayList<>(); List<Tuple2<BaseDomain, AclPermission>> domainAndPermissionList = new ArrayList<>();
domainAndPermissionList.add(Tuples.of(new Application(), applicationPermission.getPageCreatePermission())); domainAndPermissionList.add(Tuples.of(
domainAndPermissionList.add(Tuples.of(new NewPage(), pagePermission.getActionCreatePermission())); new Application(),
domainAndPermissionList.add(Tuples.of(new Workspace(), workspacePermission.getDatasourceCreatePermission())); 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) { for (Tuple2<BaseDomain, AclPermission> domainAndPermission : domainAndPermissionList) {
BaseDomain domain = domainAndPermission.getT1(); BaseDomain domain = domainAndPermission.getT1();
@ -112,11 +125,11 @@ class ImportArtifactPermissionProviderTest {
createPermissionProviderForDomainCreatePermission(domain, domainAndPermission.getT2()); createPermissionProviderForDomainCreatePermission(domain, domainAndPermission.getT2());
if (domain instanceof Application) { if (domain instanceof Application) {
assertFalse(provider.canCreatePage((Application) domain)); provider.canCreatePage((Application) domain).subscribe(Assertions::assertFalse);
} else if (domain instanceof NewPage) { } else if (domain instanceof NewPage) {
assertFalse(provider.canCreateAction((NewPage) domain)); assertFalse(provider.canCreateAction((NewPage) domain).block());
} else if (domain instanceof Workspace) { } 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() .filter(policy -> !policy.getPermission()
.equals(applicationPermission .equals(applicationPermission
.getPageCreatePermission() .getPageCreatePermission()
.block()
.getValue())) .getValue()))
.collect(Collectors.toUnmodifiableSet())); .collect(Collectors.toUnmodifiableSet()));
return applicationRepository.save(application); return applicationRepository.save(application);
@ -4984,6 +4985,7 @@ public class ImportServiceTests {
.filter(policy -> !policy.getPermission() .filter(policy -> !policy.getPermission()
.equals(applicationPermission .equals(applicationPermission
.getPageCreatePermission() .getPageCreatePermission()
.block()
.getValue())) .getValue()))
.collect(Collectors.toUnmodifiableSet())); .collect(Collectors.toUnmodifiableSet()));
return applicationRepository.save(application); return applicationRepository.save(application);

View File

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

View File

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

View File

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

View File

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

View File

@ -77,8 +77,9 @@ public class ApplicationSnapshotServiceTest {
// Since no setup is done, hence no cleanup should happen. // Since no setup is done, hence no cleanup should happen.
return; return;
} }
List<Application> deletedApplications = applicationService List<Application> deletedApplications = applicationPermission
.findByWorkspaceId(workspace.getId(), applicationPermission.getDeletePermission()) .getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspace.getId(), permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList() .collectList()
.block(); .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. // Since, no setup was done if the user context is missing. Hence, no cleanup required.
return; return;
} }
List<Application> deletedApplications = applicationService List<Application> deletedApplications = applicationPermission
.findByWorkspaceId(workspaceId, applicationPermission.getDeletePermission()) .getDeletePermission()
.flatMapMany(permission -> applicationService.findByWorkspaceId(workspaceId, permission))
.flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId())) .flatMap(remainingApplication -> applicationPageService.deleteApplication(remainingApplication.getId()))
.collectList() .collectList()
.block(); .block();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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