diff --git a/app/config.js b/app/config.js index 7ca8931c1..859a514db 100644 --- a/app/config.js +++ b/app/config.js @@ -20,6 +20,7 @@ if (ENV === 'production') { } const DEFAULT_TEST_USER = 'ipr-bamboo-admin'; +const DEFAULT_EMAIL_ADDRESS = 'rpletz'; const DEFAULTS = { env: ENV, @@ -46,6 +47,9 @@ const DEFAULTS = { testing: { username: DEFAULT_TEST_USER, }, + email: { + email: DEFAULT_EMAIL_ADDRESS, + }, log: { level: DEFAULT_LOG_LEVEL, }, @@ -129,6 +133,12 @@ const CONFIG = nconf 'testing.username': { alias: 'testing:username', }, + 'email.email': { + alias: 'email.email', + }, + 'email.password': { + alias: 'email.password', + }, 'log.level': { alias: 'log:level', }, diff --git a/app/constants.js b/app/constants.js index 629c2c93d..3ec659ca1 100644 --- a/app/constants.js +++ b/app/constants.js @@ -9,6 +9,9 @@ module.exports = { msi: 'msi', tmb: 'tmburMutationBurden', }, + NOTIFICATION_EVENT: { + USER_BOUND: 'userBound', + }, KB_PIVOT_COLUMN: 'variantType', GENE_LINKED_VARIANT_MODELS: [ 'expressionVariants', diff --git a/app/libs/email.js b/app/libs/email.js new file mode 100644 index 000000000..8a94c675e --- /dev/null +++ b/app/libs/email.js @@ -0,0 +1,90 @@ +const nodemailer = require('nodemailer'); +const CONFIG = require('../config'); +const db = require('../models'); + +const {email, password} = CONFIG.get('email'); + +const sendEmail = (subject, text, toEmail) => { + const transporter = nodemailer.createTransport({ + host: 'webmail.bcgsc.ca', + auth: { + user: email, + pass: password, + }, + tls: { + rejectUnauthorized: false, + }, + }); + + const mailOptions = { + from: `${email}@bcgsc.ca`, + to: toEmail, + subject, + text, + }; + + transporter.sendMail(mailOptions, (error, info) => { + if (error) { + console.log(error); + } else { + console.log(`Email sent: ${info.response}`); + } + }); +}; + +const getEmailList = async (triggers) => { + const notifs = await db.models.notification.scope('extended').findAll({ + where: triggers, + }); + + const emailList = []; + for (const notif of notifs) { + if (notif.user) { + if (!emailList.includes(notif.user.email)) { + emailList.push(notif.user.email); + } + } else if (notif.userGroup) { + for (const groupUser of notif.userGroup.users) { + if (!emailList.includes(groupUser.email)) { + emailList.push(groupUser.email); + } + } + } + } + + return emailList; +}; + +const notifyUsers = async (subject, text, triggers) => { + const emailList = await getEmailList(triggers); + + const transporter = nodemailer.createTransport({ + host: 'webmail.bcgsc.ca', + auth: { + user: email, + pass: password, + }, + tls: { + rejectUnauthorized: false, + }, + }); + + emailList.forEach((toEmail) => { + const mailOptions = { + from: `${email}@bcgsc.ca`, + to: toEmail, + subject, + text, + }; + + transporter.sendMail(mailOptions, (error, info) => { + if (error) { + console.log(error); + } else { + console.log(`Email sent: ${info.response}`); + } + }); + }); +}; + +module.exports = {sendEmail, getEmailList, notifyUsers}; diff --git a/app/models/notification/notification.js b/app/models/notification/notification.js index 0a0d8927a..1145470ab 100644 --- a/app/models/notification/notification.js +++ b/app/models/notification/notification.js @@ -71,6 +71,14 @@ module.exports = (sequelize, Sq) => { {model: sequelize.models.project.scope('minimal'), as: 'project'}, ], }, + extended: { + include: [ + {model: sequelize.models.user, as: 'user'}, + {model: sequelize.models.userGroup, as: 'userGroup', include: {model: sequelize.models.user, as: 'users', through: {attributes: []}}}, + {model: sequelize.models.template, as: 'template'}, + {model: sequelize.models.project, as: 'project'}, + ], + }, }, }, ); diff --git a/app/routes/notification/notification.js b/app/routes/notification/notification.js index 781552303..328487736 100644 --- a/app/routes/notification/notification.js +++ b/app/routes/notification/notification.js @@ -164,13 +164,19 @@ router.route('/') } try { - const newnotif = await db.models.notification.create({ - projectId: req.body.project_id, userId: req.body.user_id ? req.body.user_id : null, userGroupId: req.body.user_group_id ? req.body.user_group_id : null, eventType: req.body.event_type, templateId: req.body.template_id, + const newnotif = await db.models.notification.findOrCreate({ + where: { + projectId: req.body.project_id, + userId: req.body.user_id ? req.body.user_id : null, + userGroupId: req.body.user_group_id ? req.body.user_group_id : null, + eventType: req.body.event_type, + templateId: req.body.template_id, + }, }); // Load new notif with associations const result = await db.models.notification.scope('public').findOne({ - where: {id: newnotif.id}, + where: {id: newnotif[0].id}, }); return res.status(HTTP_STATUS.CREATED).json(result); diff --git a/app/routes/report/reportUser.js b/app/routes/report/reportUser.js index 17917a5e2..dfd546553 100644 --- a/app/routes/report/reportUser.js +++ b/app/routes/report/reportUser.js @@ -8,7 +8,8 @@ const router = express.Router({mergeParams: true}); const schemaGenerator = require('../../schemas/schemaGenerator'); const validateAgainstSchema = require('../../libs/validateAgainstSchema'); -const {REPORT_CREATE_BASE_URI} = require('../../constants'); +const email = require('../../libs/email'); +const {REPORT_CREATE_BASE_URI, NOTIFICATION_EVENT} = require('../../constants'); const {REPORT_EXCLUDE} = require('../../schemas/exclude'); // Generate create schema @@ -129,6 +130,21 @@ router.route('/') addedBy_id: req.user.id, }); + // Try sending email + try { + await email.notifyUsers( + `${bindUser.firstName} ${bindUser.lastName} has been bound to a report`, + `User ${bindUser.firstName} ${bindUser.lastName} has been bound to report ${req.report.ident}`, + { + eventType: NOTIFICATION_EVENT.USER_BOUND, + templateId: req.report.templateId, + }, + ); + logger.info('Email sent successfully'); + } catch (error) { + logger.error(`Email not sent successfully: ${error}`); + } + await req.report.reload(); return res.status(HTTP_STATUS.CREATED).json(req.report.view('public')); } catch (error) { diff --git a/emaildebug/emailtest.js b/emaildebug/emailtest.js new file mode 100644 index 000000000..35b7c4140 --- /dev/null +++ b/emaildebug/emailtest.js @@ -0,0 +1,53 @@ +const nodemailer = require('nodemailer'); +const Queue = require('bull'); + +const emailQueue = new Queue('emails'); + +const email = 'rpletz'; +const password = 'password'; + +const transporter = nodemailer.createTransport({ + host: 'webmail.bcgsc.ca', + auth: { + user: email, + pass: password, + }, + tls: { + rejectUnauthorized: false, + }, + pool: true, +}); + +const mail = { + to: `${email}@bcgsc.ca`, + subject: 'subject', + body: 'body', +}; + +emailQueue.process(async (job) => { + const {to, subject, body} = job.data; + const mailOptions = { + from: `${email}@bcgsc.ca`, + to, + subject, + text: body, + }; + await transporter.sendMail(mailOptions, (error, info) => { + if (error) { + console.log(error); + } else { + console.log(`Email sent: ${info.response}`); + } + }); +}); + +emailQueue.add(mail); +emailQueue.add(mail); +emailQueue.add(mail); +emailQueue.add(mail); +emailQueue.add(mail); +emailQueue.add(mail); +emailQueue.add(mail); +emailQueue.add(mail); +emailQueue.add(mail); +emailQueue.add(mail); diff --git a/package-lock.json b/package-lock.json index 118e3288b..d39863293 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@alt3/sequelize-to-json-schemas": "^0.3.56", "ajv": "^6.10.2", "bcryptjs": "~2.4.3", + "bull": "^4.11.5", "compression": "^1.7.4", "cors": "~2.8.5", "exceljs": "^4.3.0", @@ -27,6 +28,7 @@ "morgan": "^1.10.0", "nconf": "^0.12.0", "node-gyp": "^9.4.0", + "nodemailer": "^6.9.4", "path-to-regexp": "^6.2.1", "pg": "^8.7.3", "pg-native": "^3.0.1", @@ -1611,6 +1613,78 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz", + "integrity": "sha512-9bfjwDxIDWmmOKusUcqdS4Rw+SETlp9Dy39Xui9BEGEk19dDwH0jhipwFzEff/pFg95NKymc6TOTbRKcWeRqyQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.2.tgz", + "integrity": "sha512-lwriRAHm1Yg4iDf23Oxm9n/t5Zpw1lVnxYU3HnJPTi2lJRkKTrps1KVgvL6m7WvmhYVt/FIsssWay+k45QHeuw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.2.tgz", + "integrity": "sha512-MOI9Dlfrpi2Cuc7i5dXdxPbFIgbDBGgKR5F2yWEa6FVEtSWncfVNKW5AKjImAQ6CZlBK9tympdsZJ2xThBiWWA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.2.tgz", + "integrity": "sha512-FU20Bo66/f7He9Fp9sP2zaJ1Q8L9uLPZQDub/WlUip78JlPeMbVL8546HbZfcW9LNciEXc8d+tThSJjSC+tmsg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.2.tgz", + "integrity": "sha512-gsWNDCklNy7Ajk0vBBf9jEx04RUxuDQfBse918Ww+Qb9HCPoGzS+XJTLe96iN3BVK7grnLiYghP/M4L8VsaHeA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.2.tgz", + "integrity": "sha512-O+6Gs8UeDbyFpbSh2CPEz/UOrrdWPTBYNblZK5CxxLisYt4kGX3Sc+czffFonyjiGSq3jWLwJS/CCJc7tBr4sQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2834,6 +2908,37 @@ "node": ">=0.2.0" } }, + "node_modules/bull": { + "version": "4.11.5", + "resolved": "https://registry.npmjs.org/bull/-/bull-4.11.5.tgz", + "integrity": "sha512-9jazyvBBYr55IRDkfJh/mJjWiq8NJUMoCC5zTuBX4JhkZvVXegnwsaIa1jr3x9xwSxGvWEhwQ9lt1jlCT5j6pQ==", + "dependencies": { + "cron-parser": "^4.2.1", + "get-port": "^5.1.1", + "ioredis": "^5.3.2", + "lodash": "^4.17.21", + "msgpackr": "^1.5.2", + "semver": "^7.5.2", + "uuid": "^8.3.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/bull/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -3400,6 +3505,17 @@ "node": ">= 10" } }, + "node_modules/cron-parser": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", + "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", + "dependencies": { + "luxon": "^3.2.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -3541,9 +3657,9 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" }, "node_modules/denque": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz", - "integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", "engines": { "node": ">=0.10" } @@ -5414,7 +5530,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", - "dev": true, "engines": { "node": ">=8" }, @@ -5895,14 +6010,14 @@ } }, "node_modules/ioredis": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.1.0.tgz", - "integrity": "sha512-HYHnvwxFwefeUBj0hZFejLvd8Q/YNAfnZlZG/hSRxkRhXMs1H8soMEVccHd1WlLrKkynorXBsAtqDGskOdAfVQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.2.tgz", + "integrity": "sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==", "dependencies": { "@ioredis/commands": "^1.1.1", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", - "denque": "^2.0.1", + "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", @@ -8642,6 +8757,14 @@ "es5-ext": "~0.10.2" } }, + "node_modules/luxon": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz", + "integrity": "sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==", + "engines": { + "node": ">=12" + } + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -9082,6 +9205,35 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "node_modules/msgpackr": { + "version": "1.9.9", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.9.9.tgz", + "integrity": "sha512-sbn6mioS2w0lq1O6PpGtsv6Gy8roWM+o3o4Sqjd6DudrL/nOugY+KyJUimoWzHnf9OkO0T6broHFnYE/R05t9A==", + "optionalDependencies": { + "msgpackr-extract": "^3.0.2" + } + }, + "node_modules/msgpackr-extract": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.2.tgz", + "integrity": "sha512-SdzXp4kD/Qf8agZ9+iTu6eql0m3kWm1A2y1hkpTeVNENutaB0BwHlSvAIaMxwntmRUAUjon2V4L8Z/njd0Ct8A==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "node-gyp-build-optional-packages": "5.0.7" + }, + "bin": { + "download-msgpackr-prebuilds": "bin/download-prebuilds.js" + }, + "optionalDependencies": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.2", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.2" + } + }, "node_modules/nan": { "version": "2.17.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", @@ -9279,6 +9431,17 @@ "node": "^12.13 || ^14.13 || >=16" } }, + "node_modules/node-gyp-build-optional-packages": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz", + "integrity": "sha512-YlCCc6Wffkx0kHkmam79GKvDQ6x+QZkMjFGrIMxgFNILFvGSbCp2fCBC55pGTT9gVaz8Na5CLmxt/urtzRv36w==", + "optional": true, + "bin": { + "node-gyp-build-optional-packages": "bin.js", + "node-gyp-build-optional-packages-optional": "optional.js", + "node-gyp-build-optional-packages-test": "build-test.js" + } + }, "node_modules/node-gyp/node_modules/nopt": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-6.0.0.tgz", @@ -9329,6 +9492,14 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==" }, + "node_modules/nodemailer": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.4.tgz", + "integrity": "sha512-CXjQvrQZV4+6X5wP6ZIgdehJamI63MFoYFGGPtHudWym9qaEHDNdPzaj5bfMCvxG1vhAileSWW90q7nL0N36mA==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", @@ -13430,6 +13601,42 @@ "@jridgewell/sourcemap-codec": "1.4.14" } }, + "@msgpackr-extract/msgpackr-extract-darwin-arm64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-arm64/-/msgpackr-extract-darwin-arm64-3.0.2.tgz", + "integrity": "sha512-9bfjwDxIDWmmOKusUcqdS4Rw+SETlp9Dy39Xui9BEGEk19dDwH0jhipwFzEff/pFg95NKymc6TOTbRKcWeRqyQ==", + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-darwin-x64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-darwin-x64/-/msgpackr-extract-darwin-x64-3.0.2.tgz", + "integrity": "sha512-lwriRAHm1Yg4iDf23Oxm9n/t5Zpw1lVnxYU3HnJPTi2lJRkKTrps1KVgvL6m7WvmhYVt/FIsssWay+k45QHeuw==", + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-linux-arm": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm/-/msgpackr-extract-linux-arm-3.0.2.tgz", + "integrity": "sha512-MOI9Dlfrpi2Cuc7i5dXdxPbFIgbDBGgKR5F2yWEa6FVEtSWncfVNKW5AKjImAQ6CZlBK9tympdsZJ2xThBiWWA==", + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-linux-arm64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-arm64/-/msgpackr-extract-linux-arm64-3.0.2.tgz", + "integrity": "sha512-FU20Bo66/f7He9Fp9sP2zaJ1Q8L9uLPZQDub/WlUip78JlPeMbVL8546HbZfcW9LNciEXc8d+tThSJjSC+tmsg==", + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-linux-x64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-linux-x64/-/msgpackr-extract-linux-x64-3.0.2.tgz", + "integrity": "sha512-gsWNDCklNy7Ajk0vBBf9jEx04RUxuDQfBse918Ww+Qb9HCPoGzS+XJTLe96iN3BVK7grnLiYghP/M4L8VsaHeA==", + "optional": true + }, + "@msgpackr-extract/msgpackr-extract-win32-x64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@msgpackr-extract/msgpackr-extract-win32-x64/-/msgpackr-extract-win32-x64-3.0.2.tgz", + "integrity": "sha512-O+6Gs8UeDbyFpbSh2CPEz/UOrrdWPTBYNblZK5CxxLisYt4kGX3Sc+czffFonyjiGSq3jWLwJS/CCJc7tBr4sQ==", + "optional": true + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -14372,6 +14579,30 @@ "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", "integrity": "sha1-skV5w77U1tOWru5tmorn9Ugqt7s=" }, + "bull": { + "version": "4.11.5", + "resolved": "https://registry.npmjs.org/bull/-/bull-4.11.5.tgz", + "integrity": "sha512-9jazyvBBYr55IRDkfJh/mJjWiq8NJUMoCC5zTuBX4JhkZvVXegnwsaIa1jr3x9xwSxGvWEhwQ9lt1jlCT5j6pQ==", + "requires": { + "cron-parser": "^4.2.1", + "get-port": "^5.1.1", + "ioredis": "^5.3.2", + "lodash": "^4.17.21", + "msgpackr": "^1.5.2", + "semver": "^7.5.2", + "uuid": "^8.3.0" + }, + "dependencies": { + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, "busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -14800,6 +15031,14 @@ "readable-stream": "^3.4.0" } }, + "cron-parser": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/cron-parser/-/cron-parser-4.9.0.tgz", + "integrity": "sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==", + "requires": { + "luxon": "^3.2.1" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -14904,9 +15143,9 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" }, "denque": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz", - "integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==" }, "depd": { "version": "2.0.0", @@ -16351,8 +16590,7 @@ "get-port": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", - "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", - "dev": true + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==" }, "get-stream": { "version": "6.0.1", @@ -16682,14 +16920,14 @@ } }, "ioredis": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.1.0.tgz", - "integrity": "sha512-HYHnvwxFwefeUBj0hZFejLvd8Q/YNAfnZlZG/hSRxkRhXMs1H8soMEVccHd1WlLrKkynorXBsAtqDGskOdAfVQ==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.3.2.tgz", + "integrity": "sha512-1DKMMzlIHM02eBBVOFQ1+AolGjs6+xEcM4PDL7NqOS6szq7H9jSaEkIUH6/a5Hl241LzW6JLSiAbNvTQjUupUA==", "requires": { "@ioredis/commands": "^1.1.1", "cluster-key-slot": "^1.1.0", "debug": "^4.3.4", - "denque": "^2.0.1", + "denque": "^2.1.0", "lodash.defaults": "^4.2.0", "lodash.isarguments": "^3.1.0", "redis-errors": "^1.2.0", @@ -18763,6 +19001,11 @@ "es5-ext": "~0.10.2" } }, + "luxon": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.4.4.tgz", + "integrity": "sha512-zobTr7akeGHnv7eBOXcRgMeCP6+uyYsczwmeRCauvpvaAltgNyTbLH/+VaEAPUeWBT+1GuNmz4wC/6jtQzbbVA==" + }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -19106,6 +19349,29 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "msgpackr": { + "version": "1.9.9", + "resolved": "https://registry.npmjs.org/msgpackr/-/msgpackr-1.9.9.tgz", + "integrity": "sha512-sbn6mioS2w0lq1O6PpGtsv6Gy8roWM+o3o4Sqjd6DudrL/nOugY+KyJUimoWzHnf9OkO0T6broHFnYE/R05t9A==", + "requires": { + "msgpackr-extract": "^3.0.2" + } + }, + "msgpackr-extract": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/msgpackr-extract/-/msgpackr-extract-3.0.2.tgz", + "integrity": "sha512-SdzXp4kD/Qf8agZ9+iTu6eql0m3kWm1A2y1hkpTeVNENutaB0BwHlSvAIaMxwntmRUAUjon2V4L8Z/njd0Ct8A==", + "optional": true, + "requires": { + "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.2", + "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.2", + "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.2", + "node-gyp-build-optional-packages": "5.0.7" + } + }, "nan": { "version": "2.17.0", "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", @@ -19274,6 +19540,12 @@ } } }, + "node-gyp-build-optional-packages": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.0.7.tgz", + "integrity": "sha512-YlCCc6Wffkx0kHkmam79GKvDQ6x+QZkMjFGrIMxgFNILFvGSbCp2fCBC55pGTT9gVaz8Na5CLmxt/urtzRv36w==", + "optional": true + }, "node-int64": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", @@ -19293,6 +19565,11 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==" }, + "nodemailer": { + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.4.tgz", + "integrity": "sha512-CXjQvrQZV4+6X5wP6ZIgdehJamI63MFoYFGGPtHudWym9qaEHDNdPzaj5bfMCvxG1vhAileSWW90q7nL0N36mA==" + }, "nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", diff --git a/package.json b/package.json index 1f7424afb..0496d4fd9 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "@alt3/sequelize-to-json-schemas": "^0.3.56", "ajv": "^6.10.2", "bcryptjs": "~2.4.3", + "bull": "^4.11.5", "compression": "^1.7.4", "cors": "~2.8.5", "exceljs": "^4.3.0", @@ -33,6 +34,7 @@ "morgan": "^1.10.0", "nconf": "^0.12.0", "node-gyp": "^9.4.0", + "nodemailer": "^6.9.4", "path-to-regexp": "^6.2.1", "pg": "^8.7.3", "pg-native": "^3.0.1",