From 48650d96cf6016a8987fffe7de536d83767a0e9b Mon Sep 17 00:00:00 2001 From: Vladimir Zagainov Date: Tue, 18 Aug 2026 13:57:30 +0300 Subject: [PATCH] fix: address code review findings --- cmd/api/handlers.go | 4 ++-- cmd/api/main.go | 29 +++++++++++++++++++++++++++++ internal/cache/preferences.go | 7 ------- internal/routing/graph.go | 2 -- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/cmd/api/handlers.go b/cmd/api/handlers.go index 88010a9..b75194f 100644 --- a/cmd/api/handlers.go +++ b/cmd/api/handlers.go @@ -1,7 +1,7 @@ package main import ( - "crypto/hmac" + "crypto/subtle" "encoding/json" "fmt" "net/http" @@ -435,7 +435,7 @@ func adminAuth(hc *HandlerContext, w http.ResponseWriter, r *http.Request) bool return false } providedAPIKey := r.Header.Get("X-Admin-Api-Key") - if !hmac.Equal([]byte(providedAPIKey), []byte(expectedAPIKey)) { + if subtle.ConstantTimeCompare([]byte(providedAPIKey), []byte(expectedAPIKey)) != 1 { http.Error(w, "unauthorized", http.StatusUnauthorized) return false } diff --git a/cmd/api/main.go b/cmd/api/main.go index 90f0fee..3fc4d97 100644 --- a/cmd/api/main.go +++ b/cmd/api/main.go @@ -39,6 +39,35 @@ func main() { http.HandleFunc("/internal/admin/stations/", makeHandler(AdminStationStatus, handlerCtx)) http.HandleFunc("/metrics", makeHandler(MetricsHandler, handlerCtx)) + // User preferences routes + http.HandleFunc("/v1/preferences/saved-cities", func(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case http.MethodGet: + GetSavedCities(handlerCtx, w, r) + case http.MethodPost: + AddSavedCity(handlerCtx, w, r) + default: + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + } + }) + http.HandleFunc("/v1/preferences/saved-cities/", func(w http.ResponseWriter, r *http.Request) { + if r.Method == http.MethodDelete { + RemoveSavedCity(handlerCtx, w, r) + } else { + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + } + }) + http.HandleFunc("/v1/preferences/search-history", func(w http.ResponseWriter, r *http.Request) { + switch r.Method { + case http.MethodGet: + GetSearchHistory(handlerCtx, w, r) + case http.MethodPost: + AddSearchHistory(handlerCtx, w, r) + default: + http.Error(w, "method not allowed", http.StatusMethodNotAllowed) + } + }) + log.Println("Trip Planner API starting on :8080") log.Fatal(http.ListenAndServe(":8080", nil)) } diff --git a/internal/cache/preferences.go b/internal/cache/preferences.go index 41de4ec..95d8093 100644 --- a/internal/cache/preferences.go +++ b/internal/cache/preferences.go @@ -6,13 +6,6 @@ import ( "time" ) -// PreferenceKey defines the structure for preference cache keys. -type PreferenceKey struct { - UserID string // user identifier - Kind string // "saved_city" or "search_history" - CityCode string // city code for saved_city -} - // PreferenceSavedCity represents a user's saved city preference. type PreferenceSavedCity struct { CityCode string `json:"city_code"` diff --git a/internal/routing/graph.go b/internal/routing/graph.go index ad80c32..70be1c4 100644 --- a/internal/routing/graph.go +++ b/internal/routing/graph.go @@ -1038,8 +1038,6 @@ func SelectHubStations(stations []StationInfo, minOutgoingFlights int) []*Node { return hubs } -// getStationNeighbors returns neighboring stations for a given station ID in the same city. - // RouteStatus represents the current status of a route leg. type RouteStatus int32