diff options
| author | bndw <ben@bdw.to> | 2026-02-14 10:11:16 -0800 |
|---|---|---|
| committer | bndw <ben@bdw.to> | 2026-02-14 10:11:16 -0800 |
| commit | 606e0a3329a3534a00889eee19c25e7d432f7d2d (patch) | |
| tree | 526b1419eaa6b9b91126adbfa5990ec47f5d3a07 /internal/config/config.go | |
| parent | a90009e6b887a8a7ca67f49566af2caffb807776 (diff) | |
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.
Diffstat (limited to 'internal/config/config.go')
| -rw-r--r-- | internal/config/config.go | 57 |
1 files changed, 35 insertions, 22 deletions
diff --git a/internal/config/config.go b/internal/config/config.go index 3e52272..294510d 100644 --- a/internal/config/config.go +++ b/internal/config/config.go | |||
| @@ -39,12 +39,19 @@ type DatabaseConfig struct { | |||
| 39 | 39 | ||
| 40 | // AuthConfig holds authentication configuration. | 40 | // AuthConfig holds authentication configuration. |
| 41 | type AuthConfig struct { | 41 | type AuthConfig struct { |
| 42 | Enabled bool `yaml:"enabled"` | 42 | Read AuthOperationConfig `yaml:"read"` |
| 43 | Required bool `yaml:"required"` | 43 | Write AuthOperationConfig `yaml:"write"` |
| 44 | TimestampWindow int64 `yaml:"timestamp_window"` | 44 | TimestampWindow int64 `yaml:"timestamp_window"` |
| 45 | AllowedNpubsRead []string `yaml:"allowed_npubs_read"` // npub format only (bech32) - normalized to hex internally | 45 | SkipMethods []string `yaml:"skip_methods"` |
| 46 | AllowedNpubsWrite []string `yaml:"allowed_npubs_write"` // npub format only (bech32) - normalized to hex internally | 46 | } |
| 47 | SkipMethods []string `yaml:"skip_methods"` | 47 | |
| 48 | // AuthOperationConfig configures auth for a specific operation type (read or write). | ||
| 49 | type AuthOperationConfig struct { | ||
| 50 | Enabled bool `yaml:"enabled"` // false = no auth required, true = auth required | ||
| 51 | AllowedNpubs []string `yaml:"allowed_npubs"` // npub format only - normalized to hex internally | ||
| 52 | // If enabled=false: no auth, allow all | ||
| 53 | // If enabled=true && allowed_npubs=[]: auth required, any valid signature accepted | ||
| 54 | // If enabled=true && allowed_npubs=[...]: auth required, only whitelisted npubs | ||
| 48 | } | 55 | } |
| 49 | 56 | ||
| 50 | // RateLimitConfig holds rate limiting configuration. | 57 | // RateLimitConfig holds rate limiting configuration. |
| @@ -111,8 +118,14 @@ func Default() *Config { | |||
| 111 | Path: "relay.db", | 118 | Path: "relay.db", |
| 112 | }, | 119 | }, |
| 113 | Auth: AuthConfig{ | 120 | Auth: AuthConfig{ |
| 114 | Enabled: false, | 121 | Read: AuthOperationConfig{ |
| 115 | Required: false, | 122 | Enabled: false, |
| 123 | AllowedNpubs: nil, | ||
| 124 | }, | ||
| 125 | Write: AuthOperationConfig{ | ||
| 126 | Enabled: false, | ||
| 127 | AllowedNpubs: nil, | ||
| 128 | }, | ||
| 116 | TimestampWindow: 60, | 129 | TimestampWindow: 60, |
| 117 | }, | 130 | }, |
| 118 | RateLimit: RateLimitConfig{ | 131 | RateLimit: RateLimitConfig{ |
| @@ -184,15 +197,15 @@ func normalizeNpubs(cfg *Config) error { | |||
| 184 | var err error | 197 | var err error |
| 185 | 198 | ||
| 186 | // Normalize read allowlist | 199 | // Normalize read allowlist |
| 187 | cfg.Auth.AllowedNpubsRead, err = normalizeNpubList(cfg.Auth.AllowedNpubsRead) | 200 | cfg.Auth.Read.AllowedNpubs, err = normalizeNpubList(cfg.Auth.Read.AllowedNpubs) |
| 188 | if err != nil { | 201 | if err != nil { |
| 189 | return fmt.Errorf("allowed_npubs_read: %w", err) | 202 | return fmt.Errorf("auth.read.allowed_npubs: %w", err) |
| 190 | } | 203 | } |
| 191 | 204 | ||
| 192 | // Normalize write allowlist | 205 | // Normalize write allowlist |
| 193 | cfg.Auth.AllowedNpubsWrite, err = normalizeNpubList(cfg.Auth.AllowedNpubsWrite) | 206 | cfg.Auth.Write.AllowedNpubs, err = normalizeNpubList(cfg.Auth.Write.AllowedNpubs) |
| 194 | if err != nil { | 207 | if err != nil { |
| 195 | return fmt.Errorf("allowed_npubs_write: %w", err) | 208 | return fmt.Errorf("auth.write.allowed_npubs: %w", err) |
| 196 | } | 209 | } |
| 197 | 210 | ||
| 198 | return nil | 211 | return nil |
| @@ -299,11 +312,17 @@ func applyEnvOverrides(cfg *Config) { | |||
| 299 | } | 312 | } |
| 300 | 313 | ||
| 301 | // Auth | 314 | // Auth |
| 302 | if val := os.Getenv("MUXSTR_AUTH_ENABLED"); val != "" { | 315 | if val := os.Getenv("MUXSTR_AUTH_READ_ENABLED"); val != "" { |
| 303 | cfg.Auth.Enabled = parseBool(val) | 316 | cfg.Auth.Read.Enabled = parseBool(val) |
| 317 | } | ||
| 318 | if val := os.Getenv("MUXSTR_AUTH_READ_ALLOWED_NPUBS"); val != "" { | ||
| 319 | cfg.Auth.Read.AllowedNpubs = strings.Split(val, ",") | ||
| 304 | } | 320 | } |
| 305 | if val := os.Getenv("MUXSTR_AUTH_REQUIRED"); val != "" { | 321 | if val := os.Getenv("MUXSTR_AUTH_WRITE_ENABLED"); val != "" { |
| 306 | cfg.Auth.Required = parseBool(val) | 322 | cfg.Auth.Write.Enabled = parseBool(val) |
| 323 | } | ||
| 324 | if val := os.Getenv("MUXSTR_AUTH_WRITE_ALLOWED_NPUBS"); val != "" { | ||
| 325 | cfg.Auth.Write.AllowedNpubs = strings.Split(val, ",") | ||
| 307 | } | 326 | } |
| 308 | if val := os.Getenv("MUXSTR_AUTH_TIMESTAMP_WINDOW"); val != "" { | 327 | if val := os.Getenv("MUXSTR_AUTH_TIMESTAMP_WINDOW"); val != "" { |
| 309 | var n int64 | 328 | var n int64 |
| @@ -311,12 +330,6 @@ func applyEnvOverrides(cfg *Config) { | |||
| 311 | cfg.Auth.TimestampWindow = n | 330 | cfg.Auth.TimestampWindow = n |
| 312 | } | 331 | } |
| 313 | } | 332 | } |
| 314 | if val := os.Getenv("MUXSTR_AUTH_ALLOWED_NPUBS_READ"); val != "" { | ||
| 315 | cfg.Auth.AllowedNpubsRead = strings.Split(val, ",") | ||
| 316 | } | ||
| 317 | if val := os.Getenv("MUXSTR_AUTH_ALLOWED_NPUBS_WRITE"); val != "" { | ||
| 318 | cfg.Auth.AllowedNpubsWrite = strings.Split(val, ",") | ||
| 319 | } | ||
| 320 | 333 | ||
| 321 | // Rate limit | 334 | // Rate limit |
| 322 | if val := os.Getenv("MUXSTR_RATE_LIMIT_ENABLED"); val != "" { | 335 | if val := os.Getenv("MUXSTR_RATE_LIMIT_ENABLED"); val != "" { |
