Skip to content

Commit b0397d1

Browse files
committed
Add access control parameter to upload and update calls.
1 parent 4d3dda7 commit b0397d1

File tree

6 files changed

+210
-7
lines changed

6 files changed

+210
-7
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package com.cloudinary;
2+
3+
import com.cloudinary.utils.ObjectUtils;
4+
import org.cloudinary.json.JSONObject;
5+
6+
import java.util.Date;
7+
8+
/**
9+
* A class representing a single access control rule for a resource. Used as a parameter for {@link Api#update} and {@link Uploader#upload}
10+
*/
11+
public class AccessControlRule extends JSONObject {
12+
13+
/**
14+
* Construct a new token access rule
15+
* @return The access rule instance
16+
*/
17+
public static AccessControlRule token(){
18+
return new AccessControlRule(AccessType.token, null, null);
19+
}
20+
21+
/**
22+
* Construct a new anonymous access rule
23+
* @param start The start date for the rule
24+
* @return The access rule instance
25+
*/
26+
public static AccessControlRule anonymousFrom(Date start){
27+
return new AccessControlRule(AccessType.anonymous, start, null);
28+
}
29+
30+
/**
31+
* Construct a new anonymous access rule
32+
* @param end The end date for the rule
33+
* @return The access rule instance
34+
*/
35+
public static AccessControlRule anonymousUntil(Date end){
36+
return new AccessControlRule(AccessType.anonymous, null, end);
37+
}
38+
39+
/**
40+
* Construct a new anonymous access rule
41+
* @param start The start date for the rule
42+
* @param end The end date for the rule
43+
* @return The access rule instance
44+
*/
45+
public static AccessControlRule anonymous(Date start, Date end){
46+
return new AccessControlRule(AccessType.anonymous, start, end);
47+
}
48+
49+
private AccessControlRule(AccessType accessType, Date start, Date end) {
50+
put("access_type", accessType.name());
51+
if (start != null) {
52+
put("start", ObjectUtils.toISO8601(start));
53+
}
54+
55+
if (end != null) {
56+
put("end", ObjectUtils.toISO8601(end));
57+
}
58+
}
59+
60+
/**
61+
* Access type for an access rule
62+
*/
63+
public enum AccessType {
64+
anonymous, token
65+
}
66+
}

cloudinary-core/src/main/java/com/cloudinary/Util.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package com.cloudinary;
22

3-
import java.util.*;
4-
53
import com.cloudinary.utils.ObjectUtils;
64
import com.cloudinary.utils.StringUtils;
75
import org.cloudinary.json.JSONObject;
86

