Save server EntryRoot and OS type during init, use to progress toward Windows server support

This commit is contained in:
2024-05-30 22:57:05 -04:00
parent 6cf01e0d3c
commit b03d751618
4 changed files with 30 additions and 14 deletions
+3
View File
@@ -6,6 +6,7 @@ import (
"github.com/rwinkhart/MUTN/src/cli" "github.com/rwinkhart/MUTN/src/cli"
"github.com/rwinkhart/MUTN/src/sync" "github.com/rwinkhart/MUTN/src/sync"
"os" "os"
"strconv"
"strings" "strings"
) )
@@ -30,6 +31,8 @@ func main() {
case "register": case "register":
// register a new device ID // register a new device ID
os.Create(backend.ConfigDir + backend.PathSeparator + "devices" + backend.PathSeparator + args[2]) os.Create(backend.ConfigDir + backend.PathSeparator + "devices" + backend.PathSeparator + args[2])
// print EntryRoot and bool indicating OS type to stdout for client to store in config
fmt.Print(backend.EntryRoot + "\x1d" + strconv.FormatBool(backend.IsWindows))
case "init": case "init":
// create the necessary directories for libmuttonserver to function // create the necessary directories for libmuttonserver to function
backend.DirInit() backend.DirInit()
+4 -1
View File
@@ -43,7 +43,10 @@ func TempInitCli() {
backend.TempInit(map[string]string{"textEditor": textEditor, "gpgID": gpgID, "sshUser": sshUser, "sshIP": sshIP, "sshPort": sshPort, "sshKey": sshKey, "sshKeyProtected": strconv.FormatBool(sshKeyProtected)}) backend.TempInit(map[string]string{"textEditor": textEditor, "gpgID": gpgID, "sshUser": sshUser, "sshIP": sshIP, "sshPort": sshPort, "sshKey": sshKey, "sshKeyProtected": strconv.FormatBool(sshKeyProtected)})
// generate device ID // generate device ID
sync.DeviceIDGen() sshEntryRoot, sshIsWindows := sync.DeviceIDGen()
// update config file with sshEntryRoot and sshIsWindows TODO append to existing config file
backend.TempInit(map[string]string{"textEditor": textEditor, "gpgID": gpgID, "sshUser": sshUser, "sshIP": sshIP, "sshPort": sshPort, "sshKey": sshKey, "sshKeyProtected": strconv.FormatBool(sshKeyProtected), "sshEntryRoot": sshEntryRoot, "sshIsWindows": sshIsWindows})
} else { } else {
// write config file // write config file
backend.TempInit(map[string]string{"textEditor": textEditor, "gpgID": gpgID}) backend.TempInit(map[string]string{"textEditor": textEditor, "gpgID": gpgID})
+16 -10
View File
@@ -19,18 +19,19 @@ const (
ansiUpload = "\033[38;5;4m" ansiUpload = "\033[38;5;4m"
) )
// getSSHClient returns an SSH client connection to the server (also returns the remote username as a string) // getSSHClient returns an SSH client connection to the server (also returns the remote EntryRoot as a string and the server's OS as a bool - IsWindows)
// only supports key-based authentication (passphrases are supported for CLI-based implementations) // only supports key-based authentication (passphrases are supported for CLI-based implementations)
func getSSHClient(manualSync bool) (*ssh.Client, string) { func getSSHClient(manualSync bool) (*ssh.Client, string, bool) {
// get SSH config info, exit if not configured (displaying an error if the sync job was called manually) // get SSH config info, exit if not configured (displaying an error if the sync job was called manually)
var sshUserConfig []string var sshUserConfig []string
if manualSync { if manualSync {
sshUserConfig = backend.ReadConfig([]string{"sshUser", "sshIP", "sshPort", "sshKey", "sshKeyProtected"}, "SSH settings not configured - run \"mutn init\" to configure") sshUserConfig = backend.ReadConfig([]string{"sshUser", "sshIP", "sshPort", "sshKey", "sshKeyProtected", "sshEntryRoot", "sshIsWindows"}, "SSH settings not configured - run \"mutn init\" to configure")
} else { } else {
sshUserConfig = backend.ReadConfig([]string{"sshUser", "sshIP", "sshPort", "sshKey", "sshKeyProtected"}, "0") sshUserConfig = backend.ReadConfig([]string{"sshUser", "sshIP", "sshPort", "sshKey", "sshKeyProtected"}, "0")
} }
var user, ip, port, keyFile, keyFileProtected string var user, ip, port, keyFile, keyFileProtected, entryRoot string
var isWindows bool
for i, key := range sshUserConfig { for i, key := range sshUserConfig {
switch i { switch i {
case 0: case 0:
@@ -43,6 +44,10 @@ func getSSHClient(manualSync bool) (*ssh.Client, string) {
keyFile = key keyFile = key
case 4: case 4:
keyFileProtected = key keyFileProtected = key
case 5:
entryRoot = key
case 6:
isWindows, _ = strconv.ParseBool(key)
} }
} }
@@ -88,13 +93,13 @@ func getSSHClient(manualSync bool) (*ssh.Client, string) {
os.Exit(1) os.Exit(1)
} }
return sshClient, user return sshClient, entryRoot, isWindows
} }
// GetSSHOutput runs a command over SSH and returns the output as a string // GetSSHOutput runs a command over SSH and returns the output as a string
// TODO run getSSHClient() in RunJob and pass to each function that needs it (to avoid multiple connections), move defer to RunJob // TODO run getSSHClient() ONCE in RunJob and pass to each function that needs it (to avoid multiple connections), move defer to RunJob
func GetSSHOutput(cmd string, manualSync bool) string { func GetSSHOutput(cmd string, manualSync bool) string {
sshClient, _ := getSSHClient(manualSync) sshClient, _, _ := getSSHClient(manualSync)
defer sshClient.Close() defer sshClient.Close()
// create a session // create a session
@@ -189,9 +194,10 @@ func targetLocationFormatSFTP(targetName, serverEntryRoot string, serverIsWindow
} }
// sftpSync takes two slices of entries (one for downloads and one for uploads) and syncs them between the client and server using SFTP // sftpSync takes two slices of entries (one for downloads and one for uploads) and syncs them between the client and server using SFTP
// TODO test Windows server hosting support
func sftpSync(downloadList, uploadList []string, manualSync bool) { func sftpSync(downloadList, uploadList []string, manualSync bool) {
// establish an SSH connection for transfers // establish an SSH connection for transfers
sshClient, sshUser := getSSHClient(manualSync) sshClient, sshEntryRoot, sshIsWindows := getSSHClient(manualSync)
defer sshClient.Close() defer sshClient.Close()
// create an SFTP client // create an SFTP client
@@ -210,7 +216,7 @@ func sftpSync(downloadList, uploadList []string, manualSync bool) {
fmt.Println("Downloading " + ansiDownload + entryName + backend.AnsiReset) fmt.Println("Downloading " + ansiDownload + entryName + backend.AnsiReset)
// store path to remote entry // store path to remote entry
remoteEntryFullPath := targetLocationFormatSFTP(entryName, "/home/"+sshUser+"/.local/share/libmutton", false) // TODO temporarily hard-coded to expect a default home folder location on a UNIX-like server remoteEntryFullPath := targetLocationFormatSFTP(entryName, sshEntryRoot, sshIsWindows)
// save modification time of remote file // save modification time of remote file
var fileInfo os.FileInfo var fileInfo os.FileInfo
@@ -287,7 +293,7 @@ func sftpSync(downloadList, uploadList []string, manualSync bool) {
} }
// store path to remote entry // store path to remote entry
remoteEntryFullPath := targetLocationFormatSFTP(entryName, "/home/"+sshUser+"/.local/share/libmutton", false) // TODO temporarily hard-coded to expect a default home folder location on a UNIX-like server remoteEntryFullPath := targetLocationFormatSFTP(entryName, sshEntryRoot, sshIsWindows)
// create remote file // create remote file
var remoteFile *sftp.File var remoteFile *sftp.File
+7 -3
View File
@@ -4,14 +4,18 @@ import (
"github.com/rwinkhart/MUTN/src/backend" "github.com/rwinkhart/MUTN/src/backend"
"math/rand" "math/rand"
"os" "os"
"strings"
) )
// DeviceIDGen generates a new client device ID and registers it with the server // DeviceIDGen generates a new client device ID and registers it with the server
// device IDs are only needed for online synchronization // device IDs are only needed for online synchronization
func DeviceIDGen() { // returns the remote EntryRoot and OS type (OS type is a bool: backend.IsWindows)
func DeviceIDGen() (string, string) {
deviceIDPrefix, _ := os.Hostname() deviceIDPrefix, _ := os.Hostname()
deviceIDSuffix := backend.StringGen(rand.Intn(48)+48, false, 0) // TODO consider using complex string generator and removing unsafe characters manually deviceIDSuffix := backend.StringGen(rand.Intn(48)+48, false, 0) // TODO consider using complex string generator and removing unsafe characters manually
deviceID := deviceIDPrefix + "-" + deviceIDSuffix deviceID := deviceIDPrefix + "-" + deviceIDSuffix
os.Create(backend.ConfigDir + backend.PathSeparator + "devices" + backend.PathSeparator + deviceID) // TODO remove existing device ID file if it exists (from both client and server) os.Create(backend.ConfigDir + backend.PathSeparator + "devices" + backend.PathSeparator + deviceID) // TODO remove existing device ID file if it exists (from both client and server)
GetSSHOutput("libmuttonserver register "+deviceID, false) // register device ID with server sshEntryRootSSHIsWindows := strings.Split(GetSSHOutput("libmuttonserver register "+deviceID, false), "\x1d") // register device ID with server and fetch remote EntryRoot and OS type
return sshEntryRootSSHIsWindows[0], sshEntryRootSSHIsWindows[1]
} }