authkey get/generate. new schema for incognito/closed screens/sessions. rename scbase functions to use Prompt name

This commit is contained in:
sawka
2022-12-19 18:52:08 -08:00
parent 2684aaef85
commit 21bbab88c8
7 changed files with 103 additions and 31 deletions
+1 -1
View File
@@ -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
+6 -2
View File
@@ -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
View File
@@ -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
);
+9 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+9 -3
View File
@@ -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,