publish module flow finish #11
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -12,4 +12,5 @@ logs
|
||||
results
|
||||
|
||||
node_modules
|
||||
npm-debug.log
|
||||
npm-debug.log
|
||||
public/dist/
|
||||
@@ -4,3 +4,5 @@ lib-cov/
|
||||
Makefile
|
||||
.travis.yml
|
||||
logo.png
|
||||
.tmp/
|
||||
public/dist/
|
||||
16
common/nfs.js
Normal file
16
common/nfs.js
Normal file
@@ -0,0 +1,16 @@
|
||||
/*!
|
||||
* cnpmjs.org - common/nfs.js
|
||||
*
|
||||
* Copyright(c) cnpmjs.org and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
* Authors:
|
||||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
@@ -45,12 +45,12 @@ var config = {
|
||||
mysqlQueryTimeout: 5000,
|
||||
|
||||
sessionSecret: 'cnpmjs.org test session secret',
|
||||
|
||||
redis: {
|
||||
host: 'pub-redis-19533.us-east-1-4.3.ec2.garantiadata.com',
|
||||
port: 19533,
|
||||
pass: 'cnpmjs_dev'
|
||||
}
|
||||
},
|
||||
uploadDir: path.join(root, 'public', 'dist'),
|
||||
};
|
||||
|
||||
// load config/config.js, everything in config.js will cover the same key in index.js
|
||||
@@ -63,5 +63,6 @@ if (fs.existsSync(customConfig)) {
|
||||
}
|
||||
|
||||
mkdirp.sync(config.logdir);
|
||||
mkdirp.sync(config.uploadDir);
|
||||
|
||||
module.exports = config;
|
||||
|
||||
@@ -15,26 +15,243 @@
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var MOCK_MODULE_DATA = {
|
||||
_id: 'mock',
|
||||
_rev: '3-mock',
|
||||
name: 'mock',
|
||||
description: 'mock module',
|
||||
versions: {
|
||||
'0.0.0': {}
|
||||
}
|
||||
var debug = require('debug')('cnpmjs.org:controllers:registry:module');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var crypto = require('crypto');
|
||||
var config = require('../../config');
|
||||
var Module = require('../../proxy/module');
|
||||
|
||||
exports.show = function (req, res, next) {
|
||||
var name = req.params.name;
|
||||
Module.listByName(name, function (err, rows) {
|
||||
if (err || rows.length === 0) {
|
||||
return next(err);
|
||||
}
|
||||
var latest;
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var row = rows[i];
|
||||
if (row.version === 'latest') {
|
||||
latest = row;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!latest) {
|
||||
return next();
|
||||
}
|
||||
|
||||
var distTags = {};
|
||||
var versions = {};
|
||||
var times = {};
|
||||
var attachments = {};
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
var row = rows[i];
|
||||
var pkg = row.package;
|
||||
if (!pkg.version || pkg.version === 'latest') {
|
||||
continue;
|
||||
}
|
||||
|
||||
versions[pkg.version] = pkg;
|
||||
times[pkg.version] = row.gmt_modified;
|
||||
}
|
||||
|
||||
if (latest.package.version || latest.package.version !== 'init') {
|
||||
distTags['latest'] = latest.package.version;
|
||||
}
|
||||
|
||||
var info = {
|
||||
_id: latest.name,
|
||||
_rev: String(latest.id),
|
||||
name: latest.name,
|
||||
description: latest.package.description,
|
||||
versions: versions,
|
||||
"dist-tags": distTags,
|
||||
readme: latest.package.readme,
|
||||
maintainers: latest.package.maintainers,
|
||||
time: times,
|
||||
author: latest.package.author,
|
||||
repository: latest.package.repository,
|
||||
_attachments: attachments
|
||||
};
|
||||
|
||||
res.json(info);
|
||||
});
|
||||
};
|
||||
|
||||
exports.show = function (req, res) {
|
||||
res.json(MOCK_MODULE_DATA);
|
||||
exports.upload = function (req, res, next) {
|
||||
var length = Number(req.headers['content-length']) || 0;
|
||||
if (!length || req.headers['content-type'] !== 'application/octet-stream') {
|
||||
return next();
|
||||
}
|
||||
|
||||
var username = req.session.name;
|
||||
var name = req.params.name;
|
||||
var id = Number(req.params.rev);
|
||||
var filename = req.params.filename;
|
||||
|
||||
debug('%s: upload %s, file size: %d', username, req.url, length);
|
||||
Module.getById(id, function (err, mod) {
|
||||
if (err || !mod) {
|
||||
return next(err);
|
||||
}
|
||||
var match = mod.package.maintainers.filter(function (item) {
|
||||
return item.name === username;
|
||||
});
|
||||
if (match.length === 0 || mod.name !== name) {
|
||||
return res.json(401, {
|
||||
error: 'noperms',
|
||||
reason: 'Current user can not publish this module'
|
||||
});
|
||||
}
|
||||
|
||||
var filepath = path.join(config.uploadDir, filename);
|
||||
var ws = fs.createWriteStream(filepath);
|
||||
var shasum = crypto.createHash('sha1');
|
||||
req.pipe(ws);
|
||||
var dataSize = 0;
|
||||
req.on('data', function (data) {
|
||||
shasum.update(data);
|
||||
dataSize += data.length;
|
||||
});
|
||||
ws.on('finish', function () {
|
||||
if (dataSize !== length) {
|
||||
return res.json(401, {
|
||||
error: 'wrongsize',
|
||||
reason: 'Header size ' + length + ' not match download size ' + dataSize,
|
||||
});
|
||||
}
|
||||
shasum = shasum.digest('hex');
|
||||
var dist = {
|
||||
tarball: 'http://' + req.headers.host + '/dist/' + filename,
|
||||
shasum: shasum,
|
||||
size: length
|
||||
};
|
||||
mod.package.dist = dist;
|
||||
debug('%s module: save file to %s, size: %d, sha1: %s, dist: %j', id, filepath, length, shasum, dist);
|
||||
Module.update(mod, function (err, result) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
res.json(201, {ok: true, rev: String(result.id), date: result.gmt_modified});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.add = function (req, res) {
|
||||
var params = req.params;
|
||||
if (params.module === 'exist') {
|
||||
res.statusCode = 409;
|
||||
return res.json( { error: 'conflict', reason: 'Document update conflict.' });
|
||||
}
|
||||
res.statusCode = 201;
|
||||
res.end();
|
||||
exports.updateLatest = function (req, res, next) {
|
||||
var username = req.session.name;
|
||||
var name = req.params.name;
|
||||
var version = req.params.version;
|
||||
Module.get(name, 'latest', function (err, mod) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
if (!mod) {
|
||||
return next();
|
||||
}
|
||||
var match = mod.package.maintainers.filter(function (item) {
|
||||
return item.name === username;
|
||||
});
|
||||
if (match.length === 0) {
|
||||
return res.json(401, {
|
||||
error: 'noperms',
|
||||
reason: 'Current user can not publish this module'
|
||||
});
|
||||
}
|
||||
|
||||
var body = req.body;
|
||||
|
||||
mod.version = version;
|
||||
mod.author = username;
|
||||
body.dist = mod.package.dist;
|
||||
body.maintainers = mod.package.maintainers;
|
||||
if (!body.author) {
|
||||
body.author = {
|
||||
name: username,
|
||||
email: req.session.email,
|
||||
};
|
||||
}
|
||||
mod.package = body;
|
||||
debug('update %s:%s %j', mod.package.name, mod.package.version, mod.package.dist);
|
||||
// change latest to version
|
||||
Module.update(mod, function (err) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
// add a new latest version
|
||||
mod.version = 'latest';
|
||||
Module.add(mod, function (err, result) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
res.json(201, {ok: true, rev: String(result.id), date: result.gmt_modified});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.add = function (req, res, next) {
|
||||
var username = req.session.name;
|
||||
var name = req.params.name;
|
||||
var pkg = req.body;
|
||||
var maintainers = pkg.maintainers || [];
|
||||
var match = maintainers.filter(function (item) {
|
||||
return item.name === username;
|
||||
});
|
||||
if (match.length === 0) {
|
||||
return res.json(401, {
|
||||
error: 'noperms',
|
||||
reason: 'Current user can not publish this module'
|
||||
});
|
||||
}
|
||||
|
||||
Module.get(name, 'latest', function (err, mod) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
if (mod) {
|
||||
match = mod.package.maintainers.filter(function (item) {
|
||||
return item.name === username;
|
||||
});
|
||||
if (match.length === 0) {
|
||||
return res.json(401, {
|
||||
error: 'noperms',
|
||||
reason: 'Current user can not publish this module'
|
||||
});
|
||||
}
|
||||
|
||||
return res.json(409, {
|
||||
error: 'conflict',
|
||||
reason: 'Document update conflict.'
|
||||
});
|
||||
}
|
||||
|
||||
mod = {
|
||||
name: name,
|
||||
version: 'latest',
|
||||
author: username,
|
||||
package: {
|
||||
name: name,
|
||||
version: 'init',
|
||||
description: pkg.description,
|
||||
readme: pkg.readme,
|
||||
maintainers: pkg.maintainers,
|
||||
author: {
|
||||
name: username,
|
||||
email: req.session.email,
|
||||
}
|
||||
},
|
||||
};
|
||||
Module.add(mod, function (err, result) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
res.json(201, {
|
||||
ok: true,
|
||||
id: name,
|
||||
rev: String(result.id),
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@@ -21,8 +21,7 @@ var User = require('../../proxy/user');
|
||||
var eventproxy = require('eventproxy');
|
||||
|
||||
exports.show = function (req, res, next) {
|
||||
var name = req.params.name || '';
|
||||
name = name.split(':')[1];
|
||||
var name = req.params.name;
|
||||
User.get(name, function (err, row) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
@@ -55,12 +54,7 @@ exports.show = function (req, res, next) {
|
||||
// roles: [],
|
||||
// date: '2013-12-04T12:56:13.714Z' } }
|
||||
exports.add = function (req, res, next) {
|
||||
var name = req.params.name || '';
|
||||
name = name.split(':')[1];
|
||||
if (!name) {
|
||||
return next();
|
||||
}
|
||||
|
||||
var name = req.params.name;
|
||||
var body = req.body || {};
|
||||
var user = {
|
||||
name: body.name,
|
||||
@@ -121,8 +115,7 @@ exports.authSession = function (req, res, next) {
|
||||
};
|
||||
|
||||
exports.update = function (req, res, next) {
|
||||
var name = req.params.name || '';
|
||||
name = name.split(':')[1];
|
||||
var name = req.params.name;
|
||||
var rev = req.params.rev;
|
||||
if (!name || !rev) {
|
||||
return next();
|
||||
|
||||
17
docs/db.sql
17
docs/db.sql
@@ -14,3 +14,20 @@ CREATE TABLE `user` (
|
||||
KEY `gmt_modified` (`gmt_modified`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='user base info';
|
||||
|
||||
CREATE TABLE `module` (
|
||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'primary key',
|
||||
`gmt_create` datetime NOT NULL COMMENT 'create time',
|
||||
`gmt_modified` datetime NOT NULL COMMENT 'modified time',
|
||||
`author` varchar(100) NOT NULL,
|
||||
`name` varchar(100) NOT NULL COMMENT 'module name',
|
||||
`version` varchar(30) NOT NULL COMMENT 'module version',
|
||||
`package` longtext COMMENT 'package.json',
|
||||
`dist_shasum` varchar(100) DEFAULT NULL,
|
||||
`dist_tarball` varchar(2048) DEFAULT NULL,
|
||||
`dist_size` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `name` (`name`,`version`),
|
||||
KEY `gmt_modified` (`gmt_modified`),
|
||||
KEY `author` (`author`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=25 DEFAULT CHARSET=utf8 COMMENT='module info'
|
||||
|
||||
|
||||
100
docs/pkg.json
Normal file
100
docs/pkg.json
Normal file
@@ -0,0 +1,100 @@
|
||||
{
|
||||
"_id": "cnpmjs.org",
|
||||
"_rev": "3-c3267f3804042445ff9b708fb0f276cb",
|
||||
"name": "cnpmjs.org",
|
||||
"description": "cnpmjs.org",
|
||||
"dist-tags": {
|
||||
"latest": "0.0.0"
|
||||
},
|
||||
"versions": {
|
||||
"0.0.0": {
|
||||
"name": "cnpmjs.org",
|
||||
"version": "0.0.0",
|
||||
"description": "cnpmjs.org",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "make test-all"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"should": "*",
|
||||
"blanket": "*",
|
||||
"travis-cov": "*",
|
||||
"coveralls": "*",
|
||||
"mocha-lcov-reporter": "*",
|
||||
"mocha": "*"
|
||||
},
|
||||
"homepage": "https://github.com/fengmk2/cnpmjs.org",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/fengmk2/cnpmjs.org.git",
|
||||
"web": "https://github.com/fengmk2/cnpmjs.org"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/fengmk2/cnpmjs.org/issues",
|
||||
"email": "fengmk2@gmail.com"
|
||||
},
|
||||
"keywords": [
|
||||
"cnpmjs.org"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
},
|
||||
"author": {
|
||||
"name": "fengmk2",
|
||||
"email": "fengmk2@gmail.com",
|
||||
"url": "http://fengmk2.github.com"
|
||||
},
|
||||
"license": "MIT",
|
||||
"readme": "cnpmjs.org\n=======\n\n[](http://travis-ci.org/fengmk2/cnpmjs.org) [](https://coveralls.io/r/fengmk2/cnpmjs.org) [](https://drone.io/github.com/fengmk2/cnpmjs.org/latest)\n\n[](https://nodei.co/npm/cnpmjs.org/)\n\n\n\ncnpmjs.org desc\n\n## Install\n\n```bash\n$ npm install cnpmjs.org\n```\n\n## Usage\n\n```js\nvar cnpmjs.org = require('cnpmjs.org');\n\ncnpmjs.org.foo(function (err) {\n\n});\n```\n\n## License\n\n(The MIT License)\n\nCopyright (c) 2013 fengmk2 <fengmk2@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
|
||||
"readmeFilename": "README.md",
|
||||
"_id": "cnpmjs.org@0.0.0",
|
||||
"dist": {
|
||||
"shasum": "6da265fb14b151f6b9f4b77967dd90fddfdea1f2",
|
||||
"tarball": "http://registry.npmjs.org/cnpmjs.org/-/cnpmjs.org-0.0.0.tgz"
|
||||
},
|
||||
"_from": ".",
|
||||
"_npmVersion": "1.3.14",
|
||||
"_npmUser": {
|
||||
"name": "fengmk2",
|
||||
"email": "fengmk2@gmail.com"
|
||||
},
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "fengmk2",
|
||||
"email": "fengmk2@gmail.com"
|
||||
}
|
||||
],
|
||||
"directories": {}
|
||||
}
|
||||
},
|
||||
"readme": "cnpmjs.org\n=======\n\n[](http://travis-ci.org/fengmk2/cnpmjs.org) [](https://coveralls.io/r/fengmk2/cnpmjs.org) [](https://drone.io/github.com/fengmk2/cnpmjs.org/latest)\n\n[](https://nodei.co/npm/cnpmjs.org/)\n\n\n\ncnpmjs.org desc\n\n## Install\n\n```bash\n$ npm install cnpmjs.org\n```\n\n## Usage\n\n```js\nvar cnpmjs.org = require('cnpmjs.org');\n\ncnpmjs.org.foo(function (err) {\n\n});\n```\n\n## License\n\n(The MIT License)\n\nCopyright (c) 2013 fengmk2 <fengmk2@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n",
|
||||
"maintainers": [
|
||||
{
|
||||
"name": "fengmk2",
|
||||
"email": "fengmk2@gmail.com"
|
||||
}
|
||||
],
|
||||
"time": {
|
||||
"0.0.0": "2013-12-03T09:58:24.368Z"
|
||||
},
|
||||
"author": {
|
||||
"name": "fengmk2",
|
||||
"email": "fengmk2@gmail.com",
|
||||
"url": "http://fengmk2.github.com"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/fengmk2/cnpmjs.org.git",
|
||||
"web": "https://github.com/fengmk2/cnpmjs.org"
|
||||
},
|
||||
"_attachments": {
|
||||
"cnpmjs.org-0.0.0.tgz": {
|
||||
"content_type": "application/octet-stream",
|
||||
"revpos": 2,
|
||||
"digest": "md5-UCSYBJ+CbiLETV2tAXTryw==",
|
||||
"length": 1822,
|
||||
"stub": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ if (authRequired && !this.conf.get('always-auth')) {
|
||||
}
|
||||
```
|
||||
|
||||
* put full data to `https://registry.npmjs.org/packagename`
|
||||
* put full data with AuthSession to `https://registry.npmjs.org/packagename`
|
||||
|
||||
```
|
||||
var fullData =
|
||||
@@ -54,7 +54,13 @@ npm http PUT https://registry.npmjs.org/cnpmjs.org
|
||||
npm http 201 https://registry.npmjs.org/cnpmjs.org
|
||||
```
|
||||
|
||||
* get data to check exists versions
|
||||
* 409 or 201
|
||||
|
||||
```
|
||||
{ error: 'conflict', reason: 'Document update conflict.' }
|
||||
```
|
||||
|
||||
* get data (with auth header) to check exists versions
|
||||
|
||||
```
|
||||
npm http GET https://registry.npmjs.org/cnpmjs.org
|
||||
|
||||
@@ -19,7 +19,7 @@ var User = require('../proxy/user');
|
||||
|
||||
module.exports = function (options) {
|
||||
return function auth(req, res, next) {
|
||||
if (req.session.name) {
|
||||
if (req.session.name && req.session.email) {
|
||||
return next();
|
||||
}
|
||||
var authorization = (req.headers.authorization || '').split(' ')[1] || '';
|
||||
@@ -35,6 +35,7 @@ module.exports = function (options) {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
if (!row) {
|
||||
debug('auth fail user: %j, headers: %j', row, req.headers);
|
||||
return res.json(401, {
|
||||
@@ -42,7 +43,9 @@ module.exports = function (options) {
|
||||
reason: 'Name or password is incorrect.'
|
||||
});
|
||||
}
|
||||
|
||||
req.session.name = row.name;
|
||||
req.session.email = row.email;
|
||||
debug('auth pass user: %j, headers: %j', row, req.headers);
|
||||
next();
|
||||
});
|
||||
|
||||
25
middleware/login.js
Normal file
25
middleware/login.js
Normal file
@@ -0,0 +1,25 @@
|
||||
/*!
|
||||
* cnpmjs.org - middleware/login.js
|
||||
*
|
||||
* Copyright(c) cnpmjs.org and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
* Authors:
|
||||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
module.exports = function login(req, res, next) {
|
||||
if (!req.session.name) {
|
||||
return res.json(401, {
|
||||
error: 'unauthorized',
|
||||
reason: 'Login first.'
|
||||
});
|
||||
}
|
||||
next();
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cnpmjs.org",
|
||||
"version": "0.0.0",
|
||||
"version": "0.0.2",
|
||||
"description": "Private npm registry and web",
|
||||
"main": "dispatch.js",
|
||||
"scripts": {
|
||||
|
||||
140
proxy/module.js
Normal file
140
proxy/module.js
Normal file
@@ -0,0 +1,140 @@
|
||||
/**!
|
||||
* cnpmjs.org - proxy/module.js
|
||||
*
|
||||
* Copyright(c) cnpmjs.org and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
* Authors:
|
||||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var utility = require('utility');
|
||||
var config = require('../config');
|
||||
var mysql = require('../common/mysql');
|
||||
|
||||
var MODULE_COLUMNS = 'id, gmt_create, gmt_modified, author, name, version, package, dist_tarball, dist_shasum, dist_size';
|
||||
|
||||
var INSERT_MODULE_SQL = 'INSERT INTO module(gmt_create, gmt_modified, author, name, version, package, dist_tarball, dist_shasum, dist_size) \
|
||||
VALUES(now(), now(), ?, ?, ?, ?, ?, ?, ?);';
|
||||
|
||||
exports.add = function (mod, callback) {
|
||||
var pkg;
|
||||
try {
|
||||
pkg = JSON.stringify(mod.package);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
var dist = mod.package.dist || {};
|
||||
dist.tarball = '';
|
||||
dist.shasum = '';
|
||||
dist.size = 0;
|
||||
var values = [mod.author, mod.name, mod.version, pkg, dist.tarball, dist.shasum, dist.size];
|
||||
mysql.query(INSERT_MODULE_SQL, values, function (err, result) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
callback(null, {id: result.insertId, gmt_modified: new Date()});
|
||||
});
|
||||
};
|
||||
|
||||
var UPDATE_DIST_SQL = 'UPDATE module SET version=?, package=?, dist_tarball=?, dist_shasum=?, dist_size=? WHERE id=?;';
|
||||
|
||||
exports.update = function (mod, callback) {
|
||||
var pkg;
|
||||
try {
|
||||
pkg = JSON.stringify(mod.package);
|
||||
} catch (e) {
|
||||
return callback(e);
|
||||
}
|
||||
var dist = mod.package.dist;
|
||||
mysql.query(UPDATE_DIST_SQL, [mod.version, pkg, dist.tarball, dist.shasum, dist.size, mod.id],
|
||||
function (err, result) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
callback(null, {id: mod.id, gmt_modified: new Date()});
|
||||
});
|
||||
};
|
||||
|
||||
function parseRow(row) {
|
||||
row.package = JSON.parse(row.package);
|
||||
}
|
||||
|
||||
var SELECT_MODULE_BY_ID_SQL = 'SELECT ' + MODULE_COLUMNS + ' FROM module WHERE id=?;';
|
||||
|
||||
exports.getById = function (id, callback) {
|
||||
id = Number(id);
|
||||
mysql.queryOne(SELECT_MODULE_BY_ID_SQL, [id], function (err, row) {
|
||||
if (err || !row) {
|
||||
return callback(err, row);
|
||||
}
|
||||
try {
|
||||
parseRow(row);
|
||||
} catch (e) {
|
||||
e.data = row;
|
||||
return callback(e);
|
||||
}
|
||||
callback(null, row);
|
||||
});
|
||||
};
|
||||
|
||||
var SELECT_MODULE_SQL = 'SELECT ' + MODULE_COLUMNS + ' FROM module WHERE name=? AND version=?;';
|
||||
|
||||
exports.get = function (name, version, callback) {
|
||||
mysql.queryOne(SELECT_MODULE_SQL, [name, version], function (err, row) {
|
||||
if (err || !row) {
|
||||
return callback(err, row);
|
||||
}
|
||||
try {
|
||||
parseRow(row);
|
||||
} catch (e) {
|
||||
e.data = row;
|
||||
return callback(e);
|
||||
}
|
||||
callback(null, row);
|
||||
});
|
||||
};
|
||||
|
||||
var SELECT_LATEST_MODULE_SQL = 'SELECT ' + MODULE_COLUMNS + ' FROM module WHERE name=? ORDER BY id DESC LIMIT 1;';
|
||||
|
||||
exports.getLatest = function (name, callback) {
|
||||
mysql.queryOne(SELECT_LATEST_MODULE_SQL, [name], function (err, row) {
|
||||
if (err || !row) {
|
||||
return callback(err, row);
|
||||
}
|
||||
try {
|
||||
parseRow(row);
|
||||
} catch (e) {
|
||||
e.data = row;
|
||||
return callback(e);
|
||||
}
|
||||
callback(null, row);
|
||||
});
|
||||
};
|
||||
|
||||
var LIST_MODULE_SQL = 'SELECT ' + MODULE_COLUMNS + ' FROM module WHERE name=? ORDER BY id DESC;';
|
||||
|
||||
exports.listByName = function (name, callback) {
|
||||
mysql.query(LIST_MODULE_SQL, [name], function (err, rows) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
rows = rows || [];
|
||||
try {
|
||||
for (var i = 0; i < rows.length; i++) {
|
||||
parseRow(rows[i]);
|
||||
}
|
||||
} catch (e) {
|
||||
err = e;
|
||||
err.data = rows;
|
||||
}
|
||||
callback(err, rows);
|
||||
});
|
||||
};
|
||||
@@ -15,6 +15,7 @@
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var login = require('../middleware/login');
|
||||
var home = require('../controllers/registry/home');
|
||||
var mod = require('../controllers/registry/module');
|
||||
var pkg = require('../controllers/registry/package');
|
||||
@@ -24,20 +25,21 @@ var user = require('../controllers/registry/user');
|
||||
function routes(app) {
|
||||
app.get('/', home.show);
|
||||
|
||||
// module
|
||||
app.get('/:name', mod.show);
|
||||
app.put('/:name', mod.add);
|
||||
app.put('/:name', login, mod.add);
|
||||
|
||||
// put tarball
|
||||
// https://registry.npmjs.org/cnpmjs.org/-/cnpmjs.org-0.0.0.tgz/-rev/1-c85bc65e8d2470cc4d82b8f40da65b8e
|
||||
app.put('/:name/-/:filename/-rev/:rev', pkg.upload);
|
||||
app.put('/:name/-/:filename/-rev/:rev', login, mod.upload);
|
||||
// tag
|
||||
app.put('/:name/:version/-tag/latest', tag.updateLatest);
|
||||
app.put('/:name/:version/-tag/latest', login, mod.updateLatest);
|
||||
|
||||
//try to create a new user
|
||||
// try to create a new user
|
||||
// https://registry.npmjs.org/-/user/org.couchdb.user:fengmk2
|
||||
app.put('/-/user/:name', user.add);
|
||||
app.get('/-/user/:name', user.show);
|
||||
app.put('/-/user/:name/-rev/:rev', user.update);
|
||||
app.put('/-/user/org.couchdb.user::name', user.add);
|
||||
app.get('/-/user/org.couchdb.user::name', user.show);
|
||||
app.put('/-/user/org.couchdb.user::name/-rev/:rev', login, user.update);
|
||||
|
||||
// _session
|
||||
app.post('/_session', user.authSession);
|
||||
|
||||
@@ -34,12 +34,14 @@ app.use(function (req, res, next) {
|
||||
res.req = req;
|
||||
next();
|
||||
});
|
||||
|
||||
app.use('/dist', connect.static(config.uploadDir));
|
||||
|
||||
app.use(responseCookie());
|
||||
app.use(connect.cookieParser());
|
||||
app.use(session);
|
||||
app.use(connect.query());
|
||||
app.use(connect.bodyParser());
|
||||
|
||||
app.use(connect.json());
|
||||
app.use(session);
|
||||
app.use(auth());
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,7 +35,7 @@ app.use(function (req, res, next) {
|
||||
app.use(connect.cookieParser());
|
||||
app.use(session);
|
||||
app.use(connect.query());
|
||||
app.use(connect.bodyParser());
|
||||
app.use(connect.json());
|
||||
|
||||
/**
|
||||
* Routes
|
||||
|
||||
48
test/controllers/registry/module.test.js
Normal file
48
test/controllers/registry/module.test.js
Normal file
@@ -0,0 +1,48 @@
|
||||
/*!
|
||||
* cnpmjs.org - test/controllers/registry/module.test.js
|
||||
*
|
||||
* Copyright(c) cnpmjs.org and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
* Authors:
|
||||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var should = require('should');
|
||||
var request = require('supertest');
|
||||
var app = require('../../../servers/registry');
|
||||
|
||||
describe('controllers/registry/module.test.js', function () {
|
||||
before(function (done) {
|
||||
app.listen(0, done);
|
||||
});
|
||||
after(function (done) {
|
||||
app.close(done);
|
||||
});
|
||||
|
||||
describe('GET /:name', function () {
|
||||
it('should return module info', function (done) {
|
||||
request(app)
|
||||
.get('/cnpmjs.org')
|
||||
.expect(200, function (err, res) {
|
||||
should.not.exist(err);
|
||||
res.body.should.have.keys('_id', '_rev', 'name', 'description',
|
||||
'versions', 'dist-tags', 'readme', 'maintainers',
|
||||
'time', 'author', 'repository', '_attachments');
|
||||
res.body.author.should.eql({
|
||||
"name": "fengmk2",
|
||||
// "email": "fengmk2@gmail.com",
|
||||
// "url": "http://fengmk2.github.com"
|
||||
});
|
||||
res.body.name.should.equal('cnpmjs.org');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user