"email" validation rule crash sails server - Mongo with Sails.js - sails.js

while the email validation rule fails on module of the sails.js, the server is crashing.
Here the snippet of my module:
// The user's email address
email: {
type: 'string',
email: true,
required: true,
unique: true
},
And the error as below :
err: Error (E_VALIDATION) :: 1 attribute is invalid
at WLValidationError.WLError (C:\Users\yuri\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\lib\waterline\error\WLError.js:26:15)
at new WLValidationError (C:\Users\yuri\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\lib\waterline\error\WLValidationError.js:20:28)
at C:\Users\yuri\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\lib\waterline\query\validate.js:45:43
at allValidationsChecked (C:\Users\yuri\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\lib\waterline\core\validations.js:203:5)
at done (C:\Users\yuri\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:135:19)
at C:\Users\yuri\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:32:16
at C:\Users\yuri\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\lib\waterline\core\validations.js:184:23
at done (C:\Users\yuri\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:135:19)
at C:\Users\yuri\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:32:16
at C:\Users\yuri\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\lib\waterline\core\validations.js:157:64
at C:\Users\yuri\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:125:13
at Array.forEach (native)
at _each (C:\Users\yuri\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:46:24)
at Object.async.each (C:\Users\yuri\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:124:9)
at validate (C:\Users\yuri\AppData\Roaming\npm\node_modules\sails\node_modules\waterline\lib\waterline\core\validations.js:156:11)
at C:\Users\yuri\AppData\Roaming\npm\node_modules\sails\node_modules\async\lib\async.js:125:13
Invalid attributes sent to User:
• email
• undefined should be a email (instead of "admin#gmailasd", which is a string)

The correct way to declare an email field is like this :
email: {
type: 'email',
required: true,//Email field will be required for insert or update
unique: true //Insert or update will crash if you try to insert duplicate email
},
You can see all different attribut types here http://sailsjs.org/documentation/concepts/models-and-orm/attributes
If you want to catch insert/update errors you can do this on your controller :
MyModel.create({email:email}).exec(function(err, model)
{
if(err)
{
//Check if it's a validation error or a crash
if(err.code == "E_VALIDATION")
sails.log.debug("valid fail, check form");
else
sails.log.debug("crash");
}
else
{
//do what you want to do with the data
}
});

Her the answer.
Thanks to jaumard, i found the problem.
I used undefined field in error, without checking if exists before
err.originalError.code but it was undefined.
So the correct way is :
err.originalError && err.originalError.code && err.originalError.code === 11000
and not
err.originalError.code === 11000.

Previous versions of Sails recommended that email validation was achieved like this
email: {
type: 'string',
email: true,
required: true
},
The current version should be like this
email: {
type: 'email',
required: true
},

Related

Mongoose 6 - How to get only the custom validation error message without the error?

