From d6fc2e41185ef519270979d98c3abe4a57464fe8 Mon Sep 17 00:00:00 2001 From: Erik Brakkee Date: Wed, 31 Jul 2024 21:12:09 +0200 Subject: [PATCH] Rendering status as HTML tables. --- cmd/converge/converge.go | 6 ++- cmd/converge/pagehandler.go | 8 ++- cmd/templaterender/render.go | 42 ++++++++++++++- kubernetes/deployment.yaml | 2 - pkg/server/converge/websessions.go | 25 +++++++-- pkg/server/templates/sessions.templ | 80 +++++++++++++++++++++++++---- 6 files changed, 145 insertions(+), 18 deletions(-) diff --git a/cmd/converge/converge.go b/cmd/converge/converge.go index 50c8598..39370d8 100644 --- a/cmd/converge/converge.go +++ b/cmd/converge/converge.go @@ -140,7 +140,11 @@ func main() { Handler: func(w http.ResponseWriter, r *http.Request, conn net.Conn) { websession := websessions.NewSession(conn) defer websessions.SessionClosed(websession) - websession.WriteNotifications() + location, err := converge.GetUserLocation(r) + if err != nil { + panic(err) + } + websession.WriteNotifications(location) }, Text: true, } diff --git a/cmd/converge/pagehandler.go b/cmd/converge/pagehandler.go index 8e6f154..e0909cc 100644 --- a/cmd/converge/pagehandler.go +++ b/cmd/converge/pagehandler.go @@ -1,6 +1,7 @@ package main import ( + "converge/pkg/server/converge" templates2 "converge/pkg/server/templates" "net/http" "os" @@ -24,6 +25,11 @@ func pageHandler(w http.ResponseWriter, r *http.Request) { } username, _ := os.LookupEnv("CONVERGE_USERNAME") + location, err := converge.GetUserLocation(r) + if err != nil { + panic(err) + } + switch r.URL.Path { case "": fallthrough @@ -36,7 +42,7 @@ func pageHandler(w http.ResponseWriter, r *http.Request) { case "downloads.html": templates2.DownloadsTab().Render(r.Context(), w) case "sessions.html": - templates2.SessionsTab().Render(r.Context(), w) + templates2.SessionsTab(nil, location).Render(r.Context(), w) default: http.NotFound(w, r) } diff --git a/cmd/templaterender/render.go b/cmd/templaterender/render.go index 88a92d8..75bc8bc 100644 --- a/cmd/templaterender/render.go +++ b/cmd/templaterender/render.go @@ -2,11 +2,14 @@ package main import ( "context" + "converge/pkg/comms" + "converge/pkg/models" templates2 "converge/pkg/server/templates" "github.com/a-h/templ" "log" "os" "path/filepath" + "time" ) type RenderFunc func() templ.Component @@ -29,6 +32,11 @@ func render(dir string, name string, render RenderFunc) { func main() { dir := "html/docs" + netherlands, err := time.LoadLocation("Europe/Amsterdam") + if err != nil { + panic(err) + } + fullindex := func() templ.Component { return templates2.Index("s", "example.com", "converge") } @@ -41,5 +49,37 @@ func main() { render(dir, "usage.html", usage) render(dir, "downloads.html", templates2.Downloads) - render(dir, "sessions.html", templates2.SessionsTab) + render(dir, "sessions-none.html", func() templ.Component { + return templates2.SessionsTab(nil, netherlands) + }) + render(dir, "sessions.html", func() templ.Component { + + japan, err := time.LoadLocation("Asia/Tokyo") + if err != nil { + panic(err) + } + + state := models.State{} + agent := models.Agent{ + PublicId: "id", + StartTime: time.Now().In(japan), + AgentInfo: comms.AgentInfo{ + Username: "ci", + Hostname: "container123", + Pwd: "/home/ci", + OS: "linux", + Shell: "/bin/bash", + }, + ExpiryTime: time.Now().In(japan).Add(10 * time.Minute), + } + state.Agents = append(state.Agents, agent) + client := models.Client{ + PublicId: "c1", + ClientId: 3, + StartTime: time.Now().In(japan), + SessionType: "sftp", + } + state.Clients = append(state.Clients, client) + return templates2.SessionsTab(&state, netherlands) + }) } diff --git a/kubernetes/deployment.yaml b/kubernetes/deployment.yaml index 88ec4d3..120a39c 100644 --- a/kubernetes/deployment.yaml +++ b/kubernetes/deployment.yaml @@ -27,7 +27,5 @@ spec: - name: CONVERGE_PASSWORD # change this password in your final deployment value: "abc123" - - name: TZ - value: Europe/Amsterdam diff --git a/pkg/server/converge/websessions.go b/pkg/server/converge/websessions.go index 2ebc4cb..dec63fe 100644 --- a/pkg/server/converge/websessions.go +++ b/pkg/server/converge/websessions.go @@ -6,6 +6,7 @@ import ( "converge/pkg/server/templates" "log" "net" + "net/http" "sync" "time" ) @@ -57,7 +58,25 @@ func (sessions *WebSessions) NewSession(wsConnection net.Conn) *WebSession { return session } -func (session *WebSession) WriteNotifications() { +func GetUserLocation(r *http.Request) (*time.Location, error) { + // Try to get timezone from a custom header + tzName := r.Header.Get("X-Timezone") + + // If not found in header, try to get from query parameter + if tzName == "" { + tzName = r.URL.Query().Get("tz") + } + + // If still not found, default to UTC + if tzName == "" { + tzName = "UTC" + } + + // Load the location + return time.LoadLocation(tzName) +} + +func (session *WebSession) WriteNotifications(location *time.Location) { timer := time.NewTicker(10 * time.Second) defer timer.Stop() for { @@ -66,8 +85,8 @@ func (session *WebSession) WriteNotifications() { if !ok { log.Println("channel closed") } - log.Println("Got notification: ", notification.Ascii) - err := templates.State(notification).Render(context.Background(), session.conn) + //log.Println("Got notification: ", notification) + err := templates.State(notification, location).Render(context.Background(), session.conn) if err != nil { log.Printf("WS connection closed: %v", err) return diff --git a/pkg/server/templates/sessions.templ b/pkg/server/templates/sessions.templ index 84fe631..2d1f485 100644 --- a/pkg/server/templates/sessions.templ +++ b/pkg/server/templates/sessions.templ @@ -1,34 +1,94 @@ package templates -import "converge/pkg/models" +import ( + "converge/pkg/models" + "strconv" + "time" + _ "time/tzdata" +) -templ Sessions(state *models.State) { +templ Sessions(state *models.State, loc *time.Location) {

sessions

if state != nil { - @State(state) + @State(state, loc) } else { - "Loading..." + Loading... }
} -templ State(state *models.State) { +templ State(state *models.State, location *time.Location) {
-
-     { state.Ascii }
-   
+ +

agents

+ + if len(state.Agents) == 0 { +

-

+ } else { + + + + + + + + + + + + + for _, agent := range state.Agents { + + + + + + + + + + } +
idstart timeexpiry timeusernamehostOSshell
{agent.PublicId}{agent.StartTime.In(location).Format(time.DateTime)}{agent.ExpiryTime.In(location).Format(time.DateTime)}{agent.AgentInfo.Username}{agent.AgentInfo.Hostname}{agent.AgentInfo.OS}{agent.AgentInfo.Shell}
+ + } + + +

clients

+ + if len(state.Clients) == 0 { +

-

+ } else { + + + + + + + + + + for _, client := range state.Clients { + + + + + + + } +
agent ididstart timesession type
{client.PublicId}{strconv.Itoa(client.ClientId)}{client.StartTime.In(location).Format(time.DateTime)}{client.SessionType}
+ }
} -templ SessionsTab() { +templ SessionsTab(state *models.State, loc *time.Location) { @BasePage(4) { - @Sessions(nil) + @Sessions(state, loc) } } \ No newline at end of file