Skip to content

Commit

Permalink
Add change command
Browse files Browse the repository at this point in the history
  • Loading branch information
ThilinaManamgoda committed Dec 15, 2019
1 parent 0a06742 commit e27d72a
Show file tree
Hide file tree
Showing 13 changed files with 263 additions and 69 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ A local password manager
### SEE ALSO

* [password-manager add](password-manager_add.md) - Add a new password
* [password-manager change](password-manager_change.md) - Change a password entry
* [password-manager change-master-password](password-manager_change-master-password.md) - Change Master password
* [password-manager generate-password](password-manager_generate-password.md) - Generate a secure password
* [password-manager get](password-manager_get.md) - Get a password
Expand Down
104 changes: 104 additions & 0 deletions cmd/change.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright © 2019 NAME HERE <EMAIL ADDRESS>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
"github.com/ThilinaManamgoda/password-manager/pkg/inputs"
"github.com/ThilinaManamgoda/password-manager/pkg/passwords"
"github.com/pkg/errors"

"github.com/spf13/cobra"
)

// changeCmd represents the change command
var changeCmd = &cobra.Command{
Use: "change [ID]",
Short: "Change a password entry",
Long: `Change a password entry`,
Args: inputs.HasProvidedValidID(),
RunE: func(cmd *cobra.Command, args []string) error {
id := args[0]

mPassword, err := inputs.GetFlagStringVal(cmd, inputs.MasterPassword)
if err != nil {
return errors.Wrapf(err, inputs.ErrMSGCannotGetFlag, mPassword)
}
if mPassword == "" {
mPassword, err = inputs.PromptForMPassword()
if err != nil {
return errors.Wrap(err, "cannot prompt for Master password")
}
}

passwordRepo, err := passwords.InitPasswordRepo(mPassword)
if err != nil {
return errors.Wrapf(err, "cannot initialize password repository")
}

passwordEntry, err := passwordRepo.GetPasswordEntry(id)
if err != nil {
return errors.Wrapf(err, "cannot get password entry")
}

isInteractiveMode, err := inputs.GetFlagBoolVal(cmd, InteractiveMode)
if err != nil {
return err
}
var uN, password string
if isInteractiveMode {
uN, err = inputs.PromptForUsernameWithDefault(passwordEntry.Username)
if err != nil {
return errors.Wrap(err, "cannot prompt for username")
}
password, err = inputs.PromptForUserPasswordWithDefault(passwordEntry.Password)
if err != nil {
return errors.Wrap(err, "cannot prompt for password")
}
} else {
err = inputs.FromFlags(cmd, &uN, &password, nil, nil)
if err != nil {
return errors.Wrapf(err, inputs.ErrMsgCannotGetInput)
}
}
newEntry := passwords.PasswordEntry{
ID: id,
Username: uN,
Password: password,
}
err = passwordRepo.ChangePasswordEntry(id, newEntry)
if err != nil {
return errors.Wrapf(err, "cannot change password")
}
return nil
},
}

func init() {
rootCmd.AddCommand(changeCmd)

// Here you will define your flags and configuration settings.

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// changeCmd.PersistentFlags().String("foo", "", "A help for foo")

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// changeCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
changeCmd.Flags().StringP(inputs.Password, "p", "", "Password")
changeCmd.Flags().StringP(inputs.Username, "u", "", "User Name")
changeCmd.Flags().BoolP(InteractiveMode, "i", false, "Enable interactive mode")

}
2 changes: 1 addition & 1 deletion password-manager_add.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ password-manager add [ID] [flags]

* [password-manager](password-manager.md) - A local Password Manager

###### Auto generated by spf13/cobra on 12-Dec-2019
###### Auto generated by spf13/cobra on 15-Dec-2019
2 changes: 1 addition & 1 deletion password-manager_change-master-password.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ password-manager change-master-password [flags]

* [password-manager](password-manager.md) - A local Password Manager

###### Auto generated by spf13/cobra on 12-Dec-2019
###### Auto generated by spf13/cobra on 15-Dec-2019
32 changes: 32 additions & 0 deletions password-manager_change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## password-manager change

Change a password entry

### Synopsis

Change a password entry

```
password-manager change [ID] [flags]
```

