Adding a user model

Now, we will create the model that we will use to represent and persist the user. Open the api/models.py file and add the following lines after the declaration of the AddUpdateDelete class. Make sure that you add the import statements. The code file for the sample is included in the restful_python_chapter_07_02 folder:

from passlib.apps import custom_app_context as password_context 
import re 
 
 
class User(db.Model, AddUpdateDelete): 
    id = db.Column(db.Integer, primary_key=True) 
    name = db.Column(db.String(50), unique=True, nullable=False) 
    # I save the hashed password 
    hashed_password = db.Column(db.String(120), nullable=False) 
    creation_date = db.Column(db.TIMESTAMP, server_default=db.func.current_timestamp(), nullable=False) 
 
    def verify_password(self, password): 
        return password_context.verify(password, self.hashed_password) 
 
    def check_password_strength_and_hash_if_ok(self, password): 
        if len(password) < 8: 
            return 'The password is too short', False 
        if len(password) > 32: 
            return 'The password is too long', False 
        if re.search(r'[A-Z]', password) is None: 
            return 'The password must include at least one uppercase letter',
            False 
        if re.search(r'[a-z]', password) is None: 
            return 'The password must include at least one lowercase letter',
            False 
        if re.search(r'd', password) is None: 
            return 'The password must include at least one number', False 
        if re.search(r"[ !#$%&'()*+,-./[\]^_`{|}~"+r'"]', password) is None: 
            return 'The password must include at least one symbol', False 
        self.hashed_password = password_context.encrypt(password) 
        return '', True 
 
    def __init__(self, name): 
        self.name = name 

The code declares the User model, specifically a subclasses of both the db.Model and the AddUpdateDelete classes. We specified the field types, maximum lengths and defaults for the following three attributes-id, name, hashed_password and creation_date. These attributes represent fields without any relationship, and therefore, they are instances of the db.Column class. The model declares an id attribute and specifies the True value for the primary_key argument to indicate it is the primary key. SQLAlchemy will use the data to generate the necessary table in the PostgreSQL database.

The User class declares the following methods:

  • check_password_strength_and_hash_if_ok: This method uses the re module that provides regular expression matching operations to check whether the password received as an argument fulfils many qualitative requirements. The code requires the password to be longer than eight characters, with a maximum of 32 characters. The password must include at least one uppercase letter, one lowercase letter, one number, and one symbol. The code checks the results of many calls to the re.search method to determine whether the received password fulfils each requirement. In case any of the requirements isn't fulfilled, the code returns a tuple with an error message and False. Otherwise, the code calls the encrypt method for the passlib.apps.custom_app_context instance imported as password_context, with the received password as an argument. The encrypt method chooses a reasonably strong scheme based on the platform, with the default settings for rounds selection and the code saves the hashed password in the hash_password attribute. Finally, the code returns a tuple with an empty string and True, indicating that the password fulfilled the qualitative requirements and it was hashed.

Tip

By default, the passlib library will use the SHA-512 scheme for 64-bit platforms and SHA-256 for 32-bit platforms. In addition, the minimum number of rounds will be set to 535,000. We will use the default configuration values for this example. However, you must take into account that these values might require too much processing time for each request that has to validate the password. You should definitely select the most appropriate algorithm and number of rounds based on your security requirements.

  • verify_password: This method calls the verify method for the passlib.apps.custom_app_context instance imported as password_context, with the received password and the stored hashed password for the user, self.hashed_password, as the arguments. The verify method hashes the received password and returns True only if the hashed received password matches the stored hashed password. We never restore the saved password to its original state. We just compare hashed values.

The model declares a constructor, that is, the __init__ method. This constructor receives the user name in the name argument and saves it in an attribute with the same name.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.31.22