Search code examples
node.jsexpressmongooseexpress-validator

Record updating in database even with failed validation


I have an issue where even when form validation fails the record is altered in the database.

Basically what I am trying to do is submit the form, get the data from the form fields and if validation fails, it should render the view with altered user input otherwise display data from the database for that record in the input fields.

Upon successful validation it should create a flash message to display to the user. I have added a few comments in the code for explanation as well.

 exports.postEditListing = (req, res, next) => {
    // get values from form input on form submission
    const updatedTitle = req.body.title;
    const updatedDescription = req.body.description;
    const updatedCategory = req.body.category;
    const image = req.file;
    const productId = req.body.productId;
    // creates slug from title field
    const updatedSlugTitle = slugify(updatedTitle, {
        lower: true,
        remove: /[*+~.()'"!:@]/g
    });
    const errors = validationResult(req);
    // if there ARE validation errors 
    if (!errors.isEmpty()) {
        // Get categories from database where they aren't equal to what the user selected in the form
        Category.find({ catName: { $ne: updatedCategory } })
        .then(cats =>{
            // render the view again showing the form data either updated by user if they edited fields or from the database
            return res.status(422).render('account/edit-listing', {
                pageTitle: 'Edit Listing',
                path: '/account/edit-listing',
                product: {
                    title: updatedTitle,
                    _id: productId,
                    category: updatedCategory,
                    description: updatedDescription
                },
                errorMessage: errors.array(),
                successMessage: null,
                pendingCount: req.pending,
                approveCount: req.approved,
                rejectCount: req.rejected,
                userId: req.user._id,
                cats: cats
            });
        })
        .catch(err => {
            console.log(err);
        })

    }
    // If validation succeeds, find the product by ID in the database
    Product.findById(productId)
        .then(product => {
            // set database fields to the updated form input values
            product.title = updatedTitle;
            product.description = updatedDescription;
            product.titleSlug = updatedSlugTitle;
            product.category = updatedCategory;
            // if there is a new image selected, delete the existing one and set a new one
            if (image) {
                fileHelper.deleteFile(product.image);
                product.image = image.path;
            }
            // save changes to database.
            return product.save()
                .then(result => {
                    // set flash message and redirect to the same page
                    req.flash('success', 'Category successfully added.');
                    res.redirect('/account/edit-listing/' + product._id);
                    console.log('success!');

                });

        })
        .catch(err => {
            // const error = new Error(err);
            // error.httpStatusCode = 500;
            // return next(error);
            console.log(err);
        });
};

The second issue is that if the fields are filled in correctly, an error still occurs:

unhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)

UPDATE:

I have changed the above code and now I can see that success! shows in the console even if there is a validation error, meaning that this block of code runs when it actually should not get to this code at all if validation fails:

        return product.save()
            .then(result => {
                // set flash message and redirect to the same page
                req.flash('success', 'Category successfully added.');
                res.redirect('/account/edit-listing/' + product._id);
                console.log('success!');

            });

Solution

  • About the first issue. You have an if statement to check if validation fails. So you can add an else statement after if and execute the code you want only if validation is successful.