added weblogger to display logs, timestamps and levels on the webpage
This commit is contained in:
		
							parent
							
								
									0498013d1d
								
							
						
					
					
						commit
						6ea4d31109
					
				| 
						 | 
				
			
			@ -5,3 +5,4 @@ build/
 | 
			
		|||
build/*
 | 
			
		||||
pkg/*
 | 
			
		||||
agents/agents
 | 
			
		||||
logs.db
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,7 @@ import (
 | 
			
		|||
	"math/rand"
 | 
			
		||||
	"math"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	// "gontrol/src/logger"
 | 
			
		||||
 | 
			
		||||
	"github.com/gorilla/websocket"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -57,6 +58,7 @@ func registerAgent(agentName, agentId, agentIp, agentType string) error {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	log.Printf("Agent %s successfully registered.", agentName)
 | 
			
		||||
	logger.LogEntries = append(logger.LogEntries, fmt.Sprintf("%s Agent successfully registered.", time.Now().Format(time.RFC3339)))
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -67,6 +69,7 @@ func connectToWebSocket(agentName, agentId, agentIp, agentType string) error {
 | 
			
		|||
		conn, _, err = websocket.DefaultDialer.Dial(wsURL, nil)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			log.Println("WeSocket connection established")
 | 
			
		||||
			// logger.LogEntries = append(logger.LogEntries, fmt.Sprintf("%s websocket established", time.Now().Format(time.RFC3339)))
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										1
									
								
								go.mod
								
								
								
								
							| 
						 | 
				
			
			@ -7,6 +7,7 @@ require (
 | 
			
		|||
	github.com/go-sql-driver/mysql v1.8.1
 | 
			
		||||
	github.com/gorilla/websocket v1.5.3
 | 
			
		||||
	github.com/kelseyhightower/envconfig v1.4.0
 | 
			
		||||
	github.com/mattn/go-sqlite3 v1.14.28
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										2
									
								
								go.sum
								
								
								
								
							| 
						 | 
				
			
			@ -11,6 +11,8 @@ github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aN
 | 
			
		|||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
 | 
			
		||||
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
 | 
			
		||||
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
 | 
			
		||||
github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A=
 | 
			
		||||
github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
 | 
			
		||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										48
									
								
								main.go
								
								
								
								
							
							
						
						
									
										48
									
								
								main.go
								
								
								
								
							| 
						 | 
				
			
			@ -16,6 +16,7 @@ import (
 | 
			
		|||
 | 
			
		||||
	"gontrol/src/randomname"
 | 
			
		||||
	"gontrol/src/server/database"
 | 
			
		||||
	"gontrol/src/logger"
 | 
			
		||||
	api "gontrol/src/server/api"
 | 
			
		||||
	websocketserver "gontrol/src/server/websocket"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -25,8 +26,10 @@ import (
 | 
			
		|||
	"github.com/kelseyhightower/envconfig"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var tmpl *template.Template
 | 
			
		||||
var db 	 *sql.DB
 | 
			
		||||
var (
 | 
			
		||||
	tmpl *template.Template
 | 
			
		||||
	db 	 *sql.DB
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type Config struct {
 | 
			
		||||
	Database struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -135,6 +138,24 @@ func getAgentIds(w http.ResponseWriter, r *http.Request) {
 | 
			
		|||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func logsHandler(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
 | 
			
		||||
	logs, err := logger.FetchLogs(10)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		http.Error(w, "Error fetching logs", http.StatusInternalServerError)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fmt.Fprintf(w, "<div>")
 | 
			
		||||
	// for _, logEntry := range logsToSend {
 | 
			
		||||
	for _, logEntry := range logs {
 | 
			
		||||
		fmt.Fprintf(w, "<p><strong>[%s] [%s]</strong> %s</p>", logEntry.Timestamp, logEntry.Level, logEntry.Message)
 | 
			
		||||
	}
 | 
			
		||||
	fmt.Fprintf(w, "</div>")
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
func main() {
 | 
			
		||||
 | 
			
		||||
	var cfg Config
 | 
			
		||||
| 
						 | 
				
			
			@ -153,8 +174,16 @@ func main() {
 | 
			
		|||
	webMux.HandleFunc("/agentNames", getAgentNames)
 | 
			
		||||
	webMux.HandleFunc("/agentIds", getAgentIds)
 | 
			
		||||
	webMux.HandleFunc("/agents/{agentId}", agentsHandler)
 | 
			
		||||
	webMux.HandleFunc("/logs", logsHandler)
 | 
			
		||||
 | 
			
		||||
	// Sqlite3
 | 
			
		||||
	err := logger.InitDB("/tmp/gontrol_logs.db")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	defer logger.CloseDB()
 | 
			
		||||
	// initDB (cfg.Database.Username, cfg.Database.Password, cfg.Database.Host, cfg.Database.Port, cfg.Database.Name)
 | 
			
		||||
	// mysql
 | 
			
		||||
	db = database.InitDB (cfg.Database.Username, cfg.Database.Password, cfg.Database.Host, cfg.Database.Port, cfg.Database.Name)
 | 
			
		||||
	defer db.Close()
 | 
			
		||||
	name := randomname.GenerateRandomName()
 | 
			
		||||
| 
						 | 
				
			
			@ -168,20 +197,31 @@ func main() {
 | 
			
		|||
	wg.Add(1)
 | 
			
		||||
	go func() {
 | 
			
		||||
		defer wg.Done()
 | 
			
		||||
		log.Println("Websocket server is running on port 5555")
 | 
			
		||||
		logLine := "Websocket server is running on port 5555"
 | 
			
		||||
		log.Println(logLine)
 | 
			
		||||
		if err := websocketServer.ListenAndServe(); err != http.ErrServerClosed {
 | 
			
		||||
			log.Fatalf("Websocket server failed: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
		err = logger.InsertLog(logger.Info, logLine)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Println("Error inserting log:", err)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	wg.Add(1)
 | 
			
		||||
	go func() {
 | 
			
		||||
		defer wg.Done()
 | 
			
		||||
		log.Println("Web server is running on port 3333")
 | 
			
		||||
		logLine := "Web server is running on port 3333"
 | 
			
		||||
		log.Println(logLine)
 | 
			
		||||
 | 
			
		||||
		if err := webServer.ListenAndServe(); err != http.ErrServerClosed {
 | 
			
		||||
			log.Fatalf("Web server failed: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		err = logger.InsertLog(logger.Info, logLine)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Println("Error inserting log:", err)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	shutdownCh := make(chan os.Signal, 1)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,127 @@
 | 
			
		|||
package logger
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	// "net/http"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	_ "github.com/mattn/go-sqlite3"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	Lite_db *sql.DB
 | 
			
		||||
	lite_dbMutex sync.Mutex
 | 
			
		||||
 | 
			
		||||
	logMutex sync.Mutex
 | 
			
		||||
	logLimit = 10
 | 
			
		||||
	// LogEntries []string
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
    Debug   LogLevel = "DEBUG"
 | 
			
		||||
    Info    LogLevel = "INFO"
 | 
			
		||||
    Warning LogLevel = "WARNING"
 | 
			
		||||
    Error   LogLevel = "ERROR"
 | 
			
		||||
    Fatal   LogLevel = "FATAL"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type LogLevel string
 | 
			
		||||
 | 
			
		||||
type LogEntry struct {
 | 
			
		||||
	Message 	string
 | 
			
		||||
	Timestamp 	string
 | 
			
		||||
	Level 		LogLevel
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func ToLog(logLine string) string {
 | 
			
		||||
	log := fmt.Sprintf("%s",time.Now().Format(time.RFC3339) + " " + logLine)
 | 
			
		||||
	return log
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func InitDB(dbPath string) error {
 | 
			
		||||
	var err error
 | 
			
		||||
	Lite_db, err = sql.Open("sqlite3", dbPath)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("Error opening DB: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	CreateTableQuery := `CREATE TABLE IF NOT EXISTS logs (
 | 
			
		||||
		id INTEGER PRIMARY KEY AUTOINCREMENT,
 | 
			
		||||
		message TEXT,
 | 
			
		||||
		timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
 | 
			
		||||
		level TEXT
 | 
			
		||||
	);`
 | 
			
		||||
 | 
			
		||||
	_, err = Lite_db.Exec(CreateTableQuery)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("Error creating table: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func InsertLog(level LogLevel, message string) error {
 | 
			
		||||
	lite_dbMutex.Lock()
 | 
			
		||||
	defer lite_dbMutex.Unlock()
 | 
			
		||||
 | 
			
		||||
	// Future use may fulfill multiple transactions, a transaction is used
 | 
			
		||||
	tx, err := Lite_db.Begin()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("Error starting transaction: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// insertQuery := `INSERT INTO logs (message) VALUES (?)`
 | 
			
		||||
	insertQuery := `INSERT INTO logs (message, level) VALUES (?, ?)`
 | 
			
		||||
	// _, err := Lite_db.Exec(insertQuery, message, level)
 | 
			
		||||
	_, err = tx.Exec(insertQuery, message, level)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		tx.Rollback()
 | 
			
		||||
		return fmt.Errorf("Error inserting log: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = tx.Commit()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("Error committing transaction: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func FetchLogs(limit int) ([]LogEntry, error) {
 | 
			
		||||
	lite_dbMutex.Lock()
 | 
			
		||||
	defer lite_dbMutex.Unlock()
 | 
			
		||||
 | 
			
		||||
	query := `SELECT timestamp, level, message FROM logs ORDER BY timestamp DESC LIMIT ?`
 | 
			
		||||
	rows, err := Lite_db.Query(query, limit)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return  nil, fmt.Errorf("Error fetching logs: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer rows.Close()
 | 
			
		||||
 | 
			
		||||
	// var logs []string
 | 
			
		||||
	var logs []LogEntry
 | 
			
		||||
	for rows.Next() {
 | 
			
		||||
		// var message string
 | 
			
		||||
		var logEntry LogEntry
 | 
			
		||||
		if err := rows.Scan( &logEntry.Timestamp, &logEntry.Level, &logEntry.Message); err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("Error scanning row: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
		logs = append(logs, logEntry)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return logs, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func CloseDB() {
 | 
			
		||||
	if Lite_db != nil {
 | 
			
		||||
		err := Lite_db.Close()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Printf("Error closing database: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -6,6 +6,7 @@ import (
 | 
			
		|||
	"encoding/json"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"log"
 | 
			
		||||
	// "gontrol/src/logger"
 | 
			
		||||
 | 
			
		||||
	_ "github.com/go-sql-driver/mysql"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,8 @@ package websocketserver
 | 
			
		|||
import (
 | 
			
		||||
	"database/sql"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"gontrol/src/logger"
 | 
			
		||||
	"gontrol/src/randomname"
 | 
			
		||||
	"gontrol/src/server/api"
 | 
			
		||||
	"io"
 | 
			
		||||
| 
						 | 
				
			
			@ -63,7 +65,10 @@ func registerAgent(agentName, agentId, agentIp, agentType string) error {
 | 
			
		|||
	defer resp.Body.Close()
 | 
			
		||||
 | 
			
		||||
	if resp.StatusCode == http.StatusCreated {
 | 
			
		||||
		log.Printf("Agent %s successfully registered.", agentName)
 | 
			
		||||
		logLine := fmt.Sprintf("Agent %s successfully registered.", agentName)
 | 
			
		||||
		log.Printf(logLine)
 | 
			
		||||
		// logLine = logger.ToLog(logLine)
 | 
			
		||||
		logger.InsertLog(logger.Info, logLine)
 | 
			
		||||
		return nil
 | 
			
		||||
	} else if resp.StatusCode == http.StatusOK {
 | 
			
		||||
		log.Printf("Agent %s already registered.", agentName)
 | 
			
		||||
| 
						 | 
				
			
			@ -81,14 +86,14 @@ func getAgentDetails(agentId string) (*api.Agent, error) {
 | 
			
		|||
	// var ids []string
 | 
			
		||||
	resp, err := http.Get(agentURL)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("Failed to make GET request: %w", err)
 | 
			
		||||
		log.Printf("Failed to make GET request: %s", err)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
 | 
			
		||||
	doc, err := goquery.NewDocumentFromReader(resp.Body)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("Failed to parse HTML: %w", err)
 | 
			
		||||
		log.Printf("Failed to parse HTML: %s", err)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -98,7 +103,7 @@ func getAgentDetails(agentId string) (*api.Agent, error) {
 | 
			
		|||
		if strings.HasPrefix(text, "ID:") {
 | 
			
		||||
			agent.AgentID, err = strconv.Atoi(strings.TrimSpace(strings.TrimPrefix(text, "ID:")))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Printf("Converting string to integer failed in getAgentDetails(): %w", err)
 | 
			
		||||
				log.Printf("Converting string to integer failed in getAgentDetails(): %s", err)
 | 
			
		||||
			}
 | 
			
		||||
		} else if strings.HasPrefix(text, "Name:") {
 | 
			
		||||
			agent.AgentName = strings.TrimSpace(strings.TrimPrefix(text, "Name:"))
 | 
			
		||||
| 
						 | 
				
			
			@ -124,7 +129,7 @@ func getAgentIds() ([]string, error) {
 | 
			
		|||
	// var ids []string
 | 
			
		||||
	resp, err := http.Get(idURL)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("Failed to make GET request: %w", err)
 | 
			
		||||
		log.Printf("Failed to make GET request: %s", err)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer resp.Body.Close()
 | 
			
		||||
| 
						 | 
				
			
			@ -136,13 +141,13 @@ func getAgentIds() ([]string, error) {
 | 
			
		|||
 | 
			
		||||
	body, err := io.ReadAll(resp.Body)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Printf("Failed to read response body: %w", err)
 | 
			
		||||
		log.Printf("Failed to read response body: %s", err)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var agentIds []string
 | 
			
		||||
	if err := json.Unmarshal(body, &agentIds); err != nil {
 | 
			
		||||
		log.Printf("Failed to parse JSON response: %w", err)
 | 
			
		||||
		log.Printf("Failed to parse JSON response: %s", err)
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -182,7 +187,9 @@ func (wsh webSocketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request){
 | 
			
		|||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log.Printf("Agent %s connected: %s (%s)", agentId, agentName, agentIP)
 | 
			
		||||
	logLine := fmt.Sprintf("Agent %s connected: %s (%s)", agentId, agentName, agentIP)
 | 
			
		||||
	log.Printf(logLine)
 | 
			
		||||
	logger.InsertLog(logger.Info, logLine)
 | 
			
		||||
 | 
			
		||||
	agentSocketsMutex.Lock()
 | 
			
		||||
	agentSockets[agentName] = c
 | 
			
		||||
| 
						 | 
				
			
			@ -193,17 +200,22 @@ func (wsh webSocketHandler) ServeHTTP(w http.ResponseWriter, r *http.Request){
 | 
			
		|||
		delete(agentSockets, agentName)
 | 
			
		||||
		agentSocketsMutex.Unlock()
 | 
			
		||||
		c.Close()
 | 
			
		||||
		log.Printf("Agent disconnected: %s (%s)", agentName, agentIP)
 | 
			
		||||
		logLine := fmt.Sprintf("Agent disconnected: %s (%s)", agentName, agentIP)
 | 
			
		||||
		log.Printf(logLine)
 | 
			
		||||
		logger.InsertLog(logger.Info, logLine)
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		_, message, err := c.ReadMessage()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Printf("Error reading from agent %s: %v", agentName, err)
 | 
			
		||||
			logLine := fmt.Sprintf("Error reading from agent %s: %v", agentName, err)
 | 
			
		||||
			log.Printf(logLine)
 | 
			
		||||
			logger.InsertLog(logger.Error, logLine)
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		log.Printf("Message from agent %s: %s", agentName, message)
 | 
			
		||||
 | 
			
		||||
		logLine := fmt.Sprintf("Message from agent %s: %s", agentName, message)
 | 
			
		||||
		log.Printf(logLine)
 | 
			
		||||
		logger.InsertLog(logger.Debug, logLine)
 | 
			
		||||
 | 
			
		||||
		if ch, ok := responseChannels.Load(agentName); ok {
 | 
			
		||||
			responseChan := ch.(chan string)
 | 
			
		||||
| 
						 | 
				
			
			@ -274,8 +286,6 @@ var executeCommand http.HandlerFunc = func(w http.ResponseWriter, r *http.Reques
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
func Server() (*http.Server) {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	webSocketHandler := webSocketHandler {
 | 
			
		||||
		upgrader: websocket.Upgrader{
 | 
			
		||||
			CheckOrigin: func(r *http.Request) bool {
 | 
			
		||||
| 
						 | 
				
			
			@ -286,7 +296,7 @@ func Server() (*http.Server) {
 | 
			
		|||
 | 
			
		||||
	corsMiddleware := func(next http.Handler) http.Handler {
 | 
			
		||||
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
            w.Header().Set("Access-Control-Allow-Origin", "*") // Allow the WebUI origin
 | 
			
		||||
            w.Header().Set("Access-Control-Allow-Origin", "*") // Allow the WebUI origin, this needs to be changed before prod
 | 
			
		||||
            w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
 | 
			
		||||
            w.Header().Set("Access-Control-Allow-Headers", "Content-Type, HX-Current-URL, HX-Request, HX-Target, HX-Trigger, HX-Trigger-Name")
 | 
			
		||||
            if r.Method == "OPTIONS" {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@
 | 
			
		|||
    <!-- <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> -->
 | 
			
		||||
    <title>g2: gommand & gontrol</title>
 | 
			
		||||
    <script>
 | 
			
		||||
    // Query Agents for the Dropdown Menu
 | 
			
		||||
    document.addEventListener('DOMContentLoaded', () => {
 | 
			
		||||
        fetch('/agentNames')
 | 
			
		||||
            .then(response => response.json())
 | 
			
		||||
| 
						 | 
				
			
			@ -23,43 +24,19 @@
 | 
			
		|||
                });
 | 
			
		||||
            })
 | 
			
		||||
            .catch(error => console.error('Error fetching agent names:', error));
 | 
			
		||||
    fetch('http://localhost:5555/agentNames')
 | 
			
		||||
    .then(response => {
 | 
			
		||||
        console.log('Fetch response status:', response.status);
 | 
			
		||||
        return response.json();
 | 
			
		||||
    })
 | 
			
		||||
    .then(agentNames => {
 | 
			
		||||
        console.log('Connected agent names:', agentNames);
 | 
			
		||||
        // Your existing logic here
 | 
			
		||||
    })
 | 
			
		||||
    .catch(error => {
 | 
			
		||||
        console.error('Error fetching agent names:', error);
 | 
			
		||||
    });
 | 
			
		||||
        const tableRows = document.querySelectorAll('#agentList table tbody tr');
 | 
			
		||||
        console.log('Number of rows found:', tableRows.length);
 | 
			
		||||
        tableRows.forEach((row, index) => {
 | 
			
		||||
        const nameCell = row.querySelector('td[data-column="Name"]');
 | 
			
		||||
        const statusCell = row.querySelector('td[data-column="Status"]');
 | 
			
		||||
        console.log(`Row ${index + 1} - Name: ${nameCell?.textContent}, Status Cell Found: ${!!statusCell}`);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    // Query agents currently connected to the websocket and put status into the table
 | 
			
		||||
        const updateAgentStatuses = () => {
 | 
			
		||||
        fetch('http://localhost:5555/agentNames')
 | 
			
		||||
            .then(response => response.json())
 | 
			
		||||
            .then(agentNames => {
 | 
			
		||||
                console.log("Agent names fetched:", agentNames);
 | 
			
		||||
 | 
			
		||||
                // Get all rows in the table body
 | 
			
		||||
                const tableRows = document.querySelectorAll('#agentList table tbody tr');
 | 
			
		||||
 | 
			
		||||
                // Loop through each row to find the Name and update Status
 | 
			
		||||
                tableRows.forEach(row => {
 | 
			
		||||
                    const nameCell = row.querySelector('td:nth-child(2)');  // Name is in the second column
 | 
			
		||||
                    const statusCell = row.querySelector('td:nth-child(5)');  // Status is in the fifth column
 | 
			
		||||
 | 
			
		||||
                    const nameCell = row.querySelector('td:nth-child(2)');
 | 
			
		||||
                    const statusCell = row.querySelector('td:nth-child(5)');
 | 
			
		||||
                    if (nameCell && statusCell) {
 | 
			
		||||
                        const agentName = nameCell.textContent.trim();
 | 
			
		||||
 | 
			
		||||
                        if (agentNames.includes(agentName)) {
 | 
			
		||||
                            statusCell.innerHTML = '<span class="badge bg-success">Connected</span>';
 | 
			
		||||
                        } else {
 | 
			
		||||
| 
						 | 
				
			
			@ -70,12 +47,8 @@
 | 
			
		|||
            })
 | 
			
		||||
            .catch(error => console.error('Error fetching agent names:', error));
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Initial call to update statuses
 | 
			
		||||
    updateAgentStatuses();
 | 
			
		||||
 | 
			
		||||
    // Set the function to run every 5 seconds
 | 
			
		||||
    setInterval(updateAgentStatuses, 5000);
 | 
			
		||||
    setInterval(updateAgentStatuses, 1000);
 | 
			
		||||
    </script>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
			
		||||
    <title>Web Server Logs</title>
 | 
			
		||||
    <script src="https://unpkg.com/htmx.org@1.8.5"></script>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
    <h1>Web Server Logs</h1>
 | 
			
		||||
 | 
			
		||||
    <div id="logs-container">
 | 
			
		||||
        <!-- Logs will be injected here -->
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <button hx-get="/logs" hx-target="#logs-container" hx-swap="outerHTML">
 | 
			
		||||
        Load Logs
 | 
			
		||||
    </button>
 | 
			
		||||
 | 
			
		||||
    <button hx-get="/logs" hx-target="#logs-container" hx-swap="outerHTML" hx-trigger="every 2s">
 | 
			
		||||
        Auto-Refresh Logs
 | 
			
		||||
    </button>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
		Loading…
	
		Reference in New Issue