package main import ( "database/sql" "encoding/json" "log" "net/http" "strconv" "github.com/go-chi/chi/v5" _ "github.com/mattn/go-sqlite3" ) // Item repräsentiert einen Eintrag im Dashboard. type Item struct { ID int64 `json:"id"` Name string `json:"name"` // Ein eindeutiger interner Name/Slug DisplayName string `json:"displayName"` // Der Anzeigename in der UI Target string `json:"target"` // Die Domain oder IP IconURL string `json:"iconUrl"` // URL zu einem Icon } // --- Datenbank-Funktionen --- // InitDB initialisiert die Datenbank und erstellt die Tabelle, falls sie nicht existiert. func InitDB(filepath string) *sql.DB { db, err := sql.Open("sqlite3", filepath) if err != nil { log.Fatal(err) } createTableSQL := `CREATE TABLE IF NOT EXISTS items ( "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "name" TEXT, "displayName" TEXT, "target" TEXT, "iconUrl" TEXT );` _, err = db.Exec(createTableSQL) if err != nil { log.Fatal(err) } return db } // --- HTTP Handler --- // GetAllItemsHandler gibt alle Dashboard-Einträge zurück. func GetAllItemsHandler(db *sql.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { rows, err := db.Query("SELECT id, name, displayName, target, iconUrl FROM items") if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } defer rows.Close() items := []Item{} for rows.Next() { var item Item if err := rows.Scan(&item.ID, &item.Name, &item.DisplayName, &item.Target, &item.IconURL); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } items = append(items, item) } respondWithJSON(w, http.StatusOK, items) } } // CreateItemHandler erstellt einen neuen Eintrag. func CreateItemHandler(db *sql.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var item Item if err := json.NewDecoder(r.Body).Decode(&item); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } stmt, err := db.Prepare("INSERT INTO items(name, displayName, target, iconUrl) VALUES(?, ?, ?, ?)") if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } res, err := stmt.Exec(item.Name, item.DisplayName, item.Target, item.IconURL) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } id, _ := res.LastInsertId() item.ID = id respondWithJSON(w, http.StatusCreated, item) } } // UpdateItemHandler aktualisiert einen bestehenden Eintrag. func UpdateItemHandler(db *sql.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64) if err != nil { http.Error(w, "Invalid item ID", http.StatusBadRequest) return } var item Item if err := json.NewDecoder(r.Body).Decode(&item); err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } stmt, err := db.Prepare("UPDATE items SET name = ?, displayName = ?, target = ?, iconUrl = ? WHERE id = ?") if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } _, err = stmt.Exec(item.Name, item.DisplayName, item.Target, item.IconURL, id) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } item.ID = id // Stelle sicher, dass die ID im Antwortobjekt korrekt ist respondWithJSON(w, http.StatusOK, item) } } // DeleteItemHandler löscht einen Eintrag. func DeleteItemHandler(db *sql.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64) if err != nil { http.Error(w, "Invalid item ID", http.StatusBadRequest) return } _, err = db.Exec("DELETE FROM items WHERE id = ?", id) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.WriteHeader(http.StatusNoContent) } } // GetItemHandler ruft einen einzelnen Eintrag ab. func GetItemHandler(db *sql.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id, err := strconv.ParseInt(chi.URLParam(r, "id"), 10, 64) if err != nil { http.Error(w, "Invalid item ID", http.StatusBadRequest) return } var item Item err = db.QueryRow("SELECT id, name, displayName, target, iconUrl FROM items WHERE id = ?", id).Scan(&item.ID, &item.Name, &item.DisplayName, &item.Target, &item.IconURL) if err == sql.ErrNoRows { http.Error(w, "Item not found", http.StatusNotFound) return } else if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } respondWithJSON(w, http.StatusOK, item) } } // respondWithJSON ist eine Hilfsfunktion zum Senden von JSON-Antworten. func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) { response, _ := json.Marshal(payload) w.Header().Set("Content-Type", "application/json") w.WriteHeader(code) w.Write(response) }