feat: add team member role change & removal, add uptime server stats, etc

This commit is contained in:
2024-11-14 16:28:44 +00:00
parent b574f83e74
commit 33dda374c7
25 changed files with 566 additions and 110 deletions
+27 -20
View File
@@ -1,6 +1,7 @@
package term
import (
"bufio"
"io"
"log"
"strconv"
@@ -10,67 +11,75 @@ import (
"rul.sh/vaulterm/lib"
)
func NewSSHWebsocketSession(c *websocket.Conn, client *lib.SSHClient) error {
func NewSSHWebsocketSession(c *websocket.Conn, client *lib.SSHClient) ([]byte, error) {
if err := client.Connect(); err != nil {
log.Printf("error connecting to SSH: %v", err)
return err
return nil, err
}
defer client.Close()
shell, err := client.StartPtyShell()
if err != nil {
log.Printf("error starting SSH shell: %v", err)
return err
return nil, err
}
session := shell.Session
defer session.Close()
// Goroutine to send SSH stdout to WebSocket
sessionCapture, sessionCaptureWriter := io.Pipe()
defer sessionCapture.Close()
sessionLog := []byte{}
// Capture SSH session output
go func() {
reader := bufio.NewReader(sessionCapture)
for {
b, err := reader.ReadBytes('\n')
if err != nil {
break
}
sessionLog = append(sessionLog, b...)
}
}()
// Pass SSH stdout to WebSocket
go func() {
buf := make([]byte, 1024)
for {
n, err := shell.Stdout.Read(buf)
if err != nil {
if err != io.EOF {
log.Printf("error reading from SSH stdout: %v", err)
}
break
}
sessionCaptureWriter.Write(buf[:n])
if err := c.WriteMessage(websocket.BinaryMessage, buf[:n]); err != nil {
log.Printf("error writing to websocket: %v", err)
break
}
}
}()
// Goroutine to handle SSH stderr
// Pass SSH stderr to WebSocket
go func() {
buf := make([]byte, 1024)
for {
n, err := shell.Stderr.Read(buf)
if err != nil {
if err != io.EOF {
log.Printf("error reading from SSH stderr: %v", err)
}
break
}
sessionCaptureWriter.Write(buf[:n])
if err := c.WriteMessage(websocket.BinaryMessage, buf[:n]); err != nil {
log.Printf("error writing to websocket: %v", err)
break
}
}
}()
// Handle WebSocket to SSH data streaming
// Handle user input
go func() {
defer session.Close()
for {
_, msg, err := c.ReadMessage()
if err != nil {
log.Printf("error reading from websocket: %v", err)
break
}
@@ -86,15 +95,13 @@ func NewSSHWebsocketSession(c *websocket.Conn, client *lib.SSHClient) error {
shell.Stdin.Write(msg)
}
log.Println("SSH session closed")
}()
// Wait for the SSH session to close
if err := session.Wait(); err != nil {
log.Printf("SSH session ended with error: %v", err)
return err
return sessionLog, err
}
return nil
return sessionLog, nil
}
+30 -3
View File
@@ -2,9 +2,11 @@ package term
import (
"log"
"time"
"github.com/gofiber/contrib/websocket"
"rul.sh/vaulterm/app/hosts"
"rul.sh/vaulterm/db"
"rul.sh/vaulterm/lib"
"rul.sh/vaulterm/models"
"rul.sh/vaulterm/utils"
@@ -23,9 +25,19 @@ func HandleTerm(c *websocket.Conn) {
return
}
log := ""
term := &models.TermSession{
UserID: user.ID,
HostID: hostId,
Reason: c.Query("reason"),
}
if err := db.Get().Create(term).Error; err != nil {
return
}
switch data.Host.Type {
case "ssh":
sshHandler(c, data)
sshHandler(c, data, &log)
case "pve":
pveHandler(c, data)
case "incus":
@@ -33,9 +45,18 @@ func HandleTerm(c *websocket.Conn) {
default:
c.WriteMessage(websocket.TextMessage, []byte("Invalid host type"))
}
// save session log
endsAt := time.Now()
db.Get().
Where("id = ?", term.ID).
Updates(&models.TermSession{
EndsAt: &endsAt,
Log: log,
})
}
func sshHandler(c *websocket.Conn, data *models.HostDecrypted) {
func sshHandler(c *websocket.Conn, data *models.HostDecrypted, log *string) {
cfg := lib.NewSSHClient(&lib.SSHClientConfig{
HostName: data.Host.Host,
Port: data.Port,
@@ -43,9 +64,15 @@ func sshHandler(c *websocket.Conn, data *models.HostDecrypted) {
AltKey: data.AltKey,
})
if err := NewSSHWebsocketSession(c, cfg); err != nil {
out, err := NewSSHWebsocketSession(c, cfg)
if err != nil {
c.WriteMessage(websocket.TextMessage, []byte(err.Error()))
}
// copy output
if log != nil {
*log = string(out)
}
}
func pveHandler(c *websocket.Conn, data *models.HostDecrypted) {