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
118
119
120
121
122
123
124
125
|
package main
import (
"flag"
"fmt"
"os"
"strings"
"go.jolheiser.com/go-spectre"
)
func main() {
pw, err := maine(os.Args[1:])
if err != nil {
fmt.Println(err)
return
}
fmt.Println(pw)
}
func maine(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")
fs.StringVar(usernameFlag, "u", *usernameFlag, "--username")
secretFlag := fs.String("secret", "", "secret")
fs.StringVar(secretFlag, "s", *secretFlag, "--secret")
counterFlag := fs.Int("counter", 1, "counter")
fs.IntVar(counterFlag, "c", *counterFlag, "--counter")
baseFlag := fs.String("base", "com.lyndir.masterpassword", "scoper base")
fs.StringVar(baseFlag, "b", *baseFlag, "--base")
scopeFlag := spectre.Authentication
scopeFn := func(s string) (err error) {
scopeFlag, err = spectre.ParseScope(s)
return
}
fs.Func("scope", "scope", scopeFn)
fs.Func("S", "--scope", scopeFn)
var templateFlag spectre.Template
templateFn := func(s string) (err error) {
templateFlag, err = spectre.ParseTemplate(s)
return
}
fs.Func("template", "template", templateFn)
fs.Func("t", "--template", templateFn)
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: *baseFlag,
}))
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
}
|