mirror of
https://github.com/verdaccio/verdaccio.git
synced 2025-04-08 02:54:13 -05:00
fix: eslint errors (#1973)
* fix: eslint errors * fix: rename a test * fix: broken integration test due to removing next argument in the middleware. * changeset
This commit is contained in:
parent
a4667f3440
commit
31af01641f
53 changed files with 389 additions and 243 deletions
34
.changeset/three-pots-sit.md
Normal file
34
.changeset/three-pots-sit.md
Normal file
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
'@verdaccio/api': patch
|
||||
'@verdaccio/auth': patch
|
||||
'@verdaccio/cli': patch
|
||||
'@verdaccio/dev-commons': patch
|
||||
'@verdaccio/config': patch
|
||||
'@verdaccio/commons-api': patch
|
||||
'@verdaccio/file-locking': patch
|
||||
'@verdaccio/htpasswd': patch
|
||||
'@verdaccio/local-storage': patch
|
||||
'@verdaccio/readme': patch
|
||||
'@verdaccio/types': patch
|
||||
'@verdaccio/hooks': patch
|
||||
'@verdaccio/loaders': patch
|
||||
'@verdaccio/logger': patch
|
||||
'@verdaccio/logger-prettify': patch
|
||||
'@verdaccio/middleware': patch
|
||||
'@verdaccio/mock': patch
|
||||
'@verdaccio/node-api': patch
|
||||
'@verdaccio/proxy': patch
|
||||
'@verdaccio/server': patch
|
||||
'@verdaccio/store': patch
|
||||
'@verdaccio/dev-types': patch
|
||||
'@verdaccio/utils': patch
|
||||
'verdaccio': patch
|
||||
---
|
||||
|
||||
ESLint Warnings Fixed
|
||||
|
||||
Related to issue #1461
|
||||
|
||||
- max-len: most of the sensible max-len errors are fixed
|
||||
- no-unused-vars: most of these types of errors are fixed by deleting not needed declarations
|
||||
- @typescript-eslint/no-unused-vars: same as above
|
|
@ -57,31 +57,36 @@ export default function publish(
|
|||
*
|
||||
* Unpublish consist in 3 steps.
|
||||
* 1. Try to fetch metadata -> if it fails, return 404
|
||||
* 2. Compute metadata locally (client side) and send a mutate payload excluding the version to be unpublished
|
||||
* 2. Compute metadata locally (client side) and send a mutate payload excluding the version to
|
||||
* be unpublished
|
||||
* eg: if metadata reflects 1.0.1, 1.0.2 and 1.0.3, the computed metadata won't include 1.0.3.
|
||||
* 3. Once the second step has been successfully finished, delete the tarball.
|
||||
*
|
||||
* All these steps are consecutive and required, there is no transacions here, if step 3 fails, metadata might
|
||||
* get corrupted.
|
||||
* All these steps are consecutive and required, there is no transacions here, if step 3 fails,
|
||||
* metadata might get corrupted.
|
||||
*
|
||||
* Note the unpublish call will suffix in the url a /-rev/14-5d500cfce92f90fd revision number, this not
|
||||
* Note the unpublish call will suffix in the url a /-rev/14-5d500cfce92f90fd revision number,
|
||||
* this not
|
||||
* used internally.
|
||||
*
|
||||
*
|
||||
* Example flow of unpublish.
|
||||
*
|
||||
* npm http fetch GET 200 http://localhost:4873/@scope%2ftest1?write=true 1680ms
|
||||
npm http fetch PUT 201 http://localhost:4873/@scope%2ftest1/-rev/14-5d500cfce92f90fd 956606ms attempt #2
|
||||
npm http fetch GET 200 http://localhost:4873/@scope%2ftest1?write=true 1601ms
|
||||
npm http fetch DELETE 201 http://localhost:4873/@scope%2ftest1/-/test1-1.0.3.tgz/-rev/16-e11c8db282b2d992 19ms
|
||||
* npm http fetch PUT 201 http://localhost:4873/@scope%2ftest1/-rev/14-5d500cfce92f90fd
|
||||
* 956606ms attempt #2
|
||||
* npm http fetch GET 200 http://localhost:4873/@scope%2ftest1?write=true 1601ms
|
||||
* npm http fetch DELETE 201 http://localhost:4873/@scope%2ftest1/-/test1-1.0.3.tgz/-rev/16
|
||||
* -e11c8db282b2d992 19ms
|
||||
*
|
||||
* 3. Star a package
|
||||
*
|
||||
* Permissions: start a package depends of the publish and unpublish permissions, there is no specific flag for star or un start.
|
||||
* Permissions: start a package depends of the publish and unpublish permissions, there is no
|
||||
* specific flag for star or un start.
|
||||
* The URL for star is similar to the unpublish (change package format)
|
||||
*
|
||||
* npm has no enpoint for star a package, rather mutate the metadata and acts as, the difference is the
|
||||
* users property which is part of the payload and the body only includes
|
||||
* npm has no enpoint for star a package, rather mutate the metadata and acts as, the difference
|
||||
* is the users property which is part of the payload and the body only includes
|
||||
*
|
||||
* {
|
||||
"_id": pkgName,
|
||||
|
@ -209,9 +214,12 @@ export function publishPackage(storage: IStorageHandler, config: Config, auth: I
|
|||
});
|
||||
}
|
||||
|
||||
// npm-registry-client 0.3+ embeds tarball into the json upload
|
||||
// https://github.com/isaacs/npm-registry-client/commit/e9fbeb8b67f249394f735c74ef11fe4720d46ca0
|
||||
// issue https://github.com/rlidwka/sinopia/issues/31, dealing with it here:
|
||||
/**
|
||||
* npm-registry-client 0.3+ embeds tarball into the json upload
|
||||
* https://github.com/isaacs/npm-registry-client/commit/e9fbeb8b67f249394f735c74ef11fe4720d46ca0
|
||||
* issue https://github.com/rlidwka/sinopia/issues/31, dealing with it here:
|
||||
*/
|
||||
|
||||
const isInvalidBodyFormat =
|
||||
isObject(_attachments) === false ||
|
||||
hasDiffOneKey(_attachments) ||
|
||||
|
|
|
@ -4,7 +4,7 @@ import _ from 'lodash';
|
|||
import buildDebug from 'debug';
|
||||
|
||||
import { IStorageHandler } from '@verdaccio/store';
|
||||
import { $RequestExtend, $ResponseExtend, $NextFunctionVer } from '../types/custom';
|
||||
import { $RequestExtend, $NextFunctionVer } from '../types/custom';
|
||||
|
||||
const debug = buildDebug('verdaccio:api:publish:star');
|
||||
|
||||
|
|
|
@ -39,7 +39,8 @@ function compileTextSearch(textSearch: string): (pkg: Package) => boolean {
|
|||
|
||||
export default function (route, auth, storage): void {
|
||||
route.get('/-/v1/search', (req, res) => {
|
||||
// TODO: implement proper result scoring weighted by quality, popularity and maintenance query parameters
|
||||
// TODO: implement proper result scoring weighted by quality, popularity and
|
||||
// maintenance query parameters
|
||||
let [text, size, from /* , quality, popularity, maintenance */] = [
|
||||
'text',
|
||||
'size',
|
||||
|
|
|
@ -96,7 +96,8 @@ export default function (
|
|||
|
||||
/**
|
||||
* cidr_whitelist: is not being used, we pass it through
|
||||
* token: we do not store the real token (it is generated once and retrieved to the user), just a mask of it.
|
||||
* token: we do not store the real token (it is generated once and retrieved
|
||||
* to the user), just a mask of it.
|
||||
*/
|
||||
const saveToken: Token = {
|
||||
user: name,
|
||||
|
|
|
@ -162,7 +162,6 @@ class Auth implements IAuth {
|
|||
|
||||
public authenticate(username: string, password: string, cb: Callback): void {
|
||||
const plugins = this.plugins.slice(0);
|
||||
const self = this;
|
||||
(function next(): void {
|
||||
const plugin = plugins.shift() as IPluginAuth<Config>;
|
||||
|
||||
|
@ -213,7 +212,8 @@ class Auth implements IAuth {
|
|||
if (isFunction(plugin[method]) === false) {
|
||||
method = 'add_user';
|
||||
self.logger.warn(
|
||||
'the plugin method add_user in the auth plugin is deprecated and will be removed in next major release, notify to the plugin author'
|
||||
'the plugin method add_user in the auth plugin is deprecated and will' +
|
||||
' be removed in next major release, notify to the plugin author'
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -326,7 +326,6 @@ class Auth implements IAuth {
|
|||
callback: Callback
|
||||
): void {
|
||||
const plugins = this.plugins.slice(0);
|
||||
const self = this;
|
||||
const pkg = Object.assign(
|
||||
{ name: packageName, version: packageVersion },
|
||||
getMatchedPackagesSpec(packageName, this.config.packages)
|
||||
|
|
|
@ -31,7 +31,6 @@ import {
|
|||
aesDecrypt,
|
||||
verifyPayload,
|
||||
signPayload,
|
||||
buildUser,
|
||||
} from '../src';
|
||||
|
||||
setup([]);
|
||||
|
@ -428,7 +427,7 @@ describe('Auth utilities', () => {
|
|||
);
|
||||
});
|
||||
|
||||
test('should fail on verify the token and return anonymous users', async () => {
|
||||
test('should verify the token and return a remote user', async () => {
|
||||
const remoteUser = createRemoteUser('foo', []);
|
||||
const token = await signPayload(remoteUser, '12345');
|
||||
const verifiedToken = verifyJWTPayload(token, '12345');
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
import commander from 'commander';
|
||||
import { bgYellow, bgRed } from 'kleur';
|
||||
|
||||
import { setup, logger } from '@verdaccio/logger';
|
||||
import { logger } from '@verdaccio/logger';
|
||||
|
||||
import infoCommand from './commands/info';
|
||||
import initProgram from './commands/init';
|
||||
import { isVersionValid, MIN_NODE_VERSION } from './utils';
|
||||
import { isVersionValid } from './utils';
|
||||
|
||||
const isRootUser = process.getuid && process.getuid() === 0;
|
||||
|
||||
|
@ -23,7 +23,8 @@ if (isRootUser) {
|
|||
if (isVersionValid()) {
|
||||
global.console.error(
|
||||
bgRed(
|
||||
`Verdaccio requires at least Node.js ${MIN_NODE_VERSION} or higher, please upgrade your Node.js distribution`
|
||||
'Verdaccio requires at least Node.js ${MIN_NODE_VERSION} or higher,' +
|
||||
' please upgrade your Node.js distribution'
|
||||
)
|
||||
);
|
||||
process.exit(1);
|
||||
|
@ -61,7 +62,8 @@ process.on('uncaughtException', function (err) {
|
|||
{
|
||||
err: err,
|
||||
},
|
||||
'uncaught exception, please report (https://github.com/verdaccio/verdaccio/issues) this: \n@{err.stack}'
|
||||
'uncaught exception, please report (https://github.com/verdaccio/verdaccio/issues) ' +
|
||||
'this: \n@{err.stack}'
|
||||
);
|
||||
process.exit(255);
|
||||
});
|
||||
|
|
|
@ -3,7 +3,6 @@ import _ from 'lodash';
|
|||
|
||||
import { parseConfigFile } from '@verdaccio/utils';
|
||||
import { findConfigFile } from '@verdaccio/config';
|
||||
import { logger, createLogger } from '@verdaccio/logger';
|
||||
import { startVerdaccio, listenDefaultCallback } from '@verdaccio/node-api';
|
||||
|
||||
export const DEFAULT_PROCESS_NAME: string = 'verdaccio';
|
||||
|
@ -21,7 +20,8 @@ export default function initProgram(commander, pkgVersion, pkgName) {
|
|||
|
||||
process.title = web?.title || DEFAULT_PROCESS_NAME;
|
||||
|
||||
// note: self_path is only being used by @verdaccio/storage , not really useful and migth be removed soon
|
||||
// note: self_path is only being used by @verdaccio/storage, not really useful
|
||||
// and migth be removed soon
|
||||
if (!self_path) {
|
||||
verdaccioConfiguration = _.assign({}, verdaccioConfiguration, {
|
||||
self_path: path.resolve(configPathLocation),
|
||||
|
@ -45,7 +45,6 @@ export default function initProgram(commander, pkgVersion, pkgName) {
|
|||
listenDefaultCallback
|
||||
);
|
||||
} catch (err) {
|
||||
// initLogger.fatal({file: configPathLocation, err: err}, 'cannot open config file @{file}: @{!err.message}');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,7 +106,8 @@ export const SUPPORT_ERRORS = {
|
|||
|
||||
export const API_ERROR = {
|
||||
PASSWORD_SHORT: (passLength: number = DEFAULT_MIN_LIMIT_PASSWORD) =>
|
||||
`The provided password is too short. Please pick a password longer than ${passLength} characters.`,
|
||||
`The provided password is too short. Please pick a password` +
|
||||
` longer than ${passLength} characters.`,
|
||||
MUST_BE_LOGGED: 'You must be logged in to publish packages.',
|
||||
PLUGIN_ERROR: 'bug in the auth plugin system',
|
||||
CONFIG_BAD_FORMAT: 'config file must be an object',
|
||||
|
|
|
@ -43,7 +43,8 @@ export function generatePackageMetadata(
|
|||
},
|
||||
dist: {
|
||||
integrity:
|
||||
'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==',
|
||||
'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cm' +
|
||||
'E6dUBf+XoPoH4g==',
|
||||
shasum: '2c03764f651a9f016ca0b7620421457b619151b9', // pragma: allowlist secret
|
||||
tarball: `http:\/\/localhost:5555\/${pkgName}\/-\/${pkgName}-${version}.tgz`,
|
||||
},
|
||||
|
@ -54,7 +55,15 @@ export function generatePackageMetadata(
|
|||
[`${pkgName}-${version}.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=+2W32vbMBDH85y',
|
||||
'H4sIAAAAAAAAE+2W32vbMBDH85y/QnjQp9qxLEeBMsbGlocNBmN7bFdQ5WuqxJaEpGQdo//79KPeQsnI' +
|
||||
'w5KUDX/9IOvurLuz/DHSjK/YAiY6jcXSKjk6sMqypHWNdtmD6hlBI0wqQmo8nVbVqMR4OsNoVB66kF1a' +
|
||||
'W8eML+Vv10m9oF/jP6IfY4QyyTrILlD2eqkcm+gVzpdrJrPz4NuAsULJ4MZFWdBkbcByI7R79CRjx0Sc' +
|
||||
'CdnAvf+SkjUFWu8IubzBgXUhDPidQlfZ3BhlLpBUKDiQ1cDFrYDmKkNnZwjuhUM4808+xNVW8P2bMk1Y' +
|
||||
'7vJrtLC1u1MmLPjBF40+Cc4ahV6GDmI/DWygVRpMwVX3KtXUCg7Sxp7ff3nbt6TBFy65gK1iffsN41yo' +
|
||||
'EHtdFbOiisWMH8bPvXUH0SP3k+KG3UBr+DFy7OGfEJr4x5iWVeS/pLQe+D+FIv/agIWI6GX66kFuIhT+' +
|
||||
'1gDjrp/4d7WAvAwEJPh0u14IufWkM0zaW2W6nLfM2lybgJ4LTJ0/jWiAK8OcMjt8MW3OlfQppcuhhQ6k' +
|
||||
'+2OgkK2Q8DssFPi/IHpU9fz3/+xj5NjDf8QFE39VmE4JDfzPCBn4P4X6/f88f/Pu47zomiPk2Lv/dOv8' +
|
||||
'h+P/34/D/p9CL+Kp67mrGDRo0KBBp9ZPsETQegASAAA=+2W32vbMBDH85y',
|
||||
length: 512,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -74,8 +74,9 @@ function updateStorageLinks(configLocation, defaultConfig): string {
|
|||
return defaultConfig;
|
||||
}
|
||||
|
||||
// $XDG_DATA_HOME defines the base directory relative to which user specific data files should be stored,
|
||||
// If $XDG_DATA_HOME is either not set or empty, a default equal to $HOME/.local/share should be used.
|
||||
// $XDG_DATA_HOME defines the base directory relative to which user specific data
|
||||
// files should be stored, If $XDG_DATA_HOME is either not set or empty, a default
|
||||
// equal to $HOME/.local/share should be used.
|
||||
// $FlowFixMe
|
||||
let dataDir =
|
||||
process.env.XDG_DATA_HOME || Path.join(process.env.HOME as string, '.local', 'share');
|
||||
|
|
|
@ -5,7 +5,7 @@ import { setup } from '@verdaccio/logger';
|
|||
import { DEFAULT_REGISTRY, DEFAULT_UPLINK, ROLES, WEB_TITLE } from '@verdaccio/dev-commons';
|
||||
|
||||
import { parseConfigFile } from '@verdaccio/utils';
|
||||
import { Config, readDefaultConfig } from '../src';
|
||||
import { Config } from '../src';
|
||||
|
||||
setup([]);
|
||||
|
||||
|
@ -95,6 +95,4 @@ describe('Config file', () => {
|
|||
checkDefaultConfPackages(config);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Config file', () => {});
|
||||
});
|
||||
|
|
|
@ -58,7 +58,8 @@ export const API_MESSAGE = {
|
|||
|
||||
export const API_ERROR = {
|
||||
PASSWORD_SHORT: (passLength = DEFAULT_MIN_LIMIT_PASSWORD): string =>
|
||||
`The provided password is too short. Please pick a password longer than ${passLength} characters.`,
|
||||
`The provided password is too short. Please pick a password longer than ` +
|
||||
`${passLength} characters.`,
|
||||
MUST_BE_LOGGED: 'You must be logged in to publish packages.',
|
||||
PLUGIN_ERROR: 'bug in the auth plugin system',
|
||||
CONFIG_BAD_FORMAT: 'config file must be an object',
|
||||
|
|
|
@ -92,7 +92,7 @@ describe('testing locking', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('read file with options should to be found to be read it and fails to be parsed', (done) => {
|
||||
test('read file with options should be found to be read it and fails to be parsed', (done) => {
|
||||
const options = {
|
||||
parse: true,
|
||||
};
|
||||
|
@ -102,7 +102,7 @@ describe('testing locking', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('read file with options (parse, lock) should to be found to be read it as object', (done) => {
|
||||
test('read file with options (parse, lock) should be found to be read it as object', (done) => {
|
||||
const options = {
|
||||
parse: true,
|
||||
lock: true,
|
||||
|
@ -120,16 +120,19 @@ describe('testing locking', () => {
|
|||
});
|
||||
});
|
||||
|
||||
test('read file with options (parse, lock) should to be found to be read it and fails to be parsed', (done) => {
|
||||
const options = {
|
||||
parse: true,
|
||||
lock: true,
|
||||
};
|
||||
readFile(getFilePath('wrong.package.json'), options, (error: Error) => {
|
||||
expect(error.message).toMatch(/Unexpected token } in JSON at position \d+/);
|
||||
removeTempFile('wrong.package.json.lock');
|
||||
done();
|
||||
});
|
||||
});
|
||||
test(
|
||||
'read file with options (parse, lock) should be found to be read and ' + 'fails to be parsed',
|
||||
(done) => {
|
||||
const options = {
|
||||
parse: true,
|
||||
lock: true,
|
||||
};
|
||||
readFile(getFilePath('wrong.package.json'), options, (error: Error) => {
|
||||
expect(error.message).toMatch(/Unexpected token } in JSON at position \d+/);
|
||||
removeTempFile('wrong.package.json.lock');
|
||||
done();
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -207,13 +207,16 @@ describe('sanityCheck', () => {
|
|||
expect(verifyFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('should throw error for existing username and password with max number of users reached', () => {
|
||||
const verifyFn = jest.fn(() => true);
|
||||
const input = sanityCheck('test', users.test, verifyFn, users, 1);
|
||||
expect(input.status).toEqual(409);
|
||||
expect(input.message).toEqual('username is already registered');
|
||||
expect(verifyFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
test(
|
||||
'should throw error for existing username and password with max number ' + 'of users reached',
|
||||
() => {
|
||||
const verifyFn = jest.fn(() => true);
|
||||
const input = sanityCheck('test', users.test, verifyFn, users, 1);
|
||||
expect(input.status).toEqual(409);
|
||||
expect(input.message).toEqual('username is already registered');
|
||||
expect(verifyFn).toHaveBeenCalledTimes(1);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('changePasswordToHTPasswd', () => {
|
||||
|
|
|
@ -340,10 +340,12 @@ class LocalDatabase implements IPluginStorage<{}> {
|
|||
|
||||
if (this.locked) {
|
||||
this.logger.error(
|
||||
'Database is locked, please check error message printed during startup to prevent data loss.'
|
||||
'Database is locked, please check error message printed during startup to ' +
|
||||
'prevent data loss.'
|
||||
);
|
||||
return new Error(
|
||||
'Verdaccio database is locked, please contact your administrator to checkout logs during verdaccio startup.'
|
||||
'Verdaccio database is locked, please contact your administrator to checkout ' +
|
||||
'logs during verdaccio startup.'
|
||||
);
|
||||
}
|
||||
// Uses sync to prevent ugly race condition
|
||||
|
|
|
@ -18,7 +18,8 @@ export function loadPrivatePackages(path: string, logger: Logger): LocalStorage
|
|||
db = JSON.parse(data);
|
||||
} catch (err) {
|
||||
logger.error(
|
||||
`Package database file corrupted (invalid JSON), please check the error printed below.\nFile Path: ${path}`,
|
||||
`Package database file corrupted (invalid JSON), please check the error` +
|
||||
` printed below.\nFile Path: ${path}`,
|
||||
err
|
||||
);
|
||||
throw Error('Package database file corrupted (invalid JSON)');
|
||||
|
|
|
@ -31,7 +31,8 @@ const json = {
|
|||
_npmUser: {},
|
||||
dist: {
|
||||
integrity:
|
||||
'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==',
|
||||
'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9c' +
|
||||
'mE6dUBf+XoPoH4g==',
|
||||
shasum: '2c03764f651a9f016ca0b7620421457b619151b9',
|
||||
tarball: 'http://localhost:5555/@scope/pk1-test/-/@scope/pk1-test-1.0.6.tgz',
|
||||
},
|
||||
|
@ -42,7 +43,15 @@ const json = {
|
|||
'@scope/pk1-test-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=',
|
||||
'H4sIAAAAAAAAE+2W32vbMBDH85y/QnjQp9qxLEeBMsbGlocNBmN7bFdQ5WuqxJaEpGQdo//79KPeQsnI' +
|
||||
'w5KUDX/9IOvurLuz/DHSjK/YAiY6jcXSKjk6sMqypHWNdtmD6hlBI0wqQmo8nVbVqMR4OsNoVB66kF1a' +
|
||||
'W8eML+Vv10m9oF/jP6IfY4QyyTrILlD2eqkcm+gVzpdrJrPz4NuAsULJ4MZFWdBkbcByI7R79CRjx0Sc' +
|
||||
'CdnAvf+SkjUFWu8IubzBgXUhDPidQlfZ3BhlLpBUKDiQ1cDFrYDmKkNnZwjuhUM4808+xNVW8P2bMk1Y' +
|
||||
'7vJrtLC1u1MmLPjBF40+Cc4ahV6GDmI/DWygVRpMwVX3KtXUCg7Sxp7ff3nbt6TBFy65gK1iffsN41yo' +
|
||||
'EHtdFbOiisWMH8bPvXUH0SP3k+KG3UBr+DFy7OGfEJr4x5iWVeS/pLQe+D+FIv/agIWI6GX66kFuIhT+' +
|
||||
'1gDjrp/4d7WAvAwEJPh0u14IufWkM0zaW2W6nLfM2lybgJ4LTJ0/jWiAK8OcMjt8MW3OlfQppcuhhQ6k' +
|
||||
'+2OgkK2Q8DssFPi/IHpU9fz3/+xj5NjDf8QFE39VmE4JDfzPCBn4P4X6/f88f/Pu47zomiPk2Lv/dOv8' +
|
||||
'h+P/34/D/p9CL+Kp67mrGDRo0KBBp9ZPsETQegASAAA=',
|
||||
length: 512,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -73,7 +73,8 @@ describe('readme', () => {
|
|||
')'
|
||||
)
|
||||
).toEqual(
|
||||
'<p><img alt="Escape SRC - onload" src="https://www.example.com/image.png%22onload=%22alert(\'ImageOnLoad\')"></p>'
|
||||
'<p><img alt="Escape SRC - onload" src="https://www.example.com/image.png%22onload=' +
|
||||
"%22alert('ImageOnLoad')\"></p>"
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -104,10 +105,13 @@ describe('readme', () => {
|
|||
test('xss / data test/html encoded', () => {
|
||||
expect(
|
||||
parseReadme(
|
||||
'[XSS](javascript:alert('XSS'))'
|
||||
'[XSS](javascript:ale' +
|
||||
'2t('XSS'))'
|
||||
)
|
||||
).toEqual(
|
||||
'<p><a href="&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&#x28&#x27&#x58&#x53&#x53&#x27&#x29">XSS</a></p>'
|
||||
'<p><a href="&#x6A&#x61&#x76&#x61&#x73&#x63&#x72&' +
|
||||
'#x69&#x70&#x74&#x3A&#x61&#x6C&#x65&#x72&#x74&' +
|
||||
';#x28&#x27&#x58&#x53&#x53&#x27&#x29">XSS</a></p>'
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -218,7 +222,8 @@ describe('readme', () => {
|
|||
expect(
|
||||
parseReadme('\\')
|
||||
).toEqual(
|
||||
'<p><img alt="XSS" src="data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K">\\</p>'
|
||||
'<p><img alt="XSS" src="data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3Nj' +
|
||||
'cmlwdD4K">\\</p>'
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -236,7 +241,9 @@ describe('readme', () => {
|
|||
const readme: string = await readReadme('mixed-html-mk');
|
||||
|
||||
expect(clean(parseReadme(readme) as string)).toMatchInlineSnapshot(
|
||||
`"<h1 id=\\"mix-html-and-xss-markdown\\">mix html and XSS markdown</h1><p><a>Basic</a></p><p><a href=\\"https://github.com/webpack/webpack\\"><img src=\\"https://webpack.js.org/assets/icon-square-big.svg\\" height=\\"200\\" width=\\"200\\"></a></p>"`
|
||||
'"<h1 id=\\"mix-html-and-xss-markdown\\">mix html and XSS markdown</h1><p><a>Basic<' +
|
||||
'/a></p><p><a href=\\"https://github.com/webpack/webpack\\"><img src=\\"https://webp' +
|
||||
'ack.js.org/assets/icon-square-big.svg\\" height=\\"200\\" width=\\"200\\"></a></p>"'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
3
packages/core/types/index.d.ts
vendored
3
packages/core/types/index.d.ts
vendored
|
@ -514,7 +514,8 @@ declare module '@verdaccio/types' {
|
|||
tag?: string;
|
||||
}
|
||||
|
||||
// FIXME: error should be export type `VerdaccioError = HttpError & { code: number };` instead of AuthError
|
||||
// FIXME: error should be export type `VerdaccioError = HttpError & { code: number };`
|
||||
// instead of AuthError
|
||||
// but this type is on @verdaccio/commons-api and cannot be used here yet (I don't know why)
|
||||
interface HttpError extends Error {
|
||||
status: number;
|
||||
|
|
|
@ -7,13 +7,9 @@ import { parseConfigurationFile } from './__helper';
|
|||
const parseConfigurationNotifyFile = (name) => {
|
||||
return parseConfigurationFile(`notify/${name}`);
|
||||
};
|
||||
const singleNotificationConfig = parseConfigFile(parseConfigurationNotifyFile('single.notify'));
|
||||
const singleHeaderNotificationConfig = parseConfigFile(
|
||||
parseConfigurationNotifyFile('single.header.notify')
|
||||
);
|
||||
const packagePatternNotificationConfig = parseConfigFile(
|
||||
parseConfigurationNotifyFile('single.packagePattern.notify')
|
||||
);
|
||||
const multiNotificationConfig = parseConfigFile(parseConfigurationNotifyFile('multiple.notify'));
|
||||
|
||||
const mockInfo = jest.fn();
|
||||
|
|
|
@ -42,7 +42,8 @@ function isES6(plugin): boolean {
|
|||
* Load a plugin following the rules
|
||||
* - First try to load from the internal directory plugins (which will disappear soon or later).
|
||||
* - A second attempt from the external plugin directory
|
||||
* - A third attempt from node_modules, in case to have multiple match as for instance verdaccio-ldap
|
||||
* - A third attempt from node_modules, in case to have multiple match as for instance
|
||||
* verdaccio-ldap
|
||||
* and sinopia-ldap. All verdaccio prefix will have preferences.
|
||||
* @param {*} config a reference of the configuration settings
|
||||
* @param {*} pluginConfigs
|
||||
|
|
|
@ -68,7 +68,8 @@ describe('formatter', () => {
|
|||
error: undefined,
|
||||
bytes: { in: 0, out: 150186 },
|
||||
msg:
|
||||
"@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}', bytes: @{bytes.in}/@{bytes.out}",
|
||||
"@{status}, user: @{user}(@{remoteIP}), req: '@{request.method} @{request.url}', " +
|
||||
'bytes: @{bytes.in}/@{bytes.out}',
|
||||
};
|
||||
|
||||
expect(printMessage(log, prettyfierOptions)).toMatchSnapshot();
|
||||
|
|
|
@ -85,7 +85,8 @@ export function setup(options: LoggerConfig | LoggerConfigItem = [DEFAULT_LOGGER
|
|||
const isLegacyConf = _.isArray(options);
|
||||
if (isLegacyConf) {
|
||||
// FIXME: re-enable later
|
||||
// console.warn("DEPRECATE: logs does not have multi-stream support anymore, please upgrade your logger configuration");
|
||||
// console.warn("DEPRECATE: logs does not have multi-stream support anymore,
|
||||
// please upgrade your logger configuration");
|
||||
}
|
||||
|
||||
// backward compatible, pick only the first option
|
||||
|
|
|
@ -61,7 +61,8 @@ export function setSecurityWebHeaders(
|
|||
}
|
||||
|
||||
// flow: express does not match properly
|
||||
// flow info https://github.com/flowtype/flow-typed/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+express
|
||||
// flow info
|
||||
// https://github.com/flowtype/flow-typed/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+express
|
||||
export function validateName(
|
||||
req: $RequestExtend,
|
||||
res: $ResponseExtend,
|
||||
|
@ -80,7 +81,8 @@ export function validateName(
|
|||
}
|
||||
|
||||
// flow: express does not match properly
|
||||
// flow info https://github.com/flowtype/flow-typed/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+express
|
||||
// flow info
|
||||
// https://github.com/flowtype/flow-typed/issues?utf8=%E2%9C%93&q=is%3Aissue+is%3Aopen+express
|
||||
export function validatePackage(
|
||||
req: $RequestExtend,
|
||||
res: $ResponseExtend,
|
||||
|
|
|
@ -54,7 +54,8 @@ export default class VerdaccioProcess implements IServerProcess {
|
|||
this.childFork = fork(verdaccioPath, ['-c', configPath, '-l', port as string], childOptions);
|
||||
|
||||
this.childFork.on('message', (msg) => {
|
||||
// verdaccio_started is a message that comes from verdaccio in debug mode that notify has been started
|
||||
// verdaccio_started is a message that comes from verdaccio in debug mode that
|
||||
// notify has been started
|
||||
if ('verdaccio_started' in msg) {
|
||||
this.bridge
|
||||
.debug()
|
||||
|
|
|
@ -35,7 +35,8 @@ export function generateNewVersion(
|
|||
},
|
||||
dist: {
|
||||
integrity:
|
||||
'sha512-zVEqt1JUCOPsash9q4wMkJEDPD+QCx95TRhQII+JnoS31uBUKoZxhzvvUJCcLVy2CQG4QdwXARU7dYWPnrwhGg==',
|
||||
'sha512-zVEqt1JUCOPsash9q4wMkJEDPD+QCx95TRhQII+JnoS31uBUKoZxhzvvUJCcLVy2CQG4Q' +
|
||||
'dwXARU7dYWPnrwhGg==',
|
||||
shasum: shashum,
|
||||
tarball: `http:\/\/localhost:4873\/${pkgName}\/-\/${pkgName}-${version}.tgz`,
|
||||
},
|
||||
|
|
|
@ -115,7 +115,8 @@ function logHTTPSWarning(storageLocation) {
|
|||
function handleHTTPS(app: Application, configPath: string, config: ConfigWithHttps): https.Server {
|
||||
try {
|
||||
let httpsOptions = {
|
||||
secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3, // disable insecure SSLv2 and SSLv3
|
||||
// disable insecure SSLv2 and SSLv3
|
||||
secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3,
|
||||
};
|
||||
|
||||
const keyCertConfig = config.https as HttpsConfKeyCert;
|
||||
|
|
|
@ -4,7 +4,8 @@ export function displayExperimentsInfoBox(experiments) {
|
|||
const experimentList = Object.keys(experiments);
|
||||
if (experimentList.length >= 1) {
|
||||
logger.logger.warn(
|
||||
'⚠️ experiments are enabled, we recommend do not use experiments in production, comment out this section to disable it'
|
||||
'⚠️ experiments are enabled, we recommend do not use experiments in production, ' +
|
||||
'comment out this section to disable it'
|
||||
);
|
||||
experimentList.forEach((experiment) => {
|
||||
logger.logger.warn(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { API_ERROR, certPem, csrPem, keyPem } from '@verdaccio/dev-commons';
|
||||
import { certPem, csrPem, keyPem } from '@verdaccio/dev-commons';
|
||||
|
||||
import { resolveConfigPath } from './cli-utils';
|
||||
|
||||
|
|
|
@ -228,7 +228,8 @@ class ProxyStorage implements IProxy {
|
|||
message += error ? ', error: @{!error}' : ', bytes: @{bytes.in}/@{bytes.out}';
|
||||
self.logger.warn(
|
||||
{
|
||||
err: err || undefined, // if error is null/false change this to undefined so it wont log
|
||||
// if error is null/false change this to undefined so it wont log
|
||||
err: err || undefined,
|
||||
request: { method: method, url: uri },
|
||||
level: 35, // http
|
||||
status: res != null ? res.statusCode : 'ERR',
|
||||
|
@ -291,6 +292,7 @@ class ProxyStorage implements IProxy {
|
|||
})();
|
||||
}
|
||||
});
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
req.on('error', function (_err): void {
|
||||
// FIXME: _verdaccio_aborted seems not used
|
||||
// @ts-ignore
|
||||
|
|
|
@ -31,7 +31,8 @@ const json = {
|
|||
_npmUser: {},
|
||||
dist: {
|
||||
integrity:
|
||||
'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==',
|
||||
'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjc' +
|
||||
'r9cmE6dUBf+XoPoH4g==',
|
||||
shasum: '2c03764f651a9f016ca0b7620421457b619151b9',
|
||||
tarball: 'http://localhost:5555/@scope/pk1-test/-/@scope/pk1-test-1.0.6.tgz',
|
||||
},
|
||||
|
@ -42,7 +43,15 @@ const json = {
|
|||
'@scope/pk1-test-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=',
|
||||
'H4sIAAAAAAAAE+2W32vbMBDH85y/QnjQp9qxLEeBMsbGlocNBmN7bFdQ5WuqxJaEpGQdo//79KPeQsnI' +
|
||||
'w5KUDX/9IOvurLuz/DHSjK/YAiY6jcXSKjk6sMqypHWNdtmD6hlBI0wqQmo8nVbVqMR4OsNoVB66kF1a' +
|
||||
'W8eML+Vv10m9oF/jP6IfY4QyyTrILlD2eqkcm+gVzpdrJrPz4NuAsULJ4MZFWdBkbcByI7R79CRjx0Sc' +
|
||||
'CdnAvf+SkjUFWu8IubzBgXUhDPidQlfZ3BhlLpBUKDiQ1cDFrYDmKkNnZwjuhUM4808+xNVW8P2bMk1Y' +
|
||||
'7vJrtLC1u1MmLPjBF40+Cc4ahV6GDmI/DWygVRpMwVX3KtXUCg7Sxp7ff3nbt6TBFy65gK1iffsN41yo' +
|
||||
'EHtdFbOiisWMH8bPvXUH0SP3k+KG3UBr+DFy7OGfEJr4x5iWVeS/pLQe+D+FIv/agIWI6GX66kFuIhT+' +
|
||||
'1gDjrp/4d7WAvAwEJPh0u14IufWkM0zaW2W6nLfM2lybgJ4LTJ0/jWiAK8OcMjt8MW3OlfQppcuhhQ6k' +
|
||||
'+2OgkK2Q8DssFPi/IHpU9fz3/+xj5NjDf8QFE39VmE4JDfzPCBn4P4X6/f88f/Pu47zomiPk2Lv/dOv8' +
|
||||
'h+P/34/D/p9CL+Kp67mrGDRo0KBBp9ZPsETQegASAAA=',
|
||||
length: 512,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -27,7 +27,8 @@ export function generateVersion(pkgName, version) {
|
|||
},
|
||||
dist: {
|
||||
integrity:
|
||||
'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==',
|
||||
'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9c' +
|
||||
'mE6dUBf+XoPoH4g==',
|
||||
shasum: '2c03764f651a9f016ca0b7620421457b619151b9', // pragma: allowlist secret
|
||||
tarball: `http:\/\/localhost:5555\/${pkgName}\/-\/${pkgName}-${version}.tgz`,
|
||||
},
|
||||
|
@ -107,7 +108,8 @@ export function generatePackageMetadata(pkgName: string, version = '1.0.0'): Pac
|
|||
},
|
||||
dist: {
|
||||
integrity:
|
||||
'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==',
|
||||
'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr' +
|
||||
'9cmE6dUBf+XoPoH4g==',
|
||||
shasum: '2c03764f651a9f016ca0b7620421457b619151b9', // pragma: allowlist secret
|
||||
tarball: `http:\/\/localhost:5555\/${pkgName}\/-\/${pkgName}-${version}.tgz`,
|
||||
},
|
||||
|
@ -118,7 +120,15 @@ export function generatePackageMetadata(pkgName: string, version = '1.0.0'): Pac
|
|||
[`${pkgName}-${version}.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=',
|
||||
'H4sIAAAAAAAAE+2W32vbMBDH85y/QnjQp9qxLEeBMsbGlocNBmN7bFdQ5WuqxJaEpGQdo//79KPeQsnI' +
|
||||
'w5KUDX/9IOvurLuz/DHSjK/YAiY6jcXSKjk6sMqypHWNdtmD6hlBI0wqQmo8nVbVqMR4OsNoVB66kF1a' +
|
||||
'W8eML+Vv10m9oF/jP6IfY4QyyTrILlD2eqkcm+gVzpdrJrPz4NuAsULJ4MZFWdBkbcByI7R79CRjx0Sc' +
|
||||
'CdnAvf+SkjUFWu8IubzBgXUhDPidQlfZ3BhlLpBUKDiQ1cDFrYDmKkNnZwjuhUM4808+xNVW8P2bMk1Y' +
|
||||
'7vJrtLC1u1MmLPjBF40+Cc4ahV6GDmI/DWygVRpMwVX3KtXUCg7Sxp7ff3nbt6TBFy65gK1iffsN41yo' +
|
||||
'EHtdFbOiisWMH8bPvXUH0SP3k+KG3UBr+DFy7OGfEJr4x5iWVeS/pLQe+D+FIv/agIWI6GX66kFuIhT+' +
|
||||
'1gDjrp/4d7WAvAwEJPh0u14IufWkM0zaW2W6nLfM2lybgJ4LTJ0/jWiAK8OcMjt8MW3OlfQppcuhhQ6k' +
|
||||
'+2OgkK2Q8DssFPi/IHpU9fz3/+xj5NjDf8QFE39VmE4JDfzPCBn4P4X6/f88f/Pu47zomiPk2Lv/dOv8' +
|
||||
'h+P/34/D/p9CL+Kp67mrGDRo0KBBp9ZPsETQegASAAA=',
|
||||
length: 512,
|
||||
},
|
||||
},
|
||||
|
|
|
@ -536,17 +536,18 @@ describe('endpoint unit test', () => {
|
|||
/**
|
||||
* Context:
|
||||
*
|
||||
* 'non-unpublish':
|
||||
access: $authenticated
|
||||
publish: jota_unpublish_fail
|
||||
# There is some conditions to keep on mind here
|
||||
# - If unpublish is empty, fallback with the publish value
|
||||
# - If the user has permissions to publish and this empty it will be allowed to unpublish
|
||||
# - If we want to forbid anyone to unpublish, just write here any unexisting user
|
||||
unpublish: none
|
||||
|
||||
The result of this test should fail and even if jota_unpublish_fail is allowed to publish.
|
||||
|
||||
* 'non-unpublish':
|
||||
* access: $authenticated
|
||||
* publish: jota_unpublish_fail
|
||||
* # There is some conditions to keep on mind here
|
||||
* # - If unpublish is empty, fallback with the publish value
|
||||
* # - If the user has permissions to publish and this empty it will
|
||||
* # be allowed to unpublish
|
||||
* # - If we want to forbid anyone to unpublish, just write here any non-existing user
|
||||
* unpublish: none
|
||||
*
|
||||
* The result of this test should fail and even if jota_unpublish_fail is
|
||||
* allowed to publish.
|
||||
*
|
||||
*/
|
||||
const credentials = { name: 'jota_unpublish_fail', password: 'secretPass' };
|
||||
|
@ -590,10 +591,11 @@ describe('endpoint unit test', () => {
|
|||
# There is some conditions to keep on mind here
|
||||
# - If unpublish is empty, fallback with the publish value
|
||||
# - If the user has permissions to publish and this empty it will be allowed to unpublish
|
||||
# - If we want to forbid anyone to unpublish, just write here any unexisting user
|
||||
# - If we want to forbid anyone to unpublish, just write here any non-existing user
|
||||
unpublish: none
|
||||
|
||||
The result of this test should fail and even if jota_unpublish_fail is allowed to publish.
|
||||
The result of this test should fail and even if jota_unpublish_fail is allowed
|
||||
to publish.
|
||||
|
||||
*
|
||||
*/
|
||||
|
@ -823,35 +825,38 @@ describe('endpoint unit test', () => {
|
|||
done();
|
||||
});
|
||||
|
||||
test('should require both publish and unpublish access to (un)deprecate a package', async () => {
|
||||
let credentials = { name: 'only_publish', password: 'secretPass' };
|
||||
let token = await getNewToken(request(app), credentials);
|
||||
const pkg = generateDeprecateMetadata(pkgName, version, 'get deprecated');
|
||||
const [err, res] = await putPackage(
|
||||
request(app),
|
||||
`/${encodeScopedUri(pkgName)}`,
|
||||
pkg,
|
||||
token
|
||||
);
|
||||
expect(err).not.toBeNull();
|
||||
expect(res.body.error).toBeDefined();
|
||||
expect(res.body.error).toMatch(
|
||||
/user only_publish is not allowed to unpublish package @scope\/deprecate/
|
||||
);
|
||||
credentials = { name: 'only_unpublish', password: 'secretPass' };
|
||||
token = await getNewToken(request(app), credentials);
|
||||
const [err2, res2] = await putPackage(
|
||||
request(app),
|
||||
`/${encodeScopedUri(pkgName)}`,
|
||||
pkg,
|
||||
token
|
||||
);
|
||||
expect(err2).not.toBeNull();
|
||||
expect(res2.body.error).toBeDefined();
|
||||
expect(res2.body.error).toMatch(
|
||||
/user only_unpublish is not allowed to publish package @scope\/deprecate/
|
||||
);
|
||||
});
|
||||
test(
|
||||
'should require both publish and unpublish access to ' + '(un)deprecate a package',
|
||||
async () => {
|
||||
let credentials = { name: 'only_publish', password: 'secretPass' };
|
||||
let token = await getNewToken(request(app), credentials);
|
||||
const pkg = generateDeprecateMetadata(pkgName, version, 'get deprecated');
|
||||
const [err, res] = await putPackage(
|
||||
request(app),
|
||||
`/${encodeScopedUri(pkgName)}`,
|
||||
pkg,
|
||||
token
|
||||
);
|
||||
expect(err).not.toBeNull();
|
||||
expect(res.body.error).toBeDefined();
|
||||
expect(res.body.error).toMatch(
|
||||
/user only_publish is not allowed to unpublish package @scope\/deprecate/
|
||||
);
|
||||
credentials = { name: 'only_unpublish', password: 'secretPass' };
|
||||
token = await getNewToken(request(app), credentials);
|
||||
const [err2, res2] = await putPackage(
|
||||
request(app),
|
||||
`/${encodeScopedUri(pkgName)}`,
|
||||
pkg,
|
||||
token
|
||||
);
|
||||
expect(err2).not.toBeNull();
|
||||
expect(res2.body.error).toBeDefined();
|
||||
expect(res2.body.error).toMatch(
|
||||
/user only_unpublish is not allowed to publish package @scope\/deprecate/
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
test('should deprecate multiple packages', async (done) => {
|
||||
await putPackage(
|
||||
|
|
|
@ -13,7 +13,8 @@ class FilterPlugin {
|
|||
}
|
||||
// Example filter that removes a single blocked package
|
||||
if (this._config.pkg === pkg.name) {
|
||||
// In reality, we also want to remove references in attachments and dist-tags, etc. This is just a POC
|
||||
// In reality, we also want to remove references in attachments and dist-tags,
|
||||
// etc. This is just a POC
|
||||
delete pkg.versions[this._config.version];
|
||||
}
|
||||
resolve(pkg);
|
||||
|
|
|
@ -136,30 +136,34 @@ describe('endpoint user auth JWT unit test', () => {
|
|||
done();
|
||||
});
|
||||
|
||||
test('should fails on login if user credentials are invalid even if jwt valid token is provided', async (done) => {
|
||||
const credentials = { name: 'newFailsUser', password: 'secretPass' };
|
||||
const [err, res] = await addUser(request(app), credentials.name, credentials);
|
||||
expect(err).toBeNull();
|
||||
expect(res.body.ok).toBeDefined();
|
||||
expect(res.body.token).toBeDefined();
|
||||
test(
|
||||
'should fails on login if user credentials are invalid even if jwt' +
|
||||
' valid token is provided',
|
||||
async (done) => {
|
||||
const credentials = { name: 'newFailsUser', password: 'secretPass' };
|
||||
const [err, res] = await addUser(request(app), credentials.name, credentials);
|
||||
expect(err).toBeNull();
|
||||
expect(res.body.ok).toBeDefined();
|
||||
expect(res.body.token).toBeDefined();
|
||||
|
||||
const { token } = res.body;
|
||||
expect(typeof token).toBe('string');
|
||||
expect(res.body.ok).toMatch(`user '${credentials.name}' created`);
|
||||
const { token } = res.body;
|
||||
expect(typeof token).toBe('string');
|
||||
expect(res.body.ok).toMatch(`user '${credentials.name}' created`);
|
||||
|
||||
// we login when token is valid
|
||||
const newCredentials = { name: 'newFailsUser', password: 'BAD_PASSWORD' };
|
||||
const [err2, resp2] = await loginUserToken(
|
||||
request(app),
|
||||
newCredentials.name,
|
||||
newCredentials,
|
||||
token,
|
||||
HTTP_STATUS.UNAUTHORIZED
|
||||
);
|
||||
expect(err2).toBeNull();
|
||||
expect(resp2.statusCode).toBe(HTTP_STATUS.UNAUTHORIZED);
|
||||
expect(resp2.body.error).toMatch(API_ERROR.BAD_USERNAME_PASSWORD);
|
||||
// we login when token is valid
|
||||
const newCredentials = { name: 'newFailsUser', password: 'BAD_PASSWORD' };
|
||||
const [err2, resp2] = await loginUserToken(
|
||||
request(app),
|
||||
newCredentials.name,
|
||||
newCredentials,
|
||||
token,
|
||||
HTTP_STATUS.UNAUTHORIZED
|
||||
);
|
||||
expect(err2).toBeNull();
|
||||
expect(resp2.statusCode).toBe(HTTP_STATUS.UNAUTHORIZED);
|
||||
expect(resp2.body.error).toMatch(API_ERROR.BAD_USERNAME_PASSWORD);
|
||||
|
||||
done();
|
||||
});
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
@ -111,47 +111,52 @@ describe('StorageTest', () => {
|
|||
});
|
||||
|
||||
describe('test getTarball', () => {
|
||||
test.skip('should select right uplink given package.proxy for upstream tarballs', async (done) => {
|
||||
const storage: IStorageHandler = await generateSameUplinkStorage();
|
||||
const notcachedSpy = jest.spyOn(storage.uplinks.notcached, 'fetchTarball');
|
||||
const cachedSpy = jest.spyOn(storage.uplinks.cached, 'fetchTarball');
|
||||
test.skip(
|
||||
'should select right uplink given package.proxy for' + ' upstream tarballs',
|
||||
async (done) => {
|
||||
const storage: IStorageHandler = await generateSameUplinkStorage();
|
||||
const notcachedSpy = jest.spyOn(storage.uplinks.notcached, 'fetchTarball');
|
||||
const cachedSpy = jest.spyOn(storage.uplinks.cached, 'fetchTarball');
|
||||
|
||||
await new Promise((res, rej) => {
|
||||
const reader = storage.getTarball('jquery', 'jquery-1.5.1.tgz');
|
||||
reader.on('end', () => {
|
||||
expect(notcachedSpy).toHaveBeenCalledTimes(0);
|
||||
expect(cachedSpy).toHaveBeenCalledTimes(1);
|
||||
expect(cachedSpy).toHaveBeenCalledWith('http://0.0.0.0:55548/jquery/-/jquery-1.5.1.tgz');
|
||||
res();
|
||||
await new Promise((res, rej) => {
|
||||
const reader = storage.getTarball('jquery', 'jquery-1.5.1.tgz');
|
||||
reader.on('end', () => {
|
||||
expect(notcachedSpy).toHaveBeenCalledTimes(0);
|
||||
expect(cachedSpy).toHaveBeenCalledTimes(1);
|
||||
expect(cachedSpy).toHaveBeenCalledWith(
|
||||
'http://0.0.0.0:55548/jquery/-/jquery-1.5.1.tgz'
|
||||
);
|
||||
res();
|
||||
});
|
||||
reader.on('error', (err) => {
|
||||
rej(err);
|
||||
});
|
||||
reader.pipe(createNullStream());
|
||||
});
|
||||
reader.on('error', (err) => {
|
||||
rej(err);
|
||||
});
|
||||
reader.pipe(createNullStream());
|
||||
});
|
||||
|
||||
// Reset counters.
|
||||
cachedSpy.mockClear();
|
||||
notcachedSpy.mockClear();
|
||||
// Reset counters.
|
||||
cachedSpy.mockClear();
|
||||
notcachedSpy.mockClear();
|
||||
|
||||
await new Promise((res, rej) => {
|
||||
const reader = storage.getTarball('@jquery/jquery', 'jquery-1.5.1.tgz');
|
||||
reader.on('end', () => {
|
||||
expect(cachedSpy).toHaveBeenCalledTimes(0);
|
||||
expect(notcachedSpy).toHaveBeenCalledTimes(1);
|
||||
expect(notcachedSpy).toHaveBeenCalledWith(
|
||||
'http://0.0.0.0:55548/@jquery%2fjquery/-/jquery-1.5.1.tgz'
|
||||
);
|
||||
res();
|
||||
await new Promise((res, rej) => {
|
||||
const reader = storage.getTarball('@jquery/jquery', 'jquery-1.5.1.tgz');
|
||||
reader.on('end', () => {
|
||||
expect(cachedSpy).toHaveBeenCalledTimes(0);
|
||||
expect(notcachedSpy).toHaveBeenCalledTimes(1);
|
||||
expect(notcachedSpy).toHaveBeenCalledWith(
|
||||
'http://0.0.0.0:55548/@jquery%2fjquery/-/jquery-1.5.1.tgz'
|
||||
);
|
||||
res();
|
||||
});
|
||||
reader.on('error', (err) => {
|
||||
rej(err);
|
||||
});
|
||||
reader.pipe(createNullStream());
|
||||
});
|
||||
reader.on('error', (err) => {
|
||||
rej(err);
|
||||
});
|
||||
reader.pipe(createNullStream());
|
||||
});
|
||||
|
||||
done();
|
||||
});
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
describe('test _syncUplinksMetadata', () => {
|
||||
|
|
|
@ -269,7 +269,8 @@ class LocalStorage implements IStorage {
|
|||
return cb(ErrorCode.getConflict());
|
||||
}
|
||||
|
||||
// if uploaded tarball has a different shasum, it's very likely that we have some kind of error
|
||||
// if uploaded tarball has a different shasum, it's very likely that we
|
||||
// have some kind of error
|
||||
if (isObject(metadata.dist) && _.isString(metadata.dist.tarball)) {
|
||||
const tarball = metadata.dist.tarball.replace(/.*\//, '');
|
||||
|
||||
|
@ -279,7 +280,9 @@ class LocalStorage implements IStorage {
|
|||
_.isNil(metadata.dist.shasum) === false
|
||||
) {
|
||||
if (data._attachments[tarball].shasum != metadata.dist.shasum) {
|
||||
const errorMessage = `shasum error, ${data._attachments[tarball].shasum} != ${metadata.dist.shasum}`;
|
||||
const errorMessage =
|
||||
`shasum error, ` +
|
||||
`${data._attachments[tarball].shasum} != ${metadata.dist.shasum}`;
|
||||
return cb(ErrorCode.getBadRequest(errorMessage));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,8 @@ export function getLatestReadme(pkg: Package): string {
|
|||
return readme;
|
||||
}
|
||||
|
||||
// In case of empty readme - trying to get ANY readme in the following order: 'next','beta','alpha','test','dev','canary'
|
||||
// In case of empty readme - trying to get ANY readme in the following order:
|
||||
// 'next','beta','alpha','test','dev','canary'
|
||||
const readmeDistTagsPriority = ['next', 'beta', 'alpha', 'test', 'dev', 'canary'];
|
||||
readmeDistTagsPriority.forEach(function (tag): string | void {
|
||||
if (readme) {
|
||||
|
|
|
@ -665,13 +665,15 @@ class Storage {
|
|||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
// Any error here will cause a 404, like an uplink error. This is likely the right thing to do
|
||||
// Any error here will cause a 404, like an uplink error. This is likely
|
||||
// the right thing to do
|
||||
// as a broken filter is a security risk.
|
||||
const filterErrors: Error[] = [];
|
||||
// This MUST be done serially and not in parallel as they modify packageJsonLocal
|
||||
for (const filter of self.filters) {
|
||||
try {
|
||||
// These filters can assume it's save to modify packageJsonLocal and return it directly for
|
||||
// These filters can assume it's save to modify packageJsonLocal
|
||||
// and return it directly for
|
||||
// performance (i.e. need not be pure)
|
||||
packageJsonLocal = await filter.filter_metadata(packageJsonLocal);
|
||||
} catch (err) {
|
||||
|
|
|
@ -5,13 +5,13 @@ import { Config as AppConfig } from '@verdaccio/config';
|
|||
// @ts-ignore
|
||||
import { logger, setup } from '@verdaccio/logger';
|
||||
import { configExample, generateNewVersion } from '@verdaccio/mock';
|
||||
import { IStorage } from '../src/storage';
|
||||
|
||||
const readMetadata = (fileName = 'metadata') => readFile(`../fixtures/${fileName}`).toString();
|
||||
import { Config, MergeTags, Package } from '@verdaccio/types';
|
||||
import { API_ERROR, HTTP_STATUS, DIST_TAGS } from '@verdaccio/dev-commons';
|
||||
import { VerdaccioError } from '@verdaccio/commons-api';
|
||||
import { LocalStorage } from '../src/local-storage';
|
||||
import { IStorage } from '../src/storage';
|
||||
import { generatePackageTemplate } from '../src/storage-utils';
|
||||
import { readFile } from './fixtures/test.utils';
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import {
|
||||
IBasicAuth,
|
||||
IBasicStorage,
|
||||
IStorageManager,
|
||||
UpLinkConf,
|
||||
|
@ -9,7 +8,6 @@ import {
|
|||
RemoteUser,
|
||||
Config,
|
||||
Logger,
|
||||
JWTSignOptions,
|
||||
PackageAccess,
|
||||
IPluginStorage,
|
||||
StringValue as verdaccio$StringValue,
|
||||
|
@ -17,7 +15,6 @@ import {
|
|||
Package,
|
||||
IPluginStorageFilter,
|
||||
Author,
|
||||
AuthPluginPackage,
|
||||
Token,
|
||||
ITokenActions,
|
||||
TokenFilter,
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { API_ERROR, ROLES } from '@verdaccio/dev-commons';
|
||||
import { VerdaccioError, getForbidden } from '@verdaccio/commons-api';
|
||||
import { ROLES } from '@verdaccio/dev-commons';
|
||||
import {
|
||||
createAnonymousRemoteUser,
|
||||
createRemoteUser,
|
||||
|
|
|
@ -127,38 +127,41 @@ describe('Config Utilities', () => {
|
|||
expect(all.publish).toContain('admin');
|
||||
});
|
||||
|
||||
test('should normalize deprecated packages into the new ones (backward props compatible)', () => {
|
||||
const { packages } = parseConfigFile(parseConfigurationFile('deprecated-pkgs-basic'));
|
||||
const access = normalisePackageAccess(packages);
|
||||
test(
|
||||
'should normalize deprecated packages into the new ones ' + '(backward props compatible)',
|
||||
() => {
|
||||
const { packages } = parseConfigFile(parseConfigurationFile('deprecated-pkgs-basic'));
|
||||
const access = normalisePackageAccess(packages);
|
||||
|
||||
expect(access).toBeDefined();
|
||||
expect(access).toBeDefined();
|
||||
|
||||
const scoped = access[`${PACKAGE_ACCESS.SCOPE}`];
|
||||
const all = access[`${PACKAGE_ACCESS.ALL}`];
|
||||
const react = access['react-*'];
|
||||
const scoped = access[`${PACKAGE_ACCESS.SCOPE}`];
|
||||
const all = access[`${PACKAGE_ACCESS.ALL}`];
|
||||
const react = access['react-*'];
|
||||
|
||||
expect(react).toBeDefined();
|
||||
expect(react.access).toBeDefined();
|
||||
expect(react).toBeDefined();
|
||||
expect(react.access).toBeDefined();
|
||||
|
||||
// Intended checks, Typescript should catch this, we test the runtime part
|
||||
// @ts-ignore
|
||||
expect(react.access).toEqual([]);
|
||||
// @ts-ignore
|
||||
expect(react.publish[0]).toBe('admin');
|
||||
expect(react.proxy).toBeDefined();
|
||||
// @ts-ignore
|
||||
expect(react.proxy).toEqual([]);
|
||||
expect(react.storage).toBeDefined();
|
||||
// Intended checks, Typescript should catch this, we test the runtime part
|
||||
// @ts-ignore
|
||||
expect(react.access).toEqual([]);
|
||||
// @ts-ignore
|
||||
expect(react.publish[0]).toBe('admin');
|
||||
expect(react.proxy).toBeDefined();
|
||||
// @ts-ignore
|
||||
expect(react.proxy).toEqual([]);
|
||||
expect(react.storage).toBeDefined();
|
||||
|
||||
expect(react.storage).toBe('react-storage');
|
||||
expect(scoped).toBeDefined();
|
||||
expect(scoped.storage).not.toBeDefined();
|
||||
expect(all).toBeDefined();
|
||||
expect(all.access).toBeDefined();
|
||||
expect(all.storage).not.toBeDefined();
|
||||
expect(all.publish).toBeDefined();
|
||||
expect(all.proxy).toBeDefined();
|
||||
});
|
||||
expect(react.storage).toBe('react-storage');
|
||||
expect(scoped).toBeDefined();
|
||||
expect(scoped.storage).not.toBeDefined();
|
||||
expect(all).toBeDefined();
|
||||
expect(all.access).toBeDefined();
|
||||
expect(all.storage).not.toBeDefined();
|
||||
expect(all.publish).toBeDefined();
|
||||
expect(all.proxy).toBeDefined();
|
||||
}
|
||||
);
|
||||
|
||||
test('should check not default packages access', () => {
|
||||
const { packages } = parseConfigFile(parseConfigurationFile('pkgs-empty'));
|
||||
|
|
|
@ -23,7 +23,8 @@ class FunctionalEnvironment extends NodeEnvironment {
|
|||
public async setup() {
|
||||
// const SILENCE_LOG = !process.env.VERDACCIO_PROCESS_SILENCE || false;
|
||||
// @ts-ignore
|
||||
// const DEBUG_INJECT: boolean = process.env.VERDACCIO_DEBUG_INJECT ? process.env.VERDACCIO_DEBUG_INJECT : false;
|
||||
// const DEBUG_INJECT: boolean = process.env.VERDACCIO_DEBUG_INJECT ?
|
||||
// process.env.VERDACCIO_DEBUG_INJECT : false;
|
||||
const forkList: any = [];
|
||||
const serverList: any = [];
|
||||
const pathStore = path.join(__dirname, '../store');
|
||||
|
|
|
@ -73,7 +73,8 @@ export default function (server, server2) {
|
|||
.then(function (body) {
|
||||
expect(body.name).toEqual(SCOPE);
|
||||
expect(body.dist.tarball).toEqual(
|
||||
`http://${DOMAIN_SERVERS}:${PORT_SERVER_2}/@test%2fscoped/-/${PKG_NAME}-${PKG_VERSION}.tgz`
|
||||
`http://${DOMAIN_SERVERS}:${PORT_SERVER_2}/@test%2fscoped/-/${PKG_NAME}-` +
|
||||
`${PKG_VERSION}.tgz`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -10,7 +10,9 @@ const defaultPkg = {
|
|||
version: '0.1.0',
|
||||
dist: {
|
||||
shasum: 'fake',
|
||||
tarball: `http://${DOMAIN_SERVERS}:${PORT_SERVER_APP}/testexp-incomplete/-/content-length.tar.gz`,
|
||||
tarball:
|
||||
`http://${DOMAIN_SERVERS}:${PORT_SERVER_APP}/testexp-incomplete/-` +
|
||||
`/content-length.tar.gz`,
|
||||
},
|
||||
},
|
||||
'0.1.1': {
|
||||
|
|
|
@ -62,14 +62,18 @@ export default function (server, server2) {
|
|||
/* test for before() */
|
||||
});
|
||||
|
||||
test(`should fetch the newly created published tarball for ${PKG_NAME} from server1 on server2`, () => {
|
||||
return server
|
||||
.getTarball(PKG_NAME, TARBALL)
|
||||
.status(HTTP_STATUS.OK)
|
||||
.then(function (body) {
|
||||
expect(body).toEqual(getBinary());
|
||||
});
|
||||
});
|
||||
test(
|
||||
`should fetch the newly created published tarball for ${PKG_NAME} ` +
|
||||
`from server1 on server2`,
|
||||
() => {
|
||||
return server
|
||||
.getTarball(PKG_NAME, TARBALL)
|
||||
.status(HTTP_STATUS.OK)
|
||||
.then(function (body) {
|
||||
expect(body).toEqual(getBinary());
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
test(`should fetch metadata for ${PKG_NAME} match from server1`, () => {
|
||||
return server
|
||||
|
|
|
@ -15,7 +15,9 @@ export default function (server, express) {
|
|||
version: '0.1.0',
|
||||
dist: {
|
||||
shasum: 'fake',
|
||||
tarball: `http://${DOMAIN_SERVERS}:${PORT_SERVER_APP}/testexp-racycrash/-/test.tar.gz`,
|
||||
tarball:
|
||||
`http://${DOMAIN_SERVERS}:${PORT_SERVER_APP}/testexp-racycrash/-` +
|
||||
`/test.tar.gz`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -48,7 +48,8 @@ export default function (server) {
|
|||
return server
|
||||
.request({
|
||||
uri:
|
||||
'/testpkg-sec/-/%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd',
|
||||
'/testpkg-sec/-/%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%' +
|
||||
'2e%2f%2e%2e%2f%2e%2e%2fetc%2fpasswd',
|
||||
})
|
||||
.status(HTTP_STATUS.FORBIDDEN)
|
||||
.body_error(/invalid filename/);
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/**
|
||||
* PLEASE DO NOT MODIFY THIS FILE
|
||||
*
|
||||
* This test is just for teaching purpose, use this example as template for your new endpoint API unit test
|
||||
* This test is just for teaching purpose, use this example as template for your new
|
||||
* endpoint API unit test
|
||||
*
|
||||
* If you have any questions, ask at the http://chat.verdaccio.org #questions channel.
|
||||
*
|
||||
|
|
|
@ -4,7 +4,15 @@ export function generateAttachment() {
|
|||
return {
|
||||
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=',
|
||||
'H4sIAAAAAAAAE+2W32vbMBDH85y/QnjQp9qxLEeBMsbGlocNBmN7bFdQ5WuqxJaEpGQdo//79KPeQsnI' +
|
||||
'w5KUDX/9IOvurLuz/DHSjK/YAiY6jcXSKjk6sMqypHWNdtmD6hlBI0wqQmo8nVbVqMR4OsNoVB66kF1a' +
|
||||
'W8eML+Vv10m9oF/jP6IfY4QyyTrILlD2eqkcm+gVzpdrJrPz4NuAsULJ4MZFWdBkbcByI7R79CRjx0Sc' +
|
||||
'CdnAvf+SkjUFWu8IubzBgXUhDPidQlfZ3BhlLpBUKDiQ1cDFrYDmKkNnZwjuhUM4808+xNVW8P2bMk1Y' +
|
||||
'7vJrtLC1u1MmLPjBF40+Cc4ahV6GDmI/DWygVRpMwVX3KtXUCg7Sxp7ff3nbt6TBFy65gK1iffsN41yo' +
|
||||
'EHtdFbOiisWMH8bPvXUH0SP3k+KG3UBr+DFy7OGfEJr4x5iWVeS/pLQe+D+FIv/agIWI6GX66kFuIhT+' +
|
||||
'1gDjrp/4d7WAvAwEJPh0u14IufWkM0zaW2W6nLfM2lybgJ4LTJ0/jWiAK8OcMjt8MW3OlfQppcuhhQ6k' +
|
||||
'+2OgkK2Q8DssFPi/IHpU9fz3/+xj5NjDf8QFE39VmE4JDfzPCBn4P4X6/f88f/Pu47zomiPk2Lv/dOv8' +
|
||||
'h+P/34/D/p9CL+Kp67mrGDRo0KBBp9ZPsETQegASAAA=',
|
||||
length: 512,
|
||||
};
|
||||
}
|
||||
|
@ -36,7 +44,8 @@ export function generateVersion(pkgName, version) {
|
|||
},
|
||||
dist: {
|
||||
integrity:
|
||||
'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6dUBf+XoPoH4g==',
|
||||
'sha512-6gHiERpiDgtb3hjqpQH5/i7zRmvYi9pmCjQf2ZMy3QEa9wVk9RgdZaPWUt7ZOnWUPFjcr9cmE6' +
|
||||
'dUBf+XoPoH4g==',
|
||||
shasum: '2c03764f651a9f016ca0b7620421457b619151b9', // pragma: allowlist secret
|
||||
tarball: `http:\/\/localhost:5555\/${pkgName}\/-\/${pkgName}-${version}.tgz`,
|
||||
},
|
||||
|
|
Loading…
Add table
Reference in a new issue