package identity import ( "context" "errors" "os" "testing" "github.com/jackc/pgx/v5/pgxpool" ) const ( localIssuer = "http://localhost:58180/realms/voice-local" ownerSubject = "00000000-0000-0000-0000-000000000101" outsiderSubject = "00000000-0000-0000-0000-000000000103" firstHouseholdID = "10000000-0000-0000-0000-000000000211" secondHouseholdID = "20000000-0000-0000-0000-000000000211" ) func TestRepositoryEnforcesTenantAndRoleBoundaries(t *testing.T) { databaseURL := os.Getenv("TEST_DATABASE_URL") if databaseURL == "" { t.Skip("TEST_DATABASE_URL is not set") } ctx := context.Background() pool, err := pgxpool.New(ctx, databaseURL) if err != nil { t.Fatalf("connect integration database: %v", err) } defer pool.Close() repository := NewRepository(pool) owner := Principal{Issuer: localIssuer, Subject: ownerSubject} currentUser, err := repository.CurrentUser(ctx, owner) if err != nil { t.Fatalf("load owner: %v", err) } if len(currentUser.Accounts) != 1 || len(currentUser.Accounts[0].Memberships) != 1 { t.Fatalf("unexpected owner account: %#v", currentUser) } if currentUser.Accounts[0].Memberships[0].Role != RoleOwner { t.Fatalf("owner role not resolved: %#v", currentUser.Accounts[0].Memberships[0]) } if _, err := repository.RequireHouseholdCapability(ctx, owner, firstHouseholdID, CapabilityHouseholdManage); err != nil { t.Fatalf("owner should manage own household: %v", err) } outsider := Principal{Issuer: localIssuer, Subject: outsiderSubject} if _, err := repository.RequireHouseholdCapability(ctx, outsider, firstHouseholdID, CapabilityHouseholdRead); !errors.Is(err, ErrAccessDenied) { t.Fatalf("cross-tenant access error = %v, want ErrAccessDenied", err) } if _, err := repository.RequireHouseholdCapability(ctx, outsider, secondHouseholdID, CapabilityHouseholdRead); err != nil { t.Fatalf("viewer should read own household: %v", err) } if _, err := repository.RequireHouseholdCapability(ctx, outsider, secondHouseholdID, CapabilityHouseholdManage); !errors.Is(err, ErrAccessDenied) { t.Fatalf("viewer manage error = %v, want ErrAccessDenied", err) } if _, err := repository.RequireHouseholdCapability(ctx, owner, firstHouseholdID, CapabilityRecordingPlay); !errors.Is(err, ErrAccessDenied) { t.Fatalf("owner recording access error = %v, want ErrAccessDenied", err) } }