From e9260f40f1f6b08efd8549afc8bab2180f28e5ad Mon Sep 17 00:00:00 2001 From: Jon Staab Date: Tue, 26 May 2026 15:50:14 -0700 Subject: [PATCH] Clean up config file name stuff --- cmd/export/main.go | 5 +++-- cmd/import/main.go | 5 +++-- zooid/api.go | 51 +++++++++++++++++++++++----------------------- zooid/blossom.go | 16 +++++++-------- zooid/config.go | 42 +++++++++++++++++++------------------- zooid/instance.go | 7 ++++--- zooid/util.go | 2 +- 7 files changed, 65 insertions(+), 63 deletions(-) diff --git a/cmd/export/main.go b/cmd/export/main.go index 984678e..5ebba41 100644 --- a/cmd/export/main.go +++ b/cmd/export/main.go @@ -25,8 +25,9 @@ func main() { os.Exit(1) } - // Load config for the specified relay - config, err := zooid.LoadConfigFromId(*relay) + name := zooid.ConfigNameFromId(*relay) + path := zooid.ConfigPathFromName(name) + config, err := zooid.LoadConfigFromPath(path) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) diff --git a/cmd/import/main.go b/cmd/import/main.go index cb37f19..cb03480 100644 --- a/cmd/import/main.go +++ b/cmd/import/main.go @@ -39,8 +39,9 @@ func main() { os.Exit(1) } - // Load config for the specified relay - config, err := zooid.LoadConfigFromId(*relay) + name := zooid.ConfigNameFromId(*relay) + path := zooid.ConfigPathFromName(name) + config, err := zooid.LoadConfigFromPath(path) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) diff --git a/zooid/api.go b/zooid/api.go index c191169..56d49ea 100644 --- a/zooid/api.go +++ b/zooid/api.go @@ -28,7 +28,7 @@ func NewAPIHandler() *APIHandler { whitelist: whitelist, } - mux := http.NewServeMux() + mux := http.NewServeMux() mux.HandleFunc("POST /relay/{id}", api.auth(api.createRelay)) mux.HandleFunc("PUT /relay/{id}", api.auth(api.putRelay)) mux.HandleFunc("PATCH /relay/{id}", api.auth(api.patchRelay)) @@ -37,7 +37,7 @@ func NewAPIHandler() *APIHandler { api.mux = mux - return api + return api } func (api *APIHandler) auth(next http.HandlerFunc) http.HandlerFunc { @@ -72,7 +72,7 @@ func writeJSON(w http.ResponseWriter, status int, v any) { // Relay CRUD -func (api *APIHandler) configFromRequest(r *http.Request) (*Config, error) { +func (api *APIHandler) configFromRequest(path string, r *http.Request) (*Config, error) { r.Body = http.MaxBytesReader(nil, r.Body, 1024*1024) defer r.Body.Close() @@ -81,16 +81,7 @@ func (api *APIHandler) configFromRequest(r *http.Request) (*Config, error) { return nil, fmt.Errorf("failed to read body: %w", err) } - var config Config - if err := json.Unmarshal(body, &config); err != nil { - return nil, fmt.Errorf("invalid json config: %w", err) - } - - if err := config.Validate(); err != nil { - return nil, err - } - - return &config, nil + return LoadConfigFromJson(path, body) } func (api *APIHandler) patchFromRequest(r *http.Request) (map[string]interface{}, error) { @@ -121,7 +112,9 @@ func (api *APIHandler) checkDuplicateSchemaOrHost(config *Config, excludeFilenam continue } - if existing, err := LoadConfigFromName(entry.Name()); err == nil { + path := ConfigPathFromName(entry.Name()) + + if existing, err := LoadConfigFromPath(path); err == nil { if existing.Schema == config.Schema { return fmt.Errorf("schema %q is already in use", config.Schema) } @@ -137,13 +130,14 @@ func (api *APIHandler) checkDuplicateSchemaOrHost(config *Config, excludeFilenam // Create relay func (api *APIHandler) createRelay(w http.ResponseWriter, r *http.Request) { - path := ConfigPathFromId(r.PathValue("id")) + name := ConfigNameFromId(r.PathValue("id")) + path := ConfigPathFromName(name) if _, err := os.Stat(path); err == nil { writeError(w, http.StatusConflict, "relay with this id already exists") return } - config, err := api.configFromRequest(r) + config, err := api.configFromRequest(path, r) if err != nil { writeError(w, http.StatusBadRequest, err.Error()) return @@ -166,19 +160,20 @@ func (api *APIHandler) createRelay(w http.ResponseWriter, r *http.Request) { func (api *APIHandler) putRelay(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") - path := ConfigPathFromId(id) + name := ConfigNameFromId(id) + path := ConfigPathFromName(name) if _, err := os.Stat(path); err != nil { writeError(w, http.StatusConflict, "relay not found") return } - config, err := api.configFromRequest(r) + config, err := api.configFromRequest(path, r) if err != nil { writeError(w, http.StatusBadRequest, err.Error()) return } - if err := api.checkDuplicateSchemaOrHost(config, id+".toml"); err != nil { + if err := api.checkDuplicateSchemaOrHost(config, name); err != nil { writeError(w, http.StatusConflict, err.Error()) return } @@ -195,7 +190,8 @@ func (api *APIHandler) putRelay(w http.ResponseWriter, r *http.Request) { func (api *APIHandler) patchRelay(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") - path := ConfigPathFromId(id) + name := ConfigNameFromId(id) + path := ConfigPathFromName(name) if _, err := os.Stat(path); err != nil { writeError(w, http.StatusConflict, "relay not found") return @@ -223,7 +219,7 @@ func (api *APIHandler) patchRelay(w http.ResponseWriter, r *http.Request) { return } - if err := api.checkDuplicateSchemaOrHost(config, id+".toml"); err != nil { + if err := api.checkDuplicateSchemaOrHost(config, name); err != nil { writeError(w, http.StatusConflict, err.Error()) return } @@ -285,7 +281,8 @@ func deepMerge(base, patch map[string]interface{}) map[string]interface{} { func (api *APIHandler) deleteRelay(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") - path := ConfigPathFromId(id) + name := ConfigNameFromId(id) + path := ConfigPathFromName(name) if _, err := os.Stat(path); err != nil { writeError(w, http.StatusConflict, "relay not found") return @@ -303,7 +300,8 @@ func (api *APIHandler) deleteRelay(w http.ResponseWriter, r *http.Request) { func (api *APIHandler) listRelayMembers(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") - members, err := api.resolveRelayMembers(id) + name := ConfigNameFromId(id) + members, err := api.resolveRelayMembers(name) if err != nil { if os.IsNotExist(err) { writeError(w, http.StatusNotFound, "relay not found") @@ -316,16 +314,17 @@ func (api *APIHandler) listRelayMembers(w http.ResponseWriter, r *http.Request) writeJSON(w, http.StatusOK, map[string][]string{"members": members}) } -func (api *APIHandler) resolveRelayMembers(id string) ([]string, error) { +func (api *APIHandler) resolveRelayMembers(name string) ([]string, error) { instancesMux.RLock() - instance, exists := instancesByName[id+".toml"] + instance, exists := instancesByName[name] instancesMux.RUnlock() if exists { return collectMembers(instance.Management), nil } - config, err := LoadConfigFromId(id) + path := ConfigPathFromName(name) + config, err := LoadConfigFromPath(path) if err != nil { return nil, err } diff --git a/zooid/blossom.go b/zooid/blossom.go index 959f578..6c3d8ff 100644 --- a/zooid/blossom.go +++ b/zooid/blossom.go @@ -3,8 +3,8 @@ package zooid import ( "bytes" "context" - "io" "fmt" + "io" "log" "net/url" "path/filepath" @@ -34,11 +34,11 @@ func (bl *BlossomStore) Enable(instance *Instance) { switch bl.Config.Blossom.Adapter { case "local": if err := bl.UseLocalAdapter(backend); err != nil { - log.Fatalf("blossom: failed to use local adapter %q", err) + log.Fatalf("blossom: failed to use local adapter %q", err) } case "s3": if err := bl.UseS3Adapter(backend); err != nil { - log.Fatalf("blossom: failed to use s3 adapter %q", err) + log.Fatalf("blossom: failed to use s3 adapter %q", err) } default: log.Fatalf("blossom: unknown backend %q", bl.Config.Blossom.Adapter) @@ -128,13 +128,13 @@ func (bl *BlossomStore) UseLocalAdapter(backend *blossom.BlossomServer) error { // S3 adapter func (bl *BlossomStore) S3Key(sha256 string) string { - key := bl.Config.Schema + "/" + sha256 + key := bl.Config.Schema + "/" + sha256 - if bl.Config.Blossom.S3.KeyPrefix != "" { - key = bl.Config.Blossom.S3.KeyPrefix + "/" + key - } + if bl.Config.Blossom.S3.KeyPrefix != "" { + key = bl.Config.Blossom.S3.KeyPrefix + "/" + key + } - return key + return key } func (bl *BlossomStore) UseS3Adapter(backend *blossom.BlossomServer) error { diff --git a/zooid/config.go b/zooid/config.go index 25f855f..9c2f0a8 100644 --- a/zooid/config.go +++ b/zooid/config.go @@ -1,12 +1,13 @@ package zooid import ( + "encoding/json" "fiatjaf.com/nostr" "fmt" - "regexp" "github.com/BurntSushi/toml" "os" "path/filepath" + "regexp" "slices" ) @@ -60,7 +61,7 @@ type Config struct { Roles map[string]Role `toml:"roles" json:"roles"` - // Private/parsed values + // Parsed values path string secret nostr.SecretKey } @@ -76,22 +77,14 @@ type BlossomS3Settings struct { KeyPrefix string `toml:"key_prefix" json:"key_prefix"` } -func ConfigPathFromId(id string) string { - return filepath.Join(Env("CONFIG"), id+".toml") +func ConfigNameFromId(id string) string { + return id + ".toml" } func ConfigPathFromName(name string) string { return filepath.Join(Env("CONFIG"), name) } -func LoadConfigFromId(id string) (*Config, error) { - return LoadConfigFromPath(ConfigPathFromId(id)) -} - -func LoadConfigFromName(name string) (*Config, error) { - return LoadConfigFromPath(ConfigPathFromName(name)) -} - func LoadConfigFromPath(path string) (*Config, error) { var config Config if _, err := toml.DecodeFile(path, &config); err != nil { @@ -107,6 +100,21 @@ func LoadConfigFromPath(path string) (*Config, error) { return &config, nil } +func LoadConfigFromJson(path string, body []byte) (*Config, error) { + var config Config + if err := json.Unmarshal(body, &config); err != nil { + return nil, fmt.Errorf("invalid json config: %w", err) + } + + config.path = path + + if err := config.Validate(); err != nil { + return nil, err + } + + return &config, nil +} + func (config *Config) Validate() error { if config.Blossom.Adapter == "" { config.Blossom.Adapter = "local" @@ -124,14 +132,12 @@ func (config *Config) Validate() error { return fmt.Errorf("schema must contain only lowercase letters, numbers, and underscores") } - secret, err := nostr.SecretKeyFromHex(config.Secret) + secret, err := nostr.SecretKeyFromHex(config.Secret) if err != nil { return fmt.Errorf("invalid secret key: %w", err) } - // Make the secret... secret - config.Secret = "" config.secret = secret if _, err := nostr.PubKeyFromHex(config.Info.Pubkey); err != nil { @@ -159,9 +165,6 @@ func (config *Config) Validate() error { } func (config *Config) Save() error { - // Restore the secret key to the public field for saving - config.Secret = config.secret.Hex() - file, err := os.Create(config.path) if err != nil { return fmt.Errorf("Failed to open config file %s: %w", config.path, err) @@ -173,9 +176,6 @@ func (config *Config) Save() error { return fmt.Errorf("Failed to encode config file %s: %w", config.path, err) } - // Clear the secret again - config.Secret = "" - return nil } diff --git a/zooid/instance.go b/zooid/instance.go index 16ca29f..fa224ea 100644 --- a/zooid/instance.go +++ b/zooid/instance.go @@ -21,13 +21,14 @@ type Instance struct { Push *PushManager } -func MakeInstance(filename string) (*Instance, error) { - config, err := LoadConfigFromName(filename) +func MakeInstance(name string) (*Instance, error) { + path := ConfigPathFromName(name) + config, err := LoadConfigFromPath(path) if err != nil { return nil, err } - return makeInstance(config, filename) + return makeInstance(config, name) } func makeInstance(config *Config, source string) (*Instance, error) { diff --git a/zooid/util.go b/zooid/util.go index 57454b2..191afd2 100644 --- a/zooid/util.go +++ b/zooid/util.go @@ -183,7 +183,7 @@ func validateNIP98Auth(r *http.Request) (nostr.PubKey, error) { return nostr.PubKey{}, fmt.Errorf("invalid event signature") } - scheme := "http" + scheme := "http" if r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https" { scheme = scheme + "s" }