21. Data Sanitization & Schema Validation

Faraz AlamFaraz Alam
4 min read
  • "Data sanitization in MongoDB" refers to the process of defining rules within your MongoDB schema to clean and filter user input data before storing it in the database, preventing potential malicious code or invalid data from being inserted

  • mostly POST and PATCH API somehow interact with data by inserting the data either by registration or updation where we can perform strict checks.

  • we perform some check and validation inside schema defined also

  • we can see here how mongoose define schema type and according to that you can keep check on fields.

  • Some of schema types are:-

    required: true/false:- to make any field mandatory

    unique: true/false:- to make any field unique and any duplicate value not allowed in field

    default:value :- to make default value of any field property.

    lowercase:true/false:- to convert string in lowercase or uppercase

    trim:true/false :- to trim down extra space within string

    minLength / maxLength : integer :- to fix the maximum and minimum length of string to be entered in string

    min / max: value :- it is same as minLength and maxLength but it is for Number data type

    validate() :- this function is used to add custom validation function to any field

      gender: {
          type: String,
          validate(value) {
            if (!["male", "female", "others"].includes(value)) {
              throw new Error("gender invalid");
            }
          },
        },
    

    but during updation using findByIdAndUpdate() we have to add an attribute as “runValidators:true“

    timestamps:true :- to add time and date at which the data is altered in database it is added in schemas directly

  • validating email is not easy job so we need a package provided by npm known as express-validator to validate email

  • after doing “npm i express-validator“ use validator with validate function

  • API level validation is mostly applied on patch and post request

      //schema validation
      const mongoose = require("mongoose");
      const validator = require("validator");
      const userSchema = new mongoose.Schema(
        {
          firstName: {
            type: String,
            minLength: 4,
            maxLength: 25,
          },
          lastName: {
            type: String,
          },
          emailId: {
            type: String,
            required: true,
            unique: true,
            validate(value) {
              if (!validator.isEmail(value)) {
                throw new Error("invalid email address");
              }
            },
          },
          password: {
            type: String,
            required: true,
            validate(value) {
              if (!validator.isStrongPassword(value)) {
                throw new Error(
                  "Password must be at least 8 characters long, and must contain at least"
                );
              }
            },
          },
          city: {
            type: String,
          },
          age: {
            type: String,
            min: 10,
            max: 30,
          },
          gender: {
            type: String,
            validate(value) {
              if (!["male", "female", "others"].includes(value)) {
                throw new Error("gender invalid");
              }
            },
          },
          photoURL: {
            type: String,
          },
          skills: {
            type: [],
          },
          about: {
            type: String,
            default: "This is default value",
          },
        },
        {
          timestamps: true,
        }
      );
      const User = mongoose.model("User", userSchema);
      module.exports = User;
    
      //app.js
      const express = require("express");
      const app = express();
      const connectDB = require("./config/database"); //getting DB connection
      const port = 3000;
      const User = require("./models/user"); //getting User model
      app.use(express.json());
      app.get("/user", async (req, res) => {
        const userEmail = req.body.emailId;
        try {
          const user = await User.find({ emailId: userEmail });
          if (user.length === 0) {
            res.status(404).send("user list empty");
          } else {
            res.send(user);
          }
        } catch (err) {
          res.status(400).send("error saving the data:- " + err.message);
        }
      });
      app.delete("/user", async (req, res) => {
        const userID = req.body.userId;
        try {
          const user = await User.findByIdAndDelete({ _id: userID });
          res.send("deleted success");
        } catch (err) {
          res.status(400).send("Error;- " + err.message);
        }
      });
      app.post("/user", async (req, res) => {
        const user = new User(req.body);
        try {
          await user.save();
          res.send("data saved success");
        } catch (err) {
          res.status(404).send("error:- " + err.message);
        }
      });
      app.patch("/user", async (req, res) => {
        const userId = req.body.userId;
        const data = req.body;
    
        try {
          const ALLOWED_UPDATES = ["firstName", "about", "gender", "age", "city"];
          const isUpdateAllowed = Object.keys(data).every((k) =>
            ALLOWED_UPDATES.includes(k)
          );
          if (!isUpdateAllowed) {
            throw new Error("update not allowed");
          }
          if (data?.skills.length > 10) {
            throw new Error("skills cannot be more than 10");
          }
          const user = await User.findByIdAndUpdate({ _id: userId }, data, {
            returnDocument: "before", //this returnDocument is added to know the data before or after updation
            runValidators: true, //this is used to validate the data
          });
          console.log(user); //to know before/after the data updation.
          res.send("updated successfully");
        } catch (err) {
          res.status(400).send("Error:- " + err.message);
        }
      });
      connectDB()
        .then(() => {
          console.log("connected to DB");
          app.listen(port, () => {
            console.log(`Server is running on port ${port}`);
          });
        })
        .catch((err) => {
          console.error("Not connected to DB");
        });
    
0
Subscribe to my newsletter

Read articles from Faraz Alam directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Faraz Alam
Faraz Alam

Assalamualaikum warahmatullah wabarakatuh( traditional Islamic greeting in Arabic "Assalamu alaikum": "Peace be upon you." "Wa rahmatullahi": "And the mercy of Allah." "Wa barakatuh": "And His blessings.") I’m Faraz Alam, and I’m documenting my journey through the world of software technology. Despite earning a master’s degree in Computer Applications and having access to opportunities provided by my tier-3 college, I struggled to take full advantage of them due to poor management and a less productive environment. This led to joblessness, primarily due to a lack of upskilling. Now, I am dedicated to enhancing my skills and knowledge with the aim of securing a valuable job offer from leading product-based companies, including those in the FAANG group (Facebook, Amazon, Apple, Netflix, Google) and other prominent tech giants. This documentation is not for self-promotion; rather, it is for anyone who is waiting for an opportunity but feels they lack the tools and skills required to overcome challenges. It’s a testament to the effort and responsibility needed to navigate the journey towards success when you take charge of your own path. Date: 31 July 2024, 07:25 AM This page will be updated regularly to reflect new achievements and milestones as I continue to build my career.