@dereekb/zoom 12.6.21 → 13.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/LICENSE +1 -1
  2. package/index.cjs.js +4 -1417
  3. package/index.esm.js +5 -1418
  4. package/nestjs/index.cjs.js +692 -0
  5. package/nestjs/index.esm.js +662 -0
  6. package/nestjs/package.json +19 -3
  7. package/nestjs/src/lib/webhook/webhook.zoom.controller.d.ts +1 -1
  8. package/nestjs/src/lib/zoom/zoom.api.d.ts +1 -1
  9. package/package.json +14 -7
  10. package/src/lib/oauth/oauth.error.api.d.ts +2 -2
  11. package/src/lib/zoom/zoom.error.api.d.ts +2 -2
  12. package/src/lib/zoom.error.api.d.ts +2 -2
  13. package/src/lib/zoom.type.d.ts +2 -2
  14. package/nestjs/CHANGELOG.md +0 -459
  15. package/nestjs/README.md +0 -11
  16. package/nestjs/src/index.js +0 -5
  17. package/nestjs/src/index.js.map +0 -1
  18. package/nestjs/src/lib/index.js +0 -7
  19. package/nestjs/src/lib/index.js.map +0 -1
  20. package/nestjs/src/lib/oauth/index.js +0 -8
  21. package/nestjs/src/lib/oauth/index.js.map +0 -1
  22. package/nestjs/src/lib/oauth/oauth.api.js +0 -41
  23. package/nestjs/src/lib/oauth/oauth.api.js.map +0 -1
  24. package/nestjs/src/lib/oauth/oauth.config.js +0 -50
  25. package/nestjs/src/lib/oauth/oauth.config.js.map +0 -1
  26. package/nestjs/src/lib/oauth/oauth.module.js +0 -36
  27. package/nestjs/src/lib/oauth/oauth.module.js.map +0 -1
  28. package/nestjs/src/lib/oauth/oauth.service.js +0 -230
  29. package/nestjs/src/lib/oauth/oauth.service.js.map +0 -1
  30. package/nestjs/src/lib/webhook/index.js +0 -15
  31. package/nestjs/src/lib/webhook/index.js.map +0 -1
  32. package/nestjs/src/lib/webhook/webhook.zoom.config.js +0 -17
  33. package/nestjs/src/lib/webhook/webhook.zoom.config.js.map +0 -1
  34. package/nestjs/src/lib/webhook/webhook.zoom.controller.js +0 -38
  35. package/nestjs/src/lib/webhook/webhook.zoom.controller.js.map +0 -1
  36. package/nestjs/src/lib/webhook/webhook.zoom.js +0 -38
  37. package/nestjs/src/lib/webhook/webhook.zoom.js.map +0 -1
  38. package/nestjs/src/lib/webhook/webhook.zoom.module.js +0 -41
  39. package/nestjs/src/lib/webhook/webhook.zoom.module.js.map +0 -1
  40. package/nestjs/src/lib/webhook/webhook.zoom.service.js +0 -60
  41. package/nestjs/src/lib/webhook/webhook.zoom.service.js.map +0 -1
  42. package/nestjs/src/lib/webhook/webhook.zoom.type.common.js +0 -3
  43. package/nestjs/src/lib/webhook/webhook.zoom.type.common.js.map +0 -1
  44. package/nestjs/src/lib/webhook/webhook.zoom.type.js +0 -3
  45. package/nestjs/src/lib/webhook/webhook.zoom.type.js.map +0 -1
  46. package/nestjs/src/lib/webhook/webhook.zoom.type.meeting.js +0 -18
  47. package/nestjs/src/lib/webhook/webhook.zoom.type.meeting.js.map +0 -1
  48. package/nestjs/src/lib/webhook/webhook.zoom.type.validate.js +0 -5
  49. package/nestjs/src/lib/webhook/webhook.zoom.type.validate.js.map +0 -1
  50. package/nestjs/src/lib/webhook/webhook.zoom.validate.js +0 -25
  51. package/nestjs/src/lib/webhook/webhook.zoom.validate.js.map +0 -1
  52. package/nestjs/src/lib/webhook/webhook.zoom.verify.js +0 -27
  53. package/nestjs/src/lib/webhook/webhook.zoom.verify.js.map +0 -1
  54. package/nestjs/src/lib/zoom/index.js +0 -7
  55. package/nestjs/src/lib/zoom/index.js.map +0 -1
  56. package/nestjs/src/lib/zoom/zoom.api.js +0 -78
  57. package/nestjs/src/lib/zoom/zoom.api.js.map +0 -1
  58. package/nestjs/src/lib/zoom/zoom.config.js +0 -15
  59. package/nestjs/src/lib/zoom/zoom.config.js.map +0 -1
  60. package/nestjs/src/lib/zoom/zoom.module.js +0 -40
  61. package/nestjs/src/lib/zoom/zoom.module.js.map +0 -1
  62. /package/{index.cjs.d.ts → index.d.ts} +0 -0
  63. /package/{index.esm.d.ts → nestjs/index.d.ts} +0 -0
