Home

go-spectre @617f47d33789267b7dfe86670d23e10fd74a7875 - refs - log -
-
https://git.jolheiser.com/go-spectre.git
Go implementation for spectre/masterpassword
go-spectre / cmd / spectre / main.go
- raw
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package main

import (
	"flag"
	"fmt"
	"os"
	"strings"

	"go.jolheiser.com/go-spectre"
)

func main() {
	pw, err := doMain(os.Args[1:])
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(pw)
}

func doMain(args []string) (string, error) {
	fs := flag.NewFlagSet("spectre", flag.ExitOnError)
	fs.Usage = func() {
		fmt.Fprintln(fs.Output(), "spectre [FLAGS] [site]")
		fs.PrintDefaults()
	}
	usernameFlag := fs.String("username", "", "username")
	secretFlag := fs.String("secret", "", "secret")
	counterFlag := fs.Int("counter", 1, "counter")
	scoperFlag := fs.String("scoper", "com.lyndir.masterpassword", "scoper base")
	scopeFlag := spectre.Authentication
	fs.Func("scope", "scope", func(s string) (err error) {
		scopeFlag, err = spectre.ParseScope(s)
		return
	})
	var templateFlag spectre.Template
	fs.Func("template", "template", func(s string) (err error) {
		templateFlag, err = spectre.ParseTemplate(s)
		return
	})

	if err := fs.Parse(args); err != nil {
		return "", err
	}
	if err := checkEnv(fs); err != nil {
		return "", err
	}

	if templateFlag == "" {
		templateFlag = scopeFlag.DefaultTemplate()
	}

	if *usernameFlag == "" || *secretFlag == "" || fs.NArg() < 1 {
		return "", requiredArgs{
			missingUsername: *usernameFlag == "",
			missingSecret:   *secretFlag == "",
			missingSite:     fs.NArg() < 1,
		}
	}

	s, err := spectre.New(*usernameFlag, *secretFlag, spectre.WithScoper(spectre.SimpleScoper{
		Key: *scoperFlag,
	}))
	if err != nil {
		return "", err
	}

	return s.Site(fs.Arg(0),
		spectre.WithScope(scopeFlag),
		spectre.WithTemplate(templateFlag),
		spectre.WithCounter(*counterFlag),
	), nil
}

type requiredArgs struct {
	missingUsername bool
	missingSecret   bool
	missingSite     bool
}

func (r requiredArgs) Error() string {
	s := "--username, --secret, and <site-name> are required, missing: "
	if r.missingUsername {
		s += "\n- username"
	}
	if r.missingSecret {
		s += "\n- secret"
	}
	if r.missingSite {
		s += "\n- site name"
	}
	return s
}

func checkEnv(fs *flag.FlagSet) error {
	provided := map[string]struct{}{}
	fs.Visit(func(f *flag.Flag) {
		provided[f.Name] = struct{}{}
	})
	var visitErr error
	fs.VisitAll(func(f *flag.Flag) {
		if visitErr != nil {
			return
		}
		if _, ok := provided[f.Name]; ok {
			return
		}
		env := os.Getenv(fmt.Sprintf("SPECTRE_%s", strings.ToUpper(f.Name)))
		if env == "" {
			return
		}
		if err := fs.Set(f.Name, env); err != nil {
			visitErr = fmt.Errorf("could not set flag %q to %q", f.Name, env)
		}
	})
	return nil
}