From b354210b83fd3919a8e09fe460a8a5510e237844 Mon Sep 17 00:00:00 2001 From: ijadams Date: Wed, 23 Sep 2020 14:01:19 -0500 Subject: [PATCH 01/20] return email results --- src/routes/contact.js | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/routes/contact.js b/src/routes/contact.js index 5047b9d2..8bab6f14 100644 --- a/src/routes/contact.js +++ b/src/routes/contact.js @@ -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) @@ -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 = [] @@ -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) { @@ -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) { @@ -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) { @@ -190,7 +190,13 @@ router.post('/send', async (req, res) => { email.sendContactCheckInEmail(e) }) - response.setMessage('Contacts emailed') + response.setMessage({ + _meta: { + total: emails.length + }, + message: 'Contacts emailed', + results: emails + }) } catch (e) { console.error(e) response.setCode(500) @@ -204,7 +210,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: { @@ -298,7 +304,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: { @@ -311,11 +317,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++ } @@ -349,7 +355,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: { @@ -365,7 +371,7 @@ router.post('/unlink/:contact_id', async (req, res) => { contactId: contact.id } }) - + await ec.destroy() i++ } From 0035d38f7fc0b9e776e2e4f3455f7aeb4dc25858 Mon Sep 17 00:00:00 2001 From: ijadams Date: Wed, 23 Sep 2020 14:01:43 -0500 Subject: [PATCH 02/20] only return meta --- src/routes/contact.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/routes/contact.js b/src/routes/contact.js index 8bab6f14..6d0f4020 100644 --- a/src/routes/contact.js +++ b/src/routes/contact.js @@ -195,7 +195,6 @@ router.post('/send', async (req, res) => { total: emails.length }, message: 'Contacts emailed', - results: emails }) } catch (e) { console.error(e) From 15eb9d7fc44725f357be34023be6de3b70e2f317 Mon Sep 17 00:00:00 2001 From: ijadams Date: Wed, 23 Sep 2020 14:26:15 -0500 Subject: [PATCH 03/20] move into results --- src/routes/contact.js | 6 +- swagger.json | 3045 ++++++++++++++++++++++------------------- 2 files changed, 1623 insertions(+), 1428 deletions(-) diff --git a/src/routes/contact.js b/src/routes/contact.js index 6d0f4020..5b621187 100644 --- a/src/routes/contact.js +++ b/src/routes/contact.js @@ -191,10 +191,10 @@ router.post('/send', async (req, res) => { }) response.setMessage({ - _meta: { + results: { + message: 'Contacts emailed', total: emails.length - }, - message: 'Contacts emailed', + } }) } catch (e) { console.error(e) diff --git a/swagger.json b/swagger.json index e797cc16..1dbeb813 100644 --- a/swagger.json +++ b/swagger.json @@ -1,208 +1,233 @@ { - "openapi" : "3.0.1", - "servers" : [ { - "description" : "localhost", - "url" : "http://localhost:3000" - } ], - "info" : { - "description" : "An emergency response and contact management API.", - "version" : "1.3.3", - "title" : "Bmore Responsive", - "contact" : { - "email" : "hello@codeforbaltimore.org" + "openapi": "3.0.1", + "servers": [ + { + "description": "localhost", + "url": "http://localhost:3000" + } + ], + "info": { + "description": "An emergency response and contact management API.", + "version": "1.3.3", + "title": "Bmore Responsive", + "contact": { + "email": "hello@codeforbaltimore.org" }, - "license" : { - "name" : "Apache 2.0", - "url" : "http://www.apache.org/licenses/LICENSE-2.0.html" + "license": { + "name": "Apache 2.0", + "url": "http://www.apache.org/licenses/LICENSE-2.0.html" } }, - "tags" : [ { - "name" : "developer", - "description" : "Operations available to regular developers" - }, { - "name" : "user", - "description" : "Operations related to system users" - }, { - "name" : "userRole", - "description" : "Operations related to userRole" - }, { - "name" : "entity", - "description" : "Operations related to entities" - }, { - "name" : "contact", - "description" : "Operations related to contacts" - }, { - "name" : "csv", - "description" : "Operations related to csv" - } ], - "security" : [ + "tags": [ + { + "name": "developer", + "description": "Operations available to regular developers" + }, + { + "name": "user", + "description": "Operations related to system users" + }, + { + "name": "userRole", + "description": "Operations related to userRole" + }, + { + "name": "entity", + "description": "Operations related to entities" + }, + { + "name": "contact", + "description": "Operations related to contacts" + }, + { + "name": "csv", + "description": "Operations related to csv" + } + ], + "security": [ { - "bearerAuth" : [] + "bearerAuth": [] } ], - "paths" : { - "/health" : { - "get" : { - "security" : [], - "tags" : [ "developer" ], - "summary" : "returns a healthcheck", - "description" : "This returns simple system information\n", - "responses" : { - "200" : { - "description" : "the system healthcheck", - "content" : { - "application/json" : { - "schema" : { - "$ref" : "#/components/schemas/HealthcheckItem" + "paths": { + "/health": { + "get": { + "security": [], + "tags": [ + "developer" + ], + "summary": "returns a healthcheck", + "description": "This returns simple system information\n", + "responses": { + "200": { + "description": "the system healthcheck", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HealthcheckItem" } } } }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } } }, - "/user/login" : { - "post" : { - "security" : [], - "tags" : [ "user" ], - "summary" : "logs in a system user", - "description" : "The system login endpoint.", - "requestBody" : { - "description" : "The body of the payload", - "required" : true, - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "required" : [ "email", "password" ], - "properties" : { - "email" : { - "type" : "string", - "format" : "email", - "example" : "test@test.test" + "/user/login": { + "post": { + "security": [], + "tags": [ + "user" + ], + "summary": "logs in a system user", + "description": "The system login endpoint.", + "requestBody": { + "description": "The body of the payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "email", + "password" + ], + "properties": { + "email": { + "type": "string", + "format": "email", + "example": "test@test.test" }, - "password" : { - "type" : "string", - "example" : "test" + "password": { + "type": "string", + "example": "test" } } } } } }, - "responses" : { - "200" : { - "description" : "login token" + "responses": { + "200": { + "description": "login token" }, - "403" : { - "description" : "Forbidden" + "403": { + "description": "Forbidden" }, - "422" : { - "description" : "Invalid input" + "422": { + "description": "Invalid input" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } } }, - "/user" : { - "post" : { - "tags" : [ "user" ], - "summary" : "creates a new user", - "description" : "The new user endpoint. Note that displayname and phone are not written to the database.", - "requestBody" : { - "description" : "The body of the payload", - "required" : true, - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "required" : [ "email", "password" ], - "properties" : { - "email" : { - "type" : "string", - "format" : "email", - "example" : "homer.simpson@sfpp.com" + "/user": { + "post": { + "tags": [ + "user" + ], + "summary": "creates a new user", + "description": "The new user endpoint. Note that displayname and phone are not written to the database.", + "requestBody": { + "description": "The body of the payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "email", + "password" + ], + "properties": { + "email": { + "type": "string", + "format": "email", + "example": "homer.simpson@sfpp.com" }, - "password" : { - "type" : "string", - "format" : "password", - "example" : "donuts" + "password": { + "type": "string", + "format": "password", + "example": "donuts" }, - "roles" : { - "type" : "array", - "items" : { - "type" : "string", - "example" : "user" + "roles": { + "type": "array", + "items": { + "type": "string", + "example": "user" } }, - "displayName" : { - "type" : "string", - "example" : "Homer Simpson" + "displayName": { + "type": "string", + "example": "Homer Simpson" }, - "phone" : { - "type" : "string", - "example" : "1234567890" + "phone": { + "type": "string", + "example": "1234567890" } } } } } }, - "responses" : { - "200" : { - "description" : "user created" + "responses": { + "200": { + "description": "user created" }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "422" : { - "description" : "Invalid input" + "422": { + "description": "Invalid input" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } }, - "get" : { - "tags" : [ "user" ], - "summary" : "returns all system users", - "description" : "Returns all users within the system and their information.\n", - "parameters" : [ { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "responses" : { - "200" : { - "description" : "List of all users in the system and their information.", - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "_meta" : { - "type" : "object", - "properties" : { - "total" : { - "type" : "number", - "example" : 1 + "get": { + "tags": [ + "user" + ], + "summary": "returns all system users", + "description": "Returns all users within the system and their information.\n", + "parameters": [ + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "responses": { + "200": { + "description": "List of all users in the system and their information.", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "_meta": { + "type": "object", + "properties": { + "total": { + "type": "number", + "example": 1 } } }, - "results" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/UserItem" + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/UserItem" } } } @@ -210,534 +235,584 @@ } } }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } }, - "put" : { - "tags" : [ "user" ], - "summary" : "updates any single system user", - "description" : "By sending a valid payload you can update a user. Note that displayname and phone are not stored in the database.", - "parameters" : [ { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "requestBody" : { - "description" : "The body of the payload", - "required" : true, - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "required" : [ "email", "password" ], - "properties" : { - "email" : { - "type" : "string", - "format" : "email", - "example" : "homer.simpson@sfpp.com" + "put": { + "tags": [ + "user" + ], + "summary": "updates any single system user", + "description": "By sending a valid payload you can update a user. Note that displayname and phone are not stored in the database.", + "parameters": [ + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "requestBody": { + "description": "The body of the payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "email", + "password" + ], + "properties": { + "email": { + "type": "string", + "format": "email", + "example": "homer.simpson@sfpp.com" }, - "password" : { - "type" : "string", - "format" : "password", - "example" : "donuts" + "password": { + "type": "string", + "format": "password", + "example": "donuts" }, - "roles" : { - "type" : "array", - "items" : { - "type" : "string", - "example" : "admin" + "roles": { + "type": "array", + "items": { + "type": "string", + "example": "admin" } }, - "displayName" : { - "type" : "string", - "example" : "Homer Simpson" + "displayName": { + "type": "string", + "example": "Homer Simpson" }, - "phone" : { - "type" : "string", - "example" : "1234567890" + "phone": { + "type": "string", + "example": "1234567890" } } } } } }, - "responses" : { - "200" : { - "description" : "user updated" + "responses": { + "200": { + "description": "user updated" }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "422" : { - "description" : "Invalid input" + "422": { + "description": "Invalid input" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } } }, - "/user/{email}" : { - "get" : { - "tags" : [ "user" ], - "summary" : "returns a single system user", - "description" : "By passing the username, you can lookup a user.", - "parameters" : [ { - "in" : "path", - "name" : "email", - "schema" : { - "type" : "string", - "format" : "email" - }, - "required" : true, - "description" : "email of the user" - }, { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "responses" : { - "200" : { - "description" : "the user object", - "content" : { - "session/json" : { - "schema" : { - "$ref" : "#/components/schemas/UserItem" + "/user/{email}": { + "get": { + "tags": [ + "user" + ], + "summary": "returns a single system user", + "description": "By passing the username, you can lookup a user.", + "parameters": [ + { + "in": "path", + "name": "email", + "schema": { + "type": "string", + "format": "email" + }, + "required": true, + "description": "email of the user" + }, + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "responses": { + "200": { + "description": "the user object", + "content": { + "session/json": { + "schema": { + "$ref": "#/components/schemas/UserItem" } } } }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "422" : { - "description" : "Invalid input" + "422": { + "description": "Invalid input" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } }, - "delete" : { - "tags" : [ "user" ], - "summary" : "deletes a single system user", - "description" : "By sending a valid payload you can delete a user.", - "parameters" : [ { - "in" : "path", - "name" : "email", - "schema" : { - "type" : "string", - "format" : "email" - }, - "required" : true, - "description" : "the email of the user to delete." - }, { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "responses" : { - "200" : { - "description" : "user deleted" - }, - "401" : { - "description" : "Unauthorized" - }, - "422" : { - "description" : "Invalid input" - }, - "500" : { - "description" : "Server error" + "delete": { + "tags": [ + "user" + ], + "summary": "deletes a single system user", + "description": "By sending a valid payload you can delete a user.", + "parameters": [ + { + "in": "path", + "name": "email", + "schema": { + "type": "string", + "format": "email" + }, + "required": true, + "description": "the email of the user to delete." + }, + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "responses": { + "200": { + "description": "user deleted" + }, + "401": { + "description": "Unauthorized" + }, + "422": { + "description": "Invalid input" + }, + "500": { + "description": "Server error" } } } }, - "/userRole" : { - "post" : { - "tags" : [ "userRole" ], - "summary" : "creates a new user role", - "description" : "The new user role endpoint.", - "parameters" : [ { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "requestBody" : { - "description" : "The body of the payload", - "required" : true, - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "required" : [ "role" ], - "properties" : { - "role" : { - "type" : "string", - "example" : "test" + "/userRole": { + "post": { + "tags": [ + "userRole" + ], + "summary": "creates a new user role", + "description": "The new user role endpoint.", + "parameters": [ + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "requestBody": { + "description": "The body of the payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "role" + ], + "properties": { + "role": { + "type": "string", + "example": "test" }, - "path" : { - "type" : "string", - "example" : "/test" + "path": { + "type": "string", + "example": "/test" }, - "method" : { - "type" : "string", - "example" : "GET" + "method": { + "type": "string", + "example": "GET" } } } } } }, - "responses" : { - "200" : { - "description" : "policy created" + "responses": { + "200": { + "description": "policy created" }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "422" : { - "description" : "Invalid input" + "422": { + "description": "Invalid input" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } }, - "get" : { - "tags" : [ "userRole" ], - "summary" : "returns all system user roles", - "description" : "By passing in the appropriate options, you can search for\navailable user roles in the system\n", - "parameters" : [ { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "responses" : { - "200" : { - "description" : "search results matching criteria" - }, - "401" : { - "description" : "Unauthorized" - }, - "500" : { - "description" : "Server error" + "get": { + "tags": [ + "userRole" + ], + "summary": "returns all system user roles", + "description": "By passing in the appropriate options, you can search for\navailable user roles in the system\n", + "parameters": [ + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "responses": { + "200": { + "description": "search results matching criteria" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Server error" } } } }, - "/userRole/delete" : { - "post" : { - "tags" : [ "userRole" ], - "summary" : "deletes a single system user role", - "description" : "By sending a valid payload you can delete a user role.", - "parameters" : [ { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "requestBody" : { - "description" : "The body of the payload", - "required" : true, - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "required" : [ "role" ], - "properties" : { - "role" : { - "type" : "string", - "example" : "test" + "/userRole/delete": { + "post": { + "tags": [ + "userRole" + ], + "summary": "deletes a single system user role", + "description": "By sending a valid payload you can delete a user role.", + "parameters": [ + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "requestBody": { + "description": "The body of the payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "role" + ], + "properties": { + "role": { + "type": "string", + "example": "test" }, - "path" : { - "type" : "string", - "example" : "/test" + "path": { + "type": "string", + "example": "/test" }, - "method" : { - "type" : "string", - "example" : "GET" + "method": { + "type": "string", + "example": "GET" } } } } } }, - "responses" : { - "200" : { - "description" : "policy deleted" + "responses": { + "200": { + "description": "policy deleted" }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "422" : { - "description" : "Invalid input" + "422": { + "description": "Invalid input" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } } }, - "/entity" : { - "post" : { - "tags" : [ "entity" ], - "summary" : "creates a new entity", - "description" : "The new entity endpoint.", - "requestBody" : { - "description" : "The body of the payload. Contact ids must be populated if part of the body with existinct contactids.", - "required" : true, - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "required" : [ "name", "type" ], - "properties" : { - "name" : { - "type" : "string", - "example" : "The Leftorium" + "/entity": { + "post": { + "tags": [ + "entity" + ], + "summary": "creates a new entity", + "description": "The new entity endpoint.", + "requestBody": { + "description": "The body of the payload. Contact ids must be populated if part of the body with existinct contactids.", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "name", + "type" + ], + "properties": { + "name": { + "type": "string", + "example": "The Leftorium" }, - "type" : { - "type" : "string", - "example" : "Assisted Living Facility" + "type": { + "type": "string", + "example": "Assisted Living Facility" }, - "address" : { - "type" : "object", - "properties" : { - "street" : { - "type" : "array", - "items" : { - "type" : "string", - "example" : "123 Anyplace St." + "address": { + "type": "object", + "properties": { + "street": { + "type": "array", + "items": { + "type": "string", + "example": "123 Anyplace St." } }, - "city" : { - "type" : "string", - "example" : "Baltimore" + "city": { + "type": "string", + "example": "Baltimore" }, - "state" : { - "type" : "string", - "example" : "MD" + "state": { + "type": "string", + "example": "MD" }, - "zip" : { - "type" : "string", - "example" : "12345" + "zip": { + "type": "string", + "example": "12345" } } }, - "description" : { - "type" : "string", - "example" : "Everything for the left handed man, woman, and child!" + "description": { + "type": "string", + "example": "Everything for the left handed man, woman, and child!" } } } } } }, - "responses" : { - "200" : { - "description" : "entity created" + "responses": { + "200": { + "description": "entity created" }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "422" : { - "description" : "Invalid input" + "422": { + "description": "Invalid input" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } }, - "get" : { - "tags" : [ "entity" ], - "summary" : "returns all system entities", - "description" : "By passing in the appropriate options, you can search for\navailable entities in the system\n", - "parameters" : [ { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - }, { - "in" : "query", - "name" : "type", - "schema" : { - "type" : "string", - "example" : "name" - }, - "description" : "The type of field you are searching on" - }, { - "in" : "query", - "name" : "value", - "schema" : { - "type" : "string", - "example" : "The Leftorium" - }, - "description" : "The value you are searching for" - } ], - "responses" : { - "200" : { - "description" : "search results matching criteria" - }, - "401" : { - "description" : "Unauthorized" - }, - "500" : { - "description" : "Server error" + "get": { + "tags": [ + "entity" + ], + "summary": "returns all system entities", + "description": "By passing in the appropriate options, you can search for\navailable entities in the system\n", + "parameters": [ + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + }, + { + "in": "query", + "name": "type", + "schema": { + "type": "string", + "example": "name" + }, + "description": "The type of field you are searching on" + }, + { + "in": "query", + "name": "value", + "schema": { + "type": "string", + "example": "The Leftorium" + }, + "description": "The value you are searching for" + } + ], + "responses": { + "200": { + "description": "search results matching criteria" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Server error" } } }, - "put" : { - "tags" : [ "entity" ], - "summary" : "updates any single system entity", - "description" : "By sending a valid payload you can update an entity.", - "parameters" : [ { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "requestBody" : { - "description" : "The body of the payload", - "required" : true, - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "required" : [ "id" ], - "properties" : { - "id" : { - "type" : "string", - "format" : "uuid", - "example" : "05533f95-b440-4f9d-876d-653636dce0c8" + "put": { + "tags": [ + "entity" + ], + "summary": "updates any single system entity", + "description": "By sending a valid payload you can update an entity.", + "parameters": [ + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "requestBody": { + "description": "The body of the payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string", + "format": "uuid", + "example": "05533f95-b440-4f9d-876d-653636dce0c8" }, - "name" : { - "type" : "string", - "example" : "The Leftorium" + "name": { + "type": "string", + "example": "The Leftorium" }, - "address" : { - "type" : "object", - "properties" : { - "street" : { - "type" : "array", - "items" : { - "type" : "string", - "example" : "123 Anyplace St." + "address": { + "type": "object", + "properties": { + "street": { + "type": "array", + "items": { + "type": "string", + "example": "123 Anyplace St." } }, - "city" : { - "type" : "string", - "example" : "Baltimore" + "city": { + "type": "string", + "example": "Baltimore" }, - "state" : { - "type" : "string", - "example" : "MD" + "state": { + "type": "string", + "example": "MD" }, - "zip" : { - "type" : "string", - "example" : "12345" + "zip": { + "type": "string", + "example": "12345" } } }, - "checkIn" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { - "updatedAt" : { - "type" : "string", - "format" : "date-time", - "example" : "2020-01-21T13:45:52.348Z" + "checkIn": { + "type": "array", + "items": { + "type": "object", + "properties": { + "updatedAt": { + "type": "string", + "format": "date-time", + "example": "2020-01-21T13:45:52.348Z" }, - "status" : { - "type" : "string", - "example" : "Safe" + "status": { + "type": "string", + "example": "Safe" }, - "UserId" : { - "type" : "string", - "format" : "uuid", - "example" : "4d9721a2-07f8-45ac-9570-682f4774cfa5" + "UserId": { + "type": "string", + "format": "uuid", + "example": "4d9721a2-07f8-45ac-9570-682f4774cfa5" }, - "ContactId" : { - "type" : "string", - "format" : "uuid", - "example" : "4d9721a2-07f8-45ac-9570-682f4774cfa5" + "ContactId": { + "type": "string", + "format": "uuid", + "example": "4d9721a2-07f8-45ac-9570-682f4774cfa5" }, - "questionnaire" : { - "type" : "object", - "properties" : { - "id" : { - "type" : "number", - "example" : 1 + "questionnaire": { + "type": "object", + "properties": { + "id": { + "type": "number", + "example": 1 }, - "question1" : { - "type" : "string", - "example" : "They have left handed can openers" + "question1": { + "type": "string", + "example": "They have left handed can openers" }, - "question2" : { - "type" : "boolean", - "example" : false + "question2": { + "type": "boolean", + "example": false } } }, - "notes" : { - "type" : "string", - "example" : "Everything is okilly dokilly" + "notes": { + "type": "string", + "example": "Everything is okilly dokilly" } } } }, - "description" : { - "type" : "string", - "example" : "Everything for the left-handed man, woman, and child!" + "description": { + "type": "string", + "example": "Everything for the left-handed man, woman, and child!" }, - "attributes" : { - "type" : "object", - "properties" : { - "capacity" : { - "type" : "number", - "example" : 42 + "attributes": { + "type": "object", + "properties": { + "capacity": { + "type": "number", + "example": 42 } } } @@ -746,397 +821,440 @@ } } }, - "responses" : { - "200" : { - "description" : "entity updated" + "responses": { + "200": { + "description": "entity updated" }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "422" : { - "description" : "Invalid input" + "422": { + "description": "Invalid input" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } } }, - "/entity/{entity_id}" : { - "get" : { - "tags" : [ "entity" ], - "summary" : "returns a single system entity", - "description" : "By passing the entity id, you can lookup an entity.", - "parameters" : [ { - "in" : "path", - "name" : "entity_id", - "schema" : { - "type" : "string", - "format" : "uuid" - }, - "required" : true, - "description" : "id of the entity" - }, { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "responses" : { - "200" : { - "description" : "the entity object", - "content" : { - "session/json" : { - "schema" : { - "$ref" : "#/components/schemas/EntityItem" + "/entity/{entity_id}": { + "get": { + "tags": [ + "entity" + ], + "summary": "returns a single system entity", + "description": "By passing the entity id, you can lookup an entity.", + "parameters": [ + { + "in": "path", + "name": "entity_id", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "description": "id of the entity" + }, + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "responses": { + "200": { + "description": "the entity object", + "content": { + "session/json": { + "schema": { + "$ref": "#/components/schemas/EntityItem" } } } }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "422" : { - "description" : "Invalid input" + "422": { + "description": "Invalid input" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } }, - "delete" : { - "tags" : [ "entity" ], - "summary" : "deletes a single system entity", - "description" : "By sending a valid payload you can delete a user.", - "parameters" : [ { - "in" : "path", - "name" : "entity_id", - "schema" : { - "type" : "string", - "format" : "uuid" - }, - "required" : true, - "description" : "the id of the entity to delete." - }, { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "responses" : { - "200" : { - "description" : "entity_id deleted" - }, - "401" : { - "description" : "Unauthorized" - }, - "422" : { - "description" : "Invalid input" - }, - "500" : { - "description" : "Server error" + "delete": { + "tags": [ + "entity" + ], + "summary": "deletes a single system entity", + "description": "By sending a valid payload you can delete a user.", + "parameters": [ + { + "in": "path", + "name": "entity_id", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "description": "the id of the entity to delete." + }, + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "responses": { + "200": { + "description": "entity_id deleted" + }, + "401": { + "description": "Unauthorized" + }, + "422": { + "description": "Invalid input" + }, + "500": { + "description": "Server error" } } } }, - "/entity/link/{entity_id}" : { - "post" : { - "tags" : [ "entity" ], - "summary" : "links an entity with a list of given contacts", - "description" : "By passing the entity id and list of contacts, you can link the entity to each contact.", - "parameters" : [ { - "in" : "path", - "name" : "entity_id", - "schema" : { - "type" : "string", - "format" : "uuid" - }, - "required" : true, - "description" : "id of the entity" - }, { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "requestBody" : { - "description" : "The body of the payload", - "required" : true, - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "required" : [ "contacts" ], - "properties" : { - "contacts" : { - "type" : "string", - "example" : [ { - "id" : "" - }, { - "id" : "", - "title" : "" - } ] + "/entity/link/{entity_id}": { + "post": { + "tags": [ + "entity" + ], + "summary": "links an entity with a list of given contacts", + "description": "By passing the entity id and list of contacts, you can link the entity to each contact.", + "parameters": [ + { + "in": "path", + "name": "entity_id", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "description": "id of the entity" + }, + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "requestBody": { + "description": "The body of the payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "contacts" + ], + "properties": { + "contacts": { + "type": "string", + "example": [ + { + "id": "" + }, + { + "id": "", + "title": "" + } + ] } } } } } }, - "responses" : { - "200" : { - "description" : "Successful/already exists" + "responses": { + "200": { + "description": "Successful/already exists" }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "422" : { - "description" : "Invalid input" + "422": { + "description": "Invalid input" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } } }, - "/entity/unlink/{entity_id}" : { - "post" : { - "tags" : [ "entity" ], - "summary" : "unlinks an entity from a list of given contacts", - "description" : "By passing the entity id and list of contacts, you can unlink the entity from each contact.", - "parameters" : [ { - "in" : "path", - "name" : "entity_id", - "schema" : { - "type" : "string", - "format" : "uuid" - }, - "required" : true, - "description" : "id of the entity" - }, { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "requestBody" : { - "description" : "The body of the payload", - "required" : true, - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "required" : [ "contacts" ], - "properties" : { - "contacts" : { - "type" : "string", - "example" : [ { - "id" : "" - }, { - "id" : "" - } ] + "/entity/unlink/{entity_id}": { + "post": { + "tags": [ + "entity" + ], + "summary": "unlinks an entity from a list of given contacts", + "description": "By passing the entity id and list of contacts, you can unlink the entity from each contact.", + "parameters": [ + { + "in": "path", + "name": "entity_id", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "description": "id of the entity" + }, + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "requestBody": { + "description": "The body of the payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "contacts" + ], + "properties": { + "contacts": { + "type": "string", + "example": [ + { + "id": "" + }, + { + "id": "" + } + ] } } } } } }, - "responses" : { - "200" : { - "description" : "Successful/already exists" + "responses": { + "200": { + "description": "Successful/already exists" }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "422" : { - "description" : "Invalid input" + "422": { + "description": "Invalid input" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } } }, - "/contact" : { - "post" : { - "security" : [ - { - "bearerAuth" : [] - } - ], - "tags" : [ "contact" ], - "summary" : "creates a new contact", - "description" : "The new contact endpoint.", - "requestBody" : { - "description" : "The body of the payload", - "required" : true, - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "required" : [ "name" ], - "properties" : { - "name" : { - "type" : "string", - "example" : "The Leftorium" + "/contact": { + "post": { + "security": [ + { + "bearerAuth": [] + } + ], + "tags": [ + "contact" + ], + "summary": "creates a new contact", + "description": "The new contact endpoint.", + "requestBody": { + "description": "The body of the payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "name": { + "type": "string", + "example": "The Leftorium" }, - "address" : { - "type" : "object", - "properties" : { - "street" : { - "type" : "array", - "items" : { - "type" : "string", - "example" : "123 Anyplace St." + "address": { + "type": "object", + "properties": { + "street": { + "type": "array", + "items": { + "type": "string", + "example": "123 Anyplace St." } }, - "city" : { - "type" : "string", - "example" : "Baltimore" + "city": { + "type": "string", + "example": "Baltimore" }, - "state" : { - "type" : "string", - "example" : "MD" + "state": { + "type": "string", + "example": "MD" }, - "zip" : { - "type" : "string", - "example" : "12345" + "zip": { + "type": "string", + "example": "12345" } } }, - "phone" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { - "address" : { - "type" : "string", - "example" : 9.87654321E8 + "phone": { + "type": "array", + "items": { + "type": "object", + "properties": { + "address": { + "type": "string", + "example": 9.87654321E8 }, - "isPrimary" : { - "type" : "boolean", - "example" : true + "isPrimary": { + "type": "boolean", + "example": true } } } }, - "email" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { - "address" : { - "type" : "string", - "format" : "email", - "example" : "hello@leftorium.com" + "email": { + "type": "array", + "items": { + "type": "object", + "properties": { + "address": { + "type": "string", + "format": "email", + "example": "hello@leftorium.com" }, - "isPrimary" : { - "type" : "boolean", - "example" : true + "isPrimary": { + "type": "boolean", + "example": true } } } }, - "UserID" : { - "type" : "string", - "format" : "uuid", - "example" : "abafa852-ecd0-4d57-9083-85f4dfd9c402" + "UserID": { + "type": "string", + "format": "uuid", + "example": "abafa852-ecd0-4d57-9083-85f4dfd9c402" }, - "entities" : { - "type" : "string", - "example" : [ { - "id" : "" - }, { - "id" : "", - "title" : "" - } ] + "entities": { + "type": "string", + "example": [ + { + "id": "" + }, + { + "id": "", + "title": "" + } + ] } } } } } }, - "responses" : { - "201" : { - "description" : "contact created" + "responses": { + "201": { + "description": "contact created" }, - "400" : { - "description" : "Bad Request" + "400": { + "description": "Bad Request" }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } }, - "get" : { - "tags" : [ "contact" ], - "summary" : "returns all, or searched for, system contacts", - "description" : "By passing in the appropriate options, you can search for\navailable contacts in the system\n", - "parameters" : [ { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - }, { - "in" : "query", - "name" : "type", - "schema" : { - "type" : "string", - "example" : "email" - }, - "description" : "The type of field you are searching on" - }, { - "in" : "query", - "name" : "value", - "schema" : { - "type" : "string", - "example" : "ned.flanders@leftorium.com" - }, - "description" : "The value you are searching for" - } ], - "responses" : { - "200" : { - "description" : "search results matching criteria", - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "_meta" : { - "type" : "object", - "properties" : { - "total" : { - "type" : "number", - "example" : 1 + "get": { + "tags": [ + "contact" + ], + "summary": "returns all, or searched for, system contacts", + "description": "By passing in the appropriate options, you can search for\navailable contacts in the system\n", + "parameters": [ + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + }, + { + "in": "query", + "name": "type", + "schema": { + "type": "string", + "example": "email" + }, + "description": "The type of field you are searching on" + }, + { + "in": "query", + "name": "value", + "schema": { + "type": "string", + "example": "ned.flanders@leftorium.com" + }, + "description": "The value you are searching for" + } + ], + "responses": { + "200": { + "description": "search results matching criteria", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "_meta": { + "type": "object", + "properties": { + "total": { + "type": "number", + "example": 1 } } }, - "results" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/ContactItem" + "results": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ContactItem" } } } @@ -1144,125 +1262,134 @@ } } }, - "400" : { - "description" : "Invalid input" + "400": { + "description": "Invalid input" }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } }, - "put" : { - "tags" : [ "contact" ], - "summary" : "updates any single system contact", - "description" : "By sending a valid payload you can update a contact.", - "parameters" : [ { - "in" : "header", - "name" : "token", - "required" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "requestBody" : { - "description" : "The body of the payload", - "required" : true, - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "required" : [ "id" ], - "properties" : { - "id" : { - "type" : "string", - "format" : "uuid", - "example" : "05533f95-b440-4f9d-876d-653636dce0c8" + "put": { + "tags": [ + "contact" + ], + "summary": "updates any single system contact", + "description": "By sending a valid payload you can update a contact.", + "parameters": [ + { + "in": "header", + "name": "token", + "required": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "requestBody": { + "description": "The body of the payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "id" + ], + "properties": { + "id": { + "type": "string", + "format": "uuid", + "example": "05533f95-b440-4f9d-876d-653636dce0c8" }, - "name" : { - "type" : "string", - "example" : "The Leftorium" + "name": { + "type": "string", + "example": "The Leftorium" }, - "address" : { - "type" : "object", - "properties" : { - "street" : { - "type" : "array", - "items" : { - "type" : "string", - "example" : "123 Anyplace St." + "address": { + "type": "object", + "properties": { + "street": { + "type": "array", + "items": { + "type": "string", + "example": "123 Anyplace St." } }, - "city" : { - "type" : "string", - "example" : "Baltimore" + "city": { + "type": "string", + "example": "Baltimore" }, - "state" : { - "type" : "string", - "example" : "MD" + "state": { + "type": "string", + "example": "MD" }, - "zip" : { - "type" : "string", - "example" : "12345" + "zip": { + "type": "string", + "example": "12345" } } }, - "phone" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { - "address" : { - "type" : "string", - "example" : 9.87654321E8 + "phone": { + "type": "array", + "items": { + "type": "object", + "properties": { + "address": { + "type": "string", + "example": 9.87654321E8 }, - "isPrimary" : { - "type" : "boolean", - "example" : true + "isPrimary": { + "type": "boolean", + "example": true } } } }, - "email" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { - "address" : { - "type" : "string", - "format" : "email", - "example" : "hello@leftorium.com" + "email": { + "type": "array", + "items": { + "type": "object", + "properties": { + "address": { + "type": "string", + "format": "email", + "example": "hello@leftorium.com" }, - "isPrimary" : { - "type" : "boolean", - "example" : true + "isPrimary": { + "type": "boolean", + "example": true } } } }, - "UserID" : { - "type" : "string", - "format" : "uuid", - "example" : "abafa852-ecd0-4d57-9083-85f4dfd9c402" + "UserID": { + "type": "string", + "format": "uuid", + "example": "abafa852-ecd0-4d57-9083-85f4dfd9c402" }, - "entities" : { - "type" : "string", - "example" : [ { - "id" : "" - }, { - "id" : "", - "title" : "" - } ] + "entities": { + "type": "string", + "example": [ + { + "id": "" + }, + { + "id": "", + "title": "" + } + ] }, - "attributes" : { - "type" : "object", - "properties" : { - "notes" : { - "type" : "string", - "example" : "Neighbor" + "attributes": { + "type": "object", + "properties": { + "notes": { + "type": "string", + "example": "Neighbor" } } } @@ -1271,50 +1398,54 @@ } } }, - "responses" : { - "200" : { - "description" : "contact updated" + "responses": { + "200": { + "description": "contact updated" }, - "400" : { - "description" : "Bad Request" + "400": { + "description": "Bad Request" }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } } }, - "/contact/send" : { - "post" : { - "tags" : [ "contact" ], - "summary" : "sends a check-in email to all contacts", - "description" : "By sending a request to this endpoint, you can send an email to a single contact or all contacts based on entity or contact id. By sending entity ids you will send an email to each contact associated with each entity id passed. By passed contact ids you will send an email to each contact for each entity they are associated with. By passing nothing you will send an email to every contact and every association.", - "parameters" : [ { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "requestBody" : { - "description" : "The body of the payload", - "required" : true, - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "properties" : { - "relationshipTitle" : { - "type" : "array", - "items" : { - "type" : "string", - "example" : "Primary Contact" + "/contact/send": { + "post": { + "tags": [ + "contact" + ], + "summary": "sends a check-in email to all contacts", + "description": "By sending a request to this endpoint, you can send an email to a single contact or all contacts based on entity or contact id. By sending entity ids you will send an email to each contact associated with each entity id passed. By passed contact ids you will send an email to each contact for each entity they are associated with. By passing nothing you will send an email to every contact and every association.", + "parameters": [ + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "requestBody": { + "description": "The body of the payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "relationshipTitle": { + "type": "array", + "items": { + "type": "string", + "example": "Primary Contact" } } } @@ -1322,517 +1453,581 @@ } } }, - "responses" : { - "200" : { - "description" : "contacts emailed" + "responses": { + "200": { + "description": "contacts emailed", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "object", + "properties": { + "total": { + "type": "number", + "example": 1 + }, + "message": { + "type": "string", + "example": "Contacts emailed" + } + } + } + } + } + } + } }, - "400" : { - "description" : "Bad Request" + "400": { + "description": "Bad Request" }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } } }, - "/contact/{contact_id}" : { - "get" : { - "tags" : [ "contact" ], - "summary" : "returns a single system contact", - "description" : "By passing the contact id, you can lookup a contact.", - "parameters" : [ { - "in" : "path", - "name" : "contact_id", - "schema" : { - "type" : "string", - "format" : "uuid" - }, - "required" : true, - "description" : "id of the contact" - }, { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "responses" : { - "200" : { - "description" : "the contact object", - "content" : { - "session/json" : { - "schema" : { - "$ref" : "#/components/schemas/ContactItem" + "/contact/{contact_id}": { + "get": { + "tags": [ + "contact" + ], + "summary": "returns a single system contact", + "description": "By passing the contact id, you can lookup a contact.", + "parameters": [ + { + "in": "path", + "name": "contact_id", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "description": "id of the contact" + }, + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "responses": { + "200": { + "description": "the contact object", + "content": { + "session/json": { + "schema": { + "$ref": "#/components/schemas/ContactItem" } } } }, - "400" : { - "description" : "Bad Request" + "400": { + "description": "Bad Request" }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } }, - "delete" : { - "tags" : [ "contact" ], - "summary" : "deletes a single system contact", - "description" : "By sending a valid payload you can delete a user.", - "parameters" : [ { - "in" : "path", - "name" : "contact_id", - "schema" : { - "type" : "string", - "format" : "uuid" - }, - "required" : true, - "description" : "the id of the contact to delete." - }, { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "responses" : { - "200" : { - "description" : "contact_id deleted" - }, - "400" : { - "description" : "Bad Request" - }, - "401" : { - "description" : "Unauthorized" - }, - "500" : { - "description" : "Server error" + "delete": { + "tags": [ + "contact" + ], + "summary": "deletes a single system contact", + "description": "By sending a valid payload you can delete a user.", + "parameters": [ + { + "in": "path", + "name": "contact_id", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "description": "the id of the contact to delete." + }, + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "responses": { + "200": { + "description": "contact_id deleted" + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Server error" } } } }, - "/contact/link/{contact_id}" : { - "post" : { - "tags" : [ "contact" ], - "summary" : "links a contact with a list of given entities", - "description" : "By passing the contact id and list of entities, you can link the contact to each entity.", - "parameters" : [ { - "in" : "path", - "name" : "contact_id", - "schema" : { - "type" : "string", - "format" : "uuid" - }, - "required" : true, - "description" : "id of the contact" - }, { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "requestBody" : { - "description" : "The body of the payload", - "required" : true, - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "required" : [ "entities" ], - "properties" : { - "entities" : { - "type" : "string", - "example" : [ { - "id" : "" - }, { - "id" : "", - "title" : "" - } ] + "/contact/link/{contact_id}": { + "post": { + "tags": [ + "contact" + ], + "summary": "links a contact with a list of given entities", + "description": "By passing the contact id and list of entities, you can link the contact to each entity.", + "parameters": [ + { + "in": "path", + "name": "contact_id", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "description": "id of the contact" + }, + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "requestBody": { + "description": "The body of the payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "entities" + ], + "properties": { + "entities": { + "type": "string", + "example": [ + { + "id": "" + }, + { + "id": "", + "title": "" + } + ] } } } } } }, - "responses" : { - "200" : { - "description" : "Successful/already exists" + "responses": { + "200": { + "description": "Successful/already exists" }, - "400" : { - "description" : "Bad Request" + "400": { + "description": "Bad Request" }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } } }, - "/contact/unlink/{contact_id}" : { - "post" : { - "tags" : [ "contact" ], - "summary" : "unlinks a contact from a list of given entities", - "description" : "By passing the contact id and list of entities, you can unlink the contact from each entity.", - "parameters" : [ { - "in" : "path", - "name" : "contact_id", - "schema" : { - "type" : "string", - "format" : "uuid" - }, - "required" : true, - "description" : "id of the contact" - }, { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "requestBody" : { - "description" : "The body of the payload", - "required" : true, - "content" : { - "application/json" : { - "schema" : { - "type" : "object", - "required" : [ "entities" ], - "properties" : { - "entities" : { - "type" : "string", - "example" : [ { - "id" : "" - }, { - "id" : "" - } ] + "/contact/unlink/{contact_id}": { + "post": { + "tags": [ + "contact" + ], + "summary": "unlinks a contact from a list of given entities", + "description": "By passing the contact id and list of entities, you can unlink the contact from each entity.", + "parameters": [ + { + "in": "path", + "name": "contact_id", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "description": "id of the contact" + }, + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "requestBody": { + "description": "The body of the payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "required": [ + "entities" + ], + "properties": { + "entities": { + "type": "string", + "example": [ + { + "id": "" + }, + { + "id": "" + } + ] } } } } } }, - "responses" : { - "200" : { - "description" : "Successful/already exists" + "responses": { + "200": { + "description": "Successful/already exists" }, - "400" : { - "description" : "Bad Request" + "400": { + "description": "Bad Request" }, - "401" : { - "description" : "Unauthorized" + "401": { + "description": "Unauthorized" }, - "500" : { - "description" : "Server error" + "500": { + "description": "Server error" } } } }, - "/csv/{model_type}" : { - "get" : { - "tags" : [ "csv" ], - "summary" : "returns a comma separated list of the model_type requested", - "description" : "By passing the model_type, you are returned a comma separated list of that model_type. Valid model types are Entity, EntityContact, and Contact.", - "parameters" : [ { - "in" : "path", - "name" : "model_type", - "schema" : { - "type" : "string" - }, - "required" : true, - "description" : "type of model you want a csv data dump for. Options are Contact, Entity, and EntityContact." - }, { - "in" : "header", - "name" : "token", - "required" : false, - "deprecated" : true, - "schema" : { - "type" : "string", - "example" : "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" - } - } ], - "responses" : { - "200" : { - "description" : "the csv data dump with column headers" - }, - "401" : { - "description" : "Unauthorized" - }, - "422" : { - "description" : "Invalid input" - }, - "500" : { - "description" : "Server error" + "/csv/{model_type}": { + "get": { + "tags": [ + "csv" + ], + "summary": "returns a comma separated list of the model_type requested", + "description": "By passing the model_type, you are returned a comma separated list of that model_type. Valid model types are Entity, EntityContact, and Contact.", + "parameters": [ + { + "in": "path", + "name": "model_type", + "schema": { + "type": "string" + }, + "required": true, + "description": "type of model you want a csv data dump for. Options are Contact, Entity, and EntityContact." + }, + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "responses": { + "200": { + "description": "the csv data dump with column headers" + }, + "401": { + "description": "Unauthorized" + }, + "422": { + "description": "Invalid input" + }, + "500": { + "description": "Server error" } } } } }, - "components" : { - "securitySchemes" : { - "bearerAuth" : { - "type" : "http", - "scheme" : "bearer", - "bearerFormat" : "JWT" + "components": { + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer", + "bearerFormat": "JWT" } }, - "schemas" : { - "HealthcheckItem" : { - "type" : "object", - "required" : [ "uptime", "environment", "version", "requestId" ], - "properties" : { - "uptime" : { - "type" : "string", - "example" : "42:42:42" - }, - "environment" : { - "type" : "string", - "example" : "dev" - }, - "version" : { - "type" : "string", - "example" : "0.0.1" - }, - "requestId" : { - "type" : "string", - "format" : "uuid", - "example" : "602e1bd9-3eb1-4a26-a0d1-6bf08e8c0a66" + "schemas": { + "HealthcheckItem": { + "type": "object", + "required": [ + "uptime", + "environment", + "version", + "requestId" + ], + "properties": { + "uptime": { + "type": "string", + "example": "42:42:42" + }, + "environment": { + "type": "string", + "example": "dev" + }, + "version": { + "type": "string", + "example": "0.0.1" + }, + "requestId": { + "type": "string", + "format": "uuid", + "example": "602e1bd9-3eb1-4a26-a0d1-6bf08e8c0a66" } } }, - "UserItem" : { - "type" : "object", - "required" : [ "email" ], - "properties" : { - "id" : { - "type" : "string", - "format" : "uuid", - "example" : "4d9721a2-07f8-45ac-9570-682f4774cfa5" - }, - "email" : { - "type" : "string", - "format" : "email", - "example" : "homer.simpson@sfpp.com" - }, - "displayNamme" : { - "type" : "string", - "example" : "Homer Simpson" - }, - "phone" : { - "type" : "string", - "example" : "1234567890" - }, - "attributes" : { - "type" : "string", - "example" : null - }, - "createdAt" : { - "type" : "string", - "format" : "date-time", - "example" : "2020-01-21T13:45:52.348Z" - }, - "updatedAt" : { - "type" : "string", - "format" : "date-time", - "example" : "2020-01-21T13:45:52.348Z" - }, - "roles" : { - "type" : "array", - "items" : { - "type" : "string", - "example" : "user" + "UserItem": { + "type": "object", + "required": [ + "email" + ], + "properties": { + "id": { + "type": "string", + "format": "uuid", + "example": "4d9721a2-07f8-45ac-9570-682f4774cfa5" + }, + "email": { + "type": "string", + "format": "email", + "example": "homer.simpson@sfpp.com" + }, + "displayNamme": { + "type": "string", + "example": "Homer Simpson" + }, + "phone": { + "type": "string", + "example": "1234567890" + }, + "attributes": { + "type": "string", + "example": null + }, + "createdAt": { + "type": "string", + "format": "date-time", + "example": "2020-01-21T13:45:52.348Z" + }, + "updatedAt": { + "type": "string", + "format": "date-time", + "example": "2020-01-21T13:45:52.348Z" + }, + "roles": { + "type": "array", + "items": { + "type": "string", + "example": "user" } } } }, - "EntityItem" : { - "type" : "object", - "properties" : { - "id" : { - "type" : "string", - "format" : "uuid", - "example" : "c2fb852c-17fd-4e2b-9ea4-78128af9a5e9" - }, - "name" : { - "type" : "string", - "example" : "The Leftorium" - }, - "type" : { - "type" : "string", - "example" : "Test" - }, - "address" : { - "type" : "object", - "properties" : { - "address" : { - "type" : "array", - "items" : { - "type" : "string", - "example" : "123 Anyplace St." + "EntityItem": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "example": "c2fb852c-17fd-4e2b-9ea4-78128af9a5e9" + }, + "name": { + "type": "string", + "example": "The Leftorium" + }, + "type": { + "type": "string", + "example": "Test" + }, + "address": { + "type": "object", + "properties": { + "address": { + "type": "array", + "items": { + "type": "string", + "example": "123 Anyplace St." } }, - "city" : { - "type" : "string", - "example" : "Baltimore" + "city": { + "type": "string", + "example": "Baltimore" }, - "state" : { - "type" : "string", - "example" : "MD" + "state": { + "type": "string", + "example": "MD" }, - "zip" : { - "type" : "string", - "example" : "12345" + "zip": { + "type": "string", + "example": "12345" } } }, - "checkIn" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { - "updatedAt" : { - "type" : "string", - "format" : "date-time", - "example" : "2020-01-21T13:45:52.348Z" + "checkIn": { + "type": "array", + "items": { + "type": "object", + "properties": { + "updatedAt": { + "type": "string", + "format": "date-time", + "example": "2020-01-21T13:45:52.348Z" }, - "status" : { - "type" : "string", - "example" : "Safe" + "status": { + "type": "string", + "example": "Safe" }, - "UserId" : { - "type" : "string", - "format" : "uuid", - "example" : "4d9721a2-07f8-45ac-9570-682f4774cfa5" + "UserId": { + "type": "string", + "format": "uuid", + "example": "4d9721a2-07f8-45ac-9570-682f4774cfa5" }, - "ContactId" : { - "type" : "string", - "format" : "uuid", - "example" : "4d9721a2-07f8-45ac-9570-682f4774cfa5" + "ContactId": { + "type": "string", + "format": "uuid", + "example": "4d9721a2-07f8-45ac-9570-682f4774cfa5" }, - "questionnaire" : { - "type" : "object", - "properties" : { - "id" : { - "type" : "number", - "example" : 1 + "questionnaire": { + "type": "object", + "properties": { + "id": { + "type": "number", + "example": 1 }, - "question1" : { - "type" : "string", - "example" : "They have left handed can openers" + "question1": { + "type": "string", + "example": "They have left handed can openers" }, - "question2" : { - "type" : "boolean", - "example" : false + "question2": { + "type": "boolean", + "example": false } } }, - "notes" : { - "type" : "string", - "example" : "Everything is okilly dokilly" + "notes": { + "type": "string", + "example": "Everything is okilly dokilly" } } } }, - "description" : { - "type" : "string", - "example" : "Everything for the left handed man, woman, and child!" + "description": { + "type": "string", + "example": "Everything for the left handed man, woman, and child!" }, - "createdAt" : { - "type" : "string", - "format" : "date-time", - "example" : "2020-01-21T13:45:52.348Z" + "createdAt": { + "type": "string", + "format": "date-time", + "example": "2020-01-21T13:45:52.348Z" }, - "updatedAt" : { - "type" : "string", - "format" : "date-time", - "example" : "2020-01-21T13:45:52.348Z" + "updatedAt": { + "type": "string", + "format": "date-time", + "example": "2020-01-21T13:45:52.348Z" } } }, - "ContactItem" : { - "type" : "object", - "properties" : { - "id" : { - "type" : "string", - "format" : "uuid", - "example" : "abafa852-ecd0-4d57-9083-85f4dfd9c402" - }, - "UserID" : { - "type" : "string", - "format" : "uuid", - "example" : "abafa852-ecd0-4d57-9083-85f4dfd9c402" - }, - "EntityId" : { - "type" : "string", - "format" : "uuid", - "example" : "c2fb852c-17fd-4e2b-9ea4-78128af9a5e9" - }, - "name" : { - "type" : "string", - "example" : "Ned Flanders" - }, - "phone" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { - "address" : { - "type" : "string", - "example" : 6.54987321E8 + "ContactItem": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "example": "abafa852-ecd0-4d57-9083-85f4dfd9c402" + }, + "UserID": { + "type": "string", + "format": "uuid", + "example": "abafa852-ecd0-4d57-9083-85f4dfd9c402" + }, + "EntityId": { + "type": "string", + "format": "uuid", + "example": "c2fb852c-17fd-4e2b-9ea4-78128af9a5e9" + }, + "name": { + "type": "string", + "example": "Ned Flanders" + }, + "phone": { + "type": "array", + "items": { + "type": "object", + "properties": { + "address": { + "type": "string", + "example": 6.54987321E8 }, - "isPrimary" : { - "type" : "boolean", - "example" : true + "isPrimary": { + "type": "boolean", + "example": true } } } }, - "email" : { - "type" : "array", - "items" : { - "type" : "object", - "properties" : { - "address" : { - "type" : "string", - "format" : "email", - "example" : "ned.flanders@leftorium.com" + "email": { + "type": "array", + "items": { + "type": "object", + "properties": { + "address": { + "type": "string", + "format": "email", + "example": "ned.flanders@leftorium.com" }, - "isPrimary" : { - "type" : "boolean", - "example" : true + "isPrimary": { + "type": "boolean", + "example": true } } } }, - "createdAt" : { - "type" : "string", - "format" : "date-time", - "example" : "2020-01-21T13:45:52.348Z" + "createdAt": { + "type": "string", + "format": "date-time", + "example": "2020-01-21T13:45:52.348Z" }, - "updatedAt" : { - "type" : "string", - "format" : "date-time", - "example" : "2020-01-21T13:45:52.348Z" + "updatedAt": { + "type": "string", + "format": "date-time", + "example": "2020-01-21T13:45:52.348Z" } } } From 964c5a986b6e6d5856859797204b6202da291fc8 Mon Sep 17 00:00:00 2001 From: ijadams Date: Mon, 28 Sep 2020 10:42:48 -0500 Subject: [PATCH 04/20] reformat trigger ci build --- src/email/index.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/email/index.js b/src/email/index.js index 1fd91db2..0f2edcd5 100644 --- a/src/email/index.js +++ b/src/email/index.js @@ -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) => { @@ -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) { @@ -63,8 +63,8 @@ const sendContactCheckInEmail = async (info) => { await sendMail( info.email, emailTitle, - nunjucks.render('contact_check_in_html.njk', { emailTitle, emailContents, entityLink }), - nunjucks.render('contact_check_in_text.njk', { emailTitle, emailContents, entityLink }) + nunjucks.render('contact_check_in_html.njk', {emailTitle, emailContents, entityLink}), + nunjucks.render('contact_check_in_text.njk', {emailTitle, emailContents, entityLink}) ) return true @@ -73,4 +73,4 @@ const sendContactCheckInEmail = async (info) => { } } -export default { sendForgotPassword, sendContactCheckInEmail } +export default {sendForgotPassword, sendContactCheckInEmail} From 180ef3dc71daade7f68f91669cd8315951319c4b Mon Sep 17 00:00:00 2001 From: ijadams Date: Mon, 28 Sep 2020 11:35:47 -0500 Subject: [PATCH 05/20] fix test --- src/tests/contact.routes.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/contact.routes.spec.js b/src/tests/contact.routes.spec.js index 40e2114a..cc2845b8 100644 --- a/src/tests/contact.routes.spec.js +++ b/src/tests/contact.routes.spec.js @@ -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) { From a3f725860496812bfad600d2a88449cb965e1664 Mon Sep 17 00:00:00 2001 From: ijadams Date: Mon, 28 Sep 2020 15:33:16 -0500 Subject: [PATCH 06/20] add temporary auth and fix csv download for Contact --- src/routes/csv.js | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/src/routes/csv.js b/src/routes/csv.js index 01b40db8..2f478f5d 100644 --- a/src/routes/csv.js +++ b/src/routes/csv.js @@ -1,36 +1,62 @@ -import { Router } from 'express' +import {Router} from 'express' import utils from '../utils' -import { parseAsync } from 'json2csv' +import {parseAsync} from 'json2csv' 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 { + + if (!process.env.BYPASS_LOGIN) { + const e = await utils.loadCasbin() + const roles = await e.getRolesForUser(req.context.me.email) + + if (!roles.includes('admin')) { + response.setCode(400) + response.setMessage('User is not authorized to perform this action.') + return res.status(response.getCode()).send(response.getMessage()) + } + } + /** @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 }) + const results = await req.context.models[modelType].findAll({raw: true}) const processedResults = await utils.processResults(results, modelType) - if (results.length !== 0) { - response.setMessage = await parseAsync(JSON.parse(JSON.stringify(processedResults)), Object.keys(results[0]), {}) + 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(400) + response.setMessage('Not able to parse data: ' + err) + 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 From ffa8e3573078cbab1aa1696b97f162c43c9a5aad Mon Sep 17 00:00:00 2001 From: ijadams Date: Mon, 28 Sep 2020 15:36:47 -0500 Subject: [PATCH 07/20] fix test --- src/tests/contact.routes.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tests/contact.routes.spec.js b/src/tests/contact.routes.spec.js index cc2845b8..9b28a616 100644 --- a/src/tests/contact.routes.spec.js +++ b/src/tests/contact.routes.spec.js @@ -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) => { From 4e59ef2ed0b6ad1c1f304ec8e8cb2229a6a30125 Mon Sep 17 00:00:00 2001 From: ijadams Date: Tue, 29 Sep 2020 14:06:03 -0500 Subject: [PATCH 08/20] add query param for filter on csv endpoint --- src/routes/csv.js | 15 +++++++++++++-- swagger.json | 9 +++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/routes/csv.js b/src/routes/csv.js index 2f478f5d..f93622b0 100644 --- a/src/routes/csv.js +++ b/src/routes/csv.js @@ -1,6 +1,7 @@ import {Router} from 'express' import utils from '../utils' import {parseAsync} from 'json2csv' +import {Op} from 'sequelize' const router = new Router() router.use(utils.authMiddleware) @@ -27,9 +28,19 @@ router.get('/:model_type', async (req, res) => { /** @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') { + let options = {raw: true} + req.params.status = 'Spoke to owner. No follow-up needed.' + // search by name if filter param is included + if (req.params.filter && req.params.filter.length) { + options.where = { + name: { + [Op.iLike]: '%' + req.params.filter + '%' + } + } + } + /** @todo add a search filter for status once data has a status field. */ - /** @todo add filtering */ - const results = await req.context.models[modelType].findAll({raw: true}) + let results = await req.context.models[modelType].findAll(options) const processedResults = await utils.processResults(results, modelType) if (results.length !== 0) { diff --git a/swagger.json b/swagger.json index 1dbeb813..08dd9ac6 100644 --- a/swagger.json +++ b/swagger.json @@ -1748,6 +1748,15 @@ "required": true, "description": "type of model you want a csv data dump for. Options are Contact, Entity, and EntityContact." }, + { + "in": "query", + "name": "filter", + "schema": { + "type": "string", + "example": "Ned Flanders" + }, + "description": "The name filter of field you are searching on" + }, { "in": "header", "name": "token", From 64d4aed19131bf94dedc900b1bc12c15e6ad3016 Mon Sep 17 00:00:00 2001 From: ijadams Date: Tue, 29 Sep 2020 14:12:12 -0500 Subject: [PATCH 09/20] sort out query param --- src/routes/csv.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/routes/csv.js b/src/routes/csv.js index f93622b0..d3e9043d 100644 --- a/src/routes/csv.js +++ b/src/routes/csv.js @@ -29,17 +29,15 @@ router.get('/:model_type', async (req, res) => { // eslint-disable-next-line no-prototype-builtins if (req.context.models.hasOwnProperty(modelType) && modelType !== 'User' && modelType !== 'UserRole') { let options = {raw: true} - req.params.status = 'Spoke to owner. No follow-up needed.' - // search by name if filter param is included - if (req.params.filter && req.params.filter.length) { + // 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.params.filter + '%' + [Op.iLike]: '%' + req.query.filter + '%' } } } /** @todo add a search filter for status once data has a status field. */ - let results = await req.context.models[modelType].findAll(options) const processedResults = await utils.processResults(results, modelType) From a676d176c92e90358b12ee6d36f1ced25bb2225c Mon Sep 17 00:00:00 2001 From: ijadams Date: Tue, 29 Sep 2020 14:26:06 -0500 Subject: [PATCH 10/20] fix processed results bug --- src/routes/csv.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/routes/csv.js b/src/routes/csv.js index d3e9043d..ab5704a2 100644 --- a/src/routes/csv.js +++ b/src/routes/csv.js @@ -37,11 +37,12 @@ router.get('/:model_type', async (req, res) => { } } } + /** @todo add a search filter for status once data has a status field. */ let results = await req.context.models[modelType].findAll(options) - - const processedResults = await utils.processResults(results, modelType) + if (results.length !== 0) { + const processedResults = await utils.processResults(results, modelType) const fields = Object.keys(results[0]) parseAsync(processedResults, {fields}).then(csv => { response.setMessage(csv) @@ -55,6 +56,10 @@ router.get('/:model_type', async (req, res) => { 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) From d125654775f3d0faeef570ea6d6fc473242bf03d Mon Sep 17 00:00:00 2001 From: ijadams Date: Tue, 29 Sep 2020 15:02:12 -0500 Subject: [PATCH 11/20] csv edits --- src/routes/csv.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/csv.js b/src/routes/csv.js index ab5704a2..f597b9cb 100644 --- a/src/routes/csv.js +++ b/src/routes/csv.js @@ -40,7 +40,7 @@ router.get('/:model_type', async (req, res) => { /** @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) { const processedResults = await utils.processResults(results, modelType) const fields = Object.keys(results[0]) From 76a9a4b575792563e95192b0843c143cbd6fed27 Mon Sep 17 00:00:00 2001 From: ijadams Date: Wed, 30 Sep 2020 13:22:14 -0500 Subject: [PATCH 12/20] rm auth --- src/routes/csv.js | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/routes/csv.js b/src/routes/csv.js index f597b9cb..b79a05a6 100644 --- a/src/routes/csv.js +++ b/src/routes/csv.js @@ -14,17 +14,6 @@ router.get('/:model_type', async (req, res) => { try { - if (!process.env.BYPASS_LOGIN) { - const e = await utils.loadCasbin() - const roles = await e.getRolesForUser(req.context.me.email) - - if (!roles.includes('admin')) { - response.setCode(400) - response.setMessage('User is not authorized to perform this action.') - return res.status(response.getCode()).send(response.getMessage()) - } - } - /** @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') { From 89a3779eabefda6780f4191229abdb420ead007b Mon Sep 17 00:00:00 2001 From: ijadams Date: Thu, 1 Oct 2020 15:55:42 -0500 Subject: [PATCH 13/20] begin work on single email --- src/routes/contact.js | 48 +++++++++++++++++++++++ swagger.json | 89 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) diff --git a/src/routes/contact.js b/src/routes/contact.js index 5b621187..c8ebbf2b 100644 --- a/src/routes/contact.js +++ b/src/routes/contact.js @@ -204,6 +204,54 @@ router.post('/send', async (req, res) => { return res.status(response.getCode()).send(response.getMessage()) }) + +router.post('/send/:type/:id', async (req, res) => { + const response = new utils.Response() + + try { + if (req.params.type.toLowerCase() === 'entity') { + const entity = await models.Entity.findById(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] + console.log(primary) + // 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(400) + }) + } else { + response.setMessage('Email Address not found.') + response.setCode(500) + } + + response.setMessage({ + results: { + message: `${entity.name} emailed.`, + } + }) + } + } catch (e) { + console.error(e) + response.setCode(500) + } + + + return res.status(response.getCode()).send(response.getMessage()) +}) + // Updates any contact. router.put('/', async (req, res) => { const response = new utils.Response() diff --git a/swagger.json b/swagger.json index 08dd9ac6..0f135dd1 100644 --- a/swagger.json +++ b/swagger.json @@ -1491,6 +1491,95 @@ } } }, + "/contact/send/{type}/{id}": { + "post": { + "tags": [ + "contact" + ], + "summary": "sends a check-in email to all contacts", + "description": "By sending a request to this endpoint, you can send an email to a single contact or all contacts based on entity or contact id. By sending entity ids you will send an email to each contact associated with each entity id passed. By passed contact ids you will send an email to each contact for each entity they are associated with. By passing nothing you will send an email to every contact and every association.", + "parameters": [ + { + "in": "path", + "name": "id", + "schema": { + "type": "string", + "format": "uuid" + }, + "required": true, + "description": "id of the entity" + }, + { + "in": "path", + "name": "type", + "schema": { + "type": "string", + "example": "entity" + }, + "required": true, + "description": "type of the id" + }, + { + "in": "header", + "name": "token", + "required": false, + "deprecated": true, + "schema": { + "type": "string", + "example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3QiLCJpYXQiOjE1ODA3NTM0MDUsImV4cCI6MTU4MDgzOTgwNX0.Q6W7Vo6By35yjZBeLKkk96s8LyqIE2G39AG1H3LRD9M" + } + } + ], + "requestBody": { + "description": "The body of the payload", + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": {} + } + } + } + }, + "responses": { + "200": { + "description": "contact emailed", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "results": { + "type": "object", + "properties": { + "total": { + "type": "number", + "example": 1 + }, + "message": { + "type": "string", + "example": "Contact email sent" + } + } + } + } + } + } + } + }, + "400": { + "description": "Bad Request" + }, + "401": { + "description": "Unauthorized" + }, + "500": { + "description": "Server error" + } + } + } + }, "/contact/{contact_id}": { "get": { "tags": [ From 8b50c92da0253b91e2f9d18e9314a11943a66186 Mon Sep 17 00:00:00 2001 From: ijadams Date: Fri, 2 Oct 2020 14:02:11 -0500 Subject: [PATCH 14/20] update postman --- Bmore-Responsive.postman_collection.json | 58 +++++++++++++++++++++++- 1 file changed, 56 insertions(+), 2 deletions(-) diff --git a/Bmore-Responsive.postman_collection.json b/Bmore-Responsive.postman_collection.json index 508eaa07..daf1f059 100644 --- a/Bmore-Responsive.postman_collection.json +++ b/Bmore-Responsive.postman_collection.json @@ -569,7 +569,7 @@ "response": [] }, { - "name": "Contact Send", + "name": "Contact Send Bulk", "event": [ { "listen": "test", @@ -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": [ @@ -1406,4 +1460,4 @@ } ], "protocolProfileBehavior": {} -} \ No newline at end of file +} From 952fba7c0bd93ff64a8f1b7bceb3c51ecc365ab1 Mon Sep 17 00:00:00 2001 From: ijadams Date: Fri, 2 Oct 2020 14:22:35 -0500 Subject: [PATCH 15/20] add single email contact --- src/routes/contact.js | 65 ++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/src/routes/contact.js b/src/routes/contact.js index c8ebbf2b..22a05465 100644 --- a/src/routes/contact.js +++ b/src/routes/contact.js @@ -209,40 +209,47 @@ router.post('/send/:type/:id', async (req, res) => { const response = new utils.Response() try { + let entity if (req.params.type.toLowerCase() === 'entity') { - const entity = await models.Entity.findById(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] - console.log(primary) - // 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 + 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 } - email.sendContactCheckInEmail(e).then(() => { - response.setMessage(`${entity.name} emailed sent.`) - response.setCode(200) - }, err => { - response.setMessage('There was an error: ' + err) - response.setCode(400) - }) - } else { - response.setMessage('Email Address not found.') - response.setCode(500) - } + }) + } - response.setMessage({ - results: { - message: `${entity.name} emailed.`, - } + 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 + } + console.log('help', e) + email.sendContactCheckInEmail(e).then(() => { + response.setMessage(`${entity.name} emailed sent.`) + response.setCode(200) + }, err => { + response.setMessage('There was an error: ' + err) + response.setCode(400) }) + } else { + response.setMessage('Email Address not found.') + response.setCode(500) } + + response.setMessage({ + results: { + message: `${entity.name} emailed.`, + } + }) } catch (e) { console.error(e) response.setCode(500) From e81c2b1860dcd08884e0bd25e2a73c05617aa680 Mon Sep 17 00:00:00 2001 From: Ian Adams Date: Fri, 9 Oct 2020 11:17:05 -0500 Subject: [PATCH 16/20] rm log --- src/routes/contact.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/routes/contact.js b/src/routes/contact.js index 22a05465..57c4c1ca 100644 --- a/src/routes/contact.js +++ b/src/routes/contact.js @@ -232,7 +232,6 @@ router.post('/send/:type/:id', async (req, res) => { entityId: entity.id, token: temporaryToken } - console.log('help', e) email.sendContactCheckInEmail(e).then(() => { response.setMessage(`${entity.name} emailed sent.`) response.setCode(200) From cb4f97ed10263894efebda57c54d07c60d749f68 Mon Sep 17 00:00:00 2001 From: Ian Adams Date: Tue, 20 Oct 2020 10:20:01 -0500 Subject: [PATCH 17/20] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2a31b15b..48e58690 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ [![Build Status](https://travis-ci.org/CodeForBaltimore/Bmore-Responsive.svg?branch=master)](https://travis-ci.org/CodeForBaltimore/Bmore-Responsive) [![codecov](https://codecov.io/gh/CodeForBaltimore/Bmore-Responsive/branch/master/graph/badge.svg)](https://codecov.io/gh/CodeForBaltimore/Bmore-Responsive) [![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/CodeForBaltimore/Bmore-Responsive.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/CodeForBaltimore/Bmore-Responsive/context:javascript) [![Known Vulnerabilities](https://snyk.io/test/github/CodeForBaltimore/Bmore-Responsive/badge.svg)](https://snyk.io/test/github/CodeForBaltimore/Bmore-Responsive) # Bmore Responsive -A simple, flexible API to support emergency response coordination. Sample use cases include: +A simple, flexible API to support emergency response coordination. Sample use cases include: - keeping track of local nursing home status and needs during a global pandemic - identifying hospitals lacking power during a natural disaster From fecb7955c05f391fcfd8f15629004d14ca8f5346 Mon Sep 17 00:00:00 2001 From: Josh Glazer Date: Fri, 20 Nov 2020 15:41:14 -0500 Subject: [PATCH 18/20] change error type - from code review --- src/routes/contact.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/contact.js b/src/routes/contact.js index 57c4c1ca..25d1a985 100644 --- a/src/routes/contact.js +++ b/src/routes/contact.js @@ -237,7 +237,7 @@ router.post('/send/:type/:id', async (req, res) => { response.setCode(200) }, err => { response.setMessage('There was an error: ' + err) - response.setCode(400) + response.setCode(500) }) } else { response.setMessage('Email Address not found.') From 5dfdbacb2d6dbd982f75d27323afe9f161105d8a Mon Sep 17 00:00:00 2001 From: Josh Glazer Date: Fri, 20 Nov 2020 15:52:26 -0500 Subject: [PATCH 19/20] changing error status code - from code review --- src/routes/csv.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/csv.js b/src/routes/csv.js index b79a05a6..e0abe141 100644 --- a/src/routes/csv.js +++ b/src/routes/csv.js @@ -41,7 +41,7 @@ router.get('/:model_type', async (req, res) => { res.set('Content-Type', 'text/csv') return res.status(response.getCode()).send(response.getMessage()) }, err => { - response.setCode(400) + response.setCode(500) response.setMessage('Not able to parse data: ' + err) return res.status(response.getCode()).send(response.getMessage()) }) From 12ef324e1a633ba2c0e75496294af891614102c6 Mon Sep 17 00:00:00 2001 From: Josh Glazer Date: Tue, 24 Nov 2020 13:25:03 -0500 Subject: [PATCH 20/20] updated status code --- src/routes/contact.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/contact.js b/src/routes/contact.js index 522d656e..cc106a62 100644 --- a/src/routes/contact.js +++ b/src/routes/contact.js @@ -242,7 +242,7 @@ router.post('/send/:type/:id', async (req, res) => { }) } else { response.setMessage('Email Address not found.') - response.setCode(500) + response.setCode(404) } response.setMessage({