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