diff --git a/changelog/17769.txt b/changelog/17769.txt
new file mode 100644
index 000000000..12fe2d4d1
--- /dev/null
+++ b/changelog/17769.txt
@@ -0,0 +1,3 @@
+```release-note:bug
+ui: Fixes issue with not being able to download raft snapshot via service worker
+```
\ No newline at end of file
diff --git a/ui/app/components/raft-storage-overview.js b/ui/app/components/raft-storage-overview.js
index 794f99b1a..b77028e67 100644
--- a/ui/app/components/raft-storage-overview.js
+++ b/ui/app/components/raft-storage-overview.js
@@ -5,6 +5,8 @@ import { inject as service } from '@ember/service';
export default Component.extend({
flashMessages: service(),
+ auth: service(),
+
useServiceWorker: null,
async init() {
@@ -16,12 +18,32 @@ export default Component.extend({
if ('serviceWorker' in navigator) {
// this checks to see if there's an active service worker - if it failed to register
// for any reason, then this would be null
- let worker = await navigator.serviceWorker.getRegistration(config.serviceWorkerScope);
+ const worker = await navigator.serviceWorker.getRegistration(config.serviceWorkerScope);
if (worker) {
+ navigator.serviceWorker.addEventListener('message', this.serviceWorkerGetToken.bind(this));
+
this.set('useServiceWorker', true);
}
}
},
+ willDestroy() {
+ if (this.useServiceWorker) {
+ navigator.serviceWorker.removeEventListener('message', this.serviceWorkerGetToken);
+ }
+ this._super(...arguments);
+ },
+
+ serviceWorkerGetToken(event) {
+ const { action } = event.data;
+ const [port] = event.ports;
+
+ if (action === 'getToken') {
+ port.postMessage({ token: this.auth.currentToken });
+ } else {
+ console.error('Unknown event', event); // eslint-disable-line
+ port.postMessage({ error: 'Unknown request' });
+ }
+ },
actions: {
async removePeer(model) {
diff --git a/ui/lib/service-worker-authenticated-download/service-worker-registration/index.js b/ui/lib/service-worker-authenticated-download/service-worker-registration/index.js
index 525317e81..6236505e0 100644
--- a/ui/lib/service-worker-authenticated-download/service-worker-registration/index.js
+++ b/ui/lib/service-worker-authenticated-download/service-worker-registration/index.js
@@ -1,32 +1,6 @@
import { addSuccessHandler } from 'ember-service-worker/service-worker-registration';
-import Namespace from '@ember/application/namespace';
-
-function getToken() {
- // fix this later by allowing registration somewhere in the app lifecycle were we can have access to
- // services, etc.
- return Namespace.NAMESPACES_BY_ID['vault'].__container__.lookup('service:auth').currentToken;
-}
addSuccessHandler(function (registration) {
- // attach the handler for the message event so we can send over the auth token
- navigator.serviceWorker.addEventListener('message', (event) => {
- let { action } = event.data;
- let port = event.ports[0];
-
- if (action === 'getToken') {
- let token = getToken();
- if (!token) {
- console.error('Unable to retrieve Vault tokent'); // eslint-disable-line
- }
- port.postMessage({ token: token });
- } else {
- console.error('Unknown event', event); // eslint-disable-line
- port.postMessage({
- error: 'Unknown request',
- });
- }
- });
-
// attempt to unregister the service worker on unload because we're not doing any sort of caching
window.addEventListener('unload', function () {
registration.unregister();
diff --git a/ui/tests/integration/components/raft-storage-overview-test.js b/ui/tests/integration/components/raft-storage-overview-test.js
index dde28f67e..54b289439 100644
--- a/ui/tests/integration/components/raft-storage-overview-test.js
+++ b/ui/tests/integration/components/raft-storage-overview-test.js
@@ -2,17 +2,56 @@ import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { render } from '@ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
+import sinon from 'sinon';
module('Integration | Component | raft-storage-overview', function (hooks) {
setupRenderingTest(hooks);
- test('it renders', async function (assert) {
- let model = [
+ hooks.beforeEach(function () {
+ this.model = [
{ address: '127.0.0.1:8200', voter: true },
{ address: '127.0.0.1:8200', voter: true, leader: true },
];
- this.set('model', model);
+ });
+
+ test('it renders', async function (assert) {
await render(hbs``);
assert.dom('[data-raft-row]').exists({ count: 2 });
});
+
+ test('it should download snapshot via service worker', async function (assert) {
+ assert.expect(3);
+
+ const token = this.owner.lookup('service:auth').currentToken;
+ const generateMockEvent = (action) => ({
+ data: { action },
+ ports: [
+ {
+ postMessage(message) {
+ const getToken = action === 'getToken';
+ const expected = getToken ? { token } : { error: 'Unknown request' };
+ assert.deepEqual(
+ message,
+ expected,
+ `${
+ getToken ? 'Token' : 'Error'
+ } is returned to service worker in message event listener callback`
+ );
+ },
+ },
+ ],
+ });
+
+ sinon.stub(navigator.serviceWorker, 'getRegistration').resolves(true);
+ sinon.stub(navigator.serviceWorker, 'addEventListener').callsFake((name, cb) => {
+ assert.strictEqual(name, 'message', 'Event listener added for service worker message');
+ cb(generateMockEvent('getToken'));
+ cb(generateMockEvent('unknown'));
+ });
+
+ await render(hbs``);
+ // avoid clicking the download button or the url will change
+ // the service worker invokes the event listener callback when it intercepts the request to /v1/sys/storage/raft/snapshot
+ // for the test we manually fire the callback as soon as it is passed to the addEventListener stub
+ });
});