Skip to content

Instantly share code, notes, and snippets.

@mrfelton
Created June 29, 2016 21:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrfelton/a8f28a6a9203d4e122b1ea8fe54f6f89 to your computer and use it in GitHub Desktop.
Save mrfelton/a8f28a6a9203d4e122b1ea8fe54f6f89 to your computer and use it in GitHub Desktop.
Example fullcube webhook client implementation
const bodyParser = require('body-parser')
const crypto = require('crypto')
const logger = require('fullcube-logger')
module.exports = function resthookBootFn(app) {
/**
* Calculate a secret token based on the payload and the shared secret
* @param secret
* @param payload
* @returns {*}
*/
function getXHookSecret(secret, payload) {
return crypto.createHmac('sha1', secret).update(JSON.stringify(payload)).digest('hex')
}
app.use(bodyParser.json())
app.post('/resthook/incoming', (req, res) => {
logger.info('Incoming webhook received!')
const payload = req.body
const headers = req.headers
if (headers['x-hook-secret']) {
if (getXHookSecret(app.settings.fc.xTokenSecret, payload.data) !== headers['x-hook-secret']) {
const msg = 'Error validating x-hook-secret header'
logger.info(msg)
return res.status(401).send(msg)
}
logger.info('Valid x-hook-secret header')
}
if (!payload && !payload.event) {
return res.send('No payload received')
}
// Random failure 1 in 10 times
if ((Math.floor(Math.random() * 10) + 1) === 5) {
return res.status(500).send('Random generated failure')
}
// Random timeout between 1 and 5 seconds
const timeout = Math.floor(Math.random() * 5000) + 1000
const result = payload
logger.info('result', result)
switch (payload.event) {
case 'Person.created': {
app.models.Account
.upsert(payload.data.person)
.then(item => {
logger.info('Person.created item', item)
result.item = item
setTimeout(() => res.send(result), timeout)
})
.catch(err => {
logger.info('Person.created err', err)
res.status(500).send(err)
})
break
}
case 'Person.updated': {
app.models.Account
.upsert(payload.data.person)
.then(item => {
logger.info('Person.updated item', item)
result.item = item
setTimeout(() => res.send(result), timeout)
})
.catch(err => {
logger.info('Person.updated err', err)
res.status(500).send(err)
})
break
}
case 'Person.lapsed': {
app.models.Account
.findById(payload.data.person.id)
.then(item => item.updateAttribute('status', 'lapsed'))
.then(item => {
result.item = item
setTimeout(() => res.send(result), timeout)
})
.catch(err => {
logger.info('Person.lapsed err', err)
res.status(500).send(err)
})
break
}
case 'Person.subscribed': {
app.models.Account
.findById(payload.data.person.id)
.then(item => item.updateAttribute('status', 'subscribed'))
.then(item => {
result.item = item
setTimeout(() => res.send(result), timeout)
})
.catch(err => {
logger.info('Person.subscribed err', err)
res.status(500).send(err)
})
break
}
case 'Person.doPasswordReset':
case 'Person.doWelcomeEmail': {
const msg = `${payload.event} accepted but not implemented`
logger.info(msg)
res.send(msg)
break
}
default: {
const err = `Unknown payload name ${payload.event}`
logger.info(err)
res.status(400).send(err)
}
}
return null
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment