mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-30 18:17:55 +00:00 
			
		
		
		
	Raft Snapshot Download Bug (#17769)
* moves service worker message event listener from addon to raft-storage-overview component * adds changelog entry * adds raft-storage-overview test for downloading snapshot via service worker
This commit is contained in:
		
							
								
								
									
										3
									
								
								changelog/17769.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								changelog/17769.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | ```release-note:bug | ||||||
|  | ui: Fixes issue with not being able to download raft snapshot via service worker | ||||||
|  | ``` | ||||||
| @@ -5,6 +5,8 @@ import { inject as service } from '@ember/service'; | |||||||
|  |  | ||||||
| export default Component.extend({ | export default Component.extend({ | ||||||
|   flashMessages: service(), |   flashMessages: service(), | ||||||
|  |   auth: service(), | ||||||
|  |  | ||||||
|   useServiceWorker: null, |   useServiceWorker: null, | ||||||
|  |  | ||||||
|   async init() { |   async init() { | ||||||
| @@ -16,12 +18,32 @@ export default Component.extend({ | |||||||
|     if ('serviceWorker' in navigator) { |     if ('serviceWorker' in navigator) { | ||||||
|       // this checks to see if there's an active service worker - if it failed to register |       // this checks to see if there's an active service worker - if it failed to register | ||||||
|       // for any reason, then this would be null |       // 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) { |       if (worker) { | ||||||
|  |         navigator.serviceWorker.addEventListener('message', this.serviceWorkerGetToken.bind(this)); | ||||||
|  |  | ||||||
|         this.set('useServiceWorker', true); |         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: { |   actions: { | ||||||
|     async removePeer(model) { |     async removePeer(model) { | ||||||
|   | |||||||
| @@ -1,32 +1,6 @@ | |||||||
| import { addSuccessHandler } from 'ember-service-worker/service-worker-registration'; | 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) { | 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 |   // attempt to unregister the service worker on unload because we're not doing any sort of caching | ||||||
|   window.addEventListener('unload', function () { |   window.addEventListener('unload', function () { | ||||||
|     registration.unregister(); |     registration.unregister(); | ||||||
|   | |||||||
| @@ -2,17 +2,56 @@ import { module, test } from 'qunit'; | |||||||
| import { setupRenderingTest } from 'ember-qunit'; | import { setupRenderingTest } from 'ember-qunit'; | ||||||
| import { render } from '@ember/test-helpers'; | import { render } from '@ember/test-helpers'; | ||||||
| import hbs from 'htmlbars-inline-precompile'; | import hbs from 'htmlbars-inline-precompile'; | ||||||
|  | import sinon from 'sinon'; | ||||||
|  |  | ||||||
| module('Integration | Component | raft-storage-overview', function (hooks) { | module('Integration | Component | raft-storage-overview', function (hooks) { | ||||||
|   setupRenderingTest(hooks); |   setupRenderingTest(hooks); | ||||||
|  |  | ||||||
|   test('it renders', async function (assert) { |   hooks.beforeEach(function () { | ||||||
|     let model = [ |     this.model = [ | ||||||
|       { address: '127.0.0.1:8200', voter: true }, |       { address: '127.0.0.1:8200', voter: true }, | ||||||
|       { address: '127.0.0.1:8200', voter: true, leader: true }, |       { address: '127.0.0.1:8200', voter: true, leader: true }, | ||||||
|     ]; |     ]; | ||||||
|     this.set('model', model); |   }); | ||||||
|  |  | ||||||
|  |   test('it renders', async function (assert) { | ||||||
|     await render(hbs`<RaftStorageOverview @model={{this.model}} />`); |     await render(hbs`<RaftStorageOverview @model={{this.model}} />`); | ||||||
|     assert.dom('[data-raft-row]').exists({ count: 2 }); |     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`<RaftStorageOverview @model={{this.model}} />`); | ||||||
|  |     // 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 | ||||||
|  |   }); | ||||||
| }); | }); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jordan Reimer
					Jordan Reimer