pydantic-extra-types icon indicating copy to clipboard operation
pydantic-extra-types copied to clipboard

chore(feat): Support OTP as a type

Open yezz123 opened this issue 2 years ago • 4 comments

import random

from pydantic import BaseModel, Field
from pydantic_extra_types import OTP, OTP_ALPHABET


class GenerateOTP(BaseModel):
    """
    Generate an OTP
    """

    length: int = Field(6, ge=6, le=6)
    alphabet: str = Field(OTP_ALPHABET, min_length=6, max_length=32)

    def generate(self) -> OTP:
        return OTP(''.join(random.choices(self.alphabet, k=self.length)))

yezz123 avatar Feb 07 '23 21:02 yezz123

I'm a bit unclear on the usage here.

I think the api should perhaps be more like

class LoginForm(BaseModel):
    password: str  # whatever
    ot_token: OTPToken

...

LoginForm.model_validate(form_data, context={'otp_secret': otp_secret_from_database_etc})

OTPToken then just raises a ValidationError if the token is incorrect, otherwise the value could just be None.

Does that make sense?

samuelcolvin avatar Feb 08 '23 10:02 samuelcolvin

I'm a bit unclear on the usage here.

I think the api should perhaps be more like

class LoginForm(BaseModel):
    password: str  # whatever
    ot_token: OTPToken

...

LoginForm.model_validate(form_data, context={'otp_secret': otp_secret_from_database_etc})

OTPToken then just raises a ValidationError if the token is incorrect, otherwise, the value could just be None.

Does that make sense?

I think this approach is clear, more than using OTP to validate!

I will try to make this approach!

yezz123 avatar Feb 09 '23 07:02 yezz123

Hey @samuelcolvin

I think we have schema close to this:

from pydantic import BaseModel
from pydantic_extra_types import OTPToken
import pyotp

class LoginForm(BaseModel):
    username: str
    password: str
    ot_token: OTPToken

# Generate a secret key to be used for OTP generation
otp_secret = pyotp.random_base32()

# User input in the form of a dictionary
form_data = {
    'username': 'user123',
    'password': 'secret_password',
    'ot_token': pyotp.TOTP(otp_secret).now()
}

# Validate the form data
form = LoginForm.model_validate(form_data, context={'otp_secret': otp_secret})

# Print the validated form data
print(f'Login successful for user {form}')

yezz123 avatar Feb 12 '23 10:02 yezz123

@samuelcolvin all the changes fixed, This Pull request is ready to merge

yezz123 avatar Mar 09 '23 20:03 yezz123