package creds import ( "encoding/json" "errors" "os" "path/filepath" ) type Credentials struct { DefaultHost string `json:"default_host"` Hosts map[string]HostCreds `json:"hosts"` } type HostCreds struct { Token string `json:"token"` User string `json:"user,omitempty"` DefaultScope string `json:"default_scope,omitempty"` } func filePath() (string, error) { dir, err := os.UserConfigDir() if err != nil { return "", err } return filepath.Join(dir, "ninja", "credentials.json"), nil } func Load() (*Credentials, error) { p, err := filePath() if err != nil { return nil, err } b, err := os.ReadFile(p) if errors.Is(err, os.ErrNotExist) { return &Credentials{Hosts: map[string]HostCreds{}}, nil } if err != nil { return nil, err } c := &Credentials{Hosts: map[string]HostCreds{}} if err := json.Unmarshal(b, c); err != nil { return nil, err } return c, nil } func (c *Credentials) Save() error { p, err := filePath() if err != nil { return err } if err := os.MkdirAll(filepath.Dir(p), 0o700); err != nil { return err } b, err := json.MarshalIndent(c, "", " ") if err != nil { return err } return os.WriteFile(p, b, 0o600) } func (c *Credentials) Resolve(host string) (string, HostCreds, error) { if host == "" { host = c.DefaultHost } if host == "" { host = "https://my.blockninjacms.com" } if t := os.Getenv("NINJA_TOKEN"); t != "" { return host, HostCreds{Token: t}, nil } hc, ok := c.Hosts[host] if !ok || hc.Token == "" { return host, HostCreds{}, errors.New("not logged in; run `ninja login`") } return host, hc, nil }