base dashboard and login
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"crowdsec-dashy/internal/crowdsec"
|
||||
)
|
||||
|
||||
// MachinesHandler manages the machines page and its POST actions.
|
||||
type MachinesHandler struct {
|
||||
deps Deps
|
||||
}
|
||||
|
||||
func NewMachinesHandler(deps Deps) *MachinesHandler {
|
||||
return &MachinesHandler{deps: deps}
|
||||
}
|
||||
|
||||
// MachinesData is passed to the machines template.
|
||||
type MachinesData struct {
|
||||
PageData
|
||||
Machines []crowdsec.Machine
|
||||
}
|
||||
|
||||
var validMachineID = regexp.MustCompile(`^[a-zA-Z0-9_.\-]{1,128}$`)
|
||||
|
||||
// List renders the machines list.
|
||||
func (h *MachinesHandler) List(w http.ResponseWriter, r *http.Request) {
|
||||
pd := NewPageData(r, "Machines", h.deps.CLIAvailable, h.deps.PollInterval)
|
||||
if f := readFlash(r); f.Message != "" {
|
||||
pd.Flash = f
|
||||
}
|
||||
|
||||
var machines []crowdsec.Machine
|
||||
if h.deps.CLIAvailable {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 15*time.Second)
|
||||
defer cancel()
|
||||
var err error
|
||||
machines, err = h.deps.CLI.ListMachines(ctx)
|
||||
if err != nil {
|
||||
pd.Flash = FlashMessage{Type: "error", Message: fmt.Sprintf("cscli error: %v", err)}
|
||||
}
|
||||
}
|
||||
|
||||
h.deps.Renderer.Render(w, "machines", MachinesData{PageData: pd, Machines: machines})
|
||||
}
|
||||
|
||||
// Delete removes a machine by ID.
|
||||
func (h *MachinesHandler) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
r.Body = http.MaxBytesReader(w, r.Body, 4096)
|
||||
if err := r.ParseForm(); err != nil {
|
||||
flashRedirect(w, r, "/machines", "error", "invalid form data")
|
||||
return
|
||||
}
|
||||
if !checkCSRF(r) {
|
||||
http.Error(w, "forbidden", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
if !h.deps.CLIAvailable {
|
||||
flashRedirect(w, r, "/machines", "error", "cscli not available")
|
||||
return
|
||||
}
|
||||
|
||||
id := r.FormValue("id")
|
||||
if !validMachineID.MatchString(id) {
|
||||
flashRedirect(w, r, "/machines", "error", "invalid machine id")
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := h.deps.CLI.DeleteMachine(ctx, id); err != nil {
|
||||
flashRedirect(w, r, "/machines", "error", fmt.Sprintf("failed to delete machine: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
flashRedirect(w, r, "/machines", "success", fmt.Sprintf("Machine %q deleted", id))
|
||||
}
|
||||
|
||||
// Validate approves a pending machine registration.
|
||||
func (h *MachinesHandler) Validate(w http.ResponseWriter, r *http.Request) {
|
||||
r.Body = http.MaxBytesReader(w, r.Body, 4096)
|
||||
if err := r.ParseForm(); err != nil {
|
||||
flashRedirect(w, r, "/machines", "error", "invalid form data")
|
||||
return
|
||||
}
|
||||
if !checkCSRF(r) {
|
||||
http.Error(w, "forbidden", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
if !h.deps.CLIAvailable {
|
||||
flashRedirect(w, r, "/machines", "error", "cscli not available")
|
||||
return
|
||||
}
|
||||
|
||||
id := r.FormValue("id")
|
||||
if !validMachineID.MatchString(id) {
|
||||
flashRedirect(w, r, "/machines", "error", "invalid machine id")
|
||||
return
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := h.deps.CLI.ValidateMachine(ctx, id); err != nil {
|
||||
flashRedirect(w, r, "/machines", "error", fmt.Sprintf("failed to validate machine: %v", err))
|
||||
return
|
||||
}
|
||||
|
||||
flashRedirect(w, r, "/machines", "success", fmt.Sprintf("Machine %q validated", id))
|
||||
}
|
||||
Reference in New Issue
Block a user