name.go 5.99 KB
Newer Older
1 2 3 4 5 6 7
package commands

import (
	"errors"
	"fmt"

	cmds "github.com/jbenet/go-ipfs/commands"
Brian Tiger Chow's avatar
Brian Tiger Chow committed
8 9
	core "github.com/jbenet/go-ipfs/core"
	crypto "github.com/jbenet/go-ipfs/crypto"
10 11 12 13
	nsys "github.com/jbenet/go-ipfs/namesys"
	u "github.com/jbenet/go-ipfs/util"
)

14
type IpnsEntry struct {
Brian Tiger Chow's avatar
Brian Tiger Chow committed
15 16
	Name  string
	Value string
17 18
}

19 20 21 22
type ResolveOutput struct {
	Entries []IpnsEntry
}

23 24
var errNotOnline = errors.New("This command must be run in online mode. Try running 'ipfs daemon' first.")

25
var nameCmd = &cmds.Command{
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
	// TODO UsageLine: "name [publish | resolve]",
	// TODO Short:     "ipfs namespace (ipns) tool",
	Help: `ipfs name - Get/Set ipfs config values.

    ipfs name publish [<name>] <ref>  - Assign the <ref> to <name>
    ipfs name resolve [<name>]        - Resolve the <ref> value of <name>

IPNS is a PKI namespace, where names are the hashes of public keys, and
the private key enables publishing new (signed) values. In both publish
and resolve, the default value of <name> is your own identity public key.


Examples:

Publish a <ref> to your identity name:

  > ipfs name publish QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
  published name QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n to QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy

Publish a <ref> to another public key:

  > ipfs name publish QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
  published name QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n to QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy

Resolve the value of your identity:

  > ipfs name resolve
  QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy

Resolve te value of another name:

  > ipfs name resolve QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n
  QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy

`,
61 62 63 64 65 66
	Subcommands: map[string]*cmds.Command{
		"publish": publishCmd,
		"resolve": resolveCmd,
	},
}

67
var publishCmd = &cmds.Command{
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
	// TODO UsageLine: "publish",
	// TODO Short:     "publish a <ref> to ipns.",
	Help: `ipfs publish [<name>] <ref> - publish a <ref> to ipns.

IPNS is a PKI namespace, where names are the hashes of public keys, and
the private key enables publishing new (signed) values. In publish, the
default value of <name> is your own identity public key.

Examples:

Publish a <ref> to your identity name:

  > ipfs name publish QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
  published name QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n to QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy

Publish a <ref> to another public key:

  > ipfs name publish QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
  published name QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n to QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy

`,
89 90 91 92
	Arguments: []cmds.Argument{
		cmds.Argument{"name", cmds.ArgString, false, false},
		cmds.Argument{"object", cmds.ArgString, true, false},
	},
93 94 95 96
	Run: func(res cmds.Response, req cmds.Request) {
		n := req.Context().Node
		args := req.Arguments()

97 98 99 100 101
		if n.Network == nil {
			res.SetError(errNotOnline, cmds.ErrNormal)
			return
		}

102 103 104 105 106 107 108 109 110 111 112
		if n.Identity == nil {
			res.SetError(errors.New("Identity not loaded!"), cmds.ErrNormal)
			return
		}

		// name := ""
		ref := ""

		switch len(args) {
		case 2:
			// name = args[0]
113
			ref = args[1].(string)
114 115 116 117
			res.SetError(errors.New("keychains not yet implemented"), cmds.ErrNormal)
			return
		case 1:
			// name = n.Identity.ID.String()
118
			ref = args[0].(string)
119 120
		}

Brian Tiger Chow's avatar
Brian Tiger Chow committed
121 122 123
		// TODO n.Keychain.Get(name).PrivKey
		k := n.Identity.PrivKey()
		publishOutput, err := publish(n, k, ref)
124 125 126 127 128

		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
129
		res.SetOutput(publishOutput)
130
	},
131 132
	Marshallers: map[cmds.EncodingType]cmds.Marshaller{
		cmds.Text: func(res cmds.Response) ([]byte, error) {
133
			v := res.Output().(*IpnsEntry)
134 135 136
			s := fmt.Sprintf("Published name %s to %s\n", v.Name, v.Value)
			return []byte(s), nil
		},
137
	},
138
	Type: &IpnsEntry{},
139
}
Brian Tiger Chow's avatar
Brian Tiger Chow committed
140

141
var resolveCmd = &cmds.Command{
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
	// TODO UsageLine: "resolve",
	// TODO Short:     "resolve an ipns name to a <ref>",
	Help: `ipfs resolve [<name>] - Resolve an ipns name to a <ref>.

IPNS is a PKI namespace, where names are the hashes of public keys, and
the private key enables publishing new (signed) values. In resolve, the
default value of <name> is your own identity public key.


Examples:

Resolve the value of your identity:

  > ipfs name resolve
  QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy

Resolve te value of another name:

  > ipfs name resolve QmbCMUZw6JFeZ7Wp9jkzbye3Fzp2GGcPgC3nmeUjfVF87n
  QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy

`,

165 166 167 168
	Arguments: []cmds.Argument{
		cmds.Argument{"name", cmds.ArgString, false, true},
	},
	Run: func(res cmds.Response, req cmds.Request) {
169

170
		n := req.Context().Node
171
		var names []string
172

173 174 175 176 177
		if n.Network == nil {
			res.SetError(errNotOnline, cmds.ErrNormal)
			return
		}

178
		if len(req.Arguments()) == 0 {
179 180 181 182
			if n.Identity == nil {
				res.SetError(errors.New("Identity not loaded!"), cmds.ErrNormal)
				return
			}
183
			names = append(names, n.Identity.ID().String())
184
		} else {
185 186
			for _, arg := range req.Arguments() {
				name, ok := arg.(string)
187 188 189 190
				if !ok {
					res.SetError(errors.New("cast error"), cmds.ErrNormal)
					return
				}
191
				names = append(names, name)
192 193 194
			}
		}

195 196 197 198 199 200 201
		entries, err := resolve(n, names)
		if err != nil {
			res.SetError(err, cmds.ErrNormal)
			return
		}

		res.SetOutput(&ResolveOutput{entries})
202 203 204 205
	},
	Type: &ResolveOutput{},
}

206
func publish(n *core.IpfsNode, k crypto.PrivKey, ref string) (*IpnsEntry, error) {
Brian Tiger Chow's avatar
Brian Tiger Chow committed
207 208 209 210 211 212 213 214 215 216 217
	pub := nsys.NewRoutingPublisher(n.Routing)
	err := pub.Publish(k, ref)
	if err != nil {
		return nil, err
	}

	hash, err := k.GetPublic().Hash()
	if err != nil {
		return nil, err
	}

218
	return &IpnsEntry{
Brian Tiger Chow's avatar
Brian Tiger Chow committed
219 220 221 222
		Name:  u.Key(hash).String(),
		Value: ref,
	}, nil
}
223

224 225 226 227 228 229 230 231 232 233 234
func resolve(n *core.IpfsNode, names []string) ([]IpnsEntry, error) {
	var entries []IpnsEntry
	for _, name := range names {
		resolved, err := n.Namesys.Resolve(name)
		if err != nil {
			return nil, err
		}
		entries = append(entries, IpnsEntry{
			Name:  name,
			Value: resolved,
		})
235
	}
236
	return entries, nil
237
}