mirror of
https://github.com/rwinkhart/MUTN.git
synced 2026-08-28 04:46:41 -04:00
Write and append to config file using ini package
This commit is contained in:
@@ -6,16 +6,23 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ReadConfig reads the libmutton.ini file and returns a slice of values for the specified keys
|
// loadConfig loads the libmutton.ini file and returns the configuration
|
||||||
// requires readKeys: a slice of key names (indicates requested values)
|
// utility function for ParseConfig and WriteConfig, do not call directly
|
||||||
// requires missingValueError: an error message to display if a key is missing a value, set to "" for auto-generated or "0" to exit silently with status 0
|
func loadConfig() *ini.File {
|
||||||
// returns config: a slice of values for the specified keys
|
|
||||||
func ReadConfig(readKeys []string, missingValueError string) []string {
|
|
||||||
cfg, err := ini.Load(ConfigPath)
|
cfg, err := ini.Load(ConfigPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(AnsiError + "Failed to load libmutton.ini: " + err.Error() + AnsiReset)
|
fmt.Println(AnsiError + "Failed to load libmutton.ini: " + err.Error() + AnsiReset)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseConfig reads the libmutton.ini file and returns a slice of values for the specified keys
|
||||||
|
// requires readKeys: a slice of key names (indicates requested values)
|
||||||
|
// requires missingValueError: an error message to display if a key is missing a value, set to "" for auto-generated or "0" to exit silently with status 0
|
||||||
|
// returns config: a slice of values for the specified keys
|
||||||
|
func ParseConfig(readKeys []string, missingValueError string) []string {
|
||||||
|
cfg := loadConfig()
|
||||||
|
|
||||||
var config []string
|
var config []string
|
||||||
|
|
||||||
@@ -41,7 +48,44 @@ func ReadConfig(readKeys []string, missingValueError string) []string {
|
|||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
// libmuttn.ini layout
|
// WriteConfig writes the provided key-value pairs to the libmutton.ini file
|
||||||
|
func WriteConfig(configFileMap map[string]string, append bool) {
|
||||||
|
var cfg *ini.File
|
||||||
|
var libmuttonSection *ini.Section
|
||||||
|
|
||||||
|
if append {
|
||||||
|
// load existing ini file
|
||||||
|
cfg = loadConfig()
|
||||||
|
|
||||||
|
// acquire LIBMUTTON section
|
||||||
|
libmuttonSection, _ = cfg.GetSection("LIBMUTTON")
|
||||||
|
} else {
|
||||||
|
// create empty ini file
|
||||||
|
cfg = ini.Empty()
|
||||||
|
|
||||||
|
// create LIBMUTTON section
|
||||||
|
libmuttonSection, _ = cfg.NewSection("LIBMUTTON")
|
||||||
|
|
||||||
|
// set default textEditor value
|
||||||
|
if configFileMap["textEditor"] == "" {
|
||||||
|
configFileMap["textEditor"] = textEditorFallback()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// write provided configFileMap key-value pairs to the LIBMUTTON section
|
||||||
|
for key, value := range configFileMap {
|
||||||
|
libmuttonSection.Key(key).SetValue(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// save the new config file
|
||||||
|
err := cfg.SaveTo(ConfigPath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(AnsiError + "Failed to save libmutton.ini: " + err.Error() + AnsiReset)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// libmutton.ini layout
|
||||||
// [LIBMUTTON]
|
// [LIBMUTTON]
|
||||||
// gpgID = <gpg key id>
|
// gpgID = <gpg key id>
|
||||||
// textEditor = <editor command>
|
// textEditor = <editor command>
|
||||||
@@ -51,3 +95,9 @@ func ReadConfig(readKeys []string, missingValueError string) []string {
|
|||||||
// sshKey = <ssh private key identity file path>
|
// sshKey = <ssh private key identity file path>
|
||||||
// sshKeyProtected = <true/false>
|
// sshKeyProtected = <true/false>
|
||||||
// netPinEnabled = <true/false>
|
// netPinEnabled = <true/false>
|
||||||
|
// sshEntryRoot = <remote entry root>
|
||||||
|
// sshIsWindows = <true/false>
|
||||||
|
|
||||||
|
// Developers of alternative clients:
|
||||||
|
// If you are adding additional settings to the config file,
|
||||||
|
// please create a new section heading for your app-specific settings.
|
||||||
|
|||||||
+1
-2
@@ -8,7 +8,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// TODO GPG support is a temporary feature - it will be replaced with a different encryption scheme in the future
|
// TODO GPG support is a temporary feature - it will be replaced with a different encryption scheme in the future
|
||||||
// These functions may continue to exist after that point, but consider them deprecated
|
|
||||||
|
|
||||||
// DecryptGPG decrypts a GPG-encrypted file and returns the contents as a slice of (trimmed) strings
|
// DecryptGPG decrypts a GPG-encrypted file and returns the contents as a slice of (trimmed) strings
|
||||||
func DecryptGPG(targetLocation string) []string {
|
func DecryptGPG(targetLocation string) []string {
|
||||||
@@ -24,7 +23,7 @@ func DecryptGPG(targetLocation string) []string {
|
|||||||
|
|
||||||
// EncryptGPG encrypts a slice of strings using GPG and returns the encrypted data as a byte slice
|
// EncryptGPG encrypts a slice of strings using GPG and returns the encrypted data as a byte slice
|
||||||
func EncryptGPG(input []string) []byte {
|
func EncryptGPG(input []string) []byte {
|
||||||
cmd := exec.Command("gpg", "-q", "-r", ReadConfig([]string{"gpgID"}, "")[0], "-e")
|
cmd := exec.Command("gpg", "-q", "-r", ParseConfig([]string{"gpgID"}, "")[0], "-e")
|
||||||
writeToStdin(cmd, strings.Join(input, "\n"))
|
writeToStdin(cmd, strings.Join(input, "\n"))
|
||||||
encryptedBytes, err := cmd.Output()
|
encryptedBytes, err := cmd.Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -9,25 +9,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TempInit ensures libmutton directories exist and writes the libmutton configuration file
|
|
||||||
// TODO if run in append mode, extend old config file with new values, rather than creating from scratch
|
|
||||||
func TempInit(configFileMap map[string]string, append bool) {
|
|
||||||
// create EntryRoot and ConfigDir
|
|
||||||
DirInit(append)
|
|
||||||
|
|
||||||
if configFileMap["textEditor"] == "" {
|
|
||||||
configFileMap["textEditor"] = textEditorFallback()
|
|
||||||
}
|
|
||||||
|
|
||||||
// create and write config file
|
|
||||||
configFile, _ := os.OpenFile(ConfigPath, os.O_CREATE|os.O_WRONLY, 0600)
|
|
||||||
defer configFile.Close()
|
|
||||||
configFile.WriteString("[LIBMUTTON]\n")
|
|
||||||
for key, value := range configFileMap {
|
|
||||||
configFile.WriteString(key + " = " + value + "\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GpgUIDListGen generates a list of all GPG key IDs on the system and returns them as a slice of strings
|
// GpgUIDListGen generates a list of all GPG key IDs on the system and returns them as a slice of strings
|
||||||
func GpgUIDListGen() []string {
|
func GpgUIDListGen() []string {
|
||||||
cmd := exec.Command("gpg", "-k", "--with-colons")
|
cmd := exec.Command("gpg", "-k", "--with-colons")
|
||||||
|
|||||||
+1
-1
@@ -72,7 +72,7 @@ func GenUpdate(targetLocation string, hideSecrets bool) {
|
|||||||
func editNote(baseNote []string) ([]string, bool) {
|
func editNote(baseNote []string) ([]string, bool) {
|
||||||
tempFile := backend.CreateTempFile()
|
tempFile := backend.CreateTempFile()
|
||||||
defer os.Remove(tempFile.Name())
|
defer os.Remove(tempFile.Name())
|
||||||
editor := backend.ReadConfig([]string{"textEditor"}, "")[0]
|
editor := backend.ParseConfig([]string{"textEditor"}, "")[0]
|
||||||
|
|
||||||
// write baseNote to tempFile (if it is not empty)
|
// write baseNote to tempFile (if it is not empty)
|
||||||
if len(baseNote) > 0 {
|
if len(baseNote) > 0 {
|
||||||
|
|||||||
+14
-9
@@ -8,7 +8,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TempInitCli initializes the MUTN environment based on user input
|
// TempInitCli initializes the MUTN environment based on user input (will be replaced with a TUI menu)
|
||||||
func TempInitCli() {
|
func TempInitCli() {
|
||||||
// gpgID
|
// gpgID
|
||||||
var gpgID string
|
var gpgID string
|
||||||
@@ -39,17 +39,22 @@ func TempInitCli() {
|
|||||||
sshKey := input("SSH private identity file path:") // TODO implement generator and selector
|
sshKey := input("SSH private identity file path:") // TODO implement generator and selector
|
||||||
sshKeyProtected := inputBinary("Is the identity file password-protected?")
|
sshKeyProtected := inputBinary("Is the identity file password-protected?")
|
||||||
|
|
||||||
// write config file
|
// initialize libmutton directories
|
||||||
backend.TempInit(map[string]string{"textEditor": textEditor, "gpgID": gpgID, "sshUser": sshUser, "sshIP": sshIP, "sshPort": sshPort, "sshKey": sshKey, "sshKeyProtected": strconv.FormatBool(sshKeyProtected), "sshEntryRoot": "null", "sshIsWindows": "null"}, false)
|
backend.DirInit(false)
|
||||||
|
|
||||||
// generate device ID
|
// write config file (temporarily assigns sshEntryRoot and sshIsWindows to null to pass initial device ID registration)
|
||||||
|
backend.WriteConfig(map[string]string{"textEditor": textEditor, "gpgID": gpgID, "sshUser": sshUser, "sshIP": sshIP, "sshPort": sshPort, "sshKey": sshKey, "sshKeyProtected": strconv.FormatBool(sshKeyProtected), "sshEntryRoot": "null", "sshIsWindows": "null"}, false)
|
||||||
|
|
||||||
|
// generate and register device ID
|
||||||
sshEntryRoot, sshIsWindows := sync.DeviceIDGen()
|
sshEntryRoot, sshIsWindows := sync.DeviceIDGen()
|
||||||
|
|
||||||
// update config file with sshEntryRoot and sshIsWindows TODO append to existing config file
|
// update config file with sshEntryRoot and sshIsWindows
|
||||||
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}, true)
|
backend.WriteConfig(map[string]string{"sshEntryRoot": sshEntryRoot, "sshIsWindows": sshIsWindows}, true)
|
||||||
} else {
|
} else {
|
||||||
// write config file
|
// initialize libmutton directories
|
||||||
backend.TempInit(map[string]string{"textEditor": textEditor, "gpgID": gpgID}, false)
|
backend.DirInit(false)
|
||||||
}
|
|
||||||
|
|
||||||
|
// write config file
|
||||||
|
backend.WriteConfig(map[string]string{"textEditor": textEditor, "gpgID": gpgID}, false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -30,7 +30,7 @@ func getSSHClient(manualSync bool) (*ssh.Client, string, bool) {
|
|||||||
} else {
|
} else {
|
||||||
missingValueError = "0"
|
missingValueError = "0"
|
||||||
}
|
}
|
||||||
sshUserConfig = backend.ReadConfig([]string{"sshUser", "sshIP", "sshPort", "sshKey", "sshKeyProtected", "sshEntryRoot", "sshIsWindows"}, missingValueError)
|
sshUserConfig = backend.ParseConfig([]string{"sshUser", "sshIP", "sshPort", "sshKey", "sshKeyProtected", "sshEntryRoot", "sshIsWindows"}, missingValueError)
|
||||||
|
|
||||||
var user, ip, port, keyFile, keyFileProtected, entryRoot string
|
var user, ip, port, keyFile, keyFileProtected, entryRoot string
|
||||||
var isWindows bool
|
var isWindows bool
|
||||||
@@ -65,7 +65,7 @@ func getSSHClient(manualSync bool) (*ssh.Client, string, bool) {
|
|||||||
if keyFileProtected != "true" {
|
if keyFileProtected != "true" {
|
||||||
parsedKey, err = ssh.ParsePrivateKey(key)
|
parsedKey, err = ssh.ParsePrivateKey(key)
|
||||||
} else {
|
} else {
|
||||||
parsedKey, err = ssh.ParsePrivateKeyWithPassphrase(key, inputKeyFilePassphrase()) // TODO test passphrase-protected keys
|
parsedKey, err = ssh.ParsePrivateKeyWithPassphrase(key, inputKeyFilePassphrase())
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(backend.AnsiError+"Sync failed - Unable to parse private key:", keyFile+backend.AnsiReset)
|
fmt.Println(backend.AnsiError+"Sync failed - Unable to parse private key:", keyFile+backend.AnsiReset)
|
||||||
@@ -99,7 +99,7 @@ func getSSHClient(manualSync bool) (*ssh.Client, string, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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() only ONCE (from RunJob) - this only saves re-creating the client, not re-establishing the connection, so it may not be worth it
|
// TODO run getSSHClient() only ONCE (from RunJob) - this saves re-creating the client AND prevents prompting for keyfile passphrase multiple times
|
||||||
func GetSSHOutput(cmd, stdin string, manualSync bool) string {
|
func GetSSHOutput(cmd, stdin string, manualSync bool) string {
|
||||||
sshClient, _, _ := getSSHClient(manualSync)
|
sshClient, _, _ := getSSHClient(manualSync)
|
||||||
defer sshClient.Close()
|
defer sshClient.Close()
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func WalkEntryDir() ([]string, []string) {
|
|||||||
// check for errors encountered while walking directory
|
// check for errors encountered while walking directory
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
fmt.Println(backend.AnsiError+"The entry directory does not exist - run \""+os.Args[0], "init"+"\" to create it"+backend.AnsiReset) // TODO implement init command for libmuttonserver
|
fmt.Println(backend.AnsiError+"The entry directory does not exist - run \""+os.Args[0], "init"+"\" to create it"+backend.AnsiReset)
|
||||||
} else {
|
} else {
|
||||||
// otherwise, print the source of the error
|
// otherwise, print the source of the error
|
||||||
fmt.Println(backend.AnsiError + "An unexpected error occurred while generating the entry list: " + err.Error() + backend.AnsiReset)
|
fmt.Println(backend.AnsiError + "An unexpected error occurred while generating the entry list: " + err.Error() + backend.AnsiReset)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func WalkEntryDir() ([]string, []string) {
|
|||||||
// check for errors encountered while walking directory
|
// check for errors encountered while walking directory
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
fmt.Println(backend.AnsiError+"The entry directory does not exist - run \""+os.Args[0], "init"+"\" to create it"+backend.AnsiReset) // TODO implement init command for libmuttonserver
|
fmt.Println(backend.AnsiError+"The entry directory does not exist - run \""+os.Args[0], "init"+"\" to create it"+backend.AnsiReset)
|
||||||
} else {
|
} else {
|
||||||
// otherwise, print the source of the error
|
// otherwise, print the source of the error
|
||||||
fmt.Println(backend.AnsiError + "An unexpected error occurred while generating the entry list: " + err.Error() + backend.AnsiReset)
|
fmt.Println(backend.AnsiError + "An unexpected error occurred while generating the entry list: " + err.Error() + backend.AnsiReset)
|
||||||
|
|||||||
Reference in New Issue
Block a user