Skip to content

Commit

Permalink
Starting to add schema validation to API endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
Mark Moffat committed Jun 17, 2019
1 parent de5a01c commit fc1580d
Show file tree
Hide file tree
Showing 16 changed files with 1,119 additions and 184 deletions.
42 changes: 26 additions & 16 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const colors = require('colors');
const cron = require('node-cron');
const common = require('./lib/common');
const { runIndexing } = require('./lib/indexing');
const { addSchemas } = require('./lib/schema');
const { initDb } = require('./lib/db');
let handlebars = require('express-handlebars');

Expand Down Expand Up @@ -78,7 +79,7 @@ app.set('view engine', 'hbs');
// helpers for the handlebar templating platform
handlebars = handlebars.create({
helpers: {
perRowClass: function(numProducts){
perRowClass: (numProducts) => {
if(parseInt(numProducts) === 1){
return'col-md-12 col-xl-12 col m12 xl12 product-item';
}
Expand All @@ -94,7 +95,7 @@ handlebars = handlebars.create({

return'col-md-6 col-xl-6 col m6 xl6 product-item';
},
menuMatch: function(title, search){
menuMatch: (title, search) => {
if(!title || !search){
return'';
}
Expand All @@ -103,22 +104,22 @@ handlebars = handlebars.create({
}
return'';
},
getTheme: function(view){
getTheme: (view) => {
return`themes/${config.theme}/${view}`;
},
formatAmount: function(amt){
formatAmount: (amt) => {
if(amt){
return numeral(amt).format('0.00');
}
return'0.00';
},
amountNoDecimal: function(amt){
amountNoDecimal: (amt) => {
if(amt){
return handlebars.helpers.formatAmount(amt).replace('.', '');
}
return handlebars.helpers.formatAmount(amt);
},
getStatusColor: function (status){
getStatusColor: (status) => {
switch(status){
case'Paid':
return'success';
Expand All @@ -138,52 +139,58 @@ handlebars = handlebars.create({
return'danger';
}
},
checkProductOptions: function (opts){
checkProductOptions: (opts) => {
if(opts){
return'true';
}
return'false';
},
currencySymbol: function(value){
currencySymbol: (value) => {
if(typeof value === 'undefined' || value === ''){
return'$';
}
return value;
},
objectLength: function(obj){
objectLength: (obj) => {
if(obj){
return Object.keys(obj).length;
}
return 0;
},
checkedState: function (state){
stringify: (obj) => {
if(obj){
return JSON.stringify(obj);
}
return'';
},
checkedState: (state) => {
if(state === 'true' || state === true){
return'checked';
}
return'';
},
selectState: function (state, value){
selectState: (state, value) => {
if(state === value){
return'selected';
}
return'';
},
isNull: function (value, options){
isNull: (value, options) => {
if(typeof value === 'undefined' || value === ''){
return options.fn(this);
}
return options.inverse(this);
},
toLower: function (value){
toLower: (value) => {
if(value){
return value.toLowerCase();
}
return null;
},
formatDate: function (date, format){
formatDate: (date, format) => {
return moment(date).format(format);
},
ifCond: function (v1, operator, v2, options){
ifCond: (v1, operator, v2, options) => {
switch(operator){
case'==':
return(v1 === v2) ? options.fn(this) : options.inverse(this);
Expand All @@ -207,7 +214,7 @@ handlebars = handlebars.create({
return options.inverse(this);
}
},
isAnAdmin: function (value, options){
isAnAdmin: (value, options) => {
if(value === 'true' || value === true){
return options.fn(this);
}
Expand Down Expand Up @@ -355,6 +362,9 @@ initDb(config.databaseConnectionString, async (err, db) => {
config.trackStock = true;
}

// Process schemas
await addSchemas();

// We index when not in test env
if(process.env.NODE_ENV !== 'test'){
try{
Expand Down
21 changes: 21 additions & 0 deletions lib/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,32 @@ const mongoSanitize = (param) => {
return param;
};

const safeParseInt = (param) => {
if(param){
try{
return parseInt(param);
}catch(ex){
return param;
}
}else{
return param;
}
};

const checkboxBool = (param) => {
if(param && param === 'on'){
return true;
}
return false;
};

const convertBool = (value) => {
if(value === 'true' || value === true){
return true;
}
return false;
};

const showCartCloseBtn = (page) => {
let showCartCloseButton = true;
if(page === 'checkout' || page === 'pay'){
Expand Down Expand Up @@ -512,7 +531,9 @@ module.exports = {
fileSizeLimit,
cleanHtml,
mongoSanitize,
safeParseInt,
checkboxBool,
convertBool,
showCartCloseBtn,
addSitemapProducts,
clearSessionValue,
Expand Down
23 changes: 23 additions & 0 deletions lib/schema.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const path = require('path');
const fs = require('fs');
const _ = require('lodash');
const Validator = require('jsonschema').Validator;
const v = new Validator();
const glob = require('glob-fs')();

const addSchemas = () => {
const schemaFiles = glob.readdirSync('./lib/**/*.json');
_.forEach(schemaFiles, (file) => {
const fileData = JSON.parse(fs.readFileSync(file, 'utf-8'));
v.addSchema(fileData, path.basename(schemaFiles[0], '.json'));
});
};

const validateJson = (schema, json) => {
return v.validate(json, schema);
};

module.exports = {
addSchemas,
validateJson
};
40 changes: 40 additions & 0 deletions lib/schemas/editProduct.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"id": "/editProduct",
"type": "object",
"properties": {
"productPermalink": {
"type": "string"
},
"productTitle": {
"type": "string"
},
"productPrice": {
"type": "number"
},
"productDescription": {
"type": "string"
},
"productPublished": {
"type": "boolean"
},
"productTags": {
"type": "string"
},
"productOptions": {
"type": ["object", "string", "null"]
},
"productComment": {
"type": "boolean"
},
"productStock": {
"type": ["number", "null"]
}
},
"required": [
"productPermalink",
"productTitle",
"productPrice",
"productDescription",
"productPublished"
]
}
40 changes: 40 additions & 0 deletions lib/schemas/newProduct.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"id": "/newProduct",
"type": "object",
"properties": {
"productPermalink": {
"type": "string"
},
"productTitle": {
"type": "string"
},
"productPrice": {
"type": "number"
},
"productDescription": {
"type": "string"
},
"productPublished": {
"type": "boolean"
},
"productTags": {
"type": "string"
},
"productOptions": {
"type": ["object", "string", "null"]
},
"productComment": {
"type": "boolean"
},
"productStock": {
"type": ["number", "null"]
}
},
"required": [
"productPermalink",
"productTitle",
"productPrice",
"productDescription",
"productPublished"
]
}
Loading

0 comments on commit fc1580d

Please sign in to comment.