Skip to content

Commit

Permalink
Improve config file support and fix file loading error
Browse files Browse the repository at this point in the history
  • Loading branch information
sylviamoss committed Mar 26, 2024
1 parent 9360558 commit a17adc8
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 71 deletions.
59 changes: 45 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@ A tool that generates strong passwords based on easily memorable words that are

### Installing
If you have Go installed, simply run:
```
```shell
go install github.com/sylviamoss/diceware-cli@latest
```

If that's not your case, check the [Installation Guide](#installation-Guide).

### Generating passphrase
```
```shell
Usage:
diceware-cli generate [flags]

Expand All @@ -34,43 +34,74 @@ Flags:
Examples:
Generate a Portuguese passphrase and copy it automatically:
```
```shell
~> diceware-cli generate --lang=pt --copy
Pungir/Bip4/Quorum/Vau/Vida/Censor
```
Generate an English (default) passphrase with seven words, backslash separator, and copy it automatically:
```
```shell
~> diceware-cli generate --copy --size=7 --separator=\\
Unashamed2\Sublime\Rejoin\Justly\Audition\Glove\Cahoots
```

### Adding custom language dictionary
#### Overriding flags default
To avoid typing the same flags over and over again, you can override the default values using a configuration file.
You can pass the configuration file path as a flag to the `generate` command:
```shell
diceware-clid generate --config=/path/to/config.yaml
```
Or you can create the default configuration file `.diceware-cli.yaml` under your home directory and the CLI will automatically pick it up.
You can generate the configuration file content using the CLI:
```shell
~> diceware-cli config generate
# diceware-cli config file yaml content
# You can customize the default values of the flags by setting them in this file.
generate:
lang: en
separator: /
size: 6
copy: false
hide: false
lower: false
```
You can use the generated content to write directly to `$HOME/.diceware-cli.yaml`:
```shell
diceware-cli config generate > $HOME/.diceware-cli.yaml
```
Replace the values you would like to override with your own.
### Adding custom language dictionary
```shell
Usage:
diceware-cli config [flags]
diceware-cli dictionary [flags]
Flags:
--add add new config
-h, --help help for config
--lang add new language
--add-lang add new config language
-h, --help help for dictionary
--name string language name
--source string dictionary source file
```
Example of adding a Spanish diceware dictionary:
```
diceware-cli config --add-lang --source=/Users/diceware-cli/dictionary_file.txt --name=es
```shell
diceware-cli dictionary --add-lang --source=/Users/diceware-cli/dictionary_file.txt --name=es
```
The `dictionary_file.txt` content must be in the same format as this [example of word list](https://www.eff.org/files/2016/07/18/eff_large_wordlist.txt).
The custom dictionary configuration will be ketp under `$HOME/.diceware-cli.d/diceware_words_{language}`
To further generate Spanish diceware passphrase, you'd do:
```
~> diceware-cli generate --lang=es
```shell
diceware-cli generate --lang=es
```

## Installation Guide
Expand Down
47 changes: 7 additions & 40 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,12 @@ package cmd
import (
"errors"
"fmt"
"os"

"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/sylviamoss/diceware-cli/diceware"
)

func init() {
cobra.OnInitialize(initConfig)

configCmd.Flags().StringVarP(&config.file, "file", "f", "", "config file (default is $HOME/.diceware-cli.yaml)")

// Deprecated flags
configCmd.Flags().BoolVar(&config.AddLang, "add-lang", false, "add new config language")
configCmd.Flags().MarkDeprecated("add-lang", "please use the equivalent flag in the 'dictionary' command instead")
Expand All @@ -32,7 +26,6 @@ func init() {

type Config struct {
diceware.Dictionary
file string
}

var (
Expand All @@ -43,6 +36,12 @@ var (
Short: "Configures the diceware-cli config file, used to override defaults of flags",
Long: `Configures the diceware-cli settings, such as overriding the default of the generate command flags.`,
RunE: func(cmd *cobra.Command, args []string) error {
if !config.AddLang {
if err := cmd.Help(); err != nil {
fmt.Println("Use command 'generate' to start generating your strong passwords, or 'help' for instructions.")
}
}

if err := config.Configure(); err != nil {
errorMsg := fmt.Sprintf("Ops...something went wrong: %s", err.Error())
return errors.New(errorMsg)
Expand All @@ -56,7 +55,7 @@ var (
Short: "Generates the content of a diceware-cli yaml config file",
Long: `Generates a diceware-cli yaml config content to be used to override the default values of command flags.
The default location of the file is $HOME/.diceware-cli.yaml, but you can override it using 'diceware-cli --config=/path/to/config.yaml'`,
The default location of the file is $HOME/.diceware-cli.yaml, but you can override it using 'diceware-cli generate --config=/path/to/config.yaml'`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(`# diceware-cli config file yaml content
# You can customize the default values of the flags by setting them in this file.
Expand All @@ -71,35 +70,3 @@ generate:
},
}
)

func initConfig() {
if config.file != "" {
// Use config file from the flag.
viper.SetConfigFile(config.file)

if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
fmt.Println("No configuration file found: ", err.Error())
return
}
fmt.Println("Error reading config file: ", err.Error())
}

} else {
// Find home directory.
home, err := os.UserHomeDir()
cobra.CheckErr(err)

viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".diceware-cli")

if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
fmt.Println("No configuration file found: ", err.Error())
return
}
fmt.Println("Error reading config file: ", err.Error())
}
}
}
43 changes: 26 additions & 17 deletions cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import (
)

func init() {
generateCmd.Flags().StringVar(&dicewareConfig.Lang, "lang", "en", "password language\n available langs: en, pt")
generateCmd.Flags().StringVar(&dicewareConfig.Separator, "separator", "/", "character that separates the words.\nuse --separator=none to remove reparator")
generateCmd.Flags().Int32Var(&dicewareConfig.Size, "size", 6, "the amount words the password will have")
generateCmd.Flags().BoolVar(&dicewareConfig.Pbcopy, "copy", false, "pbcopy password")
generateCmd.Flags().BoolVar(&dicewareConfig.Hide, "hide", false, "pbcopy and hide password. You WON'T see the password")
generateCmd.Flags().BoolVar(&dicewareConfig.Lower, "lower", false, "remove capitalized first letters")
generateCmd.Flags().BoolVar(&dicewareConfig.RemoveNumber, "remove-number", false, "removes the random number we add by default")
generateCmd.Flags().StringVar(&generate.Lang, "lang", "en", "password language\n available langs: en, pt")
generateCmd.Flags().StringVar(&generate.Separator, "separator", "/", "character that separates the words.\nuse --separator=none to remove separator")
generateCmd.Flags().Int32Var(&generate.Size, "size", 6, "the amount words the password will have")
generateCmd.Flags().BoolVar(&generate.Pbcopy, "copy", false, "pbcopy password")
generateCmd.Flags().BoolVar(&generate.Hide, "hide", false, "pbcopy and hide password. You WON'T see the password")
generateCmd.Flags().BoolVar(&generate.Lower, "lower", false, "remove capitalized first letters")
generateCmd.Flags().BoolVar(&generate.RemoveNumber, "remove-number", false, "removes the random number we add by default")

generateCmd.Flags().StringVarP(&generate.configFile, "config", "c", "", "config file (default is $HOME/.diceware-cli.yaml)")

// Configure viper to read from the config file, if set
viper.BindPFlag("generate.lang", generateCmd.Flags().Lookup("lang"))
Expand All @@ -30,8 +32,13 @@ func init() {
rootCmd.AddCommand(generateCmd)
}

type Generate struct {
diceware.Config
configFile string
}

var (
dicewareConfig diceware.Config
generate Generate

generateCmd = &cobra.Command{
Use: "generate",
Expand All @@ -41,17 +48,19 @@ var (
You can customize the default values of the flags by setting them in the config file.`,
RunE: func(cmd *cobra.Command, args []string) error {
// Read the from config file, otherwise default value will be used
dicewareConfig = diceware.Config{
Lang: viper.GetString("generate.lang"),
Separator: viper.GetString("generate.separator"),
Size: viper.GetInt32("generate.size"),
Pbcopy: viper.GetBool("generate.copy"),
Hide: viper.GetBool("generate.hide"),
Lower: viper.GetBool("generate.lower"),
RemoveNumber: viper.GetBool("generate.remove-number"),
generate = Generate{
Config: diceware.Config{
Lang: viper.GetString("generate.lang"),
Separator: viper.GetString("generate.separator"),
Size: viper.GetInt32("generate.size"),
Pbcopy: viper.GetBool("generate.copy"),
Hide: viper.GetBool("generate.hide"),
Lower: viper.GetBool("generate.lower"),
RemoveNumber: viper.GetBool("generate.remove-number"),
},
}

if err := dicewareConfig.Generate(); err != nil {
if err := generate.Generate(); err != nil {
errorMsg := fmt.Sprintf("Ops...something went wrong: %s", err.Error())
return errors.New(errorMsg)
}
Expand Down
35 changes: 35 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os"

"github.com/spf13/cobra"
"github.com/spf13/viper"
)

var (
Expand All @@ -22,6 +23,40 @@ var (
}
)

func init() {
cobra.OnInitialize(initConfig)
}

func initConfig() {
if generate.configFile != "" {
// Use config file from the flag.
viper.SetConfigFile(generate.configFile)

if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
return
}
fmt.Println("Error reading config file: ", err.Error())
}

} else {
// Look for configuration in the home directory.
home, err := os.UserHomeDir()
cobra.CheckErr(err)

viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".diceware-cli")

if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
return
}
fmt.Println("Error reading config file: ", err.Error())
}
}
}

func Execute() {
if err := rootCmd.Execute(); err != nil {
os.Exit(1)
Expand Down

0 comments on commit a17adc8

Please sign in to comment.