### Options

```
-h, --help help for change
-i, --interactive Enable interactive mode
-p, --password string Password
-u, --username string User Name
```

### Options inherited from parent commands

```
-m, --masterPassword string Master password
```

### SEE ALSO

* [password-manager](password-manager.md) - A local Password Manager

###### Auto generated by spf13/cobra on 15-Dec-2019
2 changes: 1 addition & 1 deletion password-manager_generate-password.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ password-manager generate-password [flags]

* [password-manager](password-manager.md) - A local Password Manager

###### Auto generated by spf13/cobra on 12-Dec-2019
###### Auto generated by spf13/cobra on 15-Dec-2019
2 changes: 1 addition & 1 deletion password-manager_get.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ password-manager get [ID] [flags]

* [password-manager](password-manager.md) - A local Password Manager

###### Auto generated by spf13/cobra on 12-Dec-2019
###### Auto generated by spf13/cobra on 15-Dec-2019
2 changes: 1 addition & 1 deletion password-manager_import.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ password-manager import [flags]

* [password-manager](password-manager.md) - A local Password Manager

###### Auto generated by spf13/cobra on 12-Dec-2019
###### Auto generated by spf13/cobra on 15-Dec-2019
2 changes: 1 addition & 1 deletion password-manager_remove.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,4 @@ password-manager remove [ID] [flags]

* [password-manager](password-manager.md) - A local Password Manager

###### Auto generated by spf13/cobra on 12-Dec-2019
###### Auto generated by spf13/cobra on 15-Dec-2019
2 changes: 1 addition & 1 deletion password-manager_search-id.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ password-manager search-id [ID] [flags]

* [password-manager](password-manager.md) - A local Password Manager

###### Auto generated by spf13/cobra on 12-Dec-2019
###### Auto generated by spf13/cobra on 15-Dec-2019
2 changes: 1 addition & 1 deletion password-manager_search-label.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ password-manager search-label [ID] [flags]

* [password-manager](password-manager.md) - A local Password Manager

###### Auto generated by spf13/cobra on 12-Dec-2019
###### Auto generated by spf13/cobra on 15-Dec-2019
127 changes: 81 additions & 46 deletions pkg/inputs/inputs.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package inputs

