mirror of
https://github.com/rwinkhart/MUTN.git
synced 2026-08-27 20:36:29 -04:00
Sync with latest libmutton development version; draft documentation for release v0.4.0
This commit is contained in:
@@ -23,16 +23,7 @@ Additionally, MUTN is available as a source package ("[mutn](https://aur.archlin
|
||||
After installing, please review the [usage guide](https://github.com/rwinkhart/MUTN/blob/main/wiki/usage.md).
|
||||
|
||||
# Roadmap
|
||||
### Release v0.4.0
|
||||
- Add interactive copy menu
|
||||
- Send user to this menu after add/gen
|
||||
- libmutton v0.5.0
|
||||
- Password aging support
|
||||
- Add green/yellow/red dot indicators to entry list readout for when passwords should be changed
|
||||
### Release v0.5.0
|
||||
- libmutton v0.6.0
|
||||
- Implement "netpin" (quick-unlock)
|
||||
### Release v0.6.0
|
||||
- Switch to fully compliant Markdown (do not preserve new lines)
|
||||
- Switch to alternative Markdown renderer (minimark or BEAN)
|
||||
### Release v1.0.0 - Distribution packages
|
||||
|
||||
@@ -4,4 +4,25 @@
|
||||
Built with libmutton v0.5.0
|
||||
Release date TBD
|
||||
|
||||
This release syncs with libmutton v0.5.0 and adds a new multi-field copy menu.
|
||||
# The ??? Update
|
||||
This release adds password age-tracking support, a new interactive copy menu, and features many under-the-hood (breaking) changes.
|
||||
|
||||
## libmutton-derived Changes
|
||||
- **PLEASE** read [libmutton's release notes](https://github.com/rwinkhart/libmutton/releases/tag/v0.5.0), as they detail severe breaking changes. You **NEED** to update your `libmuttonserver` and run `mutn init` after this update!
|
||||
|
||||
## Features
|
||||
- (41b4c4b6ca2f5a74899e87c6d520df7b140671b3) (c1c95655114a689daf80d2410e19ba35b670b1b1) (107a6f4f1250de8f94d87c192d58cc47bef80c1f) (fc1e3b11fc810a79cc0673b6edf96d4753c0300c) (a75416a6792559179e39497cb033407f18c00620) (b58461b9c458795278f050ff10e91a2d05c21745) (b26c2ce17c0491890de03dc131717d557876a3e4) (8112496006c7d48dd4a8f21a9eea51eadc30f732) (12167b1eeddb49e8f5e62f788dc1da6265706f68) (aaf69eb590af4dc37013102dcff79ef115b9f809) (cac35e1d25b7a9a4bd7263406f642834418f6b76) Add new interactive copy menu
|
||||
- This menu aims to reduce the number of times the user is decrypting each entry
|
||||
- (1a9de90f890f133e6ab8f298241fe3a6237ba4c8) (7016a8a1309b06c63b9dd63fb126103d4cab6ccc) Password age tracking (from libmutton)
|
||||
- The `tweak` menu now allows adding age data to old (existing) entries
|
||||
|
||||
## Dependencies (direct/replaced)
|
||||
- Dropped (libmutton)
|
||||
- golang.design/x/clipboard
|
||||
- gopkg.in/ini.v1
|
||||
- Bumped
|
||||
- Go: v1.25.4 => 1.25.5
|
||||
- github.com/rwinkhart/go-boilerplate: v0.1.0 => v0.1.1
|
||||
- github.com/rwinkhart/libmutton: v0.4.4 => v0.5.0
|
||||
- golang.org/x/term: v0.37.0 => v0.38.0
|
||||
- golang.org/x/sys: v0.38.0 => v0.40.0
|
||||
|
||||
@@ -5,7 +5,7 @@ go 1.25.5
|
||||
require (
|
||||
github.com/charmbracelet/glamour v0.7.0
|
||||
github.com/rwinkhart/go-boilerplate v0.1.1
|
||||
github.com/rwinkhart/libmutton v0.4.3-0.20260108232004-d54b59030e72
|
||||
github.com/rwinkhart/libmutton v0.4.3-0.20260109022300-a54d15e33111
|
||||
golang.org/x/term v0.38.0
|
||||
)
|
||||
|
||||
|
||||
@@ -48,8 +48,8 @@ github.com/rwinkhart/go-highlite v0.1.1 h1:9TxbRhYVfD/3YaEgNk1BtEiZ0t8/5mxDUZqNM
|
||||
github.com/rwinkhart/go-highlite v0.1.1/go.mod h1:mWLMtCWcyV0BG4NeyPyAUGMjPvI0ds6vXmUq89QwBFA=
|
||||
github.com/rwinkhart/go-winio v0.1.0 h1:b72agLW+dETGmhR3VbcbwnStfgKfc5AfgJOXBJDkaHg=
|
||||
github.com/rwinkhart/go-winio v0.1.0/go.mod h1:ZWa7ssZJT30CCDGJ7fk/2SBTq9BIQrrVjrcss0UW2s0=
|
||||
github.com/rwinkhart/libmutton v0.4.3-0.20260108232004-d54b59030e72 h1:sFtwqO//25lLwsD77wtxyojRKSrK+ABVZSWIZg5mf1w=
|
||||
github.com/rwinkhart/libmutton v0.4.3-0.20260108232004-d54b59030e72/go.mod h1:qInUv19lzX1adFNI6Ih/IEVy+pktSTh/yA7cRTdVPH8=
|
||||
github.com/rwinkhart/libmutton v0.4.3-0.20260109022300-a54d15e33111 h1:nxQHhtdRVIUhRAc/5oYTli30tive65c8N7u75dENVWE=
|
||||
github.com/rwinkhart/libmutton v0.4.3-0.20260109022300-a54d15e33111/go.mod h1:qInUv19lzX1adFNI6Ih/IEVy+pktSTh/yA7cRTdVPH8=
|
||||
github.com/rwinkhart/peercred-mini v0.1.2 h1:4cGWDbv0whvLeVvbUdx84V/9p+2fS+DEXgrA1KxlRFo=
|
||||
github.com/rwinkhart/peercred-mini v0.1.2/go.mod h1:LLHG7YshHEpbpJJP+Il9nx2dnGj5O3VGE32rWmflj0c=
|
||||
github.com/rwinkhart/rcw v0.2.4 h1:FrRSsl+ui1WLmDwqjLSROtFPKqSeGLEfF2SPENt4qP0=
|
||||
|
||||
@@ -48,8 +48,7 @@ func main() {
|
||||
case "show", "-s":
|
||||
cli.EntryReaderDecrypt(realPath, false)
|
||||
case "copy":
|
||||
err := clip.CopyShortcut(realPath, 0)
|
||||
if err != nil {
|
||||
if err := clip.CopyShortcut(realPath, 0); err != nil {
|
||||
other.PrintError("Failed to copy password to clipboard: "+err.Error(), global.ErrorClipboard)
|
||||
}
|
||||
case "edit":
|
||||
@@ -59,8 +58,7 @@ func main() {
|
||||
case "add":
|
||||
cli.AddEntry(realPath, 0)
|
||||
case "shear":
|
||||
err := syncclient.ShearRemote(args[1], false) // pass the incomplete path as the server and all clients (reading from the deletions directory) will have a different home directory
|
||||
if err != nil {
|
||||
if err := syncclient.ShearRemote(args[1], false); err != nil {
|
||||
other.PrintError("Failed to shear target: "+err.Error(), back.ErrorWrite)
|
||||
}
|
||||
default:
|
||||
@@ -100,8 +98,7 @@ func main() {
|
||||
default:
|
||||
cli.HelpCopy()
|
||||
}
|
||||
err := clip.CopyShortcut(realPath, field)
|
||||
if err != nil {
|
||||
if err := clip.CopyShortcut(realPath, field); err != nil {
|
||||
other.PrintError("Failed to copy field to clipboard: "+err.Error(), global.ErrorClipboard)
|
||||
}
|
||||
case "edit":
|
||||
@@ -169,8 +166,7 @@ func main() {
|
||||
case "note", "-n":
|
||||
cli.AddEntry(realPath, 2)
|
||||
case "folder", "-f":
|
||||
err := syncclient.AddFolderRemote(args[1]) // pass the incomplete path as the server will have a different home directory
|
||||
if err != nil {
|
||||
if err := syncclient.AddFolderRemote(args[1]); err != nil {
|
||||
other.PrintError("Failed to add folder: "+err.Error(), back.ErrorWrite)
|
||||
}
|
||||
default:
|
||||
@@ -185,8 +181,7 @@ func main() {
|
||||
} else {
|
||||
switch args[1] {
|
||||
case "clipclear":
|
||||
err := clip.ClearArgument()
|
||||
if err != nil {
|
||||
if err := clip.ClearArgument(); err != nil {
|
||||
other.PrintError("Failure occurred in clipboard clearing process: "+err.Error(), global.ErrorClipboard)
|
||||
}
|
||||
case "startrcwd":
|
||||
@@ -215,8 +210,7 @@ func main() {
|
||||
newCfg := &config.CfgT{}
|
||||
newClientSpecificCfg := map[string]any{"mutnTextEditor": getTextEditorInput()}
|
||||
newCfg.ClientSpecific = &newClientSpecificCfg
|
||||
err := config.Write(newCfg, true)
|
||||
if err != nil {
|
||||
if err := config.Write(newCfg, true); err != nil {
|
||||
other.PrintError("Failed to set text editor: "+err.Error(), back.ErrorWrite)
|
||||
}
|
||||
case 2:
|
||||
@@ -224,7 +218,7 @@ func main() {
|
||||
if err != nil {
|
||||
other.PrintError("Failed to get current device ID: "+err.Error(), back.ErrorRead)
|
||||
}
|
||||
_, _, err = syncclient.GenDeviceID(oldDeviceID, "")
|
||||
_, _, _, err = syncclient.GenDeviceID(oldDeviceID, "")
|
||||
if err != nil {
|
||||
other.PrintError("Failed to change device ID: "+err.Error(), global.ErrorSyncProcess)
|
||||
}
|
||||
@@ -232,16 +226,14 @@ func main() {
|
||||
case 3:
|
||||
forceReage := front.InputBinary("Re-age aged entries?")
|
||||
fmt.Println("Aging entries; this may take awhile - do not terminate this process")
|
||||
err := age.AllPasswordEntries(forceReage)
|
||||
if err != nil {
|
||||
if err := age.AllPasswordEntries(forceReage); err != nil {
|
||||
other.PrintError("Failed to age entries: "+err.Error(), 1)
|
||||
}
|
||||
case 4:
|
||||
oldPassword := confirmRCWPassword("old")
|
||||
newPassword := confirmRCWPassword("new")
|
||||
fmt.Print("\nRe-encrypting entries. Please wait; do not force close this process.\n")
|
||||
err := core.EntryRefresh(oldPassword, newPassword, false)
|
||||
if err != nil {
|
||||
if err := core.EntryRefresh(oldPassword, newPassword, false); err != nil {
|
||||
other.PrintError("Re-encryption failed: "+err.Error(), global.ErrorEncryption)
|
||||
}
|
||||
fmt.Println("\nRe-encryption complete.")
|
||||
|
||||
+2
-4
@@ -102,8 +102,7 @@ func CopyMenu(vanityPath string, decSlice []string, oldPassword string) {
|
||||
}
|
||||
selectedField = fieldOptions[choice-1]
|
||||
if selectedField == "Old Password" {
|
||||
err = clip.CopyString(false, oldPassword)
|
||||
if err != nil {
|
||||
if err = clip.CopyString(false, oldPassword); err != nil {
|
||||
other.PrintError("Failed to copy old password to clipboard: "+err.Error(), global.ErrorClipboard)
|
||||
}
|
||||
continue
|
||||
@@ -115,8 +114,7 @@ func CopyMenu(vanityPath string, decSlice []string, oldPassword string) {
|
||||
done := make(chan bool)
|
||||
go clip.TOTPCopier(decSlice[2], errorChan, done)
|
||||
// block until first successful copy
|
||||
err = <-errorChan
|
||||
if err != nil {
|
||||
if err = <-errorChan; err != nil {
|
||||
other.PrintError("Failed to copy TOTP token: "+err.Error(), global.ErrorClipboard)
|
||||
}
|
||||
fmt.Println(back.AnsiGreen + "[Started]" + back.AnsiReset + " TOTP clipboard refresher")
|
||||
|
||||
+2
-4
@@ -18,8 +18,7 @@ import (
|
||||
func RenameCli(oldVanityPath string) {
|
||||
// prompt user for new location and rename
|
||||
newVanityPath := front.Input("New location:")
|
||||
err := syncclient.RenameRemote(oldVanityPath, newVanityPath)
|
||||
if err != nil {
|
||||
if err := syncclient.RenameRemote(oldVanityPath, newVanityPath); err != nil {
|
||||
other.PrintError("Failed to rename entry: "+err.Error(), back.ErrorWrite)
|
||||
}
|
||||
|
||||
@@ -131,8 +130,7 @@ func editNote(baseNote []string) ([]string, bool) {
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stderr = os.Stderr
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
if err = cmd.Run(); 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
|
||||
}
|
||||
|
||||
|
||||
@@ -30,8 +30,7 @@ func inputPasswordGen() string {
|
||||
// writeEntryCLI writes an entry to realPath and previews it (errors if no data is supplied).
|
||||
func writeEntryCLI(realPath string, decSlice []string, passwordIsNew bool, oldPassword string) {
|
||||
if core.EntryIsNotEmpty(decSlice) {
|
||||
err := core.WriteEntry(realPath, decSlice, passwordIsNew)
|
||||
if err != nil {
|
||||
if err := core.WriteEntry(realPath, decSlice, passwordIsNew); err != nil {
|
||||
other.PrintError("Failed to write entry: "+err.Error(), back.ErrorWrite)
|
||||
}
|
||||
// preview the entry
|
||||
|
||||
Reference in New Issue
Block a user