Criando um hash

Para fazer com que o password dos usuários seja salvo como um hash ao invés de plain-text vamos criar uma função para criar o hash e outra para verificar.

Além disso vamos criar uma classe herdando de str e customizar o método validate desta forma podemos usar esta classe na definição de campo do nosso model User e o pydantic vai chamar o método validate para transformar o valor do campo em um hash.

EDITE Agora vamos o dundie/security.py e adicione alguns elementos

"""Security utilities"""
from passlib.context import CryptContext

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")


def verify_password(plain_password, hashed_password) -> bool:
    """Verifies a hash against a password"""
    return pwd_context.verify(plain_password, hashed_password)


def get_password_hash(password) -> str:
    """Generates a hash from plain text"""
    return pwd_context.hash(password)


class HashedPassword(str):
    """Takes a plain text password and hashes it.
    use this as a field in your SQLModel
    class User(SQLModel, table=True):
        username: str
        password: HashedPassword
    """

    @classmethod
    def __get_validators__(cls):
        # one or more validators may be yielded which will be called in the
        # order to validate the input, each validator will receive as an input
        # the value returned from the previous validator
        yield cls.validate

    @classmethod
    def validate(cls, v):
        """Accepts a plain text password and returns a hashed password."""
        if not isinstance(v, str):
            raise TypeError("string required")

        hashed_password = get_password_hash(v)
        # you could also return a string here which would mean model.password
        # would be a string, pydantic won't care but you could end up with some
        # confusion since the value's type won't match the type annotation
        # exactly
        return cls(hashed_password)

EDITE agora o arquivo dundie/models/user.py

No topo na linha 4

from dundie.security import HashedPassword

E no model mudamos o campo password na linha 18 para

password: HashedPassword

E no final de dundie/models/user.py uma função para gerar os usernames, transformando nomes completos como Bruno Rocha em um slug como bruno-rocha

def generate_username(name: str) -> str:
    """Generates a slug username from a name"""
    return name.lower().replace(" ", "-")

Agora sim está tudo pronto para adicionarmos ao nosso CLI um comando para criar novos usuários -->