Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ RUN npm install
# Bundle app source
COPY . .


# Expose port (will not be respected by Heroku, must be defined in app)
EXPOSE $port

Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Our API spec is on Swagger. You can view it here https://app.swaggerhub.com/apis
Our database documentation can be found in our `docs` folder under `database.csv`. This documentation was created using SchemaSpy. Instructions for use can be found here https://github.com/bcgov/schemaspy

# Setup
A `Dockerfile` and `docker-compose` file have been included for convenience, however this may not be the best local setup for this project. For more information on how to use Docker with this project, please see the [docker section](#24-docker).
A `Dockerfile` and `docker-compose` file have been included for convenience, however this may not be the best local setup for this project. For more information on how to use Docker with this project, please see the [docker section](#docker).

To work on this project you should have:
- NodeJS
Expand Down Expand Up @@ -86,9 +86,9 @@ To make this easier included below is an example `.env` file using all default v
```
NODE_ENV=development
PORT=3000
DATABASE_SCHEMA=public
JWT_KEY=test123
DATABASE_URL=postgres://postgres:postgres@localhost:5432/postgres
DATABASE_SCHEMA=public
BYPASS_LOGIN=true
```

Expand All @@ -114,7 +114,7 @@ To create new models, migrations, and seeders you _must_ use the Sequelize CLI c
- `npx sequelize-cli seed:generate --name demo-user` - Creates a seeder for the `User` model and migration previously setup.

## Docker
To use the `docker-compose.yml` file included you will first need to set [environment variables](#22-environment-variables). You **MUST** set your `DATABASE_HOST` to `db` to use the `docker-compose` solution.
To use the `docker-compose.yml` file included you will first need to set [environment variables](#environment-variables). You **MUST** set your `DATABASE_HOST` to `db` to use the `docker-compose` solution.

If you are running your own database, but want to use the `Dockerfile` you will need to run that this way:
```
Expand All @@ -127,9 +127,9 @@ You can manually set the environment variables and not use a `.env` file by sett
```
-e NODE_ENV=development
-e PORT=3000
-e DATABASE_DATABASE_SCHEMA=<your database schema>
-e JWT_KEY=<your JWT phrase>
-e DATABASE_URL=<your connection string>
-e DATABASE_DATABASE_SCHEMA=<your database schema>
```

# Using this product
Expand Down
12 changes: 12 additions & 0 deletions docs/swagger/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,10 @@
"type" : "string",
"example" : "The Leftorium"
},
"type" : {
"type" : "string",
"example" : "Store"
},
"address" : {
"type" : "object",
"properties" : {
Expand Down Expand Up @@ -613,6 +617,10 @@
"type" : "string",
"example" : "The Leftorium"
},
"type" : {
"type" : "string",
"example" : "Store"
},
"address" : {
"type" : "object",
"properties" : {
Expand Down Expand Up @@ -1257,6 +1265,10 @@
"type" : "string",
"example" : "The Leftorium"
},
"type" : {
"type" : "string",
"example" : "Store"
},
"address" : {
"type" : "object",
"properties" : {
Expand Down
624 changes: 624 additions & 0 deletions rds-combined-ca-bundle.pem

Large diffs are not rendered by default.

25 changes: 22 additions & 3 deletions sequelize/config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
require('dotenv').config();
const fs = require('fs');
const rdsCa = fs.readFileSync('./rds-combined-ca-bundle.pem');

module.exports = {
development: {
use_env_variable: 'DATABASE_URL',
dialect: 'postgres',
}
use_env_variable: 'DATABASE_URL',
dialect: 'postgres',
},
production: {
use_env_variable: 'DATABASE_URL',
dialect: 'postgres',
dialectOptions: {
ssl: {
rejectUnauthorized: true,
ca: [rdsCa],
checkServerIdentity: (host, cert) => {
const error = tls.checkServerIdentity(host, cert);
if (error && !cert.subject.CN.endsWith('.rds.amazonaws.com')) {
return error;
}
}
}
}
},
};
28 changes: 24 additions & 4 deletions src/models/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,40 @@ import Sequelize from 'sequelize';
import path from 'path';
import fs from 'fs';
import _ from 'lodash';

const rdsCa = fs.readFileSync('./rds-combined-ca-bundle.pem');
console.log(__dirname)
let dbUrl;

if (process.env.DATABASE_URL) {
dbUrl = process.env.DATABASE_URL;
} else {
dbUrl = `postgres://${process.env.DATABASE_USERNAME}:${process.env.DATABASE_PASSWORD}@${process.env.DATABASE_HOST}:${process.env.DATABASE_PORT}/${process.env.DATABASE_NAME}`;
}

// Securing our db connection if prod
/** @todo allow other options besides RDS */

let dialectOptions;
if (process.env.NODE_ENV === 'production') {
dialectOptions = {
ssl: {
rejectUnauthorized: true,
ca: [rdsCa],
checkServerIdentity: (host, cert) => {
const error = tls.checkServerIdentity(host, cert);
if (error && !cert.subject.CN.endsWith('.rds.amazonaws.com')) {
return error;
}
}
}
};
}

// Initializes the database.
const sequelize = new Sequelize(
dbUrl,
{
dialect: 'postgres'
dialect: 'postgres',
dialectOptions: dialectOptions
}
);
const basename = path.basename(__filename);
Expand Down Expand Up @@ -47,5 +67,5 @@ Object.keys(models).forEach(key => {
}
});

export {sequelize};
export { sequelize };
export default models;
13 changes: 11 additions & 2 deletions src/routes/contact.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,13 @@ router.post('/', async (req, res) => {
try {
if (req.body.name !== undefined) {
const { name, phone, email, UserId, EntityId } = req.body;

// Validating emails
if (email) {
const goodEmail = await utils.validateEmails(email);
if (!goodEmail) return utils.response(res, 422);
}

const contact = await req.context.models.Contact.create({ name, email, phone, UserId, EntityId });

code = 200;
Expand All @@ -83,9 +90,11 @@ router.put('/', async (req, res) => {
if (validator.isUUID(req.body.id)) {
const { id, name, phone, email, UserId, EntityId } = req.body;

/** @todo validate emails */
// Validating emails
// if (await !utils.validateEmails(email)) res.status(500).send('Server error');
if (email) {
const goodEmail = await utils.validateEmails(email);
if (!goodEmail) return utils.response(res, 422);
}

const contact = await req.context.models.Contact.findOne({
where: {
Expand Down
7 changes: 3 additions & 4 deletions src/routes/entity.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ import validator from 'validator';
import utils from '../utils';

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

// Gets all entities.
router.get('/', async (req, res) => {
let code;
let message;
try {
const entities = await req.context.models.Entity.findAll({
});
const entities = await req.context.models.Entity.findAll();

code = 200;
message = {
Expand Down Expand Up @@ -101,7 +100,7 @@ router.put('/', async (req, res) => {
let code;
let message;
try {
if (validator.isUUID(req.body.id)) {
if (validator.isUUID(req.body.id) && validator.isEmail(req.body.email)) {
let { id, name, address, phone, email, checkIn } = req.body;

/** @todo validate emails */
Expand Down
42 changes: 22 additions & 20 deletions src/routes/user.js
Original file line number Diff line number Diff line change
Expand Up @@ -124,27 +124,29 @@ router.get('/:email', utils.authMiddleware, async (req, res) => {
return utils.response(res, code, message);
});

// Creates a new user.
router.post('/', async (req, res) => {
let code;
let message;
try {
if (validator.isEmail(req.body.email)) {
const { email, password, roles } = req.body;
const user = await req.context.models.User.create({ email, password, roles });

code = 200;
message = user.email + ' created';
} else {
code = 422;
// Creates a new user. ONLY if we're in dev
if (process.env.NODE_ENV === 'development') {
router.post('/', async (req, res) => {
let code;
let message;
try {
if (validator.isEmail(req.body.email)) {
const { email, password, roles } = req.body;
const user = await req.context.models.User.create({ email, password, roles });

code = 200;
message = user.email + ' created';
} else {
code = 422;
}
} catch (e) {
console.error(e);
code = 500;
}
} catch (e) {
console.error(e);
code = 500;
}

return utils.response(res, code, message);
});

return utils.response(res, code, message);
});
}

// Updates any user.
router.put('/', utils.authMiddleware, async (req, res) => {
Expand Down
7 changes: 6 additions & 1 deletion src/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ const authMiddleware = async (req, res, next) => {

}

/**
*
* @param {*} res the response object
* @param {Number} code the response code
* @param {String} message a custom response message
*/
const response = (res, code, message) => {
const codes = {
200: message,
Expand Down Expand Up @@ -97,7 +103,6 @@ const encryptPassword = (password, salt) => {
*/
const validateEmails = async emails => {
for (let email of emails) {
console.log(email.address)
if (!validator.isEmail(email.address)) return false;
}

Expand Down