Description
A race condition exists in the admin suggestion processing endpoint that can leave suggestions in an inconsistent state when concurrent requests attempt to accept the same suggestion.
Technical Details
Location: goodmap/core_api.py in admin_update_suggestion() endpoint (lines ~494-522)
Problem: TOCTOU (Time-of-Check-Time-of-Use) gap between:
database.get_suggestion() - checking if status is 'pending'
database.add_location() - adding the location
database.update_suggestion() - updating the status
Scenario:
When two concurrent requests accept the same suggestion:
- Both read the suggestion and see
status='pending'
- Request A successfully adds the location and updates the suggestion status
- Request B's
add_location call detects the duplicate and raises LocationAlreadyExistsError
- Request B returns 409 "Location already exists" without marking the suggestion as processed
- The suggestion remains in "pending" state despite being accepted
While duplicate location entries are prevented, the suggestion status becomes inconsistent, confusing admin users who receive a 409 error.
Proposed Solutions
Option 1: Database Transactions
Wrap add_location and update_suggestion in a database transaction/session (MongoDB supports sessions) so both operations succeed together or roll back together.
Option 2: Compare-and-Swap
Implement atomic verify-and-update in database.update_suggestion():
- Accept an
expected_status parameter (e.g., expected='pending')
- Return whether the update succeeded
- Only call
database.add_location() if the CAS succeeded
Option 3: Graceful Duplicate Handling
When add_location raises LocationAlreadyExistsError, treat it as a successful accept and mark the suggestion as processed (or already-accepted).
Context
Files Affected
goodmap/core_api.py - admin_update_suggestion() endpoint
goodmap/db.py - suggestion and location database operations
Description
A race condition exists in the admin suggestion processing endpoint that can leave suggestions in an inconsistent state when concurrent requests attempt to accept the same suggestion.
Technical Details
Location:
goodmap/core_api.pyinadmin_update_suggestion()endpoint (lines ~494-522)Problem: TOCTOU (Time-of-Check-Time-of-Use) gap between:
database.get_suggestion()- checking if status is 'pending'database.add_location()- adding the locationdatabase.update_suggestion()- updating the statusScenario:
When two concurrent requests accept the same suggestion:
status='pending'add_locationcall detects the duplicate and raisesLocationAlreadyExistsErrorWhile duplicate location entries are prevented, the suggestion status becomes inconsistent, confusing admin users who receive a 409 error.
Proposed Solutions
Option 1: Database Transactions
Wrap
add_locationandupdate_suggestionin a database transaction/session (MongoDB supports sessions) so both operations succeed together or roll back together.Option 2: Compare-and-Swap
Implement atomic verify-and-update in
database.update_suggestion():expected_statusparameter (e.g.,expected='pending')database.add_location()if the CAS succeededOption 3: Graceful Duplicate Handling
When
add_locationraisesLocationAlreadyExistsError, treat it as a successful accept and mark the suggestion as processed (or already-accepted).Context
Files Affected
goodmap/core_api.py-admin_update_suggestion()endpointgoodmap/db.py- suggestion and location database operations