diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomActionCollectionRepository.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomActionCollectionRepository.java index 393d63fe2a..5f6bd1fbe3 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomActionCollectionRepository.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomActionCollectionRepository.java @@ -16,4 +16,6 @@ public interface CustomActionCollectionRepository extends AppsmithRepository findAllActionCollectionsByNameAndPageIdsAndViewMode(String name, List pageIds, boolean viewMode, AclPermission aclPermission, Sort sort); Flux findByPageId(String pageId, AclPermission permission); + + Flux findByPageId(String pageId); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomActionCollectionRepositoryImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomActionCollectionRepositoryImpl.java index abdc926a1f..bdf04cf01f 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomActionCollectionRepositoryImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/repositories/CustomActionCollectionRepositoryImpl.java @@ -122,4 +122,9 @@ public class CustomActionCollectionRepositoryImpl extends BaseAppsmithRepository }); } + + @Override + public Flux findByPageId(String pageId) { + return this.findByPageId(pageId, null); + } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ActionCollectionService.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ActionCollectionService.java index 80bd8ecd83..957c801e3e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ActionCollectionService.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ActionCollectionService.java @@ -40,7 +40,7 @@ public interface ActionCollectionService extends CrudService findActionCollectionDTObyIdAndViewMode(String id, Boolean viewMode, AclPermission permission); - Flux findByPageId(String pageId, AclPermission permission); - Flux getActionCollectionsForViewMode(String applicationId); + + Flux findByPageId(String pageId); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ActionCollectionServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ActionCollectionServiceImpl.java index 8855b7fc05..d912be5d34 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ActionCollectionServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ActionCollectionServiceImpl.java @@ -303,8 +303,8 @@ public class ActionCollectionServiceImpl extends BaseService findByPageId(String pageId, AclPermission permission) { - return repository.findByPageId(pageId, permission); + public Flux findByPageId(String pageId) { + return repository.findByPageId(pageId); } @Override diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationPageServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationPageServiceImpl.java index de500033b1..6675d2d4a1 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationPageServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ApplicationPageServiceImpl.java @@ -593,7 +593,7 @@ public class ApplicationPageServiceImpl implements ApplicationPageService { /** * Only delete unpublished action collection and not the entire action collection. */ - Mono> archivedActionCollectionsMono = actionCollectionService.findByPageId(page.getId(), MANAGE_ACTIONS) + Mono> archivedActionCollectionsMono = actionCollectionService.findByPageId(page.getId()) .flatMap(actionCollection -> { log.debug("Going to archive actionCollectionId: {} for applicationId: {}", actionCollection.getId(), id); return actionCollectionService.deleteUnpublishedActionCollection(actionCollection.getId()); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ExamplesOrganizationCloner.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ExamplesOrganizationCloner.java index 7184179109..2803aff920 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ExamplesOrganizationCloner.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/solutions/ExamplesOrganizationCloner.java @@ -4,14 +4,15 @@ import com.appsmith.external.helpers.AppsmithEventContext; import com.appsmith.external.helpers.AppsmithEventContextType; import com.appsmith.external.models.AuthenticationDTO; import com.appsmith.external.models.BaseDomain; +import com.appsmith.external.models.Datasource; import com.appsmith.server.constants.FieldName; import com.appsmith.server.domains.Application; import com.appsmith.server.domains.ApplicationPage; -import com.appsmith.external.models.Datasource; import com.appsmith.server.domains.Layout; import com.appsmith.server.domains.NewPage; import com.appsmith.server.domains.Organization; import com.appsmith.server.domains.User; +import com.appsmith.server.dtos.ActionCollectionDTO; import com.appsmith.server.dtos.ActionDTO; import com.appsmith.server.dtos.DslActionDTO; import com.appsmith.server.dtos.PageDTO; @@ -20,11 +21,13 @@ import com.appsmith.server.exceptions.AppsmithException; import com.appsmith.server.repositories.DatasourceRepository; import com.appsmith.server.repositories.NewPageRepository; import com.appsmith.server.repositories.OrganizationRepository; +import com.appsmith.server.services.ActionCollectionService; import com.appsmith.server.services.ApplicationPageService; import com.appsmith.server.services.ApplicationService; import com.appsmith.server.services.ConfigService; import com.appsmith.server.services.DatasourceService; import com.appsmith.server.services.LayoutActionService; +import com.appsmith.server.services.LayoutCollectionService; import com.appsmith.server.services.NewActionService; import com.appsmith.server.services.OrganizationService; import com.appsmith.server.services.SessionUserService; @@ -38,7 +41,6 @@ import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; -import reactor.util.function.Tuple2; import java.util.ArrayList; import java.util.HashMap; @@ -64,6 +66,8 @@ public class ExamplesOrganizationCloner { private final NewPageRepository newPageRepository; private final NewActionService newActionService; private final LayoutActionService layoutActionService; + private final ActionCollectionService actionCollectionService; + private final LayoutCollectionService layoutCollectionService; public Mono cloneExamplesOrganization() { return sessionUserService @@ -223,7 +227,7 @@ public class ExamplesOrganizationCloner { ? applicationPageService.makePageDefault(savedPage).thenReturn(savedPage) : Mono.just(savedPage)) .flatMap(savedPage -> newPageRepository.findById(savedPage.getId())) - .flatMapMany(savedPage -> { + .flatMap(savedPage -> { clonedPages.add(savedPage); return newActionService .findByPageId(templatePageId) @@ -232,45 +236,83 @@ public class ExamplesOrganizationCloner { log.info("Preparing action for cloning {} {}.", action.getName(), newAction.getId()); action.setPageId(savedPage.getId()); return newAction; + }) + .flatMap(newAction -> { + final String originalActionId = newAction.getId(); + log.info("Creating clone of action {}", originalActionId); + makePristine(newAction); + newAction.setOrganizationId(toOrganizationId); + ActionDTO action = newAction.getUnpublishedAction(); + final String originalCollectionId = action.getCollectionId(); + action.setCollectionId(null); + + Mono actionMono = Mono.just(action); + final Datasource datasourceInsideAction = action.getDatasource(); + if (datasourceInsideAction != null) { + if (datasourceInsideAction.getId() != null) { + final String datasourceId = datasourceInsideAction.getId(); + if (!cloneDatasourceMonos.containsKey(datasourceId)) { + cloneDatasourceMonos.put(datasourceId, cloneDatasource(datasourceId, toOrganizationId).cache()); + } + actionMono = cloneDatasourceMonos.get(datasourceId) + .map(newDatasource -> { + action.setDatasource(newDatasource); + return action; + }); + } else { + datasourceInsideAction.setOrganizationId(toOrganizationId); + } + } + return Mono.zip(actionMono + .flatMap(actionDTO -> layoutActionService.createAction( + actionDTO, new AppsmithEventContext(AppsmithEventContextType.CLONE_PAGE)) + ) + .map(ActionDTO::getId), + Mono.justOrEmpty(originalActionId)); + }) + // This call to `collectMap` will wait for all actions in all pages to have been processed, and so the + // `clonedPages` list will also contain all pages cloned. + .collect(HashMap::new, (map, tuple3) -> map.put(tuple3.getT2(), tuple3.getT1())) + .flatMap(actionIdsMap -> { + // Pick all action collections + return actionCollectionService + .findByPageId(templatePageId) + .flatMap(actionCollection -> { + // Keep a record of the original collection id + final String originalCollectionId = actionCollection.getId(); + log.info("Creating clone of action collection {}", originalCollectionId); + // Sanitize them + makePristine(actionCollection); + final ActionCollectionDTO unpublishedCollection = actionCollection.getUnpublishedCollection(); + unpublishedCollection.setPageId(savedPage.getId()); + actionCollection.setOrganizationId(toOrganizationId); + actionCollection.setApplicationId(savedPage.getApplicationId()); + actionCollectionService.generateAndSetPolicies(savedPage, actionCollection); + + // Replace all action Ids from map + final HashSet newActionIds = new HashSet<>(); + unpublishedCollection + .getActionIds() + .stream() + .forEach(oldActionId -> newActionIds.add(actionIdsMap.get(oldActionId))); + unpublishedCollection.setActionIds(newActionIds); + return actionCollectionService.create(actionCollection) + .flatMap(newlyCreatedActionCollection -> { + return Flux.fromIterable(newActionIds) + .flatMap(newActionService::findById) + .flatMap(newlyCreatedAction -> { + newlyCreatedAction.getUnpublishedAction().setCollectionId(newlyCreatedAction.getId()); + return newActionService.update(newlyCreatedAction.getId(), newlyCreatedAction); + }) + .collectList(); + }); + }) + .collectList() + .thenReturn(actionIdsMap); }); }); }) - .flatMap(newAction -> { - final String originalActionId = newAction.getId(); - log.info("Creating clone of action {}", originalActionId); - makePristine(newAction); - newAction.setOrganizationId(toOrganizationId); - ActionDTO action = newAction.getUnpublishedAction(); - action.setCollectionId(null); - - Mono actionMono = Mono.just(action); - final Datasource datasourceInsideAction = action.getDatasource(); - if (datasourceInsideAction != null) { - if (datasourceInsideAction.getId() != null) { - final String datasourceId = datasourceInsideAction.getId(); - if (!cloneDatasourceMonos.containsKey(datasourceId)) { - cloneDatasourceMonos.put(datasourceId, cloneDatasource(datasourceId, toOrganizationId).cache()); - } - actionMono = cloneDatasourceMonos.get(datasourceId) - .map(newDatasource -> { - action.setDatasource(newDatasource); - return action; - }); - } else { - datasourceInsideAction.setOrganizationId(toOrganizationId); - } - } - return actionMono - .flatMap(actionDTO -> layoutActionService.createAction( - actionDTO, new AppsmithEventContext(AppsmithEventContextType.CLONE_PAGE)) - ) - .map(ActionDTO::getId) - .zipWith(Mono.justOrEmpty(originalActionId)); - }) - // This call to `collectMap` will wait for all actions in all pages to have been processed, and so the - // `clonedPages` list will also contain all pages cloned. - .collectMap(Tuple2::getT2, Tuple2::getT1) - .flatMapMany(actionIdsMap -> updateActionIdsInClonedPages(clonedPages, actionIdsMap)) + .flatMap(actionIdsMap -> updateActionIdsInClonedPages(clonedPages, actionIdsMap)) // Now publish all the example applications which have been cloned to ensure that there is a // view mode for the newly created user. .then(Mono.just(newApplicationIds)) diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ExamplesOrganizationClonerTests.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ExamplesOrganizationClonerTests.java index a6e9d10959..ccd6bab02b 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ExamplesOrganizationClonerTests.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ExamplesOrganizationClonerTests.java @@ -4,6 +4,7 @@ import com.appsmith.external.models.ActionConfiguration; import com.appsmith.external.models.AuthenticationResponse; import com.appsmith.external.models.Connection; import com.appsmith.external.models.DBAuth; +import com.appsmith.external.models.Datasource; import com.appsmith.external.models.DatasourceConfiguration; import com.appsmith.external.models.Endpoint; import com.appsmith.external.models.OAuth2; @@ -11,15 +12,18 @@ import com.appsmith.external.models.PEMCertificate; import com.appsmith.external.models.Property; import com.appsmith.external.models.SSLDetails; import com.appsmith.external.models.UploadedFile; +import com.appsmith.external.plugins.PluginExecutor; import com.appsmith.server.constants.FieldName; import com.appsmith.server.domains.Application; import com.appsmith.server.domains.ApplicationPage; -import com.appsmith.external.models.Datasource; import com.appsmith.server.domains.Layout; import com.appsmith.server.domains.NewAction; import com.appsmith.server.domains.NewPage; import com.appsmith.server.domains.Organization; import com.appsmith.server.domains.Plugin; +import com.appsmith.server.domains.PluginType; +import com.appsmith.server.domains.User; +import com.appsmith.server.dtos.ActionCollectionDTO; import com.appsmith.server.dtos.ActionDTO; import com.appsmith.server.dtos.DslActionDTO; import com.appsmith.server.dtos.PageDTO; @@ -33,6 +37,7 @@ import com.appsmith.server.services.ApplicationPageService; import com.appsmith.server.services.ApplicationService; import com.appsmith.server.services.DatasourceService; import com.appsmith.server.services.LayoutActionService; +import com.appsmith.server.services.LayoutCollectionService; import com.appsmith.server.services.NewActionService; import com.appsmith.server.services.NewPageService; import com.appsmith.server.services.OrganizationService; @@ -111,6 +116,9 @@ public class ExamplesOrganizationClonerTests { @MockBean private PluginExecutorHelper pluginExecutorHelper; + @MockBean + PluginExecutor pluginExecutor; + @Autowired private LayoutActionService layoutActionService; @@ -128,11 +136,15 @@ public class ExamplesOrganizationClonerTests { private Plugin installedPlugin; + @Autowired + private LayoutCollectionService layoutCollectionService; + private static class OrganizationData { Organization organization; List applications = new ArrayList<>(); List datasources = new ArrayList<>(); List actions = new ArrayList<>(); + List actionCollections = new ArrayList<>(); } public Mono loadOrganizationData(Organization organization) { @@ -148,7 +160,9 @@ public class ExamplesOrganizationClonerTests { .findAllByOrganizationId(organization.getId(), READ_DATASOURCES) .map(data.datasources::add), getActionsInOrganization(organization) - .map(data.actions::add) + .map(data.actions::add), + getActionCollectionsInOrganization(organization) + .map(data.actionCollections::add) ) .thenReturn(data); } @@ -180,6 +194,7 @@ public class ExamplesOrganizationClonerTests { assertThat(data.applications).isEmpty(); assertThat(data.datasources).isEmpty(); assertThat(data.actions).isEmpty(); + assertThat(data.actionCollections).isEmpty(); }) .verifyComplete(); } @@ -233,6 +248,7 @@ public class ExamplesOrganizationClonerTests { assertThat(data.datasources).isEmpty(); assertThat(data.actions).isEmpty(); + assertThat(data.actionCollections).isEmpty(); }) .verifyComplete(); } @@ -303,6 +319,7 @@ public class ExamplesOrganizationClonerTests { assertThat(data.datasources).isEmpty(); assertThat(data.actions).isEmpty(); + assertThat(data.actionCollections).isEmpty(); }) .verifyComplete(); } @@ -345,6 +362,7 @@ public class ExamplesOrganizationClonerTests { assertThat(data.applications).isEmpty(); assertThat(data.datasources).isEmpty(); assertThat(data.actions).isEmpty(); + assertThat(data.actionCollections).isEmpty(); }) .verifyComplete(); } @@ -453,6 +471,7 @@ public class ExamplesOrganizationClonerTests { assertThat(data.datasources).isEmpty(); assertThat(data.applications).isEmpty(); assertThat(data.actions).isEmpty(); + assertThat(data.actionCollections).isEmpty(); }) .verifyComplete(); } @@ -514,6 +533,7 @@ public class ExamplesOrganizationClonerTests { assertThat(data.applications).isEmpty(); assertThat(data.actions).isEmpty(); + assertThat(data.actionCollections).isEmpty(); }) .verifyComplete(); } @@ -582,144 +602,136 @@ public class ExamplesOrganizationClonerTests { assertThat(data.datasources).isEmpty(); assertThat(data.actions).isEmpty(); + assertThat(data.actionCollections).isEmpty(); }) .verifyComplete(); } @Test @WithUserDetails(value = "api_user") - public void cloneOrganizationWithDatasourcesAndApplicationsAndActions() { + public void cloneOrganizationWithDatasourcesAndApplicationsAndActionsAndCollections() { Organization newOrganization = new Organization(); newOrganization.setName("Template Organization 2"); - final Mono resultMono = Mono - .zip( - organizationService.create(newOrganization), - sessionUserService.getCurrentUser() - ) - .flatMap(tuple -> { - final Organization organization = tuple.getT1(); + final Organization organization = organizationService.create(newOrganization).block(); + final User user = sessionUserService.getCurrentUser().block(); - final Application app1 = new Application(); - app1.setName("first application"); - app1.setOrganizationId(organization.getId()); - app1.setIsPublic(true); + final Application app1 = new Application(); + app1.setName("first application"); + app1.setOrganizationId(organization.getId()); + app1.setIsPublic(true); - final Application app2 = new Application(); - app2.setName("second application"); - app2.setOrganizationId(organization.getId()); - app2.setIsPublic(true); + final Application app2 = new Application(); + app2.setName("second application"); + app2.setOrganizationId(organization.getId()); + app2.setIsPublic(true); - final Datasource ds1 = new Datasource(); - ds1.setName("datasource 1"); - ds1.setOrganizationId(organization.getId()); - ds1.setPluginId(installedPlugin.getId()); + final Datasource ds1 = new Datasource(); + ds1.setName("datasource 1"); + ds1.setOrganizationId(organization.getId()); + ds1.setPluginId(installedPlugin.getId()); - final Datasource ds2 = new Datasource(); - ds2.setName("datasource 2"); - ds2.setOrganizationId(organization.getId()); - ds2.setPluginId(installedPlugin.getId()); + final Datasource ds2 = new Datasource(); + ds2.setName("datasource 2"); + ds2.setOrganizationId(organization.getId()); + ds2.setPluginId(installedPlugin.getId()); - return Mono - .zip( - applicationPageService.createApplication(app1), - applicationPageService.createApplication(app2), - datasourceService.create(ds1), - datasourceService.create(ds2) - ) - .flatMap(tuple1 -> { - final Application app = tuple1.getT1(); - final String pageId1 = app.getPages().get(0).getId(); - final Datasource ds1WithId = tuple1.getT3(); + final Application app = applicationPageService.createApplication(app1).block(); + final Application app2Again = applicationPageService.createApplication(app2).block(); + final Datasource ds1WithId = datasourceService.create(ds1).block(); + final Datasource ds2WithId = datasourceService.create(ds2).block(); - final PageDTO newPage = new PageDTO(); - newPage.setName("A New Page"); - newPage.setApplicationId(app.getId()); - newPage.setLayouts(new ArrayList<>()); - final Layout layout = new Layout(); - layout.setId(new ObjectId().toString()); - JSONObject dsl = new JSONObject(); - dsl.put("widgetName", "testWidget"); - JSONArray temp = new JSONArray(); - temp.addAll(List.of(new JSONObject(Map.of("key", "testField")))); - dsl.put("dynamicBindingPathList", temp); - dsl.put("testField", "draft {{ newPageAction.data }}"); - layout.setDsl(dsl); - JSONObject publishedDsl = new JSONObject(dsl); - publishedDsl.put("testField", "published {{ newPageAction.data }}"); - layout.setPublishedDsl(publishedDsl); - final DslActionDTO actionDTO = new DslActionDTO(); - final HashSet dslActionDTOS = new HashSet<>(List.of(actionDTO)); - layout.setLayoutOnLoadActions(List.of(dslActionDTOS)); - newPage.getLayouts().add(layout); + final String pageId1 = app.getPages().get(0).getId(); - final ActionDTO newPageAction = new ActionDTO(); - newPageAction.setName("newPageAction"); - newPageAction.setOrganizationId(organization.getId()); - newPageAction.setDatasource(ds1WithId); - newPageAction.setPluginId(installedPlugin.getId()); - newPageAction.setActionConfiguration(new ActionConfiguration()); - newPageAction.getActionConfiguration().setHttpMethod(HttpMethod.GET); + final PageDTO newPage = new PageDTO(); + newPage.setName("A New Page"); + newPage.setApplicationId(app.getId()); + newPage.setLayouts(new ArrayList<>()); + final Layout layout = new Layout(); + layout.setId(new ObjectId().toString()); + JSONObject dsl = new JSONObject(); + dsl.put("widgetName", "testWidget"); + JSONArray temp = new JSONArray(); + temp.addAll(List.of(new JSONObject(Map.of("key", "testField")))); + dsl.put("dynamicBindingPathList", temp); + dsl.put("testField", "draft {{ newPageAction.data }}"); + layout.setDsl(dsl); + JSONObject publishedDsl = new JSONObject(dsl); + publishedDsl.put("testField", "published {{ newPageAction.data }}"); + layout.setPublishedDsl(publishedDsl); + final DslActionDTO actionDTO = new DslActionDTO(); + final HashSet dslActionDTOS = new HashSet<>(List.of(actionDTO)); + layout.setLayoutOnLoadActions(List.of(dslActionDTOS)); + newPage.getLayouts().add(layout); - final ActionDTO action1 = new ActionDTO(); - action1.setName("action1"); - action1.setPageId(pageId1); - action1.setOrganizationId(organization.getId()); - action1.setDatasource(ds1WithId); - action1.setPluginId(installedPlugin.getId()); + final ActionDTO newPageAction = new ActionDTO(); + newPageAction.setName("newPageAction"); + newPageAction.setOrganizationId(organization.getId()); + newPageAction.setDatasource(ds1WithId); + newPageAction.setPluginId(installedPlugin.getId()); + newPageAction.setActionConfiguration(new ActionConfiguration()); + newPageAction.getActionConfiguration().setHttpMethod(HttpMethod.GET); - final ActionDTO action2 = new ActionDTO(); - action2.setPageId(pageId1); - action2.setName("action2"); - action2.setOrganizationId(organization.getId()); - action2.setDatasource(ds1WithId); - action2.setPluginId(installedPlugin.getId()); + final ActionDTO action1 = new ActionDTO(); + action1.setName("action1"); + action1.setPageId(pageId1); + action1.setOrganizationId(organization.getId()); + action1.setDatasource(ds1WithId); + action1.setPluginId(installedPlugin.getId()); - final Application app2Again = tuple1.getT2(); - final String pageId2 = app2Again.getPages().get(0).getId(); - final Datasource ds2WithId = tuple1.getT4(); + final String pageId2 = app2Again.getPages().get(0).getId(); - final ActionDTO action3 = new ActionDTO(); - action3.setName("action3"); - action3.setPageId(pageId2); - action3.setOrganizationId(organization.getId()); - action3.setDatasource(ds2WithId); - action3.setPluginId(installedPlugin.getId()); + final ActionDTO action3 = new ActionDTO(); + action3.setName("action3"); + action3.setPageId(pageId2); + action3.setOrganizationId(organization.getId()); + action3.setDatasource(ds2WithId); + action3.setPluginId(installedPlugin.getId()); - final ActionDTO action4 = new ActionDTO(); - action4.setPageId(pageId2); - action4.setName("action4"); - action4.setOrganizationId(organization.getId()); - action4.setDatasource(ds2WithId); - action4.setPluginId(installedPlugin.getId()); + Mockito.when(pluginExecutorHelper.getPluginExecutor(Mockito.any())).thenReturn(Mono.just(pluginExecutor)); + Mockito.when(pluginExecutor.getHintMessages(Mockito.any(), Mockito.any())) + .thenReturn(Mono.zip(Mono.just(new HashSet<>()), Mono.just(new HashSet<>()))); - return Mono.when( - applicationPageService.createPage(newPage) - .flatMap(page -> { - newPageAction.setPageId(page.getId()); - return applicationPageService.addPageToApplication(app, page, false) - .then(layoutActionService.createSingleAction(newPageAction)) - .flatMap(savedAction -> layoutActionService.updateSingleAction(savedAction.getId(), savedAction)) - .then(newPageService.findPageById(page.getId(), READ_PAGES, false)); - }) - .map(tuple2 -> { - log.info("Created action and added page to app {}", tuple2); - return tuple2; - }), - layoutActionService.createSingleAction(action1), - layoutActionService.createSingleAction(action2), - layoutActionService.createSingleAction(action3), - layoutActionService.createSingleAction(action4) - ).thenReturn(List.of(tuple1.getT1(), tuple1.getT2())); - }) - .flatMap(applications -> - examplesOrganizationCloner.cloneOrganizationForUser( - organization.getId(), - tuple.getT2(), - Flux.fromIterable(applications), - Flux.empty() - ) - ); + Datasource jsDatasource = new Datasource(); + jsDatasource.setName("Default Database"); + jsDatasource.setOrganizationId(organization.getId()); + Plugin installedJsPlugin = pluginRepository.findByPackageName("installed-js-plugin").block(); + assert installedJsPlugin != null; + jsDatasource.setPluginId(installedJsPlugin.getId()); + + ActionCollectionDTO actionCollectionDTO1 = new ActionCollectionDTO(); + actionCollectionDTO1.setName("testCollection1"); + actionCollectionDTO1.setPageId(app.getPages().get(0).getId()); + actionCollectionDTO1.setApplicationId(app.getId()); + actionCollectionDTO1.setOrganizationId(organization.getId()); + actionCollectionDTO1.setPluginId(jsDatasource.getPluginId()); + ActionDTO action5 = new ActionDTO(); + action5.setName("run"); + action5.setActionConfiguration(new ActionConfiguration()); + action5.getActionConfiguration().setBody("mockBody"); + actionCollectionDTO1.setActions(List.of(action5)); + actionCollectionDTO1.setPluginType(PluginType.JS); + + applicationPageService.createPage(newPage) + .flatMap(page -> { + newPageAction.setPageId(page.getId()); + return applicationPageService.addPageToApplication(app, page, false) + .then(layoutActionService.createSingleAction(newPageAction)) + .flatMap(savedAction -> layoutActionService.updateSingleAction(savedAction.getId(), savedAction)) + .then(newPageService.findPageById(page.getId(), READ_PAGES, false)); }) + .map(tuple2 -> { + log.info("Created action and added page to app {}", tuple2); + return tuple2; + }).block(); + layoutActionService.createSingleAction(action1).block(); + layoutActionService.createSingleAction(action3).block(); + layoutCollectionService.createCollection(actionCollectionDTO1).block(); + + final Mono resultMono = examplesOrganizationCloner.cloneOrganizationForUser( + organization.getId(), + user, + Flux.fromIterable(List.of(app, app2Again)), + Flux.empty()) .doOnError(error -> log.error("Error preparing data for test", error)) .flatMap(this::loadOrganizationData); @@ -736,16 +748,15 @@ public class ExamplesOrganizationClonerTests { "second application" ); - final Application firstApplication = data.applications.stream().filter(app -> app.getName().equals("first application")).findFirst().orElse(null); + final Application firstApplication = data.applications.stream().filter(appFirst -> appFirst.getName().equals("first application")).findFirst().orElse(null); assert firstApplication != null; assertThat(firstApplication.getPages().stream().filter(ApplicationPage::isDefault).count()).isEqualTo(1); - final NewPage newPage = mongoTemplate.findOne(Query.query(Criteria.where("applicationId").is(firstApplication.getId()).and("unpublishedPage.name").is("A New Page")), NewPage.class); - assert newPage != null; - log.debug("new page is : {}", newPage.toString()); - final String actionId = newPage.getUnpublishedPage().getLayouts().get(0).getLayoutOnLoadActions().get(0).iterator().next().getId(); - final NewAction newPageAction = mongoTemplate.findOne(Query.query(Criteria.where("id").is(actionId)), NewAction.class); - assert newPageAction != null; - assertThat(newPageAction.getOrganizationId()).isEqualTo(data.organization.getId()); + final NewPage newPage1 = mongoTemplate.findOne(Query.query(Criteria.where("applicationId").is(firstApplication.getId()).and("unpublishedPage.name").is("A New Page")), NewPage.class); + assert newPage1 != null; + final String actionId = newPage1.getUnpublishedPage().getLayouts().get(0).getLayoutOnLoadActions().get(0).iterator().next().getId(); + final NewAction newPageAction1 = mongoTemplate.findOne(Query.query(Criteria.where("id").is(actionId)), NewAction.class); + assert newPageAction1 != null; + assertThat(newPageAction1.getOrganizationId()).isEqualTo(data.organization.getId()); assertThat(data.datasources).hasSize(2); assertThat(map(data.datasources, Datasource::getName)).containsExactlyInAnyOrder( @@ -753,16 +764,18 @@ public class ExamplesOrganizationClonerTests { "datasource 2" ); - assertThat(data.actions).hasSize(5); + assertThat(data.actions).hasSize(4); assertThat(getUnpublishedActionName(data.actions)).containsExactlyInAnyOrder( "newPageAction", "action1", - "action2", "action3", - "action4" + "run" ); + assertThat(data.actionCollections).hasSize(1); + assertThat(data.actionCollections.get(0).getActionIds()).hasSize(1); }) .verifyComplete(); + } @Test @@ -1014,4 +1027,13 @@ public class ExamplesOrganizationClonerTests { .flatMap(page -> newActionService.getUnpublishedActions(new LinkedMultiValueMap<>( Map.of(FieldName.PAGE_ID, Collections.singletonList(page.getId()))))); } + + private Flux getActionCollectionsInOrganization(Organization organization) { + return applicationService + .findByOrganizationId(organization.getId(), READ_APPLICATIONS) + // fetch the unpublished pages + .flatMap(application -> newPageService.findByApplicationId(application.getId(), READ_PAGES, false)) + .flatMap(page -> actionCollectionService.getActionCollectionsByViewMode(new LinkedMultiValueMap<>( + Map.of(FieldName.PAGE_ID, Collections.singletonList(page.getId()))), false)); + } }