Skip to content

Commit 9df291f

Browse files
committed
fix
1 parent 324e821 commit 9df291f

File tree

1 file changed

+44
-4
lines changed

1 file changed

+44
-4
lines changed

apps/geoapi/src/geoapi/routers/processes.py

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from fastapi.responses import JSONResponse
2323

2424
from geoapi.config import settings
25-
from geoapi.deps.auth import get_user_id, oauth2_scheme
25+
from geoapi.deps.auth import get_optional_user_id, get_user_id, oauth2_scheme
2626
from geoapi.models.processes import (
2727
OGC_EXCEPTION_NO_SUCH_JOB,
2828
OGC_EXCEPTION_NO_SUCH_PROCESS,
@@ -51,6 +51,35 @@
5151

5252
router = APIRouter(tags=["Processes"])
5353

54+
# Processes that can be executed without authentication (read-only analytics)
55+
# These are sync processes that only query data and don't modify anything
56+
PUBLIC_ALLOWED_PROCESSES = frozenset(
57+
{
58+
"feature-count",
59+
"unique-values",
60+
"class-breaks",
61+
"area-statistics",
62+
"extent",
63+
"aggregation-stats",
64+
"histogram",
65+
}
66+
)
67+
68+
69+
def is_public_allowed_process(process_id: str) -> bool:
70+
"""Check if a process can be executed without authentication.
71+
72+
Only read-only sync analytics processes are allowed for public access.
73+
These processes only query data and don't create jobs or modify state.
74+
75+
Args:
76+
process_id: The process identifier
77+
78+
Returns:
79+
True if the process can be executed publicly, False otherwise
80+
"""
81+
return process_id in PUBLIC_ALLOWED_PROCESSES
82+
5483

5584
def _execute_analytics_sync(process_id: str, inputs: dict[str, Any]) -> dict[str, Any]:
5685
"""Execute an analytics process synchronously.
@@ -343,25 +372,36 @@ async def execute_process(
343372
request: Request,
344373
process_id: str,
345374
execute_request: ExecuteRequest,
346-
user_id: UUID = Depends(get_user_id),
375+
user_id: UUID | None = Depends(get_optional_user_id),
347376
access_token: str | None = Depends(oauth2_scheme),
348377
) -> JSONResponse:
349378
"""Execute a process.
350379
351380
For analytics processes (feature-count, class-breaks, unique-values, area-statistics):
352381
Returns results immediately (HTTP 200).
382+
These can be executed without authentication (public access).
353383
354384
For async tool processes (buffer, clip, etc.):
355385
Creates a job and returns status info with job ID (HTTP 201).
386+
These REQUIRE authentication.
356387
Results can be retrieved via /jobs/{jobId}/results.
357388
"""
358389
base_url = get_base_url(request)
359390

360-
# Check if this is an analytics process (sync execution)
361-
if analytics_registry.is_analytics_process(process_id):
391+
# Check if this is a public-allowed analytics process (sync execution)
392+
if is_public_allowed_process(process_id):
393+
# Analytics processes are read-only and don't need authentication
362394
result = _execute_analytics_sync(process_id, execute_request.inputs)
363395
return JSONResponse(status_code=200, content=result)
364396

397+
# For all other processes, authentication is required
398+
if not user_id:
399+
raise HTTPException(
400+
status_code=status.HTTP_401_UNAUTHORIZED,
401+
detail="Authentication required for this process",
402+
headers={"WWW-Authenticate": "Bearer"},
403+
)
404+
365405
# For async processes, verify tool exists
366406
tool_info = tool_registry.get_tool(process_id)
367407
if not tool_info:

0 commit comments

Comments
 (0)