mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-12-16 21:56:25 -05:00
chore: fix unpublish issues, fix unit test
This commit is contained in:
parent
cab3596843
commit
9e17d2bc27
30 changed files with 291 additions and 366 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -6,6 +6,7 @@ build/
|
|||
### Test
|
||||
|
||||
test/unit/partials/store/test-*-storage/*
|
||||
test/unit/partials/store/storage_default_storage/*
|
||||
.verdaccio-db.json
|
||||
.sinopia-db.json
|
||||
|
||||
|
|
|
@ -86,10 +86,10 @@
|
|||
"husky": "0.15.0-rc.8",
|
||||
"identity-obj-proxy": "3.0.0",
|
||||
"in-publish": "2.0.0",
|
||||
"jest": "23.6.0",
|
||||
"jest-environment-jsdom": "23.4.0",
|
||||
"jest-environment-jsdom-global": "1.1.0",
|
||||
"jest-environment-node": "23.4.0",
|
||||
"jest": "24.1.0",
|
||||
"jest-environment-jsdom": "24.0.0",
|
||||
"jest-environment-jsdom-global": "1.1.1",
|
||||
"jest-environment-node": "24.0.0",
|
||||
"lint-staged": "7.3.0",
|
||||
"localstorage-memory": "1.0.2",
|
||||
"mini-css-extract-plugin": "0.4.3",
|
||||
|
|
|
@ -24,7 +24,7 @@ export default function publish(router: Router, auth: IAuth, storage: IStorageHa
|
|||
router.put('/:package/:_rev?/:revision?', can('publish'), media(mime.getType('json')), expectJson, publishPackage(storage, config));
|
||||
|
||||
// un-publishing an entire package
|
||||
router.delete('/:package/-rev/*', can('unpublish'), can('publish'), unPublishPackage(storage));
|
||||
router.delete('/:package/-rev/*', can('unpublish'), unPublishPackage(storage));
|
||||
|
||||
// removing a tarball
|
||||
router.delete('/:package/-/:filename/-rev/:revision', can('unpublish'), can('publish'), removeTarball(storage));
|
||||
|
|
|
@ -106,7 +106,7 @@ const defineAPI = function(config: IConfig, storage: IStorageHandler) {
|
|||
|
||||
export default (async function(configHash: any) {
|
||||
setup(configHash.logs);
|
||||
const config: IConfig = new AppConfig(configHash);
|
||||
const config: IConfig = new AppConfig(_.cloneDeep(configHash));
|
||||
const storage: IStorageHandler = new Storage(config);
|
||||
// waits until init calls have been initialized
|
||||
await storage.init(config);
|
||||
|
|
|
@ -60,6 +60,19 @@ export function allow_action(action: string) {
|
|||
};
|
||||
}
|
||||
|
||||
export function handleSpecialUnpublish() {
|
||||
return function(user: RemoteUser, pkg: Package, callback: Callback) {
|
||||
const action: string = 'unpublish';
|
||||
const hasSupport: boolean = _.isNil(pkg[action]) === false ? pkg[action] : false;
|
||||
|
||||
if (hasSupport === false) {
|
||||
return callback(null, undefined);
|
||||
}
|
||||
|
||||
return allow_action(action)(user, pkg, callback);
|
||||
};
|
||||
}
|
||||
|
||||
export function getDefaultPlugins() {
|
||||
return {
|
||||
authenticate(user: string, password: string, cb: Callback) {
|
||||
|
@ -72,7 +85,7 @@ export function getDefaultPlugins() {
|
|||
|
||||
allow_access: allow_action('access'),
|
||||
allow_publish: allow_action('publish'),
|
||||
allow_unpublish: allow_action('unpublish'),
|
||||
allow_unpublish: handleSpecialUnpublish(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -191,32 +191,32 @@ class Auth implements IAuth {
|
|||
}
|
||||
|
||||
allow_unpublish({ packageName, packageVersion }: AuthPluginPackage, user: string, callback: Callback) {
|
||||
const plugins = this.plugins.slice(0);
|
||||
const self = this;
|
||||
// $FlowFixMe
|
||||
const pkg = Object.assign({ name: packageName, version: packageVersion }, getMatchedPackagesSpec(packageName, this.config.packages));
|
||||
this.logger.trace({ packageName }, 'allow unpublish for @{packageName}');
|
||||
|
||||
(function next() {
|
||||
const plugin = plugins.shift();
|
||||
|
||||
for (const plugin of this.plugins) {
|
||||
if (_.isFunction(plugin.allow_unpublish) === false) {
|
||||
return next();
|
||||
continue;
|
||||
} else {
|
||||
plugin.allow_unpublish(user, pkg, (err, ok: boolean) => {
|
||||
if (err) {
|
||||
this.logger.trace({ packageName }, 'forbidden publish for @{packageName}, it will fallback on unpublish permissions');
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if (_.isNil(ok) === true) {
|
||||
this.logger.trace({ packageName }, 'we bypass unpublish for @{packageName}, publish will handle the access');
|
||||
return this.allow_publish(...arguments);
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
this.logger.trace({ packageName }, 'allowed unpublish for @{packageName}');
|
||||
return callback(null, ok);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
plugin.allow_unpublish(user, pkg, (err, ok: boolean) => {
|
||||
if (err) {
|
||||
self.logger.trace({ packageName }, 'forbidden unpublish for @{packageName}');
|
||||
return callback(err);
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
self.logger.trace({ packageName }, 'allowed unpublish for @{packageName}');
|
||||
return callback(null, ok);
|
||||
}
|
||||
next(); // cb(null, false) causes next plugin to roll
|
||||
});
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -123,8 +123,9 @@ export function normalisePackageAccess(packages: PackageList): PackageList {
|
|||
delete normalizedPkgs[pkg].allow_publish;
|
||||
normalizedPkgs[pkg].proxy = normalizeUserList(packages[pkg].proxy_access, packages[pkg].proxy);
|
||||
delete normalizedPkgs[pkg].proxy_access;
|
||||
// if unpublish is not defined, we set to false to fallback in publish access
|
||||
// $FlowFixMe
|
||||
normalizedPkgs[pkg].unpublish = normalizeUserList([], packages[pkg].unpublish);
|
||||
normalizedPkgs[pkg].unpublish = _.isUndefined(packages[pkg].unpublish) ? false : normalizeUserList([], packages[pkg].unpublish);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ exports[`Publish endpoints - publish package should add a new package 1`] = `
|
|||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
|
@ -40,7 +40,7 @@ exports[`Publish endpoints - publish package should change the existing package
|
|||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -14,7 +14,7 @@ exports[`Verdaccio update banner should print major update banner 1`] = `
|
|||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
|
@ -35,7 +35,7 @@ exports[`Verdaccio update banner should print minor update banner 1`] = `
|
|||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
|
@ -56,7 +56,7 @@ exports[`Verdaccio update banner should print patch update banner 1`] = `
|
|||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
|
@ -75,7 +75,7 @@ exports[`Verdaccio update banner when default registry returns with error 1`] =
|
|||
],
|
||||
"results": Array [
|
||||
Object {
|
||||
"isThrow": false,
|
||||
"type": "return",
|
||||
"value": undefined,
|
||||
},
|
||||
],
|
||||
|
|
|
@ -5,7 +5,6 @@ import _ from 'lodash';
|
|||
import path from 'path';
|
||||
import rimraf from 'rimraf';
|
||||
|
||||
import Config from '../../../src/lib/config';
|
||||
import endPointAPI from '../../../src/api/index';
|
||||
|
||||
import {HEADERS, HTTP_STATUS, HEADER_TYPE} from '../../../src/lib/constants';
|
||||
|
@ -27,7 +26,6 @@ const parseConfigurationJWTFile = () => {
|
|||
const FORBIDDEN_VUE: string = 'authorization required to access package vue';
|
||||
|
||||
describe('endpoint user auth JWT unit test', () => {
|
||||
let config;
|
||||
let app;
|
||||
let mockRegistry;
|
||||
|
||||
|
@ -36,21 +34,22 @@ describe('endpoint user auth JWT unit test', () => {
|
|||
const mockServerPort = 55546;
|
||||
rimraf(store, async () => {
|
||||
const confS = parseConfigFile(parseConfigurationJWTFile());
|
||||
const configForTest = _.clone(confS);
|
||||
configForTest.storage = store;
|
||||
configForTest.auth = {
|
||||
htpasswd: {
|
||||
file: './test-jwt-storage/.htpasswd'
|
||||
const configForTest = _.assign({}, _.cloneDeep(confS), {
|
||||
storage: store,
|
||||
plinks: {
|
||||
npmjs: {
|
||||
url: `http://${DOMAIN_SERVERS}:${mockServerPort}`
|
||||
}
|
||||
},
|
||||
self_path: store,
|
||||
auth: {
|
||||
htpasswd: {
|
||||
file: './test-jwt-storage/.htpasswd'
|
||||
}
|
||||
}
|
||||
};
|
||||
configForTest.uplinks = {
|
||||
npmjs: {
|
||||
url: `http://${DOMAIN_SERVERS}:${mockServerPort}`
|
||||
}
|
||||
};
|
||||
configForTest.self_path = store;
|
||||
config = new Config(configForTest);
|
||||
app = await endPointAPI(config);
|
||||
});
|
||||
|
||||
app = await endPointAPI(configForTest);
|
||||
mockRegistry = await mockServer(mockServerPort).init();
|
||||
done();
|
||||
});
|
||||
|
|
|
@ -5,7 +5,6 @@ import rimraf from 'rimraf';
|
|||
|
||||
import { HEADERS, HTTP_STATUS } from '../../../src/lib/constants';
|
||||
import configDefault from '../partials/config/config_access';
|
||||
import Config from '../../../src/lib/config';
|
||||
import endPointAPI from '../../../src/api/index';
|
||||
import {mockServer} from './mock';
|
||||
import {DOMAIN_SERVERS} from '../../functional/config.functional';
|
||||
|
@ -13,7 +12,6 @@ import {DOMAIN_SERVERS} from '../../functional/config.functional';
|
|||
require('../../../src/lib/logger').setup([]);
|
||||
|
||||
describe('api with no limited access configuration', () => {
|
||||
let config;
|
||||
let app;
|
||||
let mockRegistry;
|
||||
|
||||
|
@ -21,20 +19,21 @@ describe('api with no limited access configuration', () => {
|
|||
const mockServerPort = 55530;
|
||||
const store = path.join(__dirname, './partials/store/access-storage');
|
||||
rimraf(store, async () => {
|
||||
const configForTest = _.clone(configDefault);
|
||||
configForTest.auth = {
|
||||
htpasswd: {
|
||||
file: './access-storage/htpasswd-access-test'
|
||||
const configForTest = _.assign({}, _.cloneDeep(configDefault), {
|
||||
auth: {
|
||||
htpasswd: {
|
||||
file: './access-storage/htpasswd-access-test'
|
||||
}
|
||||
},
|
||||
self_path: store,
|
||||
uplinks: {
|
||||
npmjs: {
|
||||
url: `http://${DOMAIN_SERVERS}:${mockServerPort}`
|
||||
}
|
||||
}
|
||||
};
|
||||
configForTest.self_path = store;
|
||||
configForTest.uplinks = {
|
||||
npmjs: {
|
||||
url: `http://${DOMAIN_SERVERS}:${mockServerPort}`
|
||||
}
|
||||
};
|
||||
config = new Config(configForTest);
|
||||
app = await endPointAPI(config);
|
||||
});
|
||||
|
||||
app = await endPointAPI(configForTest);
|
||||
mockRegistry = await mockServer(mockServerPort).init();
|
||||
done();
|
||||
});
|
||||
|
|
|
@ -5,7 +5,6 @@ import _ from 'lodash';
|
|||
import path from 'path';
|
||||
import rimraf from 'rimraf';
|
||||
|
||||
import Config from '../../../src/lib/config';
|
||||
import endPointAPI from '../../../src/api/index';
|
||||
import {mockServer} from './mock';
|
||||
import {parseConfigFile} from '../../../src/lib/utils';
|
||||
|
@ -22,7 +21,6 @@ const parseConfigurationProfile = () => {
|
|||
|
||||
|
||||
describe('endpoint user profile', () => {
|
||||
let config;
|
||||
let app;
|
||||
let mockRegistry;
|
||||
|
||||
|
@ -31,16 +29,16 @@ describe('endpoint user profile', () => {
|
|||
const mockServerPort = 55544;
|
||||
rimraf(store, async () => {
|
||||
const parsedConfig = parseConfigFile(parseConfigurationProfile());
|
||||
const configForTest = _.clone(parsedConfig);
|
||||
configForTest.storage = store;
|
||||
configForTest.auth = {
|
||||
htpasswd: {
|
||||
file: './test-profile-storage/.htpasswd'
|
||||
}
|
||||
};
|
||||
configForTest.self_path = store;
|
||||
config = new Config(configForTest);
|
||||
app = await endPointAPI(config);
|
||||
const configForTest = _.assign({}, _.cloneDeep(parsedConfig), {
|
||||
storage: store,
|
||||
auth: {
|
||||
htpasswd: {
|
||||
file: './test-profile-storage/.htpasswd'
|
||||
}
|
||||
},
|
||||
self_path: store
|
||||
});
|
||||
app = await endPointAPI(configForTest);
|
||||
mockRegistry = await mockServer(mockServerPort).init();
|
||||
done();
|
||||
});
|
||||
|
|
|
@ -5,39 +5,40 @@ import rimraf from 'rimraf';
|
|||
|
||||
import configDefault from '../partials/config/index';
|
||||
import publishMetadata from '../partials/publish-api';
|
||||
import Config from '../../../src/lib/config';
|
||||
import endPointAPI from '../../../src/api/index';
|
||||
|
||||
import { HEADERS, API_ERROR, HTTP_STATUS, HEADER_TYPE, API_MESSAGE} from '../../../src/lib/constants';
|
||||
import {HEADERS, API_ERROR, HTTP_STATUS, HEADER_TYPE, API_MESSAGE, TOKEN_BEARER} from '../../../src/lib/constants';
|
||||
import {mockServer} from './mock';
|
||||
import {DOMAIN_SERVERS} from '../../functional/config.functional';
|
||||
import {buildToken} from '../../../src/lib/utils';
|
||||
|
||||
require('../../../src/lib/logger').setup([]);
|
||||
const credentials = { name: 'jota', password: 'secretPass' };
|
||||
|
||||
describe('endpoint unit test', () => {
|
||||
let config;
|
||||
let app;
|
||||
let mockRegistry;
|
||||
|
||||
beforeAll(function(done) {
|
||||
const store = path.join(__dirname, '../partials/store/test-storage');
|
||||
const store = path.join(__dirname, '../store/test-storage-api-spec');
|
||||
const mockServerPort = 55549;
|
||||
rimraf(store, async () => {
|
||||
const configForTest = _.clone(configDefault);
|
||||
configForTest.auth = {
|
||||
htpasswd: {
|
||||
file: './test-storage/.htpasswd'
|
||||
const configForTest = configDefault({
|
||||
auth: {
|
||||
htpasswd: {
|
||||
file: './test-storage-api-spec/.htpasswd'
|
||||
}
|
||||
},
|
||||
storage: store,
|
||||
self_path: store,
|
||||
uplinks: {
|
||||
npmjs: {
|
||||
url: `http://${DOMAIN_SERVERS}:${mockServerPort}`
|
||||
}
|
||||
}
|
||||
};
|
||||
configForTest.uplinks = {
|
||||
npmjs: {
|
||||
url: `http://${DOMAIN_SERVERS}:${mockServerPort}`
|
||||
}
|
||||
};
|
||||
configForTest.self_path = store;
|
||||
config = new Config(configForTest);
|
||||
app = await endPointAPI(config);
|
||||
}, 'api.spec.yaml');
|
||||
|
||||
app = await endPointAPI(configForTest);
|
||||
mockRegistry = await mockServer(mockServerPort).init();
|
||||
done();
|
||||
});
|
||||
|
@ -157,7 +158,7 @@ describe('endpoint unit test', () => {
|
|||
// we need it here, because token is required
|
||||
request(app)
|
||||
.get('/vue')
|
||||
.set('authorization', `Bearer ${token}`)
|
||||
.set('authorization', buildToken(TOKEN_BEARER, token))
|
||||
.expect(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON_CHARSET)
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.end(function(err, res) {
|
||||
|
@ -171,7 +172,7 @@ describe('endpoint unit test', () => {
|
|||
|
||||
test('should test fails add a new user with missing name', (done) => {
|
||||
|
||||
const credentialsShort = _.clone(credentials);
|
||||
const credentialsShort = _.cloneDeep(credentials);
|
||||
delete credentialsShort.name;
|
||||
|
||||
request(app)
|
||||
|
@ -192,7 +193,7 @@ describe('endpoint unit test', () => {
|
|||
|
||||
test('should test fails add a new user with missing password', (done) => {
|
||||
|
||||
const credentialsShort = _.clone(credentials);
|
||||
const credentialsShort = _.cloneDeep(credentials);
|
||||
delete credentialsShort.password;
|
||||
|
||||
request(app)
|
||||
|
@ -213,7 +214,7 @@ describe('endpoint unit test', () => {
|
|||
});
|
||||
|
||||
test('should test add a new user with login', (done) => {
|
||||
const newCredentials = _.clone(credentials);
|
||||
const newCredentials = _.cloneDeep(credentials);
|
||||
newCredentials.name = 'jotaNew';
|
||||
|
||||
request(app)
|
||||
|
@ -248,7 +249,7 @@ describe('endpoint unit test', () => {
|
|||
|
||||
test('should test fails add a new user with wrong password', (done) => {
|
||||
|
||||
const credentialsShort = _.clone(credentials);
|
||||
const credentialsShort = _.cloneDeep(credentials);
|
||||
credentialsShort.password = 'failPassword';
|
||||
|
||||
request(app)
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
import request from 'supertest';
|
||||
import _ from 'lodash';
|
||||
import path from 'path';
|
||||
import rimraf from 'rimraf';
|
||||
|
||||
import configDefault from '../partials/config/index';
|
||||
import publishMetadata from '../partials/publish-api';
|
||||
import forbiddenPlace from '../partials/forbidden-place';
|
||||
import Config from '../../../src/lib/config';
|
||||
import endPointAPI from '../../../src/api/index';
|
||||
|
||||
import { HEADERS, API_ERROR, HTTP_STATUS, HEADER_TYPE, DIST_TAGS} from '../../../src/lib/constants';
|
||||
|
@ -18,7 +16,6 @@ require('../../../src/lib/logger').setup([]);
|
|||
|
||||
const credentials = { name: 'user-web', password: 'secretPass' };
|
||||
describe('endpoint web unit test', () => {
|
||||
let config;
|
||||
let app;
|
||||
let mockRegistry;
|
||||
|
||||
|
@ -26,21 +23,21 @@ describe('endpoint web unit test', () => {
|
|||
const store = path.join(__dirname, '../store/test-storage-web');
|
||||
const mockServerPort = 55544;
|
||||
rimraf(store, async () => {
|
||||
const configForTest = _.clone(configDefault);
|
||||
configForTest.auth = {
|
||||
htpasswd: {
|
||||
file: './test-storage-web/.htpasswd'
|
||||
}
|
||||
};
|
||||
configForTest.storage = path.join(__dirname, '../store/test-storage-web');
|
||||
configForTest.uplinks = {
|
||||
npmjs: {
|
||||
url: `http://${DOMAIN_SERVERS}:${mockServerPort}`
|
||||
}
|
||||
};
|
||||
configForTest.self_path = store;
|
||||
config = new Config(configForTest);
|
||||
app = await endPointAPI(config);
|
||||
const configForTest = configDefault({
|
||||
auth: {
|
||||
htpasswd: {
|
||||
file: './test-storage-web/.htpasswd'
|
||||
}
|
||||
},
|
||||
storage: path.join(__dirname, '../store/test-storage-web'),
|
||||
uplinks: {
|
||||
npmjs: {
|
||||
url: `http://${DOMAIN_SERVERS}:${mockServerPort}`
|
||||
}
|
||||
},
|
||||
self_path: store
|
||||
}, 'api.web.spec.yaml');
|
||||
app = await endPointAPI(configForTest);
|
||||
mockRegistry = await mockServer(mockServerPort).init();
|
||||
done();
|
||||
});
|
||||
|
@ -52,7 +49,7 @@ describe('endpoint web unit test', () => {
|
|||
});
|
||||
|
||||
describe('Registry WebUI endpoints', () => {
|
||||
beforeAll(async function() {
|
||||
beforeAll(async () => {
|
||||
await request(app)
|
||||
.put('/@scope%2fpk1-test')
|
||||
.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.JSON)
|
||||
|
|
|
@ -22,7 +22,7 @@ import {parseConfigurationFile} from '../__helper';
|
|||
import type {IAuth, } from '../../../types/index';
|
||||
import type {Config, Security, RemoteUser} from '@verdaccio/types';
|
||||
|
||||
setup(configExample.logs);
|
||||
setup([]);
|
||||
|
||||
describe('Auth utilities', () => {
|
||||
const parseConfigurationSecurityFile = (name) => {
|
||||
|
@ -31,7 +31,7 @@ describe('Auth utilities', () => {
|
|||
|
||||
function getConfig(configFileName: string, secret: string) {
|
||||
const conf = parseConfigFile(parseConfigurationSecurityFile(configFileName));
|
||||
const secConf= _.merge(configExample, conf);
|
||||
const secConf= _.merge(configExample(), conf);
|
||||
secConf.secret = secret;
|
||||
const config: Config = new AppConfig(secConf);
|
||||
|
||||
|
|
|
@ -1,26 +1,31 @@
|
|||
import _ from 'lodash';
|
||||
// @flow
|
||||
|
||||
import Auth from '../../../src/lib/auth';
|
||||
// $FlowFixMe
|
||||
import configExample from '../partials/config/index';
|
||||
import _configExample from '../partials/config/index';
|
||||
// $FlowFixMe
|
||||
import configPlugins from '../partials/config/plugin';
|
||||
import _configPlugins from '../partials/config/plugin';
|
||||
import AppConfig from '../../../src/lib/config';
|
||||
import {setup} from '../../../src/lib/logger';
|
||||
|
||||
import type {IAuth} from '../../../types/index';
|
||||
import type {Config} from '@verdaccio/types';
|
||||
|
||||
const authConfig = Object.assign({}, configExample);
|
||||
// avoid noisy log output
|
||||
authConfig.logs = [{type: 'stdout', format: 'pretty', level: 'error'}];
|
||||
|
||||
setup(configExample.logs);
|
||||
setup([]);
|
||||
|
||||
describe('AuthTest', () => {
|
||||
let configExample;
|
||||
let configPlugins;
|
||||
|
||||
beforeEach(() => {
|
||||
configExample = _configExample({
|
||||
logs: [{type: 'stdout', format: 'pretty', level: 'error'}]
|
||||
});
|
||||
configPlugins = _.cloneDeep(_configPlugins);
|
||||
});
|
||||
|
||||
test('should be defined', () => {
|
||||
const config: Config = new AppConfig(authConfig);
|
||||
const config: Config = new AppConfig(configExample);
|
||||
const auth: IAuth = new Auth(config);
|
||||
|
||||
expect(auth).toBeDefined();
|
||||
|
|
|
@ -18,7 +18,7 @@ describe('basic system test', () => {
|
|||
|
||||
beforeAll(async function(done) {
|
||||
|
||||
app.use(await endPointAPI(config));
|
||||
app.use(await endPointAPI(config()));
|
||||
|
||||
server.listen(0, function() {
|
||||
port = server.address().port;
|
||||
|
|
|
@ -27,7 +27,7 @@ describe('startServer via API', () => {
|
|||
const version = '1.0.0';
|
||||
const port = '6000';
|
||||
|
||||
await startServer(_.clone(config), port, store, version, serverName,
|
||||
await startServer(config(), port, store, version, serverName,
|
||||
(webServer, addrs, pkgName, pkgVersion) => {
|
||||
expect(webServer).toBeDefined();
|
||||
expect(addrs).toBeDefined();
|
||||
|
@ -49,7 +49,7 @@ describe('startServer via API', () => {
|
|||
const address = 'https://www.domain.com:443';
|
||||
const realProcess = process;
|
||||
|
||||
const conf = _.clone(config);
|
||||
const conf = config();
|
||||
conf.https = {};
|
||||
// save process to catch exist
|
||||
const exitMock = jest.fn();
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import rimRaf from 'rimraf';
|
||||
import path from 'path';
|
||||
|
||||
import LocalStorage from '../../../src/lib/local-storage';
|
||||
import AppConfig from '../../../src/lib/config';
|
||||
// $FlowFixMe
|
||||
|
@ -27,8 +28,10 @@ describe('LocalStorage', () => {
|
|||
const tarballName2: string = `${pkgName}-add-tarball-1.0.5.tgz`;
|
||||
|
||||
const getStorage = (LocalStorageClass = LocalStorage) => {
|
||||
const config: Config = new AppConfig(configExample);
|
||||
config.self_path = path.join('../partials/store');
|
||||
const config: Config = new AppConfig(configExample({
|
||||
self_path: path.join('../partials/store')
|
||||
}));
|
||||
|
||||
return new LocalStorageClass(config, Logger.logger);
|
||||
}
|
||||
|
||||
|
@ -262,7 +265,7 @@ describe('LocalStorage', () => {
|
|||
// $FlowFixMe
|
||||
MockLocalStorage.prototype._writePackage = jest.fn(LocalStorage.prototype._writePackage)
|
||||
_storage = getStorage(MockLocalStorage);
|
||||
rimRaf(path.join(configExample.storage, pkgName), async () => {
|
||||
rimRaf(path.join(configExample().storage, pkgName), async () => {
|
||||
await addPackageToStore(pkgName, generatePackageTemplate(pkgName));
|
||||
await addNewVersion(pkgName, '1.0.1');
|
||||
await addNewVersion(pkgName, version);
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import Search from '../../../src/lib/search';
|
||||
import Config from '../../../src/lib/config';
|
||||
import Storage from '../../../src/lib/storage';
|
||||
|
||||
let config_hash = require('../partials/config/index');
|
||||
import buildConfig from '../partials/config/index';
|
||||
|
||||
|
||||
require('../../../src/lib/logger').setup([]);
|
||||
|
@ -33,7 +32,7 @@ let packages = [
|
|||
|
||||
describe('search', () => {
|
||||
beforeAll(async function() {
|
||||
let config = new Config(config_hash);
|
||||
let config = new Config(buildConfig());
|
||||
this.storage = new Storage(config);
|
||||
await this.storage.init(config);
|
||||
Search.configureStorage(this.storage);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// @flow
|
||||
|
||||
import _ from 'lodash';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import rimraf from 'rimraf';
|
||||
|
@ -16,19 +15,21 @@ import {API_ERROR, HTTP_STATUS} from '../../../src/lib/constants';
|
|||
import {mockServer} from './mock';
|
||||
import {DOMAIN_SERVERS} from '../../functional/config.functional';
|
||||
|
||||
setup(configExample.logs);
|
||||
setup([]);
|
||||
|
||||
const storagePath = path.join(__dirname, '../partials/store/test-storage-store.spec');
|
||||
const mockServerPort: number = 55548;
|
||||
const generateStorage = async function(port = mockServerPort, configDefault = configExample) {
|
||||
const storageConfig = _.clone(configDefault);
|
||||
storageConfig.self_path = __dirname;
|
||||
storageConfig.storage = storagePath;
|
||||
storageConfig.uplinks = {
|
||||
npmjs: {
|
||||
url: `http://${DOMAIN_SERVERS}:${port}`
|
||||
const generateStorage = async function(port = mockServerPort) {
|
||||
const storageConfig = configExample({
|
||||
self_path: __dirname,
|
||||
storage: storagePath,
|
||||
uplinks: {
|
||||
npmjs: {
|
||||
url: `http://${DOMAIN_SERVERS}:${port}`
|
||||
}
|
||||
}
|
||||
};
|
||||
}, 'store.spec.yaml');
|
||||
|
||||
const config: Config = new AppConfig(storageConfig);
|
||||
const store: IStorageHandler = new Storage(config);
|
||||
await store.init(config);
|
||||
|
@ -100,11 +101,14 @@ describe('StorageTest', () => {
|
|||
const storage: IStorageHandler = await generateStorage();
|
||||
const metadataSource = path.join(__dirname, '../partials/metadata');
|
||||
const metadataPath = path.join(storagePath, 'npm_test/package.json');
|
||||
|
||||
fs.mkdirSync(path.join(storagePath, 'npm_test'));
|
||||
fs.writeFileSync(metadataPath, fs.readFileSync(metadataSource));
|
||||
const metadata = JSON.parse(fs.readFileSync(metadataPath).toString());
|
||||
// $FlowFixMe
|
||||
storage.localStorage.updateVersions = jest.fn(storage.localStorage.updateVersions);
|
||||
expect(metadata).toBeDefined();
|
||||
console.log("M-->", metadata);
|
||||
storage._syncUplinksMetadata('npm_test', metadata, {}, (err) => {
|
||||
expect(err).toBeNull();
|
||||
expect(storage.localStorage.updateVersions).not.toHaveBeenCalled();
|
||||
|
|
|
@ -21,7 +21,7 @@ describe('UpStorge', () => {
|
|||
url: `http://0.0.0.0:${mockServerPort}`
|
||||
};
|
||||
const generateProxy = (config: UpLinkConf = uplinkDefault) => {
|
||||
const appConfig: Config = new AppConfig(configExample);
|
||||
const appConfig: Config = new AppConfig(configExample());
|
||||
|
||||
return new ProxyStorage(config, appConfig);
|
||||
};
|
||||
|
|
|
@ -1,59 +1,12 @@
|
|||
|
||||
import _ from 'lodash';
|
||||
import path from 'path';
|
||||
import {parseConfigFile} from '../../../../src/lib/utils';
|
||||
|
||||
const config = {
|
||||
storage: path.join(__dirname, '../store/test-storage'),
|
||||
uplinks: {
|
||||
'npmjs': {
|
||||
'url': 'http://localhost:4873/'
|
||||
}
|
||||
},
|
||||
packages: {
|
||||
'@*/*': {
|
||||
access: '$all',
|
||||
publish: '$all',
|
||||
proxy: 'npmjs'
|
||||
},
|
||||
|
||||
'forbidden-place': {
|
||||
access: 'nobody',
|
||||
publish: '$all'
|
||||
},
|
||||
|
||||
'react': {
|
||||
access: '$all',
|
||||
publish: '$all',
|
||||
proxy: 'npmjs'
|
||||
},
|
||||
|
||||
'corrupted-package': {
|
||||
access: '$all',
|
||||
publish: '$all',
|
||||
proxy: 'npmjs'
|
||||
},
|
||||
|
||||
'jquery': {
|
||||
access: '$all',
|
||||
publish: '$all',
|
||||
proxy: 'npmjs'
|
||||
},
|
||||
'auth-package': {
|
||||
access: '$authenticated',
|
||||
publish: '$authenticated'
|
||||
},
|
||||
'vue': {
|
||||
access: '$authenticated',
|
||||
publish: '$authenticated',
|
||||
proxy: 'npmjs'
|
||||
},
|
||||
'*': {
|
||||
access: '$all',
|
||||
publish: '$all'
|
||||
},
|
||||
},
|
||||
logs: [
|
||||
{type: 'stdout', format: 'pretty', level: 'warn'},
|
||||
],
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
export default (options, url = 'default.yaml') => {
|
||||
const locationFile = path.join(__dirname, `../config/yaml/${url}`);
|
||||
const config = parseConfigFile(locationFile);
|
||||
|
||||
return _.assign({}, _.cloneDeep(config), options);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
|
||||
import path from 'path';
|
||||
import config from './index';
|
||||
|
||||
module.exports = {
|
||||
...require('./index'),
|
||||
...config(),
|
||||
auth: {
|
||||
[`${path.join(__dirname, '../plugin/authenticate')}`]: { }
|
||||
}
|
||||
|
|
31
test/unit/partials/config/yaml/api.spec.yaml
Normal file
31
test/unit/partials/config/yaml/api.spec.yaml
Normal file
|
@ -0,0 +1,31 @@
|
|||
storage: ./storage_default_storage
|
||||
uplinks:
|
||||
npmjs:
|
||||
url: http://localhost:4873/
|
||||
packages:
|
||||
'@*/*':
|
||||
access: $all
|
||||
publish: $all
|
||||
unpublish: $all
|
||||
proxy: npmjs
|
||||
'auth-package':
|
||||
access: $authenticated
|
||||
publish: $authenticated
|
||||
'forbidden-place':
|
||||
access: nobody
|
||||
publish: $all
|
||||
'vue':
|
||||
access: $authenticated
|
||||
publish: $authenticated
|
||||
proxy: npmjs
|
||||
'jquery':
|
||||
access: $all
|
||||
publish: $all
|
||||
proxy: npmjs
|
||||
'*':
|
||||
access: $all
|
||||
publish: $all
|
||||
unpublish: xxx
|
||||
proxy: npmjs
|
||||
logs:
|
||||
- { type: stdout, format: pretty, level: error }
|
20
test/unit/partials/config/yaml/api.web.spec.yaml
Normal file
20
test/unit/partials/config/yaml/api.web.spec.yaml
Normal file
|
@ -0,0 +1,20 @@
|
|||
storage: ./storage_default_storage
|
||||
uplinks:
|
||||
npmjs:
|
||||
url: http://localhost:4873/
|
||||
packages:
|
||||
'@*/*':
|
||||
access: $all
|
||||
publish: $all
|
||||
proxy: npmjs
|
||||
unpublish: npmjs
|
||||
'forbidden-place':
|
||||
access: nobody
|
||||
publish: $all
|
||||
'*':
|
||||
access: $all
|
||||
publish: $all
|
||||
unpublish: xxx
|
||||
proxy: npmjs
|
||||
logs:
|
||||
- { type: stdout, format: pretty, level: warn }
|
38
test/unit/partials/config/yaml/default.yaml
Normal file
38
test/unit/partials/config/yaml/default.yaml
Normal file
|
@ -0,0 +1,38 @@
|
|||
storage: ./storage_default_storage
|
||||
|
||||
uplinks:
|
||||
npmjs:
|
||||
url: http://localhost:4873/
|
||||
packages:
|
||||
'@*/*':
|
||||
access: $all
|
||||
publish: $all
|
||||
proxy: npmjs
|
||||
'forbidden-place':
|
||||
access: nobody
|
||||
publish: $all
|
||||
'react':
|
||||
access: $all
|
||||
publish: $all
|
||||
proxy: npmjs
|
||||
'corrupted-package':
|
||||
access: $all
|
||||
publish: $all
|
||||
proxy: npmjs
|
||||
'jquery':
|
||||
access: $all
|
||||
publish: $all
|
||||
proxy: npmjs
|
||||
'auth-package':
|
||||
access: $authenticated
|
||||
publish: $authenticated
|
||||
'vue':
|
||||
access: $authenticated
|
||||
publish: $authenticated
|
||||
proxy: npmjs
|
||||
'*':
|
||||
access: $all
|
||||
publish: $all
|
||||
proxy: npmjs
|
||||
logs:
|
||||
- { type: stdout, format: pretty, level: warn }
|
22
test/unit/partials/config/yaml/store.spec.yaml
Normal file
22
test/unit/partials/config/yaml/store.spec.yaml
Normal file
|
@ -0,0 +1,22 @@
|
|||
uplinks:
|
||||
npmjs:
|
||||
url: http://localhost:4873/
|
||||
packages:
|
||||
'@*/*':
|
||||
access: $all
|
||||
publish: $all
|
||||
proxy: npmjs
|
||||
'corrupted-package':
|
||||
access: $all
|
||||
publish: $all
|
||||
proxy: npmjs
|
||||
'jquery':
|
||||
access: $all
|
||||
publish: $all
|
||||
proxy: npmjs
|
||||
'*':
|
||||
access: $all
|
||||
publish: $all
|
||||
proxy: npmjs
|
||||
logs:
|
||||
- { type: stdout, format: pretty, level: warn }
|
|
@ -1,163 +1,3 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`<NotFound /> component should load the component in default state 1`] = `
|
||||
ShallowWrapper {
|
||||
Symbol(enzyme.__root__): ShallowWrapper {
|
||||
Symbol(enzyme.__root__): [Circular],
|
||||
Symbol(enzyme.__unrendered__): <BrowserRouter>
|
||||
<withRouter(WithTheme(WithWidth(NotFound))) />
|
||||
</BrowserRouter>,
|
||||
Symbol(enzyme.__renderer__): Object {
|
||||
"batchedUpdates": [Function],
|
||||
"getNode": [Function],
|
||||
"render": [Function],
|
||||
"simulateError": [Function],
|
||||
"simulateEvent": [Function],
|
||||
"unmount": [Function],
|
||||
},
|
||||
Symbol(enzyme.__node__): Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": <withRouter(WithTheme(WithWidth(NotFound))) />,
|
||||
"history": Object {
|
||||
"action": "POP",
|
||||
"block": [Function],
|
||||
"createHref": [Function],
|
||||
"go": [Function],
|
||||
"goBack": [Function],
|
||||
"goForward": [Function],
|
||||
"length": 1,
|
||||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
"push": [Function],
|
||||
"replace": [Function],
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "function",
|
||||
"props": Object {},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
"type": [Function],
|
||||
},
|
||||
Symbol(enzyme.__nodes__): Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "class",
|
||||
"props": Object {
|
||||
"children": <withRouter(WithTheme(WithWidth(NotFound))) />,
|
||||
"history": Object {
|
||||
"action": "POP",
|
||||
"block": [Function],
|
||||
"createHref": [Function],
|
||||
"go": [Function],
|
||||
"goBack": [Function],
|
||||
"goForward": [Function],
|
||||
"length": 1,
|
||||
"listen": [Function],
|
||||
"location": Object {
|
||||
"hash": "",
|
||||
"pathname": "/",
|
||||
"search": "",
|
||||
"state": undefined,
|
||||
},
|
||||
"push": [Function],
|
||||
"replace": [Function],
|
||||
},
|
||||
},
|
||||
"ref": null,
|
||||
"rendered": Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "function",
|
||||
"props": Object {},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
Symbol(enzyme.__options__): Object {
|
||||
"adapter": ReactSixteenAdapter {
|
||||
"options": Object {
|
||||
"enableComponentDidUpdateOnSetState": true,
|
||||
"lifecycles": Object {
|
||||
"componentDidUpdate": Object {
|
||||
"onSetState": true,
|
||||
},
|
||||
"getDerivedStateFromProps": true,
|
||||
"getSnapshotBeforeUpdate": true,
|
||||
"setState": Object {
|
||||
"skipsComponentDidUpdateOnNullish": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"attachTo": undefined,
|
||||
"hydrateIn": undefined,
|
||||
},
|
||||
},
|
||||
Symbol(enzyme.__unrendered__): null,
|
||||
Symbol(enzyme.__renderer__): Object {
|
||||
"batchedUpdates": [Function],
|
||||
"getNode": [Function],
|
||||
"render": [Function],
|
||||
"simulateError": [Function],
|
||||
"simulateEvent": [Function],
|
||||
"unmount": [Function],
|
||||
},
|
||||
Symbol(enzyme.__node__): Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "function",
|
||||
"props": Object {},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
Symbol(enzyme.__nodes__): Array [
|
||||
Object {
|
||||
"instance": null,
|
||||
"key": undefined,
|
||||
"nodeType": "function",
|
||||
"props": Object {},
|
||||
"ref": null,
|
||||
"rendered": null,
|
||||
"type": [Function],
|
||||
},
|
||||
],
|
||||
Symbol(enzyme.__options__): Object {
|
||||
"adapter": ReactSixteenAdapter {
|
||||
"options": Object {
|
||||
"enableComponentDidUpdateOnSetState": true,
|
||||
"lifecycles": Object {
|
||||
"componentDidUpdate": Object {
|
||||
"onSetState": true,
|
||||
},
|
||||
"getDerivedStateFromProps": true,
|
||||
"getSnapshotBeforeUpdate": true,
|
||||
"setState": Object {
|
||||
"skipsComponentDidUpdateOnNullish": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"attachTo": undefined,
|
||||
"hydrateIn": undefined,
|
||||
},
|
||||
}
|
||||
`;
|
||||
exports[`<NotFound /> component should load the component in default state 1`] = `ShallowWrapper {}`;
|
||||
|
|
BIN
yarn.lock
BIN
yarn.lock
Binary file not shown.
Loading…
Reference in a new issue