I get this message from Mongoose validation:
'Validator failed for path phone with value ``'
That shouldn't happen since phone is not required.
Here's my model schema:
var user = new Schema(
{
_id : { type: String, required: true },
name : { type: String, required: true},
phone : { type: String, required: false, validate: /^\d{10}$/ },
password : { type: String },
added : { type: Date, default: Date.now },
},
{collection : 'users'}
);
It seems that mongoose's validation fails when i use required: false and set validate property up.
If I change it to:
phone : { type: String, required: false},
Everything goes right, why is that?
What am I doing wrong?
You can simply check if the value entered exists (not null or undefined). If it exists, then test the regex:
var user = new Schema(
{
_id : { type: String, required: true },
name : { type: String, required: true},
phone : { type: String,/*not required by default**/
validate: {
validator: function(v) {
var re = /^\d{10}$/;
return (!v || !v.trim().length) || re.test(v)
},
message: 'Provided phone number is invalid.'
}
},
password : { type: String },
added : { type: Date, default: Date.now },
},
{collection : 'users'}
);
I think your regex is failing validation on empty string which should in this case be valid since this field is not required. Why don't you try this regex:
/^$|^\d{10}$/
This will match an empty string or 10 digits.
You may try with a custom validator as they are only triggered when there is a value on a given key because the key selection for custom validation is done via path() :
var user = new Schema({
// ...
phone : { type: String }, // using default - required:false
// ...
});
// Custom validation
user.path('phone').validate(function (value) {
// Your validation code here, should return bool
}, 'Some error message');
Have a look at this question: Why Mongoose doesn't validate empty document?
This will also effectively prevent the document to be persisted to the DB if validation fails, unless you handle the error accordingly.
BonusTip: Try to approach custom validations in a simplistic way, for example try to avoid loops when possible and avoid using libraries like lodash or underscore for in my experience I've seen that these may have a significant performance cost when working with lots of transactions.
use this function:
const valid= (id) =>{
return id.match(/^[0-9a-fA-F]{24}$/) ? true : false;
}
Related
I'm following the official [documentation] (https://legacy.adonisjs.com/docs/4.0/validator) && indicative, but I couldn't find anything to help me.
I want to validate if the given param exists on database.
So I tried:
app/Validators/myValidator
const { rule } = use('Validator')
get rules () {
return {
userId: 'required|integer|exists:MyDatabase.users,userId', <-- this is what isn't working
date: [
rule('date'),
rule('dateFormat', 'YYYY-MM-DD')
]
}
}
// Getting the data to be validated
get data () {
const params = this.ctx.params
const { userId, date } = params
return Object.assign({}, { userId }, { date })
}
It gives me the following error:
{
"error": {
"message": "select * from `MyDatabase`.`users`.`userId` where `undefined` = '2' limit 1 - ER_PARSE_ERROR: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '.`userId` where `undefined` = '2' limit 1' at line 1",
"name": "ErrorValidator",
"status": 40
}
}
How should I properly indicate that I want to compare MyDatabase.users.userid to the given parameter?
After a few hard try/error I stumbled upon the solution.
Just need to follow what is inside hooks.js and pass the values separated by comma, like so:
get rules () {
return {
userId: 'required|integer|exists:MyDatabase,MyTable,columntoCompare',
}
}
I use loopback4. How do I make an expression to match datetime with time zone.I am interested by the hour parameter only: "finalhour"
example: 2019-12-20T10:22:50.143Z ==> 2019-12-20Tfinalhour:22:50.143Z
I tried with this: const pattern=await '^'+"T"+finalhour+'^'
but loopback usually read it as ^T10^
I'm resort to you after a long search in the forums.I will be thankful if you help me
From what i understand, you want to build a regex that match 2019-12-20TsomeNumber:22:50.143Z.
You could use this default ISO datetime regex
(\d{4})-(\d{2})-(\d{2})T(\d{2})\:(\d{2})\:(\d{2})\.\d{3,4}Z
And modify it to take your finalhour variable in it.
let finalHour = 10;
// when building regex from constructor, we need to espace the backslash ( \ )
// i did not know that.
let regex = new RegExp('(\\d{4})-(\\d{2})-(\\d{2})T' + finalHour + '\\:(\\d{2})\\:(\\d{2})\\.\\d{3,4}\\Z');
let test = '2019-12-20T10:22:50.143Z';
console.log(regex.test(test));
Also, you don't need an await keyword here because your are building a string, not waiting for a promise.
I need to return the number of order per hour. so i try this solution but it return false comparison, for example if i have one order at hour:10 it return 6
#get('/orders/count-perHour/{date}', {
responses: {
'200': {
description: 'Order model count',
content: { 'application/json': { schema: CountSchema } },
},
},
})
async countPerHour(
#param.path.string('date') date: string): Promise<any> {
let dateStart = new Date(date);
dateStart.setSeconds(0);
dateStart.setMinutes(0);
let dateEnd = new Date(date);
dateEnd.setSeconds(59);
dateEnd.setMinutes(59);
return await this.orderRepository.count(
{
createdAt: {
lte: dateEnd
,
gte: dateStart
}
}
);
}
I am trying to create user in AWS Cognito with adminCreateUser API with the below code
var cognitoidentityserviceprovider = new AWS.CognitoIdentityServiceProvider();
var params = {
UserPoolId: "us-east-1_302HlhnaC", /* required */
Username : "test#yopmail.com",
ForceAliasCreation: true,
TemporaryPassword: 'test#yopmail.com',
UserAttributes: [
{
Name: 'given_name', /* required */
Value: 'test'
},
{
Name: 'family_name', /* required */
Value: 'kumar'
},
{
Name: 'name', /* required */
Value: 'test'
},
{
Name: 'custom:dob', /* required */
Value: '1990-07-25'
},
{
Name: 'email', /* required */
Value: 'test#yopmail.com',
},
{
Name: 'email_verified', /* required */
Value: 'true',
}
/* more items */
],
};
cognitoidentityserviceprovider.adminCreateUser(params, function(error, data) {
console.log(error,data);
res.send("test");
});
It always throwing following exception :
InvalidParameterException: Attributes did not conform to the schema: custom:dob: Attribute does not exist in the schema.
Is am doing anything wrong,if yes please let me know the solution.
Thanks
You must add the custom attribute ahead of time. You can create custom attributes by visiting the User Pool and clicking the Attributes link.
Just adding my case here.
In my CloudFormation, I have:
Schema:
- AttributeDataType: String
Name: role
DeveloperOnlyAttribute: true
Mutable: true
Required: false
In the console, it translated into:
In the application adminCreateUser call, I had to provide it as dev:custom:role:
cognitoService.adminCreateUser({
UserPoolId: config.cognitoUserPoolId,
Username: email,
UserAttributes: [{
Name: 'dev:custom:role',
Value: role,
}]
}).promise()
Figured it out by trying. Wish I knew where the docs for this are.
Darcy's answer is correct. But I wanted to elaborate as that answer was focused on the AWS web console.
Also the other answer viz., prefixing "dev:" is probably an undocumented workaround (hence no documentation) and might stop working without warning.
First, the custom attributes has to be created when the Userpool is Created.
CreateUserPoolRequest request = new CreateUserPoolRequest
{
...
Schema = new List<SchemaAttributeType>
{
new SchemaAttributeType
{
Name = "email",
AttributeDataType = AttributeDataType.String,
Required = true,
Mutable = false
},
new SchemaAttributeType //custom attribute
{
Name = "blah",
AttributeDataType = AttributeDataType.String,
Mutable = false
},
...
};
And then when the user is created, it can be set.
var request = new AdminCreateUserRequest
{
...
UserAttributes = new List<AttributeType>
{
new AttributeType
{
Name = "email",
Value = "xyz#xyz.com"
},
new AttributeType //custom attribute
{
Name = $"custom:blah",
Value = "value for blah"
}
}
};
Now, just prefixing with "custom:" works.
Also note AWS continues with its tradition of having inconsistent api's by not having to prefix when creating the user pool and having the prefix when creating the user.
I am trying to include the following password rules via Validators.pattern in my angular 4 project using regex.
My external stakeholder would like a users password to be valid if it included a lowercase letter, uppercase letter and a Number OR Special character.
Below is the regex I am using, Pattern 1 works fine as does pattern2, however when I try to do the OR of them in pattern3 it does not work.
//passwordPattern1='^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9]).{8,}$';// must include numbers
//passwordPattern2='^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[#?!#$%^&*-]).{8,}$';//must include special characters
passwordPattern3='^(((?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]))|((?=.*[a-z])(?=.*[A-Z])(?=.*?[#?!#$%^&*-.])))';//Numbers or Special characters
Below is how I add it to my formGroup. see line 3
this.form = this.fb.group({
username: [null, Validators.compose([Validators.required, Validators.minLength(4), Validators.maxLength(20)])],
password: [null, Validators.compose([Validators.required,Validators.minLength(8), Validators.maxLength(128), Validators.pattern(this.passwordPattern3)])],
confirmPassword: [null, Validators.compose([Validators.required, Validators.minLength(8), Validators.maxLength(128)])]
}, {validator: matchingPasswords('password', 'confirmPassword')});
Does anyone know why the third password pattern does not seem to work in angular, and what I could do to make it work?
I tested the REGEX at http://rubular.com/ in passwordPattern3 and it works as desired. Anything I may be missing in Angulars validators.pattern()?
Regarding the security of these requirements- I am aware these rules are not the best approach for the security of a user. For this effort, I, unfortunately, do not have the influence to change the requirements from the external stakeholder. But I am awarewhy such rules may be ineffective
I know this answer doesn't use RegEx, but you could do this with custom validator functions:
function hasUpperCaseChar(val: string): boolean {
return val.split('')
.reduce((current, next) => current || next === next.toUpperCase(), false);
}
function hasLowerCaseChar(val: string): boolean {
return val.split('')
.reduce((current, next) => current || next === next.toLowerCase(), false);
}
function moreThanOneInteger(val: string): boolean {
return val.split('')
.reduce((current, next) => current || !isNaN(parseInt(next)), false);
}
function moreThanOneSpecialCharacter(val: string): boolean {
return val.split('')
.reduce((current, next) => current || '#?!#$%^&*-'.split('').includes(next), false);
}
// In another function file (e.g. MY_CUSTOM_VALIDATORS)
export const MY_VALIDATORS: any = {
password: {
gtOneInteger: (control: AbstractControl): boolean {
return hasUpperCaseChar(control.value) && hasLowerCaseChar(control.value) && moreThanOneInteger(control.value)
? null
: { gtOneInteger: false };
},
gtOneSpecialChar: (control: AbstractControl): boolean {
return hasUpperCaseChar(control.value) && hasLowerCaseChar(control.value) && moreThanOneSpecialCharacter(control.value)
? null
: { gtOneSpecialChar: false };
},
gtOneIntegerOrSpecialChar: (control: AbstractControl): boolean {
return hasUpperCaseChar(control.value) && hasLowerCaseChar(control.value) && moreThanOneInteger(control.value) && moreThanOneSpecialCharacter(control.value)
? null
: { gtOneIntegerOrSpecialChar: false };
}
}
};
// Updated your current functionality:
this.form = this.fb.group(
{
// The Validators.compose() function is not necessary with Angular 4+.
username: [null, [Validators.required, Validators.minLength(4), Validators.maxLength(20)]],
// Your previous validation:
// password: [null, [Validators.required,Validators.minLength(8), Validators.maxLength(128), Validators.pattern(this.passwordPattern3)]],
// New validation (you can use any of the ones defined above):
password: [null, [Validators.required, Validators.minLength(8), Validators.maxLength(128), MY_VALIDATORS.gtOneIntegerOrSpecialChar]]
confirmPassword: [null, [Validators.required, Validators.minLength(8), Validators.maxLength(128)]]
},
{
validator: matchingPasswords('password', 'confirmPassword')
}
);
I have been trying since to build a custom validator using Valdr AngularJs plugin with no success.
What I want to archive is an input text that should receive date and time format like : dd/MM/yyyy hh:mm (12/04/2015 12:32:10)
Based on Valdr documentation, this is what I have done so far :
myApp.factory('customValidator', function () {
return {
name: 'customValidator', // this is the validator name that can be referenced from the constraints JSON
validate: function (value, arguments) {
// value: the value to validate
// arguments: the validator arguments
return value === arguments.onlyValidValue;
}
};
});
myApp.config(function(valdrProvider)
{
valdrProvider.addValidator('customValidator');
valdrProvider.addConstraints(
{
'Person':
{
'date_send':
{
'customValidator':
{
'onlyValidValue':'^(([0-2]\d|[3][0-1])\/([0]\d|[1][0-2])\/[2][0]\d{2})$|^(([0-2]\d|[3][0-1])\/([0]\d|[1][0-2])\/[2][0]\d{2}\s([0-1]\d|[2][0-3])\:[0-5]\d\:[0-5]\d)$',
'message': 'Please date and time format has to be : 12/04/2015 12:32:10'
}
}
}
});
});
Then in my form, I have the following :
<input class="input" name="date_send" id="date_send" type="text" ng-model="date_send" />
But it doesn't work.
I will appreciate any help.
Thank you !
If you only need a regex validator, I'd recommend to use the one provided by valdr instead of writing a custom validator:
valdrProvider.addConstraints({
'Person': {
'date_send': {
'pattern': {
'value': '^(([0-2]\d|[3][0-1])\/([0]\d|[1][0-2])\/[2][0]\d{2})$|^(([0-2]\d|[3][0-1])\/([0]\d|[1][0-2])\/[2][0]\d{2}\s([0-1]\d|[2][0-3])\:[0-5]\d\:[0-5]\d)$',
'message': 'Please date and time format has to be : 12/04/2015 12:32:10'
}
}
}
});
If you want a custom validator, you have to implement the validation logic in the validator. You just copied the sample validator from the docs, which only compares the users input value with the 'onlyValidValue' configured in the constraints. What you want to do is more like:
valdrProvider.addConstraints({
'Person': {
'date_send': {
'customDateValidator': {
'message': 'Please date and time format has to be : 12/04/2015 12:32:10'
}
}
}
});
Custom validator:
myApp.factory('customDateValidator', function () {
return {
name: 'customDateValidator',
validate: function (value, arguments) {
var dateCheck = /^(([0-2]\d|[3][0-1])\/([0]\d|[1][0-2])\/[2][0]\d{2})$|^(([0-2]\d|[3][0-1])\/([0]\d|[1][0-2])\/[2][0]\d{2}\s([0-1]\d|[2][0-3])\:[0-5]\d\:[0-5]\d)$/
return dateCheck.test(value);
}
};
});
I can't be 100% sure because you didn't provide enough code but I guess your input field declaration should be
ng-model="person.date_send"
rather than
ng-model="date_send"
For reference please have a look at the custom validator demo. It's always helpful if you can provide a plunker with a complete sample.