diff options
author | Forrest L Norvell <ogd@aoaioxxysz.net> | 2015-01-22 02:52:59 +0300 |
---|---|---|
committer | Forrest L Norvell <forrest@npmjs.com> | 2015-01-23 15:51:38 +0300 |
commit | c963eb295cf766921b1680f4a71fd0ed3e1bcad8 (patch) | |
tree | 341c79824ab1a44505231e74efbf73bde20b1230 | |
parent | e9f8ab3cd6324fbf2678132324d4cd8579209442 (diff) |
add `npm access` command, with 1/3 of its features
-rw-r--r-- | lib/access.js | 123 | ||||
-rw-r--r-- | lib/config/defaults.js | 10 | ||||
-rw-r--r-- | lib/npm.js | 1 | ||||
-rw-r--r-- | test/tap/access.js | 91 |
4 files changed, 221 insertions, 4 deletions
diff --git a/lib/access.js b/lib/access.js new file mode 100644 index 000000000..a479a971c --- /dev/null +++ b/lib/access.js @@ -0,0 +1,123 @@ +var assert = require("assert") +var resolve = require("path").resolve +var url = require("url") + +var log = require("npmlog") +var readPackageJson = require("read-package-json") + +var mapToRegistry = require("./utils/map-to-registry.js") +var npa = require("npm-package-arg") +var npm = require("./npm.js") + +module.exports = access + +access.usage = "npm access public [<package>]" + + "\nnpm access restricted [<package>]" + + "\nnpm access add <read-only|read-write> <entity> [<package>]" + + "\nnpm access rm <entity> [<package>]" + + "\nnpm access ls [<package>]" + + "\nnpm access edit [<package>]" + +access.completion = function (opts, cb) { + var argv = opts.conf.argv.remain + if (argv.length === 2) { + return cb(null, ["public", "restricted", "add", "rm", "ls", "edit"]) + } + + switch (argv[2]) { + case "public": + case "restricted": + case "ls": + case "edit": + return cb(new Error("unimplemented: packages you can change")) + case "add": + if (argv.length === 3) return cb(null, ["read-only", "read-write"]) + + return cb(new Error("unimplemented: entities and packages")) + case "rm": + return cb(new Error("unimplemented: entities and packages")) + default: + return cb(new Error(argv[2]+" not recognized")) + } +} + +function access (args, cb) { + var cmd = args.shift() + switch (cmd) { + case "public": case "restricted": return changeAccess(args, cmd, cb) + case "add": case "set": return add(args, cb) + case "rm": case "del": case "clear": return rm(args, cb) + case "list": case "sl": case "ls": return ls(args, cb) + case "edit": case "ed": return edit(args, cb) + default: return cb("Usage:\n"+access.usage) + } +} + +function changeAccess (args, level, cb) { + assert(Array.isArray(args), "changeAccess requires args be an array") + assert( + ["public", "restricted"].indexOf(level) !== -1, + "access level must be either 'public' or 'restricted'" + ) + assert(typeof cb === "function", "changeAccess requires a callback") + + var p = (args.shift() || "").trim() + if (!p) return getCurrentPackage(level, cb) + changeAccess_(p, level, cb) +} + +function getCurrentPackage (level, cb) { + var here = resolve(npm.prefix, "package.json") + log.verbose("setPackageLevel", "here", here) + + readPackageJson(here, function (er, data) { + if (er) return cb(er) + + if (!data.name) { + return cb(new Error("Package must be named")) + } + + changeAccess_(data.name, level, cb) + }) +} + +function changeAccess_ (name, level, cb) { + log.verbose("changeAccess", "name", name, "level", level) + mapToRegistry(name, npm.config, function (er, uri, auth, base) { + if (er) return cb(er) + + var data = npa(name) + if (!data.scope) { + var msg = "Sorry, you can't change the access level of unscoped packages." + log.error("access", msg) + return cb(new Error(msg)) + } + + // name must be scoped, so escape separator + name = name.replace("/", "%2f") + // FIXME: mapToRegistry still isn't generic enough SIGH + uri = url.resolve(base, "-/package/"+name+"/access") + var params = { + level : level, + auth : auth + } + + npm.registry.access(uri, params, cb) + }) +} + +function add (args, cb) { + return cb(new Error("npm access add isn't implemented yet!")) +} + +function rm (args, cb) { + return cb(new Error("npm access rm isn't implemented yet!")) +} + +function ls (args, cb) { + return cb(new Error("npm access ls isn't implemented yet!")) +} + +function edit (args, cb) { + return cb(new Error("npm edit ls isn't implemented yet!")) +} diff --git a/lib/config/defaults.js b/lib/config/defaults.js index 3d99ab86f..0f9c62c69 100644 --- a/lib/config/defaults.js +++ b/lib/config/defaults.js @@ -24,7 +24,7 @@ try { exports.Umask = Umask function Umask () {} function validateUmask (data, k, val) { - return umask.validate (data, k, val) + return umask.validate(data, k, val) } function validateSemver (data, k, val) { @@ -119,7 +119,8 @@ Object.defineProperty(exports, "defaults", {get: function () { } defaults = { - "always-auth" : false + access : "restricted" + , "always-auth" : false , "bin-links" : true , browser : null @@ -228,7 +229,8 @@ Object.defineProperty(exports, "defaults", {get: function () { }}) exports.types = - { "always-auth" : Boolean + { access : ["restricted", "public"] + , "always-auth" : Boolean , "bin-links": Boolean , browser : [null, String] , ca: [null, String, Array] @@ -272,7 +274,7 @@ exports.types = // local-address must be listed as an IP for a local network interface // must be IPv4 due to node bug , "local-address" : getLocalAddresses() - , loglevel : ["silent","error","warn","http","info","verbose","silly"] + , loglevel : ["silent", "error", "warn", "http", "info", "verbose", "silly"] , logstream : Stream , long : Boolean , message: String diff --git a/lib/npm.js b/lib/npm.js index d03ec47b6..28c57712c 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -111,6 +111,7 @@ var commandCache = {} , "adduser" , "unpublish" , "owner" + , "access" , "deprecate" , "shrinkwrap" diff --git a/test/tap/access.js b/test/tap/access.js new file mode 100644 index 000000000..909fdf01a --- /dev/null +++ b/test/tap/access.js @@ -0,0 +1,91 @@ +var fs = require("fs") +var path = require("path") +var mkdirp = require("mkdirp") +var rimraf = require("rimraf") +var mr = require("npm-registry-mock") + +var test = require("tap").test +var common = require("../common-tap.js") + +var pkg = path.resolve(__dirname, "access") +var server + +var scoped = { + name : "@scoped/pkg", + version : "1.1.1" +} + +var body = { + access : "public" +} + +function mocks (server) { + server.post("/-/package/@scoped%2fpkg/access", JSON.stringify(body)) + .reply(200, { "access" : "public" }) + server.post("/-/package/@scoped%2fanother/access", JSON.stringify(body)) + .reply(200, { "access" : "public" }) +} + +test("setup", function (t) { + mkdirp(pkg, function (er) { + t.ifError(er, pkg + " made successfully") + + mr({port : common.port, mocks : mocks}, function (s) { + server = s + + fs.writeFile( + path.join(pkg, "package.json"), + JSON.stringify(scoped), + function (er) { + t.ifError(er, "wrote package.json") + t.end() + } + ) + }) + }) +}) + +test("npm access on current package", function (t) { + common.npm( + [ + "access", + "public", + "--registry", common.registry, + "--loglevel", "silent" + ], + { cwd : pkg }, + function (er, code, stdout, stderr) { + t.ifError(er, "npm access") + t.notOk(code, "exited OK") + t.notOk(stderr, "no error output") + + t.end() + } + ) +}) + +test("npm access on named package", function (t) { + common.npm( + [ + "access", + "public", "@scoped/another", + "--registry", common.registry, + "--loglevel", "silent" + ], + { cwd : pkg }, + function (er, code, stdout, stderr) { + t.ifError(er, "npm access") + t.notOk(code, "exited OK") + t.notOk(stderr, "no error output") + + t.end() + } + ) +}) + +test("cleanup", function (t) { + t.pass("cleaned up") + rimraf.sync(pkg) + server.close() + t.end() +}) |