diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/fork/internal/ApplicationForkingServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/fork/internal/ApplicationForkingServiceCEImpl.java index d7d11ea8e1..a1dd2e59d5 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/fork/internal/ApplicationForkingServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/fork/internal/ApplicationForkingServiceCEImpl.java @@ -348,6 +348,14 @@ public class ApplicationForkingServiceCEImpl implements ApplicationForkingServic }) .flatMapIterable(tuple2 -> clonedPages) .flatMap(clonedPage -> updateLayoutService.updatePageLayoutsByPageId(clonedPage.getId())) + .onErrorResume(throwable -> { + if (throwable instanceof AppsmithException e + && AppsmithError.INVALID_DYNAMIC_BINDING_REFERENCE.equals(e.getError())) { + log.error("Error while cloning page {} ", throwable.getMessage()); + return Mono.just(""); + } + return Mono.error(throwable); + }) // 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/ApplicationForkingServiceTests.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/fork/ApplicationForkingServiceTests.java similarity index 99% rename from app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ApplicationForkingServiceTests.java rename to app/server/appsmith-server/src/test/java/com/appsmith/server/fork/ApplicationForkingServiceTests.java index 8643b8b883..cc92112d72 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/solutions/ApplicationForkingServiceTests.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/fork/ApplicationForkingServiceTests.java @@ -1,4 +1,4 @@ -package com.appsmith.server.solutions; +package com.appsmith.server.fork; import com.appsmith.external.models.ActionConfiguration; import com.appsmith.external.models.ActionDTO; @@ -58,6 +58,10 @@ import com.appsmith.server.services.LayoutCollectionService; import com.appsmith.server.services.PermissionGroupService; import com.appsmith.server.services.SessionUserService; import com.appsmith.server.services.WorkspaceService; +import com.appsmith.server.solutions.EnvironmentPermission; +import com.appsmith.server.solutions.PagePermission; +import com.appsmith.server.solutions.UserAndAccessManagementService; +import com.appsmith.server.solutions.WorkspacePermission; import com.appsmith.server.themes.base.ThemeService; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/fork/ForkingServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/fork/ForkingServiceTest.java new file mode 100644 index 0000000000..3a4e877c20 --- /dev/null +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/fork/ForkingServiceTest.java @@ -0,0 +1,98 @@ +package com.appsmith.server.fork; + +import com.appsmith.server.domains.Application; +import com.appsmith.server.domains.Workspace; +import com.appsmith.server.exceptions.AppsmithError; +import com.appsmith.server.exceptions.AppsmithException; +import com.appsmith.server.fork.internal.ApplicationForkingService; +import com.appsmith.server.layouts.UpdateLayoutService; +import com.appsmith.server.repositories.ApplicationRepository; +import com.appsmith.server.services.ApplicationPageService; +import com.appsmith.server.services.WorkspaceService; +import com.appsmith.server.solutions.EnvironmentPermission; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.security.test.context.support.WithUserDetails; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; + +@Slf4j +@ExtendWith(SpringExtension.class) +@SpringBootTest +public class ForkingServiceTest { + + @Autowired + private ApplicationForkingService applicationForkingService; + + @Autowired + private WorkspaceService workspaceService; + + @Autowired + private ApplicationPageService applicationPageService; + + @Autowired + private ApplicationRepository applicationRepository; + + @Autowired + private EnvironmentPermission environmentPermission; + + @MockBean + private UpdateLayoutService updateLayoutService; + + @Test + @WithUserDetails(value = "api_user") + public void cloneApplication_whenDslParsingFails_shouldSucceed() { + Workspace originalWorkspace = new Workspace(); + originalWorkspace.setName("Source Org Test"); + Workspace sourceWorkspace = workspaceService.create(originalWorkspace).block(); + + Application app1 = new Application(); + app1.setName("awesome app 123"); + app1.setWorkspaceId(sourceWorkspace.getId()); + Application sourceApplication = + applicationPageService.createApplication(app1).block(); + final String appId = sourceApplication.getId(); + final String appName = sourceApplication.getName(); + + Mockito.when(updateLayoutService.updatePageLayoutsByPageId(Mockito.anyString())) + .thenThrow(new AppsmithException(AppsmithError.INVALID_DYNAMIC_BINDING_REFERENCE)); + + Workspace newWorkspace = new Workspace(); + newWorkspace.setName("Target Org Test"); + Workspace targetWorkspace = workspaceService.create(newWorkspace).block(); + String sourceEnvironmentId = workspaceService + .getDefaultEnvironmentId(sourceWorkspace.getId(), environmentPermission.getExecutePermission()) + .block(); + + Mono cloneMono = Mono.just(sourceApplication) + .map(sourceApplication1 -> { + sourceApplication1.setName(appName); + sourceApplication1.setId(appId); + return sourceApplication1; + }) + .flatMap(sourceApplication1 -> applicationForkingService.forkApplications( + targetWorkspace.getId(), sourceApplication1, sourceEnvironmentId)) + .then(); + + Mono> resultMono = cloneMono + .thenMany(applicationRepository.findByWorkspaceId(targetWorkspace.getId())) + .map(Application::getName) + .collectList(); + + StepVerifier.create(resultMono) + .assertNext(names -> { + assertThat(names).hasSize(1); + }) + .verifyComplete(); + } +}