fix(industrial): bbox handler — let includeOsmRaw bypass isPublic for OSM rows
Some checks failed
CI / E2E Tests (push) Has been skipped
CI / Lint → Typecheck → Test → Build (22) (push) Failing after 3s
CI / AI Services (Python) — Smoke (push) Failing after 3s
CodeQL Analysis / CodeQL (javascript-typescript) (push) Failing after 1m4s
Deploy / Build API Image (push) Failing after 9s
Deploy / Build Web Image (push) Failing after 4s
Deploy / Build AI Services Image (push) Failing after 5s
E2E Tests / Playwright E2E (push) Failing after 8s
Security Scanning / Dependency Audit (pnpm) (push) Failing after 4s
Security Scanning / Trivy Scan — Web Image (push) Failing after 33s
Security Scanning / Trivy Scan — API Image (push) Failing after 42s
Security Scanning / Trivy Scan — AI Services Image (push) Failing after 31s
Security Scanning / Trivy Filesystem Scan (push) Failing after 33s
Deploy / Deploy to Staging (push) Has been skipped
Deploy / Smoke Test Staging (push) Has been skipped
Security Scanning / Security Gate (push) Failing after 1s
Deploy / Rollback Staging (push) Has been skipped
Deploy / Deploy to Production (push) Failing after 13m17s
Deploy / Smoke Test Production (push) Has been cancelled
Deploy / Rollback Production (push) Has been cancelled

The previous filter was `isPublic = true AND dataSource IN (...)` — so even
when an admin passed `includeOsmRaw=true`, raw OSM rows were excluded
because they're imported with `isPublic = false`. That defeated the entire
admin-preview use case.

New visibility rule:
  - Public callers: only `isPublic = true` rows (MANUAL + OSM_PROMOTED).
  - Admin callers (`includeOsmRaw=true`): also include OSM raw rows
    regardless of `isPublic`, so the admin map shows the review queue.

Verified locally: bbox over HCMC with includeOsmRaw=true now returns
548 features (9 MANUAL + 539 OSM). Default public call still returns 9.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ho Ngoc Hai
2026-04-29 22:10:41 +07:00
parent b3143991ce
commit e7ca4fe8b1

View File

@@ -47,11 +47,17 @@ export class GetIndustrialParksByBboxHandler
const { south, west, north, east } = q.bbox; const { south, west, north, east } = q.bbox;
const includeBoundary = q.zoom >= BOUNDARY_ZOOM; const includeBoundary = q.zoom >= BOUNDARY_ZOOM;
const limit = Math.min(Math.max(q.limit, 1), 5000); const limit = Math.min(Math.max(q.limit, 1), 5000);
// Filter out raw OSM imports for public consumers; admins pass // Visibility logic:
// includeOsmRaw=true to see them. // - Public callers: only `isPublic = true` rows (MANUAL + OSM_PROMOTED).
const dataSourceFilter = q.includeOsmRaw // - Admin callers (`includeOsmRaw=true`): also include OSM raw rows
? `'MANUAL', 'OSM', 'OSM_PROMOTED'` // regardless of `isPublic`, so the admin map can preview the
: `'MANUAL', 'OSM_PROMOTED'`; // review queue. Other rows still respect `isPublic`.
const visibilityClause = q.includeOsmRaw
? `(
("isPublic" = true AND "dataSource"::text IN ('MANUAL', 'OSM_PROMOTED'))
OR "dataSource"::text = 'OSM'
)`
: `("isPublic" = true AND "dataSource"::text IN ('MANUAL', 'OSM_PROMOTED'))`;
// Single PostGIS query: bbox filter + optional polygon column. // Single PostGIS query: bbox filter + optional polygon column.
// && is the bbox-intersect operator and uses the GiST index. // && is the bbox-intersect operator and uses the GiST index.
@@ -70,8 +76,7 @@ export class GetIndustrialParksByBboxHandler
ST_AsGeoJSON(location) AS point, ST_AsGeoJSON(location) AS point,
${includeBoundary ? `ST_AsGeoJSON(boundary)` : `NULL::text`} AS polygon ${includeBoundary ? `ST_AsGeoJSON(boundary)` : `NULL::text`} AS polygon
FROM "IndustrialPark" FROM "IndustrialPark"
WHERE "isPublic" = true WHERE ${visibilityClause}
AND "dataSource"::text IN (${dataSourceFilter})
AND location && ST_MakeEnvelope($1, $2, $3, $4, 4326) AND location && ST_MakeEnvelope($1, $2, $3, $4, 4326)
ORDER BY "totalAreaHa" DESC NULLS LAST ORDER BY "totalAreaHa" DESC NULLS LAST
LIMIT ${limit + 1} LIMIT ${limit + 1}