Skip to content
This repository has been archived by the owner on Nov 9, 2019. It is now read-only.

Commit

Permalink
Merge branch 'release-0.4.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
bndw committed Feb 26, 2017
2 parents 3671241 + 421a82f commit 4ca6cb4
Show file tree
Hide file tree
Showing 51 changed files with 1,765 additions and 242 deletions.
9 changes: 9 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
language: go
go:
- 1.6
- tip
install:
- make
script:
- make build
- make test
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ INSTALL = install

FOLDERS = $(shell find . -mindepth 1 -type d -not -path "*.git*" -not -path "./githooks*" -not -path "./vendor*" -not -path "*bin*")

VERSION = $(shell cat VERSION)
LDFLAGS = -ldflags "-X main.version=$(VERSION)"

all: build

install_hooks:
Expand All @@ -32,7 +35,7 @@ goget:
ln -sf $(PWD) $(CURDIR)/vendor/src/$(GOPKG)

build: install_hooks goget
GOPATH=$(GOPATH) go build -o bin/pick .
GOPATH=$(GOPATH) go build $(LDFLAGS) -o bin/pick .

test: goget
GOPATH=$(GOPATH) go test -v $(FOLDERS)
Expand Down Expand Up @@ -65,4 +68,4 @@ clean:
rm -rf vendor/
rm -rf bin/

