How to pass the check empty string with enum in mongoose? - node.js

How I can ignore the error like validation failed: gender: "" is not a valid enum value for path gender when receive a empty value to save into database
My schema look like:
Person {
gender: {
type: String,
enum: ['men', 'women'],
required: false
}
}
In my code (NodeJS)
I have a check:
if (body.gender && !['men', 'women'].includes(body.gender.toLowercase())) {
throw Error("Gender invalid");
}
await savePerson(body);
If have to lowerCase value to check in case insensitive
I think in Javascript empty string is not same with null or undefined, so the error is not throw. I don't want to check !isNullOrUndefined(body.gender) as well. But in process save to mongo, error validation failed: gender: "" is not a valid enum value for path gender has been threw by mongoose

The first condition in your if is true when body.gender is not null or undefined or empty string "". So these values pass your validation and go to the .save() function
You can change to this, it will catch the invalid values above :
if (!['men', 'women'].includes(body.gender)) {
throw Error("Gender invalid");
}
console.log(!['men', 'women'].includes(undefined)); // true
console.log(!['men', 'women'].includes(null)); // true
console.log(!['men', 'women'].includes("")); // true
Edit: So, the condition is "the gender is string and is one of "men", "women" case insensitive". I suggest this validation:
if (typeof(body.gender) !== "string" || !['men', 'women'].includes(body.gender.toLowerCase())) {
throw Error("Gender invalid");
}
Below I run some test:
function isValidGender(gender) {
if (typeof(gender) !== "string" || !['men', 'women'].includes(gender.toLowerCase())) {
console.log("Error");
} else {
console.log("Valid");
}
}
isValidGender(undefined);
isValidGender(null);
isValidGender("");
isValidGender("Men");
isValidGender("wOmEn");
isValidGender("AA");

Related

Validate array of objects in Node

I have an array that looks something like this
settings: [
{ key: 'maxImageSize', value: '512' },
{ key: 'maxFileSize', value: '2048' },
{ key: 'searchResultsLimit', value: '10' },
]
I would like to validate the value of each key before saving them to a database.
Example: searchResultsLimit should be greater than 1 but never exceed 20.
I am using Objection.js and express-validator.
Thanks.
Here's a function that returns a boolean based on whether the array is valid or invalid.
function myValidate(settings) {
try {
settings.map((setting) => {
if (validator.toInt(setting.value) <= 1 || validator.toInt(setting.value) >= 20) {
console.log(setting.value);
throw new Error("Invalid");
}
});
} catch (e) {
console.log(e.message);
return false;
}
return true;
}
Turns out validator.js does not provide a validator to check if a number is in range. Check https://github.com/validatorjs/validator.js/issues/330 for details.
In case you want to just ignore the items that are invalid, you can use the filter method instead to get the items in the required range.

How to fix "type 'String' is not a subtype of type '(String?) => String?" error in flutter

I am learning flutter and getting so many errors with flutter...
I am trying to get a validation of text fields with the following methods:
validateName() {
String value = '';
if (value.isEmpty) return 'Username is Required.';
final RegExp nameExp = new RegExp(r'^[A-za-zğüşöçİĞÜŞÖÇ ]+$');
if (!nameExp.hasMatch(value))
return 'Please enter only alphabetical characters.';
return value;
}
However, I am getting the above mentioned error on validationFunction in the textformbuilder:
TextFormBuilder(
enabled: !viewModel.loading,
prefix: Feather.user,
hintText: "Username",
textInputAction: TextInputAction.next,
validateFunction: validateName(),
onSaved: (String val) {
viewModel.setName(val);
},
focusNode: viewModel.usernameFN,
nextFocusNode: viewModel.emailFN,
),
Thanks in advance!
validate function is different from your function...so change the function validate name
String validateName(String? value) {
if (value!.isEmpty) return 'Username is Required.';
final RegExp nameExp = new RegExp(r'^[A-za-zğüşöçİĞÜŞÖÇ ]+$');
if (!nameExp.hasMatch(value))
return 'Please enter only alphabetical characters.';
return value;
}
and on the textfield builder...put the validateFunction like this
TextFormBuilder(
validateFunction: validateName,
)

Mongoose js validation on sub object multiple fields

