snapshot of https://github.com/centrifugal/centrifugo.git (master, 2026-09-16; blobs > 131072B omitted)
This commit is contained in:
141
internal/tools/config.go
Normal file
141
internal/tools/config.go
Normal file
@@ -0,0 +1,141 @@
|
||||
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)
|
||||
}
|
||||
Reference in New Issue
Block a user