Skip to content

Commit 6593d9f

Browse files
Merge pull request #5451 from Countly/SER-1645-clean-up-old-fcm-api-related-code
[SER-1645] clean up old fcm api related code
2 parents 9644eec + 48e188f commit 6593d9f

File tree

5 files changed

+63
-263
lines changed

5 files changed

+63
-263
lines changed

plugins/push/api/send/platforms/a.js

Lines changed: 62 additions & 241 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { ConnectionError, ERROR, SendError, PushError, FCM_SDK_ERRORS } = require('../data/error'),
1+
const { ERROR, SendError, FCM_SDK_ERRORS } = require('../data/error'),
22
logger = require('../../../../../api/utils/log'),
33
{ Splitter } = require('./utils/splitter'),
44
{ util } = require('../std'),
@@ -56,7 +56,7 @@ class FCM extends Splitter {
5656
* Standard constructor
5757
* @param {string} log logger name
5858
* @param {string} type type of connection: ap, at, id, ia, ip, ht, hp
59-
* @param {Credentials} creds FCM server key
59+
* @param {Credentials} creds FCM credentials
6060
* @param {Object[]} messages initial array of messages to send
6161
* @param {Object} options standard stream options
6262
* @param {number} options.pool.pushes number of notifications which can be processed concurrently, this parameter is strictly set to 500
@@ -71,34 +71,20 @@ class FCM extends Splitter {
7171
this.legacyApi = !creds._data.serviceAccountFile;
7272

7373
this.log = logger(log).sub(`${threadId}-a`);
74-
if (this.legacyApi) {
75-
this.opts = {
76-
agent: this.agent,
77-
hostname: 'fcm.googleapis.com',
78-
port: 443,
79-
path: '/fcm/send',
80-
method: 'POST',
81-
headers: {
82-
'Accept': 'application/json',
83-
'Content-Type': 'application/json',
84-
'Authorization': `key=${creds._data.key}`,
85-
},
86-
};
87-
}
88-
else {
89-
const serviceAccountJSON = FORGE.util.decode64(
90-
creds._data.serviceAccountFile.substring(creds._data.serviceAccountFile.indexOf(',') + 1)
91-
);
92-
const serviceAccountObject = JSON.parse(serviceAccountJSON);
93-
const appName = creds._data.hash; // using hash as the app name
94-
const firebaseApp = firebaseAdmin.apps.find(app => app.name === appName)
95-
? firebaseAdmin.app(appName)
96-
: firebaseAdmin.initializeApp({
97-
credential: firebaseAdmin.credential.cert(serviceAccountObject, this.agent),
98-
httpAgent: this.agent
99-
}, appName);
100-
this.firebaseMessaging = firebaseApp.messaging();
101-
}
74+
75+
const serviceAccountJSON = FORGE.util.decode64(
76+
creds._data.serviceAccountFile.substring(creds._data.serviceAccountFile.indexOf(',') + 1)
77+
);
78+
const serviceAccountObject = JSON.parse(serviceAccountJSON);
79+
const appName = creds._data.hash; // using hash as the app name
80+
const firebaseApp = firebaseAdmin.apps.find(app => app.name === appName)
81+
? firebaseAdmin.app(appName)
82+
: firebaseAdmin.initializeApp({
83+
credential: firebaseAdmin.credential.cert(serviceAccountObject, this.agent),
84+
httpAgent: this.agent
85+
}, appName);
86+
this.firebaseMessaging = firebaseApp.messaging();
87+
10288

10389
this.log.i('Initialized');
10490
}
@@ -139,8 +125,6 @@ class FCM extends Splitter {
139125
const one = Math.ceil(bytes / pushes.length);
140126
let content = this.template(pushes[0].m).compile(pushes[0]);
141127

142-
let printBody = false;
143-
const oks = [];
144128
const errors = {};
145129
/**
146130
* Get an error for given code & message, create it if it doesn't exist yet
@@ -156,221 +140,66 @@ class FCM extends Splitter {
156140
}
157141
return errors[err];
158142
};
159-
if (!this.legacyApi) {
160-
const tokens = pushes.map(p => p.t);
161-
162-
// new fcm api doesn't allow objects or arrays inside "data" property
163-
if (content.data && typeof content.data === "object") {
164-
for (let prop in content.data) {
165-
if (content.data[prop] && typeof content.data[prop] === "object") {
166-
content.data[prop] = JSON.stringify(content.data[prop]);
167-
}
168-
}
169-
}
170143

171-
const messages = tokens.map(token => ({
172-
token,
173-
...content,
174-
}));
175-
176-
return this.firebaseMessaging
177-
// EXAMPLE RESPONSE of sendEach
178-
// {
179-
// "responses": [
180-
// {
181-
// "success": false,
182-
// "error": {
183-
// "code": "messaging/invalid-argument",
184-
// "message": "The registration token is not a valid FCM registration token"
185-
// }
186-
// }
187-
// ],
188-
// "successCount": 0,
189-
// "failureCount": 1
190-
// }
191-
.sendEach(messages)
192-
.then(async result => {
193-
const allPushIds = pushes.map(p => p._id);
194-
195-
if (!result.failureCount) {
196-
this.send_results(allPushIds, bytes);
197-
return;
198-
}
144+
const tokens = pushes.map(p => p.t);
145+
const messages = tokens.map(token => ({
146+
token,
147+
...content,
148+
}));
199149

200-
// array of successfully sent push._id:
201-
const sentSuccessfully = [];
202-
203-
// check for each message
204-
for (let i = 0; i < result.responses.length; i++) {
205-
const { success, error } = result.responses[i];
206-
if (success) {
207-
sentSuccessfully.push(allPushIds[i]);
208-
}
209-
else {
210-
const sdkError = FCM_SDK_ERRORS[error.code];
211-
// check if the sdk error is mapped to an internal error.
212-
// set to default if its not.
213-
let internalErrorCode = sdkError?.mapTo ?? ERROR.DATA_PROVIDER;
214-
let internalErrorMessage = sdkError?.message ?? "Invalid error message";
215-
errorObject(internalErrorCode, internalErrorMessage)
216-
.addAffected(pushes[i]._id, one);
217-
}
218-
}
219-
// send results back:
220-
for (let errorKey in errors) {
221-
this.send_push_error(errors[errorKey]);
222-
}
223-
if (sentSuccessfully.length) {
224-
this.send_results(sentSuccessfully, one * sentSuccessfully.length);
225-
}
226-
});
227-
}
228-
229-
content.registration_ids = pushes.map(p => p.t);
230-
231-
// CONNECTION TEST PAYLOAD (invalid registration token)
150+
return this.firebaseMessaging
151+
// EXAMPLE RESPONSE of sendEach
232152
// {
233-
// "data": {
234-
// "c.i": "663389aab53ebbf71a115edb",
235-
// "message": "test"
236-
// },
237-
// "registration_ids": [
238-
// "0.2124088209996502"
239-
// ]
153+
// "responses": [
154+
// {
155+
// "success": false,
156+
// "error": {
157+
// "code": "messaging/invalid-argument",
158+
// "message": "The registration token is not a valid FCM registration token"
159+
// }
160+
// }
161+
// ],
162+
// "successCount": 0,
163+
// "failureCount": 1
240164
// }
241-
// NORMAL PAYLOAD
242-
// {
243-
// "data": {
244-
// "c.i": "663389a949c58657a8e625b3",
245-
// "title": "qwer",
246-
// "message": "qwer",
247-
// "sound": "default"
248-
// },
249-
// "registration_ids": [
250-
// "dw_CueiXThqYI9owrQC0Pb:APA91bHanJn9RM-ZYnC-3wCMld5Nk3QaVJppS4HOKrpdV8kCXq7pjQlJjcd8_1xq9G6XaceZfrFPxbfehJ4YCEfMsfQVhZW1WKhnY3TbtO7HIQfYfbj35-sx_-BHAhQ5eSDuiCOZWUDP"
251-
// ]
252-
// }
253-
return this.sendRequest(JSON.stringify(content)).then(resp => {
254-
// CONNECTION TEST RESPONSE (with error)
255-
// {
256-
// "multicast_id": 2829871343601014000,
257-
// "success": 0,
258-
// "failure": 1,
259-
// "canonical_ids": 0,
260-
// "results": [
261-
// {
262-
// "error": "InvalidRegistration"
263-
// }
264-
// ]
265-
// }
266-
// NORMAL SUCCESSFUL RESPONSE
267-
// {
268-
// "multicast_id": 5676989510572196000,
269-
// "success": 1,
270-
// "failure": 0,
271-
// "canonical_ids": 0,
272-
// "results": [
273-
// {
274-
// "message_id": "0:1714653611139550%68dc6e82f9fd7ecd"
275-
// }
276-
// ]
277-
// }
278-
try {
279-
resp = JSON.parse(resp);
280-
}
281-
catch (error) {
282-
this.log.e('Bad FCM response format: %j', resp, error);
283-
throw PushError.deserialize(error, SendError);
284-
}
165+
.sendEach(messages)
166+
.then(async result => {
167+
const allPushIds = pushes.map(p => p._id);
285168

286-
if (resp.failure === 0 && resp.canonical_ids === 0) {
287-
this.send_results(pushes.map(p => p._id), bytes);
288-
return;
289-
}
169+
if (!result.failureCount) {
170+
this.send_results(allPushIds, bytes);
171+
return;
172+
}
290173

291-
if (resp.results) {
292-
resp.results.forEach((r, i) => {
293-
if (r.message_id) {
294-
if (r.registration_id) {
295-
if (r.registration_id === 'BLACKLISTED') {
296-
errorObject(ERROR.DATA_TOKEN_INVALID, 'Blacklisted').addAffected(pushes[i]._id, one);
297-
printBody = true;
298-
}
299-
else {
300-
oks.push([pushes[i]._id, r.registration_id]);
301-
}
302-
// oks.push([pushes[i]._id, r.registration_id], one); ???
303-
}
304-
else {
305-
oks.push(pushes[i]._id);
306-
}
307-
}
308-
else if (r.error === 'NotRegistered') {
309-
this.log.d('Token %s expired (%s)', pushes[i].t, r.error);
310-
errorObject(ERROR.DATA_TOKEN_EXPIRED, r.error).addAffected(pushes[i]._id, one);
311-
}
312-
else if (r.error === 'InvalidRegistration' || r.error === 'MismatchSenderId' || r.error === 'InvalidPackageName') {
313-
this.log.d('Token %s is invalid (%s)', pushes[i].t, r.error);
314-
errorObject(ERROR.DATA_TOKEN_INVALID, r.error).addAffected(pushes[i]._id, one);
174+
// array of successfully sent push._id:
175+
const sentSuccessfully = [];
176+
177+
// check for each message
178+
for (let i = 0; i < result.responses.length; i++) {
179+
const { success, error } = result.responses[i];
180+
if (success) {
181+
sentSuccessfully.push(allPushIds[i]);
315182
}
316-
// these are identical to "else" block:
317-
// else if (r.error === 'InvalidParameters') { // still hasn't figured out why this error is thrown, therefore not critical yet
318-
// printBody = true;
319-
// errorObject(ERROR.DATA_PROVIDER, r.error).addAffected(pushes[i]._id, one);
320-
// }
321-
// else if (r.error === 'MessageTooBig' || r.error === 'InvalidDataKey' || r.error === 'InvalidTtl') {
322-
// printBody = true;
323-
// errorObject(ERROR.DATA_PROVIDER, r.error).addAffected(pushes[i]._id, one);
324-
// }
325183
else {
326-
printBody = true;
327-
errorObject(ERROR.DATA_PROVIDER, r.error).addAffected(pushes[i]._id, one);
184+
const sdkError = FCM_SDK_ERRORS[error.code];
185+
// check if the sdk error is mapped to an internal error.
186+
// set to default if its not.
187+
let internalErrorCode = sdkError?.mapTo ?? ERROR.DATA_PROVIDER;
188+
let internalErrorMessage = sdkError?.message ?? "Invalid error message";
189+
errorObject(internalErrorCode, internalErrorMessage)
190+
.addAffected(pushes[i]._id, one);
328191
}
329-
});
330-
let errored = 0;
331-
for (let k in errors) {
332-
errored += errors[k].affectedBytes;
333-
this.send_push_error(errors[k]);
334192
}
335-
if (oks.length) {
336-
this.send_results(oks, bytes - errored);
193+
// send results back:
194+
for (let errorKey in errors) {
195+
this.send_push_error(errors[errorKey]);
337196
}
338-
if (printBody) {
339-
this.log.e('Provider returned error %j for %j', resp, content);
340-
}
341-
}
342-
}, ([code, error]) => {
343-
this.log.w('FCM error %d / %j', code, error);
344-
console.log("========== MAIN PROMISE ERROR");
345-
if (code === 0) {
346-
if (error.message === 'ECONNRESET' || error.code === 'ENOTFOUND' || error.code === 'ETIMEDOUT' ||
347-
error.code === 'ECONNREFUSED' || error.code === 'ECONNABORTED' || error.code === 'EHOSTUNREACH' ||
348-
error.code === 'EAI_AGAIN') {
349-
this.log.w('FCM error %d / %j', bytes, pushes.map(p => p._id));
350-
throw new ConnectionError(`FCM ${error.code}`, ERROR.CONNECTION_PROVIDER)
351-
.setConnectionError(error.code, `${error.errno} ${error.code} ${error.syscall}`)
352-
.addAffected(pushes.map(p => p._id), bytes);
197+
if (sentSuccessfully.length) {
198+
this.send_results(sentSuccessfully, one * sentSuccessfully.length);
353199
}
354-
let pe = PushError.deserialize(error, SendError);
355-
pe.addAffected(pushes.map(p => p._id), bytes);
356-
throw pe;
357-
}
358-
else if (code >= 500) {
359-
throw new ConnectionError(`FCM Unavailable: ${code}`, ERROR.CONNECTION_PROVIDER).addAffected(pushes.map(p => p._id), bytes);
360-
}
361-
else if (code === 401) {
362-
throw new ConnectionError(`FCM Unauthorized: ${code}`, ERROR.INVALID_CREDENTIALS).addAffected(pushes.map(p => p._id), bytes);
363-
}
364-
else if (code === 400) {
365-
throw new ConnectionError(`FCM Bad message: ${code}`, ERROR.DATA_PROVIDER).addAffected(pushes.map(p => p._id), bytes);
366-
}
367-
else {
368-
throw new ConnectionError(`FCM Bad response code: ${code}`, ERROR.EXCEPTION).addAffected(pushes.map(p => p._id), bytes);
369-
}
370-
});
200+
});
371201
});
372202
}
373-
374203
}
375204

376205
/**
@@ -581,7 +410,6 @@ const CREDS = {
581410
static get scheme() {
582411
return Object.assign(super.scheme, {
583412
serviceAccountFile: { required: false, type: "String" },
584-
key: { required: false, type: 'String', 'min-length': 100},
585413
hash: { required: false, type: 'String' },
586414
});
587415
}
@@ -621,9 +449,6 @@ const CREDS = {
621449
}
622450
this._data.hash = FORGE.md.sha256.create().update(serviceAccountJSON).digest().toHex();
623451
}
624-
else if (this._data.key) {
625-
this._data.hash = FORGE.md.sha256.create().update(this._data.key).digest().toHex();
626-
}
627452
else {
628453
return ["Updating FCM credentials requires a service-account.json file"];
629454
}
@@ -635,16 +460,12 @@ const CREDS = {
635460
* @returns {object} json without sensitive information
636461
*/
637462
get view() {
638-
const fcmKey = this._data?.key
639-
? `FCM server key "${this._data.key.substr(0, 10)} ... ${this._data.key.substr(this._data.key.length - 10)}"`
640-
: "";
641463
const serviceAccountFile = this._data?.serviceAccountFile
642464
? "service-account.json"
643465
: "";
644466
return {
645467
_id: this._id,
646468
type: this._data?.type,
647-
key: fcmKey,
648469
serviceAccountFile,
649470
hash: this._data?.hash,
650471
};

0 commit comments

Comments
 (0)