diff --git a/src/app/api/gis/parcela/find/route.ts b/src/app/api/gis/parcela/find/route.ts index f33657e..27dfb80 100644 --- a/src/app/api/gis/parcela/find/route.ts +++ b/src/app/api/gis/parcela/find/route.ts @@ -51,6 +51,7 @@ export async function GET(request: Request) { } let fallback: unknown = null; + let forbiddenCount = 0; for (const c of candidates) { try { const detail = (await gisApi.parcela.get(c.id)) as { @@ -70,8 +71,13 @@ export async function GET(request: Request) { return NextResponse.json(detail); } } catch (e) { - // Skip candidates that 403 (scope) or fail individually. - if (e instanceof GisApiError && e.status === 403) continue; + // Skip candidates that 403 (scope) or fail individually, + // but track 403s so we can distinguish "no data" from + // "all data was scope-blocked" at the route boundary. + if (e instanceof GisApiError && e.status === 403) { + forbiddenCount++; + continue; + } throw e; } } @@ -86,6 +92,31 @@ export async function GET(request: Request) { ); return NextResponse.json(fallback); } + + // No readable candidate AND every read returned 403 → user is + // authenticated but lacks the enrichment scope. Surface this + // explicitly so the panel can prompt re-login instead of showing + // an empty/404 state (the older behaviour was silent 404 — caller + // couldn't tell auth-loss from missing-data). + if (forbiddenCount > 0 && forbiddenCount === candidates.length) { + console.warn( + "[gis-parcela-find] all_candidates_forbidden siruta=%s cad=%s candidates=%d", + siruta, + cad, + candidates.length, + ); + return NextResponse.json( + { + error: "scope_insufficient", + hint: + "All candidates returned 403 from gis-api — token likely lacks enrichment_scope. Sign out and back in.", + candidates: candidates.length, + }, + { status: 403 }, + ); + } + + console.log("[gis-parcela-find] no_match siruta=%s cad=%s", siruta, cad); return NextResponse.json({ error: "not_found" }, { status: 404 }); } catch (err) { if (err instanceof GisApiError) { diff --git a/src/modules/geoportal/v2/feature-info-panel.tsx b/src/modules/geoportal/v2/feature-info-panel.tsx index 8ff2967..3e20754 100644 --- a/src/modules/geoportal/v2/feature-info-panel.tsx +++ b/src/modules/geoportal/v2/feature-info-panel.tsx @@ -1,9 +1,10 @@ "use client"; import { useEffect, useMemo, useState } from "react"; +import { signIn } from "next-auth/react"; import { X, RefreshCw, Loader2, FileText, Download, AlertCircle, - Home, Building, MapPin, ChevronDown, ChevronRight, Users, + Home, Building, MapPin, ChevronDown, ChevronRight, Users, LogIn, } from "lucide-react"; import { cn } from "@/shared/lib/utils"; @@ -409,9 +410,25 @@ export function FeatureInfoPanel({ feature, onClose, basic = false }: Props) { )} {error === "forbidden" && ( -
- - Nu ai permisiuni de citire detaliată (scope insuficient). +
+
+ + + Token-ul tău nu poartă scope-ul „enrichment" (gis-api a + răspuns 403 pentru toate candidate-le). Re-loghează-te ca + să primești un access_token cu scope-ul corect. + +
+
)} {error && error !== "forbidden" && (