mirror of
https://github.com/rwinkhart/MUTN.git
synced 2026-08-28 04:46:41 -04:00
Port to latest libmutton development version
This commit is contained in:
@@ -15,7 +15,6 @@ var (
|
||||
const (
|
||||
MUTNVersion = "0.D.0" // untagged releases feature a letter suffix corresponding to the eventual release version, e.g "0.2.A" -> "0.2.0", "0.2.B" -> "0.2.1"
|
||||
|
||||
AnsiBold = "\033[1m"
|
||||
ansiBlackOnWhite = "\033[38;5;0;48;5;15m"
|
||||
)
|
||||
|
||||
|
||||
+2
-1
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/rwinkhart/go-boilerplate/back"
|
||||
"github.com/rwinkhart/go-boilerplate/front"
|
||||
"github.com/rwinkhart/libmutton/cfg"
|
||||
"github.com/rwinkhart/libmutton/core"
|
||||
"github.com/rwinkhart/libmutton/syncclient"
|
||||
)
|
||||
@@ -74,7 +75,7 @@ func editNote(baseNote []string) ([]string, bool) {
|
||||
}(tempFile.Name())
|
||||
|
||||
// fetch the user's text editor
|
||||
editorCfg, _ := core.ParseConfig([][2]string{{"MUTN", "textEditor"}}, "")
|
||||
editorCfg, _ := cfg.ParseConfig([][2]string{{"MUTN", "textEditor"}}, "")
|
||||
editor := editorCfg[0]
|
||||
|
||||
// write baseNote to tempFile (if it is not empty)
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"cmp"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/rwinkhart/go-boilerplate/back"
|
||||
"github.com/rwinkhart/go-boilerplate/front"
|
||||
"github.com/rwinkhart/libmutton/core"
|
||||
"github.com/rwinkhart/libmutton/global"
|
||||
"github.com/rwinkhart/libmutton/syncclient"
|
||||
)
|
||||
|
||||
// TempInitCli initializes the MUTN environment based on user input.
|
||||
func TempInitCli() {
|
||||
// text editor
|
||||
textEditor := cmp.Or(front.Input("Text editor (leave blank for $EDITOR, falls back to \""+fallbackEditor+"\"):"), os.Getenv("EDITOR"), fallbackEditor)
|
||||
|
||||
// SSH info
|
||||
configSSH := front.InputBinary("Configure SSH settings (for synchronization)?")
|
||||
if configSSH {
|
||||
// necessary SSH info
|
||||
fmt.Println(AnsiBold + "\nNote:" + back.AnsiReset + " Only key-based authentication is supported (keys may optionally be passphrase-protected).\nThe remote server must already be in your ~" + global.PathSeparator + ".ssh" + global.PathSeparator + "known_hosts file.")
|
||||
sshUser := front.Input("Remote SSH username:")
|
||||
sshPort := front.Input("Remote SSH port:")
|
||||
sshIP := front.Input("Remote SSH IP/domain:")
|
||||
|
||||
// prompt for and ensure existence of SSH identity file
|
||||
var sshKey string
|
||||
var sshKeyIsFile bool
|
||||
for !sshKeyIsFile {
|
||||
fallbackSSHKey := back.Home + global.PathSeparator + ".ssh" + global.PathSeparator + "id_ed25519"
|
||||
sshKey = cmp.Or(back.ExpandPathWithHome(front.Input("SSH private identity file path (falls back to \""+fallbackSSHKey+"\"):")), fallbackSSHKey)
|
||||
sshKeyIsFile, _ = back.TargetIsFile(sshKey, false, 0)
|
||||
if !sshKeyIsFile {
|
||||
fmt.Println(back.AnsiError+"SSH identity file not found:", sshKey+back.AnsiReset) // do not exit after error (allow user to retry)
|
||||
}
|
||||
}
|
||||
|
||||
sshKeyProtected := front.InputBinary("Is the identity file password-protected?")
|
||||
|
||||
// initialize libmutton directories
|
||||
oldDeviceID := global.DirInit(false)
|
||||
|
||||
// write config file (temporarily assigns sshEntryRoot and sshIsWindows to null to pass initial device ID registration)
|
||||
core.WriteConfig([][3]string{{"MUTN", "textEditor", textEditor}, {"LIBMUTTON", "sshUser", sshUser}, {"LIBMUTTON", "sshIP", sshIP}, {"LIBMUTTON", "sshPort", sshPort}, {"LIBMUTTON", "sshKey", sshKey}, {"LIBMUTTON", "sshKeyProtected", strconv.FormatBool(sshKeyProtected)}, {"LIBMUTTON", "sshEntryRoot", "null"}, {"LIBMUTTON", "sshIsWindows", "false"}}, nil, false)
|
||||
|
||||
// generate and register device ID
|
||||
sshEntryRoot, sshIsWindows := syncclient.DeviceIDGen(oldDeviceID)
|
||||
|
||||
// update config file with sshEntryRoot and sshIsWindows
|
||||
core.WriteConfig([][3]string{{"LIBMUTTON", "sshEntryRoot", sshEntryRoot}, {"LIBMUTTON", "sshIsWindows", sshIsWindows}}, nil, true)
|
||||
} else {
|
||||
// initialize libmutton directories
|
||||
global.DirInit(false)
|
||||
|
||||
// write config file
|
||||
core.WriteConfig([][3]string{{"MUTN", "textEditor", textEditor}}, nil, false)
|
||||
}
|
||||
// RCW sanity check file
|
||||
var passphrase []byte
|
||||
for {
|
||||
passphrase = front.InputHidden("Master passphrase:")
|
||||
if !bytes.Equal(passphrase, front.InputHidden("Confirm master passphrase:")) {
|
||||
fmt.Println(back.AnsiError + "Passphrases do not match" + back.AnsiReset)
|
||||
continue
|
||||
}
|
||||
core.RCWSanityCheckGen(passphrase)
|
||||
break
|
||||
}
|
||||
}
|
||||
+18
-18
@@ -15,13 +15,13 @@ const (
|
||||
)
|
||||
|
||||
func HelpMain() {
|
||||
fmt.Print(AnsiBold + "\nMUTN | Copyright (c) 2024-2025 Randall Winkhart\n" + back.AnsiReset + `
|
||||
fmt.Print(back.AnsiBold + "\nMUTN | Copyright (c) 2024-2025 Randall Winkhart\n" + back.AnsiReset + `
|
||||
This software exists under the MIT license; you may redistribute it under certain conditions.
|
||||
This program comes with absolutely no warranty; type "mutn version" for details.
|
||||
|
||||
` + AnsiBold + "Usage:" + back.AnsiReset + ` mutn [/<entry name> [argument] [option]] | [argument]
|
||||
` + back.AnsiBold + "Usage:" + back.AnsiReset + ` mutn [/<entry name> [argument] [option]] | [argument]
|
||||
|
||||
` + AnsiBold + "Arguments:" + back.AnsiReset + `
|
||||
` + back.AnsiBold + "Arguments:" + back.AnsiReset + `
|
||||
help Bring up this menu
|
||||
version Display version and license information
|
||||
init Set up MUTN (generates libmutton.ini)
|
||||
@@ -32,7 +32,7 @@ This program comes with absolutely no warranty; type "mutn version" for details.
|
||||
shear Delete an existing entry
|
||||
sync Manually sync the entry directory
|
||||
|
||||
` + AnsiBold + "Options:" + back.AnsiReset + `
|
||||
` + back.AnsiBold + "Options:" + back.AnsiReset + `
|
||||
copy:
|
||||
password|-pw|<blank> Copy the password in an entry to your clipboard
|
||||
username|-u Copy the username in an entry to your clipboard
|
||||
@@ -53,17 +53,17 @@ This program comes with absolutely no warranty; type "mutn version" for details.
|
||||
note|-n Add a note entry
|
||||
folder|-f Add a new folder for entries
|
||||
|
||||
` + AnsiBold + "Tip 1:" + back.AnsiReset + ` You can quickly read an entry with "mutn /<entry name>"
|
||||
` + AnsiBold + "Tip 2:" + back.AnsiReset + ` Type "mutn" (no arguments/options) to view a list of saved entries
|
||||
` + AnsiBold + "Tip 3:" + back.AnsiReset + ` Provide "add", "edit", "copy", or "gen" as the only argument to receive more specific help
|
||||
` + AnsiBold + "Tip 4:" + back.AnsiReset + " Using \"add\", \"edit\", or \"copy\" without specifying an option (field) will default to \"password\"\n\n")
|
||||
` + back.AnsiBold + "Tip 1:" + back.AnsiReset + ` You can quickly read an entry with "mutn /<entry name>"
|
||||
` + back.AnsiBold + "Tip 2:" + back.AnsiReset + ` Type "mutn" (no arguments/options) to view a list of saved entries
|
||||
` + back.AnsiBold + "Tip 3:" + back.AnsiReset + ` Provide "add", "edit", "copy", or "gen" as the only argument to receive more specific help
|
||||
` + back.AnsiBold + "Tip 4:" + back.AnsiReset + " Using \"add\", \"edit\", or \"copy\" without specifying an option (field) will default to \"password\"\n\n")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func HelpAdd() {
|
||||
fmt.Print(AnsiBold + "\nUsage:" + back.AnsiReset + ` mutn /<entry name> add <option>
|
||||
fmt.Print(back.AnsiBold + "\nUsage:" + back.AnsiReset + ` mutn /<entry name> add <option>
|
||||
|
||||
` + AnsiBold + "Options:" + back.AnsiReset + `
|
||||
` + back.AnsiBold + "Options:" + back.AnsiReset + `
|
||||
add:
|
||||
password|-pw|<blank> Add a password entry
|
||||
note|-n Add a note entry
|
||||
@@ -72,9 +72,9 @@ func HelpAdd() {
|
||||
}
|
||||
|
||||
func HelpEdit() {
|
||||
fmt.Print(AnsiBold + "\nUsage:" + back.AnsiReset + ` mutn /<entry name> edit <option>
|
||||
fmt.Print(back.AnsiBold + "\nUsage:" + back.AnsiReset + ` mutn /<entry name> edit <option>
|
||||
|
||||
` + AnsiBold + "Options:" + back.AnsiReset + `
|
||||
` + back.AnsiBold + "Options:" + back.AnsiReset + `
|
||||
edit:
|
||||
password|-pw|<blank> Change the password in an entry
|
||||
username|-u Change the username in an entry
|
||||
@@ -86,9 +86,9 @@ func HelpEdit() {
|
||||
}
|
||||
|
||||
func HelpCopy() {
|
||||
fmt.Print(AnsiBold + "\nUsage:" + back.AnsiReset + ` mutn /<entry name> copy <option>
|
||||
fmt.Print(back.AnsiBold + "\nUsage:" + back.AnsiReset + ` mutn /<entry name> copy <option>
|
||||
|
||||
` + AnsiBold + "Options:" + back.AnsiReset + `
|
||||
` + back.AnsiBold + "Options:" + back.AnsiReset + `
|
||||
copy:
|
||||
password|-pw|<blank> Copy the password in an entry to your clipboard
|
||||
username|-u Copy the username in an entry to your clipboard
|
||||
@@ -99,18 +99,18 @@ func HelpCopy() {
|
||||
}
|
||||
|
||||
func HelpGen() {
|
||||
fmt.Print(AnsiBold + "\nUsage:" + back.AnsiReset + ` mutn /<entry name> gen [option]
|
||||
fmt.Print(back.AnsiBold + "\nUsage:" + back.AnsiReset + ` mutn /<entry name> gen [option]
|
||||
|
||||
` + AnsiBold + "Options:" + back.AnsiReset + `
|
||||
` + back.AnsiBold + "Options:" + back.AnsiReset + `
|
||||
gen:
|
||||
update|-u Generate a password for an existing entry
|
||||
|
||||
` + AnsiBold + "Tip:" + back.AnsiReset + " If no options are provided, a new password entry is generated\n\n")
|
||||
` + back.AnsiBold + "Tip:" + back.AnsiReset + " If no options are provided, a new password entry is generated\n\n")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
func MITLicense() {
|
||||
fmt.Print(AnsiBold + "\n MIT License" + back.AnsiReset + `
|
||||
fmt.Print(back.AnsiBold + "\n MIT License" + back.AnsiReset + `
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/rwinkhart/go-boilerplate/back"
|
||||
"github.com/rwinkhart/go-boilerplate/front"
|
||||
"github.com/rwinkhart/libmutton/core"
|
||||
"github.com/rwinkhart/libmutton/synccycles"
|
||||
)
|
||||
|
||||
// inputPasswordGen prompts the user for password generation parameters and returns a generated password as a string.
|
||||
@@ -23,7 +24,7 @@ func inputPasswordGen() string {
|
||||
complexity = 0.2 // (ultra) complex
|
||||
// 2 and 3 indicate complex and ultra complex charsets, respectively
|
||||
}
|
||||
return core.StringGen(passLength, complexity, passCharset)
|
||||
return synccycles.StringGen(passLength, complexity, passCharset)
|
||||
}
|
||||
|
||||
// writeEntryCLI writes an entry to targetLocation and previews it (errors if no data is supplied).
|
||||
@@ -32,7 +33,7 @@ func writeEntryCLI(targetLocation string, unencryptedEntry []string, hideSecrets
|
||||
// write the entry to the target location
|
||||
core.WriteEntry(targetLocation, []byte(strings.Join(unencryptedEntry, "\n")))
|
||||
// preview the entry
|
||||
fmt.Println(AnsiBold + "\nEntry Preview:" + back.AnsiReset)
|
||||
fmt.Println(back.AnsiBold + "\nEntry Preview:" + back.AnsiReset)
|
||||
EntryReader(unencryptedEntry, hideSecrets, true)
|
||||
} else {
|
||||
back.PrintError("No data supplied for entry", back.ErrorTargetNotFound, true)
|
||||
|
||||
Reference in New Issue
Block a user