From df5f753c82d96828e7891618d4470d41df4a2f0c Mon Sep 17 00:00:00 2001 From: Michael Tims Date: Fri, 21 Jun 2024 09:04:17 -0400 Subject: [PATCH] Provide add-in config to allow for additional host origins (#59) Co-authored-by: BLACKBAUD\Michael.Tims --- .gitignore | 3 + CHANGELOG.md | 3 + angular.json | 3 +- package-lock.json | 53 +++++----------- package.json | 2 +- projects/addin-client/README.md | 30 +++++++++ projects/addin-client/package.json | 4 +- projects/addin-client/src/public-api.ts | 1 + .../src/src/addin-client-config.service.ts | 14 +++++ .../src/src/addin-client.service.spec.ts | 61 +++++++++++++++++++ .../src/src/addin-client.service.ts | 5 +- 11 files changed, 137 insertions(+), 42 deletions(-) create mode 100644 projects/addin-client/src/src/addin-client-config.service.ts diff --git a/.gitignore b/.gitignore index f7eb89c..d9449d1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# Ignore cache directory used by @angular-eslint/builder +/.nx/cache + # See http://help.github.com/ignore-files/ for more about ignoring files. # compiled output diff --git a/CHANGELOG.md b/CHANGELOG.md index f42da58..74dec58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# 9.2.0 (2024-06-20) +- Added `AddinClientConfigService` abstract service to allow additional host origins to be supplied for the `AddinClientService`. + # 9.1.1 (2024-04-26) - Pulling in SKY UX and sky-addin-client package updates. diff --git a/angular.json b/angular.json index 9086407..bfdccf5 100644 --- a/angular.json +++ b/angular.json @@ -32,7 +32,8 @@ "karmaConfig": "projects/addin-client/karma.conf.js", "codeCoverage": true, "codeCoverageExclude": [ - "**/fixtures/**" + "**/fixtures/**", + "**/addin-client-config.service.ts" ], "styles": [ "node_modules/@skyux/theme/css/sky.css", diff --git a/package-lock.json b/package-lock.json index 26274e6..d826867 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "@angular/platform-browser": "17.3.6", "@angular/platform-browser-dynamic": "17.3.6", "@angular/router": "17.3.6", - "@blackbaud/sky-addin-client": "1.2.2", + "@blackbaud/sky-addin-client": "1.3.0", "@skyux/assets": "10.7.0", "@skyux/config": "10.7.0", "@skyux/core": "10.7.0", @@ -2394,9 +2394,9 @@ } }, "node_modules/@blackbaud/sky-addin-client": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@blackbaud/sky-addin-client/-/sky-addin-client-1.2.2.tgz", - "integrity": "sha512-WeAaEbU+3g9MpLjrP+gc3JVHbvpod5dApJQSz/q/ZgcxtXKPt8jFisDhvQcXxUBVbFNfo4JaYzRbedaNi1gq0Q==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@blackbaud/sky-addin-client/-/sky-addin-client-1.3.0.tgz", + "integrity": "sha512-q3Pok6D/VPPHKleP9UT+KxXp92nJJHRgnSw3pOjJPbKxqZ0u9bMPNZQ1pWco8tajyhr1Ng2ueedPQPEWcNrWew==" }, "node_modules/@blackbaud/skyux-design-tokens": { "version": "0.0.28", @@ -7126,9 +7126,9 @@ } }, "node_modules/engine.io": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.4.tgz", - "integrity": "sha512-KdVSDKhVKyOi+r5uEabrDLZw2qXStVvCsEB/LN3mw4WFi6Gx50jTyuxYVCwAAC0U46FdnzP/ScKRBTXb/NiEOg==", + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.5.5.tgz", + "integrity": "sha512-C5Pn8Wk+1vKBoHghJODM63yk8MvrO9EWZUfkAt5HAqIgPE4/8FF0PEGHXtEd40l223+cE5ABWuPzm38PHFXfMA==", "dev": true, "dependencies": { "@types/cookie": "^0.4.1", @@ -7140,7 +7140,7 @@ "cors": "~2.8.5", "debug": "~4.3.1", "engine.io-parser": "~5.2.1", - "ws": "~8.11.0" + "ws": "~8.17.1" }, "engines": { "node": ">=10.2.0" @@ -13204,13 +13204,13 @@ } }, "node_modules/socket.io-adapter": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.4.tgz", - "integrity": "sha512-wDNHGXGewWAjQPt3pyeYBtpWSq9cLE5UW1ZUPL/2eGK9jtse/FpXib7epSTsz0Q0m+6sg6Y4KtcFTlah1bdOVg==", + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz", + "integrity": "sha512-eLDQas5dzPgOWCk9GuuJC2lBqItuhKI4uxGgo9aIV7MYbk2h9Q6uULEh8WBzThoI7l+qU9Ast9fVUmkqPP9wYg==", "dev": true, "dependencies": { "debug": "~4.3.4", - "ws": "~8.11.0" + "ws": "~8.17.1" } }, "node_modules/socket.io-parser": { @@ -14941,27 +14941,6 @@ "webpack": "^4.0.0 || ^5.0.0" } }, - "node_modules/webpack-dev-server/node_modules/ws": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz", - "integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/webpack-merge": { "version": "5.10.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", @@ -15232,16 +15211,16 @@ "dev": true }, "node_modules/ws": { - "version": "8.11.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", - "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", "dev": true, "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { diff --git a/package.json b/package.json index 3973b5e..b69e989 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "@angular/platform-browser": "17.3.6", "@angular/platform-browser-dynamic": "17.3.6", "@angular/router": "17.3.6", - "@blackbaud/sky-addin-client": "1.2.2", + "@blackbaud/sky-addin-client": "1.3.0", "@skyux/assets": "10.7.0", "@skyux/config": "10.7.0", "@skyux/core": "10.7.0", diff --git a/projects/addin-client/README.md b/projects/addin-client/README.md index 21e9c78..4ef0976 100644 --- a/projects/addin-client/README.md +++ b/projects/addin-client/README.md @@ -252,4 +252,34 @@ this.addinClientService.showWait(); this.addinClientService.hideWait(); ``` +## Additional configuration + +The SKY UX Add-in Client allows for additional configuration to be specified by extending `AddinClientConfigService`. + +You can allow additional origins where your add-in client may run within a Blackbaud host page. Additional origins are supplied as regular expression patterns. The `AddinClientService` already allows several Blackbaud host origins by default. If you find a need to extend the defaults, you may do so by overriding the `AddinClientConfigService`'s `getAddinClientConfig()` method. + +```js +class AddinConfigService extends AddinClientConfigService { + public override getAddinClientConfig(): AddinClientConfig { + return { + allowedOrigins: [ + /^https\:\/\/[\w\-\.]+\.additionalblackbauddomain\.com$/ + ] + }; + } +} + +@NgModule({ + // specify providers + providers: [ + AddinClientService, + { + provide: AddinClientConfigService, + useClass: AddinConfigService + } + ] +}) +export class MyModule { } +``` + For more information on creating SKY Add-ins, view the documentation on the [SKY Developer Portal](https://developer.blackbaud.com/skyapi/docs/addins) diff --git a/projects/addin-client/package.json b/projects/addin-client/package.json index 3a4db6b..cbfc50d 100644 --- a/projects/addin-client/package.json +++ b/projects/addin-client/package.json @@ -1,6 +1,6 @@ { "name": "@blackbaud/skyux-lib-addin-client", - "version": "9.1.1", + "version": "9.2.0", "peerDependencies": { "@angular/common": "^17.3.6", "@angular/core": "^17.3.6", @@ -8,7 +8,7 @@ "@skyux/theme": "^10.7.0" }, "dependencies": { - "@blackbaud/sky-addin-client": "^1.2.2", + "@blackbaud/sky-addin-client": "^1.3.0", "tslib": "^2.6.2" } } diff --git a/projects/addin-client/src/public-api.ts b/projects/addin-client/src/public-api.ts index fd1a642..c301568 100644 --- a/projects/addin-client/src/public-api.ts +++ b/projects/addin-client/src/public-api.ts @@ -1,3 +1,4 @@ export * from './src/addin-client.service'; +export * from './src/addin-client-config.service'; export * from './src/events/addin-event'; export * from './src/events/addin-event-handler-instance'; diff --git a/projects/addin-client/src/src/addin-client-config.service.ts b/projects/addin-client/src/src/addin-client-config.service.ts new file mode 100644 index 0000000..1dca8f8 --- /dev/null +++ b/projects/addin-client/src/src/addin-client-config.service.ts @@ -0,0 +1,14 @@ +import { AddinClientConfig } from "@blackbaud/sky-addin-client"; + +/** + * Implement this class with your own data to initialize the add-in client service. + */ +export abstract class AddinClientConfigService { + /** + * Gets the AddinClientConfig object that will be injected the + * AddinClient instance when instantiated. + */ + public getAddinClientConfig(): AddinClientConfig { + return {}; + } +} diff --git a/projects/addin-client/src/src/addin-client.service.spec.ts b/projects/addin-client/src/src/addin-client.service.spec.ts index 34ecad7..3008b77 100644 --- a/projects/addin-client/src/src/addin-client.service.spec.ts +++ b/projects/addin-client/src/src/addin-client.service.spec.ts @@ -3,6 +3,7 @@ import { } from '@angular/core/testing'; import { AddinClientCloseModalArgs, + AddinClientConfig, AddinClientInitArgs, AddinClientNavigateArgs, AddinClientOpenHelpArgs, @@ -23,6 +24,7 @@ import { } from '@skyux-sdk/testing'; import { SkyAppConfig } from '@skyux/config'; import { SkyTheme, SkyThemeMode, SkyThemeService, SkyThemeSettings } from '@skyux/theme'; +import { AddinClientConfigService } from './addin-client-config.service'; import { AddinClientService } from './addin-client.service'; @@ -755,4 +757,63 @@ describe('Addin Client Service', () => { done(); }); }); + + describe('With Addin Client Config Service', () => { + class AddinConfigService extends AddinClientConfigService { + public override getAddinClientConfig(): AddinClientConfig { + return { + allowedOrigins: [ + /^https\:\/\/[\w\-\.]+\.additionaldomain1\.com$/, + /^https\:\/\/[\w\-\.]+\.additionaldomain2\.com$/, + /^https\:\/\/[\w\-\.]+\.additionaldomain3\.com$/ + ] + }; + } + } + + let addinClientService: AddinClientService; + let addinConfigService: AddinClientConfigService; + + class MockSkyAppConfig { + public get skyux(): any { + return {}; + } + }; + + beforeEach(() => { + TestBed.configureTestingModule( + { + providers: [ + AddinClientService, + SkyThemeService, + { + provide: SkyAppConfig, useClass: MockSkyAppConfig + }, + { + provide: AddinClientConfigService, useClass: AddinConfigService + } + ] + } + ); + + addinConfigService = TestBed.inject(AddinClientConfigService); + spyOn(addinConfigService, 'getAddinClientConfig').and.callThrough(); + + addinClientService = TestBed.inject(AddinClientService); + }); + + it('should override getAddinClientConfig function', () => { + expect(addinConfigService.getAddinClientConfig).toHaveBeenCalledTimes(1); + }); + + it('destroys the addin client', (done) => { + spyOn(addinClientService.addinClient, 'destroy').and.stub(); + + addinClientService.destroy(); + + expect(addinClientService.addinClient.destroy).toHaveBeenCalled(); + + done(); + }); + }); }); diff --git a/projects/addin-client/src/src/addin-client.service.ts b/projects/addin-client/src/src/addin-client.service.ts index 3569920..378ff3f 100644 --- a/projects/addin-client/src/src/addin-client.service.ts +++ b/projects/addin-client/src/src/addin-client.service.ts @@ -35,6 +35,7 @@ import { Observable, from } from 'rxjs'; +import { AddinClientConfigService } from './addin-client-config.service'; import { AddinEvent, AddinEventHandlerInstance @@ -84,6 +85,7 @@ export class AddinClientService { #config = inject(SkyAppConfig, { optional: true }); #rendererFactory = inject(RendererFactory2); #themeService = inject(SkyThemeService); + #addinClientConfigService = inject(AddinClientConfigService, { optional: true }); constructor() { this.addinClient = new AddinClient({ @@ -115,7 +117,8 @@ export class AddinClientService { themeChange: (settings: AddinClientThemeSettings) => { this.setTheme(settings); } - } + }, + config: this.#addinClientConfigService?.getAddinClientConfig() }); }