7+
import java.util.*;
8+
99
public class Util {
1010
static final String[] BOOLEAN_UPLOAD_OPTIONS = new String[]{"backup", "exif", "faces", "colors", "image_metadata", "use_filename", "unique_filename",
1111
"eager_async", "invalidate", "discard_original_filename", "overwrite", "phash", "return_delete_token", "async"};
@@ -48,6 +48,8 @@ public static final Map<String, Object> buildUploadParams(Map options) {
4848
}
4949
processWriteParameters(options, params);
5050
} else {
51+
// if there's a signature, it means all the params are already serialized so
52+
// we don't need to construct them, just pass the value as is:
5153
params.put("eager", (String) options.get("eager"));
5254
params.put("transformation", (String) options.get("transformation"));
5355
params.put("headers", (String) options.get("headers"));
@@ -60,6 +62,7 @@ public static final Map<String, Object> buildUploadParams(Map options) {
6062
params.put("detection", (String) options.get("detection"));
6163
params.put("similarity_search", (String) options.get("similarity_search"));
6264
params.put("auto_tagging", (String) options.get("auto_tagging"));
65+
params.put("access_control", (String) options.get("access_control"));
6366
}
6467
return params;
6568
}
@@ -92,6 +95,9 @@ public static final void processWriteParameters(Map<String, Object> options, Map
9295
params.put("custom_coordinates", Coordinates.parseCoordinates(options.get("custom_coordinates")).toString());
9396
if (options.get("context") != null)
9497
params.put("context", encodeContext(options.get("context")));
98+
if (options.get("access_control") != null) {
99+
params.put("access_control", encodeAccessControl(options.get("access_control")));
100+
}
95101
putObject("ocr", options, params);
96102
putObject("raw_convert", options, params);
97103
putObject("categorization", options, params);
@@ -102,6 +108,14 @@ public static final void processWriteParameters(Map<String, Object> options, Map
102108
params.put("auto_tagging", ObjectUtils.asFloat(options.get("auto_tagging")));
103109
}
104110

111+
protected static String encodeAccessControl(Object accessControl) {
112+
if (accessControl instanceof AccessControlRule) {
113+
accessControl = Arrays.asList(accessControl);
114+
}
115+
116+
return JSONObject.wrap(accessControl).toString();
117+
}
118+
105119
protected static String encodeContext(Object context) {
106120
if (context != null && context instanceof Map) {
107121
Map<String, String> mapArg = (Map<String, String>) context;

cloudinary-core/src/main/java/com/cloudinary/utils/ObjectUtils.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,22 @@
55
import org.cloudinary.json.JSONObject;
66

77
import java.io.*;
8+
import java.text.DateFormat;
9+
import java.text.SimpleDateFormat;
810
import java.util.*;
911

1012

1113
public class ObjectUtils {
14+
/**
15+
* Formats a Date as an ISO-8601 string representation.
16+
* @param date Date to format
17+
* @return The date formatted as ISO-8601 string
18+
*/
19+
public static String toISO8601(Date date){
20+
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.US);
21+
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
22+
return dateFormat.format(date);
23+
}
1224

1325
public static String asString(Object value) {
1426
if (value == null) {

cloudinary-core/src/test/java/com/cloudinary/UtilTest.java

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
package com.cloudinary;
22

33
import com.cloudinary.utils.ObjectUtils;
4+
import org.cloudinary.json.JSONObject;
45
import org.junit.Test;
56

7+
import java.text.ParseException;
8+
import java.text.SimpleDateFormat;
9+
import java.util.Date;
610
import java.util.Map;
711

812
import static org.junit.Assert.*;
@@ -11,6 +15,12 @@
1115
* Created by amir on 17/11/2016.
1216
*/
1317
public class UtilTest {
18+
19+
public static final String START = "2019-02-22 16:20:57 +0200";
20+
public static final String END = "2019-03-22 00:00:00 +0200";
21+
public static final String START_REFORMATTED = "2019-02-22T14:20:57Z";
22+
public static final String END_REFORMATTED = "2019-03-21T22:00:00Z";
23+
1424
@Test
1525
public void encodeContext() throws Exception {
1626
Map context = ObjectUtils.asMap("caption", "different = caption", "alt2", "alt|alternative");
@@ -19,4 +29,31 @@ public void encodeContext() throws Exception {
1929
"alt2=alt\\|alternative|caption=different \\= caption".equals(result));
2030
}
2131

32+
@Test
33+
public void testAccessControlRule() throws ParseException {
34+
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
35+
final Date start = simpleDateFormat.parse(START);
36+
final Date end = simpleDateFormat.parse(END);
37+
AccessControlRule acl = AccessControlRule.anonymous(start, end);
38+
39+
JSONObject deserializedAcl = new JSONObject(acl.toString());
40+
assertEquals(deserializedAcl.get("access_type"), "anonymous");
41+
assertEquals(deserializedAcl.get("start"), START_REFORMATTED);
42+
assertEquals(deserializedAcl.get("end"), END_REFORMATTED);
43+
44+
acl = AccessControlRule.anonymousFrom(start);
45+
assertEquals(2, acl.length());
46+
assertEquals(deserializedAcl.get("access_type"), "anonymous");
47+
assertEquals(deserializedAcl.get("start"), START_REFORMATTED);
48+
49+
acl = AccessControlRule.anonymousUntil(end);
50+
assertEquals(2, acl.length());
51+
assertEquals(deserializedAcl.get("access_type"), "anonymous");
52+
assertEquals(deserializedAcl.get("end"), END_REFORMATTED);
53+
54+
AccessControlRule token = AccessControlRule.token();
55+
assertEquals(1, token.length());
56+
assertEquals("{\"access_type\":\"token\"}", token.toString());
57+
58+
}
2259
}

cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractApiTest.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package com.cloudinary.test;
22

3-
import com.cloudinary.Api;
4-
import com.cloudinary.Cloudinary;
5-
import com.cloudinary.Coordinates;
6-
import com.cloudinary.Transformation;
3+
import com.cloudinary.*;
74
import com.cloudinary.api.ApiResponse;
85
import com.cloudinary.api.exceptions.BadRequest;
96
import com.cloudinary.api.exceptions.NotFound;
@@ -13,6 +10,7 @@
1310
import org.junit.rules.TestName;
1411

1512
import java.io.IOException;
13+
import java.text.SimpleDateFormat;
1614
import java.util.*;
1715

1816
import static org.hamcrest.Matchers.*;
@@ -594,6 +592,24 @@ public void testUpdateCustomCoordinates() throws IOException, Exception {
594592
}
595593
}
596594

595+
@Test
596+
public void testUpdateAccessControl() throws Exception {
597+
// should update access control
598+
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
599+
final Date start = simpleDateFormat.parse("2019-02-22 16:20:57 +0200");
600+
final Date end = simpleDateFormat.parse("2019-03-22 00:00:00 +0200");
601+
AccessControlRule acl = AccessControlRule.anonymous(start, end);
602+
Map uploadResult = cloudinary.uploader().upload(SRC_TEST_IMAGE, ObjectUtils.asMap("tags", UPLOAD_TAGS));
603+
ApiResponse res = cloudinary.api().update(uploadResult.get("public_id").toString(), ObjectUtils.asMap("access_control", acl));
604+
Map result = cloudinary.api().resource(uploadResult.get("public_id").toString(), ObjectUtils.asMap("access_control", true));
605+
606+
Map accessControlResult = (Map) ((List) result.get("access_control")).get(0);
607+
608+
assertEquals("anonymous", accessControlResult.get("access_type"));
609+
assertEquals("2019-02-22T14:20:57Z", accessControlResult.get("start"));
610+
assertEquals("2019-03-21T22:00:00Z", accessControlResult.get("end"));
611+
}
612+
597613
@Test
598614
public void testListUploadPresets() throws Exception {
599615
// should allow creating and listing upload_presets

cloudinary-test-common/src/main/java/com/cloudinary/test/AbstractUploaderTest.java

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44
import com.cloudinary.utils.ObjectUtils;
55
import com.cloudinary.utils.Rectangle;
66
import org.cloudinary.json.JSONArray;
7+
import org.cloudinary.json.JSONObject;
78
import org.junit.*;
89
import org.junit.rules.TestName;
910

1011
import java.io.*;
1112
import java.net.HttpURLConnection;
1213
import java.net.URL;
14+
import java.text.ParseException;
15+
import java.text.SimpleDateFormat;
1316
import java.util.*;
1417
import java.util.zip.ZipInputStream;
1518

@@ -408,11 +411,15 @@ public void testRawConvertRequest() {
408411
@Test
409412
public void testCategorizationRequest() {
410413
//should support requesting categorization
414+
String errorMessage = "";
415+
411416
try {
412417
cloudinary.uploader().upload(SRC_TEST_IMAGE, asMap("categorization", "illegal", "tags", Arrays.asList(SDK_TEST_TAG, UPLOADER_TAG)));
413418
} catch (Exception e) {
414-
assertTrue(e.getMessage().matches("(.*)(Illegal value|not a valid|invalid)(.*)"));
419+
errorMessage = e.getMessage();
415420
}
421+
422+
assertTrue(errorMessage.contains("Categorization item illegal is not valid"));
416423
}
417424

418425
@Test
@@ -571,4 +578,55 @@ public void testUploadInvalidUrl() {
571578
}
572579
}
573580

581+
@Test
582+
public void testAccessControl() throws ParseException, IOException {
583+
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
584+
final Date start = simpleDateFormat.parse("2019-02-22 16:20:57 +0200");
585+
final Date end = simpleDateFormat.parse("2019-03-22 00:00:00 +0200");
586+
AccessControlRule acl;
587+
AccessControlRule token = AccessControlRule.token();
588+
589+
acl = AccessControlRule.anonymous(start, null);
590+
Map result = cloudinary.uploader().upload(SRC_TEST_IMAGE, asMap("access_control",
591+
Arrays.asList(acl, token), "tags", Arrays.asList(SDK_TEST_TAG, UPLOADER_TAG)));
592+
593+
assertNotNull(result);
594+
List<Map<String,String>> accessControlResponse = (List<Map<String, String>>) result.get("access_control");
595+
assertNotNull(accessControlResponse);
596+
assertEquals(2, accessControlResponse.size());
597+
598+
Map<String, String> acr = accessControlResponse.get(0);
599+
assertEquals("anonymous", acr.get("access_type"));
600+
assertEquals("2019-02-22T14:20:57Z", acr.get("start"));
601+
assertThat(acr, not(hasKey("end")));
602+
603+
acr = accessControlResponse.get(1);
604+
assertEquals("token", acr.get("access_type"));
605+
assertThat(acr, not(hasKey("start")));
606+
assertThat(acr, not(hasKey("end")));
607+
608+
result = cloudinary.uploader().upload(SRC_TEST_IMAGE, asMap("access_control",
609+
acl, "tags", Arrays.asList(SDK_TEST_TAG, UPLOADER_TAG)));
610+
611+
assertNotNull(result);
612+
accessControlResponse = (List<Map<String, String>>) result.get("access_control");
613+
assertNotNull(accessControlResponse);
614+
acr = accessControlResponse.get(0);
615+
assertEquals(1, accessControlResponse.size());
616+
assertEquals("anonymous", acr.get("access_type"));
617+
assertEquals("2019-02-22T14:20:57Z", acr.get("start"));
618+
assertThat(acr, not(hasKey("end")));
619+
620+
String aclString = "[{\"access_type\":\"anonymous\",\"start\":\"2019-02-22 16:20:57 +0200\",\"end\":\"2019-03-22 00:00 +0200\"}]";
621+
result = cloudinary.uploader().upload(SRC_TEST_IMAGE, asMap("access_control",
622+
aclString, "tags", Arrays.asList(SDK_TEST_TAG, UPLOADER_TAG)));
623+
624+
assertNotNull(result);
625+
accessControlResponse = (List<Map<String, String>>) result.get("access_control");
626+
assertNotNull(accessControlResponse);
627+
assertTrue(accessControlResponse.size() == 1);
628+
assertEquals("anonymous", accessControlResponse.get(0).get("access_type"));
629+
assertEquals("2019-02-22T14:20:57Z", accessControlResponse.get(0).get("start"));
630+
assertEquals("2019-03-21T22:00:00Z", accessControlResponse.get(0).get("end"));
631+
}
574632
}

0 commit comments

Comments
 (0)