mirror of
https://github.com/rwinkhart/libmutton.git
synced 2026-08-27 20:36:29 -04:00
Handle more server-side errors from the client
This commit is contained in:
+9
-2
@@ -2,9 +2,9 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/rwinkhart/go-boilerplate/back"
|
"github.com/rwinkhart/go-boilerplate/back"
|
||||||
@@ -110,8 +110,15 @@ func main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// print EntryRoot, AgeDir and bool indicating OS type to stdout for client to store in config
|
// print EntryRoot, AgeDir and bool indicating OS type to stdout for client to store in config
|
||||||
fmt.Print(global.EntryRoot + global.FSSpace + global.AgeDir + global.FSSpace + strconv.FormatBool(global.IsWindows))
|
registerResp := synccommon.RegisterResp{EntryRoot: global.EntryRoot, AgeDir: global.AgeDir, IsWindows: global.IsWindows}
|
||||||
|
registerRespBytes, err := json.Marshal(registerResp)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("{\"errMsg\":\"%s\"}", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Print(string(registerRespBytes))
|
||||||
case "init":
|
case "init":
|
||||||
// create the necessary directories for libmuttonserver to function
|
// create the necessary directories for libmuttonserver to function
|
||||||
_, err := global.DirInit(false)
|
_, err := global.DirInit(false)
|
||||||
|
|||||||
@@ -561,5 +561,6 @@ func RunJob(returnLists bool) ([3][]string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return [3][]string{nil, nil, nil}, errors.New("unable to sync entries: " + err.Error())
|
return [3][]string{nil, nil, nil}, errors.New("unable to sync entries: " + err.Error())
|
||||||
}
|
}
|
||||||
return lists, nil // dummy return for when not returning lists
|
_ = sshClient.Close() // ignore error; non-critical/unlikely/not much could be done about it
|
||||||
|
return lists, nil // dummy return for when not returning lists
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-3
@@ -22,6 +22,7 @@ func ShearRemoteFromClient(vanityPath string, onlyShearAgeFile bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var modifier string
|
var modifier string
|
||||||
|
var output []byte
|
||||||
sshClient, offlineMode, _, _, _, err := GetSSHClient()
|
sshClient, offlineMode, _, _, _, err := GetSSHClient()
|
||||||
if offlineMode {
|
if offlineMode {
|
||||||
goto end
|
goto end
|
||||||
@@ -42,10 +43,13 @@ func ShearRemoteFromClient(vanityPath string, onlyShearAgeFile bool) error {
|
|||||||
if onlyShearAgeFile {
|
if onlyShearAgeFile {
|
||||||
modifier = "-age"
|
modifier = "-age"
|
||||||
}
|
}
|
||||||
_, err = GetSSHOutput(sshClient, "libmuttonserver shear"+modifier, deviceID+"\n"+strings.ReplaceAll(vanityPath, global.PathSeparator, global.FSPath))
|
output, err = GetSSHOutput(sshClient, "libmuttonserver shear"+modifier, deviceID+"\n"+strings.ReplaceAll(vanityPath, global.PathSeparator, global.FSPath))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("unable to shear target remotely: " + err.Error())
|
return errors.New("unable to shear target remotely: " + err.Error())
|
||||||
}
|
}
|
||||||
|
if len(output) > 11 {
|
||||||
|
return errors.New("unable to complete shear; server-side error occurred: " + string(output)[11:len(output)-2])
|
||||||
|
}
|
||||||
|
|
||||||
// close the SSH client
|
// close the SSH client
|
||||||
err = sshClient.Close()
|
err = sshClient.Close()
|
||||||
@@ -78,6 +82,7 @@ func RenameRemoteFromClient(oldVanityPath, newVanityPath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create an SSH client
|
// create an SSH client
|
||||||
|
var output []byte
|
||||||
sshClient, offlineMode, _, _, _, err := GetSSHClient()
|
sshClient, offlineMode, _, _, _, err := GetSSHClient()
|
||||||
if offlineMode {
|
if offlineMode {
|
||||||
goto end
|
goto end
|
||||||
@@ -87,13 +92,16 @@ func RenameRemoteFromClient(oldVanityPath, newVanityPath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// call the server to move the target on the remote system and add the old target to the deletions list
|
// call the server to move the target on the remote system and add the old target to the deletions list
|
||||||
_, err = GetSSHOutput(sshClient, "libmuttonserver rename",
|
output, err = GetSSHOutput(sshClient, "libmuttonserver rename",
|
||||||
(deviceIDList)[0].Name()+"\n"+
|
(deviceIDList)[0].Name()+"\n"+
|
||||||
strings.ReplaceAll(oldVanityPath, global.PathSeparator, global.FSPath)+"\n"+
|
strings.ReplaceAll(oldVanityPath, global.PathSeparator, global.FSPath)+"\n"+
|
||||||
strings.ReplaceAll(newVanityPath, global.PathSeparator, global.FSPath))
|
strings.ReplaceAll(newVanityPath, global.PathSeparator, global.FSPath))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("unable to rename target remotely: " + err.Error())
|
return errors.New("unable to rename target remotely: " + err.Error())
|
||||||
}
|
}
|
||||||
|
if len(output) > 11 {
|
||||||
|
return errors.New("unable to complete rename; server-side error occurred: " + string(output)[11:len(output)-2])
|
||||||
|
}
|
||||||
|
|
||||||
// close the SSH client
|
// close the SSH client
|
||||||
err = sshClient.Close()
|
err = sshClient.Close()
|
||||||
@@ -118,6 +126,7 @@ func AddFolderRemoteFromClient(vanityPath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create an SSH client
|
// create an SSH client
|
||||||
|
var output []byte
|
||||||
sshClient, offlineMode, _, _, _, err := GetSSHClient()
|
sshClient, offlineMode, _, _, _, err := GetSSHClient()
|
||||||
if offlineMode {
|
if offlineMode {
|
||||||
goto end
|
goto end
|
||||||
@@ -127,10 +136,13 @@ func AddFolderRemoteFromClient(vanityPath string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// call the server to create the folder remotely
|
// call the server to create the folder remotely
|
||||||
_, err = GetSSHOutput(sshClient, "libmuttonserver addfolder", strings.ReplaceAll(vanityPath, global.PathSeparator, global.FSPath)) // call the server to create the folder remotely
|
output, err = GetSSHOutput(sshClient, "libmuttonserver addfolder", strings.ReplaceAll(vanityPath, global.PathSeparator, global.FSPath)) // call the server to create the folder remotely
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("unable to add folder remotely: " + err.Error())
|
return errors.New("unable to add folder remotely: " + err.Error())
|
||||||
}
|
}
|
||||||
|
if len(output) > 11 {
|
||||||
|
return errors.New("unable to complete addfolder; server-side error occurred: " + string(output)[11:len(output)-2])
|
||||||
|
}
|
||||||
|
|
||||||
// close the SSH client
|
// close the SSH client
|
||||||
err = sshClient.Close()
|
err = sshClient.Close()
|
||||||
|
|||||||
+11
-7
@@ -16,25 +16,31 @@ const (
|
|||||||
AnsiDelete = "\033[38;5;1m"
|
AnsiDelete = "\033[38;5;1m"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FetchResponse defines the structure of responses from `libmuttonserver fetch`.
|
// FetchResp defines the structure of responses from `libmuttonserver fetch`.
|
||||||
type FetchResp struct {
|
type FetchResp struct {
|
||||||
ErrMsg *string `json:"errMsg"` // nil if no error occurred
|
ErrMsg *string `json:"errMsg"` // nil if no error occurred
|
||||||
ServerTime int64 `json:"serverTime"`
|
ServerTime int64 `json:"serverTime"`
|
||||||
Deletions []Deletion `json:"deletions"`
|
Deletions []Deletion `json:"deletions"`
|
||||||
FoldersToEntries map[string][]Entry `json:"folders"`
|
FoldersToEntries map[string][]Entry `json:"folders"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Deletion struct {
|
type Deletion struct {
|
||||||
VanityPath string `json:"vanityPath"`
|
VanityPath string `json:"vanityPath"`
|
||||||
IsAgeFile bool `json:"isAgeFile"`
|
IsAgeFile bool `json:"isAgeFile"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Entry struct {
|
type Entry struct {
|
||||||
VanityPath string `json:"vanityPath"`
|
VanityPath string `json:"vanityPath"`
|
||||||
ModTime int64 `json:"modTime"`
|
ModTime int64 `json:"modTime"`
|
||||||
AgeTimestamp *int64 `json:"ageTimestamp"` // nil if no age file is present (non-password entry)
|
AgeTimestamp *int64 `json:"ageTimestamp"` // nil if no age file is present (non-password entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RegisterResp defines the structure of responses from `libmuttonserver register`
|
||||||
|
type RegisterResp struct {
|
||||||
|
ErrMsg *string `json:"errMsg"` // nil if no error occurred
|
||||||
|
EntryRoot string `json:"entryRoot"`
|
||||||
|
AgeDir string `json:"ageDir"`
|
||||||
|
IsWindows bool `json:"isWindows"`
|
||||||
|
}
|
||||||
|
|
||||||
// GetModTimes returns a list of all entry modification times.
|
// GetModTimes returns a list of all entry modification times.
|
||||||
func GetModTimes(entryList []string) []int64 {
|
func GetModTimes(entryList []string) []int64 {
|
||||||
var modList []int64
|
var modList []int64
|
||||||
@@ -70,17 +76,15 @@ func ShearLocal(vanityPath, clientDeviceID string, onlyShearAgeFile bool) (strin
|
|||||||
if !onlyShearAgeFile {
|
if !onlyShearAgeFile {
|
||||||
f, err := os.OpenFile(global.ConfigDir+global.PathSeparator+"deletions"+global.PathSeparator+device.Name()+global.FSSpace+"entry"+global.FSSpace+strings.ReplaceAll(vanityPath, "/", global.FSPath), os.O_CREATE|os.O_WRONLY, 0600)
|
f, err := os.OpenFile(global.ConfigDir+global.PathSeparator+"deletions"+global.PathSeparator+device.Name()+global.FSSpace+"entry"+global.FSSpace+strings.ReplaceAll(vanityPath, "/", global.FSPath), os.O_CREATE|os.O_WRONLY, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// do not print error as there is currently no way of seeing server-side errors
|
|
||||||
// failure to add the target to the deletions list will exit the program and result in a client re-uploading the target (non-critical)
|
// failure to add the target to the deletions list will exit the program and result in a client re-uploading the target (non-critical)
|
||||||
os.Exit(back.ErrorWrite)
|
return "", false, err
|
||||||
}
|
}
|
||||||
_ = f.Close() // error ignored; if the file could be created, it can probably be closed
|
_ = f.Close() // error ignored; if the file could be created, it can probably be closed
|
||||||
}
|
}
|
||||||
f, err := os.OpenFile(global.ConfigDir+global.PathSeparator+"deletions"+global.PathSeparator+device.Name()+global.FSSpace+"age"+global.FSSpace+strings.ReplaceAll(vanityPath, "/", global.FSPath), os.O_CREATE|os.O_WRONLY, 0600)
|
f, err := os.OpenFile(global.ConfigDir+global.PathSeparator+"deletions"+global.PathSeparator+device.Name()+global.FSSpace+"age"+global.FSSpace+strings.ReplaceAll(vanityPath, "/", global.FSPath), os.O_CREATE|os.O_WRONLY, 0600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// do not print error as there is currently no way of seeing server-side errors
|
|
||||||
// failure to add the target to the deletions list will exit the program and result in a client re-uploading the target (non-critical)
|
// failure to add the target to the deletions list will exit the program and result in a client re-uploading the target (non-critical)
|
||||||
os.Exit(back.ErrorWrite)
|
return "", false, err
|
||||||
}
|
}
|
||||||
_ = f.Close() // error ignored; if the file could be created, it can probably be closed
|
_ = f.Close() // error ignored; if the file could be created, it can probably be closed
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-3
@@ -1,16 +1,17 @@
|
|||||||
package synccycles
|
package synccycles
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/rwinkhart/go-boilerplate/back"
|
"github.com/rwinkhart/go-boilerplate/back"
|
||||||
"github.com/rwinkhart/libmutton/global"
|
"github.com/rwinkhart/libmutton/global"
|
||||||
"github.com/rwinkhart/libmutton/syncclient"
|
"github.com/rwinkhart/libmutton/syncclient"
|
||||||
|
"github.com/rwinkhart/libmutton/synccommon"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeviceIDGen generates a new client device ID and registers it with the server (will replace existing one).
|
// DeviceIDGen generates a new client device ID and registers it with the server (will replace existing one).
|
||||||
@@ -59,7 +60,15 @@ func DeviceIDGen(oldDeviceID, prefix string) (string, string, string, error) {
|
|||||||
cleanupOnFail()
|
cleanupOnFail()
|
||||||
return "", "", "", errors.New("unable to register device ID with server: " + err.Error())
|
return "", "", "", errors.New("unable to register device ID with server: " + err.Error())
|
||||||
}
|
}
|
||||||
sshEntryRootSSHAgeDirSSHIsWindows := strings.Split(string(output), global.FSSpace)
|
var registerResp synccommon.RegisterResp
|
||||||
|
err = json.Unmarshal(output, ®isterResp)
|
||||||
|
if err != nil {
|
||||||
|
cleanupOnFail()
|
||||||
|
return "", "", "", errors.New("unable to unmarshal server register response: " + err.Error())
|
||||||
|
}
|
||||||
|
if registerResp.ErrMsg != nil {
|
||||||
|
return "", "", "", errors.New("unable to complete register; server-side error occurred: " + *registerResp.ErrMsg)
|
||||||
|
}
|
||||||
_ = sshClient.Close() // ignore error; non-critical/unlikely/not much could be done about it
|
_ = sshClient.Close() // ignore error; non-critical/unlikely/not much could be done about it
|
||||||
|
|
||||||
// remove old device ID file (locally; may not exist)
|
// remove old device ID file (locally; may not exist)
|
||||||
@@ -68,5 +77,5 @@ func DeviceIDGen(oldDeviceID, prefix string) (string, string, string, error) {
|
|||||||
return "", "", "", errors.New("unable to remove old device ID file (locally): " + err.Error())
|
return "", "", "", errors.New("unable to remove old device ID file (locally): " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
return sshEntryRootSSHAgeDirSSHIsWindows[0], sshEntryRootSSHAgeDirSSHIsWindows[1], sshEntryRootSSHAgeDirSSHIsWindows[2], nil
|
return registerResp.EntryRoot, registerResp.AgeDir, strconv.FormatBool(registerResp.IsWindows), nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user