From 17172b158c8e09ddb0448f532c751be64ccc3b71 Mon Sep 17 00:00:00 2001 From: sawka Date: Sat, 2 Jul 2022 13:31:56 -0700 Subject: [PATCH] checkpoint --- cmd/main-server.go | 72 +++++++++++++++++++++++++++++++++++++++----- pkg/sstore/dbops.go | 39 ++++++++++++++++++++++++ pkg/sstore/sstore.go | 14 ++++----- 3 files changed, 110 insertions(+), 15 deletions(-) diff --git a/cmd/main-server.go b/cmd/main-server.go index b2b2cdef..371f0bde 100644 --- a/cmd/main-server.go +++ b/cmd/main-server.go @@ -20,6 +20,7 @@ import ( "github.com/scripthaus-dev/mshell/pkg/cmdtail" "github.com/scripthaus-dev/mshell/pkg/packet" "github.com/scripthaus-dev/sh2-server/pkg/remote" + "github.com/scripthaus-dev/sh2-server/pkg/scpacket" "github.com/scripthaus-dev/sh2-server/pkg/sstore" "github.com/scripthaus-dev/sh2-server/pkg/wsshell" ) @@ -256,6 +257,53 @@ func sendCmdInput(pk *packet.InputPacketType) error { return nil } +// params: name +func GetSession(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() + name := qvals.Get("name") + if name == "" { + WriteJsonError(w, fmt.Errorf("must specify a name")) + return + } + session, err := sstore.GetSessionByName(r.Context(), name) + if err != nil { + WriteJsonError(w, err) + return + } + WriteJsonSuccess(w, session) + return +} + +// params: sessionid, windowid +func GetWindowLines(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") + windowId := qvals.Get("windowid") + if _, err := uuid.Parse(sessionId); err != nil { + WriteJsonError(w, fmt.Errorf("invalid sessionid: %w", err)) + return + } + if _, err := uuid.Parse(windowId); err != nil { + WriteJsonError(w, fmt.Errorf("invalid windowid: %w", err)) + return + } + lines, err := sstore.GetWindowLines(r.Context(), sessionId, windowId) + if err != nil { + WriteJsonError(w, err) + return + } + WriteJsonSuccess(w, lines) + return +} + func GetPtyOutFile(sessionId string, cmdId string) string { pathStr := fmt.Sprintf("/Users/mike/scripthaus/.sessions/%s/%s.ptyout", sessionId, cmdId) return pathStr @@ -337,24 +385,24 @@ func HandleRunCommand(w http.ResponseWriter, r *http.Request) { return } decoder := json.NewDecoder(r.Body) - var params runCommandParams - err := decoder.Decode(¶ms) + var commandPk scpacket.FeCommandPacketType + err := decoder.Decode(&commandPk) if err != nil { WriteJsonError(w, fmt.Errorf("error decoding json: %w", err)) return } - if _, err = uuid.Parse(params.SessionId); err != nil { - WriteJsonError(w, fmt.Errorf("invalid sessionid '%s': %w", params.SessionId, err)) + if _, err = uuid.Parse(commandPk.SessionId); err != nil { + WriteJsonError(w, fmt.Errorf("invalid sessionid '%s': %w", commandPk.SessionId, err)) return } - commandStr := strings.TrimSpace(params.Command) + commandStr := strings.TrimSpace(commandPk.CmdStr) if commandStr == "" { WriteJsonError(w, fmt.Errorf("invalid emtpty command")) return } if strings.HasPrefix(commandStr, "/comment ") { text := strings.TrimSpace(commandStr[9:]) - rtnLine := sstore.MakeNewLineText(params.SessionId, params.WindowId, text) + rtnLine := sstore.MakeNewLineText(commandPk.SessionId, commandPk.WindowId, text) WriteJsonSuccess(w, &runCommandResponse{Line: rtnLine}) return } @@ -370,10 +418,10 @@ func HandleRunCommand(w http.ResponseWriter, r *http.Request) { } return } - rtnLine := sstore.MakeNewLineCmd(params.SessionId, params.WindowId) + rtnLine := sstore.MakeNewLineCmd(commandPk.SessionId, commandPk.WindowId) // rtnLine.CmdText = commandStr runPacket := packet.MakeRunPacket() - runPacket.CK = base.MakeCommandKey(params.SessionId, rtnLine.CmdId) + runPacket.CK = base.MakeCommandKey(commandPk.SessionId, rtnLine.CmdId) runPacket.Cwd = "" runPacket.Env = nil runPacket.Command = commandStr @@ -393,6 +441,12 @@ func HandleRunCommand(w http.ResponseWriter, r *http.Request) { // * userid // * sessionid // +// /api/get-session +// params: +// * name +// returns: +// * session +// // /api/ptyout (pos=[position]) - returns contents of ptyout file // params: // * sessionid @@ -515,6 +569,8 @@ func main() { go runWebSocketServer() gr := mux.NewRouter() gr.HandleFunc("/api/ptyout", GetPtyOut) + gr.HandleFunc("/api/get-session", GetSession) + gr.HandleFunc("/api/get-window-lines", GetWindowLines) gr.HandleFunc("/api/run-command", HandleRunCommand).Methods("GET", "POST", "OPTIONS") server := &http.Server{ Addr: MainServerAddr, diff --git a/pkg/sstore/dbops.go b/pkg/sstore/dbops.go index 1bb1767e..decff430 100644 --- a/pkg/sstore/dbops.go +++ b/pkg/sstore/dbops.go @@ -130,6 +130,20 @@ func GetSessionByName(ctx context.Context, name string) (*SessionType, error) { return rtnSession, nil } +func GetWindowLines(ctx context.Context, sessionId string, windowId string) ([]*LineType, error) { + var lines []*LineType + db, err := GetDB() + if err != nil { + return nil, err + } + query := `SELECT * FROM line WHERE sessionid = ? AND windowid = ?` + err = db.SelectContext(ctx, &lines, query, sessionId, windowId) + if err != nil { + return nil, err + } + return lines, nil +} + // also creates window, and sessionremote func InsertSessionWithName(ctx context.Context, sessionName string) error { if sessionName == "" { @@ -168,3 +182,28 @@ func InsertSessionWithName(ctx context.Context, sessionName string) error { return nil }) } + +func InsertLine(ctx context.Context, line *LineType) error { + if line == nil { + return fmt.Errorf("line cannot be nil") + } + if line.LineId != 0 { + return fmt.Errorf("new line cannot have LineId set") + } + 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) + } + var maxLineId int + query = `SELECT max(lineid) FROM line WHERE sessionid = ? AND windowid = ?` + tx.GetWrap(&maxLineId, query, line.SessionId, line.WindowId) + line.LineId = maxLineId + 1 + query = `INSERT INTO line ( sessionid, windowid, lineid, ts, userid, linetype, text, cmdid) + VALUES (:sessionid,:windowid,:lineid,:ts,:userid,:linetype,:text,:cmdid)` + tx.NamedExecWrap(query, line) + return nil + }) +} diff --git a/pkg/sstore/sstore.go b/pkg/sstore/sstore.go index 19aa0c32..1a4b1f5d 100644 --- a/pkg/sstore/sstore.go +++ b/pkg/sstore/sstore.go @@ -55,13 +55,13 @@ type SessionType struct { } type WindowType struct { - SessionId string `json:"sessionid"` - WindowId string `json:"windowid"` - Name string `json:"name"` - CurRemote string `json:"curremote"` - Remotes []*RemoteType `json:"remotes"` - Lines []*LineType `json:"lines"` - Version int `json:"version"` + SessionId string `json:"sessionid"` + WindowId string `json:"windowid"` + Name string `json:"name"` + CurRemote string `json:"curremote"` + Remotes []*SessionRemote `json:"remotes"` + Lines []*LineType `json:"lines"` + Version int `json:"version"` } type SessionRemote struct {