mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
authkey get/generate. new schema for incognito/closed screens/sessions. rename scbase functions to use Prompt name
This commit is contained in:
+1
-1
@@ -403,7 +403,7 @@ func main() {
|
||||
scHomeDir := scbase.GetPromptHomeDir()
|
||||
log.Printf("[prompt] homedir = %q\n", scHomeDir)
|
||||
|
||||
scLock, err := scbase.AcquireSCLock()
|
||||
scLock, err := scbase.AcquirePromptLock()
|
||||
if err != nil || scLock == nil {
|
||||
log.Printf("[error] cannot acquire sh2 lock: %v\n", err)
|
||||
return
|
||||
|
||||
@@ -13,6 +13,7 @@ CREATE TABLE session (
|
||||
sessionidx int NOT NULL,
|
||||
activescreenid varchar(36) NOT NULL,
|
||||
notifynum int NOT NULL,
|
||||
closed boolean NOT NULL,
|
||||
ownerid varchar(36) NOT NULL,
|
||||
sharemode varchar(12) NOT NULL,
|
||||
accesskey varchar(36) NOT NULL
|
||||
@@ -41,6 +42,8 @@ CREATE TABLE screen (
|
||||
screenopts json NOT NULL,
|
||||
ownerid varchar(36) NOT NULL,
|
||||
sharemode varchar(12) NOT NULL,
|
||||
incognito boolean NOT NULL,
|
||||
closed boolean NOT NULL,
|
||||
PRIMARY KEY (sessionid, screenid)
|
||||
);
|
||||
|
||||
@@ -136,7 +139,7 @@ CREATE TABLE cmd (
|
||||
startpk json NOT NULL,
|
||||
doneinfo json NOT NULL,
|
||||
runout json NOT NULL,
|
||||
rtnstate bool NOT NULL,
|
||||
rtnstate boolean NOT NULL,
|
||||
rtnbasehash varchar(36) NOT NULL,
|
||||
rtndiffhasharr json NOT NULL,
|
||||
PRIMARY KEY (sessionid, cmdid)
|
||||
@@ -156,5 +159,6 @@ CREATE TABLE history (
|
||||
haderror boolean NOT NULL,
|
||||
cmdid varchar(36) NOT NULL,
|
||||
cmdstr text NOT NULL,
|
||||
ismetacmd boolean
|
||||
ismetacmd boolean,
|
||||
incognito boolean
|
||||
);
|
||||
|
||||
+6
-2
@@ -14,6 +14,7 @@ CREATE TABLE session (
|
||||
sessionidx int NOT NULL,
|
||||
activescreenid varchar(36) NOT NULL,
|
||||
notifynum int NOT NULL,
|
||||
closed boolean NOT NULL,
|
||||
ownerid varchar(36) NOT NULL,
|
||||
sharemode varchar(12) NOT NULL,
|
||||
accesskey varchar(36) NOT NULL
|
||||
@@ -40,6 +41,8 @@ CREATE TABLE screen (
|
||||
screenopts json NOT NULL,
|
||||
ownerid varchar(36) NOT NULL,
|
||||
sharemode varchar(12) NOT NULL,
|
||||
incognito boolean NOT NULL,
|
||||
closed boolean NOT NULL,
|
||||
PRIMARY KEY (sessionid, screenid)
|
||||
);
|
||||
CREATE TABLE screen_window (
|
||||
@@ -128,7 +131,7 @@ CREATE TABLE cmd (
|
||||
startpk json NOT NULL,
|
||||
doneinfo json NOT NULL,
|
||||
runout json NOT NULL,
|
||||
rtnstate bool NOT NULL,
|
||||
rtnstate boolean NOT NULL,
|
||||
rtnbasehash varchar(36) NOT NULL,
|
||||
rtndiffhasharr json NOT NULL,
|
||||
PRIMARY KEY (sessionid, cmdid)
|
||||
@@ -147,5 +150,6 @@ CREATE TABLE history (
|
||||
haderror boolean NOT NULL,
|
||||
cmdid varchar(36) NOT NULL,
|
||||
cmdstr text NOT NULL,
|
||||
ismetacmd boolean
|
||||
ismetacmd boolean,
|
||||
incognito boolean
|
||||
);
|
||||
|
||||
@@ -275,7 +275,7 @@ func RunCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.U
|
||||
// runPacket.State is set in remote.RunCommand()
|
||||
runPacket := packet.MakeRunPacket()
|
||||
runPacket.ReqId = uuid.New().String()
|
||||
runPacket.CK = base.MakeCommandKey(ids.SessionId, scbase.GenSCUUID())
|
||||
runPacket.CK = base.MakeCommandKey(ids.SessionId, scbase.GenPromptUUID())
|
||||
runPacket.UsePty = true
|
||||
ptermVal := defaultStr(pk.Kwargs["pterm"], DefaultPTERM)
|
||||
runPacket.TermOpts, err = GetUITermOpts(pk.UIContext.WinSize, ptermVal)
|
||||
@@ -306,8 +306,12 @@ func addToHistory(ctx context.Context, pk *scpacket.FeCommandPacketType, history
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
isIncognito, err := sstore.IsIncognitoScreen(ctx, ids.SessionId, ids.ScreenId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot add to history, error looking up incognito status of screen: %v", err)
|
||||
}
|
||||
hitem := &sstore.HistoryItemType{
|
||||
HistoryId: scbase.GenSCUUID(),
|
||||
HistoryId: scbase.GenPromptUUID(),
|
||||
Ts: time.Now().UnixMilli(),
|
||||
UserId: DefaultUserId,
|
||||
SessionId: ids.SessionId,
|
||||
@@ -318,6 +322,7 @@ func addToHistory(ctx context.Context, pk *scpacket.FeCommandPacketType, history
|
||||
CmdId: historyContext.CmdId,
|
||||
CmdStr: cmdStr,
|
||||
IsMetaCmd: isMetaCmd,
|
||||
Incognito: isIncognito,
|
||||
}
|
||||
if !isMetaCmd && historyContext.RemotePtr != nil {
|
||||
hitem.Remote = *historyContext.RemotePtr
|
||||
@@ -785,7 +790,7 @@ func RemoteNewCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ss
|
||||
return makeRemoteEditErrorReturn_new(visualEdit, fmt.Errorf("/remote:new %v", err))
|
||||
}
|
||||
r := &sstore.RemoteType{
|
||||
RemoteId: scbase.GenSCUUID(),
|
||||
RemoteId: scbase.GenPromptUUID(),
|
||||
PhysicalId: "",
|
||||
RemoteType: sstore.RemoteTypeSsh,
|
||||
RemoteAlias: editArgs.Alias,
|
||||
@@ -941,7 +946,7 @@ func CrCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.Up
|
||||
func makeStaticCmd(ctx context.Context, metaCmd string, ids resolvedIds, cmdStr string, cmdOutput []byte) (*sstore.CmdType, error) {
|
||||
cmd := &sstore.CmdType{
|
||||
SessionId: ids.SessionId,
|
||||
CmdId: scbase.GenSCUUID(),
|
||||
CmdId: scbase.GenPromptUUID(),
|
||||
CmdStr: cmdStr,
|
||||
Remote: ids.Remote.RemotePtr,
|
||||
TermOpts: sstore.TermOpts{Rows: shexec.DefaultTermRows, Cols: shexec.DefaultTermCols, FlexRows: true, MaxPtySize: remote.DefaultMaxPtySize},
|
||||
|
||||
+52
-10
@@ -20,10 +20,11 @@ import (
|
||||
const HomeVarName = "HOME"
|
||||
const PromptHomeVarName = "PROMPT_HOME"
|
||||
const SessionsDirBaseName = "sessions"
|
||||
const SCLockFile = "prompt.lock"
|
||||
const PromptLockFile = "prompt.lock"
|
||||
const PromptDirName = "prompt"
|
||||
const PromptAppPathVarName = "PROMPT_APP_PATH"
|
||||
const PromptVersion = "v0.1.0"
|
||||
const PromptAuthKeyFileName = "prompt.authkey"
|
||||
|
||||
var SessionDirCache = make(map[string]string)
|
||||
var BaseLock = &sync.Mutex{}
|
||||
@@ -63,13 +64,54 @@ func MShellBinaryFromPackage(version string, goos string, goarch string) (io.Rea
|
||||
return fd, nil
|
||||
}
|
||||
|
||||
func AcquireSCLock() (*os.File, error) {
|
||||
func createPromptAuthKeyFile(fileName string) (string, error) {
|
||||
fd, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer fd.Close()
|
||||
keyStr := GenPromptUUID()
|
||||
_, err = fd.Write([]byte(keyStr))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return keyStr, nil
|
||||
}
|
||||
|
||||
func ReadPromptAuthKey() (string, error) {
|
||||
homeDir := GetPromptHomeDir()
|
||||
err := ensureDir(homeDir)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot find/create PROMPT_HOME directory %q", homeDir)
|
||||
}
|
||||
fileName := path.Join(homeDir, PromptAuthKeyFileName)
|
||||
fd, err := os.Open(fileName)
|
||||
if err != nil && errors.Is(err, fs.ErrNotExist) {
|
||||
return createPromptAuthKeyFile(fileName)
|
||||
}
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error opening prompt authkey:%s: %v", fileName, err)
|
||||
}
|
||||
defer fd.Close()
|
||||
buf, err := io.ReadAll(fd)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error reading prompt authkey:%s: %v", fileName, err)
|
||||
}
|
||||
keyStr := string(buf)
|
||||
_, err = uuid.Parse(keyStr)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid authkey:%s format: %v", fileName, err)
|
||||
}
|
||||
return keyStr, nil
|
||||
}
|
||||
|
||||
func AcquirePromptLock() (*os.File, error) {
|
||||
homeDir := GetPromptHomeDir()
|
||||
err := ensureDir(homeDir)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot find/create PROMPT_HOME directory %q", homeDir)
|
||||
}
|
||||
lockFileName := path.Join(homeDir, SCLockFile)
|
||||
lockFileName := path.Join(homeDir, PromptLockFile)
|
||||
fd, err := os.Create(lockFileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -151,19 +193,19 @@ func RunOutFile(sessionId string, cmdId string) (string, error) {
|
||||
return fmt.Sprintf("%s/%s.runout", sdir, cmdId), nil
|
||||
}
|
||||
|
||||
type ScFileNameGenerator struct {
|
||||
ScHome string
|
||||
type PromptFileNameGenerator struct {
|
||||
PromptHome string
|
||||
}
|
||||
|
||||
func (g ScFileNameGenerator) PtyOutFile(ck base.CommandKey) string {
|
||||
return path.Join(g.ScHome, SessionsDirBaseName, ck.GetSessionId(), ck.GetCmdId()+".ptyout")
|
||||
func (g PromptFileNameGenerator) PtyOutFile(ck base.CommandKey) string {
|
||||
return path.Join(g.PromptHome, SessionsDirBaseName, ck.GetSessionId(), ck.GetCmdId()+".ptyout")
|
||||
}
|
||||
|
||||
func (g ScFileNameGenerator) RunOutFile(ck base.CommandKey) string {
|
||||
return path.Join(g.ScHome, SessionsDirBaseName, ck.GetSessionId(), ck.GetCmdId()+".runout")
|
||||
func (g PromptFileNameGenerator) RunOutFile(ck base.CommandKey) string {
|
||||
return path.Join(g.PromptHome, SessionsDirBaseName, ck.GetSessionId(), ck.GetCmdId()+".runout")
|
||||
}
|
||||
|
||||
func GenSCUUID() string {
|
||||
func GenPromptUUID() string {
|
||||
for {
|
||||
rtn := uuid.New().String()
|
||||
_, err := strconv.Atoi(rtn[0:8])
|
||||
|
||||
+20
-9
@@ -14,7 +14,7 @@ import (
|
||||
"github.com/scripthaus-dev/sh2-server/pkg/scbase"
|
||||
)
|
||||
|
||||
const HistoryCols = "historyid, ts, userid, sessionid, screenid, windowid, lineid, cmdid, haderror, cmdstr, remoteownerid, remoteid, remotename, ismetacmd"
|
||||
const HistoryCols = "historyid, ts, userid, sessionid, screenid, windowid, lineid, cmdid, haderror, cmdstr, remoteownerid, remoteid, remotename, ismetacmd, incognito"
|
||||
const DefaultMaxHistoryItems = 1000
|
||||
|
||||
func NumSessions(ctx context.Context) (int, error) {
|
||||
@@ -157,14 +157,24 @@ func InsertHistoryItem(ctx context.Context, hitem *HistoryItemType) error {
|
||||
}
|
||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||
query := `INSERT INTO history
|
||||
( historyid, ts, userid, sessionid, screenid, windowid, lineid, cmdid, haderror, cmdstr, remoteownerid, remoteid, remotename, ismetacmd) VALUES
|
||||
(:historyid,:ts,:userid,:sessionid,:screenid,:windowid,:lineid,:cmdid,:haderror,:cmdstr,:remoteownerid,:remoteid,:remotename,:ismetacmd)`
|
||||
( historyid, ts, userid, sessionid, screenid, windowid, lineid, cmdid, haderror, cmdstr, remoteownerid, remoteid, remotename, ismetacmd, incognito) VALUES
|
||||
(:historyid,:ts,:userid,:sessionid,:screenid,:windowid,:lineid,:cmdid,:haderror,:cmdstr,:remoteownerid,:remoteid,:remotename,:ismetacmd,:incognito)`
|
||||
tx.NamedExecWrap(query, hitem.ToMap())
|
||||
return nil
|
||||
})
|
||||
return txErr
|
||||
}
|
||||
|
||||
func IsIncognitoScreen(ctx context.Context, sessionId string, screenId string) (bool, error) {
|
||||
var rtn bool
|
||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||
query := `SELECT incognito FROM screen WHERE sessionid = ? AND screenid = ?`
|
||||
tx.GetWrap(&rtn, query, sessionId, screenId)
|
||||
return nil
|
||||
})
|
||||
return rtn, txErr
|
||||
}
|
||||
|
||||
func runHistoryQuery(tx *TxWrap, sessionId string, windowId string, opts HistoryQueryOpts) ([]*HistoryItemType, error) {
|
||||
// check sessionid/windowid format because we are directly inserting them into the SQL
|
||||
if sessionId != "" {
|
||||
@@ -390,12 +400,13 @@ func GetSessionByName(ctx context.Context, name string) (*SessionType, error) {
|
||||
// also creates default window, returns sessionId
|
||||
// if sessionName == "", it will be generated
|
||||
func InsertSessionWithName(ctx context.Context, sessionName string, activate bool) (UpdatePacket, error) {
|
||||
newSessionId := scbase.GenSCUUID()
|
||||
newSessionId := scbase.GenPromptUUID()
|
||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||
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`)
|
||||
query := `INSERT INTO session (sessionid, name, activescreenid, sessionidx, notifynum, ownerid, sharemode, accesskey) VALUES (?, ?, '', ?, ?, '', 'local', '')`
|
||||
query := `INSERT INTO session (sessionid, name, activescreenid, sessionidx, notifynum, closed, ownerid, sharemode, accesskey)
|
||||
VALUES (?, ?, '', ?, ?, 0, '', 'local', '')`
|
||||
tx.ExecWrap(query, newSessionId, sessionName, maxSessionIdx+1, 0)
|
||||
_, err := InsertScreen(tx.Context(), newSessionId, "", true)
|
||||
if err != nil {
|
||||
@@ -493,8 +504,8 @@ func InsertScreen(ctx context.Context, sessionId string, origScreenName string,
|
||||
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(origScreenName, "s%d", maxScreenIdx+1, screenNames)
|
||||
newScreenId = scbase.GenSCUUID()
|
||||
query = `INSERT INTO screen (sessionid, screenid, name, activewindowid, screenidx, screenopts, ownerid, sharemode) VALUES (?, ?, ?, ?, ?, ?, '', 'local')`
|
||||
newScreenId = scbase.GenPromptUUID()
|
||||
query = `INSERT INTO screen (sessionid, screenid, name, activewindowid, screenidx, screenopts, ownerid, sharemode, incognito, closed) VALUES (?, ?, ?, ?, ?, ?, '', 'local', 0, 0)`
|
||||
tx.ExecWrap(query, sessionId, newScreenId, screenName, newWindowId, maxScreenIdx+1, ScreenOptsType{})
|
||||
layout := LayoutType{Type: LayoutFull}
|
||||
query = `INSERT INTO screen_window (sessionid, screenid, windowid, name, layout, selectedline, anchor, focustype) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
@@ -541,7 +552,7 @@ func GetScreenById(ctx context.Context, sessionId string, screenId string) (*Scr
|
||||
func txCreateWindow(tx *TxWrap, sessionId string, curRemote RemotePtrType) string {
|
||||
w := &WindowType{
|
||||
SessionId: sessionId,
|
||||
WindowId: scbase.GenSCUUID(),
|
||||
WindowId: scbase.GenPromptUUID(),
|
||||
CurRemote: curRemote,
|
||||
NextLineNum: 1,
|
||||
WinOpts: WindowOptsType{},
|
||||
@@ -949,7 +960,7 @@ func UpdateRemoteState(ctx context.Context, sessionId string, windowId string, r
|
||||
ri = RIFromMap(m)
|
||||
if ri == nil {
|
||||
ri = &RemoteInstance{
|
||||
RIId: scbase.GenSCUUID(),
|
||||
RIId: scbase.GenPromptUUID(),
|
||||
Name: remotePtr.Name,
|
||||
SessionId: sessionId,
|
||||
WindowId: windowId,
|
||||
|
||||
@@ -152,6 +152,7 @@ type SessionType struct {
|
||||
ShareMode string `json:"sharemode"`
|
||||
AccessKey string `json:"-"`
|
||||
NotifyNum int64 `json:"notifynum"`
|
||||
Closed bool `json:"closed,omitempty"`
|
||||
Screens []*ScreenType `json:"screens"`
|
||||
Remotes []*RemoteInstance `json:"remotes"`
|
||||
|
||||
@@ -305,6 +306,7 @@ func (h *HistoryItemType) ToMap() map[string]interface{} {
|
||||
rtn["remoteid"] = h.Remote.RemoteId
|
||||
rtn["remotename"] = h.Remote.Name
|
||||
rtn["ismetacmd"] = h.IsMetaCmd
|
||||
rtn["incognito"] = h.Incognito
|
||||
return rtn
|
||||
}
|
||||
|
||||
@@ -328,6 +330,7 @@ func HistoryItemFromMap(m map[string]interface{}) *HistoryItemType {
|
||||
quickSetStr(&h.Remote.Name, m, "remotename")
|
||||
quickSetBool(&h.IsMetaCmd, m, "ismetacmd")
|
||||
quickSetStr(&h.HistoryNum, m, "historynum")
|
||||
quickSetBool(&h.Incognito, m, "incognito")
|
||||
return &h
|
||||
}
|
||||
|
||||
@@ -352,6 +355,8 @@ type ScreenType struct {
|
||||
ScreenOpts *ScreenOptsType `json:"screenopts"`
|
||||
OwnerId string `json:"ownerid"`
|
||||
ShareMode string `json:"sharemode"`
|
||||
Incognito bool `json:"incognito,omitempty"`
|
||||
Closed bool `json:"closed,omitempty"`
|
||||
Windows []*ScreenWindowType `json:"windows"`
|
||||
|
||||
// only for updates
|
||||
@@ -430,6 +435,7 @@ type HistoryItemType struct {
|
||||
CmdStr string `json:"cmdstr"`
|
||||
Remote RemotePtrType `json:"remote"`
|
||||
IsMetaCmd bool `json:"ismetacmd"`
|
||||
Incognito bool `json:"incognito,omitempty"`
|
||||
|
||||
// only for updates
|
||||
Remove bool `json:"remove"`
|
||||
@@ -761,7 +767,7 @@ func makeNewLineCmd(sessionId string, windowId string, userId string, cmdId stri
|
||||
rtn.SessionId = sessionId
|
||||
rtn.WindowId = windowId
|
||||
rtn.UserId = userId
|
||||
rtn.LineId = scbase.GenSCUUID()
|
||||
rtn.LineId = scbase.GenPromptUUID()
|
||||
rtn.Ts = time.Now().UnixMilli()
|
||||
rtn.LineLocal = true
|
||||
rtn.LineType = LineTypeCmd
|
||||
@@ -775,7 +781,7 @@ func makeNewLineText(sessionId string, windowId string, userId string, text stri
|
||||
rtn.SessionId = sessionId
|
||||
rtn.WindowId = windowId
|
||||
rtn.UserId = userId
|
||||
rtn.LineId = scbase.GenSCUUID()
|
||||
rtn.LineId = scbase.GenPromptUUID()
|
||||
rtn.Ts = time.Now().UnixMilli()
|
||||
rtn.LineLocal = true
|
||||
rtn.LineType = LineTypeText
|
||||
@@ -824,7 +830,7 @@ func EnsureLocalRemote(ctx context.Context) error {
|
||||
}
|
||||
// create the local remote
|
||||
localRemote := &RemoteType{
|
||||
RemoteId: scbase.GenSCUUID(),
|
||||
RemoteId: scbase.GenPromptUUID(),
|
||||
PhysicalId: physicalId,
|
||||
RemoteType: RemoteTypeSsh,
|
||||
RemoteAlias: LocalRemoteAlias,
|
||||
|
||||
Reference in New Issue
Block a user