mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
* Config: Rename DecryptConfigFile to DecryptConfigData Because this isn't really a file, it's a byte slice * Config: Rename EncryptConfigFile to EncryptConfigData Because it's not actually a file * Config: Fix config version downgrade Fixes #1769
165 lines
4.1 KiB
Go
165 lines
4.1 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"slices"
|
|
"strings"
|
|
|
|
"github.com/buger/jsonparser"
|
|
"github.com/thrasher-corp/gocryptotrader/common/file"
|
|
"github.com/thrasher-corp/gocryptotrader/config"
|
|
"github.com/thrasher-corp/gocryptotrader/config/versions"
|
|
)
|
|
|
|
var commands = []string{"upgrade", "downgrade", "encrypt", "decrypt"}
|
|
|
|
func main() {
|
|
fmt.Println("GoCryptoTrader: config-helper tool")
|
|
|
|
defaultCfgFile := config.DefaultFilePath()
|
|
|
|
var in, out, keyStr string
|
|
var inplace bool
|
|
var version int
|
|
|
|
fs := flag.NewFlagSet("config", flag.ExitOnError)
|
|
fs.Usage = func() { usage(fs) }
|
|
fs.StringVar(&in, "in", defaultCfgFile, "The config input file to process")
|
|
fs.StringVar(&out, "out", "[in].out", "The config output file")
|
|
fs.BoolVar(&inplace, "edit", false, "Edit; Save result to the original file")
|
|
fs.StringVar(&keyStr, "key", "", "The key to use for AES encryption")
|
|
fs.IntVar(&version, "version", 0, "The version to downgrade to")
|
|
|
|
cmd, args := parseCommand(os.Args[1:])
|
|
if cmd == "" {
|
|
usage(fs)
|
|
os.Exit(2)
|
|
}
|
|
|
|
if err := fs.Parse(args); err != nil {
|
|
fatal(err.Error())
|
|
}
|
|
|
|
if inplace {
|
|
out = in
|
|
} else if out == "[in].out" {
|
|
out = in + ".out"
|
|
}
|
|
|
|
var err error
|
|
key := []byte(keyStr)
|
|
data := readFile(in)
|
|
isEncrypted := config.IsEncrypted(data)
|
|
|
|
if cmd == "encrypt" && isEncrypted {
|
|
fatal("Error: File is already encrypted")
|
|
}
|
|
if cmd == "decrypt" && !isEncrypted {
|
|
fatal("Error: File is already decrypted")
|
|
}
|
|
|
|
if len(key) == 0 && (isEncrypted || cmd == "encrypt") {
|
|
if key, err = config.PromptForConfigKey(cmd == "encrypt"); err != nil {
|
|
fatal(err.Error())
|
|
}
|
|
}
|
|
|
|
if isEncrypted {
|
|
if data, err = config.DecryptConfigData(data, key); err != nil {
|
|
fatal(err.Error())
|
|
}
|
|
}
|
|
|
|
switch cmd {
|
|
case "decrypt":
|
|
if data, err = jsonparser.Set(data, []byte("-1"), "encryptConfig"); err != nil {
|
|
fatal("Unable to decrypt config data; Error: " + err.Error())
|
|
}
|
|
case "downgrade", "upgrade":
|
|
if version == 0 {
|
|
if cmd == "downgrade" {
|
|
fmt.Fprintln(os.Stderr, "Error: downgrade requires a version")
|
|
usage(fs)
|
|
os.Exit(3)
|
|
}
|
|
version = versions.LatestVersion
|
|
} else if version < 0 {
|
|
fmt.Fprintln(os.Stderr, "Error: version must be positive")
|
|
usage(fs)
|
|
os.Exit(3)
|
|
}
|
|
if data, err = versions.Manager.Deploy(context.Background(), data, version); err != nil {
|
|
fatal("Unable to " + cmd + " config; Error: " + err.Error())
|
|
}
|
|
if !isEncrypted {
|
|
break
|
|
}
|
|
fallthrough
|
|
case "encrypt":
|
|
if data, err = config.EncryptConfigData(data, key); err != nil {
|
|
fatal("Unable to encrypt config data; Error: " + err.Error())
|
|
}
|
|
}
|
|
|
|
if err := file.Write(out, data); err != nil {
|
|
fatal("Unable to write output file `" + out + "`; Error: " + err.Error())
|
|
}
|
|
|
|
fmt.Println("Success! File written to " + out)
|
|
}
|
|
|
|
func readFile(in string) []byte {
|
|
fileData, err := os.ReadFile(in)
|
|
if err != nil {
|
|
fatal("Unable to read input file " + in + "; Error: " + err.Error())
|
|
}
|
|
return fileData
|
|
}
|
|
|
|
func fatal(msg string) {
|
|
fmt.Fprintln(os.Stderr, msg)
|
|
os.Exit(2)
|
|
}
|
|
|
|
// parseCommand will return the single non-flag parameter from os.Args, and return the remaining args
|
|
// If none is provided, too many, usage() will be called and exit 1
|
|
func parseCommand(a []string) (cmd string, args []string) {
|
|
cmds, rem := []string{}, []string{}
|
|
for _, s := range a {
|
|
if slices.Contains(commands, s) {
|
|
cmds = append(cmds, s)
|
|
} else {
|
|
rem = append(rem, s)
|
|
}
|
|
}
|
|
switch len(cmds) {
|
|
case 0:
|
|
fmt.Fprintln(os.Stderr, "No command provided")
|
|
case 1:
|
|
return cmds[0], rem
|
|
default:
|
|
fmt.Fprintln(os.Stderr, "Too many commands provided: "+strings.Join(cmds, ", "))
|
|
}
|
|
return "", nil
|
|
}
|
|
|
|
// usage prints command usage and exits 1
|
|
func usage(fs *flag.FlagSet) {
|
|
//nolint:dupword // deliberate duplication of commands
|
|
fmt.Fprintln(os.Stderr, `
|
|
Usage:
|
|
config [arguments] <command>
|
|
|
|
The commands are:
|
|
encrypt encrypt infile and write to outfile
|
|
decrypt decrypt infile and write to outfile
|
|
upgrade upgrade the version of a decrypted config file
|
|
downgrade downgrade the version of a decrypted config file to a specific version
|
|
|
|
The arguments are:`)
|
|
fs.PrintDefaults()
|
|
}
|