Skip to content

Password

Operations with passwords

main.py
"""Operations with passwords.

To operations with a password, use only special methods.
Do not use this field directly.
"""

import anyio
from datetime import datetime
from zoneinfo import ZoneInfo
from typing import Annotated
from pydantic import EmailStr, Field
from pydantic_extra_types.phone_numbers import PhoneNumber, PhoneNumberValidator
from scruby import CryptModel, Scruby, ScrubyModel


class User(ScrubyModel, CryptModel):
    """User model."""

    username: str
    first_name: str
    last_name: str
    birthday: datetime
    email: EmailStr
    phone: Annotated[
        PhoneNumber,
        PhoneNumberValidator(number_format="E164"),
        Field(strict=False),
    ]
    # key is always at bottom
    key: Annotated[
        str,
        Field(
            frozen=True,
            default_factory=lambda data: data["username"],
        ),
    ]


async def main() -> None:
    """Example."""
    # Activate database.
    Scruby.run()

    # Create/get the `User` collection.
    user_coll = Scruby(User)

    # Create user
    user = User(
        username="user_1",
        first_name="John",
        last_name="Smith",
        birthday=datetime(1970, 1, 1, tzinfo=ZoneInfo("UTC")),
        email="John_Smith@gmail.com",
        phone="+447986123456",
    )

    test_pass = "user_pass_123"

    # Add user password
    user.set_password(test_pass)

    # Add user to collection
    await user_coll.add_doc(user)

    # Get user details
    user_details = await user_coll.get_doc("user_1")

    # Check a password
    user_details.password_is_valid(test_pass)  # True

    # Update existing password
    new_test_pass = "new_user_pass_123"
    user_details.update_password(test_pass, new_test_pass)

    # Update user data in a collection
    await user_coll.update_doc(user_details)

    # Full database deletion.
    # Hint: The main purpose is tests.
    Scruby.napalm()


if __name__ == "__main__":
    anyio.run(main)