Merge branch 'master' into issue-587
This commit is contained in:
commit
8d5a7f0c30
|
@ -4,7 +4,7 @@ import HTTPError from 'http-errors';
|
||||||
import type {Config} from '@verdaccio/types';
|
import type {Config} from '@verdaccio/types';
|
||||||
import type {Router} from 'express';
|
import type {Router} from 'express';
|
||||||
import type {IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer} from '../../../../types';
|
import type {IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer} from '../../../../types';
|
||||||
import {combineBaseUrl, getWebProtocol} from '../../../lib/utils';
|
// import {combineBaseUrl, getWebProtocol} from '../../../lib/utils';
|
||||||
|
|
||||||
function addUserAuthApi(route: Router, auth: IAuth, config: Config) {
|
function addUserAuthApi(route: Router, auth: IAuth, config: Config) {
|
||||||
route.post('/login', function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
|
route.post('/login', function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
|
||||||
|
@ -22,12 +22,13 @@ function addUserAuthApi(route: Router, auth: IAuth, config: Config) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
route.post('/-/logout', function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
|
// FIXME: this will be re-implemented
|
||||||
const base = combineBaseUrl(getWebProtocol(req), req.get('host'), config.url_prefix);
|
// route.post('/-/logout', function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
|
||||||
|
// const base = combineBaseUrl(getWebProtocol(req), req.get('host'), config.url_prefix);
|
||||||
|
|
||||||
res.cookies.set('token', '');
|
// res.cookies.set('token', '');
|
||||||
res.redirect(base);
|
// res.redirect(base);
|
||||||
});
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
export default addUserAuthApi;
|
export default addUserAuthApi;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
// @flow
|
// @flow
|
||||||
import {stringToMD5} from './string';
|
import {stringToMD5} from './string';
|
||||||
|
|
||||||
|
|
||||||
|
export const GRAVATAR_DEFAULT = 'https://www.gravatar.com/avatar/00000000000000000000000000000000?d=mm';
|
||||||
/**
|
/**
|
||||||
* Generate gravatar url from email address
|
* Generate gravatar url from email address
|
||||||
*/
|
*/
|
||||||
|
@ -11,6 +13,6 @@ export function generateGravatarUrl(email?: string): string {
|
||||||
|
|
||||||
return `https://www.gravatar.com/avatar/${emailMD5}`;
|
return `https://www.gravatar.com/avatar/${emailMD5}`;
|
||||||
} else {
|
} else {
|
||||||
return 'https://www.gravatar.com/avatar/00000000000000000000000000000000?d=mm';
|
return GRAVATAR_DEFAULT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,18 +5,21 @@ import rimraf from 'rimraf';
|
||||||
|
|
||||||
import configDefault from './partials/config';
|
import configDefault from './partials/config';
|
||||||
import publishMetadata from './partials/publish-api';
|
import publishMetadata from './partials/publish-api';
|
||||||
|
import forbiddenPlace from './partials/forbidden-place';
|
||||||
import Config from '../../src/lib/config';
|
import Config from '../../src/lib/config';
|
||||||
import Storage from '../../src/lib/storage';
|
import Storage from '../../src/lib/storage';
|
||||||
import Auth from '../../src/lib/auth';
|
import Auth from '../../src/lib/auth';
|
||||||
import indexAPI from '../../src/api/index';
|
import indexAPI from '../../src/api/index';
|
||||||
|
|
||||||
require('../../src/lib/logger').setup([]);
|
require('../../src/lib/logger').setup([]);
|
||||||
|
const credentials = { name: 'Jota', password: 'secretPass' };
|
||||||
|
|
||||||
describe('endpoint unit test', () => {
|
describe('endpoint unit test', () => {
|
||||||
let config;
|
let config;
|
||||||
let storage;
|
let storage;
|
||||||
let auth;
|
let auth;
|
||||||
let app;
|
let app;
|
||||||
|
jest.setTimeout(10000);
|
||||||
|
|
||||||
beforeAll(function(done) {
|
beforeAll(function(done) {
|
||||||
const store = path.join(__dirname, './partials/store/test-storage');
|
const store = path.join(__dirname, './partials/store/test-storage');
|
||||||
|
@ -36,6 +39,8 @@ describe('endpoint unit test', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Registry API Endpoints', () => {
|
||||||
|
|
||||||
describe('should test ping api', () => {
|
describe('should test ping api', () => {
|
||||||
test('should test endpoint /-/ping', (done) => {
|
test('should test endpoint /-/ping', (done) => {
|
||||||
request(app)
|
request(app)
|
||||||
|
@ -80,11 +85,7 @@ describe('endpoint unit test', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('should test user api', () => {
|
describe('should test user api', () => {
|
||||||
const credentials = { name: 'Jota', password: 'secretPass' };
|
|
||||||
|
|
||||||
test('should test add a new user', (done) => {
|
test('should test add a new user', (done) => {
|
||||||
|
|
||||||
|
|
||||||
request(app)
|
request(app)
|
||||||
.put('/-/user/org.couchdb.user:jota')
|
.put('/-/user/org.couchdb.user:jota')
|
||||||
.send(credentials)
|
.send(credentials)
|
||||||
|
@ -476,5 +477,158 @@ describe('endpoint unit test', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Registry WebUI endpoints', () => {
|
||||||
|
beforeAll(async function() {
|
||||||
|
await request(app)
|
||||||
|
.put('/@scope%2fpk1-test')
|
||||||
|
.set('content-type', 'application/json')
|
||||||
|
.send(JSON.stringify(publishMetadata))
|
||||||
|
.expect(201);
|
||||||
|
|
||||||
|
await request(app)
|
||||||
|
.put('/forbidden-place')
|
||||||
|
.set('content-type', 'application/json')
|
||||||
|
.send(JSON.stringify(forbiddenPlace))
|
||||||
|
.expect(201);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Packages', () => {
|
||||||
|
|
||||||
|
test('should display all packages', (done) => {
|
||||||
|
request(app)
|
||||||
|
.get('/-/verdaccio/packages' )
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
expect(res.body).toHaveLength(1);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should display scoped readme', (done) => {
|
||||||
|
request(app)
|
||||||
|
.get('/-/verdaccio/package/readme/@scope/pk1-test')
|
||||||
|
.expect(200)
|
||||||
|
.expect('Content-Type', 'text/plain; charset=utf-8')
|
||||||
|
.end(function(err, res) {
|
||||||
|
expect(res.text).toMatch('<h1 id="test">test</h1>\n');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should display scoped readme 404', (done) => {
|
||||||
|
request(app)
|
||||||
|
.get('/-/verdaccio/package/readme/@scope/404')
|
||||||
|
.expect(200)
|
||||||
|
.expect('Content-Type', 'text/plain; charset=utf-8')
|
||||||
|
.end(function(err, res) {
|
||||||
|
expect(res.body.error).toMatch('no such package available');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should display sidebar info', (done) => {
|
||||||
|
request(app)
|
||||||
|
.get('/-/verdaccio/sidebar/@scope/pk1-test')
|
||||||
|
.expect(200)
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.end(function(err, res) {
|
||||||
|
const sideBarInfo = res.body;
|
||||||
|
const latestVersion = publishMetadata.versions[publishMetadata['dist-tags'].latest];
|
||||||
|
|
||||||
|
expect(sideBarInfo.name).toBe(latestVersion.name);
|
||||||
|
expect(sideBarInfo.latest.author).toBeDefined();
|
||||||
|
expect(sideBarInfo.latest.author.avatar).toMatch(/www.gravatar.com/);
|
||||||
|
expect(sideBarInfo.latest.author.name).toBe(latestVersion.author.name);
|
||||||
|
expect(sideBarInfo.latest.author.email).toBe(latestVersion.author.email);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should display sidebar info 404', (done) => {
|
||||||
|
request(app)
|
||||||
|
.get('/-/verdaccio/sidebar/@scope/404')
|
||||||
|
.expect(404)
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.end(function(err, res) {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Search', () => {
|
||||||
|
|
||||||
|
test('should search pk1-test', (done) => {
|
||||||
|
request(app)
|
||||||
|
.get('/-/verdaccio/search/scope')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
expect(res.body).toHaveLength(1);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should search with 404', (done) => {
|
||||||
|
request(app)
|
||||||
|
.get('/-/verdaccio/search/@')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
// in a normal world, the output would be 1
|
||||||
|
// https://github.com/verdaccio/verdaccio/issues/345
|
||||||
|
// should fix this
|
||||||
|
expect(res.body).toHaveLength(0);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not find forbidden-place', (done) => {
|
||||||
|
request(app)
|
||||||
|
.get('/-/verdaccio/search/forbidden-place')
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
//this is expected since we are not logged
|
||||||
|
// and forbidden-place is allow_access: 'nobody'
|
||||||
|
expect(res.body).toHaveLength(0);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('User', () => {
|
||||||
|
describe('login webui', () => {
|
||||||
|
test('should log a user jota', (done) => {
|
||||||
|
request(app)
|
||||||
|
.post('/-/verdaccio/login')
|
||||||
|
.send({
|
||||||
|
username: credentials.name,
|
||||||
|
password: credentials.password
|
||||||
|
})
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
expect(res.body.error).toBeUndefined();
|
||||||
|
expect(res.body.token).toBeDefined();
|
||||||
|
expect(res.body.token).toBeTruthy();
|
||||||
|
expect(res.body.username).toMatch(credentials.name);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should fails on log unvalid user', (done) => {
|
||||||
|
request(app)
|
||||||
|
.post('/-/verdaccio/login')
|
||||||
|
.send(JSON.stringify({
|
||||||
|
username: 'fake',
|
||||||
|
password: 'fake'
|
||||||
|
}))
|
||||||
|
//FIXME: there should be 401
|
||||||
|
.expect(200)
|
||||||
|
.end(function(err, res) {
|
||||||
|
expect(res.body.error).toMatch(/bad username\/password, access denied/);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -14,7 +14,7 @@ const config = {
|
||||||
|
|
||||||
'forbidden-place': {
|
'forbidden-place': {
|
||||||
allow_access: 'nobody',
|
allow_access: 'nobody',
|
||||||
allow_publish: 'nobody'
|
allow_publish: '$all'
|
||||||
},
|
},
|
||||||
|
|
||||||
'react': {
|
'react': {
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
const json = {
|
||||||
|
"_id": "forbidden-place",
|
||||||
|
"name": "forbidden-place",
|
||||||
|
"description": "",
|
||||||
|
"dist-tags": {
|
||||||
|
"latest": "1.0.6"
|
||||||
|
},
|
||||||
|
"versions": {
|
||||||
|
"1.0.6": {
|
||||||
|
"name": "forbidden-place",
|
||||||
|
"version": "1.0.6",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"name": "Juan Picado",
|
||||||
|
"email": "juan@jotadeveloper.com"
|
||||||
|
},
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"verdaccio": "^2.7.2"
|
||||||
|
},
|
||||||
|
"readme": "# test",
|
||||||
|
"readmeFilename": "README.md",
|
||||||
|
"_id": "forbidden-place@1.0.6",
|
||||||
|
"_npmVersion": "5.5.1",
|
||||||
|
"_nodeVersion": "8.7.0",
|
||||||
|
"_npmUser": {
|
||||||
|
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"integrity": "sha512-6gHiERpiDgtb3hjqpQH5\/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==",
|
||||||
|
"shasum": "2c03764f651a9f016ca0b7620421457b619151b9",
|
||||||
|
"tarball": "http:\/\/localhost:5555\/forbidden-place\/-\/forbidden-place-1.0.6.tgz"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"readme": "# test",
|
||||||
|
"_attachments": {
|
||||||
|
"forbidden-place-1.0.6.tgz": {
|
||||||
|
"content_type": "application\/octet-stream",
|
||||||
|
"data": "H4sIAAAAAAAAE+2W32vbMBDH85y\/QnjQp9qxLEeBMsbGlocNBmN7bFdQ5WuqxJaEpGQdo\/\/79KPeQsnIw5KUDX\/9IOvurLuz\/DHSjK\/YAiY6jcXSKjk6sMqypHWNdtmD6hlBI0wqQmo8nVbVqMR4OsNoVB66kF1aW8eML+Vv10m9oF\/jP6IfY4QyyTrILlD2eqkcm+gVzpdrJrPz4NuAsULJ4MZFWdBkbcByI7R79CRjx0ScCdnAvf+SkjUFWu8IubzBgXUhDPidQlfZ3BhlLpBUKDiQ1cDFrYDmKkNnZwjuhUM4808+xNVW8P2bMk1Y7vJrtLC1u1MmLPjBF40+Cc4ahV6GDmI\/DWygVRpMwVX3KtXUCg7Sxp7ff3nbt6TBFy65gK1iffsN41yoEHtdFbOiisWMH8bPvXUH0SP3k+KG3UBr+DFy7OGfEJr4x5iWVeS\/pLQe+D+FIv\/agIWI6GX66kFuIhT+1gDjrp\/4d7WAvAwEJPh0u14IufWkM0zaW2W6nLfM2lybgJ4LTJ0\/jWiAK8OcMjt8MW3OlfQppcuhhQ6k+2OgkK2Q8DssFPi\/IHpU9fz3\/+xj5NjDf8QFE39VmE4JDfzPCBn4P4X6\/f88f\/Pu47zomiPk2Lv\/dOv8h+P\/34\/D\/p9CL+Kp67mrGDRo0KBBp9ZPsETQegASAAA=",
|
||||||
|
"length": 512
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = json;
|
|
@ -1,10 +1,11 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
import _ from 'lodash';
|
||||||
import ProxyStorage from '../../src/lib/up-storage';
|
import ProxyStorage from '../../src/lib/up-storage';
|
||||||
import AppConfig from '../../src/lib/config';
|
import AppConfig from '../../src/lib/config';
|
||||||
import _ from 'lodash';
|
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
import configExample from './partials/config';
|
import configExample from './partials/config';
|
||||||
import {setup} from '../../src/lib/logger';
|
import {setup} from '../../src/lib/logger';
|
||||||
|
|
||||||
import type {Config, UpLinkConf} from '@verdaccio/types';
|
import type {Config, UpLinkConf} from '@verdaccio/types';
|
||||||
import type {IProxy} from '../../types';
|
import type {IProxy} from '../../types';
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,42 @@
|
||||||
let assert = require('assert');
|
// @flow
|
||||||
let validate = require('../../src/lib/utils').validate_name;
|
|
||||||
|
|
||||||
describe('Validate', () => {
|
import assert from 'assert';
|
||||||
|
import {validate_name as validate} from '../../src/lib/utils';
|
||||||
|
import {generateGravatarUrl, GRAVATAR_DEFAULT} from '../../src/utils/user';
|
||||||
|
import {spliceURL} from '../../src/utils/string';
|
||||||
|
|
||||||
|
describe('Utilities', () => {
|
||||||
|
|
||||||
|
describe('String utilities', () => {
|
||||||
|
test('should splice two strings and generate a url', () => {
|
||||||
|
const url: string = spliceURL('http://domain.com', '/-/static/logo.png');
|
||||||
|
|
||||||
|
expect(url).toMatch('http://domain.com/-/static/logo.png');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should splice a empty strings and generate a url', () => {
|
||||||
|
const url: string = spliceURL('', '/-/static/logo.png');
|
||||||
|
|
||||||
|
expect(url).toMatch('/-/static/logo.png');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('User utilities', () => {
|
||||||
|
test('should generate gravatar url with email', () => {
|
||||||
|
const gravatarUrl: string = generateGravatarUrl('user@verdaccio.org');
|
||||||
|
|
||||||
|
expect(gravatarUrl).toMatch('https://www.gravatar.com/avatar/');
|
||||||
|
expect(gravatarUrl).not.toMatch('000000000');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should generate generic gravatar url', () => {
|
||||||
|
const gravatarUrl: string = generateGravatarUrl();
|
||||||
|
|
||||||
|
expect(gravatarUrl).toMatch(GRAVATAR_DEFAULT);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Validations', () => {
|
||||||
test('good ones', () => {
|
test('good ones', () => {
|
||||||
assert( validate('verdaccio') );
|
assert( validate('verdaccio') );
|
||||||
assert( validate('some.weird.package-zzz') );
|
assert( validate('some.weird.package-zzz') );
|
||||||
|
@ -39,4 +74,5 @@ describe('Validate', () => {
|
||||||
assert( !validate('pk+g') );
|
assert( !validate('pk+g') );
|
||||||
assert( !validate('pk:g') );
|
assert( !validate('pk:g') );
|
||||||
});
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue