0
Fork 0
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:
Juan Picado 2021-01-16 10:40:43 +01:00
parent 96ba927917
commit eab3007939
26 changed files with 2236 additions and 1578 deletions

View file

@ -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",

View file

@ -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:*",

View file

@ -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,
});
}
);
}
);
} }

View file

@ -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);
}
);
} }

View file

@ -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({}); );
});
} }

View file

@ -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)) {

View file

@ -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,
});
}
);
} }

View file

@ -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));
}
} }
}); );
} }

View file

@ -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',

View file

@ -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,

View file

@ -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);
}
} }
}); );
}; };
}; };
} }

View file

@ -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'));

View file

@ -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 },

View file

@ -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) {

View file

@ -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'));

View file

@ -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 {

View file

@ -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;
} }

View file

@ -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,
});
});
}; };

View file

@ -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) {

View file

@ -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) {

View file

@ -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) {

View file

@ -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) => {

View file

@ -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;

View file

@ -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;

View file

@ -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;

File diff suppressed because it is too large Load diff