mirror of https://github.com/mitchell/selfpass.git
Refactored config management strategy for spc
This commit is contained in:
parent
3d3206ddfe
commit
30e514cb88
|
@ -7,13 +7,13 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
|
||||||
|
|
||||||
|
"github.com/mitchell/selfpass/cli/types"
|
||||||
"github.com/mitchell/selfpass/credentials/commands"
|
"github.com/mitchell/selfpass/credentials/commands"
|
||||||
"github.com/mitchell/selfpass/crypto"
|
"github.com/mitchell/selfpass/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeDecrypt(masterpass string, cfg *viper.Viper) *cobra.Command {
|
func makeDecrypt(repo types.ConfigRepo) *cobra.Command {
|
||||||
decryptCmd := &cobra.Command{
|
decryptCmd := &cobra.Command{
|
||||||
Use: "decrypt [file]",
|
Use: "decrypt [file]",
|
||||||
Short: "Decrypt a file using your masterpass and secret key",
|
Short: "Decrypt a file using your masterpass and secret key",
|
||||||
|
@ -22,6 +22,9 @@ the new file.`,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
masterpass, cfg, err := repo.OpenConfig()
|
||||||
|
check(err)
|
||||||
|
|
||||||
file := args[0]
|
file := args[0]
|
||||||
fileout := file
|
fileout := file
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package commands
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"github.com/mitchell/selfpass/cli/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
func makeDecryptCfg(repo types.ConfigRepo) *cobra.Command {
|
||||||
|
decryptCfg := &cobra.Command{
|
||||||
|
Use: "decrypt-cfg",
|
||||||
|
Short: "Decrypt your config file",
|
||||||
|
Long: "Decrypt your config file, so you can access your private key, host, and certs.",
|
||||||
|
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
_, _, err := repo.OpenConfig()
|
||||||
|
check(err)
|
||||||
|
|
||||||
|
repo.DecryptConfig()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return decryptCfg
|
||||||
|
}
|
|
@ -7,13 +7,13 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
|
||||||
|
|
||||||
|
"github.com/mitchell/selfpass/cli/types"
|
||||||
"github.com/mitchell/selfpass/credentials/commands"
|
"github.com/mitchell/selfpass/credentials/commands"
|
||||||
"github.com/mitchell/selfpass/crypto"
|
"github.com/mitchell/selfpass/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeEncrypt(masterpass string, cfg *viper.Viper) *cobra.Command {
|
func makeEncrypt(repo types.ConfigRepo) *cobra.Command {
|
||||||
encryptCmd := &cobra.Command{
|
encryptCmd := &cobra.Command{
|
||||||
Use: "encrypt [file]",
|
Use: "encrypt [file]",
|
||||||
Short: "Encrypt a file using your masterpass and secret key",
|
Short: "Encrypt a file using your masterpass and secret key",
|
||||||
|
@ -22,6 +22,9 @@ new file.`,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
masterpass, cfg, err := repo.OpenConfig()
|
||||||
|
check(err)
|
||||||
|
|
||||||
file := args[0]
|
file := args[0]
|
||||||
fileEnc := file + ".enc"
|
fileEnc := file + ".enc"
|
||||||
|
|
||||||
|
|
|
@ -8,13 +8,13 @@ import (
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"github.com/mitchellh/go-homedir"
|
"github.com/mitchellh/go-homedir"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
|
||||||
"gopkg.in/AlecAivazis/survey.v1"
|
"gopkg.in/AlecAivazis/survey.v1"
|
||||||
|
|
||||||
|
"github.com/mitchell/selfpass/cli/types"
|
||||||
"github.com/mitchell/selfpass/credentials/commands"
|
"github.com/mitchell/selfpass/credentials/commands"
|
||||||
)
|
)
|
||||||
|
|
||||||
func makeInit(cfg *viper.Viper) *cobra.Command {
|
func makeInit(repo types.ConfigRepo) *cobra.Command {
|
||||||
initCmd := &cobra.Command{
|
initCmd := &cobra.Command{
|
||||||
Use: "init",
|
Use: "init",
|
||||||
Short: "This command initializes SPC for the first time",
|
Short: "This command initializes SPC for the first time",
|
||||||
|
@ -32,6 +32,7 @@ the users private key, and server certificates. (All of which will be encrypted)
|
||||||
prompt survey.Prompt
|
prompt survey.Prompt
|
||||||
privateKey = strings.Replace(uuid.New().String(), "-", "", -1)
|
privateKey = strings.Replace(uuid.New().String(), "-", "", -1)
|
||||||
)
|
)
|
||||||
|
_, cfg, _ := repo.OpenConfig()
|
||||||
|
|
||||||
prompt = &survey.Password{Message: "New master password:"}
|
prompt = &survey.Password{Message: "New master password:"}
|
||||||
check(survey.AskOne(prompt, &masterpass, nil))
|
check(survey.AskOne(prompt, &masterpass, nil))
|
||||||
|
@ -42,6 +43,8 @@ the users private key, and server certificates. (All of which will be encrypted)
|
||||||
check(fmt.Errorf("master passwords didn't match"))
|
check(fmt.Errorf("master passwords didn't match"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
repo.SetMasterpass(masterpass)
|
||||||
|
|
||||||
prompt = &survey.Input{Message: "Selfpass server address:"}
|
prompt = &survey.Input{Message: "Selfpass server address:"}
|
||||||
check(survey.AskOne(prompt, &target, nil))
|
check(survey.AskOne(prompt, &target, nil))
|
||||||
|
|
||||||
|
@ -49,7 +52,7 @@ the users private key, and server certificates. (All of which will be encrypted)
|
||||||
check(survey.AskOne(prompt, &hasPK, nil))
|
check(survey.AskOne(prompt, &hasPK, nil))
|
||||||
|
|
||||||
if hasPK {
|
if hasPK {
|
||||||
prompt = &survey.Input{Message: "Private key:"}
|
prompt = &survey.Password{Message: "Private key:"}
|
||||||
check(survey.AskOne(prompt, &privateKey, nil))
|
check(survey.AskOne(prompt, &privateKey, nil))
|
||||||
privateKey = strings.Replace(privateKey, "-", "", -1)
|
privateKey = strings.Replace(privateKey, "-", "", -1)
|
||||||
}
|
}
|
||||||
|
@ -86,8 +89,6 @@ the users private key, and server certificates. (All of which will be encrypted)
|
||||||
cfg.SetConfigFile(home + "/.spc.toml")
|
cfg.SetConfigFile(home + "/.spc.toml")
|
||||||
fmt.Println("Wrote new config to: " + home + "/.spc.toml")
|
fmt.Println("Wrote new config to: " + home + "/.spc.toml")
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptConfig(masterpass, cfg)
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,21 +3,18 @@ package commands
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/mitchellh/go-homedir"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
|
||||||
"gopkg.in/AlecAivazis/survey.v1"
|
|
||||||
|
|
||||||
|
"github.com/mitchell/selfpass/cli/repositories"
|
||||||
|
"github.com/mitchell/selfpass/cli/types"
|
||||||
"github.com/mitchell/selfpass/credentials/commands"
|
"github.com/mitchell/selfpass/credentials/commands"
|
||||||
|
credrepos "github.com/mitchell/selfpass/credentials/repositories"
|
||||||
credtypes "github.com/mitchell/selfpass/credentials/types"
|
credtypes "github.com/mitchell/selfpass/credentials/types"
|
||||||
"github.com/mitchell/selfpass/crypto"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Execute(initClient credtypes.CredentialClientInit) {
|
func Execute() {
|
||||||
rootCmd := &cobra.Command{
|
rootCmd := &cobra.Command{
|
||||||
Use: "spc",
|
Use: "spc",
|
||||||
Short: "This is the CLI client for Selfpass.",
|
Short: "This is the CLI client for Selfpass.",
|
||||||
|
@ -25,42 +22,31 @@ func Execute(initClient credtypes.CredentialClientInit) {
|
||||||
can interact with the entire Selfpass API.`,
|
can interact with the entire Selfpass API.`,
|
||||||
Version: "v0.1.0",
|
Version: "v0.1.0",
|
||||||
}
|
}
|
||||||
rootCmd.InitDefaultHelpFlag()
|
|
||||||
rootCmd.InitDefaultVersionFlag()
|
|
||||||
|
|
||||||
cfgFile := rootCmd.PersistentFlags().String("config", "", "config file (default is $HOME/.spc.toml)")
|
cfgFile := rootCmd.PersistentFlags().String("config", "", "config file (default is $HOME/.spc.toml)")
|
||||||
decryptCfg := rootCmd.Flags().Bool("decrypt-cfg", false, "decrypt config file")
|
|
||||||
check(rootCmd.ParseFlags(os.Args))
|
|
||||||
encryptCfg := !*decryptCfg
|
|
||||||
|
|
||||||
var masterpass string
|
mgr := repositories.NewConfigManager(cfgFile)
|
||||||
var cfg *viper.Viper
|
defer mgr.CloseConfig()
|
||||||
needsCfg := (len(os.Args) > 1 && !strings.Contains(strings.Join(os.Args, "--"), "--help")) || *decryptCfg
|
|
||||||
|
|
||||||
if needsCfg {
|
clientInit := credrepos.NewCredentialServiceClient
|
||||||
masterpass, cfg = openConfig(*cfgFile)
|
|
||||||
if encryptCfg && masterpass != "" {
|
|
||||||
defer encryptConfig(masterpass, cfg)
|
|
||||||
}
|
|
||||||
if *decryptCfg {
|
|
||||||
fmt.Println("Decrypting config file. It will auto-encrypt when you next run of spc.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rootCmd.AddCommand(makeInit(cfg))
|
rootCmd.AddCommand(makeInit(mgr))
|
||||||
rootCmd.AddCommand(makeEncrypt(masterpass, cfg))
|
rootCmd.AddCommand(makeEncrypt(mgr))
|
||||||
rootCmd.AddCommand(makeDecrypt(masterpass, cfg))
|
rootCmd.AddCommand(makeDecrypt(mgr))
|
||||||
rootCmd.AddCommand(commands.MakeList(makeInitClient(cfg, initClient)))
|
rootCmd.AddCommand(makeDecryptCfg(mgr))
|
||||||
rootCmd.AddCommand(commands.MakeCreate(masterpass, cfg, makeInitClient(cfg, initClient)))
|
rootCmd.AddCommand(commands.MakeList(makeInitClient(mgr, clientInit)))
|
||||||
rootCmd.AddCommand(commands.MakeGet(masterpass, cfg, makeInitClient(cfg, initClient)))
|
rootCmd.AddCommand(commands.MakeCreate(mgr, makeInitClient(mgr, clientInit)))
|
||||||
rootCmd.AddCommand(commands.MakeDelete(makeInitClient(cfg, initClient)))
|
rootCmd.AddCommand(commands.MakeGet(mgr, makeInitClient(mgr, clientInit)))
|
||||||
|
rootCmd.AddCommand(commands.MakeDelete(makeInitClient(mgr, clientInit)))
|
||||||
|
|
||||||
check(rootCmd.Execute())
|
check(rootCmd.Execute())
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeInitClient(cfg *viper.Viper, initClient credtypes.CredentialClientInit) commands.CredentialClientInit {
|
func makeInitClient(repo types.ConfigRepo, initClient credtypes.CredentialClientInit) commands.CredentialClientInit {
|
||||||
return func(ctx context.Context) credtypes.CredentialClient {
|
return func(ctx context.Context) credtypes.CredentialClient {
|
||||||
|
_, cfg, err := repo.OpenConfig()
|
||||||
|
check(err)
|
||||||
|
|
||||||
connConfig := cfg.GetStringMapString(keyConnConfig)
|
connConfig := cfg.GetStringMapString(keyConnConfig)
|
||||||
|
|
||||||
client, err := initClient(
|
client, err := initClient(
|
||||||
|
@ -70,86 +56,12 @@ func makeInitClient(cfg *viper.Viper, initClient credtypes.CredentialClientInit)
|
||||||
connConfig["cert"],
|
connConfig["cert"],
|
||||||
connConfig["key"],
|
connConfig["key"],
|
||||||
)
|
)
|
||||||
if err != nil {
|
check(err)
|
||||||
fmt.Printf("Please run 'init' command before running API commands.\nError Message: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return client
|
return client
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func openConfig(cfgFile string) (masterpass string, v *viper.Viper) {
|
|
||||||
v = viper.New()
|
|
||||||
v.SetConfigType("toml")
|
|
||||||
|
|
||||||
if cfgFile != "" {
|
|
||||||
// Use config file from the flag.
|
|
||||||
v.SetConfigFile(cfgFile)
|
|
||||||
} else {
|
|
||||||
// Find home directory.
|
|
||||||
home, err := homedir.Dir()
|
|
||||||
check(err)
|
|
||||||
|
|
||||||
// Search config in home directory with name ".spc" (without extension).
|
|
||||||
v.AddConfigPath(home)
|
|
||||||
v.SetConfigName(".spc")
|
|
||||||
|
|
||||||
cfgFile = home + "/.spc.toml"
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := os.Open(cfgFile); !os.IsNotExist(err) {
|
|
||||||
prompt := &survey.Password{Message: "Master password:"}
|
|
||||||
check(survey.AskOne(prompt, &masterpass, nil))
|
|
||||||
|
|
||||||
decryptConfig(masterpass, cfgFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
//v.AutomaticEnv() // read in environment variables that match
|
|
||||||
|
|
||||||
// If a config file is found, read it in.
|
|
||||||
if err := v.ReadInConfig(); err == nil {
|
|
||||||
fmt.Println("Using config file:", v.ConfigFileUsed())
|
|
||||||
}
|
|
||||||
|
|
||||||
return masterpass, v
|
|
||||||
}
|
|
||||||
|
|
||||||
func decryptConfig(masterpass string, cfgFile string) {
|
|
||||||
contents, err := ioutil.ReadFile(cfgFile)
|
|
||||||
check(err)
|
|
||||||
|
|
||||||
passkey, err := crypto.GenerateKeyFromPassword([]byte(masterpass))
|
|
||||||
check(err)
|
|
||||||
|
|
||||||
contents, err = crypto.CBCDecrypt(passkey, contents)
|
|
||||||
if err != nil && err.Error() == "Padding incorrect" {
|
|
||||||
fmt.Println("incorrect master password")
|
|
||||||
os.Exit(1)
|
|
||||||
} else if err != nil && err.Error() == "ciphertext is not a multiple of the block size" {
|
|
||||||
fmt.Println("Config wasn't encrypted.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
check(err)
|
|
||||||
|
|
||||||
check(ioutil.WriteFile(cfgFile, contents, 0600))
|
|
||||||
}
|
|
||||||
|
|
||||||
func encryptConfig(masterpass string, cfg *viper.Viper) {
|
|
||||||
contents, err := ioutil.ReadFile(cfg.ConfigFileUsed())
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
keypass, err := crypto.GenerateKeyFromPassword([]byte(masterpass))
|
|
||||||
check(err)
|
|
||||||
|
|
||||||
contents, err = crypto.CBCEncrypt(keypass, contents)
|
|
||||||
check(err)
|
|
||||||
|
|
||||||
check(ioutil.WriteFile(cfg.ConfigFileUsed(), contents, 0600))
|
|
||||||
}
|
|
||||||
|
|
||||||
func check(err error) {
|
func check(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
package repositories
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/mitchellh/go-homedir"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"gopkg.in/AlecAivazis/survey.v1"
|
||||||
|
|
||||||
|
"github.com/mitchell/selfpass/crypto"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewConfigManager(cfgFile *string) *ConfigManager {
|
||||||
|
return &ConfigManager{
|
||||||
|
cfgFile: cfgFile,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConfigManager struct {
|
||||||
|
masterpass string
|
||||||
|
decrypted bool
|
||||||
|
decrypt bool
|
||||||
|
cfgFile *string
|
||||||
|
v *viper.Viper
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mgr *ConfigManager) SetMasterpass(masterpass string) {
|
||||||
|
mgr.masterpass = masterpass
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mgr *ConfigManager) OpenConfig() (output string, v *viper.Viper, err error) {
|
||||||
|
if mgr.masterpass != "" {
|
||||||
|
return mgr.masterpass, mgr.v, nil
|
||||||
|
}
|
||||||
|
cfg := *mgr.cfgFile
|
||||||
|
|
||||||
|
v = viper.New()
|
||||||
|
mgr.v = v
|
||||||
|
|
||||||
|
v.SetConfigType("toml")
|
||||||
|
|
||||||
|
if cfg != "" {
|
||||||
|
// Use config file from the flag.
|
||||||
|
v.SetConfigFile(cfg)
|
||||||
|
} else {
|
||||||
|
// Find home directory.
|
||||||
|
home, err := homedir.Dir()
|
||||||
|
if err != nil {
|
||||||
|
return output, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search config in home directory with name ".spc" (without extension).
|
||||||
|
v.AddConfigPath(home)
|
||||||
|
v.SetConfigName(".spc")
|
||||||
|
|
||||||
|
cfg = home + "/.spc.toml"
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := os.Open(cfg); !os.IsNotExist(err) {
|
||||||
|
prompt := &survey.Password{Message: "Master password:"}
|
||||||
|
if err = survey.AskOne(prompt, &mgr.masterpass, nil); err != nil {
|
||||||
|
return output, nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
mgr.decrypted, err = decryptConfig(mgr.masterpass, cfg)
|
||||||
|
if err != nil {
|
||||||
|
return output, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// v.AutomaticEnv() // read in environment variables that match
|
||||||
|
|
||||||
|
// If a config file is found, read it in.
|
||||||
|
if err = v.ReadInConfig(); err != nil {
|
||||||
|
mgr.decrypted = true
|
||||||
|
return output, v, fmt.Errorf("no config found, run 'init' command")
|
||||||
|
}
|
||||||
|
|
||||||
|
return mgr.masterpass, mgr.v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func decryptConfig(masterpass string, cfgFile string) (decrypted bool, err error) {
|
||||||
|
contents, err := ioutil.ReadFile(cfgFile)
|
||||||
|
if err != nil {
|
||||||
|
return decrypted, err
|
||||||
|
}
|
||||||
|
|
||||||
|
passkey, err := crypto.GenerateKeyFromPassword([]byte(masterpass))
|
||||||
|
if err != nil {
|
||||||
|
return decrypted, err
|
||||||
|
}
|
||||||
|
|
||||||
|
contents, err = crypto.CBCDecrypt(passkey, contents)
|
||||||
|
if err != nil && err.Error() == "Padding incorrect" {
|
||||||
|
return decrypted, fmt.Errorf("incorrect master password")
|
||||||
|
} else if err != nil && err.Error() == "ciphertext is not a multiple of the block size" {
|
||||||
|
fmt.Println("Config wasn't encrypted.")
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return decrypted, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = ioutil.WriteFile(cfgFile, contents, 0600); err != nil {
|
||||||
|
return decrypted, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mgr *ConfigManager) DecryptConfig() {
|
||||||
|
mgr.decrypt = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mgr *ConfigManager) CloseConfig() {
|
||||||
|
if !mgr.decrypt && mgr.decrypted {
|
||||||
|
contents, err := ioutil.ReadFile(mgr.v.ConfigFileUsed())
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
keypass, err := crypto.GenerateKeyFromPassword([]byte(mgr.masterpass))
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
contents, err = crypto.CBCEncrypt(keypass, contents)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ioutil.WriteFile(mgr.v.ConfigFileUsed(), contents, 0600)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if mgr.decrypt {
|
||||||
|
fmt.Println("Decrypting config file. It will auto-encrypt when you next run spc.")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package types
|
||||||
|
|
||||||
|
import "github.com/spf13/viper"
|
||||||
|
|
||||||
|
type ConfigRepo interface {
|
||||||
|
OpenConfig() (masterpass string, cfg *viper.Viper, err error)
|
||||||
|
DecryptConfig()
|
||||||
|
SetMasterpass(masterpass string)
|
||||||
|
}
|
|
@ -2,9 +2,8 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/mitchell/selfpass/cli/commands"
|
"github.com/mitchell/selfpass/cli/commands"
|
||||||
"github.com/mitchell/selfpass/credentials/repositories"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
commands.Execute(repositories.NewCredentialServiceClient)
|
commands.Execute()
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,14 +11,14 @@ import (
|
||||||
"github.com/atotto/clipboard"
|
"github.com/atotto/clipboard"
|
||||||
"github.com/pquerna/otp/totp"
|
"github.com/pquerna/otp/totp"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
|
||||||
"gopkg.in/AlecAivazis/survey.v1"
|
"gopkg.in/AlecAivazis/survey.v1"
|
||||||
|
|
||||||
|
clitypes "github.com/mitchell/selfpass/cli/types"
|
||||||
"github.com/mitchell/selfpass/credentials/types"
|
"github.com/mitchell/selfpass/credentials/types"
|
||||||
"github.com/mitchell/selfpass/crypto"
|
"github.com/mitchell/selfpass/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
func MakeCreate(masterpass string, cfg *viper.Viper, initClient CredentialClientInit) *cobra.Command {
|
func MakeCreate(repo clitypes.ConfigRepo, initClient CredentialClientInit) *cobra.Command {
|
||||||
var length uint
|
var length uint
|
||||||
var numbers bool
|
var numbers bool
|
||||||
var specials bool
|
var specials bool
|
||||||
|
@ -30,6 +30,9 @@ func MakeCreate(masterpass string, cfg *viper.Viper, initClient CredentialClient
|
||||||
password.`,
|
password.`,
|
||||||
|
|
||||||
Run: func(_ *cobra.Command, args []string) {
|
Run: func(_ *cobra.Command, args []string) {
|
||||||
|
masterpass, cfg, err := repo.OpenConfig()
|
||||||
|
check(err)
|
||||||
|
|
||||||
mdqs := []*survey.Question{
|
mdqs := []*survey.Question{
|
||||||
{
|
{
|
||||||
Name: "primary",
|
Name: "primary",
|
||||||
|
|
|
@ -10,14 +10,14 @@ import (
|
||||||
"github.com/atotto/clipboard"
|
"github.com/atotto/clipboard"
|
||||||
"github.com/pquerna/otp/totp"
|
"github.com/pquerna/otp/totp"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
|
||||||
"gopkg.in/AlecAivazis/survey.v1"
|
"gopkg.in/AlecAivazis/survey.v1"
|
||||||
|
|
||||||
|
clitypes "github.com/mitchell/selfpass/cli/types"
|
||||||
"github.com/mitchell/selfpass/credentials/types"
|
"github.com/mitchell/selfpass/credentials/types"
|
||||||
"github.com/mitchell/selfpass/crypto"
|
"github.com/mitchell/selfpass/crypto"
|
||||||
)
|
)
|
||||||
|
|
||||||
func MakeGet(masterpass string, cfg *viper.Viper, initClient CredentialClientInit) *cobra.Command {
|
func MakeGet(repo clitypes.ConfigRepo, initClient CredentialClientInit) *cobra.Command {
|
||||||
getCmd := &cobra.Command{
|
getCmd := &cobra.Command{
|
||||||
Use: "get",
|
Use: "get",
|
||||||
Short: "Get a credential info and copy password to clipboard",
|
Short: "Get a credential info and copy password to clipboard",
|
||||||
|
@ -29,6 +29,9 @@ decrypting password.`,
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
client := initClient(ctx)
|
client := initClient(ctx)
|
||||||
|
masterpass, cfg, err := repo.OpenConfig()
|
||||||
|
check(err)
|
||||||
|
|
||||||
mdch, errch := client.GetAllMetadata(ctx, "")
|
mdch, errch := client.GetAllMetadata(ctx, "")
|
||||||
mds := map[string][]types.Metadata{}
|
mds := map[string][]types.Metadata{}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue