Skip to content

Commit e3e3c1a

Browse files
committed
Refactor user_id_index
1 parent 22224fd commit e3e3c1a

File tree

4 files changed

+58
-17
lines changed

4 files changed

+58
-17
lines changed

fastapi_users_db_dynamodb/__init__.py

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -142,21 +142,6 @@ class Meta:
142142

143143
oauth_name = UnicodeAttribute(hash_key=True)
144144

145-
class UserIdIndex(GlobalSecondaryIndex):
146-
"""Enable the `user_id` attribute to be a Global Secondary Index.
147-
148-
Args:
149-
GlobalSecondaryIndex (_type_): The Global Secondary Index base class.
150-
"""
151-
152-
class Meta:
153-
"""The metadata for the Global Secondary Index."""
154-
155-
index_name = "user_id-index"
156-
projection = AllProjection()
157-
158-
user_id = GUID(hash_key=True)
159-
160145
if TYPE_CHECKING: # pragma: no cover
161146
id: ID
162147
oauth_name: str
@@ -176,7 +161,6 @@ class Meta:
176161
# Global Secondary Index
177162
account_id_index = AccountIdIndex()
178163
oauth_name_index = OAuthNameIndex()
179-
user_id_index = UserIdIndex()
180164

181165

182166
class DynamoDBBaseOAuthAccountTableUUID(DynamoDBBaseOAuthAccountTable[UUID_ID]):
@@ -186,13 +170,32 @@ class DynamoDBBaseOAuthAccountTableUUID(DynamoDBBaseOAuthAccountTable[UUID_ID]):
186170
DynamoDBBaseOAuthAccountTable (_type_): The underlying table object.
187171
"""
188172

173+
# MANDATORY GSI (MUST BE IMPLEMENTED)
174+
class UserIdIndex(GlobalSecondaryIndex):
175+
"""Enable the `user_id` attribute to be a Global Secondary Index.
176+
177+
Args:
178+
GlobalSecondaryIndex (_type_): The Global Secondary Index base class.
179+
"""
180+
181+
class Meta:
182+
"""The metadata for the Global Secondary Index."""
183+
184+
index_name = "user_id-index"
185+
projection = AllProjection()
186+
187+
user_id = GUID(hash_key=True)
188+
189189
if TYPE_CHECKING: # pragma: no cover
190190
id: UUID_ID
191191
user_id: UUID_ID
192192
else:
193193
id: GUID = GUID(hash_key=True, default=uuid.uuid4)
194194
user_id: GUID = GUID(null=False)
195195

196+
# Global Secondary Index
197+
user_id_index = UserIdIndex()
198+
196199

197200
class DynamoDBUserDatabase(Generic[UP, ID], BaseUserDatabase[UP, ID]):
198201
"""
@@ -240,6 +243,13 @@ async def _hydrate_oauth_accounts(
240243

241244
user.oauth_accounts = [] # type: ignore
242245

246+
if not hasattr(self.oauth_account_table, "user_id_index") or not isinstance(
247+
self.oauth_account_table.user_id_index, # type: ignore
248+
GlobalSecondaryIndex,
249+
):
250+
raise ValueError(
251+
"Attribute 'user_id_index' not found: OAuthAccount table scheme must implement a Global Secondary Index for attribute 'user_id'."
252+
)
243253
async for oauth_acc in self.oauth_account_table.user_id_index.query( # type: ignore
244254
user.id,
245255
consistent_read=instant_update,

fastapi_users_db_dynamodb/access_token.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,30 @@ class DynamoDBBaseAccessTokenTableUUID(DynamoDBBaseAccessTokenTable[UUID_ID]):
6969
DynamoDBBaseAccessTokenTable (_type_): The underlying table object.
7070
"""
7171

72+
# OPTIONAL GSI
73+
class UserIdIndex(GlobalSecondaryIndex):
74+
"""Enable the `user_id` attribute to be a Global Secondary Index.
75+
76+
Args:
77+
GlobalSecondaryIndex (_type_): The Global Secondary Index base class.
78+
"""
79+
80+
class Meta:
81+
"""The metadata for the Global Secondary Index."""
82+
83+
index_name = "user_id-index"
84+
projection = AllProjection()
85+
86+
user_id = GUID(hash_key=True)
87+
7288
if TYPE_CHECKING: # pragma: no cover
7389
user_id: UUID_ID
7490
else:
7591
user_id: GUID = GUID(null=False)
7692

93+
# Global Secondary Index
94+
user_id_index = UserIdIndex()
95+
7796

7897
class DynamoDBAccessTokenDatabase(Generic[AP], AccessTokenDatabase[AP]):
7998
"""

fastapi_users_db_dynamodb/config.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from enum import StrEnum
22
from typing import Any, Literal, TypedDict
33

4-
__version__ = "1.0.1"
4+
__version__ = "1.0.2"
55

66

77
# Right now, only ON-DEMAND/PAY_PER_REQUEST mode is supported!

tests/test_users.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ async def test_queries_oauth(
258258
oauth_account1: dict[str, Any],
259259
oauth_account2: dict[str, Any],
260260
user_id: UUID_ID,
261+
monkeypatch,
261262
):
262263
"""Test `OAuth` implemenatation and basic **CRUD** operations.
263264
@@ -338,3 +339,14 @@ def _get_account(_user: UserOAuth):
338339
oauth_account,
339340
{"access_token": "NEW_TOKEN"},
340341
)
342+
343+
with pytest.raises(
344+
ValueError,
345+
match="OAuthAccount table scheme must implement a Global Secondary Index",
346+
):
347+
monkeypatch.setattr(
348+
dynamodb_user_db_oauth.oauth_account_table,
349+
"user_id_index",
350+
None,
351+
)
352+
await dynamodb_user_db_oauth._hydrate_oauth_accounts(oauth_user)

0 commit comments

Comments
 (0)