Angular + Go + PostgreSQL sample with strict per-tenant isolation. - Backend: Go API (basic auth, tenant-scoped repository layer, pgx pool) - Frontend: Angular 22 SPA (search, checkout, bookings, dashboard) - Database: schema, seed data and demo bookings migrations - Tests: 311 across Go (integration), Angular (unit) and Playwright (e2e), plus a generated evidence report with PDF export - Security: whitebox VAPT report under security/ Secrets (.env, tokens, DB credentials) are git-ignored. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
56 lines
1.9 KiB
Go
56 lines
1.9 KiB
Go
// Package httpapi assembles the HTTP handler tree.
|
|
//
|
|
// It lives outside package main so tests can drive the exact same routing,
|
|
// middleware order and auth rules the server runs in production, rather than a
|
|
// hand-rolled approximation of them.
|
|
package httpapi
|
|
|
|
import (
|
|
"log/slog"
|
|
"net/http"
|
|
|
|
"github.com/travelswitch/travelhub/backend/internal/handlers"
|
|
"github.com/travelswitch/travelhub/backend/internal/middleware"
|
|
"github.com/travelswitch/travelhub/backend/internal/repository"
|
|
)
|
|
|
|
// New builds the full handler.
|
|
//
|
|
// Everything under /api/ requires Basic auth plus a tenant, except the two
|
|
// endpoints registered explicitly on the root mux: health, and the tenant list
|
|
// the sign-in screen needs before any credentials exist. More specific
|
|
// patterns win in Go's mux, so those two bypass the authenticated subtree.
|
|
func New(
|
|
h *handlers.Handler,
|
|
repo *repository.Repository,
|
|
logger *slog.Logger,
|
|
corsOrigins []string,
|
|
) http.Handler {
|
|
protected := http.NewServeMux()
|
|
|
|
protected.HandleFunc("GET /api/session", h.Session)
|
|
|
|
protected.HandleFunc("GET /api/flights", h.SearchFlights)
|
|
protected.HandleFunc("GET /api/flights/{id}", h.GetFlight)
|
|
protected.HandleFunc("GET /api/airports", h.ListAirports)
|
|
protected.HandleFunc("GET /api/airlines", h.ListAirlines)
|
|
|
|
protected.HandleFunc("GET /api/bookings", h.ListBookings)
|
|
protected.HandleFunc("POST /api/bookings", h.CreateBooking)
|
|
protected.HandleFunc("GET /api/bookings/{id}", h.GetBooking)
|
|
protected.HandleFunc("POST /api/bookings/{id}/cancel", h.CancelBooking)
|
|
|
|
protected.HandleFunc("GET /api/dashboard", h.Dashboard)
|
|
|
|
root := http.NewServeMux()
|
|
root.HandleFunc("GET /api/health", h.Health)
|
|
root.HandleFunc("GET /api/tenants", h.ListTenants)
|
|
root.Handle("/api/", middleware.BasicAuth(repo, logger)(protected))
|
|
|
|
return middleware.Chain(root,
|
|
middleware.Recoverer(logger),
|
|
middleware.Logger(logger),
|
|
middleware.CORS(corsOrigins),
|
|
)
|
|
}
|