feat: list packages by username
GET /-/users/:user/packages
return user packages list
{
"user": {
"name": $name
},
"packages": [
{
"name": $name,
"description": $description,
"version": $version
}, ...
],
}
closes #661
This commit is contained in:
@@ -2,3 +2,6 @@ node_modules/
|
||||
coverage/
|
||||
.tmp/
|
||||
.git/
|
||||
tools/
|
||||
public/
|
||||
test/
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
sudo: false
|
||||
language: node_js
|
||||
node_js:
|
||||
- 'iojs-2'
|
||||
- '1'
|
||||
- '2'
|
||||
- '3'
|
||||
- '4'
|
||||
addons:
|
||||
- postgresql: '9.3'
|
||||
script: 'make test-travis-all'
|
||||
|
||||
4
Makefile
4
Makefile
@@ -3,12 +3,12 @@ REPORTER = spec
|
||||
TIMEOUT = 30000
|
||||
MOCHA_OPTS =
|
||||
DB = sqlite
|
||||
DISTURL = http://npm.taobao.org/mirrors/iojs
|
||||
DISTURL = https://npm.taobao.org/mirrors/iojs
|
||||
BIN = iojs
|
||||
|
||||
ifeq ($(findstring io.js, $(shell which node)),)
|
||||
BIN = node
|
||||
DISTURL = http://npm.taobao.org/mirrors/node
|
||||
DISTURL = https://npm.taobao.org/mirrors/node
|
||||
endif
|
||||
|
||||
install:
|
||||
|
||||
13
README.md
13
README.md
@@ -4,11 +4,8 @@ cnpmjs.org
|
||||
[![NPM version][npm-image]][npm-url]
|
||||
[![build status][travis-image]][travis-url]
|
||||
[![Test coverage][cov-image]][cov-url]
|
||||
[![Gittip][gittip-image]][gittip-url]
|
||||
[![David deps][david-image]][david-url]
|
||||
[![node version][node-image]][node-url]
|
||||
[![npm download][download-image]][download-url]
|
||||
[![gitter][gitter-image]][gitter-url]
|
||||
|
||||
[npm-image]: http://cnpmjs.org/badge/v/cnpmjs.org.svg?style=flat-square
|
||||
[npm-url]: http://cnpmjs.org/package/cnpmjs.org
|
||||
@@ -16,16 +13,10 @@ cnpmjs.org
|
||||
[travis-url]: https://travis-ci.org/cnpm/cnpmjs.org
|
||||
[cov-image]: http://codecov.io/github/cnpm/cnpmjs.org/coverage.svg?branch=master
|
||||
[cov-url]: http://codecov.io/github/cnpm/cnpmjs.org?branch=master
|
||||
[gittip-image]: https://img.shields.io/gittip/fengmk2.svg?style=flat-square
|
||||
[gittip-url]: https://www.gittip.com/fengmk2/
|
||||
[david-image]: https://img.shields.io/david/cnpm/cnpmjs.org.svg?style=flat-square
|
||||
[david-url]: https://david-dm.org/cnpm/cnpmjs.org
|
||||
[node-image]: https://img.shields.io/badge/node.js-%3E=_0.11-red.svg?style=flat-square
|
||||
[node-url]: http://nodejs.org/download/
|
||||
[download-image]: https://img.shields.io/npm/dm/cnpmjs.org.svg?style=flat-square
|
||||
[download-url]: https://npmjs.org/package/cnpmjs.org
|
||||
[gitter-image]: https://badges.gitter.im/Join%20Chat.svg
|
||||
[gitter-url]: https://gitter.im/cnpm/cnpmjs.org?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge
|
||||
|
||||

