2022-07-01 23:07:13 +02:00
|
|
|
package sstore
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"database/sql"
|
|
|
|
"fmt"
|
2022-07-13 06:51:17 +02:00
|
|
|
"strings"
|
2022-07-01 23:07:13 +02:00
|
|
|
|
|
|
|
"github.com/google/uuid"
|
2022-07-08 01:29:14 +02:00
|
|
|
"github.com/scripthaus-dev/mshell/pkg/packet"
|
2022-07-01 23:07:13 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
func NumSessions(ctx context.Context) (int, error) {
|
2022-07-13 01:10:46 +02:00
|
|
|
db, err := GetDB(ctx)
|
2022-07-01 23:07:13 +02:00
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
query := "SELECT count(*) FROM session"
|
|
|
|
var count int
|
|
|
|
err = db.GetContext(ctx, &count, query)
|
|
|
|
if err != nil {
|
|
|
|
return 0, err
|
|
|
|
}
|
|
|
|
return count, nil
|
|
|
|
}
|
|
|
|
|
2022-07-02 02:38:36 +02:00
|
|
|
func GetAllRemotes(ctx context.Context) ([]*RemoteType, error) {
|
2022-07-07 22:26:46 +02:00
|
|
|
var rtn []*RemoteType
|
|
|
|
err := WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
query := `SELECT * FROM remote`
|
|
|
|
marr := tx.SelectMaps(query)
|
|
|
|
for _, m := range marr {
|
|
|
|
rtn = append(rtn, RemoteFromMap(m))
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
2022-07-02 02:38:36 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-07-07 22:26:46 +02:00
|
|
|
return rtn, nil
|
2022-07-02 02:38:36 +02:00
|
|
|
}
|
|
|
|
|
2022-08-17 21:24:09 +02:00
|
|
|
func GetRemoteByAlias(ctx context.Context, alias string) (*RemoteType, error) {
|
|
|
|
var remote *RemoteType
|
|
|
|
err := WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
query := `SELECT * FROM remote WHERE remotealias = ?`
|
|
|
|
m := tx.GetMap(query, alias)
|
|
|
|
remote = RemoteFromMap(m)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return remote, nil
|
|
|
|
}
|
|
|
|
|
2022-08-17 00:08:28 +02:00
|
|
|
func GetRemoteById(ctx context.Context, remoteId string) (*RemoteType, error) {
|
2022-07-07 22:26:46 +02:00
|
|
|
var remote *RemoteType
|
|
|
|
err := WithTx(ctx, func(tx *TxWrap) error {
|
2022-08-17 00:08:28 +02:00
|
|
|
query := `SELECT * FROM remote WHERE remoteid = ?`
|
|
|
|
m := tx.GetMap(query, remoteId)
|
2022-07-07 22:26:46 +02:00
|
|
|
remote = RemoteFromMap(m)
|
|
|
|
return nil
|
|
|
|
})
|
2022-07-01 23:07:13 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-07-07 22:26:46 +02:00
|
|
|
return remote, nil
|
2022-07-01 23:07:13 +02:00
|
|
|
}
|
|
|
|
|
2022-08-17 00:08:28 +02:00
|
|
|
func GetRemoteByPhysicalId(ctx context.Context, physicalId string) (*RemoteType, error) {
|
2022-07-07 22:26:46 +02:00
|
|
|
var remote *RemoteType
|
|
|
|
err := WithTx(ctx, func(tx *TxWrap) error {
|
2022-08-17 00:08:28 +02:00
|
|
|
query := `SELECT * FROM remote WHERE physicalid = ?`
|
|
|
|
m := tx.GetMap(query, physicalId)
|
2022-07-07 22:26:46 +02:00
|
|
|
remote = RemoteFromMap(m)
|
|
|
|
return nil
|
|
|
|
})
|
2022-07-01 23:07:13 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-07-07 22:26:46 +02:00
|
|
|
return remote, nil
|
2022-07-01 23:07:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func InsertRemote(ctx context.Context, remote *RemoteType) error {
|
|
|
|
if remote == nil {
|
|
|
|
return fmt.Errorf("cannot insert nil remote")
|
|
|
|
}
|
2022-07-13 01:10:46 +02:00
|
|
|
db, err := GetDB(ctx)
|
2022-07-01 23:07:13 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-08-21 21:31:29 +02:00
|
|
|
query := `INSERT INTO remote ( remoteid, physicalid, remotetype, remotealias, remotecanonicalname, remotesudo, remoteuser, remotehost, connectmode, initpk, sshopts, remoteopts, lastconnectts) VALUES
|
|
|
|
(:remoteid,:physicalid,:remotetype,:remotealias,:remotecanonicalname,:remotesudo,:remoteuser,:remotehost,:connectmode,:initpk,:sshopts,:remoteopts,:lastconnectts)`
|
2022-07-07 22:26:46 +02:00
|
|
|
_, err = db.NamedExec(query, remote.ToMap())
|
2022-07-01 23:07:13 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-08-11 21:07:41 +02:00
|
|
|
func InsertHistoryItem(ctx context.Context, hitem *HistoryItemType) error {
|
|
|
|
if hitem == nil {
|
|
|
|
return fmt.Errorf("cannot insert nil history item")
|
|
|
|
}
|
|
|
|
db, err := GetDB(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-08-12 08:45:15 +02:00
|
|
|
query := `INSERT INTO history ( historyid, ts, userid, sessionid, screenid, windowid, lineid, cmdid, haderror, cmdstr) VALUES
|
|
|
|
(:historyid,:ts,:userid,:sessionid,:screenid,:windowid,:lineid,:cmdid,:haderror,:cmdstr)`
|
2022-08-11 21:07:41 +02:00
|
|
|
_, err = db.NamedExec(query, hitem)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2022-08-12 08:45:15 +02:00
|
|
|
func GetSessionHistoryItems(ctx context.Context, sessionId string, maxItems int) ([]*HistoryItemType, error) {
|
|
|
|
var rtn []*HistoryItemType
|
|
|
|
err := WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
query := `SELECT * FROM history WHERE sessionid = ? ORDER BY ts DESC LIMIT ?`
|
|
|
|
tx.SelectWrap(&rtn, query, sessionId, maxItems)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return rtn, nil
|
|
|
|
}
|
|
|
|
|
2022-08-09 01:21:46 +02:00
|
|
|
func GetBareSessions(ctx context.Context) ([]*SessionType, error) {
|
|
|
|
var rtn []*SessionType
|
|
|
|
err := WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
query := `SELECT * FROM session`
|
|
|
|
tx.SelectWrap(&rtn, query)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return rtn, nil
|
|
|
|
}
|
|
|
|
|
2022-07-08 22:23:45 +02:00
|
|
|
func GetAllSessions(ctx context.Context) ([]*SessionType, error) {
|
|
|
|
var rtn []*SessionType
|
2022-07-12 22:50:44 +02:00
|
|
|
err := WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
query := `SELECT * FROM session`
|
|
|
|
tx.SelectWrap(&rtn, query)
|
2022-08-11 03:33:32 +02:00
|
|
|
sessionMap := make(map[string]*SessionType)
|
2022-08-09 01:21:46 +02:00
|
|
|
for _, session := range rtn {
|
2022-08-11 03:33:32 +02:00
|
|
|
sessionMap[session.SessionId] = session
|
2022-08-09 01:21:46 +02:00
|
|
|
session.Full = true
|
|
|
|
}
|
2022-07-13 06:51:17 +02:00
|
|
|
var screens []*ScreenType
|
|
|
|
query = `SELECT * FROM screen ORDER BY screenidx`
|
|
|
|
tx.SelectWrap(&screens, query)
|
|
|
|
screenMap := make(map[string][]*ScreenType)
|
|
|
|
for _, screen := range screens {
|
|
|
|
screenArr := screenMap[screen.SessionId]
|
|
|
|
screenArr = append(screenArr, screen)
|
|
|
|
screenMap[screen.SessionId] = screenArr
|
|
|
|
}
|
|
|
|
for _, session := range rtn {
|
|
|
|
session.Screens = screenMap[session.SessionId]
|
|
|
|
}
|
|
|
|
var sws []*ScreenWindowType
|
|
|
|
query = `SELECT * FROM screen_window`
|
|
|
|
tx.SelectWrap(&sws, query)
|
|
|
|
screenIdMap := make(map[string]*ScreenType)
|
|
|
|
for _, screen := range screens {
|
|
|
|
screenIdMap[screen.SessionId+screen.ScreenId] = screen
|
|
|
|
}
|
|
|
|
for _, sw := range sws {
|
|
|
|
screen := screenIdMap[sw.SessionId+sw.ScreenId]
|
|
|
|
if screen == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
screen.Windows = append(screen.Windows, sw)
|
|
|
|
}
|
2022-08-11 03:33:32 +02:00
|
|
|
query = `SELECT * FROM remote_instance WHERE sessionscope`
|
|
|
|
var ris []*RemoteInstance
|
|
|
|
tx.SelectWrap(&ris, query)
|
|
|
|
for _, ri := range ris {
|
|
|
|
s := sessionMap[ri.SessionId]
|
|
|
|
if s != nil {
|
|
|
|
s.Remotes = append(s.Remotes, ri)
|
|
|
|
}
|
|
|
|
}
|
2022-07-12 22:50:44 +02:00
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return rtn, err
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetWindowById(ctx context.Context, sessionId string, windowId string) (*WindowType, error) {
|
|
|
|
var rtnWindow *WindowType
|
|
|
|
err := WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
var window WindowType
|
|
|
|
query := `SELECT * FROM window WHERE sessionid = ? AND windowid = ?`
|
|
|
|
found := tx.GetWrap(&window, query, sessionId, windowId)
|
|
|
|
if !found {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
rtnWindow = &window
|
|
|
|
query = `SELECT * FROM line WHERE sessionid = ? AND windowid = ?`
|
|
|
|
tx.SelectWrap(&window.Lines, query, sessionId, windowId)
|
|
|
|
query = `SELECT * FROM cmd WHERE cmdid IN (SELECT cmdid FROM line WHERE sessionid = ? AND windowid = ?)`
|
|
|
|
cmdMaps := tx.SelectMaps(query, sessionId, windowId)
|
|
|
|
for _, m := range cmdMaps {
|
|
|
|
window.Cmds = append(window.Cmds, CmdFromMap(m))
|
|
|
|
}
|
2022-08-11 03:33:32 +02:00
|
|
|
query = `SELECT * FROM remote_instance WHERE sessionid = ? AND windowid = ? AND NOT sessionscope`
|
|
|
|
tx.SelectWrap(&window.Remotes, query, sessionId, windowId)
|
2022-07-12 22:50:44 +02:00
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return rtnWindow, err
|
2022-07-08 22:23:45 +02:00
|
|
|
}
|
|
|
|
|
2022-07-15 03:39:40 +02:00
|
|
|
func GetSessionScreens(ctx context.Context, sessionId string) ([]*ScreenType, error) {
|
|
|
|
var rtn []*ScreenType
|
|
|
|
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
query := `SELECT * FROM screen WHERE sessionid = ? ORDER BY screenidx`
|
|
|
|
tx.SelectWrap(&rtn, query, sessionId)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return rtn, txErr
|
|
|
|
}
|
|
|
|
|
2022-07-01 23:07:13 +02:00
|
|
|
func GetSessionById(ctx context.Context, id string) (*SessionType, error) {
|
2022-08-09 01:21:46 +02:00
|
|
|
allSessions, err := GetAllSessions(ctx)
|
2022-07-01 23:07:13 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-08-09 01:21:46 +02:00
|
|
|
for _, session := range allSessions {
|
|
|
|
if session.SessionId == id {
|
|
|
|
return session, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil, nil
|
2022-07-01 23:07:13 +02:00
|
|
|
}
|
|
|
|
|
2022-07-05 07:18:01 +02:00
|
|
|
func GetSessionByName(ctx context.Context, name string) (*SessionType, error) {
|
2022-07-13 01:10:46 +02:00
|
|
|
db, err := GetDB(ctx)
|
2022-07-05 07:18:01 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
var sessionId string
|
|
|
|
query := `SELECT sessionid FROM session WHERE name = ?`
|
|
|
|
err = db.GetContext(ctx, &sessionId, query, name)
|
|
|
|
if err != nil {
|
|
|
|
if err == sql.ErrNoRows {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return GetSessionById(ctx, sessionId)
|
|
|
|
}
|
|
|
|
|
2022-07-08 22:23:45 +02:00
|
|
|
// also creates default window, returns sessionId
|
|
|
|
// if sessionName == "", it will be generated
|
2022-08-09 01:21:46 +02:00
|
|
|
func InsertSessionWithName(ctx context.Context, sessionName string, activate bool) (*SessionUpdate, error) {
|
2022-07-08 22:23:45 +02:00
|
|
|
newSessionId := uuid.New().String()
|
|
|
|
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
2022-07-13 06:51:17 +02:00
|
|
|
names := tx.SelectStrings(`SELECT name FROM session`)
|
|
|
|
sessionName = fmtUniqueName(sessionName, "session-%d", len(names)+1, names)
|
|
|
|
maxSessionIdx := tx.GetInt(`SELECT COALESCE(max(sessionidx), 0) FROM session`)
|
2022-08-16 21:08:26 +02:00
|
|
|
query := `INSERT INTO session (sessionid, name, activescreenid, sessionidx, notifynum, owneruserid, sharemode, accesskey) VALUES (?, ?, '', ?, ?, '', 'local', '')`
|
2022-07-13 06:51:17 +02:00
|
|
|
tx.ExecWrap(query, newSessionId, sessionName, maxSessionIdx+1, 0)
|
2022-07-15 03:39:40 +02:00
|
|
|
_, err := InsertScreen(tx.Context(), newSessionId, "", true)
|
2022-07-13 06:51:17 +02:00
|
|
|
if err != nil {
|
|
|
|
return err
|
2022-07-08 22:23:45 +02:00
|
|
|
}
|
2022-07-01 23:07:13 +02:00
|
|
|
return nil
|
|
|
|
})
|
2022-07-15 03:39:40 +02:00
|
|
|
if txErr != nil {
|
2022-08-09 01:21:46 +02:00
|
|
|
return nil, txErr
|
|
|
|
}
|
|
|
|
session, err := GetSessionById(ctx, newSessionId)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
update := &SessionUpdate{
|
|
|
|
Sessions: []*SessionType{session},
|
|
|
|
}
|
|
|
|
if activate {
|
|
|
|
update.ActiveSessionId = newSessionId
|
2022-07-15 03:39:40 +02:00
|
|
|
}
|
2022-08-09 01:21:46 +02:00
|
|
|
return update, nil
|
2022-07-08 22:23:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func containsStr(strs []string, testStr string) bool {
|
|
|
|
for _, s := range strs {
|
|
|
|
if s == testStr {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2022-07-13 06:51:17 +02:00
|
|
|
func fmtUniqueName(name string, defaultFmtStr string, startIdx int, strs []string) string {
|
|
|
|
var fmtStr string
|
|
|
|
if name != "" {
|
|
|
|
if !containsStr(strs, name) {
|
|
|
|
return name
|
|
|
|
}
|
|
|
|
fmtStr = name + "-%d"
|
|
|
|
startIdx = 2
|
|
|
|
} else {
|
|
|
|
fmtStr = defaultFmtStr
|
|
|
|
}
|
|
|
|
if strings.Index(fmtStr, "%d") == -1 {
|
|
|
|
panic("invalid fmtStr: " + fmtStr)
|
|
|
|
}
|
|
|
|
for {
|
|
|
|
testName := fmt.Sprintf(fmtStr, startIdx)
|
|
|
|
if containsStr(strs, testName) {
|
|
|
|
startIdx++
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
return testName
|
|
|
|
}
|
2022-07-13 01:10:46 +02:00
|
|
|
}
|
|
|
|
|
2022-07-16 02:53:23 +02:00
|
|
|
func InsertScreen(ctx context.Context, sessionId string, screenName string, activate bool) (UpdatePacket, error) {
|
2022-07-13 06:51:17 +02:00
|
|
|
var newScreenId string
|
2022-07-08 22:23:45 +02:00
|
|
|
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
2022-07-13 06:51:17 +02:00
|
|
|
query := `SELECT sessionid FROM session WHERE sessionid = ?`
|
|
|
|
if !tx.Exists(query, sessionId) {
|
|
|
|
return fmt.Errorf("cannot create screen, no session found")
|
2022-07-08 22:23:45 +02:00
|
|
|
}
|
2022-07-13 06:51:17 +02:00
|
|
|
newWindowId := txCreateWindow(tx, sessionId)
|
|
|
|
maxScreenIdx := tx.GetInt(`SELECT COALESCE(max(screenidx), 0) FROM screen WHERE sessionid = ?`, sessionId)
|
|
|
|
screenNames := tx.SelectStrings(`SELECT name FROM screen WHERE sessionid = ?`, sessionId)
|
|
|
|
screenName = fmtUniqueName(screenName, "s%d", maxScreenIdx+1, screenNames)
|
|
|
|
newScreenId = uuid.New().String()
|
2022-08-16 21:08:26 +02:00
|
|
|
query = `INSERT INTO screen (sessionid, screenid, name, activewindowid, screenidx, screenopts, owneruserid, sharemode) VALUES (?, ?, ?, ?, ?, ?, '', 'local')`
|
2022-07-13 06:51:17 +02:00
|
|
|
tx.ExecWrap(query, sessionId, newScreenId, screenName, newWindowId, maxScreenIdx+1, ScreenOptsType{})
|
|
|
|
layout := LayoutType{Type: LayoutFull}
|
|
|
|
query = `INSERT INTO screen_window (sessionid, screenid, windowid, name, layout) VALUES (?, ?, ?, ?, ?)`
|
|
|
|
tx.ExecWrap(query, sessionId, newScreenId, newWindowId, DefaultScreenWindowName, layout)
|
2022-07-15 03:39:40 +02:00
|
|
|
if activate {
|
|
|
|
query = `UPDATE session SET activescreenid = ? WHERE sessionid = ?`
|
|
|
|
tx.ExecWrap(query, newScreenId, sessionId)
|
|
|
|
}
|
2022-07-08 22:23:45 +02:00
|
|
|
return nil
|
|
|
|
})
|
2022-07-15 10:57:45 +02:00
|
|
|
newScreen, err := GetScreenById(ctx, sessionId, newScreenId)
|
|
|
|
if err != nil {
|
2022-07-16 02:53:23 +02:00
|
|
|
return nil, err
|
2022-07-15 10:57:45 +02:00
|
|
|
}
|
|
|
|
update, session := MakeSingleSessionUpdate(sessionId)
|
|
|
|
if activate {
|
|
|
|
session.ActiveScreenId = newScreenId
|
|
|
|
}
|
|
|
|
session.Screens = append(session.Screens, newScreen)
|
2022-07-16 02:53:23 +02:00
|
|
|
return update, txErr
|
2022-07-01 23:07:13 +02:00
|
|
|
}
|
2022-07-02 22:31:56 +02:00
|
|
|
|
2022-07-15 03:39:40 +02:00
|
|
|
func GetScreenById(ctx context.Context, sessionId string, screenId string) (*ScreenType, error) {
|
|
|
|
var rtnScreen *ScreenType
|
|
|
|
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
query := `SELECT * FROM screen WHERE sessionid = ? AND screenid = ?`
|
|
|
|
var screen ScreenType
|
|
|
|
found := tx.GetWrap(&screen, query, sessionId, screenId)
|
|
|
|
if !found {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
rtnScreen = &screen
|
|
|
|
query = `SELECT * FROM screen_window WHERE sessionid = ? AND screenid = ?`
|
|
|
|
tx.SelectWrap(&screen.Windows, query, sessionId, screenId)
|
2022-07-15 10:57:45 +02:00
|
|
|
screen.Full = true
|
2022-07-15 03:39:40 +02:00
|
|
|
return nil
|
|
|
|
})
|
|
|
|
if txErr != nil {
|
|
|
|
return nil, txErr
|
|
|
|
}
|
|
|
|
return rtnScreen, nil
|
|
|
|
}
|
|
|
|
|
2022-07-13 06:51:17 +02:00
|
|
|
func txCreateWindow(tx *TxWrap, sessionId string) string {
|
|
|
|
windowId := uuid.New().String()
|
2022-08-16 21:08:26 +02:00
|
|
|
query := `INSERT INTO window (sessionid, windowid, curremote, winopts, shareopts, owneruserid, sharemode) VALUES (?, ?, ?, ?, ?, '', 'local')`
|
|
|
|
tx.ExecWrap(query, sessionId, windowId, LocalRemoteName, WindowOptsType{}, WindowShareOptsType{})
|
2022-07-13 06:51:17 +02:00
|
|
|
return windowId
|
2022-07-12 22:50:44 +02:00
|
|
|
}
|
|
|
|
|
2022-07-08 06:39:25 +02:00
|
|
|
func InsertLine(ctx context.Context, line *LineType, cmd *CmdType) error {
|
2022-07-02 22:31:56 +02:00
|
|
|
if line == nil {
|
|
|
|
return fmt.Errorf("line cannot be nil")
|
|
|
|
}
|
2022-08-16 21:08:26 +02:00
|
|
|
if line.LineId == "" {
|
|
|
|
return fmt.Errorf("line must have lineid set")
|
2022-07-02 22:31:56 +02:00
|
|
|
}
|
|
|
|
return WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
var windowId string
|
|
|
|
query := `SELECT windowid FROM window WHERE sessionid = ? AND windowid = ?`
|
|
|
|
hasWindow := tx.GetWrap(&windowId, query, line.SessionId, line.WindowId)
|
|
|
|
if !hasWindow {
|
|
|
|
return fmt.Errorf("window not found, cannot insert line[%s/%s]", line.SessionId, line.WindowId)
|
|
|
|
}
|
2022-08-23 22:14:14 +02:00
|
|
|
query = `INSERT INTO line ( sessionid, windowid, lineid, ts, userid, linetype, text, cmdid, ephemeral)
|
|
|
|
VALUES (:sessionid,:windowid,:lineid,:ts,:userid,:linetype,:text,:cmdid,:ephemeral)`
|
2022-07-02 22:31:56 +02:00
|
|
|
tx.NamedExecWrap(query, line)
|
2022-07-08 06:39:25 +02:00
|
|
|
if cmd != nil {
|
|
|
|
cmdMap := cmd.ToMap()
|
|
|
|
query = `
|
2022-07-12 22:50:44 +02:00
|
|
|
INSERT INTO cmd ( sessionid, cmdid, remoteid, cmdstr, remotestate, termopts, status, startpk, donepk, runout, usedrows)
|
|
|
|
VALUES (:sessionid,:cmdid,:remoteid,:cmdstr,:remotestate,:termopts,:status,:startpk,:donepk,:runout,:usedrows)
|
2022-07-07 09:10:37 +02:00
|
|
|
`
|
2022-07-08 06:39:25 +02:00
|
|
|
tx.NamedExecWrap(query, cmdMap)
|
|
|
|
}
|
2022-07-07 09:10:37 +02:00
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-07-07 22:26:46 +02:00
|
|
|
func GetCmdById(ctx context.Context, sessionId string, cmdId string) (*CmdType, error) {
|
|
|
|
var cmd *CmdType
|
|
|
|
err := WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
query := `SELECT * FROM cmd WHERE sessionid = ? AND cmdid = ?`
|
|
|
|
m := tx.GetMap(query, sessionId, cmdId)
|
|
|
|
cmd = CmdFromMap(m)
|
|
|
|
return nil
|
|
|
|
})
|
2022-07-07 09:10:37 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2022-07-07 22:26:46 +02:00
|
|
|
return cmd, nil
|
2022-07-07 09:10:37 +02:00
|
|
|
}
|
2022-07-08 01:29:14 +02:00
|
|
|
|
2022-08-20 02:14:53 +02:00
|
|
|
func UpdateCmdDonePk(ctx context.Context, donePk *packet.CmdDonePacketType) (UpdatePacket, error) {
|
2022-07-08 01:29:14 +02:00
|
|
|
if donePk == nil || donePk.CK.IsEmpty() {
|
2022-08-20 02:14:53 +02:00
|
|
|
return nil, fmt.Errorf("invalid cmddone packet (no ck)")
|
2022-07-08 01:29:14 +02:00
|
|
|
}
|
2022-08-20 02:14:53 +02:00
|
|
|
var rtnCmd *CmdType
|
|
|
|
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
2022-07-08 01:29:14 +02:00
|
|
|
query := `UPDATE cmd SET status = ?, donepk = ? WHERE sessionid = ? AND cmdid = ?`
|
|
|
|
tx.ExecWrap(query, CmdStatusDone, quickJson(donePk), donePk.CK.GetSessionId(), donePk.CK.GetCmdId())
|
2022-08-20 02:14:53 +02:00
|
|
|
var err error
|
|
|
|
rtnCmd, err = GetCmdById(tx.Context(), donePk.CK.GetSessionId(), donePk.CK.GetCmdId())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2022-07-08 01:29:14 +02:00
|
|
|
return nil
|
|
|
|
})
|
2022-08-20 02:14:53 +02:00
|
|
|
if txErr != nil {
|
|
|
|
return nil, txErr
|
|
|
|
}
|
|
|
|
if rtnCmd == nil {
|
|
|
|
return nil, fmt.Errorf("cmd data not found for ck[%s]", donePk.CK)
|
|
|
|
}
|
|
|
|
return LineUpdate{Cmd: rtnCmd}, nil
|
2022-07-08 01:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func AppendCmdErrorPk(ctx context.Context, errPk *packet.CmdErrorPacketType) error {
|
|
|
|
if errPk == nil || errPk.CK.IsEmpty() {
|
|
|
|
return fmt.Errorf("invalid cmderror packet (no ck)")
|
|
|
|
}
|
|
|
|
return WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
query := `UPDATE cmd SET runout = json_insert(runout, '$[#]', ?) WHERE sessionid = ? AND cmdid = ?`
|
|
|
|
tx.ExecWrap(query, quickJson(errPk), errPk.CK.GetSessionId(), errPk.CK.GetCmdId())
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func HangupAllRunningCmds(ctx context.Context) error {
|
|
|
|
return WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
query := `UPDATE cmd SET status = ? WHERE status = ?`
|
|
|
|
tx.ExecWrap(query, CmdStatusHangup, CmdStatusRunning)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func HangupRunningCmdsByRemoteId(ctx context.Context, remoteId string) error {
|
|
|
|
return WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
query := `UPDATE cmd SET status = ? WHERE status = ? AND remoteid = ?`
|
|
|
|
tx.ExecWrap(query, CmdStatusHangup, CmdStatusRunning, remoteId)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
}
|
2022-07-15 03:39:40 +02:00
|
|
|
|
2022-07-15 10:57:45 +02:00
|
|
|
func getNextId(ids []string, delId string) string {
|
|
|
|
fmt.Printf("getnextid %v | %v\n", ids, delId)
|
|
|
|
if len(ids) == 0 {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
if len(ids) == 1 {
|
|
|
|
if ids[0] == delId {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return ids[0]
|
|
|
|
}
|
|
|
|
for idx := 0; idx < len(ids); idx++ {
|
|
|
|
if ids[idx] == delId {
|
|
|
|
var rtnIdx int
|
|
|
|
if idx == len(ids)-1 {
|
|
|
|
rtnIdx = idx - 1
|
|
|
|
} else {
|
|
|
|
rtnIdx = idx + 1
|
|
|
|
}
|
|
|
|
return ids[rtnIdx]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ids[0]
|
|
|
|
}
|
|
|
|
|
2022-07-16 02:53:23 +02:00
|
|
|
func SwitchScreenById(ctx context.Context, sessionId string, screenId string) (UpdatePacket, error) {
|
2022-07-15 03:39:40 +02:00
|
|
|
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
query := `SELECT screenid FROM screen WHERE sessionid = ? AND screenid = ?`
|
|
|
|
if !tx.Exists(query, sessionId, screenId) {
|
|
|
|
return fmt.Errorf("cannot switch to screen, screen=%s does not exist in session=%s", screenId, sessionId)
|
|
|
|
}
|
|
|
|
query = `UPDATE session SET activescreenid = ? WHERE sessionid = ?`
|
|
|
|
tx.ExecWrap(query, screenId, sessionId)
|
|
|
|
return nil
|
|
|
|
})
|
2022-07-15 10:57:45 +02:00
|
|
|
update, session := MakeSingleSessionUpdate(sessionId)
|
|
|
|
session.ActiveScreenId = screenId
|
2022-07-16 02:53:23 +02:00
|
|
|
return update, txErr
|
2022-07-15 03:39:40 +02:00
|
|
|
}
|
2022-07-15 10:57:45 +02:00
|
|
|
|
|
|
|
func CleanWindows() {
|
|
|
|
}
|
|
|
|
|
2022-07-16 02:53:23 +02:00
|
|
|
func DeleteScreen(ctx context.Context, sessionId string, screenId string) (UpdatePacket, error) {
|
2022-07-15 10:57:45 +02:00
|
|
|
var newActiveScreenId string
|
|
|
|
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
isActive := tx.Exists(`SELECT sessionid FROM session WHERE sessionid = ? AND activescreenid = ?`, sessionId, screenId)
|
|
|
|
fmt.Printf("delete-screen %s %s | %v\n", sessionId, screenId, isActive)
|
|
|
|
if isActive {
|
|
|
|
screenIds := tx.SelectStrings(`SELECT screenid FROM screen WHERE sessionid = ? ORDER BY screenidx`, sessionId)
|
|
|
|
nextId := getNextId(screenIds, screenId)
|
|
|
|
tx.ExecWrap(`UPDATE session SET activescreenid = ? WHERE sessionid = ?`, nextId, sessionId)
|
|
|
|
newActiveScreenId = nextId
|
|
|
|
}
|
|
|
|
query := `DELETE FROM screen_window WHERE sessionid = ? AND screenid = ?`
|
|
|
|
tx.ExecWrap(query, sessionId, screenId)
|
|
|
|
query = `DELETE FROM screen WHERE sessionid = ? AND screenid = ?`
|
|
|
|
tx.ExecWrap(query, sessionId, screenId)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
if txErr != nil {
|
2022-07-16 02:53:23 +02:00
|
|
|
return nil, txErr
|
2022-07-15 10:57:45 +02:00
|
|
|
}
|
|
|
|
go CleanWindows()
|
|
|
|
update, session := MakeSingleSessionUpdate(sessionId)
|
|
|
|
session.ActiveScreenId = newActiveScreenId
|
|
|
|
session.Screens = append(session.Screens, &ScreenType{SessionId: sessionId, ScreenId: screenId, Remove: true})
|
2022-07-16 02:53:23 +02:00
|
|
|
return update, nil
|
2022-07-15 10:57:45 +02:00
|
|
|
}
|
2022-07-16 02:37:32 +02:00
|
|
|
|
|
|
|
func GetRemoteState(ctx context.Context, rname string, sessionId string, windowId string) (string, *RemoteState, error) {
|
|
|
|
var remoteId string
|
|
|
|
var remoteState *RemoteState
|
|
|
|
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
var ri RemoteInstance
|
|
|
|
query := `SELECT * FROM remote_instance WHERE sessionid = ? AND windowid = ? AND name = ?`
|
|
|
|
found := tx.GetWrap(&ri, query, sessionId, windowId, rname)
|
|
|
|
if found {
|
|
|
|
remoteId = ri.RemoteId
|
|
|
|
remoteState = &ri.State
|
|
|
|
return nil
|
|
|
|
}
|
2022-08-17 00:08:28 +02:00
|
|
|
query = `SELECT remoteid FROM remote WHERE remotealias = ? OR remotecanonicalname = ?`
|
|
|
|
remoteId = tx.GetString(query, rname, rname)
|
2022-07-16 02:37:32 +02:00
|
|
|
if remoteId == "" {
|
|
|
|
return fmt.Errorf("remote not found", rname)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return remoteId, remoteState, txErr
|
|
|
|
}
|
2022-08-09 23:24:57 +02:00
|
|
|
|
2022-08-23 03:38:52 +02:00
|
|
|
func UpdateRemoteState(ctx context.Context, rname string, sessionId string, windowId string, remoteId string, state RemoteState) (*RemoteInstance, error) {
|
2022-08-09 23:24:57 +02:00
|
|
|
var ri RemoteInstance
|
|
|
|
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
query := `SELECT windowid FROM window WHERE sessionid = ? AND windowid = ?`
|
|
|
|
if !tx.Exists(query, sessionId, windowId) {
|
|
|
|
return fmt.Errorf("cannot update remote instance cwd, no window found")
|
|
|
|
}
|
|
|
|
query = `SELECT * FROM remote_instance WHERE sessionid = ? AND windowid = ? AND name = ?`
|
|
|
|
found := tx.GetWrap(&ri, query, sessionId, windowId, rname)
|
|
|
|
if !found {
|
|
|
|
ri = RemoteInstance{
|
|
|
|
RIId: uuid.New().String(),
|
|
|
|
Name: rname,
|
|
|
|
SessionId: sessionId,
|
|
|
|
WindowId: windowId,
|
|
|
|
RemoteId: remoteId,
|
|
|
|
SessionScope: (windowId == ""),
|
2022-08-23 03:38:52 +02:00
|
|
|
State: state,
|
2022-08-09 23:24:57 +02:00
|
|
|
}
|
|
|
|
query = `INSERT INTO remote_instance (riid, name, sessionid, windowid, remoteid, sessionscope, state) VALUES (:riid, :name, :sessionid, :windowid, :remoteid, :sessionscope, :state)`
|
|
|
|
tx.NamedExecWrap(query, ri)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
query = `UPDATE remote_instance SET state = ? WHERE sessionid = ? AND windowid = ? AND name = ?`
|
2022-08-23 03:38:52 +02:00
|
|
|
ri.State = state
|
2022-08-09 23:24:57 +02:00
|
|
|
tx.ExecWrap(query, ri.State, ri.SessionId, ri.WindowId, ri.Name)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return &ri, txErr
|
|
|
|
}
|
2022-08-17 21:24:09 +02:00
|
|
|
|
|
|
|
func UpdateCurRemote(ctx context.Context, sessionId string, windowId string, remoteName string) error {
|
|
|
|
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
|
|
|
query := `SELECT windowid FROM window WHERE sessionid = ? AND windowid = ?`
|
|
|
|
if !tx.Exists(query, sessionId, windowId) {
|
|
|
|
return fmt.Errorf("cannot update curremote, no window found")
|
|
|
|
}
|
|
|
|
query = `UPDATE window SET curremote = ? WHERE sessionid = ? AND windowid = ?`
|
|
|
|
tx.ExecWrap(query, remoteName, sessionId, windowId)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
return txErr
|
|
|
|
}
|