Files
upstream-mirror b352a9a30d
Some checks failed
test / Lint (push) Failing after 3s
test / Test with Go 1.26.8 (push) Failing after 2s
snapshot of https://github.com/centrifugal/centrifugo.git (master, 2026-09-16; blobs > 131072B omitted)
2026-09-16 01:17:21 +05:00

142 lines
2.8 KiB
Go

package tools
import (
"bytes"
"crypto/rand"
"encoding/base64"
"errors"
"fmt"
"os"
"path/filepath"
"slices"
"strings"
"text/template"
)
// PathExists returns whether the given file or directory exists or not
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
var jsonConfigTemplate = `{
"client": {
"token": {
"hmac_secret_key": "{{.TokenSecret}}"
},
"allowed_origins": []
},
"admin": {
"enabled": false,
"password": "{{.AdminPassword}}",
"secret": "{{.AdminSecret}}"
},
"http_api": {
"key": "{{.APIKey}}"
}
}
`
var tomlConfigTemplate = `[client]
allowed_origins = []
[client.token]
hmac_secret_key = "{{.TokenSecret}}"
[admin]
enabled = false
password = "{{.AdminPassword}}"
secret = "{{.AdminSecret}}"
[http_api]
key = "{{.APIKey}}"
`
var yamlConfigTemplate = `client:
token:
hmac_secret_key: "{{.TokenSecret}}"
allowed_origins: []
admin:
enabled: false
password: "{{.AdminPassword}}"
secret: "{{.AdminSecret}}"
http_api:
key: "{{.APIKey}}"
`
// GenerateConfig generates configuration file at provided path.
func GenerateConfig(f string) error {
exists, err := PathExists(f)
if err != nil {
return err
}
if exists {
return errors.New("output config file already exists: " + f)
}
ext := filepath.Ext(f)
if len(ext) > 1 {
ext = ext[1:]
}
supportedExtensions := []string{"json", "toml", "yaml", "yml"}
var t *template.Template
switch ext {
case "json":
t, err = template.New("config").Parse(jsonConfigTemplate)
case "toml":
t, err = template.New("config").Parse(tomlConfigTemplate)
case "yaml", "yml":
t, err = template.New("config").Parse(yamlConfigTemplate)
default:
return errors.New("output config file must have one of supported extensions: " + strings.Join(supportedExtensions, ", "))
}
if err != nil {
return err
}
var output bytes.Buffer
_ = t.Execute(&output, struct {
TokenSecret string
AdminPassword string
AdminSecret string
APIKey string
}{
mustGenerateSecretKey(64),
mustGenerateSecretKey(16),
mustGenerateSecretKey(64),
mustGenerateSecretKey(64),
})
return os.WriteFile(f, output.Bytes(), 0600)
}
func OptionalStringChoice(value string, choices []string) (string, error) {
if value == "" {
// Empty value is valid for optional configuration key.
return value, nil
}
if !slices.Contains(choices, value) {
return "", fmt.Errorf("invalid value: %s, possible choices are: %s", value, strings.Join(choices, ", "))
}
return value, nil
}
func mustGenerateSecretKey(byteLen int) string {
key := make([]byte, byteLen)
if _, err := rand.Read(key); err != nil {
panic(err)
}
return base64.RawURLEncoding.EncodeToString(key)
}