mirror of
https://github.com/verdaccio/verdaccio.git
synced 2024-12-30 22:34:10 -05:00
chore: update deps (#2056)
* chore: update deps * chore: update eslint * chore: update deps types
This commit is contained in:
parent
96ba927917
commit
eab3007939
26 changed files with 2236 additions and 1578 deletions
|
@ -43,6 +43,8 @@
|
|||
"jest/no-test-callback": 0,
|
||||
"jest/expect-expect": 0,
|
||||
"jest/no-try-expect": 0,
|
||||
"jest/no-done-callback": "off",
|
||||
"jest/no-conditional-expect": "off",
|
||||
"keyword-spacing": "off",
|
||||
"no-tabs": "off",
|
||||
"no-useless-escape": "off",
|
||||
|
|
96
package.json
96
package.json
|
@ -14,107 +14,107 @@
|
|||
"url": "https://opencollective.com/verdaccio"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "7.12.1",
|
||||
"@babel/core": "7.12.3",
|
||||
"@babel/node": "7.12.6",
|
||||
"@babel/cli": "7.12.10",
|
||||
"@babel/core": "7.12.10",
|
||||
"@babel/node": "7.12.10",
|
||||
"@babel/plugin-proposal-class-properties": "7.12.1",
|
||||
"@babel/plugin-proposal-decorators": "7.12.1",
|
||||
"@babel/plugin-proposal-decorators": "7.12.12",
|
||||
"@babel/plugin-proposal-export-namespace-from": "7.12.1",
|
||||
"@babel/plugin-proposal-function-sent": "7.12.1",
|
||||
"@babel/plugin-proposal-json-strings": "7.12.1",
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator": "7.12.1",
|
||||
"@babel/plugin-proposal-numeric-separator": "7.12.5",
|
||||
"@babel/plugin-proposal-numeric-separator": "7.12.7",
|
||||
"@babel/plugin-proposal-object-rest-spread": "7.12.1",
|
||||
"@babel/plugin-proposal-optional-chaining": "7.12.1",
|
||||
"@babel/plugin-proposal-optional-chaining": "7.12.7",
|
||||
"@babel/plugin-proposal-throw-expressions": "7.12.1",
|
||||
"@babel/plugin-syntax-dynamic-import": "7.8.3",
|
||||
"@babel/plugin-syntax-import-meta": "7.10.4",
|
||||
"@babel/plugin-transform-async-to-generator": "7.12.1",
|
||||
"@babel/plugin-transform-classes": "7.12.1",
|
||||
"@babel/plugin-transform-runtime": "7.12.1",
|
||||
"@babel/plugin-transform-runtime": "7.12.10",
|
||||
"@babel/polyfill": "7.12.1",
|
||||
"@babel/preset-env": "7.12.1",
|
||||
"@babel/preset-react": "7.12.5",
|
||||
"@babel/preset-typescript": "7.12.1",
|
||||
"@babel/register": "7.12.1",
|
||||
"@babel/preset-env": "7.12.11",
|
||||
"@babel/preset-react": "7.12.10",
|
||||
"@babel/preset-typescript": "7.12.7",
|
||||
"@babel/register": "7.12.10",
|
||||
"@babel/runtime": "7.12.5",
|
||||
"@changesets/changelog-github": "^0.2.7",
|
||||
"@changesets/cli": "^2.12.0",
|
||||
"@changesets/changelog-github": "^0.2.8",
|
||||
"@changesets/cli": "^2.13.0",
|
||||
"@changesets/get-dependents-graph": "^1.1.3",
|
||||
"@commitlint/cli": "8.3.5",
|
||||
"@commitlint/config-conventional": "8.2.0",
|
||||
"@octokit/rest": "17.0.0",
|
||||
"@types/async": "3.2.3",
|
||||
"@types/async": "3.2.5",
|
||||
"@types/autosuggest-highlight": "3.1.1",
|
||||
"@types/express": "4.17.6",
|
||||
"@types/http-errors": "1.6.3",
|
||||
"@types/jest": "^26.0.19",
|
||||
"@types/lodash": "4.14.165",
|
||||
"@types/mime": "2.0.2",
|
||||
"@types/http-errors": "1.8.0",
|
||||
"@types/jest": "^26.0.20",
|
||||
"@types/js-base64": "3.0.0",
|
||||
"@types/lodash": "4.14.167",
|
||||
"@types/lowdb": "^1.0.9",
|
||||
"@types/mime": "2.0.2",
|
||||
"@types/minimatch": "3.0.3",
|
||||
"@types/node": "^14.14.7",
|
||||
"@types/semver": "7.2.0",
|
||||
"@types/supertest": "2.0.9",
|
||||
"@types/autosuggest-highlight": "3.1.0",
|
||||
"@types/js-base64": "3.0.0",
|
||||
"@types/react": "16.14.2",
|
||||
"@types/react-autosuggest": "10.0.1",
|
||||
"@types/react-dom": "^16.9.10",
|
||||
"@types/react-router-dom": "5.1.6",
|
||||
"@types/react-virtualized": "9.21.10",
|
||||
"@types/request": "2.48.5",
|
||||
"@types/semver": "7.3.4",
|
||||
"@types/supertest": "2.0.10",
|
||||
"@types/testing-library__jest-dom": "^5.9.5",
|
||||
"@types/validator": "13.1.1",
|
||||
"@types/webpack": "^4.41.25",
|
||||
"@types/validator": "13.1.3",
|
||||
"@types/webpack": "^4.41.26",
|
||||
"@types/webpack-env": "1.16.0",
|
||||
"@typescript-eslint/eslint-plugin": "4.10.0",
|
||||
"@typescript-eslint/parser": "4.10.0",
|
||||
"@typescript-eslint/eslint-plugin": "4.13.0",
|
||||
"@typescript-eslint/parser": "4.13.0",
|
||||
"@verdaccio/types": "workspace:*",
|
||||
"@verdaccio/ui-theme": "workspace:*",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
"babel-eslint": "10.1.0",
|
||||
"babel-jest": "26.6.3",
|
||||
"babel-plugin-dynamic-import-node": "2.3.3",
|
||||
"babel-plugin-emotion": "10.0.33",
|
||||
"codecov": "3.6.1",
|
||||
"babel-plugin-emotion": "11.0.0",
|
||||
"codecov": "3.8.1",
|
||||
"concurrently": "^5.3.0",
|
||||
"core-js": "^3.6.5",
|
||||
"cross-env": "7.0.2",
|
||||
"core-js": "^3.8.2",
|
||||
"cross-env": "7.0.3",
|
||||
"detect-secrets": "1.0.6",
|
||||
"eslint": "7.5.0",
|
||||
"eslint": "7.18.0",
|
||||
"eslint-config-google": "0.14.0",
|
||||
"eslint-config-prettier": "6.10.0",
|
||||
"eslint-plugin-babel": "5.3.0",
|
||||
"eslint-plugin-import": "2.22.0",
|
||||
"eslint-plugin-jest": "23.8.0",
|
||||
"eslint-plugin-jsx-a11y": "6.3.1",
|
||||
"eslint-plugin-react": "7.20.6",
|
||||
"eslint-plugin-react-hooks": "4.1.0",
|
||||
"eslint-plugin-simple-import-sort": "5.0.2",
|
||||
"eslint-plugin-verdaccio": "8.4.2",
|
||||
"eslint-config-prettier": "7.1.0",
|
||||
"eslint-plugin-babel": "5.3.1",
|
||||
"eslint-plugin-import": "2.22.1",
|
||||
"eslint-plugin-jest": "24.1.3",
|
||||
"eslint-plugin-jsx-a11y": "6.4.1",
|
||||
"eslint-plugin-react": "7.22.0",
|
||||
"eslint-plugin-react-hooks": "4.2.0",
|
||||
"eslint-plugin-simple-import-sort": "7.0.0",
|
||||
"eslint-plugin-verdaccio": "9.6.1",
|
||||
"fs-extra": "8.1.0",
|
||||
"get-stdin": "7.0.0",
|
||||
"husky": "2.7.0",
|
||||
"in-publish": "2.0.0",
|
||||
"in-publish": "2.0.1",
|
||||
"jest": "26.6.3",
|
||||
"jest-environment-jsdom": "26.6.2",
|
||||
"jest-environment-jsdom-global": "^2.0.4",
|
||||
"jest-environment-node": "26.6.2",
|
||||
"jest-fetch-mock": "3.0.3",
|
||||
"jest-junit": "11.0.1",
|
||||
"kleur": "3.0.3",
|
||||
"kleur": "4.1.3",
|
||||
"lint-staged": "8.2.1",
|
||||
"nock": "12.0.3",
|
||||
"nodemon": "^2.0.7",
|
||||
"npm-run-all": "4.1.5",
|
||||
"nodemon": "^2.0.6",
|
||||
"prettier": "2.0.5",
|
||||
"prettier": "2.2.1",
|
||||
"rimraf": "3.0.2",
|
||||
"selfsigned": "1.10.7",
|
||||
"selfsigned": "1.10.8",
|
||||
"standard-version": "8.0.0",
|
||||
"supertest": "4.0.2",
|
||||
"ts-node": "^9.0.0",
|
||||
"typescript": "^4.0.5",
|
||||
"verdaccio": "^4.8.1",
|
||||
"ts-node": "^9.1.1",
|
||||
"typescript": "^4.1.3",
|
||||
"verdaccio": "^4.10.0",
|
||||
"verdaccio-audit": "workspace:*",
|
||||
"verdaccio-auth-memory": "workspace:*",
|
||||
"verdaccio-htpasswd": "workspace:*",
|
||||
|
|
|
@ -48,58 +48,60 @@ export default function (route: Router, auth: IAuth, storage: IStorageHandler):
|
|||
tag_package_version
|
||||
);
|
||||
|
||||
route.delete('/-/package/:package/dist-tags/:tag', can('publish'), function (
|
||||
req: $RequestExtend,
|
||||
res: $ResponseExtend,
|
||||
next: $NextFunctionVer
|
||||
): void {
|
||||
const tags = {};
|
||||
tags[req.params.tag] = null;
|
||||
storage.mergeTags(req.params.package, tags, function (err: VerdaccioError): $NextFunctionVer {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
res.status(HTTP_STATUS.CREATED);
|
||||
return next({
|
||||
ok: API_MESSAGE.TAG_REMOVED,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
route.get('/-/package/:package/dist-tags', can('access'), function (
|
||||
req: $RequestExtend,
|
||||
res: $ResponseExtend,
|
||||
next: $NextFunctionVer
|
||||
): void {
|
||||
storage.getPackage({
|
||||
name: req.params.package,
|
||||
uplinksLook: true,
|
||||
req,
|
||||
callback: function (err: VerdaccioError, info: Package): $NextFunctionVer {
|
||||
route.delete(
|
||||
'/-/package/:package/dist-tags/:tag',
|
||||
can('publish'),
|
||||
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
|
||||
const tags = {};
|
||||
tags[req.params.tag] = null;
|
||||
storage.mergeTags(req.params.package, tags, function (err: VerdaccioError): $NextFunctionVer {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
next(info[DIST_TAGS]);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
route.post('/-/package/:package/dist-tags', can('publish'), function (
|
||||
req: $RequestExtend,
|
||||
res: $ResponseExtend,
|
||||
next: $NextFunctionVer
|
||||
): void {
|
||||
storage.mergeTags(req.params.package, req.body, function (
|
||||
err: VerdaccioError
|
||||
): $NextFunctionVer {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
res.status(HTTP_STATUS.CREATED);
|
||||
return next({
|
||||
ok: API_MESSAGE.TAG_UPDATED,
|
||||
res.status(HTTP_STATUS.CREATED);
|
||||
return next({
|
||||
ok: API_MESSAGE.TAG_REMOVED,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
route.get(
|
||||
'/-/package/:package/dist-tags',
|
||||
can('access'),
|
||||
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
|
||||
storage.getPackage({
|
||||
name: req.params.package,
|
||||
uplinksLook: true,
|
||||
req,
|
||||
callback: function (err: VerdaccioError, info: Package): $NextFunctionVer {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
next(info[DIST_TAGS]);
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
route.post(
|
||||
'/-/package/:package/dist-tags',
|
||||
can('publish'),
|
||||
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
|
||||
storage.mergeTags(
|
||||
req.params.package,
|
||||
req.body,
|
||||
function (err: VerdaccioError): $NextFunctionVer {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
res.status(HTTP_STATUS.CREATED);
|
||||
return next({
|
||||
ok: API_MESSAGE.TAG_UPDATED,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -41,76 +41,78 @@ export default function (
|
|||
): void {
|
||||
const can = allow(auth);
|
||||
// TODO: anonymous user?
|
||||
route.get('/:package/:version?', can('access'), function (
|
||||
req: $RequestExtend,
|
||||
res: $ResponseExtend,
|
||||
next: $NextFunctionVer
|
||||
): void {
|
||||
debug('init package by version');
|
||||
const name = req.params.package;
|
||||
const getPackageMetaCallback = function (err, metadata: Package): void {
|
||||
if (err) {
|
||||
debug('error on fetch metadata for %o with error %o', name, err.message);
|
||||
return next(err);
|
||||
}
|
||||
debug('convert dist remote to local with prefix %o', config?.url_prefix);
|
||||
metadata = convertDistRemoteToLocalTarballUrls(metadata, req, config?.url_prefix);
|
||||
|
||||
let queryVersion = req.params.version;
|
||||
debug('query by param version: %o', queryVersion);
|
||||
if (_.isNil(queryVersion)) {
|
||||
debug('param %o version found', queryVersion);
|
||||
return next(metadata);
|
||||
}
|
||||
|
||||
let version = getVersion(metadata, queryVersion);
|
||||
debug('query by latest version %o and result %o', queryVersion, version);
|
||||
if (_.isNil(version) === false) {
|
||||
debug('latest version found %o', version);
|
||||
return next(version);
|
||||
}
|
||||
|
||||
if (_.isNil(metadata[DIST_TAGS]) === false) {
|
||||
if (_.isNil(metadata[DIST_TAGS][queryVersion]) === false) {
|
||||
queryVersion = metadata[DIST_TAGS][queryVersion];
|
||||
debug('dist-tag version found %o', queryVersion);
|
||||
version = getVersion(metadata, queryVersion);
|
||||
if (_.isNil(version) === false) {
|
||||
debug('dist-tag found %o', version);
|
||||
return next(version);
|
||||
}
|
||||
route.get(
|
||||
'/:package/:version?',
|
||||
can('access'),
|
||||
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
|
||||
debug('init package by version');
|
||||
const name = req.params.package;
|
||||
const getPackageMetaCallback = function (err, metadata: Package): void {
|
||||
if (err) {
|
||||
debug('error on fetch metadata for %o with error %o', name, err.message);
|
||||
return next(err);
|
||||
}
|
||||
} else {
|
||||
debug('dist tag not detected');
|
||||
}
|
||||
debug('convert dist remote to local with prefix %o', config?.url_prefix);
|
||||
metadata = convertDistRemoteToLocalTarballUrls(metadata, req, config?.url_prefix);
|
||||
|
||||
debug('package version not found %o', queryVersion);
|
||||
return next(ErrorCode.getNotFound(`${API_ERROR.VERSION_NOT_EXIST}: ${queryVersion}`));
|
||||
};
|
||||
let queryVersion = req.params.version;
|
||||
debug('query by param version: %o', queryVersion);
|
||||
if (_.isNil(queryVersion)) {
|
||||
debug('param %o version found', queryVersion);
|
||||
return next(metadata);
|
||||
}
|
||||
|
||||
debug('get package name %o', name);
|
||||
debug('uplinks look up enabled');
|
||||
storage.getPackage({
|
||||
name,
|
||||
uplinksLook: true,
|
||||
req,
|
||||
callback: getPackageMetaCallback,
|
||||
});
|
||||
});
|
||||
let version = getVersion(metadata, queryVersion);
|
||||
debug('query by latest version %o and result %o', queryVersion, version);
|
||||
if (_.isNil(version) === false) {
|
||||
debug('latest version found %o', version);
|
||||
return next(version);
|
||||
}
|
||||
|
||||
route.get('/:scopedPackage/-/:scope/:filename', can('access'), function (
|
||||
req: $RequestExtend,
|
||||
res: $ResponseExtend
|
||||
): void {
|
||||
const { scopedPackage, filename } = req.params;
|
||||
if (_.isNil(metadata[DIST_TAGS]) === false) {
|
||||
if (_.isNil(metadata[DIST_TAGS][queryVersion]) === false) {
|
||||
queryVersion = metadata[DIST_TAGS][queryVersion];
|
||||
debug('dist-tag version found %o', queryVersion);
|
||||
version = getVersion(metadata, queryVersion);
|
||||
if (_.isNil(version) === false) {
|
||||
debug('dist-tag found %o', version);
|
||||
return next(version);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
debug('dist tag not detected');
|
||||
}
|
||||
|
||||
downloadStream(scopedPackage, filename, storage, req, res);
|
||||
});
|
||||
debug('package version not found %o', queryVersion);
|
||||
return next(ErrorCode.getNotFound(`${API_ERROR.VERSION_NOT_EXIST}: ${queryVersion}`));
|
||||
};
|
||||
|
||||
route.get('/:package/-/:filename', can('access'), function (
|
||||
req: $RequestExtend,
|
||||
res: $ResponseExtend
|
||||
): void {
|
||||
downloadStream(req.params.package, req.params.filename, storage, req, res);
|
||||
});
|
||||
debug('get package name %o', name);
|
||||
debug('uplinks look up enabled');
|
||||
storage.getPackage({
|
||||
name,
|
||||
uplinksLook: true,
|
||||
req,
|
||||
callback: getPackageMetaCallback,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
route.get(
|
||||
'/:scopedPackage/-/:scope/:filename',
|
||||
can('access'),
|
||||
function (req: $RequestExtend, res: $ResponseExtend): void {
|
||||
const { scopedPackage, filename } = req.params;
|
||||
|
||||
downloadStream(scopedPackage, filename, storage, req, res);
|
||||
}
|
||||
);
|
||||
|
||||
route.get(
|
||||
'/:package/-/:filename',
|
||||
can('access'),
|
||||
function (req: $RequestExtend, res: $ResponseExtend): void {
|
||||
downloadStream(req.params.package, req.params.filename, storage, req, res);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -2,11 +2,10 @@ import { Router } from 'express';
|
|||
import { $RequestExtend, $ResponseExtend, $NextFunctionVer } from '../types/custom';
|
||||
|
||||
export default function (route: Router): void {
|
||||
route.get('/-/ping', function (
|
||||
req: $RequestExtend,
|
||||
res: $ResponseExtend,
|
||||
next: $NextFunctionVer
|
||||
) {
|
||||
next({});
|
||||
});
|
||||
route.get(
|
||||
'/-/ping',
|
||||
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer) {
|
||||
next({});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -241,50 +241,55 @@ export function publishPackage(storage: IStorageHandler, config: Config, auth: I
|
|||
// at this point document is either created or existed before
|
||||
const [firstAttachmentKey] = Object.keys(_attachments);
|
||||
|
||||
createTarball(Path.basename(firstAttachmentKey), _attachments[firstAttachmentKey], function (
|
||||
error
|
||||
) {
|
||||
debug('creating a tarball %o', firstAttachmentKey);
|
||||
if (error) {
|
||||
debug('error on create a tarball for %o with error %o', packageName, error.message);
|
||||
return next(error);
|
||||
}
|
||||
|
||||
const versionToPublish = Object.keys(versions)[0];
|
||||
|
||||
versions[versionToPublish].readme =
|
||||
_.isNil(metadataCopy.readme) === false ? String(metadataCopy.readme) : '';
|
||||
|
||||
createVersion(versionToPublish, versions[versionToPublish], function (error) {
|
||||
createTarball(
|
||||
Path.basename(firstAttachmentKey),
|
||||
_attachments[firstAttachmentKey],
|
||||
function (error) {
|
||||
debug('creating a tarball %o', firstAttachmentKey);
|
||||
if (error) {
|
||||
debug('error on create a version for %o with error %o', packageName, error.message);
|
||||
debug('error on create a tarball for %o with error %o', packageName, error.message);
|
||||
return next(error);
|
||||
}
|
||||
|
||||
addTags(metadataCopy[DIST_TAGS], async function (error) {
|
||||
const versionToPublish = Object.keys(versions)[0];
|
||||
|
||||
versions[versionToPublish].readme =
|
||||
_.isNil(metadataCopy.readme) === false ? String(metadataCopy.readme) : '';
|
||||
|
||||
createVersion(versionToPublish, versions[versionToPublish], function (error) {
|
||||
if (error) {
|
||||
debug('error on create a tag for %o with error %o', packageName, error.message);
|
||||
debug('error on create a version for %o with error %o', packageName, error.message);
|
||||
return next(error);
|
||||
}
|
||||
|
||||
try {
|
||||
await notify(
|
||||
metadataCopy,
|
||||
config,
|
||||
req.remote_user,
|
||||
`${metadataCopy.name}@${versionToPublish}`
|
||||
);
|
||||
} catch (error) {
|
||||
debug('error on notify add a new tag %o', `${metadataCopy.name}@${versionToPublish}`);
|
||||
logger.error({ error }, 'notify batch service has failed: @{error}');
|
||||
}
|
||||
addTags(metadataCopy[DIST_TAGS], async function (error) {
|
||||
if (error) {
|
||||
debug('error on create a tag for %o with error %o', packageName, error.message);
|
||||
return next(error);
|
||||
}
|
||||
|
||||
debug('add a tag succesfully for %o', `${metadataCopy.name}@${versionToPublish}`);
|
||||
res.status(HTTP_STATUS.CREATED);
|
||||
return next({ ok: okMessage, success: true });
|
||||
try {
|
||||
await notify(
|
||||
metadataCopy,
|
||||
config,
|
||||
req.remote_user,
|
||||
`${metadataCopy.name}@${versionToPublish}`
|
||||
);
|
||||
} catch (error) {
|
||||
debug(
|
||||
'error on notify add a new tag %o',
|
||||
`${metadataCopy.name}@${versionToPublish}`
|
||||
);
|
||||
logger.error({ error }, 'notify batch service has failed: @{error}');
|
||||
}
|
||||
|
||||
debug('add a tag succesfully for %o', `${metadataCopy.name}@${versionToPublish}`);
|
||||
res.status(HTTP_STATUS.CREATED);
|
||||
return next({ ok: okMessage, success: true });
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
if (isPublishablePackage(req.body) === false && isObject(req.body.users)) {
|
||||
|
|
|
@ -15,107 +15,107 @@ import { $RequestExtend, $NextFunctionVer } from '../types/custom';
|
|||
const debug = buildDebug('verdaccio:api:user');
|
||||
|
||||
export default function (route: Router, auth: IAuth, config: Config): void {
|
||||
route.get('/-/user/:org_couchdb_user', function (
|
||||
req: $RequestExtend,
|
||||
res: Response,
|
||||
next: $NextFunctionVer
|
||||
): void {
|
||||
debug('verifying user');
|
||||
const message = getAuthenticatedMessage(req.remote_user.name);
|
||||
debug('user authenticated message %o', message);
|
||||
res.status(HTTP_STATUS.OK);
|
||||
next({
|
||||
ok: message,
|
||||
});
|
||||
});
|
||||
|
||||
route.put('/-/user/:org_couchdb_user/:_rev?/:revision?', function (
|
||||
req: $RequestExtend,
|
||||
res: Response,
|
||||
next: $NextFunctionVer
|
||||
): void {
|
||||
const { name, password } = req.body;
|
||||
debug('login or adduser');
|
||||
const remoteName = req.remote_user.name;
|
||||
|
||||
if (_.isNil(remoteName) === false && _.isNil(name) === false && remoteName === name) {
|
||||
debug('login: no remote user detected');
|
||||
auth.authenticate(name, password, async function callbackAuthenticate(
|
||||
err,
|
||||
user
|
||||
): Promise<void> {
|
||||
if (err) {
|
||||
logger.trace(
|
||||
{ name, err },
|
||||
'authenticating for user @{username} failed. Error: @{err.message}'
|
||||
);
|
||||
return next(ErrorCode.getCode(HTTP_STATUS.UNAUTHORIZED, API_ERROR.BAD_USERNAME_PASSWORD));
|
||||
}
|
||||
|
||||
const restoredRemoteUser: RemoteUser = createRemoteUser(name, user.groups || []);
|
||||
const token = await getApiToken(auth, config, restoredRemoteUser, password);
|
||||
debug('login: new token');
|
||||
if (!token) {
|
||||
return next(ErrorCode.getUnauthorized());
|
||||
}
|
||||
|
||||
res.status(HTTP_STATUS.CREATED);
|
||||
|
||||
const message = getAuthenticatedMessage(req.remote_user.name);
|
||||
debug('login: created user message %o', message);
|
||||
|
||||
return next({
|
||||
ok: message,
|
||||
token,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
if (validatePassword(password) === false) {
|
||||
debug('adduser: invalid password');
|
||||
// eslint-disable-next-line new-cap
|
||||
return next(ErrorCode.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.PASSWORD_SHORT()));
|
||||
}
|
||||
|
||||
auth.add_user(name, password, async function (err, user): Promise<void> {
|
||||
if (err) {
|
||||
if (err.status >= HTTP_STATUS.BAD_REQUEST && err.status < HTTP_STATUS.INTERNAL_ERROR) {
|
||||
debug('adduser: error on create user');
|
||||
// With npm registering is the same as logging in,
|
||||
// and npm accepts only an 409 error.
|
||||
// So, changing status code here.
|
||||
return next(
|
||||
ErrorCode.getCode(err.status, err.message) || ErrorCode.getConflict(err.message)
|
||||
);
|
||||
}
|
||||
return next(err);
|
||||
}
|
||||
|
||||
const token =
|
||||
name && password ? await getApiToken(auth, config, user, password) : undefined;
|
||||
debug('adduser: new token %o', token);
|
||||
if (!token) {
|
||||
return next(ErrorCode.getUnauthorized());
|
||||
}
|
||||
|
||||
req.remote_user = user;
|
||||
res.status(HTTP_STATUS.CREATED);
|
||||
debug('adduser: user has been created');
|
||||
return next({
|
||||
ok: `user '${req.body.name}' created`,
|
||||
token,
|
||||
});
|
||||
route.get(
|
||||
'/-/user/:org_couchdb_user',
|
||||
function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {
|
||||
debug('verifying user');
|
||||
const message = getAuthenticatedMessage(req.remote_user.name);
|
||||
debug('user authenticated message %o', message);
|
||||
res.status(HTTP_STATUS.OK);
|
||||
next({
|
||||
ok: message,
|
||||
});
|
||||
}
|
||||
});
|
||||
);
|
||||
|
||||
route.delete('/-/user/token/*', function (
|
||||
req: $RequestExtend,
|
||||
res: Response,
|
||||
next: $NextFunctionVer
|
||||
): void {
|
||||
res.status(HTTP_STATUS.OK);
|
||||
next({
|
||||
ok: API_MESSAGE.LOGGED_OUT,
|
||||
});
|
||||
});
|
||||
route.put(
|
||||
'/-/user/:org_couchdb_user/:_rev?/:revision?',
|
||||
function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {
|
||||
const { name, password } = req.body;
|
||||
debug('login or adduser');
|
||||
const remoteName = req.remote_user.name;
|
||||
|
||||
if (_.isNil(remoteName) === false && _.isNil(name) === false && remoteName === name) {
|
||||
debug('login: no remote user detected');
|
||||
auth.authenticate(
|
||||
name,
|
||||
password,
|
||||
async function callbackAuthenticate(err, user): Promise<void> {
|
||||
if (err) {
|
||||
logger.trace(
|
||||
{ name, err },
|
||||
'authenticating for user @{username} failed. Error: @{err.message}'
|
||||
);
|
||||
return next(
|
||||
ErrorCode.getCode(HTTP_STATUS.UNAUTHORIZED, API_ERROR.BAD_USERNAME_PASSWORD)
|
||||
);
|
||||
}
|
||||
|
||||
const restoredRemoteUser: RemoteUser = createRemoteUser(name, user.groups || []);
|
||||
const token = await getApiToken(auth, config, restoredRemoteUser, password);
|
||||
debug('login: new token');
|
||||
if (!token) {
|
||||
return next(ErrorCode.getUnauthorized());
|
||||
}
|
||||
|
||||
res.status(HTTP_STATUS.CREATED);
|
||||
|
||||
const message = getAuthenticatedMessage(req.remote_user.name);
|
||||
debug('login: created user message %o', message);
|
||||
|
||||
return next({
|
||||
ok: message,
|
||||
token,
|
||||
});
|
||||
}
|
||||
);
|
||||
} else {
|
||||
if (validatePassword(password) === false) {
|
||||
debug('adduser: invalid password');
|
||||
// eslint-disable-next-line new-cap
|
||||
return next(ErrorCode.getCode(HTTP_STATUS.BAD_REQUEST, API_ERROR.PASSWORD_SHORT()));
|
||||
}
|
||||
|
||||
auth.add_user(name, password, async function (err, user): Promise<void> {
|
||||
if (err) {
|
||||
if (err.status >= HTTP_STATUS.BAD_REQUEST && err.status < HTTP_STATUS.INTERNAL_ERROR) {
|
||||
debug('adduser: error on create user');
|
||||
// With npm registering is the same as logging in,
|
||||
// and npm accepts only an 409 error.
|
||||
// So, changing status code here.
|
||||
return next(
|
||||
ErrorCode.getCode(err.status, err.message) || ErrorCode.getConflict(err.message)
|
||||
);
|
||||
}
|
||||
return next(err);
|
||||
}
|
||||
|
||||
const token =
|
||||
name && password ? await getApiToken(auth, config, user, password) : undefined;
|
||||
debug('adduser: new token %o', token);
|
||||
if (!token) {
|
||||
return next(ErrorCode.getUnauthorized());
|
||||
}
|
||||
|
||||
req.remote_user = user;
|
||||
res.status(HTTP_STATUS.CREATED);
|
||||
debug('adduser: user has been created');
|
||||
return next({
|
||||
ok: `user '${req.body.name}' created`,
|
||||
token,
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
route.delete(
|
||||
'/-/user/token/*',
|
||||
function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {
|
||||
res.status(HTTP_STATUS.OK);
|
||||
next({
|
||||
ok: API_MESSAGE.LOGGED_OUT,
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -31,64 +31,64 @@ export default function (route: Router, auth: IAuth): void {
|
|||
};
|
||||
}
|
||||
|
||||
route.get('/-/npm/v1/user', function (
|
||||
req: $RequestExtend,
|
||||
res: Response,
|
||||
next: $NextFunctionVer
|
||||
): void {
|
||||
if (_.isNil(req.remote_user.name) === false) {
|
||||
return next(buildProfile(req.remote_user.name));
|
||||
}
|
||||
route.get(
|
||||
'/-/npm/v1/user',
|
||||
function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {
|
||||
if (_.isNil(req.remote_user.name) === false) {
|
||||
return next(buildProfile(req.remote_user.name));
|
||||
}
|
||||
|
||||
res.status(HTTP_STATUS.UNAUTHORIZED);
|
||||
return next({
|
||||
message: API_ERROR.MUST_BE_LOGGED,
|
||||
});
|
||||
});
|
||||
|
||||
route.post('/-/npm/v1/user', function (
|
||||
req: $RequestExtend,
|
||||
res: Response,
|
||||
next: $NextFunctionVer
|
||||
): void {
|
||||
if (_.isNil(req.remote_user.name)) {
|
||||
res.status(HTTP_STATUS.UNAUTHORIZED);
|
||||
return next({
|
||||
message: API_ERROR.MUST_BE_LOGGED,
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
const { password, tfa } = req.body;
|
||||
const { name } = req.remote_user;
|
||||
|
||||
if (_.isNil(password) === false) {
|
||||
if (validatePassword(password.new) === false) {
|
||||
/* eslint new-cap:off */
|
||||
return next(ErrorCode.getCode(HTTP_STATUS.UNAUTHORIZED, API_ERROR.PASSWORD_SHORT()));
|
||||
/* eslint new-cap:off */
|
||||
route.post(
|
||||
'/-/npm/v1/user',
|
||||
function (req: $RequestExtend, res: Response, next: $NextFunctionVer): void {
|
||||
if (_.isNil(req.remote_user.name)) {
|
||||
res.status(HTTP_STATUS.UNAUTHORIZED);
|
||||
return next({
|
||||
message: API_ERROR.MUST_BE_LOGGED,
|
||||
});
|
||||
}
|
||||
|
||||
auth.changePassword(
|
||||
name,
|
||||
password.old,
|
||||
password.new,
|
||||
(err, isUpdated): $NextFunctionVer => {
|
||||
if (_.isNull(err) === false) {
|
||||
return next(
|
||||
ErrorCode.getCode(err.status, err.message) || ErrorCode.getConflict(err.message)
|
||||
);
|
||||
}
|
||||
const { password, tfa } = req.body;
|
||||
const { name } = req.remote_user;
|
||||
|
||||
if (isUpdated) {
|
||||
return next(buildProfile(req.remote_user.name));
|
||||
}
|
||||
return next(ErrorCode.getInternalError(API_ERROR.INTERNAL_SERVER_ERROR));
|
||||
if (_.isNil(password) === false) {
|
||||
if (validatePassword(password.new) === false) {
|
||||
/* eslint new-cap:off */
|
||||
return next(ErrorCode.getCode(HTTP_STATUS.UNAUTHORIZED, API_ERROR.PASSWORD_SHORT()));
|
||||
/* eslint new-cap:off */
|
||||
}
|
||||
);
|
||||
} else if (_.isNil(tfa) === false) {
|
||||
return next(ErrorCode.getCode(HTTP_STATUS.SERVICE_UNAVAILABLE, SUPPORT_ERRORS.TFA_DISABLED));
|
||||
} else {
|
||||
return next(ErrorCode.getCode(HTTP_STATUS.INTERNAL_ERROR, APP_ERROR.PROFILE_ERROR));
|
||||
|
||||
auth.changePassword(
|
||||
name,
|
||||
password.old,
|
||||
password.new,
|
||||
(err, isUpdated): $NextFunctionVer => {
|
||||
if (_.isNull(err) === false) {
|
||||
return next(
|
||||
ErrorCode.getCode(err.status, err.message) || ErrorCode.getConflict(err.message)
|
||||
);
|
||||
}
|
||||
|
||||
if (isUpdated) {
|
||||
return next(buildProfile(req.remote_user.name));
|
||||
}
|
||||
return next(ErrorCode.getInternalError(API_ERROR.INTERNAL_SERVER_ERROR));
|
||||
}
|
||||
);
|
||||
} else if (_.isNil(tfa) === false) {
|
||||
return next(
|
||||
ErrorCode.getCode(HTTP_STATUS.SERVICE_UNAVAILABLE, SUPPORT_ERRORS.TFA_DISABLED)
|
||||
);
|
||||
} else {
|
||||
return next(ErrorCode.getCode(HTTP_STATUS.INTERNAL_ERROR, APP_ERROR.PROFILE_ERROR));
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
}
|
||||
|
|
|
@ -28,103 +28,101 @@ export default function (
|
|||
storage: IStorageHandler,
|
||||
config: Config
|
||||
): void {
|
||||
route.get('/-/npm/v1/tokens', async function (
|
||||
req: $RequestExtend,
|
||||
res: Response,
|
||||
next: $NextFunctionVer
|
||||
) {
|
||||
const { name } = req.remote_user;
|
||||
route.get(
|
||||
'/-/npm/v1/tokens',
|
||||
async function (req: $RequestExtend, res: Response, next: $NextFunctionVer) {
|
||||
const { name } = req.remote_user;
|
||||
|
||||
if (_.isNil(name) === false) {
|
||||
try {
|
||||
const tokens = await storage.readTokens({ user: name });
|
||||
const totalTokens = tokens.length;
|
||||
logger.debug({ totalTokens }, 'token list retrieved: @{totalTokens}');
|
||||
if (_.isNil(name) === false) {
|
||||
try {
|
||||
const tokens = await storage.readTokens({ user: name });
|
||||
const totalTokens = tokens.length;
|
||||
logger.debug({ totalTokens }, 'token list retrieved: @{totalTokens}');
|
||||
|
||||
res.status(HTTP_STATUS.OK);
|
||||
return next({
|
||||
objects: tokens.map(normalizeToken),
|
||||
urls: {
|
||||
next: '', // TODO: pagination?
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error({ error: error.msg }, 'token list has failed: @{error}');
|
||||
return next(ErrorCode.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message));
|
||||
res.status(HTTP_STATUS.OK);
|
||||
return next({
|
||||
objects: tokens.map(normalizeToken),
|
||||
urls: {
|
||||
next: '', // TODO: pagination?
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error({ error: error.msg }, 'token list has failed: @{error}');
|
||||
return next(ErrorCode.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message));
|
||||
}
|
||||
}
|
||||
return next(ErrorCode.getUnauthorized());
|
||||
}
|
||||
return next(ErrorCode.getUnauthorized());
|
||||
});
|
||||
);
|
||||
|
||||
route.post('/-/npm/v1/tokens', function (
|
||||
req: $RequestExtend,
|
||||
res: Response,
|
||||
next: $NextFunctionVer
|
||||
) {
|
||||
const { password, readonly, cidr_whitelist } = req.body;
|
||||
const { name } = req.remote_user;
|
||||
route.post(
|
||||
'/-/npm/v1/tokens',
|
||||
function (req: $RequestExtend, res: Response, next: $NextFunctionVer) {
|
||||
const { password, readonly, cidr_whitelist } = req.body;
|
||||
const { name } = req.remote_user;
|
||||
|
||||
if (!_.isBoolean(readonly) || !_.isArray(cidr_whitelist)) {
|
||||
return next(ErrorCode.getCode(HTTP_STATUS.BAD_DATA, SUPPORT_ERRORS.PARAMETERS_NOT_VALID));
|
||||
}
|
||||
|
||||
auth.authenticate(name, password, async (err, user: RemoteUser) => {
|
||||
if (err) {
|
||||
const errorCode = err.message ? HTTP_STATUS.UNAUTHORIZED : HTTP_STATUS.INTERNAL_ERROR;
|
||||
return next(ErrorCode.getCode(errorCode, err.message));
|
||||
if (!_.isBoolean(readonly) || !_.isArray(cidr_whitelist)) {
|
||||
return next(ErrorCode.getCode(HTTP_STATUS.BAD_DATA, SUPPORT_ERRORS.PARAMETERS_NOT_VALID));
|
||||
}
|
||||
|
||||
req.remote_user = user;
|
||||
|
||||
if (!_.isFunction(storage.saveToken)) {
|
||||
return next(
|
||||
ErrorCode.getCode(HTTP_STATUS.NOT_IMPLEMENTED, SUPPORT_ERRORS.STORAGE_NOT_IMPLEMENT)
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const token = await getApiToken(auth, config, user, password);
|
||||
if (!token) {
|
||||
throw getInternalError();
|
||||
auth.authenticate(name, password, async (err, user: RemoteUser) => {
|
||||
if (err) {
|
||||
const errorCode = err.message ? HTTP_STATUS.UNAUTHORIZED : HTTP_STATUS.INTERNAL_ERROR;
|
||||
return next(ErrorCode.getCode(errorCode, err.message));
|
||||
}
|
||||
|
||||
const key = stringToMD5(token);
|
||||
// TODO: use a utility here
|
||||
const maskedToken = mask(token, 5);
|
||||
const created = new Date().getTime();
|
||||
req.remote_user = user;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
const saveToken: Token = {
|
||||
user: name,
|
||||
token: maskedToken,
|
||||
key,
|
||||
cidr: cidr_whitelist,
|
||||
readonly,
|
||||
created,
|
||||
};
|
||||
if (!_.isFunction(storage.saveToken)) {
|
||||
return next(
|
||||
ErrorCode.getCode(HTTP_STATUS.NOT_IMPLEMENTED, SUPPORT_ERRORS.STORAGE_NOT_IMPLEMENT)
|
||||
);
|
||||
}
|
||||
|
||||
await storage.saveToken(saveToken);
|
||||
logger.debug({ key, name }, 'token @{key} was created for user @{name}');
|
||||
return next(
|
||||
normalizeToken({
|
||||
token,
|
||||
try {
|
||||
const token = await getApiToken(auth, config, user, password);
|
||||
if (!token) {
|
||||
throw getInternalError();
|
||||
}
|
||||
|
||||
const key = stringToMD5(token);
|
||||
// TODO: use a utility here
|
||||
const maskedToken = mask(token, 5);
|
||||
const created = new Date().getTime();
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
const saveToken: Token = {
|
||||
user: name,
|
||||
key: saveToken.key,
|
||||
token: maskedToken,
|
||||
key,
|
||||
cidr: cidr_whitelist,
|
||||
readonly,
|
||||
created: saveToken.created,
|
||||
})
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error({ error: error.msg }, 'token creation has failed: @{error}');
|
||||
return next(ErrorCode.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message));
|
||||
}
|
||||
});
|
||||
});
|
||||
created,
|
||||
};
|
||||
|
||||
await storage.saveToken(saveToken);
|
||||
logger.debug({ key, name }, 'token @{key} was created for user @{name}');
|
||||
return next(
|
||||
normalizeToken({
|
||||
token,
|
||||
user: name,
|
||||
key: saveToken.key,
|
||||
cidr: cidr_whitelist,
|
||||
readonly,
|
||||
created: saveToken.created,
|
||||
})
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error({ error: error.msg }, 'token creation has failed: @{error}');
|
||||
return next(ErrorCode.getCode(HTTP_STATUS.INTERNAL_ERROR, error.message));
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
route.delete(
|
||||
'/-/npm/v1/tokens/token/:tokenKey',
|
||||
|
|
|
@ -35,7 +35,7 @@ export const statfile = (name: string): Promise<Error | null> => {
|
|||
};
|
||||
|
||||
export const lockfile = (name: string): Promise<unknown> => {
|
||||
return new Promise((resolve): void => {
|
||||
return new Promise<void>((resolve): void => {
|
||||
const lockOpts = {
|
||||
// time (ms) to wait when checking for stale locks
|
||||
wait: 1000,
|
||||
|
|
|
@ -172,21 +172,22 @@ export function allow(auth: IAuth): Function {
|
|||
{ action, user: remote?.name },
|
||||
`[middleware/allow][@{action}] allow for @{user}`
|
||||
);
|
||||
auth['allow_' + action]({ packageName, packageVersion }, remote, function (
|
||||
error,
|
||||
allowed
|
||||
): void {
|
||||
req.resume();
|
||||
if (error) {
|
||||
next(error);
|
||||
} else if (allowed) {
|
||||
next();
|
||||
} else {
|
||||
// last plugin (that's our built-in one) returns either
|
||||
// cb(err) or cb(null, true), so this should never happen
|
||||
throw ErrorCode.getInternalError(API_ERROR.PLUGIN_ERROR);
|
||||
auth['allow_' + action](
|
||||
{ packageName, packageVersion },
|
||||
remote,
|
||||
function (error, allowed): void {
|
||||
req.resume();
|
||||
if (error) {
|
||||
next(error);
|
||||
} else if (allowed) {
|
||||
next();
|
||||
} else {
|
||||
// last plugin (that's our built-in one) returns either
|
||||
// cb(err) or cb(null, true), so this should never happen
|
||||
throw ErrorCode.getInternalError(API_ERROR.PLUGIN_ERROR);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -215,7 +215,7 @@ export default class Server implements IServerBridge {
|
|||
}, 20);
|
||||
});
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
return new Promise<void>(function (resolve, reject) {
|
||||
promise
|
||||
.then(function () {
|
||||
reject(Error('no error'));
|
||||
|
|
|
@ -171,7 +171,7 @@ export default class S3Database implements IPluginStorage<S3Config> {
|
|||
|
||||
// Create/write database file to s3
|
||||
private async _sync(): Promise<void> {
|
||||
await new Promise((resolve, reject): void => {
|
||||
await new Promise<void>((resolve, reject): void => {
|
||||
const { bucket, keyPrefix } = this.config;
|
||||
this.logger.debug(
|
||||
{ keyPrefix, bucket },
|
||||
|
|
|
@ -315,7 +315,7 @@ export default class S3PackageManager implements ILocalPackageManager {
|
|||
Object.assign({}, baseS3Params, { Body: uploadStream })
|
||||
);
|
||||
// NOTE: there's a managedUpload.promise, but it doesn't seem to work
|
||||
const promise = new Promise((resolve): void => {
|
||||
const promise = new Promise<void>((resolve): void => {
|
||||
this.logger.debug('s3: [S3PackageManager writeTarball managedUpload] send');
|
||||
managedUpload.send((err, data) => {
|
||||
if (err) {
|
||||
|
|
|
@ -6,11 +6,11 @@ import { Route as ReactRouterDomRoute, Switch, Router } from 'react-router-dom';
|
|||
import AppContext from './AppContext';
|
||||
import loadable from './utils/loadable';
|
||||
|
||||
const NotFound = loadable(() =>
|
||||
import(/* webpackChunkName: "NotFound" */ 'verdaccio-ui/components/NotFound')
|
||||
const NotFound = loadable(
|
||||
() => import(/* webpackChunkName: "NotFound" */ 'verdaccio-ui/components/NotFound')
|
||||
);
|
||||
const VersionContextProvider = loadable(() =>
|
||||
import(/* webpackChunkName: "Provider" */ '../pages/Version/VersionContextProvider')
|
||||
const VersionContextProvider = loadable(
|
||||
() => import(/* webpackChunkName: "Provider" */ '../pages/Version/VersionContextProvider')
|
||||
);
|
||||
const VersionPage = loadable(() => import(/* webpackChunkName: "Version" */ '../pages/Version'));
|
||||
const HomePage = loadable(() => import(/* webpackChunkName: "Home" */ '../pages/home'));
|
||||
|
|
|
@ -8,8 +8,8 @@ import { TabPosition } from './tabs';
|
|||
const Versions = loadable(() => import(/* webpackChunkName: "Versions" */ './Versions'));
|
||||
const UpLinks = loadable(() => import(/* webpackChunkName: "UpLinks" */ './UpLinks'));
|
||||
|
||||
const Dependencies = loadable(() =>
|
||||
import(/* webpackChunkName: "Dependencies" */ './Dependencies')
|
||||
const Dependencies = loadable(
|
||||
() => import(/* webpackChunkName: "Dependencies" */ './Dependencies')
|
||||
);
|
||||
|
||||
interface Props {
|
||||
|
|
|
@ -3,7 +3,6 @@ import dayjs from 'dayjs';
|
|||
import localizedFormat from 'dayjs/plugin/localizedFormat';
|
||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
import i18next from 'i18next';
|
||||
import isObject from 'lodash/isObject';
|
||||
import isString from 'lodash/isString';
|
||||
|
||||
import { Time } from '../../types/packageMeta';
|
||||
|
@ -24,9 +23,7 @@ export function formatLicense(license: any): string | undefined {
|
|||
return license;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
if (license && isObject(license) && license.type) {
|
||||
// @ts-ignore
|
||||
if (license?.type) {
|
||||
return license.type;
|
||||
}
|
||||
|
||||
|
@ -50,9 +47,7 @@ export function formatRepository(repository: any): string | null {
|
|||
return repository;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
if (repository && isObject(repository) && repository.url) {
|
||||
// @ts-ignore
|
||||
if (repository?.url) {
|
||||
return repository.url;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,24 +4,23 @@ import { $ResponseExtend, $RequestExtend, $NextFunctionVer } from '../../types/c
|
|||
|
||||
export default (app: Application, configPath: string): void => {
|
||||
// Hook for tests only
|
||||
app.get('/-/_debug', function (
|
||||
req: $RequestExtend,
|
||||
res: $ResponseExtend,
|
||||
next: $NextFunctionVer
|
||||
): void {
|
||||
const doGarbabeCollector = _.isNil(global.gc) === false;
|
||||
app.get(
|
||||
'/-/_debug',
|
||||
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
|
||||
const doGarbabeCollector = _.isNil(global.gc) === false;
|
||||
|
||||
if (doGarbabeCollector) {
|
||||
global.gc();
|
||||
if (doGarbabeCollector) {
|
||||
global.gc();
|
||||
}
|
||||
|
||||
next({
|
||||
pid: process.pid,
|
||||
// @ts-ignore
|
||||
main: process.mainModule.filename,
|
||||
conf: configPath,
|
||||
mem: process.memoryUsage(),
|
||||
gc: doGarbabeCollector,
|
||||
});
|
||||
}
|
||||
|
||||
next({
|
||||
pid: process.pid,
|
||||
// @ts-ignore
|
||||
main: process.mainModule.filename,
|
||||
conf: configPath,
|
||||
mem: process.memoryUsage(),
|
||||
gc: doGarbabeCollector,
|
||||
});
|
||||
});
|
||||
);
|
||||
};
|
||||
|
|
|
@ -54,14 +54,13 @@ const defineAPI = function (config: IConfig, storage: IStorageHandler): any {
|
|||
|
||||
app.use(compression());
|
||||
|
||||
app.get('/favicon.ico', function (
|
||||
req: $RequestExtend,
|
||||
res: $ResponseExtend,
|
||||
next: $NextFunctionVer
|
||||
): void {
|
||||
req.url = '/-/static/favicon.png';
|
||||
next();
|
||||
});
|
||||
app.get(
|
||||
'/favicon.ico',
|
||||
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
|
||||
req.url = '/-/static/favicon.png';
|
||||
next();
|
||||
}
|
||||
);
|
||||
|
||||
// Hook for tests only
|
||||
if (config._debug) {
|
||||
|
|
|
@ -154,7 +154,7 @@ export function cleanUpLinksRef(keepUpLinkData: boolean, result: Package): Packa
|
|||
* @param {*} localStorage
|
||||
*/
|
||||
export function checkPackageLocal(name: string, localStorage: IStorage): Promise<any> {
|
||||
return new Promise((resolve, reject): void => {
|
||||
return new Promise<void>((resolve, reject): void => {
|
||||
localStorage.getPackageMetadata(name, (err, results): void => {
|
||||
if (!isNil(err) && err.status !== HTTP_STATUS.NOT_FOUND) {
|
||||
return reject(err);
|
||||
|
@ -168,7 +168,7 @@ export function checkPackageLocal(name: string, localStorage: IStorage): Promise
|
|||
}
|
||||
|
||||
export function publishPackage(name: string, metadata: any, localStorage: IStorage): Promise<any> {
|
||||
return new Promise((resolve, reject): void => {
|
||||
return new Promise<void>((resolve, reject): void => {
|
||||
localStorage.addPackage(name, metadata, (err, latest): void => {
|
||||
if (!_.isNull(err)) {
|
||||
return reject(err);
|
||||
|
@ -185,7 +185,7 @@ export function checkPackageRemote(
|
|||
isAllowPublishOffline: boolean,
|
||||
syncMetadata: Function
|
||||
): Promise<any> {
|
||||
return new Promise((resolve, reject): void => {
|
||||
return new Promise<void>((resolve, reject): void => {
|
||||
syncMetadata(name, null, {}, (err, packageJsonLocal, upLinksErrors): void => {
|
||||
// something weird
|
||||
if (err && err.status !== HTTP_STATUS.NOT_FOUND) {
|
||||
|
|
|
@ -486,38 +486,38 @@ class Storage {
|
|||
|
||||
const packages: Version[] = [];
|
||||
const getPackage = function (itemPkg): void {
|
||||
self.localStorage.getPackageMetadata(locals[itemPkg], function (
|
||||
err,
|
||||
pkgMetadata: Package
|
||||
): void {
|
||||
if (_.isNil(err)) {
|
||||
const latest = pkgMetadata[DIST_TAGS].latest;
|
||||
if (latest && pkgMetadata.versions[latest]) {
|
||||
const version: Version = pkgMetadata.versions[latest];
|
||||
const timeList = pkgMetadata.time as GenericBody;
|
||||
const time = timeList[latest];
|
||||
// @ts-ignore
|
||||
version.time = time;
|
||||
self.localStorage.getPackageMetadata(
|
||||
locals[itemPkg],
|
||||
function (err, pkgMetadata: Package): void {
|
||||
if (_.isNil(err)) {
|
||||
const latest = pkgMetadata[DIST_TAGS].latest;
|
||||
if (latest && pkgMetadata.versions[latest]) {
|
||||
const version: Version = pkgMetadata.versions[latest];
|
||||
const timeList = pkgMetadata.time as GenericBody;
|
||||
const time = timeList[latest];
|
||||
// @ts-ignore
|
||||
version.time = time;
|
||||
|
||||
// Add for stars api
|
||||
// @ts-ignore
|
||||
version.users = pkgMetadata.users;
|
||||
// Add for stars api
|
||||
// @ts-ignore
|
||||
version.users = pkgMetadata.users;
|
||||
|
||||
packages.push(version);
|
||||
packages.push(version);
|
||||
} else {
|
||||
self.logger.warn(
|
||||
{ package: locals[itemPkg] },
|
||||
'package @{package} does not have a "latest" tag?'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (itemPkg >= locals.length - 1) {
|
||||
callback(null, packages);
|
||||
} else {
|
||||
self.logger.warn(
|
||||
{ package: locals[itemPkg] },
|
||||
'package @{package} does not have a "latest" tag?'
|
||||
);
|
||||
getPackage(itemPkg + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (itemPkg >= locals.length - 1) {
|
||||
callback(null, packages);
|
||||
} else {
|
||||
getPackage(itemPkg + 1);
|
||||
}
|
||||
});
|
||||
);
|
||||
};
|
||||
|
||||
if (locals.length) {
|
||||
|
|
|
@ -384,7 +384,7 @@ describe('LocalStorage', () => {
|
|||
stream.done();
|
||||
});
|
||||
|
||||
test('should fails on add a duplicated new tarball ', (done) => {
|
||||
test('should fails on add a duplicated new tarball', (done) => {
|
||||
const tarballData = JSON.parse(readMetadata('addTarball'));
|
||||
const stream = storage.addTarball(pkgName, tarballName);
|
||||
stream.on('error', (err: VerdaccioError) => {
|
||||
|
|
|
@ -53,130 +53,129 @@ function addPackageWebApi(
|
|||
});
|
||||
|
||||
// Get list of all visible package
|
||||
route.get('/packages', function (
|
||||
req: $RequestExtend,
|
||||
res: $ResponseExtend,
|
||||
next: $NextFunctionVer
|
||||
): void {
|
||||
storage.getLocalDatabase(async function (err, packages): Promise<void> {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
async function processPackages(packages: PackcageExt[] = []): Promise<PackcageExt[]> {
|
||||
const permissions: PackcageExt[] = [];
|
||||
const packgesCopy = packages.slice();
|
||||
for (const pkg of packgesCopy) {
|
||||
const pkgCopy = { ...pkg };
|
||||
pkgCopy.author = formatAuthor(pkg.author);
|
||||
try {
|
||||
if (await checkAllow(pkg.name, req.remote_user)) {
|
||||
if (config.web) {
|
||||
pkgCopy.author.avatar = generateGravatarUrl(
|
||||
pkgCopy.author.email,
|
||||
config.web.gravatar
|
||||
);
|
||||
}
|
||||
if (!_.isNil(pkgCopy.dist) && !_.isNull(pkgCopy.dist.tarball)) {
|
||||
pkgCopy.dist.tarball = getLocalRegistryTarballUri(
|
||||
pkgCopy.dist.tarball,
|
||||
pkg.name,
|
||||
req,
|
||||
config.url_prefix
|
||||
);
|
||||
}
|
||||
permissions.push(pkgCopy);
|
||||
}
|
||||
} catch (err) {
|
||||
logger.logger.error(
|
||||
{ name: pkg.name, error: err },
|
||||
'permission process for @{name} has failed: @{error}'
|
||||
);
|
||||
throw err;
|
||||
}
|
||||
route.get(
|
||||
'/packages',
|
||||
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
|
||||
storage.getLocalDatabase(async function (err, packages): Promise<void> {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
return permissions;
|
||||
}
|
||||
async function processPackages(packages: PackcageExt[] = []): Promise<PackcageExt[]> {
|
||||
const permissions: PackcageExt[] = [];
|
||||
const packgesCopy = packages.slice();
|
||||
for (const pkg of packgesCopy) {
|
||||
const pkgCopy = { ...pkg };
|
||||
pkgCopy.author = formatAuthor(pkg.author);
|
||||
try {
|
||||
if (await checkAllow(pkg.name, req.remote_user)) {
|
||||
if (config.web) {
|
||||
pkgCopy.author.avatar = generateGravatarUrl(
|
||||
pkgCopy.author.email,
|
||||
config.web.gravatar
|
||||
);
|
||||
}
|
||||
if (!_.isNil(pkgCopy.dist) && !_.isNull(pkgCopy.dist.tarball)) {
|
||||
pkgCopy.dist.tarball = getLocalRegistryTarballUri(
|
||||
pkgCopy.dist.tarball,
|
||||
pkg.name,
|
||||
req,
|
||||
config.url_prefix
|
||||
);
|
||||
}
|
||||
permissions.push(pkgCopy);
|
||||
}
|
||||
} catch (err) {
|
||||
logger.logger.error(
|
||||
{ name: pkg.name, error: err },
|
||||
'permission process for @{name} has failed: @{error}'
|
||||
);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
const { web } = config;
|
||||
const order = web ? getOrder(web.sort_packages) : true;
|
||||
return permissions;
|
||||
}
|
||||
|
||||
next(sortByName(await processPackages(packages), order));
|
||||
});
|
||||
});
|
||||
const { web } = config;
|
||||
const order = web ? getOrder(web.sort_packages) : true;
|
||||
|
||||
next(sortByName(await processPackages(packages), order));
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// Get package readme
|
||||
route.get('/package/readme/(@:scope/)?:package/:version?', can('access'), function (
|
||||
req: $RequestExtend,
|
||||
res: $ResponseExtend,
|
||||
next: $NextFunctionVer
|
||||
): void {
|
||||
const packageName = req.params.scope
|
||||
? addScope(req.params.scope, req.params.package)
|
||||
: req.params.package;
|
||||
route.get(
|
||||
'/package/readme/(@:scope/)?:package/:version?',
|
||||
can('access'),
|
||||
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
|
||||
const packageName = req.params.scope
|
||||
? addScope(req.params.scope, req.params.package)
|
||||
: req.params.package;
|
||||
|
||||
storage.getPackage({
|
||||
name: packageName,
|
||||
uplinksLook: true,
|
||||
req,
|
||||
callback: function (err, info): void {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
|
||||
res.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.TEXT_PLAIN);
|
||||
try {
|
||||
next(parseReadme(info.name, info.readme));
|
||||
} catch {
|
||||
next(sanitizyReadme('ERROR: No README data found!'));
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
route.get('/sidebar/(@:scope/)?:package', can('access'), function (
|
||||
req: $RequestExtend,
|
||||
res: $ResponseExtend,
|
||||
next: $NextFunctionVer
|
||||
): void {
|
||||
const packageName: string = req.params.scope
|
||||
? addScope(req.params.scope, req.params.package)
|
||||
: req.params.package;
|
||||
|
||||
storage.getPackage({
|
||||
name: packageName,
|
||||
uplinksLook: true,
|
||||
keepUpLinkData: true,
|
||||
req,
|
||||
callback: function (err: Error, info: $SidebarPackage): void {
|
||||
if (_.isNil(err)) {
|
||||
const { v } = req.query;
|
||||
let sideBarInfo = _.clone(info);
|
||||
sideBarInfo.versions = convertDistRemoteToLocalTarballUrls(
|
||||
info,
|
||||
req,
|
||||
config.url_prefix
|
||||
).versions;
|
||||
if (typeof v === 'string' && isVersionValid(info, v)) {
|
||||
sideBarInfo.latest = sideBarInfo.versions[v];
|
||||
sideBarInfo.latest.author = formatAuthor(sideBarInfo.latest.author);
|
||||
} else {
|
||||
sideBarInfo.latest = sideBarInfo.versions[info[DIST_TAGS].latest];
|
||||
sideBarInfo.latest.author = formatAuthor(sideBarInfo.latest.author);
|
||||
storage.getPackage({
|
||||
name: packageName,
|
||||
uplinksLook: true,
|
||||
req,
|
||||
callback: function (err, info): void {
|
||||
if (err) {
|
||||
return next(err);
|
||||
}
|
||||
sideBarInfo = deleteProperties(['readme', '_attachments', '_rev', 'name'], sideBarInfo);
|
||||
const authorAvatar = config.web
|
||||
? addGravatarSupport(sideBarInfo, config.web.gravatar)
|
||||
: addGravatarSupport(sideBarInfo);
|
||||
next(authorAvatar);
|
||||
} else {
|
||||
res.status(HTTP_STATUS.NOT_FOUND);
|
||||
res.end();
|
||||
}
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
res.set(HEADER_TYPE.CONTENT_TYPE, HEADERS.TEXT_PLAIN);
|
||||
try {
|
||||
next(parseReadme(info.name, info.readme));
|
||||
} catch {
|
||||
next(sanitizyReadme('ERROR: No README data found!'));
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
route.get(
|
||||
'/sidebar/(@:scope/)?:package',
|
||||
can('access'),
|
||||
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
|
||||
const packageName: string = req.params.scope
|
||||
? addScope(req.params.scope, req.params.package)
|
||||
: req.params.package;
|
||||
|
||||
storage.getPackage({
|
||||
name: packageName,
|
||||
uplinksLook: true,
|
||||
keepUpLinkData: true,
|
||||
req,
|
||||
callback: function (err: Error, info: $SidebarPackage): void {
|
||||
if (_.isNil(err)) {
|
||||
const { v } = req.query;
|
||||
let sideBarInfo = _.clone(info);
|
||||
sideBarInfo.versions = convertDistRemoteToLocalTarballUrls(
|
||||
info,
|
||||
req,
|
||||
config.url_prefix
|
||||
).versions;
|
||||
if (typeof v === 'string' && isVersionValid(info, v)) {
|
||||
sideBarInfo.latest = sideBarInfo.versions[v];
|
||||
sideBarInfo.latest.author = formatAuthor(sideBarInfo.latest.author);
|
||||
} else {
|
||||
sideBarInfo.latest = sideBarInfo.versions[info[DIST_TAGS].latest];
|
||||
sideBarInfo.latest.author = formatAuthor(sideBarInfo.latest.author);
|
||||
}
|
||||
sideBarInfo = deleteProperties(['readme', '_attachments', '_rev', 'name'], sideBarInfo);
|
||||
const authorAvatar = config.web
|
||||
? addGravatarSupport(sideBarInfo, config.web.gravatar)
|
||||
: addGravatarSupport(sideBarInfo);
|
||||
next(authorAvatar);
|
||||
} else {
|
||||
res.status(HTTP_STATUS.NOT_FOUND);
|
||||
res.end();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export default addPackageWebApi;
|
||||
|
|
|
@ -8,48 +8,48 @@ import { $ResponseExtend, $RequestExtend, $NextFunctionVer } from './package';
|
|||
|
||||
function addSearchWebApi(route: Router, storage: IStorageHandler, auth: IAuth): void {
|
||||
// Search package
|
||||
route.get('/search/:anything', function (
|
||||
req: $RequestExtend,
|
||||
res: $ResponseExtend,
|
||||
next: $NextFunctionVer
|
||||
): void {
|
||||
const results: any = SearchInstance.query(req.params.anything);
|
||||
// FUTURE: figure out here the correct type
|
||||
const packages: any[] = [];
|
||||
route.get(
|
||||
'/search/:anything',
|
||||
function (req: $RequestExtend, res: $ResponseExtend, next: $NextFunctionVer): void {
|
||||
const results: any = SearchInstance.query(req.params.anything);
|
||||
// FUTURE: figure out here the correct type
|
||||
const packages: any[] = [];
|
||||
|
||||
const getPackageInfo = function (i): void {
|
||||
storage.getPackage({
|
||||
name: results[i].ref,
|
||||
uplinksLook: false,
|
||||
callback: (err, entry: Package): void => {
|
||||
if (!err && entry) {
|
||||
auth.allow_access({ packageName: entry.name }, req.remote_user, function (
|
||||
err,
|
||||
allowed
|
||||
): void {
|
||||
if (err || !allowed) {
|
||||
return;
|
||||
}
|
||||
const getPackageInfo = function (i): void {
|
||||
storage.getPackage({
|
||||
name: results[i].ref,
|
||||
uplinksLook: false,
|
||||
callback: (err, entry: Package): void => {
|
||||
if (!err && entry) {
|
||||
auth.allow_access(
|
||||
{ packageName: entry.name },
|
||||
req.remote_user,
|
||||
function (err, allowed): void {
|
||||
if (err || !allowed) {
|
||||
return;
|
||||
}
|
||||
|
||||
packages.push(entry.versions[entry[DIST_TAGS].latest]);
|
||||
});
|
||||
}
|
||||
packages.push(entry.versions[entry[DIST_TAGS].latest]);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (i >= results.length - 1) {
|
||||
next(packages);
|
||||
} else {
|
||||
getPackageInfo(i + 1);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
if (i >= results.length - 1) {
|
||||
next(packages);
|
||||
} else {
|
||||
getPackageInfo(i + 1);
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
if (results.length) {
|
||||
getPackageInfo(0);
|
||||
} else {
|
||||
next([]);
|
||||
if (results.length) {
|
||||
getPackageInfo(0);
|
||||
} else {
|
||||
next([]);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
}
|
||||
|
||||
export default addSearchWebApi;
|
||||
|
|
|
@ -32,36 +32,35 @@ function addUserAuthApi(route: Router, auth: IAuth, config: Config): void {
|
|||
);
|
||||
});
|
||||
|
||||
route.put('/reset_password', function (
|
||||
req: Request,
|
||||
res: Response,
|
||||
next: $NextFunctionVer
|
||||
): void {
|
||||
if (_.isNil(req.remote_user.name)) {
|
||||
res.status(HTTP_STATUS.UNAUTHORIZED);
|
||||
return next({
|
||||
// FUTURE: update to a more meaningful message
|
||||
message: API_ERROR.MUST_BE_LOGGED,
|
||||
});
|
||||
}
|
||||
route.put(
|
||||
'/reset_password',
|
||||
function (req: Request, res: Response, next: $NextFunctionVer): void {
|
||||
if (_.isNil(req.remote_user.name)) {
|
||||
res.status(HTTP_STATUS.UNAUTHORIZED);
|
||||
return next({
|
||||
// FUTURE: update to a more meaningful message
|
||||
message: API_ERROR.MUST_BE_LOGGED,
|
||||
});
|
||||
}
|
||||
|
||||
const { password } = req.body;
|
||||
const { name } = req.remote_user;
|
||||
const { password } = req.body;
|
||||
const { name } = req.remote_user;
|
||||
|
||||
if (validatePassword(password.new) === false) {
|
||||
auth.changePassword(name as string, password.old, password.new, (err, isUpdated): void => {
|
||||
if (_.isNil(err) && isUpdated) {
|
||||
next({
|
||||
ok: true,
|
||||
});
|
||||
} else {
|
||||
return next(ErrorCode.getInternalError(API_ERROR.INTERNAL_SERVER_ERROR));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return next(ErrorCode.getCode(HTTP_STATUS.BAD_REQUEST, APP_ERROR.PASSWORD_VALIDATION));
|
||||
if (validatePassword(password.new) === false) {
|
||||
auth.changePassword(name as string, password.old, password.new, (err, isUpdated): void => {
|
||||
if (_.isNil(err) && isUpdated) {
|
||||
next({
|
||||
ok: true,
|
||||
});
|
||||
} else {
|
||||
return next(ErrorCode.getInternalError(API_ERROR.INTERNAL_SERVER_ERROR));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return next(ErrorCode.getCode(HTTP_STATUS.BAD_REQUEST, APP_ERROR.PASSWORD_VALIDATION));
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
}
|
||||
|
||||
export default addUserAuthApi;
|
||||
|
|
2408
pnpm-lock.yaml
2408
pnpm-lock.yaml
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue