I am designing a user registration screen using FluentValidation.
I want to establish a control mechanism that will provide information on all steps as follows.
The code I tried;
RuleFor(p => p.Password).Matches(#"[A-Z]+").WithMessage("Your password must contain at least one uppercase letter.");
RuleFor(p => p.Password).Matches(#"[a-z]+").WithMessage("Your password must contain at least one lowercase letter.");
RuleFor(p => p.Password).Matches(#"[0-9]+").WithMessage("Your password must contain at least one number.");
RuleFor(x => x.Password).Matches(#"[\!\?\*\.]*$").WithMessage("Your password must contain at least one (!? *.).");
But I could not reach the result I wanted. I also looked at the FluentValidation documentation but could not see any useful example.
I would be glad if you help.
Thank you.
Please refer to the following example:
public class Login
{
public string Password { get; set; }
}
public class PassWordValidator : AbstractValidator<Login>
{
public PassWordValidator()
{
RuleFor(p => p.Password).NotEmpty().WithMessage("Your password cannot be empty")
.MinimumLength(8).WithMessage("Your password length must be at least 8.")
.MaximumLength(16).WithMessage("Your password length must not exceed 16.")
.Matches(#"[A-Z]+").WithMessage("Your password must contain at least one uppercase letter.")
.Matches(#"[a-z]+").WithMessage("Your password must contain at least one lowercase letter.")
.Matches(#"[0-9]+").WithMessage("Your password must contain at least one number.")
.Matches(#"[\!\?\*\.]+").WithMessage("Your password must contain at least one (!? *.).");
}
}
Action:
[HttpPost]
public IActionResult TestPassword(Login model)
{
PassWordValidator _validator = new PassWordValidator();
var validResult = _validator.Validate(model);
if (!validResult.IsValid)
{
return BadRequest(validResult.Errors);
}
return Ok();
}
Here is the test result by postman:
Related
I'm trying to use the "RegularExpression" DataAnnotation validaiton in my model. My problem is even for the valid input I provide for the field containing the validation, the regex doesn't match and it fails.
I try to test the same valid input with the regex in a stand-alone console app and I find it gets through.
My point is, when regex is being used in dataannotation as validation, it considers all input as bad input. What am I missing here?
My regex is for checking comma-seperated email IDs. Here is my model:
public partial class BuildModel
{
public Int64 ConfigID { get; set; }
[Required(ErrorMessage = "Please select a stream!")]
public String Name{ get; set; }
[RegularExpression(#"^(([a-zA-Z0-9_\-\.]+)#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)(\s*(;|,)\s*|\s*$))", ErrorMessage = "Please enter valid email IDs separated by commas")]
public string EmailIDs { get; set; }
public bool IsActive { get; set; }
}
Note: The "Required" data-annotation validation works just fine. It is just the Regex one, that won't work!
As far as i understand you just have problem within your Regex.
To validate emails separated by comma you can use this regex:
^( *[\w+-.%]+#[\w-.]+\.[A-Za-z]{2,4}( *, *)? *)+$
Check in in here.
You must the jquery.validate.min.js and jquery.validate.unobtrusive.min.js in your page without these libraries required annotation would not works.
I'm creating tests, and every time I need to update a simple object, I create tests that check if all properties that I will pass through the method are changed.
For instance:
public class User {
public string name { get; private set }
public string email { get; private set }
public string password { get; private set }
public void UpdateData(string name, string email, string password){
//update fields
}
}
Test class:
[TestMethod]
public void Should_Update_Data(){
var arrange = {
name: "NewName",
Email: "NewEmail#Something.com",
Password: "123456"
}
var user = new User();
user.UpdateData(arrange.name, arrange.Email, arrange.Password);
//Assert user.name equals arrange.name
//Assert user.email equals arrange.email
//Assert user.password equals arrange.password
}
But I'm confused if it's a good practice to do so many asserts, and it's very boring to check all properties that I'm updating were really updated...
I don't think it's necessarily bad practice to do many asserts but there are definitely benefits to keeping tests to perform a single assert:
tests stay more focused
easier to understand what is being tested
assertions won't mask other assertions, ie if user.name assertion fails then user.email will never get executed, which results in longer feedback cycles
What sorts of regressions are you trying to prevent from happening with your tests? Is it effective in detecting those regressions from happening? Does the compiler protect you in the same way?
The contract for updateData is to perform an update on those elements. Therefore, you need to test it. However, you need not explicitly test it. If another part of your test covers the updateData portion, you can rely on that coverage as an implict test.
I suppose your actual method does something more than just set some properties. If not, I would not test these methods as it's too trivial for testing.
In case it is more complicated you will need some unit tests. As for your issue with the various asserts in a single method, I tend to set up my tests a bit differently so that the asserts are separated.
I'd set up and execute the code in the initialize method and then arrange the asserts in separate methods:
[TestClass]
public class UpdatingData
{
User user;
dyanmic arrange = {
Name: "NewName",
Email: "NewEmail#Something.com",
Password: "123456"
};
[TestInitialize]
public void Because(){
user = new User();
user.UpdateData(arrange.Name, arrange.Email, arrange.Password);
//Assert user.name equals arrange.name
//Assert user.email equals arrange.email
//Assert user.password equals arrange.password
}
[TestMethod]
public void UpdatesTheName() => Assert.Equals(user.Name, arrange.Name);
[TestMethod]
public void UpdatesTheEmail() => Assert.Equals(user.Email, arrange.Email);
[TestMethod]
public void UpdatesThePassword() => Assert.Equals(user.Password, arrange.Password);
}
We have a simple operator object, which uses spring security to encode the password thusly:
class Operator
transient springSecurityService
def siteService
String username
Site site
String password
def beforeInsert() {
encodePassword()
}
def beforeUpdate() {
if (isDirty('password')) {
encodePassword()
}
}
protected void encodePassword() {
password = springSecurityService?.passwordEncoder ? springSecurityService.encodePassword(password) : password
}
Now we want to validate that the password matches a regexp which is defined at runtime. Operators can be created via the UI (i.e. standard CRUD forms). We have a different regexp for each site. The fact that the password gets overwritten with an ecoded one, and we should not test that, makes it more challenging.
Attempt 1: do the validation in the encodePassword():
def beforeInsert() {
protected void encodePassword() {
String regexp = siteService.getInheritedValue(site, "operatorPasswordRegexp")
if (!password.matches(regexp) {
thrown new RuntimeException "invalid password format"
}
password = springSecurityService?.passwordEncoder ? springSecurityService.encodePassword(password) : password
}
}
This partially works, in that it stops passwords which don't match a regexp found at runtime being created. The problem is it throws an exception, which generates a 500 error page, when we want the operator edit form to highlight the password field with a nice friendly validation message.
Attempt two, using a custom validator
static constraints = {
password password: true, blank:false, validator: { val, obj ->
if (obj.isDirty(val)) {
return true
}
String regexp = obj.siteService.getInheritedValue(obj.operates, "operatorPasswordRegexp")
if (regexp != null && regexp != "") {
return val.matches(regexp)
}
return true
}
This appears to work, but the save always fails silently. It took me some time to realise why - when you do this:
operator.password="valid1"
opertor.save(failonError:true)
No errors are thrown. Even if you remove failonError, and check the return value,its always null (no errors). BUT IT DOES NOT SAVE THE OPERATOR.
The problem is that the beforeInsert is updating the password to an encoded version which does not pass the validator of course (and isnt supposed to), the validator says no at this point, and the save silently fails. I.e. the validiator is being called twice for a single save.
The question is, how to I get the beforeInsert() code to NOT call the validator, or the validator to ignore being called from beforeInsert?
You can achieve your task using both approaches.
1: Do the validation in the encodePassword(): Instead of throwing the exception, add an error to instance. I think your encodePassword() function is in your same domain, so get errors object associated to it using this.errors. ex:
this.errors.rejectValue("password", "user.password.pattern.error")
There are different rejectValue methods, this one accepts the field name and the message code defined in your message.properties file.
2: Custom Validator:
isDirty() is not a static method, call it using the obj provided in the custom validator. isDirty() accepts the property name to be checked for dirtiness not its value.
obj.isDirty(PropertyName)
constraints is a static block, it would not be able to directly access your service. You need to inject your service using static context.
static SiteService siteService;
I would recommend to do it using custom validator.
I was attempted to apply multiple #Pattern annotations to a single field:
#Pattern(regexp = "(?=.*[0-9])", message = "Password must contain one digit.")
#Pattern(regexp = "(?=.*[a-z])", message = "Password must contain one lowercase letter.")
#Pattern(regexp = "(?=.*[A-Z])", message = "Password must contain one uppercase letter.")
#Pattern(regexp = "(?=\S+$)", message = "Password must contain no whitespace.")
private String password;
However, I cannot do this. I want individual messages per violated regex constraint on the password field. Is this possible?
My alternative is to use JSF 2.0 f:validatorRegex tags.
You can use the inner #List annotation of #Pattern:
#Pattern.List({
#Pattern(regexp = "(?=.*[0-9])", message = "Password must contain one digit."),
#Pattern(regexp = "(?=.*[a-z])", message = "Password must contain one lowercase letter."),
#Pattern(regexp = "(?=.*[A-Z])", message = "Password must contain one uppercase letter."),
#Pattern(regexp = "(?=\\S+$)", message = "Password must contain no whitespace.")
})
private String password;
Gunnar's solution won't work for me... '.+' in his regexp seem to be missing.
However, i'm using Michal's patternList and it works like a charm for me. (Play 2.3.x / Ebean-ORM)
#Pattern.List({
#Pattern(regexp = "(?=.*[0-9]).+", message = "Password must contain one digit."),
#Pattern(regexp = "(?=.*[a-z]).+", message = "Password must contain one lowercase letter."),
#Pattern(regexp = "(?=.*[A-Z]).+", message = "Password must contain one upper letter."),
#Pattern(regexp = "(?=.*[!##$%^&*+=?-_()/\"\\.,<>~`;:]).+", message ="Password must contain one special character."),
#Pattern(regexp = "(?=\\S+$).+", message = "Password must contain no whitespace.")
})
#Constraints.Required()
public String password1;
You might want to look into constraint composition. You would build one annotation per password constraint composed from the #Pattern annotation, and then finally build one composed annotation using the previously defined four. This would require no extra java code.
http://docs.jboss.org/hibernate/validator/5.0/reference/en-US/html_single/#validator-customconstraints-compound
Otherwise, build (with accompanying java code) a custom annotation called #PasswordValidator.
I tend to like composed validators, as it makes the purpose of the validation annotations clear on their purpose, instead of having many disjoint annotations.
I modified Gunnar answer and write composite constraint and this now seems to work correctly on 4 unit tests:
#NotNull
#Size(min=6, max=45)
#Pattern.List({
#Pattern(regexp = "(?=.*[0-9]).+", message = "Password must contain one digit."),
#Pattern(regexp = "(?=.*[a-z]).+", message = "Password must contain one lowercase letter."),
#Pattern(regexp = "(?=.*[A-Z]).+", message = "Password must contain one uppercase letter."),
#Pattern(regexp = "(?=.*[!##$%^&*+=?-_()/\"\\.,<>~`;:]).+", message ="Password must contain one special character."),
#Pattern(regexp = "(?=\\S+$).+", message = "Password must contain no whitespace.")
})
#Constraint(validatedBy = {}) // constraints composition
#Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})
#Retention(RetentionPolicy.RUNTIME)
public #interface StrongPassword {
String message() default "Password doesn't match bean validation constraints.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
We manage several ASP.NET MVC client web sites, which all use a data annotation like the following to validate customer email addresses (I haven't included the regex here, for readability):
[Required(ErrorMessage="Email is required")]
[RegularExpression(#"MYREGEX", ErrorMessage = "Email address is not valid")]
public string Email { get; set; }
What I would like to do is to centralise this regular expression, so that if we make a change to it, all of the sites immediately pick it up and we don't have to manually change it in each one.
The problem is that the regex argument of the data annotation must be a constant, so I cannot assign a value I've retrieved from a config file or database at runtime (which was my first thought).
Can anyone help me with a clever solution to this—or failing that, an alternative approach which will work to achieve the same goal? Or does this just require us to write a specialist custom validation attribute which will accept non-constant values?
The easiest way is to write a custom ValidationAttribute that inherits from RegularExpressionAttribute, so something like:
public class EmailAttribute : RegularExpressionAttribute
{
public EmailAttribute()
: base(GetRegex())
{ }
private static string GetRegex()
{
// TODO: Go off and get your RegEx here
return #"^[\w-]+(\.[\w-]+)*#([a-z0-9-]+(\.[a-z0-9-]+)*?\.[a-z]{2,6}|(\d{1,3}\.){3}\d{1,3})(:\d{4})?$";
}
}
That way, you still maintain use of the built in Regex validation but you can customise it. You'd just simply use it like:
[Email(ErrorMessage = "Please use a valid email address")]
Lastly, to get to client side validation to work, you would simply add the following in your Application_Start method within Global.asax, to tell MVC to use the normal regular expression validation for this validator:
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(EmailAttribute), typeof(RegularExpressionAttributeAdapter));
Checkout ScotGu's [Email] attribute (Step 4: Creating a Custom [Email] Validation Attribute).
Do you really want to put the regex in database/config file, or do you just want to centralise them? If you just want to put the regex together, you can just define and use constants like
public class ValidationRegularExpressions {
public const string Regex1 = "...";
public const string Regex2 = "...";
}
Maybe you want to manage the regexes in external files, you can write a MSBuild task to do the replacement when you build for production.
If you REALLY want to change the validation regex at runtime, define your own ValidationAttribute, like
[RegexByKey("MyKey", ErrorMessage = "Email address is not valid")]
public string Email { get; set; }
It's just a piece of code to write:
public class RegexByKeyAttribute : ValidationAttribute {
public RegexByKey(string key) {
...
}
// override some methods
public override bool IsValid(object value) {
...
}
}
Or even just:
public class RegexByKeyAttribute : RegularExpressionAttribute {
public RegexByKey(string key) : base(LoadRegex(key)) { }
// Be careful to cache the regex is this operation is expensive.
private static string LoadRegex(string key) { ... }
}
Hope it's helpful: http://msdn.microsoft.com/en-us/library/cc668224.aspx
Why not just write you own ValidationAttribute?
http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationattribute.aspx
Then you can configure that thing to pull the regex from a registry setting... config file... database... etc... etc..
How to: Customize Data Field Validation in the Data Model Using Custom