tmpfs / async-validate

Asynchronous type validation for node and the browser
Other
314 stars 45 forks source link

How to validate against other values? #61

Closed jaysson closed 8 years ago

jaysson commented 8 years ago

I am trying to validate a token against a user account, fetched by email.

const descriptor = {
        type: 'object',
        fields: {
            email: {
                type: 'string',
                required: true,
                test: function (cb) {
                    let regexp = /^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i;
                    if (!this.value.match(regexp)) {
                        this.raise('Invalid email address');
                    }
                    User.findOne({email: this.value}).then((user) => {
                        if (!user) {
                            this.raise('User not found');
                        }
                        cb();
                    }).catch((error) => {
                        throw error;
                    });
                }
            },
            token: {
                type: 'string',
                required: true,
                test: function (cb) {
                    // Need to get email here somehow
                    User.findOne({email: email, email_verification_token: this.value}).then((user) => {
                        if (!user) {
                            this.raise('Invalid token');
                        }
                        cb();
                    }).catch((error) => {
                        console.log(error)
                        this.raise(error.message)
                    });
                }
            }
        }
    };

I tried accessing this.source but it only contains the token while validating token. Email is removed after email validation.

In general, I can think of many use cases where you want to validate a field against another. For example, end_date > start_date.

How do I do this?

tmpfs commented 8 years ago

You should be able to access email via this.source.email, this.source contains the source input object being validated.

I just plugged it into a test and it is available as expected, hope it works for you.

See: https://github.com/tmpfs/async-validate#rule

Note that the state object is also available for passing data between rules so if you only wanted it available to the token validation you could put it in this.state and access it via this.state (potentially conditionally).

Let me know if this solves it for you. Ta.

tmpfs commented 8 years ago

Oops missed your point on source, double checking now...

tmpfs commented 8 years ago

Hmmm, it should not be removed from source - I've added a test case that verifies that the source contains the email field from a previous rule, see:

https://github.com/tmpfs/async-validate/commit/8e109fdef4a7ce04922109c6f5455089e3cf6199

tmpfs commented 8 years ago

If it's still not working let me see the output of console.log(this) in the token rule function.

jaysson commented 8 years ago

Seems to be working now.

I did npm update in the meanwhile.

tmpfs commented 8 years ago

Cool, thanks for letting me know. Closing as not an issue but re-open if you experience the same problem again.