Files
nilesh.pandClaude Opus 4.8 4d3eb18a6c Initial commit: TravelHub multi-tenant flight booking platform
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>
2026-09-13 11:38:01 +05:30

40 lines
1.3 KiB
Go

// Package repository holds every SQL statement in the service.
//
// Tenant isolation convention: any query touching a tenant-owned table
// (users, flights, bookings, passengers) takes tenantID as its FIRST argument
// and filters on it in the WHERE clause. Callers pass the id from the
// authenticated identity, never from client input.
package repository
import (
"errors"
"github.com/jackc/pgx/v5/pgconn"
"github.com/jackc/pgx/v5/pgxpool"
)
// ErrNotFound is returned when a lookup matches no row within the tenant.
// Handlers map it to 404, which also means a caller probing for another
// tenant's record sees a plain "not found" rather than a permission error.
var ErrNotFound = errors.New("not found")
// ErrNoSeats is returned when a booking asks for more seats than remain.
var ErrNoSeats = errors.New("not enough seats available")
// Repository is the data access layer over a pgx pool.
type Repository struct {
pool *pgxpool.Pool
}
// New builds a Repository around an open pool.
func New(pool *pgxpool.Pool) *Repository {
return &Repository{pool: pool}
}
// isUniqueViolation reports whether err is PostgreSQL's 23505, which lets
// callers retry a generated value instead of failing the request.
func isUniqueViolation(err error) bool {
var pgErr *pgconn.PgError
return errors.As(err, &pgErr) && pgErr.Code == "23505"
}