1 | module.exports = owner
|
2 |
|
3 | owner.usage = "npm owner add <username> <pkg>"
|
4 | + "\nnpm owner rm <username> <pkg>"
|
5 | + "\nnpm owner ls <pkg>"
|
6 |
|
7 | var npm = require("./npm.js")
|
8 | , log = require("npmlog")
|
9 | , mapToRegistry = require("./utils/map-to-registry.js")
|
10 | , readLocalPkg = require("./utils/read-local-package.js")
|
11 |
|
12 | owner.completion = function (opts, cb) {
|
13 | var argv = opts.conf.argv.remain
|
14 | if (argv.length > 4) return cb()
|
15 | if (argv.length <= 2) {
|
16 | var subs = ["add", "rm"]
|
17 | if (opts.partialWord === "l") subs.push("ls")
|
18 | else subs.push("ls", "list")
|
19 | return cb(null, subs)
|
20 | }
|
21 |
|
22 | npm.commands.whoami([], true, function (er, username) {
|
23 | if (er) return cb()
|
24 |
|
25 | var un = encodeURIComponent(username)
|
26 | var byUser, theUser
|
27 | switch (argv[2]) {
|
28 | case "ls":
|
29 | if (argv.length > 3) return cb()
|
30 | return mapToRegistry("-/short", npm.config, function (er, uri, auth) {
|
31 | if (er) return cb(er)
|
32 |
|
33 | npm.registry.get(uri, { auth : auth }, cb)
|
34 | })
|
35 |
|
36 | case "rm":
|
37 | if (argv.length > 3) {
|
38 | theUser = encodeURIComponent(argv[3])
|
39 | byUser = "-/by-user/" + theUser + "|" + un
|
40 | return mapToRegistry(byUser, npm.config, function (er, uri, auth) {
|
41 | if (er) return cb(er)
|
42 |
|
43 | console.error(uri)
|
44 | npm.registry.get(uri, { auth : auth }, function (er, d) {
|
45 | if (er) return cb(er)
|
46 |
|
47 | return cb(null, d[theUser].filter(function (p) {
|
48 |
|
49 | return un === "isaacs" || d[un].indexOf(p) === -1
|
50 | }))
|
51 | })
|
52 | })
|
53 | }
|
54 |
|
55 | case "add":
|
56 | if (argv.length > 3) {
|
57 | theUser = encodeURIComponent(argv[3])
|
58 | byUser = "-/by-user/" + theUser + "|" + un
|
59 | return mapToRegistry(byUser, npm.config, function (er, uri, auth) {
|
60 | if (er) return cb(er)
|
61 |
|
62 | console.error(uri)
|
63 | npm.registry.get(uri, { auth : auth }, function (er, d) {
|
64 | console.error(uri, er || d)
|
65 |
|
66 | if (er) return cb(er)
|
67 | var mine = d[un] || []
|
68 | , theirs = d[theUser] || []
|
69 | return cb(null, mine.filter(function (p) {
|
70 | return theirs.indexOf(p) === -1
|
71 | }))
|
72 | })
|
73 | })
|
74 | }
|
75 |
|
76 | return mapToRegistry("-/users", npm.config, function (er, uri, auth) {
|
77 | if (er) return cb(er)
|
78 |
|
79 | npm.registry.get(uri, { auth : auth }, function (er, list) {
|
80 | if (er) return cb()
|
81 | return cb(null, Object.keys(list).filter(function (n) {
|
82 | return n !== un
|
83 | }))
|
84 | })
|
85 | })
|
86 |
|
87 | default:
|
88 | return cb()
|
89 | }
|
90 | })
|
91 | }
|
92 |
|
93 | function owner (args, cb) {
|
94 | var action = args.shift()
|
95 | switch (action) {
|
96 | case "ls": case "list": return ls(args[0], cb)
|
97 | case "add": return add(args[0], args[1], cb)
|
98 | case "rm": case "remove": return rm(args[0], args[1], cb)
|
99 | default: return unknown(action, cb)
|
100 | }
|
101 | }
|
102 |
|
103 | function ls (pkg, cb) {
|
104 | if (!pkg) return readLocalPkg(function (er, pkg) {
|
105 | if (er) return cb(er)
|
106 | if (!pkg) return cb(owner.usage)
|
107 | ls(pkg, cb)
|
108 | })
|
109 |
|
110 | mapToRegistry(pkg, npm.config, function (er, uri, auth) {
|
111 | if (er) return cb(er)
|
112 |
|
113 | npm.registry.get(uri, { auth : auth }, function (er, data) {
|
114 | var msg = ""
|
115 | if (er) {
|
116 | log.error("owner ls", "Couldn't get owner data", pkg)
|
117 | return cb(er)
|
118 | }
|
119 | var owners = data.maintainers
|
120 | if (!owners || !owners.length) msg = "admin party!"
|
121 | else msg = owners.map(function (o) {
|
122 | return o.name + " <" + o.email + ">"
|
123 | }).join("\n")
|
124 | console.log(msg)
|
125 | cb(er, owners)
|
126 | })
|
127 | })
|
128 | }
|
129 |
|
130 | function add (user, pkg, cb) {
|
131 | if (!user) return cb(owner.usage)
|
132 | if (!pkg) return readLocalPkg(function (er, pkg) {
|
133 | if (er) return cb(er)
|
134 | if (!pkg) return cb(new Error(owner.usage))
|
135 | add(user, pkg, cb)
|
136 | })
|
137 |
|
138 | log.verbose("owner add", "%s to %s", user, pkg)
|
139 | mutate(pkg, user, function (u, owners) {
|
140 | if (!owners) owners = []
|
141 | for (var i = 0, l = owners.length; i < l; i ++) {
|
142 | var o = owners[i]
|
143 | if (o.name === u.name) {
|
144 | log.info( "owner add"
|
145 | , "Already a package owner: " + o.name + " <" + o.email + ">")
|
146 | return false
|
147 | }
|
148 | }
|
149 | owners.push(u)
|
150 | return owners
|
151 | }, cb)
|
152 | }
|
153 |
|
154 | function rm (user, pkg, cb) {
|
155 | if (!pkg) return readLocalPkg(function (er, pkg) {
|
156 | if (er) return cb(er)
|
157 | if (!pkg) return cb(new Error(owner.usage))
|
158 | rm(user, pkg, cb)
|
159 | })
|
160 |
|
161 | log.verbose("owner rm", "%s from %s", user, pkg)
|
162 | mutate(pkg, user, function (u, owners) {
|
163 | var found = false
|
164 | , m = owners.filter(function (o) {
|
165 | var match = (o.name === user)
|
166 | found = found || match
|
167 | return !match
|
168 | })
|
169 | if (!found) {
|
170 | log.info("owner rm", "Not a package owner: " + user)
|
171 | return false
|
172 | }
|
173 | if (!m.length) return new Error(
|
174 | "Cannot remove all owners of a package. Add someone else first.")
|
175 | return m
|
176 | }, cb)
|
177 | }
|
178 |
|
179 | function mutate (pkg, user, mutation, cb) {
|
180 | if (user) {
|
181 | var byUser = "-/user/org.couchdb.user:" + user
|
182 | mapToRegistry(byUser, npm.config, function (er, uri, auth) {
|
183 | if (er) return cb(er)
|
184 |
|
185 | npm.registry.get(uri, { auth : auth }, mutate_)
|
186 | })
|
187 | } else {
|
188 | mutate_(null, null)
|
189 | }
|
190 |
|
191 | function mutate_ (er, u) {
|
192 | if (!er && user && (!u || u.error)) er = new Error(
|
193 | "Couldn't get user data for " + user + ": " + JSON.stringify(u))
|
194 |
|
195 | if (er) {
|
196 | log.error("owner mutate", "Error getting user data for %s", user)
|
197 | return cb(er)
|
198 | }
|
199 |
|
200 | if (u) u = { "name" : u.name, "email" : u.email }
|
201 | mapToRegistry(pkg, npm.config, function (er, uri, auth) {
|
202 | if (er) return cb(er)
|
203 |
|
204 | npm.registry.get(uri, { auth : auth }, function (er, data) {
|
205 | if (er) {
|
206 | log.error("owner mutate", "Error getting package data for %s", pkg)
|
207 | return cb(er)
|
208 | }
|
209 |
|
210 |
|
211 |
|
212 | var beforeMutation = data.maintainers.length
|
213 |
|
214 | var m = mutation(u, data.maintainers)
|
215 | if (!m) return cb()
|
216 | if (m instanceof Error) return cb(m)
|
217 |
|
218 | data = {
|
219 | _id : data._id,
|
220 | _rev : data._rev,
|
221 | maintainers : m
|
222 | }
|
223 | var dataPath = pkg.replace("/", "%2f") + "/-rev/" + data._rev
|
224 | mapToRegistry(dataPath, npm.config, function (er, uri, auth) {
|
225 | if (er) return cb(er)
|
226 |
|
227 | var params = {
|
228 | method : "PUT",
|
229 | body : data,
|
230 | auth : auth
|
231 | }
|
232 | npm.registry.request(uri, params, function (er, data) {
|
233 | if (!er && data.error) {
|
234 | er = new Error("Failed to update package metadata: "+JSON.stringify(data))
|
235 | }
|
236 |
|
237 | if (er) {
|
238 | log.error("owner mutate", "Failed to update package metadata")
|
239 | }
|
240 | else if (m.length > beforeMutation) {
|
241 | console.log("+ %s (%s)", user, pkg)
|
242 | }
|
243 | else if (m.length < beforeMutation) {
|
244 | console.log("- %s (%s)", user, pkg)
|
245 | }
|
246 |
|
247 | cb(er, data)
|
248 | })
|
249 | })
|
250 | })
|
251 | })
|
252 | }
|
253 | }
|
254 |
|
255 | function unknown (action, cb) {
|
256 | cb("Usage: \n" + owner.usage)
|
257 | }
|