@cryptotaxi247 / kubo / commits / 3a68d6395

key cmd: refactor to use coreapi

License: MIT Signed-off-by: Łukasz Magiera <magik6k@gmail.com>

Łukasz Magiera committed Aug 3, 2018 at 16:46 UTC 3a68d6395a9e524efedee8a4e2697d356fbedb9f
2 files changed +72 -220
core/commands/keystore.go
+71 -219
@@ -1,20 +1,15 @@
1 package commands
2
3 import (
4 - "bytes"
5 - "crypto/rand"
4 "fmt"
5 "io"
8 - "sort"
9 - "strings"
6 "text/tabwriter"
7
12 - cmds "github.com/ipfs/go-ipfs/commands"
13 - e "github.com/ipfs/go-ipfs/core/commands/e"
8 + "github.com/ipfs/go-ipfs/core/commands/e"
9 + "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
10
11 + "gx/ipfs/QmNueRyPRQiV7PUEpnP4GgGLuK1rKQLaRW7sfPvUetYig1/go-ipfs-cmds"
12 "gx/ipfs/QmdE4gMduCKCGAcczM2F5ioYDfdeKuPix138wrES1YSr7f/go-ipfs-cmdkit"
16 - peer "gx/ipfs/QmdVrMn1LhB4ybb8hMVaMLXnA8XRSewMnK6YqXKXoTcRvN/go-libp2p-peer"
17 - ci "gx/ipfs/Qme1knMqwt1hKZbc1BmQFmnm9f36nyQGwXxPGVpVJ9rMK5/go-libp2p-crypto"
13 )
14
15 var KeyCmd = &cmds.Command{
@@ -70,99 +65,54 @@ var keyGenCmd = &cmds.Command{
65 Arguments: []cmdkit.Argument{
66 cmdkit.StringArg("name", true, false, "name of key to create"),
67 },
73 - Run: func(req cmds.Request, res cmds.Response) {
74 - n, err := req.InvocContext().GetNode()
75 - if err != nil {
76 - res.SetError(err, cmdkit.ErrNormal)
77 - return
78 - }
79 -
80 - typ, f, err := req.Option("type").String()
68 + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) {
69 + api, err := GetApi(env)
70 if err != nil {
71 res.SetError(err, cmdkit.ErrNormal)
72 return
73 }
74
75 + typ, f := req.Options["type"].(string)
76 if !f {
77 res.SetError(fmt.Errorf("please specify a key type with --type"), cmdkit.ErrNormal)
78 return
79 }
80
91 - size, sizefound, err := req.Option("size").Int()
92 - if err != nil {
93 - res.SetError(err, cmdkit.ErrNormal)
94 - return
95 - }
96 -
97 - name := req.Arguments()[0]
81 + name := req.Arguments[0]
82 if name == "self" {
83 res.SetError(fmt.Errorf("cannot create key with name 'self'"), cmdkit.ErrNormal)
84 return
85 }
86
103 - var sk ci.PrivKey
104 - var pk ci.PubKey
105 -
106 - switch typ {
107 - case "rsa":
108 - if !sizefound {
109 - res.SetError(fmt.Errorf("please specify a key size with --size"), cmdkit.ErrNormal)
110 - return
111 - }
87 + opts := []options.KeyGenerateOption{options.Key.Type(typ)}
88
113 - priv, pub, err := ci.GenerateKeyPairWithReader(ci.RSA, size, rand.Reader)
114 - if err != nil {
115 - res.SetError(err, cmdkit.ErrNormal)
116 - return
117 - }
118 -
119 - sk = priv
120 - pk = pub
121 - case "ed25519":
122 - priv, pub, err := ci.GenerateEd25519Key(rand.Reader)
123 - if err != nil {
124 - res.SetError(err, cmdkit.ErrNormal)
125 - return
126 - }
127 -
128 - sk = priv
129 - pk = pub
130 - default:
131 - res.SetError(fmt.Errorf("unrecognized key type: %s", typ), cmdkit.ErrNormal)
132 - return
89 + size, sizefound := req.Options["size"].(int)
90 + if sizefound {
91 + opts = append(opts, options.Key.Size(size))
92 }
93
135 - err = n.Repo.Keystore().Put(name, sk)
136 - if err != nil {
137 - res.SetError(err, cmdkit.ErrNormal)
138 - return
139 - }
94 + key, err := api.Key().Generate(req.Context, name, opts...)
95
141 - pid, err := peer.IDFromPublicKey(pk)
96 if err != nil {
97 res.SetError(err, cmdkit.ErrNormal)
98 return
99 }
100
147 - res.SetOutput(&KeyOutput{
101 + cmds.EmitOnce(res, &KeyOutput{
102 Name: name,
149 - Id: pid.Pretty(),
103 + Id: key.Id().Pretty(),
104 })
105 },
152 - Marshalers: cmds.MarshalerMap{
153 - cmds.Text: func(res cmds.Response) (io.Reader, error) {
154 - v, err := unwrapOutput(res.Output())
155 - if err != nil {
156 - return nil, err
157 - }
158 -
106 + Encoders: cmds.EncoderMap{
107 + cmds.Text: cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error {
108 k, ok := v.(*KeyOutput)
109 if !ok {
161 - return nil, e.TypeErr(k, v)
110 + return e.TypeErr(k, v)
111 }
112
164 - return strings.NewReader(k.Id + "\n"), nil
165 - },
113 + _, err := w.Write([]byte(k.Id + "\n"))
114 + return err
115 + }),
116 },
117 Type: KeyOutput{},
118 }
@@ -174,47 +124,29 @@ var keyListCmd = &cmds.Command{
124 Options: []cmdkit.Option{
125 cmdkit.BoolOption("l", "Show extra information about keys."),
126 },
177 - Run: func(req cmds.Request, res cmds.Response) {
178 - n, err := req.InvocContext().GetNode()
127 + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) {
128 + api, err := GetApi(env)
129 if err != nil {
130 res.SetError(err, cmdkit.ErrNormal)
131 return
132 }
133
184 - keys, err := n.Repo.Keystore().List()
134 + keys, err := api.Key().List(req.Context)
135 if err != nil {
136 res.SetError(err, cmdkit.ErrNormal)
137 return
138 }
139
190 - sort.Strings(keys)
191 -
192 - list := make([]KeyOutput, 0, len(keys)+1)
193 -
194 - list = append(list, KeyOutput{Name: "self", Id: n.Identity.Pretty()})
140 + list := make([]KeyOutput, 0, len(keys))
141
142 for _, key := range keys {
197 - privKey, err := n.Repo.Keystore().Get(key)
198 - if err != nil {
199 - res.SetError(err, cmdkit.ErrNormal)
200 - return
201 - }
202 -
203 - pubKey := privKey.GetPublic()
204 -
205 - pid, err := peer.IDFromPublicKey(pubKey)
206 - if err != nil {
207 - res.SetError(err, cmdkit.ErrNormal)
208 - return
209 - }
210 -
211 - list = append(list, KeyOutput{Name: key, Id: pid.Pretty()})
143 + list = append(list, KeyOutput{Name: key.Name(), Id: key.Id().Pretty()})
144 }
145
214 - res.SetOutput(&KeyOutputList{list})
146 + cmds.EmitOnce(res, &KeyOutputList{list})
147 },
216 - Marshalers: cmds.MarshalerMap{
217 - cmds.Text: keyOutputListMarshaler,
148 + Encoders: cmds.EncoderMap{
149 + cmds.Text: keyOutputListMarshaler(),
150 },
151 Type: KeyOutputList{},
152 }
@@ -230,100 +162,44 @@ var keyRenameCmd = &cmds.Command{
162 Options: []cmdkit.Option{
163 cmdkit.BoolOption("force", "f", "Allow to overwrite an existing key."),
164 },
233 - Run: func(req cmds.Request, res cmds.Response) {
234 - n, err := req.InvocContext().GetNode()
235 - if err != nil {
236 - res.SetError(err, cmdkit.ErrNormal)
237 - return
238 - }
239 -
240 - ks := n.Repo.Keystore()
241 -
242 - name := req.Arguments()[0]
243 - newName := req.Arguments()[1]
244 -
245 - if name == "self" {
246 - res.SetError(fmt.Errorf("cannot rename key with name 'self'"), cmdkit.ErrNormal)
247 - return
248 - }
249 -
250 - if newName == "self" {
251 - res.SetError(fmt.Errorf("cannot overwrite key with name 'self'"), cmdkit.ErrNormal)
252 - return
253 - }
254 -
255 - oldKey, err := ks.Get(name)
256 - if err != nil {
257 - res.SetError(fmt.Errorf("no key named %s was found", name), cmdkit.ErrNormal)
258 - return
259 - }
260 -
261 - pubKey := oldKey.GetPublic()
262 -
263 - pid, err := peer.IDFromPublicKey(pubKey)
165 + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) {
166 + api, err := GetApi(env)
167 if err != nil {
168 res.SetError(err, cmdkit.ErrNormal)
169 return
170 }
171
269 - overwrite := false
270 - force, _, _ := res.Request().Option("f").Bool()
271 - if force {
272 - exist, err := ks.Has(newName)
273 - if err != nil {
274 - res.SetError(err, cmdkit.ErrNormal)
275 - return
276 - }
277 -
278 - if exist {
279 - overwrite = true
280 - err := ks.Delete(newName)
281 - if err != nil {
282 - res.SetError(err, cmdkit.ErrNormal)
283 - return
284 - }
285 - }
286 - }
172 + name := req.Arguments[0]
173 + newName := req.Arguments[1]
174 + force := req.Options["force"].(bool)
175
288 - err = ks.Put(newName, oldKey)
176 + key, overwritten, err := api.Key().Rename(req.Context, name, newName, options.Key.Force(force))
177 if err != nil {
178 res.SetError(err, cmdkit.ErrNormal)
179 return
180 }
181
294 - err = ks.Delete(name)
295 - if err != nil {
296 - res.SetError(err, cmdkit.ErrNormal)
297 - return
298 - }
299 -
300 - res.SetOutput(&KeyRenameOutput{
182 + cmds.EmitOnce(res, &KeyRenameOutput{
183 Was: name,
184 Now: newName,
303 - Id: pid.Pretty(),
304 - Overwrite: overwrite,
185 + Id: key.Id().Pretty(),
186 + Overwrite: overwritten,
187 })
188 },
307 - Marshalers: cmds.MarshalerMap{
308 - cmds.Text: func(res cmds.Response) (io.Reader, error) {
309 - v, err := unwrapOutput(res.Output())
310 - if err != nil {
311 - return nil, err
312 - }
189 + Encoders: cmds.EncoderMap{
190 + cmds.Text: cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error {
191 k, ok := v.(*KeyRenameOutput)
192 if !ok {
315 - return nil, fmt.Errorf("expected a KeyRenameOutput as command result")
193 + return fmt.Errorf("expected a KeyRenameOutput as command result")
194 }
195
318 - buf := new(bytes.Buffer)
319 -
196 if k.Overwrite {
321 - fmt.Fprintf(buf, "Key %s renamed to %s with overwriting\n", k.Id, k.Now)
197 + fmt.Fprintf(w, "Key %s renamed to %s with overwriting\n", k.Id, k.Now)
198 } else {
323 - fmt.Fprintf(buf, "Key %s renamed to %s\n", k.Id, k.Now)
199 + fmt.Fprintf(w, "Key %s renamed to %s\n", k.Id, k.Now)
200 }
325 - return buf, nil
326 - },
201 + return nil
202 + }),
203 },
204 Type: KeyRenameOutput{},
205 }
@@ -338,76 +214,52 @@ var keyRmCmd = &cmds.Command{
214 Options: []cmdkit.Option{
215 cmdkit.BoolOption("l", "Show extra information about keys."),
216 },
341 - Run: func(req cmds.Request, res cmds.Response) {
342 - n, err := req.InvocContext().GetNode()
217 + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) {
218 + api, err := GetApi(env)
219 if err != nil {
220 res.SetError(err, cmdkit.ErrNormal)
221 return
222 }
223
348 - names := req.Arguments()
224 + names := req.Arguments
225
226 list := make([]KeyOutput, 0, len(names))
227 for _, name := range names {
352 - if name == "self" {
353 - res.SetError(fmt.Errorf("cannot remove key with name 'self'"), cmdkit.ErrNormal)
354 - return
355 - }
356 -
357 - removed, err := n.Repo.Keystore().Get(name)
358 - if err != nil {
359 - res.SetError(fmt.Errorf("no key named %s was found", name), cmdkit.ErrNormal)
360 - return
361 - }
362 -
363 - pubKey := removed.GetPublic()
364 -
365 - pid, err := peer.IDFromPublicKey(pubKey)
228 + key, err := api.Key().Remove(req.Context, name)
229 if err != nil {
230 res.SetError(err, cmdkit.ErrNormal)
231 return
232 }
233
371 - list = append(list, KeyOutput{Name: name, Id: pid.Pretty()})
234 + list = append(list, KeyOutput{Name: name, Id: key.Id().Pretty()})
235 }
236
374 - for _, name := range names {
375 - err = n.Repo.Keystore().Delete(name)
376 - if err != nil {
377 - res.SetError(err, cmdkit.ErrNormal)
378 - return
379 - }
380 - }
381 -
382 - res.SetOutput(&KeyOutputList{list})
237 + cmds.EmitOnce(res, &KeyOutputList{list})
238 },
384 - Marshalers: cmds.MarshalerMap{
385 - cmds.Text: keyOutputListMarshaler,
239 + Encoders: cmds.EncoderMap{
240 + cmds.Text: keyOutputListMarshaler(),
241 },
242 Type: KeyOutputList{},
243 }
244
390 -func keyOutputListMarshaler(res cmds.Response) (io.Reader, error) {
391 - withId, _, _ := res.Request().Option("l").Bool()
392 -
393 - v, err := unwrapOutput(res.Output())
394 - if err != nil {
395 - return nil, err
396 - }
397 - list, ok := v.(*KeyOutputList)
398 - if !ok {
399 - return nil, e.TypeErr(list, v)
400 - }
401 -
402 - buf := new(bytes.Buffer)
403 - w := tabwriter.NewWriter(buf, 1, 2, 1, ' ', 0)
404 - for _, s := range list.Keys {
405 - if withId {
406 - fmt.Fprintf(w, "%s\t%s\t\n", s.Id, s.Name)
407 - } else {
408 - fmt.Fprintf(w, "%s\n", s.Name)
245 +func keyOutputListMarshaler() cmds.EncoderFunc {
246 + return cmds.MakeEncoder(func(req *cmds.Request, w io.Writer, v interface{}) error {
247 + withId, _ := req.Options["l"].(bool)
248 +
249 + list, ok := v.(*KeyOutputList)
250 + if !ok {
251 + return e.TypeErr(list, v)
252 + }
253 +
254 + tw := tabwriter.NewWriter(w, 1, 2, 1, ' ', 0)
255 + for _, s := range list.Keys {
256 + if withId {
257 + fmt.Fprintf(tw, "%s\t%s\t\n", s.Id, s.Name)
258 + } else {
259 + fmt.Fprintf(tw, "%s\n", s.Name)
260 + }
261 }
410 - }
411 - w.Flush()
412 - return buf, nil
262 + tw.Flush()
263 + return nil
264 + })
265 }
core/commands/root.go
+1 -1
@@ -121,7 +121,7 @@ var rootSubcommands = map[string]*cmds.Command{
121 "diag": lgc.NewCommand(DiagCmd),
122 "dns": lgc.NewCommand(DNSCmd),
123 "id": lgc.NewCommand(IDCmd),
124 - "key": lgc.NewCommand(KeyCmd),
124 + "key": KeyCmd,
125 "log": lgc.NewCommand(LogCmd),
126 "ls": lgc.NewCommand(LsCmd),
127 "mount": lgc.NewCommand(MountCmd),