mirror of
https://github.com/rwinkhart/MUTN.git
synced 2026-09-03 15:47:23 -04:00
Implement password generation on new entries
This commit is contained in:
@@ -35,7 +35,8 @@ func main() {
|
|||||||
cli.EntryReaderShortcut(targetLocation, false)
|
cli.EntryReaderShortcut(targetLocation, false)
|
||||||
case "shear":
|
case "shear":
|
||||||
offline.Shear(targetLocation)
|
offline.Shear(targetLocation)
|
||||||
case "gen": // TODO offline.Gen(targetLocation), exit after run
|
case "gen":
|
||||||
|
cli.AddEntry(targetLocation, true, 1)
|
||||||
case "copy":
|
case "copy":
|
||||||
cli.HelpCopy()
|
cli.HelpCopy()
|
||||||
case "edit":
|
case "edit":
|
||||||
@@ -87,30 +88,40 @@ func main() {
|
|||||||
switch args[3] {
|
switch args[3] {
|
||||||
case "password", "-p":
|
case "password", "-p":
|
||||||
if argsCount == 4 {
|
if argsCount == 4 {
|
||||||
cli.AddEntry(targetLocation, true, false)
|
cli.AddEntry(targetLocation, true, 0)
|
||||||
} else {
|
} else {
|
||||||
switch args[4] {
|
switch args[4] {
|
||||||
case "show", "-s":
|
case "show", "-s":
|
||||||
cli.AddEntry(targetLocation, false, false)
|
cli.AddEntry(targetLocation, false, 0)
|
||||||
default:
|
default:
|
||||||
cli.AddEntry(targetLocation, true, false)
|
cli.AddEntry(targetLocation, true, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "note", "-n":
|
case "note", "-n":
|
||||||
cli.AddEntry(targetLocation, true, true)
|
cli.AddEntry(targetLocation, true, 2)
|
||||||
case "folder", "-f":
|
case "folder", "-f":
|
||||||
offline.AddFolder(targetLocation)
|
offline.AddFolder(targetLocation)
|
||||||
default:
|
default:
|
||||||
cli.HelpAdd()
|
cli.HelpAdd()
|
||||||
}
|
}
|
||||||
case "gen":
|
case "gen":
|
||||||
var field rune
|
if argsCount == 4 {
|
||||||
field = field // TODO temporary to avoid unused variable error
|
switch args[3] {
|
||||||
switch args[3] {
|
case "show", "-s":
|
||||||
case "update", "-u": // TODO offline.GenUpdate(targetLocation), exit after run
|
cli.AddEntry(targetLocation, false, 1)
|
||||||
default:
|
case "update", "-u": // TODO offline.GenUpdate(targetLocation), exit after run
|
||||||
cli.HelpGen()
|
default:
|
||||||
|
cli.HelpGen()
|
||||||
|
}
|
||||||
|
} else if args[3] == "update" || args[3] == "-u" {
|
||||||
|
switch args[4] {
|
||||||
|
case "show", "-s":
|
||||||
|
cli.AddEntry(targetLocation, false, 1)
|
||||||
|
default:
|
||||||
|
cli.AddEntry(targetLocation, true, 1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
cli.HelpGen()
|
||||||
default:
|
default:
|
||||||
cli.HelpMain()
|
cli.HelpMain()
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-3
@@ -7,7 +7,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// AddEntry creates a new entry at targetLocation by taking user input via CLI prompts
|
// AddEntry creates a new entry at targetLocation by taking user input via CLI prompts
|
||||||
func AddEntry(targetLocation string, hidePassword bool, isNote bool) {
|
// entryType: 0 = standard (password), 1 = auto-generated password, 2 = note
|
||||||
|
func AddEntry(targetLocation string, hidePassword bool, entryType uint8) {
|
||||||
_, isAccessible := offline.TargetIsFile(targetLocation, false, 0)
|
_, isAccessible := offline.TargetIsFile(targetLocation, false, 0)
|
||||||
if isAccessible {
|
if isAccessible {
|
||||||
fmt.Println(offline.AnsiError + "Target location already exists" + offline.AnsiReset)
|
fmt.Println(offline.AnsiError + "Target location already exists" + offline.AnsiReset)
|
||||||
@@ -16,9 +17,17 @@ func AddEntry(targetLocation string, hidePassword bool, isNote bool) {
|
|||||||
|
|
||||||
var unencryptedEntry []string
|
var unencryptedEntry []string
|
||||||
|
|
||||||
if !isNote {
|
if entryType < 2 {
|
||||||
username := input("Username:")
|
username := input("Username:")
|
||||||
password := inputHidden("Password:")
|
|
||||||
|
// determine whether to generate the password
|
||||||
|
var password string
|
||||||
|
if entryType == 0 {
|
||||||
|
password = inputHidden("Password:")
|
||||||
|
} else {
|
||||||
|
password = offline.StringGen(inputInt("Password length:"), inputBinary("Generate a complex (special characters) password?"), 0.2)
|
||||||
|
}
|
||||||
|
|
||||||
url := input("URL:")
|
url := input("URL:")
|
||||||
if inputBinary("Add a note to this entry?") {
|
if inputBinary("Add a note to this entry?") {
|
||||||
note := newNote()
|
note := newNote()
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import (
|
|||||||
// input prompts the user for input and returns the input as a string
|
// input prompts the user for input and returns the input as a string
|
||||||
func input(prompt string) string {
|
func input(prompt string) string {
|
||||||
fmt.Print("\n" + prompt + " ")
|
fmt.Print("\n" + prompt + " ")
|
||||||
var input string
|
var userInput string
|
||||||
fmt.Scanln(&input)
|
fmt.Scanln(&userInput)
|
||||||
return input
|
return userInput
|
||||||
}
|
}
|
||||||
|
|
||||||
// inputHidden prompts the user for input and returns the input as a string, hiding the input from the terminal
|
// inputHidden prompts the user for input and returns the input as a string, hiding the input from the terminal
|
||||||
@@ -26,6 +26,20 @@ func inputHidden(prompt string) string {
|
|||||||
return password
|
return password
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// inputInt prompts the user for input and returns the input as an integer
|
||||||
|
func inputInt(prompt string) int {
|
||||||
|
|
||||||
|
// loop until a valid integer is entered
|
||||||
|
for {
|
||||||
|
fmt.Print("\n" + prompt + " ")
|
||||||
|
var userInput int
|
||||||
|
_, err := fmt.Scanln(&userInput)
|
||||||
|
if err == nil {
|
||||||
|
return userInput
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// inputBinary prompts the user with a yes/no question and returns the response as a boolean
|
// inputBinary prompts the user with a yes/no question and returns the response as a boolean
|
||||||
func inputBinary(prompt string) bool {
|
func inputBinary(prompt string) bool {
|
||||||
reader := bufio.NewReader(os.Stdin)
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
package offline
|
package offline
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
|
"math/big"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TargetIsFile TargetStatusCheck checks if the targetLocation is a file, directory, or is inaccessible
|
// TargetIsFile TargetStatusCheck checks if the targetLocation is a file, directory, or is inaccessible
|
||||||
@@ -63,3 +67,50 @@ func RemoveTrailingEmptyStrings(slice []string) []string {
|
|||||||
}
|
}
|
||||||
return []string{}
|
return []string{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// StringGen generates a random string of a specified length and complexity
|
||||||
|
// complexity: minimum percentage of special characters to be returned in the generated string (only impacts complex strings)
|
||||||
|
func StringGen(length int, complex bool, complexity float64) string {
|
||||||
|
var extendedCharset string // hold extended character set used for complex strings
|
||||||
|
var actualSpecialChars int // track the number of special characters in the generated string
|
||||||
|
var minSpecialChars int // track the minimum number of special characters to accept
|
||||||
|
|
||||||
|
charset := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" // default character set used for all strings
|
||||||
|
if complex {
|
||||||
|
minSpecialChars = int(math.Round(float64(length) * complexity)) // determine minimum number of special characters to accept
|
||||||
|
extendedCharset = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
|
||||||
|
charset = charset + extendedCharset
|
||||||
|
} else {
|
||||||
|
extendedCharset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
// generate a random string
|
||||||
|
result := make([]byte, length)
|
||||||
|
for i := range result {
|
||||||
|
val, _ := rand.Int(rand.Reader, big.NewInt(int64(len(charset))))
|
||||||
|
result[i] = charset[val.Int64()]
|
||||||
|
}
|
||||||
|
|
||||||
|
// return early if the string is not complex
|
||||||
|
if !complex {
|
||||||
|
return string(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// count the number of special characters in the generated string
|
||||||
|
for _, char := range string(result) {
|
||||||
|
if strings.ContainsRune(extendedCharset, char) {
|
||||||
|
actualSpecialChars++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return the generated string if it contains enough special characters
|
||||||
|
if actualSpecialChars >= minSpecialChars {
|
||||||
|
return string(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset special character counter
|
||||||
|
fmt.Println("Regenerating string until desired complexity is achieved...")
|
||||||
|
actualSpecialChars = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user