diff --git a/api.go b/api.go index cf39599..0cbdcac 100644 --- a/api.go +++ b/api.go @@ -107,15 +107,19 @@ func LoadConfig(w http.ResponseWriter, r *http.Request) { w.Write([]byte("ok")) } -func GetConfig(w http.ResponseWriter, r *http.Request) { - config := []configui.File{} - for _, f := range files { - config = append(config, *f) - } - data, err := json.Marshal(config) +func getConfigHandler(w http.ResponseWriter, r *http.Request) { + data, err := GetConfig() if err != nil { HttpWriter(w, 500, err.Error()) return } w.Write(data) } + +func GetConfig() ([]byte, error) { + config := []configui.File{} + for _, f := range files { + config = append(config, *f) + } + return json.Marshal(config) +} diff --git a/main.go b/main.go index e798662..ae9d1bc 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,6 @@ package main import ( - "bytes" "embed" "flag" "fmt" @@ -13,6 +12,7 @@ import ( "time" "kumoly.io/tools/configui/configui" + "kumoly.io/tools/configui/public" ) //go:embed templates @@ -27,6 +27,7 @@ var ( flagBind string flagLogFile string + flagAllow string flagVer bool ) @@ -42,6 +43,7 @@ func init() { flag.StringVar(&flagAlias, "n", "", "alias of file") 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", "localhost:8000", "address to bind") flag.BoolVar(&flagVer, "v", false, "show version") flag.Usage = func() { @@ -96,7 +98,7 @@ func main() { mux := http.NewServeMux() mux.HandleFunc("/api/conf", func(w http.ResponseWriter, r *http.Request) { if r.Method == "GET" { - GetConfig(w, r) + getConfigHandler(w, r) } else if r.Method == "POST" { LoadConfig(w, r) } else { @@ -133,28 +135,15 @@ func main() { w.WriteHeader(404) } }) - mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - if r.URL.Path != "/" { - http.NotFound(w, r) - return - } - buf := &bytes.Buffer{} - err := tmpl.ExecuteTemplate(buf, "home", nil) - if err != nil { - w.WriteHeader(500) - w.Write([]byte(err.Error())) - } else { - w.Write(buf.Bytes()) - } - }) + mux.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.FS(public.FS)))) tmpl = template.Must(template.New("").ParseFS(tmplFS, "templates/*.tmpl", "templates/**/*.tmpl")) - + setRoutes(mux) server := &http.Server{ Addr: flagBind, WriteTimeout: time.Second * 3, ReadTimeout: time.Second * 30, - Handler: LogMiddleware(mux), + Handler: Middleware(mux), } // start server diff --git a/public/embed.go b/public/embed.go new file mode 100644 index 0000000..85d857c --- /dev/null +++ b/public/embed.go @@ -0,0 +1,6 @@ +package public + +import "embed" + +//go:embed js css +var FS embed.FS diff --git a/route.go b/route.go new file mode 100644 index 0000000..5e3f254 --- /dev/null +++ b/route.go @@ -0,0 +1,42 @@ +package main + +import ( + "net/http" +) + +func setRoutes(mux *http.ServeMux) { + + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/" { + http.NotFound(w, r) + return + } + + Files := []string{} + for file := range files { + Files = append(Files, files[file].Alias) + } + + contentB, err := GetConfig() + content := "" + if err != nil { + content = err.Error() + } else { + content = string(contentB) + } + + data := struct { + Active string + Files []string + Content string + Lang string + }{ + Files: Files, + Active: "ConfigUI", + Content: content, + Lang: "json", + } + + serve(w, "home", data) + }) +} diff --git a/templates/base/footer.tmpl b/templates/base/footer.tmpl index 7f92449..62f471c 100644 --- a/templates/base/footer.tmpl +++ b/templates/base/footer.tmpl @@ -1,6 +1,9 @@ {{define "base/footer"}} - + + + + {{end}} \ No newline at end of file diff --git a/templates/base/header.tmpl b/templates/base/header.tmpl index 4286390..832c144 100644 --- a/templates/base/header.tmpl +++ b/templates/base/header.tmpl @@ -4,8 +4,10 @@ - Serviced - + ConfigUI + + + {{end}} \ No newline at end of file diff --git a/templates/home.tmpl b/templates/home.tmpl index 45e9873..b6fa25c 100644 --- a/templates/home.tmpl +++ b/templates/home.tmpl @@ -1,14 +1,54 @@ {{define "home"}} {{template "base/header" .}} -
-
-

- Hello World -

-

- My first website with Bulma! -

+ +
+
+
+ +

ConfigUI

+
+
-
+ + +
+
+
+
+ +
+
+
+

Two

+
+
+
+
+

Three

+ + + + +
+
+
+ {{template "base/footer" .}} {{end}} \ No newline at end of file diff --git a/util.go b/util.go index 75c2874..c0df496 100644 --- a/util.go +++ b/util.go @@ -2,15 +2,17 @@ package main import ( "archive/tar" + "bytes" "compress/gzip" "io" "log" + "net" "net/http" "os" "strings" ) -func LogMiddleware(next http.Handler) http.Handler { +func Middleware(next http.Handler) http.Handler { return http.HandlerFunc( func(w http.ResponseWriter, r *http.Request) { defer func() { @@ -20,8 +22,18 @@ func LogMiddleware(next http.Handler) http.Handler { w.WriteHeader(500) } }() - next.ServeHTTP(w, r) - log.Printf("%s %s %s %s\n", r.RemoteAddr, r.Method, r.URL, r.Header.Get("User-Agent")) + abort := false + if flagAllow != "" { + if GetIP(r) != flagAllow { + HttpWriter(w, 403, "permission denyed") + abort = true + } + } + + if !abort { + next.ServeHTTP(w, r) + } + log.Printf("%s %s %s %s\n", GetIP(r), r.Method, r.URL, r.Header.Get("User-Agent")) }, ) } @@ -88,3 +100,31 @@ func HttpWriter(w http.ResponseWriter, status int, errStr string) { w.WriteHeader(status) w.Write([]byte(errStr)) } + +func GetIP(r *http.Request) string { + ip := r.Header.Get("X-Real-Ip") + if ip == "" { + ips := r.Header.Get("X-Forwarded-For") + ipArr := strings.Split(ips, ",") + ip = strings.Trim(ipArr[len(ipArr)-1], " ") + } + if ip == "" { + var err error + ip, _, err = net.SplitHostPort(r.RemoteAddr) + if err != nil { + ip = r.RemoteAddr + } + } + return ip +} + +func serve(w http.ResponseWriter, name string, data interface{}) error { + buf := &bytes.Buffer{} + err := tmpl.ExecuteTemplate(buf, "home", data) + if err != nil { + HttpWriter(w, 500, err.Error()) + return err + } + _, err = w.Write(buf.Bytes()) + return err +}