301115b74d
- Add UpdateHost handler + PUT /hosts/:id route
- CreateHost now accepts all fields (port, username, auth, notes)
- host_modal.html: full form with port, username, auth type toggle, edit mode
- host_list.html: edit button dispatches edit-host event with host data
- Connect button links to /terminal?host={id} for pre-selection
- Terminal page reads selected host from query param
- Toast notification system via Alpine.js events
- Add default template function for fallback values
160 lines
3.7 KiB
Go
160 lines
3.7 KiB
Go
package handler
|
|
|
|
import (
|
|
"strconv"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
"git.tukangketik.id/swanadiva/hostkeeper/v2/internal/model"
|
|
"git.tukangketik.id/swanadiva/hostkeeper/v2/internal/store"
|
|
)
|
|
|
|
var hostStore = store.NewHostStore()
|
|
|
|
var navItems = []fiber.Map{
|
|
{"ID": "hosts", "Label": "Hosts", "Icon": "server"},
|
|
{"ID": "terminal", "Label": "Terminal", "Icon": "terminal"},
|
|
{"ID": "sftp", "Label": "SFTP", "Icon": "folder-sync"},
|
|
{"ID": "snippets", "Label": "Snippets", "Icon": "code2"},
|
|
{"ID": "keychain", "Label": "Keychain", "Icon": "key-round"},
|
|
{"ID": "settings", "Label": "Settings", "Icon": "settings2"},
|
|
}
|
|
|
|
func Dashboard(c *fiber.Ctx) error {
|
|
hosts := hostStore.All()
|
|
return c.Render("index", fiber.Map{
|
|
"View": "hosts",
|
|
"Title": "Hosts",
|
|
"Hosts": hosts,
|
|
"Active": countByStatus(hosts, "active"),
|
|
"Offline": countByStatus(hosts, "offline"),
|
|
"NavItems": navItems,
|
|
})
|
|
}
|
|
|
|
func DashboardList(c *fiber.Ctx) error {
|
|
q := c.Query("q")
|
|
filter := c.Query("filter", "all")
|
|
hosts := hostStore.Search(q, filter)
|
|
return c.Render("host_list", fiber.Map{
|
|
"Hosts": hosts,
|
|
"Active": countByStatus(hosts, "active"),
|
|
"Offline": countByStatus(hosts, "offline"),
|
|
})
|
|
}
|
|
|
|
func parsePort(s string, def int) int {
|
|
i, err := strconv.Atoi(s)
|
|
if err != nil || i < 1 || i > 65535 {
|
|
return def
|
|
}
|
|
return i
|
|
}
|
|
|
|
func CreateHost(c *fiber.Ctx) error {
|
|
name := c.FormValue("name")
|
|
ip := c.FormValue("ip")
|
|
if name == "" || ip == "" {
|
|
return c.Status(400).SendString("name and ip required")
|
|
}
|
|
|
|
h := model.Host{
|
|
Name: name,
|
|
IP: ip,
|
|
OS: c.FormValue("os"),
|
|
Provider: c.FormValue("provider"),
|
|
Type: c.FormValue("type"),
|
|
Port: parsePort(c.FormValue("port"), 22),
|
|
Username: c.FormValue("username"),
|
|
AuthType: c.FormValue("authType"),
|
|
Password: c.FormValue("password"),
|
|
Hostname: c.FormValue("hostname"),
|
|
Notes: c.FormValue("notes"),
|
|
}
|
|
if h.Username == "" {
|
|
h.Username = "root"
|
|
}
|
|
if h.AuthType == "" {
|
|
h.AuthType = "key"
|
|
}
|
|
|
|
created := hostStore.AddFull(h)
|
|
hosts := hostStore.All()
|
|
_ = created
|
|
return c.Render("host_list", fiber.Map{
|
|
"Hosts": hosts,
|
|
"Active": countByStatus(hosts, "active"),
|
|
"Offline": countByStatus(hosts, "offline"),
|
|
})
|
|
}
|
|
|
|
func UpdateHost(c *fiber.Ctx) error {
|
|
id := c.Params("id")
|
|
existing, found := hostStore.Get(id)
|
|
if !found {
|
|
return c.Status(404).SendString("host not found")
|
|
}
|
|
|
|
if v := c.FormValue("name"); v != "" {
|
|
existing.Name = v
|
|
}
|
|
if v := c.FormValue("ip"); v != "" {
|
|
existing.IP = v
|
|
}
|
|
if v := c.FormValue("os"); v != "" {
|
|
existing.OS = v
|
|
}
|
|
if v := c.FormValue("provider"); v != "" {
|
|
existing.Provider = v
|
|
}
|
|
if v := c.FormValue("type"); v != "" {
|
|
existing.Type = v
|
|
}
|
|
if v := c.FormValue("port"); v != "" {
|
|
existing.Port = parsePort(v, 22)
|
|
}
|
|
if v := c.FormValue("username"); v != "" {
|
|
existing.Username = v
|
|
}
|
|
if v := c.FormValue("authType"); v != "" {
|
|
existing.AuthType = v
|
|
}
|
|
if v := c.FormValue("password"); v != "" {
|
|
existing.Password = v
|
|
}
|
|
if v := c.FormValue("hostname"); v != "" {
|
|
existing.Hostname = v
|
|
}
|
|
if v := c.FormValue("notes"); v != "" {
|
|
existing.Notes = v
|
|
}
|
|
|
|
hostStore.Update(existing)
|
|
hosts := hostStore.All()
|
|
return c.Render("host_list", fiber.Map{
|
|
"Hosts": hosts,
|
|
"Active": countByStatus(hosts, "active"),
|
|
"Offline": countByStatus(hosts, "offline"),
|
|
})
|
|
}
|
|
|
|
func DeleteHost(c *fiber.Ctx) error {
|
|
id := c.Params("id")
|
|
hostStore.Delete(id)
|
|
hosts := hostStore.All()
|
|
return c.Render("host_list", fiber.Map{
|
|
"Hosts": hosts,
|
|
"Active": countByStatus(hosts, "active"),
|
|
"Offline": countByStatus(hosts, "offline"),
|
|
})
|
|
}
|
|
|
|
func countByStatus(hosts []model.Host, status string) int {
|
|
n := 0
|
|
for _, h := range hosts {
|
|
if h.Status == status {
|
|
n++
|
|
}
|
|
}
|
|
return n
|
|
}
|