mirror of
https://github.com/khairul169/vaulterm.git
synced 2026-09-15 17:03:30 +07:00
feat: add team member role change & removal, add uptime server stats, etc
This commit is contained in:
+27
-20
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user