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>
48 lines
1.4 KiB
Go
48 lines
1.4 KiB
Go
// Package auth carries the authenticated caller through the request context.
|
|
//
|
|
// Every tenant-scoped query in this service takes its tenant id from the
|
|
// Identity stored here, never from anything the client can name directly in a
|
|
// query string or body. That is the single rule that keeps tenants isolated.
|
|
package auth
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"github.com/travelswitch/travelhub/backend/internal/models"
|
|
)
|
|
|
|
// Identity is the authenticated user together with the tenant they signed into.
|
|
type Identity struct {
|
|
User models.User
|
|
Tenant models.Tenant
|
|
}
|
|
|
|
// contextKey is unexported so no other package can collide with our key.
|
|
type contextKey struct{}
|
|
|
|
var identityKey contextKey
|
|
|
|
// ErrNoIdentity means the handler ran without authentication middleware in
|
|
// front of it, which is a programming error rather than a client error.
|
|
var ErrNoIdentity = errors.New("no identity in request context")
|
|
|
|
// WithIdentity returns a context carrying the identity.
|
|
func WithIdentity(ctx context.Context, id Identity) context.Context {
|
|
return context.WithValue(ctx, identityKey, id)
|
|
}
|
|
|
|
// FromContext retrieves the identity placed by the auth middleware.
|
|
func FromContext(ctx context.Context) (Identity, error) {
|
|
id, ok := ctx.Value(identityKey).(Identity)
|
|
if !ok {
|
|
return Identity{}, ErrNoIdentity
|
|
}
|
|
return id, nil
|
|
}
|
|
|
|
// IsAdmin reports whether the caller holds the tenant admin role.
|
|
func (i Identity) IsAdmin() bool {
|
|
return i.User.Role == "admin"
|
|
}
|