config file changes

This commit is contained in:
Alex Kocharin 2013-06-13 18:21:14 +04:00
parent dd1bd01b2e
commit a8fa475dc1
9 changed files with 102 additions and 39 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
node_modules
package.json
npm-debug.log

View File

@ -1,45 +1,31 @@
#!/usr/bin/env node
var pkg_file = '../package.yaml';
var fs = require('fs');
var yaml = require('js-yaml');
var commander = require('commander');
var pkg = yaml.safeLoad(fs.readFileSync('../package.yaml', 'utf8'));
var server = require('../lib/index');
var crypto = require('crypto');
var pkg = require(pkg_file);
commander
.option('-l, --listen <[host:]port>', 'host:port number to listen on (default: localhost:4873)', '4873')
.option('-s, --storage <path>', 'path to package cache (default: "~/.npmrepod")')
// todo: need something to do with invalid https certificate, but we just can't use http by default
.option('-u, --uplink <url>', 'parent registry (default: "https://registry.npmjs.org/")')
.option('-c, --config <file.yaml>', 'use this configuration file')
.option('-c, --config <config.yaml>', 'use this configuration file (default: ./config.yaml)')
.version(pkg.version)
.parse(process.argv);
var config;
if (commander.config) {
var config = yaml.safeLoad(fs.readFileSync(commander.config, 'utf8'));
config = yaml.safeLoad(fs.readFileSync(commander.config, 'utf8'));
} else {
var pass = crypto.randomBytes(8).toString('base64').replace(/[=+\/]/g, '');
var config = {
users: {
admin: {
password: crypto.createHash('sha1').update(pass).digest('hex')
},
},
uplinks: {
npmjs: {
url: 'https://registry.npmjs.org/'
},
},
packages: {
'/.*/': {
publish: ['admin'],
access: ['all'],
proxy: ['npmjs'],
}
}
try {
config = yaml.safeLoad(fs.readFileSync('./config.yaml', 'utf8'));
} catch(err) {
var created_config = require('../lib/config_gen')();
config = yaml.safeLoad(created_config.yaml);
console.log('starting with default config, use user: "%s", pass: "%s" to authenticate', created_config.user, created_config.pass);
fs.writeFileSync('./config.yaml', created_config.yaml);
}
console.log('starting with default config, use user: "admin", pass: "%s" to authenticate', pass);
}
if (!config.user_agent) config.user_agent = 'Sinopia/'+pkg.version;

View File

@ -1,4 +1,7 @@
# path to a directory with all packages
storage: ./storage
users:
user1:
# require('crypto').createHash('sha1').update('test').digest('hex')

View File

@ -24,6 +24,7 @@ function Config(config) {
var check_user_or_uplink = function(arg) {
assert(arg !== 'all' || arg !== 'owner', 'CONFIG: reserved user/uplink name: ' + arg);
assert(!arg.match(/\s/), 'CONFIG: invalid user name: ' + arg);
assert(users[arg] == null, 'CONFIG: duplicate user/uplink name: ' + arg);
users[arg] = true;
};
@ -58,10 +59,16 @@ function Config(config) {
for (var i in this.packages) {
var check_userlist = function(i, hash, action) {
if (hash[action] == null) hash[action] = [];
// if it's a string, split it to array
if (typeof(hash[action]) === 'string') {
hash[action] = hash[action].split(/\s+/);
}
assert(
typeof(hash[action]) === 'object' &&
Array.isArray(hash[action])
, 'CONFIG: bad "'+i+'" package '+action+' description (array expected)');
, 'CONFIG: bad "'+i+'" package '+action+' description (array or string expected)');
hash[action] = flatten(hash[action]);
hash[action].forEach(function(user) {
assert(

18
lib/config_def.yaml Normal file
View File

@ -0,0 +1,18 @@
# path to a directory with all packages
storage: ./storage
users:
admin:
# crypto.createHash('sha1').update(pass).digest('hex')
password: __PASSWORD__
uplinks:
npmjs:
url: https://registry.npmjs.org/
packages:
'/.*/':
publish: admin
access: all
proxy: npmjs

16
lib/config_gen.js Normal file
View File

@ -0,0 +1,16 @@
var fs = require('fs');
var crypto = require('crypto');
module.exports = function create_config() {
var pass = crypto.randomBytes(8).toString('base64').replace(/[=+\/]/g, '');
var pass_digest = crypto.createHash('sha1').update(pass).digest('hex');
var config = fs.readFileSync(require.resolve('./config_def.yaml'), 'utf8');
config = config.replace('__PASSWORD__', pass_digest);
return {
yaml: config,
user: 'admin',
pass: pass,
};
}

View File

@ -55,9 +55,23 @@ module.exports = function(config_hash) {
});
});*/
app.get('/:package', can('access'), function(req, res, next) {
// TODO: anonymous user?
app.get('/:package/:version?', can('access'), function(req, res, next) {
storage.get_package(req.params.package, function(err, info) {
if (err) return next(err);
// XXX: in some cases npm calls for /:package and for some cases
// for /:package/:version - should investigate that
if (req.params.version) {
if (info.versions[req.params.version] != null) {
info = info.versions[req.params.version];
} else {
return next(new UError({
status: 404,
msg: 'version not found: ' + req.params.version
}));
}
}
res.send(info);
});
});

View File

@ -1,6 +1,7 @@
var storage = wrap(require('./drivers/fs'));
var UError = require('./error').UserError;
var info_file = 'package.json';
var fs = require('fs');
function wrap(driver) {
if (typeof(driver.create_json) !== 'function') {
@ -24,7 +25,21 @@ function wrap(driver) {
return driver;
}
module.exports.add_package = function(name, metadata, callback) {
function Storage(config) {
if (!(this instanceof Storage)) return new Storage(config);
this.config = config;
try {
fs.mkdirSync(config.storage);
console.log('created new packages directory: ', config.storage);
} catch(err) {
if (err.code !== 'EEXIST') throw new Error(err);
}
return this;
}
Storage.prototype.add_package = function(name, metadata, callback) {
storage.create_json(name + '/' + info_file, metadata, function(err) {
if (err && err.code === 'EEXISTS') {
return callback(new UError({
@ -36,7 +51,7 @@ module.exports.add_package = function(name, metadata, callback) {
});
}
module.exports.add_version = function(name, version, metadata, tag, callback) {
Storage.prototype.add_version = function(name, version, metadata, tag, callback) {
storage.read_json(name + '/' + info_file, function(err, data) {
// TODO: race condition
if (err) return callback(err);
@ -53,7 +68,7 @@ module.exports.add_version = function(name, version, metadata, tag, callback) {
});
}
module.exports.add_tarball = function(name, filename, stream, callback) {
Storage.prototype.add_tarball = function(name, filename, stream, callback) {
if (name === info_file) {
return callback(new UError({
status: 403,
@ -81,7 +96,7 @@ module.exports.add_tarball = function(name, filename, stream, callback) {
});
}
module.exports.get_tarball = function(name, filename, callback) {
Storage.prototype.get_tarball = function(name, filename, callback) {
storage.read(name + '/' + filename, function(err) {
if (err && err.code === 'ENOENT') {
return callback(new UError({
@ -93,7 +108,7 @@ module.exports.get_tarball = function(name, filename, callback) {
});
}
module.exports.get_package = function(name, callback) {
Storage.prototype.get_package = function(name, callback) {
storage.read_json(name + '/' + info_file, function(err) {
if (err && err.code === 'ENOENT') {
return callback(new UError({
@ -105,3 +120,5 @@ module.exports.get_package = function(name, callback) {
});
}
module.exports = Storage;

View File

@ -1,7 +1,7 @@
var async = require('async');
var semver = require('semver');
var UError = require('./error').UserError;
var local = require('./st-local');
var Local = require('./st-local');
var Proxy = require('./st-proxy');
var utils = require('./utils');
@ -13,28 +13,29 @@ function Storage(config) {
for (var p in config.uplinks) {
this.uplinks[p] = new Proxy(p, config);
}
this.local = new Local(config);
return this;
}
Storage.prototype.add_package = function(name, metadata, callback) {
local.add_package(name, metadata, callback);
this.local.add_package(name, metadata, callback);
}
Storage.prototype.add_version = function(name, version, metadata, tag, callback) {
local.add_version(name, version, metadata, tag, callback);
this.local.add_version(name, version, metadata, tag, callback);
}
Storage.prototype.add_tarball = function(name, filename, stream, callback) {
local.add_tarball(name, filename, stream, callback);
this.local.add_tarball(name, filename, stream, callback);
}
Storage.prototype.get_tarball = function(name, filename, callback) {
local.get_tarball(name, filename, callback);
this.local.get_tarball(name, filename, callback);
}
Storage.prototype.get_package = function(name, callback) {
var uplinks = [local];
var uplinks = [this.local];
for (var i in this.uplinks) {
if (this.config.allow_proxy(name, i)) {
uplinks.push(this.uplinks[i]);