Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
b354210
return email results
ijadams Sep 23, 2020
0035d38
only return meta
ijadams Sep 23, 2020
15eb9d7
move into results
ijadams Sep 23, 2020
964c5a9
reformat trigger ci build
ijadams Sep 28, 2020
180ef3d
fix test
ijadams Sep 28, 2020
a3f7258
add temporary auth and fix csv download for Contact
ijadams Sep 28, 2020
ffa8e35
fix test
ijadams Sep 28, 2020
4e59ef2
add query param for filter on csv endpoint
ijadams Sep 29, 2020
64d4aed
sort out query param
ijadams Sep 29, 2020
a676d17
fix processed results bug
ijadams Sep 29, 2020
d125654
csv edits
ijadams Sep 29, 2020
76a9a4b
rm auth
ijadams Sep 30, 2020
89a3779
begin work on single email
ijadams Oct 1, 2020
8b50c92
update postman
ijadams Oct 2, 2020
952fba7
add single email contact
ijadams Oct 2, 2020
a701a17
Merge branch 'master' into 188
stoopidJSON Oct 6, 2020
158b9d4
Merge branch 'master' into 188
ijadams504 Oct 9, 2020
e81c2b1
rm log
ijadams504 Oct 9, 2020
6288309
Merge branch 'master' into 188
ijadams504 Oct 9, 2020
cb4f97e
update readme
ijadams504 Oct 20, 2020
fecb795
change error type - from code review
Nov 20, 2020
ac963cc
Merge pull request #313 from joshglazer/188
joshglazer Nov 20, 2020
5dfdbac
changing error status code - from code review
Nov 20, 2020
7bfa55d
Merge pull request #314 from joshglazer/188
joshglazer Nov 20, 2020
15d5bab
Merge branch 'master' of github.com:CodeForBaltimore/Bmore-Responsive…
Nov 20, 2020
0460a9b
Merge pull request #315 from joshglazer/188
joshglazer Nov 20, 2020
3cfb2c2
Merge branch 'master' into 188
blakenan-bellese Nov 24, 2020
12ef324
updated status code
joshglazer Nov 24, 2020
454b84a
Merge pull request #318 from joshglazer/188
joshglazer Nov 24, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 56 additions & 2 deletions Bmore-Responsive.postman_collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@
"response": []
},
{
"name": "Contact Send",
"name": "Contact Send Bulk",
"event": [
{
"listen": "test",
Expand Down Expand Up @@ -620,6 +620,60 @@
},
"response": []
},
{
"name": "Contact Send Single",
"event": [
{
"listen": "test",
"script": {
"id": "b38d3eef-47f0-4f9e-a710-d82c4fef5492",
"exec": [
"//get the 36 character id of the new contact and save it to env variable",
"//this will allow deletion of this in the Delete transaction",
"pm.environment.set(\"newContactId\", pm.response.text().slice(0,36));",
"",
"//confirm that request returns a success code of 200",
"pm.test(\"Status code is 200\", function () {",
" pm.response.to.have.status(200);",
"});"
],
"type": "text/javascript"
}
}
],
"request": {
"method": "POST",
"header": [
{
"key": "token",
"type": "text",
"value": "{{token}}"
}
],
"body": {
"mode": "raw",
"raw": "",
"options": {
"raw": {
"language": "json"
}
}
},
"url": {
"raw": "{{baseUrl}}/contact/send/{{modelType}}/{{id}}",
"host": [
"{{baseUrl}}"
],
"path": [
"contact",
"send",
"{{modelType}}",
"{{id}}"
]
}
},
"response": []
},
{
"name": "Update Contact",
"event": [
Expand Down Expand Up @@ -1406,4 +1460,4 @@
}
],
"protocolProfileBehavior": {}
}
}
8 changes: 4 additions & 4 deletions src/email/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const sendMail = async (to, subject, html, text) => {
* Send a forgot password email.
* @param {string} userEmail email address of the user we're sending to
* @param {string} resetPasswordToken temporary token for the reset password link
*
*
* @returns {Boolean}
*/
const sendForgotPassword = async (userEmail, resetPasswordToken) => {
Expand All @@ -45,8 +45,8 @@ const sendForgotPassword = async (userEmail, resetPasswordToken) => {
await sendMail(
userEmail,
'Password Reset - Healthcare Roll Call',
nunjucks.render('forgot_password_html.njk', { emailResetLink }),
nunjucks.render('forgot_password_text.njk', { emailResetLink })
nunjucks.render('forgot_password_html.njk', {emailResetLink}),
nunjucks.render('forgot_password_text.njk', {emailResetLink})
)
return true
} catch (e) {
Expand Down Expand Up @@ -74,4 +74,4 @@ const sendContactCheckInEmail = async (info) => {
}
}

export default { sendForgotPassword, sendContactCheckInEmail }
export default {sendForgotPassword, sendContactCheckInEmail}
85 changes: 72 additions & 13 deletions src/routes/contact.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import email from '../email'
import models from '../models'
import utils from '../utils'
import validator from 'validator'
import { Router } from 'express'
import {Router} from 'express'

const router = new Router()
router.use(utils.authMiddleware)
Expand Down Expand Up @@ -33,7 +33,7 @@ router.get('/', async (req, res) => {
}
}

const contacts = await models.Contact.findAll({ where })
const contacts = await models.Contact.findAll({where})

// Temp fix for JSON types and Sequelize.
let results = []
Expand Down Expand Up @@ -103,7 +103,7 @@ router.post('/', async (req, res) => {
const response = new utils.Response()
try {
if (req.body.name !== undefined && req.body.name !== '') {
const { name, phone, email, UserId, entities, attributes } = req.body
const {name, phone, email, UserId, entities, attributes} = req.body

// Validating emails
if (email) {
Expand All @@ -115,7 +115,7 @@ router.post('/', async (req, res) => {
}
}

const contact = await models.Contact.create({ name, email, phone, UserId, attributes })
const contact = await models.Contact.create({name, email, phone, UserId, attributes})
let ec

if (entities) {
Expand Down Expand Up @@ -154,10 +154,10 @@ router.post('/send', async (req, res) => {
try {
/** @todo allow for passing entity and contact arrays */
const emails = []
const { entityIds, contactIds, relationshipTitle } = req.body
const {entityIds, contactIds, relationshipTitle} = req.body

if (entityIds === undefined && contactIds === undefined) {
const whereClause = (relationshipTitle !== undefined) ? { where: { relationshipTitle } } : {}
const whereClause = (relationshipTitle !== undefined) ? {where: {relationshipTitle}} : {}
const associations = await models.EntityContact.findAll(whereClause)

if (associations.length < 1) {
Expand Down Expand Up @@ -191,12 +191,71 @@ router.post('/send', async (req, res) => {
email.sendContactCheckInEmail(e)
})

response.setMessage('Contacts emailed')
response.setMessage({
results: {
message: 'Contacts emailed',
total: emails.length
}
})
} catch (e) {
console.error(e)
response.setCode(500)
}

return res.status(response.getCode()).send(response.getMessage())
})


router.post('/send/:type/:id', async (req, res) => {
const response = new utils.Response()

try {
let entity
if (req.params.type.toLowerCase() === 'entity') {
entity = await models.Entity.findById(req.params.id)
} else if (req.params.type.toLowerCase() === 'contact') {
entity = await models.Contact.findOne({
where: {
id: req.params.id
}
})
}

if (entity.email !== null) {
const primary = entity.email.filter(e => e.isPrimary === 'true').length ? entity.email.filter(e => e.isPrimary === 'true')[0] : entity.email[0]
// short-lived temporary token that only lasts one hour
const temporaryToken = await utils.getToken(req.params.id, primary.address, 'Entity')

const e = {
email: primary.address,
name: entity.name,
entityName: entity.name,
entityId: entity.id,
token: temporaryToken
}
email.sendContactCheckInEmail(e).then(() => {
response.setMessage(`${entity.name} emailed sent.`)
response.setCode(200)
}, err => {
response.setMessage('There was an error: ' + err)
response.setCode(500)
})
} else {
response.setMessage('Email Address not found.')
response.setCode(404)
}

response.setMessage({
results: {
message: `${entity.name} emailed.`,
}
})
} catch (e) {
console.error(e)
response.setCode(500)
}


return res.status(response.getCode()).send(response.getMessage())
})

Expand All @@ -205,7 +264,7 @@ router.put('/', async (req, res) => {
const response = new utils.Response()
try {
if (validator.isUUID(req.body.id)) {
const { id, name, phone, email, UserId, entities, attributes } = req.body
const {id, name, phone, email, UserId, entities, attributes} = req.body

const contact = await models.Contact.findOne({
where: {
Expand Down Expand Up @@ -299,7 +358,7 @@ router.post('/link/:contact_id', async (req, res) => {
}
})

let i=0
let i = 0
for (const entity of req.body.entities) {
const entityToLink = await models.Entity.findOne({
where: {
Expand All @@ -312,11 +371,11 @@ router.post('/link/:contact_id', async (req, res) => {
entityId: entityToLink.id,
contactId: contact.id,
}

if (entity.title) {
ec.relationshipTitle = contact.title
}

await models.EntityContact.createIfNew(ec)
i++
}
Expand Down Expand Up @@ -350,7 +409,7 @@ router.post('/unlink/:contact_id', async (req, res) => {
}
})

let i=0
let i = 0
for (const entity of req.body.entities) {
const entityToUnLink = await models.Entity.findOne({
where: {
Expand All @@ -366,7 +425,7 @@ router.post('/unlink/:contact_id', async (req, res) => {
contactId: contact.id
}
})

await ec.destroy()
i++
}
Expand Down
45 changes: 37 additions & 8 deletions src/routes/csv.js
Original file line number Diff line number Diff line change
@@ -1,36 +1,65 @@
import { Router } from 'express'
import {Router} from 'express'
import utils from '../utils'
import { parseAsync } from 'json2csv'
import {parseAsync} from 'json2csv'
import {Op} from 'sequelize'

const router = new Router()
router.use(utils.authMiddleware)

// Gets a data dump from the passed in model (if it exists).
router.get('/:model_type', async (req, res) => {

const response = new utils.Response()
const modelType = req.params.model_type

try {

/** @todo refactor this when we change how CSV's are delivered. */
// eslint-disable-next-line no-prototype-builtins
if (req.context.models.hasOwnProperty(modelType) && modelType !== 'User' && modelType !== 'UserRole') {
/** @todo add filtering */
const results = await req.context.models[modelType].findAll({ raw: true })
let options = {raw: true}
// search by name if filter query param is included
if (req.query && req.query.filter && req.query.filter.length) {
options.where = {
name: {
[Op.iLike]: '%' + req.query.filter + '%'
}
}
}

const processedResults = await utils.processResults(results, modelType)
/** @todo add a search filter for status once data has a status field. */
let results = await req.context.models[modelType].findAll(options)

if (results.length !== 0) {
response.setMessage = await parseAsync(JSON.parse(JSON.stringify(processedResults)), Object.keys(results[0]), {})
const processedResults = await utils.processResults(results, modelType)
const fields = Object.keys(results[0])
parseAsync(processedResults, {fields}).then(csv => {
response.setMessage(csv)
const dateObj = new Date()
const dateStr = `${dateObj.getUTCMonth() + 1}_${dateObj.getUTCDate()}_${dateObj.getUTCFullYear()}`
res.setHeader('Content-disposition', `attachment; filename=HCRC_${modelType}_${dateStr}.csv`)
res.set('Content-Type', 'text/csv')
return res.status(response.getCode()).send(response.getMessage())
}, err => {
response.setCode(500)
response.setMessage('Not able to parse data: ' + err)
return res.status(response.getCode()).send(response.getMessage())
})
} else {
response.setCode(200)
response.setMessage('No results found')
return res.status(response.getCode()).send(response.getMessage())
}
} else {
response.setCode(400)
response.setMessage('Model type is invalid')
return res.status(response.getCode()).send(response.getMessage())
}
} catch (e) {
console.error(e)
response.setCode(500)
return res.status(response.getCode()).send(response.getMessage())
}

return res.status(response.getCode()).send(response.getMessage())
})

export default router
6 changes: 3 additions & 3 deletions src/tests/contact.routes.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,11 @@ describe('Contact tests', function() {
.post('/contact/send')
.set('Accept', 'application/json')
.set('authorization', authHeader)
.expect('Content-Type', 'text/html; charset=utf-8')
.expect('Content-Type', 'application/json; charset=utf-8')
.expect(200)
.end((err, res) => {
if (err) return done(err)
expect(res.text).to.equal('Contacts emailed')
expect(res.body.results.message).to.equal('Contacts emailed')
done()
})
} catch(e) {
Expand Down Expand Up @@ -259,7 +259,7 @@ describe('Contact tests', function() {
.get('/csv/Contact')
.set('Accept', 'application/json')
.set('authorization', authHeader)
.expect('Content-Type', 'text/html; charset=utf-8')
.expect('Content-Type', 'text/csv; charset=utf-8')
.expect(200)
// eslint-disable-next-line no-unused-vars
.end((err, res) => {
Expand Down
Loading