Repository navigation
Expand file tree
/
Copy pathapp.js
More file actions
148 lines (132 loc) · 5.34 KB
/
Copy pathapp.js
File metadata and controls
148 lines (132 loc) · 5.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/**
* The application entry point
*/
require('./src/bootstrap')
const _ = require('lodash')
const config = require('config')
const express = require('express')
const cors = require('cors')
const HttpStatus = require('http-status-codes')
const interceptor = require('express-interceptor')
const schedule = require('node-schedule')
const logger = require('./src/common/logger')
const eventHandlers = require('./src/eventHandlers')
const interviewService = require('./src/services/InterviewService')
const { processScheduler } = require('./src/services/PaymentSchedulerService')
const { sendSurveys } = require('./src/services/SurveyService')
const notificationSchedulerService = require('./src/services/NotificationsSchedulerService')
const { WeeklySurveySwitch } = require('./app-constants')
// setup express app
const app = express()
app.use(cors({
// Allow browsers access pagination data in headers
exposedHeaders: ['X-Page', 'X-Per-Page', 'X-Total', 'X-Total-Pages', 'X-Prev-Page', 'X-Next-Page']
}))
app.use((...args) => {
const [req, res, next] = args
// For test nylas webhook, we need raw buffer
// Here i sCustom Middleware to compute rawBody. Unfortunately using
// JSON.stringify(req.body) will remove spaces and newlines, so verification
// will fail. We must add this middleware to ensure we're computing the correct
// signature
if (req.path.match(/\/taas-teams\/nylas-webhooks/i)) {
req.rawBody = ''
req.on('data', (chunk) => (req.rawBody += chunk))
req.on('error', () => res.status(500).send('Error parsing body'))
req.on('end', () => {
// because the stream has been consumed, other parsers like bodyParser.json
// cannot stream the request data and will time out so we must explicitly parse the body
try {
req.body = req.rawBody.length ? JSON.parse(req.rawBody) : {}
next()
} catch (err) {
res.status(500).send('Error parsing body')
}
})
return
}
return express.json()(...args)
})
app.use(express.urlencoded({ extended: true }))
app.set('port', config.PORT)
// intercept the response body from jwtAuthenticator
app.use(interceptor((req, res) => {
return {
isInterceptable: () => {
return res.statusCode === 403
},
intercept: (body, send) => {
let obj
if (body.length > 0) {
try {
obj = JSON.parse(body)
} catch (e) {
logger.error('Invalid response body.')
}
}
if (obj && _.get(obj, 'result.content.message')) {
const ret = { message: obj.result.content.message }
res.statusCode = 401
send(JSON.stringify(ret))
} else {
send(body)
}
}
}
}))
// Register routes
require('./app-routes')(app)
// The error handler
// eslint-disable-next-line no-unused-vars
app.use((err, req, res, next) => {
logger.logFullError(err, { component: 'app', signature: req.signature || `${req.method}_${req.url}` })
const errorResponse = {}
const status = err.isJoi ? HttpStatus.BAD_REQUEST : (err.status || err.httpStatus || HttpStatus.INTERNAL_SERVER_ERROR)
if (_.isArray(err.details)) {
if (err.isJoi) {
_.map(err.details, (e) => {
if (e.message) {
if (_.isUndefined(errorResponse.message)) {
errorResponse.message = e.message
} else {
errorResponse.message += `, ${e.message}`
}
}
})
}
}
if (err.response) {
// extract error message from V3/V5 API
errorResponse.message = _.get(err, 'response.body.result.content.message') || _.get(err, 'response.body.message')
}
if (_.isUndefined(errorResponse.message)) {
if (err.message && (err.httpStatus || status !== HttpStatus.INTERNAL_SERVER_ERROR)) {
errorResponse.message = err.message
} else {
errorResponse.message = 'Internal server error'
}
}
res.status(status).json(errorResponse)
})
const server = app.listen(app.get('port'), () => {
logger.info({ component: 'app', message: `Express server listening on port ${app.get('port')}` })
eventHandlers.init()
// schedule updateCompletedInterviews to run every hour
schedule.scheduleJob(config.CRON_UPDATE_COMPLETED_INTERVIEWS, interviewService.updateCompletedInterviews)
// schedule sendSurveys
if (WeeklySurveySwitch.ON === config.WEEKLY_SURVEY.SWITCH) {
schedule.scheduleJob(config.WEEKLY_SURVEY.CRON, sendSurveys)
}
// schedule payment processing
schedule.scheduleJob(config.PAYMENT_PROCESSING.CRON, processScheduler)
schedule.scheduleJob(config.CRON_CANDIDATE_REVIEW, notificationSchedulerService.sendCandidatesAvailableNotifications)
schedule.scheduleJob(config.CRON_INTERVIEW_COMING_UP, notificationSchedulerService.sendInterviewComingUpNotifications)
schedule.scheduleJob(config.CRON_INTERVIEW_COMPLETED, notificationSchedulerService.sendInterviewCompletedNotifications)
schedule.scheduleJob(config.CRON_POST_INTERVIEW, notificationSchedulerService.sendPostInterviewActionNotifications)
schedule.scheduleJob(config.CRON_UPCOMING_RESOURCE_BOOKING, notificationSchedulerService.sendResourceBookingExpirationNotifications)
schedule.scheduleJob(config.CRON_INTERVIEW_EXPIRED, notificationSchedulerService.sendInterviewExpiredNotifications)
schedule.scheduleJob(config.CRON_INTERVIEW_SCHEDULE_REMINDER, notificationSchedulerService.sendInterviewScheduleReminderNotifications)
})
if (process.env.NODE_ENV === 'test') {
module.exports = server
}