From 499c9cdd406fef1c35cfcc534e6169a76f10d461 Mon Sep 17 00:00:00 2001 From: Randall Winkhart Date: Sun, 1 Jun 2025 14:31:46 -0400 Subject: [PATCH] Simplify error codes --- docs/man | 20 ++++++-------------- go.mod | 4 ++-- go.sum | 8 ++++---- mutn.go | 21 +++++++++++---------- src/cli/add.go | 3 ++- src/cli/edit.go | 16 ++++++++++------ src/cli/entryList.go | 3 ++- src/cli/entryReader.go | 11 ++++++++--- src/cli/utilitiesMisc.go | 5 +++-- 9 files changed, 48 insertions(+), 43 deletions(-) diff --git a/docs/man b/docs/man index 02f6b95..4f54ce0 100644 --- a/docs/man +++ b/docs/man @@ -1,4 +1,4 @@ -.TH MUTN 1 "21 April 2025" "v0.2.6" "MUTN man page" +.TH MUTN 1 "01 June 2025" "v0.D.0" "MUTN man page" .SH NAME \fBmutn\fR - Simple, self-hosted, SSH-synchronized password and note management based on libmutton. It is the successor to sshyp. @@ -152,23 +152,15 @@ Once this has been done, you may proceed with the client setup: 102: write error -103: sync process error +103: target not found -104: server connection error +104: sync process error -105: target not found +105: decryption error -106: target already exists +106: encryption error -107: target wrong type (file/directory) - -108: decryption error - -109: encryption error - -110: clipboard error - -111: other error +107: clipboard error .SH AUTHOR Randall Winkhart (https://github.com/rwinkhart) diff --git a/go.mod b/go.mod index 6e0d5a8..d955843 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,8 @@ go 1.24.3 require ( github.com/Trojan2021/BEAN v0.0.0-20241210230804-8f294833b514 github.com/charmbracelet/glamour v0.7.0 - github.com/rwinkhart/go-boilerplate v0.0.0-20250529185306-e2e64d7fa43b - github.com/rwinkhart/libmutton v0.3.2-0.20250601004130-4dab9f2c93e5 + github.com/rwinkhart/go-boilerplate v0.0.0-20250601181619-e38a47784de0 + github.com/rwinkhart/libmutton v0.3.2-0.20250601181751-5f8789a0f018 golang.org/x/term v0.32.0 ) diff --git a/go.sum b/go.sum index 4e588de..20071f5 100644 --- a/go.sum +++ b/go.sum @@ -57,12 +57,12 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rwinkhart/convertroman v0.2.0 h1:otUm939eXT77q/Lr31mJtMwVWEw0RjEUB71gO65h9OM= github.com/rwinkhart/convertroman v0.2.0/go.mod h1:Af6HqvX0EIM4Y3HcnNXbbRey1dLasGB7WU0+3Cowgmw= -github.com/rwinkhart/go-boilerplate v0.0.0-20250529185306-e2e64d7fa43b h1:ENgsUlCmYktd1eauEkjW6Fu8rgZzyGOS/m/6jc968xI= -github.com/rwinkhart/go-boilerplate v0.0.0-20250529185306-e2e64d7fa43b/go.mod h1:cnzIF45I0FCOvE4YIB+26pLCUx2kWyY2llKYZruNaRY= +github.com/rwinkhart/go-boilerplate v0.0.0-20250601181619-e38a47784de0 h1:Zuwn0er30tMYrBXD1n4nM3mkGhrLFAdn3sZyMHkxx2I= +github.com/rwinkhart/go-boilerplate v0.0.0-20250601181619-e38a47784de0/go.mod h1:cnzIF45I0FCOvE4YIB+26pLCUx2kWyY2llKYZruNaRY= github.com/rwinkhart/go-winio-easy-pipe-handles v0.0.0-20250407031321-96994a0e8410 h1:NhHwFM3Pgm6zRUfFKvi0p5ndjfFbVWsRwmmhyFlG4PE= github.com/rwinkhart/go-winio-easy-pipe-handles v0.0.0-20250407031321-96994a0e8410/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/rwinkhart/libmutton v0.3.2-0.20250601004130-4dab9f2c93e5 h1:ofZcQ4Pns5PsJY4ksejkt92ldDyDZ+FPhXMoRHehw4I= -github.com/rwinkhart/libmutton v0.3.2-0.20250601004130-4dab9f2c93e5/go.mod h1:uIz4AJcXW7ZHvvoPlLNWQofTBIbFa1UJ2JI6O+FSQ60= +github.com/rwinkhart/libmutton v0.3.2-0.20250601181751-5f8789a0f018 h1:SpVerjfORaFmFep1s22YxqxDdJDd+VhGotsNbcOnX40= +github.com/rwinkhart/libmutton v0.3.2-0.20250601181751-5f8789a0f018/go.mod h1:KsTWIJIHZdtDsFNAxJ0Xjpfy0mEVks5EWatswZWgdn0= github.com/rwinkhart/peercred-mini v0.1.0 h1:TiS6u8cEWzW55S9X4iVpU72Iuy/NG6rMUJMtUEVEFLw= github.com/rwinkhart/peercred-mini v0.1.0/go.mod h1:+x4Mxc2veE+YePSOpcUasjimh7n799c1KraLuQwHR20= github.com/rwinkhart/rcw v0.2.0 h1:/rFgJ+20OSThipKAX5KPwW2xbPpgh1zl49THmEkkPis= diff --git a/mutn.go b/mutn.go index bfa1062..7fe0b46 100644 --- a/mutn.go +++ b/mutn.go @@ -10,6 +10,7 @@ import ( "github.com/rwinkhart/MUTN/src/cli" "github.com/rwinkhart/go-boilerplate/back" "github.com/rwinkhart/go-boilerplate/front" + "github.com/rwinkhart/go-boilerplate/other" "github.com/rwinkhart/libmutton/core" "github.com/rwinkhart/libmutton/crypt" "github.com/rwinkhart/libmutton/global" @@ -47,7 +48,7 @@ func main() { case "copy": err := core.CopyArgument(targetLocation, 0) if err != nil { - back.PrintError("Failed to copy passphrase to clipboard: "+err.Error(), global.ErrorClipboard, true) + other.PrintError("Failed to copy passphrase to clipboard: "+err.Error(), global.ErrorClipboard, true) } case "edit": cli.EditEntryField(targetLocation, true, 0) @@ -58,7 +59,7 @@ func main() { case "shear": err := syncclient.ShearRemoteFromClient(args[1]) // pass the incomplete path as the server and all clients (reading from the deletions directory) will have a different home directory if err != nil { - back.PrintError("Failed to shear target: "+err.Error(), back.ErrorWrite, true) + other.PrintError("Failed to shear target: "+err.Error(), back.ErrorWrite, true) } default: cli.HelpMain() @@ -97,7 +98,7 @@ func main() { } err := core.CopyArgument(targetLocation, field) if err != nil { - back.PrintError("Failed to copy field to clipboard: "+err.Error(), global.ErrorClipboard, true) + other.PrintError("Failed to copy field to clipboard: "+err.Error(), global.ErrorClipboard, true) } case "edit": var field int // indicates which (numbered) field to edit @@ -163,7 +164,7 @@ func main() { case "folder", "-f": err := syncclient.AddFolderRemoteFromClient(args[1]) // pass the incomplete path as the server will have a different home directory if err != nil { - back.PrintError("Failed to add folder: "+err.Error(), back.ErrorWrite, true) + other.PrintError("Failed to add folder: "+err.Error(), back.ErrorWrite, true) } default: cli.HelpAdd() @@ -179,21 +180,21 @@ func main() { case "clipclear": err := core.ClipClearArgument() if err != nil { - back.PrintError("Failure occurred in clipboard clearing process: "+err.Error(), global.ErrorClipboard, true) + other.PrintError("Failure occurred in clipboard clearing process: "+err.Error(), global.ErrorClipboard, true) } case "startrcwd": crypt.RCWDArgument() case "sync": _, err := syncclient.RunJob(true) if err != nil { - back.PrintError("Failed to sync entries: "+err.Error(), global.ErrorSyncProcess, true) + other.PrintError("Failed to sync entries: "+err.Error(), global.ErrorSyncProcess, true) } case "init": err := core.LibmuttonInit(front.Input, [][3]string{{"MUTN", "textEditor", cmp.Or(front.Input("Text editor (leave blank for $EDITOR, falls back to \""+cli.FallbackEditor+"\"):"), os.Getenv("EDITOR"), cli.FallbackEditor)}}, confirmRCWPassphrase("new"), false) if err != nil { - back.PrintError("Initialization failed: "+err.Error(), 0, true) + other.PrintError("Initialization failed: "+err.Error(), 0, true) } case "tweak": choice := front.InputMenuGen("Action:", []string{"Change device ID", "Change master passphrase/Optimize entries"}) @@ -201,11 +202,11 @@ func main() { case 1: oldDeviceID, err := global.GetCurrentDeviceID() if err != nil { - back.PrintError("Failed to get current device ID: "+err.Error(), back.ErrorRead, true) + other.PrintError("Failed to get current device ID: "+err.Error(), back.ErrorRead, true) } _, _, err = synccycles.DeviceIDGen(oldDeviceID) if err != nil { - back.PrintError("Failed to change device ID: "+err.Error(), global.ErrorSyncProcess, true) + other.PrintError("Failed to change device ID: "+err.Error(), global.ErrorSyncProcess, true) } fmt.Println("\nDevice ID changed successfully.") case 2: @@ -214,7 +215,7 @@ func main() { fmt.Print("\nRe-encrypting entries. Please wait; do not force close this process.\n") err := core.EntryRefresh(oldPassphrase, newPassphrase, false) if err != nil { - back.PrintError("Re-encryption failed: "+err.Error(), global.ErrorEncryption, true) + other.PrintError("Re-encryption failed: "+err.Error(), global.ErrorEncryption, true) } fmt.Println("\nRe-encryption complete.") } diff --git a/src/cli/add.go b/src/cli/add.go index 6f4639b..3e3213b 100644 --- a/src/cli/add.go +++ b/src/cli/add.go @@ -3,6 +3,7 @@ package cli import ( "github.com/rwinkhart/go-boilerplate/back" "github.com/rwinkhart/go-boilerplate/front" + "github.com/rwinkhart/go-boilerplate/other" "github.com/rwinkhart/libmutton/core" ) @@ -12,7 +13,7 @@ func AddEntry(targetLocation string, hideSecrets bool, entryType uint8) { // ensure targetLocation is valid _, err := core.EntryAddPrecheck(targetLocation) if err != nil { - back.PrintError("Failed to add entry: "+err.Error(), back.ErrorWrite, true) + other.PrintError("Failed to add entry: "+err.Error(), back.ErrorWrite, true) } var decryptedEntry []string diff --git a/src/cli/edit.go b/src/cli/edit.go index a3aed74..2e0e010 100644 --- a/src/cli/edit.go +++ b/src/cli/edit.go @@ -8,6 +8,7 @@ import ( "github.com/rwinkhart/go-boilerplate/back" "github.com/rwinkhart/go-boilerplate/front" + "github.com/rwinkhart/go-boilerplate/other" "github.com/rwinkhart/libmutton/cfg" "github.com/rwinkhart/libmutton/core" "github.com/rwinkhart/libmutton/syncclient" @@ -19,7 +20,7 @@ func RenameCli(oldLocationIncomplete string) { newLocationIncomplete := front.Input("New location:") err := syncclient.RenameRemoteFromClient(oldLocationIncomplete, newLocationIncomplete) if err != nil { - back.PrintError("Failed to rename entry: "+err.Error(), back.ErrorWrite, true) + other.PrintError("Failed to rename entry: "+err.Error(), back.ErrorWrite, true) } // exit is done from sync.RenameRemoteFromClient @@ -30,7 +31,7 @@ func EditEntryField(targetLocation string, hideSecrets bool, field int) { // fetch old entry data (with all required lines present) decryptedEntry, err := core.GetOldEntryData(targetLocation, field) if err != nil { - back.PrintError("Failed to fetch entry data: "+err.Error(), back.ErrorRead, true) + other.PrintError("Failed to fetch entry data: "+err.Error(), back.ErrorRead, true) } // edit the field @@ -51,7 +52,7 @@ func EditEntryField(targetLocation string, hideSecrets bool, field int) { // edit the note editedNote, noteEdited := editNote(fieldsNote) if !noteEdited { // exit early if the note was not edited - back.PrintError("Entry is unchanged", 0, true) + other.PrintError("Entry is unchanged", 0, true) } decryptedEntry = append(fieldsMain, editedNote...) } @@ -65,7 +66,7 @@ func GenUpdate(targetLocation string, hideSecrets bool) { // fetch old entry data decryptedEntry, err := core.GetOldEntryData(targetLocation, 0) if err != nil { - back.PrintError("Failed to fetch entry data: "+err.Error(), back.ErrorRead, true) + other.PrintError("Failed to fetch entry data: "+err.Error(), back.ErrorRead, true) } // generate a new password @@ -78,7 +79,10 @@ func GenUpdate(targetLocation string, hideSecrets bool) { // editNote uses the user-specified text editor to edit an existing note (or create a new one if baseNote is empty). // Returns the edited note and a boolean indicating whether the note was edited. func editNote(baseNote []string) ([]string, bool) { - tempFile := back.CreateTempFile() + tempFile, err := back.CreateTempFile() + if err != nil { + other.PrintError("Failed to create temporary note file: "+err.Error(), back.ErrorWrite, true) + } defer func(name string) { _ = os.Remove(name) // error ignored; if the file could be created, it can probably be removed }(tempFile.Name()) @@ -112,7 +116,7 @@ func editNote(baseNote []string) ([]string, bool) { cmd.Stdout = os.Stdout cmd.Stdin = os.Stdin cmd.Stderr = os.Stderr - err := cmd.Run() + err = cmd.Run() if err != nil { panic(back.AnsiError + "Failed to write note with " + editor + back.AnsiReset) // panic is used to ensure the tempFile is removed, as per the defer statement } diff --git a/src/cli/entryList.go b/src/cli/entryList.go index 2354a81..7e841ed 100644 --- a/src/cli/entryList.go +++ b/src/cli/entryList.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/rwinkhart/go-boilerplate/back" + "github.com/rwinkhart/go-boilerplate/other" "github.com/rwinkhart/libmutton/synccommon" ) @@ -81,7 +82,7 @@ func printFileEntry(entry string, lastSlash, charCounter, indent int, colorAlter func EntryListGen() { fileList, dirList, err := synccommon.WalkEntryDir() if err != nil { - back.PrintError("Failed to generate entry list: "+err.Error(), back.ErrorRead, true) + other.PrintError("Failed to generate entry list: "+err.Error(), back.ErrorRead, true) } // print header bar w/total entry count diff --git a/src/cli/entryReader.go b/src/cli/entryReader.go index b98fccb..18ba51b 100644 --- a/src/cli/entryReader.go +++ b/src/cli/entryReader.go @@ -5,6 +5,7 @@ import ( "os" "github.com/rwinkhart/go-boilerplate/back" + "github.com/rwinkhart/go-boilerplate/other" "github.com/rwinkhart/libmutton/crypt" "github.com/rwinkhart/libmutton/global" "github.com/rwinkhart/libmutton/syncclient" @@ -68,7 +69,7 @@ fieldLoop: if syncEnabled { _, err := syncclient.RunJob(false) if err != nil { - back.PrintError("Failed to sync entries: "+err.Error(), global.ErrorSyncProcess, true) + other.PrintError("Failed to sync entries: "+err.Error(), global.ErrorSyncProcess, true) } } @@ -77,10 +78,14 @@ fieldLoop: // EntryReaderDecrypt is a wrapper for EntryReader that first decrypts an RCW-wrapped file before sending it to EntryReader. func EntryReaderDecrypt(targetLocation string, hideSecrets bool) { - if isFile, _ := back.TargetIsFile(targetLocation, true, 2); isFile { + isFile, _, err := back.TargetIsFile(targetLocation, true, 2) + if err != nil { + other.PrintError("Failed to verify target location: "+err.Error(), back.ErrorTargetNotFound, true) + } + if isFile { decBytes, err := crypt.DecryptFileToSlice(targetLocation) if err != nil { - back.PrintError("Failed to decrypt entry: "+err.Error(), global.ErrorDecryption, true) + other.PrintError("Failed to decrypt entry: "+err.Error(), global.ErrorDecryption, true) } EntryReader(decBytes, hideSecrets, false) // never sync if decrypting straight to EntryReader, as this means the entry could not have been modified } diff --git a/src/cli/utilitiesMisc.go b/src/cli/utilitiesMisc.go index 5e29a55..54762d5 100644 --- a/src/cli/utilitiesMisc.go +++ b/src/cli/utilitiesMisc.go @@ -6,6 +6,7 @@ import ( "github.com/rwinkhart/go-boilerplate/back" "github.com/rwinkhart/go-boilerplate/front" + "github.com/rwinkhart/go-boilerplate/other" "github.com/rwinkhart/libmutton/core" "github.com/rwinkhart/libmutton/synccycles" ) @@ -33,12 +34,12 @@ func writeEntryCLI(targetLocation string, decryptedEntry []string, hideSecrets b // write the entry to the target location err := core.WriteEntry(targetLocation, []byte(strings.Join(decryptedEntry, "\n"))) if err != nil { - back.PrintError("Failed to write entry: "+err.Error(), back.ErrorWrite, true) + other.PrintError("Failed to write entry: "+err.Error(), back.ErrorWrite, true) } // preview the entry fmt.Println(back.AnsiBold + "\nEntry Preview:" + back.AnsiReset) EntryReader(decryptedEntry, hideSecrets, true) } else { - back.PrintError("No data supplied for entry", back.ErrorTargetNotFound, true) + other.PrintError("No data supplied for entry", back.ErrorTargetNotFound, true) } }