From 397c9543dd1cf5a140980e18d96fb021e675322a Mon Sep 17 00:00:00 2001 From: Nikita Aksenov Date: Thu, 28 May 2026 19:20:43 +0300 Subject: [PATCH] bugfix: auth removed from /routing/search, /routing/new --- example.env | 2 ++ src/routers/routing.py | 42 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/example.env b/example.env index 5ed6a4e..f04bc6f 100644 --- a/example.env +++ b/example.env @@ -12,6 +12,8 @@ POSTGRES_TEST_DB=cars_test_db DATABASE_HOST_URL="postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432" DATABASE_URL="${DATABASE_HOST_URL}/${POSTGRES_DB}?sslmode=disable" +GEOAPIFY_API_KEY=your_geoapify_key + # Super token for trusted services. Send it as Authorization: Bearer ${API_TOKEN}. #API_TOKEN=change-me diff --git a/src/routers/routing.py b/src/routers/routing.py index 3ced9e1..c982873 100644 --- a/src/routers/routing.py +++ b/src/routers/routing.py @@ -8,7 +8,7 @@ import requests from fastapi import APIRouter, Depends, HTTPException, Query, status -from sqlalchemy import func, or_ +from sqlalchemy import func, or_, text from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.orm import Session @@ -44,6 +44,41 @@ # Сначала зоны грубо сортируются по прямому расстоянию, потом лучшие идут в API. MAX_MATRIX_TARGETS = 200 +PUBLIC_ROUTING_USER_EMAIL = "public-routing@parktrack.local" + + +def _get_public_routing_user_id(db: Session) -> int: + """ + /routing/new теперь публичный, но routes.user_id в БД NOT NULL. + Поэтому сохраняем публичные маршруты на технического пользователя. + """ + result = db.execute( + text( + """ + INSERT INTO users ( + full_name, + email, + hashed_password, + global_role, + is_active + ) + VALUES ( + 'Public Routing User', + :email, + 'disabled-public-routing-user', + CAST('user' AS global_roles), + TRUE + ) + ON CONFLICT (email) + DO UPDATE SET email = EXCLUDED.email + RETURNING user_id + """ + ), + {"email": PUBLIC_ROUTING_USER_EMAIL}, + ) + + return int(result.scalar_one()) + # --------------------------------------------------------------------------- # Внутренние типы @@ -647,7 +682,6 @@ def _selected_candidate_or_422( @router.post("/search", response_model=SearchRoutingResponse) def search_routing( body: SearchRoutingRequest, - current_user: Annotated[User, require("routing.create")], db: Annotated[Session, Depends(get_db)], ): try: @@ -687,7 +721,6 @@ def search_routing( @router.post("/new", status_code=status.HTTP_201_CREATED, response_model=RouteResponse) def create_route( body: CreateRouteRequest, - current_user: Annotated[User, require("routing.create")], db: Annotated[Session, Depends(get_db)], ): if body.selected_zone_id is not None: @@ -730,9 +763,10 @@ def create_route( best = result.candidates[0] now = datetime.now(timezone.utc) + public_user_id = _get_public_routing_user_id(db) route = Route( - user_id=current_user.user_id, + user_id=public_user_id, mode=RouteMode(body.mode), provider=GEOAPIFY_PROVIDER_NAME, origin_latitude=body.origin.latitude,