From 606e0a3329a3534a00889eee19c25e7d432f7d2d Mon Sep 17 00:00:00 2001 From: bndw Date: Sat, 14 Feb 2026 10:11:16 -0800 Subject: refactor: restructure auth config for better UX Changed from flat structure to hierarchical read/write config: Before: auth: enabled: bool required: bool allowed_npubs_read: [] allowed_npubs_write: [] After: auth: read: enabled: bool allowed_npubs: [] write: enabled: bool allowed_npubs: [] Three states per operation: - enabled=false: no auth, allow all - enabled=true, allowed_npubs=[]: auth required, any valid signature - enabled=true, allowed_npubs=[...]: auth required, whitelist only Much clearer semantics and easier to reason about. --- internal/config/config_test.go | 102 +++++++++++++++++++++++++---------------- 1 file changed, 63 insertions(+), 39 deletions(-) (limited to 'internal/config/config_test.go') diff --git a/internal/config/config_test.go b/internal/config/config_test.go index c0d4555..65a742a 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -40,8 +40,10 @@ database: path: "test.db" auth: - enabled: true - required: true + read: + enabled: true + write: + enabled: true timestamp_window: 120 rate_limit: @@ -75,12 +77,12 @@ metrics: t.Errorf("expected db path test.db, got %s", cfg.Database.Path) } - if !cfg.Auth.Enabled { - t.Error("expected auth enabled") + if !cfg.Auth.Read.Enabled { + t.Error("expected auth read enabled") } - if !cfg.Auth.Required { - t.Error("expected auth required") + if !cfg.Auth.Write.Enabled { + t.Error("expected auth write enabled") } if cfg.Auth.TimestampWindow != 120 { @@ -99,11 +101,13 @@ metrics: func TestEnvOverrides(t *testing.T) { // Set environment variables os.Setenv("MUXSTR_SERVER_GRPC_ADDR", ":7777") - os.Setenv("MUXSTR_AUTH_ENABLED", "true") + os.Setenv("MUXSTR_AUTH_READ_ENABLED", "true") + os.Setenv("MUXSTR_AUTH_WRITE_ENABLED", "true") os.Setenv("MUXSTR_RATE_LIMIT_DEFAULT_RPS", "200") defer func() { os.Unsetenv("MUXSTR_SERVER_GRPC_ADDR") - os.Unsetenv("MUXSTR_AUTH_ENABLED") + os.Unsetenv("MUXSTR_AUTH_READ_ENABLED") + os.Unsetenv("MUXSTR_AUTH_WRITE_ENABLED") os.Unsetenv("MUXSTR_RATE_LIMIT_DEFAULT_RPS") }() @@ -118,8 +122,12 @@ func TestEnvOverrides(t *testing.T) { t.Errorf("expected env override :7777, got %s", cfg.Server.GrpcAddr) } - if !cfg.Auth.Enabled { - t.Error("expected auth enabled from env") + if !cfg.Auth.Read.Enabled { + t.Error("expected auth read enabled from env") + } + + if !cfg.Auth.Write.Enabled { + t.Error("expected auth write enabled from env") } if cfg.RateLimit.DefaultRPS != 200 { @@ -206,7 +214,8 @@ func TestSaveAndLoad(t *testing.T) { // Create config cfg := Default() cfg.Server.GrpcAddr = ":9999" - cfg.Auth.Enabled = true + cfg.Auth.Read.Enabled = true + cfg.Auth.Write.Enabled = true cfg.RateLimit.DefaultRPS = 100 // Save to temp file @@ -232,8 +241,12 @@ func TestSaveAndLoad(t *testing.T) { t.Errorf("expected grpc_addr :9999, got %s", loaded.Server.GrpcAddr) } - if !loaded.Auth.Enabled { - t.Error("expected auth enabled") + if !loaded.Auth.Read.Enabled { + t.Error("expected auth read enabled") + } + + if !loaded.Auth.Write.Enabled { + t.Error("expected auth write enabled") } if loaded.RateLimit.DefaultRPS != 100 { @@ -259,12 +272,15 @@ database: path: "test.db" auth: - enabled: true - allowed_npubs_read: - - npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6 - - npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft - allowed_npubs_write: - - npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6 + read: + enabled: true + allowed_npubs: + - npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6 + - npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft + write: + enabled: true + allowed_npubs: + - npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6 ` if _, err := tmpfile.Write([]byte(configData)); err != nil { @@ -278,17 +294,17 @@ auth: } // Verify read npubs were normalized to hex - if len(cfg.Auth.AllowedNpubsRead) != 2 { - t.Errorf("expected 2 allowed npubs for read, got %d", len(cfg.Auth.AllowedNpubsRead)) + if len(cfg.Auth.Read.AllowedNpubs) != 2 { + t.Errorf("expected 2 allowed npubs for read, got %d", len(cfg.Auth.Read.AllowedNpubs)) } // Verify write npubs were normalized to hex - if len(cfg.Auth.AllowedNpubsWrite) != 1 { - t.Errorf("expected 1 allowed npub for write, got %d", len(cfg.Auth.AllowedNpubsWrite)) + if len(cfg.Auth.Write.AllowedNpubs) != 1 { + t.Errorf("expected 1 allowed npub for write, got %d", len(cfg.Auth.Write.AllowedNpubs)) } // Check that they're hex format (64 chars, not npub1...) - for i, pubkey := range cfg.Auth.AllowedNpubsRead { + for i, pubkey := range cfg.Auth.Read.AllowedNpubs { if len(pubkey) != 64 { t.Errorf("read npub %d: expected 64 hex chars, got %d", i, len(pubkey)) } @@ -297,7 +313,7 @@ auth: } } - for i, pubkey := range cfg.Auth.AllowedNpubsWrite { + for i, pubkey := range cfg.Auth.Write.AllowedNpubs { if len(pubkey) != 64 { t.Errorf("write npub %d: expected 64 hex chars, got %d", i, len(pubkey)) } @@ -310,14 +326,14 @@ auth: expectedHex1 := "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d" expectedHex2 := "fa984bd7dbb282f07e16e7ae87b26a2a7b9b90b7246a44771f0cf5ae58018f52" - if cfg.Auth.AllowedNpubsRead[0] != expectedHex1 { - t.Errorf("read npub 0: expected %s, got %s", expectedHex1, cfg.Auth.AllowedNpubsRead[0]) + if cfg.Auth.Read.AllowedNpubs[0] != expectedHex1 { + t.Errorf("read npub 0: expected %s, got %s", expectedHex1, cfg.Auth.Read.AllowedNpubs[0]) } - if cfg.Auth.AllowedNpubsRead[1] != expectedHex2 { - t.Errorf("read npub 1: expected %s, got %s", expectedHex2, cfg.Auth.AllowedNpubsRead[1]) + if cfg.Auth.Read.AllowedNpubs[1] != expectedHex2 { + t.Errorf("read npub 1: expected %s, got %s", expectedHex2, cfg.Auth.Read.AllowedNpubs[1]) } - if cfg.Auth.AllowedNpubsWrite[0] != expectedHex1 { - t.Errorf("write npub 0: expected %s, got %s", expectedHex1, cfg.Auth.AllowedNpubsWrite[0]) + if cfg.Auth.Write.AllowedNpubs[0] != expectedHex1 { + t.Errorf("write npub 0: expected %s, got %s", expectedHex1, cfg.Auth.Write.AllowedNpubs[0]) } } @@ -337,8 +353,10 @@ server: database: path: "test.db" auth: - allowed_npubs_read: - - 3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d + read: + enabled: true + allowed_npubs: + - 3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d `, expectError: true, errorMsg: "must start with 'npub1'", @@ -352,8 +370,10 @@ server: database: path: "test.db" auth: - allowed_npubs_write: - - 3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d + write: + enabled: true + allowed_npubs: + - 3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d `, expectError: true, errorMsg: "must start with 'npub1'", @@ -367,10 +387,14 @@ server: database: path: "test.db" auth: - allowed_npubs_read: - - npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6 - allowed_npubs_write: - - npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft + read: + enabled: true + allowed_npubs: + - npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6 + write: + enabled: true + allowed_npubs: + - npub1l2vyh47mk2p0qlsku7hg0vn29faehy9hy34ygaclpn66ukqp3afqutajft `, expectError: false, }, -- cgit v1.2.3