222 lines
4.9 KiB
Go
222 lines
4.9 KiB
Go
package configui
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
func (cui *ConfigUI) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
cui.middleware(cui.mux()).ServeHTTP(w, r)
|
|
}
|
|
|
|
func (cui *ConfigUI) middleware(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(
|
|
func(w http.ResponseWriter, r *http.Request) {
|
|
rw := &CuiResponseWriter{w, 0}
|
|
defer catch(rw, r)
|
|
ip := GetIP(r)
|
|
if cui.AllowIP != "" {
|
|
if !matchIPGlob(ip, cui.AllowIP) {
|
|
rw.WriteHeader(403)
|
|
panic("permission denied")
|
|
}
|
|
}
|
|
next.ServeHTTP(rw, r)
|
|
//logging
|
|
if !strings.HasPrefix(r.URL.Path, "/public") && r.URL.Query().Get("f") != "true" {
|
|
log.Printf("%s %s %d %s %s\n", ip, r.Method, rw.StatueCode, r.URL, r.Header.Get("User-Agent"))
|
|
}
|
|
},
|
|
)
|
|
}
|
|
|
|
func (cui *ConfigUI) mux() *http.ServeMux {
|
|
cuiR := http.NewServeMux()
|
|
cuiR.HandleFunc("/api/conf", func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method == "GET" {
|
|
cui.GetConfig(w, r)
|
|
} else if r.Method == "POST" {
|
|
cui.PostConfig(w, r)
|
|
} else {
|
|
w.WriteHeader(404)
|
|
}
|
|
})
|
|
cuiR.HandleFunc("/api/files", func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method == "GET" {
|
|
cui.ListFiles(w, r)
|
|
} else {
|
|
w.WriteHeader(404)
|
|
}
|
|
})
|
|
cuiR.HandleFunc("/api/file", func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method == "GET" {
|
|
cui.GetFile(w, r)
|
|
} else if r.Method == "POST" {
|
|
cui.PostFile(w, r)
|
|
} else {
|
|
w.WriteHeader(404)
|
|
}
|
|
})
|
|
cuiR.HandleFunc("/api/apply", func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method == "POST" {
|
|
cui.Apply(w, r)
|
|
} else {
|
|
w.WriteHeader(404)
|
|
}
|
|
})
|
|
cuiR.HandleFunc("/api/export", func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method == "GET" {
|
|
cui.Download(w, r)
|
|
} else {
|
|
w.WriteHeader(404)
|
|
}
|
|
})
|
|
cuiR.Handle("/public/", http.StripPrefix("/public/", http.FileServer(http.FS(cui.PublicFS))))
|
|
cuiR.HandleFunc("/", cui.App)
|
|
return cuiR
|
|
}
|
|
|
|
func (cui *ConfigUI) ListFiles(w http.ResponseWriter, r *http.Request) {
|
|
data, err := json.Marshal(cui.Files)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
w.Write(data)
|
|
}
|
|
|
|
func (cui *ConfigUI) GetFile(w http.ResponseWriter, r *http.Request) {
|
|
name := r.URL.Query().Get("name")
|
|
file, err := cui.File(name)
|
|
if err != nil {
|
|
response(w, 404, []byte("file not found"))
|
|
return
|
|
}
|
|
data, err := file.Read()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
response, err := json.Marshal(map[string]string{
|
|
"path": file.Path,
|
|
"name": file.Name,
|
|
"action": file.Action,
|
|
"data": string(data),
|
|
})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.Write(response)
|
|
}
|
|
|
|
func (cui *ConfigUI) PostFile(w http.ResponseWriter, r *http.Request) {
|
|
data, err := ioutil.ReadAll(r.Body)
|
|
r.Body.Close()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
f := File{}
|
|
if err := json.Unmarshal(data, &f); err != nil {
|
|
panic(err)
|
|
}
|
|
file, err := cui.File(f.Name)
|
|
if err != nil {
|
|
response(w, 404, []byte("file not found"))
|
|
return
|
|
}
|
|
if err := file.Write([]byte(f.Data)); err != nil {
|
|
panic(err)
|
|
}
|
|
w.Write([]byte("ok"))
|
|
}
|
|
|
|
func (cui *ConfigUI) Apply(w http.ResponseWriter, r *http.Request) {
|
|
name := r.URL.Query().Get("name")
|
|
file, err := cui.File(name)
|
|
if err != nil {
|
|
response(w, 404, []byte("file not found"))
|
|
return
|
|
}
|
|
result, err := file.Do()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
w.Write([]byte(result))
|
|
}
|
|
|
|
func (cui *ConfigUI) Download(w http.ResponseWriter, r *http.Request) {
|
|
if name := r.URL.Query().Get("name"); name != "" {
|
|
if name == cui.AppName {
|
|
data, err := cui.Config()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
w.Header().Set(
|
|
"Content-Disposition", `
|
|
attachment; filename="`+cui.AppName+`.json"`,
|
|
)
|
|
w.Write(data)
|
|
return
|
|
}
|
|
file, err := cui.File(name)
|
|
if err != nil {
|
|
response(w, 404, []byte("file not found"))
|
|
return
|
|
}
|
|
data, err := file.Read()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
w.Header().Set("Content-Disposition", `attachment; filename="`+filepath.Base(file.Path)+`"`)
|
|
w.Write(data)
|
|
return
|
|
}
|
|
fs := []string{}
|
|
for _, i := range cui.fileIndex {
|
|
fs = append(fs, cui.Files[i].Path)
|
|
}
|
|
if cui.ConfigPath != "" {
|
|
fs = append(fs, cui.ConfigPath)
|
|
}
|
|
w.Header().Set("Content-Disposition", `attachment; filename="export.tar.gz"`)
|
|
bundle(w, fs, cui.AppName, false)
|
|
}
|
|
|
|
func (cui *ConfigUI) PostConfig(w http.ResponseWriter, r *http.Request) {
|
|
if cui.NoReconfig {
|
|
panic("system reconfig is disabled")
|
|
}
|
|
data, err := ioutil.ReadAll(r.Body)
|
|
r.Body.Close()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
err = cui.LoadConfig(string(data))
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if cui.ConfigPath != "" {
|
|
info, err := os.Stat(cui.ConfigPath)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
err = os.WriteFile(cui.ConfigPath, data, info.Mode())
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
w.Write([]byte("ok"))
|
|
}
|
|
|
|
func (cui *ConfigUI) GetConfig(w http.ResponseWriter, r *http.Request) {
|
|
data, err := cui.Config()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
w.Write(data)
|
|
}
|