Преглед на файлове

Update all validation. Include string sanitization.

Lee Morgan преди 6 години
родител
ревизия
f974174708

+ 1 - 0
app.js

@@ -14,6 +14,7 @@ app.use(session({
     saveUninitialized: true,
     resave: false
 }));
+app.use(require("sanitize").middleware);
 app.use(express.static(__dirname + "/views"));
 app.use(express.urlencoded({extended: true}));
 app.use(express.json());

+ 19 - 0
package-lock.json

@@ -276,6 +276,11 @@
       "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.1.tgz",
       "integrity": "sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw=="
     },
+    "lodash": {
+      "version": "4.17.15",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
+      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
+    },
     "media-typer": {
       "version": "0.3.0",
       "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@@ -473,6 +478,15 @@
       "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
       "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
     },
+    "sanitize": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/sanitize/-/sanitize-2.1.0.tgz",
+      "integrity": "sha512-HLDVriFJnrm6ElDe2E8alAKDMZGMtM8CdKhvunp9592j8hNwZmmsmhk/t6WZbWonKJsHK0OoxH5S1Yoie4sSpw==",
+      "requires": {
+        "lodash": "^4.17.0",
+        "validator": "^3.33.0"
+      }
+    },
     "semver": {
       "version": "5.7.1",
       "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
@@ -568,6 +582,11 @@
       "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
       "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
     },
+    "validator": {
+      "version": "3.43.0",
+      "resolved": "https://registry.npmjs.org/validator/-/validator-3.43.0.tgz",
+      "integrity": "sha1-lkZLmS1BloM9l6GUv0Cxn/VLrgU="
+    },
     "vary": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",

+ 2 - 1
package.json

@@ -23,6 +23,7 @@
     "ejs": "^2.7.1",
     "express": "^4.17.1",
     "express-session": "^1.17.0",
-    "mongoose": "^5.7.4"
+    "mongoose": "^5.7.4",
+    "sanitize": "^2.1.0"
   }
 }

+ 1 - 1
views/inventoryPage/addIngredient.js

@@ -40,7 +40,7 @@ let addIngredientObj = {
             quantity: document.querySelector("#addQuantity").value
         }
 
