diff --git a/packages/client-sdk-nodejs/package-lock.json b/packages/client-sdk-nodejs/package-lock.json index 418899658..7b4dc6c67 100644 --- a/packages/client-sdk-nodejs/package-lock.json +++ b/packages/client-sdk-nodejs/package-lock.json @@ -1994,9 +1994,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", - "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz", + "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==", "dev": true, "engines": { "node": ">=0.4.0" @@ -2828,9 +2828,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.604", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.604.tgz", - "integrity": "sha512-JAJ4lyLJYudlgJPYJicimU9R+qZ/3iyeyQS99bfT7PWi7psYWeN84lPswTjpHxQueU34PKxM/IJzQS6poYlovQ==", + "version": "1.4.605", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.605.tgz", + "integrity": "sha512-V52j+P5z6cdRqTjPR/bYNxx7ETCHIkm5VIGuyCy3CMrfSnbEpIlLnk5oHmZo7gYvDfh2TfHeanB6rawyQ23ktg==", "dev": true }, "node_modules/emittery": { diff --git a/packages/client-sdk-nodejs/src/internal/webhook-client.ts b/packages/client-sdk-nodejs/src/internal/webhook-client.ts index 5e38aca64..a0b38f825 100644 --- a/packages/client-sdk-nodejs/src/internal/webhook-client.ts +++ b/packages/client-sdk-nodejs/src/internal/webhook-client.ts @@ -11,6 +11,7 @@ import { ListWebhooks, PostUrlWebhookDestination, GetWebhookSecret, + RotateWebhookSecret, } from '@gomomento/sdk-core'; import {ChannelCredentials, Interceptor} from '@grpc/grpc-js'; import {IWebhookClient} from '@gomomento/sdk-core/dist/src/internal/clients/pubsub/IWebhookClient'; @@ -190,4 +191,46 @@ export class WebhookClient implements IWebhookClient { ); }); } + + async rotateWebhookSecret( + id: WebhookId + ): Promise { + try { + validateCacheName(id.cacheName); + validateWebhookName(id.webhookName); + } catch (err) { + return new RotateWebhookSecret.Error(normalizeSdkError(err as Error)); + } + + const webhookId = grpcWebhook._WebhookId.fromObject({ + webhook_name: id.webhookName, + cache_name: id.cacheName, + }); + const request = new grpcWebhook._RotateWebhookSecretRequest({ + webhook_id: webhookId, + }); + this.logger.debug('issuing "RotateWebhookSecret" request'); + + return await new Promise(resolve => { + this.webhookClient.RotateWebhookSecret( + request, + {interceptors: this.unaryInterceptors}, + (err, resp) => { + if (err || !resp) { + resolve( + new RotateWebhookSecret.Error(cacheServiceErrorMapper(err)) + ); + } else { + resolve( + new RotateWebhookSecret.Success({ + secret: resp.secret_string, + webhookName: id.webhookName, + cacheName: id.cacheName, + }) + ); + } + } + ); + }); + } } diff --git a/packages/client-sdk-web/package-lock.json b/packages/client-sdk-web/package-lock.json index 34e025561..089009d0b 100644 --- a/packages/client-sdk-web/package-lock.json +++ b/packages/client-sdk-web/package-lock.json @@ -138,30 +138,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz", - "integrity": "sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz", + "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.3.tgz", - "integrity": "sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.5.tgz", + "integrity": "sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.3", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.5", "@babel/helper-compilation-targets": "^7.22.15", "@babel/helper-module-transforms": "^7.23.3", - "@babel/helpers": "^7.23.2", - "@babel/parser": "^7.23.3", + "@babel/helpers": "^7.23.5", + "@babel/parser": "^7.23.5", "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.3", - "@babel/types": "^7.23.3", + "@babel/traverse": "^7.23.5", + "@babel/types": "^7.23.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -177,12 +177,12 @@ } }, "node_modules/@babel/core/node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -270,12 +270,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.3.tgz", - "integrity": "sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.5.tgz", + "integrity": "sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==", "dev": true, "dependencies": { - "@babel/types": "^7.23.3", + "@babel/types": "^7.23.5", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -408,9 +408,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz", + "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -426,32 +426,32 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz", + "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", - "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.5.tgz", + "integrity": "sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==", "dev": true, "dependencies": { "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.23.5", + "@babel/types": "^7.23.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", - "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", + "version": "7.23.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz", + "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==", "dev": true, "dependencies": { "@babel/helper-validator-identifier": "^7.22.20", @@ -534,9 +534,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.3.tgz", - "integrity": "sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.5.tgz", + "integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -737,12 +737,12 @@ } }, "node_modules/@babel/template/node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -821,19 +821,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.3.tgz", - "integrity": "sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.5.tgz", + "integrity": "sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.3", + "@babel/code-frame": "^7.23.5", + "@babel/generator": "^7.23.5", "@babel/helper-environment-visitor": "^7.22.20", "@babel/helper-function-name": "^7.23.0", "@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.3", - "@babel/types": "^7.23.3", + "@babel/parser": "^7.23.5", + "@babel/types": "^7.23.5", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -842,12 +842,12 @@ } }, "node_modules/@babel/traverse/node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -935,12 +935,12 @@ } }, "node_modules/@babel/types": { - "version": "7.23.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.3.tgz", - "integrity": "sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.5.tgz", + "integrity": "sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-string-parser": "^7.23.4", "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, @@ -1565,9 +1565,9 @@ "dev": true }, "node_modules/@types/babel__core": { - "version": "7.20.4", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.4.tgz", - "integrity": "sha512-mLnSC22IC4vcWiuObSRjrLd9XcBTGf59vUSoq2jkQDJ/QQ8PMI9rSuzE+aEV8karUMbskw07bKYoUJCKTUaygg==", + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", "dev": true, "dependencies": { "@babel/parser": "^7.20.7", @@ -1684,9 +1684,9 @@ "dev": true }, "node_modules/@types/semver": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.5.tgz", - "integrity": "sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==", + "version": "7.5.6", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.6.tgz", + "integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==", "dev": true }, "node_modules/@types/stack-utils": { @@ -1708,9 +1708,9 @@ "dev": true }, "node_modules/@types/yargs": { - "version": "17.0.31", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.31.tgz", - "integrity": "sha512-bocYSx4DI8TmdlvxqGpVNXOgCNR1Jj0gNPhhAY+iz1rgKDAaYrAYdFYnhDV1IFuiuVc9HkOwyDcFxaTElF3/wg==", + "version": "17.0.32", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.32.tgz", + "integrity": "sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -1914,6 +1914,7 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.6.tgz", "integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==", + "deprecated": "Use your platform's native atob() and btoa() methods instead", "dev": true }, "node_modules/acorn": { @@ -1960,9 +1961,9 @@ } }, "node_modules/acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", - "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz", + "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==", "dev": true, "engines": { "node": ">=0.4.0" @@ -2373,9 +2374,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", + "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", "dev": true, "funding": [ { @@ -2392,9 +2393,9 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", + "caniuse-lite": "^1.0.30001565", + "electron-to-chromium": "^1.4.601", + "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, "bin": { @@ -2464,9 +2465,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001563", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001563.tgz", - "integrity": "sha512-na2WUmOxnwIZtwnFI2CZ/3er0wdNzU7hN+cPYz/z2ajHThnkWjNBOpEPP4n+4r2WPM847JaMotaJE3bnfzjyKw==", + "version": "1.0.30001566", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz", + "integrity": "sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==", "dev": true, "funding": [ { @@ -2833,6 +2834,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz", "integrity": "sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==", + "deprecated": "Use your platform's native DOMException instead", "dev": true, "dependencies": { "webidl-conversions": "^7.0.0" @@ -2842,9 +2844,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.588", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.588.tgz", - "integrity": "sha512-soytjxwbgcCu7nh5Pf4S2/4wa6UIu+A3p03U2yVr53qGxi1/VTR3ENI+p50v+UxqqZAfl48j3z55ud7VHIOr9w==", + "version": "1.4.605", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.605.tgz", + "integrity": "sha512-V52j+P5z6cdRqTjPR/bYNxx7ETCHIkm5VIGuyCy3CMrfSnbEpIlLnk5oHmZo7gYvDfh2TfHeanB6rawyQ23ktg==", "dev": true }, "node_modules/emittery": { @@ -5073,12 +5075,12 @@ } }, "node_modules/jest-message-util/node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.23.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz", + "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==", "dev": true, "dependencies": { - "@babel/highlight": "^7.22.13", + "@babel/highlight": "^7.23.4", "chalk": "^2.4.2" }, "engines": { @@ -5879,9 +5881,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "dev": true }, "node_modules/normalize-path": { @@ -5930,13 +5932,13 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -7361,9 +7363,9 @@ "dev": true }, "node_modules/v8-to-istanbul": { - "version": "9.1.3", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.3.tgz", - "integrity": "sha512-9lDD+EVI2fjFsMWXc6dy5JJzBsVTcQ2fVkfBvncZ6xJWG9wtBhOldG+mHkSL0+V1K/xgZz0JDO5UT5hFwHUghg==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz", + "integrity": "sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", diff --git a/packages/client-sdk-web/src/internal/webhook-client.ts b/packages/client-sdk-web/src/internal/webhook-client.ts index 7d39205be..0c2e389f6 100644 --- a/packages/client-sdk-web/src/internal/webhook-client.ts +++ b/packages/client-sdk-web/src/internal/webhook-client.ts @@ -11,6 +11,7 @@ import { PostUrlWebhookDestination, WebhookDestinationType, GetWebhookSecret, + RotateWebhookSecret, } from '@gomomento/sdk-core'; import {IWebhookClient} from '@gomomento/sdk-core/dist/src/internal/clients/pubsub/IWebhookClient'; import {cacheServiceErrorMapper} from '../errors/cache-service-error-mapper'; @@ -31,6 +32,7 @@ import { _Webhook, _WebhookDestination, _WebhookId, + _RotateWebhookSecretRequest, } from '@gomomento/generated-types-webtext/dist/webhook_pb'; export class WebhookClient implements IWebhookClient { @@ -207,4 +209,44 @@ export class WebhookClient implements IWebhookClient { ); }); } + + async rotateWebhookSecret( + id: WebhookId + ): Promise { + try { + validateCacheName(id.cacheName); + validateWebhookName(id.webhookName); + } catch (err) { + return new RotateWebhookSecret.Error(normalizeSdkError(err as Error)); + } + + const request = new _RotateWebhookSecretRequest(); + const webhookId = new _WebhookId(); + webhookId.setWebhookName(id.webhookName); + webhookId.setCacheName(id.cacheName); + request.setWebhookId(webhookId); + this.logger.debug('issuing "RotateWebhookSecret" request'); + + return await new Promise(resolve => { + this.webhookClient.rotateWebhookSecret( + request, + this.clientMetadataProvider.createClientMetadata(), + (err, resp) => { + if (err || !resp) { + resolve( + new RotateWebhookSecret.Error(cacheServiceErrorMapper(err)) + ); + } else { + resolve( + new RotateWebhookSecret.Success({ + secret: resp.getSecretString(), + webhookName: id.webhookName, + cacheName: id.cacheName, + }) + ); + } + } + ); + }); + } } diff --git a/packages/common-integration-tests/package-lock.json b/packages/common-integration-tests/package-lock.json index e3ef83045..07eb34a90 100644 --- a/packages/common-integration-tests/package-lock.json +++ b/packages/common-integration-tests/package-lock.json @@ -36,6 +36,7 @@ } }, "../core": { + "name": "@gomomento/sdk-core", "version": "0.0.1", "license": "Apache-2.0", "dependencies": { diff --git a/packages/common-integration-tests/src/webhooks.ts b/packages/common-integration-tests/src/webhooks.ts index 08a4a2628..52169b9c4 100644 --- a/packages/common-integration-tests/src/webhooks.ts +++ b/packages/common-integration-tests/src/webhooks.ts @@ -3,6 +3,7 @@ import { ListWebhooks, GetWebhookSecret, TopicPublish, + RotateWebhookSecret, } from '@gomomento/sdk-core'; import { getWebhookRequestDetails, @@ -66,7 +67,7 @@ export function runWebhookTests( }); }); - describe('put list delete getWebhookSecret', () => { + describe('put list delete getWebhookSecret rotateWebhookSecret', () => { it('should create a new webhook, list it, and then delete it', async () => { const webhook = testWebhook(integrationTestCacheName); await WithWebhook(topicClient, webhook, async () => { @@ -132,5 +133,35 @@ export function runWebhookTests( expect(detes.invocationCount).toBe(1); }); }); + it('should rotate a webhook secret', async () => { + const webhook = testWebhook(integrationTestCacheName); + await WithWebhook(topicClient, webhook, async () => { + const getSecretResp = await topicClient.getWebhookSecret( + webhook.id.cacheName, + webhook.id.webhookName + ); + if (!(getSecretResp instanceof GetWebhookSecret.Success)) { + throw new Error( + `unknown error occured when making a 'getWebhookSecret' request: ${getSecretResp.toString()}` + ); + } + expect(getSecretResp.secret()).toBeTruthy(); + const rotateResp = await topicClient.rotateWebhookSecret( + webhook.id.cacheName, + webhook.id.webhookName + ); + if (!(rotateResp instanceof RotateWebhookSecret.Success)) { + throw new Error( + `unknown error occured when making a 'rotateWebhookSecret' request: ${rotateResp.toString()}` + ); + } + expect(rotateResp.secret()).toBeTruthy(); + expect(rotateResp.webhookName()).toEqual(getSecretResp.webhookName()); + expect(rotateResp.cacheName()).toEqual(getSecretResp.cacheName()); + + // make sure the secrets are in fact different + expect(rotateResp.secret() === getSecretResp.secret()).toBeFalsy(); + }); + }); }); } diff --git a/packages/core/src/clients/ITopicClient.ts b/packages/core/src/clients/ITopicClient.ts index 5e7427675..43deb773b 100644 --- a/packages/core/src/clients/ITopicClient.ts +++ b/packages/core/src/clients/ITopicClient.ts @@ -6,6 +6,7 @@ import { PutWebhook, DeleteWebhook, GetWebhookSecret, + RotateWebhookSecret, } from '../index'; import {PutWebhookCallOptions} from '../utils/webhook-call-options'; @@ -36,4 +37,8 @@ export interface ITopicClient { cacheName: string, webhookName: string ): Promise; + rotateWebhookSecret( + cacheName: string, + webhookName: string + ): Promise; } diff --git a/packages/core/src/internal/clients/pubsub/AbstractTopicClient.ts b/packages/core/src/internal/clients/pubsub/AbstractTopicClient.ts index 6d2a593d4..4d4e8f231 100644 --- a/packages/core/src/internal/clients/pubsub/AbstractTopicClient.ts +++ b/packages/core/src/internal/clients/pubsub/AbstractTopicClient.ts @@ -9,6 +9,7 @@ import { DeleteWebhook, GetWebhookSecret, PostUrlWebhookDestination, + RotateWebhookSecret, } from '../../../index'; import {IPubsubClient} from './IPubsubClient'; import {IWebhookClient} from './IWebhookClient'; @@ -131,4 +132,23 @@ export abstract class AbstractTopicClient implements ITopicClient { ): Promise { return await this.webhookClient.getWebhookSecret({cacheName, webhookName}); } + + /** + * Rotates the signing secret for a webhook + * + * @param {string} cacheName - The name of the cache associated with the webhook + * @param {string} webhookName - The name of the webhook + * @returns {Promise} - + * {@link RotateWebhookSecret.Success} on success. + * {@link RotateWebhookSecret.Error} on failure. + */ + public async rotateWebhookSecret( + cacheName: string, + webhookName: string + ): Promise { + return await this.webhookClient.rotateWebhookSecret({ + cacheName, + webhookName, + }); + } } diff --git a/packages/core/src/internal/clients/pubsub/IWebhookClient.ts b/packages/core/src/internal/clients/pubsub/IWebhookClient.ts index 030b4be79..12ca8dc5f 100644 --- a/packages/core/src/internal/clients/pubsub/IWebhookClient.ts +++ b/packages/core/src/internal/clients/pubsub/IWebhookClient.ts @@ -5,6 +5,7 @@ import { Webhook, WebhookId, GetWebhookSecret, + RotateWebhookSecret, } from '../../../index'; export interface IWebhookClient { @@ -12,4 +13,5 @@ export interface IWebhookClient { putWebhook(webhook: Webhook): Promise; deleteWebhook(id: WebhookId): Promise; getWebhookSecret(id: WebhookId): Promise; + rotateWebhookSecret(id: WebhookId): Promise; } diff --git a/packages/core/src/messages/responses/webhook/index.ts b/packages/core/src/messages/responses/webhook/index.ts index c00e2963a..9c1bdf68c 100644 --- a/packages/core/src/messages/responses/webhook/index.ts +++ b/packages/core/src/messages/responses/webhook/index.ts @@ -2,3 +2,4 @@ export * as DeleteWebhook from './delete-webhook'; export * as ListWebhooks from './list-webhooks'; export * as PutWebhook from './put-webhook'; export * as GetWebhookSecret from './get-webhook-secret'; +export * as RotateWebhookSecret from './rotate-webhook-secret'; diff --git a/packages/core/src/messages/responses/webhook/rotate-webhook-secret.ts b/packages/core/src/messages/responses/webhook/rotate-webhook-secret.ts new file mode 100644 index 000000000..65ceee64b --- /dev/null +++ b/packages/core/src/messages/responses/webhook/rotate-webhook-secret.ts @@ -0,0 +1,76 @@ +import {SdkError} from '../../../errors'; +import {ResponseBase, ResponseError, ResponseSuccess} from '../response-base'; + +/** + * Parent response type for a RotateWebhookSecret request. The + * response object is resolved to a type-safe object of one of + * the following subtypes: + * + * - {Success} + * - {Error} + * + * `instanceof` type guards can be used to operate on the appropriate subtype. + * @example + * For example: + * ``` + * if (response instanceof RotateWebhookSecret.Error) { + * // Handle error as appropriate. The compiler will smart-cast `response` to type + * // `RotateWebhookSecret.Error` in this block, so you will have access to the properties + * // of the Error class; e.g. `response.errorCode()`. + * } + * ``` + */ +export abstract class Response extends ResponseBase {} + +type Props = { + secret: string; + cacheName: string; + webhookName: string; +}; + +class _Success extends Response { + private readonly _secret: string; + private readonly _webhookName: string; + private readonly _cacheName: string; + constructor(props: Props) { + super(); + this._secret = props.secret; + this._cacheName = props.cacheName; + this._webhookName = props.webhookName; + } + + secret(): string { + return this._secret; + } + + webhookName(): string { + return this._webhookName; + } + + cacheName(): string { + return this._cacheName; + } +} + +/** + * Indicates a Successful RotateWebhookSecret request. + */ +export class Success extends ResponseSuccess(_Success) {} + +class _Error extends Response { + constructor(protected _innerException: SdkError) { + super(); + } +} + +/** + * Indicates that an error occurred during the RotateWebhookSecret request. + * + * This response object includes the following fields that you can use to determine + * how you would like to handle the error: + * + * - `errorCode()` - a unique Momento error code indicating the type of error that occurred. + * - `message()` - a human-readable description of the error + * - `innerException()` - the original error that caused the failure; can be re-thrown. + */ +export class Error extends ResponseError(_Error) {}