Solved thread

This post is marked as solved. If you think the information contained on this thread must be part of the official documentation, please contribute submitting a pull request to its repository.

StringLength validator for passwords at the model level

Hi community,

I would like to do StringLength validator in the users model on passwords entered in a view for registration. Minimum of 6 characters Max 60. The received password string is hashed in the users controller before it is saved to the model, so it is always 59 characters in length due hashing. So even if the users picks a password with 2 characters, it will pass stringlength constraints.

What should I do? I wish to use a model validator.

Cheers!

DN

I know this probably isn't what you were looking for but why not just verify the length in the controller before hashing along with the length using javascript before submission?

Thanks for your reply. I may end up trying that, but I'd like the validator because of the ease of appending messages. We usually try to work it out with the given functionality, and if that can't work as expected, we bolt on.

I know this probably isn't what you were looking for but why not just verify the length in the controller before hashing along with the length using javascript before submission?



4.4k

You could validate the length in the in the validation() function, then hash the password in the `afterValidation() function.

Just make sure that you check for changes using $this->keepSnapshots(true); in your initialize() function so that you only validate the password length when it was actually changed. You can check for changes like so:


public function initialize() {

     // Keep a snapshot of the model
    $this->keepSnapshots(true);
}

public function validation(){

    // Setup the validator
    $this->validate(new \Phalcon\Mvc\Model\Validator\StringLength(array(
            'field' => 'password',
            'max' => 60,
            'min' => 6,
            'messageMaximum' => 'Your password is too long.',
            'messageMinimum' => 'Your password is too short.'
    )));

    return !$this->validationHasFailed();
}

public function afterValidation(){

    // If there has been a change in the password, re-hash it
    if($this->hasChanged('password')){
        $this->password = password_hash($this->password, PASSWORD_BCRYPT)
    }

}

More Info on Recording Snapshots

I didn't test that code specifically but it should point you in the right direction

edited Apr '15

Thanks for the reply. I didn't know about the afterValidation function. I thought the last stop was validation, so I should have read a little further. I see also a beforeValidation as well. I'll quickly check this out.

edited Apr '15

Well, the validation seems to work, but the model kicks out a message "The record doesn't have a valid data snapshot" when trying to save the user. I have included $this->keepSnapshots(true) in the initialize. Any idea what causes this. I try to search the forum, but nothing on this.



4.4k
Accepted
answer

Sorry about that. It sounds like you were adding the user, which in that case, there wouldn't be a valid snapshot since there isn't anything to take a snapshot of.

Remov the afterValidation() function and replace it with the following two:

public function afterValidationOnCreate(){

    // Always hash the password on update
    $this->password = password_hash($this->password, PASSWORD_BCRYPT)
}

public function afterValidationOnUpdate(){

    // If there has been a change in the password, re-hash it
    if($this->hasChanged('password')){
        $this->password = password_hash($this->password, PASSWORD_BCRYPT)
    }

}
edited Apr '15

I'll credit you for the answer, though I just ended up removing the hasChanged method from afterValidation(). I can't find in the documentation anything like afterValidationOnCreate(). Could you give a link?



4.4k

Thank you for accepting the answer. Here is a link to the docs for the model events: Model Events And Event Manager