Today I took care of a couple of odds and ends regarding the user system: the need to have stricter password validators, and the need to verify an email address.
First off, the validators. I wanted to have additional requirements for the password, such as requiring a number and requiring a digit. I consulted the WTForms documentation on validators, which also invited a side glance into the Factory Method. This is something I’m going to be looking at when I have to improve my recipe scraper. But that’s for another post.
My first version of the validator was a bit cumbersome, but worked as proof of concept:
It’s essentially an expanded version of the example given on the WTForms documentation, with the use of several any() calls to check if there was a digit or an acceptable symbol. I tried it and it seemed to work when I gave it bad information:
It’s too cumbersome, though. It can tell if something is wrong, but doesn’t give the user feedback on which of the three issues (length, digit, symbol) is the problem. What I really needed to do was create several different validators.
I decided to use the already existing Length validator for my length, and split the rest of the code into two new validators: DigitRequired and SymbolRequired:
Then, because all these validators would be clumped up anyway, I created a list with all of the validators for passwords, called PasswordValidators:
This made it very easy to simply put the password validators in wherever I needed them:
Done. I gave it a few simple tests and everything seemed to be working. That was easy. On to the next issue.
Validating Email Addresses
Most apps with a user account system require the user to verify their email address before sending them anything important, such as a request to change their password. I wanted to implement this feature as well, and since I already had something similar implemented for the reset password, I figured it would be pretty simple.
First, I created a new line in my Users model to check if their email is validated:
Then, while still in the User class, I created new methods to generate an email verify token, and to check that token. Originally I used the same validators from my password changer, but I didn’t want this link to be time-sensitive, so I ultimately added new ones. In the future, however, I think it would be a good idea to combine these (maybe with a factory method?), since there’s too much repetition going on.
Then, I created a new funciton to generate the email to send to validate the address, and made sure to send it when the user first registered their account:
Then, I wrote in a new route to validate the token. It retrieves the User’s id from the token and changes that user’s email_verified bool to true. Thus, the email is verified.
Finally, I added a check in my reset_password route to see if the user’s email was verified. If it was not, then it does not send a link to change the password. This might make it tricky for people who don’t verify their emails to change their password, but I might add in a secondary option at some point.
And done! Two important additions to my user functionality. We’re almost done here.