diff --git a/cmd/monfront/create.go b/cmd/monfront/create.go
new file mode 100644
index 0000000..43805a1
--- /dev/null
+++ b/cmd/monfront/create.go
@@ -0,0 +1,148 @@
+package main
+
+import (
+ "database/sql"
+ "fmt"
+ "log"
+ "net/http"
+ "strings"
+)
+
+func showCreate(con *Context) {
+ if con.r.Method == "POST" {
+ addCreate(con)
+ return
+ }
+ if con.r.Method != "GET" {
+ con.w.WriteHeader(http.StatusMethodNotAllowed)
+ con.w.Write([]byte("method is not supported"))
+ return
+ }
+ if !con.CanEdit {
+ con.w.WriteHeader(http.StatusForbidden)
+ con.w.Write([]byte("no permission to change data"))
+ return
+ }
+ con.Content = map[string]any{}
+
+ primitives := []struct {
+ name string
+ query string
+ }{
+ {"commands", "select id, name, updated, command, message from commands order by name"},
+ {"checkers", "select id, name, description from checkers order by name"},
+ {"notifier", "select id, name, settings from notifier order by name"},
+ {"nodes", "select id, name, updated, message from nodes order by name"},
+ }
+ for _, prim := range primitives {
+ rows, err := DB.Query(prim.query)
+ defer rows.Close()
+ if err != nil {
+ log.Printf("could not get commands: %s", err)
+ con.Error = "could not get commands"
+ returnError(http.StatusInternalServerError, con, con.w)
+ return
+ }
+ result, err := rowsToResult(rows)
+ if err != nil {
+ log.Printf("could not get %s: %s", prim.name, err)
+ con.Error = "could not get " + prim.name
+ returnError(http.StatusInternalServerError, con, con.w)
+ return
+ }
+ con.Content[prim.name] = result
+ }
+
+ con.w.Header()["Content-Type"] = []string{"text/html"}
+ con.Render("create_index")
+ return
+}
+
+type (
+ sqlResult struct {
+ Columns []string
+ Rows [][]sql.NullString
+ }
+)
+
+func rowsToResult(rows *sql.Rows) (*sqlResult, error) {
+ res := &sqlResult{}
+ cols, err := rows.Columns()
+ if err != nil {
+ return res, fmt.Errorf("could not get columns: %w", err)
+ }
+ res.Columns = cols
+ res.Rows = [][]sql.NullString{}
+ colNum := len(cols)
+
+ for rows.Next() {
+ line := make([]sql.NullString, colNum)
+ lineMap := make([]any, colNum)
+ for i := 0; i < colNum; i++ {
+ lineMap[i] = &(line[i])
+ }
+ if err := rows.Scan(lineMap...); err != nil {
+ return res, fmt.Errorf("could not scan values: %w", err)
+ }
+ res.Rows = append(res.Rows, line)
+ }
+
+ return res, nil
+}
+
+func addCreate(con *Context) {
+ if !con.CanEdit {
+ con.w.WriteHeader(http.StatusForbidden)
+ con.w.Write([]byte("no permission to change data"))
+ return
+ }
+
+ if err := con.r.ParseForm(); err != nil {
+ con.w.WriteHeader(http.StatusBadRequest)
+ fmt.Fprintf(con.w, "could not parse parameters: %s", err)
+ return
+ }
+
+ con.w.Header()["Location"] = []string{"/create"}
+
+ addType := con.r.PostForm.Get("type")
+ types := map[string]struct {
+ Fields []string
+ Table string
+ }{
+ "command": {[]string{"name", "command", "message"}, "commands"},
+ "node": {[]string{"name", "message"}, "nodes"},
+ "checker": {[]string{"name", "description"}, "checkers"},
+ "notifier": {[]string{"name", "settings"}, "notifier"},
+ "check": {[]string{"name", "message", "options", "intval", "node_id", "command_id", "checker_id"}, "checks"},
+ }
+ t, found := types[addType]
+ if !found {
+ con.Error = "undefined type '" + addType + "'"
+ returnError(http.StatusBadRequest, con, con.w)
+ return
+ }
+
+ fields := make([]any, len(t.Fields))
+ vals := make([]string, len(t.Fields))
+ for i := 0; i < len(fields); i++ {
+ vals[i] = fmt.Sprintf(`$%d`, i+1)
+ fields[i] = con.r.PostForm.Get(t.Fields[i])
+ if fields[i] == "" {
+ con.Error = "field " + t.Fields[i] + " must not be empty"
+ returnError(http.StatusBadRequest, con, con.w)
+ return
+ }
+ }
+ stmt := `insert into ` + t.Table + `(` + strings.Join(t.Fields, ",") + `) values (` + strings.Join(vals, ",") + `)`
+ _, err := DB.Exec(stmt, fields...)
+ if err != nil {
+ log.Printf("could not insert new %s: %s", addType, err)
+ con.Error = "could not insert new " + addType
+ returnError(http.StatusInternalServerError, con, con.w)
+ return
+ }
+
+ con.w.WriteHeader(http.StatusSeeOther)
+ return
+}
diff --git a/cmd/monfront/main.go b/cmd/monfront/main.go
index 63c1b9a..a318e75 100644
--- a/cmd/monfront/main.go
+++ b/cmd/monfront/main.go
@@ -170,6 +170,7 @@ func main() {
s := newServer(l, db, tmpl, auth, autho)
s.Handle("/", showChecks)
+ s.Handle("/create", showCreate)
s.Handle("/check", showCheck)
s.Handle("/checks", showChecks)
s.Handle("/groups", showGroups)
diff --git a/cmd/monfront/server.go b/cmd/monfront/server.go
index 2ada1d0..8e53c64 100644
--- a/cmd/monfront/server.go
+++ b/cmd/monfront/server.go
@@ -46,6 +46,8 @@ type (
CheckDetails *checkDetails `json:"check_details,omitempty"`
Groups []group `json:"groups,omitempty"`
Unhandled bool `json:"-"` // set this flag when unhandled was called
+
+ Content map[string]any `json:"-"` // used for the configuration dashboard
}
)
diff --git a/cmd/monfront/templates/create_index.html b/cmd/monfront/templates/create_index.html
new file mode 100644
index 0000000..1e4a67e
--- /dev/null
+++ b/cmd/monfront/templates/create_index.html
@@ -0,0 +1,84 @@
+{{ template "header" . }}
+create entries
+ checks
+
+ nodes
+ create new node
+
+ commands
+ create new command
+
+ checkers
+ create new checker instance
+
+ notifier
+ create new notifier
+
+
{{ $col }} | + {{ end }} ++ |
---|---|
{{ if $col.Valid }}{{ $col.String }}{{ end }} | + {{ end }} ++ + + | +