diff --git a/pyproject.toml b/pyproject.toml index 11f90c6..ea1cc94 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,6 +12,7 @@ dependencies = [ "alembic>=1.18.4", "arq>=0.27.0", "asyncpg>=0.31.0", + "email-validator>=2.3.0", "fastapi>=0.135.1", "httpx[socks]>=0.28.1", "pydantic>=2.12.5", @@ -57,4 +58,4 @@ extend-immutable-calls = ["Depends", "fastapi.Depends", "Query", "fastapi.Query" [tool.mypy] plugins = ["pydantic.mypy"] -strict = true \ No newline at end of file +strict = true diff --git a/src/proxy_pool/accounts/schemas.py b/src/proxy_pool/accounts/schemas.py new file mode 100644 index 0000000..fa78026 --- /dev/null +++ b/src/proxy_pool/accounts/schemas.py @@ -0,0 +1,67 @@ +from datetime import datetime +from uuid import UUID + +from pydantic import BaseModel, EmailStr, Field + +from proxy_pool.accounts.models import CreditTxType + + +class UserCreate(BaseModel): + email: EmailStr + display_name: str | None = Field(default=None, max_length=128) + + +class UserResponse(BaseModel): + model_config = {"from_attributes": True} + + id: UUID + email: str + display_name: str | None + is_active: bool + created_at: datetime + + +class ApiKeyResponse(BaseModel): + model_config = {"from_attributes": True} + + id: UUID + prefix: str + label: str | None + is_active: bool + last_used_at: datetime | None + expires_at: datetime | None + created_at: datetime + + +class ApiKeyCreated(BaseModel): + """Returned only at key creation time — includes the raw key.""" + + id: UUID + key: str + prefix: str + label: str | None + + +class RegisterResponse(BaseModel): + user: UserResponse + api_key: ApiKeyCreated + + +class ApiKeyCreate(BaseModel): + label: str | None = Field(default=None, max_length=128) + + +class CreditTransactionResponse(BaseModel): + model_config = {"from_attributes": True} + + id: UUID + amount: int + tx_type: CreditTxType + description: str | None + reference_id: UUID | None + created_at: datetime + + +class CreditBalanceResponse(BaseModel): + balance: int + recent_transactions: list[CreditTransactionResponse] diff --git a/uv.lock b/uv.lock index 965f622..4108148 100644 --- a/uv.lock +++ b/uv.lock @@ -223,6 +223,28 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0d/4a/331fe2caf6799d591109bb9c08083080f6de90a823695d412a935622abb2/coverage-7.13.4-py3-none-any.whl", hash = "sha256:1af1641e57cf7ba1bd67d677c9abdbcd6cc2ab7da3bca7fa1e2b7e50e65f2ad0", size = 211242, upload-time = "2026-02-09T12:59:02.032Z" }, ] +[[package]] +name = "dnspython" +version = "2.8.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/8b/57666417c0f90f08bcafa776861060426765fdb422eb10212086fb811d26/dnspython-2.8.0.tar.gz", hash = "sha256:181d3c6996452cb1189c4046c61599b84a5a86e099562ffde77d26984ff26d0f", size = 368251, upload-time = "2025-09-07T18:58:00.022Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" }, +] + +[[package]] +name = "email-validator" +version = "2.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "dnspython" }, + { name = "idna" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f5/22/900cb125c76b7aaa450ce02fd727f452243f2e91a61af068b40adba60ea9/email_validator-2.3.0.tar.gz", hash = "sha256:9fc05c37f2f6cf439ff414f8fc46d917929974a82244c20eb10231ba60c54426", size = 51238, upload-time = "2025-08-26T13:09:06.831Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/de/15/545e2b6cf2e3be84bc1ed85613edd75b8aea69807a71c26f4ca6a9258e82/email_validator-2.3.0-py3-none-any.whl", hash = "sha256:80f13f623413e6b197ae73bb10bf4eb0908faf509ad8362c5edeb0be7fd450b4", size = 35604, upload-time = "2025-08-26T13:09:05.858Z" }, +] + [[package]] name = "factory-boy" version = "3.3.3" @@ -668,6 +690,7 @@ dependencies = [ { name = "alembic" }, { name = "arq" }, { name = "asyncpg" }, + { name = "email-validator" }, { name = "fastapi" }, { name = "httpx", extra = ["socks"] }, { name = "pydantic" }, @@ -695,6 +718,7 @@ requires-dist = [ { name = "alembic", specifier = ">=1.18.4" }, { name = "arq", specifier = ">=0.27.0" }, { name = "asyncpg", specifier = ">=0.31.0" }, + { name = "email-validator", specifier = ">=2.3.0" }, { name = "fastapi", specifier = ">=0.135.1" }, { name = "httpx", extras = ["socks"], specifier = ">=0.28.1" }, { name = "pydantic", specifier = ">=2.12.5" },