-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #35 from andela/feature/164599833/user-email-notif…
…ication #164599833 user notification
- Loading branch information
Showing
14 changed files
with
447 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,17 @@ | ||
import '@babel/polyfill'; | ||
import server from '../index'; | ||
import http from 'http'; | ||
import socketIo from 'socket.io'; | ||
import app from '../index'; | ||
import { env } from '../helpers/utils'; | ||
import logger from '../helpers/logger'; | ||
|
||
const port = env('PORT', 3000); | ||
const server = http.createServer(app); | ||
server.listen(port, () => logger.log(`Running on port ${port}`)); | ||
|
||
// add socket connection | ||
const io = socketIo(server); | ||
io.on('connection', (socket) => { | ||
// make socket global, so that new emitters can be created | ||
global.socket = socket; | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
import logger from '../helpers/logger'; | ||
import models from '../models/index'; | ||
import Mail from '../helpers/sendMail'; | ||
import Response from '../helpers/responseHelper'; | ||
import { STATUS } from '../helpers/constants'; | ||
/** | ||
* @description This class represents a notification in the app | ||
* @class NotificationsController | ||
*/ | ||
class NotificationsController { | ||
/** | ||
* This function gets a user setting | ||
* @param {Number} id - The message to be sent | ||
* @returns {Promise} - returns a promise | ||
*/ | ||
static async getSetting(id) { | ||
const userSetting = await models.Setting.findOne({ where: { userId: id } }); | ||
return userSetting; | ||
} | ||
|
||
/** | ||
* This function gets a users email | ||
* @param {Number} id - The message to be sent | ||
* @returns {String} - returns user email | ||
*/ | ||
static async getEmail(id) { | ||
const userData = await models.User.findOne({ where: { id } }); | ||
const { dataValues } = userData; | ||
return (dataValues.email); | ||
} | ||
|
||
|
||
/** | ||
* This function creates a new notification | ||
* It checks if the user is ok with getting notifications | ||
* By default a user gets in-app notifications if the user wants to recieve them in general | ||
* It checks what type of notification a user wants to get and sends it | ||
* If notification is to be sent to one user, then put the id in an array. | ||
* @param {String} message - The message to be sent | ||
* @param {Array} userIds - The users to send notifications to | ||
* @returns {void} | ||
*/ | ||
static async create(message, userIds) { | ||
// loop through each user | ||
// eslint-disable-next-line no-restricted-syntax | ||
for (const id of userIds) { | ||
// for a single id | ||
// get the user settings | ||
// eslint-disable-next-line no-await-in-loop | ||
const userSettingsData = await this.getSetting(id); | ||
if (userSettingsData != null) { | ||
const { dataValues } = userSettingsData; | ||
// check if the user can recieve notification | ||
if (dataValues.canNotify) { | ||
// check if the user can recieve email notification | ||
if (dataValues.canEmail) { | ||
// get the email of the user | ||
// eslint-disable-next-line no-await-in-loop | ||
const email = await this.getEmail(id); | ||
// send the user an email notification | ||
this.sendMailNotification(email, message); | ||
} | ||
// send default in app mail | ||
// eslint-disable-next-line no-await-in-loop | ||
await this.sendInAppNotification(id, message); | ||
} | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* This function sends an email notification to a user | ||
* @param {String} email - The email of the user | ||
* @param {String} message - This is the notification message | ||
* @returns {Boolean} - returns a boolean | ||
*/ | ||
static async sendMailNotification(email, message) { | ||
const data = { | ||
email, | ||
subject: 'Notification', | ||
mailContext: { | ||
message | ||
}, | ||
template: 'notification' | ||
}; | ||
try { | ||
await Mail.sendMail(data); | ||
return true; | ||
} catch (e) { | ||
logger.log(e); | ||
return false; | ||
} | ||
} | ||
|
||
/** | ||
* This function sends an in-app notification to a user | ||
* @param {String} id - The user id | ||
* @param {String} message - This is the notification message | ||
* @returns {void} | ||
*/ | ||
static async sendInAppNotification(id, message) { | ||
try { | ||
await models.Notification.create({ message, userId: id }); | ||
} catch (e) { | ||
logger.log(e); | ||
} | ||
if (global.socket) { | ||
await global.socket.emit(`notification${id}`, { message }); | ||
} | ||
} | ||
|
||
/** | ||
* This function gets an authenticated users notifications from the database | ||
* @param {Request} request - request object | ||
* @param {Response} response - response object | ||
* @returns {Response} response object | ||
*/ | ||
static async getAllNotifications(request, response) { | ||
// get user id | ||
const userId = request.user.id; | ||
// get users notifications | ||
try { | ||
const notificationData = await models.Notification.findAll({ | ||
where: { userId }, | ||
raw: true | ||
}); | ||
if (notificationData == null) { | ||
return Response.send(response, STATUS.OK, null, 'No notifications'); | ||
} | ||
return Response.send(response, STATUS.OK, notificationData, 'Successful'); | ||
} catch (e) { | ||
logger.log(e); | ||
return Response.send(response, STATUS.BAD_REQUEST, null, 'An error occured', false); | ||
} | ||
} | ||
} | ||
export default NotificationsController; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
database/migrations/20190313141157-create-notifications.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
|
||
|
||
module.exports = { | ||
up: (queryInterface, Sequelize) => queryInterface.createTable('Notifications', { | ||
id: { | ||
allowNull: false, | ||
autoIncrement: true, | ||
primaryKey: true, | ||
type: Sequelize.INTEGER | ||
}, | ||
message: { | ||
type: Sequelize.STRING, | ||
allowNull: false | ||
}, | ||
createdAt: { | ||
allowNull: false, | ||
type: Sequelize.DATE | ||
}, | ||
updatedAt: { | ||
allowNull: false, | ||
type: Sequelize.DATE | ||
}, | ||
userId: { | ||
allowNull: false, | ||
type: Sequelize.INTEGER, | ||
onDelete: 'CASCADE', | ||
references: { | ||
model: 'Users', | ||
key: 'id', | ||
} | ||
} | ||
}), | ||
down: (queryInterface, Sequelize) => queryInterface.dropTable('Notifications') | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/** | ||
* A model class representing user resource | ||
* | ||
* @param {Sequelize} sequelize - Sequelize object | ||
* @param {Sequelize.DataTypes} DataTypes - A convinient object holding data types | ||
* @return {Sequelize.Model} - User model | ||
*/ | ||
|
||
const Notification = (sequelize, DataTypes) => { | ||
/** | ||
* @type {Sequelize.Model} | ||
*/ | ||
const NotificationSchema = sequelize.define('Notification', { | ||
message: { | ||
type: DataTypes.STRING, | ||
allowNull: false | ||
}, | ||
createdAt: { | ||
type: DataTypes.DATE, | ||
defaultValue: sequelize.NOW | ||
}, | ||
updatedAt: { | ||
type: DataTypes.DATE, | ||
defaultValue: sequelize.NOW, | ||
onUpdate: sequelize.NOW | ||
} | ||
}, {}); | ||
|
||
NotificationSchema.associate = (models) => { | ||
NotificationSchema.belongsTo(models.User, { | ||
foreignKey: 'userId', | ||
targetKey: 'id', | ||
onDelete: 'CASCADE' | ||
}); | ||
}; | ||
return NotificationSchema; | ||
}; | ||
|
||
export default Notification; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import express from 'express'; | ||
import notificationsController from '../controllers/notificationsController'; | ||
import middlewares from '../middlewares'; | ||
|
||
const notificationsRouter = express.Router(); | ||
|
||
|
||
/** | ||
* /api/v1/users/confirm_account: | ||
* get: | ||
* tags: | ||
* - Notifications | ||
* description: Get all of a users notifications | ||
* produces: | ||
* - application/json | ||
* parameters: | ||
* - name: Authorization | ||
* description: Auth token | ||
* in: header | ||
* required: true | ||
* type: string | ||
* responses: | ||
* 200: | ||
* description: OK | ||
* schema: | ||
* type: object | ||
*/ | ||
notificationsRouter.get( | ||
'/', | ||
middlewares.authenticate, | ||
notificationsController.getAllNotifications | ||
); | ||
|
||
export default notificationsRouter; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.