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 }