implement history

This commit is contained in:
sawka 2022-08-11 23:45:15 -07:00
parent d5cf15e946
commit a67ae15b32
7 changed files with 97 additions and 5 deletions

View File

@ -10,6 +10,7 @@ import (
"net/http"
"os"
"runtime/debug"
"strconv"
"strings"
"sync"
"time"
@ -163,6 +164,37 @@ func HandleGetRemotes(w http.ResponseWriter, r *http.Request) {
return
}
// params: sessionid
func HandleGetHistory(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
w.Header().Set("Access-Control-Allow-Credentials", "true")
w.Header().Set("Vary", "Origin")
w.Header().Set("Cache-Control", "no-cache")
qvals := r.URL.Query()
sessionId := qvals.Get("sessionid")
if _, err := uuid.Parse(sessionId); err != nil {
WriteJsonError(w, fmt.Errorf("invalid sessionid: %w", err))
return
}
numItems := 1000
numStr := qvals.Get("num")
if numStr != "" {
parsedNum, err := strconv.Atoi(numStr)
if err == nil {
numItems = parsedNum
}
}
hitems, err := sstore.GetSessionHistoryItems(r.Context(), sessionId, numItems)
if err != nil {
WriteJsonError(w, err)
return
}
rtnMap := make(map[string]interface{})
rtnMap["history"] = hitems
WriteJsonSuccess(w, rtnMap)
return
}
// params: sessionid, windowid
func HandleGetWindow(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", r.Header.Get("Origin"))
@ -441,6 +473,7 @@ func main() {
gr.HandleFunc("/api/get-all-sessions", HandleGetAllSessions)
gr.HandleFunc("/api/get-window", HandleGetWindow)
gr.HandleFunc("/api/get-remotes", HandleGetRemotes)
gr.HandleFunc("/api/get-history", HandleGetHistory)
gr.HandleFunc("/api/run-command", HandleRunCommand).Methods("GET", "POST", "OPTIONS")
server := &http.Server{
Addr: MainServerAddr,

View File

@ -88,6 +88,7 @@ CREATE TABLE history (
screenid varchar(36) NOT NULL,
windowid varchar(36) NOT NULL,
lineid int NOT NULL,
haderror boolean NOT NULL,
cmdid varchar(36) NOT NULL,
cmdstr text NOT NULL
);

View File

@ -82,6 +82,7 @@ CREATE TABLE history (
screenid varchar(36) NOT NULL,
windowid varchar(36) NOT NULL,
lineid int NOT NULL,
haderror boolean NOT NULL,
cmdid varchar(36) NOT NULL,
cmdstr text NOT NULL
);

View File

@ -9,6 +9,7 @@ import (
"sort"
"strconv"
"strings"
"time"
"github.com/google/uuid"
"github.com/scripthaus-dev/mshell/pkg/base"
@ -278,7 +279,29 @@ func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.U
return sstore.LineUpdate{Line: rtnLine, Cmd: cmd}, nil
}
func addToHistory(ctx context.Context, pk *scpacket.FeCommandPacketType, cmdStr string) error {
func addToHistory(ctx context.Context, pk *scpacket.FeCommandPacketType, update sstore.UpdatePacket, hadError bool) error {
cmdStr := firstArg(pk)
ids, err := resolveIds(ctx, pk, R_Session|R_Screen|R_Window)
if err != nil {
return err
}
lineId, cmdId := sstore.ReadLineCmdIdFromUpdate(update)
hitem := &sstore.HistoryItemType{
HistoryId: uuid.New().String(),
Ts: time.Now().UnixMilli(),
UserId: DefaultUserId,
SessionId: ids.SessionId,
ScreenId: ids.ScreenId,
WindowId: ids.WindowId,
LineId: lineId,
HadError: hadError,
CmdId: cmdId,
CmdStr: cmdStr,
}
err = sstore.InsertHistoryItem(ctx, hitem)
if err != nil {
return err
}
return nil
}
@ -291,9 +314,19 @@ func EvalCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.
if commandStr == "" {
return nil, fmt.Errorf("/eval, invalid emtpty command")
}
update, err := evalCommandInternal(ctx, pk)
if !resolveBool(pk.Kwargs["nohist"], false) {
addToHistory(ctx, pk, pk.Args[0])
err := addToHistory(ctx, pk, update, (err != nil))
if err != nil {
fmt.Printf("[error] adding to history: %w\n", err)
// continue...
}
}
return update, err
}
func evalCommandInternal(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
commandStr := strings.TrimSpace(pk.Args[0])
metaCmd := ""
metaSubCmd := ""
if commandStr == "cd" || strings.HasPrefix(commandStr, "cd ") {
@ -337,7 +370,6 @@ func EvalCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.
newPk.Kwargs[fields[0]] = fields[1]
}
}
return HandleCommand(ctx, newPk)
}

View File

@ -93,8 +93,8 @@ func InsertHistoryItem(ctx context.Context, hitem *HistoryItemType) error {
if err != nil {
return err
}
query := `INSERT INTO history ( historyid, ts, userid, sessionid, screenid, windowid, lineid, cmdid, cmdstr) VALUES
(:historyid,:ts,:userid,:sessionid,:screenid,:windowid,:lineid,:cmdid,:cmdstr)`
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)`
_, err = db.NamedExec(query, hitem)
if err != nil {
return err
@ -102,6 +102,19 @@ func InsertHistoryItem(ctx context.Context, hitem *HistoryItemType) error {
return nil
}
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
}
func GetBareSessions(ctx context.Context) ([]*SessionType, error) {
var rtn []*SessionType
err := WithTx(ctx, func(tx *TxWrap) error {

View File

@ -164,6 +164,7 @@ type HistoryItemType struct {
ScreenId string `json:"screenid"`
WindowId string `json:"windowid"`
LineId int64 `json:"lineid"`
HadError bool `json:"haderror"`
CmdId string `json:"cmdid"`
CmdStr string `json:"cmdstr"`

View File

@ -74,6 +74,17 @@ func (LineUpdate) UpdateType() string {
return LineCmdUpdateStr
}
func ReadLineCmdIdFromUpdate(update UpdatePacket) (int64, string) {
lineUpdate, ok := update.(LineUpdate)
if !ok {
return 0, ""
}
if lineUpdate.Line == nil {
return 0, ""
}
return lineUpdate.Line.LineId, lineUpdate.Line.CmdId
}
type InfoMsgType struct {
InfoTitle string `json:"infotitle"`
InfoError string `json:"infoerror,omitempty"`