Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
764c32646e | ||
|
|
dea16e72de | ||
|
|
7f951a6c5d | ||
|
|
a1f2bc87b7 | ||
|
|
706a5e053b | ||
|
|
eddc1a1bb9 | ||
|
|
6e5abe44b9 | ||
|
|
e6484e7e7b | ||
|
|
7a88fa49d2 | ||
|
|
82189bd393 |
17
History.md
17
History.md
@@ -1,4 +1,21 @@
|
||||
|
||||
1.2.2 / 2014-08-08
|
||||
==================
|
||||
|
||||
* bump koa
|
||||
|
||||
1.2.1 / 2014-08-07
|
||||
==================
|
||||
|
||||
* deprecated bug fix and support undeprecate
|
||||
|
||||
1.2.0 / 2014-08-07
|
||||
==================
|
||||
|
||||
* show deprecated message
|
||||
* Sync deprecated field if it missing
|
||||
* Support $ cnpm deprecate [pkgname]@[version] "message". fixed #415
|
||||
|
||||
1.1.0 / 2014-08-07
|
||||
==================
|
||||
|
||||
|
||||
60
controllers/registry/deprecate.js
Normal file
60
controllers/registry/deprecate.js
Normal file
@@ -0,0 +1,60 @@
|
||||
/**!
|
||||
* cnpmjs.org - controllers/registry/deprecate.js
|
||||
*
|
||||
* Copyright(c) fengmk2 and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
* Authors:
|
||||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var Module = require('../../proxy/module');
|
||||
|
||||
module.exports = deprecateVersions;
|
||||
|
||||
/**
|
||||
* @see https://github.com/cnpm/cnpmjs.org/issues/415
|
||||
*/
|
||||
function* deprecateVersions(next) {
|
||||
var body = this.request.body;
|
||||
var name = this.params.name || this.params[0];
|
||||
|
||||
var tasks = [];
|
||||
for (var version in body.versions) {
|
||||
tasks.push(Module.get(name, version));
|
||||
}
|
||||
var rs = yield tasks;
|
||||
|
||||
var updateTasks = [];
|
||||
for (var i = 0; i < rs.length; i++) {
|
||||
var row = rs[i];
|
||||
if (!row) {
|
||||
// some version not exists
|
||||
this.status = 400;
|
||||
this.body = {
|
||||
error: 'version_error',
|
||||
reason: 'Some versions: ' + JSON.stringify(Object.keys(body.versions)) + ' not found'
|
||||
};
|
||||
return;
|
||||
}
|
||||
var data = body.versions[row.package.version];
|
||||
if (typeof data.deprecated === 'string') {
|
||||
row.package.deprecated = data.deprecated;
|
||||
updateTasks.push(Module.updatePackage(row.id, row.package));
|
||||
}
|
||||
}
|
||||
yield updateTasks;
|
||||
// update last modified
|
||||
yield* Module.updateLastModified(name);
|
||||
|
||||
this.status = 201;
|
||||
this.body = {
|
||||
ok: true
|
||||
};
|
||||
}
|
||||
@@ -41,6 +41,7 @@ var ModuleUnpublished = require('../../proxy/module_unpublished');
|
||||
var packageService = require('../../services/package');
|
||||
var UserService = require('../../services/user');
|
||||
var downloadAsReadStream = require('../utils').downloadAsReadStream;
|
||||
var deprecateVersions = require('./deprecate');
|
||||
|
||||
/**
|
||||
* show all version of a module
|
||||
@@ -431,11 +432,43 @@ exports.addPackageAndDist = function *(next) {
|
||||
var name = this.params.name || this.params[0];
|
||||
var filename = Object.keys(pkg._attachments || {})[0];
|
||||
var version = Object.keys(pkg.versions || {})[0];
|
||||
if (!version || !filename) {
|
||||
if (!version) {
|
||||
this.status = 400;
|
||||
this.body = {
|
||||
error: 'version_error',
|
||||
reason: 'filename or version not found, filename: ' + filename + ', version: ' + version
|
||||
reason: 'version ' + version + ' not found'
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
// check maintainers
|
||||
var isMaintainer = yield* packageService.isMaintainer(name, username);
|
||||
if (!isMaintainer) {
|
||||
this.status = 403;
|
||||
this.body = {
|
||||
error: 'forbidden user',
|
||||
reason: username + ' not authorized to modify ' + name
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
if (!filename) {
|
||||
var hasDeprecated = false;
|
||||
for (var v in pkg.versions) {
|
||||
var row = pkg.versions[v];
|
||||
if (typeof row.deprecated === 'string') {
|
||||
hasDeprecated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hasDeprecated) {
|
||||
return yield* deprecateVersions.call(this, next);
|
||||
}
|
||||
|
||||
this.status = 400;
|
||||
this.body = {
|
||||
error: 'filename_error',
|
||||
reason: 'filename ' + filename + ' not found'
|
||||
};
|
||||
return;
|
||||
}
|
||||
@@ -501,17 +534,6 @@ exports.addPackageAndDist = function *(next) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check maintainers
|
||||
var isMaintainer = yield* packageService.isMaintainer(name, username);
|
||||
if (!isMaintainer) {
|
||||
this.status = 403;
|
||||
this.body = {
|
||||
error: 'forbidden user',
|
||||
reason: username + ' not authorized to modify ' + name
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
// upload attachment
|
||||
var tarballBuffer;
|
||||
tarballBuffer = new Buffer(attachment.data, 'base64');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "cnpmjs.org",
|
||||
"version": "1.1.0",
|
||||
"version": "1.2.2",
|
||||
"description": "Private npm registry and web for Enterprise, base on MySQL and Simple Store Service",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
@@ -28,7 +28,7 @@
|
||||
"graceful": "~0.1.0",
|
||||
"gravatar": "~1.0.6",
|
||||
"humanize-number": "~0.0.2",
|
||||
"koa": "~0.8.2",
|
||||
"koa": "~0.9.0",
|
||||
"koa-limit": "~1.0.2",
|
||||
"koa-markdown": "~0.0.3",
|
||||
"koa-middlewares": "~1.2.0",
|
||||
|
||||
@@ -162,26 +162,6 @@ exports.updateDescription = function (id, description, callback) {
|
||||
mysql.query(UPDATE_DESC_SQL, [description, id], callback);
|
||||
};
|
||||
|
||||
var UPDATE_PACKAGE_SQL = multiline(function () {;/*
|
||||
UPDATE
|
||||
module
|
||||
SET
|
||||
package=?
|
||||
WHERE
|
||||
id=?;
|
||||
*/});
|
||||
exports.updateReadme = function (id, readme, callback) {
|
||||
exports.getById(id, function (err, data) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
data.package = data.package || {};
|
||||
data.package.readme = readme;
|
||||
var pkg = stringifyPackage(data.package);
|
||||
mysql.query(UPDATE_PACKAGE_SQL, [pkg, id], callback);
|
||||
});
|
||||
};
|
||||
|
||||
var UPDATE_DIST_SQL = 'UPDATE module SET ? WHERE id=?';
|
||||
exports.update = function (mod, callback) {
|
||||
var pkg;
|
||||
@@ -746,3 +726,39 @@ exports.listByAuthor = function* (author, callback) {
|
||||
});
|
||||
return yield mysql.query(LIST_BY_AUTH_SQLS[3], [ids]);
|
||||
};
|
||||
|
||||
var UPDATE_PACKAGE_SQL = multiline(function () {;/*
|
||||
UPDATE
|
||||
module
|
||||
SET
|
||||
package=?
|
||||
WHERE
|
||||
id=?;
|
||||
*/});
|
||||
|
||||
exports.updatePackage = function* (id, pkg) {
|
||||
pkg = stringifyPackage(pkg);
|
||||
return yield mysql.query(UPDATE_PACKAGE_SQL, [pkg, id]);
|
||||
};
|
||||
|
||||
exports.updatePackageFields = function* (id, fields) {
|
||||
var data = yield exports.getById(id);
|
||||
if (!data) {
|
||||
throw new Error('module#' + id + ' not exists');
|
||||
}
|
||||
data.package = data.package || {};
|
||||
for (var k in fields) {
|
||||
data.package[k] = fields[k];
|
||||
}
|
||||
return yield* exports.updatePackage(id, data.package);
|
||||
};
|
||||
|
||||
exports.updateReadme = function* (id, readme) {
|
||||
var data = yield exports.getById(id);
|
||||
if (!data) {
|
||||
throw new Error('module#' + id + ' not exists');
|
||||
}
|
||||
data.package = data.package || {};
|
||||
data.package.readme = readme;
|
||||
return yield* exports.updatePackage(id, data.package);
|
||||
};
|
||||
|
||||
@@ -341,6 +341,7 @@ SyncModuleWorker.prototype._sync = function* (name, pkg) {
|
||||
var missingReadmes = [];
|
||||
var missingStarUsers = [];
|
||||
var npmUsernames = {};
|
||||
var missingDeprecateds = [];
|
||||
|
||||
// find out all user names
|
||||
for (var v in pkg.versions) {
|
||||
@@ -430,8 +431,9 @@ SyncModuleWorker.prototype._sync = function* (name, pkg) {
|
||||
var sourceAuthor = version.maintainers && version.maintainers[0] &&
|
||||
version.maintainers[0].name || exists.author;
|
||||
|
||||
if (exists.package && exists.package.dist.shasum === version.dist.shasum &&
|
||||
exists.author === sourceAuthor) {
|
||||
if (exists.package &&
|
||||
exists.package.dist.shasum === version.dist.shasum &&
|
||||
exists.author === sourceAuthor) {
|
||||
// * author make sure equal
|
||||
// * shasum make sure equal
|
||||
if ((version.publish_time === exists.publish_time) ||
|
||||
@@ -454,6 +456,14 @@ SyncModuleWorker.prototype._sync = function* (name, pkg) {
|
||||
readme: version.readme
|
||||
});
|
||||
}
|
||||
|
||||
if (version.deprecated && version.deprecated !== exists.package.deprecated) {
|
||||
// need to sync deprecated field
|
||||
missingDeprecateds.push({
|
||||
id: exists.id,
|
||||
deprecated: version.deprecated
|
||||
});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -604,6 +614,29 @@ SyncModuleWorker.prototype._sync = function* (name, pkg) {
|
||||
}
|
||||
}
|
||||
|
||||
function *syncDeprecateds() {
|
||||
if (missingDeprecateds.length === 0) {
|
||||
return;
|
||||
}
|
||||
that.log(' [%s] saving %d Deprecated fields', name, missingDeprecateds.length);
|
||||
|
||||
var res = yield gather(missingDeprecateds.map(function (item) {
|
||||
return Module.updatePackageFields(item.id, {
|
||||
deprecated: item.deprecated
|
||||
});
|
||||
}));
|
||||
|
||||
for (var i = 0; i < res.length; i++) {
|
||||
var item = missingDeprecateds[i];
|
||||
var r = res[i];
|
||||
if (r.error) {
|
||||
that.log(' save error, id: %s, error: %s', item.id, r.error.message);
|
||||
} else {
|
||||
that.log(' saved, id: %s', item.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function *syncMissingUsers() {
|
||||
var missingUsers = [];
|
||||
var names = Object.keys(npmUsernames);
|
||||
@@ -660,7 +693,9 @@ SyncModuleWorker.prototype._sync = function* (name, pkg) {
|
||||
}
|
||||
}
|
||||
|
||||
yield [syncDes(), syncTag(), syncReadme(), syncMissingStarUsers(), syncMissingUsers()];
|
||||
yield [
|
||||
syncDes(), syncTag(), syncReadme(), syncDeprecateds(),
|
||||
syncMissingStarUsers(), syncMissingUsers()];
|
||||
return syncedVersionNames;
|
||||
};
|
||||
|
||||
|
||||
211
test/controllers/registry/deprecate.test.js
Normal file
211
test/controllers/registry/deprecate.test.js
Normal file
@@ -0,0 +1,211 @@
|
||||
/**!
|
||||
* cnpmjs.org - test/controllers/registry/deprecate.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 fs = require('fs');
|
||||
var path = require('path');
|
||||
var should = require('should');
|
||||
var request = require('supertest');
|
||||
var mm = require('mm');
|
||||
var pedding = require('pedding');
|
||||
var app = require('../../../servers/registry');
|
||||
var utils = require('../../utils');
|
||||
|
||||
var fixtures = path.join(path.dirname(path.dirname(__dirname)), 'fixtures');
|
||||
|
||||
describe('controllers/registry/deprecate.test.js', function () {
|
||||
var pkgname = 'testmodule-deprecate';
|
||||
before(function (done) {
|
||||
done = pedding(2, done);
|
||||
var pkg = utils.getPackage(pkgname, '0.0.1', utils.admin);
|
||||
|
||||
request(app.listen())
|
||||
.put('/' + pkgname)
|
||||
.set('authorization', utils.adminAuth)
|
||||
.send(pkg)
|
||||
.expect(201, function (err) {
|
||||
should.not.exist(err);
|
||||
pkg = utils.getPackage(pkgname, '0.0.2', utils.admin);
|
||||
// publish 0.0.2
|
||||
request(app.listen())
|
||||
.put('/' + pkgname)
|
||||
.set('authorization', utils.adminAuth)
|
||||
.send(pkg)
|
||||
.expect(201, done);
|
||||
});
|
||||
|
||||
pkg = utils.getPackage(pkgname, '1.0.0', utils.admin);
|
||||
request(app.listen())
|
||||
.put('/' + pkgname)
|
||||
.set('authorization', utils.adminAuth)
|
||||
.send(pkg)
|
||||
.expect(201, done);
|
||||
});
|
||||
|
||||
afterEach(mm.restore);
|
||||
|
||||
describe('PUT /:name', function () {
|
||||
it('should deprecate version@1.0.0', function (done) {
|
||||
request(app.listen())
|
||||
.put('/' + pkgname)
|
||||
.set('authorization', utils.adminAuth)
|
||||
.send({
|
||||
name: pkgname,
|
||||
versions: {
|
||||
'1.0.0': {
|
||||
deprecated: 'mock test deprecated message 1.0.0'
|
||||
}
|
||||
}
|
||||
})
|
||||
.expect({
|
||||
ok: true
|
||||
})
|
||||
.expect(201, function (err, res) {
|
||||
should.not.exist(err);
|
||||
request(app.listen())
|
||||
.get('/' + pkgname + '/1.0.0')
|
||||
.expect(200, function (err, res) {
|
||||
should.not.exist(err);
|
||||
res.body.deprecated.should.equal('mock test deprecated message 1.0.0');
|
||||
|
||||
// undeprecated
|
||||
request(app.listen())
|
||||
.put('/' + pkgname)
|
||||
.set('authorization', utils.adminAuth)
|
||||
.send({
|
||||
name: pkgname,
|
||||
versions: {
|
||||
'1.0.0': {
|
||||
deprecated: ''
|
||||
}
|
||||
}
|
||||
})
|
||||
.expect({
|
||||
ok: true
|
||||
})
|
||||
.expect(201, function (err) {
|
||||
should.not.exist(err);
|
||||
request(app.listen())
|
||||
.get('/' + pkgname + '/1.0.0')
|
||||
.expect(200, function (err, res) {
|
||||
should.not.exist(err);
|
||||
res.body.deprecated.should.equal('');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should deprecate version@<1.0.0', function (done) {
|
||||
request(app.listen())
|
||||
.put('/' + pkgname)
|
||||
.set('authorization', utils.adminAuth)
|
||||
.send({
|
||||
name: pkgname,
|
||||
versions: {
|
||||
'1.0.0': {
|
||||
version: '1.0.0'
|
||||
},
|
||||
'0.0.1': {
|
||||
deprecated: 'mock test deprecated message 0.0.1'
|
||||
},
|
||||
'0.0.2': {
|
||||
deprecated: 'mock test deprecated message 0.0.2'
|
||||
}
|
||||
}
|
||||
})
|
||||
.expect({
|
||||
ok: true
|
||||
})
|
||||
.expect(201, function (err, res) {
|
||||
should.not.exist(err);
|
||||
done = pedding(3, done);
|
||||
|
||||
request(app.listen())
|
||||
.get('/' + pkgname + '/0.0.1')
|
||||
.expect(200, function (err, res) {
|
||||
should.not.exist(err);
|
||||
res.body.deprecated.should.equal('mock test deprecated message 0.0.1');
|
||||
done();
|
||||
});
|
||||
|
||||
request(app.listen())
|
||||
.get('/' + pkgname + '/0.0.2')
|
||||
.expect(200, function (err, res) {
|
||||
should.not.exist(err);
|
||||
res.body.deprecated.should.equal('mock test deprecated message 0.0.2');
|
||||
done();
|
||||
});
|
||||
|
||||
// not change 1.0.0
|
||||
request(app.listen())
|
||||
.get('/' + pkgname + '/1.0.0')
|
||||
.expect(200, function (err, res) {
|
||||
should.not.exist(err);
|
||||
res.body.deprecated.should.equal('');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should 404 deprecate not exists version', function (done) {
|
||||
request(app.listen())
|
||||
.put('/' + pkgname)
|
||||
.set('authorization', utils.adminAuth)
|
||||
.send({
|
||||
name: pkgname,
|
||||
versions: {
|
||||
'1.0.1': {
|
||||
deprecated: 'mock test deprecated message'
|
||||
},
|
||||
'1.0.0': {
|
||||
deprecated: 'mock test deprecated message'
|
||||
}
|
||||
}
|
||||
})
|
||||
.expect({
|
||||
error: 'version_error',
|
||||
reason: 'Some versions: ["1.0.1","1.0.0"] not found'
|
||||
})
|
||||
.expect(400, done);
|
||||
});
|
||||
|
||||
it('should 403', function (done) {
|
||||
request(app.listen())
|
||||
.put('/' + pkgname)
|
||||
.set('authorization', utils.otherUserAuth)
|
||||
.send({
|
||||
name: pkgname,
|
||||
versions: {
|
||||
'1.0.0': {
|
||||
version: '1.0.0'
|
||||
},
|
||||
'0.0.1': {
|
||||
deprecated: 'mock test deprecated message 0.0.1'
|
||||
},
|
||||
'0.0.2': {
|
||||
deprecated: 'mock test deprecated message 0.0.2'
|
||||
}
|
||||
}
|
||||
})
|
||||
.expect({
|
||||
error: 'no_perms',
|
||||
reason: 'Private mode enable, only admin can publish this module'
|
||||
})
|
||||
.expect(403, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -477,7 +477,7 @@ describe('controllers/registry/module.test.js', function () {
|
||||
.send(pkg)
|
||||
.expect(400, function (err, res) {
|
||||
should.not.exist(err);
|
||||
res.body.reason.should.containEql('filename or version not found');
|
||||
res.body.reason.should.equal('version undefined not found');
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -502,7 +502,7 @@ describe('controllers/registry/module.test.js', function () {
|
||||
should.not.exist(err);
|
||||
res.body.should.eql({
|
||||
error: 'version_error',
|
||||
reason: 'filename or version not found, filename: undefined, version: undefined'
|
||||
reason: 'version undefined not found'
|
||||
});
|
||||
done();
|
||||
});
|
||||
@@ -580,7 +580,7 @@ describe('controllers/registry/module.test.js', function () {
|
||||
should.not.exist(err);
|
||||
res.body.should.eql({
|
||||
error: 'version_error',
|
||||
reason: 'filename or version not found, filename: mk2testmodule-0.0.1.tgz, version: undefined'
|
||||
reason: 'version undefined not found'
|
||||
});
|
||||
done();
|
||||
});
|
||||
|
||||
@@ -18,14 +18,30 @@ var should = require('should');
|
||||
var mm = require('mm');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
var request = require('supertest');
|
||||
var mysql = require('../../common/mysql');
|
||||
var Module = require('../../proxy/module');
|
||||
var config = require('../../config');
|
||||
var utils = require('../utils');
|
||||
var app = require('../../servers/registry');
|
||||
|
||||
var fixtures = path.join(path.dirname(__dirname), 'fixtures');
|
||||
|
||||
var id;
|
||||
var pkgname = 'module-proxy-test-pkg';
|
||||
var pkgversion = '1.0.0';
|
||||
|
||||
describe('proxy/module.test.js', function () {
|
||||
|
||||
before(function (done) {
|
||||
var pkg = utils.getPackage(pkgname, pkgversion, utils.admin);
|
||||
request(app.listen())
|
||||
.put('/' + pkgname)
|
||||
.set('authorization', utils.adminAuth)
|
||||
.send(pkg)
|
||||
.expect(201, done);
|
||||
});
|
||||
|
||||
afterEach(mm.restore);
|
||||
|
||||
describe('addTag()', function () {
|
||||
@@ -154,15 +170,12 @@ describe('proxy/module.test.js', function () {
|
||||
});
|
||||
|
||||
describe('updateReadme()', function () {
|
||||
it('should update ok', function (done) {
|
||||
Module.updateReadme(id, 'test', function (err, data) {
|
||||
should.not.exist(err);
|
||||
Module.getById(id, function (err, data) {
|
||||
should.not.exist(err);
|
||||
data.package.readme.should.equal('test');
|
||||
done();
|
||||
});
|
||||
});
|
||||
it('should update ok', function* () {
|
||||
var row = yield Module.get(pkgname, pkgversion);
|
||||
should.exist(row);
|
||||
yield* Module.updateReadme(row.id, 'test');
|
||||
var data = yield Module.getById(row.id);
|
||||
data.package.readme.should.equal('test');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
.nav-tabs{margin:20px 0;}
|
||||
.nav-cont{display:none;}
|
||||
.nav-cont.active{display:block;}
|
||||
.deprecated{color:red;}
|
||||
</style>
|
||||
<script>
|
||||
$(function () {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</h1>
|
||||
|
||||
<% if (package.deprecated) { %>
|
||||
<p class="deprecated"><%= package.deprecated %></p>
|
||||
<p class="deprecated">[DEPRECATED] <%= package.deprecated %></p>
|
||||
<% } %>
|
||||
|
||||
<% if (package.description) { %>
|
||||
|
||||
Reference in New Issue
Block a user