001package com.box.sdkgen.managers.webhooks;
002
003import static com.box.sdkgen.internal.utils.UtilsManager.compareSignatures;
004import static com.box.sdkgen.internal.utils.UtilsManager.computeWebhookSignature;
005import static com.box.sdkgen.internal.utils.UtilsManager.convertToString;
006import static com.box.sdkgen.internal.utils.UtilsManager.dateTimeFromString;
007import static com.box.sdkgen.internal.utils.UtilsManager.dateTimeToEpochSeconds;
008import static com.box.sdkgen.internal.utils.UtilsManager.entryOf;
009import static com.box.sdkgen.internal.utils.UtilsManager.getEpochTimeInSeconds;
010import static com.box.sdkgen.internal.utils.UtilsManager.mapOf;
011import static com.box.sdkgen.internal.utils.UtilsManager.mergeMaps;
012import static com.box.sdkgen.internal.utils.UtilsManager.prepareParams;
013
014import com.box.sdkgen.networking.auth.Authentication;
015import com.box.sdkgen.networking.fetchoptions.FetchOptions;
016import com.box.sdkgen.networking.fetchoptions.ResponseFormat;
017import com.box.sdkgen.networking.fetchresponse.FetchResponse;
018import com.box.sdkgen.networking.network.NetworkSession;
019import com.box.sdkgen.schemas.webhook.Webhook;
020import com.box.sdkgen.schemas.webhooks.Webhooks;
021import com.box.sdkgen.serialization.json.JsonManager;
022import java.time.OffsetDateTime;
023import java.util.Map;
024
025public class WebhooksManager {
026
027  public Authentication auth;
028
029  public NetworkSession networkSession;
030
031  public WebhooksManager() {
032    this.networkSession = new NetworkSession();
033  }
034
035  protected WebhooksManager(Builder builder) {
036    this.auth = builder.auth;
037    this.networkSession = builder.networkSession;
038  }
039
040  /**
041   * Returns all defined webhooks for the requesting application.
042   *
043   * <p>This API only returns webhooks that are applied to files or folders that are owned by the
044   * authenticated user. This means that an admin can not see webhooks created by a service account
045   * unless the admin has access to those folders, and vice versa.
046   */
047  public Webhooks getWebhooks() {
048    return getWebhooks(new GetWebhooksQueryParams(), new GetWebhooksHeaders());
049  }
050
051  /**
052   * Returns all defined webhooks for the requesting application.
053   *
054   * <p>This API only returns webhooks that are applied to files or folders that are owned by the
055   * authenticated user. This means that an admin can not see webhooks created by a service account
056   * unless the admin has access to those folders, and vice versa.
057   *
058   * @param queryParams Query parameters of getWebhooks method
059   */
060  public Webhooks getWebhooks(GetWebhooksQueryParams queryParams) {
061    return getWebhooks(queryParams, new GetWebhooksHeaders());
062  }
063
064  /**
065   * Returns all defined webhooks for the requesting application.
066   *
067   * <p>This API only returns webhooks that are applied to files or folders that are owned by the
068   * authenticated user. This means that an admin can not see webhooks created by a service account
069   * unless the admin has access to those folders, and vice versa.
070   *
071   * @param headers Headers of getWebhooks method
072   */
073  public Webhooks getWebhooks(GetWebhooksHeaders headers) {
074    return getWebhooks(new GetWebhooksQueryParams(), headers);
075  }
076
077  /**
078   * Returns all defined webhooks for the requesting application.
079   *
080   * <p>This API only returns webhooks that are applied to files or folders that are owned by the
081   * authenticated user. This means that an admin can not see webhooks created by a service account
082   * unless the admin has access to those folders, and vice versa.
083   *
084   * @param queryParams Query parameters of getWebhooks method
085   * @param headers Headers of getWebhooks method
086   */
087  public Webhooks getWebhooks(GetWebhooksQueryParams queryParams, GetWebhooksHeaders headers) {
088    Map<String, String> queryParamsMap =
089        prepareParams(
090            mapOf(
091                entryOf("marker", convertToString(queryParams.getMarker())),
092                entryOf("limit", convertToString(queryParams.getLimit()))));
093    Map<String, String> headersMap = prepareParams(mergeMaps(mapOf(), headers.getExtraHeaders()));
094    FetchResponse response =
095        this.networkSession
096            .getNetworkClient()
097            .fetch(
098                new FetchOptions.Builder(
099                        String.join(
100                            "", this.networkSession.getBaseUrls().getBaseUrl(), "/2.0/webhooks"),
101                        "GET")
102                    .params(queryParamsMap)
103                    .headers(headersMap)
104                    .responseFormat(ResponseFormat.JSON)
105                    .auth(this.auth)
106                    .networkSession(this.networkSession)
107                    .build());
108    return JsonManager.deserialize(response.getData(), Webhooks.class);
109  }
110
111  /**
112   * Creates a webhook.
113   *
114   * @param requestBody Request body of createWebhook method
115   */
116  public Webhook createWebhook(CreateWebhookRequestBody requestBody) {
117    return createWebhook(requestBody, new CreateWebhookHeaders());
118  }
119
120  /**
121   * Creates a webhook.
122   *
123   * @param requestBody Request body of createWebhook method
124   * @param headers Headers of createWebhook method
125   */
126  public Webhook createWebhook(CreateWebhookRequestBody requestBody, CreateWebhookHeaders headers) {
127    Map<String, String> headersMap = prepareParams(mergeMaps(mapOf(), headers.getExtraHeaders()));
128    FetchResponse response =
129        this.networkSession
130            .getNetworkClient()
131            .fetch(
132                new FetchOptions.Builder(
133                        String.join(
134                            "", this.networkSession.getBaseUrls().getBaseUrl(), "/2.0/webhooks"),
135                        "POST")
136                    .headers(headersMap)
137                    .data(JsonManager.serialize(requestBody))
138                    .contentType("application/json")
139                    .responseFormat(ResponseFormat.JSON)
140                    .auth(this.auth)
141                    .networkSession(this.networkSession)
142                    .build());
143    return JsonManager.deserialize(response.getData(), Webhook.class);
144  }
145
146  /**
147   * Retrieves a specific webhook.
148   *
149   * @param webhookId The ID of the webhook. Example: "3321123"
150   */
151  public Webhook getWebhookById(String webhookId) {
152    return getWebhookById(webhookId, new GetWebhookByIdHeaders());
153  }
154
155  /**
156   * Retrieves a specific webhook.
157   *
158   * @param webhookId The ID of the webhook. Example: "3321123"
159   * @param headers Headers of getWebhookById method
160   */
161  public Webhook getWebhookById(String webhookId, GetWebhookByIdHeaders headers) {
162    Map<String, String> headersMap = prepareParams(mergeMaps(mapOf(), headers.getExtraHeaders()));
163    FetchResponse response =
164        this.networkSession
165            .getNetworkClient()
166            .fetch(
167                new FetchOptions.Builder(
168                        String.join(
169                            "",
170                            this.networkSession.getBaseUrls().getBaseUrl(),
171                            "/2.0/webhooks/",
172                            convertToString(webhookId)),
173                        "GET")
174                    .headers(headersMap)
175                    .responseFormat(ResponseFormat.JSON)
176                    .auth(this.auth)
177                    .networkSession(this.networkSession)
178                    .build());
179    return JsonManager.deserialize(response.getData(), Webhook.class);
180  }
181
182  /**
183   * Updates a webhook.
184   *
185   * @param webhookId The ID of the webhook. Example: "3321123"
186   */
187  public Webhook updateWebhookById(String webhookId) {
188    return updateWebhookById(
189        webhookId, new UpdateWebhookByIdRequestBody(), new UpdateWebhookByIdHeaders());
190  }
191
192  /**
193   * Updates a webhook.
194   *
195   * @param webhookId The ID of the webhook. Example: "3321123"
196   * @param requestBody Request body of updateWebhookById method
197   */
198  public Webhook updateWebhookById(String webhookId, UpdateWebhookByIdRequestBody requestBody) {
199    return updateWebhookById(webhookId, requestBody, new UpdateWebhookByIdHeaders());
200  }
201
202  /**
203   * Updates a webhook.
204   *
205   * @param webhookId The ID of the webhook. Example: "3321123"
206   * @param headers Headers of updateWebhookById method
207   */
208  public Webhook updateWebhookById(String webhookId, UpdateWebhookByIdHeaders headers) {
209    return updateWebhookById(webhookId, new UpdateWebhookByIdRequestBody(), headers);
210  }
211
212  /**
213   * Updates a webhook.
214   *
215   * @param webhookId The ID of the webhook. Example: "3321123"
216   * @param requestBody Request body of updateWebhookById method
217   * @param headers Headers of updateWebhookById method
218   */
219  public Webhook updateWebhookById(
220      String webhookId,
221      UpdateWebhookByIdRequestBody requestBody,
222      UpdateWebhookByIdHeaders headers) {
223    Map<String, String> headersMap = prepareParams(mergeMaps(mapOf(), headers.getExtraHeaders()));
224    FetchResponse response =
225        this.networkSession
226            .getNetworkClient()
227            .fetch(
228                new FetchOptions.Builder(
229                        String.join(
230                            "",
231                            this.networkSession.getBaseUrls().getBaseUrl(),
232                            "/2.0/webhooks/",
233                            convertToString(webhookId)),
234                        "PUT")
235                    .headers(headersMap)
236                    .data(JsonManager.serialize(requestBody))
237                    .contentType("application/json")
238                    .responseFormat(ResponseFormat.JSON)
239                    .auth(this.auth)
240                    .networkSession(this.networkSession)
241                    .build());
242    return JsonManager.deserialize(response.getData(), Webhook.class);
243  }
244
245  /**
246   * Deletes a webhook.
247   *
248   * @param webhookId The ID of the webhook. Example: "3321123"
249   */
250  public void deleteWebhookById(String webhookId) {
251    deleteWebhookById(webhookId, new DeleteWebhookByIdHeaders());
252  }
253
254  /**
255   * Deletes a webhook.
256   *
257   * @param webhookId The ID of the webhook. Example: "3321123"
258   * @param headers Headers of deleteWebhookById method
259   */
260  public void deleteWebhookById(String webhookId, DeleteWebhookByIdHeaders headers) {
261    Map<String, String> headersMap = prepareParams(mergeMaps(mapOf(), headers.getExtraHeaders()));
262    FetchResponse response =
263        this.networkSession
264            .getNetworkClient()
265            .fetch(
266                new FetchOptions.Builder(
267                        String.join(
268                            "",
269                            this.networkSession.getBaseUrls().getBaseUrl(),
270                            "/2.0/webhooks/",
271                            convertToString(webhookId)),
272                        "DELETE")
273                    .headers(headersMap)
274                    .responseFormat(ResponseFormat.NO_CONTENT)
275                    .auth(this.auth)
276                    .networkSession(this.networkSession)
277                    .build());
278  }
279
280  /**
281   * Validate a webhook message by verifying the signature and the delivery timestamp
282   *
283   * @param body The request body of the webhook message
284   * @param headers The headers of the webhook message
285   * @param primaryKey The primary signature to verify the message with
286   */
287  public static boolean validateMessage(
288      String body, Map<String, String> headers, String primaryKey) {
289    return validateMessage(body, headers, primaryKey, null, 600);
290  }
291
292  /**
293   * Validate a webhook message by verifying the signature and the delivery timestamp
294   *
295   * @param body The request body of the webhook message
296   * @param headers The headers of the webhook message
297   * @param primaryKey The primary signature to verify the message with
298   * @param secondaryKey The secondary signature to verify the message with
299   */
300  public static boolean validateMessage(
301      String body, Map<String, String> headers, String primaryKey, String secondaryKey) {
302    return validateMessage(body, headers, primaryKey, secondaryKey, 600);
303  }
304
305  /**
306   * Validate a webhook message by verifying the signature and the delivery timestamp
307   *
308   * @param body The request body of the webhook message
309   * @param headers The headers of the webhook message
310   * @param primaryKey The primary signature to verify the message with
311   * @param maxAge The maximum age of the message in seconds, defaults to 10 minutes
312   */
313  public static boolean validateMessage(
314      String body, Map<String, String> headers, String primaryKey, Integer maxAge) {
315    return validateMessage(body, headers, primaryKey, null, maxAge);
316  }
317
318  /**
319   * Validate a webhook message by verifying the signature and the delivery timestamp
320   *
321   * @param body The request body of the webhook message
322   * @param headers The headers of the webhook message
323   * @param primaryKey The primary signature to verify the message with
324   * @param secondaryKey The secondary signature to verify the message with
325   * @param maxAge The maximum age of the message in seconds, defaults to 10 minutes
326   */
327  public static boolean validateMessage(
328      String body,
329      Map<String, String> headers,
330      String primaryKey,
331      String secondaryKey,
332      Integer maxAge) {
333    OffsetDateTime deliveryTimestamp = dateTimeFromString(headers.get("box-delivery-timestamp"));
334    long currentEpoch = getEpochTimeInSeconds();
335    if (currentEpoch - maxAge > dateTimeToEpochSeconds(deliveryTimestamp)
336        || dateTimeToEpochSeconds(deliveryTimestamp) > currentEpoch) {
337      return false;
338    }
339    if (!(primaryKey == null)
340        && !(headers.get("box-signature-primary") == null)
341        && compareSignatures(
342            computeWebhookSignature(body, headers, primaryKey, false),
343            headers.get("box-signature-primary"))) {
344      return true;
345    }
346    if (!(primaryKey == null)
347        && !(headers.get("box-signature-primary") == null)
348        && compareSignatures(
349            computeWebhookSignature(body, headers, primaryKey, true),
350            headers.get("box-signature-primary"))) {
351      return true;
352    }
353    if (!(secondaryKey == null)
354        && !(headers.get("box-signature-secondary") == null)
355        && compareSignatures(
356            computeWebhookSignature(body, headers, secondaryKey, false),
357            headers.get("box-signature-secondary"))) {
358      return true;
359    }
360    if (!(secondaryKey == null)
361        && !(headers.get("box-signature-secondary") == null)
362        && compareSignatures(
363            computeWebhookSignature(body, headers, secondaryKey, true),
364            headers.get("box-signature-secondary"))) {
365      return true;
366    }
367    return false;
368  }
369
370  public Authentication getAuth() {
371    return auth;
372  }
373
374  public NetworkSession getNetworkSession() {
375    return networkSession;
376  }
377
378  public static class Builder {
379
380    protected Authentication auth;
381
382    protected NetworkSession networkSession;
383
384    public Builder() {}
385
386    public Builder auth(Authentication auth) {
387      this.auth = auth;
388      return this;
389    }
390
391    public Builder networkSession(NetworkSession networkSession) {
392      this.networkSession = networkSession;
393      return this;
394    }
395
396    public WebhooksManager build() {
397      if (this.networkSession == null) {
398        this.networkSession = new NetworkSession();
399      }
400      return new WebhooksManager(this);
401    }
402  }
403}