mirror of
https://github.com/HabitRPG/habitica.git
synced 2025-12-17 22:57:21 +01:00
Push notifications (#7682)
* Fix Social Push notifications * Fix code formatting issues * Fix commented issues * Fix Syntax errors * update push notify dependency * specify push-notify version * change how apn key is loaded * feat(push-notifications): improve logging * feat(push-notifications): disable v2 push notifications * test(push-notifications): add unit tests and improve integration ones * fix(push-notifications): throw when required params are missing * fix(tests): correct descriptions and remove wrong comment * fix(push-notifications): trim APN key * fix(apn): log feedback only if it has data * fix(apn): load cert and key differently * fix(tests): correctly load apn during tests * download creds from S3 and create AWS lib * convert s3 buffer to a string * fix(apn): remove console.log and do not use cert twice * invert key and cert, disable failing test * invert key and cert
This commit is contained in:
@@ -20,7 +20,6 @@ import { removeFromArray } from '../../libs/api-v3/collectionManipulators';
|
||||
import * as firebase from '../../libs/api-v3/firebase';
|
||||
import { sendTxn as sendTxnEmail } from '../../libs/api-v3/email';
|
||||
import { encrypt } from '../../libs/api-v3/encryption';
|
||||
import common from '../../../../common';
|
||||
import sendPushNotification from '../../libs/api-v3/pushNotifications';
|
||||
let api = {};
|
||||
|
||||
@@ -537,11 +536,18 @@ async function _inviteByUUID (uuid, group, inviter, req, res) {
|
||||
sendTxnEmail(userToInvite, `invited-${groupTemplate}`, emailVars);
|
||||
}
|
||||
|
||||
sendPushNotification(
|
||||
userToInvite,
|
||||
common.i18n.t(group.type === 'guild' ? 'invitedGuild' : 'invitedParty'),
|
||||
group.name
|
||||
);
|
||||
if (userToInvite.preferences.pushNotifications[`invited${groupLabel}`] !== false) {
|
||||
let identifier = group.type === 'guild' ? 'invitedGuild' : 'invitedParty';
|
||||
sendPushNotification(
|
||||
userToInvite,
|
||||
{
|
||||
title: group.name,
|
||||
message: res.t(identifier),
|
||||
identifier,
|
||||
payload: {groupID: group._id},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
let userInvited = await userToInvite.save();
|
||||
if (group.type === 'guild') {
|
||||
|
||||
@@ -302,6 +302,18 @@ api.sendPrivateMessage = {
|
||||
{name: 'PMS_INBOX_URL', content: '/#/options/groups/inbox'},
|
||||
]);
|
||||
}
|
||||
if (receiver.preferences.pushNotifications.newPM !== false) {
|
||||
sendPushNotification(
|
||||
receiver,
|
||||
{
|
||||
title: res.t('newPM'),
|
||||
message: res.t('newPMInfo', {name: getUserInfo(sender, ['name']).name, message}),
|
||||
identifier: 'newPM',
|
||||
category: 'newPM',
|
||||
payload: {replyTo: sender._id},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
res.respond(200, {});
|
||||
},
|
||||
@@ -372,8 +384,15 @@ api.transferGems = {
|
||||
{name: 'X_GEMS_GIFTED', content: gemAmount},
|
||||
]);
|
||||
}
|
||||
|
||||
sendPushNotification(sender, res.t('giftedGems'), res.t('giftedGemsInfo', { amount: gemAmount, name: byUsername }));
|
||||
if (receiver.preferences.pushNotifications.giftedGems !== false) {
|
||||
sendPushNotification(receiver,
|
||||
{
|
||||
title: res.t('giftedGems'),
|
||||
message: res.t('giftedGemsInfo', {amount: gemAmount, name: byUsername}),
|
||||
identifier: 'giftedGems',
|
||||
payload: {replyTo: sender._id},
|
||||
});
|
||||
}
|
||||
|
||||
res.respond(200, {});
|
||||
},
|
||||
|
||||
95
website/server/controllers/api-v3/pushNotifications.js
Normal file
95
website/server/controllers/api-v3/pushNotifications.js
Normal file
@@ -0,0 +1,95 @@
|
||||
import { authWithHeaders } from '../../middlewares/api-v3/auth';
|
||||
import {
|
||||
NotAuthorized,
|
||||
NotFound,
|
||||
} from '../../libs/api-v3/errors';
|
||||
|
||||
let api = {};
|
||||
|
||||
/**
|
||||
* @apiIgnore
|
||||
* @api {post} /api/v3/user/push-devices Add a push device to a user
|
||||
* @apiVersion 3.0.0
|
||||
* @apiName UserAddPushDevice
|
||||
* @apiGroup User
|
||||
*
|
||||
* @apiParam {string} regId The id of the push device
|
||||
* @apiParam {string} type The type of push device
|
||||
*
|
||||
* @apiSuccess {Object} data List of push devices
|
||||
* @apiSuccess {string} message Success message
|
||||
*/
|
||||
api.addPushDevice = {
|
||||
method: 'POST',
|
||||
url: '/user/push-devices',
|
||||
middlewares: [authWithHeaders()],
|
||||
async handler (req, res) {
|
||||
let user = res.locals.user;
|
||||
|
||||
req.checkBody('regId', res.t('regIdRequired')).notEmpty();
|
||||
req.checkBody('type', res.t('typeRequired')).notEmpty().isIn(['ios', 'android']);
|
||||
|
||||
let validationErrors = req.validationErrors();
|
||||
if (validationErrors) throw validationErrors;
|
||||
|
||||
let pushDevices = user.pushDevices;
|
||||
|
||||
let item = {
|
||||
regId: req.body.regId,
|
||||
type: req.body.type,
|
||||
};
|
||||
|
||||
if (pushDevices.find(device => device.regId === item.regId)) {
|
||||
throw new NotAuthorized(res.t('pushDeviceAlreadyAdded'));
|
||||
}
|
||||
|
||||
pushDevices.push(item);
|
||||
|
||||
await user.save();
|
||||
|
||||
res.respond(200, user.pushDevices, res.t('pushDeviceAdded'));
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @apiIgnore
|
||||
* @api {delete} /api/v3/user/push-devices remove a push device from a user
|
||||
* @apiVersion 3.0.0
|
||||
* @apiName UserRemovePushDevice
|
||||
* @apiGroup User
|
||||
*
|
||||
* @apiParam {string} regId The id of the push device
|
||||
*
|
||||
* @apiSuccess {Object} data List of push devices
|
||||
* @apiSuccess {string} message Success message
|
||||
*/
|
||||
api.removePushDevice = {
|
||||
method: 'DELETE',
|
||||
url: '/user/push-devices/:regId',
|
||||
middlewares: [authWithHeaders()],
|
||||
async handler (req, res) {
|
||||
let user = res.locals.user;
|
||||
|
||||
req.checkParams('regId', res.t('regIdRequired')).notEmpty();
|
||||
let validationErrors = req.validationErrors();
|
||||
if (validationErrors) throw validationErrors;
|
||||
let regId = req.params.regId;
|
||||
|
||||
let pushDevices = user.pushDevices;
|
||||
|
||||
let indexOfPushDevice = pushDevices.findIndex((element) => {
|
||||
return element.regId === regId;
|
||||
});
|
||||
|
||||
if (indexOfPushDevice === -1) {
|
||||
throw new NotFound(res.t('pushDeviceNotFound'));
|
||||
}
|
||||
|
||||
pushDevices.splice(indexOfPushDevice, 1);
|
||||
await user.save();
|
||||
|
||||
res.respond(200, user.pushDevices, res.t('pushDeviceRemoved'));
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = api;
|
||||
@@ -106,11 +106,18 @@ api.inviteToQuest = {
|
||||
let inviterVars = getUserInfo(user, ['name', 'email']);
|
||||
let membersToEmail = members.filter(member => {
|
||||
// send push notifications while filtering members before sending emails
|
||||
sendPushNotification(
|
||||
member,
|
||||
common.i18n.t('questInvitationTitle'),
|
||||
common.i18n.t('questInvitationInfo', { quest: quest.text() })
|
||||
);
|
||||
if (member.preferences.pushNotifications.invitedQuest !== false) {
|
||||
sendPushNotification(
|
||||
member,
|
||||
{
|
||||
title: res.t('questInvitationTitle'),
|
||||
message: res.t('questInvitationInfo', {quest: quest.text(req.language)}),
|
||||
identifier: 'questInvitation',
|
||||
category: 'questInvitation',
|
||||
}
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
return member.preferences.emailNotifications.invitedQuest !== false;
|
||||
});
|
||||
|
||||
@@ -1266,32 +1266,6 @@ api.userReroll = {
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @api {post} /api/v3/user/addPushDevice Add a push device to a user
|
||||
* @apiVersion 3.0.0
|
||||
* @apiName UserAddPushDevice
|
||||
* @apiGroup User
|
||||
*
|
||||
* @apiParam {string} regId The id of the push device
|
||||
* @apiParam {string} uuid The type of push device
|
||||
*
|
||||
* @apiSuccess {Object} data List of push devices
|
||||
* @apiSuccess {string} message Success message
|
||||
*/
|
||||
api.userAddPushDevice = {
|
||||
method: 'POST',
|
||||
middlewares: [authWithHeaders()],
|
||||
url: '/user/addPushDevice',
|
||||
async handler (req, res) {
|
||||
let user = res.locals.user;
|
||||
|
||||
let addPushDeviceRes = common.ops.addPushDevice(user, req);
|
||||
await user.save();
|
||||
|
||||
res.respond(200, ...addPushDeviceRes);
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* @api {post} /api/v3/user/reset Reset user
|
||||
* @apiVersion 3.0.0
|
||||
|
||||
Reference in New Issue
Block a user