是否有必要使用joi和mongoose验证相同的架构,以防止未验证的数据插入?

时间:2019-03-20 19:34:43

标签: node.js mongodb express mongoose

我的问题是,是否需要双重验证,包括使用joi和mongoose来防止未验证的数据插入,或者是否出于工作目的,只会让我失去性能? 我想防止joi的验证出现错误, 如果发生这种情况,则未经验证的数据将插入到MongoDb中。 最好的做法是什么?

我的代码:

Product.js:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const model = mongoose.model;

const ProductSchema = new Schema({

name: {
    type: String,
    minlength: 5,
    maxlength: 50,
    required: true,
    validate: [{
            validator: async name => await Product.where({ name }).countDocuments() === 0,
            message: ({ value }) => `El nombre del producto: ${value} ya esta cogido.` // TODO: security
        },
        {
            validator: async function(value) {
                const regex = /^[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ]{1}[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ\s]{3,48}[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ]{1}$/;
                return await regex.test(value);

            },
            message: 'solo letras y numeros, sin espacio al principio y al final' // TODO: security
        },
    ]
},

description: {
    type: String,
    minlength: 30,
    maxlength: 250,
    required: true,
    validate: {
        validator: async function(value) {
            const regex = /^[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ]{1}[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ\s]{28,248}[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ]{1}$/;
            return await regex.test(value)
        },
        message: 'solo letras y numeros, sin espacio al principio y al final' // TODO: security
    }
},

shortDescription: {
    type: String,
    minlength: 20,
    maxlength: 100,
    required: true,
    validate: {
        validator: async function(value) {
            const regex = /^[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ]{1}[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ\s]{18,98}[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ]{1}$/;
            return await regex.test(value)
        },
        message: 'solo letras y numeros, sin espacio al principio y al final' // TODO: security
    }
},

tags: [{
    type: String,
    requirer: true,
    validate: {
        validator: async function(value) {
            const regex = /^[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ]{1}[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ\s]{3,98}[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ]{1}$/;
            return await ((value && value.length > 4) && (regex.test(value)));
        },
        message: 'El producto tiene que tener como minimo un tag y cada tag min 5 caracteres solo letras y numeros, sin espacio al principio y al final.' // TODO: security
    }
}],

price: {
    type: Number,
    min: 30,
    required: true,
    validate: {

        validator: async val => await (

            val.isInteger && val >= 30
        ),
        message: ({ value }) => `El precio del producto: ${value} es invalido, tiene que ser positivo y mayor o igual a 30` // TODO: security
    }
},

create_At: { type: Date, default: Date.now }
});


const Product = model('Product', ProductSchema);

exports.Product = Product;

ProductJoiValidation:

const Joi = require('joi');

const nameSchema = Joi.string().min(5).max(50).regex(/^[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ]{1}[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ\s]{3,48}[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ]{1}$/).label("Nombre del producto").options({
    language: {
        string: {
            regex: {
                base: "El nombre del producto no puede contener espacios ni al principio ni al final, solo caracteres alfanumericos"
            }
        }
    }
});

const descriptionSchema = Joi.string().min(30).max(250).regex(/^[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ]{1}[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ\s]{28,248}[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ]{1}$/).label("Descripcion del producto").options({
    language: {
        string: {
            regex: {
                base: "La descripcion del producto no puede contener espacios ni al principio ni al final, solo caracteres alfanumericos"
            }
        }
    }
});

const shortDescriptionSchema = Joi.string().min(20).max(100).regex(/^[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ]{1}[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ\s]{18,98}[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ]{1}$/).label("Descripcion corta del producto").options({
    language: {
        string: {
            regex: {
                base: "La descripcion del producto no puede contener espacios ni al principio ni al final, solo caracteres alfanumericos"
            }
        }
    }
});

const tagsSchema = Joi.array().items(Joi.string().min(5).regex(/^[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ]{1}[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ\s]{3,98}[a-zA-Z0-9ÁÉÍÓÚñáéíóúÑ]{1}$/)).min(1).label("tags").options({
    language: {
        string: {
            regex: {
                base: "Los tags del producto no puede contener espacios ni al principio ni al final, solo caracteres alfanumericos"
            }
        }
    }
});

const priceSchema = Joi.number().integer().positive().min(30);


const createProductSchema = Joi.object().keys({

    name: nameSchema.required(),
    description: descriptionSchema.required(),
    shortDescription: shortDescriptionSchema.required(),   
    tags: tagsSchema.required(),      
    price: priceSchema.required()

});

function validateCreateProduct(createProduct) {

    return Joi.validate(createProduct, createProductSchema, { abortEarly: false });
};

module.exports = {
    validateCreateProduct    
}

我想防止joi的验证出现错误, 如果发生这种情况,未经验证的数据将插入到MongoDb中。

这里最好的是什么?

2 个答案:

答案 0 :(得分:1)

您可以尝试Joigoose。您创建一个Joi Schema并将其传递给Mongoose,例如:

new Mongoose.Schema(Joigoose.convert(joiUserSchema));

我已经使用了一段时间,没有问题。

答案 1 :(得分:0)

您必须使用适当的JOI函数来验证数据。如果使用,则标准是使用中间件https://www.npmjs.com/package/express-joi-validation,该中间件会引发错误并且不会在控制器中执行代码。并且不要在端点处理程序中进行验证,而要使用中间件,否则事情会变得混乱!很棒的事情是,您只需要传递您的JOI对象,程序包将负责响应。