diff --git a/src/api/web/endpoint/user.js b/src/api/web/endpoint/user.js index 857d9dc3f..bf459306d 100644 --- a/src/api/web/endpoint/user.js +++ b/src/api/web/endpoint/user.js @@ -4,7 +4,7 @@ import HTTPError from 'http-errors'; import type {Config} from '@verdaccio/types'; import type {Router} from 'express'; 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) { 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) { - const base = combineBaseUrl(getWebProtocol(req), req.get('host'), config.url_prefix); + // FIXME: this will be re-implemented + // 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.redirect(base); - }); + // res.cookies.set('token', ''); + // res.redirect(base); + // }); } export default addUserAuthApi; diff --git a/src/utils/user.js b/src/utils/user.js index 5eae16b7d..d3ca87c0f 100644 --- a/src/utils/user.js +++ b/src/utils/user.js @@ -1,6 +1,8 @@ // @flow import {stringToMD5} from './string'; + +export const GRAVATAR_DEFAULT = 'https://www.gravatar.com/avatar/00000000000000000000000000000000?d=mm'; /** * Generate gravatar url from email address */ @@ -11,6 +13,6 @@ export function generateGravatarUrl(email?: string): string { return `https://www.gravatar.com/avatar/${emailMD5}`; } else { - return 'https://www.gravatar.com/avatar/00000000000000000000000000000000?d=mm'; + return GRAVATAR_DEFAULT; } } diff --git a/test/unit/api.spec.js b/test/unit/api.spec.js index 881a1679c..512b39be6 100644 --- a/test/unit/api.spec.js +++ b/test/unit/api.spec.js @@ -5,18 +5,21 @@ import rimraf from 'rimraf'; import configDefault from './partials/config'; import publishMetadata from './partials/publish-api'; +import forbiddenPlace from './partials/forbidden-place'; import Config from '../../src/lib/config'; import Storage from '../../src/lib/storage'; import Auth from '../../src/lib/auth'; import indexAPI from '../../src/api/index'; require('../../src/lib/logger').setup([]); +const credentials = { name: 'Jota', password: 'secretPass' }; describe('endpoint unit test', () => { let config; let storage; let auth; let app; + jest.setTimeout(10000); beforeAll(function(done) { const store = path.join(__dirname, './partials/store/test-storage'); @@ -36,445 +39,596 @@ describe('endpoint unit test', () => { }); }); - describe('should test ping api', () => { - test('should test endpoint /-/ping', (done) => { - request(app) - .get('/-/ping') - .expect('Content-Type', /json/) - .expect(200) - .end(function(err, res) { - if (err) { - return done(err); - } - done(); - }); + describe('Registry API Endpoints', () => { + + describe('should test ping api', () => { + test('should test endpoint /-/ping', (done) => { + request(app) + .get('/-/ping') + .expect('Content-Type', /json/) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + done(); + }); + }); + }); + + describe('should test whoami api', () => { + test('should test /-/whoami endpoint', (done) => { + request(app) + .get('/-/whoami') + .expect('Content-Type', /json/) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + done(); + }); + }); + + test('should test /whoami endpoint', (done) => { + request(app) + .get('/-/whoami') + .expect('Content-Type', /json/) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + done(); + }); + }); + }); + + describe('should test user api', () => { + test('should test add a new user', (done) => { + request(app) + .put('/-/user/org.couchdb.user:jota') + .send(credentials) + .expect('Content-Type', /json/) + .expect(201) + .end(function(err, res) { + if (err) { + return done(err); + } + + expect(res.body.ok).toBeDefined(); + expect(res.body.ok).toMatch(`user '${credentials.name}' created`); + done(); + }); + }); + + test('should test fails add a new user with missing name', (done) => { + + const credentialsShort = _.clone(credentials); + delete credentialsShort.name; + + request(app) + .put('/-/user/org.couchdb.user:jota') + .send(credentialsShort) + .expect('Content-Type', /json/) + .expect(400) + .end(function(err, res) { + if (err) { + return done(err); + } + + expect(res.body.error).toBeDefined(); + expect(res.body.error).toMatch(/username and password is required/); + done(); + }); + }); + + test('should test fails add a new user with missing password', (done) => { + + const credentialsShort = _.clone(credentials); + delete credentialsShort.password; + + request(app) + .put('/-/user/org.couchdb.user:jota') + .send(credentialsShort) + .expect('Content-Type', /json/) + .expect(400) + .end(function(err, res) { + if (err) { + return done(err); + } + + expect(res.body.error).toBeDefined(); + //FIXME: message is not 100% accurate + expect(res.body.error).toMatch(/username and password is required/); + done(); + }); + }); + + test('should test add a new user with login', (done) => { + + request(app) + .put('/-/user/org.couchdb.user:jota') + .send(credentials) + .expect('Content-Type', /json/) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + expect(res.body).toBeTruthy(); + done(); + }); + }); + + test('should test fails add a new user with wrong password', (done) => { + + const credentialsShort = _.clone(credentials); + credentialsShort.password = 'failPassword'; + + request(app) + .put('/-/user/org.couchdb.user:jota') + .send(credentialsShort) + .expect('Content-Type', /json/) + .expect(401) + .end(function(err, res) { + if (err) { + return done(err); + } + + expect(res.body.error).toBeDefined(); + expect(res.body.error).toMatch(/unauthorized/); + done(); + }); + }); + + }); + + describe('should test package api', () => { + + test('should fetch jquery package from remote uplink', (done) => { + + request(app) + .get('/jquery') + .set('content-type', 'application/json; charset=utf-8') + .expect('Content-Type', /json/) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + + expect(res.body).toBeDefined(); + expect(res.body.name).toMatch(/jquery/); + done(); + }); + }); + + test('should fetch jquery specific version package from remote uplink', (done) => { + + request(app) + .get('/jquery/1.5.1') + .set('content-type', 'application/json; charset=utf-8') + .expect('Content-Type', /json/) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + + expect(res.body).toBeDefined(); + expect(res.body.name).toMatch(/jquery/); + done(); + }); + }); + + test('should fetch jquery specific tag package from remote uplink', (done) => { + + request(app) + .get('/jquery/latest') + .set('content-type', 'application/json; charset=utf-8') + .expect('Content-Type', /json/) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + + expect(res.body).toBeDefined(); + expect(res.body.name).toMatch(/jquery/); + done(); + }); + }); + + test('should fails on fetch jquery specific tag package from remote uplink', (done) => { + + request(app) + .get('/jquery/never-will-exist-this-tag') + .set('content-type', 'application/json; charset=utf-8') + .expect('Content-Type', /json/) + .expect(404) + .end(function(err, res) { + if (err) { + return done(err); + } + done(); + }); + }); + + test('should not found a unexisting remote package under scope', (done) => { + + request(app) + .get('/@verdaccio/not-found') + .set('content-type', 'application/json; charset=utf-8') + .expect('Content-Type', /json/) + .expect(404) + .end(function(err, res) { + if (err) { + return done(err); + } + done(); + }); + }); + + test('should forbid access to remote package', (done) => { + + request(app) + .get('/forbidden-place') + .set('content-type', 'application/json; charset=utf-8') + .expect('Content-Type', /json/) + .expect(403) + .end(function(err, res) { + if (err) { + return done(err); + } + done(); + }); + }); + + test('should fetch a tarball from remote uplink', (done) => { + + request(app) + .get('/jquery/-/jquery-1.5.1.tgz') + .expect('Content-Type', /application\/octet-stream/) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + + expect(res.body).toBeDefined(); + done(); + }); + }); + + test('should fails fetch a tarball from remote uplink', (done) => { + + request(app) + .get('/jquery/-/jquery-0.0.1.tgz') + .expect('Content-Type', /application\/octet-stream/) + .expect(404) + .end(function(err, res) { + if (err) { + return done(err); + } + + done(); + }); + }); + + }); + + describe('should test dist-tag api', () => { + const jqueryVersion = '2.1.2'; + const jqueryUpdatedVersion = { + 'beta': '3.0.0', + 'jota': '1.6.3' + }; + + test('should set a new tag on jquery', (done) => { + + request(app) + .put('/jquery/verdaccio-tag') + .send(JSON.stringify(jqueryVersion)) + .set('accept', 'gzip') + .set('accept-encoding', 'application/json') + .set('content-type', 'application/json') + .expect(201) + .end(function(err, res) { + if (err) { + return done(err); + } + + expect(res.body.ok).toBeDefined(); + expect(res.body.ok).toMatch(/package tagged/); + done(); + }); + }); + + test('should fetch all tag for jquery', (done) => { + + request(app) + .get('/-/package/jquery/dist-tags') + .set('accept-encoding', 'application/json') + .set('content-type', 'application/json') + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + + expect(res.body).toBeDefined(); + expect(res.body['verdaccio-tag']).toMatch(jqueryVersion); + done(); + }); + }); + + test('should update a new tag on jquery', (done) => { + + request(app) + .post('/-/package/jquery/dist-tags') + .send(JSON.stringify(jqueryUpdatedVersion)) + .set('content-type', 'application/json') + .expect(201) + .end(function(err, res) { + if (err) { + return done(err); + } + + expect(res.body.ok).toBeDefined(); + expect(res.body.ok).toMatch(/tags updated/); + done(); + }); + }); + + test('should fetch all tags for jquery and ccheck previous update', (done) => { + + request(app) + .get('/-/package/jquery/dist-tags') + .set('accept-encoding', 'application/json') + .set('content-type', 'application/json') + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + + expect(res.body).toBeDefined(); + expect(res.body['beta']).toMatch(jqueryUpdatedVersion['beta']); + done(); + }); + }); + + test('should set a remove a tag on jquery', (done) => { + + request(app) + .del('/-/package/jquery/dist-tags/verdaccio-tag') + .set('accept-encoding', 'application/json') + .set('content-type', 'application/json') + //.expect('Content-Type', /json/) + .expect(201) + .end(function(err, res) { + if (err) { + return done(err); + } + + expect(res.body.ok).toBeDefined(); + expect(res.body.ok).toMatch(/tag removed/); + done(); + }); + }); + + }); + + describe('should test search api', () => { + test('should perform a search', (done) => { + const now = Date.now() + const cacheTime = now - 6000000; + request(app) + .get('/-/all/since?stale=update_after&startkey=' + cacheTime) + // .set('accept-encoding', 'application/json') + // .set('content-type', 'application/json') + //.expect('Content-Type', /json/) + .expect(200) + .end(function(err, res) { + if (err) { + return done(err); + } + //TODO: we have to catch the stream check whether it returns something + // we should not spend much time on this api since is deprecated somehow. + done(); + }); + }); + + }); + + describe('should test publish api', () => { + test('should publish a new package', (done) => { + request(app) + .put('/@scope%2fpk1-test') + .set('content-type', 'application/json') + .send(JSON.stringify(publishMetadata)) + .expect(201) + .end(function(err, res) { + if (err) { + return done(err); + } + expect(res.body.ok).toBeDefined(); + expect(res.body.success).toBeDefined(); + expect(res.body.success).toBeTruthy(); + expect(res.body.ok).toMatch(/created new package/); + done(); + }); + }); + + test('should unpublish a new package', (done) => { + //FUTURE: for some reason it does not remove the scope folder + request(app) + .del('/@scope%2fpk1-test/-rev/4-6abcdb4efd41a576') + .set('content-type', 'application/json') + .expect(201) + .end(function(err, res) { + if (err) { + return done(err); + } + expect(res.body.ok).toBeDefined(); + expect(res.body.ok).toMatch(/package removed/); + done(); + }); + }); }); }); - describe('should test whoami api', () => { - test('should test /-/whoami endpoint', (done) => { - request(app) - .get('/-/whoami') - .expect('Content-Type', /json/) - .expect(200) - .end(function(err, res) { - if (err) { - return done(err); - } - done(); - }); + 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); }); - test('should test /whoami endpoint', (done) => { - request(app) - .get('/-/whoami') - .expect('Content-Type', /json/) - .expect(200) - .end(function(err, res) { - if (err) { - return done(err); - } - done(); + 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('

test

\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(); + }); + }); + }); }); }); - - describe('should test user api', () => { - const credentials = { name: 'Jota', password: 'secretPass' }; - - test('should test add a new user', (done) => { - - - request(app) - .put('/-/user/org.couchdb.user:jota') - .send(credentials) - .expect('Content-Type', /json/) - .expect(201) - .end(function(err, res) { - if (err) { - return done(err); - } - - expect(res.body.ok).toBeDefined(); - expect(res.body.ok).toMatch(`user '${credentials.name}' created`); - done(); - }); - }); - - test('should test fails add a new user with missing name', (done) => { - - const credentialsShort = _.clone(credentials); - delete credentialsShort.name; - - request(app) - .put('/-/user/org.couchdb.user:jota') - .send(credentialsShort) - .expect('Content-Type', /json/) - .expect(400) - .end(function(err, res) { - if (err) { - return done(err); - } - - expect(res.body.error).toBeDefined(); - expect(res.body.error).toMatch(/username and password is required/); - done(); - }); - }); - - test('should test fails add a new user with missing password', (done) => { - - const credentialsShort = _.clone(credentials); - delete credentialsShort.password; - - request(app) - .put('/-/user/org.couchdb.user:jota') - .send(credentialsShort) - .expect('Content-Type', /json/) - .expect(400) - .end(function(err, res) { - if (err) { - return done(err); - } - - expect(res.body.error).toBeDefined(); - //FIXME: message is not 100% accurate - expect(res.body.error).toMatch(/username and password is required/); - done(); - }); - }); - - test('should test add a new user with login', (done) => { - - request(app) - .put('/-/user/org.couchdb.user:jota') - .send(credentials) - .expect('Content-Type', /json/) - .expect(200) - .end(function(err, res) { - if (err) { - return done(err); - } - expect(res.body).toBeTruthy(); - done(); - }); - }); - - test('should test fails add a new user with wrong password', (done) => { - - const credentialsShort = _.clone(credentials); - credentialsShort.password = 'failPassword'; - - request(app) - .put('/-/user/org.couchdb.user:jota') - .send(credentialsShort) - .expect('Content-Type', /json/) - .expect(401) - .end(function(err, res) { - if (err) { - return done(err); - } - - expect(res.body.error).toBeDefined(); - expect(res.body.error).toMatch(/unauthorized/); - done(); - }); - }); - - }); - - describe('should test package api', () => { - - test('should fetch jquery package from remote uplink', (done) => { - - request(app) - .get('/jquery') - .set('content-type', 'application/json; charset=utf-8') - .expect('Content-Type', /json/) - .expect(200) - .end(function(err, res) { - if (err) { - return done(err); - } - - expect(res.body).toBeDefined(); - expect(res.body.name).toMatch(/jquery/); - done(); - }); - }); - - test('should fetch jquery specific version package from remote uplink', (done) => { - - request(app) - .get('/jquery/1.5.1') - .set('content-type', 'application/json; charset=utf-8') - .expect('Content-Type', /json/) - .expect(200) - .end(function(err, res) { - if (err) { - return done(err); - } - - expect(res.body).toBeDefined(); - expect(res.body.name).toMatch(/jquery/); - done(); - }); - }); - - test('should fetch jquery specific tag package from remote uplink', (done) => { - - request(app) - .get('/jquery/latest') - .set('content-type', 'application/json; charset=utf-8') - .expect('Content-Type', /json/) - .expect(200) - .end(function(err, res) { - if (err) { - return done(err); - } - - expect(res.body).toBeDefined(); - expect(res.body.name).toMatch(/jquery/); - done(); - }); - }); - - test('should fails on fetch jquery specific tag package from remote uplink', (done) => { - - request(app) - .get('/jquery/never-will-exist-this-tag') - .set('content-type', 'application/json; charset=utf-8') - .expect('Content-Type', /json/) - .expect(404) - .end(function(err, res) { - if (err) { - return done(err); - } - done(); - }); - }); - - test('should not found a unexisting remote package under scope', (done) => { - - request(app) - .get('/@verdaccio/not-found') - .set('content-type', 'application/json; charset=utf-8') - .expect('Content-Type', /json/) - .expect(404) - .end(function(err, res) { - if (err) { - return done(err); - } - done(); - }); - }); - - test('should forbid access to remote package', (done) => { - - request(app) - .get('/forbidden-place') - .set('content-type', 'application/json; charset=utf-8') - .expect('Content-Type', /json/) - .expect(403) - .end(function(err, res) { - if (err) { - return done(err); - } - done(); - }); - }); - - test('should fetch a tarball from remote uplink', (done) => { - - request(app) - .get('/jquery/-/jquery-1.5.1.tgz') - .expect('Content-Type', /application\/octet-stream/) - .expect(200) - .end(function(err, res) { - if (err) { - return done(err); - } - - expect(res.body).toBeDefined(); - done(); - }); - }); - - test('should fails fetch a tarball from remote uplink', (done) => { - - request(app) - .get('/jquery/-/jquery-0.0.1.tgz') - .expect('Content-Type', /application\/octet-stream/) - .expect(404) - .end(function(err, res) { - if (err) { - return done(err); - } - - done(); - }); - }); - - }); - - describe('should test dist-tag api', () => { - const jqueryVersion = '2.1.2'; - const jqueryUpdatedVersion = { - 'beta': '3.0.0', - 'jota': '1.6.3' - }; - - test('should set a new tag on jquery', (done) => { - - request(app) - .put('/jquery/verdaccio-tag') - .send(JSON.stringify(jqueryVersion)) - .set('accept', 'gzip') - .set('accept-encoding', 'application/json') - .set('content-type', 'application/json') - .expect(201) - .end(function(err, res) { - if (err) { - return done(err); - } - - expect(res.body.ok).toBeDefined(); - expect(res.body.ok).toMatch(/package tagged/); - done(); - }); - }); - - test('should fetch all tag for jquery', (done) => { - - request(app) - .get('/-/package/jquery/dist-tags') - .set('accept-encoding', 'application/json') - .set('content-type', 'application/json') - .expect(200) - .end(function(err, res) { - if (err) { - return done(err); - } - - expect(res.body).toBeDefined(); - expect(res.body['verdaccio-tag']).toMatch(jqueryVersion); - done(); - }); - }); - - test('should update a new tag on jquery', (done) => { - - request(app) - .post('/-/package/jquery/dist-tags') - .send(JSON.stringify(jqueryUpdatedVersion)) - .set('content-type', 'application/json') - .expect(201) - .end(function(err, res) { - if (err) { - return done(err); - } - - expect(res.body.ok).toBeDefined(); - expect(res.body.ok).toMatch(/tags updated/); - done(); - }); - }); - - test('should fetch all tags for jquery and ccheck previous update', (done) => { - - request(app) - .get('/-/package/jquery/dist-tags') - .set('accept-encoding', 'application/json') - .set('content-type', 'application/json') - .expect(200) - .end(function(err, res) { - if (err) { - return done(err); - } - - expect(res.body).toBeDefined(); - expect(res.body['beta']).toMatch(jqueryUpdatedVersion['beta']); - done(); - }); - }); - - test('should set a remove a tag on jquery', (done) => { - - request(app) - .del('/-/package/jquery/dist-tags/verdaccio-tag') - .set('accept-encoding', 'application/json') - .set('content-type', 'application/json') - //.expect('Content-Type', /json/) - .expect(201) - .end(function(err, res) { - if (err) { - return done(err); - } - - expect(res.body.ok).toBeDefined(); - expect(res.body.ok).toMatch(/tag removed/); - done(); - }); - }); - - }); - - describe('should test search api', () => { - test('should perform a search', (done) => { - const now = Date.now() - const cacheTime = now - 6000000; - request(app) - .get('/-/all/since?stale=update_after&startkey=' + cacheTime) - // .set('accept-encoding', 'application/json') - // .set('content-type', 'application/json') - //.expect('Content-Type', /json/) - .expect(200) - .end(function(err, res) { - if (err) { - return done(err); - } - //TODO: we have to catch the stream check whether it returns something - // we should not spend much time on this api since is deprecated somehow. - done(); - }); - }); - - }); - - describe('should test publish api', () => { - test('should publish a new package', (done) => { - request(app) - .put('/@scope%2fpk1-test') - .set('content-type', 'application/json') - .send(JSON.stringify(publishMetadata)) - .expect(201) - .end(function(err, res) { - if (err) { - return done(err); - } - expect(res.body.ok).toBeDefined(); - expect(res.body.success).toBeDefined(); - expect(res.body.success).toBeTruthy(); - expect(res.body.ok).toMatch(/created new package/); - done(); - }); - }); - - test('should unpublish a new package', (done) => { - //FUTURE: for some reason it does not remove the scope folder - request(app) - .del('/@scope%2fpk1-test/-rev/4-6abcdb4efd41a576') - .set('content-type', 'application/json') - .expect(201) - .end(function(err, res) { - if (err) { - return done(err); - } - expect(res.body.ok).toBeDefined(); - expect(res.body.ok).toMatch(/package removed/); - done(); - }); - }); - }); - }); diff --git a/test/unit/partials/config.js b/test/unit/partials/config.js index 722dae174..92d044625 100644 --- a/test/unit/partials/config.js +++ b/test/unit/partials/config.js @@ -14,7 +14,7 @@ const config = { 'forbidden-place': { allow_access: 'nobody', - allow_publish: 'nobody' + allow_publish: '$all' }, 'react': { diff --git a/test/unit/partials/forbidden-place.js b/test/unit/partials/forbidden-place.js new file mode 100644 index 000000000..da6f078b0 --- /dev/null +++ b/test/unit/partials/forbidden-place.js @@ -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; diff --git a/test/unit/up-storage.spec.js b/test/unit/up-storage.spec.js index ed946fbab..035079d36 100644 --- a/test/unit/up-storage.spec.js +++ b/test/unit/up-storage.spec.js @@ -1,10 +1,11 @@ // @flow +import _ from 'lodash'; import ProxyStorage from '../../src/lib/up-storage'; import AppConfig from '../../src/lib/config'; -import _ from 'lodash'; // $FlowFixMe import configExample from './partials/config'; import {setup} from '../../src/lib/logger'; + import type {Config, UpLinkConf} from '@verdaccio/types'; import type {IProxy} from '../../types'; diff --git a/test/unit/utils.spec.js b/test/unit/utils.spec.js index 8d1a54bb6..4dce407d5 100644 --- a/test/unit/utils.spec.js +++ b/test/unit/utils.spec.js @@ -1,42 +1,78 @@ -let assert = require('assert'); -let validate = require('../../src/lib/utils').validate_name; +// @flow -describe('Validate', () => { - test('good ones', () => { - assert( validate('verdaccio') ); - assert( validate('some.weird.package-zzz') ); - assert( validate('old-package@0.1.2.tgz') ); +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'); + }); }); - test('uppercase', () => { - assert( validate('EVE') ); - assert( validate('JSONStream') ); + 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); + }); }); - test('no package.json', () => { - assert( !validate('package.json') ); - }); + describe('Validations', () => { + test('good ones', () => { + assert( validate('verdaccio') ); + assert( validate('some.weird.package-zzz') ); + assert( validate('old-package@0.1.2.tgz') ); + }); - test('no path seps', () => { - assert( !validate('some/thing') ); - assert( !validate('some\\thing') ); - }); + test('uppercase', () => { + assert( validate('EVE') ); + assert( validate('JSONStream') ); + }); - test('no hidden', () => { - assert( !validate('.bin') ); - }); + test('no package.json', () => { + assert( !validate('package.json') ); + }); - test('no reserved', () => { - assert( !validate('favicon.ico') ); - assert( !validate('node_modules') ); - assert( !validate('__proto__') ); - }); + test('no path seps', () => { + assert( !validate('some/thing') ); + assert( !validate('some\\thing') ); + }); - test('other', () => { - assert( !validate('pk g') ); - assert( !validate('pk\tg') ); - assert( !validate('pk%20g') ); - assert( !validate('pk+g') ); - assert( !validate('pk:g') ); + test('no hidden', () => { + assert( !validate('.bin') ); + }); + + test('no reserved', () => { + assert( !validate('favicon.ico') ); + assert( !validate('node_modules') ); + assert( !validate('__proto__') ); + }); + + test('other', () => { + assert( !validate('pk g') ); + assert( !validate('pk\tg') ); + assert( !validate('pk%20g') ); + assert( !validate('pk+g') ); + assert( !validate('pk:g') ); + }); }); });