|
||||
|
||||
@@ -120,8 +111,8 @@ Tips: make sure your code is following the [node-style-guide](https://github.com
|
||||
|
||||
## Sponsors
|
||||
|
||||
- [](http://www.ucloud.cn/sdk?sem=sdk-CNPMJS)
|
||||
- [](http://www.ucloud.cn?sem=sdk-CNPMJS)
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
[MIT](LICENSE.txt)
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/**!
|
||||
* cnpmjs.org - config/index.js
|
||||
*
|
||||
* Copyright(c) cnpmjs.org and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
|
||||
29
controllers/registry/package/list_by_user.js
Normal file
29
controllers/registry/package/list_by_user.js
Normal file
@@ -0,0 +1,29 @@
|
||||
/**!
|
||||
* list packages by username
|
||||
*
|
||||
* Copyright(c) cnpmjs.org and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
* Authors:
|
||||
* fengmk2 <m@fengmk2.com> (http://fengmk2.com)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
const packageService = require('../../../services/package');
|
||||
|
||||
module.exports = function*() {
|
||||
const username = this.params.user;
|
||||
const packages = yield packageService.listModulesByUser(username);
|
||||
|
||||
this.body = {
|
||||
user: {
|
||||
name: username,
|
||||
},
|
||||
packages: packages,
|
||||
};
|
||||
};
|
||||
@@ -1,12 +1,10 @@
|
||||
/**!
|
||||
* cnpmjs.org - dispatch.js
|
||||
*
|
||||
* Copyright(c) cnpmjs.org and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
* Authors:
|
||||
* dead_horse <dead_horse@qq.com>
|
||||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
|
||||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.com)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -144,4 +144,4 @@ Release [History](/history).
|
||||
|
||||
## Sponsors
|
||||
|
||||
- [](http://www.ucloud.cn/sdk?sem=sdk-CNPMJS)
|
||||
- [](http://www.ucloud.cn?sem=sdk-CNPMJS)
|
||||
|
||||
2
index.js
2
index.js
@@ -1,6 +1,4 @@
|
||||
/**!
|
||||
* cnpmjs.org - index.js
|
||||
*
|
||||
* Copyright(c) cnpmjs.org and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
/**!
|
||||
* cnpmjs.org - models/index.js
|
||||
*
|
||||
* Copyright(c) fengmk2 and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
* Authors:
|
||||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
|
||||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.com)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
@@ -15,7 +13,6 @@
|
||||
*/
|
||||
|
||||
var path = require('path');
|
||||
var Sequelize = require('sequelize');
|
||||
var sequelize = require('../common/sequelize');
|
||||
|
||||
function load(name) {
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
"registry"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 0.11.14"
|
||||
"node": ">= 1.0.0"
|
||||
},
|
||||
"author": [
|
||||
"fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)",
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
/**!
|
||||
* cnpmjs.org - routes/registry.js
|
||||
*
|
||||
* Copyright(c) cnpmjs.org and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
* Authors:
|
||||
* dead_horse <dead_horse@qq.com>
|
||||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
|
||||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.com)
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
@@ -36,6 +34,7 @@ var removeOneVersion = require('../controllers/registry/package/remove_version')
|
||||
var updatePackage = require('../controllers/registry/package/update');
|
||||
var downloadPackage = require('../controllers/registry/package/download');
|
||||
var downloadTotal = require('../controllers/registry/package/download_total');
|
||||
var listPackagesByUser = require('../controllers/registry/package/list_by_user');
|
||||
|
||||
var addUser = require('../controllers/registry/user/add');
|
||||
var showUser = require('../controllers/registry/user/show');
|
||||
@@ -113,6 +112,7 @@ function routes(app) {
|
||||
|
||||
// list all packages of user
|
||||
app.get('/-/by-user/:user', userPackage.list);
|
||||
app.get('/-/users/:user/packages', listPackagesByUser);
|
||||
|
||||
// download times
|
||||
app.get('/downloads/range/:range/:name', downloadTotal);
|
||||
|
||||
@@ -128,7 +128,7 @@ exports.listModules = function* (names) {
|
||||
id: ids
|
||||
},
|
||||
attributes: [
|
||||
'name', 'description'
|
||||
'name', 'description', 'version',
|
||||
]
|
||||
});
|
||||
return rows;
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/*!
|
||||
* cnpmjs.org - sync/sync_exist.js
|
||||
*
|
||||
* Copyright(c) cnpmjs.org and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
@@ -16,7 +14,6 @@
|
||||
|
||||
var debug = require('debug')('cnpmjs.org:sync:sync_exist');
|
||||
var Status = require('./status');
|
||||
var ms = require('humanize-ms');
|
||||
var thunkify = require('thunkify-wrap');
|
||||
var config = require('../config');
|
||||
var npmService = require('../services/npm');
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**!
|
||||
* sync packages since by some days ago
|
||||
*
|
||||
* Copyright(c) fengmk2 and other contributors.
|
||||
* Copyright(c) cnpmjs.org and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
* Authors:
|
||||
@@ -55,7 +55,7 @@ function* sync(sinceTimestamp) {
|
||||
console.log('All packages sync done, successes %d, fails %d',
|
||||
worker.successes.length, worker.fails.length);
|
||||
process.exit(0);
|
||||
};
|
||||
}
|
||||
|
||||
co(function* () {
|
||||
var timestamp = Date.now() - ms(process.argv[2] || '30d');
|
||||
|
||||
87
test/controllers/registry/package/list_by_user.test.js
Normal file
87
test/controllers/registry/package/list_by_user.test.js
Normal file
@@ -0,0 +1,87 @@
|
||||
/**!
|
||||
* Copyright(c) cnpmjs.org and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
* Authors:
|
||||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.com)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var request = require('supertest');
|
||||
var mm = require('mm');
|
||||
var should = require('should');
|
||||
var app = require('../../../../servers/registry');
|
||||
var utils = require('../../../utils');
|
||||
|
||||
describe('test/controllers/registry/package/list_by_user.test.js', function () {
|
||||
var user = 'cnpmjstest_list_by_user';
|
||||
var userauth = 'Basic ' + new Buffer(user + ':' + user).toString('base64');
|
||||
|
||||
afterEach(mm.restore);
|
||||
|
||||
before(function (done) {
|
||||
var pkg = utils.getPackage('@cnpmtest/list_by_user_module1', '1.0.1', user);
|
||||
request(app)
|
||||
.put('/' + pkg.name)
|
||||
.set('authorization', userauth)
|
||||
.send(pkg)
|
||||
.expect(201, function (err) {
|
||||
should.not.exist(err);
|
||||
|
||||
var pkg2 = utils.getPackage('@cnpmtest/list_by_user_module2', '2.0.0', user);
|
||||
request(app)
|
||||
.put('/' + pkg2.name)
|
||||
.set('authorization', userauth)
|
||||
.send(pkg2)
|
||||
.expect(201, done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('GET /-/users/:user/packages', function () {
|
||||
it('should get 200', function (done) {
|
||||
var url = '/-/users/' + user + '/packages';
|
||||
request(app)
|
||||
.get(url)
|
||||
.expect(function(res) {
|
||||
var data = res.body;
|
||||
data.user.name.should.equal(user);
|
||||
var map = {};
|
||||
data.packages.forEach(function(pkg) {
|
||||
map[pkg.name] = pkg;
|
||||
});
|
||||
map['@cnpmtest/list_by_user_module1'].should.be.an.Object;
|
||||
map['@cnpmtest/list_by_user_module1'].should.eql({
|
||||
name: '@cnpmtest/list_by_user_module1',
|
||||
description: '',
|
||||
version: '1.0.1',
|
||||
});
|
||||
|
||||
map['@cnpmtest/list_by_user_module2'].should.be.an.Object;
|
||||
map['@cnpmtest/list_by_user_module2'].should.eql({
|
||||
name: '@cnpmtest/list_by_user_module2',
|
||||
description: '',
|
||||
version: '2.0.0',
|
||||
});
|
||||
})
|
||||
.expect(200, done);
|
||||
});
|
||||
|
||||
it('should get empty packages list when user not exists', function (done) {
|
||||
var url = '/-/users/not-exist-username/packages';
|
||||
request(app)
|
||||
.get(url)
|
||||
.expect({
|
||||
user: {
|
||||
name: 'not-exist-username',
|
||||
},
|
||||
packages: [],
|
||||
})
|
||||
.expect(200, done);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -38,6 +38,7 @@ var usernames = [
|
||||
'cnpmjstest10', // admin
|
||||
'cnpmjstestAdmin2', // other admin
|
||||
'cnpmjstestAdmin3', // other admin
|
||||
'cnpmjstest_list_by_user',
|
||||
];
|
||||
|
||||
var count = usernames.length;
|
||||
|
||||
@@ -124,7 +124,7 @@ describe('test/services/package.test.js', function () {
|
||||
var mods = yield* Package.listPublicModulesByUser('listPublicModuleNamesByUser-user');
|
||||
mods.should.length(3);
|
||||
mods.forEach(function (mod) {
|
||||
mod.toJSON().should.have.keys('name', 'description');
|
||||
mod.toJSON().should.have.keys('name', 'description', 'version');
|
||||
mod.name.should.containEql('listPublicModuleNamesByUser-module');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
/**!
|
||||
* cnpmjs.org - test/utils.js
|
||||
*
|
||||
* Copyright(c) fengmk2 and other contributors.
|
||||
* Copyright(c) cnpmjs.org and other contributors.
|
||||
* MIT Licensed
|
||||
*
|
||||
* Authors:
|
||||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.github.com)
|
||||
* fengmk2 <fengmk2@gmail.com> (http://fengmk2.com)
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -59,10 +59,12 @@
|
||||
<% if (!packages.length) { %>
|
||||
<div class="alert alert-warning">Can not found any package by <%= user.name %>.</div>
|
||||
<% } %>
|
||||
<% for (var i = 0; i < packages.length; i++) { %>
|
||||
<% for (var i = 0; i < packages.length; i++) {
|
||||
var package = packages[i];
|
||||
%>
|
||||
<div class="package">
|
||||
<a href="/package/<%= packages[i].name %>" class="package-name"><%= packages[i].name %></a>
|
||||
<span class="package-description"><%= packages[i].description %></span>
|
||||
<a href="/package/<%= packages[i].name %>" class="package-name"><%= package.name %></a>
|
||||
<span class="package-description">(latest: <%= package.version %>) <%= package.description %></span>
|
||||
</div>
|
||||
<% } %>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user