Skip to content

Commit 24da552

Browse files
authored
Merge pull request #532 from nanotaboada/feat/put-squad-number-mismatch-validation
feat(api): enforce squad number immutability on PUT
2 parents 2beb177 + c8360c5 commit 24da552

File tree

3 files changed

+28
-0
lines changed

3 files changed

+28
-0
lines changed

models/player_model.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,15 @@
55
- `PlayerRequestModel`: Represents player data for Create and Update operations.
66
- `PlayerResponseModel`: Represents player data including UUID for Retrieve operations.
77
8+
Design decision — single request model vs split models:
9+
A single `PlayerRequestModel` is intentionally shared by both POST (Create)
10+
and PUT (Update). Per-operation differences are handled at the route layer
11+
rather than by duplicating the model:
12+
- POST checks that `squad_number` does not already exist (→ 409 Conflict).
13+
- PUT checks that `squad_number` in the body matches the path parameter
14+
(→ 400 Bad Request), ensuring the request is unambiguous. The path
15+
parameter is always the authoritative source of identity on PUT.
16+
817
These models are used for data validation and serialization in the API.
918
"""
1019

routes/player_route.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,14 @@ async def put_async(
199199
async_session (AsyncSession): The async version of a SQLAlchemy ORM session.
200200
201201
Raises:
202+
HTTPException: HTTP 400 Bad Request if squad_number in the request body does
203+
not match the path parameter. The path parameter is the authoritative source
204+
of identity on PUT; a mismatch makes the request ambiguous.
202205
HTTPException: HTTP 404 Not Found error if the Player with the specified Squad
203206
Number does not exist.
204207
"""
208+
if player_model.squad_number != squad_number:
209+
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST)
205210
player = await player_service.retrieve_by_squad_number_async(
206211
async_session, squad_number
207212
)

tests/test_main.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,20 @@ def test_request_put_player_squadnumber_existing_response_status_no_content(clie
234234
assert response.status_code == 204
235235

236236

237+
def test_request_put_player_squadnumber_mismatch_response_status_bad_request(client):
238+
"""PUT /players/squadnumber/{squad_number} with mismatched squad number in body returns 400 Bad Request"""
239+
# Arrange
240+
squad_number = existing_player().squad_number
241+
player = existing_player()
242+
player.squad_number = unknown_player().squad_number
243+
# Act
244+
response = client.put(
245+
PATH + "squadnumber/" + str(squad_number), json=player.__dict__
246+
)
247+
# Assert
248+
assert response.status_code == 400
249+
250+
237251
# DELETE /players/squadnumber/{squad_number} -----------------------------------
238252

239253

0 commit comments

Comments
 (0)