redis / redis-om-python

Object mapping, and more, for Redis and Python
MIT License
1.09k stars 108 forks source link

pydantic validators fail silently #464

Open XChikuX opened 1 year ago

XChikuX commented 1 year ago

This code works fine if the password conforms to the validator rules. Especially during assignment of a parent JsonModel. However when I run a get() method to retrieve data I run into errors.

I have the follow EmbeddedJsonModel.

class identity(EmbeddedJsonModel):
    '''
    A Password|Token verification class
    '''
    password: str | None
    auth_token: str | None
    # session_token: str | None

    @root_validator
    def password_or_token(cls, values):
        if values['password'] or values['auth_token']:
            return values
        raise ValueError("Password or Token must be provided")

    @validator("password", pre=True)
    def password_hasher(cls, password):
        if password:
            if len(password) >= 8 and len(password) <= 16:
                if not (any(char in special_characters for char in password)
                and any(char.isdigit() for char in password)):
                    raise ValueError("Password must contain at least 1 number and 1 special character")
            else:
                raise ValueError("Password must be between 8 and 16 characters")
            return ph().hash(password)

x = await RedisUser.get(pk) This fails with the following error: KeyError: 'password' This indicates that the Model completely rejected the key 'password' on getting it back. Since the value is hashed and doesn't necessarily pass the validation check anymore on retrieval from the DB.

If I comment out the @root_validator then my 2nd validator returns the correct error.

Similarly, If I comment the 2nd validator @validator("password") then the program works. My root validator runs.

This problem may extend to the sync version as well.

This is what I sent to the DB: identity(pk='01GPZQCPEDZG928P7XCTHJYB36', password='<password hash that fails the validator check>', auth_token=None)

This is what I got back: identity(pk='01GPZQCPEDZG928P7XCTHJYB36', auth_token=None)

XChikuX commented 1 year ago

This could be a pydantic problem. Will need to debug further.