我们如何将参数传递给自定义快速验证器?

时间:2022-08-01 19:41:28

I would like to prevent a registration with an email address which already exists. Is it possible to use express-validator's new syntax for this? For example:

我想阻止使用已存在的电子邮件地址进行注册。是否可以使用express-validator的新语法?例如:

  router.post('/register', [
    check('email').custom((value, {req}) => {
        return new Promise((resolve, reject) => {
           Users.findOne({email:req.body.email}, function(err, user){
           if(err) {
             reject(new Error('Server Error'))
           }
           if(Boolean(user)) {
             reject(new Error('E-mail already in use'))
           }
           resolve(true)
         });
    });
  })
]
....

How would i pass Users?

我将如何通过用户?

2 个解决方案

#1


1  

express-validator is only aware of the request object itself, what keeps its complexity pretty low for the end-user.
More importantly, it only truly knows about the request's input locations -- body, cookies, headers, query and params.

express-validator只知道请求对象本身,这使得最终用户的复杂性相当低。更重要的是,它只是真正了解请求的输入位置 - 正文,cookie,标题,查询和参数。

Your custom validator is completely correct. That being said, it might not be testable, as you seem to be depending on global context.

您的自定义验证器完全正确。话虽如此,它可能不是可测试的,因为你似乎依赖于全球背景。

In order to make it testable, the 2 options that I see are:

为了使其可测试,我看到的两个选项是:

1. Inject req.Users:

This one would involve using some middleware that sets your store objects onto req:

这个将涉及使用一些中间件将您的商店对象设置为req:

// Validator definition
const emailValidator = (value, { req }) => {
  return req.Users.findOne({ email: value }).then(...);
}

// In production code
// Sets req.Users, req.ToDo, req.YourOtherBusinessNeed
app.use(myObjectsStore.middleware);
app.post('/users', check('email').custom(emailValidator));

// In tests
req = { Users: MockedUsersObject };
expect(emailValidator('foo@bar.com', { req })).rejects.toThrow('email exists');

2. Write a factory function that returns an instance of your validator:

This is my preferred solution, as it doesn't involve using the request object anymore.

这是我的首选解决方案,因为它不再涉及使用请求对象。

// Validator definition
const createEmailValidator = Users => value => {
  return Users.findOne({ email: value }).then(...);
};

// In production code
app.post('/users', [
  check('email').custom(createEmailValidator(myObjectsStore.Users)),
]);

// Or in tests
expect(createEmailValidator(MockedUsersObject)('foo@bar.com')).rejects.toThrow('email exists');

Hope this helps!

希望这可以帮助!

#2


1  

Converting my comments into a final, conclusive answer here :

将我的评论转换为最终的结论性答案:

A validator is simply supposed to validate the fields of request entities against the given criteria of data type / length / pattern.

验证器应该根据数据类型/长度/模式的给定标准来验证请求实体的字段。

You would need to write the method yourself, to determine if the user pre-exists or not. An express-validator ( or rather any validator ) would not do the task of cherry picking if the item exists in your list of items ( or your data-source), neither should it interact with the data-source concerned.

您需要自己编写方法,以确定用户是否预先存在。如果项目列表(或您的数据源)中存在项目,则快速验证器(或者更确切地说是任何验证器)将不执行樱桃挑选任务,也不应该与相关数据源交互。

#1


1  

express-validator is only aware of the request object itself, what keeps its complexity pretty low for the end-user.
More importantly, it only truly knows about the request's input locations -- body, cookies, headers, query and params.

express-validator只知道请求对象本身,这使得最终用户的复杂性相当低。更重要的是,它只是真正了解请求的输入位置 - 正文,cookie,标题,查询和参数。

Your custom validator is completely correct. That being said, it might not be testable, as you seem to be depending on global context.

您的自定义验证器完全正确。话虽如此,它可能不是可测试的,因为你似乎依赖于全球背景。

In order to make it testable, the 2 options that I see are:

为了使其可测试,我看到的两个选项是:

1. Inject req.Users:

This one would involve using some middleware that sets your store objects onto req:

这个将涉及使用一些中间件将您的商店对象设置为req:

// Validator definition
const emailValidator = (value, { req }) => {
  return req.Users.findOne({ email: value }).then(...);
}

// In production code
// Sets req.Users, req.ToDo, req.YourOtherBusinessNeed
app.use(myObjectsStore.middleware);
app.post('/users', check('email').custom(emailValidator));

// In tests
req = { Users: MockedUsersObject };
expect(emailValidator('foo@bar.com', { req })).rejects.toThrow('email exists');

2. Write a factory function that returns an instance of your validator:

This is my preferred solution, as it doesn't involve using the request object anymore.

这是我的首选解决方案,因为它不再涉及使用请求对象。

// Validator definition
const createEmailValidator = Users => value => {
  return Users.findOne({ email: value }).then(...);
};

// In production code
app.post('/users', [
  check('email').custom(createEmailValidator(myObjectsStore.Users)),
]);

// Or in tests
expect(createEmailValidator(MockedUsersObject)('foo@bar.com')).rejects.toThrow('email exists');

Hope this helps!

希望这可以帮助!

#2


1  

Converting my comments into a final, conclusive answer here :

将我的评论转换为最终的结论性答案:

A validator is simply supposed to validate the fields of request entities against the given criteria of data type / length / pattern.

验证器应该根据数据类型/长度/模式的给定标准来验证请求实体的字段。

You would need to write the method yourself, to determine if the user pre-exists or not. An express-validator ( or rather any validator ) would not do the task of cherry picking if the item exists in your list of items ( or your data-source), neither should it interact with the data-source concerned.

您需要自己编写方法,以确定用户是否预先存在。如果项目列表(或您的数据源)中存在项目,则快速验证器(或者更确切地说是任何验证器)将不执行樱桃挑选任务,也不应该与相关数据源交互。