1
0
mirror of https://github.com/verdaccio/verdaccio.git synced 2025-02-21 07:29:37 +01:00

Merge branch 'feat-new-detail-page' of github.com:verdaccio/verdaccio into feat-new-detail-page

This commit is contained in:
Priscila Oliveira 2019-01-20 12:04:34 +01:00
commit f725597baa
19 changed files with 76 additions and 46 deletions

@ -12,3 +12,5 @@ Dockerfile
*.rpi
*.html
*.scss
*.png
*.jpg

@ -164,16 +164,15 @@ Verdaccio aims to support all features of a standard npm client that make sense
- npm audit - **supported**
## Sponsors
## Special Thanks
#### Open Source License
Thanks to the following companies to help us to achieve our goals providing free open source licenses.
Thanks to the following sponsors to help to achieve our goals providing us free open source licenses.
[![jetbrain](assets/thanks/jetbrains/logo.png)](https://www.jetbrains.com/)
[![crowdin](assets/thanks/crowdin/logo.png)](https://crowdin.com/)
[![balsamiq](assets/thanks/balsamiq/logo.jpg)](https://balsamiq.com/)
[![jetbrain](assets/sponsor/jetbrains/logo.png)](https://www.jetbrains.com/)
[![crowdin](assets/sponsor/crowdin/logo.png)](https://crowdin.com/)
#### Open Collective
## Open Collective Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/verdaccio#sponsor)]
@ -188,7 +187,7 @@ Support this project by becoming a sponsor. Your logo will show up here with a l
[![sponsor](https://opencollective.com/verdaccio/sponsor/8/avatar.svg)](https://opencollective.com/verdaccio/sponsor/8/website)
[![sponsor](https://opencollective.com/verdaccio/sponsor/9/avatar.svg)](https://opencollective.com/verdaccio/sponsor/9/website)
## Backers
## Open Collective Backers
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/verdaccio#backer)]
@ -218,5 +217,5 @@ If you have any issue you can try the following options, do no desist to ask or
Verdaccio is [MIT licensed](https://github.com/verdaccio/verdaccio/blob/master/LICENSE)
The Verdaccio documentation and logos (e.g., .md, .png, .sketch) files in the /docs and /assets folder) is
The Verdaccio documentation and logos (excluding /thanks, e.g., .md, .png, .sketch) files within the /assets folder) is
[Creative Commons licensed](https://github.com/verdaccio/verdaccio/blob/master/LICENSE-docs).

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

@ -78,7 +78,7 @@
"@commitlint/config-conventional": "7.1.2",
"@material-ui/core": "3.9.0",
"@material-ui/icons": "3.0.2",
"@verdaccio/types": "4.1.3",
"@verdaccio/types": "4.1.4",
"autosuggest-highlight": "3.1.1",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "10.0.1",

@ -61,7 +61,7 @@ export default function(route, auth, storage) {
stream.on('data', function each(pkg) {
processing_pkgs++;
auth.allow_access(pkg.name, req.remote_user, function(err, allowed) {
auth.allow_access({ packageName: pkg.name }, req.remote_user, function(err, allowed) {
processing_pkgs--;
if (err) {

@ -5,7 +5,7 @@
import _ from 'lodash';
import { validateName as utilValidateName, validatePackage as utilValidatePackage, isObject, ErrorCode } from '../lib/utils';
import { validateName as utilValidateName, validatePackage as utilValidatePackage, getVersionFromTarball, isObject, ErrorCode } from '../lib/utils';
import { API_ERROR, HEADER_TYPE, HEADERS, HTTP_STATUS, TOKEN_BASIC, TOKEN_BEARER } from '../lib/constants';
import { stringToMD5 } from '../lib/crypto-utils';
import type { $ResponseExtend, $RequestExtend, $NextFunctionVer, IAuth } from '../../types';
@ -99,12 +99,11 @@ export function allow(auth: IAuth) {
return function(action: string) {
return function(req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
req.pause();
let packageName = req.params.package;
if (req.params.scope) {
packageName = `@${req.params.scope}/${packageName}`;
}
const packageName = req.params.scope ? `@${req.params.scope}/${req.params.package}` : req.params.package;
const packageVersion = req.params.filename ? getVersionFromTarball(req.params.filename) : undefined;
// $FlowFixMe
auth['allow_' + action](packageName, req.remote_user, function(error, allowed) {
auth['allow_' + action]({ packageName, packageVersion }, req.remote_user, function(error, allowed) {
req.resume();
if (error) {
next(error);

@ -7,6 +7,7 @@ import _ from 'lodash';
import { addScope, addGravatarSupport, deleteProperties, sortByName, parseReadme } from '../../../lib/utils';
import { allow } from '../../middleware';
import { DIST_TAGS, HEADER_TYPE, HEADERS, HTTP_STATUS } from '../../../lib/constants';
import logger from '../../../lib/logger';
import type { Router } from 'express';
import type { IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler, $SidebarPackage } from '../../../../types';
import type { Config } from '@verdaccio/types';
@ -17,7 +18,7 @@ function addPackageWebApi(route: Router, storage: IStorageHandler, auth: IAuth,
const checkAllow = (name, remoteUser) =>
new Promise((resolve, reject) => {
try {
auth.allow_access(name, remoteUser, (err, allowed) => {
auth.allow_access({ packageName: name }, remoteUser, (err, allowed) => {
if (err) {
resolve(false);
} else {
@ -44,6 +45,7 @@ function addPackageWebApi(route: Router, storage: IStorageHandler, auth: IAuth,
permissions.push(pkg);
}
} catch (err) {
logger.logger.error({ name: pkg.name, error: err }, 'permission process for @{name} has failed: @{error}');
throw err;
}
}

@ -20,7 +20,7 @@ function addSearchWebApi(route: Router, storage: IStorageHandler, auth: IAuth) {
uplinksLook: false,
callback: (err, entry) => {
if (!err && entry) {
auth.allow_access(entry.name, req.remote_user, function(err, allowed) {
auth.allow_access({ packageName: entry.name }, req.remote_user, function(err, allowed) {
if (err || !allowed) {
return;
}

@ -23,7 +23,7 @@ import {
import { convertPayloadToBase64, ErrorCode } from './utils';
import { getMatchedPackagesSpec } from './config-utils';
import type { Config, Logger, Callback, IPluginAuth, RemoteUser, JWTSignOptions, Security } from '@verdaccio/types';
import type { Config, Logger, Callback, IPluginAuth, RemoteUser, JWTSignOptions, Security, AuthPluginPackage } from '@verdaccio/types';
import type { $Response, NextFunction } from 'express';
import type { $RequestExtend, IAuth } from '../../types';
@ -160,10 +160,10 @@ class Auth implements IAuth {
/**
* Allow user to access a package.
*/
allow_access(packageName: string, user: RemoteUser, callback: Callback) {
allow_access({ packageName, packageVersion }: AuthPluginPackage, user: RemoteUser, callback: Callback) {
const plugins = this.plugins.slice(0);
// $FlowFixMe
const pkg = Object.assign({ name: packageName }, getMatchedPackagesSpec(packageName, this.config.packages));
const pkg = Object.assign({ name: packageName, version: packageVersion }, getMatchedPackagesSpec(packageName, this.config.packages));
const self = this;
this.logger.trace({ packageName }, 'allow access for @{packageName}');
@ -193,11 +193,11 @@ class Auth implements IAuth {
/**
* Allow user to publish a package.
*/
allow_publish(packageName: string, user: string, callback: Callback) {
allow_publish({ packageName, packageVersion }: AuthPluginPackage, user: string, callback: Callback) {
const plugins = this.plugins.slice(0);
const self = this;
// $FlowFixMe
const pkg = Object.assign({ name: packageName }, getMatchedPackagesSpec(packageName, this.config.packages));
const pkg = Object.assign({ name: packageName, version: packageVersion }, getMatchedPackagesSpec(packageName, this.config.packages));
this.logger.trace({ packageName }, 'allow publish for @{packageName}');
(function next() {

@ -642,7 +642,7 @@ class LocalStorage implements IStorage {
const { packages } = this.config;
if (packages) {
const listPackagesConf = Object.keys(packages || {});
const listPackagesConf = Object.keys(packages);
listPackagesConf.map(pkg => {
if (packages[pkg].storage) {

@ -322,17 +322,20 @@ class Storage implements IStorageHandler {
);
lstream.on('error', function(err) {
self.logger.error({ err: err }, 'uplink error: @{err.message}');
cb(), (cb = function() {});
cb();
cb = function() {};
});
lstream.on('end', function() {
cb(), (cb = function() {});
cb();
cb = function() {};
});
stream.abort = function() {
if (lstream.abort) {
lstream.abort();
}
cb(), (cb = function() {});
cb();
cb = function() {};
};
},
// executed after all series
@ -411,7 +414,7 @@ class Storage implements IStorageHandler {
const upLinks = [];
const hasToLookIntoUplinks = _.isNil(options.uplinksLook) || options.uplinksLook;
if (!packageInfo || packageInfo === null) {
if (!packageInfo) {
exists = false;
packageInfo = generatePackageTemplate(name);
}

@ -145,7 +145,7 @@ class ProxyStorage implements IProxy {
let error;
const responseLength = err ? 0 : body.length;
// $FlowFixMe
processBody(err, body);
processBody();
logActivity();
// $FlowFixMe
cb(err, res, body);
@ -552,7 +552,7 @@ class ProxyStorage implements IProxy {
// https://github.com/rlidwka/sinopia/issues/254
//
if (this.proxy === false) {
headers['X-Forwarded-For'] = (req && req.headers['x-forwarded-for'] ? req.headers['x-forwarded-for'] + ', ' : '') + req.connection.remoteAddress;
headers['X-Forwarded-For'] = (req.headers['x-forwarded-for'] ? req.headers['x-forwarded-for'] + ', ' : '') + req.connection.remoteAddress;
}
}

@ -502,3 +502,13 @@ export function parseReadme(packageName: string, readme: string): string {
export function buildToken(type: string, token: string): string {
return `${_.capitalize(type)} ${token}`;
}
/**
* return package version from tarball name
* @param {String} name
* @returns {String}
*/
export function getVersionFromTarball(name: string) {
// $FlowFixMe
return /.+-(\d.+)\.tgz/.test(name) ? name.match(/.+-(\d.+)\.tgz/)[1] : undefined;
}

@ -34,11 +34,10 @@ export const GENERIC_AVATAR: string = `
* Generate gravatar url from email address
*/
export function generateGravatarUrl(email: string = '', online: boolean = true): string {
let emailCopy = email;
if (online) {
if (_.isString(email) && _.size(email) > 0) {
emailCopy = email.trim().toLocaleLowerCase();
const emailMD5 = stringToMD5(emailCopy);
email = email.trim().toLocaleLowerCase();
const emailMD5 = stringToMD5(email);
return `https://www.gravatar.com/avatar/${emailMD5}`;
}
return GENERIC_AVATAR;

@ -24,7 +24,7 @@ export default class ExampleMiddlewarePlugin implements IPluginMiddleware {
name: 'test'
};
auth.authenticate('user', 'password', () => {});
auth.allow_access('packageName', remoteUser, () => {});
auth.allow_access({packageName: 'packageName'}, remoteUser, () => {});
auth.add_user('user', 'password', () => {});
auth.aesEncrypt(new Buffer('pass'));
// storage

@ -11,7 +11,8 @@ import {
combineBaseUrl,
getVersion,
normalizeDistTags,
getWebProtocol
getWebProtocol,
getVersionFromTarball
} from '../../../src/lib/utils';
import { DIST_TAGS } from '../../../src/lib/constants';
import Logger, { setup } from '../../../src/lib/logger';
@ -259,6 +260,21 @@ describe('Utilities', () => {
}).toThrow(expect.hasAssertions());
});
});
describe('getVersionFromTarball', () => {
test('should get the right version', () => {
const simpleName = 'test-name-4.2.12.tgz'
const complexName = 'test-5.6.4-beta.2.tgz'
const otherComplexName = 'test-3.5.0-6.tgz'
expect(getVersionFromTarball(simpleName)).toEqual('4.2.12')
expect(getVersionFromTarball(complexName)).toEqual('5.6.4-beta.2')
expect(getVersionFromTarball(otherComplexName)).toEqual('3.5.0-6')
})
test('should don\'n fall at incorrect tarball name', () => {
expect(getVersionFromTarball('incorrectName')).toBeUndefined()
})
});
});
describe('String utilities', () => {

BIN
yarn.lock

Binary file not shown.