Skip to content

Commit

Permalink
add npm access command, with 1/3 of its features
Browse files Browse the repository at this point in the history
  • Loading branch information
othiym23 committed Jan 23, 2015
1 parent e9f8ab3 commit c963eb2
Show file tree
Hide file tree
Showing 4 changed files with 221 additions and 4 deletions.
123 changes: 123 additions & 0 deletions lib/access.js
Original file line number Diff line number Diff line change
@@ -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!"))
}
10 changes: 6 additions & 4 deletions lib/config/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -119,7 +119,8 @@ Object.defineProperty(exports, "defaults", {get: function () {
}

defaults = {
"always-auth" : false
access : "restricted"
, "always-auth" : false
, "bin-links" : true
, browser : null

Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions lib/npm.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ var commandCache = {}
, "adduser"
, "unpublish"
, "owner"
, "access"
, "deprecate"
, "shrinkwrap"

Expand Down
91 changes: 91 additions & 0 deletions test/tap/access.js
Original file line number Diff line number Diff line change
@@ -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()
})

0 comments on commit c963eb2

Please sign in to comment.