mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-12-30 22:34:10 -05:00
refactor: config file using flow
This commit is contained in:
parent
3917b19976
commit
dd3a937ac9
11 changed files with 113 additions and 65 deletions
|
@ -52,7 +52,7 @@
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "6.1.3",
|
"@commitlint/cli": "6.1.3",
|
||||||
"@commitlint/config-conventional": "6.1.3",
|
"@commitlint/config-conventional": "6.1.3",
|
||||||
"@verdaccio/types": "3.0.0",
|
"@verdaccio/types": "3.0.1",
|
||||||
"babel-cli": "6.26.0",
|
"babel-cli": "6.26.0",
|
||||||
"babel-core": "6.26.0",
|
"babel-core": "6.26.0",
|
||||||
"babel-eslint": "8.2.2",
|
"babel-eslint": "8.2.2",
|
||||||
|
|
|
@ -15,13 +15,13 @@ import type {$ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler,
|
||||||
import type {Config as IConfig} from '@verdaccio/types';
|
import type {Config as IConfig} from '@verdaccio/types';
|
||||||
import {ErrorCode} from '../lib/utils';
|
import {ErrorCode} from '../lib/utils';
|
||||||
import {API_ERROR, HTTP_STATUS} from '../lib/constants';
|
import {API_ERROR, HTTP_STATUS} from '../lib/constants';
|
||||||
|
import AppConfig from '../lib/config';
|
||||||
|
|
||||||
const LoggerApp = require('../lib/logger');
|
const LoggerApp = require('../lib/logger');
|
||||||
const Config = require('../lib/config');
|
|
||||||
const Middleware = require('./middleware');
|
const Middleware = require('./middleware');
|
||||||
const Cats = require('../lib/status-cats');
|
const Cats = require('../lib/status-cats');
|
||||||
|
|
||||||
const defineAPI = function(config: Config, storage: IStorageHandler) {
|
const defineAPI = function(config: IConfig, storage: IStorageHandler) {
|
||||||
const auth: IAuth = new Auth(config);
|
const auth: IAuth = new Auth(config);
|
||||||
const app: $Application = express();
|
const app: $Application = express();
|
||||||
// run in production mode by default, just in case
|
// run in production mode by default, just in case
|
||||||
|
@ -103,7 +103,7 @@ const defineAPI = function(config: Config, storage: IStorageHandler) {
|
||||||
|
|
||||||
export default async function(configHash: any) {
|
export default async function(configHash: any) {
|
||||||
LoggerApp.setup(configHash.logs);
|
LoggerApp.setup(configHash.logs);
|
||||||
const config: IConfig = new Config(configHash);
|
const config: IConfig = new AppConfig(configHash);
|
||||||
const storage: IStorageHandler = new Storage(config);
|
const storage: IStorageHandler = new Storage(config);
|
||||||
// waits until init calls have been intialized
|
// waits until init calls have been intialized
|
||||||
await storage.init(config);
|
await storage.init(config);
|
||||||
|
|
|
@ -9,6 +9,7 @@ import type {Config, Logger, Callback} from '@verdaccio/types';
|
||||||
import type {$Response, NextFunction} from 'express';
|
import type {$Response, NextFunction} from 'express';
|
||||||
import type {$RequestExtend, JWTPayload} from '../../types';
|
import type {$RequestExtend, JWTPayload} from '../../types';
|
||||||
import {API_ERROR, ROLES} from './constants';
|
import {API_ERROR, ROLES} from './constants';
|
||||||
|
import {getMatchedPackagesSpec} from './config-utils';
|
||||||
|
|
||||||
|
|
||||||
const LoggerApi = require('./logger');
|
const LoggerApi = require('./logger');
|
||||||
|
@ -146,7 +147,7 @@ class Auth {
|
||||||
allow_access(packageName: string, user: string, callback: Callback) {
|
allow_access(packageName: string, user: string, callback: Callback) {
|
||||||
let plugins = this.plugins.slice(0);
|
let plugins = this.plugins.slice(0);
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
let pkg = Object.assign({name: packageName}, this.config.getMatchedPackagesSpec(packageName));
|
let pkg = Object.assign({name: packageName}, getMatchedPackagesSpec(packageName, this.config.packages));
|
||||||
|
|
||||||
(function next() {
|
(function next() {
|
||||||
const plugin = plugins.shift();
|
const plugin = plugins.shift();
|
||||||
|
@ -175,7 +176,7 @@ class Auth {
|
||||||
allow_publish(packageName: string, user: string, callback: Callback) {
|
allow_publish(packageName: string, user: string, callback: Callback) {
|
||||||
let plugins = this.plugins.slice(0);
|
let plugins = this.plugins.slice(0);
|
||||||
// $FlowFixMe
|
// $FlowFixMe
|
||||||
let pkg = Object.assign({name: packageName}, this.config.getMatchedPackagesSpec(packageName));
|
let pkg = Object.assign({name: packageName}, getMatchedPackagesSpec(packageName, this.config.packages));
|
||||||
|
|
||||||
(function next() {
|
(function next() {
|
||||||
const plugin = plugins.shift();
|
const plugin = plugins.shift();
|
||||||
|
|
9
src/lib/bootstrap.js
vendored
9
src/lib/bootstrap.js
vendored
|
@ -64,9 +64,12 @@ export function getListListenAddresses(argListen: string, configListen: mixed) {
|
||||||
* @param {String} pkgVersion
|
* @param {String} pkgVersion
|
||||||
* @param {String} pkgName
|
* @param {String} pkgName
|
||||||
*/
|
*/
|
||||||
function startVerdaccio(config: any, cliListen: string,
|
function startVerdaccio(config: any,
|
||||||
configPath: string, pkgVersion: string,
|
cliListen: string,
|
||||||
pkgName: string, callback: Callback) {
|
configPath: string,
|
||||||
|
pkgVersion: string,
|
||||||
|
pkgName: string,
|
||||||
|
callback: Callback) {
|
||||||
if (isObject(config) === false) {
|
if (isObject(config) === false) {
|
||||||
throw new Error('config file must be an object');
|
throw new Error('config file must be an object');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import minimatch from 'minimatch';
|
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
|
import minimatch from 'minimatch';
|
||||||
|
|
||||||
import {ErrorCode} from './utils';
|
import {ErrorCode} from './utils';
|
||||||
|
|
||||||
|
import type {PackageList} from '@verdaccio/types';
|
||||||
|
import type {MatchedPackage} from '../../types';
|
||||||
const BLACKLIST = {
|
const BLACKLIST = {
|
||||||
all: true,
|
all: true,
|
||||||
anonymous: true,
|
anonymous: true,
|
||||||
|
@ -38,17 +40,6 @@ export function normalizeUserlist(oldFormat: any, newFormat: any) {
|
||||||
return _.flatten(result);
|
return _.flatten(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getMatchedPackagesSpec(packages: any, pkg: any) {
|
|
||||||
for (let i in packages) {
|
|
||||||
// $FlowFixMe
|
|
||||||
if (minimatch.makeRe(i).exec(pkg)) {
|
|
||||||
return packages[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
export function uplinkSanityCheck(uplinks: any, users: any = BLACKLIST) {
|
export function uplinkSanityCheck(uplinks: any, users: any = BLACKLIST) {
|
||||||
const newUplinks = _.clone(uplinks);
|
const newUplinks = _.clone(uplinks);
|
||||||
let newUsers = _.clone(users);
|
let newUsers = _.clone(users);
|
||||||
|
@ -88,8 +79,36 @@ export function sanityCheckUplinksProps(configUpLinks: any) {
|
||||||
return uplinks;
|
return uplinks;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function normalisePackageAccess(packages: any): any {
|
/**
|
||||||
const normalizedPkgs: any = {...packages};
|
* Check whether an uplink can proxy
|
||||||
|
*/
|
||||||
|
export function hasProxyTo(pkg: string, upLink: string, packages: PackageList): boolean {
|
||||||
|
const matchedPkg: MatchedPackage = (getMatchedPackagesSpec(pkg, packages): MatchedPackage);
|
||||||
|
const proxyList = typeof matchedPkg !== 'undefined' ? matchedPkg.proxy : [];
|
||||||
|
if (proxyList) {
|
||||||
|
return proxyList.reduce((prev, curr) => {
|
||||||
|
if (upLink === curr) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return prev;
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMatchedPackagesSpec(pkg: string, packages: PackageList): MatchedPackage {
|
||||||
|
for (let i in packages) {
|
||||||
|
// $FlowFixMe
|
||||||
|
if (minimatch.makeRe(i).exec(pkg)) {
|
||||||
|
return packages[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalisePackageAccess(packages: PackageList): PackageList {
|
||||||
|
const normalizedPkgs: PackageList = {...packages};
|
||||||
// add a default rule for all packages to make writing plugins easier
|
// add a default rule for all packages to make writing plugins easier
|
||||||
if (_.isNil(normalizedPkgs['**'])) {
|
if (_.isNil(normalizedPkgs['**'])) {
|
||||||
normalizedPkgs['**'] = {};
|
normalizedPkgs['**'] = {};
|
||||||
|
|
|
@ -1,12 +1,25 @@
|
||||||
|
// @flow
|
||||||
|
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import minimatch from 'minimatch';
|
|
||||||
|
|
||||||
import {generateRandomHexString} from './crypto-utils';
|
import {generateRandomHexString} from './crypto-utils';
|
||||||
import {normalisePackageAccess, sanityCheckUplinksProps, uplinkSanityCheck} from './config-utils';
|
import {
|
||||||
|
getMatchedPackagesSpec,
|
||||||
|
normalisePackageAccess,
|
||||||
|
sanityCheckUplinksProps,
|
||||||
|
uplinkSanityCheck} from './config-utils';
|
||||||
import {getUserAgent, isObject} from './utils';
|
import {getUserAgent, isObject} from './utils';
|
||||||
import {APP_ERROR} from './constants';
|
import {APP_ERROR} from './constants';
|
||||||
|
|
||||||
|
import type {
|
||||||
|
PackageList,
|
||||||
|
Config as AppConfig,
|
||||||
|
Logger,
|
||||||
|
} from '@verdaccio/types';
|
||||||
|
|
||||||
|
import type {MatchedPackage, StartUpConfig} from '../../types';
|
||||||
|
|
||||||
const LoggerApi = require('./logger');
|
const LoggerApi = require('./logger');
|
||||||
const strategicConfigProps = ['uplinks', 'packages'];
|
const strategicConfigProps = ['uplinks', 'packages'];
|
||||||
const allowedEnvConfig = ['http_proxy', 'https_proxy', 'no_proxy'];
|
const allowedEnvConfig = ['http_proxy', 'https_proxy', 'no_proxy'];
|
||||||
|
@ -14,10 +27,24 @@ const allowedEnvConfig = ['http_proxy', 'https_proxy', 'no_proxy'];
|
||||||
/**
|
/**
|
||||||
* Coordinates the application configuration
|
* Coordinates the application configuration
|
||||||
*/
|
*/
|
||||||
class Config {
|
class Config implements AppConfig {
|
||||||
constructor(config) {
|
logger: Logger;
|
||||||
|
user_agent: string;
|
||||||
|
secret: string;
|
||||||
|
uplinks: any;
|
||||||
|
packages: PackageList;
|
||||||
|
users: any;
|
||||||
|
server_id: string;
|
||||||
|
self_path: string;
|
||||||
|
storage: string | void;
|
||||||
|
$key: any;
|
||||||
|
$value: any;
|
||||||
|
|
||||||
|
constructor(config: StartUpConfig) {
|
||||||
const self = this;
|
const self = this;
|
||||||
this.logger = LoggerApi.logger;
|
this.logger = LoggerApi.logger;
|
||||||
|
this.self_path = config.self_path;
|
||||||
|
this.storage = config.storage;
|
||||||
|
|
||||||
for (let configProp in config) {
|
for (let configProp in config) {
|
||||||
if (self[configProp] == null) {
|
if (self[configProp] == null) {
|
||||||
|
@ -44,7 +71,7 @@ class Config {
|
||||||
this.uplinks = sanityCheckUplinksProps(uplinkSanityCheck(this.uplinks));
|
this.uplinks = sanityCheckUplinksProps(uplinkSanityCheck(this.uplinks));
|
||||||
|
|
||||||
if (_.isNil(this.users) === false) {
|
if (_.isNil(this.users) === false) {
|
||||||
this.logger.warn(`[users]: property on configuration file
|
this.logger.warn(`[users]: property on configuration file
|
||||||
is not longer supported, property being ignored`);
|
is not longer supported, property being ignored`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,42 +90,18 @@ class Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether an uplink can proxy
|
|
||||||
* @param {String} pkg package anem
|
|
||||||
* @param {*} upLink
|
|
||||||
* @return {Boolean}
|
|
||||||
*/
|
|
||||||
hasProxyTo(pkg, upLink) {
|
|
||||||
return (this.getMatchedPackagesSpec(pkg).proxy || []).reduce(function(prev, curr) {
|
|
||||||
if (upLink === curr) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return prev;
|
|
||||||
}, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check for package spec
|
* Check for package spec
|
||||||
* @param {String} pkg package name
|
|
||||||
* @return {Object}
|
|
||||||
*/
|
*/
|
||||||
getMatchedPackagesSpec(pkg) {
|
getMatchedPackagesSpec(pkg: string): MatchedPackage {
|
||||||
for (let i in this.packages) {
|
return getMatchedPackagesSpec(pkg, this.packages);
|
||||||
if (minimatch.makeRe(i).exec(pkg)) {
|
|
||||||
return this.packages[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store or create whether recieve a secret key
|
* Store or create whether recieve a secret key
|
||||||
* @param {String} secret
|
|
||||||
* @return {String}
|
|
||||||
*/
|
*/
|
||||||
checkSecretKey(secret) {
|
checkSecretKey(secret: string): string {
|
||||||
if (_.isString(secret) && secret !== '') {
|
if (_.isString(secret) && _.isEmpty(secret) === false) {
|
||||||
this.secret = secret;
|
this.secret = secret;
|
||||||
return secret;
|
return secret;
|
||||||
}
|
}
|
||||||
|
@ -109,4 +112,4 @@ class Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Config;
|
export default Config;
|
||||||
|
|
|
@ -26,6 +26,7 @@ Callback,
|
||||||
Logger,
|
Logger,
|
||||||
} from '@verdaccio/types';
|
} from '@verdaccio/types';
|
||||||
import type {IReadTarball, IUploadTarball} from '@verdaccio/streams';
|
import type {IReadTarball, IUploadTarball} from '@verdaccio/streams';
|
||||||
|
import {hasProxyTo} from './config-utils';
|
||||||
|
|
||||||
const LoggerApi = require('../lib/logger');
|
const LoggerApi = require('../lib/logger');
|
||||||
|
|
||||||
|
@ -412,9 +413,9 @@ class Storage implements IStorageHandler {
|
||||||
packageInfo = generatePackageTemplate(name);
|
packageInfo = generatePackageTemplate(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let up in this.uplinks) {
|
for (let uplink in this.uplinks) {
|
||||||
if (this.config.hasProxyTo(name, up)) {
|
if (hasProxyTo(name, uplink, this.config.packages)) {
|
||||||
upLinks.push(this.uplinks[up]);
|
upLinks.push(this.uplinks[uplink]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ describe('Config Utilities', () => {
|
||||||
return path.join(__dirname, `../partials/config/yaml/${name}.yaml`);
|
return path.join(__dirname, `../partials/config/yaml/${name}.yaml`);
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('getMatchedPackagesSpec', () => {
|
describe('normalisePackageAccess', () => {
|
||||||
test('should test basic conversion', ()=> {
|
test('should test basic conversion', ()=> {
|
||||||
const {packages} = parseConfigFile(parsePartial('pkgs-basic'));
|
const {packages} = parseConfigFile(parsePartial('pkgs-basic'));
|
||||||
const access = normalisePackageAccess(packages);
|
const access = normalisePackageAccess(packages);
|
||||||
|
@ -58,8 +58,14 @@ describe('Config Utilities', () => {
|
||||||
const react = access['react-*'];
|
const react = access['react-*'];
|
||||||
|
|
||||||
expect(react).toBeDefined();
|
expect(react).toBeDefined();
|
||||||
|
expect(react.access).toBeDefined();
|
||||||
|
// $FlowFixMe
|
||||||
expect(react.access[0]).toBe(ROLES.$ALL);
|
expect(react.access[0]).toBe(ROLES.$ALL);
|
||||||
|
expect(react.publish).toBeDefined();
|
||||||
|
// $FlowFixMe);
|
||||||
expect(react.publish[0]).toBe('admin');
|
expect(react.publish[0]).toBe('admin');
|
||||||
|
expect(react.proxy).toBeDefined();
|
||||||
|
// $FlowFixMe
|
||||||
expect(react.proxy[0]).toBe('uplink2');
|
expect(react.proxy[0]).toBe('uplink2');
|
||||||
expect(react.storage).toBeDefined();
|
expect(react.storage).toBeDefined();
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
|
|
||||||
|
|
||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import Search from '../../../src/lib/search';
|
import Search from '../../../src/lib/search';
|
||||||
|
import Config from '../../../src/lib/config';
|
||||||
import Storage from '../../../src/lib/storage';
|
import Storage from '../../../src/lib/storage';
|
||||||
|
|
||||||
let config_hash = require('../partials/config/index');
|
let config_hash = require('../partials/config/index');
|
||||||
let Config = require('../../../src/lib/config');
|
|
||||||
|
|
||||||
require('../../../src/lib/logger').setup([]);
|
require('../../../src/lib/logger').setup([]);
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import type {
|
||||||
MergeTags,
|
MergeTags,
|
||||||
Config,
|
Config,
|
||||||
Logger,
|
Logger,
|
||||||
|
PackageAccess,
|
||||||
Package} from '@verdaccio/types';
|
Package} from '@verdaccio/types';
|
||||||
import type {
|
import type {
|
||||||
IUploadTarball,
|
IUploadTarball,
|
||||||
|
@ -95,6 +96,20 @@ export interface IStorageHandler {
|
||||||
_updateVersionsHiddenUpLink(versions: Versions, upLink: IProxy): void;
|
_updateVersionsHiddenUpLink(versions: Versions, upLink: IProxy): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// export interface ConfigHandler {
|
||||||
|
// checkSecretKey(token: string): string;
|
||||||
|
// hasProxyTo(pkg: string, upLink: string): boolean;
|
||||||
|
// getMatchedPackagesSpec(storage: string): verdaccio$PackageAccess | void;
|
||||||
|
// [key: string]: number;
|
||||||
|
// }
|
||||||
|
|
||||||
|
export type StartUpConfig = {
|
||||||
|
storage: string;
|
||||||
|
self_path: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MatchedPackage = PackageAccess | void;
|
||||||
|
|
||||||
export interface IStorage {
|
export interface IStorage {
|
||||||
config: Config;
|
config: Config;
|
||||||
localData: ILocalData;
|
localData: ILocalData;
|
||||||
|
|
BIN
yarn.lock
BIN
yarn.lock
Binary file not shown.
Loading…
Reference in a new issue