1package daemon23import (4 "context"5 "errors"6 "net/http/httptest"7 "strings"8 "testing"910 "github.com/FelineStateMachine/tinyrelay/internal/catalog"11 "github.com/FelineStateMachine/tinyrelay/internal/sites"12)1314func TestTenantScopedSiteHostIsolation(t *testing.T) {15 ctx := context.Background()16 app, err := New(ctx, Config{DataDir: t.TempDir(), DefaultTenant: "alice", PublicURL: "https://relay.test"})17 if err != nil {18 t.Fatal(err)19 }20 defer app.Close(ctx)21 owner := strings.Repeat("a", 64)22 alice, err := app.Create(ctx, CreateOptions{Name: "alice", Owner: owner, Template: "default"})23 if err != nil {24 t.Fatal(err)25 }26 if _, err := app.Create(ctx, CreateOptions{Name: "bob", Owner: owner, Template: "default"}); err != nil {27 t.Fatal(err)28 }29 key := strings.Repeat("b", 64)30 label, err := sites.Base36(key)31 if err != nil {32 t.Fatal(err)33 }34 label += "docs"35 for _, tc := range []struct{ host, want string }{{label + ".alice.relay.test", alice.Name}, {label + ".bob.relay.test", "bob"}} {36 r := httptest.NewRequest("GET", "https://"+tc.host+"/", nil)37 meta, gotLabel, found, err := app.resolveHostedSite(r)38 if err != nil || !found {39 t.Fatalf("%s: found=%v err=%v", tc.host, found, err)40 }41 if meta.Name != tc.want || gotLabel != label {42 t.Fatalf("%s: meta=%s label=%s", tc.host, meta.Name, gotLabel)43 }44 }45}4647func TestCustomSiteHostMapsOnlyConfiguredTenant(t *testing.T) {48 ctx := context.Background()49 app, err := New(ctx, Config{DataDir: t.TempDir(), DefaultTenant: "alice", PublicURL: "https://relay.test"})50 if err != nil {51 t.Fatal(err)52 }53 defer app.Close(ctx)54 owner := strings.Repeat("a", 64)55 meta, err := app.Create(ctx, CreateOptions{Name: "alice", Owner: owner, Template: "default"})56 if err != nil {57 t.Fatal(err)58 }59 key := strings.Repeat("c", 64)60 label, _ := sites.Base36(key)61 label += "x"62 if _, err := app.Catalog().AddHost(ctx, meta.ID, "sites.example.test", label); err != nil {63 t.Fatal(err)64 }65 r := httptest.NewRequest("GET", "https://sites.example.test/", nil)66 got, gotLabel, found, err := app.resolveHostedSite(r)67 if err != nil || !found {68 t.Fatalf("custom host: found=%v err=%v", found, err)69 }70 if got.ID != meta.ID || gotLabel != label {71 t.Fatalf("custom host mapped to %s/%s", got.ID, gotLabel)72 }73}7475func TestUnknownSiteHostNeverFallsBackToDefaultRelay(t *testing.T) {76 ctx := context.Background()77 app, err := New(ctx, Config{DataDir: t.TempDir(), DefaultTenant: "alice", PublicURL: "https://relay.test"})78 if err != nil {79 t.Fatal(err)80 }81 defer app.Close(ctx)82 owner := strings.Repeat("a", 64)83 if _, err := app.Create(ctx, CreateOptions{Name: "alice", Owner: owner, Template: "default"}); err != nil {84 t.Fatal(err)85 }86 key := strings.Repeat("d", 64)87 label, err := sites.Base36(key)88 if err != nil {89 t.Fatal(err)90 }91 label += "missing"92 r := httptest.NewRequest("GET", "https://"+label+".unknown.relay.test/", nil)93 _, _, found, err := app.resolveHostedSite(r)94 if !found || !errors.Is(err, catalog.ErrNotFound) {95 t.Fatalf("unknown tenant: found=%v err=%v", found, err)96 }97}