@@ -0,0 +1,692 @@
1
+ 'use strict';
2
+
3
+ var common = require('@nestjs/common');
4
+ var zoom = require('@dereekb/zoom');
5
+ var util = require('@dereekb/util');
6
+ var path = require('path');
7
+ var fs = require('fs');
8
+ var config = require('@nestjs/config');
9
+ var nestjs = require('@dereekb/nestjs');
10
+ var crypto = require('crypto');
11
+
12
+ /******************************************************************************
13
+ Copyright (c) Microsoft Corporation.
14
+
15
+ Permission to use, copy, modify, and/or distribute this software for any
16
+ purpose with or without fee is hereby granted.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
19
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
20
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
21
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
22
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
23
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
24
+ PERFORMANCE OF THIS SOFTWARE.
25
+ ***************************************************************************** */
26
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
27
+
28
+
29
+ function __decorate(decorators, target, key, desc) {
30
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
31
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
32
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
33
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
34
+ }
35
+
36
+ function __param(paramIndex, decorator) {
37
+ return function (target, key) { decorator(target, key, paramIndex); }
38
+ }
39
+
40
+ function __metadata(metadataKey, metadataValue) {
41
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
42
+ }
43
+
44
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
45
+ var e = new Error(message);
46
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
47
+ };
48
+
49
+ /**
50
+ * Configuration for ZoomService
51
+ */
52
+ class ZoomOAuthServiceConfig {
53
+ zoomOAuth;
54
+ factoryConfig;
55
+ static assertValidConfig(config) {
56
+ const {
57
+ zoomOAuth
58
+ } = config;
59
+ if (!zoomOAuth) {
60
+ throw new Error('ZoomOAuthServiceConfig.zoomOAuth is required');
61
+ } else {
62
+ if (!zoomOAuth.accountId) {
63
+ throw new Error('ZoomOAuthServiceConfig.zoomOAuth.accountId is required');
64
+ } else if (!zoomOAuth.clientSecret) {
65
+ throw new Error('ZoomOAuthServiceConfig.zoomOAuth.clientSecret is required');
66
+ } else if (!zoomOAuth.clientId) {
67
+ throw new Error('ZoomOAuthServiceConfig.zoomOAuth.clientId is required');
68
+ }
69
+ }
70
+ }
71
+ }
72
+ function readZoomOAuthServiceConfigFromConfigService(configService, prefix) {
73
+ const prefixString = util.characterPrefixSuffixInstance({
74
+ suffix: '_',
75
+ suffixEmptyString: false
76
+ }).prefixSuffixString(prefix ?? '');
77
+ const accountIdKey = `${prefixString}ZOOM_ACCOUNT_ID`;
78
+ const clientIdKey = `${prefixString}ZOOM_CLIENT_ID`;
79
+ const clientSecretKey = `${prefixString}ZOOM_CLIENT_SECRET`;
80
+ const accountId = configService.getOrThrow(accountIdKey);
81
+ const clientId = configService.getOrThrow(clientIdKey);
82
+ const clientSecret = configService.getOrThrow(clientSecretKey);
83
+ const config = {
84
+ zoomOAuth: {
85
+ authEntityType: 'account',
86
+ accountId,
87
+ clientId,
88
+ clientSecret
89
+ }
90
+ };
91
+ ZoomOAuthServiceConfig.assertValidConfig(config);
92
+ return config;
93
+ }
94
+
95
+ /**
96
+ * Service used for retrieving ZoomAccessTokenCache for Zoom services.
97
+ */
98
+ exports.ZoomOAuthAccessTokenCacheService = class ZoomOAuthAccessTokenCacheService {};
99
+ exports.ZoomOAuthAccessTokenCacheService = __decorate([common.Injectable()], exports.ZoomOAuthAccessTokenCacheService);
100
+ function logMergeZoomOAuthAccessTokenCacheServiceErrorFunction(failedUpdates) {
101
+ console.warn(`mergeZoomOAuthAccessTokenCacheServices(): failed updating ${failedUpdates.length} caches.`);
102
+ failedUpdates.forEach(([x, e], i) => {
103
+ console.warn(`Cache update failure ${i + 1}: - ${e}`);
104
+ });
105
+ }
106
+ /**
107
+ * Merges the input services in order to use some as a backup source.
108
+ *
109
+ * If once source fails retrieval, the next will be tried.
110
+ *
111
+ * When updating a cached token, it will update the token across all services.
112
+ *
113
+ * @param servicesToMerge Must include atleast one service. Empty arrays will throw an error.
114
+ */
115
+ function mergeZoomOAuthAccessTokenCacheServices(inputServicesToMerge, logError) {
116
+ const allServices = [...inputServicesToMerge];
117
+ const logErrorFunction = typeof logError === 'function' ? logError : logError !== false ? logMergeZoomOAuthAccessTokenCacheServiceErrorFunction : undefined;
118
+ if (allServices.length === 0) {
119
+ throw new Error('mergeZoomOAuthAccessTokenCacheServices() input cannot be empty.');
120
+ }
121
+ const loadZoomAccessTokenCache = accessCachesForServices => {
122
+ const loadCachedTokenFromFirstService = util.tryWithPromiseFactoriesFunction({
123
+ promiseFactories: accessCachesForServices.map(x => () => x.loadCachedToken().catch(() => null).then(x => {
124
+ let result = undefined;
125
+ if (x && !util.isPast(x.expiresAt)) {
126
+ result = x; // only return from cache if it is not expired
127
+ }
128
+ return result;
129
+ })),
130
+ successOnMaybe: false,
131
+ throwErrors: false
132
+ });
133
+ const cacheForService = {
134
+ loadCachedToken: function () {
135
+ return loadCachedTokenFromFirstService();
136
+ },
137
+ updateCachedToken: async function (accessToken) {
138
+ return Promise.allSettled(accessCachesForServices.map(x => x.updateCachedToken(accessToken).then(() => null).catch(e => {
139
+ return [x, e];
140
+ }))).then(x => {
141
+ // only find the failures if we're logging
142
+ if (logErrorFunction != null) {
143
+ const failedUpdates = util.filterMaybeArrayValues(x.map(y => y.value));
144
+ if (failedUpdates.length) {
145
+ logErrorFunction(failedUpdates);
146
+ }
147
+ }
148
+ });
149
+ }
150
+ };
151
+ return cacheForService;
152
+ };
153
+ const allServiceAccessTokenCaches = allServices.map(x => x.loadZoomAccessTokenCache());
154
+ const allServicesWithCacheForRefreshToken = allServices.filter(x => x.cacheForRefreshToken != null);
155
+ const cacheForRefreshToken = allServiceAccessTokenCaches.length > 0 ? refreshToken => {
156
+ const allCaches = allServicesWithCacheForRefreshToken.map(x => x.cacheForRefreshToken(refreshToken));
157
+ return loadZoomAccessTokenCache(allCaches);
158
+ } : undefined;
159
+ const service = {
160
+ loadZoomAccessTokenCache: () => loadZoomAccessTokenCache(allServiceAccessTokenCaches),
161
+ cacheForRefreshToken
162
+ };
163
+ return service;
164
+ }
165
+ // MARK: Memory Access Token Cache
166
+ /**
167
+ * Creates a ZoomOAuthAccessTokenCacheService that uses in-memory storage.
168
+ *
169
+ * @returns
170
+ */
171
+ function memoryZoomOAuthAccessTokenCacheService(existingToken, logAccessToConsole) {
172
+ let token = existingToken;
173
+ function loadZoomAccessTokenCache() {
174
+ const accessTokenCache = {
175
+ loadCachedToken: async function () {
176
+ if (logAccessToConsole) {
177
+ console.log('retrieving access token from memory: ', {
178
+ token
179
+ });
180
+ }
181
+ return token;
182
+ },
183
+ updateCachedToken: async function (accessToken) {
184
+ token = accessToken;
185
+ if (logAccessToConsole) {
186
+ console.log('updating access token in memory: ', {
187
+ accessToken
188
+ });
189
+ }
190
+ }
191
+ };
192
+ return accessTokenCache;
193
+ }
194
+ return {
195
+ loadZoomAccessTokenCache,
196
+ cacheForRefreshToken: () => loadZoomAccessTokenCache()
197
+ };
198
+ }
199
+ // MARK: File System Access Token Cache
200
+ const DEFAULT_FILE_ZOOM_ACCOUNTS_ACCESS_TOKEN_CACHE_SERVICE_PATH = '.tmp/zoom-access-tokens.json';
201
+ /**
202
+ * Creates a ZoomOAuthAccessTokenCacheService that reads and writes the access token to the file system.
203
+ *
204
+ * Useful for testing.
205
+ *
206
+ * @returns
207
+ */
208
+ function fileZoomOAuthAccessTokenCacheService(filename = DEFAULT_FILE_ZOOM_ACCOUNTS_ACCESS_TOKEN_CACHE_SERVICE_PATH, useMemoryCache = true) {
209
+ let loadedToken = null;
210
+ async function loadTokenFile() {
211
+ let token = undefined;
212
+ if (!loadedToken) {
213
+ token = (await readTokenFile()) ?? {};
214
+ } else {
215
+ token = loadedToken;
216
+ }
217
+ return token;
218
+ }
219
+ function readTokenFile() {
220
+ return new Promise(resolve => {
221
+ fs.mkdirSync(path.dirname(filename), {
222
+ recursive: true
223
+ }); // make the directory first
224
+ fs.readFile(filename, {}, (x, data) => {
225
+ let result = undefined;
226
+ if (!x) {
227
+ try {
228
+ result = JSON.parse(data.toString());
229
+ if (result?.token) {
230
+ result.token.expiresAt = new Date(result.token.expiresAt);
231
+ }
232
+ } catch (e) {
233
+ console.error('Failed reading token file: ', e);
234
+ }
235
+ }
236
+ resolve(result);
237
+ });
238
+ }).then(x => {
239
+ // update loaded tokens
240
+ if (useMemoryCache) {
241
+ loadedToken = {
242
+ ...loadedToken,
243
+ ...x
244
+ };
245
+ }
246
+ return x;
247
+ });
248
+ }
249
+ async function writeTokenFile(tokens) {
250
+ return new Promise((resolve, reject) => {
251
+ fs.writeFile(filename, JSON.stringify(tokens), {}, x => {
252
+ if (!x) {
253
+ resolve();
254
+ } else {
255
+ reject(x);
256
+ }
257
+ });
258
+ });
259
+ }
260
+ async function deleteTokenFile() {
261
+ return new Promise((resolve, reject) => {
262
+ fs.rm(filename, x => {
263
+ if (!x) {
264
+ resolve();
265
+ } else {
266
+ reject(x);
267
+ }
268
+ });
269
+ });
270
+ }
271
+ function loadZoomAccessTokenCache() {
272
+ const accessTokenCache = {
273
+ loadCachedToken: async function () {
274
+ const tokens = await loadTokenFile();
275
+ const token = tokens.token;
276
+ // console.log('retrieving access token from file: ', { token });
277
+ return token;
278
+ },
279
+ updateCachedToken: async function (accessToken) {
280
+ const tokenFile = await loadTokenFile();
281
+ if (tokenFile) {
282
+ tokenFile.token = accessToken;
283
+ }
284
+ // console.log('updating access token in file: ', { accessToken });
285
+ try {
286
+ await writeTokenFile(tokenFile);
287
+ } catch (e) {
288
+ console.error('Failed updating access token in file: ', e);
289
+ }
290
+ }
291
+ };
292
+ return accessTokenCache;
293
+ }
294
+ return {
295
+ loadZoomAccessTokenCache,
296
+ readTokenFile,
297
+ writeTokenFile,
298
+ deleteTokenFile
299
+ };
300
+ }
301
+
302
+ exports.ZoomOAuthApi = class ZoomOAuthApi {
303
+ config;
304
+ cacheService;
305
+ zoomOAuth;
306
+ get oauthContext() {
307
+ return this.zoomOAuth.oauthContext;
308
+ }
309
+ constructor(config, cacheService) {
310
+ this.config = config;
311
+ this.cacheService = cacheService;
312
+ const accessTokenCache = config.zoomOAuth.accessTokenCache ? config.zoomOAuth.accessTokenCache : cacheService.loadZoomAccessTokenCache();
313
+ this.zoomOAuth = zoom.zoomOAuthFactory(config.factoryConfig ?? {})({
314
+ accessTokenCache,
315
+ ...config.zoomOAuth
316
+ });
317
+ }
318
+ // MARK: Accessors
319
+ get serverAccessToken() {
320
+ return zoom.serverAccessToken(this.oauthContext);
321
+ }
322
+ get userAccessToken() {
323
+ return zoom.userAccessToken(this.oauthContext);
324
+ }
325
+ };
326
+ exports.ZoomOAuthApi = __decorate([common.Injectable(), __param(0, common.Inject(ZoomOAuthServiceConfig)), __param(1, common.Inject(exports.ZoomOAuthAccessTokenCacheService)), __metadata("design:paramtypes", [ZoomOAuthServiceConfig, exports.ZoomOAuthAccessTokenCacheService])], exports.ZoomOAuthApi);
327
+
328
+ function zoomOAuthServiceConfigFactory(configService) {
329
+ const config = readZoomOAuthServiceConfigFromConfigService(configService);
330
+ return config;
331
+ }
332
+ /**
333
+ * Convenience function used to generate ModuleMetadata for an app's ZoomOAuthModule.
334
+ *
335
+ * @param provide
336
+ * @param useFactory
337
+ * @returns
338
+ */
339
+ function appZoomOAuthModuleMetadata(config$1) {
340
+ const {
341
+ dependencyModule,
342
+ imports,
343
+ exports: exports$1,
344
+ providers
345
+ } = config$1;
346
+ const dependencyModuleImport = dependencyModule ? [dependencyModule] : [];
347
+ return {
348
+ imports: [config.ConfigModule, ...dependencyModuleImport, ...(imports ?? [])],
349
+ exports: [exports.ZoomOAuthApi, ...(exports$1 ?? [])],
350
+ providers: [{
351
+ provide: ZoomOAuthServiceConfig,
352
+ inject: [config.ConfigService],
353
+ useFactory: config$1.zoomOAuthServiceConfigFactory ?? zoomOAuthServiceConfigFactory
354
+ }, exports.ZoomOAuthApi, ...(providers ?? [])]
355
+ };
356
+ }
357
+
358
+ const ZOOM_SECRET_TOKEN_ENV_VAR = 'ZOOM_SECRET_TOKEN';
359
+ /**
360
+ * Configuration for ZoomService
361
+ */
362
+ class ZoomWebhookServiceConfig {
363
+ webhookConfig;
364
+ static assertValidConfig(config) {
365
+ if (!config.webhookConfig.zoomSecretToken) {
366
+ throw new Error('No zoom secret token specified.');
367
+ }
368
+ }
369
+ }
370
+
371
+ // MARK: Meeting Alert
372
+ const ZOOM_WEBHOOK_MEETING_ALERT_EVENT_TYPE = 'meeting.alert';
373
+ // MARK: Meeting Created
374
+ const ZOOM_WEBHOOK_MEETING_CREATED_EVENT_TYPE = 'meeting.created';
375
+ // MARK: Meeting Updated
376
+ const ZOOM_WEBHOOK_MEETING_UPDATED_EVENT_TYPE = 'meeting.updated';
377
+ // MARK: Meeting Deleted
378
+ const ZOOM_WEBHOOK_MEETING_DELETED_EVENT_TYPE = 'meeting.deleted';
379
+ // MARK: Meeting Started
380
+ const ZOOM_WEBHOOK_MEETING_STARTED_EVENT_TYPE = 'meeting.started';
381
+ // MARK: Meeting Ended
382
+ const ZOOM_WEBHOOK_MEETING_ENDED_EVENT_TYPE = 'meeting.ended';
383
+ // MARK: Meeting Permanently Deleted
384
+ const ZOOM_WEBHOOK_MEETING_PERMANENTLY_DELETED_EVENT_TYPE = 'meeting.permanently_deleted';
385
+
386
+ /**
387
+ * Creates a ZoomWebhookEvent and treats the data as the input type.
388
+ *
389
+ * @param event
390
+ * @returns
391
+ */
392
+ function zoomWebhookEvent(event) {
393
+ return {
394
+ event: event.event,
395
+ event_ts: event.event_ts,
396
+ payload: event.payload
397
+ };
398
+ }
399
+ const zoomEventHandlerFactory = util.handlerFactory(x => x.event);
400
+ const zoomEventHandlerConfigurerFactory = util.handlerConfigurerFactory({
401
+ configurerForAccessor: accessor => {
402
+ // eslint-disable-next-line
403
+ const fnWithKey = util.handlerMappedSetFunctionFactory(accessor, zoomWebhookEvent);
404
+ const configurer = {
405
+ ...accessor,
406
+ // Meetings
407
+ handleMeetingCreated: fnWithKey(ZOOM_WEBHOOK_MEETING_CREATED_EVENT_TYPE),
408
+ handleMeetingUpdated: fnWithKey(ZOOM_WEBHOOK_MEETING_UPDATED_EVENT_TYPE),
409
+ handleMeetingDeleted: fnWithKey(ZOOM_WEBHOOK_MEETING_DELETED_EVENT_TYPE),
410
+ handleMeetingStarted: fnWithKey(ZOOM_WEBHOOK_MEETING_STARTED_EVENT_TYPE),
411
+ handleMeetingEnded: fnWithKey(ZOOM_WEBHOOK_MEETING_ENDED_EVENT_TYPE),
412
+ handleMeetingPermanentlyDeleted: fnWithKey(ZOOM_WEBHOOK_MEETING_PERMANENTLY_DELETED_EVENT_TYPE)
413
+ };
414
+ return configurer;
415
+ }
416
+ });
417
+
418
+ /**
419
+ * Verifies a Zoom webhook event header.
420
+ *
421
+ * @see https://developers.zoom.us/docs/api/webhooks/#verify-with-zooms-header
422
+ *
423
+ * @param zoomSecretToken The Zoom secret token.
424
+ * @returns A function that verifies a Zoom webhook event.
425
+ */
426
+ function zoomWebhookEventVerifier(zoomSecretToken) {
427
+ return (request, rawBody) => {
428
+ const requestBodyString = String(request.body);
429
+ const message = `v0:${request.headers['x-zm-request-timestamp']}:${requestBodyString}`;
430
+ const hashForVerify = crypto.createHmac('sha256', zoomSecretToken).update(message).digest('hex');
431
+ const signature = `v0=${hashForVerify}`;
432
+ const valid = request.headers['x-zm-signature'] === signature;
433
+ const result = {
434
+ valid,
435
+ event: JSON.parse(requestBodyString)
436
+ };
437
+ return result;
438
+ };
439
+ }
440
+
441
+ const ZOOM_WEBHOOK_URL_VALIDATION_EVENT_TYPE = 'endpoint.url_validation';
442
+
443
+ /**
444
+ * Creates a ZoomWebhookEventValidationFunction.
445
+ *
446
+ * @param zoomSecretToken The secret token used to validate the event.
447
+ * @returns A ZoomWebhookEventValidationFunction.
448
+ */
449
+ function zoomWebhookEventValidationFunction(zoomSecretToken) {
450
+ return event => {
451
+ const {
452
+ plainToken
453
+ } = event.payload;
454
+ if (!plainToken) {
455
+ throw new Error(`The expected plaintoken value was not provided by the event's payload.`);
456
+ }
457
+ const encryptedToken = crypto.createHmac('sha256', zoomSecretToken).update(plainToken).digest('hex');
458
+ const result = {
459
+ plainToken,
460
+ encryptedToken
461
+ };
462
+ return result;
463
+ };
464
+ }
465
+
466
+ /**
467
+ * Service that makes system changes based on Zoom webhook events.
468
+ */
469
+ exports.ZoomWebhookService = class ZoomWebhookService {
470
+ logger = new common.Logger('ZoomWebhookService');
471
+ _verifier;
472
+ _validator;
473
+ handler = zoomEventHandlerFactory();
474
+ configure = zoomEventHandlerConfigurerFactory(this.handler);
475
+ constructor(config) {
476
+ this._verifier = zoomWebhookEventVerifier(config.webhookConfig.zoomSecretToken);
477
+ this._validator = zoomWebhookEventValidationFunction(config.webhookConfig.zoomSecretToken);
478
+ }
479
+ async updateForWebhook(req, rawBody) {
480
+ const {
481
+ valid,
482
+ event
483
+ } = this._verifier(req, rawBody);
484
+ let handled = false;
485
+ let validationEventResponse;
486
+ if (!valid) {
487
+ this.logger.warn('Received invalid zoom event: ', event);
488
+ } else if (event.event === ZOOM_WEBHOOK_URL_VALIDATION_EVENT_TYPE) {
489
+ validationEventResponse = this._validator(event);
490
+ handled = true;
491
+ } else {
492
+ handled = await this.updateForZoomEvent(event);
493
+ }
494
+ const result = {
495
+ valid,
496
+ handled,
497
+ event,
498
+ validationEventResponse
499
+ };
500
+ return result;
501
+ }
502
+ async updateForZoomEvent(event) {
503
+ const handled = await this.handler(event);
504
+ if (!handled) {
505
+ this.logger.warn('Received unexpected/unhandled zoom event: ', event);
506
+ }
507
+ return handled;
508
+ }
509
+ };
510
+ exports.ZoomWebhookService = __decorate([common.Injectable(), __param(0, common.Inject(ZoomWebhookServiceConfig)), __metadata("design:paramtypes", [ZoomWebhookServiceConfig])], exports.ZoomWebhookService);
511
+
512
+ exports.ZoomWebhookController = class ZoomWebhookController {
513
+ zoomWebhookService;
514
+ constructor(zoomWebhookService) {
515
+ this.zoomWebhookService = zoomWebhookService;
516
+ }
517
+ async handleZoomWebhook(res, req, rawBody) {
518
+ const {
519
+ valid,
520
+ validationEventResponse
521
+ } = await this.zoomWebhookService.updateForWebhook(req, rawBody);
522
+ const response = res.status(200); // always return a 200 status code
523
+ if (valid && validationEventResponse) {
524
+ response.json(validationEventResponse);
525
+ } else {
526
+ response.json({});
527
+ }
528
+ }
529
+ };
530
+ __decorate([common.Post(), __param(0, common.Res()), __param(1, common.Req()), __param(2, nestjs.RawBody()), __metadata("design:type", Function), __metadata("design:paramtypes", [Object, Object, Object]), __metadata("design:returntype", Promise)], exports.ZoomWebhookController.prototype, "handleZoomWebhook", null);
531
+ exports.ZoomWebhookController = __decorate([common.Controller('/webhook/zoom'), __param(0, common.Inject(exports.ZoomWebhookService)), __metadata("design:paramtypes", [exports.ZoomWebhookService])], exports.ZoomWebhookController);
532
+
533
+ function zoomWebhookServiceConfigFactory(configService) {
534
+ const config = {
535
+ webhookConfig: {
536
+ zoomSecretToken: configService.get(ZOOM_SECRET_TOKEN_ENV_VAR)
537
+ }
538
+ };
539
+ ZoomWebhookServiceConfig.assertValidConfig(config);
540
+ return config;
541
+ }
542
+ /**
543
+ * Configures webhooks for the service.
544
+ */
545
+ exports.ZoomWebhookModule = class ZoomWebhookModule {};
546
+ exports.ZoomWebhookModule = __decorate([common.Module({
547
+ imports: [config.ConfigModule],
548
+ controllers: [exports.ZoomWebhookController],
549
+ exports: [exports.ZoomWebhookService],
550
+ providers: [{
551
+ provide: ZoomWebhookServiceConfig,
552
+ inject: [config.ConfigService],
553
+ useFactory: zoomWebhookServiceConfigFactory
554
+ }, exports.ZoomWebhookService]
555
+ })], exports.ZoomWebhookModule);
556
+
557
+ /**
558
+ * Configuration for ZoomService
559
+ */
560
+ class ZoomServiceConfig {
561
+ zoom;
562
+ factoryConfig;
563
+ static assertValidConfig(config) {
564
+ // TODO?
565
+ }
566
+ }
567
+
568
+ exports.ZoomApi = class ZoomApi {
569
+ config;
570
+ zoomOAuthApi;
571
+ zoom;
572
+ get zoomContext() {
573
+ return this.zoom.zoomServerContext;
574
+ }
575
+ get zoomRateLimiter() {
576
+ return this.zoom.zoomServerContext.zoomRateLimiter;
577
+ }
578
+ constructor(config, zoomOAuthApi) {
579
+ this.config = config;
580
+ this.zoomOAuthApi = zoomOAuthApi;
581
+ this.zoom = zoom.zoomFactory({
582
+ ...config.factoryConfig,
583
+ oauthContext: zoomOAuthApi.oauthContext
584
+ })(config.zoom);
585
+ }
586
+ // MARK: Users
587
+ get getUser() {
588
+ return zoom.getUser(this.zoomContext);
589
+ }
590
+ get listUsers() {
591
+ return zoom.listUsers(this.zoomContext);
592
+ }
593
+ get listUsersPageFactory() {
594
+ return zoom.listUsersPageFactory(this.zoomContext);
595
+ }
596
+ // MARK: Meetings
597
+ get listMeetingsForUser() {
598
+ return zoom.listMeetingsForUser(this.zoomContext);
599
+ }
600
+ get listMeetingsForUserPageFactory() {
601
+ return zoom.listMeetingsForUserPageFactory(this.zoomContext);
602
+ }
603
+ get createMeetingForUser() {
604
+ return zoom.createMeetingForUser(this.zoomContext);
605
+ }
606
+ get getMeeting() {
607
+ return zoom.getMeeting(this.zoomContext);
608
+ }
609
+ get updateMeeting() {
610
+ return zoom.updateMeeting(this.zoomContext);
611
+ }
612
+ get deleteMeeting() {
613
+ return zoom.deleteMeeting(this.zoomContext);
614
+ }
615
+ // MARK: Past Meetings
616
+ get getPastMeeting() {
617
+ return zoom.getPastMeeting(this.zoomContext);
618
+ }
619
+ get getPastMeetingParticipants() {
620
+ return zoom.getPastMeetingParticipants(this.zoomContext);
621
+ }
622
+ };
623
+ exports.ZoomApi = __decorate([common.Injectable(), __param(0, common.Inject(ZoomServiceConfig)), __param(1, common.Inject(exports.ZoomOAuthApi)), __metadata("design:paramtypes", [ZoomServiceConfig, exports.ZoomOAuthApi])], exports.ZoomApi);
624
+ class ZoomApiUserContext {
625
+ constructor(refreshToken) {
626
+ // TODO: ...
627
+ }
628
+ }
629
+
630
+ // MARK: Provider Factories
631
+ function zoomServiceConfigFactory(configService) {
632
+ const config = {
633
+ zoom: {}
634
+ };
635
+ ZoomServiceConfig.assertValidConfig(config);
636
+ return config;
637
+ }
638
+ /**
639
+ * Convenience function used to generate ModuleMetadata for an app's ZoomModule.
640
+ *
641
+ * @param provide
642
+ * @param useFactory
643
+ * @returns
644
+ */
645
+ function appZoomModuleMetadata(config$1) {
646
+ const {
647
+ dependencyModule,
648
+ imports,
649
+ exports: exports$1,
650
+ providers
651
+ } = config$1;
652
+ const dependencyModuleImport = dependencyModule ? [dependencyModule] : [];
653
+ return {
654
+ imports: [config.ConfigModule, ...dependencyModuleImport, ...(imports ?? [])],
655
+ exports: [exports.ZoomApi, ...(exports$1 ?? [])],
656
+ providers: [{
657
+ provide: ZoomServiceConfig,
658
+ inject: [config.ConfigService],
659
+ useFactory: zoomServiceConfigFactory
660
+ }, exports.ZoomApi, ...(providers ?? [])]
661
+ };
662
+ }
663
+
664
+ exports.DEFAULT_FILE_ZOOM_ACCOUNTS_ACCESS_TOKEN_CACHE_SERVICE_PATH = DEFAULT_FILE_ZOOM_ACCOUNTS_ACCESS_TOKEN_CACHE_SERVICE_PATH;
665
+ exports.ZOOM_SECRET_TOKEN_ENV_VAR = ZOOM_SECRET_TOKEN_ENV_VAR;
666
+ exports.ZOOM_WEBHOOK_MEETING_ALERT_EVENT_TYPE = ZOOM_WEBHOOK_MEETING_ALERT_EVENT_TYPE;
667
+ exports.ZOOM_WEBHOOK_MEETING_CREATED_EVENT_TYPE = ZOOM_WEBHOOK_MEETING_CREATED_EVENT_TYPE;
668
+ exports.ZOOM_WEBHOOK_MEETING_DELETED_EVENT_TYPE = ZOOM_WEBHOOK_MEETING_DELETED_EVENT_TYPE;
669
+ exports.ZOOM_WEBHOOK_MEETING_ENDED_EVENT_TYPE = ZOOM_WEBHOOK_MEETING_ENDED_EVENT_TYPE;
670
+ exports.ZOOM_WEBHOOK_MEETING_PERMANENTLY_DELETED_EVENT_TYPE = ZOOM_WEBHOOK_MEETING_PERMANENTLY_DELETED_EVENT_TYPE;
671
+ exports.ZOOM_WEBHOOK_MEETING_STARTED_EVENT_TYPE = ZOOM_WEBHOOK_MEETING_STARTED_EVENT_TYPE;
672
+ exports.ZOOM_WEBHOOK_MEETING_UPDATED_EVENT_TYPE = ZOOM_WEBHOOK_MEETING_UPDATED_EVENT_TYPE;
673
+ exports.ZOOM_WEBHOOK_URL_VALIDATION_EVENT_TYPE = ZOOM_WEBHOOK_URL_VALIDATION_EVENT_TYPE;
674
+ exports.ZoomApiUserContext = ZoomApiUserContext;
675
+ exports.ZoomOAuthServiceConfig = ZoomOAuthServiceConfig;
676
+ exports.ZoomServiceConfig = ZoomServiceConfig;
677
+ exports.ZoomWebhookServiceConfig = ZoomWebhookServiceConfig;
678
+ exports.appZoomModuleMetadata = appZoomModuleMetadata;
679
+ exports.appZoomOAuthModuleMetadata = appZoomOAuthModuleMetadata;
680
+ exports.fileZoomOAuthAccessTokenCacheService = fileZoomOAuthAccessTokenCacheService;
681
+ exports.logMergeZoomOAuthAccessTokenCacheServiceErrorFunction = logMergeZoomOAuthAccessTokenCacheServiceErrorFunction;
682
+ exports.memoryZoomOAuthAccessTokenCacheService = memoryZoomOAuthAccessTokenCacheService;
683
+ exports.mergeZoomOAuthAccessTokenCacheServices = mergeZoomOAuthAccessTokenCacheServices;
684
+ exports.readZoomOAuthServiceConfigFromConfigService = readZoomOAuthServiceConfigFromConfigService;
685
+ exports.zoomEventHandlerConfigurerFactory = zoomEventHandlerConfigurerFactory;
686
+ exports.zoomEventHandlerFactory = zoomEventHandlerFactory;
687
+ exports.zoomOAuthServiceConfigFactory = zoomOAuthServiceConfigFactory;
688
+ exports.zoomServiceConfigFactory = zoomServiceConfigFactory;
689
+ exports.zoomWebhookEvent = zoomWebhookEvent;
690
+ exports.zoomWebhookEventValidationFunction = zoomWebhookEventValidationFunction;
691
+ exports.zoomWebhookEventVerifier = zoomWebhookEventVerifier;
692
+ exports.zoomWebhookServiceConfigFactory = zoomWebhookServiceConfigFactory;