diff --git a/zooid/api.go b/zooid/api.go index 92cffd9..057069d 100644 --- a/zooid/api.go +++ b/zooid/api.go @@ -13,6 +13,7 @@ import ( "fiatjaf.com/nostr" "github.com/BurntSushi/toml" + "github.com/gosimple/slug" ) // APIHandler handles REST API requests for managing virtual relays @@ -92,14 +93,28 @@ func (api *APIHandler) resolveRelayMembers(id string) ([]string, error) { return members, nil } - instance, err := MakeInstance(api.configName(id)) + config, err := api.loadConfigFromPath(api.configPath(id)) if err != nil { return nil, err } - defer instance.Cleanup() + + events := &EventStore{ + Config: config, + Schema: &Schema{Name: slug.Make(config.Schema)}, + } + + if err := events.Init(); err != nil { + return nil, fmt.Errorf("failed to init event store: %w", err) + } + + management := &ManagementStore{ + Config: config, + Events: events, + } memberSet := make(map[string]struct{}) - for _, pubkey := range instance.Management.GetMembers() { + + for _, pubkey := range management.GetMembers() { memberSet[pubkey.Hex()] = struct{}{} } @@ -346,11 +361,10 @@ func (api *APIHandler) validatePatchedConfig(config *Config) error { if _, err := nostr.SecretKeyFromHex(config.Secret); err != nil { return fmt.Errorf("invalid secret key: %w", err) } - if config.Info.Pubkey == "" { - return fmt.Errorf("info.pubkey is required") - } - if _, err := nostr.PubKeyFromHex(config.Info.Pubkey); err != nil { - return fmt.Errorf("invalid info.pubkey: %w", err) + if config.Info.Pubkey != "" { + if _, err := nostr.PubKeyFromHex(config.Info.Pubkey); err != nil { + return fmt.Errorf("invalid info.pubkey: %w", err) + } } return nil } diff --git a/zooid/api_test.go b/zooid/api_test.go index 2e616c6..6bc66ce 100644 --- a/zooid/api_test.go +++ b/zooid/api_test.go @@ -13,6 +13,7 @@ import ( "testing" "fiatjaf.com/nostr" + "github.com/gosimple/slug" ) func TestAPIHandler_Authentication(t *testing.T) { @@ -676,25 +677,40 @@ func TestAPIHandler_ListRelayMembers(t *testing.T) { t.Run("list members from config fallback", func(t *testing.T) { relaySecret := nostr.Generate() - owner := nostr.Generate().Public() - rolePubkey := nostr.Generate().Public() + member1 := nostr.Generate().Public() + member2 := nostr.Generate().Public() config := &Config{ Host: "members.example.com", Schema: "members_" + RandomString(8), Secret: relaySecret.Hex(), - Roles: map[string]Role{ - "admin": { - Pubkeys: []string{rolePubkey.Hex()}, - }, - }, } - config.Info.Pubkey = owner.Hex() if err := api.saveConfig(api.configPath("fallback"), config); err != nil { t.Fatalf("failed to save config: %v", err) } + // Seed DB with RELAY_MEMBERS to simulate a prior relay load. + seedEvents := &EventStore{ + Config: &Config{secret: relaySecret}, + Schema: &Schema{Name: slug.Make(config.Schema)}, + } + if err := seedEvents.Init(); err != nil { + t.Fatalf("failed to init seed events: %v", err) + } + membersEvent := nostr.Event{ + Kind: RELAY_MEMBERS, + CreatedAt: nostr.Now(), + Tags: nostr.Tags{ + {"-"}, + {"member", member1.Hex()}, + {"member", member2.Hex()}, + }, + } + if err := seedEvents.SignAndStoreEvent(&membersEvent, false); err != nil { + t.Fatalf("failed to seed members event: %v", err) + } + instancesMux.Lock() oldByName := instancesByName oldByHost := instancesByHost @@ -725,9 +741,8 @@ func TestAPIHandler_ListRelayMembers(t *testing.T) { } expected := map[string]struct{}{ - owner.Hex(): {}, - relaySecret.Public().Hex(): {}, - rolePubkey.Hex(): {}, + member1.Hex(): {}, + member2.Hex(): {}, } if len(payload.Members) != len(expected) { diff --git a/zooid/events.go b/zooid/events.go index be9611b..f691c88 100644 --- a/zooid/events.go +++ b/zooid/events.go @@ -364,7 +364,7 @@ func (events *EventStore) SignAndStoreEvent(event *nostr.Event, broadcast bool) return err } - if broadcast { + if broadcast && events.Relay != nil { events.Relay.BroadcastEvent(*event) } diff --git a/zooid/instance_test.go b/zooid/instance_test.go index d3f0f1a..73bd957 100644 --- a/zooid/instance_test.go +++ b/zooid/instance_test.go @@ -27,7 +27,7 @@ func createTestInstance() *Instance { schema := &Schema{Name: "test_" + RandomString(8)} - relay := &khatru.Relay{} + relay := khatru.NewRelay() events := &EventStore{ Relay: relay, diff --git a/zooid/main_test.go b/zooid/main_test.go new file mode 100644 index 0000000..fca0e77 --- /dev/null +++ b/zooid/main_test.go @@ -0,0 +1,20 @@ +package zooid + +import ( + "os" + "testing" +) + +func TestMain(m *testing.M) { + dir, err := os.MkdirTemp("", "zooid-test-*") + if err != nil { + panic(err) + } + + os.Setenv("DATA", dir) + + code := m.Run() + + os.RemoveAll(dir) + os.Exit(code) +} diff --git a/zooid/management_test.go b/zooid/management_test.go index bdad552..21b9e0d 100644 --- a/zooid/management_test.go +++ b/zooid/management_test.go @@ -13,7 +13,7 @@ func createTestManagementStore() *ManagementStore { secret: nostr.Generate(), } schema := &Schema{Name: "test_" + RandomString(8)} - relay := &khatru.Relay{} + relay := khatru.NewRelay() events := &EventStore{ Relay: relay, Config: config,