89 lines
2.8 KiB
Go
89 lines
2.8 KiB
Go
package server
|
|
|
|
import (
|
|
"bytes"
|
|
"html/template"
|
|
"log"
|
|
"net/http"
|
|
)
|
|
|
|
// A panel page is either a fragment - its content alone, for the shell to put
|
|
// in place without reloading - or the shell with that content already in it.
|
|
|
|
func isFrag(r *http.Request) bool { return r.URL.Query().Get("frag") == "1" }
|
|
|
|
// pageView is the shell's view a page is shown in; the machine pages (Порты,
|
|
// Статус, Изменить) open as a dialog over the machines view.
|
|
var pageView = map[string]string{"dashboard": "dashboard", "settings": "settings"}
|
|
|
|
func (s *Server) renderPage(w http.ResponseWriter, r *http.Request, name string, data map[string]any) {
|
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
w.Header().Set("Cache-Control", "no-store")
|
|
if data == nil {
|
|
data = map[string]any{}
|
|
}
|
|
data["IsAdmin"] = s.currentAdmin(r).IsAdmin()
|
|
if !isFrag(r) {
|
|
if _, ok := pageView[name]; !ok {
|
|
// A machine page asked for whole: the machines view with it in
|
|
// a dialog.
|
|
s.shell(w, r, map[string]any{"View": "dashboard", "Dialog": r.URL.Path})
|
|
return
|
|
}
|
|
}
|
|
var body bytes.Buffer
|
|
if err := s.tmpl.ExecuteTemplate(&body, name+"-body", data); err != nil {
|
|
log.Printf("template %s: %v", name, err)
|
|
http.Error(w, "internal error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
if isFrag(r) {
|
|
_, _ = w.Write(body.Bytes())
|
|
return
|
|
}
|
|
data["View"] = pageView[name]
|
|
data["Body"] = template.HTML(body.String())
|
|
s.shell(w, r, data)
|
|
}
|
|
|
|
// shell writes the shell page with data (View, Body, Open, Dialog).
|
|
func (s *Server) shell(w http.ResponseWriter, r *http.Request, data map[string]any) {
|
|
data["IsAdmin"] = s.currentAdmin(r).IsAdmin()
|
|
if data["View"] == "dashboard" && data["Body"] == nil {
|
|
// The machines list under a dialog: draw it too.
|
|
var body bytes.Buffer
|
|
if err := s.tmpl.ExecuteTemplate(&body, "dashboard-body", s.dashboardData(r)); err == nil {
|
|
data["Body"] = template.HTML(body.String())
|
|
}
|
|
}
|
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
w.Header().Set("Cache-Control", "no-store")
|
|
if err := s.tmpl.ExecuteTemplate(w, "app.html", data); err != nil {
|
|
log.Printf("template app.html: %v", err)
|
|
}
|
|
}
|
|
|
|
// handleShell serves the shell alone: the terminal view, or with a pane of
|
|
// a machine opened at once (/agents/{id}/terminal, /agents/{id}/files).
|
|
func (s *Server) handleShell(w http.ResponseWriter, r *http.Request) {
|
|
data := map[string]any{"View": "terminal"}
|
|
if id := r.PathValue("id"); id != "" {
|
|
a, _ := s.db.GetAgent(id)
|
|
if a == nil {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
kind := "term"
|
|
switch r.PathValue("kind") {
|
|
case "", "terminal":
|
|
case "files":
|
|
kind = "files"
|
|
default:
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
data["Open"] = map[string]any{"kind": kind, "agent": map[string]string{"id": a.ID, "name": a.Name, "host": a.Hostname, "user": a.TerminalUser()}}
|
|
}
|
|
s.shell(w, r, data)
|
|
}
|