import (
"fmt"
"github.com/manifoldco/promptui"
"github.com/pkg/errors"
"github.com/spf13/cobra"
Expand All @@ -36,8 +37,30 @@ const (
ErrMSGCannotGetFlag = "cannot get value of %s flag"

MasterPassword = "masterPassword"

MaxPasswordCharacters = 6
)

var (
userNameValidator = func(input string) error {
if len(input) < MaxPasswordCharacters {
return errors.New(fmt.Sprintf("username must have more than %d characters", MaxPasswordCharacters))
}
return nil
}

passwordValidator = func(errorMsg string) func(input string) error {
return func(input string) error {
if len(input) < MaxPasswordCharacters {
return errors.New(errorMsg)
}
return nil
}
}
masterPasswordValidator = passwordValidator(fmt.Sprintf("master password must have more than %d characters", MaxPasswordCharacters))
userPasswordValidator = passwordValidator(fmt.Sprintf("password must have more than %d characters", MaxPasswordCharacters))
newMasterPasswordValidator = passwordValidator(fmt.Sprintf("new master password must have more than %d characters", MaxPasswordCharacters))
)
// IsPasswordValid method check whether the Password is valid or not
func IsPasswordValid(passphrase string) bool {
return passphrase != ""
Expand All @@ -61,7 +84,6 @@ func GetFlagIntVal(cmd *cobra.Command, flag string) (int, error) {
return val, nil
}


// GetFlagBoolVal method returns the Boolean flag value
func GetFlagBoolVal(cmd *cobra.Command, flag string) (bool, error) {
val, err := cmd.Flags().GetBool(flag)
Expand Down Expand Up @@ -99,6 +121,29 @@ func PromptForString(label string, validate promptui.ValidateFunc) (string, erro
return prompt.Run()
}

func PromptForStringWithDefault(label, defaultVal string, validate promptui.ValidateFunc) (string, error) {
prompt := promptui.Prompt{
Label: label,
Validate: validate,
Default: defaultVal,
}
return prompt.Run()
}

func PromptForUserPasswordWithDefault(defaultVal string)(string, error){
return PromptForPasswordWithDefault("Password ", defaultVal, userPasswordValidator)
}

func PromptForPasswordWithDefault(label, defaultVal string, validate promptui.ValidateFunc) (string, error) {
prompt := promptui.Prompt{
Label: label,
Validate: validate,
Default: defaultVal,
Mask: '*',
}
return prompt.Run()
}

func promptForPassword(label string, validate promptui.ValidateFunc) (string, error) {
prompt := promptui.Prompt{
Label: label,
Expand Down Expand Up @@ -132,26 +177,37 @@ func HasProvidedValidID() func(cmd *cobra.Command, args []string) error {
}

func FromFlags(cmd *cobra.Command, uN, password, mPassword *string, labels *[]string) error {
uNVal, err := GetFlagStringVal(cmd, Username)
if err != nil {
return errors.Wrapf(err, ErrMSGCannotGetFlag, Username)
if uN !=nil {
uNVal, err := GetFlagStringVal(cmd, Username)
if err != nil {
return errors.Wrapf(err, ErrMSGCannotGetFlag, Username)
}
*uN = uNVal
}
*uN = uNVal
passwordVal, err := GetFlagStringVal(cmd, Password)
if err != nil {
return errors.Wrapf(err, ErrMSGCannotGetFlag, Password)

if password != nil {
passwordVal, err := GetFlagStringVal(cmd, Password)
if err != nil {
return errors.Wrapf(err, ErrMSGCannotGetFlag, Password)
}
*password = passwordVal
}
*password = passwordVal
labelsVal, err := GetFlagStringArrayVal(cmd, Labels)
if err != nil {
return errors.Wrapf(err, ErrMSGCannotGetFlag, Labels)

if labels !=nil {
labelsVal, err := GetFlagStringArrayVal(cmd, Labels)
if err != nil {
return errors.Wrapf(err, ErrMSGCannotGetFlag, Labels)
}
*labels = labelsVal
}
*labels = labelsVal
mPasswordVal, err := GetFlagStringVal(cmd, MasterPassword)
if err != nil {
return errors.Wrapf(err, ErrMSGCannotGetFlag, MasterPassword)

if mPassword !=nil {
mPasswordVal, err := GetFlagStringVal(cmd, MasterPassword)
if err != nil {
return errors.Wrapf(err, ErrMSGCannotGetFlag, MasterPassword)
}
*mPassword = mPasswordVal
}
*mPassword = mPasswordVal
return nil
}

Expand Down Expand Up @@ -180,13 +236,11 @@ func FromPrompt(uN, password, mPassword *string, labels *[]string) error {
}

func PromptForUsername() (string, error) {
validate := func(input string) error {
if len(input) < 3 {
return errors.New("username must have more than 3 characters")
}
return nil
}
return PromptForString("Username ", validate)
return PromptForString("Username ", userNameValidator)
}

func PromptForUsernameWithDefault(defaultVal string) (string, error) {
return PromptForStringWithDefault("Username ", defaultVal, userNameValidator)
}

func PromptForLabels() ([]string, error) {
Expand All @@ -204,34 +258,15 @@ func PromptForLabels() ([]string, error) {
return l, nil
}


func PromptForNewMPassword() (string, error) {
validate := func(input string) error {
if len(input) < 6 {
return errors.New("new master password must have more than 6 characters")
}
return nil
}
return promptForPassword("New Master password ", validate)
return promptForPassword("New Master password ", newMasterPasswordValidator)
}

func PromptForMPassword() (string, error) {
validate := func(input string) error {
if len(input) < 6 {
return errors.New("master password must have more than 6 characters")
}
return nil
}
return promptForPassword("Master password ", validate)
return promptForPassword("Master password ", masterPasswordValidator)
}

// PromptForPassword function prompt for password and returns the input
func PromptForPassword() (string, error) {
validate := func(input string) error {
if len(input) < 6 {
return errors.New("password must have more than 6 characters")
}
return nil
}
return promptForPassword("Password ", validate)
return promptForPassword("Password ", userPasswordValidator)
}
Loading

0 comments on commit e27d72a

Please sign in to comment.