-        if(validator.ingredient.quantity){
+        if(validator.ingredient.quantity(item.quantity)){
             axios.post("/merchant/ingredients/create", item)
                 .then((ingredient)=>{
                     if(typeof(ingredient.data) === "string"){

+ 0 - 5
views/merchantSetupPage/addIngredients.js

@@ -59,11 +59,6 @@ addIngredientsObj = {
             if(row.children[0].children[0].checked){
                 let quantity = row.children[3].children[0].value;
 
-                if(quantity === ""){
-                    banner.createError("Must provide a quantity for all checked ingredients");
-                    return;
-                }
-
                 if(validator.ingredient.quantity(quantity)){
                     controller.data.inventory.push({
                         ingredient: {

+ 6 - 14
views/merchantSetupPage/createIngredients.js

@@ -84,23 +84,15 @@ let createIngredientsObj = {
         let axiosIngredients = [];
         
         for(let row of tbody.children){
-            let name = row.children[0].children[0].value;
-            let category = row.children[1].children[0].value;
             let quantity = row.children[2].children[0].value;
-            let unit = row.children[3].children[0].value;
 
-            let checkName = validator.ingredient.name(name);
-            let checkCategory = validator.ingredient.category(category);
-            let checkQuantity = validator.ingredient.quantity(quantity);
-            let checkUnit = validator.ingredient.unit(unit);
-
-            if(checkName && checkCategory && checkQuantity && checkUnit){
-                let newIngredient = {
-                    name: name,
-                    category: category,
-                    unit: unit
-                }
+            let newIngredient = {
+                name: row.children[0].children[0].value,
+                category: row.children[1].children[0].value,
+                unit: row.children[3].children[0].value
+            }
 
+            if(validator.ingredient.all(newIngredient, quantity)){
                 axiosIngredients.push(newIngredient);
 
                 newIngredients.push({

+ 0 - 1
views/merchantSetupPage/createRecipes.js

@@ -133,7 +133,6 @@ let createRecipesObj = {
                 }
 
                 this.showRecipe();
-
             }
         }
     },

+ 65 - 55
views/recipesPage/singleRecipe.js

@@ -71,8 +71,9 @@ let singleRecipeObj = {
 
         let saveButton = document.createElement("button");
         saveButton.innerText = "Save";
-        actionTd.appendChild(saveButton);
+        saveButton.classList = "button-small";
         saveButton.onclick = ()=>{this.addIngredient(recipe, name.value, quantity.value, row);};
+        actionTd.appendChild(saveButton);
     },
 
     addIngredient: function(recipe, ingredientId, quantity, row){
@@ -81,6 +82,8 @@ let singleRecipeObj = {
             quantity: quantity
         }
         
+
+        // Lets just not show the ingredient... duh
         for(let ingredient of recipe.ingredients){
             if(ingredient.ingredient._id === ingredientId){
                 banner.createError("That ingredient is already in this recipe");
@@ -88,60 +91,62 @@ let singleRecipeObj = {
             }
         }
         
-        axios.post("/merchant/recipes/ingredients/create", {recipeId: recipe._id, item: item})
-            .then((response)=>{
-                if(typeof(response.data) === "string"){
-                    banner.createError(response.data);
-                }else{
-                    for(let i = 0; i < merchant.recipes.length; i++){
-                        if(merchant.recipes[i]._id === recipe._id){
-                            merchant.recipes.splice(i, 1);
-                            break;
+        if(validator.ingredient.quantity(item.quantity)){
+            axios.post("/merchant/recipes/ingredients/create", {recipeId: recipe._id, item: item})
+                .then((response)=>{
+                    if(typeof(response.data) === "string"){
+                        banner.createError(response.data);
+                    }else{
+                        for(let i = 0; i < merchant.recipes.length; i++){
+                            if(merchant.recipes[i]._id === recipe._id){
+                                merchant.recipes.splice(i, 1);
+                                break;
+                            }
                         }
-                    }
-                    merchant.recipes.push(response.data);
-                    recipesObj.isPopulated = false;
+                        merchant.recipes.push(response.data);
+                        recipesObj.isPopulated = false;
 
-                    //Change row from displaying options to showing default display
-                    while(row.children.length > 0){
-                        row.removeChild(row.firstChild);
-                    }
+                        //Change row from displaying options to showing default display
+                        while(row.children.length > 0){
+                            row.removeChild(row.firstChild);
+                        }
 
-                    let addIngredient = merchant.inventory.find(i => i.ingredient._id === ingredientId);
+                        let addIngredient = merchant.inventory.find(i => i.ingredient._id === ingredientId);
 
-                    let name = document.createElement("td");
-                    name.innerText = addIngredient.ingredient.name;
-                    row.appendChild(name);
+                        let name = document.createElement("td");
+                        name.innerText = addIngredient.ingredient.name;
+                        row.appendChild(name);
 
-                    let quantity = document.createElement("td");
-                    quantity.innerText = `${item.quantity} ${addIngredient.ingredient.unit}`;
-                    row.appendChild(quantity);
+                        let quantity = document.createElement("td");
+                        quantity.innerText = `${item.quantity} ${addIngredient.ingredient.unit}`;
+                        row.appendChild(quantity);
 
-                    let actions = document.createElement("td");
-                    row.appendChild(actions);
+                        let actions = document.createElement("td");
+                        row.appendChild(actions);
 
-                    let editButton = document.createElement("button");
-                    editButton.innerText = "Edit";
-                    editButton.onclick = ()=>{this.editIngredient(row, addIngredient, recipe);};
-                    actions.appendChild(editButton);
+                        let editButton = document.createElement("button");
+                        editButton.innerText = "Edit";
+                        editButton.classList = "button-small";
+                        editButton.onclick = ()=>{this.editIngredient(row, addIngredient, recipe);};
+                        actions.appendChild(editButton);
 
-                    let removeButton = document.createElement("button");
-                    removeButton.innerText = "Remove";
-                    removeButton.onclick = ()=>{this.deleteIngredient(recipe._id, ingredientId, row);};
-                    actions.appendChild(removeButton);
-                }
-            })
-            .catch((err)=>{
-                row.parentNode.removeChild(row);
-                banner.createError("There was an error and the recipe could not be updated");
-            });
+                        let removeButton = document.createElement("button");
+                        removeButton.innerText = "Remove";
+                        removeButton.classList = "button-small";
+                        removeButton.onclick = ()=>{this.deleteIngredient(recipe._id, ingredientId, row);};
+                        actions.appendChild(removeButton);
+                    }
+                })
+                .catch((err)=>{
+                    row.parentNode.removeChild(row);
+                    banner.createError("There was an error and the recipe could not be updated");
+                });
+        }
     },
 
     //Delete ingredient from table
     //Delete ingredient from database
     deleteIngredient: function(recipeId, ingredientId, row){
-        
-        
         axios.post("/merchant/recipes/ingredients/remove", {ingredientId: ingredientId, recipeId: recipeId})
             .then((result)=>{
                 if(typeof(result.data) === "string"){
@@ -199,18 +204,23 @@ let singleRecipeObj = {
         button.innerText = "Edit";
         button.onclick = ()=>{this.editIngredient(row, ingredient, recipe);};
 
-        axios.post("/merchant/recipes/ingredients/update", {recipeId: recipe._id, ingredient: ingredient})
-            .then((result)=>{
-                if(typeof(result.data) === "string"){
-                    banner.createError(result.data);
-                }else{
-                    td.innerText = `${ingredient.quantity} ${ingredient.ingredient.unit}`;
-                    banner.createNotification("Ingredient successfully updated");
-                }
-            })
-            .catch((err)=>{
-                td.innerText = `${originalQuantity} ${ingredient.ingredient.unit}`;
-                banner.createError("There was an error and the ingredient could not be updated");
-            });
+        if(validator.ingredient.quantity(ingredient.quantity)){
+            axios.post("/merchant/recipes/ingredients/update", {recipeId: recipe._id, ingredient: ingredient})
+                .then((result)=>{
+                    if(typeof(result.data) === "string"){
+                        td.innerText = `${originalQuantity} ${ingredient.ingredient.unit}`;
+                        banner.createError(result.data);
+                    }else{
+                        td.innerText = `${ingredient.quantity} ${ingredient.ingredient.unit}`;
+                        banner.createNotification("Ingredient successfully updated");
+                    }
+                })
+                .catch((err)=>{
+                    td.innerText = `${originalQuantity} ${ingredient.ingredient.unit}`;
+                    banner.createError("There was an error and the ingredient could not be updated");
+                });
+        }else{
+            td.innerText = `${originalQuantity} ${ingredient.ingredient.unit}`;
+        }
     },
 }

+ 52 - 3
views/shared/validation.js

@@ -1,6 +1,15 @@
 let validator = {
     ingredient: {
         name: function(ingName, createBanner = true){
+            //Check for special chars
+            if(!validator.isSanitary(ingName)){
+                if(createBanner){
+                    banner.createError("Your inputs contain illegal characters");
+                }
+                return false
+            }
+
+            //Check for length
             if(ingName.length < 2){
                 if(createBanner){
                     banner.createError("Ingredient name must contain at least 2 characters");
@@ -12,6 +21,16 @@ let validator = {
         },
 
         category: function(ingCategory, createBanner = true){
+            //Check for special chars
+            if(!validator.isSanitary(ingCategory)){
+                if(createBanner){
+                    banner.createError("Your inputs contain illegal characters");
+                }
+
+                return false;
+            }
+
+            //Check for length
             if(ingCategory.length < 3){
                 if(createBanner){
                     banner.createError("Category name must contain at least 3 characters");
@@ -23,17 +42,35 @@ let validator = {
         },
 
         quantity: function(num, createBanner = true){
+            if(isNaN(num) || num === ""){
+                if(createBanner){
+                    banner.createError("Must enter a valid number");
+                }
+
+                return false;
+            }
+
             if(num < 0){
                 if(createBanner){
                     banner.createError("Quantity cannot be a negative number");
                 }
+
                 return false;
             }
 
             return true;
         },
 
-        unit: (ingUnit)=>{
+        unit: function(ingUnit, createBanner = true){
+            //Check for special chars
+            if(!validator.isSanitary(ingUnit)){
+                if(createBanner){
+                    banner.createError("Your inputs contain illegal characters");
+                }
+
+                return false;
+            }
+
             return true;
         },
 
@@ -42,8 +79,8 @@ let validator = {
         all: function(ingObject, quantity = 0, createBanner = true){
             let nameCheck = this.name(ingObject.name, createBanner);
             let categoryCheck = this.category(ingObject.category, createBanner);
-            let unitCheck = this.unit(ingObject.unitType, createBanner);
-            let quantityCheck = this.quantity(Number(quantity), createBanner);
+            let unitCheck = this.unit(ingObject.unit, createBanner);
+            let quantityCheck = this.quantity(quantity, createBanner);
 
             if(!nameCheck || !categoryCheck || !quantityCheck || !unitCheck){
                 return false;
@@ -71,5 +108,17 @@ let validator = {
 
             return true;
         }
+    },
+
+    isSanitary: function(str){
+        let disallowed = ["\\", "<", ">", "$"];
+
+        for(let char of disallowed){
+            if(str.includes(char)){
+                return false;
+            }
+        }
+
+        return true;
     }
 }