I am attempting to validate an entire object (multipel fields) within mongoose.
I have the following custom schema definition:
module.exports.ItemQuantityPair = (ItemModel, strictStacking)=>{
return {
type: {
itemID: { type:Number, required:true },
quantity: { type:Number, min:1, default:1 },
},
validate: {
validator: async value => { //stacking
if(!strictStacking || value.quantity===1) //if no strict stacking, or only quantity of 1 don't validate
return true;
let item = await ItemModel.findOne({itemID:value.itemID}); //otherwise get the item and check if its stackable
if(!item.stackable)
return false; //invalid, quantity > 1 and not stackable
else
return true; //valid, quantity > 1 and stackable
},
message: props=>`${props.value} this item was supplied with a quantity larger than 1, but the item was found to not be stackable. Ensure only stackable items have quantity > 1`
},
}
}
Then later in my schema I use this custom object like so:
const AccountSchema = new mongoose.Schema({
inventory: [ItemQuantityPair(ItemModel, true)] //inventory is a list of ItemQuantity pairs
});
When I try this, I'm presented with the error TypeError: Invalid schema configuration: 'undefined' is not a valid type within the array 'inventory' I assume this is because I can't assign an object tp the type field since these are the only built-in types: https://mongoosejs.com/docs/schematypes.html#what-is-a-schematype. Normally I would validate each field separately, but this specific validation requires both fields' values (quantity and itemID) to be determined as valid or not.
How can I cleanly accomplish validation on multiple fields?
Thanks

Mongoose Boolean false vs undefined?

In mongoose, what is the right way to check the field value is undefined, rather than false?
We have model, which has a Boolean property, but not be initially set. For this reason the possible values are actually: undefined | true | false. Here we need to make the distinction.
The operation is being done from with a NodeJS based application.
An example, as requested:
// Simply schema
const PreferencesSchema = new mongoose.Schema({
forUser: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }
allowActionX: {
type: Boolean,
default: undefined
}
});
const Preferences = mongoose.model<any>('Preferences', PreferencesSchema);
const preferences = Preferences.findOne({ user: user });
// if preference.allowActionX is not defined:
// use default behaviour
// else if preference.allowActionX is true
// do action X
// else
// don't do action X
If you want to return a document where a field exists AND is not null, use { a : {$ne: null}}
otherwise you can also check afterword with the === operator to determine if something is false vs undefined
The triple equals, ===, in JavaScript, tests for strict equality. This means both the type and the value we are comparing have to be the same.
if (myvar === false) {
//insert code
}
else if ( myvar === undefined){
//insert code
}
https://codeburst.io/javascript-double-equals-vs-triple-equals-61d4ce5a121a

How to write regex in a sequelize.js field validation.isIn.args

I had wrote two regex in isIn.args, i want the phone validator can check my input value is one of these, but failed.
var ValidateMe = sequelize.define('Foo', {
phone: {
type: Sequelize.STRING(20),
validate: {
isIn: {
args: [[
// moible number of china
/^(13|14|15|17|18)\d{9}$/i,
// telphone number of china
/^((\(\d{2,3}\))|(\d{3}\-)|(\d{3}))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$/i
]],
msg: "moible or telphone number format error!"
}
}
}
})
I want get the result:
var inputNumber = '15208282123'; // or '8008123'
( /^(13|14|15|17|18)\d{9}$/i.test(inputNumber)
|| /^((\(\d{2,3}\))|(\d{3}\-)|(\d{3}))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$/i.test(inputNumber)
) === true;
Run it in the browser console, result is true.
sequelize "isIn" validator doesn't provide regex support, it checks weather value is directly present in the list of args or not, instead "is" validator supports regex, but i don't think it will support more than one regex at a time, you need to either convert 2 reg ex into 1 or create custom validator which checks both the regex and return true if one of them is passed, something like below
var ValidateMe = sequelize.define('Foo', {
phone: {
type: Sequelize.STRING(20),
validate: {
validatePhone: function(value) {
if(!/^(13|14|15|17|18)\d{9}$/i.test(value) && !/^((\(\d{2,3}\))|(\d{3}\-)|(\d{3}))?(\(0\d{2,3}\)|0\d{2,3}-)?[1-9]\d{6,7}(\-\d{1,4})?$/i.test(value)) {
throw new Error('phone format error!')
}
}
}
}
})

Resources