From cb5b13da3d58f5cc63306b6313950eb7c69ca27d Mon Sep 17 00:00:00 2001 From: michalkuperman Date: Mon, 25 Nov 2019 15:29:57 +0200 Subject: [PATCH 1/6] "encode URL in API calls" --- .../strategies/AbstractApiStrategy.java | 16 +++++++++++++++- .../java/com/cloudinary/http42/ApiStrategy.java | 6 +----- .../java/com/cloudinary/http43/ApiStrategy.java | 5 +---- .../java/com/cloudinary/http44/ApiStrategy.java | 7 ++----- .../com/cloudinary/test/AbstractApiTest.java | 11 ++++++++++- 5 files changed, 29 insertions(+), 16 deletions(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java b/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java index c5b68906..65d0970d 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java +++ b/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java @@ -2,10 +2,13 @@ import com.cloudinary.Api; import com.cloudinary.Api.HttpMethod; +import com.cloudinary.SmartUrlEncoder; import com.cloudinary.api.ApiResponse; - +import com.cloudinary.utils.StringUtils; +import java.util.Arrays; import java.util.Map; + public abstract class AbstractApiStrategy { protected Api api; @@ -13,6 +16,17 @@ public void init(Api api) { this.api = api; } + protected String createApiUrl (Iterable uri, String prefix, String cloudName){ + + String apiUrl = StringUtils.join(Arrays.asList(prefix, "v1_1", cloudName), "/"); + for (String component : uri) { + component = SmartUrlEncoder.encode(component); + apiUrl = apiUrl + "/" + component; + + } + return apiUrl; + } + @SuppressWarnings("rawtypes") public abstract ApiResponse callApi(HttpMethod method, Iterable uri, Map params, Map options) throws Exception; diff --git a/cloudinary-http42/src/main/java/com/cloudinary/http42/ApiStrategy.java b/cloudinary-http42/src/main/java/com/cloudinary/http42/ApiStrategy.java index a0a9e0bf..7c19aeb9 100644 --- a/cloudinary-http42/src/main/java/com/cloudinary/http42/ApiStrategy.java +++ b/cloudinary-http42/src/main/java/com/cloudinary/http42/ApiStrategy.java @@ -43,11 +43,7 @@ public ApiResponse callApi(HttpMethod method, Iterable uri, Map uri, Map uri, Map Date: Tue, 26 Nov 2019 12:12:11 +0200 Subject: [PATCH 2/6] "indentation in tests and remove try catch" --- .../com/cloudinary/test/AbstractApiTest.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java index ec5d9584..4c5acefb 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java @@ -484,7 +484,8 @@ public void testListTransformationByNamed() throws Exception { } finally { try { api.deleteTransformation(name, null); - } catch (Exception ignored){} + } catch (Exception ignored) { + } } } @@ -653,7 +654,7 @@ public void testGetUploadPreset() throws Exception { String[] tags = {"a", "b", "c"}; Map context = ObjectUtils.asMap("a", "b", "c", "d"); Map result = api.createUploadPreset(ObjectUtils.asMap("unsigned", true, "folder", "folder", "transformation", EXPLICIT_TRANSFORMATION, "tags", tags, "context", - context,"live",true)); + context, "live", true)); String name = result.get("name").toString(); Map preset = api.uploadPreset(name, ObjectUtils.emptyMap()); assertEquals(preset.get("name"), name); @@ -693,7 +694,7 @@ public void testUpdateUploadPreset() throws Exception { String name = api.createUploadPreset(ObjectUtils.asMap("folder", "folder")).get("name").toString(); Map preset = api.uploadPreset(name, ObjectUtils.emptyMap()); Map settings = (Map) preset.get("settings"); - settings.putAll(ObjectUtils.asMap("colors", true, "unsigned", true, "disallow_public_id", true,"live",true)); + settings.putAll(ObjectUtils.asMap("colors", true, "unsigned", true, "disallow_public_id", true, "live", true)); api.updateUploadPreset(name, settings); settings.remove("unsigned"); preset = api.uploadPreset(name, ObjectUtils.emptyMap()); @@ -778,14 +779,11 @@ public void testRestore() throws Exception { } @Test - public void testEncodeUrlInApiCall() throws Exception { - try { - Map result = api.subFolders("sub^folder test", null); - assertEquals("sub%5Efolder%20test", ((Map) ((org.cloudinary.json.JSONArray) result.get("folders")).get(0)).get("path")); - } catch (Exception ignored) { - - } + public void testEncodeUrlInApiCall() throws Exception { + Map result = api.subFolders("sub^folder test", null); + assertEquals("sub%5Efolder%20test", ((Map) ((org.cloudinary.json.JSONArray) result.get("folders")).get(0)).get("path")); } + @Test public void testUploadMapping() throws Exception { String aptTestUploadMapping = "api_test_upload_mapping" + SUFFIX; @@ -955,7 +953,7 @@ public void testDeleteFolder() throws Exception { Thread.sleep(5000); api.deleteResources(Collections.singletonList(uploadResult.get("public_id").toString()), emptyMap()); ApiResponse result = api.deleteFolder(toDelete, emptyMap()); - assertTrue(((ArrayList)result.get("deleted")).contains(toDelete)); + assertTrue(((ArrayList) result.get("deleted")).contains(toDelete)); // should throw exception (folder not found): api.deleteFolder(cloudinary.randomPublicId(), emptyMap()); From 358bfbf3f47ee055a8a2ce381f7949fcc27bf3f2 Mon Sep 17 00:00:00 2001 From: Michal kuperman <51990104+michalkcloudinay@users.noreply.github.com> Date: Thu, 28 Nov 2019 14:21:55 +0200 Subject: [PATCH 3/6] Add validation for `CLOUDINARY_URL` scheme (#185) --- .../java/com/cloudinary/Configuration.java | 5 ++++- .../com/cloudinary/test/CloudinaryTest.java | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Configuration.java b/cloudinary-core/src/main/java/com/cloudinary/Configuration.java index c9e68b2e..da5f5e26 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Configuration.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Configuration.java @@ -186,6 +186,9 @@ public static Configuration from(String cloudinaryUrl) { static protected Map parseConfigUrl(String cloudinaryUrl) { Map params = new HashMap(); URI cloudinaryUri = URI.create(cloudinaryUrl); + if (cloudinaryUri.getScheme() == null || !cloudinaryUri.getScheme().equalsIgnoreCase("cloudinary")){ + throw new IllegalArgumentException("Invalid CLOUDINARY_URL scheme. Expecting to start with 'cloudinary://'"); + } params.put("cloud_name", cloudinaryUri.getHost()); if (cloudinaryUri.getUserInfo() != null) { String[] creds = cloudinaryUri.getUserInfo().split(":"); @@ -427,4 +430,4 @@ public Builder from(Configuration other) { return this; } } -} \ No newline at end of file +} diff --git a/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java b/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java index 4f8f6339..dabb1f4d 100644 --- a/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java +++ b/cloudinary-core/src/test/java/com/cloudinary/test/CloudinaryTest.java @@ -1230,6 +1230,24 @@ public void testConfiguration() throws IllegalAccessException { assertFieldsEqual(config, copy); } + @Test + public void testCloudinaryUrlValidScheme() { + String cloudinaryUrl = "cloudinary://123456789012345:ALKJdjklLJAjhkKJ45hBK92baj3@test"; + Configuration.from(cloudinaryUrl); + } + + @Test(expected = IllegalArgumentException.class) + public void testCloudinaryUrlInvalidScheme() { + String cloudinaryUrl = "https://123456789012345:ALKJdjklLJAjhkKJ45hBK92baj3@test"; + Configuration.from(cloudinaryUrl); + } + + @Test(expected = IllegalArgumentException.class) + public void testCloudinaryUrlEmptyScheme() { + String cloudinaryUrl = " "; + Configuration.from(cloudinaryUrl); + } + private void assertFieldsEqual(Object a, Object b) throws IllegalAccessException { assertEquals("Two objects must be the same class", a.getClass(), b.getClass()); Field[] fields = a.getClass().getFields(); From 659249e39847356fe8fb4dfe41ab8d1e8169fec9 Mon Sep 17 00:00:00 2001 From: Michal kuperman <51990104+michalkcloudinay@users.noreply.github.com> Date: Mon, 2 Dec 2019 11:01:53 +0200 Subject: [PATCH 4/6] Support create folder API (#188) --- .../src/main/java/com/cloudinary/Api.java | 15 ++++++++--- .../com/cloudinary/test/AbstractApiTest.java | 26 +++++++++++++++---- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/Api.java b/cloudinary-core/src/main/java/com/cloudinary/Api.java index 0fe6c180..1627c997 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/Api.java +++ b/cloudinary-core/src/main/java/com/cloudinary/Api.java @@ -244,7 +244,7 @@ public ApiResponse updateUploadPreset(String name, Map options) throws Exception if (options == null) options = ObjectUtils.emptyMap(); Map params = Util.buildUploadParams(options); Util.clearEmpty(params); - params.putAll(ObjectUtils.only(options, "unsigned", "disallow_public_id","live")); + params.putAll(ObjectUtils.only(options, "unsigned", "disallow_public_id", "live")); return callApi(HttpMethod.PUT, Arrays.asList("upload_presets", name), params, options); } @@ -252,7 +252,7 @@ public ApiResponse createUploadPreset(Map options) throws Exception { if (options == null) options = ObjectUtils.emptyMap(); Map params = Util.buildUploadParams(options); Util.clearEmpty(params); - params.putAll(ObjectUtils.only(options, "name", "unsigned", "disallow_public_id","live")); + params.putAll(ObjectUtils.only(options, "name", "unsigned", "disallow_public_id", "live")); return callApi(HttpMethod.POST, Arrays.asList("upload_presets"), params, options); } @@ -268,6 +268,13 @@ public ApiResponse subFolders(String ofFolderPath, Map options) throws Exception return callApi(HttpMethod.GET, Arrays.asList("folders", ofFolderPath), ObjectUtils.emptyMap(), options); } + //Creates an empty folder + public ApiResponse createFolder(String folderName, Map options) throws Exception { + if (options == null) + options = ObjectUtils.emptyMap(); + return callApi(HttpMethod.POST, Arrays.asList("folders", folderName), ObjectUtils.emptyMap(), options); + } + public ApiResponse restore(Iterable publicIds, Map options) throws Exception { if (options == null) options = ObjectUtils.emptyMap(); @@ -583,7 +590,7 @@ private ApiResponse updateResourcesAccessMode(String accessMode, String byKey, O */ public ApiResponse addMetadataField(MetadataField field) throws Exception { return callApi(HttpMethod.POST, Collections.singletonList("metadata_fields"), - ObjectUtils.toMap(field), ObjectUtils.asMap ("content_type", "json")); + ObjectUtils.toMap(field), ObjectUtils.asMap("content_type", "json")); } /** @@ -639,7 +646,7 @@ public ApiResponse updateMetadataFieldDatasource(String fieldExternalId, List entriesExternalId) throws Exception { List uri = Arrays.asList("metadata_fields", fieldExternalId, "datasource"); - return callApi(HttpMethod.DELETE, uri,Collections.singletonMap("external_ids", entriesExternalId) , Collections.emptyMap()); + return callApi(HttpMethod.DELETE, uri, Collections.singletonMap("external_ids", entriesExternalId), Collections.emptyMap()); } /** diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java index 068768c6..5ae9598c 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java @@ -46,6 +46,7 @@ abstract public class AbstractApiTest extends MockableTest { public static final Transformation DELETE_TRANSFORMATION = new Transformation().width(100).crop("scale").overlay(new TextLayer().text(SUFFIX + "_delete").fontFamily("Arial").fontSize(60)); public static final String TEST_KEY = "test-key" + SUFFIX; public static final String API_TEST_RESTORE = "api_test_restore" + SUFFIX; + public static final Set createdFolders = new HashSet(); protected Api api; @@ -119,6 +120,12 @@ public static void tearDownClass() { api.deleteUploadPreset(API_TEST_UPLOAD_PRESET_4, ObjectUtils.emptyMap()); } catch (Exception ignored) { } + try { + for (String folder : createdFolders) { + api.deleteFolder(folder, ObjectUtils.emptyMap()); + } + } catch (Exception ignored) { + } } @@ -484,7 +491,8 @@ public void testListTransformationByNamed() throws Exception { } finally { try { api.deleteTransformation(name, null); - } catch (Exception ignored){} + } catch (Exception ignored) { + } } } @@ -653,7 +661,7 @@ public void testGetUploadPreset() throws Exception { String[] tags = {"a", "b", "c"}; Map context = ObjectUtils.asMap("a", "b", "c", "d"); Map result = api.createUploadPreset(ObjectUtils.asMap("unsigned", true, "folder", "folder", "transformation", EXPLICIT_TRANSFORMATION, "tags", tags, "context", - context,"live",true)); + context, "live", true)); String name = result.get("name").toString(); Map preset = api.uploadPreset(name, ObjectUtils.emptyMap()); assertEquals(preset.get("name"), name); @@ -693,7 +701,7 @@ public void testUpdateUploadPreset() throws Exception { String name = api.createUploadPreset(ObjectUtils.asMap("folder", "folder")).get("name").toString(); Map preset = api.uploadPreset(name, ObjectUtils.emptyMap()); Map settings = (Map) preset.get("settings"); - settings.putAll(ObjectUtils.asMap("colors", true, "unsigned", true, "disallow_public_id", true,"live",true)); + settings.putAll(ObjectUtils.asMap("colors", true, "unsigned", true, "disallow_public_id", true, "live", true)); api.updateUploadPreset(name, settings); settings.remove("unsigned"); preset = api.uploadPreset(name, ObjectUtils.emptyMap()); @@ -758,6 +766,14 @@ public void testFolderApi() throws Exception { api.deleteResourcesByPrefix("test_folder", ObjectUtils.emptyMap()); } + @Test + public void testCreateFolder() throws Exception { + String apTestCreateFolder = "api_test_create_folder" + "_" + SUFFIX; + createdFolders.add(apTestCreateFolder); + Map result = api.createFolder("apTestCreateFolder", null); + assertTrue((Boolean) result.get("success")); + } + @Test public void testRestore() throws Exception { // should support restoring resources @@ -946,7 +962,7 @@ public void testDeleteFolder() throws Exception { Thread.sleep(5000); api.deleteResources(Collections.singletonList(uploadResult.get("public_id").toString()), emptyMap()); ApiResponse result = api.deleteFolder(toDelete, emptyMap()); - assertTrue(((ArrayList)result.get("deleted")).contains(toDelete)); + assertTrue(((ArrayList) result.get("deleted")).contains(toDelete)); // should throw exception (folder not found): api.deleteFolder(cloudinary.randomPublicId(), emptyMap()); @@ -958,4 +974,4 @@ public void testCinemagraphAnalysisResource() throws Exception { ApiResponse res = api.resource(API_TEST, Collections.singletonMap("cinemagraph_analysis", true)); assertNotNull(res.get("cinemagraph_analysis")); } -} \ No newline at end of file +} From f1cd08baf8adc9bf4e059039f912eb22d61a7ae0 Mon Sep 17 00:00:00 2001 From: michalkuperman Date: Mon, 25 Nov 2019 15:29:57 +0200 Subject: [PATCH 5/6] "encode URL in API calls" --- .../strategies/AbstractApiStrategy.java | 16 +++++++++++++++- .../java/com/cloudinary/http42/ApiStrategy.java | 6 +----- .../java/com/cloudinary/http43/ApiStrategy.java | 5 +---- .../java/com/cloudinary/http44/ApiStrategy.java | 7 ++----- .../com/cloudinary/test/AbstractApiTest.java | 9 +++++++++ 5 files changed, 28 insertions(+), 15 deletions(-) diff --git a/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java b/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java index c5b68906..65d0970d 100644 --- a/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java +++ b/cloudinary-core/src/main/java/com/cloudinary/strategies/AbstractApiStrategy.java @@ -2,10 +2,13 @@ import com.cloudinary.Api; import com.cloudinary.Api.HttpMethod; +import com.cloudinary.SmartUrlEncoder; import com.cloudinary.api.ApiResponse; - +import com.cloudinary.utils.StringUtils; +import java.util.Arrays; import java.util.Map; + public abstract class AbstractApiStrategy { protected Api api; @@ -13,6 +16,17 @@ public void init(Api api) { this.api = api; } + protected String createApiUrl (Iterable uri, String prefix, String cloudName){ + + String apiUrl = StringUtils.join(Arrays.asList(prefix, "v1_1", cloudName), "/"); + for (String component : uri) { + component = SmartUrlEncoder.encode(component); + apiUrl = apiUrl + "/" + component; + + } + return apiUrl; + } + @SuppressWarnings("rawtypes") public abstract ApiResponse callApi(HttpMethod method, Iterable uri, Map params, Map options) throws Exception; diff --git a/cloudinary-http42/src/main/java/com/cloudinary/http42/ApiStrategy.java b/cloudinary-http42/src/main/java/com/cloudinary/http42/ApiStrategy.java index a0a9e0bf..7c19aeb9 100644 --- a/cloudinary-http42/src/main/java/com/cloudinary/http42/ApiStrategy.java +++ b/cloudinary-http42/src/main/java/com/cloudinary/http42/ApiStrategy.java @@ -43,11 +43,7 @@ public ApiResponse callApi(HttpMethod method, Iterable uri, Map uri, Map uri, Map Date: Tue, 26 Nov 2019 12:12:11 +0200 Subject: [PATCH 6/6] "indentation in tests and remove try catch" --- .../java/com/cloudinary/test/AbstractApiTest.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java index 4ce640fe..424970d7 100644 --- a/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java +++ b/cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java @@ -794,14 +794,11 @@ public void testRestore() throws Exception { } @Test - public void testEncodeUrlInApiCall() throws Exception { - try { - Map result = api.subFolders("sub^folder test", null); - assertEquals("sub%5Efolder%20test", ((Map) ((org.cloudinary.json.JSONArray) result.get("folders")).get(0)).get("path")); - } catch (Exception ignored) { - - } + public void testEncodeUrlInApiCall() throws Exception { + Map result = api.subFolders("sub^folder test", null); + assertEquals("sub%5Efolder%20test", ((Map) ((org.cloudinary.json.JSONArray) result.get("folders")).get(0)).get("path")); } + @Test public void testUploadMapping() throws Exception { String aptTestUploadMapping = "api_test_upload_mapping" + SUFFIX;