const userSchema = new mongoose.Schema({
email: {
type: String,
unique: true,
required: [true, 'Email address is required'],
minlength: [4, 'Must be at least 4 characters long']
}
});
When I log the error I get:
User validation failed: email: Must be at least 4 characters long
How can I get only my custom message:
Must be at least 4 characters long
The only thing I do as of now is
const messageString = message.split(':');
messageString[3]
But is there a better way? I saw some solutions for this but its all for mongoose version 5 or less and it doesnt apply to version 6 as the error object has different properties.
On a side note (maybe this should be a seperate question) but as the error object is different now, how can I check if its a mongoose validation error? The err object doesnt come with it anymore.
Error: User validation failed: email: Must be at least 4 characters long
at ValidationError.inspect (/Users/... {
errors: {
email: ValidatorError: Must be at least 4 characters long
at validate (/Users/user/....
at processTicksAndRejections (node:internal/process/task_queues:78:11) {
properties: [Object],
kind: 'minlength',
path: 'email',
value: 'hgg',
reason: undefined,
[Symbol(mongoose:validatorError)]: true
}
},
_message: 'User validation failed'
}
Also, I dont want to have to access the modal property 'email' when accessing any other property as in my errorhandler, I want to keep it reusable for other errors too

Input definition optional keys

I generated an action with sails generate action task/update-task. I now am trying to create an input parameter that should be an object with optional keys:
inputs: {
fields: {
type: {
body: 'string?',
rruleSetStr: 'string?',
},
required: true,
description: 'All keys are not required, but at least one is'
},
However I keep getting error:
The action `task/update-task` could not be registered. It looks like a machine definition (actions2), but it could not be used to build an action.
Details: ImplementationError: Sorry, could not interpret "task/update-task.js" because its underlying implementation has a problem:
------------------------------------------------------
• Invalid input definition ("fields"). Unrecognized `type`. (Must be 'string', 'number', 'boolean', 'json' or 'ref'. Or set it to a type schema like `[{id:'number', name: {givenName: 'Lisa'}}]`.)
------------------------------------------------------
If you are the maintainer of "task/update-task.js", then you can change its implementation to solve the problem above. Otherwise, please file a bug report with the maintainer, or fork your own copy and fix that.
[?] See https://sailsjs.com/support for help.
at machineAsAction (C:\Users\Mercurius\Documents\GitHub\Homie-Web\node_modules\machine-as-action\lib\machine-as-action.js:271:28)
at helpRegisterAction (C:\Users\Mercurius\Documents\GitHub\Homie-Web\node_modules\sails\lib\app\private\controller\help-register-action.js:63:27)
at C:\Users\Mercurius\Documents\GitHub\Homie-Web\node_modules\sails\lib\app\private\controller\load-action-modules.js:146:13
Does anyone know where the documentation is on how to make optional keys in this? I tried here - http://node-machine.org/spec/machine#inputs - but no luck.
Type must be 'string', 'number', 'boolean', 'json' or 'ref' like error say.
So u need set type to 'ref' (object or array), and u can use custom function for validate.
inputs: {
fields: {
type: 'ref',
custom: function (data) {
// some logic
// example
if (typeof data.body !== "string") {
return false;
// or u can use trow Error('Body is not a string')
}
return true;
},
required: true,
description: 'All keys are not required, but at least one is'
}
Now input is type object and in custom function return false or trow Error('Some problem') break validation.
If u use schema type, just remove ? from your example:
inputs: {
fields: {
type: {
body: 'string',
rruleSetStr: 'string'
},
required: true,
description: 'All keys are not required, but at least one is'
}
This is Runtime (recursive) type-checking for JavaScript., please check documentation for writing rules.

Getting "Invalid exit definition" on Compilation of Sails Helper (Sails v1.0)

I'm getting the error
Invalid exit definition ("success"). Must be a dictionary-- i.e. plain JavaScript object like `{}`.
Invalid exit definition ("error"). Must be a dictionary-- i.e. plain JavaScript object like `{}`.
when doing sails lift. The error is on getRole.js
module.exports = {
friendlyName: 'Get Role',
description: '',
inputs: {
user_id: {
friendlyName: 'User Id',
description: 'The ID of the user to check role',
type: 'string',
required: true
}
},
exits: {
success: function (role){
return role;
},
error: function (message) {
return message;
}
},
fn: function (inputs, exits) {
User.findOne({ id: inputs.user_id } , function (err, user) {
if (err) return exits.err(err);
return exits.success(user.role);
});
}
};
This is a new error, and looking at my git, nothing has changed in my code since it successfully compiled. I understand the Sails version (v1.0) I'm using in beta, so I'm taking that into account.
Exits cannot be defined as functions. There is a special syntax (Machine Spec) to define exits. In your example this should work:
exits: {
error: {
description: 'Unexpected error occurred.',
},
success: {
description: 'Role was succesffuly fetched'
}
},
You can read more info about helper exits here: https://next.sailsjs.com/documentation/concepts/helpers
May changes occur on the last release 1.0.0-38. I've not checked underneath yet, but the way to execute helpers changed: on .exec() I get errors. Now, use .switch();

Sails.JS association validation

I'm using several one to many associations in Sails.JS that look like the following:
User
email: {
type: 'string',
required: true,
unique: true
},
projects: {
collection: 'project',
via: 'user'
}
Project
name: {
type: 'string',
required: true,
minLength: 3,
maxLength: 50
},
user: {
model: 'user',
required: true
},
sites: {
collection: 'site',
via: 'project'
}
Site
project: {
model: 'project',
required: true
},
name: {
type: 'string',
required: true
}
Now when I fire off a POST request to /project it creates the project fine, and specifying the param 'user' (taken from the session) associates the project with that particular user.
The same goes for when I create a new site. However, I appear to be able to specify any number for the param 'project', even if that particular project ID doesn't exist. Really it should fail the validation if the project doesn't exist and not create the site. I thought it'd look up the association with project and check that the project ID specified is valid?
Also, I only want to be able to create a site that is associated with a project that belongs to the current user. How would I go about doing this?
Thanks in advance.
I'm not sure if it's a bug or intended behavior with your non-existent project ID association, but one work-around is to have a beforeCreate hook in your models to verify that the project ID exists:
// In your Site model
beforeCreate: function(values, next) {
...
var projectID = values['project'];
Project.findOne(projectID, function (err, project) {
if (err || !project) return next("some error message");
return next();
});
}
You can also do a check in the beforeCreate hook for your second question:
// In your Site model
beforeCreate: function(values, next) {
...
var projectID = values['project'];
Project.findOne(projectID).populate('user').exec(function (err, project) {
if (err || !project) return next("some error message");
if (project.user.id != values['userID']) return next("some other error message");
return next();
});
}
Note that you'll have to pass 'userID' as a param into the params for creating a Site instance.

Cannot save a document in Mongoose - Validator required failed for path error

Following is my schema:
var userSchema = new Schema({
username: {
type: String,
required: true
},
password: {
type: String,
required: false
}
});
Now, when I attempt to save a document of the above schema, I get the following error:
{ message: 'Validation failed',
name: 'ValidationError',
errors:
{ username:
{ message: 'Validator "required" failed for path username',
name: 'ValidatorError',
path: 'username',
type: 'required' } } }
The above is the error object returned by mongoose upon save. I searched for this error but could not understand what is wrong. The document that I am trying to save is as follows:
{
username: "foo"
password: "bar"
}
Any idea what this means? I searched the mongoose docs too but could not find anything under the validation section.
First, you are missing a comma (,) after foo.
Now, is { username: "foo", password: "bar" } JSON sent via http, our an actual object in your server-side code ?
If it is, try to console.log(youVariable.username) and see if it shows undefined or the value foo. If you see undefined, then your object is not parsed properly.
You can make sure that whom ever is sending the POST request is sending a "application/json" in the header, you could be receiving something else, thus your JSON isn't parsed to a valid javascript object.