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}