diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/DataTypeStringUtils.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/DataTypeStringUtils.java index 23857c5bdb..1b2bd86075 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/DataTypeStringUtils.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/helpers/DataTypeStringUtils.java @@ -245,7 +245,6 @@ public class DataTypeStringUtils { case STRING: default: try { - replacement = escapeSpecialCharacters(replacement); String valueAsString = objectMapper.writeValueAsString(replacement); input = placeholderPattern.matcher(input).replaceFirst(Matcher.quoteReplacement(valueAsString)); } catch (JsonProcessingException e) { @@ -262,19 +261,6 @@ public class DataTypeStringUtils { return input; } - private static String escapeSpecialCharacters(String raw) { - String escaped = raw; - escaped = escaped.replace("\\", "\\\\"); - escaped = escaped.replace("\"", "\\\""); - escaped = escaped.replace("\b", "\\b"); - escaped = escaped.replace("\f", "\\f"); - escaped = escaped.replace("\n", "\\n"); - escaped = escaped.replace("\r", "\\r"); - escaped = escaped.replace("\t", "\\t"); - // TODO: escape other non-printing characters using uXXXX notation - return escaped; - } - private static boolean isBinary(String input) { for (int i = 0; i < input.length(); i++) { int tempB = input.charAt(i); diff --git a/app/server/appsmith-plugins/amazons3Plugin/src/main/java/com/external/plugins/AmazonS3Plugin.java b/app/server/appsmith-plugins/amazons3Plugin/src/main/java/com/external/plugins/AmazonS3Plugin.java index 5687d4d8a1..3194592412 100644 --- a/app/server/appsmith-plugins/amazons3Plugin/src/main/java/com/external/plugins/AmazonS3Plugin.java +++ b/app/server/appsmith-plugins/amazons3Plugin/src/main/java/com/external/plugins/AmazonS3Plugin.java @@ -13,10 +13,13 @@ import com.amazonaws.services.s3.model.S3ObjectSummary; import com.amazonaws.services.s3.transfer.TransferManager; import com.amazonaws.services.s3.transfer.TransferManagerBuilder; import com.amazonaws.util.IOUtils; +import com.appsmith.external.dtos.ExecuteActionDTO; import com.appsmith.external.dtos.MultipartFormDataDTO; import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError; import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginException; import com.appsmith.external.exceptions.pluginExceptions.StaleConnectionException; +import com.appsmith.external.helpers.DataTypeStringUtils; +import com.appsmith.external.helpers.MustacheHelper; import com.appsmith.external.models.ActionConfiguration; import com.appsmith.external.models.ActionExecutionRequest; import com.appsmith.external.models.ActionExecutionResult; @@ -28,6 +31,7 @@ import com.appsmith.external.models.Property; import com.appsmith.external.models.RequestParamDTO; import com.appsmith.external.plugins.BasePlugin; import com.appsmith.external.plugins.PluginExecutor; +import com.appsmith.external.plugins.SmartSubstitutionInterface; import com.external.plugins.constants.AmazonS3Action; import lombok.extern.slf4j.Slf4j; import org.pf4j.Extension; @@ -72,12 +76,14 @@ import static com.external.plugins.constants.FieldName.LIST_UNSIGNED_URL; import static com.external.plugins.constants.FieldName.PATH; import static com.external.plugins.constants.FieldName.READ_USING_BASE64_ENCODING; import static com.external.utils.DatasourceUtils.getS3ClientBuilder; +import static java.lang.Boolean.TRUE; public class AmazonS3Plugin extends BasePlugin { private static final String S3_DRIVER = "com.amazonaws.services.s3.AmazonS3"; public static final int S3_SERVICE_PROVIDER_PROPERTY_INDEX = 1; public static final int CUSTOM_ENDPOINT_REGION_PROPERTY_INDEX = 2; + public static final String SMART_SUBSTITUTION = "smartSubstitution"; public static final int CUSTOM_ENDPOINT_INDEX = 0; private static final String DEFAULT_URL_EXPIRY_IN_MINUTES = "5"; // max 7 days is possible private static final String YES = "YES"; @@ -92,7 +98,7 @@ public class AmazonS3Plugin extends BasePlugin { @Slf4j @Extension - public static class S3PluginExecutor implements PluginExecutor { + public static class S3PluginExecutor implements PluginExecutor, SmartSubstitutionInterface { private final Scheduler scheduler = Schedulers.elastic(); /* @@ -283,9 +289,67 @@ public class AmazonS3Plugin extends BasePlugin { } @Override - public Mono execute(AmazonS3 connection, - DatasourceConfiguration datasourceConfiguration, - ActionConfiguration actionConfiguration) { + public Mono execute(AmazonS3 connection, DatasourceConfiguration datasourceConfiguration, ActionConfiguration actionConfiguration) { + // Unused function + return Mono.error(new AppsmithPluginException(AppsmithPluginError.PLUGIN_ERROR, "Unsupported Operation")); + } + + @Override + public Mono executeParameterized(AmazonS3 connection, + ExecuteActionDTO executeActionDTO, + DatasourceConfiguration datasourceConfiguration, + ActionConfiguration actionConfiguration) { + + + final Map formData = actionConfiguration.getFormData(); + List> parameters = new ArrayList<>(); + + Boolean smartJsonSubstitution = TRUE; + + Object smartSubstitutionObject = formData.getOrDefault(SMART_SUBSTITUTION, TRUE); + + if (smartSubstitutionObject instanceof Boolean) { + smartJsonSubstitution = (Boolean) smartSubstitutionObject; + } else if (smartSubstitutionObject instanceof String) { + // Older UI configuration used to set this value as a string which may/may not be castable to a boolean + // directly. This is to ensure we are backward compatible + smartJsonSubstitution = Boolean.parseBoolean((String) smartSubstitutionObject); + } + + try { + // Smartly substitute in Json fields and replace all the bindings with values. + if (TRUE.equals(smartJsonSubstitution)) { + final String body = actionConfiguration.getBody() != null ? actionConfiguration.getBody() : ""; + // First extract all the bindings in order + List mustacheKeysInOrder = MustacheHelper.extractMustacheKeysInOrder(body); + // Replace all the bindings with a placeholder + String updatedValue = MustacheHelper.replaceMustacheWithPlaceholder(body, mustacheKeysInOrder); + + updatedValue = (String) smartSubstitutionOfBindings(updatedValue, + mustacheKeysInOrder, + executeActionDTO.getParams(), + parameters); + + actionConfiguration.setBody(updatedValue); + + } + } catch (AppsmithPluginException e) { + // Initializing object for error condition + ActionExecutionResult errorResult = new ActionExecutionResult(); + errorResult.setStatusCode(AppsmithPluginError.PLUGIN_ERROR.getAppErrorCode().toString()); + errorResult.setIsExecutionSuccess(false); + errorResult.setErrorInfo(e); + return Mono.just(errorResult); + } + + prepareConfigurationsForExecution(executeActionDTO, actionConfiguration, datasourceConfiguration); + + return this.executeCommon(connection, datasourceConfiguration, actionConfiguration); + } + + private Mono executeCommon(AmazonS3 connection, + DatasourceConfiguration datasourceConfiguration, + ActionConfiguration actionConfiguration) { final String[] query = new String[1]; Map requestProperties = new HashMap<>(); @@ -293,48 +357,48 @@ public class AmazonS3Plugin extends BasePlugin { return Mono.fromCallable(() -> { - /* - * - AmazonS3 API collection does not seem to provide any API to test connection validity or staleness. - * Hence, unable to do stale connection check explicitly. - * - If connection object is null, then assume stale connection. - */ - if (connection == null) { - return Mono.error(new StaleConnectionException()); - } + /* + * - AmazonS3 API collection does not seem to provide any API to test connection validity or staleness. + * Hence, unable to do stale connection check explicitly. + * - If connection object is null, then assume stale connection. + */ + if (connection == null) { + return Mono.error(new StaleConnectionException()); + } - if (actionConfiguration == null) { - return Mono.error( - new AppsmithPluginException( - AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, - "At least one of the mandatory fields in S3 query creation form is empty - 'Action'/" + - "'Bucket Name'/'File Path'/'Content'. Please fill all the mandatory fields and try " + - "again." - ) - ); - } + if (actionConfiguration == null) { + return Mono.error( + new AppsmithPluginException( + AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, + "At least one of the mandatory fields in S3 query creation form is empty - 'Action'/" + + "'Bucket Name'/'File Path'/'Content'. Please fill all the mandatory fields and try " + + "again." + ) + ); + } - Map formData = actionConfiguration.getFormData(); + Map formData = actionConfiguration.getFormData(); - String command = (String) getValueSafelyFromFormData(formData, COMMAND); + String command = (String) getValueSafelyFromFormData(formData, COMMAND); - if (StringUtils.isNullOrEmpty(command)) { - return Mono.error( - new AppsmithPluginException( - AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, - "Mandatory parameter 'Command' is missing. Did you forget to select one of the commands" + - " from the Command dropdown ?" - ) - ); - } + if (StringUtils.isNullOrEmpty(command)) { + return Mono.error( + new AppsmithPluginException( + AppsmithPluginError.PLUGIN_EXECUTE_ARGUMENT_ERROR, + "Mandatory parameter 'Command' is missing. Did you forget to select one of the commands" + + " from the Command dropdown ?" + ) + ); + } - AmazonS3Action s3Action = AmazonS3Action.valueOf(command); - query[0] = s3Action.name(); + AmazonS3Action s3Action = AmazonS3Action.valueOf(command); + query[0] = s3Action.name(); - requestParams.add(new RequestParamDTO(COMMAND, - command, null, null, null)); + requestParams.add(new RequestParamDTO(COMMAND, + command, null, null, null)); - final String bucketName = (s3Action == AmazonS3Action.LIST_BUCKETS) ? - null : (String) getValueSafelyFromFormData(formData, BUCKET); + final String bucketName = (s3Action == AmazonS3Action.LIST_BUCKETS) ? + null : (String) getValueSafelyFromFormData(formData, BUCKET); // If the action_type is LIST_BUCKET, remove the bucket name requirement if (s3Action != AmazonS3Action.LIST_BUCKETS @@ -762,7 +826,19 @@ public class AmazonS3Plugin extends BasePlugin { ActionConfiguration actionConfiguration = new ActionConfiguration(); actionConfiguration.setFormData(configMap); return datasourceCreate(datasourceConfiguration) - .flatMap(connection -> execute(connection, datasourceConfiguration, actionConfiguration)); + .flatMap(connection -> executeParameterized(connection, new ExecuteActionDTO(), datasourceConfiguration, actionConfiguration)); } + + @Override + public Object substituteValueInInput(int index, + String binding, + String value, + Object input, + List> insertedParams, + Object... args) { + String jsonBody = (String) input; + return DataTypeStringUtils.jsonSmartReplacementPlaceholderWithValue(jsonBody, value, insertedParams); + } + } } diff --git a/app/server/appsmith-plugins/amazons3Plugin/src/main/resources/setting.json b/app/server/appsmith-plugins/amazons3Plugin/src/main/resources/setting.json new file mode 100644 index 0000000000..f66f149cde --- /dev/null +++ b/app/server/appsmith-plugins/amazons3Plugin/src/main/resources/setting.json @@ -0,0 +1,36 @@ +{ + "setting": [ + { + "sectionName": "", + "id": 1, + "children": [ + { + "label": "Run query on page load", + "configProperty": "executeOnLoad", + "controlType": "SWITCH", + "info": "Will refresh data each time the page is loaded" + }, + { + "label": "Request confirmation before running query", + "configProperty": "confirmBeforeExecute", + "controlType": "SWITCH", + "info": "Ask confirmation from the user each time before refreshing data" + }, + { + "label": "Smart JSON Substitution", + "info": "Turning on this property fixes the JSON substitution of bindings in the Content field by adding/removing quotes intelligently and reduces developer errors", + "configProperty": "actionConfiguration.formData.smartSubstitution", + "controlType": "SWITCH", + "initialValue": true + }, + { + "label": "Query timeout (in milliseconds)", + "info": "Maximum time after which the query will return", + "configProperty": "actionConfiguration.timeoutInMillisecond", + "controlType": "INPUT_TEXT", + "dataType": "NUMBER" + } + ] + } + ] +} \ No newline at end of file diff --git a/app/server/appsmith-plugins/amazons3Plugin/src/test/java/com/external/plugins/AmazonS3PluginTest.java b/app/server/appsmith-plugins/amazons3Plugin/src/test/java/com/external/plugins/AmazonS3PluginTest.java index 76589ae1ff..a642ce9c8e 100644 --- a/app/server/appsmith-plugins/amazons3Plugin/src/test/java/com/external/plugins/AmazonS3PluginTest.java +++ b/app/server/appsmith-plugins/amazons3Plugin/src/test/java/com/external/plugins/AmazonS3PluginTest.java @@ -8,6 +8,7 @@ import com.amazonaws.services.s3.model.S3Object; import com.amazonaws.services.s3.model.S3ObjectInputStream; import com.amazonaws.services.s3.model.S3ObjectSummary; import com.amazonaws.util.Base64; +import com.appsmith.external.dtos.ExecuteActionDTO; import com.appsmith.external.exceptions.pluginExceptions.AppsmithPluginError; import com.appsmith.external.exceptions.pluginExceptions.StaleConnectionException; import com.appsmith.external.models.ActionConfiguration; @@ -15,6 +16,7 @@ import com.appsmith.external.models.ActionExecutionResult; import com.appsmith.external.models.DBAuth; import com.appsmith.external.models.DatasourceConfiguration; import com.appsmith.external.models.Endpoint; +import com.appsmith.external.models.Param; import com.appsmith.external.models.Property; import com.appsmith.external.models.RequestParamDTO; import lombok.extern.slf4j.Slf4j; @@ -36,6 +38,7 @@ import java.util.Set; import static com.appsmith.external.constants.ActionConstants.ACTION_CONFIGURATION_PATH; import static com.appsmith.external.helpers.PluginUtils.setValueSafelyInFormData; +import static com.external.plugins.AmazonS3Plugin.SMART_SUBSTITUTION; import static com.external.plugins.constants.FieldName.BUCKET; import static com.external.plugins.constants.FieldName.COMMAND; import static com.external.plugins.constants.FieldName.CREATE_DATATYPE; @@ -216,12 +219,15 @@ public class AmazonS3PluginTest { @Test public void testStaleConnectionExceptionFromExecuteMethod() { DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + ExecuteActionDTO executeActionDTO = new ExecuteActionDTO(); ActionConfiguration actionConfiguration = new ActionConfiguration(); + actionConfiguration.setFormData(Map.of()); Mono pluginExecutorMono = Mono.just(new AmazonS3Plugin.S3PluginExecutor()); Mono resultMono = pluginExecutorMono .flatMap(executor -> { - return executor.execute( + return executor.executeParameterized( null, + executeActionDTO, datasourceConfiguration, actionConfiguration); }); @@ -233,6 +239,7 @@ public class AmazonS3PluginTest { @Test public void testListFilesInBucketWithNoUrl() { DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + ExecuteActionDTO executeActionDTO = new ExecuteActionDTO(); AmazonS3Plugin.S3PluginExecutor pluginExecutor = new AmazonS3Plugin.S3PluginExecutor(); ActionConfiguration actionConfiguration = new ActionConfiguration(); @@ -266,10 +273,11 @@ public class AmazonS3PluginTest { when(mockConnection.listNextBatchOfObjects(mockObjectListing)).thenReturn(mockObjectListing); when(mockObjectListing.getObjectSummaries()).thenReturn(mockS3ObjectSummaryList); - Mono resultMono = pluginExecutor.execute( - mockConnection, - datasourceConfiguration, - actionConfiguration); + Mono resultMono = pluginExecutor.executeParameterized( + mockConnection, + executeActionDTO, + datasourceConfiguration, + actionConfiguration); StepVerifier.create(resultMono) .assertNext(result -> { @@ -293,12 +301,13 @@ public class AmazonS3PluginTest { /* * - This method tests the create file program flow till the point where an actual call is made by the AmazonS3 * connection to upload a file. - * - If everything goes well, then then only expected exception is the one thrown by AmazonS3 connection + * - If everything goes well, then only expected exception is the one thrown by AmazonS3 connection * regarding false credentials. */ @Test public void testCreateFileFromBodyWithFalseCredentialsAndNonNullDuration() { DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + ExecuteActionDTO executeActionDTO = new ExecuteActionDTO(); AmazonS3Plugin.S3PluginExecutor pluginExecutor = new AmazonS3Plugin.S3PluginExecutor(); ActionConfiguration actionConfiguration = new ActionConfiguration(); @@ -317,10 +326,11 @@ public class AmazonS3PluginTest { actionConfiguration.setFormData(configMap); AmazonS3 connection = pluginExecutor.datasourceCreate(datasourceConfiguration).block(); - Mono resultMono = pluginExecutor.execute( - connection, - datasourceConfiguration, - actionConfiguration); + Mono resultMono = pluginExecutor.executeParameterized( + connection, + executeActionDTO, + datasourceConfiguration, + actionConfiguration); StepVerifier.create(resultMono) .assertNext(result -> { @@ -336,12 +346,13 @@ public class AmazonS3PluginTest { /* * - This method tests the create file program flow till the point where an actual call is made by the AmazonS3 * connection to upload a file. - * - If everything goes well, then then only expected exception is the one thrown by AmazonS3 connection + * - If everything goes well, then only expected exception is the one thrown by AmazonS3 connection * regarding false credentials. */ @Test public void testFileUploadFromBodyWithMissingDuration() { DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + ExecuteActionDTO executeActionDTO = new ExecuteActionDTO(); AmazonS3Plugin.S3PluginExecutor pluginExecutor = new AmazonS3Plugin.S3PluginExecutor(); ActionConfiguration actionConfiguration = new ActionConfiguration(); @@ -359,8 +370,56 @@ public class AmazonS3PluginTest { actionConfiguration.setFormData(configMap); AmazonS3 connection = pluginExecutor.datasourceCreate(datasourceConfiguration).block(); - Mono resultMono = pluginExecutor.execute( + Mono resultMono = pluginExecutor.executeParameterized( connection, + executeActionDTO, + datasourceConfiguration, + actionConfiguration); + + StepVerifier.create(resultMono) + .assertNext(result -> { + assertFalse(result.getIsExecutionSuccess()); + String message = (String) result.getBody(); + assertTrue(message.contains("The AWS Access Key Id you provided does not exist in " + + "our records")); + assertEquals(AppsmithPluginError.PLUGIN_ERROR.getTitle(), result.getTitle()); + }) + .verifyComplete(); + } + + /* + * - This method tests the create file program flow till the point where an actual call is made by the AmazonS3 + * connection to upload a file. + * - If this test fails, the point of failure is expected to be the logic for smart substitution + * - If everything goes well, then only expected exception is the one thrown by AmazonS3 connection + * regarding false credentials. + */ + @Test + public void testSmartSubstitutionJSONBody() { + DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + ExecuteActionDTO executeActionDTO = new ExecuteActionDTO(); + executeActionDTO.setParams(List.of(new Param("dynamicallyFoundFilePickerObject", "Random\"Unescaped'String"))); + AmazonS3Plugin.S3PluginExecutor pluginExecutor = new AmazonS3Plugin.S3PluginExecutor(); + + ActionConfiguration actionConfiguration = new ActionConfiguration(); + String dummyBody = "{\"data\": {{dynamicallyFoundFilePickerObject}}}"; + actionConfiguration.setBody(dummyBody); + + String dummyPath = "path"; + actionConfiguration.setPath(dummyPath); + + Map configMap = new HashMap<>(); + setValueSafelyInFormData(configMap, SMART_SUBSTITUTION, true); + setValueSafelyInFormData(configMap, COMMAND, "UPLOAD_FILE_FROM_BODY"); + setValueSafelyInFormData(configMap, BUCKET, "bucket_name"); + setValueSafelyInFormData(configMap, CREATE_DATATYPE, "NO"); + + actionConfiguration.setFormData(configMap); + + AmazonS3 connection = pluginExecutor.datasourceCreate(datasourceConfiguration).block(); + Mono resultMono = pluginExecutor.executeParameterized( + connection, + executeActionDTO, datasourceConfiguration, actionConfiguration); @@ -378,6 +437,7 @@ public class AmazonS3PluginTest { @Test public void testFileUploadFromBody_withMalformedBody_returnsErrorMessage() { DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + ExecuteActionDTO executeActionDTO = new ExecuteActionDTO(); AmazonS3Plugin.S3PluginExecutor pluginExecutor = new AmazonS3Plugin.S3PluginExecutor(); ActionConfiguration actionConfiguration = new ActionConfiguration(); @@ -396,8 +456,9 @@ public class AmazonS3PluginTest { actionConfiguration.setFormData(configMap); AmazonS3 connection = pluginExecutor.datasourceCreate(datasourceConfiguration).block(); - Mono resultMono = pluginExecutor.execute( + Mono resultMono = pluginExecutor.executeParameterized( connection, + executeActionDTO, datasourceConfiguration, actionConfiguration); @@ -428,6 +489,7 @@ public class AmazonS3PluginTest { @Test public void testFileUploadFromBodyWithFilepickerAndNonBase64() { DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + ExecuteActionDTO executeActionDTO = new ExecuteActionDTO(); AmazonS3Plugin.S3PluginExecutor pluginExecutor = new AmazonS3Plugin.S3PluginExecutor(); ActionConfiguration actionConfiguration = new ActionConfiguration(); @@ -446,10 +508,11 @@ public class AmazonS3PluginTest { actionConfiguration.setFormData(configMap); AmazonS3 connection = pluginExecutor.datasourceCreate(datasourceConfiguration).block(); - Mono resultMono = pluginExecutor.execute( - connection, - datasourceConfiguration, - actionConfiguration); + Mono resultMono = pluginExecutor.executeParameterized( + connection, + executeActionDTO, + datasourceConfiguration, + actionConfiguration); StepVerifier.create(resultMono) .assertNext(result -> { @@ -478,6 +541,7 @@ public class AmazonS3PluginTest { @Test public void testReadFileFromPathWithoutBase64Encoding() { DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + ExecuteActionDTO executeActionDTO = new ExecuteActionDTO(); AmazonS3Plugin.S3PluginExecutor pluginExecutor = new AmazonS3Plugin.S3PluginExecutor(); ActionConfiguration actionConfiguration = new ActionConfiguration(); @@ -503,10 +567,11 @@ public class AmazonS3PluginTest { S3ObjectInputStream dummyS3ObjectInputStream = new S3ObjectInputStream(dummyInputStream, null); when(mockS3Object.getObjectContent()).thenReturn(dummyS3ObjectInputStream); - Mono resultMono = pluginExecutor.execute( - mockConnection, - datasourceConfiguration, - actionConfiguration); + Mono resultMono = pluginExecutor.executeParameterized( + mockConnection, + executeActionDTO, + datasourceConfiguration, + actionConfiguration); StepVerifier.create(resultMono) .assertNext(result -> { @@ -520,6 +585,7 @@ public class AmazonS3PluginTest { @Test public void testReadFileFromPathWithBase64Encoding() { DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + ExecuteActionDTO executeActionDTO = new ExecuteActionDTO(); AmazonS3Plugin.S3PluginExecutor pluginExecutor = new AmazonS3Plugin.S3PluginExecutor(); ActionConfiguration actionConfiguration = new ActionConfiguration(); @@ -545,8 +611,9 @@ public class AmazonS3PluginTest { S3ObjectInputStream dummyS3ObjectInputStream = new S3ObjectInputStream(dummyInputStream, null); when(mockS3Object.getObjectContent()).thenReturn(dummyS3ObjectInputStream); - Mono resultMono = pluginExecutor.execute( + Mono resultMono = pluginExecutor.executeParameterized( mockConnection, + executeActionDTO, datasourceConfiguration, actionConfiguration); @@ -576,6 +643,7 @@ public class AmazonS3PluginTest { @Test public void testDeleteFile() { DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + ExecuteActionDTO executeActionDTO = new ExecuteActionDTO(); AmazonS3Plugin.S3PluginExecutor pluginExecutor = new AmazonS3Plugin.S3PluginExecutor(); ActionConfiguration actionConfiguration = new ActionConfiguration(); @@ -594,10 +662,11 @@ public class AmazonS3PluginTest { AmazonS3 mockConnection = mock(AmazonS3.class); doNothing().when(mockConnection).deleteObject(anyString(), anyString()); - Mono resultMono = pluginExecutor.execute( - mockConnection, - datasourceConfiguration, - actionConfiguration); + Mono resultMono = pluginExecutor.executeParameterized( + mockConnection, + executeActionDTO, + datasourceConfiguration, + actionConfiguration); StepVerifier.create(resultMono) .assertNext(result -> { assertTrue(result.getIsExecutionSuccess()); @@ -624,6 +693,7 @@ public class AmazonS3PluginTest { @Test public void testListFilesWithPrefix() { DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + ExecuteActionDTO executeActionDTO = new ExecuteActionDTO(); AmazonS3Plugin.S3PluginExecutor pluginExecutor = new AmazonS3Plugin.S3PluginExecutor(); ActionConfiguration actionConfiguration = new ActionConfiguration(); @@ -657,8 +727,9 @@ public class AmazonS3PluginTest { when(mockConnection.listNextBatchOfObjects(mockObjectListing)).thenReturn(mockObjectListing); when(mockObjectListing.getObjectSummaries()).thenReturn(mockS3ObjectSummaryList); - Mono resultMono = pluginExecutor.execute( + Mono resultMono = pluginExecutor.executeParameterized( mockConnection, + executeActionDTO, datasourceConfiguration, actionConfiguration); @@ -684,6 +755,7 @@ public class AmazonS3PluginTest { @Test public void testListFilesWithUnsignedUrl() throws MalformedURLException { DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + ExecuteActionDTO executeActionDTO = new ExecuteActionDTO(); AmazonS3Plugin.S3PluginExecutor pluginExecutor = new AmazonS3Plugin.S3PluginExecutor(); ActionConfiguration actionConfiguration = new ActionConfiguration(); @@ -723,8 +795,9 @@ public class AmazonS3PluginTest { URL dummyUrl2 = new URL("http", "dummy_url_1", ""); when(mockConnection.getUrl(anyString(), anyString())).thenReturn(dummyUrl1).thenReturn(dummyUrl2); - Mono resultMono = pluginExecutor.execute( + Mono resultMono = pluginExecutor.executeParameterized( mockConnection, + executeActionDTO, datasourceConfiguration, actionConfiguration); @@ -761,6 +834,7 @@ public class AmazonS3PluginTest { @Test public void testListFilesWithSignedUrl() throws MalformedURLException { DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + ExecuteActionDTO executeActionDTO = new ExecuteActionDTO(); AmazonS3Plugin.S3PluginExecutor pluginExecutor = new AmazonS3Plugin.S3PluginExecutor(); ActionConfiguration actionConfiguration = new ActionConfiguration(); @@ -800,8 +874,9 @@ public class AmazonS3PluginTest { URL dummyUrl2 = new URL("http", "dummy_url_1", ""); when(mockConnection.generatePresignedUrl(any())).thenReturn(dummyUrl1).thenReturn(dummyUrl2); - Mono resultMono = pluginExecutor.execute( + Mono resultMono = pluginExecutor.executeParameterized( mockConnection, + executeActionDTO, datasourceConfiguration, actionConfiguration); @@ -841,6 +916,7 @@ public class AmazonS3PluginTest { @Test public void testListFilesWithSignedUrlAndNullDuration() throws MalformedURLException { DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + ExecuteActionDTO executeActionDTO = new ExecuteActionDTO(); AmazonS3Plugin.S3PluginExecutor pluginExecutor = new AmazonS3Plugin.S3PluginExecutor(); ActionConfiguration actionConfiguration = new ActionConfiguration(); @@ -879,8 +955,9 @@ public class AmazonS3PluginTest { URL dummyUrl2 = new URL("http", "dummy_url_1", ""); when(mockConnection.generatePresignedUrl(any())).thenReturn(dummyUrl1).thenReturn(dummyUrl2); - Mono resultMono = pluginExecutor.execute( + Mono resultMono = pluginExecutor.executeParameterized( mockConnection, + executeActionDTO, datasourceConfiguration, actionConfiguration); @@ -940,6 +1017,7 @@ public class AmazonS3PluginTest { @Test public void testListBuckets() { DatasourceConfiguration datasourceConfiguration = createDatasourceConfiguration(); + ExecuteActionDTO executeActionDTO = new ExecuteActionDTO(); AmazonS3Plugin.S3PluginExecutor pluginExecutor = new AmazonS3Plugin.S3PluginExecutor(); Bucket mockS3Bucket = mock(Bucket.class); mockS3Bucket.setName("dummy_bucket"); @@ -956,28 +1034,29 @@ public class AmazonS3PluginTest { AmazonS3 mockConnection = mock(AmazonS3.class); when(mockConnection.listBuckets()).thenReturn(List.of(mockS3Bucket)); - Mono resultMono = pluginExecutor.execute( - mockConnection, - datasourceConfiguration, - actionConfiguration); + Mono resultMono = pluginExecutor.executeParameterized( + mockConnection, + executeActionDTO, + datasourceConfiguration, + actionConfiguration); StepVerifier.create(resultMono) - .assertNext(result -> { - assertTrue(result.getIsExecutionSuccess()); + .assertNext(result -> { + assertTrue(result.getIsExecutionSuccess()); - Map> node = (Map>) result.getBody(); - List buckets = node.get("bucketList"); - assertTrue(buckets.size() == 1); - assertEquals(buckets.get(0), mockS3Bucket.getName()); - /* - * - RequestParamDTO object only have attributes configProperty and value at this point. - */ - List expectedRequestParams = new ArrayList<>(); - expectedRequestParams.add(new RequestParamDTO("command", "LIST_BUCKETS", - null, null, null)); // Action - expectedRequestParams.add(new RequestParamDTO("bucket", null, - null, null, null)); // Bucket name - assertEquals(result.getRequest().getRequestParams().toString(), expectedRequestParams.toString()); - }) + Map> node = (Map>) result.getBody(); + List buckets = node.get("bucketList"); + assertTrue(buckets.size() == 1); + assertEquals(buckets.get(0), mockS3Bucket.getName()); + /* + * - RequestParamDTO object only have attributes configProperty and value at this point. + */ + List expectedRequestParams = new ArrayList<>(); + expectedRequestParams.add(new RequestParamDTO("command", "LIST_BUCKETS", + null, null, null)); // Action + expectedRequestParams.add(new RequestParamDTO("bucket", null, + null, null, null)); // Bucket name + assertEquals(result.getRequest().getRequestParams().toString(), expectedRequestParams.toString()); + }) .verifyComplete(); }