fix: Forking fails when template has REST datasource with Bearer Token Authentication (#19930)
## Description When an application is exported with credentials i.e. template application, it does not contain the bearer token authentication credentials. As a result, when user is trying to import this application, the datasource configuration popup appears. This PR fixes this issue. TL;DR enable export-import application with bearer token authentication Fixes #19415 Media > A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video ## Type of change - Bug fix (non-breaking change which fixes an issue) ## How Has This Been Tested? - Manual - Jest ### Test Plan > Add Testsmith test cases links that relate to this PR ### Issues raised during DP testing > Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR) ## Checklist: ### Dev activity - [x] My code follows the style guidelines of this project - [x] I have performed a self-review of my own code - [x] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [x] My changes generate no new warnings - [x] I have added tests that prove my fix is effective or that my feature works - [x] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag ### QA activity: - [ ] Test plan has been approved by relevant developers - [ ] Test plan has been peer reviewed by QA - [ ] Cypress test cases have been added and approved by either SDET or manual QA - [ ] Organized project review call with relevant stakeholders after Round 1/2 of QA - [ ] Added Test Plan Approved label after reveiwing all Cypress test
This commit is contained in:
parent
e4ade30d18
commit
89ae5ddf7f
|
|
@ -30,6 +30,8 @@ public class DecryptedSensitiveFields {
|
|||
BasicAuth basicAuth;
|
||||
|
||||
OAuth2 openAuth2;
|
||||
|
||||
BearerTokenAuth bearerTokenAuth;
|
||||
|
||||
public DecryptedSensitiveFields(AuthenticationResponse authResponse) {
|
||||
this.token = authResponse.getToken();
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.appsmith.external.models.AuthenticationDTO;
|
|||
import com.appsmith.external.models.AuthenticationResponse;
|
||||
import com.appsmith.external.models.BaseDomain;
|
||||
import com.appsmith.external.models.BasicAuth;
|
||||
import com.appsmith.external.models.BearerTokenAuth;
|
||||
import com.appsmith.external.models.DBAuth;
|
||||
import com.appsmith.external.models.Datasource;
|
||||
import com.appsmith.external.models.DatasourceConfiguration;
|
||||
|
|
@ -1983,6 +1984,10 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
|
|||
authResponse.setExpiresAt(Instant.now());
|
||||
auth2.setAuthenticationResponse(authResponse);
|
||||
datasource.getDatasourceConfiguration().setAuthentication(auth2);
|
||||
} else if (StringUtils.equals(authType, BearerTokenAuth.class.getName())) {
|
||||
BearerTokenAuth auth = new BearerTokenAuth();
|
||||
auth.setBearerToken(decryptedFields.getBearerTokenAuth().getBearerToken());
|
||||
datasource.getDatasourceConfiguration().setAuthentication(auth);
|
||||
}
|
||||
return datasource;
|
||||
}
|
||||
|
|
@ -2020,6 +2025,8 @@ public class ImportExportApplicationServiceCEImpl implements ImportExportApplica
|
|||
} else if (authentication instanceof BasicAuth auth) {
|
||||
dsDecryptedFields.setPassword(auth.getPassword());
|
||||
dsDecryptedFields.setBasicAuth(auth);
|
||||
} else if (authentication instanceof BearerTokenAuth auth) {
|
||||
dsDecryptedFields.setBearerTokenAuth(auth);
|
||||
}
|
||||
dsDecryptedFields.setAuthType(authentication.getClass().getName());
|
||||
return dsDecryptedFields;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.appsmith.external.models.AuthenticationDTO;
|
|||
import com.appsmith.external.models.AuthenticationResponse;
|
||||
import com.appsmith.external.models.BaseDomain;
|
||||
import com.appsmith.external.models.BasicAuth;
|
||||
import com.appsmith.external.models.BearerTokenAuth;
|
||||
import com.appsmith.external.models.DBAuth;
|
||||
import com.appsmith.external.models.Datasource;
|
||||
import com.appsmith.external.models.DatasourceConfiguration;
|
||||
|
|
@ -32,7 +33,6 @@ import com.appsmith.server.domains.Workspace;
|
|||
import com.appsmith.server.dtos.ActionCollectionDTO;
|
||||
import com.appsmith.server.dtos.ApplicationImportDTO;
|
||||
import com.appsmith.server.dtos.ApplicationJson;
|
||||
import com.appsmith.server.dtos.CustomJSLibApplicationDTO;
|
||||
import com.appsmith.server.dtos.ExportFileDTO;
|
||||
import com.appsmith.server.dtos.PageDTO;
|
||||
import com.appsmith.server.exceptions.AppsmithError;
|
||||
|
|
@ -2019,6 +2019,10 @@ public class ImportExportApplicationServiceCEImplV2 implements ImportExportAppli
|
|||
authResponse.setExpiresAt(Instant.now());
|
||||
auth2.setAuthenticationResponse(authResponse);
|
||||
datasource.getDatasourceConfiguration().setAuthentication(auth2);
|
||||
} else if (org.apache.commons.lang.StringUtils.equals(authType, BearerTokenAuth.class.getName())) {
|
||||
BearerTokenAuth auth = new BearerTokenAuth();
|
||||
auth.setBearerToken(decryptedFields.getBearerTokenAuth().getBearerToken());
|
||||
datasource.getDatasourceConfiguration().setAuthentication(auth);
|
||||
}
|
||||
return datasource;
|
||||
}
|
||||
|
|
@ -2059,6 +2063,8 @@ public class ImportExportApplicationServiceCEImplV2 implements ImportExportAppli
|
|||
BasicAuth auth = (BasicAuth) authentication;
|
||||
dsDecryptedFields.setPassword(auth.getPassword());
|
||||
dsDecryptedFields.setBasicAuth(auth);
|
||||
} else if (authentication instanceof BearerTokenAuth auth) {
|
||||
dsDecryptedFields.setBearerTokenAuth(auth);
|
||||
}
|
||||
dsDecryptedFields.setAuthType(authentication.getClass().getName());
|
||||
return dsDecryptedFields;
|
||||
|
|
|
|||
|
|
@ -3,13 +3,17 @@ package com.appsmith.server.solutions;
|
|||
import com.appsmith.external.helpers.AppsmithBeanUtils;
|
||||
import com.appsmith.external.models.ActionConfiguration;
|
||||
import com.appsmith.external.models.ActionDTO;
|
||||
import com.appsmith.external.models.BearerTokenAuth;
|
||||
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.DecryptedSensitiveFields;
|
||||
import com.appsmith.external.models.InvisibleActionFields;
|
||||
import com.appsmith.external.models.PluginType;
|
||||
import com.appsmith.external.models.Policy;
|
||||
import com.appsmith.external.models.Property;
|
||||
import com.appsmith.external.models.SSLDetails;
|
||||
import com.appsmith.server.constants.FieldName;
|
||||
import com.appsmith.server.constants.SerialiseApplicationObjective;
|
||||
import com.appsmith.server.domains.ActionCollection;
|
||||
|
|
@ -3509,4 +3513,79 @@ public class ImportExportApplicationServiceTests {
|
|||
.verifyComplete();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUserDetails(value = "api_user")
|
||||
public void exportApplication_WithBearerTokenAndExportWithConfig_exportedWithDecryptedFields() {
|
||||
String randomUUID = UUID.randomUUID().toString();
|
||||
|
||||
Workspace testWorkspace = new Workspace();
|
||||
testWorkspace.setName("workspace-" + randomUUID);
|
||||
// User apiUser = userService.findByEmail("api_user").block();
|
||||
Mono<Workspace> workspaceMono = workspaceService.create(testWorkspace).cache();
|
||||
|
||||
Mono<Application> applicationMono = workspaceMono.flatMap(workspace -> {
|
||||
Application testApplication = new Application();
|
||||
testApplication.setName("application-" + randomUUID);
|
||||
testApplication.setExportWithConfiguration(true);
|
||||
testApplication.setWorkspaceId(workspace.getId());
|
||||
return applicationPageService.createApplication(testApplication);
|
||||
}).flatMap(application -> {
|
||||
ApplicationAccessDTO accessDTO = new ApplicationAccessDTO();
|
||||
accessDTO.setPublicAccess(true);
|
||||
return applicationService.changeViewAccess(application.getId(), accessDTO).thenReturn(application);
|
||||
});
|
||||
|
||||
Mono<Datasource> datasourceMono = workspaceMono.zipWith(pluginRepository.findByPackageName("restapi-plugin"))
|
||||
.flatMap(objects -> {
|
||||
Workspace workspace = objects.getT1();
|
||||
Plugin plugin = objects.getT2();
|
||||
|
||||
Datasource datasource = new Datasource();
|
||||
datasource.setPluginId(plugin.getId());
|
||||
datasource.setName("RestAPIWithBearerToken");
|
||||
datasource.setWorkspaceId(workspace.getId());
|
||||
datasource.setIsConfigured(true);
|
||||
|
||||
BearerTokenAuth bearerTokenAuth = new BearerTokenAuth();
|
||||
bearerTokenAuth.setBearerToken("token_" + randomUUID);
|
||||
|
||||
SSLDetails sslDetails = new SSLDetails();
|
||||
sslDetails.setAuthType(SSLDetails.AuthType.DEFAULT);
|
||||
Connection connection = new Connection();
|
||||
connection.setSsl(sslDetails);
|
||||
|
||||
DatasourceConfiguration datasourceConfiguration = new DatasourceConfiguration();
|
||||
datasourceConfiguration.setAuthentication(bearerTokenAuth);
|
||||
datasourceConfiguration.setConnection(connection);
|
||||
datasourceConfiguration.setConnection(new Connection());
|
||||
datasourceConfiguration.setUrl("https://mock-api.appsmith.com");
|
||||
|
||||
datasource.setDatasourceConfiguration(datasourceConfiguration);
|
||||
return datasourceService.create(datasource);
|
||||
});
|
||||
|
||||
Mono<ApplicationJson> exportAppMono = Mono.zip(applicationMono, datasourceMono).flatMap(objects -> {
|
||||
ApplicationPage applicationPage = objects.getT1().getPages().get(0);
|
||||
ActionDTO action = new ActionDTO();
|
||||
action.setName("validAction");
|
||||
action.setPageId(applicationPage.getId());
|
||||
action.setPluginId(objects.getT2().getPluginId());
|
||||
action.setDatasource(objects.getT2());
|
||||
|
||||
ActionConfiguration actionConfiguration = new ActionConfiguration();
|
||||
actionConfiguration.setHttpMethod(HttpMethod.GET);
|
||||
actionConfiguration.setPath("/test/path");
|
||||
action.setActionConfiguration(actionConfiguration);
|
||||
|
||||
return layoutActionService.createSingleAction(action, Boolean.FALSE)
|
||||
.then(importExportApplicationService.exportApplicationById(objects.getT1().getId(), ""));
|
||||
});
|
||||
|
||||
StepVerifier.create(exportAppMono).assertNext(applicationJson -> {
|
||||
assertThat(applicationJson.getDecryptedFields()).isNotEmpty();
|
||||
DecryptedSensitiveFields fields = applicationJson.getDecryptedFields().get("RestAPIWithBearerToken");
|
||||
assertThat(fields.getBearerTokenAuth().getBearerToken()).isEqualTo("token_" + randomUUID);
|
||||
}).verifyComplete();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,17 @@ package com.appsmith.server.solutions;
|
|||
import com.appsmith.external.helpers.AppsmithBeanUtils;
|
||||
import com.appsmith.external.models.ActionConfiguration;
|
||||
import com.appsmith.external.models.ActionDTO;
|
||||
import com.appsmith.external.models.BearerTokenAuth;
|
||||
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.DecryptedSensitiveFields;
|
||||
import com.appsmith.external.models.InvisibleActionFields;
|
||||
import com.appsmith.external.models.PluginType;
|
||||
import com.appsmith.external.models.Policy;
|
||||
import com.appsmith.external.models.Property;
|
||||
import com.appsmith.external.models.SSLDetails;
|
||||
import com.appsmith.server.constants.FieldName;
|
||||
import com.appsmith.server.constants.SerialiseApplicationObjective;
|
||||
import com.appsmith.server.domains.ActionCollection;
|
||||
|
|
@ -30,7 +34,6 @@ import com.appsmith.server.dtos.ApplicationAccessDTO;
|
|||
import com.appsmith.server.dtos.ApplicationImportDTO;
|
||||
import com.appsmith.server.dtos.ApplicationJson;
|
||||
import com.appsmith.server.dtos.ApplicationPagesDTO;
|
||||
import com.appsmith.server.dtos.CustomJSLibApplicationDTO;
|
||||
import com.appsmith.server.dtos.PageDTO;
|
||||
import com.appsmith.server.dtos.PageNameIdDTO;
|
||||
import com.appsmith.server.exceptions.AppsmithError;
|
||||
|
|
@ -95,7 +98,6 @@ import java.time.Instant;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
|
@ -3601,4 +3603,79 @@ public class ImportExportApplicationServiceV2Tests {
|
|||
.verifyComplete();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUserDetails(value = "api_user")
|
||||
public void exportApplication_WithBearerTokenAndExportWithConfig_exportedWithDecryptedFields() {
|
||||
String randomUUID = UUID.randomUUID().toString();
|
||||
|
||||
Workspace testWorkspace = new Workspace();
|
||||
testWorkspace.setName("workspace-" + randomUUID);
|
||||
// User apiUser = userService.findByEmail("api_user").block();
|
||||
Mono<Workspace> workspaceMono = workspaceService.create(testWorkspace).cache();
|
||||
|
||||
Mono<Application> applicationMono = workspaceMono.flatMap(workspace -> {
|
||||
Application testApplication = new Application();
|
||||
testApplication.setName("application-" + randomUUID);
|
||||
testApplication.setExportWithConfiguration(true);
|
||||
testApplication.setWorkspaceId(workspace.getId());
|
||||
return applicationPageService.createApplication(testApplication);
|
||||
}).flatMap(application -> {
|
||||
ApplicationAccessDTO accessDTO = new ApplicationAccessDTO();
|
||||
accessDTO.setPublicAccess(true);
|
||||
return applicationService.changeViewAccess(application.getId(), accessDTO).thenReturn(application);
|
||||
});
|
||||
|
||||
Mono<Datasource> datasourceMono = workspaceMono.zipWith(pluginRepository.findByPackageName("restapi-plugin"))
|
||||
.flatMap(objects -> {
|
||||
Workspace workspace = objects.getT1();
|
||||
Plugin plugin = objects.getT2();
|
||||
|
||||
Datasource datasource = new Datasource();
|
||||
datasource.setPluginId(plugin.getId());
|
||||
datasource.setName("RestAPIWithBearerToken");
|
||||
datasource.setWorkspaceId(workspace.getId());
|
||||
datasource.setIsConfigured(true);
|
||||
|
||||
BearerTokenAuth bearerTokenAuth = new BearerTokenAuth();
|
||||
bearerTokenAuth.setBearerToken("token_" + randomUUID);
|
||||
|
||||
SSLDetails sslDetails = new SSLDetails();
|
||||
sslDetails.setAuthType(SSLDetails.AuthType.DEFAULT);
|
||||
Connection connection = new Connection();
|
||||
connection.setSsl(sslDetails);
|
||||
|
||||
DatasourceConfiguration datasourceConfiguration = new DatasourceConfiguration();
|
||||
datasourceConfiguration.setAuthentication(bearerTokenAuth);
|
||||
datasourceConfiguration.setConnection(connection);
|
||||
datasourceConfiguration.setConnection(new Connection());
|
||||
datasourceConfiguration.setUrl("https://mock-api.appsmith.com");
|
||||
|
||||
datasource.setDatasourceConfiguration(datasourceConfiguration);
|
||||
return datasourceService.create(datasource);
|
||||
});
|
||||
|
||||
Mono<ApplicationJson> exportAppMono = Mono.zip(applicationMono, datasourceMono).flatMap(objects -> {
|
||||
ApplicationPage applicationPage = objects.getT1().getPages().get(0);
|
||||
ActionDTO action = new ActionDTO();
|
||||
action.setName("validAction");
|
||||
action.setPageId(applicationPage.getId());
|
||||
action.setPluginId(objects.getT2().getPluginId());
|
||||
action.setDatasource(objects.getT2());
|
||||
|
||||
ActionConfiguration actionConfiguration = new ActionConfiguration();
|
||||
actionConfiguration.setHttpMethod(HttpMethod.GET);
|
||||
actionConfiguration.setPath("/test/path");
|
||||
action.setActionConfiguration(actionConfiguration);
|
||||
|
||||
return layoutActionService.createSingleAction(action, Boolean.FALSE)
|
||||
.then(importExportApplicationService.exportApplicationById(objects.getT1().getId(), ""));
|
||||
});
|
||||
|
||||
StepVerifier.create(exportAppMono).assertNext(applicationJson -> {
|
||||
assertThat(applicationJson.getDecryptedFields()).isNotEmpty();
|
||||
DecryptedSensitiveFields fields = applicationJson.getDecryptedFields().get("RestAPIWithBearerToken");
|
||||
assertThat(fields.getBearerTokenAuth().getBearerToken()).isEqualTo("token_" + randomUUID);
|
||||
}).verifyComplete();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user