mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
remote editing checkpoint
This commit is contained in:
+52
-39
@@ -33,9 +33,11 @@ const (
|
||||
const DefaultUserId = "sawka"
|
||||
const MaxNameLen = 50
|
||||
const MaxRemoteAliasLen = 50
|
||||
const PasswordUnchangedSentinel = "--unchanged--"
|
||||
|
||||
var ColorNames = []string{"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", "orange"}
|
||||
var RemoteColorNames = []string{"red", "green", "yellow", "blue", "magenta", "cyan", "white", "orange"}
|
||||
var RemoteSetArgs = []string{"alias", "connectmode", "key", "password", "autoinstall", "color"}
|
||||
|
||||
var hostNameRe = regexp.MustCompile("^[a-z][a-z0-9.-]*$")
|
||||
var userHostRe = regexp.MustCompile("^(sudo@)?([a-z][a-z0-9-]*)@([a-z][a-z0-9.-]*)(?::([0-9]+))?$")
|
||||
@@ -96,7 +98,6 @@ func init() {
|
||||
registerCmdFn("remote:connect", RemoteConnectCommand)
|
||||
registerCmdFn("remote:install", RemoteInstallCommand)
|
||||
registerCmdFn("remote:installcancel", RemoteInstallCancelCommand)
|
||||
registerCmdFn("remote:edit", RemoteEditCommand)
|
||||
|
||||
registerCmdFn("window:resize", WindowResizeCommand)
|
||||
|
||||
@@ -494,32 +495,51 @@ func RemoteDisconnectCommand(ctx context.Context, pk *scpacket.FeCommandPacketTy
|
||||
}, nil
|
||||
}
|
||||
|
||||
func RemoteEditCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
ids, err := resolveUiIds(ctx, pk, R_Session|R_Window|R_Remote)
|
||||
func makeRemoteEditUpdate_new(err error) sstore.UpdatePacket {
|
||||
redit := &sstore.RemoteEditType{
|
||||
RemoteEdit: true,
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
redit.ErrorStr = err.Error()
|
||||
}
|
||||
update := sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
RemoteEdit: &sstore.RemoteEditType{
|
||||
RemoteEdit: true,
|
||||
RemoteId: ids.Remote.RemotePtr.RemoteId,
|
||||
},
|
||||
RemoteEdit: redit,
|
||||
},
|
||||
}
|
||||
return update, nil
|
||||
return update
|
||||
}
|
||||
|
||||
func makeRemoteEditErrorReturn(visual bool, err error) (sstore.UpdatePacket, error) {
|
||||
func makeRemoteEditErrorReturn_new(visual bool, err error) (sstore.UpdatePacket, error) {
|
||||
if visual {
|
||||
return sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
RemoteEdit: &sstore.RemoteEditType{
|
||||
RemoteEdit: true,
|
||||
ErrorStr: err.Error(),
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
return makeRemoteEditUpdate_new(err), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func makeRemoteEditUpdate_edit(ids resolvedIds, err error) sstore.UpdatePacket {
|
||||
redit := &sstore.RemoteEditType{
|
||||
RemoteEdit: true,
|
||||
}
|
||||
redit.RemoteId = ids.Remote.RemotePtr.RemoteId
|
||||
if ids.Remote.RemoteCopy.SSHOpts != nil {
|
||||
redit.KeyStr = ids.Remote.RemoteCopy.SSHOpts.SSHIdentity
|
||||
redit.HasPassword = (ids.Remote.RemoteCopy.SSHOpts.SSHPassword != "")
|
||||
}
|
||||
if err != nil {
|
||||
redit.ErrorStr = err.Error()
|
||||
}
|
||||
update := sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
RemoteEdit: redit,
|
||||
},
|
||||
}
|
||||
return update
|
||||
}
|
||||
|
||||
func makeRemoteEditErrorReturn_edit(ids resolvedIds, visual bool, err error) (sstore.UpdatePacket, error) {
|
||||
if visual {
|
||||
return makeRemoteEditUpdate_edit(ids, err), nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
@@ -543,6 +563,9 @@ func parseRemoteEditArgs(isNew bool, pk *scpacket.FeCommandPacketType) (*RemoteE
|
||||
var isSudo bool
|
||||
|
||||
if isNew {
|
||||
if len(pk.Args) == 0 {
|
||||
return nil, fmt.Errorf("/remote:new must specify user@host argument (set visual=1 to edit in UI)")
|
||||
}
|
||||
userHost := pk.Args[0]
|
||||
m := userHostRe.FindStringSubmatch(userHost)
|
||||
if m == nil {
|
||||
@@ -652,7 +675,7 @@ func parseRemoteEditArgs(isNew bool, pk *scpacket.FeCommandPacketType) (*RemoteE
|
||||
if _, found := pk.Kwargs[sstore.RemoteField_Color]; found {
|
||||
editMap[sstore.RemoteField_Color] = color
|
||||
}
|
||||
if _, found := pk.Kwargs["password"]; found {
|
||||
if _, found := pk.Kwargs["password"]; found && pk.Kwargs["password"] != PasswordUnchangedSentinel {
|
||||
editMap[sstore.RemoteField_SSHPassword] = sshPassword
|
||||
}
|
||||
|
||||
@@ -673,18 +696,12 @@ func parseRemoteEditArgs(isNew bool, pk *scpacket.FeCommandPacketType) (*RemoteE
|
||||
func RemoteNewCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
visualEdit := resolveBool(pk.Kwargs["visual"], false)
|
||||
isSubmitted := resolveBool(pk.Kwargs["submit"], false)
|
||||
if (len(pk.Args) == 0 || pk.Args[0] == "") && !isSubmitted {
|
||||
return sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
RemoteEdit: &sstore.RemoteEditType{
|
||||
RemoteEdit: true,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
if visualEdit && !isSubmitted && len(pk.Args) == 0 {
|
||||
return makeRemoteEditUpdate_new(nil), nil
|
||||
}
|
||||
editArgs, err := parseRemoteEditArgs(true, pk)
|
||||
if err != nil {
|
||||
return makeRemoteEditErrorReturn(visualEdit, fmt.Errorf("/remote:new %v", err))
|
||||
return makeRemoteEditErrorReturn_new(visualEdit, fmt.Errorf("/remote:new %v", err))
|
||||
}
|
||||
r := &sstore.RemoteType{
|
||||
RemoteId: scbase.GenSCUUID(),
|
||||
@@ -704,7 +721,7 @@ func RemoteNewCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ss
|
||||
}
|
||||
err = remote.AddRemote(ctx, r)
|
||||
if err != nil {
|
||||
return makeRemoteEditErrorReturn(visualEdit, fmt.Errorf("cannot create remote %q: %v", r.RemoteCanonicalName, err))
|
||||
return makeRemoteEditErrorReturn_new(visualEdit, fmt.Errorf("cannot create remote %q: %v", r.RemoteCanonicalName, err))
|
||||
}
|
||||
// SUCCESS
|
||||
update := sstore.ModelUpdate{
|
||||
@@ -725,21 +742,17 @@ func RemoteSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ss
|
||||
isSubmitted := resolveBool(pk.Kwargs["submit"], false)
|
||||
editArgs, err := parseRemoteEditArgs(false, pk)
|
||||
if err != nil {
|
||||
return makeRemoteEditErrorReturn(visualEdit, fmt.Errorf("/remote:new %v", err))
|
||||
return makeRemoteEditErrorReturn_edit(ids, visualEdit, fmt.Errorf("/remote:new %v", err))
|
||||
}
|
||||
if visualEdit && !isSubmitted && len(editArgs.EditMap) == 0 {
|
||||
return sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
RemoteEdit: &sstore.RemoteEditType{
|
||||
RemoteEdit: true,
|
||||
RemoteId: ids.Remote.RemotePtr.RemoteId,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
return makeRemoteEditUpdate_edit(ids, nil), nil
|
||||
}
|
||||
if !visualEdit && len(editArgs.EditMap) == 0 {
|
||||
return nil, fmt.Errorf("/remote:set no updates, can set %s. (set visual=1 to edit in UI)", formatStrs(RemoteSetArgs, "or", false))
|
||||
}
|
||||
err = ids.Remote.MShell.UpdateRemote(ctx, editArgs.EditMap)
|
||||
if err != nil {
|
||||
return makeRemoteEditErrorReturn(visualEdit, fmt.Errorf("/remote:new error updating remote: %v", err))
|
||||
return makeRemoteEditErrorReturn_edit(ids, visualEdit, fmt.Errorf("/remote:new error updating remote: %v", err))
|
||||
}
|
||||
update := sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
|
||||
@@ -34,6 +34,7 @@ type ResolvedRemote struct {
|
||||
MShell *remote.MShellProc
|
||||
RState remote.RemoteRuntimeState
|
||||
RemoteState *sstore.RemoteState
|
||||
RemoteCopy *sstore.RemoteType
|
||||
}
|
||||
|
||||
type ResolveItem struct {
|
||||
@@ -321,6 +322,7 @@ func resolveRemoteFromPtr(ctx context.Context, rptr *sstore.RemotePtrType, sessi
|
||||
return nil, fmt.Errorf("invalid remote '%s', not found", rptr.RemoteId)
|
||||
}
|
||||
rstate := msh.GetRemoteRuntimeState()
|
||||
rcopy := msh.GetRemoteCopy()
|
||||
displayName := rstate.GetDisplayName(rptr)
|
||||
rtn := &ResolvedRemote{
|
||||
DisplayName: displayName,
|
||||
@@ -328,6 +330,7 @@ func resolveRemoteFromPtr(ctx context.Context, rptr *sstore.RemotePtrType, sessi
|
||||
RemoteState: nil,
|
||||
RState: rstate,
|
||||
MShell: msh,
|
||||
RemoteCopy: &rcopy,
|
||||
}
|
||||
if sessionId != "" && windowId != "" {
|
||||
state, err := sstore.GetRemoteState(ctx, sessionId, windowId, *rptr)
|
||||
|
||||
@@ -415,8 +415,13 @@ func (msh *MShellProc) GetRemoteRuntimeState() RemoteRuntimeState {
|
||||
vars["local"] = "1"
|
||||
}
|
||||
vars["port"] = "22"
|
||||
if msh.Remote.SSHOpts != nil && msh.Remote.SSHOpts.SSHPort != 0 {
|
||||
vars["port"] = strconv.Itoa(msh.Remote.SSHOpts.SSHPort)
|
||||
if msh.Remote.SSHOpts != nil {
|
||||
if msh.Remote.SSHOpts.SSHPort != 0 {
|
||||
vars["port"] = strconv.Itoa(msh.Remote.SSHOpts.SSHPort)
|
||||
}
|
||||
}
|
||||
if msh.Remote.RemoteOpts != nil && msh.Remote.RemoteOpts.Color != "" {
|
||||
vars["color"] = msh.Remote.RemoteOpts.Color
|
||||
}
|
||||
if msh.ServerProc != nil && msh.ServerProc.InitPk != nil {
|
||||
state.DefaultState = &sstore.RemoteState{
|
||||
|
||||
+1
-1
@@ -1051,7 +1051,7 @@ func UpdateRemote(ctx context.Context, remoteId string, editMap map[string]inter
|
||||
}
|
||||
if alias, found := editMap[RemoteField_Alias]; found {
|
||||
query = `SELECT remoteid FROM remote WHERE remotealias = ? AND remoteid <> ?`
|
||||
if tx.Exists(query, alias, remoteId) {
|
||||
if alias != "" && tx.Exists(query, alias, remoteId) {
|
||||
return fmt.Errorf("remote has duplicate alias, cannot update")
|
||||
}
|
||||
query = `UPDATE remote SET remotealias = ? WHERE remoteid = ?`
|
||||
|
||||
@@ -80,10 +80,12 @@ func InfoMsgUpdate(infoMsgFmt string, args ...interface{}) *ModelUpdate {
|
||||
}
|
||||
|
||||
type RemoteEditType struct {
|
||||
RemoteEdit bool `json:"remoteedit"`
|
||||
RemoteId string `json:"remoteid,omitempty"`
|
||||
ErrorStr string `json:"errorstr,omitempty"`
|
||||
InfoStr string `json:"infostr,omitempty"`
|
||||
RemoteEdit bool `json:"remoteedit"`
|
||||
RemoteId string `json:"remoteid,omitempty"`
|
||||
ErrorStr string `json:"errorstr,omitempty"`
|
||||
InfoStr string `json:"infostr,omitempty"`
|
||||
KeyStr string `json:"keystr,omitempty"`
|
||||
HasPassword bool `json:"haspassword,omitempty"`
|
||||
}
|
||||
|
||||
type InfoMsgType struct {
|
||||
|
||||
Reference in New Issue
Block a user