@superhuman/push-receiver
Advanced tools
| jest.mock('../src/utils/decrypt'); | ||
| const Client = require('../src/client'); | ||
| const decrypt = require('../src/utils/decrypt'); | ||
| const KEYS = { | ||
| authSecret : 'auth-secret', | ||
| privateKey : 'private-key', | ||
| }; | ||
| function createClient(persistentIds = []) { | ||
| return new Client({ keys : KEYS }, { persistentIds }); | ||
| } | ||
| describe('Client', () => { | ||
| describe('_onDataMessage', () => { | ||
| beforeEach(() => { | ||
| decrypt.mockReset(); | ||
| }); | ||
| [ | ||
| 'Unsupported state or unable to authenticate data', | ||
| 'crypto-key is missing', | ||
| 'salt is missing', | ||
| ].forEach(errorMessage => { | ||
| it(`emits "${errorMessage}" after recording the persistent id`, done => { | ||
| const client = createClient(); | ||
| const object = { persistentId : 'persistent-id' }; | ||
| const decryptionError = new Error(errorMessage); | ||
| decrypt.mockImplementation(() => { | ||
| throw decryptionError; | ||
| }); | ||
| client.on('error', error => { | ||
| expect(error).toBe(decryptionError); | ||
| expect(client._persistentIds).toEqual(['persistent-id']); | ||
| expect(decrypt).toHaveBeenCalledWith(object, KEYS); | ||
| done(); | ||
| }); | ||
| client._onDataMessage(object); | ||
| expect(client._persistentIds).toEqual(['persistent-id']); | ||
| }); | ||
| }); | ||
| it('emits unrelated decrypt errors without recording the persistent id', done => { | ||
| const client = createClient(); | ||
| const object = { persistentId : 'persistent-id' }; | ||
| const decryptionError = new Error('unexpected decrypt failure'); | ||
| decrypt.mockImplementation(() => { | ||
| throw decryptionError; | ||
| }); | ||
| client.on('error', error => { | ||
| expect(error).toBe(decryptionError); | ||
| expect(client._persistentIds).toEqual([]); | ||
| done(); | ||
| }); | ||
| client._onDataMessage(object); | ||
| expect(client._persistentIds).toEqual([]); | ||
| }); | ||
| it('records and emits successfully decrypted messages', () => { | ||
| const client = createClient(); | ||
| const object = { persistentId : 'persistent-id' }; | ||
| const message = { title : 'Hello' }; | ||
| const onNotification = jest.fn(); | ||
| decrypt.mockReturnValue(message); | ||
| client.on('ON_NOTIFICATION_RECEIVED', onNotification); | ||
| client._onDataMessage(object); | ||
| expect(client._persistentIds).toEqual(['persistent-id']); | ||
| expect(onNotification).toHaveBeenCalledWith({ | ||
| notification : message, | ||
| persistentId : 'persistent-id', | ||
| }); | ||
| }); | ||
| }); | ||
| }); |
+1
-1
| { | ||
| "name": "@superhuman/push-receiver", | ||
| "version": "2.1.5", | ||
| "version": "2.1.6", | ||
| "description": | ||
@@ -5,0 +5,0 @@ "A module to subscribe to GCM/FCM and receive notifications within a node process.", |
+17
-17
@@ -194,20 +194,7 @@ const EventEmitter = require('events'); | ||
| } catch (error) { | ||
| switch (true) { | ||
| case error.message.includes( | ||
| 'Unsupported state or unable to authenticate data' | ||
| ): | ||
| case error.message.includes('crypto-key is missing'): | ||
| case error.message.includes('salt is missing'): | ||
| // NOTE(ibash) Periodically we're unable to decrypt notifications. In | ||
| // all cases we've been able to receive future notifications using the | ||
| // same keys. So, we silently drop this notification. | ||
| console.warn( | ||
| 'Message dropped as it could not be decrypted: ' + error.message | ||
| ); | ||
| this._persistentIds.push(object.persistentId); | ||
| return; | ||
| default: { | ||
| throw error; | ||
| } | ||
| if (isReportableDecryptionError(error)) { | ||
| this._persistentIds.push(object.persistentId); | ||
| } | ||
| this._emitError(error); | ||
| return; | ||
| } | ||
@@ -224,2 +211,15 @@ | ||
| } | ||
| _emitError(error) { | ||
| // Let Parser advance past this packet before consumers handle the error. | ||
| setImmediate(() => this.emit('error', error)); | ||
| } | ||
| }; | ||
| function isReportableDecryptionError(error) { | ||
| return [ | ||
| 'Unsupported state or unable to authenticate data', | ||
| 'crypto-key is missing', | ||
| 'salt is missing', | ||
| ].some(message => error.message.includes(message)); | ||
| } |
+2
-2
@@ -11,4 +11,4 @@ const path = require('path'); | ||
| // https://github.com/dcodeIO/protobuf.js#browserify-integration | ||
| protobuf.util.Long = Long | ||
| protobuf.configure() | ||
| protobuf.util.Long = Long; | ||
| protobuf.configure(); | ||
@@ -15,0 +15,0 @@ const serverKey = toBase64(Buffer.from(fcmKey)); |
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
60522
3.92%24
4.35%1088
6.46%