From 734b563237cbf60d1be6bc3167e83db546b574be Mon Sep 17 00:00:00 2001 From: Nidhi Date: Wed, 23 Aug 2023 16:32:14 +0530 Subject: [PATCH] fix: Make sure updatable connections come back with decrypted tokens (#26558) --- .../ce/DatasourceContextServiceCEImpl.java | 11 ++- .../DatasourceContextServiceTest.java | 78 +++++++++++++++++++ 2 files changed, 83 insertions(+), 6 deletions(-) diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/DatasourceContextServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/DatasourceContextServiceCEImpl.java index 3ae2df532e..26ddf22e25 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/DatasourceContextServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/ce/DatasourceContextServiceCEImpl.java @@ -147,15 +147,14 @@ public class DatasourceContextServiceCEImpl implements DatasourceContextServiceC public Mono updateDatasourceAndSetAuthentication(Object connection, DatasourceStorage datasourceStorage) { Mono datasourceStorageMono = Mono.just(datasourceStorage); - if (connection instanceof UpdatableConnection) { + if (connection instanceof UpdatableConnection updatableConnection) { datasourceStorage.setUpdatedAt(Instant.now()); datasourceStorage .getDatasourceConfiguration() - .setAuthentication(((UpdatableConnection) connection) - .getAuthenticationDTO(datasourceStorage - .getDatasourceConfiguration() - .getAuthentication())); - datasourceStorageMono = datasourceStorageService.save(datasourceStorage); + .setAuthentication(updatableConnection.getAuthenticationDTO( + datasourceStorage.getDatasourceConfiguration().getAuthentication())); + datasourceStorageMono = datasourceStorageService.updateDatasourceStorage( + datasourceStorage, datasourceStorage.getEnvironmentId(), Boolean.FALSE); } return datasourceStorageMono.thenReturn(connection); } diff --git a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/DatasourceContextServiceTest.java b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/DatasourceContextServiceTest.java index c9a6f58f0c..36eca71702 100644 --- a/app/server/appsmith-server/src/test/java/com/appsmith/server/services/DatasourceContextServiceTest.java +++ b/app/server/appsmith-server/src/test/java/com/appsmith/server/services/DatasourceContextServiceTest.java @@ -1,12 +1,15 @@ package com.appsmith.server.services; +import com.appsmith.external.helpers.restApiUtils.connections.OAuth2ClientCredentials; import com.appsmith.external.models.ApiKeyAuth; +import com.appsmith.external.models.AuthenticationDTO; import com.appsmith.external.models.BasicAuth; import com.appsmith.external.models.DBAuth; import com.appsmith.external.models.Datasource; import com.appsmith.external.models.DatasourceConfiguration; import com.appsmith.external.models.DatasourceStorage; import com.appsmith.external.models.DatasourceStorageDTO; +import com.appsmith.external.models.OAuth2; import com.appsmith.external.models.UpdatableConnection; import com.appsmith.external.plugins.PluginExecutor; import com.appsmith.external.services.EncryptionService; @@ -419,6 +422,7 @@ public class DatasourceContextServiceTest { DatasourceStorage createdDatasourceStorage = datasourceStorageService.createDatasourceStorageFromDatasourceStorageDTO(datasourceStorageDTO); + createdDatasourceStorage.setPluginId(createdDatasource.getPluginId()); DatasourceContextIdentifier datasourceContextIdentifier = new DatasourceContextIdentifier(createdDatasource.getId(), defaultEnvironmentId); @@ -545,4 +549,78 @@ public class DatasourceContextServiceTest { assertThat(datasourceContextIdentifier.getDatasourceId()).isEqualTo(sampleDatasourceId); assertThat(datasourceContextIdentifier.getEnvironmentId()).isEqualTo(defaultEnvironmentId); } + + @Test + @WithUserDetails(value = "api_user") + public void + testUpdateDatasourceAndSetAuthentication_withNoRealChange_keepsDatasourceConfigurationValuesDecrypted() { + Mockito.when(pluginExecutorHelper.getPluginExecutor(Mockito.any())) + .thenReturn(Mono.just(new MockPluginExecutor())); + + Mono pluginMono = pluginService.findByPackageName("restapi-plugin"); + Datasource datasource = new Datasource(); + datasource.setName( + "testUpdateDatasourceAndSetAuthentication_withNoRealChange_keepsDatasourceConfigurationValuesDecrypted"); + DatasourceConfiguration datasourceConfiguration = new DatasourceConfiguration(); + datasourceConfiguration.setUrl("http://test.com"); + OAuth2 authenticationDTO = new OAuth2(); + String username = "username"; + String password = "This is the decrypted value to test for"; + authenticationDTO.setClientId(username); + authenticationDTO.setClientSecret(password); + authenticationDTO.setAccessTokenUrl("http://test.com"); + authenticationDTO.setGrantType(OAuth2.Type.CLIENT_CREDENTIALS); + datasourceConfiguration.setAuthentication(authenticationDTO); + datasource.setWorkspaceId(workspaceId); + + DatasourceStorageDTO datasourceStorageDTO = new DatasourceStorageDTO(); + datasourceStorageDTO.setDatasourceConfiguration(datasourceConfiguration); + datasourceStorageDTO.setEnvironmentId(defaultEnvironmentId); + datasourceStorageDTO.setIsConfigured(Boolean.TRUE); + + HashMap storages = new HashMap<>(); + storages.put(defaultEnvironmentId, datasourceStorageDTO); + datasource.setDatasourceStorages(storages); + + final Datasource createdDatasource = pluginMono + .map(plugin -> { + datasource.setPluginId(plugin.getId()); + return datasource; + }) + .flatMap(datasourceService::create) + .block(); + + assert createdDatasource != null; + + DatasourceStorage datasourceStorage = datasourceService + .findById(createdDatasource.getId()) + .flatMap(datasource1 -> + datasourceStorageService.findByDatasourceAndEnvironmentId(datasource1, defaultEnvironmentId)) + .block(); + + OAuth2ClientCredentials oAuth2ClientCredentials = Mockito.mock(OAuth2ClientCredentials.class); + Mockito.when(oAuth2ClientCredentials.getAuthenticationDTO(Mockito.any())) + .thenCallRealMethod(); + + // Check that the value was decrypted before + DatasourceConfiguration savedDsConfig = datasourceStorage.getDatasourceConfiguration(); + AuthenticationDTO auth1 = savedDsConfig.getAuthentication(); + assertThat(auth1).isInstanceOf(OAuth2.class); + assertThat(((OAuth2) auth1).getClientSecret()).isEqualTo(password); + + Mono resultMono = datasourceContextService.updateDatasourceAndSetAuthentication( + oAuth2ClientCredentials, datasourceStorage); + + // Check that the value remains decrypted after + StepVerifier.create(resultMono) + .assertNext(result -> { + DatasourceConfiguration newDsConfig = datasourceStorage.getDatasourceConfiguration(); + AuthenticationDTO auth2 = newDsConfig.getAuthentication(); + + assertThat(auth2).isInstanceOf(OAuth2.class); + + assertThat(((OAuth2) auth2).getClientSecret()).isEqualTo(password); + }) + .verifyComplete(); + } }