.PHONY: all install_hooks goget build test install uninstall fmt gofmt config clean
.PHONY: all install_hooks goget build test install uninstall fmt gofmt govet config clean
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
pick
====
[![Build Status](https://travis-ci.org/bndw/pick.svg?branch=master)](https://travis-ci.org/bndw/pick)

A minimal password manager for OS X and Linux.

![demo](https://github.com/bndw/pick/raw/master/demo.gif)
Expand All @@ -8,7 +10,7 @@ A minimal password manager for OS X and Linux.

#### go get
```sh
$ go get github.com/bndw/pick
$ go get -u github.com/bndw/pick
```

#### Homebrew
Expand All @@ -34,6 +36,7 @@ Available Commands:
backup Backup the safe
cat Cat a credential
cp Copy a credential to the clipboard
edit Edit a credential
export Export decrypted credentials in JSON format
ls List all credentials
rm Remove a credential
Expand Down
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0.4.0
1 change: 1 addition & 0 deletions backends/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ type Client interface {
Load() ([]byte, error)
Save([]byte) error
Backup() error
SafeLocation() string
}

func New(config *Config) (Client, error) {
Expand Down
4 changes: 4 additions & 0 deletions backends/disk.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ func (db *DiskBackend) Save(data []byte) error {
return nil
}

func (db *DiskBackend) SafeLocation() string {
return db.path
}

func (f fileInfoSlice) Len() int {
return len(f)
}
Expand Down
4 changes: 4 additions & 0 deletions backends/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,7 @@ func (b *mockBackend) Save(ciphertext []byte) error {
b.Data = ciphertext
return nil
}

func (b *mockBackend) SafeLocation() string {
return "mock-safe-location"
}
51 changes: 22 additions & 29 deletions commands/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,64 +2,66 @@ package commands

import (
"fmt"
"os"

"github.com/bndw/pick/errors"
"github.com/bndw/pick/strings"
"github.com/bndw/pick/utils"
"github.com/bndw/pick/utils/pswdgen"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

func init() {
rootCmd.AddCommand(&cobra.Command{
Use: "add [name] [username] [password]",
Short: "Add a credential",
Long: `The add command is used to add a new credential.
`,
Long: "The add command is used to add a new credential.",
Run: func(cmd *cobra.Command, args []string) {
os.Exit(Add(args...))
runCommand(Add, cmd, args)
},
})
}

func Add(args ...string) int {
safe, err := loadSafe()
func Add(args []string, flags *pflag.FlagSet) error {
safe, err := newSafeLoader().Load()
if err != nil {
return handleError(err)
return err
}

name, username, password, errCode := parseAddArgs(args)
if errCode > 0 {
return errCode
name, username, password, err := parseAddArgs(args)
if err != nil {
return err
}

account, err := safe.Add(name, username, password)
if _, conflict := err.(*errors.AccountExists); conflict && overwrite(name) {
var replaceErr error
if account, replaceErr = safe.Replace(name, username, password); replaceErr != nil {
return handleError(replaceErr)
var editErr error
if account, editErr = safe.Edit(name, username, password); editErr != nil {
return editErr
}
} else if err != nil {
return handleError(err)
return err
}

fmt.Println("Credential added")
if utils.Confirm("Copy password to clipboard", true) {
if err := utils.CopyToClipboard(account.Password); err != nil {
return handleError(err)
return err
}
fmt.Println(strings.PasswordCopiedToClipboard)
}
return 0
return nil
}

func overwrite(name string) bool {
prompt := fmt.Sprintf("%s already exists, overwrite", name)
return utils.Confirm(prompt, false)
}

func parseAddArgs(args []string) (name, username, password string, errCode int) {
func parseAddArgs(args []string) (name, username, password string, err error) {
if len(args) > 3 {
fmt.Println("Usage: add [name] [username] [password]")
return "", "", "", 1
err = &errors.InvalidCommandUsage{}
return
}

switch len(args) {
Expand All @@ -73,41 +75,32 @@ func parseAddArgs(args []string) (name, username, password string, errCode int)
name = args[0]
}

errCode = 1
var err error

if name == "" {
if name, err = utils.GetInput("Enter a credential name"); err != nil {
fmt.Println(err)
return
}
}

if username == "" {
if username, err = utils.GetInput(fmt.Sprintf("Enter a username for %s", name)); err != nil {
fmt.Println(err)
return
}
}

if password == "" {
if utils.Confirm("Generate password", true) {
password, err = utils.GeneratePassword(config.General.PasswordLen)
if err != nil {
fmt.Println(err)
if password, err = pswdgen.Generate(config.General.Password); err != nil {
return
}
} else {
var _password []byte
if _password, err = utils.GetPasswordInput(fmt.Sprintf("Enter a password for %s", name)); err != nil {
fmt.Println(err)
return
}

password = string(_password)
}
}

errCode = 0
return
}
15 changes: 7 additions & 8 deletions commands/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,33 @@ package commands

import (
"fmt"
"os"

"github.com/bndw/pick/safe"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

func init() {
rootCmd.AddCommand(&cobra.Command{
Use: "backup",
Short: "Backup the safe",
Long: `The backup command is used to backup your current safe.
`,
Long: "The backup command is used to backup your current safe.",
Run: func(cmd *cobra.Command, args []string) {
os.Exit(Backup(args...))
runCommand(Backup, cmd, args)
},
})
}

func Backup(args ...string) int {
func Backup(args []string, flags *pflag.FlagSet) error {
backendClient, err := newBackendClient()
if err != nil {
return handleError(err)
return err
}

if err := safe.Backup(backendClient); err != nil {
return handleError(err)
return err
}

fmt.Println("Backup created")
return 0
return nil
}
84 changes: 61 additions & 23 deletions commands/cat.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,45 +2,83 @@ package commands

import (
"fmt"
"os"

"github.com/bndw/pick/errors"
"github.com/bndw/pick/safe"
"github.com/bndw/pick/utils"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

func init() {
rootCmd.AddCommand(&cobra.Command{
cmd := &cobra.Command{
Use: "cat [name]",
Short: "Cat a credential",
Long: `The cat command is used to print a credential to stdout.
`,
Long: "The cat command is used to print a credential to stdout.",
Run: func(cmd *cobra.Command, args []string) {
if len(args) != 1 {
fmt.Println("USAGE: cat [name]")
os.Exit(1)
}

os.Exit(Cat(args...))
runCommand(Cat, cmd, args)
},
})
}
cmd.Flags().Bool("history", false, "show credential history")
rootCmd.AddCommand(cmd)
}

func printAccount(name string, account *safe.Account, showHistory bool) {
// Print header
if showHistory && account.History != nil {
history := account.History
account.History = nil
history = append(history, *account)
for i, l := 0, len(history); i < l; i++ {
printCredential(&history[i], " ", i == 0)
}
} else {
// Print a credential
printCredential(account, "", true)
}
}

func printCredential(account *safe.Account, printPrefix string, isInitialAccount bool) {
// Print a credential
var createdOrModified string
if isInitialAccount {
createdOrModified = "created"
} else {
createdOrModified = "modified"
}
fmt.Printf("%s: %s\n%susername: %s\n%spassword: %s\n",
createdOrModified,
utils.FormatUnixTime(account.ModifiedOn),
printPrefix, account.Username,
printPrefix, account.Password)
}

func Cat(args ...string) int {
safe, err := loadSafe()
func Cat(args []string, flags *pflag.FlagSet) error {
if len(args) != 1 {
return &errors.InvalidCommandUsage{}
}
name := args[0]

showHistory, err := parseCatFlags(flags)
if err != nil {
return handleError(err)
return err
}

account, err := safe.Get(args[0])
safe, err := newSafeLoader().Load()
if err != nil {
return handleError(err)
return err
}

fmt.Printf(`account: %s
username: %s
password: %s
created: %s
`, account.Name, account.Username, account.Password,
utils.FormatUnixTime(account.CreatedOn))
return 0
account, err := safe.Get(name)
if err != nil {
return err
}

printAccount(name, account, showHistory)
return nil
}

func parseCatFlags(flags *pflag.FlagSet) (showHistory bool, err error) {
showHistory, err = flags.GetBool("history")
return
}
Loading

0 comments on commit 4ca6cb4

Please sign in to comment.