Skip to content

Commit a6689c0

Browse files
committed
Fix tests
1 parent 3b37c9f commit a6689c0

File tree

5 files changed

+60
-51
lines changed

5 files changed

+60
-51
lines changed

fastapi_users_db_dynamodb/__init__.py

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from boto3.dynamodb.conditions import Attr
2626
from fastapi_users.db.base import BaseUserDatabase
2727
from fastapi_users.models import ID, OAP, UP
28+
from pydantic import BaseModel, ConfigDict, Field
2829

2930
from fastapi_users_db_dynamodb._aioboto3_patch import * # noqa: F403
3031
from fastapi_users_db_dynamodb.generics import GUID
@@ -34,22 +35,30 @@
3435
UUID_ID = uuid.UUID
3536

3637

37-
class DynamoDBBaseUserTable(Generic[ID]):
38+
class DynamoDBBaseUserTable(BaseModel, Generic[ID]):
3839
"""Base user table schema for DynamoDB."""
3940

41+
model_config = ConfigDict(arbitrary_types_allowed=True)
42+
4043
__tablename__ = "user"
4144

4245
if TYPE_CHECKING:
4346
id: ID
44-
email: str
45-
hashed_password: str
46-
is_active: bool
47-
is_superuser: bool
48-
is_verified: bool
47+
email: str = Field(..., description="The email of the user")
48+
hashed_password: str = Field(..., description="The hashed password of the user")
49+
is_active: bool = Field(
50+
default=True, description="Whether the user is marked as active in the database"
51+
)
52+
is_superuser: bool = Field(
53+
default=False, description="Whether the user has admin rights"
54+
)
55+
is_verified: bool = Field(
56+
default=False, description="Whether the user has verified their email"
57+
)
4958

5059

5160
class DynamoDBBaseUserTableUUID(DynamoDBBaseUserTable[UUID_ID]):
52-
id: UUID_ID
61+
id: UUID_ID = Field(default_factory=uuid.uuid4, description="The ID for the user")
5362

5463

5564
class DynamoDBBaseOAuthAccountTable(Generic[ID]):
@@ -59,18 +68,27 @@ class DynamoDBBaseOAuthAccountTable(Generic[ID]):
5968

6069
if TYPE_CHECKING:
6170
id: ID
62-
oauth_name: str
63-
access_token: str
64-
expires_at: int | None
65-
refresh_token: str | None
66-
account_id: str
67-
account_email: str
68-
user_id: ID
71+
oauth_name: str = Field(..., description="The name of the OAuth social provider")
72+
access_token: str = Field(
73+
..., description="The access token linked with the OAuth account"
74+
)
75+
expires_at: int | None = Field(
76+
default=None, description="The timestamp at which this account expires"
77+
)
78+
refresh_token: str | None = Field(
79+
default=None, description="The refresh token associated with this OAuth account"
80+
)
81+
account_id: str = Field(..., description="The ID of this OAuth account")
82+
account_email: str = Field(
83+
..., description="The email associated with this OAuth account"
84+
)
6985

7086

7187
class DynamoDBBaseOAuthAccountTableUUID(DynamoDBBaseUserTable[UUID_ID]):
72-
id: UUID_ID
73-
user_id: GUID
88+
id: UUID_ID = Field(
89+
default_factory=uuid.uuid4, description="The ID for the OAuth account"
90+
)
91+
user_id: GUID = Field(..., description="The user ID this OAuth account belongs to")
7492

7593

7694
class DynamoDBUserDatabase(Generic[UP, ID], BaseUserDatabase[UP, ID]):

fastapi_users_db_dynamodb/access_token.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,23 +14,30 @@
1414
import aioboto3
1515
from fastapi_users.authentication.strategy.db import AP, AccessTokenDatabase
1616
from fastapi_users.models import ID
17+
from pydantic import BaseModel, ConfigDict, Field
1718

1819
from fastapi_users_db_dynamodb._aioboto3_patch import * # noqa: F403
20+
from fastapi_users_db_dynamodb.generics import GUID
1921

2022

21-
class DynamoDBBaseAccessTokenTable(Generic[ID]):
23+
class DynamoDBBaseAccessTokenTable(BaseModel, Generic[ID]):
2224
"""Base access token table schema for DynamoDB."""
2325

26+
model_config = ConfigDict(arbitrary_types_allowed=True)
27+
2428
__tablename__ = "accesstoken"
2529

26-
token: str
27-
created_at: datetime
30+
token: str = Field(..., description="The token value of the AccessToken object")
31+
created_at: datetime = Field(
32+
default_factory=lambda: datetime.now(timezone.utc),
33+
description="The date of creation of the AccessToken object",
34+
)
2835
if TYPE_CHECKING:
2936
user_id: ID
3037

3138

