1 package credentials
2
3 import (
4 "bufio"
5 "bytes"
6 "encoding/json"
7 "fmt"
8 "io"
9 "os"
10 "strings"
11 )
12
13
14
15
16 type Action = string
17
18
19 const (
20 ActionStore Action = "store"
21 ActionGet Action = "get"
22 ActionErase Action = "erase"
23 ActionList Action = "list"
24 ActionVersion Action = "version"
25 )
26
27
28 type Credentials struct {
29 ServerURL string
30 Username string
31 Secret string
32 }
33
34
35
36
37
38 func (c *Credentials) isValid() (bool, error) {
39 if len(c.ServerURL) == 0 {
40 return false, NewErrCredentialsMissingServerURL()
41 }
42
43 if len(c.Username) == 0 {
44 return false, NewErrCredentialsMissingUsername()
45 }
46
47 return true, nil
48 }
49
50
51
52
53 var CredsLabel = "Docker Credentials"
54
55
56 func SetCredsLabel(label string) {
57 CredsLabel = label
58 }
59
60
61
62
63
64
65 func Serve(helper Helper) {
66 if len(os.Args) != 2 {
67 _, _ = fmt.Fprintln(os.Stdout, usage())
68 os.Exit(1)
69 }
70
71 switch os.Args[1] {
72 case "--version", "-v":
73 _ = PrintVersion(os.Stdout)
74 os.Exit(0)
75 case "--help", "-h":
76 _, _ = fmt.Fprintln(os.Stdout, usage())
77 os.Exit(0)
78 }
79
80 if err := HandleCommand(helper, os.Args[1], os.Stdin, os.Stdout); err != nil {
81 _, _ = fmt.Fprintln(os.Stdout, err)
82 os.Exit(1)
83 }
84 }
85
86 func usage() string {
87 return fmt.Sprintf("Usage: %s <store|get|erase|list|version>", Name)
88 }
89
90
91 func HandleCommand(helper Helper, action Action, in io.Reader, out io.Writer) error {
92 switch action {
93 case ActionStore:
94 return Store(helper, in)
95 case ActionGet:
96 return Get(helper, in, out)
97 case ActionErase:
98 return Erase(helper, in)
99 case ActionList:
100 return List(helper, out)
101 case ActionVersion:
102 return PrintVersion(out)
103 default:
104 return fmt.Errorf("%s: unknown action: %s", Name, action)
105 }
106 }
107
108
109
110 func Store(helper Helper, reader io.Reader) error {
111 scanner := bufio.NewScanner(reader)
112
113 buffer := new(bytes.Buffer)
114 for scanner.Scan() {
115 buffer.Write(scanner.Bytes())
116 }
117
118 if err := scanner.Err(); err != nil && err != io.EOF {
119 return err
120 }
121
122 var creds Credentials
123 if err := json.NewDecoder(buffer).Decode(&creds); err != nil {
124 return err
125 }
126
127 if ok, err := creds.isValid(); !ok {
128 return err
129 }
130
131 return helper.Add(&creds)
132 }
133
134
135
136
137 func Get(helper Helper, reader io.Reader, writer io.Writer) error {
138 scanner := bufio.NewScanner(reader)
139
140 buffer := new(bytes.Buffer)
141 for scanner.Scan() {
142 buffer.Write(scanner.Bytes())
143 }
144
145 if err := scanner.Err(); err != nil && err != io.EOF {
146 return err
147 }
148
149 serverURL := strings.TrimSpace(buffer.String())
150 if len(serverURL) == 0 {
151 return NewErrCredentialsMissingServerURL()
152 }
153
154 username, secret, err := helper.Get(serverURL)
155 if err != nil {
156 return err
157 }
158
159 buffer.Reset()
160 err = json.NewEncoder(buffer).Encode(Credentials{
161 ServerURL: serverURL,
162 Username: username,
163 Secret: secret,
164 })
165 if err != nil {
166 return err
167 }
168
169 _, _ = fmt.Fprint(writer, buffer.String())
170 return nil
171 }
172
173
174
175 func Erase(helper Helper, reader io.Reader) error {
176 scanner := bufio.NewScanner(reader)
177
178 buffer := new(bytes.Buffer)
179 for scanner.Scan() {
180 buffer.Write(scanner.Bytes())
181 }
182
183 if err := scanner.Err(); err != nil && err != io.EOF {
184 return err
185 }
186
187 serverURL := strings.TrimSpace(buffer.String())
188 if len(serverURL) == 0 {
189 return NewErrCredentialsMissingServerURL()
190 }
191
192 return helper.Delete(serverURL)
193 }
194
195
196
197 func List(helper Helper, writer io.Writer) error {
198 accts, err := helper.List()
199 if err != nil {
200 return err
201 }
202 return json.NewEncoder(writer).Encode(accts)
203 }
204
205
206 func PrintVersion(writer io.Writer) error {
207 _, _ = fmt.Fprintf(writer, "%s (%s) %s\n", Name, Package, Version)
208 return nil
209 }
210
View as plain text