diff --git a/cmd/configui/main.go b/cmd/configui/main.go index af888f9..2ef3b02 100644 --- a/cmd/configui/main.go +++ b/cmd/configui/main.go @@ -18,6 +18,7 @@ var ( flagConfigPath string flagBind string + flagAddr string flagNoReconfig bool flagLogFile string flagAllow string @@ -36,7 +37,8 @@ func init() { flag.StringVar(&flagAction, "c", "", "cmd to apply") flag.StringVar(&flagLogFile, "log", "", "log to file") flag.StringVar(&flagAllow, "allow", "", "IPs to allow, blank to allow all") - flag.StringVar(&flagBind, "bind", "0.0.0.0:8000", "address to bind") + flag.StringVar(&flagBind, "bind", "0.0.0.0:8000", "address to bind, (deprecated, use -addr instead)") + flag.StringVar(&flagAddr, "addr", "0.0.0.0:8000", "address to bind") flag.BoolVar(&flagNoReconfig, "static", false, "disable config api") flag.BoolVar(&flagVer, "v", false, "show version") flag.Usage = func() { @@ -53,6 +55,11 @@ func main() { return } + // deprecate fix + if flagBind != "0.0.0.0:8000" && flagAddr == "0.0.0.0:8000" { + flagAddr = flagBind + } + cui := configui.New() // setup values @@ -98,7 +105,7 @@ func main() { // setup routes server := &http.Server{ - Addr: flagBind, + Addr: flagAddr, // disable timeout due to cui controlling cmd timeouts // WriteTimeout: time.Second * 30, // ReadTimeout: time.Second * 30, @@ -106,7 +113,7 @@ func main() { } // start server - log.Info("Listening on ", flagBind) + log.Info("Listening on ", flagAddr) err := server.ListenAndServe() if err != nil { log.Error(err) diff --git a/configui.go b/configui.go index 1b0f40b..c1f79a5 100644 --- a/configui.go +++ b/configui.go @@ -27,6 +27,9 @@ const version = "v0.1.13" //go:embed templates var tmplFS embed.FS +//go:embed schema.json +var SCHEMA []byte + var Ext2Mode map[string]string = map[string]string{ "go": "golang", "log": "sh", @@ -39,9 +42,6 @@ var Ext2Mode map[string]string = map[string]string{ type Action struct { Name string `json:"name"` Cmd string `json:"cmd"` - Dir string `json:"dir,omitempty"` - Envs []string `json:"env,omitempty"` - Args []string `json:"arg,omitempty"` run chan struct{} `json:"-"` pid int `json:"-"` } @@ -152,6 +152,9 @@ func (cui *ConfigUI) LoadConfig(confstr string) error { // construct fileIndex tmpIndex := map[string]int{} for i, f := range tmpConf.Files { + if f.Name == "" && f.Path == "" { + continue + } if f.Name == "" { f.Name = f.Path } diff --git a/go.mod b/go.mod index 481ab30..b3ba2ff 100644 --- a/go.mod +++ b/go.mod @@ -6,9 +6,12 @@ require ( kumoly.io/lib/klog v0.0.8 kumoly.io/lib/ksrv v0.0.2-0.20211112060911-0d61b343a298 kumoly.io/lib/stat v0.0.1 + kumoly.io/tools/kconfig v0.1.3 ) require ( github.com/mattn/go-isatty v0.0.14 // indirect + github.com/rs/zerolog v1.26.0 // indirect golang.org/x/sys v0.0.0-20211103235746-7861aae1554b // indirect + kumoly.io/lib/guard v0.1.2-0.20211124052638-9dfd98f9a848 // indirect ) diff --git a/go.sum b/go.sum index d1feb51..af7e115 100644 --- a/go.sum +++ b/go.sum @@ -1,11 +1,44 @@ +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.26.0 h1:ORM4ibhEZeTeQlCojCK2kPz1ogAY4bGs4tD+SaAdGaE= +github.com/rs/zerolog v1.26.0/go.mod h1:yBiM87lvSqX8h0Ww4sdzNSkVYZ8dL2xjZJG1lAuGZEo= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b h1:1VkfZQv42XQlA/jchYumAnv1UPo6RgF9rJFkTgZIxO4= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +kumoly.io/lib/guard v0.1.2-0.20211124052638-9dfd98f9a848 h1:ALCeJga3775AJDkk7YbMQEcYxpwHtinUN+YjkpacNhA= +kumoly.io/lib/guard v0.1.2-0.20211124052638-9dfd98f9a848/go.mod h1:yWg9RDSI6YXkOPmP6Ad93aMqzlxhgW8LOe/ZRjjYX3U= kumoly.io/lib/klog v0.0.8 h1:6hTfDlZh7KGnPrd2tUrauCKRImSnyyN9DHXpey3Czn8= kumoly.io/lib/klog v0.0.8/go.mod h1:Snm+c1xRrh/RbXsxQf7UGYbAJGPcIa6bEEN+CmzJh7M= kumoly.io/lib/ksrv v0.0.2-0.20211112060911-0d61b343a298 h1:0raqoIXmNpD6s1SrJbieAyIIkDyhe+aqfaXvx8wenrI= kumoly.io/lib/ksrv v0.0.2-0.20211112060911-0d61b343a298/go.mod h1:pwd+NspxnoxPJAETRY2V4i2qZc+orKLxvWzGUBiqBW8= kumoly.io/lib/stat v0.0.1 h1:Ck596El7Ixk7GZyzQq/86F1YCl7iYffHmzEdFx1sSRM= kumoly.io/lib/stat v0.0.1/go.mod h1:zqMV9q4TC94VGbpDn/mGBTwRNWBVWlVg1taLlCBAWc8= +kumoly.io/tools/kconfig v0.1.3 h1:okLWqlvASZzfAj3kXzpB/Q8V7WZNd24Y6MLPhWPTwP8= +kumoly.io/tools/kconfig v0.1.3/go.mod h1:j6GYUb50c0pFMxfQgoUl5n4P++AapoG+L5YHxHyyjN4= diff --git a/schema.json b/schema.json new file mode 100644 index 0000000..baa2b82 --- /dev/null +++ b/schema.json @@ -0,0 +1,148 @@ +{ + "title": "ConfigUI", + "type": "object", + "id": "configui", + "properties": { + "app_name": { + "type": "string", + "title": "AppName", + "default": "ConfigUI", + "required":true + }, + "files":{ + "title":"Files", + "type": "array", + "format":"table", + "items":{ + "$ref": "#/definitions/file" + } + }, + "actions":{ + "title":"Actions", + "type": "array", + "format":"table", + "items":{ + "$ref": "#/definitions/action" + } + }, + "base_url":{ + "type": "string", + "title": "BaseUrl", + "default": "/" + }, + "config_path":{ + "title":"Config Path", + "type": "string", + "discription":"path to config file" + }, + "shell":{ + "title":"Shell", + "type": "string", + "description":"shell to use when running cmds", + "required":true, + "options":{ + "infoText":"run commands are structured as SHELL -c \"CMD\", \nthe default shell is \nunix:`/usr/bin/sh`\nwindows:`C:\\Windows\\System32\\cmd`\ndarwin:`/bin/bash`" + } + }, + "allow_ip":{ + "type":"string", + "title":"AllowedIP", + "description":"IPs to allow, blank to allow all" + }, + "timeout":{ + "type": "string", + "title": "Command Timeout", + "default": "10s", + "description": "timeout to wait for command to finish" + }, + "log_path": { + "type":"string", + "title":"Log Path", + "description":"empty for stdout" + }, + "log_level": { + "type": "integer", + "title": "log level", + "default": 9 + }, + "cust":{ + "title": "Custom Template", + "type": "string", + "description": "path to custom templates" + }, + + "result_bellow": { + "title":"Result Bellow", + "type": "boolean", + "format": "checkbox", + "description":"show results bellow editor", + "default": false + }, + "production":{ + "type": "boolean", + "format": "checkbox", + "title": "Production Mode", + "default": true + }, + "no_reconfig":{ + "title":"NoReconfig", + "type": "boolean", + "format": "checkbox", + "description":"disable config at runtime", + "default": false + }, + "hide_config": { + "title":"Hide Config", + "type": "boolean", + "format": "checkbox", + "description":"hide config panel", + "default": false + } + }, + "definitions": { + "file": { + "type": "object", + "properties":{ + "name": { + "title": "Name", + "type": "string" + }, + "path": { + "title": "Path", + "type": "string" + }, + "cmd": { + "title": "Command", + "type": "string" + }, + "ro": { + "title": "Read Only", + "format":"checkbox", + "type": "boolean" + }, + "lang": { + "title": "Lang", + "type": "string", + "description":"set editor language mode" + }, + "order": { + "type": "integer", + "default":0 + } + } + }, + "action":{ + "type": "object", + "properties":{ + "name": { + "title": "Name", + "type": "string" + }, + "cmd": { + "title": "Command", + "type": "string" + } + } + } + } +} \ No newline at end of file diff --git a/server.go b/server.go index d4192a3..5df729b 100644 --- a/server.go +++ b/server.go @@ -2,10 +2,11 @@ package configui import ( "net/http" - "strings" + "path/filepath" "kumoly.io/lib/ksrv" "kumoly.io/lib/stat" + "kumoly.io/tools/kconfig" ) func (cui *ConfigUI) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -17,10 +18,19 @@ func (cui *ConfigUI) middleware(next http.Handler) http.Handler { cui.ksrv_log = k.GetLogger() cui.setLog() k.SetNoLogCondition(func(r *http.Request) bool { - if strings.HasPrefix(r.URL.Path, "/public") || r.URL.Query().Get("f") == "true" { + ext := filepath.Ext(r.URL.Path) + switch ext { + case ".js": return true + case ".css": + return true + case ".ttf": + return true + case ".ico": + return true + } - return false + return r.URL.Query().Get("f") == "true" }) return k.Middleware( http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { @@ -106,6 +116,26 @@ func (cui *ConfigUI) mux() *http.ServeMux { w.WriteHeader(404) } }) + + k := kconfig.New() + k.Schema = SCHEMA + k.Load = func() []byte { + b, err := cui.Config() + if err != nil { + cui.log.Error(err) + return []byte{} + } + return b + } + k.Apply = func(b []byte) error { + err := cui.LoadConfig(string(b)) + if err == nil { + k.AppName = cui.AppName + } + return err + } + cuiR.Handle("/kconfig/", http.StripPrefix("/kconfig", k)) + cuiR.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.FS(cui.PublicFS)))) cuiR.HandleFunc("/", cui.App) return cuiR diff --git a/templates/components/kconfig.tmpl b/templates/components/kconfig.tmpl new file mode 100644 index 0000000..91336b8 --- /dev/null +++ b/templates/components/kconfig.tmpl @@ -0,0 +1,42 @@ +{{define "components/kconfig"}} + + + + +{{end}} \ No newline at end of file diff --git a/templates/home.tmpl b/templates/home.tmpl index cac3ce3..2d4af71 100644 --- a/templates/home.tmpl +++ b/templates/home.tmpl @@ -1,6 +1,7 @@ {{define "home"}} {{template "base/header" .}} {{template "components/error" .}} +{{template "components/kconfig" .}} @@ -56,6 +57,7 @@ var Active = "{{.File.Name}}"; {{end}}
Export Files + {{if not .HideConfig}}Config{{end}}