Skip to content
21 changes: 13 additions & 8 deletions apps/condo/domains/notification/adapters/appleAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,11 @@
* Prepares notification for either/both sending to Apple push and/or emulation if FAKE tokens present
* Converts single notification to notifications array (for multiple tokens provided) for batch request
* @param notificationRaw
* @param data
* @param dataByToken
* @param tokens
* @returns {*[][]}
*/
static prepareBatchData (notificationRaw, data, tokens = [], pushTypes = {}, appIds) {
static prepareBatchData (notificationRaw, dataByToken = {}, tokens = [], pushTypes = {}, appIds) {

Check warning on line 154 in apps/condo/domains/notification/adapters/appleAdapter.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Default parameters should be last.

See more on https://sonarcloud.io/project/issues?id=open-condo-software_condo&issues=AZyfOXOEa4rHBstULRbr&open=AZyfOXOEa4rHBstULRbr&pullRequest=7271
const notification = AppleAdapter.validateAndPrepareNotification(notificationRaw)
const notifications = [] // User can have many Remote Clients. Message is created for the user, so from 1 message there can be many notifications
const fakeNotifications = []
Expand All @@ -161,12 +161,14 @@
const isFakeToken = pushToken.startsWith(PUSH_FAKE_TOKEN_SUCCESS) || pushToken.startsWith(PUSH_FAKE_TOKEN_FAIL)
const target = isFakeToken ? fakeNotifications : notifications
const pushType = pushTypes[pushToken] || PUSH_TYPE_DEFAULT
const preparedData = AppleAdapter.prepareData(data, pushToken)
const data = dataByToken[pushToken]
if (!data) return

const pushData = pushType === PUSH_TYPE_SILENT_DATA
? {
token: pushToken,
data: {
...preparedData,
...data,
'_title': notification.title,
'_body': notification.body,
},
Expand All @@ -176,14 +178,17 @@
}
: {
token: pushToken,
data: preparedData,
data: data,
notification,
...DEFAULT_PUSH_SETTINGS,
type: pushType,
appId: get(appIds, pushToken),
}

if (!APPS_WITH_DISABLED_NOTIFICATIONS.includes(get(appIds, pushToken)) && !APPS_WITH_DISABLED_NOTIFICATIONS.includes(data.app)) target.push(pushData)
if (
!APPS_WITH_DISABLED_NOTIFICATIONS.includes(get(appIds, pushToken))
&& (!data.app || !APPS_WITH_DISABLED_NOTIFICATIONS.includes(data.app))
) target.push(pushData)

if (!pushContext[pushType]) pushContext[pushType] = pushData
})
Expand All @@ -203,10 +208,10 @@
* @param pushTypes
* @returns {Promise<null|(boolean|T|{state: string, error: *})[]>}
*/
async sendNotification ({ notification, data, tokens, pushTypes, appIds, metaByToken } = {}, isVoIP = false) {
async sendNotification ({ notification, dataByToken, tokens, pushTypes, appIds, metaByToken } = {}, isVoIP = false) {
if (!tokens || isEmpty(tokens)) return [false, { error: 'No pushTokens available.' }]

const [notifications, fakeNotifications, pushContext] = AppleAdapter.prepareBatchData(notification, data, tokens, pushTypes, appIds)
const [notifications, fakeNotifications, pushContext] = AppleAdapter.prepareBatchData(notification, dataByToken, tokens, pushTypes, appIds)
let result = AppleAdapter.getEmptyResult()

if (!isNull(this.#config) && !isEmpty(notifications)) {
Expand Down
61 changes: 39 additions & 22 deletions apps/condo/domains/notification/adapters/appleAdapter.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,19 @@ describe('Apple adapter utils', () => {

it('should succeed sending push notification to fake success push token', async () => {
const tokens = [PUSH_FAKE_TOKEN_SUCCESS]
const dataByToken = Object.fromEntries(
tokens.map(token => [token, {
app : 'condo',
type: 'notification',
}])
)
const [isOk, result] = await adapter.sendNotification({
tokens,
notification: {
title: 'Doma.ai',
body: `${dayjs().format()} Condo greets you!`,
},
data: {
app : 'condo',
type: 'notification',
},
dataByToken: dataByToken,
})

expect(isOk).toBeTruthy()
Expand Down Expand Up @@ -153,9 +156,11 @@ describe('Apple adapter utils', () => {
title: 'Doma.ai',
body: `${dayjs().format()} Condo greets you!`,
},
data: {
app : 'condo',
type: 'notification',
dataByToken: {
[PUSH_FAKE_TOKEN_FAIL]: {
app: 'condo',
type: 'notification',
},
},
})

Expand All @@ -171,15 +176,19 @@ describe('Apple adapter utils', () => {
})

it('should succeed sending push notification to fake success and fake fail push tokens', async () => {
const data = {
app : 'condo',
type: 'notification',
}
const [isOk, result] = await adapter.sendNotification({
tokens: [PUSH_FAKE_TOKEN_SUCCESS, PUSH_FAKE_TOKEN_FAIL],
notification: {
title: 'Doma.ai',
body: `${dayjs().format()} Condo greets you!`,
},
data: {
app : 'condo',
type: 'notification',
dataByToken: {
[PUSH_FAKE_TOKEN_SUCCESS]: data,
[PUSH_FAKE_TOKEN_FAIL]: data,
},
})

Expand All @@ -206,9 +215,11 @@ describe('Apple adapter utils', () => {
title: 'Doma.ai',
body: `${dayjs().format()} Condo greets you!`,
},
data: {
app : 'condo',
type: 'notification',
dataByToken: {
[PUSH_FAKE_TOKEN_SUCCESS]: {
app : 'condo',
type: 'notification',
},
},
pushTypes: {
[PUSH_FAKE_TOKEN_SUCCESS]: PUSH_TYPE_DEFAULT,
Expand Down Expand Up @@ -239,9 +250,11 @@ describe('Apple adapter utils', () => {
title: 'Doma.ai',
body: `${dayjs().format()} Condo greets you!`,
},
data: {
app : 'condo',
type: 'notification',
dataByToken: {
[PUSH_FAKE_TOKEN_SUCCESS]: {
app: 'condo',
type: 'notification',
},
},
pushTypes: {
[PUSH_FAKE_TOKEN_SUCCESS]: PUSH_TYPE_SILENT_DATA,
Expand Down Expand Up @@ -272,9 +285,11 @@ describe('Apple adapter utils', () => {
notification: {
body: `${dayjs().format()} Condo greets you!`,
},
data: {
app : 'condo',
type: 'notification',
dataByToken: {
[PUSH_FAKE_TOKEN_SUCCESS]: {
app: 'condo',
type: 'notification',
},
},
})
).rejects.toThrow(EMPTY_NOTIFICATION_TITLE_BODY_ERROR)
Expand All @@ -287,9 +302,11 @@ describe('Apple adapter utils', () => {
notification: {
title: 'Doma.ai',
},
data: {
app : 'condo',
type: 'notification',
dataByToken: {
[PUSH_FAKE_TOKEN_SUCCESS]: {
app: 'condo',
type: 'notification',
},
},
})
).rejects.toThrow(EMPTY_NOTIFICATION_TITLE_BODY_ERROR)
Expand Down
27 changes: 16 additions & 11 deletions apps/condo/domains/notification/adapters/firebaseAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
/**
* Firebase rejects push if any of data fields is not a string, so we should convert all non-string fields to strings
* @param data
* @param token {string}
*/
static prepareData (data = {}, token) {
const result = { token }
Expand Down Expand Up @@ -170,11 +171,11 @@
* Prepares notification for either/both sending to FireBase and/or emulation if FAKE tokens present
* Converts single notification to notifications array (for multiple tokens provided) for batch request
* @param notificationRaw
* @param data
* @param dataByToken
* @param tokens
* @returns {*[][]}
*/
static prepareBatchData (notificationRaw, data, tokens = [], pushTypes = {}, isVoIP = false, appIds = {}) {
static prepareBatchData (notificationRaw, dataByToken = {}, tokens = [], pushTypes = {}, isVoIP = false, appIds = {}) {
const notification = FirebaseAdapter.validateAndPrepareNotification(notificationRaw)
const notifications = []
const fakeNotifications = []
Expand All @@ -185,12 +186,14 @@
const isFakeToken = pushToken.startsWith(PUSH_FAKE_TOKEN_SUCCESS) || pushToken.startsWith(PUSH_FAKE_TOKEN_FAIL)
const target = isFakeToken ? fakeNotifications : notifications
const pushType = pushTypes[pushToken] || PUSH_TYPE_DEFAULT
const preparedData = FirebaseAdapter.prepareData(data, pushToken)
const data = dataByToken[pushToken]
if (!data) return

const pushData = pushType === PUSH_TYPE_SILENT_DATA
? {
token: pushToken,
data: {
...preparedData,
...data,
'_title': notification.title,
'_body': notification.body,
},
Expand All @@ -199,16 +202,18 @@
}
: {
token: pushToken,
data: preparedData,
data: data,
notification,
...DEFAULT_PUSH_SETTINGS,
...extraPayload,
}

// appId is set for each pushToken, so we can check if the app is disabled
// data.app is also checked for backward compatibility, as it was used in the old implementation
const appId = appIds[pushToken]
if (!APPS_WITH_DISABLED_NOTIFICATIONS.includes(appId) && !APPS_WITH_DISABLED_NOTIFICATIONS.includes(data.app)) target.push(pushData)
if (
!APPS_WITH_DISABLED_NOTIFICATIONS.includes(appId)
&& (!data.app || !APPS_WITH_DISABLED_NOTIFICATIONS.includes(data.app))
) target.push(pushData)

if (!pushContext[pushType]) pushContext[pushType] = pushData
})
Expand All @@ -224,18 +229,18 @@
* PUSH_FAKE_TOKEN_SUCCESS provided within tokens
* @param notification
* @param tokens
* @param data
* @param dataByToken
* @param pushTypes
+ * @param appIds - Object mapping pushToken to appId for routing notifications to the correct Firebase app
* @param metaByToken
* @returns {Promise<null|(boolean|T|{state: string, error: *})[]>}
*/
async sendNotification ({ notification, data, tokens, pushTypes, appIds, metaByToken } = {}, isVoIP = false) {
async sendNotification ({ notification, dataByToken, tokens, pushTypes, appIds, metaByToken } = {}, isVoIP = false) {

Check failure on line 238 in apps/condo/domains/notification/adapters/firebaseAdapter.js

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 38 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=open-condo-software_condo&issues=AZyfOXOVa4rHBstULRbs&open=AZyfOXOVa4rHBstULRbs&pullRequest=7271
if (!tokens || isEmpty(tokens)) return [false, { error: 'No pushTokens available.' }]

const [notifications, fakeNotifications, pushContext] = FirebaseAdapter.prepareBatchData(
notification,
data,
notification,
dataByToken,
tokens,
pushTypes,
isVoIP,
Expand Down
Loading