3239
class DynamoDBBaseAccessTokenTableUUID(DynamoDBBaseAccessTokenTable[uuid.UUID]):
33-
user_id: uuid.UUID
40+
user_id: GUID = Field(..., description="The user ID this token belongs to")
3441

3542

3643
class DynamoDBAccessTokenDatabase(Generic[AP], AccessTokenDatabase[AP]):

fastapi_users_db_dynamodb/generics.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from pydantic import UUID4
1313

1414

15-
class GUID:
15+
class GUID(UUID4):
1616
"""
1717
Platform-independent GUID type.
1818
@@ -49,7 +49,7 @@ def now_utc() -> datetime:
4949
return datetime.now(timezone.utc)
5050

5151

52-
class TIMESTAMPAware:
52+
class TIMESTAMPAware(datetime):
5353
"""
5454
Kept for API compatibility.
5555

tests/test_access_token.py

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
import uuid
21
from collections.abc import AsyncGenerator
32
from datetime import datetime, timedelta, timezone
43

54
import aioboto3
65
import pytest
76
import pytest_asyncio
87
from moto import mock_aws
9-
from pydantic import UUID4
8+
from pydantic import UUID4, BaseModel
109

1110
from fastapi_users_db_dynamodb import DynamoDBBaseUserTableUUID, DynamoDBUserDatabase
1211
from fastapi_users_db_dynamodb._aioboto3_patch import * # noqa: F403
@@ -18,7 +17,7 @@
1817
from tests.tables import ensure_table_exists
1918

2019

21-
class Base:
20+
class Base(BaseModel):
2221
pass
2322

2423

@@ -30,11 +29,6 @@ class User(DynamoDBBaseUserTableUUID, Base):
3029
pass
3130

3231

33-
@pytest.fixture
34-
def user_id() -> UUID4:
35-
return uuid.uuid4()
36-
37-
3832
@pytest_asyncio.fixture
3933
async def dynamodb_access_token_db(
4034
user_id: UUID4,

tests/test_users.py

Lines changed: 11 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import pytest
55
import pytest_asyncio
66
from moto import mock_aws
7+
from pydantic import BaseModel, ConfigDict, Field
78

89
from fastapi_users_db_dynamodb import (
910
UUID_ID,
@@ -16,12 +17,12 @@
1617
from tests.tables import ensure_table_exists
1718

1819

19-
class Base:
20-
pass
20+
class Base(BaseModel):
21+
model_config = ConfigDict(arbitrary_types_allowed=True)
2122

2223

2324
class User(DynamoDBBaseUserTableUUID, Base):
24-
first_name: str | None
25+
first_name: str | None = Field(default=None, description="First name of the user")
2526

2627

2728
class OAuthBase:
@@ -33,8 +34,10 @@ class OAuthAccount(DynamoDBBaseOAuthAccountTableUUID, OAuthBase):
3334

3435

3536
class UserOAuth(DynamoDBBaseUserTableUUID, OAuthBase):
36-
first_name: str | None
37-
oauth_accounts: list[OAuthAccount]
37+
first_name: str | None = Field(default=None, description="First name of the user")
38+
oauth_accounts: list[OAuthAccount] = Field(
39+
default_factory=list, description="Linked OAuth accounts"
40+
)
3841

3942

4043
@pytest_asyncio.fixture
@@ -118,7 +121,7 @@ async def test_queries(dynamodb_user_db: DynamoDBUserDatabase[User, UUID_ID]):
118121
await dynamodb_user_db.get_by_oauth_account("foo", "bar")
119122
with pytest.raises(NotImplementedError):
120123
await dynamodb_user_db.add_oauth_account(user, {})
121-
with pytest.raises(NotImplementedError):
124+
with pytest.raises(ValueError):
122125
oauth_account = OAuthAccount()
123126
await dynamodb_user_db.update_oauth_account(user, oauth_account, {})
124127

@@ -161,23 +164,10 @@ async def test_queries_custom_fields(
161164
@pytest.mark.asyncio
162165
async def test_queries_oauth(
163166
dynamodb_user_db_oauth: DynamoDBUserDatabase[UserOAuth, UUID_ID],
167+
oauth_account1,
168+
oauth_account2,
164169
):
165170
# Test OAuth accounts
166-
oauth_account1 = {
167-
"oauth_name": "service1",
168-
"access_token": "TOKEN",
169-
"expires_at": 1579000751,
170-
"account_id": "user_oauth1",
171-
"account_email": "king.arthur@camelot.bt",
172-
}
173-
oauth_account2 = {
174-
"oauth_name": "service2",
175-
"access_token": "TOKEN",
176-
"expires_at": 1579000751,
177-
"account_id": "user_oauth2",
178-
"account_email": "king.arthur@camelot.bt",
179-
}
180-
181171
user_create = {"email": "lancelot@camelot.bt", "hashed_password": "guinevere"}
182172

183173
# Create user

0 commit comments

Comments
 (0)