From 3db59dc5c4c8c6fdc1dff678394c74a6cc62482c Mon Sep 17 00:00:00 2001 From: Kamil Berdychowski Date: Tue, 9 Nov 2021 15:26:22 +0100 Subject: [PATCH 1/2] Fixes deprecated enums still being used (#931) --- CHANGELOG.md | 1 + src/intTest/java/com/box/sdk/EventLogIT.java | 52 ++++++- .../com/box/sdk/EnterpriseEventsRequest.java | 101 +++++++++++++ src/main/java/com/box/sdk/EventLog.java | 139 +++++++++++++++++- src/test/java/com/box/sdk/EventLogTest.java | 95 ++++++++++++ .../com/box/sdk/JSONRequestInterceptor.java | 3 +- 6 files changed, 382 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/box/sdk/EnterpriseEventsRequest.java create mode 100644 src/test/java/com/box/sdk/EventLogTest.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f0e6b327..299e64981 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ __Breaking Changes:__ __New Features and Enhancements:__ __Bug Fixes:__ + - Fix for deprecated enums still being used ([#931](https://github.com/box/box-java-sdk/issues/931)) ## 2.57.0 [2021-10-18] diff --git a/src/intTest/java/com/box/sdk/EventLogIT.java b/src/intTest/java/com/box/sdk/EventLogIT.java index ba17ef6d1..e9665d37e 100644 --- a/src/intTest/java/com/box/sdk/EventLogIT.java +++ b/src/intTest/java/com/box/sdk/EventLogIT.java @@ -16,7 +16,9 @@ public void getEnterpriseEventsReturnsAtLeastOneEvent() { BoxAPIConnection api = new BoxAPIConnection(TestConfig.getAccessToken()); Date after = new Date(0L); Date before = new Date(System.currentTimeMillis()); - EventLog events = EventLog.getEnterpriseEvents(api, after, before); + + EnterpriseEventsRequest request = new EnterpriseEventsRequest().after(after).before(before); + EventLog events = EventLog.getEnterpriseEvents(api, request); assertThat(events.getSize(), is(not(0))); assertThat(events.getStartDate(), is(equalTo(after))); @@ -30,7 +32,9 @@ public void getEnterpriseEventsGmtPlus530() { TimeZone.setDefault(null); Date after = new Date(0L); Date before = new Date(System.currentTimeMillis()); - EventLog events = EventLog.getEnterpriseEvents(api, after, before); + + EnterpriseEventsRequest request = new EnterpriseEventsRequest().after(after).before(before); + EventLog events = EventLog.getEnterpriseEvents(api, request); assertThat(events.getSize(), is(not(0))); assertThat(events.getStartDate(), is(equalTo(after))); @@ -45,6 +49,50 @@ public void getEnterpriseEventsGmtPlus530WithLimit() { Date after = new Date(0L); Date before = new Date(System.currentTimeMillis()); int limit = 5; + + EnterpriseEventsRequest request = new EnterpriseEventsRequest().after(after).before(before).limit(limit); + EventLog events = EventLog.getEnterpriseEvents(api, request); + + assertThat(events.getSize(), is(not(0))); + assertThat(events.getStartDate(), is(equalTo(after))); + assertThat(events.getEndDate(), is(equalTo(before))); + assertThat(events.getLimit(), is(equalTo(limit))); + } + + @Test + public void getEnterpriseEventsReturnsAtLeastOneEventDeprecated() { + BoxAPIConnection api = new BoxAPIConnection(TestConfig.getAccessToken()); + Date after = new Date(0L); + Date before = new Date(System.currentTimeMillis()); + EventLog events = EventLog.getEnterpriseEvents(api, after, before); + + assertThat(events.getSize(), is(not(0))); + assertThat(events.getStartDate(), is(equalTo(after))); + assertThat(events.getEndDate(), is(equalTo(before))); + } + + @Test + public void getEnterpriseEventsGmtPlus530Deprecated() { + BoxAPIConnection api = new BoxAPIConnection(TestConfig.getAccessToken()); + System.setProperty("user.timezone", "Asia/Calcutta"); + TimeZone.setDefault(null); + Date after = new Date(0L); + Date before = new Date(System.currentTimeMillis()); + EventLog events = EventLog.getEnterpriseEvents(api, after, before); + + assertThat(events.getSize(), is(not(0))); + assertThat(events.getStartDate(), is(equalTo(after))); + assertThat(events.getEndDate(), is(equalTo(before))); + } + + @Test + public void getEnterpriseEventsGmtPlus530WithLimitDeprecated() { + BoxAPIConnection api = new BoxAPIConnection(TestConfig.getAccessToken()); + System.setProperty("user.timezone", "Asia/Calcutta"); + TimeZone.setDefault(null); + Date after = new Date(0L); + Date before = new Date(System.currentTimeMillis()); + int limit = 5; EventLog events = EventLog.getEnterpriseEvents(api, "", after, before, limit); assertThat(events.getSize(), is(not(0))); diff --git a/src/main/java/com/box/sdk/EnterpriseEventsRequest.java b/src/main/java/com/box/sdk/EnterpriseEventsRequest.java new file mode 100644 index 000000000..c9b77ce08 --- /dev/null +++ b/src/main/java/com/box/sdk/EnterpriseEventsRequest.java @@ -0,0 +1,101 @@ +package com.box.sdk; + +import static com.box.sdk.EventLog.ENTERPRISE_LIMIT; + +import com.box.sdk.BoxEvent.EventType; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Date; + +/** + * Class describing request to get Admin Logs. You can use it's fluent interface to create new request like so: + *
+ * {@code
+ * new EnterpriseEventsRequest().position("stream_position").limit(50);
+ * }
+ * 
+ */ +public final class EnterpriseEventsRequest { + private static final String ADMIN_LOGS_STREAM_TYPE = "admin_logs"; + private Date before; + private Date after; + private String position; + private int limit = ENTERPRISE_LIMIT; + private Collection types = new ArrayList<>(); + + /** + * The lower bound on the timestamp of the events returned. + * @param date the lower bound on the timestamp of the events returned. + * @return request being created. + */ + public EnterpriseEventsRequest after(Date date) { + this.after = date; + return this; + } + + /** + * The upper bound on the timestamp of the events returned. + * @param date the upper bound on the timestamp of the events returned. + * @return request being created. + */ + public EnterpriseEventsRequest before(Date date) { + this.before = date; + return this; + } + + /** + * The starting position of the event stream. + * @param position the starting position of the event stream. + * @return request being created. + */ + public EnterpriseEventsRequest position(String position) { + this.position = position; + return this; + } + + /** + * The number of entries to be returned in the response. + * @param limit the number of entries to be returned in the response. + * @return request being created. + */ + public EnterpriseEventsRequest limit(int limit) { + this.limit = limit; + return this; + } + + /** + * List of event types to filter by. + * @param types list of event types to filter by. + * @return request being created. + */ + public EnterpriseEventsRequest types(EventType... types) { + this.types = Arrays.asList(types); + return this; + } + + Date getAfter() { + return after; + } + + Date getBefore() { + return before; + } + + String getPosition() { + return position; + } + + int getLimit() { + return limit; + } + + + Collection getTypes() { + return types; + } + + String getStreamType() { + return ADMIN_LOGS_STREAM_TYPE; + } +} diff --git a/src/main/java/com/box/sdk/EventLog.java b/src/main/java/com/box/sdk/EventLog.java index 9bda5c269..e5961ad57 100644 --- a/src/main/java/com/box/sdk/EventLog.java +++ b/src/main/java/com/box/sdk/EventLog.java @@ -1,10 +1,12 @@ package com.box.sdk; +import com.eclipsesource.json.Json; import com.eclipsesource.json.JsonArray; import com.eclipsesource.json.JsonObject; import com.eclipsesource.json.JsonValue; import java.net.MalformedURLException; import java.net.URL; +import java.util.Collection; import java.util.Date; import java.util.Iterator; import java.util.LinkedHashSet; @@ -19,7 +21,7 @@ */ public class EventLog implements Iterable { - private static final int ENTERPRISE_LIMIT = 500; + static final int ENTERPRISE_LIMIT = 500; /** * Enterprise Event URL Template. */ @@ -29,7 +31,7 @@ public class EventLog implements Iterable { private final int limit; private final String nextStreamPosition; private final String streamPosition; - private final Set set; + private final Set events; private Date startDate; private Date endDate; @@ -40,10 +42,10 @@ public class EventLog implements Iterable { this.nextStreamPosition = json.get("next_stream_position").asString(); this.chunkSize = json.get("chunk_size").asInt(); - this.set = new LinkedHashSet(this.chunkSize); + this.events = new LinkedHashSet<>(this.chunkSize); JsonArray entries = json.get("entries").asArray(); for (JsonValue entry : entries) { - this.set.add(new BoxEvent(api, entry.asObject())); + this.events.add(new BoxEvent(api, entry.asObject())); } } @@ -57,7 +59,9 @@ public class EventLog implements Iterable { * @param before the upper bound on the timestamp of the events returned. * @param types an optional list of event types to filter by. * @return a log of all the events that met the given criteria. + * @deprecated Use {@link #getEnterpriseEvents(BoxAPIConnection, EnterpriseEventsRequest)} */ + @Deprecated public static EventLog getEnterpriseEvents(BoxAPIConnection api, String position, Date after, Date before, BoxEvent.Type... types) { return getEnterpriseEvents(api, position, after, before, ENTERPRISE_LIMIT, types); @@ -71,7 +75,9 @@ public static EventLog getEnterpriseEvents(BoxAPIConnection api, String position * @param before the upper bound on the timestamp of the events returned. * @param types an optional list of event types to filter by. * @return a log of all the events that met the given criteria. + * @deprecated Use {@link #getEnterpriseEvents(BoxAPIConnection, EnterpriseEventsRequest)} */ + @Deprecated public static EventLog getEnterpriseEvents(BoxAPIConnection api, Date after, Date before, BoxEvent.Type... types) { return getEnterpriseEvents(api, null, after, before, ENTERPRISE_LIMIT, types); } @@ -87,7 +93,9 @@ public static EventLog getEnterpriseEvents(BoxAPIConnection api, Date after, Dat * @param limit the number of entries to be returned in the response. * @param types an optional list of event types to filter by. * @return a log of all the events that met the given criteria. + * @deprecated Use {@link #getEnterpriseEvents(BoxAPIConnection, EnterpriseEventsRequest)} */ + @Deprecated public static EventLog getEnterpriseEvents(BoxAPIConnection api, String position, Date after, Date before, int limit, BoxEvent.Type... types) { @@ -141,6 +149,83 @@ public static EventLog getEnterpriseEvents(BoxAPIConnection api, String position return log; } + /** + * Gets all the enterprise events. You can specify a date range to limit when events occured, + * starting from a given position within the event stream, set limit or specify event types that should be filtered. + * Example: + *
+     * {@code
+     * EnterpriseEventsRequest request = new EnterpriseEventsRequest()
+     *     .after(after)        // The lower bound on the timestamp of the events returned.
+     *     .before(before)      // The upper bound on the timestamp of the events returned.
+     *     .limit(200)          // The number of entries to be returned in the response.
+     *     .position(position)  // The starting position of the event stream.
+     *     .types(EventType.LOGIN, EventType.FAILED_LOGIN); // List of event types to filter by.
+     * EventLog.getEnterpriseEvents(api, request);
+     * }
+     * 
+ * @param api the API connection to use. + * @param enterpriseEventsRequest request to get events. + * @return a log of all the events that met the given criteria. + */ + public static EventLog getEnterpriseEvents(BoxAPIConnection api, EnterpriseEventsRequest enterpriseEventsRequest) { + EventLogRequest request = new EventLogRequest( + enterpriseEventsRequest.getBefore(), + enterpriseEventsRequest.getAfter(), + enterpriseEventsRequest.getPosition(), + enterpriseEventsRequest.getLimit(), + enterpriseEventsRequest.getTypes() + ); + return getEnterpriseEventsForStreamType(api, enterpriseEventsRequest.getStreamType(), request); + } + + private static EventLog getEnterpriseEventsForStreamType( + BoxAPIConnection api, String streamType, EventLogRequest request + ) { + URL url = new URLTemplate("events?").build(api.getBaseURL()); + QueryStringBuilder queryBuilder = new QueryStringBuilder(url.getQuery()); + queryBuilder.appendParam("stream_type", streamType); + addParamsToQuery(request, queryBuilder); + + try { + url = queryBuilder.addToURL(url); + } catch (MalformedURLException e) { + throw new BoxAPIException("Couldn't append a query string to the provided URL."); + } + + BoxAPIRequest apiRequest = new BoxAPIRequest(api, url, "GET"); + BoxJSONResponse response = (BoxJSONResponse) apiRequest.send(); + JsonObject responseJSON = Json.parse(response.getJSON()).asObject(); + EventLog log = new EventLog(api, responseJSON, request.getPosition(), request.getLimit()); + log.setStartDate(request.getAfter()); + log.setEndDate(request.getBefore()); + return log; + } + + private static void addParamsToQuery(EventLogRequest request, QueryStringBuilder queryBuilder) { + if (request.getAfter() != null) { + queryBuilder.appendParam("created_after", BoxDateFormat.format(request.getAfter())); + } + if (request.getBefore() != null) { + queryBuilder.appendParam("created_before", BoxDateFormat.format(request.getBefore())); + } + if (request.getPosition() != null) { + queryBuilder.appendParam("stream_position", request.getPosition()); + } + if (request.getLimit() != ENTERPRISE_LIMIT) { + queryBuilder.appendParam("limit", request.getLimit()); + } + if (request.getTypes().size() > 0) { + StringBuilder filterBuilder = new StringBuilder(); + for (BoxEvent.EventType filterType : request.getTypes()) { + filterBuilder.append(filterType.name()); + filterBuilder.append(','); + } + filterBuilder.deleteCharAt(filterBuilder.length() - 1); + queryBuilder.appendParam("event_type", filterBuilder.toString()); + } + } + /** * Returns an iterator over the events in this log. * @@ -148,7 +233,7 @@ public static EventLog getEnterpriseEvents(BoxAPIConnection api, String position */ @Override public Iterator iterator() { - return this.set.iterator(); + return this.events.iterator(); } /** @@ -243,6 +328,48 @@ public int getChunkSize() { * @return the number of events, excluding duplicates. */ public int getSize() { - return this.set.size(); + return this.events.size(); + } + + private static final class EventLogRequest { + private final Date before; + private final Date after; + private final String position; + private final Integer limit; + private final Collection types; + + private EventLogRequest( + Date before, + Date after, + String position, + Integer limit, + Collection types + ) { + this.before = before; + this.after = after; + this.position = position; + this.limit = limit; + this.types = types; + } + + private Date getBefore() { + return before; + } + + private Date getAfter() { + return after; + } + + private String getPosition() { + return position; + } + + private Integer getLimit() { + return limit; + } + + private Collection getTypes() { + return types; + } } } diff --git a/src/test/java/com/box/sdk/EventLogTest.java b/src/test/java/com/box/sdk/EventLogTest.java new file mode 100644 index 000000000..864392700 --- /dev/null +++ b/src/test/java/com/box/sdk/EventLogTest.java @@ -0,0 +1,95 @@ +package com.box.sdk; + +import static com.box.sdk.BoxEvent.EventType.FAILED_LOGIN; +import static com.box.sdk.BoxEvent.EventType.LOGIN; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; + +import java.net.URLDecoder; +import java.util.Date; +import org.junit.Test; + +public class EventLogTest { + + private static final BoxJSONResponse EMPTY_RESPONSE = new BoxJSONResponse() { + @Override + public String getJSON() { + return "{\"entries\": [], \"next_stream_position\": \"new_position\", \"chunk_size\": 0}"; + } + }; + + @Test + public void getEnterpriseEvents() { + final Date after = new Date(0L); + final Date before = new Date(System.currentTimeMillis()); + final int limit = 100; + final String position = "some_position"; + BoxEvent.EventType[] eventTypes = {LOGIN, FAILED_LOGIN}; + BoxAPIConnection api = new BoxAPIConnection(""); + api.setRequestInterceptor(new RequestInterceptor() { + @Override + public BoxAPIResponse onRequest(BoxAPIRequest request) { + try { + String query = URLDecoder.decode(request.getUrl().getQuery(), "UTF-8"); + assertThat(query, containsString("stream_type=admin_logs")); + assertThat(query, containsString("created_after=" + BoxDateFormat.format(after))); + assertThat(query, containsString("created_before=" + BoxDateFormat.format(before))); + assertThat(query, containsString("limit=" + limit)); + assertThat(query, containsString("stream_position=" + position)); + assertThat(query, containsString("event_type=LOGIN,FAILED_LOGIN")); + return EMPTY_RESPONSE; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + + EnterpriseEventsRequest request = new EnterpriseEventsRequest() + .after(after) + .before(before) + .limit(limit) + .position(position) + .types(eventTypes); + EventLog.getEnterpriseEvents(api, request); + } + + @Test + public void getEnterpriseEventsWithoutAnyParams() { + BoxAPIConnection api = new BoxAPIConnection(""); + api.setRequestInterceptor(new RequestInterceptor() { + @Override + public BoxAPIResponse onRequest(BoxAPIRequest request) { + try { + String query = URLDecoder.decode(request.getUrl().getQuery(), "UTF-8"); + assertThat(query, is("stream_type=admin_logs")); + return EMPTY_RESPONSE; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + + EventLog.getEnterpriseEvents(api, new EnterpriseEventsRequest()); + } + + @Test + public void getEnterpriseEventsAddsLimitOnlyIfDifferentThanDefault() { + final int limit = 100; + BoxAPIConnection api = new BoxAPIConnection(""); + api.setRequestInterceptor(new RequestInterceptor() { + @Override + public BoxAPIResponse onRequest(BoxAPIRequest request) { + try { + String query = URLDecoder.decode(request.getUrl().getQuery(), "UTF-8"); + assertThat(query, is("stream_type=admin_logs&limit=" + limit)); + return EMPTY_RESPONSE; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + + EventLog.getEnterpriseEvents(api, new EnterpriseEventsRequest().limit(limit)); + } +} diff --git a/src/test/java/com/box/sdk/JSONRequestInterceptor.java b/src/test/java/com/box/sdk/JSONRequestInterceptor.java index 23c362846..543e4aea5 100644 --- a/src/test/java/com/box/sdk/JSONRequestInterceptor.java +++ b/src/test/java/com/box/sdk/JSONRequestInterceptor.java @@ -2,6 +2,7 @@ import static org.junit.Assert.fail; +import com.eclipsesource.json.Json; import com.eclipsesource.json.JsonObject; import java.io.BufferedReader; import java.io.IOException; @@ -29,7 +30,7 @@ public BoxAPIResponse onRequest(BoxAPIRequest request) { JsonObject json = null; try { - json = JsonObject.readFrom(bodyReader); + json = Json.parse(bodyReader).asObject(); bodyReader.close(); } catch (IOException e) { fail(e.getMessage()); From c38c78034590417485d1f05002fc805c50b9e43f Mon Sep 17 00:00:00 2001 From: Kamil Berdychowski Date: Tue, 9 Nov 2021 17:11:01 +0100 Subject: [PATCH 2/2] Added usage of new method to documentation --- doc/events.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/doc/events.md b/doc/events.md index 5311bee02..91581dcd8 100644 --- a/doc/events.md +++ b/doc/events.md @@ -72,7 +72,10 @@ will only work with an API connection for an enterprise admin account. // get the last two hours of unfiltered enterprise events Date startDate = new Date(System.currentTimeMillis() - (1000 * 60 * 60 * 2)); Date endDate = new Date(System.currentTimeMillis()); -EventLog eventLog = EventLog.getEnterpriseEvents(api, startDate, endDate); +EnterpriseEventsRequest request = new EnterpriseEventsRequest() + .after(startDate) + .before(endDate); +EventLog eventLog = EventLog.getEnterpriseEvents(api, request); for (BoxEvent event : eventLog) { System.out.println("Enterprise Event Created by User: " + event.getCreatedBy().getName() @@ -88,9 +91,12 @@ limit field. ```java int LIMIT = 5; BoxAPIConnection api = new BoxAPIConnection("YOUR-DEVELOPER-TOKEN-WITH-ADMIN-ACCESS"); -EventLog eventLog = EventLog.getEnterpriseEvents(api, "STREAM-POSITION" - new Date(System.currentTimeMillis() - (1000 * 60 * 60 * 2)), - new Date(System.currentTimeMillis()), LIMIT); +EnterpriseEventsRequest request = new EnterpriseEventsRequest() + .after(new Date(System.currentTimeMillis() - (1000 * 60 * 60 * 2))) + .before(new Date(System.currentTimeMillis())) + .position("STREAM-POSITION") + .limit(LIMIT); +EventLog eventLog = EventLog.getEnterpriseEvents(api, request); for (BoxEvent event : eventLog) { System.out.println("Enterprise Event Created by User: " + event.getCreatedBy().getName()