Skip to content

Commit 7e101f1

Browse files
committed
fix(spp_api_v2_gis): add sudo() to geofence router and harden error responses
- Add sudo() to all geofence model access calls (5 places) to fix 403 errors when API runs as public user - Replace str(e) in 500 error handlers with generic messages across geofence, spatial_query, proximity, and statistics routers to prevent leaking Odoo internals - Add statistics:read scope to statistics router for consistency with spatial_query and proximity routers - Fix Odoo False -> None conversion for geofence description field
1 parent 41bd6c6 commit 7e101f1

4 files changed

Lines changed: 23 additions & 18 deletions

File tree

spp_api_v2_gis/routers/geofence.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ async def create_geofence(
6060
)
6161

6262
# Get the geofence model
63-
geofence_model = env["spp.gis.geofence"]
63+
# nosemgrep: odoo-sudo-without-context
64+
geofence_model = env["spp.gis.geofence"].sudo()
6465

6566
# Prepare kwargs for optional fields
6667
kwargs = {}
@@ -70,7 +71,8 @@ async def create_geofence(
7071
# Handle incident_code if provided
7172
if request.incident_code:
7273
# Find incident by code (external ID)
73-
incident = env["spp.hazard.incident"].search([("code", "=", request.incident_code)], limit=1)
74+
# nosemgrep: odoo-sudo-without-context
75+
incident = env["spp.hazard.incident"].sudo().search([("code", "=", request.incident_code)], limit=1)
7476
if not incident:
7577
raise HTTPException(
7678
status_code=status.HTTP_404_NOT_FOUND,
@@ -98,7 +100,7 @@ async def create_geofence(
98100
return GeofenceResponse(
99101
id=geofence.id,
100102
name=geofence.name,
101-
description=geofence.description,
103+
description=geofence.description or None,
102104
geofence_type=geofence.geofence_type,
103105
area_sqkm=geofence.area_sqkm,
104106
active=geofence.active,
@@ -115,7 +117,7 @@ async def create_geofence(
115117
_logger.exception("Error creating geofence")
116118
raise HTTPException(
117119
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
118-
detail=f"Failed to create geofence: {str(e)}",
120+
detail="Failed to create geofence",
119121
) from e
120122

121123

@@ -171,7 +173,8 @@ async def list_geofences(
171173
domain.append(("active", "=", True))
172174

173175
# Get geofence model
174-
geofence_model = env["spp.gis.geofence"]
176+
# nosemgrep: odoo-sudo-without-context
177+
geofence_model = env["spp.gis.geofence"].sudo()
175178

176179
# Get total count
177180
total = geofence_model.search_count(domain)
@@ -232,7 +235,8 @@ async def get_geofence(
232235
)
233236

234237
# Get geofence model
235-
geofence_model = env["spp.gis.geofence"]
238+
# nosemgrep: odoo-sudo-without-context
239+
geofence_model = env["spp.gis.geofence"].sudo()
236240

237241
# Search for geofence
238242
geofence = geofence_model.browse(geofence_id)
@@ -250,7 +254,7 @@ async def get_geofence(
250254
_logger.exception("Error converting geofence to GeoJSON")
251255
raise HTTPException(
252256
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
253-
detail=f"Failed to convert geofence to GeoJSON: {str(e)}",
257+
detail="Failed to retrieve geofence data",
254258
) from e
255259

256260

@@ -285,7 +289,8 @@ async def delete_geofence(
285289
)
286290

287291
# Get geofence model
288-
geofence_model = env["spp.gis.geofence"]
292+
# nosemgrep: odoo-sudo-without-context
293+
geofence_model = env["spp.gis.geofence"].sudo()
289294

290295
# Search for geofence
291296
geofence = geofence_model.browse(geofence_id)
@@ -303,5 +308,5 @@ async def delete_geofence(
303308
_logger.exception("Error archiving geofence")
304309
raise HTTPException(
305310
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
306-
detail=f"Failed to archive geofence: {str(e)}",
311+
detail="Failed to archive geofence",
307312
) from e

spp_api_v2_gis/routers/proximity.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ async def query_proximity(
7373
status_code=status.HTTP_400_BAD_REQUEST,
7474
detail=str(e),
7575
) from None
76-
except Exception as e:
76+
except Exception:
7777
_logger.exception("Proximity query failed")
7878
raise HTTPException(
7979
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
80-
detail=f"Proximity query failed: {str(e)}",
80+
detail="Proximity query failed",
8181
) from None

spp_api_v2_gis/routers/spatial_query.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ async def query_statistics(
8080
_logger.exception("Spatial query failed")
8181
raise HTTPException(
8282
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
83-
detail=f"Spatial query failed: {str(e)}",
83+
detail="Spatial query failed",
8484
) from e
8585

8686

@@ -129,9 +129,9 @@ async def query_statistics_batch(
129129
status_code=status.HTTP_400_BAD_REQUEST,
130130
detail=str(e),
131131
) from None
132-
except Exception as e:
132+
except Exception:
133133
_logger.exception("Batch spatial query failed")
134134
raise HTTPException(
135135
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
136-
detail=f"Batch spatial query failed: {str(e)}",
136+
detail="Batch spatial query failed",
137137
) from None

spp_api_v2_gis/routers/statistics.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ async def list_statistics(
3838
for spatial queries and map visualization.
3939
"""
4040
# Check read scope
41-
if not api_client.has_scope("gis", "read"):
41+
if not (api_client.has_scope("gis", "read") or api_client.has_scope("statistics", "read")):
4242
raise HTTPException(
4343
status_code=status.HTTP_403_FORBIDDEN,
44-
detail="Client does not have gis:read scope",
44+
detail="Client does not have gis:read or statistics:read scope",
4545
)
4646

4747
try:
@@ -84,9 +84,9 @@ async def list_statistics(
8484
total_count=total_count,
8585
)
8686

87-
except Exception as e:
87+
except Exception:
8888
_logger.exception("Failed to list statistics")
8989
raise HTTPException(
9090
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
91-
detail=f"Failed to list statistics: {str(e)}",
91+
detail="Failed to list statistics",
9292
) from None

0 commit comments

Comments
 (0)