solved issue with the style of presentation of the agent response on the website. Added agentType to the api, agent and database

This commit is contained in:
Stefan Friese 2025-01-22 16:02:44 +00:00
parent 323c04af89
commit 9e45adfff5
8 changed files with 335 additions and 72 deletions

View File

@ -37,10 +37,9 @@ type Message struct {
Payload string `json:"payload"` Payload string `json:"payload"`
} }
var conn *websocket.Conn var conn *websocket.Conn
func registerAgent(agentName string, agentId string, agentIp string) error { func registerAgent(agentName, agentId, agentIp, agentType string) error {
// agent:= Agent{ // agent:= Agent{
// AgentName: agentName, // AgentName: agentName,
// InitialContact: time.Now().Format(time.RFC3339), // InitialContact: time.Now().Format(time.RFC3339),
@ -57,6 +56,7 @@ func registerAgent(agentName string, agentId string, agentIp string) error {
form := url.Values{} form := url.Values{}
form.Add("agentId", agentId) form.Add("agentId", agentId)
form.Add("agentName", agentName) form.Add("agentName", agentName)
form.Add("agentType", agentType)
form.Add("IPv4Address", agentIp) form.Add("IPv4Address", agentIp)
resp, err := http.PostForm(registerURL, form) resp, err := http.PostForm(registerURL, form)
@ -124,13 +124,6 @@ func listenForCommands(agentName, agentIp string) {
continue continue
} }
// for {
// _, rawMessage, err := conn.ReadMessage()
// if err != nil {
// log.Printf("Error reading message: %v", err)
// break
// }
var message Message var message Message
if err := json.Unmarshal(rawMessage, &message); err != nil { if err := json.Unmarshal(rawMessage, &message); err != nil {
log.Printf("Error unmarshalling message: %v", err) log.Printf("Error unmarshalling message: %v", err)
@ -180,8 +173,9 @@ func main() {
// agentId := "1234" // agentId := "1234"
agentId := strconv.Itoa(randomInt(5)) agentId := strconv.Itoa(randomInt(5))
agentIp := "127.0.0.1" agentIp := "127.0.0.1"
agentType := "BaseAgent"
if err := registerAgent(agentName, agentId, agentIp); err != nil { if err := registerAgent(agentName, agentId, agentIp, agentType); err != nil {
log.Fatalf("Agent registration failed: %v", err) log.Fatalf("Agent registration failed: %v", err)
} }

View File

@ -4,6 +4,7 @@ drop table if exists agents;
create table agents ( create table agents (
id UUID default uuid() Primary Key, id UUID default uuid() Primary Key,
agentId int unique, agentId int unique,
agentType varchar(255),
agentName varchar(255), agentName varchar(255),
IPv4Address varchar(15), IPv4Address varchar(15),
initialContact timestamp, initialContact timestamp,

View File

@ -135,7 +135,6 @@ func getHomepage(w http.ResponseWriter, r *http.Request) {
} }
func listAgents(w http.ResponseWriter, r *http.Request) { func listAgents(w http.ResponseWriter, r *http.Request) {
// agents, err := getAgents()
agents, err := api.GetAgents(db) agents, err := api.GetAgents(db)
if err != nil { if err != nil {
http.Error(w, "Failed to fetch agents", http.StatusInternalServerError) http.Error(w, "Failed to fetch agents", http.StatusInternalServerError)
@ -161,10 +160,6 @@ func main() {
var wg sync.WaitGroup var wg sync.WaitGroup
// webSocketHandler := webSocketHandler {
// upgrader: websocket.Upgrader{},
// }
websocketServer := websocketserver.Server() websocketServer := websocketserver.Server()
@ -185,10 +180,6 @@ func main() {
webServer := &http.Server { webServer := &http.Server {
Addr: ":3333", Addr: ":3333",
Handler: webMux, Handler: webMux,
// BaseContext: func(l net.Listener) context.Context {
// ctx = context.WithValue(ctx, keyServerAddr, l.Addr().String())
// return ctx
// },
} }
wg.Add(1) wg.Add(1)

View File

@ -11,6 +11,7 @@ import (
type Agent struct { type Agent struct {
AgentID int `json:"agentId"` AgentID int `json:"agentId"`
AgentName string `json:"agentName"` AgentName string `json:"agentName"`
AgentType string `json:"agentType"`
InitialContact string `json:"initialContact"` InitialContact string `json:"initialContact"`
LastContact string `json:"lastContact"` LastContact string `json:"lastContact"`
IPv4Address string `json:"IPv4Address"` IPv4Address string `json:"IPv4Address"`
@ -44,12 +45,13 @@ func CreateAgent(db *sql.DB, w http.ResponseWriter, r * http.Request) (http.Resp
agentName := r.FormValue("agentName") agentName := r.FormValue("agentName")
agentId := r.FormValue("agentId") agentId := r.FormValue("agentId")
agentType := r.FormValue("agentType")
IPv4Address := r.FormValue("IPv4Address") IPv4Address := r.FormValue("IPv4Address")
// initalContact := r.FormValue("initialContact") // initalContact := r.FormValue("initialContact")
// lastContact := r.FormValue("lastContact") // lastContact := r.FormValue("lastContact")
query := "INSERT INTO agents (agentId, agentName, IPv4Address, initialContact, lastContact) VALUES (?, ?, ?, NOW(), NOW())" query := "INSERT INTO agents (agentId, agentName, agentType, IPv4Address, initialContact, lastContact) VALUES (?, ?, ?, ?, NOW(), NOW())"
_, err = db.Exec(query, agentId, agentName, IPv4Address) _, err = db.Exec(query, agentId, agentName, agentType, IPv4Address)
if err != nil { if err != nil {
http.Error(w, "Failed to create agent", http.StatusInternalServerError) http.Error(w, "Failed to create agent", http.StatusInternalServerError)
return nil, err return nil, err
@ -81,7 +83,7 @@ func UpdateAgent(db *sql.DB, w http.ResponseWriter, r *http.Request, agentId str
} }
func GetAgents(db *sql.DB) ([]Agent, error) { func GetAgents(db *sql.DB) ([]Agent, error) {
query := "SELECT agentId, agentName, IPv4Address, initialContact, lastContact FROM agents" query := "SELECT agentId, agentName, agentType, IPv4Address, initialContact, lastContact FROM agents"
rows, err := db.Query(query) rows, err := db.Query(query)
if err != nil { if err != nil {
return nil, err return nil, err
@ -91,7 +93,7 @@ func GetAgents(db *sql.DB) ([]Agent, error) {
var agents []Agent var agents []Agent
for rows.Next() { for rows.Next() {
var agent Agent var agent Agent
err := rows.Scan(&agent.AgentID, &agent.AgentName, &agent.IPv4Address, &agent.InitialContact, &agent.LastContact) err := rows.Scan(&agent.AgentID, &agent.AgentName, &agent.AgentType, &agent.IPv4Address, &agent.InitialContact, &agent.LastContact)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -101,9 +103,9 @@ func GetAgents(db *sql.DB) ([]Agent, error) {
} }
func GetAgent(db *sql.DB, w http.ResponseWriter, r *http.Request, agentId string) (Agent, error) { func GetAgent(db *sql.DB, w http.ResponseWriter, r *http.Request, agentId string) (Agent, error) {
query := "Select agentId, agentName, initialContact, lastContact from agents where agentId = ?" query := "Select agentId, agentName, agentType, initialContact, lastContact from agents where agentId = ?"
var agent Agent var agent Agent
err := db.QueryRow(query, agentId).Scan(&agent.AgentID, &agent.AgentName, &agent.InitialContact, &agent.LastContact) err := db.QueryRow(query, agentId).Scan(&agent.AgentID, &agent.AgentName, &agent.AgentType, &agent.InitialContact, &agent.LastContact)
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
http.Error(w, "Agent not found", http.StatusNotFound) http.Error(w, "Agent not found", http.StatusNotFound)
return Agent{} , err return Agent{} , err

View File

@ -6,9 +6,13 @@ import (
"net/http" "net/http"
"sync" "sync"
"time"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
) )
var responseChannels sync.Map // Key: agentName, Value: chan string
type webSocketHandler struct { type webSocketHandler struct {
upgrader websocket.Upgrader upgrader websocket.Upgrader
} }
@ -29,46 +33,6 @@ var getAgentNames http.HandlerFunc = func(w http.ResponseWriter, r *http.Request
} }
// func (wsh webSocketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
// c, err := wsh.upgrader.Upgrade(w, r, nil)
// if err != nil {
// log.Printf("Error %s when upgrading connection to websocket", err)
// return
// }
// defer c.Close()
// _, agentNameBytes, err := c.ReadMessage()
// if err != nil {
// log.Printf("Failed to read agent name: %s", err)
// return
// }
// agentName := string(agentNameBytes)
// agentSocketsMutex.Lock()
// agentSockets[agentName] = c
// agentSocketsMutex.Unlock()
// log.Printf("Agent registered: %s", agentName)
// for {
// mt , message, err := c.ReadMessage()
// if err != nil {
// log.Printf("Error reading message: %s from agent: %s", err, agentName)
// }
// log.Printf("Received message: %s from agent: %s", message, agentName)
// if err = c.WriteMessage(mt, message); err !=nil {
// log.Printf("Error writing the message: %s", err)
// break
// }
// }
// agentSocketsMutex.Lock()
// delete(agentSockets, agentName)
// agentSocketsMutex.UnLock()
// log.Printf("Agent disconnected: %s", agentName)
// }
func (wsh webSocketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request){ func (wsh webSocketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request){
c, err := wsh.upgrader.Upgrade(w, r, nil) c, err := wsh.upgrader.Upgrade(w, r, nil)
if err != nil { if err != nil {
@ -99,16 +63,17 @@ func (wsh webSocketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request){
}() }()
for { for {
mt, message, err := c.ReadMessage() _, message, err := c.ReadMessage()
if err != nil { if err != nil {
log.Printf("Error reading from agent %s: %v", agentName, err) log.Printf("Error reading from agent %s: %v", agentName, err)
break break
} }
log.Printf("Message from agent %s: %s", agentName, message) log.Printf("Message from agent %s: %s", agentName, message)
if err = c.WriteMessage(mt, message); err != nil {
log.Printf("Error writing to agent %s: %v", agentName, err) if ch, ok := responseChannels.Load(agentName); ok {
break responseChan := ch.(chan string)
responseChan <- string(message)
} }
} }
} }
@ -137,6 +102,10 @@ var executeCommand http.HandlerFunc = func(w http.ResponseWriter, r *http.Reques
return return
} }
responseChan := make(chan string, 1)
responseChannels.Store(agentName, responseChan)
defer responseChannels.Delete(agentName)
message := Message { message := Message {
Type: "command", Type: "command",
Payload: command, Payload: command,
@ -150,8 +119,24 @@ var executeCommand http.HandlerFunc = func(w http.ResponseWriter, r *http.Reques
return return
} }
w.WriteHeader(http.StatusOK) select {
w.Write([]byte("Command sent successfully")) case response := <-responseChan:
var parsedResponse map[string]string
if err := json.Unmarshal([]byte(response), &parsedResponse); err != nil {
http.Error(w, "Failed to parse response", http.StatusInternalServerError)
return
}
payload, ok := parsedResponse["payload"]
if !ok {
http.Error(w, "Invalid response structure", http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "text/plain")
w.Write([]byte(payload))
case <- time.After(10 * time.Second):
http.Error(w, "Agent repsonse timed out", http.StatusGatewayTimeout)
}
} }
func Server() (*http.Server) { func Server() (*http.Server) {

View File

@ -1,3 +1,288 @@
<!-- <!DOCTYPE html> -->
<!-- <html lang="en"> -->
<!-- <head> -->
<!-- <meta charset="UTF-8"> -->
<!-- <meta http-equiv="X-UA-Compatible" content="IE=edge"> -->
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
<!-- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> -->
<!-- <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script> -->
<!-- <script src="https://unpkg.com/htmx.org@1.9.12"></script> -->
<!-- <title>g2: gommand & gontrol</title> -->
<!-- <script> -->
<!-- document.addEventListener('DOMContentLoaded', () => { -->
<!-- // Fetch agent names to populate the dropdown -->
<!-- fetch('/agentNames') -->
<!-- .then(response => response.json()) -->
<!-- .then(agentNames => { -->
<!-- const dropdown = document.getElementById('agentName'); -->
<!-- agentNames.forEach(name => { -->
<!-- const option = document.createElement('option'); -->
<!-- option.value = name; -->
<!-- option.textContent = name; -->
<!-- dropdown.appendChild(option); -->
<!-- }); -->
<!-- }) -->
<!-- .catch(error => console.error('Error fetching agent names:', error)); -->
<!-- // WebSocket setup -->
<!-- const socket = new WebSocket("ws://localhost:5555/data"); -->
<!-- // Handle WebSocket messages -->
<!-- socket.onmessage = (event) => { -->
<!-- const message = JSON.parse(event.data); -->
<!-- if (message.type === 'response') { -->
<!-- const output = document.getElementById('commandOutput'); -->
<!-- output.textContent = message.payload; // Display the agent's response -->
<!-- } -->
<!-- }; -->
<!-- // Handle WebSocket errors -->
<!-- socket.onerror = (error) => { -->
<!-- console.error("WebSocket error:", error); -->
<!-- }; -->
<!-- // Handle WebSocket closure -->
<!-- socket.onclose = () => { -->
<!-- console.warn('WebSocket connection closed.'); -->
<!-- }; -->
<!-- // Intercept HTMX requests for /executeCommand -->
<!-- document.body.addEventListener('htmx:beforeRequest', (evt) => { -->
<!-- const url = evt.detail.pathInfo.requestPath; -->
<!-- if (url === '/executeCommand') { -->
<!-- evt.preventDefault(); // Stop HTMX from processing the request -->
<!-- // Collect form data -->
<!-- const formData = new FormData(evt.detail.elt); -->
<!-- const payload = new URLSearchParams(formData); // Convert form data to query string -->
<!-- // Send form data using fetch -->
<!-- fetch('http://localhost:5555/executeCommand', { -->
<!-- method: 'POST', -->
<!-- headers: { -->
<!-- 'Content-Type': 'application/x-www-form-urlencoded', -->
<!-- }, -->
<!-- body: payload, -->
<!-- }).then((response) => { -->
<!-- if (!response.ok) { -->
<!-- console.error('Failed to execute command:', response.statusText); -->
<!-- } -->
<!-- console.log(response) -->
<!-- }); -->
<!-- } -->
<!-- }); -->
<!-- }); -->
<!-- </script> -->
<!-- </head> -->
<!-- <body> -->
<!-- <div class="container"> -->
<!-- <div class="row"> -->
<!-- <div class="col"> -->
<!-- <h2>Agents</h2> -->
<!-- <!-1- Agent List -1-> -->
<!-- <div id="agentList" hx-get="/agents" hx-trigger="load" hx-swap="innerHTML"></div> -->
<!-- <!-1- Command Execution -1-> -->
<!-- <div id="agentCommands"> -->
<!-- <h3>Command Execution</h3> -->
<!-- <form hx-post="/executeCommand" hx-target="#commandOutput" hx-encoding="application/x-www-form-urlencoded" hx-swap="innerHTML"> -->
<!-- <div class="mb-3"> -->
<!-- <label for="agentName" class="form-label">Agent Name</label> -->
<!-- <select class="form-select" id="agentName" name="agentName" required> -->
<!-- <!-1- Dynamically populated with agent names -1-> -->
<!-- </select> -->
<!-- </div> -->
<!-- <div class="mb-3"> -->
<!-- <label for="command" class="form-label">Command</label> -->
<!-- <input type="text" class="form-control" id="command" name="command" placeholder="Enter command" required> -->
<!-- </div> -->
<!-- <button type="submit" class="btn btn-primary">Execute</button> -->
<!-- </form> -->
<!-- <div id="commandOutput" class="mt-3 p-2 border">Here goes the output...</div> -->
<!-- </div> -->
<!-- <!-1- Add Agent Form -1-> -->
<!-- <button class="btn btn-primary mt-3" data-bs-toggle="collapse" data-bs-target="#addAgentForm">Add Agent</button> -->
<!-- <div id="addAgentForm" class="collapse mt-2"> -->
<!-- <form hx-post="/agents" hx-target="#agentList" hx-swap="innerHTML"> -->
<!-- <div class="mb-3"> -->
<!-- <label for="agentId" class="form-label">Agent Id</label> -->
<!-- <input type="text" class="form-control" id="agentId" name="agentId" required> -->
<!-- </div> -->
<!-- <div class="mb-3"> -->
<!-- <label for="agentName" class="form-label">Agent Name</label> -->
<!-- <input type="text" class="form-control" id="agentNameInput" name="agentName" required> -->
<!-- </div> -->
<!-- <div class="mb-3"> -->
<!-- <label for="IPv4Address" class="form-label">IPv4 Address</label> -->
<!-- <input type="text" class="form-control" id="IPv4Address" name="IPv4Address" required> -->
<!-- </div> -->
<!-- <div class="mb-3"> -->
<!-- <label for="initialContact" class="form-label">Initial Contact</label> -->
<!-- <input type="datetime-local" class="form-control" id="initialContact" name="initialContact" required> -->
<!-- </div> -->
<!-- <div class="mb-3"> -->
<!-- <label for="lastContact" class="form-label">Last Contact</label> -->
<!-- <input type="datetime-local" class="form-control" id="lastContact" name="lastContact" required> -->
<!-- </div> -->
<!-- <button type="submit" class="btn btn-success">Add Agent</button> -->
<!-- </form> -->
<!-- </div> -->
<!-- </div> -->
<!-- <!-1- Agent Details -1-> -->
<!-- <div class="col" id="agentDetails"> -->
<!-- <h3>Details</h3> -->
<!-- <p>Select an agent to view details.</p> -->
<!-- </div> -->
<!-- </div> -->
<!-- </div> -->
<!-- </body> -->
<!-- </html> -->
<!-- <!DOCTYPE html> -->
<!-- <html lang="en"> -->
<!-- <head> -->
<!-- <meta charset="UTF-8"> -->
<!-- <meta http-equiv="X-UA-Compatible" content="IE=edge"> -->
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
<!-- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous"> -->
<!-- <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script> -->
<!-- <script src="https://unpkg.com/htmx.org@1.9.12"></script> -->
<!-- <title>g2: gommand & gontrol</title> -->
<!-- <script> -->
<!-- document.addEventListener('DOMContentLoaded', () => { -->
<!-- // Fetch agent names to populate the dropdown -->
<!-- fetch('/agentNames') -->
<!-- .then(response => response.json()) -->
<!-- .then(agentNames => { -->
<!-- const dropdown = document.getElementById('agentName'); -->
<!-- agentNames.forEach(name => { -->
<!-- const option = document.createElement('option'); -->
<!-- option.value = name; -->
<!-- option.textContent = name; -->
<!-- dropdown.appendChild(option); -->
<!-- }); -->
<!-- }) -->
<!-- .catch(error => console.error('Error fetching agent names:', error)); -->
<!-- // WebSocket setup for listening to agent responses -->
<!-- const socket = new WebSocket("ws://localhost:5555/executeCommand"); -->
<!-- // Handle WebSocket messages -->
<!-- socket.onmessage = (event) => { -->
<!-- const message = JSON.parse(event.data); -->
<!-- if (message.type === 'response') { -->
<!-- const output = document.getElementById('commandOutput'); -->
<!-- output.textContent = message.payload; // Display the agent's response -->
<!-- } -->
<!-- }; -->
<!-- // Handle WebSocket errors -->
<!-- socket.onerror = (error) => { -->
<!-- console.error("WebSocket error:", error); -->
<!-- }; -->
<!-- // Handle WebSocket closure -->
<!-- socket.onclose = () => { -->
<!-- console.warn('WebSocket connection closed.'); -->
<!-- }; -->
<!-- // Intercept HTMX requests for /executeCommand to send via WebSocket -->
<!-- document.body.addEventListener('htmx:beforeRequest', (evt) => { -->
<!-- const url = evt.detail.pathInfo.requestPath; -->
<!-- if (url === '/executeCommand') { -->
<!-- evt.preventDefault(); // Stop HTMX from processing the request -->
<!-- // Collect form data -->
<!-- const formData = new FormData(evt.detail.elt); -->
<!-- const payload = new URLSearchParams(formData); // Convert form data to query string -->
<!-- // Send form data using fetch -->
<!-- fetch('http://localhost:5555/executeCommand', { -->
<!-- method: 'POST', -->
<!-- headers: { -->
<!-- 'Content-Type': 'application/x-www-form-urlencoded', -->
<!-- }, -->
<!-- body: payload, -->
<!-- }).then((response) => { -->
<!-- if (!response.ok) { -->
<!-- console.error('Failed to execute command:', response.statusText); -->
<!-- } -->
<!-- }); -->
<!-- } -->
<!-- }); -->
<!-- }); -->
<!-- </script> -->
<!-- </head> -->
<!-- <body> -->
<!-- <div class="container"> -->
<!-- <div class="row"> -->
<!-- <div class="col"> -->
<!-- <h2>Agents</h2> -->
<!-- <!-1- Agent List -1-> -->
<!-- <div id="agentList" hx-get="/agents" hx-trigger="load" hx-swap="innerHTML"></div> -->
<!-- <!-1- Command Execution -1-> -->
<!-- <div id="agentCommands"> -->
<!-- <h3>Command Execution</h3> -->
<!-- <form hx-post="/executeCommand" hx-target="#commandOutput" hx-encoding="application/x-www-form-urlencoded" hx-swap="innerHTML"> -->
<!-- <div class="mb-3"> -->
<!-- <label for="agentName" class="form-label">Agent Name</label> -->
<!-- <select class="form-select" id="agentName" name="agentName" required> -->
<!-- <!-1- Dynamically populated with agent names -1-> -->
<!-- </select> -->
<!-- </div> -->
<!-- <div class="mb-3"> -->
<!-- <label for="command" class="form-label">Command</label> -->
<!-- <input type="text" class="form-control" id="command" name="command" placeholder="Enter command" required> -->
<!-- </div> -->
<!-- <button type="submit" class="btn btn-primary">Execute</button> -->
<!-- </form> -->
<!-- <div id="commandOutput" class="mt-3 p-2 border">Here goes the output...</div> -->
<!-- </div> -->
<!-- <!-1- Add Agent Form -1-> -->
<!-- <button class="btn btn-primary mt-3" data-bs-toggle="collapse" data-bs-target="#addAgentForm">Add Agent</button> -->
<!-- <div id="addAgentForm" class="collapse mt-2"> -->
<!-- <form hx-post="/agents" hx-target="#agentList" hx-swap="innerHTML"> -->
<!-- <div class="mb-3"> -->
<!-- <label for="agentId" class="form-label">Agent Id</label> -->
<!-- <input type="text" class="form-control" id="agentId" name="agentId" required> -->
<!-- </div> -->
<!-- <div class="mb-3"> -->
<!-- <label for="agentName" class="form-label">Agent Name</label> -->
<!-- <input type="text" class="form-control" id="agentNameInput" name="agentName" required> -->
<!-- </div> -->
<!-- <div class="mb-3"> -->
<!-- <label for="IPv4Address" class="form-label">IPv4 Address</label> -->
<!-- <input type="text" class="form-control" id="IPv4Address" name="IPv4Address" required> -->
<!-- </div> -->
<!-- <div class="mb-3"> -->
<!-- <label for="initialContact" class="form-label">Initial Contact</label> -->
<!-- <input type="datetime-local" class="form-control" id="initialContact" name="initialContact" required> -->
<!-- </div> -->
<!-- <div class="mb-3"> -->
<!-- <label for="lastContact" class="form-label">Last Contact</label> -->
<!-- <input type="datetime-local" class="form-control" id="lastContact" name="lastContact" required> -->
<!-- </div> -->
<!-- <button type="submit" class="btn btn-success">Add Agent</button> -->
<!-- </form> -->
<!-- </div> -->
<!-- </div> -->
<!-- <!-1- Agent Details -1-> -->
<!-- <div class="col" id="agentDetails"> -->
<!-- <h3>Details</h3> -->
<!-- <p>Select an agent to view details.</p> -->
<!-- </div> -->
<!-- </div> -->
<!-- </div> -->
<!-- </body> -->
<!-- </html> -->
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -37,7 +322,9 @@
const message = JSON.parse(event.data); const message = JSON.parse(event.data);
if (message.type === 'response') { if (message.type === 'response') {
const output = document.getElementById('commandOutput'); const output = document.getElementById('commandOutput');
output.textContent = message.payload; output.textContent = "";
output.innerText = message.payload.trim();
console.log("Raw websocket Data:", event.data);
} }
}; };

View File

@ -2,6 +2,7 @@
<h2>Agent Details</h2> <h2>Agent Details</h2>
<p>ID: {{.AgentID}}</p> <p>ID: {{.AgentID}}</p>
<p>Name: {{.AgentName}}</p> <p>Name: {{.AgentName}}</p>
<p>Type: {{.AgentType}}</p>
<p>Initial Contact: {{.InitialContact}}</p> <p>Initial Contact: {{.InitialContact}}</p>
<p>Last Contact: {{.LastContact}}</p> <p>Last Contact: {{.LastContact}}</p>
<button hx-get="/agents" hx-target="#agentList" hx-swap="innerHTML">Back to List</button> <button hx-get="/agents" hx-target="#agentList" hx-swap="innerHTML">Back to List</button>

View File

@ -3,6 +3,7 @@
<tr> <tr>
<th>ID</th> <th>ID</th>
<th>Name</th> <th>Name</th>
<th>Type</th>
<th>IPv4 Address</th> <th>IPv4 Address</th>
<th>Initial Contact</th> <th>Initial Contact</th>
<th>Last Contact</th> <th>Last Contact</th>
@ -14,6 +15,7 @@
<tr> <tr>
<td>{{.AgentID}}</td> <td>{{.AgentID}}</td>
<td>{{.AgentName}}</td> <td>{{.AgentName}}</td>
<td>{{.AgentType}}</td>
<td>{{.IPv4Address}}</td> <td>{{.IPv4Address}}</td>
<td>{{.InitialContact}}</td> <td>{{.InitialContact}}</td>
<td>{{.LastContact}}</td> <td>{{.LastContact}}</td>